From 3d881f4b8fc8f1dcdad624a64d784a15455f0b7a Mon Sep 17 00:00:00 2001 From: henbagle Date: Sat, 30 Dec 2023 17:54:09 -0500 Subject: [PATCH] Parse SwitchContainer --- .../HierarchyTests/SwitchContainerTests.cs | 14 +- .../SwitchContainer/SwitchContainer_V56.bin | Bin 0 -> 175 bytes .../Model/Hierarchy/Enums/GroupType.cs | 43 ++++++ .../Model/Hierarchy/Enums/OnSwitchMode.cs | 7 + .../Model/Hierarchy/HircItemContainer.cs | 2 +- ...peFactory.cs => HircItemSubtypeFactory.cs} | 5 +- .../Model/Hierarchy/SwitchContainer.cs | 135 ++++++++++++++++++ 7 files changed, 201 insertions(+), 5 deletions(-) create mode 100644 ME3Tweaks.Wwiser.Tests/TestData/Hierarchy/SwitchContainer/SwitchContainer_V56.bin create mode 100644 ME3Tweaks.Wwiser/Model/Hierarchy/Enums/GroupType.cs create mode 100644 ME3Tweaks.Wwiser/Model/Hierarchy/Enums/OnSwitchMode.cs rename ME3Tweaks.Wwiser/Model/Hierarchy/{HircTypeFactory.cs => HircItemSubtypeFactory.cs} (93%) create mode 100644 ME3Tweaks.Wwiser/Model/Hierarchy/SwitchContainer.cs diff --git a/ME3Tweaks.Wwiser.Tests/HierarchyTests/SwitchContainerTests.cs b/ME3Tweaks.Wwiser.Tests/HierarchyTests/SwitchContainerTests.cs index de68478..876818b 100644 --- a/ME3Tweaks.Wwiser.Tests/HierarchyTests/SwitchContainerTests.cs +++ b/ME3Tweaks.Wwiser.Tests/HierarchyTests/SwitchContainerTests.cs @@ -1,6 +1,16 @@ -namespace ME3Tweaks.Wwiser.Tests.HierarchyTests; +using ME3Tweaks.Wwiser.Model.Hierarchy; + +namespace ME3Tweaks.Wwiser.Tests.HierarchyTests; public class SwitchContainerTests { - + [TestCase("SwitchContainer_V56.bin", 56)] + public void SwitchContainer_Reserializes(string filename, int version) + { + var data = TestData.GetTestDataBytes(@"Hierarchy",@"SwitchContainer", filename); + var (_, result) = TestHelpers.Deserialize(data, version); + + var reserialized = TestHelpers.Serialize(result, version); + Assert.That(reserialized, Is.EquivalentTo(data)); + } } \ No newline at end of file diff --git a/ME3Tweaks.Wwiser.Tests/TestData/Hierarchy/SwitchContainer/SwitchContainer_V56.bin b/ME3Tweaks.Wwiser.Tests/TestData/Hierarchy/SwitchContainer/SwitchContainer_V56.bin new file mode 100644 index 0000000000000000000000000000000000000000..d5d5691c2542ff2d6ffe1ee4cbdf60609c8efefd GIT binary patch literal 175 zcmZ?oh~j4egA>=xl>h($ literal 0 HcmV?d00001 diff --git a/ME3Tweaks.Wwiser/Model/Hierarchy/Enums/GroupType.cs b/ME3Tweaks.Wwiser/Model/Hierarchy/Enums/GroupType.cs new file mode 100644 index 0000000..77aed64 --- /dev/null +++ b/ME3Tweaks.Wwiser/Model/Hierarchy/Enums/GroupType.cs @@ -0,0 +1,43 @@ +using BinarySerialization; + +namespace ME3Tweaks.Wwiser.Model.Hierarchy.Enums; + +public class GroupType : IBinarySerializable +{ + public GroupTypeInner Value { get; set; } + + public void Serialize(Stream stream, Endianness endianness, BinarySerializationContext serializationContext) + { + var version = serializationContext.FindAncestor().Version; + if (version <= 89) + { + stream.Write(BitConverter.GetBytes((uint)Value)); + } + else + { + stream.WriteByte((byte)Value); + } + } + + public void Deserialize(Stream stream, Endianness endianness, BinarySerializationContext serializationContext) + { + var version = serializationContext.FindAncestor().Version; + if (version <= 89) + { + Span span = stackalloc byte[4]; + var read = stream.Read(span); + if (read != 4) throw new Exception(); + Value = (GroupTypeInner)BitConverter.ToUInt32(span); + } + else + { + Value = (GroupTypeInner)stream.ReadByte(); + } + } + + public enum GroupTypeInner : uint + { + Switch, + State + } +} \ No newline at end of file diff --git a/ME3Tweaks.Wwiser/Model/Hierarchy/Enums/OnSwitchMode.cs b/ME3Tweaks.Wwiser/Model/Hierarchy/Enums/OnSwitchMode.cs new file mode 100644 index 0000000..4d939ab --- /dev/null +++ b/ME3Tweaks.Wwiser/Model/Hierarchy/Enums/OnSwitchMode.cs @@ -0,0 +1,7 @@ +namespace ME3Tweaks.Wwiser.Model.Hierarchy.Enums; + +public enum OnSwitchMode : uint +{ + PlayToEnd, + Stop +} \ No newline at end of file diff --git a/ME3Tweaks.Wwiser/Model/Hierarchy/HircItemContainer.cs b/ME3Tweaks.Wwiser/Model/Hierarchy/HircItemContainer.cs index 0d694ee..b058f26 100644 --- a/ME3Tweaks.Wwiser/Model/Hierarchy/HircItemContainer.cs +++ b/ME3Tweaks.Wwiser/Model/Hierarchy/HircItemContainer.cs @@ -13,6 +13,6 @@ public class HircItemContainer [FieldOrder(3)] [FieldLength(nameof(Size))] - [SubtypeFactory($"{nameof(Type)}.{nameof(Type.Value)}", typeof(HircTypeFactory))] + [SubtypeFactory($"{nameof(Type)}.{nameof(Type.Value)}", typeof(HircItemSubtypeFactory))] public required HircItem Item { get; set; } } \ No newline at end of file diff --git a/ME3Tweaks.Wwiser/Model/Hierarchy/HircTypeFactory.cs b/ME3Tweaks.Wwiser/Model/Hierarchy/HircItemSubtypeFactory.cs similarity index 93% rename from ME3Tweaks.Wwiser/Model/Hierarchy/HircTypeFactory.cs rename to ME3Tweaks.Wwiser/Model/Hierarchy/HircItemSubtypeFactory.cs index 0536463..299a5d6 100644 --- a/ME3Tweaks.Wwiser/Model/Hierarchy/HircTypeFactory.cs +++ b/ME3Tweaks.Wwiser/Model/Hierarchy/HircItemSubtypeFactory.cs @@ -4,7 +4,7 @@ namespace ME3Tweaks.Wwiser.Model.Hierarchy; -public class HircTypeFactory : ISubtypeFactory +public class HircItemSubtypeFactory : ISubtypeFactory { private static readonly Dictionary TypeToEnum = new() { @@ -12,6 +12,7 @@ public class HircTypeFactory : ISubtypeFactory { typeof(Action), HircType.Action }, { typeof(Event), HircType.Event }, { typeof(RandSeqContainer), HircType.RandomSequenceContainer }, + { typeof(SwitchContainer), HircType.SwitchContainer }, { typeof(ActorMixer), HircType.ActorMixer }, { typeof(LayerContainer), HircType.LayerContainer }, { typeof(Attenuation), HircType.Attenuation }, @@ -46,7 +47,7 @@ public bool TryGetType(object key, [UnscopedRef] out Type type) HircType.Action => typeof(Action), HircType.Event => typeof(Event), HircType.RandomSequenceContainer => typeof(RandSeqContainer), - //HircType.SwitchContainer => + HircType.SwitchContainer => typeof(SwitchContainer), HircType.ActorMixer => typeof(ActorMixer), //HircType.Bus => HircType.LayerContainer => typeof(LayerContainer), diff --git a/ME3Tweaks.Wwiser/Model/Hierarchy/SwitchContainer.cs b/ME3Tweaks.Wwiser/Model/Hierarchy/SwitchContainer.cs new file mode 100644 index 0000000..056bf1e --- /dev/null +++ b/ME3Tweaks.Wwiser/Model/Hierarchy/SwitchContainer.cs @@ -0,0 +1,135 @@ +using BinarySerialization; +using ME3Tweaks.Wwiser.Model.Hierarchy.Enums; +using ME3Tweaks.Wwiser.Model.ParameterNode; + +namespace ME3Tweaks.Wwiser.Model.Hierarchy; + +public class SwitchContainer : HircItem, IHasNode +{ + [FieldOrder(0)] + public NodeBaseParameters NodeBaseParameters { get; set; } = new(); + + [FieldOrder(1)] + public GroupType GroupType { get; set; } = new(); + + [FieldOrder(2)] + public uint GroupId { get; set; } + + [FieldOrder(3)] + public uint DefaultSwitchId { get; set; } + + [FieldOrder(4)] + [SerializeAs(SerializedType.UInt1)] + public bool IsContinuousValidation { get; set; } + + [FieldOrder(5)] + public Children Children { get; set; } = new(); + + [FieldOrder(6)] + public uint SwitchGroupCount { get; set; } + + [FieldOrder(7)] + [FieldCount(nameof(SwitchGroupCount))] + public List SwitchGroups { get; set; } = new(); + + [FieldOrder(8)] + public uint SwitchParamsCount { get; set; } + + [FieldOrder(9)] + [FieldCount(nameof(SwitchParamsCount))] + public List SwitchParams { get; set; } = new(); +} + +public class SwitchParams : IAkIdentifiable, IBinarySerializable +{ + [Ignore] + public uint Id { get; set; } + + [Ignore] + public bool IsFirstOnly { get; set; } + + [Ignore] + public bool ContinuePlayback { get; set; } + + [Ignore] + public OnSwitchMode OnSwitchMode { get; set; } + + [Ignore] + public float FadeInTime { get; set; } + + [Ignore] + public float FadeOutTime { get; set; } + + public void Serialize(Stream stream, Endianness endianness, BinarySerializationContext serializationContext) + { + var version = serializationContext.FindAncestor().Version; + + stream.Write(BitConverter.GetBytes(Id)); + + if (version <= 89) + { + stream.WriteBoolByte(IsFirstOnly); + stream.WriteBoolByte(ContinuePlayback); + stream.Write(BitConverter.GetBytes((uint)OnSwitchMode)); + } + else + { + byte bitVector = 0; + if (IsFirstOnly) bitVector |= 1 << 0; + if (ContinuePlayback) bitVector |= 1 << 1; + stream.WriteByte(bitVector); + + stream.WriteByte((byte)OnSwitchMode); + } + + stream.Write(BitConverter.GetBytes(FadeInTime)); + stream.Write(BitConverter.GetBytes(FadeOutTime)); + } + + public void Deserialize(Stream stream, Endianness endianness, BinarySerializationContext serializationContext) + { + var version = serializationContext.FindAncestor().Version; + + Span span = stackalloc byte[4]; + var read = stream.Read(span); + if (read != 4) throw new Exception(); + Id = BitConverter.ToUInt32(span); + + if (version <= 89) + { + IsFirstOnly = stream.ReadBoolByte(); + ContinuePlayback = stream.ReadBoolByte(); + + read = stream.Read(span); + if (read != 4) throw new Exception(); + OnSwitchMode = (OnSwitchMode)BitConverter.ToUInt32(span); + } + else + { + var bitVector = stream.ReadByte(); + IsFirstOnly = (bitVector & (1 << 0)) == 1 << 0; + ContinuePlayback = (bitVector & (1 << 1)) == 1 << 1; + + OnSwitchMode = (OnSwitchMode)((byte)stream.ReadByte() & 0x7); + } + + + read = stream.Read(span); + if (read != 4) throw new Exception(); + FadeInTime = BitConverter.ToSingle(span); + + read = stream.Read(span); + if (read != 4) throw new Exception(); + FadeOutTime = BitConverter.ToSingle(span); + } +} + +public class SwitchGroup : AkIdentifiable +{ + [FieldOrder(0)] + public uint ItemCount { get; set; } + + [FieldOrder(1)] + [FieldCount(nameof(ItemCount))] + public List ItemIds { get; set; } = new(); +} \ No newline at end of file