예제 #1
0
            /// <summary>
            /// Gets the custom property name (blueprint struct var names)
            /// </summary>
            public string GetPropertyName(UProperty property)
            {
                string propertyName;

                exportableProperties.TryGetValue(property, out propertyName);
                return(propertyName);
            }
예제 #2
0
        private bool ArePropertiesTheSame(UProperty a, UProperty b, bool checkPropertiesNames)
        {
            if (a == b)
            {
                return(true);
            }

            if (a == null || b == null)// one of properties is null
            {
                return(false);
            }

            if (checkPropertiesNames && (a.GetFName() != b.GetFName()))
            {
                return(false);
            }

            if (a.GetSize() != b.GetSize())
            {
                return(false);
            }

            if (a.GetOffset_ForGC() != b.GetOffset_ForGC())
            {
                return(false);
            }

            if (!Native_UProperty.SameType(a.Address, b.Address))
            {
                return(false);
            }

            return(true);
        }
예제 #3
0
        private bool CanExportPropertyImpl(UProperty property, UStruct owner, bool isBlueprintType)
        {
            // There seem to be a lot of values which could potentially make a property visible from blueprint
            // TODO: Find all of the remaining values which we need to check

            // TODO: Make this stops the search? There shouldn't be any more owner properties once it reaches
            // the first non-owner owned property
            if (isBlueprintType && property.GetOwnerStruct() != owner)
            {
                return(false);
            }

            if (Settings.ExportAllProperties)
            {
                return(true);
            }

            if (property.HasAnyPropertyFlags(EPropertyFlags.Deprecated))
            {
                return(false);
            }

            return(property.HasAnyPropertyFlags(EPropertyFlags.BlueprintVisible | EPropertyFlags.BlueprintAssignable) &&
                   (!property.HasAnyPropertyFlags(EPropertyFlags.NativeAccessSpecifierPrivate) || property.GetBoolMetaData(MDProp.AllowPrivateAccess)) &&
                   (!property.GetBoolMetaData(MDProp.BlueprintPrivate) || property.GetBoolMetaData(MDProp.AllowPrivateAccess)));
            //property.HasAnyPropertyFlags(EPropertyFlags.NativeAccessSpecifierPublic | EPropertyFlags.NativeAccessSpecifierProtected | EPropertyFlags.Protected);
        }
예제 #4
0
            public void AddProperty(UProperty property, string bpVarName, bool exportable)
            {
                // If the ScriptName metadata is set use that for the property name instead
                string scriptName = property.GetMetaData(MDProp.ScriptName);

                if (!string.IsNullOrEmpty(scriptName))
                {
                    bpVarName = scriptName;
                }

                allProperties.Add(property, bpVarName);

                if (exportable)
                {
                    exportableProperties.Add(property, bpVarName);
                    if (IsBlittable && (!codeGenerator.IsBlittablePropertyType(property) || property.IsFixedSizeArray))
                    {
                        IsBlittable = false;
                    }
                }
                else
                {
                    nonExportableProperties.Add(property, bpVarName);

                    // This property isn't being exported, our struct size wont match the real struct size
                    IsBlittable = false;
                }
            }
예제 #5
0
        /// <summary>
        /// Returns the string representation of the equivalent output of a marshaler on zeroed memory for the given UProperty.
        /// For most types this will be "default(XXXX)".
        /// </summary>
        private string GetPropertyMarshalerDefaultValue(UProperty property, List <string> namespaces)
        {
            string typeName = GetTypeName(property, namespaces);

            // NOTE: Most of this is pretty useless, just remove this and use default(XXXX);

            // TODO: Implement and return safe versions of TArray/TSet/TMap which wrap a regular collection type
            // so that code which normally wouldn't result in an error can execute normally

            if (property.IsFixedSizeArray)
            {
                return("default(" + typeName + ")");
            }

            switch (property.PropertyType)
            {
            case EPropertyType.Delegate:
            case EPropertyType.MulticastDelegate:
                return("new " + typeName + "()");

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

            default:
                return("default(" + typeName + ")");
            }
        }
예제 #6
0
 /// <summary>
 /// Returns true if the marshaler requires the property address for marshaling (in the FromNative/ToNative methods)
 /// </summary>
 private bool MarshalerRequiresNativePropertyField(UProperty property)
 {
     if (IsCollectionProperty(property))
     {
         // Collections need the property for creating the marshaler, but not for the actual marshaling itself
         return(false);
     }
     return(RequiresNativePropertyField(property));
 }
예제 #7
0
 public static UObject FindImportedObject(UProperty property, UObject ownerObject, UObject objectClass, UClass requiredMetaClass, string text, uint portFlags)
 {
     using (FStringUnsafe textUnsafe = new FStringUnsafe(text))
     {
         return(GCHelper.Find(Native_UObjectPropertyBase.FindImportedObject(
                                  property == null ? IntPtr.Zero : property.Address,
                                  ownerObject == null ? IntPtr.Zero : ownerObject.Address,
                                  objectClass == null ? IntPtr.Zero : objectClass.Address,
                                  requiredMetaClass == null ? IntPtr.Zero : requiredMetaClass.Address,
                                  ref textUnsafe.Array,
                                  portFlags)));
     }
 }
예제 #8
0
        private bool CanExportProperty(UProperty property, UStruct owner, bool isBlueprintType)
        {
            bool export = CanExportPropertyImpl(property, owner, isBlueprintType);

            if (!export && forceExportProperties.Contains(property.GetPathName()))
            {
                return(true);
            }
            if (export && forceHideProperties.Contains(property.GetPathName()))
            {
                return(false);
            }
            return(export);
        }
예제 #9
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);
        }
예제 #10
0
        /// <summary>
        /// Reimplementation of UFunction::IsSignatureCompatibleWith for debugging purposes
        /// (the native function with engine symbols debugs badly)
        /// </summary>
        internal bool InternalIsSignatureCompatibleWith(UFunction otherFunction, EPropertyFlags ignoreFlags)
        {
            // Early out if they're exactly the same function
            if (this == otherFunction)
            {
                return(true);
            }

            // Run thru the parameter property chains to compare each property
            TFieldIterator <UProperty> iteratorA = new TFieldIterator <UProperty>(this);
            TFieldIterator <UProperty> iteratorB = new TFieldIterator <UProperty>(otherFunction);

            while (iteratorA.Current != null && (iteratorA.Current.PropertyFlags.HasFlag(EPropertyFlags.Parm)))
            {
                if (iteratorB.Current != null && (iteratorB.Current.PropertyFlags.HasFlag(EPropertyFlags.Parm)))
                {
                    // Compare the two properties to make sure their types are identical
                    // Note: currently this requires both to be strictly identical and wouldn't allow functions that differ only by how derived a class is,
                    // which might be desirable when binding delegates, assuming there is directionality in the SignatureIsCompatibleWith call
                    UProperty propA = iteratorA.Current;
                    UProperty propB = iteratorB.Current;

                    EPropertyFlags flags1 = propA.PropertyFlags;
                    EPropertyFlags flags2 = propB.PropertyFlags;

                    if (!ArePropertiesTheSame(propA, propB, false))
                    {
                        // Type mismatch between an argument of A and B
                        return(false);
                    }

                    // Check the flags as well
                    EPropertyFlags propertyMash = propA.PropertyFlags ^ propB.PropertyFlags;
                    if ((propertyMash & ~ignoreFlags) != 0)
                    {
                        return(false);
                    }
                }
                else
                {
                    // B ran out of arguments before A did
                    return(false);
                }
                iteratorA.MoveNext();
                iteratorB.MoveNext();
            }

            // They matched all the way thru A's properties, but it could still be a mismatch if B has remaining parameters
            return(!(iteratorB.Current != null && (iteratorB.Current.PropertyFlags.HasFlag(EPropertyFlags.Parm))));
        }
예제 #11
0
        private void UpdateAvailableTypesProp(UProperty property)
        {
            UField field1 = null;
            UField field2 = null;

            GetStructEnumOrFuncFromProp(property, out field1, out field2);
            if (field1 != null)
            {
                UpdateAvailableTypes(field1);
            }
            if (field2 != null)
            {
                UpdateAvailableTypes(field2);
            }
        }
예제 #12
0
 /// <summary>
 /// Parses a text buffer into an object reference.
 /// </summary>
 /// <param name="property">the property that the value is being importing to</param>
 /// <param name="ownerObject">the object that is importing the value; used for determining search scope.</param>
 /// <param name="requiredMetaClass">the meta-class for the object to find; if the object that is resolved is not of this class type, the result is NULL.</param>
 /// <param name="portFlags">bitmask of EPropertyPortFlags that can modify the behavior of the search</param>
 /// <param name="buffer">the text to parse; should point to a textual representation of an object reference.  Can be just the object name (either fully
 /// fully qualified or not), or can be formatted as a const object reference (i.e. SomeClass'SomePackage.TheObject')
 /// When the function returns, Buffer will be pointing to the first character after the object value text in the input stream.</param>
 /// <param name="resolvedValue">receives the object that is resolved from the input text.</param>
 /// <returns>true if the text is successfully resolved into a valid object reference of the correct type, false otherwise.</returns>
 public static bool ParseObjectPropertyValue(UProperty property, UObject ownerObject, UClass requiredMetaClass, uint portFlags, string buffer, out UObject resolvedValue)
 {
     using (FStringUnsafe bufferUnsafe = new FStringUnsafe(buffer))
     {
         IntPtr outResolvedValueAddress = IntPtr.Zero;
         bool   result = Native_UObjectPropertyBase.ParseObjectPropertyValue(
             property == null ? IntPtr.Zero : property.Address,
             ownerObject == null ? IntPtr.Zero : ownerObject.Address,
             requiredMetaClass == null ? IntPtr.Zero : requiredMetaClass.Address,
             portFlags,
             ref bufferUnsafe.Array,
             ref outResolvedValueAddress);
         resolvedValue = GCHelper.Find(outResolvedValueAddress);
         return(result);
     }
 }
예제 #13
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();
            }
        }
예제 #14
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);
            }
        }
            public void AddProperty(UProperty property, string bpVarName, bool exportable)
            {
                allProperties.Add(property, bpVarName);

                if (exportable)
                {
                    exportableProperties.Add(property, bpVarName);
                    if (IsBlittable && (!codeGenerator.IsBlittablePropertyType(property) || property.IsFixedSizeArray))
                    {
                        IsBlittable = false;
                    }
                }
                else
                {
                    nonExportableProperties.Add(property, bpVarName);

                    // This property isn't being exported, our struct size wont match the real struct size
                    IsBlittable = false;
                }
            }
예제 #16
0
                private void AddMember(UField field, string name, bool isResolvedName)
                {
                    CollapsedMember collapsedMember = null;

                    UProperty property = field as UProperty;

                    if (property != null)
                    {
                        structInfo.collapsedMembersByProperty.TryGetValue(property, out collapsedMember);
                    }

                    UFunction function = field as UFunction;

                    if (function != null)
                    {
                        structInfo.collapsedMembersByFunction.TryGetValue(function, out collapsedMember);
                    }

                    if (collapsedMember != null)
                    {
                        if (isResolvedName)
                        {
                            collapsedMember.ResolvedName = name;
                        }
                        else
                        {
                            name = collapsedMember.Name;
                        }
                    }

                    NameConflictFieldInfo fieldInfo;

                    if (!MembersByName.TryGetValue(name, out fieldInfo))
                    {
                        MembersByName.Add(name, fieldInfo = new NameConflictFieldInfo(name));
                    }
                    fieldInfo.AddField(field, collapsedMember);
                }
예제 #17
0
        /// <summary>
        /// Returns true if the property address is required by generated code
        /// </summary>
        private bool RequiresNativePropertyField(UProperty property)
        {
            if (!Settings.LazyFunctionParamInitDestroy && property.GetOwnerStruct().IsA <UFunction>())
            {
                // We need the property address to call InitializeValue / DestroyValue
                if (!property.HasAllPropertyFlags(EPropertyFlags.ZeroConstructor | EPropertyFlags.NoDestructor))
                {
                    return(true);
                }
                return(true);
            }

            if (property.IsFixedSizeArray)
            {
                return(true);
            }
            switch (property.PropertyType)
            {
            case EPropertyType.Enum:
            case EPropertyType.Bool:
            case EPropertyType.Array:
            case EPropertyType.Set:
            case EPropertyType.Map:
                return(true);

            default:
                UNumericProperty numericProperty = property as UNumericProperty;
                if ((numericProperty != null && numericProperty.IsEnum && numericProperty.GetIntPropertyEnum() != null))
                {
                    return(true);
                }
                break;
            }

            return(false);
        }
예제 #18
0
        private string GetBlittablePropertyTypeName(UProperty property, List <string> namespaces)
        {
            if (!IsBlittablePropertyType(property))
            {
                return(null);
            }

            switch (property.PropertyType)
            {
            case EPropertyType.Name: return(Names.FName);

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

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

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

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

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

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

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

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

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

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

            case EPropertyType.Struct: return(GetTypeName(property, namespaces));

            default: return(null);
            }
        }
예제 #19
0
        /// <summary>
        /// Blueprints will always have return values as out values. If there is a single out value treat it
        /// as the return value instead.
        /// </summary>
        internal UProperty GetBlueprintReturnProperty()
        {
            UClass owner           = GetOwnerClass();
            bool   isBlueprintType = owner != null && owner.IsA <UBlueprintGeneratedClass>();

            if (!isBlueprintType)
            {
                return(null);
            }

            if (GetReturnProperty() != null)
            {
                return(null);
            }

            UProperty returnProperty = null;

            foreach (UProperty parameter in GetFields <UProperty>())
            {
                if (!parameter.HasAnyPropertyFlags(EPropertyFlags.Parm))
                {
                    continue;
                }

                if (parameter.HasAnyPropertyFlags(EPropertyFlags.OutParm) &&
                    !parameter.HasAnyPropertyFlags(EPropertyFlags.ReferenceParm))
                {
                    if (returnProperty != null)
                    {
                        return(null);
                    }
                    returnProperty = parameter;
                }
            }
            return(returnProperty);
        }
예제 #20
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);
            }
        }
예제 #21
0
 private string GetMarshalerFromProperty(UProperty property, List <string> namespaces, bool isFunction)
 {
     return(GetMarshalerFromProperty(property, namespaces, isFunction, false));
 }
예제 #22
0
 private void AppendPropertyDestroy(CSharpTextBuilder builder, UProperty property, string propertyName,
                                    string baseAddressName, List <string> namespaces)
 {
     throw new NotImplementedException();
 }
예제 #23
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();
        }
예제 #24
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);
                    }
                }
            }
        }
예제 #25
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
                {
                    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) + "]");
            }
        }
예제 #26
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 + ");");
            }
        }
예제 #27
0
 /// <summary>
 /// Returns true if the owner of the given property is a UClass or a UScriptStruct which is being generated
 /// as a class in managed code
 /// </summary>
 private bool IsOwnerClassOrStructAsClass(UProperty property)
 {
     return(IsClassOrStructAsClass(property.GetOwnerStruct()));
 }
예제 #28
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);
 }
예제 #29
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;
            }
        }
예제 #30
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();
        }