diff --git a/ME3Tweaks.Wwiser.Tests/ActionTests/PlayTests.cs b/ME3Tweaks.Wwiser.Tests/ActionTests/PlayTests.cs new file mode 100644 index 0000000..b8ea1bd --- /dev/null +++ b/ME3Tweaks.Wwiser.Tests/ActionTests/PlayTests.cs @@ -0,0 +1,36 @@ +using ME3Tweaks.Wwiser.Model.Action; +using ME3Tweaks.Wwiser.Model.RTPC; +using Action = ME3Tweaks.Wwiser.Model.Hierarchy.Action; + +namespace ME3Tweaks.Wwiser.Tests.ActionTests; + +public class PlayTests +{ + [Test] + public void Play_V134_Parses() + { + var data = TestData.GetTestDataBytes(@"Action",@"Play_v134.bin"); + var (_, result) = TestHelpers.Deserialize(data, 134); + + Assert.Multiple(() => + { + Assert.That(result.Type.Value, Is.EqualTo(ActionTypeValue.Play)); + Assert.That(result.IsBus, Is.EqualTo(false)); + Assert.That(result.ActionParams, Is.InstanceOf()); + + var play = result.ActionParams as Play; + Assert.That(play!.Params.CurveInterpolation, Is.EqualTo(CurveInterpolation.Linear)); + }); + } + + [TestCase("Play_V134.bin", 134)] + [TestCase("Play_V56.bin", 56)] + public void Play_Reserializes(string file, int version) + { + var data = TestData.GetTestDataBytes(@"Action",file); + var (_, result) = TestHelpers.Deserialize(data, version); + + var reserialized = TestHelpers.Serialize(result, version); + Assert.That(reserialized, Is.EqualTo(data)); + } +} \ No newline at end of file diff --git a/ME3Tweaks.Wwiser.Tests/TestData/Action/Play_V134.bin b/ME3Tweaks.Wwiser.Tests/TestData/Action/Play_V134.bin new file mode 100644 index 0000000..8310e77 Binary files /dev/null and b/ME3Tweaks.Wwiser.Tests/TestData/Action/Play_V134.bin differ diff --git a/ME3Tweaks.Wwiser.Tests/TestData/Action/Play_V56.bin b/ME3Tweaks.Wwiser.Tests/TestData/Action/Play_V56.bin new file mode 100644 index 0000000..34c7ccf Binary files /dev/null and b/ME3Tweaks.Wwiser.Tests/TestData/Action/Play_V56.bin differ diff --git a/ME3Tweaks.Wwiser/Model/Action/ActionParamsFactory.cs b/ME3Tweaks.Wwiser/Model/Action/ActionParamsFactory.cs index bec2d5b..868bcb5 100644 --- a/ME3Tweaks.Wwiser/Model/Action/ActionParamsFactory.cs +++ b/ME3Tweaks.Wwiser/Model/Action/ActionParamsFactory.cs @@ -6,28 +6,18 @@ namespace ME3Tweaks.Wwiser.Model.Action; public class ActionParamsFactory : ISubtypeFactory { - private static readonly Dictionary TypeToEnum = new() - { - { typeof(Play), ActionTypeValue.Play}, - }; - public bool TryGetKey(Type valueType, [UnscopedRef] out object key) { - if (TypeToEnum.TryGetValue(valueType, out var value)) - { - key = value; - return true; - } - - // fallback - key = ActionTypeValue.Play; - return false; + throw new NotImplementedException(); } public bool TryGetType(object key, [UnscopedRef] out Type type) { type = (ActionTypeValue)key switch { + ActionTypeValue.Stop => typeof(Active), + ActionTypeValue.Pause => typeof(Active), + ActionTypeValue.Resume => typeof(Active), ActionTypeValue.Play => typeof(Play), _ => typeof(Play) }; diff --git a/ME3Tweaks.Wwiser/Model/Action/ActionSpecificParamsFactory.cs b/ME3Tweaks.Wwiser/Model/Action/ActionSpecificParamsFactory.cs new file mode 100644 index 0000000..2ac59a8 --- /dev/null +++ b/ME3Tweaks.Wwiser/Model/Action/ActionSpecificParamsFactory.cs @@ -0,0 +1,23 @@ +using System.Diagnostics.CodeAnalysis; +using BinarySerialization; +using ME3Tweaks.Wwiser.Model.Hierarchy; + +namespace ME3Tweaks.Wwiser.Model.Action; + +public class ActionSpecificParamsFactory : ISubtypeFactory +{ + public bool TryGetKey(Type valueType, [UnscopedRef] out object key) + { + throw new NotImplementedException(); + } + + public bool TryGetType(object key, [UnscopedRef] out Type type) + { + type = (ActionTypeValue)key switch + { + ActionTypeValue.Play => typeof(Specific.Action), + _ => typeof(Play) + }; + return true; + } +} diff --git a/ME3Tweaks.Wwiser/Model/Action/Active.cs b/ME3Tweaks.Wwiser/Model/Action/Active.cs new file mode 100644 index 0000000..5f1e4ab --- /dev/null +++ b/ME3Tweaks.Wwiser/Model/Action/Active.cs @@ -0,0 +1,14 @@ +using BinarySerialization; +using ME3Tweaks.Wwiser.Attributes; + +namespace ME3Tweaks.Wwiser.Model.Action; + +public class Active : IActionParams +{ + [FieldOrder(1)] + [SerializeWhenVersion(56, ComparisonOperator.LessThanOrEqual)] + public uint SubSectionSize { get; set; } + + [FieldOrder(2)] + public required ActiveParams Params { get; set; } +} \ No newline at end of file diff --git a/ME3Tweaks.Wwiser/Model/Action/ActiveParams.cs b/ME3Tweaks.Wwiser/Model/Action/ActiveParams.cs new file mode 100644 index 0000000..037565e --- /dev/null +++ b/ME3Tweaks.Wwiser/Model/Action/ActiveParams.cs @@ -0,0 +1,36 @@ +using BinarySerialization; +using ME3Tweaks.Wwiser.Attributes; +using ME3Tweaks.Wwiser.Model.Action.Specific; +using ME3Tweaks.Wwiser.Model.RTPC; + +namespace ME3Tweaks.Wwiser.Model.Action; + +public class ActiveParams +{ + [FieldOrder(0)] + [SerializeWhenVersion(56, ComparisonOperator.LessThanOrEqual)] + public int Time { get; set; } + + [FieldOrder(1)] + [SerializeWhenVersion(56, ComparisonOperator.LessThanOrEqual)] + public int TimeMin { get; set; } + + [FieldOrder(2)] + [SerializeWhenVersion(56, ComparisonOperator.LessThanOrEqual)] + public int TimeMax { get; set; } + + [FieldOrder(3)] + [SerializeAs(SerializedType.UInt1)] + public CurveInterpolation CurveInterpolation { get; set; } + + [FieldOrder(4)] + [SerializeWhenVersion(56, ComparisonOperator.LessThanOrEqual)] + [SubtypeFactory($"{nameof(Hierarchy.Action.Type)}.{nameof(Hierarchy.Action.Type.Value)}", + typeof(ActionSpecificParamsFactory), BindingMode = BindingMode.OneWay, + AncestorType = typeof(Hierarchy.Action), RelativeSourceMode = RelativeSourceMode.FindAncestor)] + public required ISpecificParams SpecificParams { get; set; } + + [FieldOrder(5)] + [SerializeWhenVersion(56, ComparisonOperator.LessThanOrEqual)] + public ExceptParams ExceptParams { get; set; } = new(); +} \ No newline at end of file diff --git a/ME3Tweaks.Wwiser/Model/Action/ExceptParams.cs b/ME3Tweaks.Wwiser/Model/Action/ExceptParams.cs index b3de894..34df0eb 100644 --- a/ME3Tweaks.Wwiser/Model/Action/ExceptParams.cs +++ b/ME3Tweaks.Wwiser/Model/Action/ExceptParams.cs @@ -6,8 +6,8 @@ namespace ME3Tweaks.Wwiser.Model.Action; public class ExceptParams { - [FieldOrder(0)] - public VarCount ExceptionCount { get; set; } + [FieldOrder(0)] + public VarCount ExceptionCount { get; set; } = new(); [FieldOrder(1)] [FieldCount($"{nameof(ExceptionCount)}.{nameof(ExceptionCount.Value)}")] diff --git a/ME3Tweaks.Wwiser/Model/Action/ActionParams.cs b/ME3Tweaks.Wwiser/Model/Action/IActionParams.cs similarity index 56% rename from ME3Tweaks.Wwiser/Model/Action/ActionParams.cs rename to ME3Tweaks.Wwiser/Model/Action/IActionParams.cs index 85a0387..104905a 100644 --- a/ME3Tweaks.Wwiser/Model/Action/ActionParams.cs +++ b/ME3Tweaks.Wwiser/Model/Action/IActionParams.cs @@ -1,6 +1,3 @@ namespace ME3Tweaks.Wwiser.Model.Action; -public class ActionParams -{ - -} \ No newline at end of file +public interface IActionParams; \ No newline at end of file diff --git a/ME3Tweaks.Wwiser/Model/Action/Play.cs b/ME3Tweaks.Wwiser/Model/Action/Play.cs index e58512f..70770d4 100644 --- a/ME3Tweaks.Wwiser/Model/Action/Play.cs +++ b/ME3Tweaks.Wwiser/Model/Action/Play.cs @@ -1,40 +1,17 @@ using BinarySerialization; using ME3Tweaks.Wwiser.Attributes; +using ME3Tweaks.Wwiser.Model.Action.Specific; using ME3Tweaks.Wwiser.Model.RTPC; namespace ME3Tweaks.Wwiser.Model.Action; -public class Play : ActionParams +public class Play : Active { - [FieldOrder(0)] - [SerializeWhenVersion(56, ComparisonOperator.LessThanOrEqual)] - public int Time { get; set; } - [FieldOrder(1)] - [SerializeWhenVersion(56, ComparisonOperator.LessThanOrEqual)] - public int TimeMin { get; set; } - - [FieldOrder(2)] - [SerializeWhenVersion(56, ComparisonOperator.LessThanOrEqual)] - public int TimeMax { get; set; } - - [FieldOrder(3)] - [SerializeAs(SerializedType.UInt1)] - public CurveInterpolation CurveInterpolation { get; set; } - - [FieldOrder(4)] - [SerializeWhenVersion(56, ComparisonOperator.LessThanOrEqual)] - public SpecificParams SpecificParams { get; set; } - - [FieldOrder(5)] - [SerializeWhenVersion(56, ComparisonOperator.LessThanOrEqual)] - public ExceptParams ExceptParams { get; set; } - - [FieldOrder(6)] [SerializeWhenVersion(26, ComparisonOperator.GreaterThan)] public uint BankId { get; set; } - [FieldOrder(7)] + [FieldOrder(2)] [SerializeWhenVersion(144, ComparisonOperator.GreaterThanOrEqual)] public uint BankType { get; set; } } \ No newline at end of file diff --git a/ME3Tweaks.Wwiser/Model/Action/SpecificParams.cs b/ME3Tweaks.Wwiser/Model/Action/Specific/Action.cs similarity index 71% rename from ME3Tweaks.Wwiser/Model/Action/SpecificParams.cs rename to ME3Tweaks.Wwiser/Model/Action/Specific/Action.cs index 6c21b16..436afcc 100644 --- a/ME3Tweaks.Wwiser/Model/Action/SpecificParams.cs +++ b/ME3Tweaks.Wwiser/Model/Action/Specific/Action.cs @@ -1,9 +1,9 @@ using BinarySerialization; using ME3Tweaks.Wwiser.Attributes; -namespace ME3Tweaks.Wwiser.Model.Action; +namespace ME3Tweaks.Wwiser.Model.Action.Specific; -public class SpecificParams +public class Action : ISpecificParams { [FieldOrder(0)] [FieldLength(0x10)] diff --git a/ME3Tweaks.Wwiser/Model/Action/Specific/ISpecificParams.cs b/ME3Tweaks.Wwiser/Model/Action/Specific/ISpecificParams.cs new file mode 100644 index 0000000..e8a673c --- /dev/null +++ b/ME3Tweaks.Wwiser/Model/Action/Specific/ISpecificParams.cs @@ -0,0 +1,3 @@ +namespace ME3Tweaks.Wwiser.Model.Action.Specific; + +public interface ISpecificParams; \ No newline at end of file diff --git a/ME3Tweaks.Wwiser/Model/Hierarchy/Action.cs b/ME3Tweaks.Wwiser/Model/Hierarchy/Action.cs index c98c4df..7089cc4 100644 --- a/ME3Tweaks.Wwiser/Model/Hierarchy/Action.cs +++ b/ME3Tweaks.Wwiser/Model/Hierarchy/Action.cs @@ -26,20 +26,16 @@ public class Action : HircItem public int DelayMax { get; set; } [FieldOrder(5)] - [SerializeWhenVersion(56, ComparisonOperator.LessThanOrEqual)] - public uint SubSectionSize { get; set; } // TODO: this needs to go away - - [FieldOrder(6)] [SerializeWhenVersion(65, ComparisonOperator.GreaterThan)] [SerializeAs(SerializedType.UInt1)] public bool IsBus { get; set; } - [FieldOrder(7)] + [FieldOrder(6)] [SerializeWhenVersion(56, ComparisonOperator.GreaterThan)] public InitialParamsV62 PropBundle { get; set; } = new(); - [FieldOrder(8)] - [FieldLength(nameof(SubSectionSize))] - [SubtypeFactory($"{nameof(Type)}.{nameof(Type.Value)}", typeof(ActionParamsFactory))] - public ActionParams ActionParams { get; set; } = new(); + [FieldOrder(7)] + [SubtypeFactory($"{nameof(Type)}.{nameof(Type.Value)}", typeof(ActionParamsFactory), + BindingMode = BindingMode.OneWay)] + public required IActionParams ActionParams { get; set; } } \ No newline at end of file