Skip to content

Commit

Permalink
UPropertis mappings generation
Browse files Browse the repository at this point in the history
  • Loading branch information
LongerWarrior committed Jul 4, 2024
1 parent 88adbe1 commit 8f8d1b6
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 10 deletions.
45 changes: 45 additions & 0 deletions UAssetAPI/FieldTypes/UField.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using UAssetAPI.UnrealTypes;
using UAssetAPI.ExportTypes;
using UAssetAPI.CustomVersions;
using UAssetAPI.Unversioned;

namespace UAssetAPI.FieldTypes;

Expand Down Expand Up @@ -89,6 +90,50 @@ public override void Write(AssetBinaryWriter writer)
}

public UProperty() { }

public EPropertyType GetUsmapPropertyType()
{
return this switch
{
UEnumProperty => EPropertyType.EnumProperty,
UByteProperty => EPropertyType.ByteProperty,
UBoolProperty => EPropertyType.BoolProperty,
UInt8Property => EPropertyType.Int8Property,
UInt16Property => EPropertyType.Int16Property,
UIntProperty => EPropertyType.IntProperty,
UInt64Property => EPropertyType.Int64Property,
UUInt16Property => EPropertyType.UInt16Property,
UUInt32Property => EPropertyType.UInt32Property,
UUInt64Property => EPropertyType.UInt64Property,
UFloatProperty => EPropertyType.FloatProperty,
UDoubleProperty => EPropertyType.DoubleProperty,

UAssetClassProperty => EPropertyType.SoftObjectProperty,
USoftClassProperty => EPropertyType.SoftObjectProperty,
UClassProperty => EPropertyType.ObjectProperty,
UAssetObjectProperty => EPropertyType.AssetObjectProperty,
UWeakObjectProperty => EPropertyType.WeakObjectProperty,
ULazyObjectProperty => EPropertyType.LazyObjectProperty,
USoftObjectProperty => EPropertyType.SoftObjectProperty,
UObjectProperty => EPropertyType.ObjectProperty,

UNameProperty => EPropertyType.NameProperty,
UStrProperty => EPropertyType.StrProperty,
UTextProperty => EPropertyType.TextProperty,

UInterfaceProperty => EPropertyType.InterfaceProperty,

UMulticastDelegateProperty => EPropertyType.MulticastDelegateProperty,
UDelegateProperty => EPropertyType.DelegateProperty,

UMapProperty => EPropertyType.MapProperty,
USetProperty => EPropertyType.SetProperty,
UArrayProperty => EPropertyType.ArrayProperty,
UStructProperty => EPropertyType.StructProperty,

_ => EPropertyType.Unknown,
};
}
}

public class UEnumProperty : UProperty
Expand Down
12 changes: 8 additions & 4 deletions UAssetAPI/UnrealTypes/FPackageIndex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,14 @@ public Import ToImport(UnrealPackage asset)
/// <exception cref="System.InvalidOperationException">Thrown when this is not an index into the export map.</exception>
public Export ToExport(UnrealPackage asset)
{
if (!IsExport()) throw new InvalidOperationException("Index = " + Index + "; cannot call ToExport()");
int newIndex = Index - 1;
if (newIndex < 0 || newIndex >= asset.Exports.Count) return null;
return asset.Exports[newIndex];
if (!IsExport() || Index > asset.Exports.Count) throw new InvalidOperationException("Index = " + Index + "; cannot call ToExport()");
return asset.Exports[Index - 1];
}

public T ToExport<T>(UnrealPackage asset) where T : Export
{
if (!IsExport() || Index > asset.Exports.Count) throw new InvalidOperationException("Index = " + Index + "; cannot call ToExport()");
return (T)asset.Exports[Index-1];
}

public override bool Equals(object obj)
Expand Down
125 changes: 119 additions & 6 deletions UAssetAPI/Unversioned/Usmap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UAssetAPI.CustomVersions;
using UAssetAPI.ExportTypes;
using UAssetAPI.FieldTypes;
using UAssetAPI.PropertyTypes.Objects;
Expand Down Expand Up @@ -424,7 +425,7 @@ private static UsmapPropertyData ConvertFPropertyToUsmapPropertyData(StructExpor
var underlyingProp = (entry as FEnumProperty).UnderlyingProp;
if (enumIndex.IsExport())
{
var exp2 = enumIndex.ToExport(exp.Asset) as EnumExport;
var exp2 = enumIndex.ToExport<EnumExport>(exp.Asset);
var allNames = new List<string>();
foreach (var cosa in exp2.Enum.Names) allNames.Add(cosa.Item1.ToString());
converted1 = new UsmapEnumData(exp2.ObjectName.ToString(), allNames) { InnerType = ConvertFPropertyToUsmapPropertyData(exp, underlyingProp) };
Expand Down Expand Up @@ -458,7 +459,7 @@ private static UsmapPropertyData ConvertFPropertyToUsmapPropertyData(StructExpor
FPackageIndex enumIndex = (entry as FByteProperty).Enum;
if (enumIndex.IsExport())
{
var exp2 = enumIndex.ToExport(exp.Asset) as EnumExport;
var exp2 = enumIndex.ToExport<EnumExport>(exp.Asset);
var allNames = new List<string>();
foreach (var cosa in exp2.Enum.Names) allNames.Add(cosa.Item1.ToString());
converted1 = new UsmapEnumData(exp2.ObjectName.ToString(), allNames) { InnerType = new UsmapPropertyData(EPropertyType.ByteProperty) };
Expand Down Expand Up @@ -511,6 +512,103 @@ private static UsmapPropertyData ConvertFPropertyToUsmapPropertyData(StructExpor
return converted1;
}

private static UsmapPropertyData ConvertUPropertyToUsmapPropertyData(PropertyExport exp)
{
var asset = exp.Asset;
var typ = exp.Property.GetUsmapPropertyType();
UsmapPropertyData converted;
switch (exp.Property)
{
case UEnumProperty enumprop:
var enumIndex = enumprop.Enum;
var underlyingProp = enumprop.UnderlyingProp;
if (enumIndex.IsExport())
{
var exp2 = enumIndex.ToExport<EnumExport>(exp.Asset);
var allNames = new List<string>();
foreach (var cosa in exp2.Enum.Names) allNames.Add(cosa.Item1.ToString());
converted = new UsmapEnumData(exp2.ObjectName.ToString(), allNames) { InnerType = ConvertUPropertyToUsmapPropertyData(underlyingProp.ToExport<PropertyExport>(asset)) };
}
else if (enumIndex.IsImport())
{
string enumName = enumIndex.ToImport(exp.Asset).ObjectName?.Value.Value;
if (enumName == null || !exp.Asset.Mappings.EnumMap.TryGetValue(enumName, out UsmapEnum value))
{
if (!exp.Asset.HasUnversionedProperties)
{
return new UsmapEnumData(enumName, []) { InnerType = new UsmapPropertyData(EPropertyType.ByteProperty) };
}
else
{
throw new InvalidOperationException("Attempt to index into non-existent enum " + enumName);
}
}
var allNames = new List<string>();
foreach (var cosa in value.Values) allNames.Add(cosa.ToString());
converted = new UsmapEnumData(enumName, allNames) { InnerType = ConvertUPropertyToUsmapPropertyData(underlyingProp.ToExport<PropertyExport>(asset)) };
}
else
{
converted = null;
}
break;
case UByteProperty byt:
enumIndex = byt.Enum;
if (enumIndex.IsExport())
{
var exp2 = enumIndex.ToExport<EnumExport>(exp.Asset);
var allNames = new List<string>();
foreach (var cosa in exp2.Enum.Names) allNames.Add(cosa.Item1.ToString());
converted = new UsmapEnumData(exp2.ObjectName.ToString(), allNames) { InnerType = new UsmapPropertyData(EPropertyType.ByteProperty) };
}
else if (enumIndex.IsImport())
{
string enumName = enumIndex.ToImport(exp.Asset).ObjectName?.Value.Value;
if (enumName == null || !exp.Asset.Mappings.EnumMap.TryGetValue(enumName, out UsmapEnum value))
{
if (!exp.Asset.HasUnversionedProperties)
{
return new UsmapEnumData(enumName, []) { InnerType = new UsmapPropertyData(EPropertyType.ByteProperty) };
}
else
{
//should not happen cause it was before 425
throw new InvalidOperationException("Attempt to index into non-existent enum " + enumName);
}
}
var allNames = new List<string>();
foreach (var cosa in value.Values) allNames.Add(cosa.ToString());
converted = new UsmapEnumData(enumName, allNames) { InnerType = new UsmapPropertyData(EPropertyType.ByteProperty) };
}
else
{
converted = new UsmapPropertyData(EPropertyType.ByteProperty); // this is most likely an InnerType of an EnumProperty
}
break;
case UStructProperty strukt:
var strucstr = Export.GetClassTypeForAncestry(strukt.Struct, asset, out _);
converted = new UsmapStructData(strucstr.ToString());
break;
case UArrayProperty array:
converted = new UsmapArrayData(EPropertyType.ArrayProperty) { InnerType = ConvertUPropertyToUsmapPropertyData(array.Inner.ToExport<PropertyExport>(asset)) };
break;
case USetProperty set:
converted = new UsmapArrayData(EPropertyType.SetProperty) { InnerType = ConvertUPropertyToUsmapPropertyData(set.ElementProp.ToExport<PropertyExport>(asset)) };
break;
case UMapProperty map:
converted = new UsmapMapData()
{
InnerType = ConvertUPropertyToUsmapPropertyData(map.KeyProp.ToExport<PropertyExport>(asset)),
ValueType = ConvertUPropertyToUsmapPropertyData(map.ValueProp.ToExport<PropertyExport>(asset))
};
break;
default:
converted = new UsmapPropertyData(typ);
break;
}
return converted;
}

public static UsmapSchema GetSchemaFromStructExport(string exportName, UnrealPackage asset)
{
if (asset == null) throw new InvalidOperationException("Cannot evaluate struct export without package reference");
Expand All @@ -525,12 +623,27 @@ public static UsmapSchema GetSchemaFromStructExport(StructExport exp, bool isCas
{
var res = new Dictionary<int, UsmapProperty>();
int idx = 0;
foreach (FProperty entry in exp.LoadedProperties)
if (exp.Asset.GetCustomVersion<FCoreObjectVersion>() >= FCoreObjectVersion.FProperties)
{
UsmapProperty converted = new UsmapProperty(entry.Name.ToString(), (ushort)idx, 0, 1, ConvertFPropertyToUsmapPropertyData(exp, entry));
res.Add(idx, converted);
idx++;
foreach (FProperty entry in exp.LoadedProperties)
{
UsmapProperty converted = new UsmapProperty(entry.Name.ToString(), (ushort)idx, 0, 1, ConvertFPropertyToUsmapPropertyData(exp, entry));
res.Add(idx, converted);
idx++;
}
}
else
{
foreach (var entry in exp.Children)
{
if (entry.ToExport(exp.Asset) is not PropertyExport field) continue;

UsmapProperty converted = new UsmapProperty(field.ObjectName.ToString(), (ushort)idx, 0, 1, ConvertUPropertyToUsmapPropertyData(field));
res.Add(idx, converted);
idx++;
}
}

return new UsmapSchema(exp.ObjectName.ToString(), exp.SuperStruct.IsImport() ? exp.SuperStruct.ToImport(exp.Asset).ObjectName.ToString() : null, (ushort)res.Count, res, isCaseInsensitive, true);
}

Expand Down

0 comments on commit 8f8d1b6

Please sign in to comment.