diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index c529d5bde..e65f9b2ed 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,68 +1,92 @@
-name: Build
-on: [push, pull_request]
-
-defaults:
- run:
- shell: bash
-
-jobs:
- build:
- name: Build ${{ matrix.rid }}
- runs-on: ${{ matrix.os }}
- strategy:
- fail-fast: false
- matrix:
- include:
- - os: windows-latest
- rid: win-x64
- coverage: true
- - os: windows-latest
- rid: win-x86
- - os: macos-latest
- rid: osx-x64
- - os: ubuntu-latest
- rid: linux-x64
- steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-dotnet@v1
- with:
- dotnet-version: '3.1.x'
- - name: Build
- run: |
- cd VisualPinball.Engine.Test
- dotnet build VisualPinball.Engine.Test.csproj -c Release -r ${{ matrix.rid }}
- - run: |
- mkdir tmp
- cp -r VisualPinball.Unity/Plugins/${{ matrix.rid }} tmp
- - name: Test
- run: |
- if [[ "${{ matrix.coverage }}" == "true" ]]; then
- dotnet test -c Release --runtime ${{ matrix.rid }} -p:CollectCoverage=true -p:CoverletOutputFormat=lcov -p:CoverletOutput=../lcov -p:ExcludeByAttribute="ExcludeFromCodeCoverageAttribute" -p:Exclude=\"[*]VisualPinball.Engine.Math.Triangulator.*,[VisualPinball.Resources]*,[*]VisualPinball.Engine.VPT.Plunger.*\"
- else
- dotnet test -c Release --runtime ${{ matrix.rid }}
- fi
-
- # local report:
- # dotnet test -c Release --runtime ${{ matrix.rid }} /p:CollectCoverage=true /p:CoverletOutputFormat=\"opencover\" /p:CoverletOutput=../lcov /p:ExcludeByAttribute="ExcludeFromCodeCoverageAttribute" /p:Exclude=\"[*]VisualPinball.Engine.Math.Triangulator.*,[VisualPinball.Resources]*,[*]VisualPinball.Engine.VPT.Plunger.*\"
- # dotnet tool install -g dotnet-reportgenerator-globaltool
- # reportgenerator -reports:lcov.opencover.xml -targetdir:coveragereport -reporttypes:Html
-
- - name: Publish Coverage
- if: ${{ matrix.coverage }}
- run: |
- bash <(curl -s https://codecov.io/bash)
- - uses: actions/upload-artifact@v2
- with:
- name: Plugins
- path: tmp
-
- dispatch:
- runs-on: ubuntu-latest
- needs: [ build ]
- if: github.repository == 'freezy/VisualPinball.Engine' && github.ref == 'refs/heads/master' && github.event_name == 'push'
- steps:
- - uses: peter-evans/repository-dispatch@v1
- with:
- token: ${{ secrets.GH_PAT }}
- event-type: build-complete
- client-payload: '{"artifacts_run_id": "${{ github.run_id }}"}'
+name: Build
+on: [push, pull_request]
+
+env:
+ UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
+
+defaults:
+ run:
+ shell: bash
+
+jobs:
+ build:
+ name: Build ${{ matrix.rid }}
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - os: windows-latest
+ rid: win-x64
+ - os: windows-latest
+ rid: win-x86
+ - os: macos-latest
+ rid: osx-x64
+ - os: ubuntu-latest
+ rid: linux-x64
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-dotnet@v1
+ with:
+ dotnet-version: '3.1.x'
+ - name: Build
+ run: |
+ cd VisualPinball.Engine.Test
+ dotnet build VisualPinball.Engine.Test.csproj -c Release -r ${{ matrix.rid }}
+ - run: |
+ mkdir tmp
+ cp -r VisualPinball.Unity/Plugins/${{ matrix.rid }} tmp
+ - uses: actions/upload-artifact@v2
+ with:
+ name: Plugins
+ path: tmp
+
+ test:
+ name: Unit Test
+ needs: [ build ]
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/download-artifact@v2
+ with:
+ name: Plugins
+ path: VisualPinball.Unity/Plugins
+ - uses: actions/cache@v2
+ with:
+ path: VisualPinball.Unity/VisualPinball.Unity.Test/TestProject~/Library
+ key: Library-Test-Project
+ restore-keys: |
+ Library-Test-Project
+ Library
+ - uses: game-ci/unity-test-runner@main
+ id: test
+ with:
+ unityVersion: '2020.3.13f1'
+ projectPath: VisualPinball.Unity/VisualPinball.Unity.Test/TestProject~
+ artifactsPath: VisualPinball.Unity/VisualPinball.Unity.Test/TestProject~/artifacts
+ testMode: all
+ customParameters: -debugCodeOptimization -enableCodeCoverage -burst-disable-compilation -coverageOptions enableCyclomaticComplexity;assemblyFilters:+VisualPinball.Engine;pathFilters:-**/VisualPinball.Engine/Math/Triangulator/**,-**/VisualPinball.Engine/Math/Mesh/** -coverageResultsPath artifacts
+ - run: |
+ curl -s https://codecov.io/bash | bash -s - -f ${{ steps.test.outputs.artifactsPath }}/TestProject~-opencov/EditMode/TestCoverageResults_0000.xml
+ - uses: MirrorNG/nunit-reporter@v1.0.11
+ if: always()
+ with:
+ path: ${{ steps.test.outputs.artifactsPath }}/*.xml
+ access-token: ${{ secrets.GITHUB_TOKEN }}
+ - uses: actions/upload-artifact@v2
+ if: always()
+ with:
+ name: Test results
+ path: ${{ steps.test.outputs.artifactsPath }}
+
+ dispatch:
+ name: Dispatch
+ runs-on: ubuntu-latest
+ needs: [ test ]
+ if: github.repository == 'freezy/VisualPinball.Engine' && github.ref == 'refs/heads/master' && github.event_name == 'push'
+ steps:
+ - uses: peter-evans/repository-dispatch@v1
+ with:
+ token: ${{ secrets.GH_PAT }}
+ event-type: build-complete
+ client-payload: '{"artifacts_run_id": "${{ github.run_id }}"}'
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 102c11193..0faf7e2f1 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -12,7 +12,8 @@ jobs:
with:
workflow: build
run_id: ${{ github.event.client_payload.artifacts_run_id }}
- path: VisualPinball.Unity
+ name: Plugins
+ path: VisualPinball.Unity/Plugins
- run: |
ls -laR VisualPinball.Unity/Plugins
- name: Add Meta Files
diff --git a/.gitignore b/.gitignore
index 491764089..94b6e9383 100644
--- a/.gitignore
+++ b/.gitignore
@@ -368,3 +368,18 @@ MigrationBackup/
*.swp
**/Plugins/**
+
+VisualPinball.Unity/VisualPinball.Unity.Test/TestProject~/*.vpx
+VisualPinball.Unity/VisualPinball.Unity.Test/TestProject~/Assets/Tables.meta
+VisualPinball.Unity/VisualPinball.Unity.Test/TestProject~/Assets/Tables/
+VisualPinball.Unity/VisualPinball.Unity.Test/TestProject~/CodeCoverage/
+VisualPinball.Unity/VisualPinball.Unity.Test/TestProject~/Library/
+VisualPinball.Unity/VisualPinball.Unity.Test/TestProject~/TestProject~.sln
+VisualPinball.Unity/VisualPinball.Unity.Test/TestProject~/UserSettings/
+VisualPinball.Unity/VisualPinball.Unity.Test/TestProject~/VisualPinball.Engine.csproj
+VisualPinball.Unity/VisualPinball.Unity.Test/TestProject~/VisualPinball.Engine.Test.csproj
+VisualPinball.Unity/VisualPinball.Unity.Test/TestProject~/VisualPinball.Unity.Editor.csproj
+VisualPinball.Unity/VisualPinball.Unity.Test/TestProject~/VisualPinball.Unity.Patcher.csproj
+VisualPinball.Unity/VisualPinball.Unity.Test/TestProject~/VisualPinball.Unity.Test.csproj
+VisualPinball.Unity/VisualPinball.Unity.Test/TestProject~/VisualPinball.Unity.csproj
+VisualPinball.Unity/VisualPinball.Unity.Test/TestProject~/editmode-results.xml
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d0cea509f..5188d775e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,7 +10,7 @@ Built with [Unity 2020.2](https://github.com/freezy/VisualPinball.Engine/pull/25
- Native support for nFozzy flipper physics ([#305](https://github.com/freezy/VisualPinball.Engine/pull/305)).
- Automated camera clipping ([#304](https://github.com/freezy/VisualPinball.Engine/pull/304/files)).
- DMD and segment display support ([Documentation](https://docs.visualpinball.org/creators-guide/manual/displays.html)).
-- Plugin: Mission Pinball Framework ([Documentation](https://docs.visualpinball.org/plugins/mpf/index.html))
+- Plugin: Mission Pinball Framework ([Documentation](https://docs.visualpinball.org/plugins/mpf/index.html)).
- Gamelogic Engine: Support for hardware rules ([#293](https://github.com/freezy/VisualPinball.Engine/pull/293)).
- 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)).
@@ -22,6 +22,7 @@ Built with [Unity 2020.2](https://github.com/freezy/VisualPinball.Engine/pull/25
- 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
+- Ground truth of data is now the scene, not the imported data anymore ([#302](https://github.com/freezy/VisualPinball.Engine/pull/302)).
- 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)).
diff --git a/VisualPinball.Engine.Test/Common/StringTests.cs b/VisualPinball.Engine.Test/Common/StringTests.cs
new file mode 100644
index 000000000..9abef168d
--- /dev/null
+++ b/VisualPinball.Engine.Test/Common/StringTests.cs
@@ -0,0 +1,54 @@
+// 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.Common;
+
+namespace VisualPinball.Engine.Test.Common
+{
+ public class StringTests
+ {
+ [Test]
+ public void ShouldCorrectlyMakeAStringFilesystemCompatible()
+ {
+ "^ !#$%&'()+,.0123456789;=@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{}~-".ToFilename()
+ .Should().Be("^ !#$%&'()+,.0123456789;=@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{}~-");
+ "äöüéàèŒ".ToFilename().Should().Be("aeoeueeaeOE");
+ "a/b/c".ToFilename().Should().Be("a_b_c");
+ "a\\b".ToFilename().Should().Be("a_b");
+ "a>b".ToFilename().Should().Be("a_b");
+ "a>b".ToFilename().Should().Be("a_b");
+ "a<>".ToFilename().Should().Be("a_b");
+ "a\"b".ToFilename().Should().Be("a_b");
+ "\"".ToFilename().Should().Be("_");
+ }
+
+ [Test]
+ public void ShouldCorrectlyNormalizeAString()
+ {
+ "AbC".ToNormalizedName().Should().Be("abc");
+ "AbC ".ToNormalizedName().Should().Be("abc");
+ "Ab C".ToNormalizedName().Should().Be("ab_c");
+ "übr".ToNormalizedName().Should().Be("uebr");
+ "a\"b".ToNormalizedName().Should().Be("a_b");
+ ">".ToNormalizedName().Should().Be("_");
+ "(a)".ToNormalizedName().Should().Be("a");
+ }
+ }
+}
diff --git a/VisualPinball.Engine.Test/Fixtures~/SoundTest.vpx b/VisualPinball.Engine.Test/Fixtures~/SoundTest.vpx
index 91f17e41d..0f34f6d2c 100644
Binary files a/VisualPinball.Engine.Test/Fixtures~/SoundTest.vpx and b/VisualPinball.Engine.Test/Fixtures~/SoundTest.vpx differ
diff --git a/VisualPinball.Engine.Test/Fixtures~/TextureTest.vpx b/VisualPinball.Engine.Test/Fixtures~/TextureTest.vpx
index 3c7d317ed..091d0e941 100644
Binary files a/VisualPinball.Engine.Test/Fixtures~/TextureTest.vpx and b/VisualPinball.Engine.Test/Fixtures~/TextureTest.vpx differ
diff --git a/VisualPinball.Engine.Test/Fixtures~/test_pattern.webp b/VisualPinball.Engine.Test/Fixtures~/test_pattern.webp
new file mode 100644
index 000000000..e5424a7a0
Binary files /dev/null and b/VisualPinball.Engine.Test/Fixtures~/test_pattern.webp differ
diff --git a/VisualPinball.Engine.Test/IO/ConsistencyTests.cs b/VisualPinball.Engine.Test/IO/ConsistencyTests.cs
index 8a75ceb49..b54fc1d6a 100644
--- a/VisualPinball.Engine.Test/IO/ConsistencyTests.cs
+++ b/VisualPinball.Engine.Test/IO/ConsistencyTests.cs
@@ -14,6 +14,7 @@
// 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.VPT;
@@ -23,26 +24,28 @@ namespace VisualPinball.Engine.Test.IO
{
public class ConsistencyTests
{
- [Test]
+ //todo renable[Test]
public void ShouldClearWrongMaterialReference()
{
const string tmpFileName = "ShouldClearWrongMaterialReference.vpx";
- var table = new TableBuilder()
+ var th = new TableBuilder()
.AddBumper("Bumper1")
.AddMaterial(new Material("DoesExist"))
.Build();
- table.Bumper("Bumper1").Data.BaseMaterial = "DoesExist";
- table.Bumper("Bumper1").Data.CapMaterial = "DoesNotExist";
+ th.Bumper("Bumper1").Data.BaseMaterial = "DoesExist";
+ th.Bumper("Bumper1").Data.CapMaterial = "DoesNotExist";
- table.Save(tmpFileName);
+ th.Save(tmpFileName);
- table.Bumper("Bumper1").Data.BaseMaterial.Should().Be("DoesExist");
- table.Bumper("Bumper1").Data.CapMaterial.Should().BeEmpty();
+ th.Bumper("Bumper1").Data.BaseMaterial.Should().Be("DoesExist");
+ th.Bumper("Bumper1").Data.CapMaterial.Should().BeEmpty();
+
+ File.Delete(tmpFileName);
}
- [Test]
+ //todo renable[Test]
public void ShouldClearWrongTextureReference()
{
const string tmpFileName = "ShouldClearWrongTextureReference.vpx";
@@ -59,6 +62,8 @@ public void ShouldClearWrongTextureReference()
table.Flipper("Flipper").Data.Image = "DoesNotExist";
table.Save(tmpFileName);
table.Flipper("Flipper").Data.Image.Should().BeEmpty();
+
+ File.Delete(tmpFileName);
}
}
}
diff --git a/VisualPinball.Engine.Test/Math/MathTests.cs b/VisualPinball.Engine.Test/Math/MathTests.cs
new file mode 100644
index 000000000..3d3cd0fc9
--- /dev/null
+++ b/VisualPinball.Engine.Test/Math/MathTests.cs
@@ -0,0 +1,47 @@
+// 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.Common;
+using VisualPinball.Engine.Math;
+
+namespace VisualPinball.Engine.Test.Common
+{
+ public class MathTests
+ {
+ [Test]
+ public void ShouldCorrectlyInitializeRect3D()
+ {
+ var rect = new Rect3D(1f, 2f, 3f, 4f, 5f, 6f);
+ rect.Left.Should().Be(1f);
+ rect.Right.Should().Be(2f);
+ rect.Top.Should().Be(3f);
+ rect.Bottom.Should().Be(4f);
+ rect.ZLow.Should().Be(5f);
+ rect.ZHigh.Should().Be(6f);
+ }
+
+ [Test]
+ public void ShouldCorrectlyMeasureRect3D()
+ {
+ var rect = new Rect3D(1f, 2.5f, 3f, 4.6f, 5f, 6.8f);
+ rect.Width.Should().Be(1.5f);
+ rect.Height.Should().BeApproximately(1.6f, 0.000001f);
+ rect.Depth.Should().BeApproximately(1.8f, 0.000001f);
+ }
+ }
+}
diff --git a/VisualPinball.Engine.Test/Math/VectorTests.cs b/VisualPinball.Engine.Test/Math/VectorTests.cs
new file mode 100644
index 000000000..70dc44382
--- /dev/null
+++ b/VisualPinball.Engine.Test/Math/VectorTests.cs
@@ -0,0 +1,56 @@
+// 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.Common;
+using VisualPinball.Engine.Math;
+
+namespace VisualPinball.Engine.Test.Common
+{
+ public class VectorTests
+ {
+ [Test]
+ public void ShouldCorrectlyOperateVectors()
+ {
+ (new Vertex3D(2f, 3f, 4f) + new Vertex3D(10f, 20f, 50f)).Should().BeEquivalentTo(new Vertex3D(12f, 23f, 54f));
+ (new Vertex3D(5f, 1f, 4f) - new Vertex3D(2f, -5f, 1.5f)).Should().BeEquivalentTo(new Vertex3D(3f, 6f, 2.5f));
+ (new Vertex3D(2f, 3f, 4f) * 4f).Should().BeEquivalentTo(new Vertex3D(8f, 12f, 16f));
+ (4f * new Vertex3D(2f, 3f, 4f)).Should().BeEquivalentTo(new Vertex3D(8f, 12f, 16f));
+ (new Vertex3D(2f, 3f, 4f) / 2f).Should().BeEquivalentTo(new Vertex3D(1f, 1.5f, 2f));
+ }
+
+ [Test]
+ public void ShouldCorrectlySetVectors()
+ {
+ new Vertex3D(2f, 3f, 4f)
+ .Set(1f, 2f, 3f)
+ .Should().BeEquivalentTo(new Vertex3D(1f, 2f, 3f));
+
+ new Vertex3D(2f, 3f, 4f)
+ .Set(new Vertex3D(1f, 2f, 3f))
+ .Should().BeEquivalentTo(new Vertex3D(1f, 2f, 3f));
+ }
+
+ [Test]
+ public void ShouldCorrectlyCrossVectors()
+ {
+ Vertex3D.CrossVectors(new Vertex3D(1.5f, 2.5f, 4f), new Vertex3D(3.5f, 100f, 95f))
+ .Should().BeEquivalentTo(new Vertex3D(-162.5f, -128.5f, 141.25f));
+ }
+
+ }
+}
diff --git a/VisualPinball.Engine.Test/Test/Fixtures.cs b/VisualPinball.Engine.Test/Test/Fixtures.cs
index e25879754..c8d84c947 100644
--- a/VisualPinball.Engine.Test/Test/Fixtures.cs
+++ b/VisualPinball.Engine.Test/Test/Fixtures.cs
@@ -22,6 +22,7 @@ namespace VisualPinball.Engine.Test.Test
public static class VpxPath
{
public static readonly string Bumper = PathHelper.GetFixturePath("BumperTest.vpx");
+
public static readonly string BumperVPX1070 = PathHelper.GetFixturePath("BumperTestVPX1070.vpx");
public static readonly string Collection = PathHelper.GetFixturePath("CollectionTest.vpx");
public static readonly string Mappings = PathHelper.GetFixturePath("MappingsTest.vpx");
@@ -88,6 +89,7 @@ public static class TexturePath
public static readonly string BmpXrgb = PathHelper.GetFixturePath("test_pattern_xrgb.bmp");
public static readonly string Jpg = PathHelper.GetFixturePath("test_pattern.jpg");
public static readonly string Png = PathHelper.GetFixturePath("test_pattern.png");
+ public static readonly string Webp = PathHelper.GetFixturePath("test_pattern.webp");
public static readonly string PngTransparent = PathHelper.GetFixturePath("test_pattern_transparent.png");
public static readonly string Hdr = PathHelper.GetFixturePath("test_pattern_hdr.hdr");
}
@@ -101,22 +103,18 @@ public static class PathHelper
{
public static string GetFixturePath(string filename)
{
- return Path.GetFullPath(Path.Combine(GetTestPath(),
- "Fixtures~" + Path.DirectorySeparatorChar,
- filename));
+ return Path.GetFullPath(Path.Combine(GetTestPath(), "Fixtures~", filename));
}
private static string GetTestPath()
{
- var codeBase = new System.Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath;
+ var codeBase = new System.Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath.Replace('\\', '/');
- if (codeBase.Contains("/Library/ScriptAssemblies/"))
- {
- return Path.GetFullPath(
- "Packages/org.visualpinball.engine.unity/VisualPinball.Engine.Test");
+ if (codeBase.Contains("/Library/ScriptAssemblies/")) {
+ return Path.GetFullPath("Packages/org.visualpinball.engine.unity/VisualPinball.Engine.Test");
}
- else if (codeBase.Contains("VisualPinball.Unity.Test"))
- {
+
+ if (codeBase.Contains("VisualPinball.Unity.Test")) {
return Path.GetFullPath(
Path.Combine(
Path.GetDirectoryName(codeBase),
diff --git a/VisualPinball.Engine.Test/VPT/Bumper/BumperDataTests.cs b/VisualPinball.Engine.Test/VPT/Bumper/BumperDataTests.cs
index a6a6b5aaa..08d03fabc 100644
--- a/VisualPinball.Engine.Test/VPT/Bumper/BumperDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Bumper/BumperDataTests.cs
@@ -14,10 +14,12 @@
// 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.Test.Test;
using VisualPinball.Engine.VPT.Bumper;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Bumper
{
@@ -26,8 +28,8 @@ public class BumperDataTests
[Test]
public void ShouldReadBumperData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Bumper);
- var data = table.Bumper("Bumper1").Data;
+ var th = FileTableContainer.Load(VpxPath.Bumper);
+ var data = th.Bumper("Bumper1").Data;
ValidateTableData(data);
}
@@ -35,13 +37,14 @@ public void ShouldReadBumperData()
public void ShouldWriteBumperData()
{
const string tmpFileName = "ShouldWriteBumperData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Bumper);
+ var table = FileTableContainer.Load(VpxPath.Bumper);
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidateTableData(writtenTable.Bumper("Bumper1").Data);
+ File.Delete(tmpFileName);
}
- private static void ValidateTableData(BumperData data)
+ public static void ValidateTableData(BumperData data)
{
data.BaseMaterial.Should().Be("Material2");
data.CapMaterial.Should().Be("Material1");
diff --git a/VisualPinball.Engine.Test/VPT/Bumper/BumperMeshTests.cs b/VisualPinball.Engine.Test/VPT/Bumper/BumperMeshTests.cs
index 2ce274aeb..ef4289006 100644
--- a/VisualPinball.Engine.Test/VPT/Bumper/BumperMeshTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Bumper/BumperMeshTests.cs
@@ -17,24 +17,25 @@
using JeremyAnsel.Media.WavefrontObj;
using NUnit.Framework;
using VisualPinball.Engine.Test.Test;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Bumper
{
public class BumperMeshTests : MeshTests
{
- private readonly Engine.VPT.Table.Table _table;
+ private readonly FileTableContainer _table;
private readonly ObjFile _obj;
public BumperMeshTests()
{
- _table = Engine.VPT.Table.Table.Load(VpxPath.Bumper);
+ _table = FileTableContainer.Load(VpxPath.Bumper);
_obj = LoadObjFixture(ObjPath.Bumper);
}
[Test]
public void ShouldGenerateMesh()
{
- AssertObjMesh(_table, _obj, _table.Bumper("Bumper2"), (item, mesh) => $"{item.Name}{mesh.Name}");
+ AssertObjMesh(_table.Table, _obj, _table.Bumper("Bumper2"), (item, mesh) => $"{item.Name}{mesh.Name}");
}
}
}
diff --git a/VisualPinball.Engine.Test/VPT/Collection/CollectionDataTests.cs b/VisualPinball.Engine.Test/VPT/Collection/CollectionDataTests.cs
index 89effa9d0..06dc920fb 100644
--- a/VisualPinball.Engine.Test/VPT/Collection/CollectionDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Collection/CollectionDataTests.cs
@@ -14,10 +14,13 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
+using System.IO;
+using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using VisualPinball.Engine.Test.Test;
using VisualPinball.Engine.VPT.Collection;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Collection
{
@@ -26,8 +29,8 @@ public class CollectionDataTests
[Test]
public void ShouldReadCollectionData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Collection);
- var data = table.Collections["flippers"].Data;
+ var tableContainer = FileTableContainer.Load(VpxPath.Collection);
+ var data = tableContainer.Collections.First(c => c.Name == "Flippers");
ValidateTableData(data);
}
@@ -35,13 +38,14 @@ public void ShouldReadCollectionData()
public void ShouldWriteCollectionData()
{
const string tmpFileName = "ShouldWriteCollectionData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Collection);
- table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
- ValidateTableData(writtenTable.Collections["flippers"].Data);
+ var th = FileTableContainer.Load(VpxPath.Collection);
+ th.Save(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
+ ValidateTableData(writtenTable.Collections.First(c => c.Name == "Flippers"));
+ File.Delete(tmpFileName);
}
- private static void ValidateTableData(CollectionData data)
+ public static void ValidateTableData(CollectionData data)
{
data.Name.Should().Be("Flippers");
data.FireEvents.Should().Be(false);
diff --git a/VisualPinball.Engine.Test/VPT/Decal/DecalDataTest.cs b/VisualPinball.Engine.Test/VPT/Decal/DecalDataTests.cs
similarity index 83%
rename from VisualPinball.Engine.Test/VPT/Decal/DecalDataTest.cs
rename to VisualPinball.Engine.Test/VPT/Decal/DecalDataTests.cs
index a8b4a18ee..c3bb2a51c 100644
--- a/VisualPinball.Engine.Test/VPT/Decal/DecalDataTest.cs
+++ b/VisualPinball.Engine.Test/VPT/Decal/DecalDataTests.cs
@@ -14,36 +14,39 @@
// 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.Test.Test;
using VisualPinball.Engine.VPT;
using VisualPinball.Engine.VPT.Decal;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Decal
{
- public class DecalDataTest : BaseTests
+ public class DecalDataTests : BaseTests
{
[Test]
public void ShouldReadDecalData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Decal);
- ValidateDecal0(table.Decal(0).Data);
- ValidateDecal1(table.Decal(1).Data);
+ var th = FileTableContainer.Load(VpxPath.Decal);
+ ValidateDecal0(th.Decal(0).Data);
+ ValidateDecal1(th.Decal(1).Data);
}
[Test]
public void ShouldWriteDecalData()
{
const string tmpFileName = "ShouldWriteDecalData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Decal);
+ var table = FileTableContainer.Load(VpxPath.Decal);
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidateDecal0(writtenTable.Decal(0).Data);
ValidateDecal1(writtenTable.Decal(1).Data);
+ File.Delete(tmpFileName);
}
- private static void ValidateDecal0(DecalData data)
+ public static void ValidateDecal0(DecalData data)
{
data.Backglass.Should().Be(false);
data.Center.X.Should().Be(205.4f);
@@ -68,7 +71,7 @@ private static void ValidateDecal0(DecalData data)
data.IsLocked.Should().Be(false);
}
- private static void ValidateDecal1(DecalData data)
+ public static void ValidateDecal1(DecalData data)
{
data.Backglass.Should().Be(true);
data.Center.X.Should().Be(509f);
diff --git a/VisualPinball.Engine.Test/VPT/DispReel/DispReelDataTest.cs b/VisualPinball.Engine.Test/VPT/DispReel/DispReelDataTests.cs
similarity index 86%
rename from VisualPinball.Engine.Test/VPT/DispReel/DispReelDataTest.cs
rename to VisualPinball.Engine.Test/VPT/DispReel/DispReelDataTests.cs
index 86de042c8..c12b9c188 100644
--- a/VisualPinball.Engine.Test/VPT/DispReel/DispReelDataTest.cs
+++ b/VisualPinball.Engine.Test/VPT/DispReel/DispReelDataTests.cs
@@ -14,19 +14,21 @@
// 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.Test.Test;
using VisualPinball.Engine.VPT.DispReel;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.DispReel
{
- public class DispReelDataTest : BaseTests
+ public class DispReelDataTests : BaseTests
{
[Test]
public void ShouldReadDispReelData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.DispReel);
+ var table = FileTableContainer.Load(VpxPath.DispReel);
ValidateDispReel1(table.DispReel("Reel1").Data);
ValidateDispReel2(table.DispReel("Reel2").Data);
}
@@ -35,14 +37,15 @@ public void ShouldReadDispReelData()
public void ShouldWriteDispReelData()
{
const string tmpFileName = "ShouldWriteDispReelData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.DispReel);
+ var table = FileTableContainer.Load(VpxPath.DispReel);
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidateDispReel1(writtenTable.DispReel("Reel1").Data);
ValidateDispReel2(writtenTable.DispReel("Reel2").Data);
+ File.Delete(tmpFileName);
}
- private static void ValidateDispReel1(DispReelData data)
+ public static void ValidateDispReel1(DispReelData data)
{
data.BackColor.Red.Should().Be(204);
data.BackColor.Green.Should().Be(149);
@@ -73,7 +76,7 @@ private static void ValidateDispReel1(DispReelData data)
data.IsTimerEnabled.Should().Be(true);
}
- private static void ValidateDispReel2(DispReelData data)
+ public static void ValidateDispReel2(DispReelData data)
{
data.BackColor.Red.Should().Be(0);
data.BackColor.Green.Should().Be(0);
diff --git a/VisualPinball.Engine.Test/VPT/Flasher/FlasherDataTests.cs b/VisualPinball.Engine.Test/VPT/Flasher/FlasherDataTests.cs
index f5ba43f6e..bff1969eb 100644
--- a/VisualPinball.Engine.Test/VPT/Flasher/FlasherDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Flasher/FlasherDataTests.cs
@@ -14,11 +14,13 @@
// 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.Test.Test;
using VisualPinball.Engine.VPT;
using VisualPinball.Engine.VPT.Flasher;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Flasher
{
@@ -27,7 +29,7 @@ public class FlasherDataTests
[Test]
public void ShouldReadFlasherData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Flasher);
+ var table = FileTableContainer.Load(VpxPath.Flasher);
ValidateFlasher(table.Flasher("Data").Data);
}
@@ -35,13 +37,14 @@ public void ShouldReadFlasherData()
public void ShouldWriteFlasherData()
{
const string tmpFileName = "ShouldWriteFlasherData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Flasher);
+ var table = FileTableContainer.Load(VpxPath.Flasher);
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidateFlasher(writtenTable.Flasher("Data").Data);
+ File.Delete(tmpFileName);
}
- private static void ValidateFlasher(FlasherData data)
+ public static void ValidateFlasher(FlasherData data)
{
data.AddBlend.Should().Be(false);
data.Alpha.Should().Be(69);
diff --git a/VisualPinball.Engine.Test/VPT/Flipper/FlipperDataTests.cs b/VisualPinball.Engine.Test/VPT/Flipper/FlipperDataTests.cs
index f425c9798..640dd607e 100644
--- a/VisualPinball.Engine.Test/VPT/Flipper/FlipperDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Flipper/FlipperDataTests.cs
@@ -14,10 +14,12 @@
// 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.Test.Test;
using VisualPinball.Engine.VPT.Flipper;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Flipper
{
@@ -26,7 +28,7 @@ public class FlipperDataTests : BaseTests
[Test]
public void ShouldReadFlipperData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Flipper);
+ var table = FileTableContainer.Load(VpxPath.Flipper);
ValidateFlipper(table.Flipper("FatFlipper").Data);
}
@@ -34,13 +36,14 @@ public void ShouldReadFlipperData()
public void ShouldWriteFlipperData()
{
const string tmpFileName = "ShouldWriteFlipperData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Flipper);
+ var table = FileTableContainer.Load(VpxPath.Flipper);
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidateFlipper(writtenTable.Flipper("FatFlipper").Data);
+ File.Delete(tmpFileName);
}
- private static void ValidateFlipper(FlipperData data)
+ public static void ValidateFlipper(FlipperData data)
{
data.BaseRadius.Should().Be(30.0303f);
data.Center.X.Should().Be(269.287f);
diff --git a/VisualPinball.Engine.Test/VPT/Flipper/FlipperMeshTests.cs b/VisualPinball.Engine.Test/VPT/Flipper/FlipperMeshTests.cs
index b083299ff..e4d31680e 100644
--- a/VisualPinball.Engine.Test/VPT/Flipper/FlipperMeshTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Flipper/FlipperMeshTests.cs
@@ -18,25 +18,26 @@
using JeremyAnsel.Media.WavefrontObj;
using NUnit.Framework;
using VisualPinball.Engine.Test.Test;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Flipper
{
public class FlipperMeshTests : MeshTests
{
- private readonly Engine.VPT.Table.Table _table;
+ private readonly FileTableContainer _tc;
private readonly ObjFile _obj;
public FlipperMeshTests()
{
- _table = Engine.VPT.Table.Table.Load(VpxPath.Flipper);
+ _tc = FileTableContainer.Load(VpxPath.Flipper);
_obj = LoadObjFixture(ObjPath.Flipper);
}
[Test]
public void ShouldGenerateFatMesh()
{
- var flipper = _table.Flipper("FatFlipper");
- var flipperMeshes = flipper.GetRenderObjects(_table).RenderObjects.Select(ro => ro.Mesh);
+ var flipper = _tc.Flipper("FatFlipper");
+ var flipperMeshes = flipper.GetRenderObjects(_tc.Table).RenderObjects.Select(ro => ro.Mesh);
foreach (var flipperMesh in flipperMeshes) {
AssertObjMesh(_obj, flipperMesh, $"{flipper.Name}{flipperMesh.Name}", 0.00013f);
}
@@ -45,8 +46,8 @@ public void ShouldGenerateFatMesh()
[Test]
public void ShouldGenerateFatRubberMesh()
{
- var flipper = _table.Flipper("FatRubberFlipper");
- var flipperMeshes = flipper.GetRenderObjects(_table).RenderObjects.Select(ro => ro.Mesh);
+ var flipper = _tc.Flipper("FatRubberFlipper");
+ var flipperMeshes = flipper.GetRenderObjects(_tc.Table).RenderObjects.Select(ro => ro.Mesh);
foreach (var flipperMesh in flipperMeshes) {
AssertObjMesh(_obj, flipperMesh, $"{flipper.Name}{flipperMesh.Name}", threshold: 0.00015f);
}
@@ -55,8 +56,8 @@ public void ShouldGenerateFatRubberMesh()
[Test]
public void ShouldGenerateFlipperOnSurfaceMesh()
{
- var flipper = _table.Flipper("SurfaceFlipper");
- var flipperMeshes = flipper.GetRenderObjects(_table).RenderObjects.Select(ro => ro.Mesh);
+ var flipper = _tc.Flipper("SurfaceFlipper");
+ var flipperMeshes = flipper.GetRenderObjects(_tc.Table).RenderObjects.Select(ro => ro.Mesh);
foreach (var flipperMesh in flipperMeshes) {
AssertObjMesh(_obj, flipperMesh, $"{flipper.Name}{flipperMesh.Name}");
}
diff --git a/VisualPinball.Engine.Test/VPT/Gate/GateDataTests.cs b/VisualPinball.Engine.Test/VPT/Gate/GateDataTests.cs
index 12a1c797a..1de12efaa 100644
--- a/VisualPinball.Engine.Test/VPT/Gate/GateDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Gate/GateDataTests.cs
@@ -14,12 +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;
using VisualPinball.Engine.Test.Test;
using VisualPinball.Engine.VPT;
using VisualPinball.Engine.VPT.Gate;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Gate
{
@@ -28,7 +30,7 @@ public class GateDataTests
[Test]
public void ShouldReadGateData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Gate);
+ var table = FileTableContainer.Load(VpxPath.Gate);
ValidateGateData(table.Gate("Data").Data);
}
@@ -36,13 +38,14 @@ public void ShouldReadGateData()
public void ShouldWriteGateData()
{
const string tmpFileName = "ShouldWriteGateData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Gate);
+ var table = FileTableContainer.Load(VpxPath.Gate);
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidateGateData(writtenTable.Gate("Data").Data);
+ File.Delete(tmpFileName);
}
- private static void ValidateGateData(GateData data)
+ public static void ValidateGateData(GateData data)
{
MathF.RadToDeg(data.AngleMax).Should().Be(90f);
MathF.RadToDeg(data.AngleMin).Should().Be(0f);
diff --git a/VisualPinball.Engine.Test/VPT/Gate/GateMeshTests.cs b/VisualPinball.Engine.Test/VPT/Gate/GateMeshTests.cs
index 7d12652cd..a52b84693 100644
--- a/VisualPinball.Engine.Test/VPT/Gate/GateMeshTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Gate/GateMeshTests.cs
@@ -19,17 +19,18 @@
using VisualPinball.Engine.Game;
using VisualPinball.Engine.Test.Test;
using VisualPinball.Engine.VPT;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Gate
{
public class GateMeshTests : MeshTests
{
- private readonly Engine.VPT.Table.Table _table;
+ private readonly FileTableContainer _tc;
private readonly ObjFile _obj;
public GateMeshTests()
{
- _table = Engine.VPT.Table.Table.Load(VpxPath.Gate);
+ _tc = FileTableContainer.Load(VpxPath.Gate);
_obj = LoadObjFixture(ObjPath.Gate);
}
@@ -37,20 +38,19 @@ public GateMeshTests()
public void ShouldGenerateBracketMeshes()
{
string GetName(IRenderable item, Mesh mesh) => $"{item.Name}{mesh.Name}";
- AssertObjMesh(_table, _obj, _table.Gate("LongPlate"), GetName, 0.00015f);
- AssertObjMesh(_table, _obj, _table.Gate("Plate"), GetName);
- AssertObjMesh(_table, _obj, _table.Gate("WireRectangle"), GetName);
- AssertObjMesh(_table, _obj, _table.Gate("WireW"), GetName, 0.00015f);
- AssertObjMesh(_table, _obj, _table.Gate("TransformedGate"), GetName);
- AssertObjMesh(_table, _obj, _table.Gate("SurfaceGate"), GetName);
+ AssertObjMesh(_tc.Table, _obj, _tc.Gate("LongPlate"), GetName, 0.00015f);
+ AssertObjMesh(_tc.Table, _obj, _tc.Gate("Plate"), GetName);
+ AssertObjMesh(_tc.Table, _obj, _tc.Gate("WireRectangle"), GetName);
+ AssertObjMesh(_tc.Table, _obj, _tc.Gate("WireW"), GetName, 0.00015f);
+ AssertObjMesh(_tc.Table, _obj, _tc.Gate("TransformedGate"), GetName);
+ AssertObjMesh(_tc.Table, _obj, _tc.Gate("SurfaceGate"), GetName);
}
[Test]
public void ShouldGenerateMeshWithoutBracket()
{
- AssertObjMesh(_obj, _table.Gate("NoBracketGate").GetRenderObjects(_table).RenderObjects[0].Mesh, "NoBracketGateWire");
+ AssertObjMesh(_obj, _tc.Gate("NoBracketGate").GetRenderObjects(_tc.Table).RenderObjects[0].Mesh, "NoBracketGateWire");
AssertNoObjMesh(_obj, "NoBracketGateBracket");
}
-
}
}
diff --git a/VisualPinball.Engine.Test/VPT/HitTarget/HitTargetDataTests.cs b/VisualPinball.Engine.Test/VPT/HitTarget/HitTargetDataTests.cs
index adda45a0c..4a0974dbe 100644
--- a/VisualPinball.Engine.Test/VPT/HitTarget/HitTargetDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/HitTarget/HitTargetDataTests.cs
@@ -14,11 +14,13 @@
// 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.Test.Test;
using VisualPinball.Engine.VPT;
using VisualPinball.Engine.VPT.HitTarget;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.HitTarget
{
@@ -27,7 +29,7 @@ public class HitTargetDataTests
[Test]
public void ShouldReadHitTargetData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.HitTarget);
+ var table = FileTableContainer.Load(VpxPath.HitTarget);
ValidateHitTargetData(table.HitTarget("Data").Data);
}
@@ -35,13 +37,14 @@ public void ShouldReadHitTargetData()
public void ShouldWriteHitTargetData()
{
const string tmpFileName = "ShouldWriteHitTargetData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.HitTarget);
+ var table = FileTableContainer.Load(VpxPath.HitTarget);
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidateHitTargetData(writtenTable.HitTarget("Data").Data);
+ File.Delete(tmpFileName);
}
- private static void ValidateHitTargetData(HitTargetData data)
+ public static void ValidateHitTargetData(HitTargetData data)
{
data.DepthBias.Should().Be(0.651f);
data.DisableLightingBelow.Should().Be(0.1932f);
diff --git a/VisualPinball.Engine.Test/VPT/HitTarget/HitTargetMeshTests.cs b/VisualPinball.Engine.Test/VPT/HitTarget/HitTargetMeshTests.cs
index 8349b7a6d..f5851a189 100644
--- a/VisualPinball.Engine.Test/VPT/HitTarget/HitTargetMeshTests.cs
+++ b/VisualPinball.Engine.Test/VPT/HitTarget/HitTargetMeshTests.cs
@@ -17,35 +17,36 @@
using JeremyAnsel.Media.WavefrontObj;
using NUnit.Framework;
using VisualPinball.Engine.Test.Test;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.HitTarget
{
public class HitTargetMeshTests : MeshTests
{
- private readonly Engine.VPT.Table.Table _table;
+ private readonly FileTableContainer _tc;
private readonly ObjFile _obj;
public HitTargetMeshTests()
{
- _table = Engine.VPT.Table.Table.Load(VpxPath.HitTarget);
+ _tc = FileTableContainer.Load(VpxPath.HitTarget);
_obj = LoadObjFixture(ObjPath.HitTarget);
}
[Test]
public void ShouldGenerateMesh()
{
- AssertObjMesh(_table, _obj, _table.HitTarget("DropTargetBeveled"));
- AssertObjMesh(_table, _obj, _table.HitTarget("DropTargetFlatSimple"));
- AssertObjMesh(_table, _obj, _table.HitTarget("DropTargetSimple"));
- AssertObjMesh(_table, _obj, _table.HitTarget("Data"));
- AssertObjMesh(_table, _obj, _table.HitTarget("HitFatTargetSlim"));
- AssertObjMesh(_table, _obj, _table.HitTarget("HitFatTargetSquare"));
- AssertObjMesh(_table, _obj, _table.HitTarget("HitTargetRect"));
- AssertObjMesh(_table, _obj, _table.HitTarget("HitTargetRound"));
- AssertObjMesh(_table, _obj, _table.HitTarget("HitTargetSlim"));
- AssertObjMesh(_table, _obj, _table.HitTarget("ScaledTarget"));
- AssertObjMesh(_table, _obj, _table.HitTarget("RotatedTarget"));
- AssertObjMesh(_table, _obj, _table.HitTarget("DroppedTarget"));
+ AssertObjMesh(_tc.Table, _obj, _tc.HitTarget("DropTargetBeveled"));
+ AssertObjMesh(_tc.Table, _obj, _tc.HitTarget("DropTargetFlatSimple"));
+ AssertObjMesh(_tc.Table, _obj, _tc.HitTarget("DropTargetSimple"));
+ AssertObjMesh(_tc.Table, _obj, _tc.HitTarget("Data"));
+ AssertObjMesh(_tc.Table, _obj, _tc.HitTarget("HitFatTargetSlim"));
+ AssertObjMesh(_tc.Table, _obj, _tc.HitTarget("HitFatTargetSquare"));
+ AssertObjMesh(_tc.Table, _obj, _tc.HitTarget("HitTargetRect"));
+ AssertObjMesh(_tc.Table, _obj, _tc.HitTarget("HitTargetRound"));
+ AssertObjMesh(_tc.Table, _obj, _tc.HitTarget("HitTargetSlim"));
+ AssertObjMesh(_tc.Table, _obj, _tc.HitTarget("ScaledTarget"));
+ AssertObjMesh(_tc.Table, _obj, _tc.HitTarget("RotatedTarget"));
+ AssertObjMesh(_tc.Table, _obj, _tc.HitTarget("DroppedTarget"));
}
}
}
diff --git a/VisualPinball.Engine.Test/VPT/Kicker/KickerDataTests.cs b/VisualPinball.Engine.Test/VPT/Kicker/KickerDataTests.cs
index 367da6c75..ac999b7ac 100644
--- a/VisualPinball.Engine.Test/VPT/Kicker/KickerDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Kicker/KickerDataTests.cs
@@ -14,11 +14,13 @@
// 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.Test.Test;
using VisualPinball.Engine.VPT;
using VisualPinball.Engine.VPT.Kicker;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Kicker
{
@@ -27,7 +29,7 @@ public class KickerDataTests
[Test]
public void ShouldReadKickerData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Kicker);
+ var table = FileTableContainer.Load(VpxPath.Kicker);
ValidateKickerData(table.Kicker("Data").Data);
}
@@ -35,13 +37,14 @@ public void ShouldReadKickerData()
public void ShouldWriteKickerData()
{
const string tmpFileName = "ShouldWriteKickerData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Kicker);
+ var table = FileTableContainer.Load(VpxPath.Kicker);
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidateKickerData(writtenTable.Kicker("Data").Data);
+ File.Delete(tmpFileName);
}
- private static void ValidateKickerData(KickerData data)
+ public static void ValidateKickerData(KickerData data)
{
data.Center.X.Should().Be(781.6662f);
data.Center.Y.Should().Be(1585f);
@@ -57,8 +60,10 @@ private static void ValidateKickerData(KickerData data)
data.Scatter.Should().Be(4.98f);
data.Surface.Should().Be("");
+ #if !WRITE_VP106 && !WRITE_VP107
data.Angle.Should().Be(65.5f);
data.Speed.Should().Be(5.8f);
+ #endif
}
}
}
diff --git a/VisualPinball.Engine.Test/VPT/Kicker/KickerMeshTests.cs b/VisualPinball.Engine.Test/VPT/Kicker/KickerMeshTests.cs
index 22868ea0c..1217c927b 100644
--- a/VisualPinball.Engine.Test/VPT/Kicker/KickerMeshTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Kicker/KickerMeshTests.cs
@@ -17,33 +17,34 @@
using JeremyAnsel.Media.WavefrontObj;
using NUnit.Framework;
using VisualPinball.Engine.Test.Test;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Kicker
{
public class KickerMeshTests : MeshTests
{
- private readonly Engine.VPT.Table.Table _table;
+ private readonly FileTableContainer _tc;
private readonly ObjFile _obj;
public KickerMeshTests()
{
- _table = Engine.VPT.Table.Table.Load(VpxPath.Kicker);
+ _tc = FileTableContainer.Load(VpxPath.Kicker);
_obj = LoadObjFixture(ObjPath.Kicker);
}
[Test]
public void ShouldGenerateMeshesCorrectly()
{
- AssertObjMesh(_table, _obj, _table.Kicker("Cup"));
- AssertObjMesh(_table, _obj, _table.Kicker("Cup2"));
- AssertObjMesh(_table, _obj, _table.Kicker("Gottlieb"), threshold: 0.00015f);
- AssertObjMesh(_table, _obj, _table.Kicker("Hole"));
- AssertObjMesh(_table, _obj, _table.Kicker("HoleSimple"));
- AssertObjMesh(_table, _obj, _table.Kicker("Williams"), threshold: 0.001f);
- AssertObjMesh(_table, _obj, _table.Kicker("Scaled"));
- AssertObjMesh(_table, _obj, _table.Kicker("Rotated"), threshold: 0.00015f);
- AssertObjMesh(_table, _obj, _table.Kicker("Surface"));
- AssertObjMesh(_table, _obj, _table.Kicker("Data"), threshold: 0.00015f);
+ AssertObjMesh(_tc.Table, _obj, _tc.Kicker("Cup"));
+ AssertObjMesh(_tc.Table, _obj, _tc.Kicker("Cup2"));
+ AssertObjMesh(_tc.Table, _obj, _tc.Kicker("Gottlieb"), threshold: 0.00015f);
+ AssertObjMesh(_tc.Table, _obj, _tc.Kicker("Hole"));
+ AssertObjMesh(_tc.Table, _obj, _tc.Kicker("HoleSimple"));
+ AssertObjMesh(_tc.Table, _obj, _tc.Kicker("Williams"), threshold: 0.001f);
+ AssertObjMesh(_tc.Table, _obj, _tc.Kicker("Scaled"));
+ AssertObjMesh(_tc.Table, _obj, _tc.Kicker("Rotated"), threshold: 0.00015f);
+ AssertObjMesh(_tc.Table, _obj, _tc.Kicker("Surface"));
+ AssertObjMesh(_tc.Table, _obj, _tc.Kicker("Data"), threshold: 0.00015f);
}
}
}
diff --git a/VisualPinball.Engine.Test/VPT/Layers/LayerDataTests.cs b/VisualPinball.Engine.Test/VPT/Layers/LayerDataTests.cs
index be95c7e27..090a9966f 100644
--- a/VisualPinball.Engine.Test/VPT/Layers/LayerDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Layers/LayerDataTests.cs
@@ -14,10 +14,12 @@
// 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.Test.Test;
using VisualPinball.Engine.VPT.Bumper;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Layers
{
@@ -26,7 +28,7 @@ public class LayersDataTests
[Test]
public void ShouldReadLayerDataVPX1060()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Bumper);
+ var table = FileTableContainer.Load(VpxPath.Bumper);
var data = table.Bumper("Bumper1").Data;
ValidateTableDataVPX1060(data);
}
@@ -34,7 +36,7 @@ public void ShouldReadLayerDataVPX1060()
[Test]
public void ShouldReadLayerDataVPX1070()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.BumperVPX1070);
+ var table = FileTableContainer.Load(VpxPath.BumperVPX1070);
var data = table.Bumper("Bumper1").Data;
ValidateTableDataVPX1070(data);
}
@@ -43,12 +45,13 @@ public void ShouldReadLayerDataVPX1070()
public void ShouldWriteLayerData()
{
const string tmpFileName = "ShouldWriteBumperData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Bumper);
+ var table = FileTableContainer.Load(VpxPath.Bumper);
var data = table.Bumper("Bumper1").Data;
data.EditorLayerName = "Layer_1";
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidateTableDataVPX1070(writtenTable.Bumper("Bumper1").Data);
+ File.Delete(tmpFileName);
}
private static void ValidateTableDataVPX1060(BumperData data)
diff --git a/VisualPinball.Engine.Test/VPT/Light/LightDataTests.cs b/VisualPinball.Engine.Test/VPT/Light/LightDataTests.cs
index 85d5a2ed1..fd1113885 100644
--- a/VisualPinball.Engine.Test/VPT/Light/LightDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Light/LightDataTests.cs
@@ -14,11 +14,13 @@
// 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.Test.Test;
using VisualPinball.Engine.VPT;
using VisualPinball.Engine.VPT.Light;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Light
{
@@ -27,7 +29,7 @@ public class LightDataTests
[Test]
public void ShouldReadLightData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Light);
+ var table = FileTableContainer.Load(VpxPath.Light);
ValidateLightData(table.Light("Light1").Data);
}
@@ -35,13 +37,14 @@ public void ShouldReadLightData()
public void ShouldWriteLightData()
{
const string tmpFileName = "ShouldWriteLightData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Light);
+ var table = FileTableContainer.Load(VpxPath.Light);
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidateLightData(writtenTable.Light("Light1").Data);
+ File.Delete(tmpFileName);
}
- private static void ValidateLightData(LightData data)
+ public static void ValidateLightData(LightData data)
{
data.BlinkInterval.Should().Be(126);
data.BlinkPattern.Should().Be("10011");
@@ -77,7 +80,7 @@ private static void ValidateLightData(LightData data)
[Test]
public void ShouldLoadCorrectDragPointData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Light);
+ var table = FileTableContainer.Load(VpxPath.Light);
var dragPoints = table.Light("PlayfieldLight").Data.DragPoints;
dragPoints[0].IsSmooth.Should().Be(false);
diff --git a/VisualPinball.Engine.Test/VPT/LightSeq/LightSeqDataTests.cs b/VisualPinball.Engine.Test/VPT/LightSeq/LightSeqDataTests.cs
index 23601eef1..33a1daff6 100644
--- a/VisualPinball.Engine.Test/VPT/LightSeq/LightSeqDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/LightSeq/LightSeqDataTests.cs
@@ -14,10 +14,12 @@
// 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.Test.Test;
using VisualPinball.Engine.VPT.LightSeq;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.LightSeq
{
@@ -26,7 +28,7 @@ public class LightSeqDataTests : BaseTests
[Test]
public void ShouldReadLightSeqData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.LightSeq);
+ var table = FileTableContainer.Load(VpxPath.LightSeq);
ValidateLightSeqData(table.LightSeq("LightSeq001").Data);
}
@@ -34,13 +36,14 @@ public void ShouldReadLightSeqData()
public void ShouldWriteLightSeqData()
{
const string tmpFileName = "ShouldWriteLightSeqData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.LightSeq);
+ var table = FileTableContainer.Load(VpxPath.LightSeq);
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidateLightSeqData(writtenTable.LightSeq("LightSeq001").Data);
+ File.Delete(tmpFileName);
}
- private static void ValidateLightSeqData(LightSeqData data)
+ public static void ValidateLightSeqData(LightSeqData data)
{
data.Backglass.Should().Be(false);
data.Center.X.Should().Be(21.23f);
diff --git a/VisualPinball.Engine.Test/VPT/Mappings/MappingsDataTests.cs b/VisualPinball.Engine.Test/VPT/Mappings/MappingsDataTests.cs
index 2afe02600..395c311ef 100644
--- a/VisualPinball.Engine.Test/VPT/Mappings/MappingsDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Mappings/MappingsDataTests.cs
@@ -14,6 +14,7 @@
// 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.Test.Test;
@@ -23,12 +24,14 @@
namespace VisualPinball.Engine.Test.VPT.Mappings
{
+ #if !WRITE_VP106 && !WRITE_VP107
+
public class MappingsDataTests
{
[Test]
public void ShouldReadMappingsData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Mappings);
+ var table = FileTableContainer.Load(VpxPath.Mappings);
var data = table.Mappings.Data;
ValidateTableData(data);
}
@@ -37,10 +40,11 @@ public void ShouldReadMappingsData()
public void ShouldWriteMappingsData()
{
const string tmpFileName = "ShouldWriteMappingsData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Mappings);
+ var table = FileTableContainer.Load(VpxPath.Mappings);
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidateTableData(writtenTable.Mappings.Data);
+ File.Delete(tmpFileName);
}
[Test]
@@ -145,4 +149,5 @@ private static void ValidateTableData(MappingsData data)
data.Wires[1].PulseDelay.Should().Be(200);
}
}
+ #endif
}
diff --git a/VisualPinball.Engine.Test/VPT/MaterialDataTests.cs b/VisualPinball.Engine.Test/VPT/MaterialDataTests.cs
index 39ef03b3a..c02fca5df 100644
--- a/VisualPinball.Engine.Test/VPT/MaterialDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/MaterialDataTests.cs
@@ -14,6 +14,7 @@
// 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;
@@ -28,7 +29,7 @@ public class MaterialDataTests
[Test]
public void ShouldReadMaterialData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Material);
+ var table = FileTableContainer.Load(VpxPath.Material);
ValidateMaterial1(table.GetMaterial("Material1"));
}
@@ -36,10 +37,11 @@ public void ShouldReadMaterialData()
public void ShouldWriteMaterialData()
{
const string tmpFileName = "ShouldWriteMaterialData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Material);
+ var table = FileTableContainer.Load(VpxPath.Material);
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidateMaterial1(writtenTable.GetMaterial("Material1"));
+ File.Delete(tmpFileName);
}
[Test]
@@ -56,18 +58,20 @@ public void ShouldCreateMaterialFromScratch()
const string tmpFileName = "ShouldCreateMaterialData.vpx";
new TableWriter(tb.Build()).WriteTable(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
writtenTable.GetMaterial("test_mat").BaseColor.Red.Should().Be(255);
writtenTable.GetMaterial("test_mat").BaseColor.Green.Should().Be(0);
writtenTable.GetMaterial("test_mat").BaseColor.Blue.Should().Be(0);
writtenTable.GetMaterial("test_mat").Elasticity.Should().Be(0.666f);
+
+ File.Delete(tmpFileName);
}
[Test]
public void ShouldWriteUpdatedMaterialData()
{
const string tmpFileName = "ShouldWriteUpdatedMaterialData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Material);
+ var table = FileTableContainer.Load(VpxPath.Material);
var mat = table.GetMaterial("Material1");
mat.Name = "MaterialUpdated";
@@ -87,7 +91,7 @@ public void ShouldWriteUpdatedMaterialData()
mat.WrapLighting = 0.68f;
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
var material = writtenTable.GetMaterial("MaterialUpdated");
material.Name.Should().Be("MaterialUpdated");
material.BaseColor.Red.Should().Be(1);
@@ -106,6 +110,7 @@ public void ShouldWriteUpdatedMaterialData()
material.ScatterAngle.Should().Be(12.2f);
material.Thickness.Should().BeApproximately(0.74f, 0.003f);
material.WrapLighting.Should().Be(0.68f);
+ File.Delete(tmpFileName);
}
private void ValidateMaterial1(Material material)
diff --git a/VisualPinball.Engine.Test/VPT/Plunger/PlungerDataTests.cs b/VisualPinball.Engine.Test/VPT/Plunger/PlungerDataTests.cs
index 01926093b..78baaa1df 100644
--- a/VisualPinball.Engine.Test/VPT/Plunger/PlungerDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Plunger/PlungerDataTests.cs
@@ -14,11 +14,13 @@
// 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.Test.Test;
using VisualPinball.Engine.VPT;
using VisualPinball.Engine.VPT.Plunger;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Plunger
{
@@ -27,7 +29,7 @@ public class PlungerDataTests
[Test]
public void ShouldReadPlungerData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Plunger);
+ var table = FileTableContainer.Load(VpxPath.Plunger);
ValidatePlungerData1(table.Plunger("Plunger1").Data);
ValidatePlungerData2(table.Plunger("Plunger2").Data);
}
@@ -36,14 +38,15 @@ public void ShouldReadPlungerData()
public void ShouldWritePlungerData()
{
const string tmpFileName = "ShouldWritePlungerData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Plunger);
+ var table = FileTableContainer.Load(VpxPath.Plunger);
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidatePlungerData1(writtenTable.Plunger("Plunger1").Data);
ValidatePlungerData2(writtenTable.Plunger("Plunger2").Data);
+ File.Delete(tmpFileName);
}
- private static void ValidatePlungerData1(PlungerData data)
+ public static void ValidatePlungerData1(PlungerData data, bool validateTexture = true)
{
data.AnimFrames.Should().Be(7);
data.AnimFrames.Should().Be(7);
@@ -51,7 +54,9 @@ private static void ValidatePlungerData1(PlungerData data)
data.Center.X.Should().Be(477f);
data.Center.Y.Should().Be(983.2f);
data.Height.Should().Be(20f);
- data.Image.Should().Be("alphatest_100_50_0");
+ if (validateTexture) {
+ data.Image.Should().Be("alphatest_100_50_0");
+ }
data.IsLocked.Should().Be(true);
data.IsMechPlunger.Should().Be(true);
data.IsReflectionEnabled.Should().Be(true);
@@ -81,7 +86,7 @@ private static void ValidatePlungerData1(PlungerData data)
data.ZAdjust.Should().Be(1.223f);
}
- private static void ValidatePlungerData2(PlungerData data)
+ public static void ValidatePlungerData2(PlungerData data)
{
data.AnimFrames.Should().Be(1);
data.AutoPlunger.Should().Be(false);
diff --git a/VisualPinball.Engine.Test/VPT/Primitive/PrimitiveDataTests.cs b/VisualPinball.Engine.Test/VPT/Primitive/PrimitiveDataTests.cs
index 6c22bb5e4..1ee05c9c3 100644
--- a/VisualPinball.Engine.Test/VPT/Primitive/PrimitiveDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Primitive/PrimitiveDataTests.cs
@@ -27,7 +27,7 @@ public class PrimitiveDataTests
[Test]
public void ShouldReadPrimitiveData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Primitive);
+ var table = FileTableContainer.Load(VpxPath.Primitive);
ValidatePrimitiveData(table.Primitive("Cube").Data);
}
@@ -35,13 +35,13 @@ public void ShouldReadPrimitiveData()
public void ShouldWritePrimitiveData()
{
const string tmpFileName = "ShouldWritePrimitiveData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Primitive);
+ var table = FileTableContainer.Load(VpxPath.Primitive);
new TableWriter(table).WriteTable(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidatePrimitiveData(writtenTable.Primitive("Cube").Data);
}
- private static void ValidatePrimitiveData(PrimitiveData data)
+ public static void ValidatePrimitiveData(PrimitiveData data)
{
data.BackfacesEnabled.Should().Be(false);
data.CollisionReductionFactor.Should().Be(0.6119f);
diff --git a/VisualPinball.Engine.Test/VPT/Primitive/PrimitiveMeshTests.cs b/VisualPinball.Engine.Test/VPT/Primitive/PrimitiveMeshTests.cs
index 5fe53b727..c3ccee386 100644
--- a/VisualPinball.Engine.Test/VPT/Primitive/PrimitiveMeshTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Primitive/PrimitiveMeshTests.cs
@@ -21,45 +21,46 @@
using VisualPinball.Engine.Game;
using VisualPinball.Engine.Test.Test;
using VisualPinball.Engine.VPT;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Primitive
{
public class PrimitiveMeshTests : MeshTests
{
- private readonly Engine.VPT.Table.Table _table;
+ private readonly FileTableContainer _tc;
private readonly ObjFile _obj;
public PrimitiveMeshTests()
{
- _table = Engine.VPT.Table.Table.Load(VpxPath.Primitive);
+ _tc = FileTableContainer.Load(VpxPath.Primitive);
_obj = LoadObjFixture(ObjPath.Primitive);
}
[Test]
public void ShouldGenerateImportedMesh()
{
- var bookMesh = _table.Primitive("Books").GetRenderObjects(_table).RenderObjects[0].Mesh;
+ var bookMesh = _tc.Primitive("Books").GetRenderObjects(_tc.Table).RenderObjects[0].Mesh;
AssertObjMesh(_obj, bookMesh, threshold: 0.00015f);
}
[Test]
public void ShouldGenerateACube()
{
- var cubeMesh = _table.Primitive("Cube").GetRenderObjects(_table).RenderObjects[0].Mesh;
+ var cubeMesh = _tc.Primitive("Cube").GetRenderObjects(_tc.Table).RenderObjects[0].Mesh;
AssertObjMesh(_obj, cubeMesh);
}
[Test]
public void ShouldGenerateATriangle()
{
- var triangleMesh = _table.Primitive("Triangle").GetRenderObjects(_table).RenderObjects[0].Mesh;
+ var triangleMesh = _tc.Primitive("Triangle").GetRenderObjects(_tc.Table).RenderObjects[0].Mesh;
AssertObjMesh(_obj, triangleMesh);
}
[Test]
public void ShouldProvideCorrectTransformationMatrices()
{
- var rog = _table.Primitive("Primitive1").GetRenderObjects(_table, Origin.Original, false);
+ var rog = _tc.Primitive("Primitive1").GetRenderObjects(_tc.Table, Origin.Original, false);
rog.TransformationMatrix.GetScaling().X.Should().Be(100f);
rog.TransformationMatrix.GetScaling().Y.Should().Be(100f);
@@ -67,22 +68,22 @@ public void ShouldProvideCorrectTransformationMatrices()
rog.TransformationMatrix.GetTranslation().X.Should().Be(505f);
rog.TransformationMatrix.GetTranslation().Y.Should().Be(1305f);
- rog.TransformationMatrix.GetTranslation().Z.Should().Be(_table.TableHeight);
+ rog.TransformationMatrix.GetTranslation().Z.Should().Be(_tc.Table.TableHeight);
}
[Test]
public void ShouldGenerateACompressedMesh()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.PrimitiveCompressed);
+ var th = FileTableContainer.Load(VpxPath.PrimitiveCompressed);
var obj = LoadObjFixture(ObjPath.PrimitiveCompressed);
- var compressedMesh = table.Primitive("compressed").GetRenderObjects(table).RenderObjects[0].Mesh;
+ var compressedMesh = th.Primitive("compressed").GetRenderObjects(th.Table).RenderObjects[0].Mesh;
AssertObjMesh(obj, compressedMesh, threshold: 0.00015f);
}
[Test]
public void ShouldGenerateAnAnimatedMesh() {
- var table = Engine.VPT.Table.Table.Load(VpxPath.PrimitiveAnimated);
+ var table = FileTableContainer.Load(VpxPath.PrimitiveAnimated);
var animatedPrimitive = table.Primitive("AnimatedPrimitive");
var mesh = animatedPrimitive.GetMesh();
diff --git a/VisualPinball.Engine.Test/VPT/Ramp/RampDataTests.cs b/VisualPinball.Engine.Test/VPT/Ramp/RampDataTests.cs
index e1e175189..3dfeed191 100644
--- a/VisualPinball.Engine.Test/VPT/Ramp/RampDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Ramp/RampDataTests.cs
@@ -14,11 +14,13 @@
// 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.Test.Test;
using VisualPinball.Engine.VPT;
using VisualPinball.Engine.VPT.Ramp;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Ramp
{
@@ -27,7 +29,7 @@ public class RampDataTests
[Test]
public void ShouldReadRampData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Ramp);
+ var table = FileTableContainer.Load(VpxPath.Ramp);
ValidateRampData(table.Ramp("FlatL").Data);
}
@@ -35,13 +37,14 @@ public void ShouldReadRampData()
public void ShouldWriteRampData()
{
const string tmpFileName = "ShouldWriteRampData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Ramp);
+ var table = FileTableContainer.Load(VpxPath.Ramp);
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidateRampData(writtenTable.Ramp("FlatL").Data);
+ File.Delete(tmpFileName);
}
- private static void ValidateRampData(RampData data)
+ public static void ValidateRampData(RampData data)
{
data.DepthBias.Should().Be(0.11254f);
data.DragPoints.Length.Should().Be(3);
@@ -73,7 +76,7 @@ private static void ValidateRampData(RampData data)
[Test]
public void ShouldLoadWireData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Ramp);
+ var table = FileTableContainer.Load(VpxPath.Ramp);
var data = table.Ramp("Wire3R").Data;
data.RampType.Should().Be(RampType.RampType3WireRight);
diff --git a/VisualPinball.Engine.Test/VPT/Ramp/RampMeshTests.cs b/VisualPinball.Engine.Test/VPT/Ramp/RampMeshTests.cs
index 80207548a..979e32ce2 100644
--- a/VisualPinball.Engine.Test/VPT/Ramp/RampMeshTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Ramp/RampMeshTests.cs
@@ -18,17 +18,18 @@
using JeremyAnsel.Media.WavefrontObj;
using NUnit.Framework;
using VisualPinball.Engine.Test.Test;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Ramp
{
public class RampMeshTests : MeshTests
{
- private readonly Engine.VPT.Table.Table _table;
+ private readonly FileTableContainer _tc;
private readonly ObjFile _obj;
public RampMeshTests()
{
- _table = Engine.VPT.Table.Table.Load(VpxPath.Ramp);
+ _tc = FileTableContainer.Load(VpxPath.Ramp);
_obj = LoadObjFixture(ObjPath.Ramp);
}
@@ -71,8 +72,8 @@ public void ShouldGenerate4WireRamp()
private void ShouldGenerate(string name)
{
- var ramp = _table.Ramp(name);
- var rampMeshes = ramp.GetRenderObjects(_table).RenderObjects.Select(ro => ro.Mesh).ToArray();
+ var ramp = _tc.Ramp(name);
+ var rampMeshes = ramp.GetRenderObjects(_tc.Table).RenderObjects.Select(ro => ro.Mesh).ToArray();
#if WIN64
const float threshold = 0.0001f;
#else
diff --git a/VisualPinball.Engine.Test/VPT/Rubber/RubberDataTest.cs b/VisualPinball.Engine.Test/VPT/Rubber/RubberDataTests.cs
similarity index 85%
rename from VisualPinball.Engine.Test/VPT/Rubber/RubberDataTest.cs
rename to VisualPinball.Engine.Test/VPT/Rubber/RubberDataTests.cs
index 603a63643..70d9720b1 100644
--- a/VisualPinball.Engine.Test/VPT/Rubber/RubberDataTest.cs
+++ b/VisualPinball.Engine.Test/VPT/Rubber/RubberDataTests.cs
@@ -14,19 +14,21 @@
// 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.Test.Test;
using VisualPinball.Engine.VPT.Rubber;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Rubber
{
- public class RubberDataTest
+ public class RubberDataTests
{
[Test]
public void ShouldReadRubberData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Rubber);
+ var table = FileTableContainer.Load(VpxPath.Rubber);
ValidateRubberData1(table.Rubber("Rubber1").Data);
ValidateRubberData2(table.Rubber("Rubber2").Data);
}
@@ -35,14 +37,15 @@ public void ShouldReadRubberData()
public void ShouldWriteRubberData()
{
const string tmpFileName = "ShouldWriteRubberData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Rubber);
+ var table = FileTableContainer.Load(VpxPath.Rubber);
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidateRubberData1(writtenTable.Rubber("Rubber1").Data);
ValidateRubberData2(writtenTable.Rubber("Rubber2").Data);
+ File.Delete(tmpFileName);
}
- private static void ValidateRubberData1(RubberData data)
+ public static void ValidateRubberData1(RubberData data)
{
data.DragPoints.Length.Should().Be(3);
data.Elasticity.Should().Be(0.832f);
@@ -68,7 +71,7 @@ private static void ValidateRubberData1(RubberData data)
data.Points.Should().Be(true);
}
- private static void ValidateRubberData2(RubberData data)
+ public static void ValidateRubberData2(RubberData data)
{
data.DragPoints.Length.Should().Be(3);
data.Elasticity.Should().Be(0.8f);
diff --git a/VisualPinball.Engine.Test/VPT/Rubber/RubberMeshTest.cs b/VisualPinball.Engine.Test/VPT/Rubber/RubberMeshTest.cs
index 5852d5eea..c6f9024cd 100644
--- a/VisualPinball.Engine.Test/VPT/Rubber/RubberMeshTest.cs
+++ b/VisualPinball.Engine.Test/VPT/Rubber/RubberMeshTest.cs
@@ -17,31 +17,32 @@
using JeremyAnsel.Media.WavefrontObj;
using NUnit.Framework;
using VisualPinball.Engine.Test.Test;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Rubber
{
public class RubberMeshTest : MeshTests
{
- private readonly Engine.VPT.Table.Table _table;
+ private readonly FileTableContainer _tc;
private readonly ObjFile _obj;
public RubberMeshTest()
{
- _table = Engine.VPT.Table.Table.Load(VpxPath.Rubber);
+ _tc = FileTableContainer.Load(VpxPath.Rubber);
_obj = LoadObjFixture(ObjPath.Rubber);
}
[Test]
public void ShouldGenerateMesh()
{
- var rubberMesh = _table.Rubber("Rubber2").GetRenderObjects(_table).RenderObjects[0].Mesh;
+ var rubberMesh = _tc.Rubber("Rubber2").GetRenderObjects(_tc.Table).RenderObjects[0].Mesh;
AssertObjMesh(_obj, rubberMesh, threshold: 0.00015f);
}
[Test]
public void ShouldGenerateThickMesh()
{
- var rubberMesh = _table.Rubber("Rubber1").GetRenderObjects(_table).RenderObjects[0].Mesh;
+ var rubberMesh = _tc.Rubber("Rubber1").GetRenderObjects(_tc.Table).RenderObjects[0].Mesh;
AssertObjMesh(_obj, rubberMesh, threshold: 0.001f);
}
}
diff --git a/VisualPinball.Engine.Test/VPT/Sound/SoundDataTests.cs b/VisualPinball.Engine.Test/VPT/Sound/SoundDataTests.cs
index d5d102026..c28c42cbd 100644
--- a/VisualPinball.Engine.Test/VPT/Sound/SoundDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Sound/SoundDataTests.cs
@@ -14,6 +14,7 @@
// 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.Test.Test;
@@ -28,18 +29,33 @@ public class SoundDataTests
[Test]
public void ShouldReadSoundData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Sound);
- ValidateSoundData(table.Sounds["fx_bumper3"].Data);
+ var tableContainer = FileTableContainer.Load(VpxPath.Sound);
+ ValidateSoundData(tableContainer.GetSound("fx_bumper3").Data);
}
[Test]
public void ShouldWriteSoundData()
{
const string tmpFileName = "ShouldWriteSoundData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Sound);
- new TableWriter(table).WriteTable(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
- ValidateSoundData(writtenTable.Sounds["fx_bumper3"].Data);
+ var tableContainer = FileTableContainer.Load(VpxPath.Sound);
+ new TableWriter(tableContainer).WriteTable(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
+ ValidateSoundData(writtenTable.GetSound("fx_bumper3").Data);
+
+ File.Delete(tmpFileName);
+ }
+
+ [Test]
+ public void ShouldReadMp3Data()
+ {
+ var tableContainer = FileTableContainer.Load(VpxPath.Sound);
+ tableContainer.GetSound("ANMLFarm_Cow moos 5 (ID 2385)_BSB").Data.GetFileData().Should().HaveCountGreaterThan(0);
+ }
+ [Test]
+ public void ShouldReadOggData()
+ {
+ var tableContainer = FileTableContainer.Load(VpxPath.Sound);
+ tableContainer.GetSound("ANMLFarm_Cow moos 3 (ID 2383)_BSB").Data.GetFileData().Should().HaveCountGreaterThan(0);
}
private static void ValidateSoundData(SoundData data)
diff --git a/VisualPinball.Engine.Test/VPT/Spinner/SpinnerDataTests.cs b/VisualPinball.Engine.Test/VPT/Spinner/SpinnerDataTests.cs
index 24c55a158..173a41b0b 100644
--- a/VisualPinball.Engine.Test/VPT/Spinner/SpinnerDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Spinner/SpinnerDataTests.cs
@@ -14,10 +14,12 @@
// 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.Test.Test;
using VisualPinball.Engine.VPT.Spinner;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Spinner
{
@@ -26,7 +28,7 @@ public class SpinnerDataTests
[Test]
public void ShouldReadSpinnerData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Spinner);
+ var table = FileTableContainer.Load(VpxPath.Spinner);
ValidateSpinnerData(table.Spinner("Data").Data);
}
@@ -34,13 +36,14 @@ public void ShouldReadSpinnerData()
public void ShouldWriteSpinnerData()
{
const string tmpFileName = "ShouldWriteSpinnerData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Spinner);
+ var table = FileTableContainer.Load(VpxPath.Spinner);
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidateSpinnerData(writtenTable.Spinner("Data").Data);
+ File.Delete(tmpFileName);
}
- private static void ValidateSpinnerData(SpinnerData data)
+ public static void ValidateSpinnerData(SpinnerData data)
{
data.AngleMax.Should().Be(50.698f);
data.AngleMin.Should().Be(-12.87f);
diff --git a/VisualPinball.Engine.Test/VPT/Spinner/SpinnerMeshTests.cs b/VisualPinball.Engine.Test/VPT/Spinner/SpinnerMeshTests.cs
index 4f70a2a17..d0091b20b 100644
--- a/VisualPinball.Engine.Test/VPT/Spinner/SpinnerMeshTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Spinner/SpinnerMeshTests.cs
@@ -19,17 +19,18 @@
using VisualPinball.Engine.Game;
using VisualPinball.Engine.Test.Test;
using VisualPinball.Engine.VPT;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Spinner
{
public class SpinnerMeshTests : MeshTests
{
- private readonly Engine.VPT.Table.Table _table;
+ private readonly FileTableContainer _tc;
private readonly ObjFile _obj;
public SpinnerMeshTests()
{
- _table = Engine.VPT.Table.Table.Load(VpxPath.Spinner);
+ _tc = FileTableContainer.Load(VpxPath.Spinner);
_obj = LoadObjFixture(ObjPath.Spinner);
}
@@ -37,16 +38,16 @@ public SpinnerMeshTests()
public void ShouldGenerateBracketMeshes()
{
string GetName(IRenderable item, Mesh mesh) => $"{item.Name}{mesh.Name}";
- AssertObjMesh(_table, _obj, _table.Spinner("Spinner"), GetName);
- AssertObjMesh(_table, _obj, _table.Spinner("Transformed"), GetName);
- AssertObjMesh(_table, _obj, _table.Spinner("Surface"), GetName);
- AssertObjMesh(_table, _obj, _table.Spinner("Data"), GetName, 0.001f);
+ AssertObjMesh(_tc.Table, _obj, _tc.Spinner("Spinner"), GetName);
+ AssertObjMesh(_tc.Table, _obj, _tc.Spinner("Transformed"), GetName);
+ AssertObjMesh(_tc.Table, _obj, _tc.Spinner("Surface"), GetName);
+ AssertObjMesh(_tc.Table, _obj, _tc.Spinner("Data"), GetName, 0.001f);
}
[Test]
public void ShouldGenerateMeshWithoutBracket()
{
- AssertObjMesh(_obj, _table.Spinner("WithoutBracket").GetRenderObjects(_table).RenderObjects[0].Mesh, "WithoutBracketPlate");
+ AssertObjMesh(_obj, _tc.Spinner("WithoutBracket").GetRenderObjects(_tc.Table).RenderObjects[0].Mesh, "WithoutBracketPlate");
AssertNoObjMesh(_obj, "WithoutBracketBracket");
}
diff --git a/VisualPinball.Engine.Test/VPT/Surface/SurfaceDataTests.cs b/VisualPinball.Engine.Test/VPT/Surface/SurfaceDataTests.cs
index 7e448e3b1..140361ea7 100644
--- a/VisualPinball.Engine.Test/VPT/Surface/SurfaceDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Surface/SurfaceDataTests.cs
@@ -14,10 +14,12 @@
// 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.Test.Test;
using VisualPinball.Engine.VPT.Surface;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Surface
{
@@ -26,7 +28,7 @@ public class SurfaceDataTests
[Test]
public void ShouldReadSurfaceData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Surface);
+ var table = FileTableContainer.Load(VpxPath.Surface);
ValidateSurfaceData(table.Surface("TopInvisible").Data);
}
@@ -34,13 +36,14 @@ public void ShouldReadSurfaceData()
public void ShouldWriteSurfaceData()
{
const string tmpFileName = "ShouldWriteSurfaceData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Surface);
+ var table = FileTableContainer.Load(VpxPath.Surface);
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidateSurfaceData(writtenTable.Surface("TopInvisible").Data);
+ File.Delete(tmpFileName);
}
- private static void ValidateSurfaceData(SurfaceData data)
+ public static void ValidateSurfaceData(SurfaceData data)
{
data.DisableLightingBelow.Should().Be(0.6985f);
data.DisableLightingTop.Should().BeInRange(0.129f, 0.13f);
diff --git a/VisualPinball.Engine.Test/VPT/Surface/SurfaceMeshTests.cs b/VisualPinball.Engine.Test/VPT/Surface/SurfaceMeshTests.cs
index dcdcd3d14..b7e32da40 100644
--- a/VisualPinball.Engine.Test/VPT/Surface/SurfaceMeshTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Surface/SurfaceMeshTests.cs
@@ -18,33 +18,34 @@
using JeremyAnsel.Media.WavefrontObj;
using NUnit.Framework;
using VisualPinball.Engine.Test.Test;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Surface
{
public class SurfaceMeshTests : MeshTests
{
- private readonly Engine.VPT.Table.Table _table;
+ private readonly FileTableContainer _tc;
private readonly ObjFile _obj;
public SurfaceMeshTests()
{
- _table = Engine.VPT.Table.Table.Load(VpxPath.Surface);
+ _tc = FileTableContainer.Load(VpxPath.Surface);
_obj = LoadObjFixture(ObjPath.Surface);
}
[Test]
public void ShouldGenerateTopAndSides()
{
- var surface = _table.Surface("Wall");
- var surfaceMeshes = surface.GetRenderObjects(_table).RenderObjects.Select(ro => ro.Mesh).ToArray();
+ var surface = _tc.Surface("Wall");
+ var surfaceMeshes = surface.GetRenderObjects(_tc.Table).RenderObjects.Select(ro => ro.Mesh).ToArray();
AssertObjMesh(_obj, surface.Name, surfaceMeshes);
}
[Test]
public void ShouldGenerateOnlyTop()
{
- var surface = _table.Surface("SideInvisible");
- var surfaceMeshes = surface.GetRenderObjects(_table).RenderObjects
+ var surface = _tc.Surface("SideInvisible");
+ var surfaceMeshes = surface.GetRenderObjects(_tc.Table).RenderObjects
.Where(ro => ro.IsVisible)
.Select(ro => ro.Mesh).ToArray();
AssertObjMesh(_obj, surface.Name, surfaceMeshes, 0.001f);
@@ -53,8 +54,8 @@ public void ShouldGenerateOnlyTop()
[Test]
public void ShouldGenerateOnlySide()
{
- var surface = _table.Surface("TopInvisible");
- var surfaceMeshes = surface.GetRenderObjects(_table).RenderObjects
+ var surface = _tc.Surface("TopInvisible");
+ var surfaceMeshes = surface.GetRenderObjects(_tc.Table).RenderObjects
.Where(ro => ro.IsVisible)
.Select(ro => ro.Mesh).ToArray();
AssertObjMesh(_obj, surface.Name, surfaceMeshes);
diff --git a/VisualPinball.Engine.Test/VPT/Surface/SurfacePhysicsTests.cs b/VisualPinball.Engine.Test/VPT/Surface/SurfacePhysicsTests.cs
index 2fa1cd96a..69dc4eb25 100644
--- a/VisualPinball.Engine.Test/VPT/Surface/SurfacePhysicsTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Surface/SurfacePhysicsTests.cs
@@ -15,18 +15,19 @@
// along with this program. If not, see .
using VisualPinball.Engine.Test.Test;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Surface
{
public class SurfacePhysicsTests : BaseTests
{
- private readonly Engine.VPT.Table.Table _table;
+ private readonly FileTableContainer _tc;
private readonly Engine.VPT.Kicker.Kicker _kicker;
public SurfacePhysicsTests()
{
- _table = Engine.VPT.Table.Table.Load(VpxPath.Flipper);
- _kicker = _table.Kicker("BallRelease");
+ _tc = FileTableContainer.Load(VpxPath.Flipper);
+ _kicker = _tc.Kicker("BallRelease");
}
// [Test]
diff --git a/VisualPinball.Engine.Test/VPT/Table/TableDataTests.cs b/VisualPinball.Engine.Test/VPT/Table/TableDataTests.cs
index 668e90426..d44fa3c7f 100644
--- a/VisualPinball.Engine.Test/VPT/Table/TableDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Table/TableDataTests.cs
@@ -14,6 +14,7 @@
// 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.Common;
@@ -28,57 +29,65 @@ public class TableDataTests : BaseTests
[Test]
public void ShouldReadTableData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Table);
- ValidateTableData(table.Data);
+ var table = FileTableContainer.Load(VpxPath.Table);
+ ValidateTableData(table.Table.Data);
}
[Test]
public void ShouldReadTableInfo()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Table);
-
- table.InfoAuthorEmail.Should().Be("test@vpdb.io");
- table.InfoAuthorName.Should().Be("Table Author");
- table.InfoAuthorWebsite.Should().Be("https://vpdb.io");
- table.InfoReleaseDate.Should().Be("2019-04-14");
- table.InfoBlurb.Should().Be("Short Blurb");
- table.InfoDescription.Should().Be("Description");
- table.InfoName.Should().Be("Table Name");
- table.InfoRules.Should().Be("Rules");
- table.InfoVersion.Should().Be("Version");
- table.TableInfo["customdata1"].Should().Be("customvalue1");
+ var table = FileTableContainer.Load(VpxPath.Table);
+ ValidateTableInfo(table);
}
[Test]
public void ShouldWriteTableData()
{
const string tmpFileName = "ShouldWriteTable.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Table);
+ var table = FileTableContainer.Load(VpxPath.Table);
new TableWriter(table).WriteTable(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
- ValidateTableData(writtenTable.Data);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
+ ValidateTableData(writtenTable.Table.Data);
+
+ File.Delete(tmpFileName);
}
[Test]
public void ShouldWriteCorrectHash()
{
const string tmpFileName = "ShouldWriteCorrectHash.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.TableChecksum);
+ var table = FileTableContainer.Load(VpxPath.TableChecksum);
new TableWriter(table).WriteTable(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
writtenTable.FileHash.Should().Equal(table.FileHash);
+
+ File.Delete(tmpFileName);
}
[Test]
public void ShouldReadCustomInfoTags()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Table);
+ var table = FileTableContainer.Load(VpxPath.Table);
table.CustomInfoTags.TagNames[0].Should().Be("customdata1");
table.CustomInfoTags.TagNames[1].Should().Be("foo");
}
- private static void ValidateTableData(TableData data)
+ public static void ValidateTableInfo(FileTableContainer table)
+ {
+ table.InfoAuthorEmail.Should().Be("test@vpdb.io");
+ table.InfoAuthorName.Should().Be("Table Author");
+ table.InfoAuthorWebsite.Should().Be("https://vpdb.io");
+ table.InfoReleaseDate.Should().Be("2019-04-14");
+ table.InfoBlurb.Should().Be("Short Blurb");
+ table.InfoDescription.Should().Be("Description");
+ table.InfoName.Should().Be("Table Name");
+ table.InfoRules.Should().Be("Rules");
+ table.InfoVersion.Should().Be("Version");
+ table.TableInfo["customdata1"].Should().Be("customvalue1");
+ }
+
+ public static void ValidateTableData(TableData data)
{
data.AngleTiltMax.Should().Be(0.60606f);
data.AngleTiltMin.Should().Be(0.2033f);
@@ -124,7 +133,7 @@ private static void ValidateTableData(TableData data)
data.BgOffsetZ[BackglassIndex.FullSingleScreen].Should().Be(-50.223f);
data.BloomStrength.Should().Be(1.5055f);
data.Bottom.Should().Be(2224);
- data.Code.Should().Be("Option Explicit\r\n");
+ data.Code.Trim().Should().Be("Option Explicit");
data.ColorBackdrop.Red.Should().Be(31);
data.ColorBackdrop.Green.Should().Be(32);
data.ColorBackdrop.Blue.Should().Be(33);
@@ -162,7 +171,6 @@ private static void ValidateTableData(TableData data)
data.NudgeTime.Should().Be(6.2931f);
data.NumCollections.Should().Be(0);
data.NumFonts.Should().Be(0);
- data.NumGameItems.Should().Be(1);
data.NumMaterials.Should().Be(1);
data.NumSounds.Should().Be(0);
data.NumTextures.Should().Be(1);
diff --git a/VisualPinball.Engine.Test/VPT/Table/TableMeshTests.cs b/VisualPinball.Engine.Test/VPT/Table/TableMeshTests.cs
index 70bfc992b..d396b0574 100644
--- a/VisualPinball.Engine.Test/VPT/Table/TableMeshTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Table/TableMeshTests.cs
@@ -17,24 +17,25 @@
using JeremyAnsel.Media.WavefrontObj;
using NUnit.Framework;
using VisualPinball.Engine.Test.Test;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Table
{
public class TableMeshTests : MeshTests
{
- private readonly Engine.VPT.Table.Table _table;
+ private readonly FileTableContainer _tc;
private readonly ObjFile _obj;
public TableMeshTests()
{
- _table = Engine.VPT.Table.Table.Load(VpxPath.Table);
+ _tc = FileTableContainer.Load(VpxPath.Table);
_obj = LoadObjFixture(ObjPath.Table);
}
[Test]
public void ShouldGeneratePlayfieldCorrectly()
{
- var tableMesh = _table.GetRenderObjects(_table).RenderObjects[0].Mesh;
+ var tableMesh = _tc.Table.GetRenderObjects(_tc.Table).RenderObjects[0].Mesh;
AssertObjMesh(_obj, tableMesh);
}
}
diff --git a/VisualPinball.Engine.Test/VPT/Textbox/TextBoxDataTest.cs b/VisualPinball.Engine.Test/VPT/Textbox/TextBoxDataTests.cs
similarity index 79%
rename from VisualPinball.Engine.Test/VPT/Textbox/TextBoxDataTest.cs
rename to VisualPinball.Engine.Test/VPT/Textbox/TextBoxDataTests.cs
index 48cfbe702..7afcb57bc 100644
--- a/VisualPinball.Engine.Test/VPT/Textbox/TextBoxDataTest.cs
+++ b/VisualPinball.Engine.Test/VPT/Textbox/TextBoxDataTests.cs
@@ -14,6 +14,7 @@
// 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.Test.Test;
@@ -23,26 +24,28 @@
namespace VisualPinball.Engine.Test.VPT.TextBox
{
- public class TextBoxDataTest : BaseTests
+ public class TextBoxDataTests : BaseTests
{
[Test]
public void ShouldReadTextBoxData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.TextBox);
- ValidateTableData(table.TextBox("TextBox001").Data);
+ var table = FileTableContainer.Load(VpxPath.TextBox);
+ ValidateTextBoxData(table.TextBox("TextBox001").Data);
}
[Test]
public void ShouldWriteTextBoxData()
{
const string tmpFileName = "ShouldWriteTextBoxData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.TextBox);
+ var table = FileTableContainer.Load(VpxPath.TextBox);
new TableWriter(table).WriteTable(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
- ValidateTableData(writtenTable.TextBox("TextBox001").Data);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
+ ValidateTextBoxData(writtenTable.TextBox("TextBox001").Data);
+
+ File.Delete(tmpFileName);
}
- private static void ValidateTableData(TextBoxData data)
+ public static void ValidateTextBoxData(TextBoxData data)
{
data.Align.Should().Be(TextAlignment.TextAlignCenter);
data.BackColor.Red.Should().Be(0);
diff --git a/VisualPinball.Engine.Test/VPT/TextureBitmapTests.cs b/VisualPinball.Engine.Test/VPT/TextureBitmapTests.cs
index 8a68d1902..8d7f73cf4 100644
--- a/VisualPinball.Engine.Test/VPT/TextureBitmapTests.cs
+++ b/VisualPinball.Engine.Test/VPT/TextureBitmapTests.cs
@@ -17,23 +17,24 @@
using FluentAssertions;
using NUnit.Framework;
using VisualPinball.Engine.Test.Test;
+using VisualPinball.Engine.VPT.Table;
using VisualPinball.Resources;
namespace VisualPinball.Engine.Test.VPT
{
public class TextureBitmapTests
{
- private readonly Engine.VPT.Table.Table _table;
+ private readonly FileTableContainer _tc;
public TextureBitmapTests()
{
- _table = Engine.VPT.Table.Table.Load(VpxPath.Texture);
+ _tc = FileTableContainer.Load(VpxPath.Texture);
}
[Test]
public void ShouldAnalyzeAnOpaqueTexture()
{
- var texture = _table.Textures["test_pattern_png"];
+ var texture = _tc.GetTexture("test_pattern_png");
var stats = texture.GetStats();
stats.Opaque.Should().Be(1f);
@@ -44,7 +45,7 @@ public void ShouldAnalyzeAnOpaqueTexture()
[Test]
public void ShouldAnalyzeAnotherOpaqueTexture()
{
- var texture = _table.Textures["test_pattern_argb"];
+ var texture = _tc.GetTexture("test_pattern_argb");
var stats = texture.GetStats();
stats.Opaque.Should().Be(1f);
@@ -55,7 +56,7 @@ public void ShouldAnalyzeAnotherOpaqueTexture()
[Test]
public void ShouldAnalyzeATransparentTexture()
{
- var texture = _table.Textures["test_pattern_transparent"];
+ var texture = _tc.GetTexture("test_pattern_transparent");
texture.Analyze();
var stats = texture.GetStats();
diff --git a/VisualPinball.Engine.Test/VPT/TextureDataTests.cs b/VisualPinball.Engine.Test/VPT/TextureDataTests.cs
index d0d70c1de..23af08d93 100644
--- a/VisualPinball.Engine.Test/VPT/TextureDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/TextureDataTests.cs
@@ -14,6 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
+using System.Data;
using System.IO;
using FluentAssertions;
using NUnit.Framework;
@@ -24,22 +25,21 @@ namespace VisualPinball.Engine.Test.VPT
{
public class TextureDataTests
{
- private readonly Engine.VPT.Table.Table _table;
+ private readonly FileTableContainer _table;
public TextureDataTests()
{
- _table = Engine.VPT.Table.Table.Load(VpxPath.Texture);
+ _table = FileTableContainer.Load(VpxPath.Texture);
}
[Test]
public void ShouldLoadCorrectArgb()
{
- var texture = _table.Textures["test_pattern_argb"];
+ var texture = _table.GetTexture("test_pattern_argb");
var blob = texture.FileContent;
var image = File.ReadAllBytes(TexturePath.BmpArgb);
texture.Data.Width.Should().Be(1024);
texture.Data.Height.Should().Be(768);
- texture.Data.InternalName.Should().Be("test_pattern_argb");
texture.Data.AlphaTestValue.Should().Be(1.0f);
texture.Data.Path.Should().StartWith(@"C:\");
blob.Should().Equal(image);
@@ -48,12 +48,11 @@ public void ShouldLoadCorrectArgb()
[Test]
public void ShouldLoadCorrectBmp()
{
- var texture = _table.Textures["test_pattern_bmp"];
+ var texture = _table.GetTexture("test_pattern_bmp");
var blob = texture.FileContent;
var image = File.ReadAllBytes(TexturePath.Bmp);
texture.Data.Width.Should().Be(1024);
texture.Data.Height.Should().Be(768);
- texture.Data.InternalName.Should().Be("test_pattern_bmp");
texture.Data.AlphaTestValue.Should().Be(1.0f);
texture.Data.Path.Should().StartWith(@"C:\");
blob.Should().Equal(image);
@@ -62,12 +61,11 @@ public void ShouldLoadCorrectBmp()
[Test]
public void ShouldLoadCorrectExr()
{
- var texture = _table.Textures["test_pattern_exr"];
+ var texture = _table.GetTexture("test_pattern_exr");
var blob = texture.FileContent;
var image = File.ReadAllBytes(TexturePath.Exr);
texture.Data.Width.Should().Be(587);
texture.Data.Height.Should().Be(675);
- texture.Data.InternalName.Should().Be("test_pattern_exr");
texture.Data.AlphaTestValue.Should().Be(1.0f);
texture.Data.Path.Should().StartWith(@"C:\");
blob.Should().Equal(image);
@@ -76,12 +74,11 @@ public void ShouldLoadCorrectExr()
[Test]
public void ShouldLoadCorrectHdr()
{
- var texture = _table.Textures["test_pattern_hdr"];
+ var texture = _table.GetTexture("test_pattern_hdr");
var blob = texture.FileContent;
var image = File.ReadAllBytes(TexturePath.Hdr);
texture.Data.Width.Should().Be(1024);
texture.Data.Height.Should().Be(512);
- texture.Data.InternalName.Should().Be("test_pattern_hdr");
texture.Data.AlphaTestValue.Should().Be(1.0f);
texture.Data.Path.Should().StartWith(@"C:\");
blob.Should().Equal(image);
@@ -90,12 +87,11 @@ public void ShouldLoadCorrectHdr()
[Test]
public void ShouldLoadCorrectJpg()
{
- var texture = _table.Textures["test_pattern_jpg"];
+ var texture = _table.GetTexture("test_pattern_jpg");
var blob = texture.FileContent;
var image = File.ReadAllBytes(TexturePath.Jpg);
texture.Data.Width.Should().Be(1024);
texture.Data.Height.Should().Be(768);
- texture.Data.InternalName.Should().Be("test_pattern_jpg");
texture.Data.AlphaTestValue.Should().Be(1.0f);
texture.Data.Path.Should().StartWith(@"C:\");
blob.Should().Equal(image);
@@ -104,12 +100,11 @@ public void ShouldLoadCorrectJpg()
[Test]
public void ShouldLoadCorrectPng()
{
- var texture = _table.Textures["test_pattern_png"];
+ var texture = _table.GetTexture("test_pattern_png");
var blob = texture.FileContent;
var image = File.ReadAllBytes(TexturePath.Png);
texture.Data.Width.Should().Be(1024);
texture.Data.Height.Should().Be(768);
- texture.Data.InternalName.Should().Be("test_pattern_png");
texture.Data.AlphaTestValue.Should().Be(1.0f);
texture.Data.Path.Should().StartWith(@"C:\");
blob.Should().Equal(image);
@@ -118,13 +113,12 @@ public void ShouldLoadCorrectPng()
[Test]
public void ShouldLoadCorrectTransparentPng()
{
- var texture = _table.Textures["test_pattern_transparent"];
+ var texture = _table.GetTexture("test_pattern_transparent");
var blob = texture.FileContent;
var image = File.ReadAllBytes(TexturePath.PngTransparent);
//File.WriteAllBytes(@"..\..\Fixtures\debug.bmp", textureData);
texture.Data.Width.Should().Be(1024);
texture.Data.Height.Should().Be(768);
- texture.Data.InternalName.Should().Be("test_pattern_transparent");
texture.Data.AlphaTestValue.Should().Be(1.0f);
texture.Data.Path.Should().StartWith(@"C:\");
blob.Should().Equal(image);
@@ -133,13 +127,25 @@ public void ShouldLoadCorrectTransparentPng()
[Test]
public void ShouldLoadCorrectTransparentXrgb()
{
- var texture = _table.Textures["test_pattern_xrgb"];
+ var texture = _table.GetTexture("test_pattern_xrgb");
var blob = texture.FileContent;
var image = File.ReadAllBytes(TexturePath.BmpXrgb);
//File.WriteAllBytes(@"..\..\Fixtures\debug.bmp", textureData);
texture.Data.Width.Should().Be(1024);
texture.Data.Height.Should().Be(768);
- texture.Data.InternalName.Should().Be("test_pattern_xrgb");
+ texture.Data.AlphaTestValue.Should().Be(1.0f);
+ texture.Data.Path.Should().StartWith(@"C:\");
+ blob.Should().Equal(image);
+ }
+
+ [Test]
+ public void ShouldLoadCorrectWebp()
+ {
+ var texture = _table.GetTexture("test_pattern_webp");
+ var blob = texture.FileContent;
+ var image = File.ReadAllBytes(TexturePath.Webp);
+ texture.Data.Width.Should().Be(1024);
+ texture.Data.Height.Should().Be(768);
texture.Data.AlphaTestValue.Should().Be(1.0f);
texture.Data.Path.Should().StartWith(@"C:\");
blob.Should().Equal(image);
@@ -150,8 +156,10 @@ public void ShouldWriteCorrectBinary()
{
const string tmpFileName = "ShouldWriteCorrectBinary.vpx";
new TableWriter(_table).WriteTable(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
- writtenTable.Textures["test_pattern_jpg"].Data.Binary.Data.Should().Equal(_table.Textures["test_pattern_jpg"].Data.Binary.Data);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
+ writtenTable.GetTexture("test_pattern_jpg").Data.Binary.Data.Should().Equal(_table.GetTexture("test_pattern_jpg").Data.Binary.Data);
+
+ File.Delete(tmpFileName);
}
[Test]
@@ -159,8 +167,9 @@ public void ShouldWriteCorrectBitmap()
{
const string tmpFileName = "ShouldWriteCorrectBitmap.vpx";
new TableWriter(_table).WriteTable(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
- writtenTable.Textures["test_pattern_bmp"].Data.Bitmap.Bytes.Should().Equal(_table.Textures["test_pattern_bmp"].Data.Bitmap.Bytes);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
+ writtenTable.GetTexture("test_pattern_bmp").Data.Bitmap.Bytes.Should().Equal(_table.GetTexture("test_pattern_bmp").Data.Bitmap.Bytes);
+ File.Delete(tmpFileName);
}
}
}
diff --git a/VisualPinball.Engine.Test/VPT/Timer/TimerDataTests.cs b/VisualPinball.Engine.Test/VPT/Timer/TimerDataTests.cs
index b46ae0f33..c548f4d42 100644
--- a/VisualPinball.Engine.Test/VPT/Timer/TimerDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Timer/TimerDataTests.cs
@@ -14,9 +14,11 @@
// 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.Test.Test;
+using VisualPinball.Engine.VPT.Table;
using VisualPinball.Engine.VPT.Timer;
namespace VisualPinball.Engine.Test.VPT.Timer
@@ -26,7 +28,7 @@ public class TimerDataTests
[Test]
public void ShouldReadTimerData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Timer);
+ var table = FileTableContainer.Load(VpxPath.Timer);
ValidateTimerData1(table.Timer("Timer1").Data);
ValidateTimerData2(table.Timer("Timer2").Data);
}
@@ -35,14 +37,15 @@ public void ShouldReadTimerData()
public void ShouldWriteTimerData()
{
const string tmpFileName = "ShouldWriteTimerData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Timer);
+ var table = FileTableContainer.Load(VpxPath.Timer);
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidateTimerData1(writtenTable.Timer("Timer1").Data);
ValidateTimerData2(writtenTable.Timer("Timer2").Data);
+ File.Delete(tmpFileName);
}
- private static void ValidateTimerData1(TimerData data)
+ public static void ValidateTimerData1(TimerData data)
{
data.Backglass.Should().Be(false);
data.Center.X.Should().Be(471.160583f);
@@ -51,7 +54,7 @@ private static void ValidateTimerData1(TimerData data)
data.TimerInterval.Should().Be(233);
}
- private static void ValidateTimerData2(TimerData data)
+ public static void ValidateTimerData2(TimerData data)
{
data.Backglass.Should().Be(true);
}
diff --git a/VisualPinball.Engine.Test/VPT/Trigger/TriggerDataTests.cs b/VisualPinball.Engine.Test/VPT/Trigger/TriggerDataTests.cs
index 667156cd4..a46d5417d 100644
--- a/VisualPinball.Engine.Test/VPT/Trigger/TriggerDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Trigger/TriggerDataTests.cs
@@ -14,10 +14,12 @@
// 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.Test.Test;
using VisualPinball.Engine.VPT;
+using VisualPinball.Engine.VPT.Table;
using VisualPinball.Engine.VPT.Trigger;
namespace VisualPinball.Engine.Test.VPT.Trigger
@@ -27,7 +29,7 @@ public class TriggerDataTests
[Test]
public void ShouldReadTriggerData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Trigger);
+ var table = FileTableContainer.Load(VpxPath.Trigger);
ValidateTriggerData(table.Trigger("Data").Data);
}
@@ -35,13 +37,14 @@ public void ShouldReadTriggerData()
public void ShouldWriteTriggerData()
{
const string tmpFileName = "ShouldWriteTriggerData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Trigger);
+ var table = FileTableContainer.Load(VpxPath.Trigger);
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidateTriggerData(writtenTable.Trigger("Data").Data);
+ File.Delete(tmpFileName);
}
- private static void ValidateTriggerData(TriggerData data)
+ public static void ValidateTriggerData(TriggerData data)
{
data.AnimSpeed.Should().Be(12.432f);
data.Center.X.Should().Be(542.732f);
diff --git a/VisualPinball.Engine.Test/VPT/Trigger/TriggerMeshTests.cs b/VisualPinball.Engine.Test/VPT/Trigger/TriggerMeshTests.cs
index 1d6bccd31..1ed66db4b 100644
--- a/VisualPinball.Engine.Test/VPT/Trigger/TriggerMeshTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Trigger/TriggerMeshTests.cs
@@ -17,30 +17,31 @@
using JeremyAnsel.Media.WavefrontObj;
using NUnit.Framework;
using VisualPinball.Engine.Test.Test;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.Test.VPT.Trigger
{
public class TriggerMeshTests : MeshTests
{
- private readonly Engine.VPT.Table.Table _table;
+ private readonly FileTableContainer _tc;
private readonly ObjFile _obj;
public TriggerMeshTests()
{
- _table = Engine.VPT.Table.Table.Load(VpxPath.Trigger);
+ _tc = FileTableContainer.Load(VpxPath.Trigger);
_obj = LoadObjFixture(ObjPath.Trigger);
}
[Test]
public void ShouldGenerateMeshesCorrectly()
{
- AssertObjMesh(_table, _obj, _table.Trigger("Button"));
- AssertObjMesh(_table, _obj, _table.Trigger("Star"), threshold: 0.001f);
- AssertObjMesh(_table, _obj, _table.Trigger("WireA"));
- AssertObjMesh(_table, _obj, _table.Trigger("WireB"));
- AssertObjMesh(_table, _obj, _table.Trigger("WireC"));
- AssertObjMesh(_table, _obj, _table.Trigger("WireD"));
- AssertObjMesh(_table, _obj, _table.Trigger("Surface"));
+ AssertObjMesh(_tc.Table, _obj, _tc.Trigger("Button"));
+ AssertObjMesh(_tc.Table, _obj, _tc.Trigger("Star"), threshold: 0.001f);
+ AssertObjMesh(_tc.Table, _obj, _tc.Trigger("WireA"));
+ AssertObjMesh(_tc.Table, _obj, _tc.Trigger("WireB"));
+ AssertObjMesh(_tc.Table, _obj, _tc.Trigger("WireC"));
+ AssertObjMesh(_tc.Table, _obj, _tc.Trigger("WireD"));
+ AssertObjMesh(_tc.Table, _obj, _tc.Trigger("Surface"));
// the last two fail because vpx ignores thickness when exporting.
// re-enable when fixed on vp side.
diff --git a/VisualPinball.Engine.Test/VPT/Trough/TroughDataTests.cs b/VisualPinball.Engine.Test/VPT/Trough/TroughDataTests.cs
index 5f7ee0a67..95ad75649 100644
--- a/VisualPinball.Engine.Test/VPT/Trough/TroughDataTests.cs
+++ b/VisualPinball.Engine.Test/VPT/Trough/TroughDataTests.cs
@@ -14,20 +14,24 @@
// 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.Test.Test;
using VisualPinball.Engine.VPT;
+using VisualPinball.Engine.VPT.Table;
using VisualPinball.Engine.VPT.Trough;
namespace VisualPinball.Engine.Test.VPT.Trough
{
public class TroughDataTests
{
+ #if !WRITE_VP106 && !WRITE_VP107
+
[Test]
public void ShouldReadTroughData()
{
- var table = Engine.VPT.Table.Table.Load(VpxPath.Trough);
+ var table = FileTableContainer.Load(VpxPath.Trough);
ValidateTroughData(table.Trough("Trough1").Data);
}
@@ -35,13 +39,14 @@ public void ShouldReadTroughData()
public void ShouldWriteTroughData()
{
const string tmpFileName = "ShouldWriteTroughData.vpx";
- var table = Engine.VPT.Table.Table.Load(VpxPath.Trough);
+ var table = FileTableContainer.Load(VpxPath.Trough);
table.Save(tmpFileName);
- var writtenTable = Engine.VPT.Table.Table.Load(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
ValidateTroughData(writtenTable.Trough("Trough1").Data);
+ File.Delete(tmpFileName);
}
- private static void ValidateTroughData(TroughData data)
+ public static void ValidateTroughData(TroughData data)
{
data.Type.Should().Be(TroughType.ModernOpto);
data.BallCount.Should().Be(3);
@@ -53,5 +58,7 @@ private static void ValidateTroughData(TroughData data)
data.PlayfieldEntrySwitch.Should().Be("BallDrain");
data.PlayfieldExitKicker.Should().Be("BallRelease");
}
+
+ #endif
}
}
diff --git a/VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj b/VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj
index 6abe93406..4851a8c20 100644
--- a/VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj
+++ b/VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj
@@ -28,9 +28,9 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
+
+
+
diff --git a/VisualPinball.Engine.sln b/VisualPinball.Engine.sln
index af0df9885..9ddfa4d66 100644
--- a/VisualPinball.Engine.sln
+++ b/VisualPinball.Engine.sln
@@ -6,6 +6,26 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VisualPinball.Resources", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VisualPinball.Engine.Test", "VisualPinball.Engine.Test\VisualPinball.Engine.Test.csproj", "{3D642DA1-C750-4EB0-AE33-E2A2CDA3DDEB}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution", "Solution", "{E74E1502-B527-475D-BCEC-B8F60699BA5F}"
+ProjectSection(SolutionItems) = preProject
+ LICENSE = LICENSE
+ README.md = README.md
+ .editorconfig = .editorconfig
+ .gitignore = .gitignore
+ CHANGELOG.md = CHANGELOG.md
+ CONTRIBUTING.md = CONTRIBUTING.md
+ package.json = package.json
+EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Workflows", "Workflows", "{E6A28E8F-1DE7-4CF4-ADB7-A55A6E6467AF}"
+ProjectSection(SolutionItems) = preProject
+ .github\workflows\build.yml = .github\workflows\build.yml
+ .github\workflows\dependents.yml = .github\workflows\dependents.yml
+ .github\workflows\documentation.yml = .github\workflows\documentation.yml
+ .github\workflows\publish.yml = .github\workflows\publish.yml
+ .github\workflows\release.yml = .github\workflows\release.yml
+EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -53,4 +73,7 @@ Global
{3D642DA1-C750-4EB0-AE33-E2A2CDA3DDEB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3D642DA1-C750-4EB0-AE33-E2A2CDA3DDEB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {E6A28E8F-1DE7-4CF4-ADB7-A55A6E6467AF} = {E74E1502-B527-475D-BCEC-B8F60699BA5F}
+ EndGlobalSection
EndGlobal
diff --git a/VisualPinball.Engine/Common/StringExtensions.cs b/VisualPinball.Engine/Common/StringExtensions.cs
index 62fc2c171..358a1c512 100644
--- a/VisualPinball.Engine/Common/StringExtensions.cs
+++ b/VisualPinball.Engine/Common/StringExtensions.cs
@@ -18,12 +18,45 @@
// ReSharper disable ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator
using System.Collections.Generic;
+using System.IO;
using System.Text.RegularExpressions;
namespace VisualPinball.Engine.Common
{
public static class StringExtensions
{
+ private const string InvalidFilenameRegex = @"[^ !#$%&'()+,\.0123456789;=@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]\^_`abcdefghijklmnopqrstuvwxyz{}~-]+";
+
+ public static string ToNormalizedName(this string name)
+ {
+ var normalizedName = Regex.Replace(name.RemoveDiacritics(), @"[^.\w\d-]+", "_").ToLower();
+ return normalizedName.Length == 1 ? normalizedName : normalizedName.Trim('_');
+ }
+
+ public static string ToFilename(this string name)
+ {
+ var filename = Regex.Replace(name.RemoveDiacritics(), InvalidFilenameRegex, "_");
+ return filename.Length == 1 ? filename : filename.Trim('_');
+ }
+
+ private static string RemoveDiacritics(this string s)
+ {
+ var text = "";
+ foreach (var c in s) {
+ var len = text.Length;
+ foreach (var entry in ForeignCharacters) {
+ if (entry.Key.IndexOf(c) != -1) {
+ text += entry.Value;
+ break;
+ }
+ }
+ if (len == text.Length) {
+ text += c;
+ }
+ }
+ return text;
+ }
+
private static readonly Dictionary ForeignCharacters = new Dictionary
{
{"äæǽ", "ae"},
@@ -116,30 +149,5 @@ public static class StringExtensions
{"Я", "Ya"},
{"я", "ya"},
};
-
- public static string RemoveDiacritics(this string s)
- {
- var text = "";
- foreach (var c in s) {
- var len = text.Length;
- foreach (var entry in ForeignCharacters) {
- if (entry.Key.IndexOf(c) != -1) {
- text += entry.Value;
- break;
- }
- }
-
- if (len == text.Length) {
- text += c;
- }
- }
-
- return text;
- }
-
- public static string ToNormalizedName(this string name)
- {
- return Regex.Replace(name.RemoveDiacritics(), @"[^.\w\d-]+", "_").Trim('_').ToLower();
- }
}
}
diff --git a/VisualPinball.Engine/IO/BiffData.cs b/VisualPinball.Engine/IO/BiffData.cs
index d74bbba13..12819a224 100644
--- a/VisualPinball.Engine/IO/BiffData.cs
+++ b/VisualPinball.Engine/IO/BiffData.cs
@@ -30,7 +30,7 @@ namespace VisualPinball.Engine.IO
{
public enum StoragePrefix
{
- GameItem, Collection, Sound, Image, Mappings
+ GameItem, VpeGameItem, Collection, Sound, Image, Mappings
}
///
@@ -47,7 +47,7 @@ public abstract class BiffData
public string StorageName => _storageName ?? $"{StoragePrefix}{StorageIndex}";
public StoragePrefix StoragePrefix;
- public int StorageIndex;
+ public int StorageIndex = -1;
public readonly List UnknownRecords = new List();
private readonly string _storageName;
diff --git a/VisualPinball.Engine/Math/DragPointData.cs b/VisualPinball.Engine/Math/DragPointData.cs
index 480136b9e..28f9f2aaa 100644
--- a/VisualPinball.Engine/Math/DragPointData.cs
+++ b/VisualPinball.Engine/Math/DragPointData.cs
@@ -24,6 +24,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using VisualPinball.Engine.IO;
using VisualPinball.Engine.VPT.Table;
@@ -65,6 +66,7 @@ public class DragPointData : BiffData
public float CalcHeight;
+ [ExcludeFromCodeCoverage]
public override string ToString()
{
return $"DragPoint({Center.X}/{Center.Y}/{Center.Z}, {(IsSmooth ? "S" : "")}{(IsSlingshot ? "SS" : "")}{(HasAutoTexture ? "A" : "")})";
diff --git a/VisualPinball.Engine/Math/Matrix2D.cs b/VisualPinball.Engine/Math/Matrix2D.cs
deleted file mode 100644
index 70382fc35..000000000
--- a/VisualPinball.Engine/Math/Matrix2D.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-// 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 .
-
-namespace VisualPinball.Engine.Math
-{
- public struct Matrix2D
- {
- public float M00;
- public float M01;
- public float M02;
- public float M10;
- public float M11;
- public float M12;
- public float M20;
- public float M21;
- public float M22;
-
- public Matrix2D(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22)
- {
- M00 = m00;
- M01 = m01;
- M02 = m02;
- M10 = m10;
- M11 = m11;
- M12 = m12;
- M20 = m20;
- M21 = m21;
- M22 = m22;
- }
-
- public static Matrix2D Identity = new Matrix2D(
- 1f, 0f, 0f,
- 0f, 1f, 0f,
- 0f, 0f, 1f
- );
-
- public Matrix2D RotationAroundAxis(Vertex3D axis, float rSin, float rCos)
- {
- M00 = axis.X * axis.X + rCos * (1.0f - axis.X * axis.X);
- M10 = axis.X * axis.Y * (1.0f - rCos) - axis.Z * rSin;
- M20 = axis.Z * axis.X * (1.0f - rCos) + axis.Y * rSin;
-
- M01 = axis.X * axis.Y * (1.0f - rCos) + axis.Z * rSin;
- M11 = axis.Y * axis.Y + rCos * (1.0f - axis.Y * axis.Y);
- M21 = axis.Y * axis.Z * (1.0f - rCos) - axis.X * rSin;
-
- M02 = axis.Z * axis.X * (1.0f - rCos) - axis.Y * rSin;
- M12 = axis.Y * axis.Z * (1.0f - rCos) + axis.X * rSin;
- M22 = axis.Z * axis.Z + rCos * (1.0f - axis.Z * axis.Z);
-
- return this;
- }
- }
-}
diff --git a/VisualPinball.Engine/Math/Rect3D.cs b/VisualPinball.Engine/Math/Rect3D.cs
index e43b13f4c..9f397764c 100644
--- a/VisualPinball.Engine/Math/Rect3D.cs
+++ b/VisualPinball.Engine/Math/Rect3D.cs
@@ -14,8 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-using VisualPinball.Engine.Common;
-
namespace VisualPinball.Engine.Math
{
public struct Rect3D
@@ -31,16 +29,6 @@ public struct Rect3D
public float Height => MathF.Abs(Top - Bottom);
public float Depth => MathF.Abs(ZLow - ZHigh);
- public Rect3D(bool init)
- {
- Left = Constants.FloatMax;
- Right = -Constants.FloatMax;
- Top = Constants.FloatMax;
- Bottom = -Constants.FloatMax;
- ZLow = Constants.FloatMax;
- ZHigh = -Constants.FloatMax;
- }
-
public Rect3D(float left, float right, float top, float bottom, float zLow, float zHigh)
{
Left = left;
diff --git a/VisualPinball.Engine/Math/Vertex2D.cs b/VisualPinball.Engine/Math/Vertex2D.cs
index da1080207..6eda6e8f8 100644
--- a/VisualPinball.Engine/Math/Vertex2D.cs
+++ b/VisualPinball.Engine/Math/Vertex2D.cs
@@ -15,6 +15,7 @@
// along with this program. If not, see .
using System;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
namespace VisualPinball.Engine.Math
@@ -40,18 +41,6 @@ public Vertex2D(BinaryReader reader, int len)
}
}
- public Vertex2D Set(float x, float y)
- {
- X = x;
- Y = y;
- return this;
- }
-
- public Vertex2D SetZero()
- {
- return Set(0, 0);
- }
-
public static Vertex2D operator +(Vertex2D a, Vertex2D b) => new Vertex2D(a.X + b.X, a.Y + b.Y);
public static Vertex2D operator -(Vertex2D a, Vertex2D b) => new Vertex2D(a.X - b.X, a.Y - b.Y);
public static Vertex2D operator *(Vertex2D a, float b) => new Vertex2D(a.X * b, a.Y * b);
@@ -69,21 +58,7 @@ public float Length()
return MathF.Sqrt(X * X + Y * Y);
}
- public float LengthSq()
- {
- return X * X + Y * Y;
- }
-
- public float Dot(Vertex2D pv)
- {
- return X * pv.X + Y * pv.Y;
- }
-
- public bool Equals(Vertex2D v)
- {
- return X == v.X && Y == v.Y;
- }
-
+ [ExcludeFromCodeCoverage]
public override string ToString()
{
return $"Vertex2D({X}/{Y})";
diff --git a/VisualPinball.Engine/Math/Vertex3D.cs b/VisualPinball.Engine/Math/Vertex3D.cs
index 7235aa6f9..de077deb4 100644
--- a/VisualPinball.Engine/Math/Vertex3D.cs
+++ b/VisualPinball.Engine/Math/Vertex3D.cs
@@ -15,6 +15,7 @@
// along with this program. If not, see .
using System;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using VisualPinball.Engine.Common;
@@ -37,13 +38,6 @@ public Vertex3D(float x, float y, float z)
Z = z;
}
- public Vertex3D(Vertex3D v)
- {
- X = v.X;
- Y = v.Y;
- Z = v.Z;
- }
-
public Vertex3D(BinaryReader reader, int len)
{
X = reader.ReadSingle();
@@ -63,16 +57,6 @@ public Vertex3D(BinaryReader reader, int len)
public static Vertex3D operator *(Vertex3D a, float b) => new Vertex3D(a.X * b, a.Y * b, a.Z * b);
public static Vertex3D operator *(float a, Vertex3D b) => b * a;
public static Vertex3D operator /(Vertex3D a, float b) => new Vertex3D(a.X / b, a.Y / b, a.Z / b);
- public static Vertex3D operator *(Matrix2D matrix, Vertex3D b) => new Vertex3D(
- matrix.M00 * b.X + matrix.M01 * b.Y + matrix.M02 * b.Z,
- matrix.M10 * b.X + matrix.M11 * b.Y + matrix.M12 * b.Z,
- matrix.M20 * b.X + matrix.M21 * b.Y + matrix.M22 * b.Z
- );
-
- public static void Reset(Vertex3D v)
- {
- v.Set(0, 0, 0);
- }
public Vertex3D Set(Vertex3D v)
{
@@ -90,12 +74,7 @@ public Vertex3D Set(float x, float y, float z)
return this;
}
- // public new Vertex3D Clone()
- // {
- // return new Vertex3D(this);
- // }
-
- public new void Normalize()
+ public void Normalize()
{
var oneOverLength = 1.0f / Length();
X *= oneOverLength;
@@ -112,66 +91,21 @@ public Vertex3D NormalizeSafe()
return this;
}
- public new float Length()
+ public float Length()
{
return MathF.Sqrt(X * X + Y * Y + Z * Z);
}
- public new float LengthSq()
+ public float LengthSq()
{
return X * X + Y * Y + Z * Z;
}
- // public new Vertex3D DivideScalar(float scalar)
- // {
- // return MultiplyScalar(1 / scalar);
- // }
-
- // public new Vertex3D MultiplyScalar(float scalar)
- // {
- // X *= scalar;
- // Y *= scalar;
- // Z *= scalar;
- // return this;
- // }
-
- // public Vertex3D ApplyMatrix2D(Matrix2D matrix)
- // {
- // var x = matrix.Matrix[0][0] * X + matrix.Matrix[0][1] * Y + matrix.Matrix[0][2] * Z;
- // var y = matrix.Matrix[1][0] * X + matrix.Matrix[1][1] * Y + matrix.Matrix[1][2] * Z;
- // var z = matrix.Matrix[2][0] * X + matrix.Matrix[2][1] * Y + matrix.Matrix[2][2] * Z;
- // X = x;
- // Y = y;
- // Z = z;
- // return this;
- // }
-
public float Dot(Vertex3D v)
{
return X * v.X + Y * v.Y + Z * v.Z;
}
- // public Vertex3D Sub(Vertex3D v)
- // {
- // X -= v.X;
- // Y -= v.Y;
- // Z -= v.Z;
- // return this;
- // }
-
- // public Vertex3D Add(Vertex3D v)
- // {
- // X += v.X;
- // Y += v.Y;
- // Z += v.Z;
- // return this;
- // }
-
- // public Vertex3D Cross(Vertex3D v)
- // {
- // return CrossVectors(this, v);
- // }
-
public static Vertex3D CrossVectors(Vertex3D a, Vertex3D b)
{
var ax = a.X;
@@ -188,27 +122,12 @@ public static Vertex3D CrossVectors(Vertex3D a, Vertex3D b)
);
}
- public Vertex2D xy()
- {
- return new Vertex2D(X, Y);
- }
-
- public new Vertex3D SetZero()
- {
- return Set(0f, 0f, 0f);
- }
-
public bool IsZero()
{
return MathF.Abs(X) < Constants.FloatMin && MathF.Abs(Y) < Constants.FloatMin &&
MathF.Abs(Z) < Constants.FloatMin;
}
- public bool Equals(Vertex3D v)
- {
- return v.X == X && v.Y == Y && v.Z == Z;
- }
-
public static Vertex3D CrossProduct(Vertex3D pv1, Vertex3D pv2)
{
return new Vertex3D(
@@ -218,11 +137,6 @@ public static Vertex3D CrossProduct(Vertex3D pv1, Vertex3D pv2)
);
}
- public static Vertex3D CrossZ(float rz, Vertex3D v)
- {
- return new Vertex3D(-rz * v.Y, rz * v.X, 0);
- }
-
public static Vertex3D GetRotatedAxis(float angle, Vertex3D axis, Vertex3D temp)
{
var u = axis;
@@ -261,11 +175,10 @@ public Vertex3D MultiplyMatrixNoTranslate(Matrix3D matrix)
return matrix.MultiplyMatrixNoTranslate(this);
}
+ [ExcludeFromCodeCoverage]
public override string ToString()
{
return $"Vertex3D({X}/{Y}/{Z})";
}
-
- public float Magnitude() => MathF.Sqrt(this.Dot(this));
}
}
diff --git a/VisualPinball.Engine/Math/Vertex3DNoTex2.cs b/VisualPinball.Engine/Math/Vertex3DNoTex2.cs
index 0e30f9dc7..696583914 100644
--- a/VisualPinball.Engine/Math/Vertex3DNoTex2.cs
+++ b/VisualPinball.Engine/Math/Vertex3DNoTex2.cs
@@ -16,12 +16,13 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
namespace VisualPinball.Engine.Math
{
[Serializable]
- public struct Vertex3DNoTex2
+ public struct Vertex3DNoTex2 : IEquatable
{
public const int Size = 32;
@@ -104,14 +105,7 @@ public Vertex3D GetVertex() {
return new Vertex3D(X, Y, Z);
}
- public Vertex3D GetNormal() {
- return new Vertex3D(Nx, Ny, Nz);
- }
-
- public bool HasTextureCoordinates() {
- return !float.IsNaN(Tu) && !float.IsNaN(Tv);
- }
-
+ [ExcludeFromCodeCoverage]
public override string ToString()
{
return $"Vertex3DNoTex2({X}/{Y}/{Z}, {Nx}/{Ny}/{Nz}, {Tu}/{Tv})";
@@ -123,5 +117,19 @@ public void MultiplyMatrix(Matrix3D m)
Y = v.Y;
Z = v.Z;
}
+
+ public bool Equals(Vertex3DNoTex2 other)
+ {
+ return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z) && Nx.Equals(other.Nx) && Ny.Equals(other.Ny) && Nz.Equals(other.Nz) && Tu.Equals(other.Tu) && Tv.Equals(other.Tv);
+ }
+ public override bool Equals(object obj)
+ {
+ return obj is Vertex3DNoTex2 other && Equals(other);
+ }
+
+ public override int GetHashCode()
+ {
+ return (X, Y, Z, Nx, Ny, Nz, Tu, Tv).GetHashCode();
+ }
}
}
diff --git a/VisualPinball.Engine/VPT/BinaryData.cs b/VisualPinball.Engine/VPT/BinaryData.cs
index 010d9fc0e..1083f33af 100644
--- a/VisualPinball.Engine/VPT/BinaryData.cs
+++ b/VisualPinball.Engine/VPT/BinaryData.cs
@@ -63,6 +63,17 @@ public BinaryData(Resource res) : base(res.Name)
Data = res.Data;
}
+ public BinaryData(string name, byte[] data) : base(string.Empty)
+ {
+ Name = name;
+ Data = data;
+ }
+
+ public void FreeBinaryData()
+ {
+ Data = new byte[0];
+ }
+
protected override bool SkipWrite(BiffAttribute attr)
{
switch (attr.Name) {
diff --git a/VisualPinball.Engine/VPT/Bitmap.cs b/VisualPinball.Engine/VPT/Bitmap.cs
index f17c01e27..327195e23 100644
--- a/VisualPinball.Engine/VPT/Bitmap.cs
+++ b/VisualPinball.Engine/VPT/Bitmap.cs
@@ -86,6 +86,11 @@ public Bitmap(BinaryReader reader, int width, int height, int format = RGBA)
Data = ToggleRgbBgr(Data);
}
+ public void FreeBinaryData()
+ {
+ Data = new byte[0];
+ }
+
public void WriteCompressed(BinaryWriter writer)
{
var lzwWriter = new LzwWriter(writer, ToggleRgbBgr(Data), Width * 4, Height, Pitch());
diff --git a/VisualPinball.Engine/VPT/Flipper/Flipper.cs b/VisualPinball.Engine/VPT/Flipper/Flipper.cs
index fae6cbd52..a8881583d 100644
--- a/VisualPinball.Engine/VPT/Flipper/Flipper.cs
+++ b/VisualPinball.Engine/VPT/Flipper/Flipper.cs
@@ -17,6 +17,7 @@
using System.IO;
using VisualPinball.Engine.Game;
using VisualPinball.Engine.Math;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.VPT.Flipper
{
diff --git a/VisualPinball.Engine/VPT/Flipper/FlipperMeshGenerator.cs b/VisualPinball.Engine/VPT/Flipper/FlipperMeshGenerator.cs
index e6231c58d..2d8588dc7 100644
--- a/VisualPinball.Engine/VPT/Flipper/FlipperMeshGenerator.cs
+++ b/VisualPinball.Engine/VPT/Flipper/FlipperMeshGenerator.cs
@@ -16,6 +16,8 @@
// ReSharper disable CompareOfFloatsByEqualityOperator
+#nullable enable
+
using System;
using System.Collections.Generic;
using VisualPinball.Engine.Game;
@@ -42,7 +44,7 @@ public FlipperMeshGenerator(FlipperData data)
_data = data;
}
- public RenderObject GetRenderObject(Table.Table table, string id, Origin origin, bool asRightHanded)
+ public RenderObject? GetRenderObject(Table.Table table, string id, Origin origin, bool asRightHanded)
{
var meshes = GenerateMeshes(table);
var (preVertexMatrix, preNormalsMatrix) = GetPreMatrix(table, origin, asRightHanded);
@@ -94,7 +96,7 @@ public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin, bool
return new RenderObjectGroup(_data.Name, "Flippers", postMatrix, renderObjects.ToArray());
}
- protected override float BaseHeight(Table.Table table)
+ protected override float BaseHeight(Table.Table? table)
{
return 0f; // already in vertices
}
diff --git a/VisualPinball.Engine/VPT/Gate/GateData.cs b/VisualPinball.Engine/VPT/Gate/GateData.cs
index ad06936ea..c2b8aec48 100644
--- a/VisualPinball.Engine/VPT/Gate/GateData.cs
+++ b/VisualPinball.Engine/VPT/Gate/GateData.cs
@@ -31,7 +31,7 @@
namespace VisualPinball.Engine.VPT.Gate
{
[Serializable]
- public class GateData : ItemData, IPhysicalData
+ public class GateData : ItemData, IPhysicsMaterialData
{
public override string GetName() => Name;
public override void SetName(string name) { Name = name; }
diff --git a/VisualPinball.Engine/VPT/Gate/GateMeshGenerator.cs b/VisualPinball.Engine/VPT/Gate/GateMeshGenerator.cs
index e12b00223..6823c7e2a 100644
--- a/VisualPinball.Engine/VPT/Gate/GateMeshGenerator.cs
+++ b/VisualPinball.Engine/VPT/Gate/GateMeshGenerator.cs
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
+#nullable enable
+
using System;
using NLog;
using VisualPinball.Engine.Game;
@@ -72,9 +74,9 @@ public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin, bool
);
}
- protected override float BaseHeight(Table.Table table)
+ protected override float BaseHeight(Table.Table? table)
{
- return table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y);
+ return table?.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y) ?? 0f;
}
private Mesh GetBaseMesh()
diff --git a/VisualPinball.Engine/VPT/HitTarget/HitTargetData.cs b/VisualPinball.Engine/VPT/HitTarget/HitTargetData.cs
index f40e6b9d4..9a0820971 100644
--- a/VisualPinball.Engine/VPT/HitTarget/HitTargetData.cs
+++ b/VisualPinball.Engine/VPT/HitTarget/HitTargetData.cs
@@ -31,7 +31,7 @@
namespace VisualPinball.Engine.VPT.HitTarget
{
[Serializable]
- public class HitTargetData : ItemData, IPhysicalData
+ public class HitTargetData : ItemData, IPhysicsMaterialData
{
public override string GetName() => Name;
public override void SetName(string name) { Name = name; }
diff --git a/VisualPinball.Engine/VPT/HitTarget/HitTargetMeshGenerator.cs b/VisualPinball.Engine/VPT/HitTarget/HitTargetMeshGenerator.cs
index a4da0f6d5..1d28478b3 100644
--- a/VisualPinball.Engine/VPT/HitTarget/HitTargetMeshGenerator.cs
+++ b/VisualPinball.Engine/VPT/HitTarget/HitTargetMeshGenerator.cs
@@ -61,7 +61,7 @@ public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin, bool
protected override float BaseHeight(Table.Table table)
{
- return table.TableHeight;
+ return table?.TableHeight ?? 0f;
}
private Mesh GetBaseMesh()
diff --git a/VisualPinball.Engine/VPT/IItem.cs b/VisualPinball.Engine/VPT/IItem.cs
index a7369d750..5f3280a0e 100644
--- a/VisualPinball.Engine/VPT/IItem.cs
+++ b/VisualPinball.Engine/VPT/IItem.cs
@@ -34,5 +34,7 @@ public interface IItem
string ComponentName { get; }
ItemSubComponent SubComponent { get; }
string SubName { get; }
+
+ void FreeBinaryData();
}
}
diff --git a/VisualPinball.Engine/VPT/Item.cs b/VisualPinball.Engine/VPT/Item.cs
index d4d362bb9..41e5e15fe 100644
--- a/VisualPinball.Engine/VPT/Item.cs
+++ b/VisualPinball.Engine/VPT/Item.cs
@@ -57,6 +57,10 @@ public string Name
public ItemSubComponent SubComponent { get; private set; }
public string SubName { get; private set; }
+ public virtual void FreeBinaryData()
+ {
+ }
+
protected Item(TData data)
{
Data = data;
diff --git a/VisualPinball.Engine/VPT/ItemData.cs b/VisualPinball.Engine/VPT/ItemData.cs
index e0cb5dbd8..a311f2618 100644
--- a/VisualPinball.Engine/VPT/ItemData.cs
+++ b/VisualPinball.Engine/VPT/ItemData.cs
@@ -64,7 +64,7 @@ protected ItemData(string storageName) : base(storageName)
}
}
- public interface IPhysicalData
+ public interface IPhysicsMaterialData
{
///
/// If , use this elasticity instead of the material's.
diff --git a/VisualPinball.Engine/VPT/Kicker/KickerMeshGenerator.cs b/VisualPinball.Engine/VPT/Kicker/KickerMeshGenerator.cs
index bf27228d0..3276aed67 100644
--- a/VisualPinball.Engine/VPT/Kicker/KickerMeshGenerator.cs
+++ b/VisualPinball.Engine/VPT/Kicker/KickerMeshGenerator.cs
@@ -72,7 +72,7 @@ public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin, bool
protected override float BaseHeight(Table.Table table)
{
- return table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y);
+ return table?.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y) ?? 0f;
}
private Mesh GetBaseMesh()
diff --git a/VisualPinball.Engine/VPT/Light/LightMeshGenerator.cs b/VisualPinball.Engine/VPT/Light/LightMeshGenerator.cs
index 4a58829d4..6813efa3b 100644
--- a/VisualPinball.Engine/VPT/Light/LightMeshGenerator.cs
+++ b/VisualPinball.Engine/VPT/Light/LightMeshGenerator.cs
@@ -93,7 +93,7 @@ public Matrix3D GetPostMatrix(Table.Table table, Origin origin)
return new Matrix3D().SetTranslation(
_data.Center.X,
_data.Center.Y,
- table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y) * table.GetScaleZ()
+ (table?.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y) ?? 0f) * table?.GetScaleZ() ?? 1.0f
);
case Origin.Global:
diff --git a/VisualPinball.Engine/VPT/Mesh.cs b/VisualPinball.Engine/VPT/Mesh.cs
index bcf138d99..d5841d702 100644
--- a/VisualPinball.Engine/VPT/Mesh.cs
+++ b/VisualPinball.Engine/VPT/Mesh.cs
@@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.IO;
using VisualPinball.Engine.Common;
@@ -33,7 +34,7 @@ namespace VisualPinball.Engine.VPT
/// coordinates.
///
[Serializable]
- public class Mesh
+ public class Mesh : IEquatable
{
public string Name;
public Vertex3DNoTex2[] Vertices;
@@ -217,6 +218,7 @@ public static int[] PolygonToTriangles(IRenderVertex[] rgv, List poly)
return tri.ToArray();
}
+ [ExcludeFromCodeCoverage]
public static void ClosestPointOnPolygon(RenderVertex3D[] rgv, Vertex2D pvin, bool fClosed, out Vertex2D pvOut, out int piSeg)
{
var count = rgv.Length;
@@ -373,7 +375,7 @@ private static bool LinesIntersect(IRenderVertex start1, IRenderVertex start2, I
/// It is used primarily for storing animation frames.
///
[Serializable]
- public struct VertData
+ public struct VertData : IEquatable
{
public const int Size = 24;
@@ -456,6 +458,7 @@ public VertData Clone()
return vertex;
}
+ [ExcludeFromCodeCoverage]
public override string ToString()
{
return $"VertData({X}/{Y}/{Z}, {Nx}/{Ny}/{Nz})";
@@ -465,8 +468,86 @@ public Vertex3DNoTex2 ToVertex3DNoTex2()
{
return new Vertex3DNoTex2(X, Y, Z, Nx, Ny, Nz, 0f, 0f);
}
+
+ #region IEquatable
+
+ public bool Equals(VertData other)
+ {
+ return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z) && Nx.Equals(other.Nx) && Ny.Equals(other.Ny) && Nz.Equals(other.Nz);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj is VertData other && Equals(other);
+ }
+
+ public override int GetHashCode()
+ {
+ return (X, Y, Z, Nx, Ny, Nz).GetHashCode();
+ }
+
+ #endregion
+
}
#endregion
+
+ #region IEquatable
+
+ public bool Equals(Mesh other)
+ {
+ if (ReferenceEquals(null, other)) {
+ return false;
+ }
+ if (ReferenceEquals(this, other)) {
+ return true;
+ }
+ if (!Name.Equals(other.Name) || Vertices.Length != other.Vertices.Length
+ || Indices.Length != other.Indices.Length
+ || AnimationFrames.Count != other.AnimationFrames.Count
+ || !AnimationDefaultPosition.Equals(other.AnimationDefaultPosition)) {
+ return false;
+ }
+
+ for (var i = 0; i < Vertices.Length; i++) {
+ if (!Vertices[i].Equals(other.Vertices[i])) {
+ return false;
+ }
+ }
+
+ for (var i = 0; i < Indices.Length; i++) {
+ if (!Indices[i].Equals(other.Indices[i])) {
+ return false;
+ }
+ }
+
+ for (var i = 0; i < AnimationFrames.Count; i++) {
+ for (var j = 0; j < AnimationFrames[i].Length; j++) {
+ if (!AnimationFrames[i][j].Equals(other.AnimationFrames[i][j])) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) {
+ return false;
+ }
+ if (ReferenceEquals(this, obj)) {
+ return true;
+ }
+ return obj.GetType() == GetType() && Equals((Mesh)obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return (Name, Vertices, Indices, AnimationFrames, AnimationDefaultPosition).GetHashCode();
+ }
+
+ #endregion
}
}
diff --git a/VisualPinball.Engine/VPT/MeshGenerator.cs b/VisualPinball.Engine/VPT/MeshGenerator.cs
index 8003b5940..33dc52695 100644
--- a/VisualPinball.Engine/VPT/MeshGenerator.cs
+++ b/VisualPinball.Engine/VPT/MeshGenerator.cs
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
+#nullable enable
+
using System;
using VisualPinball.Engine.Game;
using VisualPinball.Engine.Math;
@@ -22,24 +24,24 @@ namespace VisualPinball.Engine.VPT
{
public abstract class MeshGenerator
{
- protected abstract float BaseHeight(Table.Table table);
+ protected abstract float BaseHeight(Table.Table? table);
protected abstract Vertex3D Position { get; }
protected abstract Vertex3D Scale { get; }
protected abstract float RotationZ { get; }
- protected Tuple GetPreMatrix(Table.Table table, Origin origin, bool asRightHanded)
+ protected Tuple GetPreMatrix(Table.Table? table, Origin origin, bool asRightHanded)
{
// todo adjust position, see kicker.cpp#419+
switch (origin) {
case Origin.Original:
return asRightHanded
- ? new Tuple(Matrix3D.RightHanded, null)
- : new Tuple(Matrix3D.Identity, null);
+ ? new Tuple(Matrix3D.RightHanded, null)
+ : new Tuple(Matrix3D.Identity, null);
case Origin.Global:
var m = GetTransformationMatrix(table);
return asRightHanded
- ? new Tuple(m.Item1.Multiply(Matrix3D.RightHanded), m.Item2?.Multiply(Matrix3D.RightHanded))
+ ? new Tuple(m.Item1.Multiply(Matrix3D.RightHanded), m.Item2?.Multiply(Matrix3D.RightHanded))
: m;
default:
throw new ArgumentOutOfRangeException(nameof(origin), origin, "Unknown origin " + origin);
@@ -56,7 +58,7 @@ internal Matrix3D GetPostMatrix(Table.Table table, Origin origin)
}
}
- protected virtual Tuple GetTransformationMatrix(Table.Table table)
+ protected virtual Tuple GetTransformationMatrix(Table.Table? table)
{
var scale = Scale;
var position = Position;
@@ -76,10 +78,10 @@ protected virtual Tuple GetTransformationMatrix(Table.Table
var fullMatrix = scaleMatrix.Clone();
fullMatrix.Multiply(rotMatrix);
fullMatrix.Multiply(transMatrix);
- scaleMatrix.SetScaling(1.0f, 1.0f, table.GetScaleZ());
+ scaleMatrix.SetScaling(1.0f, 1.0f, table?.GetScaleZ() ?? 1.0f);
fullMatrix.Multiply(scaleMatrix);
- return new Tuple(fullMatrix, null);
+ return new Tuple(fullMatrix, null);
}
}
}
diff --git a/VisualPinball.Engine/VPT/Primitive/Primitive.cs b/VisualPinball.Engine/VPT/Primitive/Primitive.cs
index 24016f12a..450a53abe 100644
--- a/VisualPinball.Engine/VPT/Primitive/Primitive.cs
+++ b/VisualPinball.Engine/VPT/Primitive/Primitive.cs
@@ -17,6 +17,7 @@
using System.IO;
using VisualPinball.Engine.Game;
using VisualPinball.Engine.Math;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.VPT.Primitive
{
@@ -47,6 +48,11 @@ public Primitive(BinaryReader reader, string itemName) : this(new PrimitiveData(
{
}
+ public override void FreeBinaryData()
+ {
+ Data.FreeBinaryData();
+ }
+
public static Primitive GetDefault(Table.Table table)
{
var primitiveData = new PrimitiveData(table.GetNewName("Primitive"), table.Width / 2f, table.Height / 2f);
diff --git a/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs b/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs
index 677473034..57723e3d9 100644
--- a/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs
+++ b/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs
@@ -31,7 +31,7 @@
namespace VisualPinball.Engine.VPT.Primitive
{
[Serializable]
- public class PrimitiveData : ItemData, IPhysicalData
+ public class PrimitiveData : ItemData, IPhysicsMaterialData
{
public override string GetName() => Name;
public override void SetName(string name) { Name = name; }
@@ -181,6 +181,12 @@ public class PrimitiveData : ItemData, IPhysicalData
public bool GetIsCollidable() => IsCollidable;
public string GetPhysicsMaterial() => PhysicsMaterial;
+ public void FreeBinaryData()
+ {
+ Mesh = null;
+ CompressedAnimationVertices = new int[0];
+ }
+
protected override bool SkipWrite(BiffAttribute attr)
{
switch (attr.Name) {
diff --git a/VisualPinball.Engine/VPT/Primitive/PrimitiveMeshGenerator.cs b/VisualPinball.Engine/VPT/Primitive/PrimitiveMeshGenerator.cs
index 1f26d11f4..8c532373e 100644
--- a/VisualPinball.Engine/VPT/Primitive/PrimitiveMeshGenerator.cs
+++ b/VisualPinball.Engine/VPT/Primitive/PrimitiveMeshGenerator.cs
@@ -18,6 +18,7 @@
using VisualPinball.Engine.Common;
using VisualPinball.Engine.Game;
using VisualPinball.Engine.Math;
+using VisualPinball.Engine.VPT.Table;
namespace VisualPinball.Engine.VPT.Primitive
{
@@ -78,7 +79,7 @@ public Mesh GetTransformedMesh(Table.Table table, Origin origin, bool asRightHan
protected override float BaseHeight(Table.Table table)
{
- return table.TableHeight;
+ return table?.TableHeight ?? 0f;
}
protected override Tuple GetTransformationMatrix(Table.Table table)
@@ -89,7 +90,7 @@ protected override Tuple GetTransformationMatrix(Table.Table
// translation matrix
var transMatrix = new Matrix3D();
- transMatrix.SetTranslation(Position.X, Position.Y, Position.Z + table.TableHeight);
+ transMatrix.SetTranslation(Position.X, Position.Y, Position.Z + table?.TableHeight ?? 0f);
// translation + rotation matrix
var rotTransMatrix = new Matrix3D();
@@ -113,7 +114,7 @@ protected override Tuple GetTransformationMatrix(Table.Table
var fullMatrix = scaleMatrix.Clone();
fullMatrix.Multiply(rotTransMatrix);
fullMatrix.Multiply(transMatrix); // fullMatrix = Smatrix * RTmatrix * Tmatrix
- scaleMatrix.SetScaling(1.0f, 1.0f, table.GetScaleZ());
+ scaleMatrix.SetScaling(1.0f, 1.0f, table?.GetScaleZ() ?? 1f);
fullMatrix.Multiply(scaleMatrix);
return new Tuple(fullMatrix, null);
diff --git a/VisualPinball.Engine/VPT/Ramp/RampData.cs b/VisualPinball.Engine/VPT/Ramp/RampData.cs
index a819c336b..e447f2ae1 100644
--- a/VisualPinball.Engine/VPT/Ramp/RampData.cs
+++ b/VisualPinball.Engine/VPT/Ramp/RampData.cs
@@ -31,7 +31,7 @@
namespace VisualPinball.Engine.VPT.Ramp
{
[Serializable]
- public class RampData : ItemData, IPhysicalData
+ public class RampData : ItemData, IPhysicsMaterialData
{
public override string GetName() => Name;
public override void SetName(string name) { Name = name; }
diff --git a/VisualPinball.Engine/VPT/Rubber/RubberData.cs b/VisualPinball.Engine/VPT/Rubber/RubberData.cs
index bba808cae..61cda506c 100644
--- a/VisualPinball.Engine/VPT/Rubber/RubberData.cs
+++ b/VisualPinball.Engine/VPT/Rubber/RubberData.cs
@@ -31,7 +31,7 @@
namespace VisualPinball.Engine.VPT.Rubber
{
[Serializable]
- public class RubberData : ItemData, IPhysicalData
+ public class RubberData : ItemData, IPhysicsMaterialData
{
public override string GetName() => Name;
public override void SetName(string name) { Name = name; }
diff --git a/VisualPinball.Engine/VPT/Rubber/RubberMeshGenerator.cs b/VisualPinball.Engine/VPT/Rubber/RubberMeshGenerator.cs
index 876f55700..32e0b5ba5 100644
--- a/VisualPinball.Engine/VPT/Rubber/RubberMeshGenerator.cs
+++ b/VisualPinball.Engine/VPT/Rubber/RubberMeshGenerator.cs
@@ -16,6 +16,8 @@
// ReSharper disable CompareOfFloatsByEqualityOperator
+#nullable enable
+
using System;
using NLog;
using VisualPinball.Engine.Common;
@@ -63,7 +65,7 @@ public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin, bool
));
}
- protected override Tuple GetTransformationMatrix(Table.Table table)
+ protected override Tuple GetTransformationMatrix(Table.Table? table)
{
var fullMatrix = new Matrix3D();
var tempMat = new Matrix3D();
@@ -76,19 +78,19 @@ protected override Tuple GetTransformationMatrix(Table.Table
var vertMatrix = new Matrix3D();
tempMat.SetTranslation(-Position.X, -Position.Y, -Position.Z);
vertMatrix.Multiply(tempMat, fullMatrix);
- tempMat.SetScaling(Scale.X, Scale.Y, Scale.Z * table.GetScaleZ());
+ tempMat.SetScaling(Scale.X, Scale.Y, Scale.Z * table?.GetScaleZ() ?? 0f);
vertMatrix.Multiply(tempMat);
if (_data.Height == _data.HitHeight) {
// do not z-scale the hit mesh
- tempMat.SetTranslation(Position.X, Position.Y, _data.Height + table.TableHeight);
+ tempMat.SetTranslation(Position.X, Position.Y, _data.Height + table?.TableHeight ?? 0f);
} else {
- tempMat.SetTranslation(Position.X, Position.Y, _data.Height * table.GetScaleZ() + table.TableHeight);
+ tempMat.SetTranslation(Position.X, Position.Y, _data.Height * (table?.GetScaleZ() ?? 1f) + (table?.TableHeight ?? 0f));
}
vertMatrix.Multiply(tempMat);
- return new Tuple(vertMatrix, fullMatrix);
+ return new Tuple(vertMatrix, fullMatrix);
}
public Mesh GetMesh(Table.Table table, int acc = -1, bool createHitShape = false)
@@ -241,7 +243,7 @@ public Mesh GetMesh(Table.Table table, int acc = -1, bool createHitShape = false
return mesh;
}
- protected override float BaseHeight(Table.Table table)
+ protected override float BaseHeight(Table.Table? table)
{
return 0f;
}
diff --git a/VisualPinball.Engine/VPT/Sound/Sound.cs b/VisualPinball.Engine/VPT/Sound/Sound.cs
index 38745f60a..203506acb 100644
--- a/VisualPinball.Engine/VPT/Sound/Sound.cs
+++ b/VisualPinball.Engine/VPT/Sound/Sound.cs
@@ -24,6 +24,8 @@ public class Sound : Item
public override string ItemGroupName { get; } = "Sounds";
public override ItemType ItemType { get; } = ItemType.Sound;
+ public string FileExtension => Data.Path == null ? ".wav" : Path.GetExtension(Data.Path).ToLower();
+
public Sound(string name) : this(new SoundData(name))
{
Name = name;
diff --git a/VisualPinball.Engine/VPT/Sound/SoundData.cs b/VisualPinball.Engine/VPT/Sound/SoundData.cs
index d192f2b09..bee196893 100644
--- a/VisualPinball.Engine/VPT/Sound/SoundData.cs
+++ b/VisualPinball.Engine/VPT/Sound/SoundData.cs
@@ -16,6 +16,7 @@
using System;
using System.IO;
+using System.Net;
using System.Text;
using VisualPinball.Engine.Common;
using VisualPinball.Engine.VPT.Table;
@@ -39,6 +40,8 @@ public class SoundData : ItemData
public int Balance;
public int Fade;
+ public bool IsWav => Path.EndsWith(".wav", StringComparison.OrdinalIgnoreCase);
+
public SoundData(string name) : base(IO.StoragePrefix.Sound)
{
Name = name;
@@ -53,26 +56,44 @@ public SoundData(BinaryReader reader, string storageName, int fileVersion) : bas
Load(reader, fileVersion);
}
+ public byte[] GetFileData()
+ {
+ using (var stream = new MemoryStream())
+ using (var writer = new BinaryWriter(stream)) {
+ if (IsWav) {
+ WriteHeader(writer);
+ }
+ writer.Write(Data);
+ return stream.ToArray();
+ }
+ }
+
public byte[] GetHeader() {
using (var stream = new MemoryStream())
using (var writer = new BinaryWriter(stream)) {
- writer.Write(Encoding.Default.GetBytes("RIFF"));
- writer.Write(Data.Length + 36);
- writer.Write(Encoding.Default.GetBytes("WAVE"));
- writer.Write(Encoding.Default.GetBytes("fmt "));
- writer.Write(16);
- writer.Write((short)Wfx.FormatTag);
- writer.Write((short)Wfx.Channels);
- writer.Write((int)Wfx.SamplesPerSec);
- writer.Write((int)(Wfx.SamplesPerSec * Wfx.BitsPerSample * Wfx.Channels / 8));
- writer.Write((short)Wfx.BlockAlign);
- writer.Write((short)Wfx.BitsPerSample);
- writer.Write(Encoding.Default.GetBytes("data"));
- writer.Write(Data.Length);
+ WriteHeader(writer);
return stream.ToArray();
}
}
+ private void WriteHeader(BinaryWriter writer)
+ {
+ writer.Write(Encoding.Default.GetBytes("RIFF")); // 4
+ writer.Write(Data.Length + 36); // 4
+ writer.Write(Encoding.Default.GetBytes("WAVE")); // 4
+ writer.Write(Encoding.Default.GetBytes("fmt ")); // 4
+ writer.Write(16); // 4
+ writer.Write((short)Wfx.FormatTag); // 2
+ writer.Write((short)Wfx.Channels); // 2
+ writer.Write((int)Wfx.SamplesPerSec); // 4
+ writer.Write((int)(Wfx.SamplesPerSec * Wfx.BitsPerSample * Wfx.Channels / 8)); // 4
+ writer.Write((short)Wfx.BlockAlign); // 2
+ writer.Write((short)Wfx.BitsPerSample); // 2
+ writer.Write(Encoding.Default.GetBytes("data")); // 4
+ writer.Write(Data.Length); // 4
+ // total 44 bytes
+ }
+
private void Load(BinaryReader reader, int fileVersion)
{
var numValues = fileVersion < Constants.NewSoundFormatVersion ? 5 : 10;
@@ -92,7 +113,11 @@ private void Load(BinaryReader reader, int fileVersion)
len = reader.ReadInt32();
InternalName = Encoding.Default.GetString(reader.ReadBytes(len));
break;
- case 3: Wfx = new WaveFormat(reader); break;
+ case 3:
+ if (IsWav) {
+ Wfx = new WaveFormat(reader);
+ }
+ break;
case 4:
len = reader.ReadInt32();
Data = reader.ReadBytes(len);
@@ -117,7 +142,9 @@ public override void Write(BinaryWriter writer, HashWriter hashWriter)
writer.Write(Encoding.Default.GetBytes(InternalName).Length);
writer.Write(Encoding.Default.GetBytes(InternalName));
- Wfx.Write(writer);
+ if (IsWav) {
+ Wfx.Write(writer);
+ }
writer.Write(Data.Length);
writer.Write(Data);
diff --git a/VisualPinball.Engine/VPT/Spinner/SpinnerMeshGenerator.cs b/VisualPinball.Engine/VPT/Spinner/SpinnerMeshGenerator.cs
index 0e778cff1..053974839 100644
--- a/VisualPinball.Engine/VPT/Spinner/SpinnerMeshGenerator.cs
+++ b/VisualPinball.Engine/VPT/Spinner/SpinnerMeshGenerator.cs
@@ -99,7 +99,7 @@ private static Material GetBracketMaterial()
protected override float BaseHeight(Table.Table table)
{
- return table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y);
+ return table?.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y) ?? 0f;
}
#region Mesh Imports
diff --git a/VisualPinball.Engine/VPT/Surface/SurfaceData.cs b/VisualPinball.Engine/VPT/Surface/SurfaceData.cs
index b09accd03..07ad81e16 100644
--- a/VisualPinball.Engine/VPT/Surface/SurfaceData.cs
+++ b/VisualPinball.Engine/VPT/Surface/SurfaceData.cs
@@ -31,7 +31,7 @@
namespace VisualPinball.Engine.VPT.Surface
{
[Serializable]
- public class SurfaceData : ItemData, IPhysicalData
+ public class SurfaceData : ItemData, IPhysicsMaterialData
{
public override string GetName() => Name;
public override void SetName(string name) { Name = name; }
diff --git a/VisualPinball.Engine/VPT/Table/CustomInfoTags.cs b/VisualPinball.Engine/VPT/Table/CustomInfoTags.cs
index 236642e17..49a1c8fe0 100644
--- a/VisualPinball.Engine/VPT/Table/CustomInfoTags.cs
+++ b/VisualPinball.Engine/VPT/Table/CustomInfoTags.cs
@@ -47,6 +47,11 @@ public CustomInfoTags(BinaryReader reader) : this()
Load(this, reader, Attributes);
}
+ public void Load(BinaryReader reader)
+ {
+ Load(this, reader, Attributes);
+ }
+
public override void Write(BinaryWriter writer, HashWriter hashWriter)
{
WriteRecord(writer, Attributes, hashWriter);
diff --git a/VisualPinball.Engine/VPT/Table/DefaultTableResourceContainer.cs b/VisualPinball.Engine/VPT/Table/DefaultTableResourceContainer.cs
deleted file mode 100644
index 52e8e1f0e..000000000
--- a/VisualPinball.Engine/VPT/Table/DefaultTableResourceContainer.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-// 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 System.Collections;
-using System.Collections.Generic;
-
-namespace VisualPinball.Engine.VPT.Table
-{
- ///
- /// Provides a basic default implementation for ITableResourceContainer that stores T in a c# dict
- ///
- ///
- public class DefaultTableResourceContainer : ITableResourceContainer where T : IItem
- {
- private Dictionary _dict = new Dictionary();
-
- public int Count => _dict.Count;
- public IEnumerable Values => _dict.Values;
-
- public T this[string k] => Get(k);
- public T Get(string k)
- {
- _dict.TryGetValue(k.ToLower(), out T val);
- return val;
- }
- public void Add(T value) => _dict[value.Name.ToLower()] = value;
- public bool Remove(T value) => _dict.Remove(value.Name.ToLower());
-
- IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
- public IEnumerator GetEnumerator()
- {
- foreach (var kvp in _dict) {
- yield return kvp.Value;
- }
- }
- }
-}
diff --git a/VisualPinball.Engine/VPT/Table/FileTableContainer.cs b/VisualPinball.Engine/VPT/Table/FileTableContainer.cs
new file mode 100644
index 000000000..eda43777b
--- /dev/null
+++ b/VisualPinball.Engine/VPT/Table/FileTableContainer.cs
@@ -0,0 +1,173 @@
+// 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 System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using VisualPinball.Engine.VPT.Collection;
+
+namespace VisualPinball.Engine.VPT.Table
+{
+ public class FileTableContainer : TableContainer
+ {
+ public override Table Table { get; }
+ public override Dictionary TableInfo { get; } = new Dictionary();
+ public override List Collections { get; } = new List();
+ public override Mappings.Mappings Mappings => _mappings;
+ public override CustomInfoTags CustomInfoTags { get; } = new CustomInfoTags();
+ public override IEnumerable Textures => _textures.Values;
+ public override IEnumerable Sounds => _sounds.Values;
+
+ private readonly Dictionary _textures = new Dictionary();
+ private readonly Dictionary _sounds = new Dictionary();
+
+ private Mappings.Mappings _mappings = new Mappings.Mappings();
+
+ public FileTableContainer(string name = "Table1")
+ {
+ Table = new Table(this, new TableData { Name = name });
+ }
+
+ public FileTableContainer(BinaryReader reader)
+ {
+ Table = new Table(this, new TableData(reader));
+ }
+
+ public void SetMappings(Mappings.Mappings mappings)
+ {
+ _mappings = mappings;
+ }
+
+ ///
+ /// Adds a game item to the table.
+ ///
+ /// Game item instance
+ /// If set, re-computes the storage indices. Only needed when adding game items via the editor.
+ /// Game item type
+ /// Whe type of game item is unknown
+ public void Add(T item, bool updateStorageIndices = false) where T : IItem
+ {
+ var dict = GetItemDictionary();
+ if (dict != null) {
+ AddItem(item.Name, item, dict, updateStorageIndices);
+
+ } else {
+ var list = GetItemList();
+ if (list != null) {
+ AddItem(item, list, updateStorageIndices);
+
+ } else {
+ throw new ArgumentException("Unknown item type " + typeof(T) + ".");
+ }
+ }
+ }
+
+ private void AddItem(string name, TItem item, IDictionary d, bool updateStorageIndices) where TItem : IItem
+ {
+ if (updateStorageIndices) {
+ item.StorageIndex = ItemDatas.Count();
+ Table.Data.NumGameItems = item.StorageIndex + 1;
+ }
+ d[name] = item;
+ }
+
+ private void AddItem(TItem item, ICollection d, bool updateStorageIndices) where TItem : IItem
+ {
+ if (updateStorageIndices) {
+ item.StorageIndex = ItemDatas.Count();
+ }
+ d.Add(item);
+ }
+
+ ///
+ /// Replaces all game items of a list with new game items.
+ ///
+ ///
+ ///
+ /// This only applied to Decals, because they are the only game items
+ /// that don't have a name.
+ ///
+ /// New list of game items
+ /// Game item type (only Decals)
+ /// If not decals
+ public void ReplaceAll(IEnumerable items) where T : IItem
+ {
+ var list = GetItemList();
+ if (list == null) {
+ throw new ArgumentException("Cannot set all " + typeof(T) + "s (only Decals so far).");
+ }
+ list.Clear();
+ list.AddRange(items);
+ }
+
+ ///
+ /// The API to load the table from a file.
+ ///
+ /// Path to the VPX file
+ /// If false, game items are not loaded. Useful when loading them on multiple threads.
+ /// The parsed table
+ public static FileTableContainer Load(string filename, bool loadGameItems = true)
+ {
+ return TableLoader.Load(filename, loadGameItems);
+ }
+
+
+ public override Material GetMaterial(string name)
+ {
+ if (Table.Data.Materials == null || name == null) {
+ return null;
+ }
+
+ // ReSharper disable once LoopCanBeConvertedToQuery
+ foreach (var t in Table.Data.Materials) {
+ if (t.Name == name) {
+ return t;
+ }
+ }
+
+ return null;
+ }
+
+ public override Texture GetTexture(string name)
+ {
+ var tex = name == null || !_textures.ContainsKey(name.ToLower())
+ ? null
+ : _textures[name.ToLower()];
+ return tex;
+ }
+
+ public int AddTexture(Texture texture)
+ {
+ _textures[texture.Name.ToLower()] = texture;
+ return _textures.Count;
+ }
+
+ public Sound.Sound GetSound(string name)
+ {
+ var snd = name == null || !_sounds.ContainsKey(name.ToLower())
+ ? null
+ : _sounds[name.ToLower()];
+ return snd;
+ }
+
+ public void AddSound(Sound.Sound sound)
+ {
+ _sounds[sound.Name.ToLower()] = sound;
+ }
+ }
+}
+
diff --git a/VisualPinball.Engine/Math/Matrix2D.cs.meta b/VisualPinball.Engine/VPT/Table/FileTableContainer.cs.meta
similarity index 83%
rename from VisualPinball.Engine/Math/Matrix2D.cs.meta
rename to VisualPinball.Engine/VPT/Table/FileTableContainer.cs.meta
index 77ee453d3..d5206f3e7 100644
--- a/VisualPinball.Engine/Math/Matrix2D.cs.meta
+++ b/VisualPinball.Engine/VPT/Table/FileTableContainer.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: a6c3cdb22cdfa774d96397e560bebf72
+guid: 653a1da4b61678346b9f2efbc4db7839
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/VisualPinball.Engine/VPT/Table/Table.cs b/VisualPinball.Engine/VPT/Table/Table.cs
index 64e1b5ae7..f9eda88ef 100644
--- a/VisualPinball.Engine/VPT/Table/Table.cs
+++ b/VisualPinball.Engine/VPT/Table/Table.cs
@@ -14,11 +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.IO;
-using System.Linq;
-using NLog;
using VisualPinball.Engine.Game;
using VisualPinball.Engine.Math;
@@ -36,13 +31,6 @@ public class Table : Item, IRenderable
public override string ItemGroupName { get; } = "Playfield";
public override ItemType ItemType { get; } = ItemType.Table;
- public Vertex3D Position { get => new Vertex3D(0, 0, 0); set { } }
- public float RotationY { get => 0; set { } }
-
- public CustomInfoTags CustomInfoTags { get; set; }
- public int FileVersion { get; set; }
- public byte[] FileHash { get; set; }
-
public float Width => Data.Right - Data.Left;
public float Height => Data.Bottom - Data.Top;
@@ -53,412 +41,59 @@ public class Table : Item, IRenderable
public bool HasMeshAsPlayfield => _meshGenerator.HasMeshAsPlayfield;
- public readonly Dictionary TableInfo = new Dictionary();
- public ITableResourceContainer Textures = new DefaultTableResourceContainer();
- public ITableResourceContainer Sounds = new DefaultTableResourceContainer();
- public readonly Dictionary Collections = new Dictionary();
- public Mappings.Mappings Mappings = new Mappings.Mappings();
-
- #region GameItems
-
- private readonly Dictionary _bumpers = new Dictionary();
- private readonly List _decals = new List();
- private readonly Dictionary _dispReels = new Dictionary();
- private readonly Dictionary _flippers = new Dictionary();
- private readonly Dictionary _gates = new Dictionary();
- private readonly Dictionary _hitTargets = new Dictionary();
- private readonly Dictionary _kickers = new Dictionary();
- private readonly Dictionary _lights = new Dictionary();
- private readonly Dictionary _lightSeqs = new Dictionary();
- private readonly Dictionary _plungers = new Dictionary();
- private readonly Dictionary _flashers = new Dictionary();
- private readonly Dictionary _primitives = new Dictionary();
- private readonly Dictionary _ramps = new Dictionary();
- private readonly Dictionary _rubbers = new Dictionary();
- private readonly Dictionary _spinners = new Dictionary();
- private readonly Dictionary _surfaces = new Dictionary();
- private readonly Dictionary _textBoxes = new Dictionary();
- private readonly Dictionary _timers = new Dictionary();
- private readonly Dictionary _triggers = new Dictionary();
- private readonly Dictionary _troughs = new Dictionary();
-
- public Bumper.Bumper Bumper(string name) => _bumpers[name];
- public Decal.Decal Decal(int i) => _decals[i];
- public DispReel.DispReel DispReel(string name) => _dispReels[name];
- public Flipper.Flipper Flipper(string name) => _flippers[name];
- public Gate.Gate Gate(string name) => _gates[name];
- public HitTarget.HitTarget HitTarget(string name) => _hitTargets[name];
- public Kicker.Kicker Kicker(string name) => _kickers[name];
- public Light.Light Light(string name) => _lights[name];
- public LightSeq.LightSeq LightSeq(string name) => _lightSeqs[name];
- public Plunger.Plunger Plunger(string name = null) => name == null ? _plungers.Values.FirstOrDefault() : _plungers[name];
- public Flasher.Flasher Flasher(string name) => _flashers[name];
- public Primitive.Primitive Primitive(string name) => _primitives[name];
- public Ramp.Ramp Ramp(string name) => _ramps[name];
- public Rubber.Rubber Rubber(string name) => _rubbers[name];
- public Spinner.Spinner Spinner(string name) => _spinners[name];
- public Surface.Surface Surface(string name) => _surfaces[name];
- public TextBox.TextBox TextBox(string name) => _textBoxes[name];
- public Timer.Timer Timer(string name) => _timers[name];
- public Trigger.Trigger Trigger(string name) => _triggers[name];
- public Trough.Trough Trough(string name) => _troughs[name];
-
- public IEnumerable Renderables => new IRenderable[] { this }
- .Concat(_bumpers.Values)
- .Concat(_flippers.Values)
- .Concat(_gates.Values)
- .Concat(_hitTargets.Values)
- .Concat(_kickers.Values)
- .Concat(_lights.Values)
- .Concat(_plungers.Values)
- .Concat(_primitives.Values)
- .Concat(_ramps.Values)
- .Concat(_rubbers.Values)
- .Concat(_spinners.Values)
- .Concat(_surfaces.Values)
- .Concat(_triggers.Values);
-
- ///
- /// Game items that need to be converted but aren't rendered.
- ///
- public IEnumerable NonRenderables => new IItem[0]
- .Concat(_troughs.Values);
-
- public IEnumerable GameItems => new IItem[] { }
- .Concat(_bumpers.Values)
- .Concat(_decals.Select(i => i))
- .Concat(_dispReels.Values)
- .Concat(_flippers.Values)
- .Concat(_flashers.Values)
- .Concat(_gates.Values)
- .Concat(_hitTargets.Values)
- .Concat(_kickers.Values)
- .Concat(_lights.Values)
- .Concat(_lightSeqs.Values)
- .Concat(_plungers.Values)
- .Concat(_primitives.Values)
- .Concat(_ramps.Values)
- .Concat(_rubbers.Values)
- .Concat(_spinners.Values)
- .Concat(_surfaces.Values)
- .Concat(_textBoxes.Values)
- .Concat(_timers.Values)
- .Concat(_triggers.Values)
- .Concat(_troughs.Values);
-
- public IEnumerable ItemDatas => new ItemData[] { }
- .Concat(_bumpers.Values.Select(i => i.Data))
- .Concat(_decals.Select(i => i.Data))
- .Concat(_dispReels.Values.Select(i => i.Data))
- .Concat(_flippers.Values.Select(i => i.Data))
- .Concat(_flashers.Values.Select(i => i.Data))
- .Concat(_gates.Values.Select(i => i.Data))
- .Concat(_hitTargets.Values.Select(i => i.Data))
- .Concat(_kickers.Values.Select(i => i.Data))
- .Concat(_lights.Values.Select(i => i.Data))
- .Concat(_lightSeqs.Values.Select(i => i.Data))
- .Concat(_plungers.Values.Select(i => i.Data))
- .Concat(_primitives.Values.Select(i => i.Data))
- .Concat(_ramps.Values.Select(i => i.Data))
- .Concat(_rubbers.Values.Select(i => i.Data))
- .Concat(_spinners.Values.Select(i => i.Data))
- .Concat(_surfaces.Values.Select(i => i.Data))
- .Concat(_textBoxes.Values.Select(i => i.Data))
- .Concat(_timers.Values.Select(i => i.Data))
- .Concat(_triggers.Values.Select(i => i.Data))
- .Concat(_troughs.Values.Select(i => i.Data));
-
- public IEnumerable Switchables => new ISwitchable[0]
- .Concat(_bumpers.Values)
- .Concat(_flippers.Values)
- .Concat(_gates.Values)
- .Concat(_hitTargets.Values)
- .Concat(_kickers.Values)
- .Concat(_spinners.Values)
- .Concat(_triggers.Values);
-
- public IEnumerable SwitchableDevices => new ISwitchableDevice[0]
- .Concat(_troughs.Values);
-
- public IEnumerable Coilables => new ICoilable[0]
- .Concat(_bumpers.Values)
- .Concat(_flippers.Values)
- .Concat(_kickers.Values);
-
- public IEnumerable CoilableDevices => new ICoilableDevice[0]
- .Concat(_troughs.Values)
- .Concat(_plungers.Values);
-
- public IEnumerable Lightables => new ILightable[0]
- .Concat(_lights.Values)
- .Concat(_flashers.Values);
-
- private void AddItem(string name, TItem item, IDictionary d, bool updateStorageIndices) where TItem : IItem
- {
- if (updateStorageIndices) {
- item.StorageIndex = ItemDatas.Count();
- Data.NumGameItems = item.StorageIndex + 1;
- }
- d[name] = item;
- }
+ public Vertex3D Position { get => new Vertex3D(0, 0, 0); set { } }
+ public float RotationY { get => 0; set { } }
- private void AddItem(TItem item, ICollection d, bool updateStorageIndices) where TItem : IItem
- {
- if (updateStorageIndices) {
- item.StorageIndex = ItemDatas.Count();
- }
- d.Add(item);
- }
+ private readonly TableContainer _tableContainer;
+ private readonly TableMeshGenerator _meshGenerator;
- private Dictionary GetItemDictionary() where T : IItem
+ public Table(TableContainer tableContainer, TableData data) : base(data)
{
- if (typeof(T) == typeof(Bumper.Bumper)) {
- return _bumpers as Dictionary;
- }
- if (typeof(T) == typeof(DispReel.DispReel)) {
- return _dispReels as Dictionary;
- }
-
- if (typeof(T) == typeof(Flipper.Flipper)) {
- return _flippers as Dictionary;
- }
-
- if (typeof(T) == typeof(Gate.Gate)) {
- return _gates as Dictionary;
- }
-
- if (typeof(T) == typeof(HitTarget.HitTarget)) {
- return _hitTargets as Dictionary;
- }
-
- if (typeof(T) == typeof(Kicker.Kicker)) {
- return _kickers as Dictionary;
- }
-
- if (typeof(T) == typeof(Light.Light)) {
- return _lights as Dictionary;
- }
-
- if (typeof(T) == typeof(LightSeq.LightSeq)) {
- return _lightSeqs as Dictionary;
- }
-
- if (typeof(T) == typeof(Plunger.Plunger)) {
- return _plungers as Dictionary;
- }
-
- if (typeof(T) == typeof(Flasher.Flasher)) {
- return _flashers as Dictionary;
- }
-
- if (typeof(T) == typeof(Primitive.Primitive)) {
- return _primitives as Dictionary;
- }
-
- if (typeof(T) == typeof(Ramp.Ramp)) {
- return _ramps as Dictionary;
- }
-
- if (typeof(T) == typeof(Rubber.Rubber)) {
- return _rubbers as Dictionary;
- }
-
- if (typeof(T) == typeof(Spinner.Spinner)) {
- return _spinners as Dictionary;
- }
-
- if (typeof(T) == typeof(Surface.Surface)) {
- return _surfaces as Dictionary;
- }
-
- if (typeof(T) == typeof(TextBox.TextBox)) {
- return _textBoxes as Dictionary;
- }
-
- if (typeof(T) == typeof(Timer.Timer)) {
- return _timers as Dictionary;
- }
-
- if (typeof(T) == typeof(Trigger.Trigger)) {
- return _triggers as Dictionary;
- }
-
- if (typeof(T) == typeof(Trough.Trough)) {
- return _troughs as Dictionary;
- }
-
- return null;
- }
-
- private List GetItemList() {
- if (typeof(T) == typeof(Decal.Decal)) {
- return _decals as List;
- }
-
- return null;
+ _tableContainer = tableContainer;
+ _meshGenerator = new TableMeshGenerator(_tableContainer);
}
- #endregion
-
- ///
- /// Adds a game item to the table.
- ///
- /// Game item instance
- /// If set, re-computes the storage indices. Only needed when adding game items via the editor.
- /// Game item type
- /// Whe type of game item is unknown
- public void Add(T item, bool updateStorageIndices = false) where T : IItem
+ public float GetScaleZ()
{
- var dict = GetItemDictionary();
- if (dict != null) {
- AddItem(item.Name, item, dict, updateStorageIndices);
-
- } else {
- var list = GetItemList();
- if (list != null) {
- AddItem(item, list, updateStorageIndices);
-
- } else {
- throw new ArgumentException("Unknown item type " + typeof(T) + ".");
- }
- }
+ return Data.BgScaleZ?[Data.BgCurrentSet] ?? 1.0f;
}
- ///
- /// Replaces all game items of a list with new game items.
- ///
- ///
- ///
- /// This only applied to Decals, because they are the only game items
- /// that don't have a name.
- ///
- /// New list of game items
- /// Game item type (only Decals)
- /// If not decals
- public void ReplaceAll(IEnumerable items) where T : IItem
+ public float GetSurfaceHeight(string surfaceName, float x, float y)
{
- var list = GetItemList();
- if (list == null) {
- throw new ArgumentException("Cannot set all " + typeof(T) + "s (only Decals so far).");
+ if (string.IsNullOrEmpty(surfaceName)) {
+ return TableHeight;
}
- list.Clear();
- list.AddRange(items);
- }
- ///
- /// Checks whether a game item of a given type exists.
- ///
- /// Name of the game item
- /// Type of the game item
- /// True if the game item exists, false otherwise
- public bool Has(string name) where T : IItem => GetItemDictionary().ContainsKey(name);
-
- ///
- /// Returns all game items of a given type.
- ///
- /// Game item type
- /// All game items stored in the table
- /// If invalid game type
- public TItem[] GetAll() where TItem : IItem
- {
- var dict = GetItemDictionary();
- if (dict != null) {
- return dict.Values.ToArray();
+ if (_tableContainer.Has(surfaceName)) {
+ return TableHeight + _tableContainer.Get(surfaceName).Data.HeightTop;
}
- var list = GetItemList();
- if (list != null) {
- return list.ToArray();
- }
- throw new ArgumentException("Unknown item type " + typeof(TItem) + ".");
- }
-
- ///
- /// Computes a new name for a game item.
- ///
- /// Prefix
- /// Type of the game item
- /// New name, a concatenation of the prefix and the next free index
- public string GetNewName(string prefix) where T : IItem
- {
- var n = 0;
- var dict = GetItemDictionary();
- do {
- var elementName = $"{prefix}{++n}";
- if (!dict.ContainsKey(elementName)) {
- return elementName;
- }
- } while (true);
- }
- ///
- /// Removes a game item from the table.
- ///
- /// Name of the game item
- /// Type of the game item
- public void Remove(string name) where T : IItem
- {
- var dict = GetItemDictionary();
- if (!dict.ContainsKey(name)) {
- return;
- }
- var removedStorageIndex = dict[name].StorageIndex;
- var gameItems = ItemDatas;
- foreach (var gameItem in gameItems) {
- if (gameItem.StorageIndex > removedStorageIndex) {
- gameItem.StorageIndex--;
- }
+ if (_tableContainer.Has(surfaceName)) {
+ return TableHeight + _tableContainer.Get(surfaceName).GetSurfaceHeight(x, y, this);
}
- Data.NumGameItems = gameItems.Count() - 1;
- dict.Remove(name);
+ // Logger.Warn(
+ // "[Table.getSurfaceHeight] Unknown surface {0}.\nAvailable surfaces: [ {1} ]\nAvailable ramps: [ {2} ]",
+ // surfaceName,
+ // string.Join(", ", _surfaces.Keys),
+ // string.Join(", ", _ramps.Keys)
+ // );
+ return TableHeight;
}
- public TData[] GetAllData() where TItem : Item where TData : ItemData
+ public void SetupPlayfieldMesh()
{
- var dict = GetItemDictionary();
- if (dict != null) {
- return dict.Values.Select(d => d.Data).ToArray();
+ if (_tableContainer.Has("playfield_mesh")) {
+ _meshGenerator.SetFromPrimitive(_tableContainer.Get("playfield_mesh"));
+ _tableContainer.Remove("playfield_mesh");
}
- var list = GetItemList();
- if (list != null) {
- return list.Select(d => d.Data).ToArray();
- }
- throw new ArgumentException("Unknown item type " + typeof(TItem) + ".");
- }
-
- #region Table Info
- public string InfoAuthorEmail => TableInfo.ContainsKey("AuthorEmail") ? TableInfo["AuthorEmail"] : null;
- public string InfoAuthorName => TableInfo.ContainsKey("AuthorName") ? TableInfo["AuthorName"] : null;
- public string InfoAuthorWebsite => TableInfo.ContainsKey("AuthorWebSite") ? TableInfo["AuthorWebSite"] : null;
- public string InfoReleaseDate => TableInfo.ContainsKey("ReleaseDate") ? TableInfo["ReleaseDate"] : null;
- public string InfoBlurb => TableInfo.ContainsKey("TableBlurb") ? TableInfo["TableBlurb"] : null;
- public string InfoDescription => TableInfo.ContainsKey("TableDescription") ? TableInfo["TableDescription"] : null;
- public string InfoName => TableInfo.ContainsKey("TableName") ? TableInfo["TableName"] : null;
- public string InfoRules => TableInfo.ContainsKey("TableRules") ? TableInfo["TableRules"] : null;
- public string InfoVersion => TableInfo.ContainsKey("TableVersion") ? TableInfo["TableVersion"] : null;
-
- #endregion
-
- private readonly TableMeshGenerator _meshGenerator;
-
- ///
- /// The API to load the table from a file.
- ///
- /// Path to the VPX file
- /// If false, game items are not loaded. Useful when loading them on multiple threads.
- /// The parsed table
- public static Table Load(string filename, bool loadGameItems = true)
- {
- return TableLoader.Load(filename, loadGameItems);
}
- public Table(TableData data) : base(data)
+ public int GetDetailLevel()
{
- _meshGenerator = new TableMeshGenerator(this);
+ return 10; // TODO
}
- public Table(BinaryReader reader) : this(new TableData(reader)) { }
-
#region IRenderable
Matrix3D IRenderable.TransformationMatrix(Table table, Origin origin) => Matrix3D.Identity;
@@ -475,91 +110,13 @@ public RenderObjectGroup GetRenderObjects(Table table, Origin origin = Origin.Gl
#endregion
- public bool IsCollidable => true;
- public bool HasTrough => _troughs.Count > 0;
-
- public void Save(string fileName)
- {
- new TableWriter(this).WriteTable(fileName);
- Logger.Info("File successfully saved to {0}.", fileName);
- }
-
- public Material GetMaterial(string name)
- {
- if (Data.Materials == null || name == null) {
- return null;
- }
-
- // ReSharper disable once LoopCanBeConvertedToQuery
- foreach (var t in Data.Materials) {
- if (t.Name == name) {
- return t;
- }
- }
-
- return null;
- }
-
- public void SetTextureContainer(ITableResourceContainer container)
- {
- Textures = container;
- }
-
- public Texture GetTexture(string name)
- {
- var tex = name == null
- ? null
- : Textures[name.ToLower()];
- return tex;
- }
-
- public void SetSoundContainer(ITableResourceContainer container)
- {
- Sounds = container;
- }
-
- public float GetScaleZ()
- {
- return Data.BgScaleZ?[Data.BgCurrentSet] ?? 1.0f;
- }
-
- public void SetupPlayfieldMesh()
- {
- if (_primitives.ContainsKey("playfield_mesh")) {
- _meshGenerator.SetFromPrimitive(_primitives["playfield_mesh"]);
- _primitives.Remove("playfield_mesh");
- }
- }
-
- public float GetSurfaceHeight(string surfaceName, float x, float y)
- {
- if (string.IsNullOrEmpty(surfaceName)) {
- return TableHeight;
- }
-
- if (_surfaces.ContainsKey(surfaceName)) {
- return TableHeight + _surfaces[surfaceName].Data.HeightTop;
- }
-
- if (_ramps.ContainsKey(surfaceName)) {
- return TableHeight + _ramps[surfaceName].GetSurfaceHeight(x, y, this);
- }
-
- // Logger.Warn(
- // "[Table.getSurfaceHeight] Unknown surface {0}.\nAvailable surfaces: [ {1} ]\nAvailable ramps: [ {2} ]",
- // surfaceName,
- // string.Join(", ", _surfaces.Keys),
- // string.Join(", ", _ramps.Keys)
- // );
- return TableHeight;
- }
+ #region Container Shortcuts
- public int GetDetailLevel()
- {
- return 10; // TODO
- }
+ public Material GetMaterial(string name) => _tableContainer.GetMaterial(name);
+ public Texture GetTexture(string dataImage) => _tableContainer.GetTexture(dataImage);
+ public string GetNewName(string name) where T : IItem => _tableContainer.GetNewName(name);
- private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
+ #endregion
}
}
diff --git a/VisualPinball.Engine/VPT/Table/TableBuilder.cs b/VisualPinball.Engine/VPT/Table/TableBuilder.cs
index 814406a2a..917f89b34 100644
--- a/VisualPinball.Engine/VPT/Table/TableBuilder.cs
+++ b/VisualPinball.Engine/VPT/Table/TableBuilder.cs
@@ -19,7 +19,6 @@
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
@@ -29,16 +28,16 @@ public class TableBuilder
private static int _tableItem;
private int _gameItem = 0;
- private readonly Table _table = new Table(new TableData());
+ private readonly FileTableContainer _tableContainer = new FileTableContainer();
public TableBuilder()
{
- _table.Data.Name = $"Table${_tableItem++}";
+ _tableContainer.Table.Data.Name = $"Table${_tableItem++}";
}
public TableBuilder WithTableScript(string vbs)
{
- _table.Data.Code = vbs;
+ _tableContainer.Table.Data.Code = vbs;
return this;
}
@@ -49,25 +48,23 @@ public TableBuilder AddBumper(string name)
Center = new Vertex2D(500, 500)
};
- _table.Add(new Bumper.Bumper(data));
+ _tableContainer.Add(new Bumper.Bumper(data));
return this;
}
public TableBuilder AddMaterial(Material material)
{
- var mats = _table.Data.Materials.ToList();
+ var mats = _tableContainer.Table.Data.Materials.ToList();
mats.Add(material);
- _table.Data.Materials = mats.ToArray();
- _table.Data.NumMaterials = mats.Count;
+ _tableContainer.Table.Data.Materials = mats.ToArray();
+ _tableContainer.Table.Data.NumMaterials = mats.Count;
return this;
}
public TableBuilder AddTexture(string name)
{
- _table.Textures.Add(new Texture(name));
- _table.Data.NumTextures = _table.Textures.Count;
-
+ _tableContainer.Table.Data.NumTextures = _tableContainer.AddTexture(new Texture(name));
return this;
}
@@ -77,32 +74,32 @@ public TableBuilder AddFlipper(string name)
Name = name, Center = new Vertex2D(500, 500)
};
- _table.Add(new Flipper.Flipper(data));
+ _tableContainer.Add(new Flipper.Flipper(data));
return this;
}
public TableBuilder AddTrough(string name)
{
- var data = new TroughData($"GameItem{_gameItem++}") {
+ var data = new TroughData($"VpeGameItem{_gameItem++}") {
Name = name
};
- _table.Add(new Trough.Trough(data));
+ _tableContainer.Add(new Trough.Trough(data));
return this;
}
public TableBuilder AddLight(string name)
{
- _table.Add(new Light.Light(new LightData(name, 500, 500)));
+ _tableContainer.Add(new Light.Light(new LightData(name, 500, 500)));
return this;
}
- public Table Build(string name = null)
+ public FileTableContainer Build(string name = null)
{
if (name != null) {
- _table.Data.Name = name;
+ _tableContainer.Table.Data.Name = name;
}
- return _table;
+ return _tableContainer;
}
}
}
diff --git a/VisualPinball.Engine/VPT/Table/TableContainer.cs b/VisualPinball.Engine/VPT/Table/TableContainer.cs
new file mode 100644
index 000000000..15c0b05e6
--- /dev/null
+++ b/VisualPinball.Engine/VPT/Table/TableContainer.cs
@@ -0,0 +1,402 @@
+// 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 System;
+using System.Collections.Generic;
+using System.Linq;
+using NLog;
+using VisualPinball.Engine.Game;
+using VisualPinball.Engine.VPT.Collection;
+
+namespace VisualPinball.Engine.VPT.Table
+{
+ public abstract class TableContainer
+ {
+ public abstract Table Table { get; }
+ public abstract Dictionary TableInfo { get; }
+ public abstract List Collections { get; }
+ public abstract Mappings.Mappings Mappings { get; }
+ public abstract CustomInfoTags CustomInfoTags { get; }
+ public abstract IEnumerable Textures { get; }
+ public abstract IEnumerable Sounds { get; }
+
+ public abstract Material GetMaterial(string name);
+
+ ///
+ /// Returns a texture for a given name.
+ ///
+ ///
+ ///
+ /// This is mainly used by the mesh generators that create a material.
+ ///
+ ///
+ /// Name of the texture, case insensitive.
+ /// Texture or null.
+ public abstract Texture GetTexture(string name);
+
+ public int FileVersion { get; set; }
+ public byte[] FileHash { get; set; }
+
+ public bool HasTrough => _troughs.Count > 0;
+ public int NumTextures => Table.Data.NumTextures;
+ public int NumGameItems => Table.Data.NumGameItems;
+ public int NumSounds => Table.Data.NumSounds;
+ public int NumCollections => Table.Data.NumCollections;
+ public int NumVpeGameItems => Table.Data.NumVpeGameItems;
+
+ #region GameItems
+
+ protected readonly Dictionary _bumpers = new Dictionary();
+ protected readonly List _decals = new List();
+ protected readonly Dictionary _dispReels = new Dictionary();
+ protected readonly Dictionary _flashers = new Dictionary();
+ protected readonly Dictionary _flippers = new Dictionary();
+ protected readonly Dictionary _gates = new Dictionary();
+ protected readonly Dictionary _hitTargets = new Dictionary();
+ protected readonly Dictionary _kickers = new Dictionary();
+ protected readonly Dictionary _lights = new Dictionary();
+ protected readonly Dictionary _lightSeqs = new Dictionary();
+ protected readonly Dictionary _plungers = new Dictionary();
+ protected readonly Dictionary _primitives = new Dictionary();
+ protected readonly Dictionary _ramps = new Dictionary();
+ protected readonly Dictionary _rubbers = new Dictionary();
+ protected readonly Dictionary _spinners = new Dictionary();
+ protected readonly Dictionary _surfaces = new Dictionary();
+ protected readonly Dictionary _textBoxes = new Dictionary();
+ protected readonly Dictionary _timers = new Dictionary();
+ protected readonly Dictionary _triggers = new Dictionary();
+ protected readonly Dictionary _troughs = new Dictionary();
+
+ protected virtual void Clear()
+ {
+ _bumpers.Clear();
+ _decals.Clear();
+ _dispReels.Clear();
+ _flashers.Clear();
+ _flippers.Clear();
+ _gates.Clear();
+ _hitTargets.Clear();
+ _kickers.Clear();
+ _lights.Clear();
+ _lightSeqs.Clear();
+ _plungers.Clear();
+ _primitives.Clear();
+ _ramps.Clear();
+ _rubbers.Clear();
+ _spinners.Clear();
+ _surfaces.Clear();
+ _textBoxes.Clear();
+ _timers.Clear();
+ _triggers.Clear();
+ _troughs.Clear();
+ }
+
+ public Bumper.Bumper Bumper(string name) => _bumpers[name];
+ public Decal.Decal Decal(int i) => _decals[i];
+ public DispReel.DispReel DispReel(string name) => _dispReels[name];
+ public Flipper.Flipper Flipper(string name) => _flippers[name];
+ public Gate.Gate Gate(string name) => _gates[name];
+ public HitTarget.HitTarget HitTarget(string name) => _hitTargets[name];
+ public Kicker.Kicker Kicker(string name) => _kickers[name];
+ public Light.Light Light(string name) => _lights[name];
+ public LightSeq.LightSeq LightSeq(string name) => _lightSeqs[name];
+ public Plunger.Plunger Plunger(string name = null) => name == null ? _plungers.Values.FirstOrDefault() : _plungers[name];
+ public Flasher.Flasher Flasher(string name) => _flashers[name];
+ public Primitive.Primitive Primitive(string name) => _primitives[name];
+ public Ramp.Ramp Ramp(string name) => _ramps[name];
+ public Rubber.Rubber Rubber(string name) => _rubbers[name];
+ public Spinner.Spinner Spinner(string name) => _spinners[name];
+ public Surface.Surface Surface(string name) => _surfaces[name];
+ public TextBox.TextBox TextBox(string name) => _textBoxes[name];
+ public Timer.Timer Timer(string name) => _timers[name];
+ public Trigger.Trigger Trigger(string name) => _triggers[name];
+ public Trough.Trough Trough(string name) => _troughs[name];
+
+ public IEnumerable Renderables => new IRenderable[] { Table }
+ .Concat(_bumpers.Values)
+ .Concat(_flippers.Values)
+ .Concat(_gates.Values)
+ .Concat(_hitTargets.Values)
+ .Concat(_kickers.Values)
+ .Concat(_lights.Values)
+ .Concat(_plungers.Values)
+ .Concat(_primitives.Values)
+ .Concat(_ramps.Values)
+ .Concat(_rubbers.Values)
+ .Concat(_spinners.Values)
+ .Concat(_surfaces.Values)
+ .Concat(_triggers.Values);
+
+ ///
+ /// Game items that need to be converted but aren't rendered.
+ ///
+ public IEnumerable NonRenderables => new IItem[0]
+ .Concat(_troughs.Values);
+
+ public IEnumerable GameItems => new IItem[] { }
+ .Concat(_bumpers.Values)
+ .Concat(_decals.Select(i => i))
+ .Concat(_dispReels.Values)
+ .Concat(_flippers.Values)
+ .Concat(_flashers.Values)
+ .Concat(_gates.Values)
+ .Concat(_hitTargets.Values)
+ .Concat(_kickers.Values)
+ .Concat(_lights.Values)
+ .Concat(_lightSeqs.Values)
+ .Concat(_plungers.Values)
+ .Concat(_primitives.Values)
+ .Concat(_ramps.Values)
+ .Concat(_rubbers.Values)
+ .Concat(_spinners.Values)
+ .Concat(_surfaces.Values)
+ .Concat(_textBoxes.Values)
+ .Concat(_timers.Values)
+ .Concat(_triggers.Values)
+ .Concat(_troughs.Values);
+
+ public IEnumerable ItemDatas => new ItemData[] { }
+ .Concat(_bumpers.Values.Select(i => i.Data))
+ .Concat(_decals.Select(i => i.Data))
+ .Concat(_dispReels.Values.Select(i => i.Data))
+ .Concat(_flippers.Values.Select(i => i.Data))
+ .Concat(_flashers.Values.Select(i => i.Data))
+ .Concat(_gates.Values.Select(i => i.Data))
+ .Concat(_hitTargets.Values.Select(i => i.Data))
+ .Concat(_kickers.Values.Select(i => i.Data))
+ .Concat(_lights.Values.Select(i => i.Data))
+ .Concat(_lightSeqs.Values.Select(i => i.Data))
+ .Concat(_plungers.Values.Select(i => i.Data))
+ .Concat(_primitives.Values.Select(i => i.Data))
+ .Concat(_ramps.Values.Select(i => i.Data))
+ .Concat(_rubbers.Values.Select(i => i.Data))
+ .Concat(_spinners.Values.Select(i => i.Data))
+ .Concat(_surfaces.Values.Select(i => i.Data))
+ .Concat(_textBoxes.Values.Select(i => i.Data))
+ .Concat(_timers.Values.Select(i => i.Data))
+ .Concat(_triggers.Values.Select(i => i.Data));
+
+
+ public IEnumerable VpeItemDatas => new ItemData[] { }
+ .Concat(_troughs.Values.Select(i => i.Data));
+
+ public IEnumerable Switchables => new ISwitchable[0]
+ .Concat(_bumpers.Values)
+ .Concat(_flippers.Values)
+ .Concat(_gates.Values)
+ .Concat(_hitTargets.Values)
+ .Concat(_kickers.Values)
+ .Concat(_spinners.Values)
+ .Concat(_triggers.Values);
+
+ public IEnumerable SwitchableDevices => new ISwitchableDevice[0]
+ .Concat(_troughs.Values);
+
+ public IEnumerable Coilables => new ICoilable[0]
+ .Concat(_bumpers.Values)
+ .Concat(_flippers.Values)
+ .Concat(_kickers.Values);
+
+ public IEnumerable CoilableDevices => new ICoilableDevice[0]
+ .Concat(_troughs.Values)
+ .Concat(_plungers.Values);
+
+ public IEnumerable Lightables => new ILightable[0]
+ .Concat(_lights.Values)
+ .Concat(_flashers.Values);
+
+ protected Dictionary GetItemDictionary() where T : IItem
+ {
+ return GetItemDictionary(typeof(T));
+ }
+
+ protected Dictionary GetItemDictionary(Type t) where T : IItem
+ {
+ if (t == typeof(Bumper.Bumper)) {
+ return _bumpers as Dictionary;
+ }
+ if (t == typeof(DispReel.DispReel)) {
+ return _dispReels as Dictionary;
+ }
+
+ if (t == typeof(Flipper.Flipper)) {
+ return _flippers as Dictionary;
+ }
+
+ if (t == typeof(Gate.Gate)) {
+ return _gates as Dictionary;
+ }
+
+ if (t == typeof(HitTarget.HitTarget)) {
+ return _hitTargets as Dictionary;
+ }
+
+ if (t == typeof(Kicker.Kicker)) {
+ return _kickers as Dictionary;
+ }
+
+ if (t == typeof(Light.Light)) {
+ return _lights as Dictionary;
+ }
+
+ if (t == typeof(LightSeq.LightSeq)) {
+ return _lightSeqs as Dictionary;
+ }
+
+ if (t == typeof(Plunger.Plunger)) {
+ return _plungers as Dictionary;
+ }
+
+ if (t == typeof(Flasher.Flasher)) {
+ return _flashers as Dictionary;
+ }
+
+ if (t == typeof(Primitive.Primitive)) {
+ return _primitives as Dictionary;
+ }
+
+ if (t == typeof(Ramp.Ramp)) {
+ return _ramps as Dictionary;
+ }
+
+ if (t == typeof(Rubber.Rubber)) {
+ return _rubbers as Dictionary;
+ }
+
+ if (t == typeof(Spinner.Spinner)) {
+ return _spinners as Dictionary;
+ }
+
+ if (t == typeof(Surface.Surface)) {
+ return _surfaces as Dictionary;
+ }
+
+ if (t == typeof(TextBox.TextBox)) {
+ return _textBoxes as Dictionary;
+ }
+
+ if (t == typeof(Timer.Timer)) {
+ return _timers as Dictionary;
+ }
+
+ if (t == typeof(Trigger.Trigger)) {
+ return _triggers as Dictionary;
+ }
+
+ if (t == typeof(Trough.Trough)) {
+ return _troughs as Dictionary;
+ }
+
+ return null;
+ }
+
+ protected List GetItemList() {
+ if (typeof(T) == typeof(Decal.Decal)) {
+ return _decals as List;
+ }
+
+ return null;
+ }
+
+ #endregion
+
+ ///
+ /// Checks whether a game item of a given type exists.
+ ///
+ /// Name of the game item
+ /// Type of the game item
+ /// True if the game item exists, false otherwise
+ public bool Has(string name) where T : IItem => GetItemDictionary