Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

editor: new Element, MetalWireguide - first RP for review #366

Merged
merged 12 commits into from
Jan 10, 2022
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)).
Expand Down
Binary file not shown.
2 changes: 2 additions & 0 deletions VisualPinball.Engine.Test/Test/Fixtures.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
103 changes: 103 additions & 0 deletions VisualPinball.Engine.Test/VPT/MetalWireGuide/MetalWireDataTests.cs
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.

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);
*/
}
}
}
49 changes: 49 additions & 0 deletions VisualPinball.Engine.Test/VPT/MetalWireGuide/MetalWireMeshTest.cs
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.

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);
//}
}
}
2 changes: 1 addition & 1 deletion VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<Title>VisualPinball.Engine.Test</Title>
<Description>A .NET port of Visual Pinball in C#</Description>
<Authors>freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz;Pandeli</Authors>
<Authors>freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz;Pandeli;Cupid</Authors>
<Copyright>Copyright 2021 freezy - &lt;freezy@vpdb.io&gt;</Copyright>
<AssemblyVersion>0.1.0.0</AssemblyVersion>
<AssemblyFileVersion>0.1.0.0</AssemblyFileVersion>
Expand Down
42 changes: 30 additions & 12 deletions VisualPinball.Engine/Math/SplineVertex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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;

Expand All @@ -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<RenderVertex2D, CatmullCurve2DCatmullCurveFactory>(dragPoints, true, accuracy);
return DragPoint.GetRgVertex<RenderVertex2D, CatmullCurve2DCatmullCurveFactory>(dragPoints, loop, accuracy);
}
}
}
1 change: 1 addition & 0 deletions VisualPinball.Engine/VPT/ItemType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public enum ItemType
Rubber = 21,
HitTarget = 22,
Count = 23,
MetalWireGuide = 24,
Invalid = -1,

// VPE internal
Expand Down
8 changes: 8 additions & 0 deletions VisualPinball.Engine/VPT/MetalWireGuide.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 31 additions & 0 deletions VisualPinball.Engine/VPT/MetalWireGuide/IMetalWireGuideData.cs
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.

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; }
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading