From 1fea0308f3aa8a8a03b851355891cf008c5f4c8a Mon Sep 17 00:00:00 2001 From: freezy Date: Sun, 14 Feb 2021 22:55:00 +0100 Subject: [PATCH 01/16] data: Add support for alpha channel when parsing colors. --- VisualPinball.Engine/IO/BiffColorAttribute.cs | 2 +- VisualPinball.Engine/Math/Color.cs | 21 ++++++++++--------- VisualPinball.Engine/VPT/MaterialData.cs | 12 +++++------ VisualPinball.Engine/VPT/Table/TableData.cs | 2 +- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/VisualPinball.Engine/IO/BiffColorAttribute.cs b/VisualPinball.Engine/IO/BiffColorAttribute.cs index 23b5ca1a2..0192cc7f5 100644 --- a/VisualPinball.Engine/IO/BiffColorAttribute.cs +++ b/VisualPinball.Engine/IO/BiffColorAttribute.cs @@ -46,7 +46,7 @@ private static void WriteColor(BinaryWriter writer, Color value) private Color ReadColor(BinaryReader reader, int len) { - return new Color(reader.ReadInt32(), ColorFormat); + return new Color(reader.ReadUInt32(), ColorFormat); } } } diff --git a/VisualPinball.Engine/Math/Color.cs b/VisualPinball.Engine/Math/Color.cs index 6338d511c..9bde27d77 100644 --- a/VisualPinball.Engine/Math/Color.cs +++ b/VisualPinball.Engine/Math/Color.cs @@ -31,7 +31,7 @@ public class Color public float B => Blue / 255f; public float A => Alpha / 255f; - public int Bgr => Blue * 65536 + Green * 256 + Red; + public uint Bgr => (uint)Alpha * 16777216 + (uint)Blue * 65536 + (uint)Green * 256 + (uint)Red; public Color(int red, int green, int blue, int alpha) { @@ -41,19 +41,20 @@ public Color(int red, int green, int blue, int alpha) Alpha = alpha; } - public Color(long color, ColorFormat format) + public Color(uint color, ColorFormat format) { switch (format) { case ColorFormat.Bgr: Red = (int)(color & 0x000000ff); - Green = (int)(color & 0x0000ff00) >> 8; - Blue = (int)(color & 0x00ff0000) >> 16; + Green = (int)((color & 0x0000ff00) >> 8); + Blue = (int)((color & 0x00ff0000) >> 16); + Alpha = (int)(color >> 24); break; case ColorFormat.Argb: - Red = (int)(color & 0x00ff0000) >> 16; - Green = (int)(color & 0x0000ff00) >> 8; + Red = (int)((color & 0x00ff0000) >> 16); + Green = (int)((color & 0x0000ff00) >> 8); Blue = (int)(color & 0x000000ff); - Alpha = (int)(color & 0xff000000) >> 24; + Alpha = (int)((color & 0xff000000) >> 24); break; } } @@ -73,13 +74,13 @@ public override string ToString() return $"rgba({System.Math.Round(R, 3)}, {System.Math.Round(G, 3)}, {System.Math.Round(B, 3)}, {System.Math.Round(A, 3)})"; } - public int ToInt(ColorFormat format) + public uint ToInt(ColorFormat format) { switch (format) { case ColorFormat.Bgr: - return Red + (Green << 8) + (Blue << 16); + return (uint)Red + ((uint)Green << 8) + ((uint)Blue << 16) + ((uint)Alpha << 24); case ColorFormat.Argb: - return (Red << 16) + (Green << 8) + Blue + (Alpha << 24); + return ((uint)Red << 16) + ((uint)Green << 8) + (uint)Blue + ((uint)Alpha << 24); } return 0; } diff --git a/VisualPinball.Engine/VPT/MaterialData.cs b/VisualPinball.Engine/VPT/MaterialData.cs index 366148d26..469ba8267 100644 --- a/VisualPinball.Engine/VPT/MaterialData.cs +++ b/VisualPinball.Engine/VPT/MaterialData.cs @@ -34,17 +34,17 @@ internal class MaterialData /// /// can be overriden by texture on object itself /// - public int BaseColor; + public uint BaseColor; /// /// specular of glossy layer /// - public int Glossiness; + public uint Glossiness; /// /// specular of clear coat layer /// - public int ClearCoat; + public uint ClearCoat; /// /// wrap/rim lighting factor (0(off)..1(full)) @@ -91,9 +91,9 @@ public MaterialData(BinaryReader reader) { var startPos = reader.BaseStream.Position; Name = BiffUtil.ReadNullTerminatedString(reader, 32); - BaseColor = reader.ReadInt32(); - Glossiness = reader.ReadInt32(); - ClearCoat = reader.ReadInt32(); + BaseColor = reader.ReadUInt32(); + Glossiness = reader.ReadUInt32(); + ClearCoat = reader.ReadUInt32(); WrapLighting = reader.ReadSingle(); IsMetal = reader.ReadByte(); reader.BaseStream.Seek(3, SeekOrigin.Current); diff --git a/VisualPinball.Engine/VPT/Table/TableData.cs b/VisualPinball.Engine/VPT/Table/TableData.cs index 939de17ef..6c063231d 100644 --- a/VisualPinball.Engine/VPT/Table/TableData.cs +++ b/VisualPinball.Engine/VPT/Table/TableData.cs @@ -173,7 +173,7 @@ public class TableData : ItemData public Color LightAmbient = new Color(0, 0, 0, 255); [BiffInt("LZDI", Pos = 76)] - public int Light0Emission { + public uint Light0Emission { set => Light[0].Emission = new Color(value, ColorFormat.Bgr); get => Light[0].Emission.Bgr; } From 4b8403c0d5fa5db38a4548326b7ef38dbf57cffe Mon Sep 17 00:00:00 2001 From: freezy Date: Sun, 14 Feb 2021 22:55:40 +0100 Subject: [PATCH 02/16] data: Fix string encoding. --- VisualPinball.Engine/IO/BiffStringAttribute.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/VisualPinball.Engine/IO/BiffStringAttribute.cs b/VisualPinball.Engine/IO/BiffStringAttribute.cs index 48437d85e..880d1666d 100644 --- a/VisualPinball.Engine/IO/BiffStringAttribute.cs +++ b/VisualPinball.Engine/IO/BiffStringAttribute.cs @@ -23,8 +23,7 @@ namespace VisualPinball.Engine.IO { public class BiffStringAttribute : BiffAttribute { - - private static readonly Encoding StringEncoding = Encoding.ASCII; + private static readonly Encoding StringEncoding = Encoding.GetEncoding("iso-8859-1"); /// /// Wide strings have a zero byte between each character. From a3ede49954dd2dc7d671c55d4abf8e2bb439a850 Mon Sep 17 00:00:00 2001 From: freezy Date: Sun, 14 Feb 2021 22:56:32 +0100 Subject: [PATCH 03/16] data: Automatically assign layer name if not set. --- VisualPinball.Engine/VPT/ItemData.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/VisualPinball.Engine/VPT/ItemData.cs b/VisualPinball.Engine/VPT/ItemData.cs index edef913a4..15a687e1b 100644 --- a/VisualPinball.Engine/VPT/ItemData.cs +++ b/VisualPinball.Engine/VPT/ItemData.cs @@ -34,7 +34,15 @@ public abstract class ItemData : BiffData public bool IsLocked; [BiffInt("LAYR", Pos = 1001)] - public int EditorLayer; + public int EditorLayer { + get => _editorLayer; + set { + _editorLayer = value; + if (string.IsNullOrEmpty(EditorLayerName)) { + EditorLayerName = $"Layer_{value + 1}"; + } + } + } [BiffString("LANR", Pos = 1002)] public string EditorLayerName = string.Empty; @@ -42,6 +50,7 @@ public abstract class ItemData : BiffData [BiffBool("LVIS", Pos = 1003)] public bool EditorLayerVisibility = true; + private int _editorLayer; public abstract string GetName(); public abstract void SetName(string name); From c8aa0fa84795cee6bb0b195bd418c2f8793e5f6b Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 15 Feb 2021 00:04:53 +0100 Subject: [PATCH 04/16] data: Fix writing of animation vertices. --- VisualPinball.Engine/IO/BiffAttribute.cs | 4 +- .../VPT/Primitive/PrimitiveData.cs | 58 +++++++++---------- 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/VisualPinball.Engine/IO/BiffAttribute.cs b/VisualPinball.Engine/IO/BiffAttribute.cs index b70459ffc..e4afc0e3e 100644 --- a/VisualPinball.Engine/IO/BiffAttribute.cs +++ b/VisualPinball.Engine/IO/BiffAttribute.cs @@ -249,9 +249,9 @@ public object GetValue(object obj) return Field != null ? Field.GetValue(obj) : null; } - protected void WriteStart(BinaryWriter writer, int dataLength, HashWriter hashWriter) + protected void WriteStart(BinaryWriter writer, int dataLength, HashWriter hashWriter, string name = null) { - var tag = Encoding.Default.GetBytes(Name); + var tag = Encoding.Default.GetBytes(name ?? Name); if (Name.Length < 4) { tag = tag.Concat(new byte[4 - Name.Length]).ToArray(); } diff --git a/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs b/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs index 6277be190..677473034 100644 --- a/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs +++ b/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs @@ -57,14 +57,17 @@ public class PrimitiveData : ItemData, IPhysicalData [BiffInt("M3CJ", Pos = 44)] public int CompressedIndices = 0; - [BiffInt("M3AY", Pos = 46)] - public int CompressedAnimationVertices; + /// + /// Is written with mesh below. Also it seems redundant and probably don't even needs to be read. + /// + [BiffInt("M3AY", Pos = 46, SkipWrite = true)] + public int[] CompressedAnimationVertices; [BiffVertices("M3DX", SkipWrite = true)] [BiffVertices("M3CX", IsCompressed = true, Pos = 42)] [BiffIndices("M3DI", SkipWrite = true)] [BiffIndices("M3CI", IsCompressed = true, Pos = 45)] - [BiffAnimation("M3AX", IsCompressed = true, Pos = 47)] + [BiffAnimation("M3AX", IsCompressed = true, Pos = 47 )] public Mesh Mesh = new Mesh(); [BiffFloat("RTV0", Index = 0, Pos = 3)] @@ -180,15 +183,18 @@ public class PrimitiveData : ItemData, IPhysicalData protected override bool SkipWrite(BiffAttribute attr) { - if (!Use3DMesh) { - switch (attr.Name) { - case "M3VN": - case "M3CY": - case "M3FN": - case "M3CJ": + switch (attr.Name) { + case "M3VN": + case "M3CY": + case "M3FN": + case "M3DN": + case "M3CJ": + if (!Use3DMesh) { return true; - } + } + break; } + return false; } @@ -397,16 +403,13 @@ public BiffAnimationAttribute(string name) : base(name) { } public override void Parse(T obj, BinaryReader reader, int len) { - if (obj is PrimitiveData primitiveData) - { - try - { + if (obj is PrimitiveData primitiveData) { + try { ParseAnimation(primitiveData, IsCompressed ? BiffZlib.Decompress(reader.ReadBytes(len)) : reader.ReadBytes(len)); - } - catch (Exception e) - { + + } catch (Exception e) { throw new Exception($"Error parsing animation data for {primitiveData.Name} ({primitiveData.StorageName}).", e); } } @@ -414,10 +417,8 @@ public override void Parse(T obj, BinaryReader reader, int len) public override void Write(TItem obj, BinaryWriter writer, HashWriter hashWriter) { - if (obj is PrimitiveData primitiveData) - { - if (!primitiveData.Use3DMesh) - { + if (obj is PrimitiveData primitiveData) { + if (!primitiveData.Use3DMesh) { // don't write animation if not using 3d mesh return; } @@ -425,32 +426,29 @@ public override void Write(TItem obj, BinaryWriter writer, HashWriter has for (var i = 0; i < primitiveData.Mesh.AnimationFrames.Count; i++) { var animationData = SerializeAnimation(primitiveData.Mesh.AnimationFrames[i]); var data = IsCompressed ? BiffZlib.Compress(animationData) : animationData; + WriteStart(writer, 4, hashWriter, "M3AY"); + writer.Write(data.Length); WriteStart(writer, data.Length, hashWriter); writer.Write(data); hashWriter?.Write(data); } - } - else - { + } else { throw new InvalidOperationException("Unknown type for [" + GetType().Name + "] on field \"" + Name + "\"."); } } private void ParseAnimation(PrimitiveData data, byte[] bytes) { - if (data.NumVertices == 0) - { + if (data.NumVertices == 0) { throw new ArgumentOutOfRangeException(nameof(data), "Cannot create animation when size is unknown."); } - if (bytes.Length != data.NumVertices * Mesh.VertData.Size) - { + if (bytes.Length != data.NumVertices * Mesh.VertData.Size) { throw new ArgumentOutOfRangeException($"Tried to read {data.NumVertices} vertex animations for primitive item \"${data.Name}\" (${data.StorageName}), but had ${bytes.Length} bytes available."); } - if (!(GetValue(data) is Mesh mesh)) - { + if (!(GetValue(data) is Mesh mesh)) { throw new ArgumentException("BiffAnimationAttribute attribute must sit on a Mesh object."); } From 38c501f11d920ceee1177c57a0f45bcbc46a3534 Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 15 Feb 2021 00:44:19 +0100 Subject: [PATCH 05/16] data: Add compiler flag for omitting VPE data. --- VisualPinball.Engine/IO/BiffAttribute.cs | 5 +++++ VisualPinball.Engine/IO/BiffData.cs | 5 +++++ VisualPinball.Engine/VPT/Flipper/FlipperData.cs | 2 +- VisualPinball.Engine/VPT/Kicker/KickerData.cs | 4 ++-- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/VisualPinball.Engine/IO/BiffAttribute.cs b/VisualPinball.Engine/IO/BiffAttribute.cs index e4afc0e3e..ff9bc930e 100644 --- a/VisualPinball.Engine/IO/BiffAttribute.cs +++ b/VisualPinball.Engine/IO/BiffAttribute.cs @@ -90,6 +90,11 @@ public abstract class BiffAttribute : Attribute, ISortableBiffRecord /// public bool SkipHash = false; + /// + /// If set, counts as data exclusively used by VPE and can be disabled when writing with SKIP_VPE_DATA + /// + public bool IsVpeEnhancement = false; + /// /// If put on a field, this is the info from C#'s reflection API. /// diff --git a/VisualPinball.Engine/IO/BiffData.cs b/VisualPinball.Engine/IO/BiffData.cs index c20de3990..2f9013f38 100644 --- a/VisualPinball.Engine/IO/BiffData.cs +++ b/VisualPinball.Engine/IO/BiffData.cs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#define SKIP_VPE_DATA + using System; using System.Collections.Generic; using System.IO; @@ -204,6 +206,9 @@ protected void WriteRecord(BinaryWriter writer, Dictionary !a[0].SkipWrite && !SkipWrite(a[0])) +#if SKIP_VPE_DATA + .Where(a => !a[0].IsVpeEnhancement) +#endif .Select(a => a[0] as ISortableBiffRecord) .Concat(UnknownRecords ?? new List()) .OrderBy(r => r.GetPosition()); diff --git a/VisualPinball.Engine/VPT/Flipper/FlipperData.cs b/VisualPinball.Engine/VPT/Flipper/FlipperData.cs index 490749b6c..9a1750e5b 100644 --- a/VisualPinball.Engine/VPT/Flipper/FlipperData.cs +++ b/VisualPinball.Engine/VPT/Flipper/FlipperData.cs @@ -146,7 +146,7 @@ public class FlipperData : ItemData // new fields by VPE // ----------------- - [BiffBool("DWND", Pos = 100, SkipHash = true)] + [BiffBool("DWND", Pos = 100, SkipHash = true, IsVpeEnhancement = true)] public bool IsDualWound; public float OverrideMass; diff --git a/VisualPinball.Engine/VPT/Kicker/KickerData.cs b/VisualPinball.Engine/VPT/Kicker/KickerData.cs index 9010b7380..ef0c19fa9 100644 --- a/VisualPinball.Engine/VPT/Kicker/KickerData.cs +++ b/VisualPinball.Engine/VPT/Kicker/KickerData.cs @@ -87,10 +87,10 @@ public class KickerData : ItemData // new fields by VPE // ----------------- - [BiffFloat("ANGL", Pos = 16, SkipHash = true)] + [BiffFloat("ANGL", Pos = 16, SkipHash = true, IsVpeEnhancement = true)] public float Angle = 90f; - [BiffFloat("SPED", Pos = 17, SkipHash = true)] + [BiffFloat("SPED", Pos = 17, SkipHash = true, IsVpeEnhancement = true)] public float Speed = 3f; public KickerData(string name, float x, float y) : base(StoragePrefix.GameItem) From 7f92f6a58c85fdad3479906442e11afa75c57e74 Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 15 Feb 2021 00:54:45 +0100 Subject: [PATCH 06/16] data: Add test for parsing colors. --- .../Common/ColorTests.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 VisualPinball.Engine.Test/Common/ColorTests.cs diff --git a/VisualPinball.Engine.Test/Common/ColorTests.cs b/VisualPinball.Engine.Test/Common/ColorTests.cs new file mode 100644 index 000000000..61d8c85b4 --- /dev/null +++ b/VisualPinball.Engine.Test/Common/ColorTests.cs @@ -0,0 +1,26 @@ +using System.IO; +using FluentAssertions; +using NUnit.Framework; +using VisualPinball.Engine.Math; +using VisualPinball.Engine.VPT.Table; + +namespace VisualPinball.Engine.Test.Common +{ + public class ColorTests + { + [Test] + public void TestColor() + { + using (var memStream = new MemoryStream(new byte[] {0xff, 0xa0, 0xb4, 0x80 })) { + using (var reader = new BinaryReader(memStream)) { + var intCol = reader.ReadUInt32(); + var color = new Color(intCol, ColorFormat.Bgr); + color.Red.Should().Be(0xff); + color.Green.Should().Be(0xa0); + color.Blue.Should().Be(0xb4); + color.Alpha.Should().Be(0x80); + } + } + } + } +} From 565d4a14301f3a3b1e5dc72b63753edfa6414a3a Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 15 Feb 2021 20:50:19 +0100 Subject: [PATCH 07/16] data: Add compiler flags for VP10.6 and VP10.7 compatibility. --- VisualPinball.Engine/IO/BiffAttribute.cs | 8 +++++++- VisualPinball.Engine/IO/BiffData.cs | 14 ++++++++++---- VisualPinball.Engine/IO/BiffIgnoreAttribute.cs | 5 +++++ VisualPinball.Engine/Math/DragPointData.cs | 9 ++++++--- VisualPinball.Engine/VPT/Flipper/FlipperData.cs | 6 +++--- VisualPinball.Engine/VPT/ItemData.cs | 5 +++-- VisualPinball.Engine/VPT/Table/TableWriter.cs | 2 ++ 7 files changed, 36 insertions(+), 13 deletions(-) diff --git a/VisualPinball.Engine/IO/BiffAttribute.cs b/VisualPinball.Engine/IO/BiffAttribute.cs index ff9bc930e..5cf543b21 100644 --- a/VisualPinball.Engine/IO/BiffAttribute.cs +++ b/VisualPinball.Engine/IO/BiffAttribute.cs @@ -91,10 +91,16 @@ public abstract class BiffAttribute : Attribute, ISortableBiffRecord public bool SkipHash = false; /// - /// If set, counts as data exclusively used by VPE and can be disabled when writing with SKIP_VPE_DATA + /// If set, counts as data exclusively used by VPE and can be disabled when writing with WRITE_VP106 + /// or WRITE_VP107 active. /// public bool IsVpeEnhancement = false; + /// + /// If set, this attribute won't written if the WRITE_VP106 flag is set. + /// + public bool WasAddedInVp107 = false; + /// /// If put on a field, this is the info from C#'s reflection API. /// diff --git a/VisualPinball.Engine/IO/BiffData.cs b/VisualPinball.Engine/IO/BiffData.cs index 2f9013f38..f0270461e 100644 --- a/VisualPinball.Engine/IO/BiffData.cs +++ b/VisualPinball.Engine/IO/BiffData.cs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#define SKIP_VPE_DATA +#define WRITE_VP107 using System; using System.Collections.Generic; @@ -143,8 +143,11 @@ protected static void Init(Type type, Dictionary> at /// protected static T Load(T obj, BinaryReader reader, Dictionary> attributes) where T : BiffData { - + #if WRITE_VP106 || WRITE_VP106 + var ignoredTags = typeof(T).GetCustomAttributes().Where(a => !a.IsDeprecatedInVP).Select(a => a.Name).ToArray(); + #else var ignoredTags = typeof(T).GetCustomAttributes().Select(a => a.Name).ToArray(); + #endif // initially read length and BIFF record name var len = reader.ReadInt32(); @@ -206,9 +209,12 @@ protected void WriteRecord(BinaryWriter writer, Dictionary !a[0].SkipWrite && !SkipWrite(a[0])) -#if SKIP_VPE_DATA + #if WRITE_VP107 .Where(a => !a[0].IsVpeEnhancement) -#endif + #endif + #if WRITE_VP106 + .Where(a => !a[0].IsVpeEnhancement && !a[0].WasAddedInVp107) + #endif .Select(a => a[0] as ISortableBiffRecord) .Concat(UnknownRecords ?? new List()) .OrderBy(r => r.GetPosition()); diff --git a/VisualPinball.Engine/IO/BiffIgnoreAttribute.cs b/VisualPinball.Engine/IO/BiffIgnoreAttribute.cs index 8ccccd52c..592c45ca6 100644 --- a/VisualPinball.Engine/IO/BiffIgnoreAttribute.cs +++ b/VisualPinball.Engine/IO/BiffIgnoreAttribute.cs @@ -23,6 +23,11 @@ public class BiffIgnoreAttribute : Attribute { public readonly string Name; + /// + /// If set, marks this as "deprecated in VP", which still writes it when the WRITE_VP106 or WRITE_VP107 flag is set. + /// + public bool IsDeprecatedInVP; + public BiffIgnoreAttribute(string name) { Name = name; diff --git a/VisualPinball.Engine/Math/DragPointData.cs b/VisualPinball.Engine/Math/DragPointData.cs index 2d04f9a8c..480136b9e 100644 --- a/VisualPinball.Engine/Math/DragPointData.cs +++ b/VisualPinball.Engine/Math/DragPointData.cs @@ -31,9 +31,6 @@ namespace VisualPinball.Engine.Math { [Serializable] - [BiffIgnore("LANR")] - [BiffIgnore("LAYR")] - [BiffIgnore("LVIS")] public class DragPointData : BiffData { [BiffVertex("VCEN", Pos = 1, WriteAsVertex2D = true)] @@ -60,6 +57,12 @@ public class DragPointData : BiffData [BiffInt("LAYR", Pos = 8)] public int EditorLayer; + [BiffString("LANR", Pos = 9, WasAddedInVp107 = true)] + public string EditorLayerName = string.Empty; + + [BiffBool("LVIS", Pos = 10, WasAddedInVp107 = true)] + public bool EditorLayerVisibility = true; + public float CalcHeight; public override string ToString() diff --git a/VisualPinball.Engine/VPT/Flipper/FlipperData.cs b/VisualPinball.Engine/VPT/Flipper/FlipperData.cs index 9a1750e5b..af82ccca5 100644 --- a/VisualPinball.Engine/VPT/Flipper/FlipperData.cs +++ b/VisualPinball.Engine/VPT/Flipper/FlipperData.cs @@ -32,9 +32,9 @@ namespace VisualPinball.Engine.VPT.Flipper { [Serializable] - [BiffIgnore("RWDT")] - [BiffIgnore("RHGT")] - [BiffIgnore("RTHK")] + [BiffIgnore("RWDT", IsDeprecatedInVP = true)] + [BiffIgnore("RHGT", IsDeprecatedInVP = true)] + [BiffIgnore("RTHK", IsDeprecatedInVP = true)] public class FlipperData : ItemData { public override string GetName() => Name; diff --git a/VisualPinball.Engine/VPT/ItemData.cs b/VisualPinball.Engine/VPT/ItemData.cs index 15a687e1b..e0cb5dbd8 100644 --- a/VisualPinball.Engine/VPT/ItemData.cs +++ b/VisualPinball.Engine/VPT/ItemData.cs @@ -44,13 +44,14 @@ public int EditorLayer { } } - [BiffString("LANR", Pos = 1002)] + [BiffString("LANR", Pos = 1002, WasAddedInVp107 = true)] public string EditorLayerName = string.Empty; - [BiffBool("LVIS", Pos = 1003)] + [BiffBool("LVIS", Pos = 1003, WasAddedInVp107 = true)] public bool EditorLayerVisibility = true; private int _editorLayer; + public abstract string GetName(); public abstract void SetName(string name); diff --git a/VisualPinball.Engine/VPT/Table/TableWriter.cs b/VisualPinball.Engine/VPT/Table/TableWriter.cs index aeb2d85e7..09322652c 100644 --- a/VisualPinball.Engine/VPT/Table/TableWriter.cs +++ b/VisualPinball.Engine/VPT/Table/TableWriter.cs @@ -114,7 +114,9 @@ private void WriteGameItems(HashWriter hashWriter) } // 5. Mappings + #if !WRITE_VP106 && !WRITE_VP107 _table.Mappings.Data.WriteData(_gameStorage); + #endif } private void WriteImages() From 5bb68100416555258db5a7fda74480a86ee6547a Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 15 Feb 2021 21:02:06 +0100 Subject: [PATCH 08/16] data: Add elastic falloff to surface (#275). --- .../VPT/Surface/SurfaceData.cs | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/VisualPinball.Engine/VPT/Surface/SurfaceData.cs b/VisualPinball.Engine/VPT/Surface/SurfaceData.cs index 60a5d1729..b09accd03 100644 --- a/VisualPinball.Engine/VPT/Surface/SurfaceData.cs +++ b/VisualPinball.Engine/VPT/Surface/SurfaceData.cs @@ -74,7 +74,7 @@ public class SurfaceData : ItemData, IPhysicalData public string TopMaterial = string.Empty; [MaterialReference] - [BiffString("MAPH", Pos = 29)] + [BiffString("MAPH", Pos = 30)] public string PhysicsMaterial = string.Empty; [MaterialReference] @@ -99,34 +99,37 @@ public class SurfaceData : ItemData, IPhysicalData [BiffFloat("SLTH", Pos = 19)] public float SlingshotThreshold = 0f; - [BiffBool("SLGA", Pos = 24)] + [BiffBool("SLGA", Pos = 25)] public bool SlingshotAnimation = true; [BiffFloat("ELAS", Pos = 20)] public float Elasticity; - [BiffFloat("WFCT", Pos = 21)] + [BiffFloat("ELFO", Pos = 21, WasAddedInVp107 = true)] + public float ElasticityFalloff; + + [BiffFloat("WFCT", Pos = 22)] public float Friction; - [BiffFloat("WSCT", Pos = 22)] + [BiffFloat("WSCT", Pos = 23)] public float Scatter; - [BiffBool("VSBL", Pos = 23)] + [BiffBool("VSBL", Pos = 24)] public bool IsTopBottomVisible = true; - [BiffBool("OVPH", Pos = 30)] + [BiffBool("OVPH", Pos = 31)] public bool OverwritePhysics = true; - [BiffFloat("DILI", QuantizedUnsignedBits = 8, Pos = 26)] + [BiffFloat("DILI", QuantizedUnsignedBits = 8, Pos = 27)] public float DisableLightingTop; - [BiffFloat("DILB", Pos = 27)] + [BiffFloat("DILB", Pos = 28)] public float DisableLightingBelow; - [BiffBool("SVBL", Pos = 25)] + [BiffBool("SVBL", Pos = 26)] public bool IsSideVisible = true; - [BiffBool("REEN", Pos = 28)] + [BiffBool("REEN", Pos = 29)] public bool IsReflectionEnabled = true; [BiffDragPoint("DPNT", TagAll = true, Pos = 2000)] @@ -143,7 +146,7 @@ public class SurfaceData : ItemData, IPhysicalData // IPhysicalData public float GetElasticity() => Elasticity; - public float GetElasticityFalloff() => 0; + public float GetElasticityFalloff() => ElasticityFalloff; public float GetFriction() => Friction; public float GetScatter() => Scatter; public bool GetOverwritePhysics() => OverwritePhysics; From 387a53d3e8247341df90fa7535636544c57e5e8f Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 15 Feb 2021 21:26:44 +0100 Subject: [PATCH 09/16] data: Clean invalid material and texture reference before writing. --- VisualPinball.Engine/VPT/Table/TableWriter.cs | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/VisualPinball.Engine/VPT/Table/TableWriter.cs b/VisualPinball.Engine/VPT/Table/TableWriter.cs index 09322652c..33fffd4ff 100644 --- a/VisualPinball.Engine/VPT/Table/TableWriter.cs +++ b/VisualPinball.Engine/VPT/Table/TableWriter.cs @@ -14,8 +14,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . + using System; +using System.Collections.Generic; using System.Linq; +using System.Reflection; using OpenMcdf; using VisualPinball.Engine.IO; @@ -104,6 +107,15 @@ private void WriteGameItems(HashWriter hashWriter) // 2. game items foreach (var writeable in _table.ItemDatas.OrderBy(gi => gi.StorageIndex)) { + + #if !WRITE_VP106 + + // clean material and texture references + CleanInvalidReferences(writeable, v => _table.GetMaterial(v)); + CleanInvalidReferences(writeable, v => _table.GetTexture(v)); + + #endif + writeable.WriteData(_gameStorage); } @@ -142,5 +154,49 @@ private static void WriteStream(CFStorage storage, string streamName, byte[] dat storage.AddStream(streamName).SetData(data); hashWriter?.Write(data); } + + private static void CleanInvalidReferences(ItemData data, Func getter) where TAttr: Attribute + { + var refs = GetMembersWithAttribute(data); + foreach (var r in refs) { + var value = GetValue(r, data); + if (getter(value) == null) { + SetValue(r, data, string.Empty); + } + } + } + + private static IEnumerable GetMembersWithAttribute(ItemData data) where TAttr: Attribute + { + return data.GetType() + .GetMembers(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + .Where(member => member.GetCustomAttribute() != null); + } + + private static T GetValue(MemberInfo memberInfo, ItemData data) + { + switch (memberInfo.MemberType) { + case MemberTypes.Field: + return (T)((FieldInfo)memberInfo).GetValue(data); + case MemberTypes.Property: + return (T)((PropertyInfo)memberInfo).GetValue(data); + default: + throw new NotImplementedException(); + } + } + + private static void SetValue(MemberInfo memberInfo, ItemData data, T value) + { + switch (memberInfo.MemberType) { + case MemberTypes.Field: + ((FieldInfo)memberInfo).SetValue(data, value); + break; + case MemberTypes.Property: + ((PropertyInfo)memberInfo).SetValue(data, value); + break; + default: + throw new NotImplementedException(); + } + } } } From ff228ef85d5ca459aa19427ca103d00d64fae994 Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 15 Feb 2021 22:23:37 +0100 Subject: [PATCH 10/16] data: Tag removed attribues in VP10.7 and don't write them if WRITE_VP107 is set. --- VisualPinball.Engine/IO/BiffAttribute.cs | 5 +++++ VisualPinball.Engine/IO/BiffData.cs | 2 +- VisualPinball.Engine/VPT/BinaryData.cs | 2 +- VisualPinball.Engine/VPT/Flasher/FlasherData.cs | 2 ++ VisualPinball.Engine/VPT/TextureData.cs | 2 +- 5 files changed, 10 insertions(+), 3 deletions(-) diff --git a/VisualPinball.Engine/IO/BiffAttribute.cs b/VisualPinball.Engine/IO/BiffAttribute.cs index 5cf543b21..0cdce6fcf 100644 --- a/VisualPinball.Engine/IO/BiffAttribute.cs +++ b/VisualPinball.Engine/IO/BiffAttribute.cs @@ -101,6 +101,11 @@ public abstract class BiffAttribute : Attribute, ISortableBiffRecord /// public bool WasAddedInVp107 = false; + /// + /// If set, this attribute won't written if the WRITE_VP107 flag is set. + /// + public bool WasRemovedInVp107 = false; + /// /// If put on a field, this is the info from C#'s reflection API. /// diff --git a/VisualPinball.Engine/IO/BiffData.cs b/VisualPinball.Engine/IO/BiffData.cs index f0270461e..1c841fa08 100644 --- a/VisualPinball.Engine/IO/BiffData.cs +++ b/VisualPinball.Engine/IO/BiffData.cs @@ -210,7 +210,7 @@ protected void WriteRecord(BinaryWriter writer, Dictionary !a[0].SkipWrite && !SkipWrite(a[0])) #if WRITE_VP107 - .Where(a => !a[0].IsVpeEnhancement) + .Where(a => !a[0].IsVpeEnhancement && !a[0].WasRemovedInVp107) #endif #if WRITE_VP106 .Where(a => !a[0].IsVpeEnhancement && !a[0].WasAddedInVp107) diff --git a/VisualPinball.Engine/VPT/BinaryData.cs b/VisualPinball.Engine/VPT/BinaryData.cs index f8bebccdb..010d9fc0e 100644 --- a/VisualPinball.Engine/VPT/BinaryData.cs +++ b/VisualPinball.Engine/VPT/BinaryData.cs @@ -41,7 +41,7 @@ public class BinaryData : ItemData, IImageData [BiffString("NAME", HasExplicitLength = true, Pos = 1)] public string Name = string.Empty; - [BiffString("INME", Pos = 2)] + [BiffString("INME", Pos = 2, WasRemovedInVp107 = true)] public string InternalName = string.Empty; [BiffString("PATH", Pos = 3)] diff --git a/VisualPinball.Engine/VPT/Flasher/FlasherData.cs b/VisualPinball.Engine/VPT/Flasher/FlasherData.cs index 00b8b13fb..ce28bed14 100644 --- a/VisualPinball.Engine/VPT/Flasher/FlasherData.cs +++ b/VisualPinball.Engine/VPT/Flasher/FlasherData.cs @@ -59,9 +59,11 @@ public class FlasherData : ItemData [BiffColor("COLR", Pos = 7)] public Color Color = new Color(0xfffffff, ColorFormat.Bgr); + [TextureReference] [BiffString("IMAG", Pos = 11)] public string ImageA; + [TextureReference] [BiffString("IMAB", Pos = 12)] public string ImageB; diff --git a/VisualPinball.Engine/VPT/TextureData.cs b/VisualPinball.Engine/VPT/TextureData.cs index 137429825..a7398d0b9 100644 --- a/VisualPinball.Engine/VPT/TextureData.cs +++ b/VisualPinball.Engine/VPT/TextureData.cs @@ -40,7 +40,7 @@ public class TextureData : ItemData [BiffString("NAME", HasExplicitLength = true, Pos = 1)] public string Name = string.Empty; - [BiffString("INME", Pos = 2)] + [BiffString("INME", Pos = 2, WasRemovedInVp107 = true)] public string InternalName; [BiffString("PATH", Pos = 3)] From aa1afd0dd608f78f24f6c3b4511fd2d10dfa1233 Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 15 Feb 2021 22:42:47 +0100 Subject: [PATCH 11/16] data: Add notes (#275). --- VisualPinball.Engine/VPT/Table/TableData.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/VisualPinball.Engine/VPT/Table/TableData.cs b/VisualPinball.Engine/VPT/Table/TableData.cs index 6c063231d..2ec23b937 100644 --- a/VisualPinball.Engine/VPT/Table/TableData.cs +++ b/VisualPinball.Engine/VPT/Table/TableData.cs @@ -135,6 +135,9 @@ public class TableData : ItemData [BiffString("BLIF", Pos = 66)] public string BallImageFront; + [BiffString("NOTX", Pos = 67.5, WasAddedInVp107 = true)] + public string Notes; + [BiffString("SSHT", Pos = 68)] public string ScreenShot; From 8d45fdcad16af1f8b8360788b8e6fde278a4c663 Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 15 Feb 2021 22:43:59 +0100 Subject: [PATCH 12/16] data: Clean up flags. --- VisualPinball.Engine/IO/BiffData.cs | 2 -- VisualPinball.Engine/VPT/Table/TableWriter.cs | 1 - 2 files changed, 3 deletions(-) diff --git a/VisualPinball.Engine/IO/BiffData.cs b/VisualPinball.Engine/IO/BiffData.cs index 1c841fa08..d74bbba13 100644 --- a/VisualPinball.Engine/IO/BiffData.cs +++ b/VisualPinball.Engine/IO/BiffData.cs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#define WRITE_VP107 - using System; using System.Collections.Generic; using System.IO; diff --git a/VisualPinball.Engine/VPT/Table/TableWriter.cs b/VisualPinball.Engine/VPT/Table/TableWriter.cs index 33fffd4ff..a9a77745d 100644 --- a/VisualPinball.Engine/VPT/Table/TableWriter.cs +++ b/VisualPinball.Engine/VPT/Table/TableWriter.cs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . - using System; using System.Collections.Generic; using System.Linq; From a68c8cc2f371bbb2378cf2df0a48ddf024efa4be Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 15 Feb 2021 22:54:31 +0100 Subject: [PATCH 13/16] data: Fix layer tests. --- VisualPinball.Engine.Test/Common/ColorTests.cs | 8 ++++++++ VisualPinball.Engine.Test/IO/BiffAttributeTest.cs | 7 +++---- VisualPinball.Engine.Test/VPT/Bumper/BumperDataTests.cs | 2 +- VisualPinball.Engine.Test/VPT/Decal/DecalDataTest.cs | 4 ++-- .../VPT/DispReel/DispReelDataTest.cs | 4 ++-- VisualPinball.Engine.Test/VPT/Flasher/FlasherDataTests.cs | 2 +- VisualPinball.Engine.Test/VPT/Flipper/FlipperDataTests.cs | 2 +- VisualPinball.Engine.Test/VPT/Layers/LayerDataTests.cs | 2 +- 8 files changed, 19 insertions(+), 12 deletions(-) diff --git a/VisualPinball.Engine.Test/Common/ColorTests.cs b/VisualPinball.Engine.Test/Common/ColorTests.cs index 61d8c85b4..3ab867799 100644 --- a/VisualPinball.Engine.Test/Common/ColorTests.cs +++ b/VisualPinball.Engine.Test/Common/ColorTests.cs @@ -8,6 +8,14 @@ namespace VisualPinball.Engine.Test.Common { public class ColorTests { + // [Test] + // public void ShouldExportCorrectly() + // { + // const string path = "../../../../TestTables~/The Machine-Bride Of Pinbot (10.7).vpx"; + // var table = TableLoader.Load(path); + // new TableWriter(table).WriteTable("../../../../TestTables~/The Machine-Bride Of Pinbot (vpe).vpx"); + // } + [Test] public void TestColor() { diff --git a/VisualPinball.Engine.Test/IO/BiffAttributeTest.cs b/VisualPinball.Engine.Test/IO/BiffAttributeTest.cs index 767089847..08ea934ea 100644 --- a/VisualPinball.Engine.Test/IO/BiffAttributeTest.cs +++ b/VisualPinball.Engine.Test/IO/BiffAttributeTest.cs @@ -51,10 +51,9 @@ public void ShouldBeAppliedToStrings() [Test] public void ShouldBeAppliedToIntegers() { - GetAttributes(typeof(BiffIntAttribute), (memberType, member, biffDataType, attr) => - { - if (memberType != typeof(int) && memberType != typeof(int[])) { - throw new Exception($"BiffInt of {biffDataType.FullName}.{member.Name} ({attr.Name}) must be either int or int[], but is {memberType.Name}."); + GetAttributes(typeof(BiffIntAttribute), (memberType, member, biffDataType, attr) => { + if (memberType != typeof(int) && memberType != typeof(int[]) && memberType != typeof(uint) && memberType != typeof(uint[])) { + throw new Exception($"BiffInt of {biffDataType.FullName}.{member.Name} ({attr.Name}) must be either (u)int or (u)int[], but is {memberType.Name}."); } }); } diff --git a/VisualPinball.Engine.Test/VPT/Bumper/BumperDataTests.cs b/VisualPinball.Engine.Test/VPT/Bumper/BumperDataTests.cs index 3167d49af..a6a6b5aaa 100644 --- a/VisualPinball.Engine.Test/VPT/Bumper/BumperDataTests.cs +++ b/VisualPinball.Engine.Test/VPT/Bumper/BumperDataTests.cs @@ -71,7 +71,7 @@ private static void ValidateTableData(BumperData data) data.IsTimerEnabled.Should().Be(false); data.EditorLayer.Should().Be(0); - data.EditorLayerName.Should().Be(string.Empty); + data.EditorLayerName.Should().Be("Layer_1"); data.EditorLayerVisibility.Should().Be(true); data.IsLocked.Should().Be(false); } diff --git a/VisualPinball.Engine.Test/VPT/Decal/DecalDataTest.cs b/VisualPinball.Engine.Test/VPT/Decal/DecalDataTest.cs index 3b89d2825..a8b4a18ee 100644 --- a/VisualPinball.Engine.Test/VPT/Decal/DecalDataTest.cs +++ b/VisualPinball.Engine.Test/VPT/Decal/DecalDataTest.cs @@ -63,7 +63,7 @@ private static void ValidateDecal0(DecalData data) data.VerticalText.Should().Be(false); data.Width.Should().Be(66.1165f); data.EditorLayer.Should().Be(2); - data.EditorLayerName.Should().Be(string.Empty); + data.EditorLayerName.Should().Be("Layer_3"); data.EditorLayerVisibility.Should().Be(true); data.IsLocked.Should().Be(false); } @@ -88,7 +88,7 @@ private static void ValidateDecal1(DecalData data) data.VerticalText.Should().Be(true); data.Width.Should().Be(100f); data.EditorLayer.Should().Be(0); - data.EditorLayerName.Should().Be(string.Empty); + data.EditorLayerName.Should().Be("Layer_1"); data.EditorLayerVisibility.Should().Be(true); data.IsLocked.Should().Be(true); } diff --git a/VisualPinball.Engine.Test/VPT/DispReel/DispReelDataTest.cs b/VisualPinball.Engine.Test/VPT/DispReel/DispReelDataTest.cs index 6a63c2322..86de042c8 100644 --- a/VisualPinball.Engine.Test/VPT/DispReel/DispReelDataTest.cs +++ b/VisualPinball.Engine.Test/VPT/DispReel/DispReelDataTest.cs @@ -49,7 +49,7 @@ private static void ValidateDispReel1(DispReelData data) data.BackColor.Blue.Should().Be(19); data.DigitRange.Should().Be(3); data.EditorLayer.Should().Be(6); - data.EditorLayerName.Should().Be(string.Empty); + data.EditorLayerName.Should().Be("Layer_7"); data.EditorLayerVisibility.Should().Be(true); data.Height.Should().Be(42); data.Image.Should().Be("tex_transparent"); @@ -80,7 +80,7 @@ private static void ValidateDispReel2(DispReelData data) data.BackColor.Blue.Should().Be(255); data.DigitRange.Should().Be(9); data.EditorLayer.Should().Be(0); - data.EditorLayerName.Should().Be(string.Empty); + data.EditorLayerName.Should().Be("Layer_1"); data.EditorLayerVisibility.Should().Be(true); data.Height.Should().Be(40); data.Image.Should().Be(""); diff --git a/VisualPinball.Engine.Test/VPT/Flasher/FlasherDataTests.cs b/VisualPinball.Engine.Test/VPT/Flasher/FlasherDataTests.cs index 1382d3e6c..f5ba43f6e 100644 --- a/VisualPinball.Engine.Test/VPT/Flasher/FlasherDataTests.cs +++ b/VisualPinball.Engine.Test/VPT/Flasher/FlasherDataTests.cs @@ -73,7 +73,7 @@ private static void ValidateFlasher(FlasherData data) data.IsTimerEnabled.Should().Be(false); data.EditorLayer.Should().Be(10); - data.EditorLayerName.Should().Be(string.Empty); + data.EditorLayerName.Should().Be("Layer_11"); data.EditorLayerVisibility.Should().Be(true); data.IsLocked.Should().Be(true); } diff --git a/VisualPinball.Engine.Test/VPT/Flipper/FlipperDataTests.cs b/VisualPinball.Engine.Test/VPT/Flipper/FlipperDataTests.cs index 68dafcf9a..f425c9798 100644 --- a/VisualPinball.Engine.Test/VPT/Flipper/FlipperDataTests.cs +++ b/VisualPinball.Engine.Test/VPT/Flipper/FlipperDataTests.cs @@ -77,7 +77,7 @@ private static void ValidateFlipper(FlipperData data) data.IsTimerEnabled.Should().Be(false); data.EditorLayer.Should().Be(0); - data.EditorLayerName.Should().Be(string.Empty); + data.EditorLayerName.Should().Be("Layer_1"); data.EditorLayerVisibility.Should().Be(true); data.IsLocked.Should().Be(false); } diff --git a/VisualPinball.Engine.Test/VPT/Layers/LayerDataTests.cs b/VisualPinball.Engine.Test/VPT/Layers/LayerDataTests.cs index ddec8da92..be95c7e27 100644 --- a/VisualPinball.Engine.Test/VPT/Layers/LayerDataTests.cs +++ b/VisualPinball.Engine.Test/VPT/Layers/LayerDataTests.cs @@ -54,7 +54,7 @@ public void ShouldWriteLayerData() private static void ValidateTableDataVPX1060(BumperData data) { data.EditorLayer.Should().Be(0); - data.EditorLayerName.Should().Be(string.Empty); + data.EditorLayerName.Should().Be("Layer_1"); data.EditorLayerVisibility.Should().Be(true); data.IsLocked.Should().Be(false); } From 6d818fcc593121c4ea3eb562934dae5e1dae5739 Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 15 Feb 2021 22:55:38 +0100 Subject: [PATCH 14/16] chore(test): Cleanup unused test. --- VisualPinball.Engine.Test/Common/ColorTests.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/VisualPinball.Engine.Test/Common/ColorTests.cs b/VisualPinball.Engine.Test/Common/ColorTests.cs index 3ab867799..8eb9f46d5 100644 --- a/VisualPinball.Engine.Test/Common/ColorTests.cs +++ b/VisualPinball.Engine.Test/Common/ColorTests.cs @@ -2,20 +2,11 @@ using FluentAssertions; using NUnit.Framework; using VisualPinball.Engine.Math; -using VisualPinball.Engine.VPT.Table; namespace VisualPinball.Engine.Test.Common { public class ColorTests { - // [Test] - // public void ShouldExportCorrectly() - // { - // const string path = "../../../../TestTables~/The Machine-Bride Of Pinbot (10.7).vpx"; - // var table = TableLoader.Load(path); - // new TableWriter(table).WriteTable("../../../../TestTables~/The Machine-Bride Of Pinbot (vpe).vpx"); - // } - [Test] public void TestColor() { From 1db51a103edc1b5969493d70c17f6962936d61c5 Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 15 Feb 2021 23:08:38 +0100 Subject: [PATCH 15/16] doc: Update CHANGELOG. --- CHANGELOG.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3167093c6..84d9f2cd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,16 +7,23 @@ Built with [Unity 2020.2](https://github.com/freezy/VisualPinball.Engine/pull/255). ### Added +- Support for Extended ASCII strings ([#291](https://github.com/freezy/VisualPinball.Engine/pull/291)). +- Support for Elasticity Falloff in walls (added in VP 10.7) ([#291](https://github.com/freezy/VisualPinball.Engine/pull/291)). +- Support for table notes (added in VP 10.7) ([#291](https://github.com/freezy/VisualPinball.Engine/pull/291)). - Slow motion during gameplay ([#288](https://github.com/freezy/VisualPinball.Engine/pull/288)). - [Lamp Manager](https://docs.visualpinball.org/creators-guide/editor/lamp-manager.html) ([#282](https://github.com/freezy/VisualPinball.Engine/pull/282)). - The VPE core is now also available on [NuGet](https://www.nuget.org/packages/VisualPinball.Engine/). - VPE is now packaged and published on every merge! -- Native trough component ([#229](https://github.com/freezy/VisualPinball.Engine/pull/229), [#248](https://github.com/freezy/VisualPinball.Engine/pull/248), [#256](https://github.com/freezy/VisualPinball.Engine/pull/256), [Documentation](https://docs.visualpinball.org/creators-guide/manual/mechanisms/troughs.html)) +- Native trough component ([#229](https://github.com/freezy/VisualPinball.Engine/pull/229), [#248](https://github.com/freezy/VisualPinball.Engine/pull/248), [#256](https://github.com/freezy/VisualPinball.Engine/pull/256), [Documentation](https://docs.visualpinball.org/creators-guide/manual/mechanisms/troughs.html)). ### Changed - Plunger is now a coil device, meaning it can both be pulled back and fired through different inputs. -- Move render pipelines into separate repos ([#259](https://github.com/freezy/VisualPinball.Engine/pull/259)) -- Put game-, mesh-, collision- animation data into separate components ([#227](https://github.com/freezy/VisualPinball.Engine/pull/227), [Documentation](https://docs.visualpinball.org/creators-guide/editor/unity-components.html)) +- Move render pipelines into separate repos ([#259](https://github.com/freezy/VisualPinball.Engine/pull/259)). +- Put game-, mesh-, collision- animation data into separate components ([#227](https://github.com/freezy/VisualPinball.Engine/pull/227), [Documentation](https://docs.visualpinball.org/creators-guide/editor/unity-components.html)). ### Fixed -- Fixed a few bugs in drag point gizmos ([#246](https://github.com/freezy/VisualPinball.Engine/pull/246)) +- Alpha channel of color values is now correctly written ([#291](https://github.com/freezy/VisualPinball.Engine/pull/291)). +- Layer names are correctly computed when importing a 10.6 file ([#291](https://github.com/freezy/VisualPinball.Engine/pull/291)). +- Clear texture and material references that don't exist before writing (VP 10.7 behavior) ([#291](https://github.com/freezy/VisualPinball.Engine/pull/291)). +- Bug in writing animation vertices which caused VP to hang when re-reading the file ([#291](https://github.com/freezy/VisualPinball.Engine/pull/291)). +- A few bugs in drag point gizmos ([#246](https://github.com/freezy/VisualPinball.Engine/pull/246)). From 9d1e0742b541efa69343592e137090386437a34d Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 15 Feb 2021 23:35:41 +0100 Subject: [PATCH 16/16] data: Add tests for reference clearing. --- .../Common/ColorTests.cs | 25 -------- .../IO/ConsistencyTests.cs | 64 +++++++++++++++++++ .../Math/{ColorTest.cs => ColorTests.cs} | 18 +++++- .../VPT/Table/TableBuilder.cs | 9 +++ 4 files changed, 90 insertions(+), 26 deletions(-) delete mode 100644 VisualPinball.Engine.Test/Common/ColorTests.cs create mode 100644 VisualPinball.Engine.Test/IO/ConsistencyTests.cs rename VisualPinball.Engine.Test/Math/{ColorTest.cs => ColorTests.cs} (71%) diff --git a/VisualPinball.Engine.Test/Common/ColorTests.cs b/VisualPinball.Engine.Test/Common/ColorTests.cs deleted file mode 100644 index 8eb9f46d5..000000000 --- a/VisualPinball.Engine.Test/Common/ColorTests.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.IO; -using FluentAssertions; -using NUnit.Framework; -using VisualPinball.Engine.Math; - -namespace VisualPinball.Engine.Test.Common -{ - public class ColorTests - { - [Test] - public void TestColor() - { - using (var memStream = new MemoryStream(new byte[] {0xff, 0xa0, 0xb4, 0x80 })) { - using (var reader = new BinaryReader(memStream)) { - var intCol = reader.ReadUInt32(); - var color = new Color(intCol, ColorFormat.Bgr); - color.Red.Should().Be(0xff); - color.Green.Should().Be(0xa0); - color.Blue.Should().Be(0xb4); - color.Alpha.Should().Be(0x80); - } - } - } - } -} diff --git a/VisualPinball.Engine.Test/IO/ConsistencyTests.cs b/VisualPinball.Engine.Test/IO/ConsistencyTests.cs new file mode 100644 index 000000000..8a75ceb49 --- /dev/null +++ b/VisualPinball.Engine.Test/IO/ConsistencyTests.cs @@ -0,0 +1,64 @@ +// Visual Pinball Engine +// Copyright (C) 2021 freezy and VPE Team +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +using FluentAssertions; +using NUnit.Framework; +using VisualPinball.Engine.VPT; +using VisualPinball.Engine.VPT.Table; + +namespace VisualPinball.Engine.Test.IO +{ + public class ConsistencyTests + { + [Test] + public void ShouldClearWrongMaterialReference() + { + const string tmpFileName = "ShouldClearWrongMaterialReference.vpx"; + + var table = new TableBuilder() + .AddBumper("Bumper1") + .AddMaterial(new Material("DoesExist")) + .Build(); + + table.Bumper("Bumper1").Data.BaseMaterial = "DoesExist"; + table.Bumper("Bumper1").Data.CapMaterial = "DoesNotExist"; + + table.Save(tmpFileName); + + table.Bumper("Bumper1").Data.BaseMaterial.Should().Be("DoesExist"); + table.Bumper("Bumper1").Data.CapMaterial.Should().BeEmpty(); + } + + [Test] + public void ShouldClearWrongTextureReference() + { + const string tmpFileName = "ShouldClearWrongTextureReference.vpx"; + + var table = new TableBuilder() + .AddFlipper("Flipper") + .AddTexture("DoesExist") + .Build(); + + table.Flipper("Flipper").Data.Image = "DoesExist"; + table.Save(tmpFileName); + table.Flipper("Flipper").Data.Image.Should().Be("DoesExist"); + + table.Flipper("Flipper").Data.Image = "DoesNotExist"; + table.Save(tmpFileName); + table.Flipper("Flipper").Data.Image.Should().BeEmpty(); + } + } +} diff --git a/VisualPinball.Engine.Test/Math/ColorTest.cs b/VisualPinball.Engine.Test/Math/ColorTests.cs similarity index 71% rename from VisualPinball.Engine.Test/Math/ColorTest.cs rename to VisualPinball.Engine.Test/Math/ColorTests.cs index adbc848a2..5e71695b7 100644 --- a/VisualPinball.Engine.Test/Math/ColorTest.cs +++ b/VisualPinball.Engine.Test/Math/ColorTests.cs @@ -14,13 +14,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System.IO; using FluentAssertions; using NUnit.Framework; using VisualPinball.Engine.Math; namespace VisualPinball.Engine.Test.Math { - public class TableDataTests + public class ColorTests { [Test] public void ShouldCorrectlyParseRgbColor() @@ -40,5 +41,20 @@ public void ShouldCorrectlyParseArgbColor() color.Blue.Should().Be(0x78); color.Alpha.Should().Be(0x12); } + + [Test] + public void TestColor() + { + using (var memStream = new MemoryStream(new byte[] {0xff, 0xa0, 0xb4, 0x80 })) { + using (var reader = new BinaryReader(memStream)) { + var intCol = reader.ReadUInt32(); + var color = new Color(intCol, ColorFormat.Bgr); + color.Red.Should().Be(0xff); + color.Green.Should().Be(0xa0); + color.Blue.Should().Be(0xb4); + color.Alpha.Should().Be(0x80); + } + } + } } } diff --git a/VisualPinball.Engine/VPT/Table/TableBuilder.cs b/VisualPinball.Engine/VPT/Table/TableBuilder.cs index b0ce787bf..814406a2a 100644 --- a/VisualPinball.Engine/VPT/Table/TableBuilder.cs +++ b/VisualPinball.Engine/VPT/Table/TableBuilder.cs @@ -19,6 +19,7 @@ using VisualPinball.Engine.VPT.Bumper; using VisualPinball.Engine.VPT.Flipper; using VisualPinball.Engine.VPT.Light; +using VisualPinball.Engine.VPT.Rubber; using VisualPinball.Engine.VPT.Trough; namespace VisualPinball.Engine.VPT.Table @@ -62,6 +63,14 @@ public TableBuilder AddMaterial(Material material) return this; } + public TableBuilder AddTexture(string name) + { + _table.Textures.Add(new Texture(name)); + _table.Data.NumTextures = _table.Textures.Count; + + return this; + } + public TableBuilder AddFlipper(string name) { var data = new FlipperData($"GameItem{_gameItem++}") {