Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)).
7 changes: 3 additions & 4 deletions VisualPinball.Engine.Test/IO/BiffAttributeTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,9 @@ public void ShouldBeAppliedToStrings()
[Test]
public void ShouldBeAppliedToIntegers()
{
GetAttributes<BiffIntAttribute>(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<BiffIntAttribute>(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}.");
}
});
}
Expand Down
64 changes: 64 additions & 0 deletions VisualPinball.Engine.Test/IO/ConsistencyTests.cs
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.

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();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

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()
Expand All @@ -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);
}
}
}
}
}
2 changes: 1 addition & 1 deletion VisualPinball.Engine.Test/VPT/Bumper/BumperDataTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
4 changes: 2 additions & 2 deletions VisualPinball.Engine.Test/VPT/Decal/DecalDataTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand Down
4 changes: 2 additions & 2 deletions VisualPinball.Engine.Test/VPT/DispReel/DispReelDataTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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("");
Expand Down
2 changes: 1 addition & 1 deletion VisualPinball.Engine.Test/VPT/Flasher/FlasherDataTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion VisualPinball.Engine.Test/VPT/Flipper/FlipperDataTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion VisualPinball.Engine.Test/VPT/Layers/LayerDataTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
20 changes: 18 additions & 2 deletions VisualPinball.Engine/IO/BiffAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,22 @@ public abstract class BiffAttribute : Attribute, ISortableBiffRecord
/// </summary>
public bool SkipHash = false;

/// <summary>
/// If set, counts as data exclusively used by VPE and can be disabled when writing with WRITE_VP106
/// or WRITE_VP107 active.
/// </summary>
public bool IsVpeEnhancement = false;

/// <summary>
/// If set, this attribute won't written if the WRITE_VP106 flag is set.
/// </summary>
public bool WasAddedInVp107 = false;

/// <summary>
/// If set, this attribute won't written if the WRITE_VP107 flag is set.
/// </summary>
public bool WasRemovedInVp107 = false;

/// <summary>
/// If put on a field, this is the info from C#'s reflection API.
/// </summary>
Expand Down Expand Up @@ -249,9 +265,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();
}
Expand Down
2 changes: 1 addition & 1 deletion VisualPinball.Engine/IO/BiffColorAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
11 changes: 10 additions & 1 deletion VisualPinball.Engine/IO/BiffData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,11 @@ protected static void Init(Type type, Dictionary<string, List<BiffAttribute>> at
/// <returns></returns>
protected static T Load<T>(T obj, BinaryReader reader, Dictionary<string, List<BiffAttribute>> attributes) where T : BiffData
{

#if WRITE_VP106 || WRITE_VP106
var ignoredTags = typeof(T).GetCustomAttributes<BiffIgnoreAttribute>().Where(a => !a.IsDeprecatedInVP).Select(a => a.Name).ToArray();
#else
var ignoredTags = typeof(T).GetCustomAttributes<BiffIgnoreAttribute>().Select(a => a.Name).ToArray();
#endif

// initially read length and BIFF record name
var len = reader.ReadInt32();
Expand Down Expand Up @@ -204,6 +207,12 @@ protected void WriteRecord(BinaryWriter writer, Dictionary<string, List<BiffAttr
// filter known records, join them with unknown records, and sort.
var records = attributes.Values
.Where(a => !a[0].SkipWrite && !SkipWrite(a[0]))
#if WRITE_VP107
.Where(a => !a[0].IsVpeEnhancement && !a[0].WasRemovedInVp107)
#endif
#if WRITE_VP106
.Where(a => !a[0].IsVpeEnhancement && !a[0].WasAddedInVp107)
#endif
.Select(a => a[0] as ISortableBiffRecord)
.Concat(UnknownRecords ?? new List<UnknownBiffRecord>())
.OrderBy(r => r.GetPosition());
Expand Down
5 changes: 5 additions & 0 deletions VisualPinball.Engine/IO/BiffIgnoreAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ public class BiffIgnoreAttribute : Attribute
{
public readonly string Name;

/// <summary>
/// If set, marks this as "deprecated in VP", which still writes it when the WRITE_VP106 or WRITE_VP107 flag is set.
/// </summary>
public bool IsDeprecatedInVP;

public BiffIgnoreAttribute(string name)
{
Name = name;
Expand Down
3 changes: 1 addition & 2 deletions VisualPinball.Engine/IO/BiffStringAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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");

/// <summary>
/// Wide strings have a zero byte between each character.
Expand Down
21 changes: 11 additions & 10 deletions VisualPinball.Engine/Math/Color.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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;
}
}
Expand All @@ -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;
}
Expand Down
9 changes: 6 additions & 3 deletions VisualPinball.Engine/Math/DragPointData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion VisualPinball.Engine/VPT/BinaryData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
Loading