Skip to content

Commit

Permalink
add indexers into struct, array, DataTableExport, asset; fix broken N…
Browse files Browse the repository at this point in the history
…ormalExport indexer; some fixes for HandleCloned; FName clone dummies; add TestClone test
  • Loading branch information
atenfyr committed Aug 16, 2024
1 parent 1342c05 commit 72910c9
Show file tree
Hide file tree
Showing 21 changed files with 354 additions and 39 deletions.
51 changes: 51 additions & 0 deletions UAssetAPI.Tests/AssetUnitTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,57 @@ public void TestEditorAssets()
public void TestTraditionalUE5_3()
{
TestUE5_3Subsection("Engine", EngineVersion.VER_UE5_3, new Usmap(Path.Combine("TestAssets", "TestUE5_3", "Engine", "Engine.usmap")));
TestUE5_3Subsection("RON", EngineVersion.VER_UE5_3, new Usmap(Path.Combine("TestAssets", "TestUE5_3", "RON", "ReadyOrNot.usmap")));
}

/// <summary>
/// In this test, we test the Clone function, along with indexers for assets and exports.
/// </summary>
[TestMethod]
public void TestClone()
{
var mappings = new Usmap(Path.Combine("TestAssets", "TestUE5_3", "RON", "ReadyOrNot.usmap"));

// clone everything and check for binary equality
var blueprint = new UAsset(Path.Combine("TestAssets", "TestUE5_3", "RON", "AmmoDataTable.uasset"), EngineVersion.VER_UE5_3, mappings);
for (int i = 0; i < blueprint.Exports.Count; i++)
{
Export curExp = blueprint.Exports[i];
if (curExp is NormalExport nExp)
{
for (int j = 0; j < nExp.Data.Count; j++)
{
nExp.Data[j] = (PropertyData)nExp.Data[j].Clone();
}
}
if (curExp is DataTableExport dtExp)
{
for (int j = 0; j < dtExp.Table.Data.Count; j++)
{
dtExp.Table.Data[j] = (StructPropertyData)dtExp.Table.Data[j].Clone();
}
}
}
Assert.IsTrue(blueprint.VerifyBinaryEquality());

// some basic tests with the indexers
DataTableExport exp = (DataTableExport)blueprint["AmmoDataTable"];
StructPropertyData struc = (StructPropertyData)exp["556x45JHP"];
StructPropertyData nuevo = (StructPropertyData)struc.Clone();
nuevo["Damage"] = new FloatPropertyData() { Value = 60 };
exp["556x45JHP_MODIFIED"] = nuevo;

// save, read again, and verify
blueprint.Write(blueprint.FilePath);

var blueprint2 = new UAsset(blueprint.FilePath, EngineVersion.VER_UE5_3, mappings);
Assert.IsTrue(blueprint2.VerifyBinaryEquality());

DataTableExport exp2 = (DataTableExport)blueprint["AmmoDataTable"];
StructPropertyData struc2 = (StructPropertyData)exp["556x45JHP"];
StructPropertyData struc2_2 = (StructPropertyData)exp["556x45JHP_MODIFIED"];
Assert.IsTrue(struc2["Damage"] is FloatPropertyData blah2 && blah2.Value == 30);
Assert.IsTrue(struc2_2["Damage"] is FloatPropertyData blah3 && blah3.Value == 60);
}

/// <summary>
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
9 changes: 9 additions & 0 deletions UAssetAPI.Tests/UAssetAPI.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,15 @@
<None Update="TestAssets\TestUE5_3\Engine\OpenWorld.umap">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="TestAssets\TestUE5_3\RON\AmmoDataTable.uasset">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="TestAssets\TestUE5_3\RON\AmmoDataTable.uexp">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="TestAssets\TestUE5_3\RON\ReadyOrNot.usmap">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="TestAssets\TestUnknownProperties\BP_DetPack_Charge.uasset">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
Expand Down
67 changes: 67 additions & 0 deletions UAssetAPI/ExportTypes/DataTableExport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,73 @@ public UDataTable(List<StructPropertyData> data)
/// </summary>
public class DataTableExport : NormalExport
{
/// <summary>
/// Gets or sets the value associated with the specified key. This operation loops linearly, so it may not be suitable for high-performance environments.
/// </summary>
/// <param name="key">The key associated with the value to get or set.</param>
public override PropertyData this[FName key]
{
get
{
for (int i = 0; i < Data.Count; i++)
{
if (Data[i].Name == key) return Data[i];
}
for (int i = 0; i < Table.Data.Count; i++)
{
if (Table.Data[i].Name == key) return Table.Data[i];
}
return null;
}
set
{
value.Name = key;

for (int i = 0; i < Data.Count; i++)
{
if (Data[i].Name == key)
{
Data[i] = value;
return;
}
}

if (value is StructPropertyData)
{
for (int i = 0; i < Table.Data.Count; i++)
{
if (Table.Data[i].Name == key)
{
Table.Data[i] = (StructPropertyData)value;
return;
}
}

Table.Data.Add((StructPropertyData)value);
}
else
{
Data.Add(value);
}
}
}

/// <summary>
/// Gets or sets the value associated with the specified key. This operation loops linearly, so it may not be suitable for high-performance environments.
/// </summary>
/// <param name="key">The key associated with the value to get or set.</param>
public override PropertyData this[string key]
{
get
{
return this[FName.FromString(Asset, key)];
}
set
{
this[FName.FromString(Asset, key)] = value;
}
}

public UDataTable Table;

public DataTableExport(Export super) : base(super)
Expand Down
11 changes: 7 additions & 4 deletions UAssetAPI/ExportTypes/NormalExport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class NormalExport : Export
/// Gets or sets the value associated with the specified key. This operation loops linearly, so it may not be suitable for high-performance environments.
/// </summary>
/// <param name="key">The key associated with the value to get or set.</param>
public PropertyData this[FName key]
public virtual PropertyData this[FName key]
{
get
{
Expand All @@ -29,23 +29,26 @@ public PropertyData this[FName key]
}
set
{
value.Name = key;

for (int i = 0; i < Data.Count; i++)
{
if (Data[i].Name == key)
{
Data[i] = value;
Data[i].Name = key;
break;
return;
}
}

Data.Add(value);
}
}

/// <summary>
/// Gets or sets the value associated with the specified key. This operation loops linearly, so it may not be suitable for high-performance environments.
/// </summary>
/// <param name="key">The key associated with the value to get or set.</param>
public PropertyData this[string key]
public virtual PropertyData this[string key]
{
get
{
Expand Down
53 changes: 53 additions & 0 deletions UAssetAPI/PropertyTypes/Objects/ArrayPropertyData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,59 @@ public bool ShouldSerializeDummyStruct()
return Value.Length == 0;
}

/// <summary>
/// Gets or sets the value associated with the specified key. This operation loops linearly, so it may not be suitable for high-performance environments.
/// </summary>
/// <param name="key">The key associated with the value to get or set.</param>
public virtual PropertyData this[FName key]
{
get
{
if (Value == null) return null;

for (int i = 0; i < Value.Length; i++)
{
if (Value[i].Name == key) return Value[i];
}
return null;
}
set
{
if (Value == null) Value = [];
value.Name = key;

for (int i = 0; i < Value.Length; i++)
{
if (Value[i].Name == key)
{
Value[i] = value;
return;
}
}

var newValue = new PropertyData[Value.Length + 1];
Array.Copy(Value, newValue, Value.Length);
newValue[newValue.Length - 1] = value;
Value = newValue;
}
}

/// <summary>
/// Gets or sets the value associated with the specified key. This operation loops linearly, so it may not be suitable for high-performance environments.
/// </summary>
/// <param name="key">The key associated with the value to get or set.</param>
public virtual PropertyData this[string key]
{
get
{
return this[FName.DefineDummy(null, key)];
}
set
{
this[FName.DefineDummy(null, key)] = value;
}
}

public ArrayPropertyData(FName name) : base(name)
{
Value = [];
Expand Down
1 change: 1 addition & 0 deletions UAssetAPI/PropertyTypes/Objects/EnumPropertyData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ protected override void HandleCloned(PropertyData res)
{
EnumPropertyData cloningProperty = (EnumPropertyData)res;
cloningProperty.EnumType = (FName)this.EnumType?.Clone();
cloningProperty.InnerType = (FName)this.InnerType?.Clone();
}
}
}
21 changes: 14 additions & 7 deletions UAssetAPI/PropertyTypes/Objects/MapPropertyData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -220,17 +220,24 @@ protected override void HandleCloned(PropertyData res)
{
MapPropertyData cloningProperty = (MapPropertyData)res;

var newDict = new TMap<PropertyData, PropertyData>();
foreach (var entry in this.Value)
if (this.Value != null)
{
newDict[(PropertyData)entry.Key.Clone()] = (PropertyData)entry.Value.Clone();
var newDict = new TMap<PropertyData, PropertyData>();
foreach (var entry in this.Value)
{
newDict[(PropertyData)entry.Key.Clone()] = (PropertyData)entry.Value.Clone();
}
cloningProperty.Value = newDict;
}
else
{
cloningProperty.Value = null;
}
cloningProperty.Value = newDict;

cloningProperty.KeysToRemove = (PropertyData[])this.KeysToRemove.Clone();
cloningProperty.KeysToRemove = (PropertyData[])this.KeysToRemove?.Clone();

cloningProperty.KeyType = (FName)this.KeyType.Clone();
cloningProperty.ValueType = (FName)this.ValueType.Clone();
cloningProperty.KeyType = (FName)this.KeyType?.Clone();
cloningProperty.ValueType = (FName)this.ValueType?.Clone();
}
}
}
17 changes: 12 additions & 5 deletions UAssetAPI/PropertyTypes/Objects/MulticastDelegatePropertyData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,20 @@ protected override void HandleCloned(PropertyData res)
{
MulticastDelegatePropertyData cloningProperty = (MulticastDelegatePropertyData)res;

FDelegate[] newData = new FDelegate[Value.Length];
for (int i = 0; i < Value.Length; i++)
if (Value != null)
{
newData[i] = new FDelegate(Value[i].Object, (FName)Value[i].Delegate.Clone());
}
FDelegate[] newData = new FDelegate[Value.Length];
for (int i = 0; i < Value.Length; i++)
{
newData[i] = new FDelegate(Value[i].Object, (FName)Value[i].Delegate.Clone());
}

cloningProperty.Value = newData;
cloningProperty.Value = newData;
}
else
{
cloningProperty.Value = null;
}
}
}

Expand Down
15 changes: 11 additions & 4 deletions UAssetAPI/PropertyTypes/Objects/SetPropertyData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,18 @@ protected override void HandleCloned(PropertyData res)
base.HandleCloned(res);
SetPropertyData cloningProperty = (SetPropertyData)res;

PropertyData[] newData = new PropertyData[this.ElementsToRemove.Length];
for (int i = 0; i < this.Value.Length; i++)
if (this.ElementsToRemove != null)
{
newData[i] = (PropertyData)this.Value[i].Clone();
PropertyData[] newData = new PropertyData[this.ElementsToRemove.Length];
for (int i = 0; i < this.Value.Length; i++)
{
newData[i] = (PropertyData)this.Value[i].Clone();
}
cloningProperty.ElementsToRemove = newData;
}
else
{
cloningProperty.ElementsToRemove = null;
}
cloningProperty.ElementsToRemove = newData;
}
}
6 changes: 3 additions & 3 deletions UAssetAPI/PropertyTypes/Objects/TextPropertyData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -456,8 +456,8 @@ protected override void HandleCloned(PropertyData res)
{
TextPropertyData cloningProperty = (TextPropertyData)res;

cloningProperty.TableId = (FName)TableId.Clone();
cloningProperty.Namespace = (FString)Namespace.Clone();
cloningProperty.Namespace = (FString)CultureInvariantString.Clone();
cloningProperty.TableId = (FName)TableId?.Clone();
cloningProperty.Namespace = (FString)Namespace?.Clone();
cloningProperty.CultureInvariantString = (FString)CultureInvariantString?.Clone();
}
}
2 changes: 1 addition & 1 deletion UAssetAPI/PropertyTypes/Objects/UnknownPropertyData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ protected override void HandleCloned(PropertyData res)
{
UnknownPropertyData cloningProperty = (UnknownPropertyData)res;

cloningProperty.SerializingPropertyType = (FString)SerializingPropertyType.Clone();
cloningProperty.SerializingPropertyType = (FString)SerializingPropertyType?.Clone();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,6 @@ public override string ToString()
protected override void HandleCloned(PropertyData res)
{
DateTimePropertyData cloningProperty = (DateTimePropertyData)res;
cloningProperty.Value = new DateTime(cloningProperty.Value.Ticks);
cloningProperty.Value = new DateTime(this.Value.Ticks);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,6 @@ public override string ToString()
protected override void HandleCloned(PropertyData res)
{
TimespanPropertyData cloningProperty = (TimespanPropertyData)res;
cloningProperty.Value = new TimeSpan(cloningProperty.Value.Ticks);
cloningProperty.Value = new TimeSpan(this.Value.Ticks);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@ protected int WriteExpressionInput(AssetBinaryWriter writer, bool includeHeader)
protected override void HandleCloned(PropertyData res)
{
MaterialInputPropertyData<T> cloningProperty = (MaterialInputPropertyData<T>)res;
cloningProperty.InputName = (FName)this.InputName.Clone();
cloningProperty.InputNameOld = (FString)this.InputNameOld.Clone();
cloningProperty.ExpressionName = (FName)this.ExpressionName.Clone();
cloningProperty.InputName = (FName)this.InputName?.Clone();
cloningProperty.InputNameOld = (FString)this.InputNameOld?.Clone();
cloningProperty.ExpressionName = (FName)this.ExpressionName?.Clone();
}
}

Expand Down
Loading

0 comments on commit 72910c9

Please sign in to comment.