diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5093920c6..7f16fd730 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@
Built with Unity 2021.2.
### Added
+- We got a new game item called *Metal Wire Guide* (thanks @Cupiii, [#366](https://github.com/freezy/VisualPinball.Engine/pull/366))
- A *Collision Switch* component ([#344](https://github.com/freezy/VisualPinball.Engine/pull/344), [Documentation](https://docs.visualpinball.org/creators-guide/manual/mechanisms/collision-switches.html)).
- A *Rotator* component ([#337](https://github.com/freezy/VisualPinball.Engine/pull/337), [Documentation](https://docs.visualpinball.org/creators-guide/manual/mechanisms/rotators.html)).
- A *Teleporter* component ([#336](https://github.com/freezy/VisualPinball.Engine/pull/336), [Documentation](https://docs.visualpinball.org/creators-guide/manual/mechanisms/teleporters.html)).
diff --git a/VisualPinball.Engine.Test/Fixtures~/MetalWireGuideTest.vpx b/VisualPinball.Engine.Test/Fixtures~/MetalWireGuideTest.vpx
new file mode 100644
index 000000000..3b0863c5a
Binary files /dev/null and b/VisualPinball.Engine.Test/Fixtures~/MetalWireGuideTest.vpx differ
diff --git a/VisualPinball.Engine.Test/Test/Fixtures.cs b/VisualPinball.Engine.Test/Test/Fixtures.cs
index c8d84c947..db138eccd 100644
--- a/VisualPinball.Engine.Test/Test/Fixtures.cs
+++ b/VisualPinball.Engine.Test/Test/Fixtures.cs
@@ -53,6 +53,7 @@ public static class VpxPath
public static readonly string Timer = PathHelper.GetFixturePath("TimerTest.vpx");
public static readonly string Trigger = PathHelper.GetFixturePath("TriggerTest.vpx");
public static readonly string Trough = PathHelper.GetFixturePath("TroughTest.vpx");
+ public static readonly string MetalWireGuide = PathHelper.GetFixturePath("MetalWireGuideTest.vpx");
}
public static class ObjPath
@@ -79,6 +80,7 @@ public static class ObjPath
public static readonly string Surface = PathHelper.GetFixturePath("SurfaceTest.obj");
public static readonly string Table = PathHelper.GetFixturePath("TableTest.obj");
public static readonly string Trigger = PathHelper.GetFixturePath("TriggerTest.obj");
+ public static readonly string MetalWireGuide = PathHelper.GetFixturePath("MetalWireGuideTest.obj");
}
public static class TexturePath
diff --git a/VisualPinball.Engine.Test/VPT/MetalWireGuide/MetalWireDataTests.cs b/VisualPinball.Engine.Test/VPT/MetalWireGuide/MetalWireDataTests.cs
new file mode 100644
index 000000000..6550c0eb5
--- /dev/null
+++ b/VisualPinball.Engine.Test/VPT/MetalWireGuide/MetalWireDataTests.cs
@@ -0,0 +1,103 @@
+// 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.IO;
+using FluentAssertions;
+using NUnit.Framework;
+using VisualPinball.Engine.Test.Test;
+using VisualPinball.Engine.VPT.MetalWireGuide;
+using VisualPinball.Engine.VPT.Table;
+
+namespace VisualPinball.Engine.Test.VPT.MetalWireGuide
+{
+ public class MetalWireGuideDataTests
+ {
+ [Test]
+ public void ShouldReadMetalWireGuideData()
+ {
+ var table = FileTableContainer.Load(VpxPath.MetalWireGuide);
+ ValidateMetalWireGuideData1(table.MetalWireGuide("MetalWireGuide1").Data);
+ ValidateMetalWireGuideData2(table.MetalWireGuide("MetalWireGuide2").Data);
+ }
+
+ [Test]
+ public void ShouldWriteMetalWireGuideData()
+ {
+ const string tmpFileName = "ShouldWriteMetalWireGuideData.vpx";
+ var table = FileTableContainer.Load(VpxPath.MetalWireGuide);
+ table.Save(tmpFileName);
+ var writtenTable = FileTableContainer.Load(tmpFileName);
+ ValidateMetalWireGuideData1(writtenTable.MetalWireGuide("MetalWireGuide1").Data);
+ ValidateMetalWireGuideData2(writtenTable.MetalWireGuide("MetalWireGuide2").Data);
+ File.Delete(tmpFileName);
+ }
+
+ public static void ValidateMetalWireGuideData1(MetalWireGuideData data)
+ {
+ data.DragPoints.Length.Should().Be(3);
+ /* Todo: Test :-)
+ data.Elasticity.Should().Be(0.832f);
+ data.ElasticityFalloff.Should().Be(0.321f);
+ data.Friction.Should().Be(0.685f);
+ data.Height.Should().Be(25.556f);
+ data.HitEvent.Should().Be(false);
+ data.HitHeight.Should().Be(25.193f);
+ data.Image.Should().Be("test_pattern");
+ data.IsCollidable.Should().Be(true);
+ data.IsReflectionEnabled.Should().Be(true);
+ data.IsVisible.Should().Be(true);
+ data.Material.Should().Be("Playfield");
+ data.OverwritePhysics.Should().Be(true);
+ data.PhysicsMaterial.Should().Be("");
+ data.RotX.Should().Be(65.23f);
+ data.RotY.Should().Be(75.273f);
+ data.RotZ.Should().Be(70.962f);
+ data.Scatter.Should().Be(5.225f);
+ data.ShowInEditor.Should().Be(false);
+ data.StaticRendering.Should().Be(true);
+ data.Thickness.Should().Be(12);
+ data.Points.Should().Be(true);
+ */
+ }
+
+ public static void ValidateMetalWireGuideData2(MetalWireGuideData data)
+ {
+ data.DragPoints.Length.Should().Be(2);
+ /* Todo Tests... :-)
+ data.Elasticity.Should().Be(0.8f);
+ data.ElasticityFalloff.Should().Be(0.3f);
+ data.Friction.Should().Be(0.6f);
+ data.Height.Should().Be(25f);
+ data.HitEvent.Should().Be(false);
+ data.HitHeight.Should().Be(25f);
+ data.Image.Should().Be("");
+ data.IsCollidable.Should().Be(false);
+ data.IsReflectionEnabled.Should().Be(true);
+ data.IsVisible.Should().Be(true);
+ data.Material.Should().Be("");
+ data.OverwritePhysics.Should().Be(true);
+ data.PhysicsMaterial.Should().Be("");
+ data.RotX.Should().Be(0f);
+ data.RotY.Should().Be(0f);
+ data.RotZ.Should().Be(0f);
+ data.Scatter.Should().Be(5f);
+ data.ShowInEditor.Should().Be(false);
+ data.StaticRendering.Should().Be(false);
+ data.Thickness.Should().Be(8);
+ */
+ }
+ }
+}
diff --git a/VisualPinball.Engine.Test/VPT/MetalWireGuide/MetalWireMeshTest.cs b/VisualPinball.Engine.Test/VPT/MetalWireGuide/MetalWireMeshTest.cs
new file mode 100644
index 000000000..f02928d1d
--- /dev/null
+++ b/VisualPinball.Engine.Test/VPT/MetalWireGuide/MetalWireMeshTest.cs
@@ -0,0 +1,49 @@
+// 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 JeremyAnsel.Media.WavefrontObj;
+using NUnit.Framework;
+using VisualPinball.Engine.Test.Test;
+using VisualPinball.Engine.VPT.Table;
+
+namespace VisualPinball.Engine.Test.VPT.MetalWireGuide
+{
+ public class MetalWireGuideMeshTest : MeshTests
+ {
+ private readonly FileTableContainer _tc;
+ private readonly ObjFile _obj;
+
+ public MetalWireGuideMeshTest()
+ {
+ _tc = FileTableContainer.Load(VpxPath.MetalWireGuide);
+ _obj = LoadObjFixture(ObjPath.MetalWireGuide);
+ }
+
+ //[Test] todo fix (and change for MetalWireGuide)
+ //public void ShouldGenerateMesh()
+ //{
+ // var rubberMesh = _tc.Rubber("Rubber2").GetRenderObjects(_tc.Table).RenderObjects[0].Mesh;
+ // AssertObjMesh(_obj, rubberMesh, threshold: 0.00015f);
+ //}
+
+ // [Test] todo fix (and change for MetalWireGuide)
+ //public void ShouldGenerateThickMesh()
+ //{
+ // var rubberMesh = _tc.Rubber("Rubber1").GetRenderObjects(_tc.Table).RenderObjects[0].Mesh;
+ // AssertObjMesh(_obj, rubberMesh, threshold: 0.001f);
+ //}
+ }
+}
diff --git a/VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj b/VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj
index 7ff303131..4b7be23a6 100644
--- a/VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj
+++ b/VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj
@@ -5,7 +5,7 @@
true
VisualPinball.Engine.Test
A .NET port of Visual Pinball in C#
- freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz;Pandeli
+ freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz;Pandeli;Cupid
Copyright 2021 freezy - <freezy@vpdb.io>
0.1.0.0
0.1.0.0
diff --git a/VisualPinball.Engine/Math/SplineVertex.cs b/VisualPinball.Engine/Math/SplineVertex.cs
index a098fd5fb..0ba292219 100644
--- a/VisualPinball.Engine/Math/SplineVertex.cs
+++ b/VisualPinball.Engine/Math/SplineVertex.cs
@@ -39,19 +39,31 @@ public class SplineVertex
public Vertex2D[] RgvLocal;
- public SplineVertex(DragPointData[] dragPoints, int thickness, int tableDetailLevel, float accuracy, bool staticRendering = true, float margin = 0f)
+ public SplineVertex(DragPointData[] dragPoints, int thickness, int tableDetailLevel, float accuracy, bool staticRendering = true, float margin = 0f, bool loop = true)
{
- var vertices = GetCentralCurve(dragPoints, tableDetailLevel, accuracy, staticRendering);
+ var vertices = GetCentralCurve(dragPoints, tableDetailLevel, accuracy, staticRendering, loop: loop);
var numVertices = vertices.Length;
Cross = new bool[numVertices + 1];
MiddlePoints = new Vertex2D[numVertices + 1];
RgvLocal = new Vertex2D[(numVertices + 1) * 2];
- for (var i = 0; i < numVertices; i++) {
- // prev and next wrap around as rubbers always loop
+ for (var i = 0; i < numVertices; i++)
+ {
+ // prev and next wrap around in loops
var prev = vertices[i > 0 ? i - 1 : numVertices - 1];
var next = vertices[i < numVertices - 1 ? i + 1 : 0];
+
+ // .. but have to be corrected at start and end with "virtual vertices" continuing the spline when not looping, so cuts perpendicular to the tangents
+ // maybe fix ramps after that that also hat the same problem.
+ if (!loop && i == 0) {
+ prev = new RenderVertex2D(vertices[0].X*2-vertices[1].X, vertices[0].Y * 2 - vertices[1].Y);
+ }
+ if (!loop && i == (numVertices-1))
+ {
+ next = new RenderVertex2D(vertices[numVertices-1].X * 2 - vertices[numVertices - 2].X, vertices[numVertices - 1].Y * 2 - vertices[numVertices - 2].Y);
+ }
+
var middle = vertices[i];
Cross[i] = middle.IsControlPoint;
@@ -63,12 +75,13 @@ public SplineVertex(DragPointData[] dragPoints, int thickness, int tableDetailLe
var normal1 = new Vertex2D(prev.Y - middle.Y, middle.X - prev.X); // vector vmiddle-vprev rotated RIGHT
var normal2 = new Vertex2D(middle.Y - next.Y, next.X - middle.X); // vector vnext-vmiddle rotated RIGHT
- // not needed special start/end handling as rubbers always loop, except for the case where there are only 2 control points
- if (numVertices == 2 && i == numVertices - 1) {
+ // not needed special start/end handling as rubbers always loop, except for the case where there are only 2 control points
+ // I guess this does not work as intended, but could not figure out what was wrong. i think that somehow the normal of Node 1 is wrong. /cupiii
+ if (numVertices == 2 && i == numVertices - 1) {
normal1.Normalize();
normal = normal1;
- } else if (numVertices == 2 && i == 0) {
+ } else if (numVertices == 2 && i == 0) {
normal2.Normalize();
normal = normal2;
@@ -121,12 +134,17 @@ public SplineVertex(DragPointData[] dragPoints, int thickness, int tableDetailLe
}
}
- Cross[numVertices] = vertices[0].IsControlPoint;
- MiddlePoints[numVertices] = MiddlePoints[0];
- VertexCount = numVertices + 1;
+ if (loop)
+ VertexCount = numVertices;
+ else
+ {
+ MiddlePoints[numVertices] = MiddlePoints[0];
+ Cross[numVertices] = vertices[0].IsControlPoint;
+ VertexCount = numVertices + 1;
+ }
}
- private static RenderVertex2D[] GetCentralCurve(DragPointData[] dragPoints, int tableDetailLevel, float acc, bool staticRendering = true)
+ private static RenderVertex2D[] GetCentralCurve(DragPointData[] dragPoints, int tableDetailLevel, float acc, bool staticRendering = true, bool loop = true)
{
float accuracy;
@@ -141,7 +159,7 @@ private static RenderVertex2D[] GetCentralCurve(DragPointData[] dragPoints, int
accuracy = 4.0f * MathF.Pow(10.0f, (10.0f - accuracy) * (float) (1.0 / 1.5));
}
- return DragPoint.GetRgVertex(dragPoints, true, accuracy);
+ return DragPoint.GetRgVertex(dragPoints, loop, accuracy);
}
}
}
diff --git a/VisualPinball.Engine/VPT/ItemType.cs b/VisualPinball.Engine/VPT/ItemType.cs
index a0d8cc706..b81a144e2 100644
--- a/VisualPinball.Engine/VPT/ItemType.cs
+++ b/VisualPinball.Engine/VPT/ItemType.cs
@@ -50,6 +50,7 @@ public enum ItemType
Rubber = 21,
HitTarget = 22,
Count = 23,
+ MetalWireGuide = 24,
Invalid = -1,
// VPE internal
diff --git a/VisualPinball.Engine/VPT/MetalWireGuide.meta b/VisualPinball.Engine/VPT/MetalWireGuide.meta
new file mode 100644
index 000000000..03d3286dc
--- /dev/null
+++ b/VisualPinball.Engine/VPT/MetalWireGuide.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: d2b47637016044e449395b9302c7a858
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Engine/VPT/MetalWireGuide/IMetalWireGuideData.cs b/VisualPinball.Engine/VPT/MetalWireGuide/IMetalWireGuideData.cs
new file mode 100644
index 000000000..f442bfc82
--- /dev/null
+++ b/VisualPinball.Engine/VPT/MetalWireGuide/IMetalWireGuideData.cs
@@ -0,0 +1,31 @@
+// Visual Pinball Engine
+// Copyright (C) 2020 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 VisualPinball.Engine.Math;
+
+namespace VisualPinball.Engine.VPT.MetalWireGuide
+{
+ public interface IMetalWireGuideData
+ {
+ DragPointData[] DragPoints { get; }
+ int Thickness { get; }
+ float Height { get; }
+ float Bendradius { get; }
+ float RotX { get; }
+ float RotY { get; }
+ float RotZ { get; }
+ }
+}
diff --git a/VisualPinball.Engine/VPT/MetalWireGuide/IMetalWireGuideData.cs.meta b/VisualPinball.Engine/VPT/MetalWireGuide/IMetalWireGuideData.cs.meta
new file mode 100644
index 000000000..852a6c96a
--- /dev/null
+++ b/VisualPinball.Engine/VPT/MetalWireGuide/IMetalWireGuideData.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c04bd7143df8951498caba013fd1002c
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Engine/VPT/MetalWireGuide/MetalWireGuide.cs b/VisualPinball.Engine/VPT/MetalWireGuide/MetalWireGuide.cs
new file mode 100644
index 000000000..068f9c05a
--- /dev/null
+++ b/VisualPinball.Engine/VPT/MetalWireGuide/MetalWireGuide.cs
@@ -0,0 +1,69 @@
+// 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.IO;
+using VisualPinball.Engine.Game;
+using VisualPinball.Engine.Math;
+
+namespace VisualPinball.Engine.VPT.MetalWireGuide
+{
+ public class MetalWireGuide : Item, IRenderable
+ {
+ public override string ItemGroupName => "MetalWireGuides";
+
+ public readonly MetalWireGuideMeshGenerator MeshGenerator;
+
+ public MetalWireGuide(MetalWireGuideData data) : base(data)
+ {
+ MeshGenerator = new MetalWireGuideMeshGenerator(Data);
+ }
+
+ public MetalWireGuide(BinaryReader reader, string itemName) : this(new MetalWireGuideData(reader, itemName))
+ {
+ }
+
+ public static MetalWireGuide GetDefault(Table.Table table)
+ {
+ var x = table.Width / 2f;
+ var y = table.Height / 2f;
+ var metalWireGuideData = new MetalWireGuideData(table.GetNewName("MetalWireGuide")) {
+ DragPoints = new[] {
+ new DragPointData(x, y - 100f) {IsSmooth = true },
+ new DragPointData(x - 50f * MathF.Cos(MathF.PI / 4), y - 50f * MathF.Sin(MathF.PI / 4)) {IsSmooth = true },
+ new DragPointData(x - 50f, y) {IsSmooth = true },
+ new DragPointData(x - 50f * MathF.Cos(MathF.PI / 4), y + 50f * MathF.Sin(MathF.PI / 4)) {IsSmooth = true },
+ new DragPointData(x, y + 50f) {IsSmooth = true },
+ new DragPointData(x + 50f * MathF.Cos(MathF.PI / 4), y + 50f * MathF.Sin(MathF.PI / 4)) {IsSmooth = true },
+ new DragPointData(x + 50f, y) {IsSmooth = true },
+ new DragPointData(x + 50f * MathF.Cos(MathF.PI / 4), y - 50f * MathF.Sin(MathF.PI / 4)) {IsSmooth = true },
+ }
+ };
+ return new MetalWireGuide(metalWireGuideData);
+ }
+
+ #region IRenderable
+
+ Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => Matrix3D.Identity;
+ public Mesh GetMesh(string id, Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true)
+ {
+ return MeshGenerator.GetMesh(table, Data);
+ }
+
+ public PbrMaterial GetMaterial(string id, Table.Table table) => MeshGenerator.GetMaterial(table, Data);
+
+ #endregion
+ }
+}
diff --git a/VisualPinball.Engine/VPT/MetalWireGuide/MetalWireGuide.cs.meta b/VisualPinball.Engine/VPT/MetalWireGuide/MetalWireGuide.cs.meta
new file mode 100644
index 000000000..59e05327e
--- /dev/null
+++ b/VisualPinball.Engine/VPT/MetalWireGuide/MetalWireGuide.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2465aad86669bea46bd07c503813aea7
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Engine/VPT/MetalWireGuide/MetalWireGuideData.cs b/VisualPinball.Engine/VPT/MetalWireGuide/MetalWireGuideData.cs
new file mode 100644
index 000000000..1618a898b
--- /dev/null
+++ b/VisualPinball.Engine/VPT/MetalWireGuide/MetalWireGuideData.cs
@@ -0,0 +1,149 @@
+// 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 .
+
+#region ReSharper
+// ReSharper disable UnassignedField.Global
+// ReSharper disable StringLiteralTypo
+// ReSharper disable FieldCanBeMadeReadOnly.Global
+// ReSharper disable ConvertToConstant.Global
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using VisualPinball.Engine.IO;
+using VisualPinball.Engine.Math;
+using VisualPinball.Engine.VPT.Table;
+
+namespace VisualPinball.Engine.VPT.MetalWireGuide
+{
+ [Serializable]
+ public class MetalWireGuideData : ItemData, IMetalWireGuideData
+ {
+ public override string GetName() => Name;
+ public override void SetName(string name) { Name = name; }
+
+ [BiffString("NAME", IsWideString = true, Pos = 8)]
+ public string Name = string.Empty;
+
+ [BiffFloat("HTTP", Pos = 1)]
+ public float Height { get; set; } = 25f;
+
+ [BiffFloat("HTHI", Pos = 2)]
+ public float HitHeight { get; set; } = 25f;
+
+ [BiffInt("WDTP", Pos = 3)]
+ public int Thickness { get; set; } = 8;
+
+ [BiffFloat("HTRD", Pos = 22)]
+ public float Bendradius { get; set; } = 8f;
+
+ [BiffBool("HTEV", Pos = 4)]
+ public bool HitEvent = false;
+
+ [BiffString("MATR", Pos = 5)]
+ public string Material = string.Empty;
+
+ [BiffString("IMAG", Pos = 9)]
+ public string Image = string.Empty;
+
+ [BiffFloat("ELAS", Pos = 10)]
+ public float Elasticity;
+
+ [BiffFloat("ELFO", Pos = 11)]
+ public float ElasticityFalloff;
+
+ [BiffFloat("RFCT", Pos = 12)]
+ public float Friction;
+
+ [BiffFloat("RSCT", Pos = 13)]
+ public float Scatter;
+
+ [BiffBool("CLDR", Pos = 14)]
+ public bool IsCollidable = true;
+
+ [BiffBool("RVIS", Pos = 15)]
+ public bool IsVisible = true;
+
+ [BiffBool("REEN", Pos = 21)]
+ public bool IsReflectionEnabled = true;
+
+ [BiffBool("ESTR", Pos = 16)]
+ public bool StaticRendering = true;
+
+ [BiffBool("ESIE", Pos = 17)]
+ public bool ShowInEditor = true;
+
+ [BiffFloat("ROTX", Pos = 18)]
+ public float RotX { get; set; } = 0f;
+
+ [BiffFloat("ROTY", Pos = 19)]
+ public float RotY { get; set; } = 0f;
+
+ [BiffFloat("ROTZ", Pos = 20)]
+ public float RotZ { get; set; } = 0f;
+
+ [BiffString("MAPH", Pos = 22)]
+ public string PhysicsMaterial = string.Empty;
+
+ [BiffBool("OVPH", Pos = 23)]
+ public bool OverwritePhysics = false;
+
+ [BiffDragPoint("DPNT", TagAll = true, Pos = 2000)]
+ public DragPointData[] DragPoints { get; set; }
+
+ [BiffBool("TMON", Pos = 6)]
+ public bool IsTimerEnabled;
+
+ [BiffInt("TMIN", Pos = 7)]
+ public int TimerInterval;
+
+ [BiffTag("PNTS", Pos = 1999)]
+ public bool Points;
+
+ public MetalWireGuideData() : base(StoragePrefix.GameItem)
+ {
+ }
+
+ public MetalWireGuideData(string name) : base(StoragePrefix.GameItem)
+ {
+ Name = name;
+ }
+
+ #region BIFF
+
+ static MetalWireGuideData()
+ {
+ Init(typeof(MetalWireGuideData), Attributes);
+ }
+
+ public MetalWireGuideData(BinaryReader reader, string storageName) : base(storageName)
+ {
+ Load(this, reader, Attributes);
+ }
+
+ public override void Write(BinaryWriter writer, HashWriter hashWriter)
+ {
+ writer.Write((int)ItemType.MetalWireGuide);
+ WriteRecord(writer, Attributes, hashWriter);
+ WriteEnd(writer, hashWriter);
+ }
+
+ private static readonly Dictionary> Attributes = new Dictionary>();
+
+ #endregion
+ }
+}
diff --git a/VisualPinball.Engine/VPT/MetalWireGuide/MetalWireGuideData.cs.meta b/VisualPinball.Engine/VPT/MetalWireGuide/MetalWireGuideData.cs.meta
new file mode 100644
index 000000000..fd529d5a8
--- /dev/null
+++ b/VisualPinball.Engine/VPT/MetalWireGuide/MetalWireGuideData.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 41d6cb564dddd52499250e5a44a02176
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Engine/VPT/MetalWireGuide/MetalWireGuideMeshGenerator.cs b/VisualPinball.Engine/VPT/MetalWireGuide/MetalWireGuideMeshGenerator.cs
new file mode 100644
index 000000000..62ca3ad69
--- /dev/null
+++ b/VisualPinball.Engine/VPT/MetalWireGuide/MetalWireGuideMeshGenerator.cs
@@ -0,0 +1,237 @@
+// 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 .
+
+// ReSharper disable CompareOfFloatsByEqualityOperator
+
+#nullable enable
+
+using VisualPinball.Engine.Common;
+using VisualPinball.Engine.Game;
+using VisualPinball.Engine.Math;
+
+namespace VisualPinball.Engine.VPT.MetalWireGuide
+{
+ public class MetalWireGuideMeshGenerator
+ {
+ private readonly IMetalWireGuideData _data;
+
+ private Vertex3D _middlePoint;
+
+ public MetalWireGuideMeshGenerator(IMetalWireGuideData data)
+ {
+ _data = data;
+ }
+
+ public Mesh GetTransformedMesh(float playfieldHeight, float meshHeight, int detailLevel, float bendradius, int acc = -1, bool createHitShape = false, float margin = 0f)
+ {
+ var mesh = GetMesh(playfieldHeight, meshHeight, detailLevel, bendradius, acc, createHitShape, margin);
+ return mesh.Transform(GetRotationMatrix());
+ }
+
+ public Mesh GetMesh(Table.Table table, MetalWireGuideData metalWireGuideData)
+ {
+ var mesh = GetTransformedMesh(table.TableHeight, _data.Height, table.GetDetailLevel(), _data.Bendradius);
+ mesh.Name = metalWireGuideData.Name;
+ var preMatrix = new Matrix3D();
+ preMatrix.SetTranslation(0, 0, -_data.Height);
+ return mesh.Transform(preMatrix);
+ }
+
+ public PbrMaterial GetMaterial(Table.Table table, MetalWireGuideData metalWireGuideData)
+ {
+ return new PbrMaterial(table.GetMaterial(metalWireGuideData.Material), table.GetTexture(metalWireGuideData.Image));
+ }
+
+ private Matrix3D GetRotationMatrix()
+ {
+ var fullMatrix = new Matrix3D();
+ var tempMat = new Matrix3D();
+
+ tempMat.SetTranslation(-_middlePoint.X, -_middlePoint.Y, -_middlePoint.Z);
+ fullMatrix.Multiply(tempMat, fullMatrix);
+
+ tempMat.RotateZMatrix(MathF.DegToRad(_data.RotZ));
+ fullMatrix.Multiply(tempMat);
+ tempMat.RotateYMatrix(MathF.DegToRad(_data.RotY));
+ fullMatrix.Multiply(tempMat);
+ tempMat.RotateXMatrix(MathF.DegToRad(_data.RotX));
+ fullMatrix.Multiply(tempMat);
+
+ tempMat.SetTranslation(_middlePoint.X, _middlePoint.Y, _middlePoint.Z);
+ fullMatrix.Multiply(tempMat);
+
+ return fullMatrix;
+ }
+
+ private Mesh GetMesh(float playfieldHeight, float meshHeight, int detailLevel, float bendradius, int acc = -1, bool createHitShape = false, float margin = 0f)
+ {
+ var mesh = new Mesh();
+ // i dont understand the calculation of splineaccuracy here /cupiii
+ var accuracy = (int)(10.0f * 1.2f);
+ if (acc != -1) { // hit shapes and UI display have the same, static, precision
+ accuracy = acc;
+ }
+
+ var splineAccuracy = acc != -1 ? 4.0f * MathF.Pow(10.0f, (10.0f - PhysicsConstants.HitShapeDetailLevel) * (float)(1.0 / 1.5)) : -1.0f;
+ SplineVertex sv = new SplineVertex(_data.DragPoints, _data.Thickness, detailLevel, splineAccuracy, margin: margin, loop: false);
+
+ var height = playfieldHeight + meshHeight;
+ // hack - Component has to get edited. --- and TODO: Thickness should become a float.
+ var standheight = 50;
+
+ // one ring for each Splinevertex, two for the stands, and "bendradius" tomes two for the bend (should be enough)
+ // todo: could be better, if accuracy was taken into account
+ var numRingsInBend = (int)(bendradius + 1);
+ var numRings = sv.VertexCount-1 + numRingsInBend * 2 + 2;
+ var numSegments = accuracy;
+
+ var up = new Vertex3D(0f, 0f, 1f);
+ var points = new Vertex3D[numRings]; // middlepoints of rings
+ var tangents = new Vertex3D[numRings]; // pointing into the direction of the spline, even first and last
+ var right = new Vertex3D[numRings]; // pointing right, looking into tangent direction
+ var down = new Vertex3D[numRings]; // pointing down from tangent view
+ var accLength = new float[numRings]; // accumulated length of the wire beginning at 0;
+
+ // copy the data from the pline into the middle of the new variables
+ for (int i = 0; i < sv.VertexCount-1; i++)
+ {
+ points[i + numRingsInBend + 1] = new Vertex3D(sv.MiddlePoints[i].X, sv.MiddlePoints[i].Y, height);
+ right[i + numRingsInBend + 1] = new Vertex3D(sv.RgvLocal[i].X - sv.MiddlePoints[i].X, sv.RgvLocal[i].Y - sv.MiddlePoints[i].Y, 0f);
+ right[i + numRingsInBend + 1].Normalize();
+ tangents[i + numRingsInBend + 1] = Vertex3D.CrossProduct(right[i + numRingsInBend + 1], new Vertex3D(0f, 0f, 1f));
+ tangents[i + numRingsInBend + 1].Normalize();
+ }
+
+ // first set up beginning of the stand
+ points[0] = points[numRingsInBend + 1] + tangents[numRingsInBend + 1] * bendradius * -1 + up * standheight * -1f;
+ tangents[0] = new Vertex3D(0f, 0f, 1f);
+ right[0] = right[numRingsInBend+1];
+ // set up the first point of the bend
+ points[1] = points[numRingsInBend + 1] + tangents[numRingsInBend + 1] * bendradius * -1 + up * bendradius * -1f;
+ tangents[1] = tangents[0];
+ right[1] = right[0];
+ // now bend from point 1 to numRingsInBend+1(-1)
+ var diffXY = points[numRingsInBend + 1] - points[1];
+ diffXY.Z = 0;
+ var diffZ = points[numRingsInBend + 1] - points[1];
+ diffZ.X = 0;
+ diffZ.Y = 0;
+ for (int i = 1; i < (numRingsInBend+1); i++)
+ {
+
+ points[numRingsInBend - i + 1] = points[1] + diffXY - (float)System.Math.Sin(System.Math.PI / 2 / numRingsInBend * i) * diffXY + (float)System.Math.Cos(System.Math.PI / 2 / numRingsInBend * i) * diffZ;
+ var tmp = tangents[numRingsInBend + 1];
+ tmp.Normalize();
+ tangents[numRingsInBend - i + 1] = tmp * (float)System.Math.Cos(System.Math.PI / 2 / numRingsInBend * i) + (float)System.Math.Sin(System.Math.PI / 2 / numRingsInBend * i) * up;
+ right[numRingsInBend - i + 1] = right[0];
+ }
+ // set up last point
+ points[numRings-1] = points[(numRings - 1) - numRingsInBend - 1] + tangents[numRings - 1 - numRingsInBend - 1] * bendradius + up * standheight * -1f;
+ tangents[numRings-1] = new Vertex3D(0f, 0f, -1f);
+ right[numRings - 1] = right[(numRings - 1) - numRingsInBend - 1];
+ // and the point before
+ points[numRings-2] = points[(numRings - 1) - numRingsInBend - 1] + tangents[numRings - 1 - numRingsInBend - 1] * bendradius + up * bendradius * -1f;
+ tangents[numRings - 2] = tangents[numRings - 1];
+ right[numRings - 2] = right[numRings - 1];
+ // now bend again
+ diffXY = points[numRings - 1 - numRingsInBend - 1] - points[numRings-2];
+ diffXY.Z = 0;
+ diffZ = points[numRings - 1 - numRingsInBend - 1] - points[numRings - 2];
+ diffZ.X = 0;
+ diffZ.Y = 0;
+ for (int i = 1; i < (numRingsInBend + 1); i++)
+ {
+
+ points[numRings - 2 - numRingsInBend + i] = points[numRings - 2] + diffXY - (float)System.Math.Sin(System.Math.PI / 2 / numRingsInBend * i) * diffXY + (float)System.Math.Cos(System.Math.PI / 2 / numRingsInBend * i) * diffZ;
+ var tmp = tangents[numRings - 1 - numRingsInBend - 1];
+ tmp.Normalize();
+ tangents[numRings - 2 - numRingsInBend + i] = tmp * (float)System.Math.Cos(System.Math.PI / 2 / numRingsInBend * i) + (float)System.Math.Sin(System.Math.PI / 2 / numRingsInBend * i) * up*-1;
+ right[numRings - 2 - numRingsInBend + i] = right[numRings-1];
+ }
+
+ // calculate downvectors
+ for (int i = 0; i < numRings; i++)
+ {
+ down[i] = Vertex3D.CrossProduct(right[i], tangents[i]);
+ down[i].Normalize();
+ }
+
+ // For UV calculation we need the whole length of the wire
+ accLength[0] = 0.0f;
+ for (int i = 1; i < numRings; i++)
+ accLength[i] = accLength[i - 1] + (points[i]-points[i-1]).Length();
+ var totalLength = accLength[numRings-1];
+
+ var numVertices = numRings * numSegments;
+ var numIndices = (numRings-1) * numSegments * 6;
+ mesh.Vertices = new Vertex3DNoTex2[numVertices];
+ mesh.Indices = new int[numIndices];
+
+ // precalculate the rings (positive X is left, positive Y is up) Starting at the bottom clockwise (X=0, Y=1)
+ var ringsX = new float[numSegments];
+ var ringsY = new float[numSegments];
+ for (int i = 0; i < numSegments;i++)
+ {
+ ringsX[i] = -1.0f * (float)System.Math.Sin(System.Math.PI*2 * i / numSegments) * _data.Thickness;
+ ringsY[i] = -1.0f * (float)System.Math.Cos(System.Math.PI + System.Math.PI*2 * i / numSegments) * _data.Thickness;
+ }
+
+ var verticesIndex = 0;
+ var indicesIndex = 0;
+
+ // calculate Vertices first
+ for (int currentRing = 0; currentRing < numRings; currentRing++)
+ {
+ // calculate one ring
+ for (int currentSegment = 0; currentSegment < numSegments; currentSegment++)
+ {
+ mesh.Vertices[verticesIndex++] = new Vertex3DNoTex2
+ {
+ X = points[currentRing].X + right[currentRing].X * ringsX[currentSegment] + down[currentRing].X * ringsY[currentSegment],
+ Y = points[currentRing].Y + right[currentRing].Y * ringsX[currentSegment] + down[currentRing].Y * ringsY[currentSegment],
+ Z = points[currentRing].Z + right[currentRing].Z * ringsX[currentSegment] + down[currentRing].Z * ringsY[currentSegment],
+ Nx = right[currentRing].X * ringsX[currentSegment] + down[currentRing].X * ringsY[currentSegment],
+ Ny = right[currentRing].Y * ringsX[currentSegment] + down[currentRing].Y * ringsY[currentSegment],
+ Nz = right[currentRing].Z * ringsX[currentSegment] + down[currentRing].Z * ringsY[currentSegment],
+ Tu = accLength[currentRing] / totalLength,
+ Tv = (float)currentSegment/((float)numSegments-1)
+
+ };
+ }
+
+
+ // could be integrated in above for loop, but better to read and will be optimized anyway by compiler
+ if (currentRing > 0)
+ {
+ for (int currentSegment = 0; currentSegment < numSegments; currentSegment++)
+ {
+ var csp1 = currentSegment + 1;
+ if (csp1 >= numSegments)
+ csp1 = 0;
+ mesh.Indices[indicesIndex++] = (currentRing - 1) * numSegments + currentSegment;
+ mesh.Indices[indicesIndex++] = currentRing * numSegments + currentSegment;
+ mesh.Indices[indicesIndex++] = currentRing * numSegments + csp1;
+ mesh.Indices[indicesIndex++] = (currentRing - 1) * numSegments + currentSegment;
+ mesh.Indices[indicesIndex++] = currentRing * numSegments + csp1;
+ mesh.Indices[indicesIndex++] = (currentRing - 1) * numSegments + csp1;
+ }
+ }
+ }
+
+ return mesh;
+ }
+ }
+}
diff --git a/VisualPinball.Engine/VPT/MetalWireGuide/MetalWireGuideMeshGenerator.cs.meta b/VisualPinball.Engine/VPT/MetalWireGuide/MetalWireGuideMeshGenerator.cs.meta
new file mode 100644
index 000000000..2657ce29d
--- /dev/null
+++ b/VisualPinball.Engine/VPT/MetalWireGuide/MetalWireGuideMeshGenerator.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 181d3df3b2969c741aaa46c906d356ca
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Engine/VPT/Rubber/Rubber.cs b/VisualPinball.Engine/VPT/Rubber/Rubber.cs
index 7f7df8810..50c5cbd72 100644
--- a/VisualPinball.Engine/VPT/Rubber/Rubber.cs
+++ b/VisualPinball.Engine/VPT/Rubber/Rubber.cs
@@ -19,6 +19,7 @@
using VisualPinball.Engine.Math;
namespace VisualPinball.Engine.VPT.Rubber
+
{
public class Rubber : Item, IRenderable
{
diff --git a/VisualPinball.Engine/VPT/Table/TableContainer.cs b/VisualPinball.Engine/VPT/Table/TableContainer.cs
index bdedbcb89..653d1e0c7 100644
--- a/VisualPinball.Engine/VPT/Table/TableContainer.cs
+++ b/VisualPinball.Engine/VPT/Table/TableContainer.cs
@@ -78,6 +78,7 @@ public abstract class TableContainer
protected readonly Dictionary _timers = new Dictionary();
protected readonly Dictionary _triggers = new Dictionary();
protected readonly Dictionary _troughs = new Dictionary();
+ protected readonly Dictionary _metalWireGuides = new Dictionary();
protected virtual void Clear()
{
@@ -101,6 +102,7 @@ protected virtual void Clear()
_timers.Clear();
_triggers.Clear();
_troughs.Clear();
+ _metalWireGuides.Clear();
}
public Bumper.Bumper Bumper(string name) => _bumpers[name.ToLower()];
@@ -123,6 +125,7 @@ protected virtual void Clear()
public Timer.Timer Timer(string name) => _timers[name.ToLower()];
public Trigger.Trigger Trigger(string name) => _triggers[name.ToLower()];
public Trough.Trough Trough(string name) => _troughs[name.ToLower()];
+ public MetalWireGuide.MetalWireGuide MetalWireGuide(string name) => _metalWireGuides[name.ToLower()];
public IEnumerable Renderables => Array.Empty()
.Concat(_bumpers.Values)
@@ -137,7 +140,8 @@ protected virtual void Clear()
.Concat(_rubbers.Values)
.Concat(_spinners.Values)
.Concat(_surfaces.Values)
- .Concat(_triggers.Values);
+ .Concat(_triggers.Values)
+ .Concat(_metalWireGuides.Values);
///
/// Game items that need to be converted but aren't rendered.
@@ -165,7 +169,8 @@ protected virtual void Clear()
.Concat(_textBoxes.Values)
.Concat(_timers.Values)
.Concat(_triggers.Values)
- .Concat(_troughs.Values);
+ .Concat(_triggers.Values)
+ .Concat(_metalWireGuides.Values);
public IEnumerable ItemDatas => ItemSupportedDatas.Concat(ItemLegacyDatas);
@@ -183,7 +188,8 @@ protected virtual void Clear()
.Concat(_rubbers.Values.Select(i => i.Data))
.Concat(_spinners.Values.Select(i => i.Data))
.Concat(_surfaces.Values.Select(i => i.Data))
- .Concat(_triggers.Values.Select(i => i.Data));
+ .Concat(_triggers.Values.Select(i => i.Data))
+ .Concat(_metalWireGuides.Values.Select(i => i.Data));
public IEnumerable ItemLegacyDatas => new ItemData[] { }
.Concat(_decals.Select(i => i.Data))
@@ -282,6 +288,12 @@ protected Dictionary GetItemDictionary(Type t) where T : IItem
return _troughs as Dictionary;
}
+ if (t == typeof(MetalWireGuide.MetalWireGuide))
+ {
+ return _metalWireGuides as Dictionary;
+ }
+
+
return null;
}
diff --git a/VisualPinball.Engine/VPT/Table/TableLoader.cs b/VisualPinball.Engine/VPT/Table/TableLoader.cs
index 3af9fa966..8cb3110a1 100644
--- a/VisualPinball.Engine/VPT/Table/TableLoader.cs
+++ b/VisualPinball.Engine/VPT/Table/TableLoader.cs
@@ -114,6 +114,7 @@ public static void LoadGameItem(byte[] itemData, int storageIndex, out ItemType
case ItemType.Timer: item = new Timer.Timer(reader, itemName); break;
case ItemType.Trigger: item = new Trigger.Trigger(reader, itemName); break;
case ItemType.Trough: item = new Trough.Trough(reader, $"VpeGameItem{storageIndex}"); break;
+ case ItemType.MetalWireGuide: item = new MetalWireGuide.MetalWireGuide(reader, itemName); break;
default:
Logger.Info("Unhandled item type " + itemType);
itemType = ItemType.Invalid; break;
@@ -245,6 +246,12 @@ private static void LoadGameItems(FileTableContainer tableContainer, CFStorage s
tableContainer.Add(item);
break;
}
+ case ItemType.MetalWireGuide:
+ {
+ var item = new MetalWireGuide.MetalWireGuide(reader, itemName);
+ tableContainer.Add(item);
+ break;
+ }
}
}
}
diff --git a/VisualPinball.Engine/VisualPinball.Engine.csproj b/VisualPinball.Engine/VisualPinball.Engine.csproj
index 9bdb13c87..bb59e5b5a 100644
--- a/VisualPinball.Engine/VisualPinball.Engine.csproj
+++ b/VisualPinball.Engine/VisualPinball.Engine.csproj
@@ -5,7 +5,7 @@
true
VisualPinball.Engine
The core of Visual Pinball ported to .NET
- freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz
+ freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz;Pandeli;Cupid
Copyright 2021 freezy - <freezy@vpdb.io>
0.1.0.0
0.1.0.0
diff --git a/VisualPinball.Resources/VisualPinball.Resources.csproj b/VisualPinball.Resources/VisualPinball.Resources.csproj
index bad18b0b4..37b776f47 100644
--- a/VisualPinball.Resources/VisualPinball.Resources.csproj
+++ b/VisualPinball.Resources/VisualPinball.Resources.csproj
@@ -3,7 +3,7 @@
netstandard2.1
VisualPinball.Resources
Meshes and Textures shipped with Visual Pinball
- freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz;Pandeli
+ freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz;Pandeli;Cupid
Copyright 2021 freezy - <freezy@vpdb.io>
0.1.0.0
0.1.0.0
diff --git a/VisualPinball.Unity/Assets/Editor/Icons/large_blue/metal_wire_guides.png b/VisualPinball.Unity/Assets/Editor/Icons/large_blue/metal_wire_guides.png
new file mode 100644
index 000000000..bcd4b400c
Binary files /dev/null and b/VisualPinball.Unity/Assets/Editor/Icons/large_blue/metal_wire_guides.png differ
diff --git a/VisualPinball.Unity/Assets/Editor/Icons/large_blue/metal_wire_guides.png.meta b/VisualPinball.Unity/Assets/Editor/Icons/large_blue/metal_wire_guides.png.meta
new file mode 100644
index 000000000..45b7ded38
--- /dev/null
+++ b/VisualPinball.Unity/Assets/Editor/Icons/large_blue/metal_wire_guides.png.meta
@@ -0,0 +1,122 @@
+fileFormatVersion: 2
+guid: 5d6ea50630493e648bff754d64ed09ea
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 11
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 1
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 1
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ vTOnly: 0
+ ignoreMasterTextureLimit: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 2
+ aniso: 1
+ mipBias: 0
+ wrapU: 0
+ wrapV: 0
+ wrapW: 0
+ nPOTScale: 1
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 0
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 0
+ textureShape: 1
+ singleChannelComponent: 0
+ flipbookRows: 1
+ flipbookColumns: 1
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ ignorePngGamma: 0
+ applyGammaDecoding: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 512
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Server
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID:
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ nameFileIdTable: {}
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Unity/Assets/Editor/Icons/large_gray/metal_wire_guides.png b/VisualPinball.Unity/Assets/Editor/Icons/large_gray/metal_wire_guides.png
new file mode 100644
index 000000000..0f1a7392b
Binary files /dev/null and b/VisualPinball.Unity/Assets/Editor/Icons/large_gray/metal_wire_guides.png differ
diff --git a/VisualPinball.Unity/Assets/Editor/Icons/large_gray/metal_wire_guides.png.meta b/VisualPinball.Unity/Assets/Editor/Icons/large_gray/metal_wire_guides.png.meta
new file mode 100644
index 000000000..698743ea3
--- /dev/null
+++ b/VisualPinball.Unity/Assets/Editor/Icons/large_gray/metal_wire_guides.png.meta
@@ -0,0 +1,122 @@
+fileFormatVersion: 2
+guid: 8f5016f61fa493b4f820999b63081774
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 11
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 1
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 1
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ vTOnly: 0
+ ignoreMasterTextureLimit: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 2
+ aniso: 1
+ mipBias: 0
+ wrapU: 0
+ wrapV: 0
+ wrapW: 0
+ nPOTScale: 1
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 0
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 0
+ textureShape: 1
+ singleChannelComponent: 0
+ flipbookRows: 1
+ flipbookColumns: 1
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ ignorePngGamma: 0
+ applyGammaDecoding: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 512
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Server
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID:
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ nameFileIdTable: {}
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Unity/Assets/Editor/Icons/large_green/metal_wire_guides.png b/VisualPinball.Unity/Assets/Editor/Icons/large_green/metal_wire_guides.png
new file mode 100644
index 000000000..086037ca1
Binary files /dev/null and b/VisualPinball.Unity/Assets/Editor/Icons/large_green/metal_wire_guides.png differ
diff --git a/VisualPinball.Unity/Assets/Editor/Icons/large_green/metal_wire_guides.png.meta b/VisualPinball.Unity/Assets/Editor/Icons/large_green/metal_wire_guides.png.meta
new file mode 100644
index 000000000..3b07734c8
--- /dev/null
+++ b/VisualPinball.Unity/Assets/Editor/Icons/large_green/metal_wire_guides.png.meta
@@ -0,0 +1,122 @@
+fileFormatVersion: 2
+guid: 6a2ceb97b21b14042b0f928766d785c4
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 11
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 1
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 1
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ vTOnly: 0
+ ignoreMasterTextureLimit: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 2
+ aniso: 1
+ mipBias: 0
+ wrapU: 0
+ wrapV: 0
+ wrapW: 0
+ nPOTScale: 1
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 0
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 0
+ textureShape: 1
+ singleChannelComponent: 0
+ flipbookRows: 1
+ flipbookColumns: 1
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ ignorePngGamma: 0
+ applyGammaDecoding: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 512
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Server
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID:
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ nameFileIdTable: {}
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Unity/Assets/Editor/Icons/large_orange/metal_wire_guides.png b/VisualPinball.Unity/Assets/Editor/Icons/large_orange/metal_wire_guides.png
new file mode 100644
index 000000000..9c266f30d
Binary files /dev/null and b/VisualPinball.Unity/Assets/Editor/Icons/large_orange/metal_wire_guides.png differ
diff --git a/VisualPinball.Unity/Assets/Editor/Icons/large_orange/metal_wire_guides.png.meta b/VisualPinball.Unity/Assets/Editor/Icons/large_orange/metal_wire_guides.png.meta
new file mode 100644
index 000000000..64bdcbc64
--- /dev/null
+++ b/VisualPinball.Unity/Assets/Editor/Icons/large_orange/metal_wire_guides.png.meta
@@ -0,0 +1,122 @@
+fileFormatVersion: 2
+guid: bd8ddd3b9ba2b4546afbbcc3badeeeba
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 11
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 1
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 1
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ vTOnly: 0
+ ignoreMasterTextureLimit: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 2
+ aniso: 1
+ mipBias: 0
+ wrapU: 0
+ wrapV: 0
+ wrapW: 0
+ nPOTScale: 1
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 0
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 0
+ textureShape: 1
+ singleChannelComponent: 0
+ flipbookRows: 1
+ flipbookColumns: 1
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ ignorePngGamma: 0
+ applyGammaDecoding: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 512
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Server
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID:
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ nameFileIdTable: {}
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Unity/Assets/Editor/Icons/small_blue/metal_wire_guides.png b/VisualPinball.Unity/Assets/Editor/Icons/small_blue/metal_wire_guides.png
new file mode 100644
index 000000000..fcfbae104
Binary files /dev/null and b/VisualPinball.Unity/Assets/Editor/Icons/small_blue/metal_wire_guides.png differ
diff --git a/VisualPinball.Unity/Assets/Editor/Icons/small_blue/metal_wire_guides.png.meta b/VisualPinball.Unity/Assets/Editor/Icons/small_blue/metal_wire_guides.png.meta
new file mode 100644
index 000000000..a491cead0
--- /dev/null
+++ b/VisualPinball.Unity/Assets/Editor/Icons/small_blue/metal_wire_guides.png.meta
@@ -0,0 +1,122 @@
+fileFormatVersion: 2
+guid: a11e8e75e5068e146898cb04a4caa683
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 11
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 0
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ vTOnly: 0
+ ignoreMasterTextureLimit: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 2
+ aniso: 1
+ mipBias: 0
+ wrapU: 1
+ wrapV: 1
+ wrapW: 0
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 0
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 2
+ textureShape: 1
+ singleChannelComponent: 0
+ flipbookRows: 1
+ flipbookColumns: 1
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ ignorePngGamma: 0
+ applyGammaDecoding: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 64
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Server
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID:
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ nameFileIdTable: {}
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Unity/Assets/Editor/Icons/small_gray/metal_wire_guides.png b/VisualPinball.Unity/Assets/Editor/Icons/small_gray/metal_wire_guides.png
new file mode 100644
index 000000000..322ebea87
Binary files /dev/null and b/VisualPinball.Unity/Assets/Editor/Icons/small_gray/metal_wire_guides.png differ
diff --git a/VisualPinball.Unity/Assets/Editor/Icons/small_gray/metal_wire_guides.png.meta b/VisualPinball.Unity/Assets/Editor/Icons/small_gray/metal_wire_guides.png.meta
new file mode 100644
index 000000000..9f08ac9a2
--- /dev/null
+++ b/VisualPinball.Unity/Assets/Editor/Icons/small_gray/metal_wire_guides.png.meta
@@ -0,0 +1,122 @@
+fileFormatVersion: 2
+guid: cf79f97d67191d74f89ff6ef88a90e39
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 11
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 0
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ vTOnly: 0
+ ignoreMasterTextureLimit: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 2
+ aniso: 1
+ mipBias: 0
+ wrapU: 1
+ wrapV: 1
+ wrapW: 0
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 0
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 2
+ textureShape: 1
+ singleChannelComponent: 0
+ flipbookRows: 1
+ flipbookColumns: 1
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ ignorePngGamma: 0
+ applyGammaDecoding: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 64
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Server
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID:
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ nameFileIdTable: {}
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Unity/Assets/Editor/Icons/small_green/metal_wire_guides.png b/VisualPinball.Unity/Assets/Editor/Icons/small_green/metal_wire_guides.png
new file mode 100644
index 000000000..7096f4921
Binary files /dev/null and b/VisualPinball.Unity/Assets/Editor/Icons/small_green/metal_wire_guides.png differ
diff --git a/VisualPinball.Unity/Assets/Editor/Icons/small_green/metal_wire_guides.png.meta b/VisualPinball.Unity/Assets/Editor/Icons/small_green/metal_wire_guides.png.meta
new file mode 100644
index 000000000..46b45e5ab
--- /dev/null
+++ b/VisualPinball.Unity/Assets/Editor/Icons/small_green/metal_wire_guides.png.meta
@@ -0,0 +1,122 @@
+fileFormatVersion: 2
+guid: 6cf673cf3917e0248b351b4296514c1d
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 11
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 0
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ vTOnly: 0
+ ignoreMasterTextureLimit: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 2
+ aniso: 1
+ mipBias: 0
+ wrapU: 1
+ wrapV: 1
+ wrapW: 0
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 0
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 2
+ textureShape: 1
+ singleChannelComponent: 0
+ flipbookRows: 1
+ flipbookColumns: 1
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ ignorePngGamma: 0
+ applyGammaDecoding: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 64
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Server
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID:
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ nameFileIdTable: {}
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Unity/Assets/Editor/Icons/small_orange/metal_wire_guides.png b/VisualPinball.Unity/Assets/Editor/Icons/small_orange/metal_wire_guides.png
new file mode 100644
index 000000000..9101a405f
Binary files /dev/null and b/VisualPinball.Unity/Assets/Editor/Icons/small_orange/metal_wire_guides.png differ
diff --git a/VisualPinball.Unity/Assets/Editor/Icons/small_orange/metal_wire_guides.png.meta b/VisualPinball.Unity/Assets/Editor/Icons/small_orange/metal_wire_guides.png.meta
new file mode 100644
index 000000000..505c72fe3
--- /dev/null
+++ b/VisualPinball.Unity/Assets/Editor/Icons/small_orange/metal_wire_guides.png.meta
@@ -0,0 +1,122 @@
+fileFormatVersion: 2
+guid: 646999b23e4fc304f9277dee4ad46cd8
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 11
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 0
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ vTOnly: 0
+ ignoreMasterTextureLimit: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 2
+ aniso: 1
+ mipBias: 0
+ wrapU: 1
+ wrapV: 1
+ wrapW: 0
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 0
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 2
+ textureShape: 1
+ singleChannelComponent: 0
+ flipbookRows: 1
+ flipbookColumns: 1
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ ignorePngGamma: 0
+ applyGammaDecoding: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 64
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 0
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 3
+ buildTarget: Server
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID:
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ nameFileIdTable: {}
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Unity/Assets/Resources/Prefabs/MetalWireGuide.prefab b/VisualPinball.Unity/Assets/Resources/Prefabs/MetalWireGuide.prefab
new file mode 100644
index 000000000..5efa4de90
--- /dev/null
+++ b/VisualPinball.Unity/Assets/Resources/Prefabs/MetalWireGuide.prefab
@@ -0,0 +1,113 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &5446999501863086646
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 657206998972773943}
+ - component: {fileID: 7950640923248477891}
+ - component: {fileID: 2107529826525245329}
+ - component: {fileID: -3250516992663423584}
+ - component: {fileID: 4392546155774236836}
+ - component: {fileID: 171621741425913877}
+ m_Layer: 0
+ m_Name: MetalWireGuide
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &657206998972773943
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 5446999501863086646}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 0}
+ m_RootOrder: 0
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &7950640923248477891
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 5446999501863086646}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: f05deabc91c0d3d4db83a445f2a755b9, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ _isLocked: 0
+ _editorLayer: 0
+ _editorLayerName:
+ _editorLayerVisibility: 1
+ _height: 25
+ _thickness: 8
+ Rotation: {x: 0, y: 0, z: 0}
+ _dragPoints: []
+--- !u!114 &2107529826525245329
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 5446999501863086646}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 735a13a6d901dbc4fb644b96ba7801ff, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ PhysicsMaterial: {fileID: 0}
+ ShowColliderMesh: 1
+ ShowAabbs: 0
+ HitEvent: 0
+ HitHeight: 25
+ OverwritePhysics: 0
+ Elasticity: 0
+ ElasticityFalloff: 0
+ Friction: 0
+ Scatter: 0
+--- !u!114 &-3250516992663423584
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 5446999501863086646}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: bcc8f0e761a7bc145abb5a6f918953aa, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+--- !u!33 &4392546155774236836
+MeshFilter:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 5446999501863086646}
+ m_Mesh: {fileID: 0}
+--- !u!114 &171621741425913877
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 5446999501863086646}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: ea7d7495833204790ba1d3a8755397f8, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ ConversionMode: 1
diff --git a/VisualPinball.Unity/Assets/Resources/Prefabs/MetalWireGuide.prefab.meta b/VisualPinball.Unity/Assets/Resources/Prefabs/MetalWireGuide.prefab.meta
new file mode 100644
index 000000000..988f0cc41
--- /dev/null
+++ b/VisualPinball.Unity/Assets/Resources/Prefabs/MetalWireGuide.prefab.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 073cf4ebd8b550b4699ac09545ec5673
+PrefabImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Import/VpxSceneConverter.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Import/VpxSceneConverter.cs
index 82389a04a..d2b9922f8 100644
--- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Import/VpxSceneConverter.cs
+++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Import/VpxSceneConverter.cs
@@ -46,6 +46,7 @@
using VisualPinball.Engine.VPT.Timer;
using VisualPinball.Engine.VPT.Trigger;
using VisualPinball.Engine.VPT.Trough;
+using VisualPinball.Engine.VPT.MetalWireGuide;
using VisualPinball.Unity.Playfield;
using Light = VisualPinball.Engine.VPT.Light.Light;
using Material = UnityEngine.Material;
@@ -189,6 +190,7 @@ private void SaveLegacyData()
_sourceContainer.WriteDataToDict(_tableComponent.LegacyContainer.Surfaces);
_sourceContainer.WriteDataToDict(_tableComponent.LegacyContainer.Triggers);
_sourceContainer.WriteDataToDict(_tableComponent.LegacyContainer.Bumpers);
+ _sourceContainer.WriteDataToDict(_tableComponent.LegacyContainer.MetalWireGuides);
_tableComponent.LegacyContainer.Decals = _sourceContainer.GetAllData();
_tableComponent.LegacyContainer.DispReels = _sourceContainer.GetAllData();
@@ -331,20 +333,21 @@ private IVpxPrefab InstantiateAndParentPrefab(IItem item)
private IVpxPrefab InstantiatePrefab(IItem item)
{
switch (item) {
- case Bumper bumper: return bumper.InstantiatePrefab();
- case Flipper flipper: return flipper.InstantiatePrefab();
- case Gate gate: return gate.InstantiatePrefab();
- case HitTarget hitTarget: return hitTarget.InstantiatePrefab();
- case Kicker kicker: return kicker.InstantiatePrefab();
- case Light lt: return lt.InstantiatePrefab(_sourceTable);
- case Plunger plunger: return plunger.InstantiatePrefab();
- case Primitive primitive: return primitive.InstantiatePrefab(_playfieldGo);
- case Ramp ramp: return ramp.InstantiatePrefab();
- case Rubber rubber: return rubber.InstantiatePrefab();
- case Spinner spinner: return spinner.InstantiatePrefab();
- case Surface surface: return surface.InstantiatePrefab();
- case Trigger trigger: return trigger.InstantiatePrefab();
- case Trough trough: return trough.InstantiatePrefab();
+ case Bumper bumper: return bumper.InstantiatePrefab();
+ case Flipper flipper: return flipper.InstantiatePrefab();
+ case Gate gate: return gate.InstantiatePrefab();
+ case HitTarget hitTarget: return hitTarget.InstantiatePrefab();
+ case Kicker kicker: return kicker.InstantiatePrefab();
+ case Light lt: return lt.InstantiatePrefab(_sourceTable);
+ case Plunger plunger: return plunger.InstantiatePrefab();
+ case Primitive primitive: return primitive.InstantiatePrefab(_playfieldGo);
+ case Ramp ramp: return ramp.InstantiatePrefab();
+ case Rubber rubber: return rubber.InstantiatePrefab();
+ case Spinner spinner: return spinner.InstantiatePrefab();
+ case Surface surface: return surface.InstantiatePrefab();
+ case Trigger trigger: return trigger.InstantiatePrefab();
+ case Trough trough: return trough.InstantiatePrefab();
+ case MetalWireGuide metalWireGuide : return metalWireGuide.InstantiatePrefab();
}
throw new InvalidOperationException("Unknown item " + item + " to setup!");
diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs
index c451bd8bf..f10a44f06 100644
--- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs
+++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs
@@ -34,6 +34,7 @@
using VisualPinball.Engine.VPT.Table;
using VisualPinball.Engine.VPT.Trigger;
using VisualPinball.Engine.VPT.Trough;
+using VisualPinball.Engine.VPT.MetalWireGuide;
using Light = VisualPinball.Engine.VPT.Light.Light;
using Texture = UnityEngine.Texture;
@@ -181,6 +182,12 @@ private void OnGUI()
CreatePrefab("Slingshots", "Prefabs/Slingshot");
}
+ if (CreateButton("Metal Wire\nGuide", Icons.MetalWireGuide(color: iconColor), iconSize, buttonStyle))
+ {
+ CreateItem(MetalWireGuide.GetDefault, "New MetalWireGuide");
+ }
+
+
GUILayout.EndHorizontal();
}
diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs
index 347c8ff35..9a7af6c14 100644
--- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs
+++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs
@@ -94,6 +94,7 @@ public IconVariant(string name, IconSize size, IconColor color)
private const string TeleporterName = "teleporter";
private const string TriggerName = "trigger";
private const string TroughName = "trough";
+ private const string MetalWireGuideName = "metal_wire_guides";
// colored
private const string CoilEventName = "coil_event";
@@ -106,8 +107,7 @@ public IconVariant(string name, IconSize size, IconColor color)
HitTargetName, KeyName, KickerName, LightGroupName, LightName, MechName, MechPinMameName, PlayfieldName, PlugName, PlungerName,
PrimitiveName, RampName, RotatorName, RubberName, SlingshotName, SpinnerName, SurfaceName, SwitchNcName, SwitchNoName, TableName,
TeleporterName, TriggerName, TroughName,
-
- CoilEventName, SwitchEventName, LampEventName, LampSeqName
+ CoilEventName, SwitchEventName, LampEventName, LampSeqName, MetalWireGuideName
};
private readonly Dictionary _icons = new Dictionary();
@@ -167,6 +167,7 @@ private static IIconLookup[] GetLookups() {
public static Texture2D LightGroup(IconSize size = IconSize.Large, IconColor color = IconColor.Gray) => Instance.GetItem(LightGroupName, size, color);
public static Texture2D Mech(IconSize size = IconSize.Large, IconColor color = IconColor.Gray) => Instance.GetItem(MechName, size, color);
public static Texture2D MechPinMame(IconSize size = IconSize.Large, IconColor color = IconColor.Gray) => Instance.GetItem(MechPinMameName, size, color);
+ public static Texture2D MetalWireGuide(IconSize size = IconSize.Large, IconColor color = IconColor.Gray) => Instance.GetItem(MetalWireGuideName, size, color);
public static Texture2D Playfield(IconSize size = IconSize.Large, IconColor color = IconColor.Gray) => Instance.GetItem(PlayfieldName, size, color);
public static Texture2D Plug(IconSize size = IconSize.Large, IconColor color = IconColor.Gray) => Instance.GetItem(PlugName, size, color);
public static Texture2D Plunger(IconSize size = IconSize.Large, IconColor color = IconColor.Gray) => Instance.GetItem(PlungerName, size, color);
@@ -274,6 +275,7 @@ public Texture2D Lookup(T mb, IconSize size = IconSize.Large, IconColor color
case TeleporterComponent _: return Icons.Teleporter(size, color);
case TriggerComponent _: return Icons.Trigger(size, color);
case TroughComponent _: return Icons.Trough(size, color);
+ case MetalWireGuideComponent _: return Icons.MetalWireGuide(size, color);
case CollisionSwitchComponent _: return Icons.Switch(false, size, color);
default: return null;
}
@@ -343,6 +345,9 @@ public void DisableGizmoIcons()
Icons.DisableGizmo();
Icons.DisableGizmo();
Icons.DisableGizmo();
+ Icons.DisableGizmo();
+ Icons.DisableGizmo();
+ Icons.DisableGizmo();
}
}
}
diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide.meta
new file mode 100644
index 000000000..32209ea42
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: f036ffc59eafb434cb84fe88893813a5
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideColliderInspector.cs
new file mode 100644
index 000000000..33b690fde
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideColliderInspector.cs
@@ -0,0 +1,88 @@
+// 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 .
+
+// ReSharper disable AssignmentInConditionalExpression
+
+using UnityEditor;
+using VisualPinball.Engine.VPT.MetalWireGuide;
+
+namespace VisualPinball.Unity.Editor
+{
+ [CustomEditor(typeof(MetalWireGuideColliderComponent)), CanEditMultipleObjects]
+ public class MetalWireGuideColliderInspector : ColliderInspector
+ {
+ private bool _foldoutMaterial = true;
+ private SerializedProperty _hitEventProperty;
+ private SerializedProperty _hitHeightProperty;
+ private SerializedProperty _overwritePhysicsProperty;
+ private SerializedProperty _physicsMaterialProperty;
+ private SerializedProperty _elasticityProperty;
+ private SerializedProperty _elasticityFalloffProperty;
+ private SerializedProperty _frictionProperty;
+ private SerializedProperty _scatterProperty;
+
+ protected override void OnEnable()
+ {
+ base.OnEnable();
+
+ _hitEventProperty = serializedObject.FindProperty(nameof(MetalWireGuideColliderComponent.HitEvent));
+ _hitHeightProperty = serializedObject.FindProperty(nameof(MetalWireGuideColliderComponent.HitHeight));
+
+ _overwritePhysicsProperty = serializedObject.FindProperty(nameof(MetalWireGuideColliderComponent.OverwritePhysics));
+ _physicsMaterialProperty = serializedObject.FindProperty(nameof(ColliderComponent.PhysicsMaterial));
+ _elasticityProperty = serializedObject.FindProperty(nameof(MetalWireGuideColliderComponent.Elasticity));
+ _elasticityFalloffProperty = serializedObject.FindProperty(nameof(MetalWireGuideColliderComponent.ElasticityFalloff));
+ _frictionProperty = serializedObject.FindProperty(nameof(MetalWireGuideColliderComponent.Friction));
+ _scatterProperty = serializedObject.FindProperty(nameof(MetalWireGuideColliderComponent.Scatter));
+ }
+
+ public override void OnInspectorGUI()
+ {
+
+ if (HasErrors()) {
+ return;
+ }
+
+ BeginEditing();
+
+ OnPreInspectorGUI();
+
+ PropertyField(_hitEventProperty, "Has Hit Event");
+ PropertyField(_hitHeightProperty, "Hit Height", updateColliders: true);
+
+ // physics material
+ if (_foldoutMaterial = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMaterial, "Physics Material")) {
+ EditorGUI.BeginDisabledGroup(_overwritePhysicsProperty.boolValue);
+ PropertyField(_physicsMaterialProperty, "Preset");
+ EditorGUI.EndDisabledGroup();
+
+ PropertyField(_overwritePhysicsProperty);
+
+ EditorGUI.BeginDisabledGroup(!_overwritePhysicsProperty.boolValue);
+ PropertyField(_elasticityProperty);
+ PropertyField(_elasticityFalloffProperty);
+ PropertyField(_frictionProperty);
+ PropertyField(_scatterProperty, "Scatter Angle");
+ EditorGUI.EndDisabledGroup();
+ }
+ EditorGUILayout.EndFoldoutHeaderGroup();
+
+ base.OnInspectorGUI();
+
+ EndEditing();
+ }
+ }
+}
diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideColliderInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideColliderInspector.cs.meta
new file mode 100644
index 000000000..c5339348b
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideColliderInspector.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e584fb57ba10628438f41ce0d4538c1e
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideExtensions.cs
new file mode 100644
index 000000000..ecd7942d5
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideExtensions.cs
@@ -0,0 +1,30 @@
+// 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 UnityEngine;
+using VisualPinball.Engine.VPT.MetalWireGuide;
+
+namespace VisualPinball.Unity.Editor
+{
+ public static class MetalWireGuideExtensions
+ {
+ internal static IVpxPrefab InstantiatePrefab(this MetalWireGuide metalWireGuide)
+ {
+ var prefab = UnityEngine.Resources.Load("Prefabs/MetalWireGuide");
+ return new VpxPrefab(prefab, metalWireGuide);
+ }
+ }
+}
diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideExtensions.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideExtensions.cs.meta
new file mode 100644
index 000000000..d7f487241
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideExtensions.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 692a65125db0eb54ba3ac6ad2621efbf
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideInspector.cs
new file mode 100644
index 000000000..d5ead010e
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideInspector.cs
@@ -0,0 +1,96 @@
+// 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 .
+
+// ReSharper disable AssignmentInConditionalExpression
+
+using System.Collections.Generic;
+using UnityEditor;
+using UnityEngine;
+using VisualPinball.Engine.Math;
+using VisualPinball.Engine.VPT.MetalWireGuide;
+
+namespace VisualPinball.Unity.Editor
+{
+ [CustomEditor(typeof(MetalWireGuideComponent)), CanEditMultipleObjects]
+ public class MetalWireGuideInspector : MainInspector, IDragPointsInspector
+ {
+
+ private SerializedProperty _heightProperty;
+ private SerializedProperty _thicknessProperty;
+ private SerializedProperty _rotationProperty;
+ private SerializedProperty _bendradius;
+
+ protected override void OnEnable()
+ {
+ base.OnEnable();
+
+
+ DragPointsHelper = new DragPointsInspectorHelper(MainComponent, this);
+ DragPointsHelper.OnEnable();
+
+ _heightProperty = serializedObject.FindProperty(nameof(MetalWireGuideComponent._height));
+ _thicknessProperty = serializedObject.FindProperty(nameof(MetalWireGuideComponent._thickness));
+ _rotationProperty = serializedObject.FindProperty(nameof(MetalWireGuideComponent.Rotation));
+ _bendradius = serializedObject.FindProperty(nameof(MetalWireGuideComponent._bendradius));
+ }
+
+ protected override void OnDisable()
+ {
+ base.OnDisable();
+ DragPointsHelper.OnDisable();
+ }
+
+ public override void OnInspectorGUI()
+ {
+ if (HasErrors()) {
+ return;
+ }
+
+ BeginEditing();
+
+ OnPreInspectorGUI();
+
+ PropertyField(_rotationProperty, rebuildMesh: true);
+ PropertyField(_heightProperty, rebuildMesh: true);
+ PropertyField(_thicknessProperty, rebuildMesh: true);
+ PropertyField(_bendradius, rebuildMesh: true);
+
+ DragPointsHelper.OnInspectorGUI(this);
+
+ base.OnInspectorGUI();
+
+ EndEditing();
+ }
+
+ private void OnSceneGUI()
+ {
+ DragPointsHelper.OnSceneGUI(this);
+ }
+
+ #region Dragpoint Tooling
+
+ public bool DragPointsActive => true;
+ public DragPointData[] DragPoints { get => MainComponent.DragPoints; set => MainComponent.DragPoints = value; }
+ public Vector3 EditableOffset => new Vector3(0.0f, 0.0f, MainComponent._height);
+ public Vector3 GetDragPointOffset(float ratio) => Vector3.zero;
+ public bool PointsAreLooping => false;
+ public IEnumerable DragPointExposition => new[] { DragPointExposure.Smooth };
+ public ItemDataTransformType HandleType => ItemDataTransformType.TwoD;
+ public DragPointsInspectorHelper DragPointsHelper { get; private set; }
+
+ #endregion
+ }
+}
diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideInspector.cs.meta
new file mode 100644
index 000000000..0aae8861f
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideInspector.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e94f80524d6f79747af961df618d2b75
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideMeshInspector.cs
new file mode 100644
index 000000000..19ea4309f
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideMeshInspector.cs
@@ -0,0 +1,36 @@
+// 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 .
+
+// ReSharper disable AssignmentInConditionalExpression
+
+using UnityEditor;
+using VisualPinball.Engine.VPT.MetalWireGuide;
+
+namespace VisualPinball.Unity.Editor
+{
+ [CustomEditor(typeof(MetalWireGuideMeshComponent)), CanEditMultipleObjects]
+ public class MetalWireGuideMeshInspector : MeshInspector
+ {
+ public override void OnInspectorGUI()
+ {
+ if (HasErrors()) {
+ return;
+ }
+
+ EditorGUILayout.HelpBox("This component computes the metal wire guide meshes.", MessageType.Info);
+ }
+ }
+}
diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideMeshInspector.cs.meta
new file mode 100644
index 000000000..dc042eef4
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/MetalWireGuide/MetalWireGuideMeshInspector.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2cc13a8d5490bb44582a79bf0f3439d2
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VisualPinball.Unity.Editor.csproj b/VisualPinball.Unity/VisualPinball.Unity.Editor/VisualPinball.Unity.Editor.csproj
index f4f742070..dd556bf03 100644
--- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VisualPinball.Unity.Editor.csproj
+++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VisualPinball.Unity.Editor.csproj
@@ -3,7 +3,7 @@
netstandard2.1
VisualPinball.Unity.Editor
A bridge between VisualPinball.Engine and Unity
- freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz;Pandeli
+ freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz;Pandeli;Cupid
Copyright 2021 freezy - <freezy@vpdb.io>
0.1.0.0
0.1.0.0
diff --git a/VisualPinball.Unity/VisualPinball.Unity.Patcher/VisualPinball.Unity.Patcher.csproj b/VisualPinball.Unity/VisualPinball.Unity.Patcher/VisualPinball.Unity.Patcher.csproj
index d25803d52..8b7f612b5 100644
--- a/VisualPinball.Unity/VisualPinball.Unity.Patcher/VisualPinball.Unity.Patcher.csproj
+++ b/VisualPinball.Unity/VisualPinball.Unity.Patcher/VisualPinball.Unity.Patcher.csproj
@@ -3,7 +3,7 @@
netstandard2.1
VisualPinball.Unity.Patcher
A bridge between VisualPinball.Engine and Unity
- freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz;Pandeli
+ freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz;Pandeli;Cupid
Copyright 2021 freezy - <freezy@vpdb.io>
0.1.0.0
0.1.0.0
diff --git a/VisualPinball.Unity/VisualPinball.Unity.Test/VPT/MetalWireGudieTests.cs b/VisualPinball.Unity/VisualPinball.Unity.Test/VPT/MetalWireGudieTests.cs
new file mode 100644
index 000000000..c3e61840e
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity.Test/VPT/MetalWireGudieTests.cs
@@ -0,0 +1,46 @@
+// 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.IO;
+using NUnit.Framework;
+using UnityEngine;
+using VisualPinball.Engine.Test.Test;
+using VisualPinball.Engine.Test.VPT.MetalWireGuide;
+using VisualPinball.Engine.VPT.Table;
+using VisualPinball.Unity.Editor;
+
+namespace VisualPinball.Unity.Test
+{
+ public class MetalWireGuideTests
+ {
+ [Test]
+ public void ShouldWriteImportedMetalWireGuideData()
+ {
+ const string tmpFileName = "ShouldWriteMetalWireGuideData.vpx";
+ var go = VpxImportEngine.ImportIntoScene(VpxPath.MetalWireGuide, options: ConvertOptions.SkipNone);
+ var ta = go.GetComponent();
+ ta.TableContainer.Save(tmpFileName);
+
+ var writtenTable = FileTableContainer.Load(tmpFileName);
+ MetalWireGuideDataTests.ValidateMetalWireGuideData1(writtenTable.MetalWireGuide("MetalWireGuide1").Data);
+ MetalWireGuideDataTests.ValidateMetalWireGuideData2(writtenTable.MetalWireGuide("MetalWireGuide2").Data);
+
+ File.Delete(tmpFileName);
+ Object.DestroyImmediate(go);
+ }
+
+ }
+}
diff --git a/VisualPinball.Unity/VisualPinball.Unity.Test/VPT/MetalWireGudieTests.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Test/VPT/MetalWireGudieTests.cs.meta
new file mode 100644
index 000000000..2b71bfa80
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity.Test/VPT/MetalWireGudieTests.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d522663b483be2b46904b6462748d6af
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Unity/VisualPinball.Unity.Test/VisualPinball.Unity.Test.csproj b/VisualPinball.Unity/VisualPinball.Unity.Test/VisualPinball.Unity.Test.csproj
index c5df604a1..9ba7f113e 100644
--- a/VisualPinball.Unity/VisualPinball.Unity.Test/VisualPinball.Unity.Test.csproj
+++ b/VisualPinball.Unity/VisualPinball.Unity.Test/VisualPinball.Unity.Test.csproj
@@ -3,7 +3,7 @@
netcoreapp3.1
VisualPinball.Unity.Test
A bridge between VisualPinball.Engine and Unity
- freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz;Pandeli
+ freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz;Pandeli;Cupid
Copyright 2021 freezy - <freezy@vpdb.io>
0.1.0.0
0.1.0.0
diff --git a/VisualPinball.Unity/VisualPinball.Unity/Game/Player.cs b/VisualPinball.Unity/VisualPinball.Unity/Game/Player.cs
index a6e842938..2d8268706 100644
--- a/VisualPinball.Unity/VisualPinball.Unity/Game/Player.cs
+++ b/VisualPinball.Unity/VisualPinball.Unity/Game/Player.cs
@@ -338,6 +338,11 @@ public void RegisterTrough(TroughComponent component)
Register(new TroughApi(component.gameObject, this), component);
}
+ public void RegisterMetalWireGuide(MetalWireGuideComponent component, Entity entity)
+ {
+ Register(new MetalWireGuideApi(component.gameObject, entity, this), component, entity);
+ }
+
private void Register(TApi api, MonoBehaviour component, Entity entity = default) where TApi : IApi
{
TableApi.Register(component, api);
diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/Job/TableLoader.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/Job/TableLoader.cs
index 722faebe1..8671db6fb 100644
--- a/VisualPinball.Unity/VisualPinball.Unity/Import/Job/TableLoader.cs
+++ b/VisualPinball.Unity/VisualPinball.Unity/Import/Job/TableLoader.cs
@@ -43,6 +43,7 @@
using VisualPinball.Engine.VPT.Timer;
using VisualPinball.Engine.VPT.Trigger;
using VisualPinball.Engine.VPT.Trough;
+using VisualPinball.Engine.VPT.MetalWireGuide;
namespace VisualPinball.Unity
{
@@ -150,6 +151,10 @@ public static FileTableContainer LoadTable(string path)
tableContainer.Add(objHandle.Target as Trough);
break;
}
+ case ItemType.MetalWireGuide:{
+ tableContainer.Add(objHandle.Target as MetalWireGuide);
+ break;
+ }
default:
throw new ArgumentException("Unknown item type " + (ItemType)job.ItemType[i] + ".");
}
diff --git a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/ColliderHeader.cs b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/ColliderHeader.cs
index 068cdb60a..d5ac67f53 100644
--- a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/ColliderHeader.cs
+++ b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/ColliderHeader.cs
@@ -50,7 +50,7 @@ public struct ColliderHeader
/// check this in order to know whether to emit
/// the hit event.
///
- public bool IsPrimitive => ItemType == ItemType.Primitive || ItemType == ItemType.Ramp || ItemType == ItemType.Rubber;
+ public bool IsPrimitive => ItemType == ItemType.Primitive || ItemType == ItemType.Ramp || ItemType == ItemType.Rubber || ItemType == ItemType.MetalWireGuide;
public void Init(ColliderInfo info, ColliderType colliderType)
{
diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide.meta
new file mode 100644
index 000000000..3dccf30f5
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: af8456f94f2fa334b9edc8f7175015b6
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideApi.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideApi.cs
new file mode 100644
index 000000000..21a1e4db8
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideApi.cs
@@ -0,0 +1,74 @@
+// 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 Unity.Entities;
+using UnityEngine;
+using VisualPinball.Engine.VPT.MetalWireGuide;
+
+namespace VisualPinball.Unity
+{
+ public class MetalWireGuideApi : CollidableApi,
+ IApi, IApiHittable
+ {
+ ///
+ /// Event emitted when the table is started.
+ ///
+ public event EventHandler Init;
+
+ ///
+ /// Event emitted when the ball hits the metal wire gudie.
+ ///
+ public event EventHandler Hit;
+
+ internal MetalWireGuideApi(GameObject go, Entity entity, Player player) : base(go, entity, player)
+ {
+ }
+
+ #region Collider Generation
+
+ protected override bool FireHitEvents => ColliderComponent.HitEvent;
+ protected override float HitThreshold => 2.0f; // hard coded threshold for now
+
+ protected override void CreateColliders(List colliders, float margin)
+ {
+ var colliderGenerator = new MetalWireGuideColliderGenerator(this, new MetalWireGuideMeshGenerator(MainComponent));
+ colliderGenerator.GenerateColliders(MainComponent.PlayfieldHeight, ColliderComponent.HitHeight, MainComponent.Bendradius, MainComponent.PlayfieldDetailLevel, colliders, margin);
+ }
+
+ #endregion
+
+ #region Events
+
+ void IApi.OnInit(BallManager ballManager)
+ {
+ base.OnInit(ballManager);
+ Init?.Invoke(this, EventArgs.Empty);
+ }
+
+ void IApi.OnDestroy()
+ {
+ }
+
+ void IApiHittable.OnHit(Entity ballEntity, bool _)
+ {
+ Hit?.Invoke(this, new HitEventArgs(ballEntity));
+ }
+
+ #endregion
+ }
+}
diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideApi.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideApi.cs.meta
new file mode 100644
index 000000000..9f1c40cff
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideApi.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c7f5e1aa51bd3e545a93dbb82d8080eb
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideColliderComponent.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideColliderComponent.cs
new file mode 100644
index 000000000..9caee1a6a
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideColliderComponent.cs
@@ -0,0 +1,64 @@
+// Visual Pinball Engine
+// Copyright (C) 2021 freezy and VPE Team
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+// ReSharper disable InconsistentNaming
+
+using System;
+using Unity.Entities;
+using UnityEngine;
+using VisualPinball.Engine.VPT.MetalWireGuide;
+
+namespace VisualPinball.Unity
+{
+ [AddComponentMenu("Visual Pinball/Collision/MetalWireGuide Collider")]
+ public class MetalWireGuideColliderComponent : ColliderComponent
+ {
+ #region Data
+
+ [Tooltip("If set, a hit event is triggered.")]
+ public bool HitEvent;
+
+ [Tooltip("Z-axis translation for the collider mesh.")]
+ public float HitHeight = 25f;
+
+ [Tooltip("Ignore the assigned physics material above and use the value below.")]
+ public bool OverwritePhysics;
+
+ [Min(0f)]
+ [Tooltip("Bounciness, also known as coefficient of restitution. Higher is more bouncy.")]
+ public float Elasticity;
+
+ [Min(0f)]
+ [Tooltip("How much to decrease elasticity for fast impacts.")]
+ public float ElasticityFalloff;
+
+ [Min(0)]
+ [Tooltip("Friction of the material.")]
+ public float Friction;
+
+ [Range(-90f, 90f)]
+ [Tooltip("When hit, add a random angle between 0 and this value to the trajectory.")]
+ public float Scatter;
+
+ #endregion
+
+ public static readonly Type[] ValidParentTypes = Type.EmptyTypes;
+
+ public override PhysicsMaterialData PhysicsMaterialData => GetPhysicsMaterialData(Elasticity, ElasticityFalloff, Friction, Scatter, OverwritePhysics);
+ protected override IApiColliderGenerator InstantiateColliderApi(Player player, Entity entity)
+ => new MetalWireGuideApi(gameObject, entity, player);
+ }
+}
diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideColliderComponent.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideColliderComponent.cs.meta
new file mode 100644
index 000000000..b421778b7
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideColliderComponent.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 735a13a6d901dbc4fb644b96ba7801ff
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {fileID: 2800000, guid: 6cf673cf3917e0248b351b4296514c1d, type: 3}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideColliderGenerator.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideColliderGenerator.cs
new file mode 100644
index 000000000..97af246f9
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideColliderGenerator.cs
@@ -0,0 +1,69 @@
+// Visual Pinball Engine
+// Copyright (C) 2020 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.Generic;
+using VisualPinball.Engine.VPT;
+using VisualPinball.Engine.VPT.MetalWireGuide;
+
+namespace VisualPinball.Unity
+{
+ public class MetalWireGuideColliderGenerator
+ {
+ private readonly IApiColliderGenerator _api;
+ private readonly MetalWireGuideMeshGenerator _meshGenerator;
+
+ public MetalWireGuideColliderGenerator(MetalWireGuideApi metalWireGuideApi, MetalWireGuideMeshGenerator meshGenerator)
+ {
+ _api = metalWireGuideApi;
+ _meshGenerator = meshGenerator;
+ }
+
+ internal void GenerateColliders(float playfieldHeight, float hitHeight, float bendradius, int detailLevel, List colliders, float margin)
+ {
+ var mesh = _meshGenerator.GetTransformedMesh(playfieldHeight, hitHeight, detailLevel, bendradius, 6, true, margin); //!! adapt hacky code in the function if changing the "6" here
+ var addedEdges = EdgeSet.Get();
+
+ // add collision triangles and edges
+ for (var i = 0; i < mesh.Indices.Length; i += 3) {
+ // NB: HitTriangle wants CCW vertices, but for rendering we have them in CW order
+ var rg0 = mesh.Vertices[mesh.Indices[i]].ToUnityFloat3();
+ var rg1 = mesh.Vertices[mesh.Indices[i + 2]].ToUnityFloat3();
+ var rg2 = mesh.Vertices[mesh.Indices[i + 1]].ToUnityFloat3();
+
+ colliders.Add(new TriangleCollider(rg0, rg1, rg2, _api.GetColliderInfo()));
+
+ GenerateHitEdge(mesh, addedEdges, mesh.Indices[i], mesh.Indices[i + 2], colliders);
+ GenerateHitEdge(mesh, addedEdges, mesh.Indices[i + 2], mesh.Indices[i + 1], colliders);
+ GenerateHitEdge(mesh, addedEdges, mesh.Indices[i + 1], mesh.Indices[i], colliders);
+ }
+
+ // add collision vertices
+ foreach (var mv in mesh.Vertices) {
+ colliders.Add(new PointCollider(mv.ToUnityFloat3(), _api.GetColliderInfo()));
+ }
+ }
+
+ private void GenerateHitEdge(Mesh mesh, EdgeSet addedEdges, int i, int j,
+ ICollection colliders)
+ {
+ if (addedEdges.ShouldAddHitEdge(i, j)) {
+ var v1 = mesh.Vertices[i].ToUnityFloat3();
+ var v2 = mesh.Vertices[j].ToUnityFloat3();
+ colliders.Add(new Line3DCollider(v1, v2, _api.GetColliderInfo()));
+ }
+ }
+ }
+}
diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideColliderGenerator.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideColliderGenerator.cs.meta
new file mode 100644
index 000000000..8259dab1e
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideColliderGenerator.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 006ddeefa3aadc849a05fa7fd77b74de
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideComponent.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideComponent.cs
new file mode 100644
index 000000000..d7da683af
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideComponent.cs
@@ -0,0 +1,230 @@
+// 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 .
+
+#region ReSharper
+// ReSharper disable CompareOfFloatsByEqualityOperator
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable InconsistentNaming
+#endregion
+
+using System;
+using System.Collections.Generic;
+using Unity.Entities;
+using UnityEngine;
+using VisualPinball.Engine.Math;
+using VisualPinball.Engine.VPT;
+using VisualPinball.Engine.VPT.MetalWireGuide;
+using VisualPinball.Engine.VPT.Table;
+
+namespace VisualPinball.Unity
+{
+ [AddComponentMenu("Visual Pinball/Game Item/Metal Wire Guide")]
+ public class MetalWireGuideComponent : MainRenderableComponent,
+ IMetalWireGuideData, IConvertGameObjectToEntity
+ {
+ #region Data
+
+ [Tooltip("Height of the rubber (z-axis).")]
+ public float _height = 25f;
+
+ [Min(0)]
+ [Tooltip("How thick the rubber band is rendered.")]
+ public int _thickness = 8;
+
+ [Tooltip("Rotation on the playfield")]
+ public Vector3 Rotation;
+
+ [Tooltip("Radius of the bend")]
+ public float _bendradius = 8f;
+
+ [SerializeField]
+ private DragPointData[] _dragPoints;
+
+ #endregion
+
+ #region IMetalWireGuideData
+
+ public DragPointData[] DragPoints { get => _dragPoints; set => _dragPoints = value; }
+ public int Thickness => _thickness;
+ public float Height => _height;
+ public float RotX => Rotation.x;
+ public float RotY => Rotation.y;
+ public float RotZ => Rotation.z;
+ public float Bendradius => _bendradius;
+
+ #endregion
+
+ #region Overrides
+
+ public override ItemType ItemType => ItemType.MetalWireGuide;
+ public override string ItemName => "MetalWireGuide";
+
+ public override MetalWireGuideData InstantiateData() => new MetalWireGuideData();
+
+ protected override Type MeshComponentType { get; } = typeof(MeshComponent);
+ protected override Type ColliderComponentType { get; } = typeof(ColliderComponent);
+
+ #endregion
+
+ #region Transformation
+
+ public override void OnPlayfieldHeightUpdated() => RebuildMeshes();
+
+ #endregion
+
+ #region Conversion
+
+ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
+ {
+ Convert(entity, dstManager);
+
+ // register
+ transform.GetComponentInParent().RegisterMetalWireGuide(this, entity);
+ }
+
+ public override IEnumerable SetData(MetalWireGuideData data)
+ {
+ var updatedComponents = new List { this };
+
+ // geometry
+ _height = data.Height;
+ Rotation = new Vector3(data.RotX, data.RotY, data.RotZ);
+ _thickness = data.Thickness;
+ DragPoints = data.DragPoints;
+ _bendradius = data.Bendradius;
+
+ // collider data
+ var collComponent = GetComponent();
+ if (collComponent) {
+ collComponent.enabled = data.IsCollidable;
+
+ collComponent.HitEvent = data.HitEvent;
+ collComponent.HitHeight = data.HitHeight;
+ collComponent.OverwritePhysics = data.OverwritePhysics;
+ collComponent.Elasticity = data.Elasticity;
+ collComponent.ElasticityFalloff = data.ElasticityFalloff;
+ collComponent.Friction = data.Friction;
+ collComponent.Scatter = data.Scatter;
+
+ updatedComponents.Add(collComponent);
+ }
+
+ return updatedComponents;
+ }
+
+ public override IEnumerable SetReferencedData(MetalWireGuideData data, Table table, IMaterialProvider materialProvider, ITextureProvider textureProvider, Dictionary components)
+ {
+ // mesh
+ var mesh = GetComponent();
+ if (mesh) {
+ mesh.CreateMesh(data, table, textureProvider, materialProvider);
+ mesh.enabled = data.IsVisible;
+ SetEnabled(data.IsVisible);
+ }
+
+ // collider data
+ var collComponent = GetComponentInChildren();
+ if (collComponent) {
+ collComponent.PhysicsMaterial = materialProvider.GetPhysicsMaterial(data.PhysicsMaterial);
+ }
+
+ return Array.Empty();
+ }
+
+ public override MetalWireGuideData CopyDataTo(MetalWireGuideData data, string[] materialNames, string[] textureNames, bool forExport)
+ {
+ // update the name
+ data.Name = name;
+
+ // geometry
+ data.Height = _height;
+ data.RotX = Rotation.x;
+ data.RotY = Rotation.y;
+ data.RotZ = Rotation.z;
+ data.Thickness = _thickness;
+ data.Bendradius = _bendradius;
+ data.DragPoints = DragPoints;
+
+ // visibility
+ data.IsVisible = GetEnabled();
+
+ // collision
+ var collComponent = GetComponentInChildren();
+ if (collComponent) {
+ data.IsCollidable = collComponent.enabled;
+
+ data.HitEvent = collComponent.HitEvent;
+ data.HitHeight = collComponent.HitHeight;
+
+ data.PhysicsMaterial = collComponent.PhysicsMaterial ? collComponent.PhysicsMaterial.name : string.Empty;
+ data.OverwritePhysics = collComponent.OverwritePhysics;
+ data.Elasticity = collComponent.Elasticity;
+ data.ElasticityFalloff = collComponent.ElasticityFalloff;
+ data.Friction = collComponent.Friction;
+ data.Scatter = collComponent.Scatter;
+
+ } else {
+ data.IsCollidable = false;
+ }
+
+ return data;
+ }
+
+ #endregion
+
+ #region Editor Tooling
+
+ private Vector3 DragPointCenter {
+ get {
+ var sum = Vertex3D.Zero;
+ foreach (var t in DragPoints) {
+ sum += t.Center;
+ }
+ var center = sum / DragPoints.Length;
+ return center.ToUnityVector3();
+ }
+ }
+
+ public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD;
+ public override Vector3 GetEditorPosition()
+ {
+ var pos = DragPoints.Length == 0 ? Vector3.zero : DragPointCenter;
+ return new Vector3(pos.x, pos.y, _height);
+ }
+ public override void SetEditorPosition(Vector3 pos) {
+ if (DragPoints.Length == 0) {
+ return;
+ }
+ var diff = (pos - DragPointCenter).ToVertex3D();
+ diff.Z = 0f;
+ foreach (var pt in DragPoints) {
+ pt.Center += diff;
+ }
+ _height = pos.z;
+ RebuildMeshes();
+ }
+
+ public override ItemDataTransformType EditorRotationType => ItemDataTransformType.ThreeD;
+ public override Vector3 GetEditorRotation() => Rotation;
+ public override void SetEditorRotation(Vector3 rot) {
+ Rotation = rot;
+ RebuildMeshes();
+ }
+
+ #endregion
+ }
+}
diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideComponent.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideComponent.cs.meta
new file mode 100644
index 000000000..c408066ee
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideComponent.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f05deabc91c0d3d4db83a445f2a755b9
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {fileID: 2800000, guid: 646999b23e4fc304f9277dee4ad46cd8, type: 3}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideMeshComponent.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideMeshComponent.cs
new file mode 100644
index 000000000..392aba994
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideMeshComponent.cs
@@ -0,0 +1,38 @@
+// 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 UnityEngine;
+using VisualPinball.Engine.VPT;
+using VisualPinball.Engine.VPT.MetalWireGuide;
+using VisualPinball.Engine.VPT.Table;
+using Mesh = VisualPinball.Engine.VPT.Mesh;
+
+namespace VisualPinball.Unity
+{
+ [ExecuteInEditMode]
+ [AddComponentMenu("Visual Pinball/Mesh/Metal Wire Guide Mesh")]
+ public class MetalWireGuideMeshComponent : MeshComponent
+ {
+ public static readonly Type[] ValidParentTypes = Type.EmptyTypes;
+
+ protected override Mesh GetMesh(MetalWireGuideData data)
+ => new MetalWireGuideMeshGenerator(MainComponent).GetTransformedMesh(MainComponent.PlayfieldHeight, MainComponent.Height, MainComponent.PlayfieldDetailLevel, MainComponent.Bendradius);
+
+ protected override PbrMaterial GetMaterial(MetalWireGuideData data, Table table)
+ => new MetalWireGuideMeshGenerator(MainComponent).GetMaterial(table, data);
+ }
+}
diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideMeshComponent.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideMeshComponent.cs.meta
new file mode 100644
index 000000000..c026cfc21
--- /dev/null
+++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/MetalWireGuide/MetalWireGuideMeshComponent.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bcc8f0e761a7bc145abb5a6f918953aa
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {fileID: 2800000, guid: a11e8e75e5068e146898cb04a4caa683, type: 3}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderComponent.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderComponent.cs
index 015ae4220..578ada8df 100644
--- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderComponent.cs
+++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderComponent.cs
@@ -65,6 +65,7 @@ public class PrimitiveColliderComponent : ColliderComponent GetPhysicsMaterialData(Elasticity, ElasticityFalloff, Friction, Scatter, OverwritePhysics);
diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshComponent.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshComponent.cs
index 2744aefe2..de85b983f 100644
--- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshComponent.cs
+++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshComponent.cs
@@ -54,6 +54,7 @@ public class PrimitiveMeshComponent : MeshComponent Spinners = new SerializableDictionary();
public SerializableDictionary Surfaces = new SerializableDictionary();
public SerializableDictionary Triggers = new SerializableDictionary();
+ public SerializableDictionary MetalWireGuides = new SerializableDictionary();
public DecalData[] Decals;
public DispReelData[] DispReels;
diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/SceneTableContainer.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/SceneTableContainer.cs
index 492741ce4..8a8433c10 100644
--- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/SceneTableContainer.cs
+++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/SceneTableContainer.cs
@@ -46,6 +46,7 @@
using VisualPinball.Engine.VPT.Timer;
using VisualPinball.Engine.VPT.Trigger;
using VisualPinball.Engine.VPT.Trough;
+using VisualPinball.Engine.VPT.MetalWireGuide;
using Light = VisualPinball.Engine.VPT.Light.Light;
using Material = VisualPinball.Engine.VPT.Material;
using Texture = VisualPinball.Engine.VPT.Texture;
@@ -281,6 +282,10 @@ private void Add(IMainComponent comp, bool forExport)
var troughData = troughComponent.CopyDataTo(new TroughData(), MaterialNames, TextureNames, forExport);
Add(comp.gameObject.name, new Trough(troughData));
break;
+ case MetalWireGuideComponent metalWireGuideComponent:
+ var metalWireGuideData = metalWireGuideComponent.CopyDataTo(_tableComponent.LegacyContainer.MetalWireGuides.ContainsKey(name) ? _tableComponent.LegacyContainer.MetalWireGuides[name] : new MetalWireGuideData(), MaterialNames, TextureNames, forExport);
+ Add(comp.gameObject.name, new MetalWireGuide(metalWireGuideData));
+ break;
}
}
diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableApi.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableApi.cs
index d1152ba8c..43852e5ef 100644
--- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableApi.cs
+++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableApi.cs
@@ -45,6 +45,7 @@ public class TableApi : IApi
private readonly Dictionary _teleportersByName = new Dictionary();
private readonly Dictionary _triggersByName = new Dictionary();
private readonly Dictionary _troughsByName = new Dictionary();
+ private readonly Dictionary _metalWireGuidesByName = new Dictionary();
private readonly Dictionary _switchablesByName = new Dictionary();
private readonly Dictionary _hittablesByName = new Dictionary();
@@ -67,6 +68,7 @@ public class TableApi : IApi
private readonly Dictionary _teleportersByComponent = new Dictionary();
private readonly Dictionary _triggersByComponent = new Dictionary();
private readonly Dictionary _troughsByComponent = new Dictionary();
+ private readonly Dictionary _metalWireGuidesByComponent = new Dictionary();
private readonly Dictionary _switchablesByComponent = new Dictionary();
private readonly Dictionary _hittablesByComponent = new Dictionary();
@@ -199,6 +201,14 @@ public TableApi(Player player)
public TroughApi Trough(string name) => Get(name);
public TroughApi Trough(MonoBehaviour component) => Get(component);
+ ///
+ /// Returns a metal wire guide by name.
+ ///
+ /// Name of the metal wire guide
+ /// MetalWireGuide or `null` if no metal wire guide with that name exists.
+ public MetalWireGuideApi MetalWireGuide(string name) => Get(name);
+ public MetalWireGuideApi MetalWireGuide(MonoBehaviour component) => Get(component);
+
///
/// Returns a step rotator by name.
///
@@ -295,6 +305,7 @@ private Dictionary GetNameDictionary(Type t) where T : IApi
if (t == typeof(TeleporterApi)) return _teleportersByName as Dictionary;
if (t == typeof(TriggerApi)) return _triggersByName as Dictionary;
if (t == typeof(TroughApi)) return _troughsByName as Dictionary;
+ if (t == typeof(MetalWireGuideApi)) return _metalWireGuidesByName as Dictionary;
// can be null, because we don't track all elements, namely hittable switches
return null;
@@ -322,6 +333,7 @@ private Dictionary GetComponentDictionary(Type t) where T :
if (t == typeof(TeleporterApi)) return _teleportersByComponent as Dictionary;
if (t == typeof(TriggerApi)) return _triggersByComponent as Dictionary;
if (t == typeof(TroughApi)) return _troughsByComponent as Dictionary;
+ if (t == typeof(MetalWireGuideApi)) return _metalWireGuidesByComponent as Dictionary;
// can be null, because we don't track all elements, namely hittable switches
return null;
diff --git a/VisualPinball.Unity/VisualPinball.Unity/VisualPinball.Unity.csproj b/VisualPinball.Unity/VisualPinball.Unity/VisualPinball.Unity.csproj
index 5d0563777..6519a3f1e 100644
--- a/VisualPinball.Unity/VisualPinball.Unity/VisualPinball.Unity.csproj
+++ b/VisualPinball.Unity/VisualPinball.Unity/VisualPinball.Unity.csproj
@@ -3,7 +3,7 @@
netstandard2.1
VisualPinball.Unity
A bridge between VisualPinball.Engine and Unity
- freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz;Pandeli
+ freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz;Pandeli;Cupid
Copyright 2021 freezy - <freezy@vpdb.io>
0.1.0.0
0.1.0.0
diff --git a/package.json b/package.json
index aea37b651..2c52aff61 100644
--- a/package.json
+++ b/package.json
@@ -27,7 +27,8 @@
"Rowlan",
"Kleis Auke Wolthuizen ",
"Eli Curtz ",
- "Pandeli"
+ "Pandeli",
+ "Cupid"
],
"documentationUrl": "https://docs.visualpinball.org/",
"changelogUrl": "https://docs.visualpinball.org/CHANGELOG.html",