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); } } } }
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); } }
/// <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; } }
public FScriptMapHelper(UMapProperty property) : this(property.Address, IntPtr.Zero) { }
public FScriptMapHelper(UMapProperty property, IntPtr map) : this(property.Address, map) { }
// 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); }
public void Destroy(UMapProperty property) { Destroy(property.Address); }