Skip to content

Commit

Permalink
Rewrite StateChunk to be version independent, parse FeedbackInfo
Browse files Browse the repository at this point in the history
  • Loading branch information
henbagle committed Dec 7, 2023
1 parent 662f677 commit c6a6479
Show file tree
Hide file tree
Showing 13 changed files with 244 additions and 55 deletions.
8 changes: 4 additions & 4 deletions ME3Tweaks.Wwiser.Tests/HierarchyTests/StateChunkTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ namespace ME3Tweaks.Wwiser.Tests.HierarchyTests;

public class StateChunkTests
{
[Test]
public void V134_EmptyStateChunkAware_Parses()
[TestCase(new byte[] {00, 00}, 134)]
[TestCase(new byte[] {00, 00, 00, 00}, 120)]
public void Empty_MultipleVersions_Parses(byte[] data, int version)
{
byte[] data = { 00, 00 };
var (_, result) = TestHelpers.Deserialize<StateChunk_Aware>(data, 134);
var (_, result) = TestHelpers.Deserialize<StateChunk>(data, version);

Assert.Multiple(() =>
{
Expand Down
3 changes: 2 additions & 1 deletion ME3Tweaks.Wwiser/Model/Hierarchy/Attenuation.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using BinarySerialization;
using ME3Tweaks.Wwiser.Attributes;
using ME3Tweaks.Wwiser.Model.ParameterNode;
using ME3Tweaks.Wwiser.Model.RTPC;

namespace ME3Tweaks.Wwiser.Model.Hierarchy;
Expand Down Expand Up @@ -31,7 +32,7 @@ public class Attenuation : HircItem
public List<RtpcConversionTable> Curves { get; set; } = new();

[FieldOrder(6)]
public RtpcCurves RtpcCurves { get; set; } = new();
public RtpcParameterNodeBase RtpcParameterNodeBase { get; set; } = new();
}

public class CurveToUse : IBinarySerializable
Expand Down
5 changes: 3 additions & 2 deletions ME3Tweaks.Wwiser/Model/Hierarchy/FxBase.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using BinarySerialization;
using ME3Tweaks.Wwiser.Attributes;
using ME3Tweaks.Wwiser.Formats;
using ME3Tweaks.Wwiser.Model.ParameterNode;
using ME3Tweaks.Wwiser.Model.Plugins;
using ME3Tweaks.Wwiser.Model.RTPC;
using ME3Tweaks.Wwiser.Model.State;
Expand Down Expand Up @@ -29,15 +30,15 @@ public class FxBase : HircItem
public List<MediaMapItem> Media { get; set; } = new();

[FieldOrder(5)]
public RtpcCurves RtpcCurves { get; set; } = new();
public RtpcParameterNodeBase RtpcParameterNodeBase { get; set; } = new();

[FieldOrder(6)]
[SerializeWhenVersionBetween(123, 126)]
public ushort Unk1 { get; set; }

[FieldOrder(7)]
[SerializeWhenVersion(126, ComparisonOperator.GreaterThan)]
public StateChunk_Aware StateChunk { get; set; } = new();
public StateChunk StateChunk { get; set; } = new();

[FieldOrder(8)]
[SerializeWhenVersion(90, ComparisonOperator.GreaterThan)]
Expand Down
89 changes: 89 additions & 0 deletions ME3Tweaks.Wwiser/Model/ParameterNode/FeedbackInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
using BinarySerialization;

namespace ME3Tweaks.Wwiser.Model.ParameterNode;

public class FeedbackInfo : IBinarySerializable
{
[Ignore]
public uint Size { get; set; }

[Ignore]
public uint[] Unks { get; set; } = Array.Empty<uint>();

[Ignore]
public uint BusId { get; set; }

[Ignore]
public float FeedbackVolume { get; set; }

[Ignore]
public float FeedbackModifierMin { get; set; }

[Ignore]
public float FeedbackModifierMax { get; set; }

[Ignore]
public float FeedbackLPF { get; set; }

[Ignore]
public float FeedbackLPFModifierMin { get; set; }

[Ignore]
public float FeedbackLPFModifierMax { get; set; }

public void Serialize(Stream stream, Endianness endianness, BinarySerializationContext serializationContext)
{
var context = serializationContext.FindAncestor<BankSerializationContext>();
if (!context.UseFeedback) return;
if (context.Version <= 26)
{
Size = (uint)Unks.Length * sizeof(uint);
stream.Write(BitConverter.GetBytes(Size));
foreach (var u in Unks)
{
stream.Write(BitConverter.GetBytes(u));
}
stream.Write(BitConverter.GetBytes(FeedbackVolume));
}
else
{
stream.Write(BitConverter.GetBytes(BusId));
if (BusId != 0)
{
stream.Write(BitConverter.GetBytes(FeedbackVolume));
stream.Write(BitConverter.GetBytes(FeedbackModifierMin));
stream.Write(BitConverter.GetBytes(FeedbackModifierMax));
stream.Write(BitConverter.GetBytes(FeedbackLPF));
stream.Write(BitConverter.GetBytes(FeedbackLPFModifierMin));
stream.Write(BitConverter.GetBytes(FeedbackLPFModifierMax));
}
}
}

public void Deserialize(Stream stream, Endianness endianness, BinarySerializationContext serializationContext)
{
var context = serializationContext.FindAncestor<BankSerializationContext>();
var reader = new BinaryReader(stream);
if (!context.UseFeedback) return;
if (context.Version <= 26)
{
Size = reader.ReadUInt32();
Unks = new uint[Size / 4];
Unks = Unks.Select(_ => reader.ReadUInt32()).ToArray();
FeedbackVolume = reader.ReadSingle();
}
else
{
BusId = reader.ReadUInt32();
if (BusId != 0)
{
FeedbackVolume = reader.ReadSingle();
FeedbackModifierMin = reader.ReadSingle();
FeedbackModifierMax = reader.ReadSingle();
FeedbackLPF = reader.ReadSingle();
FeedbackLPFModifierMin = reader.ReadSingle();
FeedbackLPFModifierMax = reader.ReadSingle();
}
}
}
}
19 changes: 19 additions & 0 deletions ME3Tweaks.Wwiser/Model/ParameterNode/NodeBaseParameters.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using BinarySerialization;
using ME3Tweaks.Wwiser.Attributes;
using ME3Tweaks.Wwiser.Model.Hierarchy.Enums;
using ME3Tweaks.Wwiser.Model.State;

namespace ME3Tweaks.Wwiser.Model.ParameterNode;

Expand All @@ -9,6 +10,8 @@ public class NodeBaseParameters
[FieldOrder(0)]
public InitialFxParams FxParams { get; set; } = new();

// TODO: InitialMetadataParams on >v136 - not relevant to mass effect

[FieldOrder(1)]
[SerializeAs(SerializedType.UInt1)]
[SerializeWhenVersionBetween(90, 145)]
Expand Down Expand Up @@ -53,4 +56,20 @@ public class NodeBaseParameters

[FieldOrder(12)]
public AdvSettingsParams AdvSettingsParams { get; set; } = new();

//TODO: Convert between the following two properties on version conversion
[FieldOrder(13)]
[SerializeWhenVersion(52, ComparisonOperator.LessThanOrEqual)]
public StateGroupChunk StateGroupChunk { get; set; } = new();

[FieldOrder(14)]
[SerializeWhenVersion(52, ComparisonOperator.GreaterThan)]
public StateChunk StateChunk { get; set; } = new();

[FieldOrder(15)]
public RtpcParameterNodeBase Rtpc { get; set; } = new();

[FieldOrder(16)]
[SerializeWhenVersion(126, ComparisonOperator.GreaterThan)]
public FeedbackInfo FeedbackInfo { get; set; } = new();
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using BinarySerialization;
using ME3Tweaks.Wwiser.Model.RTPC;

namespace ME3Tweaks.Wwiser.Model.RTPC;
namespace ME3Tweaks.Wwiser.Model.ParameterNode;

public class RtpcCurves
public class RtpcParameterNodeBase
{
//TODO: <=v36 this is a uint - not relevant to mass effect
[FieldOrder(0)]
Expand Down
9 changes: 0 additions & 9 deletions ME3Tweaks.Wwiser/Model/State/IStateChunk.cs

This file was deleted.

11 changes: 11 additions & 0 deletions ME3Tweaks.Wwiser/Model/State/State.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,22 @@ namespace ME3Tweaks.Wwiser.Model.State;

public class State : AkIdentifiable
{
[FieldOrder(0)]
[SerializeWhenVersion(120, ComparisonOperator.LessThanOrEqual)]
public uint StateId { get; set; }

[FieldOrder(1)]
[SerializeWhenVersion(52, ComparisonOperator.LessThanOrEqual)]
[SerializeAs(SerializedType.UInt1)]
public bool IsCustom { get; set; }

// Lower versions - reference to something else?
[FieldOrder(2)]
[SerializeWhenVersion(145, ComparisonOperator.LessThanOrEqual)]
public uint StateInstanceId { get; set; }

// Higher versions, data is inlined???? idk
[FieldOrder(3)]
[SerializeWhenVersion(145, ComparisonOperator.GreaterThan)]
public PropBundle<ushort, float> Properties { get; set; } = new();

Expand Down
13 changes: 12 additions & 1 deletion ME3Tweaks.Wwiser/Model/State/StateChunk.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
using BinarySerialization;
using ME3Tweaks.Wwiser.Attributes;
using ME3Tweaks.Wwiser.Formats;

namespace ME3Tweaks.Wwiser.Model.State;

public class StateChunk : IStateChunk
// Covers StateChunk and StateChunk_Aware?
public class StateChunk
{
[FieldOrder(0)]
[SerializeWhenVersion(125, ComparisonOperator.GreaterThan)]
public VarCount StatePropsCount { get; set; } = new();

[FieldOrder(1)]
[FieldCount($"{nameof(StatePropsCount)}.{nameof(StatePropsCount.Value)}")]
[SerializeWhenVersion(125, ComparisonOperator.GreaterThan)]
public List<StateProp> PropertyInfo { get; set; } = new();

[FieldOrder(2)]
public VarCount StateGroupsCount { get; set; } = new();

[FieldOrder(3)]
Expand Down
21 changes: 0 additions & 21 deletions ME3Tweaks.Wwiser/Model/State/StateChunk_Aware.cs

This file was deleted.

54 changes: 54 additions & 0 deletions ME3Tweaks.Wwiser/Model/State/StateCount.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using BinarySerialization;
using ME3Tweaks.Wwiser.Formats;

namespace ME3Tweaks.Wwiser.Model.State;

/// <summary>
/// Weirdly serialized count in different versions.
/// &lt;=122 it's a normal uint, otherwise some sort of space-saving uint
/// </summary>
public class StateCount : IBinarySerializable
{
[Ignore]
public uint Value { get; set; }

public void Serialize(Stream stream, Endianness endianness, BinarySerializationContext serializationContext)
{
var context = serializationContext.FindAncestor<BankSerializationContext>();
if (context.Version > 122)
{
VarCount.WriteResizingUint(stream, Value);
}
else if (context.Version is > 36 and <= 52)
{
stream.Write(BitConverter.GetBytes((ushort)Value));
}
else
{
stream.Write(BitConverter.GetBytes(Value));
}
}
public void Deserialize(Stream stream, Endianness endianness, BinarySerializationContext serializationContext)
{

var context = serializationContext.FindAncestor<BankSerializationContext>();
if (context.Version > 122)
{
Value = VarCount.ReadResizingUint(stream);
}
else if (context.Version is > 36 and <= 52)
{
Span<byte> span = stackalloc byte[2];
var read = stream.Read(span);
if (read != 2) throw new Exception();
Value = BitConverter.ToUInt16(span);
}
else
{
Span<byte> span = stackalloc byte[4];
var read = stream.Read(span);
if (read != 4) throw new Exception();
Value = BitConverter.ToUInt32(span);
}
}
}
16 changes: 1 addition & 15 deletions ME3Tweaks.Wwiser/Model/State/StateGroupChunk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,9 @@ public class StateGroupChunk : AkIdentifiable
public SyncType StateSyncType { get; set; }

Check warning on line 9 in ME3Tweaks.Wwiser/Model/State/StateGroupChunk.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'StateSyncType' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 9 in ME3Tweaks.Wwiser/Model/State/StateGroupChunk.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'StateSyncType' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

[FieldOrder(2)]
public VarCount StateCount { get; set; } = new();
public StateCount StateCount { get; set; } = new();

[FieldOrder(3)]
[FieldCount($"{nameof(StateCount)}.{nameof(StateCount.Value)}")]
public List<State> States { get; set; } = new();

public enum SyncType : byte
{
Immediate,
NextGrid,
NextBar,
NextBeat,
NextMarker,
NextUserMarker,
EntryMarker,
ExitMarker,
ExitNever,
LastExitPosition
}
}
Loading

0 comments on commit c6a6479

Please sign in to comment.