private static void SetAllMetaData(IntPtr obj, ManagedUnrealReflectionBase field, UMeta.Target target) { if (!FBuild.WithEditor || !metaDataEnabled || field == null || string.IsNullOrEmpty(field.Path)) { return; } IntPtr outermost = Native_UObjectBaseUtility.GetOutermost(obj); IntPtr metadata = outermost == IntPtr.Zero ? IntPtr.Zero : Native_UPackage.GetMetaData(outermost); if (metadata == IntPtr.Zero) { return; } Dictionary <FName, string> values = null; if (!metaDataMap.TryGetValue(field.Path.ToLower(), out values)) { values = new Dictionary <FName, string>(); } switch (target) { // Class / interface case UMeta.Target.Class: case UMeta.Target.Interface: // See GetMetadataKeyword (Engine\Source\Programs\UnrealHeaderTool\Private\BaseParser.cpp) // "NotBlueprintable" removes "NotBlueprintable" and adds "IsBlueprintBase=false" // "Blueprintable" and adds "IsBlueprintBase=true" // "BlueprintInternalUseOnly" adds "BlueprintType" if (!values.ContainsKey(UMeta.GetKeyName(MDClass.IsBlueprintBase))) { if (values.ContainsKey(UMeta.GetKeyName(MDClass.Blueprintable))) { values[UMeta.GetKeyName(MDClass.IsBlueprintBase)] = "true"; } else if (values.ContainsKey(UMeta.GetKeyName(MDClass.NotBlueprintable))) { values[UMeta.GetKeyName(MDClass.IsBlueprintBase)] = "false"; } } MetaDataMergeClassCategories(metadata, obj, values); break; } SetMetaDataBlueprintability(values, target, field as ManagedUnrealTypeInfo); using (TArrayUnsafe <FName> keysUnsafe = new TArrayUnsafe <FName>()) using (TArrayUnsafe <string> valuesUnsafe = new TArrayUnsafe <string>()) { keysUnsafe.AddRange(values.Keys.ToArray()); valuesUnsafe.AddRange(values.Values.ToArray()); Native_UMetaData.SetObjectValues(metadata, obj, keysUnsafe.Address, valuesUnsafe.Address); } }
private IntPtr CreateProperty(IntPtr outer, PropertyInfo propertyInfo) { // Note that HeaderParser.cpp and UObjectGlobals.cpp use "new" instead of NewObject for creating properties // KismetCompilerMisc.cpp uses NewObject // The "new" initialization sets the offset and adds the property to the owner which in the case of UStruct // does the following: // void UStruct::AddCppProperty(UProperty* Property) { Property->Next = Children; Children = Property; } USharpPathAttribute pathAttribute = propertyInfo.GetCustomAttribute <USharpPathAttribute>(); if (pathAttribute == null) { return(IntPtr.Zero); } string root, directory, moduleName, typeName, propertyName; FPackageName.GetPathInfo(pathAttribute.Path, out root, out directory, out moduleName, out typeName, out propertyName); if (string.IsNullOrEmpty(propertyName)) { return(IntPtr.Zero); } IntPtr property = CreateProperty(outer, propertyInfo.PropertyType, propertyName, pathAttribute.PropertyType, pathAttribute.InnerPropertyType1, pathAttribute.InnerPropertyType2); if (property == IntPtr.Zero) { return(IntPtr.Zero); } if (FBuild.WithMetaData) { IntPtr outermost = Native_UObjectBaseUtility.GetOutermost(property); IntPtr metadata = outermost == IntPtr.Zero ? IntPtr.Zero : Native_UPackage.GetMetaData(outermost); if (metadata != IntPtr.Zero) { string categoryName = null; //propertyInfo.GetCustomAttribute if (string.IsNullOrEmpty(categoryName)) { categoryName = "Default"; } SetMetaData(metadata, property, "Category", categoryName); } } return(property); }