From 98715719fd97de0c76ab45ed6a5290b6f6231c80 Mon Sep 17 00:00:00 2001 From: Eli Curtz Date: Mon, 17 Aug 2020 12:55:21 -0700 Subject: [PATCH 001/124] Added BiffAnimationAttribute to PrimitiveData and Mesh.VertexData for loading and storing mesh animations. --- VisualPinball.Engine/VPT/Mesh.cs | 102 ++++++++++++++++++ .../VPT/Primitive/PrimitiveData.cs | 100 +++++++++++++++++ 2 files changed, 202 insertions(+) diff --git a/VisualPinball.Engine/VPT/Mesh.cs b/VisualPinball.Engine/VPT/Mesh.cs index c60ac889a..f78b40d1f 100644 --- a/VisualPinball.Engine/VPT/Mesh.cs +++ b/VisualPinball.Engine/VPT/Mesh.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.IO; using VisualPinball.Engine.Common; using VisualPinball.Engine.Math; @@ -23,6 +24,8 @@ public class Mesh public int[] Indices; public bool IsSet => Vertices != null && Indices != null; + public List AnimationFrames; + public Mesh() { } public Mesh(string name) @@ -311,5 +314,104 @@ private static bool LinesIntersect(IRenderVertex start1, IRenderVertex start2, I return d341 * d342 < 0.0; } + + + #region VertData + /// + /// VertData is a utility struct containing position and normal data.

+ /// + /// It is used primarily for storing animation frames. + ///

+ [Serializable] + public struct VertData + { + public const int Size = 28; + + public float X; + public float Y; + public float Z; + + public float Nx; + public float Ny; + public float Nz; + + public VertData(BinaryReader reader) + { + var startPos = reader.BaseStream.Position; + X = reader.ReadSingle(); + Y = reader.ReadSingle(); + Z = reader.ReadSingle(); + Nx = reader.ReadSingle(); + Ny = reader.ReadSingle(); + Nz = reader.ReadSingle(); + var remainingSize = Size - (reader.BaseStream.Position - startPos); + if (remainingSize > 0) + { + throw new InvalidOperationException(); + } + } + + public VertData(IReadOnlyList arr) + { + X = arr.Count > 0 ? arr[0] : float.NaN; + Y = arr.Count > 1 ? arr[1] : float.NaN; + Z = arr.Count > 2 ? arr[2] : float.NaN; + Nx = arr.Count > 3 ? arr[3] : float.NaN; + Ny = arr.Count > 4 ? arr[4] : float.NaN; + Nz = arr.Count > 5 ? arr[5] : float.NaN; + } + + public VertData(float x, float y, float z, float nx = float.NaN, float ny = float.NaN, float nz = float.NaN) + { + X = x; + Y = y; + Z = z; + Nx = nx; + Ny = ny; + Nz = nz; + } + + public void Write(BinaryWriter writer) + { + writer.Write(X); + writer.Write(Y); + writer.Write(Z); + writer.Write(Nx); + writer.Write(Ny); + writer.Write(Nz); + } + + public Vertex3D GetVertex() + { + return new Vertex3D(X, Y, Z); + } + + public Vertex3D GetNormal() + { + return new Vertex3D(Nx, Ny, Nz); + } + + public VertData Clone() + { + var vertex = new VertData + { + X = X, + Y = Y, + Z = Z, + Nx = Nx, + Ny = Ny, + Nz = Nz + }; + return vertex; + } + + public override string ToString() + { + return $"VertData({X}/{Y}/{Z}, {Nx}/{Ny}/{Nz})"; + } + } + #endregion + } + } diff --git a/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs b/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs index 807932e6e..62a4ded37 100644 --- a/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs +++ b/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs @@ -45,6 +45,7 @@ public class PrimitiveData : ItemData [BiffVertices("M3CX", IsCompressed = true, Pos = 42)] [BiffIndices("M3DI", SkipWrite = true)] [BiffIndices("M3CI", IsCompressed = true, Pos = 45)] + [BiffAnimation("M3DX", IsCompressed = true, Pos = 333)] public Mesh Mesh = new Mesh(); [BiffFloat("RTV0", Index = 0, Pos = 3)] @@ -352,4 +353,103 @@ private static byte[] SerializeIndices(PrimitiveData data) } } } + + /// + /// Parses animated vertex data.

+ /// + ///

+ public class BiffAnimationAttribute : BiffAttribute + { + /// + /// If set, the vertices are Zlib-compressed. + /// + public bool IsCompressed; + + public BiffAnimationAttribute(string name) : base(name) { } + + public override void Parse(T obj, BinaryReader reader, int len) + { + if (obj is PrimitiveData primitiveData) + { + try + { + ParseAnimation(primitiveData, IsCompressed + ? BiffZlib.Decompress(reader.ReadBytes(len)) + : reader.ReadBytes(len)); + } + catch (Exception e) + { + throw new Exception($"Error parsing animation data for {primitiveData.Name} ({primitiveData.StorageName}).", e); + } + } + } + + public override void Write(TItem obj, BinaryWriter writer, HashWriter hashWriter) + { + if (obj is PrimitiveData primitiveData) + { + if (!primitiveData.Use3DMesh) + { + // don't write animation if not using 3d mesh + return; + } + + for (var i = 0; i < primitiveData.Mesh.AnimationFrames.Count; i++) + { + var animationData = SerializeAnimation(primitiveData.Mesh.AnimationFrames[i]); + var data = IsCompressed ? BiffZlib.Compress(animationData) : animationData; + WriteStart(writer, data.Length, hashWriter); + writer.Write(data); + hashWriter?.Write(data); + } + + } + else + { + throw new InvalidOperationException("Unknown type for [" + GetType().Name + "] on field \"" + Name + "\"."); + } + } + + private void ParseAnimation(PrimitiveData data, byte[] bytes) + { + if (data.NumVertices == 0) + { + throw new ArgumentOutOfRangeException(nameof(data), "Cannot create animation when size is unknown."); + } + + if (bytes.Length < data.NumVertices * Mesh.VertData.Size) + { + throw new ArgumentOutOfRangeException($"Tried to read {data.NumVertices} vertex anoimations for primitive item \"${data.Name}\" (${data.StorageName}), but only ${bytes.Length} bytes available."); + } + + if (!(GetValue(data) is Mesh mesh)) + { + throw new ArgumentException("BiffAnimationAttribute attribute must sit on a Mesh object."); + } + + var vertices = new Mesh.VertData[data.NumVertices]; + using (var stream = new MemoryStream(bytes)) + using (var reader = new BinaryReader(stream)) + { + for (var i = 0; i < data.NumVertices; i++) + { + vertices[i] = new Mesh.VertData(reader); + } + } + mesh.AnimationFrames.Add(vertices); + } + + private static byte[] SerializeAnimation(Mesh.VertData[] data) + { + using (var stream = new MemoryStream()) + using (var writer = new BinaryWriter(stream)) + { + for (var i = 0; i < data.Length; i++) + { + data[i].Write(writer); + } + return stream.ToArray(); + } + } + } } From c8ddec36a200e0092d07c48af4763c6400f020a2 Mon Sep 17 00:00:00 2001 From: Eli Curtz Date: Mon, 17 Aug 2020 13:37:22 -0700 Subject: [PATCH 002/124] Fixed struct size of Mesh.VertData and tag for BiffAnimation. --- VisualPinball.Engine/VPT/Mesh.cs | 2 +- VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/VisualPinball.Engine/VPT/Mesh.cs b/VisualPinball.Engine/VPT/Mesh.cs index f78b40d1f..72d54ae69 100644 --- a/VisualPinball.Engine/VPT/Mesh.cs +++ b/VisualPinball.Engine/VPT/Mesh.cs @@ -325,7 +325,7 @@ private static bool LinesIntersect(IRenderVertex start1, IRenderVertex start2, I [Serializable] public struct VertData { - public const int Size = 28; + public const int Size = 24; public float X; public float Y; diff --git a/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs b/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs index 62a4ded37..7f78b83de 100644 --- a/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs +++ b/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs @@ -45,7 +45,7 @@ public class PrimitiveData : ItemData [BiffVertices("M3CX", IsCompressed = true, Pos = 42)] [BiffIndices("M3DI", SkipWrite = true)] [BiffIndices("M3CI", IsCompressed = true, Pos = 45)] - [BiffAnimation("M3DX", IsCompressed = true, Pos = 333)] + [BiffAnimation("M3AX", IsCompressed = true, Pos = 333)] public Mesh Mesh = new Mesh(); [BiffFloat("RTV0", Index = 0, Pos = 3)] @@ -419,7 +419,7 @@ private void ParseAnimation(PrimitiveData data, byte[] bytes) if (bytes.Length < data.NumVertices * Mesh.VertData.Size) { - throw new ArgumentOutOfRangeException($"Tried to read {data.NumVertices} vertex anoimations for primitive item \"${data.Name}\" (${data.StorageName}), but only ${bytes.Length} bytes available."); + throw new ArgumentOutOfRangeException($"Tried to read {data.NumVertices} vertex animations for primitive item \"${data.Name}\" (${data.StorageName}), but only ${bytes.Length} bytes available."); } if (!(GetValue(data) is Mesh mesh)) From ee0871b3a58ee8452e67d3b168535466584b6e9a Mon Sep 17 00:00:00 2001 From: Eli Curtz Date: Tue, 18 Aug 2020 11:52:58 -0700 Subject: [PATCH 003/124] Add blendshape data to meshes with vertex animation and use a SkinnedMeshRenderer instead of regular MeshRenderer. --- VisualPinball.Engine/VPT/Mesh.cs | 23 ++++++++++++++++--- .../VPT/Primitive/PrimitiveData.cs | 2 +- .../Extensions/MeshExtensions.cs | 16 +++++++++++++ .../Import/VpxConverter.cs | 14 ++++++++--- 4 files changed, 48 insertions(+), 7 deletions(-) diff --git a/VisualPinball.Engine/VPT/Mesh.cs b/VisualPinball.Engine/VPT/Mesh.cs index 72d54ae69..0c7891f46 100644 --- a/VisualPinball.Engine/VPT/Mesh.cs +++ b/VisualPinball.Engine/VPT/Mesh.cs @@ -24,7 +24,7 @@ public class Mesh public int[] Indices; public bool IsSet => Vertices != null && Indices != null; - public List AnimationFrames; + public List AnimationFrames = new List(); public Mesh() { } @@ -90,11 +90,18 @@ public Mesh Clone(string name = null) { var mesh = new Mesh { Name = name ?? Name, Vertices = new Vertex3DNoTex2[Vertices.Length], - Indices = new int[Indices.Length] + Indices = new int[Indices.Length], + AnimationFrames = new List(AnimationFrames.Count) }; - //mesh.animationFrames = this.animationFrames.map(a => a.clone()); Vertices.Select(v => v.Clone()).ToArray().CopyTo(mesh.Vertices, 0); Indices.CopyTo(mesh.Indices, 0); + if (AnimationFrames.Count > 0) { + for (int i = 0; i < AnimationFrames.Count; i++) { + mesh.AnimationFrames.Add(new VertData[Vertices.Length]); + AnimationFrames[i].CopyTo(mesh.AnimationFrames[i], 0); + } + } + //mesh.faceIndexOffset = this.faceIndexOffset; return mesh; } @@ -391,6 +398,16 @@ public Vertex3D GetNormal() return new Vertex3D(Nx, Ny, Nz); } + public UnityEngine.Vector3 ToUnityVector3() + { + return new UnityEngine.Vector3(X, Y, Z); + } + + public UnityEngine.Vector3 ToUnityNormalVector3() + { + return new UnityEngine.Vector3(Nx, Ny, Nz); + } + public VertData Clone() { var vertex = new VertData diff --git a/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs b/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs index 7f78b83de..37ef67a44 100644 --- a/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs +++ b/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs @@ -45,7 +45,7 @@ public class PrimitiveData : ItemData [BiffVertices("M3CX", IsCompressed = true, Pos = 42)] [BiffIndices("M3DI", SkipWrite = true)] [BiffIndices("M3CI", IsCompressed = true, Pos = 45)] - [BiffAnimation("M3AX", IsCompressed = true, Pos = 333)] + [BiffAnimation("M3AX", IsCompressed = true, Pos = 48)] public Mesh Mesh = new Mesh(); [BiffFloat("RTV0", Index = 0, Pos = 3)] diff --git a/VisualPinball.Unity/VisualPinball.Unity/Extensions/MeshExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/Extensions/MeshExtensions.cs index 7f468165c..2bfc0d855 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Extensions/MeshExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Extensions/MeshExtensions.cs @@ -54,6 +54,22 @@ public static void ApplyToUnityMesh(this Engine.VPT.Mesh vpMesh, Mesh mesh) // faces mesh.triangles = vpMesh.Indices; + + // animation + if (vpMesh.AnimationFrames.Count > 0) { + float deltaWeight = 100f / vpMesh.AnimationFrames.Count; + Vector3[] deltaVertices = new Vector3[vpMesh.Vertices.Length]; + Vector3[] deltaNormals = new Vector3[vpMesh.Vertices.Length]; + + float weight = deltaWeight; + for (int i = 0; i < vpMesh.AnimationFrames.Count; i++, weight+= deltaWeight) { + for (int j = 0; j < vpMesh.Vertices.Length; j++) { + deltaVertices[j] = vpMesh.AnimationFrames[i][j].ToUnityVector3() - vertices[j]; + deltaNormals[j] = vpMesh.AnimationFrames[i][j].ToUnityNormalVector3() - normals[j]; + } + mesh.AddBlendShapeFrame("animation", weight, deltaVertices, deltaNormals, null); + } + } } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index b3b1c0e31..b5698e14c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -111,9 +111,17 @@ public static GameObject ConvertRenderObject(RenderObject ro, GameObject obj, Ta mf.sharedMesh = mesh; // apply material - var mr = obj.AddComponent(); - mr.sharedMaterial = ro.Material.ToUnityMaterial(ta); - mr.enabled = ro.IsVisible; + if (ro.Mesh.AnimationFrames.Count > 0) { + var smr = obj.AddComponent(); + smr.sharedMaterial = ro.Material.ToUnityMaterial(table); + smr.sharedMesh = mesh; + smr.enabled = ro.IsVisible; + } + else { + var mr = obj.AddComponent(); + mr.sharedMaterial = ro.Material.ToUnityMaterial(table); + mr.enabled = ro.IsVisible; + } return obj; } From 5895de45413928a5ad5d7c30a7260e09534b6bb5 Mon Sep 17 00:00:00 2001 From: Eli Curtz Date: Fri, 21 Aug 2020 18:39:30 -0700 Subject: [PATCH 004/124] Added (inexplicably) required calls to RecalculateNormals() and RecalculateTangents() when building blendshapes. --- VisualPinball.Engine/VPT/Mesh.cs | 11 +++++ .../VPT/Primitive/PrimitiveData.cs | 14 +++--- .../Extensions/MeshExtensions.cs | 48 +++++++++++++++++-- 3 files changed, 62 insertions(+), 11 deletions(-) diff --git a/VisualPinball.Engine/VPT/Mesh.cs b/VisualPinball.Engine/VPT/Mesh.cs index 0c7891f46..94ed7b578 100644 --- a/VisualPinball.Engine/VPT/Mesh.cs +++ b/VisualPinball.Engine/VPT/Mesh.cs @@ -351,6 +351,7 @@ public VertData(BinaryReader reader) Nx = reader.ReadSingle(); Ny = reader.ReadSingle(); Nz = reader.ReadSingle(); + var remainingSize = Size - (reader.BaseStream.Position - startPos); if (remainingSize > 0) { @@ -378,6 +379,16 @@ public VertData(float x, float y, float z, float nx = float.NaN, float ny = floa Nz = nz; } + public VertData(UnityEngine.Vector3 vertex, UnityEngine.Vector3 normal) + { + X = vertex.x; + Y = vertex.y; + Z = vertex.z; + Nx = normal.x; + Ny = normal.y; + Nz = normal.z; + } + public void Write(BinaryWriter writer) { writer.Write(X); diff --git a/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs b/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs index 37ef67a44..96e1faee9 100644 --- a/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs +++ b/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs @@ -41,11 +41,14 @@ public class PrimitiveData : ItemData [BiffInt("M3CJ", Pos = 44)] public int CompressedIndices = 0; + [BiffInt("M3AY", Pos = 46)] + public int CompressedAnimationVertices; + [BiffVertices("M3DX", SkipWrite = true)] [BiffVertices("M3CX", IsCompressed = true, Pos = 42)] [BiffIndices("M3DI", SkipWrite = true)] [BiffIndices("M3CI", IsCompressed = true, Pos = 45)] - [BiffAnimation("M3AX", IsCompressed = true, Pos = 48)] + [BiffAnimation("M3AX", IsCompressed = true, Pos = 47)] public Mesh Mesh = new Mesh(); [BiffFloat("RTV0", Index = 0, Pos = 3)] @@ -147,7 +150,7 @@ public class PrimitiveData : ItemData [BiffString("M3DN", Pos = 39)] public string MeshFileName = string.Empty; - [BiffFloat("PIDB", Pos = 46)] + [BiffFloat("PIDB", Pos = 48)] public float DepthBias = 0; protected override bool SkipWrite(BiffAttribute attr) @@ -394,8 +397,7 @@ public override void Write(TItem obj, BinaryWriter writer, HashWriter has return; } - for (var i = 0; i < primitiveData.Mesh.AnimationFrames.Count; i++) - { + for (var i = 0; i < primitiveData.Mesh.AnimationFrames.Count; i++) { var animationData = SerializeAnimation(primitiveData.Mesh.AnimationFrames[i]); var data = IsCompressed ? BiffZlib.Compress(animationData) : animationData; WriteStart(writer, data.Length, hashWriter); @@ -417,9 +419,9 @@ private void ParseAnimation(PrimitiveData data, byte[] bytes) throw new ArgumentOutOfRangeException(nameof(data), "Cannot create animation when size is unknown."); } - if (bytes.Length < data.NumVertices * Mesh.VertData.Size) + if (bytes.Length != data.NumVertices * Mesh.VertData.Size) { - throw new ArgumentOutOfRangeException($"Tried to read {data.NumVertices} vertex animations for primitive item \"${data.Name}\" (${data.StorageName}), but only ${bytes.Length} bytes available."); + throw new ArgumentOutOfRangeException($"Tried to read {data.NumVertices} vertex animations for primitive item \"${data.Name}\" (${data.StorageName}), but had ${bytes.Length} bytes available."); } if (!(GetValue(data) is Mesh mesh)) diff --git a/VisualPinball.Unity/VisualPinball.Unity/Extensions/MeshExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/Extensions/MeshExtensions.cs index 2bfc0d855..0f8bc3337 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Extensions/MeshExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Extensions/MeshExtensions.cs @@ -6,13 +6,18 @@ namespace VisualPinball.Unity { public static class MeshExtensions { + public const string AnimationShape = "animation"; + public static Engine.VPT.Mesh ToVpMesh(this Mesh unityMesh) { var vpMesh = new Engine.VPT.Mesh(unityMesh.name); vpMesh.Vertices = new Vertex3DNoTex2[unityMesh.vertexCount]; + var unityVertices = unityMesh.vertices; + var unityNormals = unityMesh.normals; + for (int i = 0; i < vpMesh.Vertices.Length; i++) { - var unityVertex = unityMesh.vertices[i]; - var unityNormal = unityMesh.normals[i]; + var unityVertex = unityVertices[i]; + var unityNormal = unityNormals[i]; var unityUv = unityMesh.uv[i]; vpMesh.Vertices[i] = new Vertex3DNoTex2( unityVertex.x, unityVertex.y, unityVertex.z, @@ -20,6 +25,33 @@ public static Engine.VPT.Mesh ToVpMesh(this Mesh unityMesh) unityUv.x, -unityUv.y ); } vpMesh.Indices = unityMesh.triangles; + + if (unityMesh.blendShapeCount > 0) { + int animationIndex = unityMesh.GetBlendShapeIndex(AnimationShape); + + // use the first blendshape if none with default name + if (animationIndex < 0) { + animationIndex = 0; + } + + Vector3[] deltaVertices = new Vector3[unityMesh.vertexCount]; + Vector3[] deltaNormals = new Vector3[unityMesh.vertexCount]; + + int frameCount = unityMesh.GetBlendShapeFrameCount(animationIndex); + for (int i = 0; i < frameCount; i++) { + unityMesh.GetBlendShapeFrameVertices(animationIndex, i, deltaVertices, deltaNormals, null); + + Engine.VPT.Mesh.VertData[] frameData = new Engine.VPT.Mesh.VertData[unityMesh.vertexCount]; + for (int j = 0; j < unityMesh.vertexCount; j++) { + Vector3 vertex = deltaVertices[j] + unityVertices[j]; + Vector3 normal = deltaNormals[j] + unityNormals[j]; + frameData[j] = new Engine.VPT.Mesh.VertData(vertex, normal); + } + + vpMesh.AnimationFrames.Add(frameData); + } + } + return vpMesh; } @@ -50,25 +82,31 @@ public static void ApplyToUnityMesh(this Engine.VPT.Mesh vpMesh, Mesh mesh) mesh.vertices = vertices; mesh.normals = normals; mesh.uv = uv; - mesh.RecalculateBounds(); + //mesh.RecalculateBounds(); // redundant if setting tringles // faces mesh.triangles = vpMesh.Indices; // animation if (vpMesh.AnimationFrames.Count > 0) { - float deltaWeight = 100f / vpMesh.AnimationFrames.Count; + float deltaWeight = 1f / vpMesh.AnimationFrames.Count; Vector3[] deltaVertices = new Vector3[vpMesh.Vertices.Length]; Vector3[] deltaNormals = new Vector3[vpMesh.Vertices.Length]; float weight = deltaWeight; for (int i = 0; i < vpMesh.AnimationFrames.Count; i++, weight+= deltaWeight) { + for (int j = 0; j < vpMesh.Vertices.Length; j++) { deltaVertices[j] = vpMesh.AnimationFrames[i][j].ToUnityVector3() - vertices[j]; + deltaNormals[j] = vpMesh.AnimationFrames[i][j].ToUnityNormalVector3() - normals[j]; } - mesh.AddBlendShapeFrame("animation", weight, deltaVertices, deltaNormals, null); + mesh.AddBlendShapeFrame(AnimationShape, weight, deltaVertices, deltaNormals, null); } + + // HACK this is insane and almost certainly a Unity bug + mesh.RecalculateNormals(); + mesh.RecalculateTangents(); } } } From 6de9e4e1038caf6a54ae631846db49ec978864e1 Mon Sep 17 00:00:00 2001 From: Eli Curtz Date: Thu, 27 Aug 2020 13:35:35 -0700 Subject: [PATCH 005/124] Changed argument for Material.toUnityMaterial() --- .../VisualPinball.Unity/Import/VpxConverter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index b5698e14c..ed71f324a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -113,13 +113,13 @@ public static GameObject ConvertRenderObject(RenderObject ro, GameObject obj, Ta // apply material if (ro.Mesh.AnimationFrames.Count > 0) { var smr = obj.AddComponent(); - smr.sharedMaterial = ro.Material.ToUnityMaterial(table); + smr.sharedMaterial = ro.Material.ToUnityMaterial(ta); smr.sharedMesh = mesh; smr.enabled = ro.IsVisible; } else { var mr = obj.AddComponent(); - mr.sharedMaterial = ro.Material.ToUnityMaterial(table); + mr.sharedMaterial = ro.Material.ToUnityMaterial(ta); mr.enabled = ro.IsVisible; } From b736b0f96d7461f8273b432b8ef85c94c890979e Mon Sep 17 00:00:00 2001 From: Eli Curtz Date: Thu, 27 Aug 2020 14:04:52 -0700 Subject: [PATCH 006/124] Remove Mesh.VertData dependency on UnityEngine.Vector3 --- VisualPinball.Engine/VPT/Mesh.cs | 10 ---------- .../VisualPinball.Unity/Extensions/MeshExtensions.cs | 4 +++- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/VisualPinball.Engine/VPT/Mesh.cs b/VisualPinball.Engine/VPT/Mesh.cs index 94ed7b578..b838cf5da 100644 --- a/VisualPinball.Engine/VPT/Mesh.cs +++ b/VisualPinball.Engine/VPT/Mesh.cs @@ -379,16 +379,6 @@ public VertData(float x, float y, float z, float nx = float.NaN, float ny = floa Nz = nz; } - public VertData(UnityEngine.Vector3 vertex, UnityEngine.Vector3 normal) - { - X = vertex.x; - Y = vertex.y; - Z = vertex.z; - Nx = normal.x; - Ny = normal.y; - Nz = normal.z; - } - public void Write(BinaryWriter writer) { writer.Write(X); diff --git a/VisualPinball.Unity/VisualPinball.Unity/Extensions/MeshExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/Extensions/MeshExtensions.cs index 0f8bc3337..55f104283 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Extensions/MeshExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Extensions/MeshExtensions.cs @@ -45,7 +45,9 @@ public static Engine.VPT.Mesh ToVpMesh(this Mesh unityMesh) for (int j = 0; j < unityMesh.vertexCount; j++) { Vector3 vertex = deltaVertices[j] + unityVertices[j]; Vector3 normal = deltaNormals[j] + unityNormals[j]; - frameData[j] = new Engine.VPT.Mesh.VertData(vertex, normal); + frameData[j] = new Engine.VPT.Mesh.VertData( + vertex.x, vertex.y, vertex.z, + normal.x, normal.y, normal.z); } vpMesh.AnimationFrames.Add(frameData); From e78a758921e8dffcf59b0b3ffa35c1d7e91ad9a2 Mon Sep 17 00:00:00 2001 From: Eli Curtz Date: Thu, 27 Aug 2020 14:15:43 -0700 Subject: [PATCH 007/124] Added Vector3 extension methods to Mesh.VertData --- VisualPinball.Engine/VPT/Mesh.cs | 10 ---------- .../VisualPinball.Unity/Extensions/MeshExtensions.cs | 10 ++++++++++ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/VisualPinball.Engine/VPT/Mesh.cs b/VisualPinball.Engine/VPT/Mesh.cs index b838cf5da..6da26f6db 100644 --- a/VisualPinball.Engine/VPT/Mesh.cs +++ b/VisualPinball.Engine/VPT/Mesh.cs @@ -399,16 +399,6 @@ public Vertex3D GetNormal() return new Vertex3D(Nx, Ny, Nz); } - public UnityEngine.Vector3 ToUnityVector3() - { - return new UnityEngine.Vector3(X, Y, Z); - } - - public UnityEngine.Vector3 ToUnityNormalVector3() - { - return new UnityEngine.Vector3(Nx, Ny, Nz); - } - public VertData Clone() { var vertex = new VertData diff --git a/VisualPinball.Unity/VisualPinball.Unity/Extensions/MeshExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/Extensions/MeshExtensions.cs index 55f104283..95902e3e8 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Extensions/MeshExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Extensions/MeshExtensions.cs @@ -111,6 +111,16 @@ public static void ApplyToUnityMesh(this Engine.VPT.Mesh vpMesh, Mesh mesh) mesh.RecalculateTangents(); } } + + public static Vector3 ToUnityVector3(this Engine.VPT.Mesh.VertData vpVert) + { + return new Vector3(vpVert.X, vpVert.Y, vpVert.Z); + } + + public static Vector3 ToUnityNormalVector3(this Engine.VPT.Mesh.VertData vpVert) + { + return new Vector3(vpVert.Nx, vpVert.Ny, vpVert.Nz); + } } } From b539a14c7feccc10c3ae059b442cb536bbbcd2f1 Mon Sep 17 00:00:00 2001 From: Eli Curtz Date: Sat, 29 Aug 2020 11:50:24 -0700 Subject: [PATCH 008/124] Simple OBJ sequence for testing model animation. Cube that expands and contracts on X, then Y, then Z. --- .../Fixtures~/cube_0.obj | 46 +++++++++++++++++++ .../Fixtures~/cube_1.obj | 46 +++++++++++++++++++ .../Fixtures~/cube_2.obj | 46 +++++++++++++++++++ .../Fixtures~/cube_3.obj | 46 +++++++++++++++++++ .../Fixtures~/cube_4.obj | 46 +++++++++++++++++++ .../Fixtures~/cube_5.obj | 46 +++++++++++++++++++ .../Fixtures~/cube_6.obj | 46 +++++++++++++++++++ 7 files changed, 322 insertions(+) create mode 100755 VisualPinball.Engine.Test/Fixtures~/cube_0.obj create mode 100755 VisualPinball.Engine.Test/Fixtures~/cube_1.obj create mode 100755 VisualPinball.Engine.Test/Fixtures~/cube_2.obj create mode 100755 VisualPinball.Engine.Test/Fixtures~/cube_3.obj create mode 100755 VisualPinball.Engine.Test/Fixtures~/cube_4.obj create mode 100755 VisualPinball.Engine.Test/Fixtures~/cube_5.obj create mode 100755 VisualPinball.Engine.Test/Fixtures~/cube_6.obj diff --git a/VisualPinball.Engine.Test/Fixtures~/cube_0.obj b/VisualPinball.Engine.Test/Fixtures~/cube_0.obj new file mode 100755 index 000000000..3b3af7ac3 --- /dev/null +++ b/VisualPinball.Engine.Test/Fixtures~/cube_0.obj @@ -0,0 +1,46 @@ +# Blender v2.80 (sub 49) OBJ File: '' +# www.blender.org +mtllib cube.mtl +o Cube +v 50.000000 50.000000 -50.000000 +v 50.000000 -50.000000 -50.000000 +v 50.000000 50.000000 50.000000 +v 50.000000 -50.000000 50.000000 +v -50.000000 50.000000 -50.000000 +v -50.000000 -50.000000 -50.000000 +v -50.000000 50.000000 50.000000 +v -50.000000 -50.000000 50.000000 +vt 0.375000 0.000000 +vt 0.625000 0.000000 +vt 0.625000 0.250000 +vt 0.375000 0.250000 +vt 0.375000 0.250000 +vt 0.625000 0.250000 +vt 0.625000 0.500000 +vt 0.375000 0.500000 +vt 0.625000 0.750000 +vt 0.375000 0.750000 +vt 0.625000 0.750000 +vt 0.625000 1.000000 +vt 0.375000 1.000000 +vt 0.125000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.750000 +vt 0.125000 0.750000 +vt 0.625000 0.500000 +vt 0.875000 0.500000 +vt 0.875000 0.750000 +vn 0.0000 1.0000 0.0000 +vn 0.0000 0.0000 1.0000 +vn -1.0000 0.0000 0.0000 +vn 0.0000 -1.0000 0.0000 +vn 1.0000 0.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +usemtl Material +s off +f 1/1/1 5/2/1 7/3/1 3/4/1 +f 4/5/2 3/6/2 7/7/2 8/8/2 +f 8/8/3 7/7/3 5/9/3 6/10/3 +f 6/10/4 2/11/4 4/12/4 8/13/4 +f 2/14/5 1/15/5 3/16/5 4/17/5 +f 6/18/6 5/19/6 1/20/6 2/11/6 diff --git a/VisualPinball.Engine.Test/Fixtures~/cube_1.obj b/VisualPinball.Engine.Test/Fixtures~/cube_1.obj new file mode 100755 index 000000000..590cf9aad --- /dev/null +++ b/VisualPinball.Engine.Test/Fixtures~/cube_1.obj @@ -0,0 +1,46 @@ +# Blender v2.80 (sub 49) OBJ File: '' +# www.blender.org +mtllib cube_x.mtl +o Cube +v 100.000000 50.000000 -50.000000 +v 100.000000 -50.000000 -50.000000 +v 100.000000 50.000000 50.000000 +v 100.000000 -50.000000 50.000000 +v -100.000000 50.000000 -50.000000 +v -100.000000 -50.000000 -50.000000 +v -100.000000 50.000000 50.000000 +v -100.000000 -50.000000 50.000000 +vt 0.375000 0.000000 +vt 0.625000 0.000000 +vt 0.625000 0.250000 +vt 0.375000 0.250000 +vt 0.375000 0.250000 +vt 0.625000 0.250000 +vt 0.625000 0.500000 +vt 0.375000 0.500000 +vt 0.625000 0.750000 +vt 0.375000 0.750000 +vt 0.625000 0.750000 +vt 0.625000 1.000000 +vt 0.375000 1.000000 +vt 0.125000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.750000 +vt 0.125000 0.750000 +vt 0.625000 0.500000 +vt 0.875000 0.500000 +vt 0.875000 0.750000 +vn 0.0000 1.0000 0.0000 +vn 0.0000 0.0000 1.0000 +vn -1.0000 0.0000 0.0000 +vn 0.0000 -1.0000 0.0000 +vn 1.0000 0.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +usemtl Material +s off +f 1/1/1 5/2/1 7/3/1 3/4/1 +f 4/5/2 3/6/2 7/7/2 8/8/2 +f 8/8/3 7/7/3 5/9/3 6/10/3 +f 6/10/4 2/11/4 4/12/4 8/13/4 +f 2/14/5 1/15/5 3/16/5 4/17/5 +f 6/18/6 5/19/6 1/20/6 2/11/6 diff --git a/VisualPinball.Engine.Test/Fixtures~/cube_2.obj b/VisualPinball.Engine.Test/Fixtures~/cube_2.obj new file mode 100755 index 000000000..3b3af7ac3 --- /dev/null +++ b/VisualPinball.Engine.Test/Fixtures~/cube_2.obj @@ -0,0 +1,46 @@ +# Blender v2.80 (sub 49) OBJ File: '' +# www.blender.org +mtllib cube.mtl +o Cube +v 50.000000 50.000000 -50.000000 +v 50.000000 -50.000000 -50.000000 +v 50.000000 50.000000 50.000000 +v 50.000000 -50.000000 50.000000 +v -50.000000 50.000000 -50.000000 +v -50.000000 -50.000000 -50.000000 +v -50.000000 50.000000 50.000000 +v -50.000000 -50.000000 50.000000 +vt 0.375000 0.000000 +vt 0.625000 0.000000 +vt 0.625000 0.250000 +vt 0.375000 0.250000 +vt 0.375000 0.250000 +vt 0.625000 0.250000 +vt 0.625000 0.500000 +vt 0.375000 0.500000 +vt 0.625000 0.750000 +vt 0.375000 0.750000 +vt 0.625000 0.750000 +vt 0.625000 1.000000 +vt 0.375000 1.000000 +vt 0.125000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.750000 +vt 0.125000 0.750000 +vt 0.625000 0.500000 +vt 0.875000 0.500000 +vt 0.875000 0.750000 +vn 0.0000 1.0000 0.0000 +vn 0.0000 0.0000 1.0000 +vn -1.0000 0.0000 0.0000 +vn 0.0000 -1.0000 0.0000 +vn 1.0000 0.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +usemtl Material +s off +f 1/1/1 5/2/1 7/3/1 3/4/1 +f 4/5/2 3/6/2 7/7/2 8/8/2 +f 8/8/3 7/7/3 5/9/3 6/10/3 +f 6/10/4 2/11/4 4/12/4 8/13/4 +f 2/14/5 1/15/5 3/16/5 4/17/5 +f 6/18/6 5/19/6 1/20/6 2/11/6 diff --git a/VisualPinball.Engine.Test/Fixtures~/cube_3.obj b/VisualPinball.Engine.Test/Fixtures~/cube_3.obj new file mode 100755 index 000000000..ca18898ab --- /dev/null +++ b/VisualPinball.Engine.Test/Fixtures~/cube_3.obj @@ -0,0 +1,46 @@ +# Blender v2.80 (sub 49) OBJ File: '' +# www.blender.org +mtllib cube_y.mtl +o Cube +v 50.000000 50.000000 -100.000000 +v 50.000000 -50.000000 -100.000000 +v 50.000000 50.000000 100.000000 +v 50.000000 -50.000000 100.000000 +v -50.000000 50.000000 -100.000000 +v -50.000000 -50.000000 -100.000000 +v -50.000000 50.000000 100.000000 +v -50.000000 -50.000000 100.000000 +vt 0.375000 0.000000 +vt 0.625000 0.000000 +vt 0.625000 0.250000 +vt 0.375000 0.250000 +vt 0.375000 0.250000 +vt 0.625000 0.250000 +vt 0.625000 0.500000 +vt 0.375000 0.500000 +vt 0.625000 0.750000 +vt 0.375000 0.750000 +vt 0.625000 0.750000 +vt 0.625000 1.000000 +vt 0.375000 1.000000 +vt 0.125000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.750000 +vt 0.125000 0.750000 +vt 0.625000 0.500000 +vt 0.875000 0.500000 +vt 0.875000 0.750000 +vn 0.0000 1.0000 0.0000 +vn 0.0000 0.0000 1.0000 +vn -1.0000 0.0000 0.0000 +vn 0.0000 -1.0000 0.0000 +vn 1.0000 0.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +usemtl Material +s off +f 1/1/1 5/2/1 7/3/1 3/4/1 +f 4/5/2 3/6/2 7/7/2 8/8/2 +f 8/8/3 7/7/3 5/9/3 6/10/3 +f 6/10/4 2/11/4 4/12/4 8/13/4 +f 2/14/5 1/15/5 3/16/5 4/17/5 +f 6/18/6 5/19/6 1/20/6 2/11/6 diff --git a/VisualPinball.Engine.Test/Fixtures~/cube_4.obj b/VisualPinball.Engine.Test/Fixtures~/cube_4.obj new file mode 100755 index 000000000..3b3af7ac3 --- /dev/null +++ b/VisualPinball.Engine.Test/Fixtures~/cube_4.obj @@ -0,0 +1,46 @@ +# Blender v2.80 (sub 49) OBJ File: '' +# www.blender.org +mtllib cube.mtl +o Cube +v 50.000000 50.000000 -50.000000 +v 50.000000 -50.000000 -50.000000 +v 50.000000 50.000000 50.000000 +v 50.000000 -50.000000 50.000000 +v -50.000000 50.000000 -50.000000 +v -50.000000 -50.000000 -50.000000 +v -50.000000 50.000000 50.000000 +v -50.000000 -50.000000 50.000000 +vt 0.375000 0.000000 +vt 0.625000 0.000000 +vt 0.625000 0.250000 +vt 0.375000 0.250000 +vt 0.375000 0.250000 +vt 0.625000 0.250000 +vt 0.625000 0.500000 +vt 0.375000 0.500000 +vt 0.625000 0.750000 +vt 0.375000 0.750000 +vt 0.625000 0.750000 +vt 0.625000 1.000000 +vt 0.375000 1.000000 +vt 0.125000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.750000 +vt 0.125000 0.750000 +vt 0.625000 0.500000 +vt 0.875000 0.500000 +vt 0.875000 0.750000 +vn 0.0000 1.0000 0.0000 +vn 0.0000 0.0000 1.0000 +vn -1.0000 0.0000 0.0000 +vn 0.0000 -1.0000 0.0000 +vn 1.0000 0.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +usemtl Material +s off +f 1/1/1 5/2/1 7/3/1 3/4/1 +f 4/5/2 3/6/2 7/7/2 8/8/2 +f 8/8/3 7/7/3 5/9/3 6/10/3 +f 6/10/4 2/11/4 4/12/4 8/13/4 +f 2/14/5 1/15/5 3/16/5 4/17/5 +f 6/18/6 5/19/6 1/20/6 2/11/6 diff --git a/VisualPinball.Engine.Test/Fixtures~/cube_5.obj b/VisualPinball.Engine.Test/Fixtures~/cube_5.obj new file mode 100755 index 000000000..9c4cfa515 --- /dev/null +++ b/VisualPinball.Engine.Test/Fixtures~/cube_5.obj @@ -0,0 +1,46 @@ +# Blender v2.80 (sub 49) OBJ File: '' +# www.blender.org +mtllib cube_z.mtl +o Cube +v 50.000000 100.000000 -50.000000 +v 50.000000 -100.000000 -50.000000 +v 50.000000 100.000000 50.000000 +v 50.000000 -100.000000 50.000000 +v -50.000000 100.000000 -50.000000 +v -50.000000 -100.000000 -50.000000 +v -50.000000 100.000000 50.000000 +v -50.000000 -100.000000 50.000000 +vt 0.375000 0.000000 +vt 0.625000 0.000000 +vt 0.625000 0.250000 +vt 0.375000 0.250000 +vt 0.375000 0.250000 +vt 0.625000 0.250000 +vt 0.625000 0.500000 +vt 0.375000 0.500000 +vt 0.625000 0.750000 +vt 0.375000 0.750000 +vt 0.625000 0.750000 +vt 0.625000 1.000000 +vt 0.375000 1.000000 +vt 0.125000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.750000 +vt 0.125000 0.750000 +vt 0.625000 0.500000 +vt 0.875000 0.500000 +vt 0.875000 0.750000 +vn 0.0000 1.0000 0.0000 +vn 0.0000 0.0000 1.0000 +vn -1.0000 0.0000 0.0000 +vn 0.0000 -1.0000 0.0000 +vn 1.0000 0.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +usemtl Material +s off +f 1/1/1 5/2/1 7/3/1 3/4/1 +f 4/5/2 3/6/2 7/7/2 8/8/2 +f 8/8/3 7/7/3 5/9/3 6/10/3 +f 6/10/4 2/11/4 4/12/4 8/13/4 +f 2/14/5 1/15/5 3/16/5 4/17/5 +f 6/18/6 5/19/6 1/20/6 2/11/6 diff --git a/VisualPinball.Engine.Test/Fixtures~/cube_6.obj b/VisualPinball.Engine.Test/Fixtures~/cube_6.obj new file mode 100755 index 000000000..3b3af7ac3 --- /dev/null +++ b/VisualPinball.Engine.Test/Fixtures~/cube_6.obj @@ -0,0 +1,46 @@ +# Blender v2.80 (sub 49) OBJ File: '' +# www.blender.org +mtllib cube.mtl +o Cube +v 50.000000 50.000000 -50.000000 +v 50.000000 -50.000000 -50.000000 +v 50.000000 50.000000 50.000000 +v 50.000000 -50.000000 50.000000 +v -50.000000 50.000000 -50.000000 +v -50.000000 -50.000000 -50.000000 +v -50.000000 50.000000 50.000000 +v -50.000000 -50.000000 50.000000 +vt 0.375000 0.000000 +vt 0.625000 0.000000 +vt 0.625000 0.250000 +vt 0.375000 0.250000 +vt 0.375000 0.250000 +vt 0.625000 0.250000 +vt 0.625000 0.500000 +vt 0.375000 0.500000 +vt 0.625000 0.750000 +vt 0.375000 0.750000 +vt 0.625000 0.750000 +vt 0.625000 1.000000 +vt 0.375000 1.000000 +vt 0.125000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.750000 +vt 0.125000 0.750000 +vt 0.625000 0.500000 +vt 0.875000 0.500000 +vt 0.875000 0.750000 +vn 0.0000 1.0000 0.0000 +vn 0.0000 0.0000 1.0000 +vn -1.0000 0.0000 0.0000 +vn 0.0000 -1.0000 0.0000 +vn 1.0000 0.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +usemtl Material +s off +f 1/1/1 5/2/1 7/3/1 3/4/1 +f 4/5/2 3/6/2 7/7/2 8/8/2 +f 8/8/3 7/7/3 5/9/3 6/10/3 +f 6/10/4 2/11/4 4/12/4 8/13/4 +f 2/14/5 1/15/5 3/16/5 4/17/5 +f 6/18/6 5/19/6 1/20/6 2/11/6 From 4223292e3c0b3f0e6c0cdd1d2d25d1e42c970255 Mon Sep 17 00:00:00 2001 From: freezy Date: Sun, 30 Aug 2020 15:48:38 +0200 Subject: [PATCH 009/124] primtive: Add test coverage for reading animated mesh data. --- .../Fixtures~/PrimitiveAnimated.obj | 178 ++++++++++++++++++ .../Fixtures~/PrimitiveAnimated.vpx | Bin 0 -> 32768 bytes .../Fixtures~/PrimitiveAnimated_00000.obj | 89 +++++++++ .../Fixtures~/PrimitiveAnimated_00001.obj | 89 +++++++++ .../Fixtures~/PrimitiveAnimated_00002.obj | 89 +++++++++ .../Fixtures~/PrimitiveAnimated_00003.obj | 89 +++++++++ .../Fixtures~/PrimitiveAnimated_00004.obj | 89 +++++++++ .../Fixtures~/PrimitiveAnimated_00005.obj | 89 +++++++++ .../Fixtures~/PrimitiveAnimated_00006.obj | 89 +++++++++ ...cube_0.obj => PrimitiveAnimated_Src_0.obj} | 0 ...cube_1.obj => PrimitiveAnimated_Src_1.obj} | 0 ...cube_2.obj => PrimitiveAnimated_Src_2.obj} | 0 ...cube_3.obj => PrimitiveAnimated_Src_3.obj} | 0 ...cube_4.obj => PrimitiveAnimated_Src_4.obj} | 0 ...cube_5.obj => PrimitiveAnimated_Src_5.obj} | 0 ...cube_6.obj => PrimitiveAnimated_Src_6.obj} | 0 VisualPinball.Engine.Test/Test/Fixtures.cs | 10 + VisualPinball.Engine.Test/Test/MeshTests.cs | 13 +- .../VPT/Primitive/PrimitiveMeshTests.cs | 25 ++- VisualPinball.Engine/VPT/Mesh.cs | 5 + 20 files changed, 846 insertions(+), 8 deletions(-) create mode 100644 VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated.obj create mode 100644 VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated.vpx create mode 100644 VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00000.obj create mode 100644 VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00001.obj create mode 100644 VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00002.obj create mode 100644 VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00003.obj create mode 100644 VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00004.obj create mode 100644 VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00005.obj create mode 100644 VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00006.obj rename VisualPinball.Engine.Test/Fixtures~/{cube_0.obj => PrimitiveAnimated_Src_0.obj} (100%) mode change 100755 => 100644 rename VisualPinball.Engine.Test/Fixtures~/{cube_1.obj => PrimitiveAnimated_Src_1.obj} (100%) mode change 100755 => 100644 rename VisualPinball.Engine.Test/Fixtures~/{cube_2.obj => PrimitiveAnimated_Src_2.obj} (100%) mode change 100755 => 100644 rename VisualPinball.Engine.Test/Fixtures~/{cube_3.obj => PrimitiveAnimated_Src_3.obj} (100%) mode change 100755 => 100644 rename VisualPinball.Engine.Test/Fixtures~/{cube_4.obj => PrimitiveAnimated_Src_4.obj} (100%) mode change 100755 => 100644 rename VisualPinball.Engine.Test/Fixtures~/{cube_5.obj => PrimitiveAnimated_Src_5.obj} (100%) mode change 100755 => 100644 rename VisualPinball.Engine.Test/Fixtures~/{cube_6.obj => PrimitiveAnimated_Src_6.obj} (100%) mode change 100755 => 100644 diff --git a/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated.obj b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated.obj new file mode 100644 index 000000000..71127fa8a --- /dev/null +++ b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated.obj @@ -0,0 +1,178 @@ +# Visual Pinball table OBJ file +mtllib PrimitiveAnimated.mtl +o Table1 +v 0.000000 0.000000 -10.000000 +v 1000.000000 0.000000 -10.000000 +v 0.000000 2000.000000 -10.000000 +v 1000.000000 2000.000000 -10.000000 +vt 0.000000 1.000000 +vt 1.000000 1.000000 +vt 0.000000 0.000000 +vt 1.000000 0.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +usemtl Playfield +s 1 +f 4/4/4 2/2/2 1/1/1 +f 3/3/3 4/4/4 1/1/1 +o Wall001 +v 441.708527 1475.574097 -10.000000 +v 441.708527 1475.574097 -60.000000 +v 441.708527 1575.573975 -60.000000 +v 441.708527 1575.573975 -10.000000 +v 441.708527 1575.573975 -10.000000 +v 441.708527 1575.573975 -60.000000 +v 541.708618 1575.573975 -60.000000 +v 541.708618 1575.573975 -10.000000 +v 541.708618 1575.573975 -10.000000 +v 541.708618 1575.573975 -60.000000 +v 541.708618 1475.574097 -60.000000 +v 541.708618 1475.574097 -10.000000 +v 541.708618 1475.574097 -10.000000 +v 541.708618 1475.574097 -60.000000 +v 441.708527 1475.574097 -60.000000 +v 441.708527 1475.574097 -10.000000 +v 441.708527 1475.574097 -60.000000 +v 441.708527 1575.573975 -60.000000 +v 541.708618 1575.573975 -60.000000 +v 541.708618 1475.574097 -60.000000 +vt 0.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 1.000000 +vt 0.441709 0.262213 +vt 0.441709 0.212213 +vt 0.541709 0.212213 +vt 0.541709 0.262213 +vn -1.000000 -0.000000 -0.000000 +vn -1.000000 -0.000000 -0.000000 +vn -1.000000 -0.000000 -0.000000 +vn -1.000000 -0.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 1.000000 -0.000000 -0.000000 +vn 1.000000 -0.000000 -0.000000 +vn 1.000000 -0.000000 -0.000000 +vn 1.000000 -0.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +usemtl +s 1 +f 7/7/7 6/6/6 5/5/5 +f 8/8/8 7/7/7 5/5/5 +f 11/11/11 10/10/10 9/9/9 +f 12/12/12 11/11/11 9/9/9 +f 15/15/15 14/14/14 13/13/13 +f 16/16/16 15/15/15 13/13/13 +f 19/19/19 18/18/18 17/17/17 +f 20/20/20 19/19/19 17/17/17 +f 22/22/22 23/23/23 21/21/21 +f 23/23/23 24/24/24 21/21/21 +o AnimatedPrimitive +v 50.000000 50.000000 40.000000 +v -50.000000 50.000000 40.000000 +v -50.000000 50.000000 -60.000000 +v 50.000000 50.000000 -60.000000 +v 50.000000 -50.000000 -60.000000 +v 50.000000 50.000000 -60.000000 +v -50.000000 50.000000 -60.000000 +v -50.000000 -50.000000 -60.000000 +v -50.000000 -50.000000 -60.000000 +v -50.000000 50.000000 -60.000000 +v -50.000000 50.000000 40.000000 +v -50.000000 -50.000000 40.000000 +v -50.000000 -50.000000 40.000000 +v 50.000000 -50.000000 40.000000 +v 50.000000 -50.000000 -60.000000 +v -50.000000 -50.000000 -60.000000 +v 50.000000 -50.000000 40.000000 +v 50.000000 50.000000 40.000000 +v 50.000000 50.000000 -60.000000 +v 50.000000 -50.000000 -60.000000 +v -50.000000 -50.000000 40.000000 +v -50.000000 50.000000 40.000000 +v 50.000000 50.000000 40.000000 +v 50.000000 -50.000000 40.000000 +vt 0.375000 1.000000 +vt 0.625000 1.000000 +vt 0.625000 0.750000 +vt 0.375000 0.750000 +vt 0.375000 0.750000 +vt 0.625000 0.750000 +vt 0.625000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.500000 +vt 0.625000 0.500000 +vt 0.625000 0.250000 +vt 0.375000 0.250000 +vt 0.375000 0.250000 +vt 0.625000 0.250000 +vt 0.625000 0.000000 +vt 0.375000 0.000000 +vt 0.125000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.250000 +vt 0.125000 0.250000 +vt 0.625000 0.500000 +vt 0.875000 0.500000 +vt 0.875000 0.250000 +vt 0.625000 0.250000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +usemtl +f 27/27/27 26/26/26 25/25/25 +f 28/28/28 27/27/27 25/25/25 +f 31/31/31 30/30/30 29/29/29 +f 32/32/32 31/31/31 29/29/29 +f 35/35/35 34/34/34 33/33/33 +f 36/36/36 35/35/35 33/33/33 +f 39/39/39 38/38/38 37/37/37 +f 40/40/40 39/39/39 37/37/37 +f 43/43/43 42/42/42 41/41/41 +f 44/44/44 43/43/43 41/41/41 +f 47/47/47 46/46/46 45/45/45 +f 48/48/48 47/47/47 45/45/45 diff --git a/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated.vpx b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated.vpx new file mode 100644 index 0000000000000000000000000000000000000000..7ec018a0835a8d9f0982d65b7d730ea0db682ccd GIT binary patch literal 32768 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 GLEwM=6qLOH literal 0 HcmV?d00001 diff --git a/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00000.obj b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00000.obj new file mode 100644 index 000000000..50e8785f8 --- /dev/null +++ b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00000.obj @@ -0,0 +1,89 @@ +# Visual Pinball table OBJ file +mtllib PrimitiveAnimated_00000.mtl +# Visual Pinball OBJ file +# numVerts: 24 numFaces: 36 +o AnimatedPrimitive +v 50.000000 50.000000 50.000000 +v -50.000000 50.000000 50.000000 +v -50.000000 50.000000 -50.000000 +v 50.000000 50.000000 -50.000000 +v 50.000000 -50.000000 -50.000000 +v 50.000000 50.000000 -50.000000 +v -50.000000 50.000000 -50.000000 +v -50.000000 -50.000000 -50.000000 +v -50.000000 -50.000000 -50.000000 +v -50.000000 50.000000 -50.000000 +v -50.000000 50.000000 50.000000 +v -50.000000 -50.000000 50.000000 +v -50.000000 -50.000000 50.000000 +v 50.000000 -50.000000 50.000000 +v 50.000000 -50.000000 -50.000000 +v -50.000000 -50.000000 -50.000000 +v 50.000000 -50.000000 50.000000 +v 50.000000 50.000000 50.000000 +v 50.000000 50.000000 -50.000000 +v 50.000000 -50.000000 -50.000000 +v -50.000000 -50.000000 50.000000 +v -50.000000 50.000000 50.000000 +v 50.000000 50.000000 50.000000 +v 50.000000 -50.000000 50.000000 +vt 0.375000 1.000000 +vt 0.625000 1.000000 +vt 0.625000 0.750000 +vt 0.375000 0.750000 +vt 0.375000 0.750000 +vt 0.625000 0.750000 +vt 0.625000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.500000 +vt 0.625000 0.500000 +vt 0.625000 0.250000 +vt 0.375000 0.250000 +vt 0.375000 0.250000 +vt 0.625000 0.250000 +vt 0.625000 0.000000 +vt 0.375000 0.000000 +vt 0.125000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.250000 +vt 0.125000 0.250000 +vt 0.625000 0.500000 +vt 0.875000 0.500000 +vt 0.875000 0.250000 +vt 0.625000 0.250000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +f 3/3/3 2/2/2 1/1/1 +f 4/4/4 3/3/3 1/1/1 +f 7/7/7 6/6/6 5/5/5 +f 8/8/8 7/7/7 5/5/5 +f 11/11/11 10/10/10 9/9/9 +f 12/12/12 11/11/11 9/9/9 +f 15/15/15 14/14/14 13/13/13 +f 16/16/16 15/15/15 13/13/13 +f 19/19/19 18/18/18 17/17/17 +f 20/20/20 19/19/19 17/17/17 +f 23/23/23 22/22/22 21/21/21 +f 24/24/24 23/23/23 21/21/21 diff --git a/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00001.obj b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00001.obj new file mode 100644 index 000000000..de4ee01d8 --- /dev/null +++ b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00001.obj @@ -0,0 +1,89 @@ +# Visual Pinball table OBJ file +mtllib PrimitiveAnimated_00001.mtl +# Visual Pinball OBJ file +# numVerts: 24 numFaces: 36 +o AnimatedPrimitive +v 100.000000 50.000000 50.000000 +v -100.000000 50.000000 50.000000 +v -100.000000 50.000000 -50.000000 +v 100.000000 50.000000 -50.000000 +v 100.000000 -50.000000 -50.000000 +v 100.000000 50.000000 -50.000000 +v -100.000000 50.000000 -50.000000 +v -100.000000 -50.000000 -50.000000 +v -100.000000 -50.000000 -50.000000 +v -100.000000 50.000000 -50.000000 +v -100.000000 50.000000 50.000000 +v -100.000000 -50.000000 50.000000 +v -100.000000 -50.000000 50.000000 +v 100.000000 -50.000000 50.000000 +v 100.000000 -50.000000 -50.000000 +v -100.000000 -50.000000 -50.000000 +v 100.000000 -50.000000 50.000000 +v 100.000000 50.000000 50.000000 +v 100.000000 50.000000 -50.000000 +v 100.000000 -50.000000 -50.000000 +v -100.000000 -50.000000 50.000000 +v -100.000000 50.000000 50.000000 +v 100.000000 50.000000 50.000000 +v 100.000000 -50.000000 50.000000 +vt 0.375000 1.000000 +vt 0.625000 1.000000 +vt 0.625000 0.750000 +vt 0.375000 0.750000 +vt 0.375000 0.750000 +vt 0.625000 0.750000 +vt 0.625000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.500000 +vt 0.625000 0.500000 +vt 0.625000 0.250000 +vt 0.375000 0.250000 +vt 0.375000 0.250000 +vt 0.625000 0.250000 +vt 0.625000 0.000000 +vt 0.375000 0.000000 +vt 0.125000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.250000 +vt 0.125000 0.250000 +vt 0.625000 0.500000 +vt 0.875000 0.500000 +vt 0.875000 0.250000 +vt 0.625000 0.250000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +f 3/3/3 2/2/2 1/1/1 +f 4/4/4 3/3/3 1/1/1 +f 7/7/7 6/6/6 5/5/5 +f 8/8/8 7/7/7 5/5/5 +f 11/11/11 10/10/10 9/9/9 +f 12/12/12 11/11/11 9/9/9 +f 15/15/15 14/14/14 13/13/13 +f 16/16/16 15/15/15 13/13/13 +f 19/19/19 18/18/18 17/17/17 +f 20/20/20 19/19/19 17/17/17 +f 23/23/23 22/22/22 21/21/21 +f 24/24/24 23/23/23 21/21/21 diff --git a/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00002.obj b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00002.obj new file mode 100644 index 000000000..c26978cec --- /dev/null +++ b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00002.obj @@ -0,0 +1,89 @@ +# Visual Pinball table OBJ file +mtllib PrimitiveAnimated_00002.mtl +# Visual Pinball OBJ file +# numVerts: 24 numFaces: 36 +o AnimatedPrimitive +v 50.000000 50.000000 50.000000 +v -50.000000 50.000000 50.000000 +v -50.000000 50.000000 -50.000000 +v 50.000000 50.000000 -50.000000 +v 50.000000 -50.000000 -50.000000 +v 50.000000 50.000000 -50.000000 +v -50.000000 50.000000 -50.000000 +v -50.000000 -50.000000 -50.000000 +v -50.000000 -50.000000 -50.000000 +v -50.000000 50.000000 -50.000000 +v -50.000000 50.000000 50.000000 +v -50.000000 -50.000000 50.000000 +v -50.000000 -50.000000 50.000000 +v 50.000000 -50.000000 50.000000 +v 50.000000 -50.000000 -50.000000 +v -50.000000 -50.000000 -50.000000 +v 50.000000 -50.000000 50.000000 +v 50.000000 50.000000 50.000000 +v 50.000000 50.000000 -50.000000 +v 50.000000 -50.000000 -50.000000 +v -50.000000 -50.000000 50.000000 +v -50.000000 50.000000 50.000000 +v 50.000000 50.000000 50.000000 +v 50.000000 -50.000000 50.000000 +vt 0.375000 1.000000 +vt 0.625000 1.000000 +vt 0.625000 0.750000 +vt 0.375000 0.750000 +vt 0.375000 0.750000 +vt 0.625000 0.750000 +vt 0.625000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.500000 +vt 0.625000 0.500000 +vt 0.625000 0.250000 +vt 0.375000 0.250000 +vt 0.375000 0.250000 +vt 0.625000 0.250000 +vt 0.625000 0.000000 +vt 0.375000 0.000000 +vt 0.125000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.250000 +vt 0.125000 0.250000 +vt 0.625000 0.500000 +vt 0.875000 0.500000 +vt 0.875000 0.250000 +vt 0.625000 0.250000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +f 3/3/3 2/2/2 1/1/1 +f 4/4/4 3/3/3 1/1/1 +f 7/7/7 6/6/6 5/5/5 +f 8/8/8 7/7/7 5/5/5 +f 11/11/11 10/10/10 9/9/9 +f 12/12/12 11/11/11 9/9/9 +f 15/15/15 14/14/14 13/13/13 +f 16/16/16 15/15/15 13/13/13 +f 19/19/19 18/18/18 17/17/17 +f 20/20/20 19/19/19 17/17/17 +f 23/23/23 22/22/22 21/21/21 +f 24/24/24 23/23/23 21/21/21 diff --git a/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00003.obj b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00003.obj new file mode 100644 index 000000000..16a203ee3 --- /dev/null +++ b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00003.obj @@ -0,0 +1,89 @@ +# Visual Pinball table OBJ file +mtllib PrimitiveAnimated_00003.mtl +# Visual Pinball OBJ file +# numVerts: 24 numFaces: 36 +o AnimatedPrimitive +v 50.000000 50.000000 100.000000 +v -50.000000 50.000000 100.000000 +v -50.000000 50.000000 -100.000000 +v 50.000000 50.000000 -100.000000 +v 50.000000 -50.000000 -100.000000 +v 50.000000 50.000000 -100.000000 +v -50.000000 50.000000 -100.000000 +v -50.000000 -50.000000 -100.000000 +v -50.000000 -50.000000 -100.000000 +v -50.000000 50.000000 -100.000000 +v -50.000000 50.000000 100.000000 +v -50.000000 -50.000000 100.000000 +v -50.000000 -50.000000 100.000000 +v 50.000000 -50.000000 100.000000 +v 50.000000 -50.000000 -100.000000 +v -50.000000 -50.000000 -100.000000 +v 50.000000 -50.000000 100.000000 +v 50.000000 50.000000 100.000000 +v 50.000000 50.000000 -100.000000 +v 50.000000 -50.000000 -100.000000 +v -50.000000 -50.000000 100.000000 +v -50.000000 50.000000 100.000000 +v 50.000000 50.000000 100.000000 +v 50.000000 -50.000000 100.000000 +vt 0.375000 1.000000 +vt 0.625000 1.000000 +vt 0.625000 0.750000 +vt 0.375000 0.750000 +vt 0.375000 0.750000 +vt 0.625000 0.750000 +vt 0.625000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.500000 +vt 0.625000 0.500000 +vt 0.625000 0.250000 +vt 0.375000 0.250000 +vt 0.375000 0.250000 +vt 0.625000 0.250000 +vt 0.625000 0.000000 +vt 0.375000 0.000000 +vt 0.125000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.250000 +vt 0.125000 0.250000 +vt 0.625000 0.500000 +vt 0.875000 0.500000 +vt 0.875000 0.250000 +vt 0.625000 0.250000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +f 3/3/3 2/2/2 1/1/1 +f 4/4/4 3/3/3 1/1/1 +f 7/7/7 6/6/6 5/5/5 +f 8/8/8 7/7/7 5/5/5 +f 11/11/11 10/10/10 9/9/9 +f 12/12/12 11/11/11 9/9/9 +f 15/15/15 14/14/14 13/13/13 +f 16/16/16 15/15/15 13/13/13 +f 19/19/19 18/18/18 17/17/17 +f 20/20/20 19/19/19 17/17/17 +f 23/23/23 22/22/22 21/21/21 +f 24/24/24 23/23/23 21/21/21 diff --git a/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00004.obj b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00004.obj new file mode 100644 index 000000000..7db92d0c9 --- /dev/null +++ b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00004.obj @@ -0,0 +1,89 @@ +# Visual Pinball table OBJ file +mtllib PrimitiveAnimated_00004.mtl +# Visual Pinball OBJ file +# numVerts: 24 numFaces: 36 +o AnimatedPrimitive +v 50.000000 50.000000 50.000000 +v -50.000000 50.000000 50.000000 +v -50.000000 50.000000 -50.000000 +v 50.000000 50.000000 -50.000000 +v 50.000000 -50.000000 -50.000000 +v 50.000000 50.000000 -50.000000 +v -50.000000 50.000000 -50.000000 +v -50.000000 -50.000000 -50.000000 +v -50.000000 -50.000000 -50.000000 +v -50.000000 50.000000 -50.000000 +v -50.000000 50.000000 50.000000 +v -50.000000 -50.000000 50.000000 +v -50.000000 -50.000000 50.000000 +v 50.000000 -50.000000 50.000000 +v 50.000000 -50.000000 -50.000000 +v -50.000000 -50.000000 -50.000000 +v 50.000000 -50.000000 50.000000 +v 50.000000 50.000000 50.000000 +v 50.000000 50.000000 -50.000000 +v 50.000000 -50.000000 -50.000000 +v -50.000000 -50.000000 50.000000 +v -50.000000 50.000000 50.000000 +v 50.000000 50.000000 50.000000 +v 50.000000 -50.000000 50.000000 +vt 0.375000 1.000000 +vt 0.625000 1.000000 +vt 0.625000 0.750000 +vt 0.375000 0.750000 +vt 0.375000 0.750000 +vt 0.625000 0.750000 +vt 0.625000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.500000 +vt 0.625000 0.500000 +vt 0.625000 0.250000 +vt 0.375000 0.250000 +vt 0.375000 0.250000 +vt 0.625000 0.250000 +vt 0.625000 0.000000 +vt 0.375000 0.000000 +vt 0.125000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.250000 +vt 0.125000 0.250000 +vt 0.625000 0.500000 +vt 0.875000 0.500000 +vt 0.875000 0.250000 +vt 0.625000 0.250000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +f 3/3/3 2/2/2 1/1/1 +f 4/4/4 3/3/3 1/1/1 +f 7/7/7 6/6/6 5/5/5 +f 8/8/8 7/7/7 5/5/5 +f 11/11/11 10/10/10 9/9/9 +f 12/12/12 11/11/11 9/9/9 +f 15/15/15 14/14/14 13/13/13 +f 16/16/16 15/15/15 13/13/13 +f 19/19/19 18/18/18 17/17/17 +f 20/20/20 19/19/19 17/17/17 +f 23/23/23 22/22/22 21/21/21 +f 24/24/24 23/23/23 21/21/21 diff --git a/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00005.obj b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00005.obj new file mode 100644 index 000000000..98eec4eee --- /dev/null +++ b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00005.obj @@ -0,0 +1,89 @@ +# Visual Pinball table OBJ file +mtllib PrimitiveAnimated_00005.mtl +# Visual Pinball OBJ file +# numVerts: 24 numFaces: 36 +o AnimatedPrimitive +v 50.000000 100.000000 50.000000 +v -50.000000 100.000000 50.000000 +v -50.000000 100.000000 -50.000000 +v 50.000000 100.000000 -50.000000 +v 50.000000 -100.000000 -50.000000 +v 50.000000 100.000000 -50.000000 +v -50.000000 100.000000 -50.000000 +v -50.000000 -100.000000 -50.000000 +v -50.000000 -100.000000 -50.000000 +v -50.000000 100.000000 -50.000000 +v -50.000000 100.000000 50.000000 +v -50.000000 -100.000000 50.000000 +v -50.000000 -100.000000 50.000000 +v 50.000000 -100.000000 50.000000 +v 50.000000 -100.000000 -50.000000 +v -50.000000 -100.000000 -50.000000 +v 50.000000 -100.000000 50.000000 +v 50.000000 100.000000 50.000000 +v 50.000000 100.000000 -50.000000 +v 50.000000 -100.000000 -50.000000 +v -50.000000 -100.000000 50.000000 +v -50.000000 100.000000 50.000000 +v 50.000000 100.000000 50.000000 +v 50.000000 -100.000000 50.000000 +vt 0.375000 1.000000 +vt 0.625000 1.000000 +vt 0.625000 0.750000 +vt 0.375000 0.750000 +vt 0.375000 0.750000 +vt 0.625000 0.750000 +vt 0.625000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.500000 +vt 0.625000 0.500000 +vt 0.625000 0.250000 +vt 0.375000 0.250000 +vt 0.375000 0.250000 +vt 0.625000 0.250000 +vt 0.625000 0.000000 +vt 0.375000 0.000000 +vt 0.125000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.250000 +vt 0.125000 0.250000 +vt 0.625000 0.500000 +vt 0.875000 0.500000 +vt 0.875000 0.250000 +vt 0.625000 0.250000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +f 3/3/3 2/2/2 1/1/1 +f 4/4/4 3/3/3 1/1/1 +f 7/7/7 6/6/6 5/5/5 +f 8/8/8 7/7/7 5/5/5 +f 11/11/11 10/10/10 9/9/9 +f 12/12/12 11/11/11 9/9/9 +f 15/15/15 14/14/14 13/13/13 +f 16/16/16 15/15/15 13/13/13 +f 19/19/19 18/18/18 17/17/17 +f 20/20/20 19/19/19 17/17/17 +f 23/23/23 22/22/22 21/21/21 +f 24/24/24 23/23/23 21/21/21 diff --git a/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00006.obj b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00006.obj new file mode 100644 index 000000000..981c4e861 --- /dev/null +++ b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_00006.obj @@ -0,0 +1,89 @@ +# Visual Pinball table OBJ file +mtllib PrimitiveAnimated_00006.mtl +# Visual Pinball OBJ file +# numVerts: 24 numFaces: 36 +o AnimatedPrimitive +v 50.000000 50.000000 50.000000 +v -50.000000 50.000000 50.000000 +v -50.000000 50.000000 -50.000000 +v 50.000000 50.000000 -50.000000 +v 50.000000 -50.000000 -50.000000 +v 50.000000 50.000000 -50.000000 +v -50.000000 50.000000 -50.000000 +v -50.000000 -50.000000 -50.000000 +v -50.000000 -50.000000 -50.000000 +v -50.000000 50.000000 -50.000000 +v -50.000000 50.000000 50.000000 +v -50.000000 -50.000000 50.000000 +v -50.000000 -50.000000 50.000000 +v 50.000000 -50.000000 50.000000 +v 50.000000 -50.000000 -50.000000 +v -50.000000 -50.000000 -50.000000 +v 50.000000 -50.000000 50.000000 +v 50.000000 50.000000 50.000000 +v 50.000000 50.000000 -50.000000 +v 50.000000 -50.000000 -50.000000 +v -50.000000 -50.000000 50.000000 +v -50.000000 50.000000 50.000000 +v 50.000000 50.000000 50.000000 +v 50.000000 -50.000000 50.000000 +vt 0.375000 1.000000 +vt 0.625000 1.000000 +vt 0.625000 0.750000 +vt 0.375000 0.750000 +vt 0.375000 0.750000 +vt 0.625000 0.750000 +vt 0.625000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.500000 +vt 0.625000 0.500000 +vt 0.625000 0.250000 +vt 0.375000 0.250000 +vt 0.375000 0.250000 +vt 0.625000 0.250000 +vt 0.625000 0.000000 +vt 0.375000 0.000000 +vt 0.125000 0.500000 +vt 0.375000 0.500000 +vt 0.375000 0.250000 +vt 0.125000 0.250000 +vt 0.625000 0.500000 +vt 0.875000 0.500000 +vt 0.875000 0.250000 +vt 0.625000 0.250000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 0.000000 -1.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn -1.000000 0.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 1.000000 0.000000 -0.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 1.000000 +f 3/3/3 2/2/2 1/1/1 +f 4/4/4 3/3/3 1/1/1 +f 7/7/7 6/6/6 5/5/5 +f 8/8/8 7/7/7 5/5/5 +f 11/11/11 10/10/10 9/9/9 +f 12/12/12 11/11/11 9/9/9 +f 15/15/15 14/14/14 13/13/13 +f 16/16/16 15/15/15 13/13/13 +f 19/19/19 18/18/18 17/17/17 +f 20/20/20 19/19/19 17/17/17 +f 23/23/23 22/22/22 21/21/21 +f 24/24/24 23/23/23 21/21/21 diff --git a/VisualPinball.Engine.Test/Fixtures~/cube_0.obj b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_Src_0.obj old mode 100755 new mode 100644 similarity index 100% rename from VisualPinball.Engine.Test/Fixtures~/cube_0.obj rename to VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_Src_0.obj diff --git a/VisualPinball.Engine.Test/Fixtures~/cube_1.obj b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_Src_1.obj old mode 100755 new mode 100644 similarity index 100% rename from VisualPinball.Engine.Test/Fixtures~/cube_1.obj rename to VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_Src_1.obj diff --git a/VisualPinball.Engine.Test/Fixtures~/cube_2.obj b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_Src_2.obj old mode 100755 new mode 100644 similarity index 100% rename from VisualPinball.Engine.Test/Fixtures~/cube_2.obj rename to VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_Src_2.obj diff --git a/VisualPinball.Engine.Test/Fixtures~/cube_3.obj b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_Src_3.obj old mode 100755 new mode 100644 similarity index 100% rename from VisualPinball.Engine.Test/Fixtures~/cube_3.obj rename to VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_Src_3.obj diff --git a/VisualPinball.Engine.Test/Fixtures~/cube_4.obj b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_Src_4.obj old mode 100755 new mode 100644 similarity index 100% rename from VisualPinball.Engine.Test/Fixtures~/cube_4.obj rename to VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_Src_4.obj diff --git a/VisualPinball.Engine.Test/Fixtures~/cube_5.obj b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_Src_5.obj old mode 100755 new mode 100644 similarity index 100% rename from VisualPinball.Engine.Test/Fixtures~/cube_5.obj rename to VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_Src_5.obj diff --git a/VisualPinball.Engine.Test/Fixtures~/cube_6.obj b/VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_Src_6.obj old mode 100755 new mode 100644 similarity index 100% rename from VisualPinball.Engine.Test/Fixtures~/cube_6.obj rename to VisualPinball.Engine.Test/Fixtures~/PrimitiveAnimated_Src_6.obj diff --git a/VisualPinball.Engine.Test/Test/Fixtures.cs b/VisualPinball.Engine.Test/Test/Fixtures.cs index 0c63d6efd..072b641d8 100644 --- a/VisualPinball.Engine.Test/Test/Fixtures.cs +++ b/VisualPinball.Engine.Test/Test/Fixtures.cs @@ -21,6 +21,7 @@ public static class VpxPath public static readonly string MaterialTexture = PathHelper.GetFixturePath("MaterialTextureTest.vpx"); public static readonly string Plunger = PathHelper.GetFixturePath("PlungerTest.vpx"); public static readonly string Primitive = PathHelper.GetFixturePath("PrimitiveTest.vpx"); + public static readonly string PrimitiveAnimated = PathHelper.GetFixturePath("PrimitiveAnimated.vpx"); public static readonly string PrimitiveCompressed = PathHelper.GetFixturePath("PrimitiveCompressed.vpx"); public static readonly string Ramp = PathHelper.GetFixturePath("RampTest.vpx"); public static readonly string Rubber = PathHelper.GetFixturePath("RubberTest.vpx"); @@ -43,6 +44,15 @@ public static class ObjPath public static readonly string HitTarget = PathHelper.GetFixturePath("HitTargetTest.obj"); public static readonly string Kicker = PathHelper.GetFixturePath("KickerTest.obj"); public static readonly string Primitive = PathHelper.GetFixturePath("PrimitiveTest.obj"); + public static readonly string[] PrimitiveAnimated = { + PathHelper.GetFixturePath("PrimitiveAnimated_00000.obj"), + PathHelper.GetFixturePath("PrimitiveAnimated_00001.obj"), + PathHelper.GetFixturePath("PrimitiveAnimated_00002.obj"), + PathHelper.GetFixturePath("PrimitiveAnimated_00003.obj"), + PathHelper.GetFixturePath("PrimitiveAnimated_00004.obj"), + PathHelper.GetFixturePath("PrimitiveAnimated_00005.obj"), + PathHelper.GetFixturePath("PrimitiveAnimated_00006.obj") + }; public static readonly string PrimitiveCompressed = PathHelper.GetFixturePath("PrimitiveCompressed.obj"); public static readonly string Ramp = PathHelper.GetFixturePath("RampTest.obj"); public static readonly string Rubber = PathHelper.GetFixturePath("RubberTest.obj"); diff --git a/VisualPinball.Engine.Test/Test/MeshTests.cs b/VisualPinball.Engine.Test/Test/MeshTests.cs index 2c251ec04..a08b1d990 100644 --- a/VisualPinball.Engine.Test/Test/MeshTests.cs +++ b/VisualPinball.Engine.Test/Test/MeshTests.cs @@ -63,7 +63,7 @@ protected static void AssertObjMesh(ObjFile objFile, string name, Mesh[] meshes, } } - protected static void AssertObjMesh(ObjFile objFile, Mesh mesh, string name = null, float threshold = Threshold) + protected static void AssertObjMesh(ObjFile objFile, Mesh mesh, string name = null, float threshold = Threshold, bool switchZ = false) { name = name ?? mesh.Name; var objGroup = objFile.Groups.FirstOrDefault(g => g.Name == name); @@ -72,9 +72,9 @@ protected static void AssertObjMesh(ObjFile objFile, Mesh mesh, string name = nu } var i = 0; foreach (var face in objGroup.Faces) { - AssertVerticesEqual(objFile.Vertices[face.Vertices[2].Vertex - 1].Position, mesh.Vertices[mesh.Indices[i]], threshold); - AssertVerticesEqual(objFile.Vertices[face.Vertices[1].Vertex - 1].Position, mesh.Vertices[mesh.Indices[i + 1]], threshold); - AssertVerticesEqual(objFile.Vertices[face.Vertices[0].Vertex - 1].Position, mesh.Vertices[mesh.Indices[i + 2]], threshold); + AssertVerticesEqual(objFile.Vertices[face.Vertices[2].Vertex - 1].Position, mesh.Vertices[mesh.Indices[i]], threshold, switchZ); + AssertVerticesEqual(objFile.Vertices[face.Vertices[1].Vertex - 1].Position, mesh.Vertices[mesh.Indices[i + 1]], threshold, switchZ); + AssertVerticesEqual(objFile.Vertices[face.Vertices[0].Vertex - 1].Position, mesh.Vertices[mesh.Indices[i + 2]], threshold, switchZ); i += 3; } @@ -88,11 +88,12 @@ protected static void AssertNoObjMesh(ObjFile objFile, string name) } } - private static void AssertVerticesEqual(ObjVector4 expected, Vertex3DNoTex2 actual, float threshold) + private static void AssertVerticesEqual(ObjVector4 expected, Vertex3DNoTex2 actual, float threshold, bool switchZ = false) { + var sign = switchZ ? -1 : 1; actual.X.Should().BeApproximately(expected.X, threshold); actual.Y.Should().BeApproximately(expected.Y, threshold); - actual.Z.Should().BeApproximately(expected.Z, threshold); + actual.Z.Should().BeApproximately(sign * expected.Z, threshold); } } } diff --git a/VisualPinball.Engine.Test/VPT/Primitive/PrimitiveMeshTests.cs b/VisualPinball.Engine.Test/VPT/Primitive/PrimitiveMeshTests.cs index 74f491434..6df73f1cd 100644 --- a/VisualPinball.Engine.Test/VPT/Primitive/PrimitiveMeshTests.cs +++ b/VisualPinball.Engine.Test/VPT/Primitive/PrimitiveMeshTests.cs @@ -1,8 +1,10 @@ -using FluentAssertions; +using System.Linq; +using FluentAssertions; using JeremyAnsel.Media.WavefrontObj; using NUnit.Framework; using VisualPinball.Engine.Game; using VisualPinball.Engine.Test.Test; +using VisualPinball.Engine.VPT; namespace VisualPinball.Engine.Test.VPT.Primitive { @@ -58,8 +60,27 @@ public void ShouldGenerateACompressedMesh() var table = Engine.VPT.Table.Table.Load(VpxPath.PrimitiveCompressed); var obj = LoadObjFixture(ObjPath.PrimitiveCompressed); - var compressedMesh = table.Primitive("compressed").GetRenderObjects(_table).RenderObjects[0].Mesh; + var compressedMesh = table.Primitive("compressed").GetRenderObjects(table).RenderObjects[0].Mesh; AssertObjMesh(obj, compressedMesh, threshold: 0.00015f); } + + [Test] + public void ShouldGenerateAnAnimatedMesh() { + var table = Engine.VPT.Table.Table.Load(VpxPath.PrimitiveAnimated); + + var animatedPrimitive = table.Primitive("AnimatedPrimitive"); + var mesh = animatedPrimitive.GetMesh(); + + for (var i = 0; i < 7; i++) { + var obj = LoadObjFixture(ObjPath.PrimitiveAnimated[i]); + var frame = mesh.AnimationFrames[i]; + var frameMesh = new Mesh( + frame.Select(v => v.ToVertex3DNoTex2()).ToArray(), + mesh.Indices + ); + + AssertObjMesh(obj, frameMesh, "AnimatedPrimitive", switchZ: true); + } + } } } diff --git a/VisualPinball.Engine/VPT/Mesh.cs b/VisualPinball.Engine/VPT/Mesh.cs index 6da26f6db..8cf754a6c 100644 --- a/VisualPinball.Engine/VPT/Mesh.cs +++ b/VisualPinball.Engine/VPT/Mesh.cs @@ -417,6 +417,11 @@ public override string ToString() { return $"VertData({X}/{Y}/{Z}, {Nx}/{Ny}/{Nz})"; } + + public Vertex3DNoTex2 ToVertex3DNoTex2() + { + return new Vertex3DNoTex2(X, Y, Z, Nx, Ny, Nz, 0f, 0f); + } } #endregion From d81d22d0df5377cba5ed738062d3a58fa0aa42b7 Mon Sep 17 00:00:00 2001 From: freezy Date: Sun, 30 Aug 2020 15:49:18 +0200 Subject: [PATCH 010/124] project: Add Microsoft.NET.Test.Sdk to test project. --- VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj b/VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj index 8077a11bc..cdf4e2c7f 100644 --- a/VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj +++ b/VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj @@ -24,6 +24,7 @@ + From b687bd5a87d4d35f3245192bacf2c5162e2e49c9 Mon Sep 17 00:00:00 2001 From: freezy Date: Sun, 30 Aug 2020 22:07:58 +0200 Subject: [PATCH 011/124] project: Update authors. --- VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj | 2 +- VisualPinball.Engine/VisualPinball.Engine.csproj | 2 +- VisualPinball.Resources/VisualPinball.Resources.csproj | 2 +- .../VisualPinball.Unity.Editor.csproj | 2 +- .../VisualPinball.Unity.Patcher.csproj | 2 +- .../VisualPinball.Unity.Test/VisualPinball.Unity.Test.csproj | 2 +- .../VisualPinball.Unity/VisualPinball.Unity.csproj | 2 +- package.json | 4 +++- 8 files changed, 10 insertions(+), 8 deletions(-) diff --git a/VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj b/VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj index cdf4e2c7f..0815ea4e3 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 + freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz Copyright 2020 freezy - <freezy@vpdb.io> 0.1.0.0 0.1.0.0 diff --git a/VisualPinball.Engine/VisualPinball.Engine.csproj b/VisualPinball.Engine/VisualPinball.Engine.csproj index c0ca16d93..a203f5d28 100644 --- a/VisualPinball.Engine/VisualPinball.Engine.csproj +++ b/VisualPinball.Engine/VisualPinball.Engine.csproj @@ -5,7 +5,7 @@ true VisualPinball.Engine A .NET port of Visual Pinball in C# - freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan + freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz Copyright 2020 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 4217f33a6..f24bfa0c3 100644 --- a/VisualPinball.Resources/VisualPinball.Resources.csproj +++ b/VisualPinball.Resources/VisualPinball.Resources.csproj @@ -3,7 +3,7 @@ netstandard2.0 VisualPinball.Resources A .NET port of Visual Pinball in C# - freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke + freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz Copyright 2020 freezy - <freezy@vpdb.io> 0.1.0.0 0.1.0.0 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VisualPinball.Unity.Editor.csproj b/VisualPinball.Unity/VisualPinball.Unity.Editor/VisualPinball.Unity.Editor.csproj index 90f63d73c..560a0ffbe 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.0 VisualPinball.Unity.Editor A bridge between VisualPinball.Engine and Unity - freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke + freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz Copyright 2020 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 c65487832..c567986af 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.0 VisualPinball.Unity.Patcher A bridge between VisualPinball.Engine and Unity - freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke + freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz Copyright 2020 freezy - <freezy@vpdb.io> 0.1.0.0 0.1.0.0 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Test/VisualPinball.Unity.Test.csproj b/VisualPinball.Unity/VisualPinball.Unity.Test/VisualPinball.Unity.Test.csproj index 0a028fa0c..4dbec3c25 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 + freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz Copyright 2020 freezy - <freezy@vpdb.io> 0.1.0.0 0.1.0.0 diff --git a/VisualPinball.Unity/VisualPinball.Unity/VisualPinball.Unity.csproj b/VisualPinball.Unity/VisualPinball.Unity/VisualPinball.Unity.csproj index 777b70bfb..5760d5120 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VisualPinball.Unity.csproj +++ b/VisualPinball.Unity/VisualPinball.Unity/VisualPinball.Unity.csproj @@ -3,7 +3,7 @@ netstandard2.0 VisualPinball.Unity A bridge between VisualPinball.Engine and Unity - freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke + freezy;ravarcade;shaderbytes;rbxnk;jsm174;Vroonsh;Rowlan;kleisauke;ecurtz Copyright 2020 freezy - <freezy@vpdb.io> 0.1.0.0 0.1.0.0 diff --git a/package.json b/package.json index 7f4b433aa..389694959 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,8 @@ "jsm174 ", "Roger Bocksnick ", "VrôÕnsh ", - "Rowlan" + "Rowlan", + "Kleis Auke Wolthuizen ", + "Eli Curtz " ] } From 67428979eb232b9eac59bb946f4869c3640d9443 Mon Sep 17 00:00:00 2001 From: Eli Curtz Date: Sat, 3 Oct 2020 16:34:43 -0700 Subject: [PATCH 012/124] Moved game object to item name compare from EditorApplication.hierarchyChanged to OnPreInspectorGUI --- .../Inspectors/ItemInspector.cs | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/ItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/ItemInspector.cs index 009c3c472..1ce665d38 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/ItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/ItemInspector.cs @@ -21,13 +21,11 @@ protected virtual void OnEnable() { _table = (target as MonoBehaviour)?.gameObject.GetComponentInParent(); PopulateDropDownOptions(); - EditorApplication.hierarchyChanged += OnHierarchyChange; } protected virtual void OnDisable() { - EditorApplication.hierarchyChanged -= OnHierarchyChange; } - + protected void PopulateDropDownOptions() { if (_table == null) return; @@ -48,17 +46,6 @@ protected void PopulateDropDownOptions() } } - private void OnHierarchyChange() - { - if (target is MonoBehaviour bh && target is IIdentifiableItemAuthoring item && bh != null) { - if (item.Name != bh.gameObject.name) { - var oldName = item.Name; - item.Name = bh.gameObject.name; - ItemRenamed?.Invoke(item, oldName, bh.gameObject.name); - } - } - } - protected void OnPreInspectorGUI() { var item = (target as IEditableItemAuthoring); @@ -72,6 +59,14 @@ protected void OnPreInspectorGUI() item.IsLocked = newLock; SceneView.RepaintAll(); } + + if (target is IIdentifiableItemAuthoring identity && target is MonoBehaviour bh) { + if (identity.Name != bh.gameObject.name) { + var oldName = identity.Name; + identity.Name = bh.gameObject.name; + ItemRenamed?.Invoke(identity, oldName, bh.gameObject.name); + } + } } public override void OnInspectorGUI() From 344615395eff365433c2438f52b8f742f7bc172e Mon Sep 17 00:00:00 2001 From: Eli Curtz Date: Sat, 3 Oct 2020 17:01:24 -0700 Subject: [PATCH 013/124] Reverse local change to match upstream master --- VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj b/VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj index 0815ea4e3..73e449462 100644 --- a/VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj +++ b/VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj @@ -24,7 +24,6 @@ - From 4d0a4b7f9806f13e480f2f5daa6985842b41a0c4 Mon Sep 17 00:00:00 2001 From: Eli Curtz Date: Mon, 19 Oct 2020 17:35:00 -0700 Subject: [PATCH 014/124] Minimal boilerplate for new trough items. --- VisualPinball.Engine/VPT/ItemType.cs | 3 +- VisualPinball.Engine/VPT/Trough.meta | 8 ++ VisualPinball.Engine/VPT/Trough/Trough.cs | 39 ++++++++ .../VPT/Trough/Trough.cs.meta | 11 +++ VisualPinball.Engine/VPT/Trough/TroughData.cs | 92 +++++++++++++++++++ .../VPT/Trough/TroughData.cs.meta | 11 +++ .../Inspectors/TroughInspector.cs | 56 +++++++++++ .../Inspectors/TroughInspector.cs.meta | 11 +++ .../VisualPinball.Unity/VPT/Trough.meta | 8 ++ .../VPT/Trough/TroughApi.cs | 43 +++++++++ .../VPT/Trough/TroughApi.cs.meta | 11 +++ .../VPT/Trough/TroughAuthoring.cs | 70 ++++++++++++++ .../VPT/Trough/TroughAuthoring.cs.meta | 11 +++ .../VPT/Trough/TroughExtensions.cs | 32 +++++++ .../VPT/Trough/TroughExtensions.cs.meta | 11 +++ 15 files changed, 416 insertions(+), 1 deletion(-) create mode 100644 VisualPinball.Engine/VPT/Trough.meta create mode 100644 VisualPinball.Engine/VPT/Trough/Trough.cs create mode 100644 VisualPinball.Engine/VPT/Trough/Trough.cs.meta create mode 100644 VisualPinball.Engine/VPT/Trough/TroughData.cs create mode 100644 VisualPinball.Engine/VPT/Trough/TroughData.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TroughInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TroughInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Trough.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughApi.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughApi.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughExtensions.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughExtensions.cs.meta diff --git a/VisualPinball.Engine/VPT/ItemType.cs b/VisualPinball.Engine/VPT/ItemType.cs index 6546da8aa..73f69f1f7 100644 --- a/VisualPinball.Engine/VPT/ItemType.cs +++ b/VisualPinball.Engine/VPT/ItemType.cs @@ -49,7 +49,8 @@ public enum ItemType Flasher = 20, Rubber = 21, HitTarget = 22, - Count = 23, + Trough = 23, + Count = 24, Invalid = -1, // VPE internal diff --git a/VisualPinball.Engine/VPT/Trough.meta b/VisualPinball.Engine/VPT/Trough.meta new file mode 100644 index 000000000..d0ffa86e7 --- /dev/null +++ b/VisualPinball.Engine/VPT/Trough.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3fd1432f7bc694b779c7e8e0d9018022 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Engine/VPT/Trough/Trough.cs b/VisualPinball.Engine/VPT/Trough/Trough.cs new file mode 100644 index 000000000..4ab5bb8e2 --- /dev/null +++ b/VisualPinball.Engine/VPT/Trough/Trough.cs @@ -0,0 +1,39 @@ +// 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.IO; +using VisualPinball.Engine.Game; + +namespace VisualPinball.Engine.VPT.Trough +{ + public class Trough : Item, IRenderable + { + public override string ItemType => "Trough"; + + public Trough(TroughData data) : base(data) + { + } + + public Trough(BinaryReader reader, string itemName) : this(new TroughData(reader, itemName)) + { + } + + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) + { + return null; + } + } +} diff --git a/VisualPinball.Engine/VPT/Trough/Trough.cs.meta b/VisualPinball.Engine/VPT/Trough/Trough.cs.meta new file mode 100644 index 000000000..c25340d05 --- /dev/null +++ b/VisualPinball.Engine/VPT/Trough/Trough.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 359e5a55a56254a68931446a9b6d6e9a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Engine/VPT/Trough/TroughData.cs b/VisualPinball.Engine/VPT/Trough/TroughData.cs new file mode 100644 index 000000000..b86eab083 --- /dev/null +++ b/VisualPinball.Engine/VPT/Trough/TroughData.cs @@ -0,0 +1,92 @@ +// 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 . + +#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.Trough +{ + [Serializable] + public class TroughData : ItemData + { + public override string GetName() => Name; + public override void SetName(string name) { Name = name; } + + [BiffString("NAME", IsWideString = true, Pos = 9)] + public string Name; + + [BiffVertex("ENTR", Pos = 1)] + public Vertex2D Entrance; + + [BiffFloat("EXIT", Pos = 10)] + public float ExitOffset = 200.0f; + + [BiffFloat("ORIN", Pos = 10)] + public float Orientation = 0.0f; + + [BiffInt("BCNT", Pos = 3)] + public int BallCount = 3; + + [BiffInt("SCNT", Pos = 4)] + public int SwitchCount = 3; + + [BiffFloat("TIME", Pos = 5)] + public float SettleTime = 0.1f; + + [BiffFloat("FORC", Pos = 6)] + public float Force = 15f; + + [BiffFloat("BSCT", Pos = 7)] + public float Scatter = 0f; + + [BiffString("SURF", Pos = 16)] + public string Surface = string.Empty; + + #region BIFF + + static TroughData() + { + Init(typeof(TroughData), Attributes); + } + + public TroughData(BinaryReader reader, string storageName) : base(storageName) + { + Load(this, reader, Attributes); + } + + public override void Write(BinaryWriter writer, HashWriter hashWriter) + { + writer.Write((int)ItemType.Trough); + WriteRecord(writer, Attributes, hashWriter); + WriteEnd(writer, hashWriter); + } + + private static readonly Dictionary> Attributes = new Dictionary>(); + + #endregion + } +} diff --git a/VisualPinball.Engine/VPT/Trough/TroughData.cs.meta b/VisualPinball.Engine/VPT/Trough/TroughData.cs.meta new file mode 100644 index 000000000..6de4b2d57 --- /dev/null +++ b/VisualPinball.Engine/VPT/Trough/TroughData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 23d7577ef803444a88c18204c09da04b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TroughInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TroughInspector.cs new file mode 100644 index 000000000..27d9eca9e --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TroughInspector.cs @@ -0,0 +1,56 @@ +// 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 UnityEditor; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(TroughAuthoring))] + public class TroughInspector : ItemInspector + { + private TroughAuthoring _trough; + private bool _foldoutPosition = true; + private bool _foldoutMisc = true; + + protected override void OnEnable() + { + base.OnEnable(); + _trough = target as TroughAuthoring; + } + + public override void OnInspectorGUI() + { + OnPreInspectorGUI(); + + if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { + ItemDataField("", ref _trough.data.Entrance); + ItemDataField("Rotation", ref _trough.data.Orientation); + ItemDataField("Exit Offset", ref _trough.data.ExitOffset); + SurfaceField("Surface", ref _trough.data.Surface); + } + EditorGUILayout.EndFoldoutHeaderGroup(); + + if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { + ItemDataField("Max Balls", ref _trough.data.BallCount, dirtyMesh: false); + ItemDataField("Switch Count", ref _trough.data.SwitchCount, dirtyMesh: false); + ItemDataField("Settle Time", ref _trough.data.SettleTime, dirtyMesh: false); + } + EditorGUILayout.EndFoldoutHeaderGroup(); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TroughInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TroughInspector.cs.meta new file mode 100644 index 000000000..5f04f1680 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TroughInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f921351c72e0e4f6f99bbbf5bc8be9fa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough.meta new file mode 100644 index 000000000..61ae11faf --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 975c786b0dfc94e5085f535e38e194fa +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughApi.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughApi.cs new file mode 100644 index 000000000..ea02d49af --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughApi.cs @@ -0,0 +1,43 @@ +// 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; +using Unity.Entities; + +namespace VisualPinball.Unity +{ + public class TroughApi : ItemApi, + IApiInitializable + { + /// + /// Event emitted when the table is started. + /// + public event EventHandler Init; + + internal TroughApi(Engine.VPT.Trough.Trough item, Entity entity, Player player) : base(item, entity, player) + { + } + + #region Events + + void IApiInitializable.OnInit(BallManager ballManager) + { + Init?.Invoke(this, EventArgs.Empty); + } + + #endregion + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughApi.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughApi.cs.meta new file mode 100644 index 000000000..e0d3099e8 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughApi.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4020d37ef294341f0b853a9dadccb9a9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughAuthoring.cs new file mode 100644 index 000000000..d6d330541 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughAuthoring.cs @@ -0,0 +1,70 @@ +// 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 . + +#region ReSharper +// ReSharper disable CompareOfFloatsByEqualityOperator +// ReSharper disable ClassNeverInstantiated.Global +// ReSharper disable MemberCanBePrivate.Global +#endregion + +using System.Collections.Generic; +using Unity.Entities; +using UnityEngine; +using VisualPinball.Engine.Game; +using VisualPinball.Engine.Math; +using VisualPinball.Engine.VPT.Trough; + +namespace VisualPinball.Unity +{ + [ExecuteAlways] + [AddComponentMenu("Visual Pinball/Trough")] + public class TroughAuthoring : ItemAuthoring, IConvertGameObjectToEntity + { + protected override string[] Children => new[] { "Entrance", "Exit" }; + + protected override Trough GetItem() => new Trough(data); + + private void OnDestroy() + { + if (!Application.isPlaying) { + Table?.Remove(Name); + } + } + + public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) + { + //Convert(entity, dstManager); + //dstManager.AddComponentData(entity, new LineSlingshotData + //{ + // IsDisabled = false, + // Threshold = data.SlingshotThreshold, + //}); + //transform.GetComponentInParent().RegisterTrough(Item, entity, gameObject); + } + + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; + public override Vector3 GetEditorPosition() => data.Entrance.ToUnityVector3(0f); + public override void SetEditorPosition(Vector3 pos) => data.Entrance = pos.ToVertex2Dxy(); + + public override ItemDataTransformType EditorRotationType => ItemDataTransformType.OneD; + public override Vector3 GetEditorRotation() => new Vector3(data.Orientation, 0, 0); + public override void SetEditorRotation(Vector3 rot) => data.Orientation = rot.x; + + public override ItemDataTransformType EditorScaleType => ItemDataTransformType.OneD; + public override Vector3 GetEditorScale() => new Vector3(data.ExitOffset, 0f, 0f); + public override void SetEditorScale(Vector3 scale) => data.ExitOffset = scale.x; + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughAuthoring.cs.meta new file mode 100644 index 000000000..7309dfe10 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 467487a171ee448a5b826714ef66c3ed +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughExtensions.cs new file mode 100644 index 000000000..164188d84 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughExtensions.cs @@ -0,0 +1,32 @@ +// 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 Unity.Entities; +using UnityEngine; +using VisualPinball.Engine.Game; + +namespace VisualPinball.Unity +{ + internal static class TroughExtensions + { + public static TroughAuthoring SetupGameObject(this Engine.VPT.Trough.Trough Trough, GameObject obj, RenderObjectGroup rog) + { + var ic = obj.AddComponent().SetItem(Trough); + obj.AddComponent(); + return ic as TroughAuthoring; + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughExtensions.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughExtensions.cs.meta new file mode 100644 index 000000000..5cc93bac9 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f92811f35ae2d479cb785222f9e19832 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 86707419371a9ee2b5fef965fa5877dea0518042 Mon Sep 17 00:00:00 2001 From: freezy Date: Thu, 24 Sep 2020 22:43:26 +0200 Subject: [PATCH 015/124] rubber: Add separate collision authoring component. --- VisualPinball.Engine/VPT/Table/Table.cs | 2 + .../VisualPinball.Unity.Editor/VPT.meta | 8 ++ .../VPT/ItemColliderInspector.cs | 46 ++++++ .../VPT/ItemColliderInspector.cs.meta | 11 ++ .../{Inspectors => VPT}/ItemInspector.cs | 134 ++++++++++-------- .../{Inspectors => VPT}/ItemInspector.cs.meta | 2 +- .../VPT/Rubber.meta | 8 ++ .../VPT/Rubber/RubberColliderInspector.cs | 73 ++++++++++ .../Rubber/RubberColliderInspector.cs.meta | 11 ++ .../Rubber}/RubberInspector.cs | 0 .../Rubber}/RubberInspector.cs.meta | 2 +- .../VPT/ItemColliderAuthoring.cs | 40 ++++++ .../VPT/ItemColliderAuthoring.cs.meta | 11 ++ .../VPT/Rubber/RubberColliderAuthoring.cs | 27 ++++ .../Rubber/RubberColliderAuthoring.cs.meta | 11 ++ 15 files changed, 327 insertions(+), 59 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs.meta rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT}/ItemInspector.cs (73%) rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT}/ItemInspector.cs.meta (83%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs.meta rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Rubber}/RubberInspector.cs (100%) rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Rubber}/RubberInspector.cs.meta (83%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs.meta diff --git a/VisualPinball.Engine/VPT/Table/Table.cs b/VisualPinball.Engine/VPT/Table/Table.cs index 5e4ba35af..a70b7baa7 100644 --- a/VisualPinball.Engine/VPT/Table/Table.cs +++ b/VisualPinball.Engine/VPT/Table/Table.cs @@ -36,6 +36,8 @@ public class Table : Item, IRenderable, IHittable { public override string ItemType => "Table"; + public readonly List Hittables2 = new List(); + public CustomInfoTags CustomInfoTags { get; set; } public int FileVersion { get; set; } public byte[] FileHash { get; set; } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT.meta new file mode 100644 index 000000000..564b92796 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9a42e28ac3c006e43a965c05bf963a26 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs new file mode 100644 index 000000000..d1f01dbc0 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs @@ -0,0 +1,46 @@ +// 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 UnityEngine; + +namespace VisualPinball.Unity.Editor +{ + public class ItemColliderInspector : ItemInspector where TAuthoring : MonoBehaviour + { + protected TAuthoring GetAuthoring() + { + var mb = target as MonoBehaviour; + if (mb == null) { + return null; + } + var go = mb.gameObject; + + var auth = go.GetComponent(); + if (auth == null && go.transform.parent != null) { + auth = go.transform.parent.GetComponent(); + } + + if (auth == null && go.transform.parent.transform.parent != null) { + auth = go.transform.parent.transform.parent.GetComponent(); + } + + if (auth == null) { + Debug.LogWarning("No parent rubber authoring component found."); + } + return auth; + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs.meta new file mode 100644 index 000000000..33f510f54 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 93e669ec49fec7a4898dda9b82670dc3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/ItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs similarity index 73% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/ItemInspector.cs rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs index 523d352c0..edd89345b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/ItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs @@ -24,44 +24,66 @@ namespace VisualPinball.Unity.Editor { public abstract class ItemInspector : UnityEditor.Editor - { - protected TableAuthoring _table; - protected SurfaceAuthoring _surface; + { + private TableAuthoring _table; + private SurfaceAuthoring _surface; - protected string[] _allMaterials = new string[0]; - protected string[] _allTextures = new string[0]; + private string[] _allMaterials = new string[0]; + private string[] _allTextures = new string[0]; public static event Action ItemRenamed; + #region Unity Events + protected virtual void OnEnable() { -#if UNITY_EDITOR - // for convenience move item behavior to the top of the list - // we're opting to due this here as opposed to at import time since modifying objects - // in this way caused them to not be part of the created object undo stack - if (target != null && target is MonoBehaviour mb) { - int numComp = mb.GetComponents().Length; - for (int i = 0; i <= numComp; i++) { - UnityEditorInternal.ComponentUtility.MoveComponentUp(mb); - } - } -#endif +// #if UNITY_EDITOR +// // for convenience move item behavior to the top of the list +// // we're opting to due this here as opposed to at import time since modifying objects +// // in this way caused them to not be part of the created object undo stack +// if (target != null && target is MonoBehaviour mb) { +// int numComp = mb.GetComponents().Length; +// for (int i = 0; i <= numComp; i++) { +// UnityEditorInternal.ComponentUtility.MoveComponentUp(mb); +// } +// } +// #endif + _table = (target as MonoBehaviour)?.gameObject.GetComponentInParent(); PopulateDropDownOptions(); } + protected virtual void OnDisable() { } - - protected void PopulateDropDownOptions() + + public override void OnInspectorGUI() + { + if (!(target is IEditableItemAuthoring item)) { + return; + } + + GUILayout.Space(10); + if( GUILayout.Button( "Force Update Mesh" ) ) { + item.MeshDirty = true; + } + + if (item.MeshDirty) { + item.RebuildMeshes(); + } + } + + #endregion + + private void PopulateDropDownOptions() { if (_table == null) return; if (_table.data.Materials != null) { _allMaterials = new string[_table.data.Materials.Length + 1]; _allMaterials[0] = "- none -"; - for (int i = 0; i < _table.data.Materials.Length; i++) { + for (var i = 0; i < _table.data.Materials.Length; i++) { _allMaterials[i + 1] = _table.data.Materials[i].Name; } Array.Sort(_allMaterials, 1, _allMaterials.Length - 1); @@ -74,6 +96,18 @@ protected void PopulateDropDownOptions() } } + private void OnHierarchyChange() + { + if (target is MonoBehaviour bh && target is IIdentifiableItemAuthoring item && bh != null) { + var go = bh.gameObject; + if (item.Name != go.name) { + var oldName = item.Name; + item.Name = go.name; + ItemRenamed?.Invoke(item, oldName, go.name); + } + } + } + protected void OnPreInspectorGUI() { if (!(target is IEditableItemAuthoring item)) { @@ -88,7 +122,7 @@ protected void OnPreInspectorGUI() } EditorGUI.BeginChangeCheck(); - bool newLock = EditorGUILayout.Toggle("IsLocked", item.IsLocked); + var newLock = EditorGUILayout.Toggle("IsLocked", item.IsLocked); if (EditorGUI.EndChangeCheck()) { FinishEdit("IsLocked"); @@ -105,25 +139,12 @@ protected void OnPreInspectorGUI() } } - public override void OnInspectorGUI() - { - var item = target as IEditableItemAuthoring; - if (item == null) return; - - GUILayout.Space(10); - if( GUILayout.Button( "Force Update Mesh" ) ) { - item.MeshDirty = true; - } - - if (item.MeshDirty) { - item.RebuildMeshes(); - } - } + #region Data Fields protected void ItemDataField(string label, ref float field, bool dirtyMesh = true) { EditorGUI.BeginChangeCheck(); - float val = EditorGUILayout.FloatField(label, field); + var val = EditorGUILayout.FloatField(label, field); if (EditorGUI.EndChangeCheck()) { FinishEdit(label, dirtyMesh); field = val; @@ -133,7 +154,7 @@ protected void ItemDataField(string label, ref float field, bool dirtyMesh = tru public void ItemDataSlider(string label, ref float field, float leftVal, float rightVal, bool dirtyMesh = true) { EditorGUI.BeginChangeCheck(); - float val = EditorGUILayout.Slider(label, field, leftVal, rightVal); + var val = EditorGUILayout.Slider(label, field, leftVal, rightVal); if (EditorGUI.EndChangeCheck()) { FinishEdit(label, dirtyMesh); field = val; @@ -143,7 +164,7 @@ public void ItemDataSlider(string label, ref float field, float leftVal, float r protected void ItemDataField(string label, ref int field, bool dirtyMesh = true) { EditorGUI.BeginChangeCheck(); - int val = EditorGUILayout.IntField(label, field); + var val = EditorGUILayout.IntField(label, field); if (EditorGUI.EndChangeCheck()) { FinishEdit(label, dirtyMesh); field = val; @@ -153,7 +174,7 @@ protected void ItemDataField(string label, ref int field, bool dirtyMesh = true) public void ItemDataSlider(string label, ref int field, int leftVal, int rightVal, bool dirtyMesh = true) { EditorGUI.BeginChangeCheck(); - int val = EditorGUILayout.IntSlider(label, field, leftVal, rightVal); + var val = EditorGUILayout.IntSlider(label, field, leftVal, rightVal); if (EditorGUI.EndChangeCheck()) { FinishEdit(label, dirtyMesh); field = val; @@ -163,7 +184,7 @@ public void ItemDataSlider(string label, ref int field, int leftVal, int rightVa protected void ItemDataField(string label, ref string field, bool dirtyMesh = true) { EditorGUI.BeginChangeCheck(); - string val = EditorGUILayout.TextField(label, field); + var val = EditorGUILayout.TextField(label, field); if (EditorGUI.EndChangeCheck()) { FinishEdit(label, dirtyMesh); field = val; @@ -173,7 +194,7 @@ protected void ItemDataField(string label, ref string field, bool dirtyMesh = tr protected void ItemDataField(string label, ref bool field, bool dirtyMesh = true) { EditorGUI.BeginChangeCheck(); - bool val = EditorGUILayout.Toggle(label, field); + var val = EditorGUILayout.Toggle(label, field); if (EditorGUI.EndChangeCheck()) { FinishEdit(label, dirtyMesh); field = val; @@ -183,7 +204,7 @@ protected void ItemDataField(string label, ref bool field, bool dirtyMesh = true protected void ItemDataField(string label, ref Vertex2D field, bool dirtyMesh = true) { EditorGUI.BeginChangeCheck(); - Vertex2D val = EditorGUILayout.Vector2Field(label, field.ToUnityVector2()).ToVertex2D(); + var val = EditorGUILayout.Vector2Field(label, field.ToUnityVector2()).ToVertex2D(); if (EditorGUI.EndChangeCheck()) { FinishEdit(label, dirtyMesh); field = val; @@ -193,7 +214,7 @@ protected void ItemDataField(string label, ref Vertex2D field, bool dirtyMesh = protected void ItemDataField(string label, ref Vertex3D field, bool dirtyMesh = true) { EditorGUI.BeginChangeCheck(); - Vertex3D val = EditorGUILayout.Vector3Field(label, field.ToUnityVector3()).ToVertex3D(); + var val = EditorGUILayout.Vector3Field(label, field.ToUnityVector3()).ToVertex3D(); if (EditorGUI.EndChangeCheck()) { FinishEdit(label, dirtyMesh); field = val; @@ -203,7 +224,7 @@ protected void ItemDataField(string label, ref Vertex3D field, bool dirtyMesh = protected void ItemDataField(string label, ref Engine.Math.Color field, bool dirtyMesh = true) { EditorGUI.BeginChangeCheck(); - Engine.Math.Color val = EditorGUILayout.ColorField(label, field.ToUnityColor()).ToEngineColor(); + var val = EditorGUILayout.ColorField(label, field.ToUnityColor()).ToEngineColor(); if (EditorGUI.EndChangeCheck()) { FinishEdit(label, dirtyMesh); field = val; @@ -216,9 +237,8 @@ protected void SurfaceField(string label, ref string field, bool dirtyMesh = tru _surface = null; } - var mb = target as MonoBehaviour; if (_surface == null && _table != null) { - string currentFieldName = field; + var currentFieldName = field; if (currentFieldName != null && _table.Table.Has(currentFieldName)) { _surface = _table.gameObject.GetComponentsInChildren(true) .FirstOrDefault(s => s.name == currentFieldName); @@ -229,7 +249,7 @@ protected void SurfaceField(string label, ref string field, bool dirtyMesh = tru _surface = (SurfaceAuthoring)EditorGUILayout.ObjectField(label, _surface, typeof(SurfaceAuthoring), true); if (EditorGUI.EndChangeCheck()) { FinishEdit(label, dirtyMesh); - field = _surface != null ? _surface.name : ""; + field = _surface != null ? _surface.name : string.Empty; } } @@ -239,8 +259,8 @@ protected void DropDownField(string label, ref T field, string[] optionString return; } - int selectedIndex = 0; - for (int i = 0; i < optionValues.Length; i++) { + var selectedIndex = 0; + for (var i = 0; i < optionValues.Length; i++) { if (optionValues[i].Equals(field)) { selectedIndex = i; break; @@ -264,9 +284,9 @@ protected void TextureField(string label, ref string field, bool dirtyMesh = tru PopulateDropDownOptions(); } - int selectedIndex = 0; - for (int i = 0; i < _allTextures.Length; i++) { - if (_allTextures[i].ToLower() == field.ToLower()) { + var selectedIndex = 0; + for (var i = 0; i < _allTextures.Length; i++) { + if (string.Equals(_allTextures[i], field, StringComparison.CurrentCultureIgnoreCase)) { selectedIndex = i; break; } @@ -275,7 +295,7 @@ protected void TextureField(string label, ref string field, bool dirtyMesh = tru selectedIndex = EditorGUILayout.Popup(label, selectedIndex, _allTextures); if (EditorGUI.EndChangeCheck() && selectedIndex >= 0 && selectedIndex < _allTextures.Length) { FinishEdit(label, dirtyMesh); - field = selectedIndex == 0 ? "" : _allTextures[selectedIndex]; + field = selectedIndex == 0 ? string.Empty : _allTextures[selectedIndex]; } } @@ -289,23 +309,23 @@ protected void MaterialField(string label, ref string field, bool dirtyMesh = tr DropDownField(label, ref field, _allMaterials, _allMaterials, dirtyMesh); if (_allMaterials.Length > 0 && field == _allMaterials[0]) { - field = ""; // don't store the none value string in our data + field = string.Empty; // don't store the none value string in our data } } + #endregion + protected virtual void FinishEdit(string label, bool dirtyMesh = true) { - string undoLabel = $"[{target?.name}] Edit {label}"; + var undoLabel = $"[{target?.name}] Edit {label}"; if (dirtyMesh) { // set dirty flag true before recording object state for the undo so meshes will rebuild after the undo as well - var item = target as IEditableItemAuthoring; - if (item != null) { + if (target is IEditableItemAuthoring item) { item.MeshDirty = true; Undo.RecordObject(this, undoLabel); } } Undo.RecordObject(target, undoLabel); } - } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/ItemInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/ItemInspector.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs.meta index 9cd1fd1c4..4ae53d39c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/ItemInspector.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 4a7559a45700bea4b8d8ff82a82bd77d +guid: a2066b2884485fc43b52fab565e84334 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber.meta new file mode 100644 index 000000000..2f2cc9cf5 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 06dc9d272597af3489086141dfd37ab7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs new file mode 100644 index 000000000..35f92fdc6 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs @@ -0,0 +1,73 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Rubber; + + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(RubberColliderAuthoring))] + public class RubberColliderInspector : ItemColliderInspector + { + private RubberData _rubberData; + + private bool _foldoutMaterial = true; + + protected override void OnEnable() + { + base.OnEnable(); + + var rubberAuthoring = GetAuthoring(); + if (rubberAuthoring != null) { + _rubberData = rubberAuthoring.data; + } + } + + public override void OnInspectorGUI() + { + if (_rubberData == null) { + return; + } + + ItemDataField("Collidable", ref _rubberData.IsCollidable, false); + + EditorGUI.BeginDisabledGroup(!_rubberData.IsCollidable); + ItemDataField("Has Hit Event", ref _rubberData.HitEvent, false); + ItemDataField("Hit Height", ref _rubberData.HitHeight, false); + EditorGUI.EndDisabledGroup(); + + if (_foldoutMaterial = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMaterial, "Physics Material")) { + EditorGUI.BeginDisabledGroup(_rubberData.OverwritePhysics || !_rubberData.IsCollidable); + MaterialField("Preset", ref _rubberData.PhysicsMaterial, false); + EditorGUI.EndDisabledGroup(); + + EditorGUI.BeginDisabledGroup(!_rubberData.IsCollidable); + ItemDataField("Overwrite Preset", ref _rubberData.OverwritePhysics, false); + EditorGUI.EndDisabledGroup(); + + EditorGUI.BeginDisabledGroup(!_rubberData.OverwritePhysics || !_rubberData.IsCollidable); + ItemDataField("Elasticity", ref _rubberData.Elasticity, false); + ItemDataField("Elasticity Falloff", ref _rubberData.ElasticityFalloff, false); + ItemDataField("Friction", ref _rubberData.Friction, false); + ItemDataField("Scatter Angle", ref _rubberData.Scatter, false); + EditorGUI.EndDisabledGroup(); + } + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs.meta new file mode 100644 index 000000000..db4245f1b --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f54cc084a0b4566418917791e9a5e7fc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/RubberInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs similarity index 100% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/RubberInspector.cs rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/RubberInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/RubberInspector.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs.meta index 23d2b3388..6654e7a35 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/RubberInspector.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: ef5a85eaa858e83459a5c4477ff1655e +guid: 3c3fc4539266e10479c02009ea258e46 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs new file mode 100644 index 000000000..192f44eba --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs @@ -0,0 +1,40 @@ +// 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; +using UnityEngine; +using VisualPinball.Engine.Game; +using VisualPinball.Engine.VPT; + +namespace VisualPinball.Unity +{ + public class ItemColliderAuthoring : MonoBehaviour where TData : ItemData where TItem : Item, IHittable + { + [NonSerialized] + public TData Data; + + [NonSerialized] + public TItem Item; + + public ItemColliderAuthoring SetItem(TItem item, string gameObjectName = null) + { + Item = item; + Data = item.Data; + name = (gameObjectName ?? Data.GetName()) + " (collider)"; + return this; + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs.meta new file mode 100644 index 000000000..4636c0fe3 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7c2ebdc131d07b5409091624dfb9e829 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs new file mode 100644 index 000000000..0f458aeab --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs @@ -0,0 +1,27 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Rubber; + +namespace VisualPinball.Unity +{ + [AddComponentMenu("Visual Pinball/Collision/Rubber Collider")] + public class RubberColliderAuthoring : ItemColliderAuthoring + { + + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs.meta new file mode 100644 index 000000000..4d3812879 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8c1025cd8f2b2e441aa98bef9fc14b8e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From e3c160d6df52b5f48b87b1304829e58a0b1f3114 Mon Sep 17 00:00:00 2001 From: freezy Date: Thu, 24 Sep 2020 23:09:21 +0200 Subject: [PATCH 016/124] surface: Add separate collision authoring component. --- .../VPT/Rubber/RubberColliderInspector.cs | 9 +- .../VPT/Rubber/RubberInspector.cs | 23 +--- .../VPT/Surface.meta | 8 ++ .../VPT/Surface/SurfaceColliderInspector.cs | 112 ++++++++++++++++++ .../Surface/SurfaceColliderInspector.cs.meta | 11 ++ .../Surface}/SurfaceInspector.cs | 29 +---- .../Surface}/SurfaceInspector.cs.meta | 2 +- .../VPT/Surface/SurfaceColliderAuthoring.cs | 27 +++++ .../Surface/SurfaceColliderAuthoring.cs.meta | 11 ++ 9 files changed, 178 insertions(+), 54 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs.meta rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Surface}/SurfaceInspector.cs (62%) rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Surface}/SurfaceInspector.cs.meta (83%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs.meta diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs index 35f92fdc6..200c35e02 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs @@ -50,24 +50,23 @@ public override void OnInspectorGUI() EditorGUI.BeginDisabledGroup(!_rubberData.IsCollidable); ItemDataField("Has Hit Event", ref _rubberData.HitEvent, false); ItemDataField("Hit Height", ref _rubberData.HitHeight, false); - EditorGUI.EndDisabledGroup(); if (_foldoutMaterial = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMaterial, "Physics Material")) { - EditorGUI.BeginDisabledGroup(_rubberData.OverwritePhysics || !_rubberData.IsCollidable); + EditorGUI.BeginDisabledGroup(_rubberData.OverwritePhysics); MaterialField("Preset", ref _rubberData.PhysicsMaterial, false); EditorGUI.EndDisabledGroup(); - EditorGUI.BeginDisabledGroup(!_rubberData.IsCollidable); ItemDataField("Overwrite Preset", ref _rubberData.OverwritePhysics, false); - EditorGUI.EndDisabledGroup(); - EditorGUI.BeginDisabledGroup(!_rubberData.OverwritePhysics || !_rubberData.IsCollidable); + EditorGUI.BeginDisabledGroup(!_rubberData.OverwritePhysics); ItemDataField("Elasticity", ref _rubberData.Elasticity, false); ItemDataField("Elasticity Falloff", ref _rubberData.ElasticityFalloff, false); ItemDataField("Friction", ref _rubberData.Friction, false); ItemDataField("Scatter Angle", ref _rubberData.Scatter, false); EditorGUI.EndDisabledGroup(); } + + EditorGUI.EndDisabledGroup(); } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs index 322126571..89ed10afe 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +// ReSharper disable AssignmentInConditionalExpression + using UnityEditor; namespace VisualPinball.Unity.Editor @@ -24,7 +26,6 @@ public class RubberInspector : DragPointsItemInspector private RubberAuthoring _rubber; private bool _foldoutColorsAndFormatting = true; private bool _foldoutPosition = true; - private bool _foldoutPhysics = true; private bool _foldoutMisc = true; protected override void OnEnable() @@ -57,26 +58,6 @@ public override void OnInspectorGUI() } EditorGUILayout.EndFoldoutHeaderGroup(); - if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "Physics")) { - EditorGUI.BeginDisabledGroup(_rubber.data.OverwritePhysics); - MaterialField("Physics Material", ref _rubber.data.PhysicsMaterial, dirtyMesh: false); - EditorGUI.EndDisabledGroup(); - - ItemDataField("Overwrite Material Settings", ref _rubber.data.OverwritePhysics, dirtyMesh: false); - - EditorGUI.BeginDisabledGroup(!_rubber.data.OverwritePhysics); - ItemDataField("Elasticity", ref _rubber.data.Elasticity, dirtyMesh: false); - ItemDataField("Elasticity Falloff", ref _rubber.data.ElasticityFalloff, dirtyMesh: false); - ItemDataField("Friction", ref _rubber.data.Friction, dirtyMesh: false); - ItemDataField("Scatter Angle", ref _rubber.data.Scatter, dirtyMesh: false); - EditorGUI.EndDisabledGroup(); - - ItemDataField("Hit Height", ref _rubber.data.HitHeight, dirtyMesh: false); - ItemDataField("Collidable", ref _rubber.data.IsCollidable, dirtyMesh: false); - ItemDataField("Has Hit Event", ref _rubber.data.HitEvent, dirtyMesh: false); - } - EditorGUILayout.EndFoldoutHeaderGroup(); - if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { ItemDataField("Timer Enabled", ref _rubber.data.IsTimerEnabled, dirtyMesh: false); ItemDataField("Timer Interval", ref _rubber.data.TimerInterval, dirtyMesh: false); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface.meta new file mode 100644 index 000000000..287ddf48a --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4e6b2d645b196424884198152b701e05 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs new file mode 100644 index 000000000..9dffc44f3 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs @@ -0,0 +1,112 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Rubber; +using VisualPinball.Engine.VPT.Surface; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(SurfaceColliderAuthoring))] + public class SurfaceColliderInspector : ItemColliderInspector + { + private SurfaceData _surfaceData; + + private bool _foldoutMaterial = true; + private bool _foldoutSlingshot = true; + + protected override void OnEnable() + { + base.OnEnable(); + + var surfaceAuthoring = GetAuthoring(); + if (surfaceAuthoring != null) { + _surfaceData = surfaceAuthoring.data; + } + } + + public override void OnInspectorGUI() + { + if (_surfaceData == null) { + return; + } + + ItemDataField("Collidable", ref _surfaceData.IsCollidable, false); + + EditorGUI.BeginDisabledGroup(!_surfaceData.IsCollidable); + + ItemDataField("Has Hit Event", ref _surfaceData.HitEvent, false); + EditorGUI.BeginDisabledGroup(!_surfaceData.HitEvent); + ItemDataField("Hit Threshold", ref _surfaceData.Threshold, false); + EditorGUI.EndDisabledGroup(); + + ItemDataField("Can Drop", ref _surfaceData.IsDroppable, false); + ItemDataField("Is Bottom Collidable", ref _surfaceData.IsBottomSolid, false); + + if (_foldoutSlingshot = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutSlingshot, "Slingshot")) { + ItemDataField("Slingshot Force", ref _surfaceData.SlingshotForce, false); + ItemDataField("Slingshot Threshold", ref _surfaceData.SlingshotThreshold, false); + } + EditorGUILayout.EndFoldoutHeaderGroup(); + + if (_foldoutMaterial = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMaterial, "Physics Material")) { + EditorGUI.BeginDisabledGroup(_surfaceData.OverwritePhysics); + MaterialField("Preset", ref _surfaceData.PhysicsMaterial, false); + EditorGUI.EndDisabledGroup(); + + ItemDataField("Overwrite Preset", ref _surfaceData.OverwritePhysics, false); + + EditorGUI.BeginDisabledGroup(!_surfaceData.OverwritePhysics); + ItemDataField("Elasticity", ref _surfaceData.Elasticity, false); + ItemDataField("Friction", ref _surfaceData.Friction, false); + ItemDataField("Scatter Angle", ref _surfaceData.Scatter, false); + EditorGUI.EndDisabledGroup(); + } + EditorGUILayout.EndFoldoutHeaderGroup(); + + EditorGUI.EndDisabledGroup(); + + + + + // ItemDataField("Collidable", ref _surfaceData.IsCollidable, false); + // + // EditorGUI.BeginDisabledGroup(!_surfaceData.IsCollidable); + // ItemDataField("Has Hit Event", ref _surfaceData.HitEvent, false); + // ItemDataField("Hit Height", ref _surfaceData.HitHeight, false); + // EditorGUI.EndDisabledGroup(); + // + // if (_foldoutMaterial = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMaterial, "Physics Material")) { + // EditorGUI.BeginDisabledGroup(_rubberData.OverwritePhysics || !_rubberData.IsCollidable); + // MaterialField("Preset", ref _rubberData.PhysicsMaterial, false); + // EditorGUI.EndDisabledGroup(); + // + // EditorGUI.BeginDisabledGroup(!_rubberData.IsCollidable); + // ItemDataField("Overwrite Preset", ref _rubberData.OverwritePhysics, false); + // EditorGUI.EndDisabledGroup(); + // + // EditorGUI.BeginDisabledGroup(!_rubberData.OverwritePhysics || !_rubberData.IsCollidable); + // ItemDataField("Elasticity", ref _rubberData.Elasticity, false); + // ItemDataField("Elasticity Falloff", ref _rubberData.ElasticityFalloff, false); + // ItemDataField("Friction", ref _rubberData.Friction, false); + // ItemDataField("Scatter Angle", ref _rubberData.Scatter, false); + // EditorGUI.EndDisabledGroup(); + // } + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs.meta new file mode 100644 index 000000000..1460030f3 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 002cdc142fbb783409853d29ae98d02f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/SurfaceInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs similarity index 62% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/SurfaceInspector.cs rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs index 32e2c1efe..ad922b6f6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/SurfaceInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +// ReSharper disable AssignmentInConditionalExpression + using UnityEditor; namespace VisualPinball.Unity.Editor @@ -57,33 +59,6 @@ public override void OnInspectorGUI() } EditorGUILayout.EndFoldoutHeaderGroup(); - if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "State & Physics")) { - ItemDataField("Has Hit Event", ref _targetSurf.data.HitEvent, dirtyMesh: false); - EditorGUI.BeginDisabledGroup(!_targetSurf.data.HitEvent); - ItemDataField("Hit Threshold", ref _targetSurf.data.Threshold, dirtyMesh: false); - EditorGUI.EndDisabledGroup(); - - ItemDataField("Slingshot Force", ref _targetSurf.data.SlingshotForce, dirtyMesh: false); - ItemDataField("Slingshot Threshold", ref _targetSurf.data.SlingshotThreshold, dirtyMesh: false); - - EditorGUI.BeginDisabledGroup(_targetSurf.data.OverwritePhysics); - MaterialField("Physics Material", ref _targetSurf.data.PhysicsMaterial, dirtyMesh: false); - EditorGUI.EndDisabledGroup(); - - ItemDataField("Overwrite Material Settings", ref _targetSurf.data.OverwritePhysics, dirtyMesh: false); - - EditorGUI.BeginDisabledGroup(!_targetSurf.data.OverwritePhysics); - ItemDataField("Elasticity", ref _targetSurf.data.Elasticity, dirtyMesh: false); - ItemDataField("Friction", ref _targetSurf.data.Friction, dirtyMesh: false); - ItemDataField("Scatter Angle", ref _targetSurf.data.Scatter, dirtyMesh: false); - EditorGUI.EndDisabledGroup(); - - ItemDataField("Can Drop", ref _targetSurf.data.IsDroppable, dirtyMesh: false); - ItemDataField("Collidable", ref _targetSurf.data.IsCollidable, dirtyMesh: false); - ItemDataField("Is Bottom Collidable", ref _targetSurf.data.IsBottomSolid, dirtyMesh: false); - } - EditorGUILayout.EndFoldoutHeaderGroup(); - if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { ItemDataField("Timer Enabled", ref _targetSurf.data.IsTimerEnabled, dirtyMesh: false); ItemDataField("Timer Interval", ref _targetSurf.data.TimerInterval, dirtyMesh: false); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/SurfaceInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/SurfaceInspector.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs.meta index b7b9e00f5..fa91ae95a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/SurfaceInspector.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: acc775ecdd5eea841944c1fa24c9f3d2 +guid: b782f911e5cecf24e9234ef3e6e69473 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs new file mode 100644 index 000000000..d034d2d2d --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs @@ -0,0 +1,27 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Surface; + +namespace VisualPinball.Unity +{ + [AddComponentMenu("Visual Pinball/Collision/Surface Collider")] + public class SurfaceColliderAuthoring : ItemColliderAuthoring + { + + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs.meta new file mode 100644 index 000000000..1d727a671 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 08f1966f4a3f62b4cbab7f6e76d277e7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From eb04c03c37b2ac23902987bae1f545cfe4721c6c Mon Sep 17 00:00:00 2001 From: freezy Date: Thu, 24 Sep 2020 23:18:43 +0200 Subject: [PATCH 017/124] import: Add collider component to rubber and surface. --- .../Import/VpxConverter.cs | 29 +++++++++---------- .../VPT/Rubber/RubberExtensions.cs | 6 ++-- .../VPT/Surface/SurfaceExtensions.cs | 6 ++-- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index 4c2119fc8..120c38d05 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -203,22 +203,21 @@ public static IEnumerable> ConvertRenderObjects( obj.transform.SetFromMatrix(rog.TransformationMatrix.ToUnityMatrix()); // add unity component - MonoBehaviour ic = null; switch (item) { - case Bumper bumper: ic = bumper.SetupGameObject(obj, rog); break; - case Flipper flipper: ic = flipper.SetupGameObject(obj, rog); break; - case Gate gate: ic = gate.SetupGameObject(obj, rog); break; - case HitTarget hitTarget: ic = hitTarget.SetupGameObject(obj, rog); break; - case Kicker kicker: ic = kicker.SetupGameObject(obj, rog); break; - case Engine.VPT.Light.Light lt: ic = lt.SetupGameObject(obj, rog); break; - case Plunger plunger: ic = plunger.SetupGameObject(obj, rog); break; - case Primitive primitive: ic = primitive.SetupGameObject(obj, rog); break; - case Ramp ramp: ic = ramp.SetupGameObject(obj, rog); break; - case Rubber rubber: ic = rubber.SetupGameObject(obj, rog); break; - case Spinner spinner: ic = spinner.SetupGameObject(obj, rog); break; - case Surface surface: ic = surface.SetupGameObject(obj, rog); break; - case Table table: ic = table.SetupGameObject(obj, rog); break; - case Trigger trigger: ic = trigger.SetupGameObject(obj, rog); break; + case Bumper bumper: bumper.SetupGameObject(obj, rog); break; + case Flipper flipper: flipper.SetupGameObject(obj, rog); break; + case Gate gate: gate.SetupGameObject(obj, rog); break; + case HitTarget hitTarget: hitTarget.SetupGameObject(obj, rog); break; + case Kicker kicker: kicker.SetupGameObject(obj, rog); break; + case Engine.VPT.Light.Light lt: lt.SetupGameObject(obj, rog); break; + case Plunger plunger: plunger.SetupGameObject(obj, rog); break; + case Primitive primitive: primitive.SetupGameObject(obj, rog); break; + case Ramp ramp: ramp.SetupGameObject(obj, rog); break; + case Rubber rubber: rubber.SetupGameObject(obj, rog); break; + case Spinner spinner: spinner.SetupGameObject(obj, rog); break; + case Surface surface: surface.SetupGameObject(obj, rog); break; + case Table table: table.SetupGameObject(obj, rog); break; + case Trigger trigger: trigger.SetupGameObject(obj, rog); break; } return createdObjs; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs index 18537bb24..6c9849bcd 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs @@ -22,11 +22,11 @@ namespace VisualPinball.Unity { internal static class RubberExtensions { - public static RubberAuthoring SetupGameObject(this Engine.VPT.Rubber.Rubber rubber, GameObject obj, RenderObjectGroup rog) + public static void SetupGameObject(this Engine.VPT.Rubber.Rubber rubber, GameObject obj, RenderObjectGroup rog) { - var ic = obj.AddComponent().SetItem(rubber); + obj.AddComponent().SetItem(rubber); + obj.AddComponent(); obj.AddComponent(); - return ic as RubberAuthoring; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs index 6941f3b06..68f9a9696 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs @@ -22,11 +22,11 @@ namespace VisualPinball.Unity { internal static class SurfaceExtensions { - public static SurfaceAuthoring SetupGameObject(this Engine.VPT.Surface.Surface surface, GameObject obj, RenderObjectGroup rog) + public static void SetupGameObject(this Engine.VPT.Surface.Surface surface, GameObject obj, RenderObjectGroup rog) { - var ic = obj.AddComponent().SetItem(surface); + obj.AddComponent().SetItem(surface); + obj.AddComponent(); obj.AddComponent(); - return ic as SurfaceAuthoring; } } } From 0873c1881563087ba4a447e8805ef327a7e6d86e Mon Sep 17 00:00:00 2001 From: freezy Date: Fri, 25 Sep 2020 00:02:05 +0200 Subject: [PATCH 018/124] import: Add name parse function. --- .../Game/RenderObjectGroup.cs | 24 +++++++ .../Import/VpxConverter.cs | 65 ++++++++++--------- 2 files changed, 59 insertions(+), 30 deletions(-) diff --git a/VisualPinball.Engine/Game/RenderObjectGroup.cs b/VisualPinball.Engine/Game/RenderObjectGroup.cs index 6998b7bd4..03015e45a 100644 --- a/VisualPinball.Engine/Game/RenderObjectGroup.cs +++ b/VisualPinball.Engine/Game/RenderObjectGroup.cs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using System.Linq; using VisualPinball.Engine.Math; @@ -42,5 +43,28 @@ public RenderObjectGroup(string name, string parent, Matrix3D matrix, params Ren RenderObjects = renderObjects; TransformationMatrix = matrix; } + + public enum ItemSubType + { + None, Collider, Mesh + } + + public (string, ItemSubType, string) SplitName() + { + var names = Name.Split(new[] {'_'}, 3, StringSplitOptions.None); + if (names.Length == 1) { + return (Name, ItemSubType.None, null); + } + switch (names[1].ToLower()) { + case "collider": + return (names[0], ItemSubType.Collider, names.Length > 2 ? names[2] : null); + + case "mesh": + return (names[0], ItemSubType.Mesh, names.Length > 2 ? names[2] : null); + + default: + return (Name, ItemSubType.None, null); + } + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index 120c38d05..baafe025b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -118,35 +118,9 @@ public void Convert(string fileName, Table table, bool applyPatch = true, string _table.Mappings.PopulateSwitches((dga.GameEngine as IGamelogicEngineWithSwitches).AvailableSwitches, table.Switchables); _table.Mappings.PopulateCoils((dga.GameEngine as IGamelogicEngineWithCoils).AvailableCoils, table.Coilables); } - } - public static GameObject ConvertRenderObject(RenderObject ro, GameObject obj, TableAuthoring ta) - { - if (ro.Mesh == null) { - Logger.Warn($"No mesh for object {obj.name}, skipping."); - return null; - } - - var mesh = ro.Mesh.ToUnityMesh($"{obj.name}_mesh"); - - // apply mesh to game object - var mf = obj.AddComponent(); - mf.sharedMesh = mesh; - - // apply material - if (ro.Mesh.AnimationFrames.Count > 0) { - var smr = obj.AddComponent(); - smr.sharedMaterial = ro.Material.ToUnityMaterial(ta); - smr.sharedMesh = mesh; - smr.enabled = ro.IsVisible; - } - else { - var mr = obj.AddComponent(); - mr.sharedMaterial = ro.Material.ToUnityMaterial(ta); - mr.enabled = ro.IsVisible; - } - - return obj; + // don't need that anymore. + DestroyImmediate(this); } private void ConvertGameItems(GameObject tableGameObject) @@ -160,11 +134,14 @@ private void ConvertRenderables(GameObject tableGameObject) var createdObjs = new Dictionary>>(); foreach (var renderable in _renderObjects.Keys) { var ro = _renderObjects[renderable]; + + // create item type parent if (!_parents.ContainsKey(ro.Parent)) { var parent = new GameObject(ro.Parent); parent.transform.parent = gameObject.transform; _parents[ro.Parent] = parent; } + createdObjs[renderable] = ConvertRenderObjects(renderable, ro, _parents[ro.Parent], _tableAuthoring, out _); } @@ -178,13 +155,15 @@ private void ConvertRenderables(GameObject tableGameObject) public static IEnumerable> ConvertRenderObjects(IRenderable item, RenderObjectGroup rog, GameObject parent, TableAuthoring tb, out GameObject obj) { + var (name, subType, childName) = rog.SplitName(); + obj = new GameObject(rog.Name); obj.transform.parent = parent.transform; var createdObjs = new Tuple[0]; if (rog.HasOnlyChild && !rog.ForceChild) { - ConvertRenderObject(rog.RenderObjects[0], obj, tb); + SetupRenderObject(rog.RenderObjects[0], obj, tb); createdObjs = new[] { new Tuple(obj, rog.RenderObjects[0]) }; } else if (rog.HasChildren) { @@ -194,7 +173,7 @@ public static IEnumerable> ConvertRenderObjects( var subObj = new GameObject(ro.Name); subObj.transform.SetParent(obj.transform, false); subObj.layer = ChildObjectsLayer; - ConvertRenderObject(ro, subObj, tb); + SetupRenderObject(ro, subObj, tb); createdObjs[i++] = new Tuple(subObj, ro); } } @@ -222,6 +201,32 @@ public static IEnumerable> ConvertRenderObjects( return createdObjs; } + private static void SetupRenderObject(RenderObject ro, GameObject obj, TableAuthoring ta) + { + if (ro.Mesh == null) { + Logger.Warn($"No mesh for object {obj.name}, skipping."); + return; + } + + var mesh = ro.Mesh.ToUnityMesh($"{obj.name}_mesh"); + + // apply mesh to game object + var mf = obj.AddComponent(); + mf.sharedMesh = mesh; + + // apply material + if (ro.Mesh.AnimationFrames.Count > 0) { + var smr = obj.AddComponent(); + smr.sharedMaterial = ro.Material.ToUnityMaterial(ta); + smr.sharedMesh = mesh; + smr.enabled = ro.IsVisible; + } else { + var mr = obj.AddComponent(); + mr.sharedMaterial = ro.Material.ToUnityMaterial(ta); + mr.enabled = ro.IsVisible; + } + } + private void MakeSerializable(GameObject go, Table table) { // add table component (plus other data) From 9957656aed1d802c348f61495c0caf3cdc59f063 Mon Sep 17 00:00:00 2001 From: freezy Date: Fri, 25 Sep 2020 00:19:51 +0200 Subject: [PATCH 019/124] rog: Analyze name on creation. --- VisualPinball.Engine/Game/RenderObjectGroup.cs | 17 +++++++++++------ .../VisualPinball.Unity/Import/VpxConverter.cs | 10 ++++++---- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/VisualPinball.Engine/Game/RenderObjectGroup.cs b/VisualPinball.Engine/Game/RenderObjectGroup.cs index 03015e45a..0d46ae671 100644 --- a/VisualPinball.Engine/Game/RenderObjectGroup.cs +++ b/VisualPinball.Engine/Game/RenderObjectGroup.cs @@ -30,6 +30,10 @@ public class RenderObjectGroup public readonly RenderObject[] RenderObjects; public readonly Matrix3D TransformationMatrix; + public readonly string ComponentName; + public readonly ItemSubComponent SubComponent; + public readonly string SubName; + public bool ForceChild { get; set; } public bool HasOnlyChild => RenderObjects.Length == 1; public bool HasChildren => RenderObjects.Length > 0; @@ -42,28 +46,29 @@ public RenderObjectGroup(string name, string parent, Matrix3D matrix, params Ren Parent = parent; RenderObjects = renderObjects; TransformationMatrix = matrix; + (ComponentName, SubComponent, SubName) = SplitName(); } - public enum ItemSubType + public enum ItemSubComponent { None, Collider, Mesh } - public (string, ItemSubType, string) SplitName() + private (string, ItemSubComponent, string) SplitName() { var names = Name.Split(new[] {'_'}, 3, StringSplitOptions.None); if (names.Length == 1) { - return (Name, ItemSubType.None, null); + return (Name, ItemSubComponent.None, null); } switch (names[1].ToLower()) { case "collider": - return (names[0], ItemSubType.Collider, names.Length > 2 ? names[2] : null); + return (names[0], ItemSubComponent.Collider, names.Length > 2 ? names[2] : null); case "mesh": - return (names[0], ItemSubType.Mesh, names.Length > 2 ? names[2] : null); + return (names[0], ItemSubComponent.Mesh, names.Length > 2 ? names[2] : null); default: - return (Name, ItemSubType.None, null); + return (Name, ItemSubComponent.None, null); } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index baafe025b..310a33f6a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -132,8 +132,12 @@ private void ConvertGameItems(GameObject tableGameObject) private void ConvertRenderables(GameObject tableGameObject) { var createdObjs = new Dictionary>>(); - foreach (var renderable in _renderObjects.Keys) { - var ro = _renderObjects[renderable]; + var renderObjects = from entry + in _renderObjects orderby entry.Value.SubComponent select entry; + + foreach (var kv in renderObjects) { + var renderable = kv.Key; + var ro = kv.Value; // create item type parent if (!_parents.ContainsKey(ro.Parent)) { @@ -155,8 +159,6 @@ private void ConvertRenderables(GameObject tableGameObject) public static IEnumerable> ConvertRenderObjects(IRenderable item, RenderObjectGroup rog, GameObject parent, TableAuthoring tb, out GameObject obj) { - var (name, subType, childName) = rog.SplitName(); - obj = new GameObject(rog.Name); obj.transform.parent = parent.transform; From 4aaa9d362f83a417edd7834825015cb94869a18d Mon Sep 17 00:00:00 2001 From: freezy Date: Fri, 25 Sep 2020 00:25:30 +0200 Subject: [PATCH 020/124] import: Attach objects to parent if matched by name. --- .../Import/VpxConverter.cs | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index 310a33f6a..b072b122d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -131,22 +131,37 @@ private void ConvertGameItems(GameObject tableGameObject) private void ConvertRenderables(GameObject tableGameObject) { + var createdRootObjs = new Dictionary(); var createdObjs = new Dictionary>>(); var renderObjects = from entry in _renderObjects orderby entry.Value.SubComponent select entry; foreach (var kv in renderObjects) { var renderable = kv.Key; - var ro = kv.Value; + var rog = kv.Value; // create item type parent - if (!_parents.ContainsKey(ro.Parent)) { - var parent = new GameObject(ro.Parent); + if (!_parents.ContainsKey(rog.Parent)) { + var parent = new GameObject(rog.Parent); parent.transform.parent = gameObject.transform; - _parents[ro.Parent] = parent; + _parents[rog.Parent] = parent; } - createdObjs[renderable] = ConvertRenderObjects(renderable, ro, _parents[ro.Parent], _tableAuthoring, out _); + // create object(s) + createdObjs[renderable] = ConvertRenderObjects(renderable, rog, _parents[rog.Parent], _tableAuthoring, out var rootObj); + + // if the object's names was parsed to be part of another object, re-link to other object. + if (rog.SubComponent != RenderObjectGroup.ItemSubComponent.None) { + if (!createdRootObjs.ContainsKey(rog.ComponentName.ToLower())) { + Logger.Warn($"Cannot find component \"{rog.ComponentName.ToLower()}\" that is supposed to be the parent of \"{rog.Name}\"."); + + } else { + var mainObj = createdRootObjs[rog.ComponentName.ToLower()]; + rootObj.transform.SetParent(mainObj.transform, false); + } + } else { + createdRootObjs[rog.Name.ToLower()] = rootObj; + } } // now we have all renderables imported, patch them. From f27af51403dbe4ca0040feddab546a4e544635d8 Mon Sep 17 00:00:00 2001 From: freezy Date: Fri, 25 Sep 2020 00:36:44 +0200 Subject: [PATCH 021/124] import: Don't create mesh if it's a collider. --- .../VPT/ItemColliderInspector.cs | 37 ++++++------ .../VPT/Rubber/RubberColliderInspector.cs | 10 +--- .../VPT/Surface/SurfaceColliderInspector.cs | 36 +----------- .../Import/VpxConverter.cs | 56 +++++++++++-------- .../VPT/ItemColliderAuthoring.cs | 46 +++++++++++---- .../VPT/Rubber/RubberColliderAuthoring.cs | 3 +- .../VPT/Rubber/RubberExtensions.cs | 20 ++++++- .../VPT/Surface/SurfaceColliderAuthoring.cs | 3 +- .../VPT/Surface/SurfaceExtensions.cs | 20 ++++++- 9 files changed, 128 insertions(+), 103 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs index d1f01dbc0..5bc993691 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs @@ -14,33 +14,30 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using UnityEditor; using UnityEngine; +using VisualPinball.Engine.Game; +using VisualPinball.Engine.VPT; namespace VisualPinball.Unity.Editor { - public class ItemColliderInspector : ItemInspector where TAuthoring : MonoBehaviour + public class ItemColliderInspector : ItemInspector + where TColliderAuthoring : ItemColliderAuthoring + where TData : ItemData + where TItem : Item, IHittable, IRenderable + where TAuthoring : ItemAuthoring { - protected TAuthoring GetAuthoring() - { - var mb = target as MonoBehaviour; - if (mb == null) { - return null; - } - var go = mb.gameObject; - - var auth = go.GetComponent(); - if (auth == null && go.transform.parent != null) { - auth = go.transform.parent.GetComponent(); - } - - if (auth == null && go.transform.parent.transform.parent != null) { - auth = go.transform.parent.transform.parent.GetComponent(); + public TData Data { + get { + var mb = target as TColliderAuthoring; + return mb == null ? null : mb.Data; } + } - if (auth == null) { - Debug.LogWarning("No parent rubber authoring component found."); - } - return auth; + protected void NoDataPanel() + { + // todo add more details + GUILayout.Label("No data! Parent missing?"); } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs index 200c35e02..5f27f6989 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs @@ -19,11 +19,10 @@ using UnityEditor; using VisualPinball.Engine.VPT.Rubber; - namespace VisualPinball.Unity.Editor { [CustomEditor(typeof(RubberColliderAuthoring))] - public class RubberColliderInspector : ItemColliderInspector + public class RubberColliderInspector : ItemColliderInspector { private RubberData _rubberData; @@ -32,16 +31,13 @@ public class RubberColliderInspector : ItemColliderInspector protected override void OnEnable() { base.OnEnable(); - - var rubberAuthoring = GetAuthoring(); - if (rubberAuthoring != null) { - _rubberData = rubberAuthoring.data; - } + _rubberData = Data; } public override void OnInspectorGUI() { if (_rubberData == null) { + NoDataPanel(); return; } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs index 9dffc44f3..808f80888 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs @@ -23,7 +23,7 @@ namespace VisualPinball.Unity.Editor { [CustomEditor(typeof(SurfaceColliderAuthoring))] - public class SurfaceColliderInspector : ItemColliderInspector + public class SurfaceColliderInspector : ItemColliderInspector { private SurfaceData _surfaceData; @@ -33,16 +33,13 @@ public class SurfaceColliderInspector : ItemColliderInspector protected override void OnEnable() { base.OnEnable(); - - var surfaceAuthoring = GetAuthoring(); - if (surfaceAuthoring != null) { - _surfaceData = surfaceAuthoring.data; - } + _surfaceData = Data; } public override void OnInspectorGUI() { if (_surfaceData == null) { + NoDataPanel(); return; } @@ -80,33 +77,6 @@ public override void OnInspectorGUI() EditorGUILayout.EndFoldoutHeaderGroup(); EditorGUI.EndDisabledGroup(); - - - - - // ItemDataField("Collidable", ref _surfaceData.IsCollidable, false); - // - // EditorGUI.BeginDisabledGroup(!_surfaceData.IsCollidable); - // ItemDataField("Has Hit Event", ref _surfaceData.HitEvent, false); - // ItemDataField("Hit Height", ref _surfaceData.HitHeight, false); - // EditorGUI.EndDisabledGroup(); - // - // if (_foldoutMaterial = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMaterial, "Physics Material")) { - // EditorGUI.BeginDisabledGroup(_rubberData.OverwritePhysics || !_rubberData.IsCollidable); - // MaterialField("Preset", ref _rubberData.PhysicsMaterial, false); - // EditorGUI.EndDisabledGroup(); - // - // EditorGUI.BeginDisabledGroup(!_rubberData.IsCollidable); - // ItemDataField("Overwrite Preset", ref _rubberData.OverwritePhysics, false); - // EditorGUI.EndDisabledGroup(); - // - // EditorGUI.BeginDisabledGroup(!_rubberData.OverwritePhysics || !_rubberData.IsCollidable); - // ItemDataField("Elasticity", ref _rubberData.Elasticity, false); - // ItemDataField("Elasticity Falloff", ref _rubberData.ElasticityFalloff, false); - // ItemDataField("Friction", ref _rubberData.Friction, false); - // ItemDataField("Scatter Angle", ref _rubberData.Scatter, false); - // EditorGUI.EndDisabledGroup(); - // } } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index b072b122d..1ae3c6390 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -177,10 +177,38 @@ public static IEnumerable> ConvertRenderObjects( obj = new GameObject(rog.Name); obj.transform.parent = parent.transform; - var createdObjs = new Tuple[0]; + var createdObjs = rog.SubComponent == RenderObjectGroup.ItemSubComponent.Collider + ? new Tuple[0] + : SetupRenderObject(obj, rog, tb); + + // apply transformation + obj.transform.SetFromMatrix(rog.TransformationMatrix.ToUnityMatrix()); + + // add unity component + switch (item) { + case Bumper bumper: bumper.SetupGameObject(obj, rog); break; + case Flipper flipper: flipper.SetupGameObject(obj, rog); break; + case Gate gate: gate.SetupGameObject(obj, rog); break; + case HitTarget hitTarget: hitTarget.SetupGameObject(obj, rog); break; + case Kicker kicker: kicker.SetupGameObject(obj, rog); break; + case Engine.VPT.Light.Light lt: lt.SetupGameObject(obj, rog); break; + case Plunger plunger: plunger.SetupGameObject(obj, rog); break; + case Primitive primitive: primitive.SetupGameObject(obj, rog); break; + case Ramp ramp: ramp.SetupGameObject(obj, rog); break; + case Rubber rubber: rubber.SetupGameObject(obj, rog); break; + case Spinner spinner: spinner.SetupGameObject(obj, rog); break; + case Surface surface: surface.SetupGameObject(obj, rog); break; + case Table table: table.SetupGameObject(obj, rog); break; + case Trigger trigger: trigger.SetupGameObject(obj, rog); break; + } + return createdObjs; + } + private static IEnumerable> SetupRenderObject(GameObject obj, RenderObjectGroup rog, TableAuthoring tb) + { + var createdObjs = new Tuple[0]; if (rog.HasOnlyChild && !rog.ForceChild) { - SetupRenderObject(rog.RenderObjects[0], obj, tb); + SetupMesh(obj, rog.RenderObjects[0], tb); createdObjs = new[] { new Tuple(obj, rog.RenderObjects[0]) }; } else if (rog.HasChildren) { @@ -190,35 +218,15 @@ public static IEnumerable> ConvertRenderObjects( var subObj = new GameObject(ro.Name); subObj.transform.SetParent(obj.transform, false); subObj.layer = ChildObjectsLayer; - SetupRenderObject(ro, subObj, tb); + SetupMesh(subObj, ro, tb); createdObjs[i++] = new Tuple(subObj, ro); } } - // apply transformation - obj.transform.SetFromMatrix(rog.TransformationMatrix.ToUnityMatrix()); - - // add unity component - switch (item) { - case Bumper bumper: bumper.SetupGameObject(obj, rog); break; - case Flipper flipper: flipper.SetupGameObject(obj, rog); break; - case Gate gate: gate.SetupGameObject(obj, rog); break; - case HitTarget hitTarget: hitTarget.SetupGameObject(obj, rog); break; - case Kicker kicker: kicker.SetupGameObject(obj, rog); break; - case Engine.VPT.Light.Light lt: lt.SetupGameObject(obj, rog); break; - case Plunger plunger: plunger.SetupGameObject(obj, rog); break; - case Primitive primitive: primitive.SetupGameObject(obj, rog); break; - case Ramp ramp: ramp.SetupGameObject(obj, rog); break; - case Rubber rubber: rubber.SetupGameObject(obj, rog); break; - case Spinner spinner: spinner.SetupGameObject(obj, rog); break; - case Surface surface: surface.SetupGameObject(obj, rog); break; - case Table table: table.SetupGameObject(obj, rog); break; - case Trigger trigger: trigger.SetupGameObject(obj, rog); break; - } return createdObjs; } - private static void SetupRenderObject(RenderObject ro, GameObject obj, TableAuthoring ta) + private static void SetupMesh(GameObject obj, RenderObject ro, TableAuthoring ta) { if (ro.Mesh == null) { Logger.Warn($"No mesh for object {obj.name}, skipping."); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs index 192f44eba..835c40ca9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs @@ -14,27 +14,51 @@ // 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.Game; using VisualPinball.Engine.VPT; namespace VisualPinball.Unity { - public class ItemColliderAuthoring : MonoBehaviour where TData : ItemData where TItem : Item, IHittable + public class ItemColliderAuthoring : MonoBehaviour + where TData : ItemData + where TItem : Item, IHittable, IRenderable + where TAuthoring : ItemAuthoring { - [NonSerialized] - public TData Data; + public TData Data => GetData(); - [NonSerialized] - public TItem Item; + private TData _data; - public ItemColliderAuthoring SetItem(TItem item, string gameObjectName = null) + public void SetItem(TItem item, RenderObjectGroup rog) { - Item = item; - Data = item.Data; - name = (gameObjectName ?? Data.GetName()) + " (collider)"; - return this; + _data = item.Data; + name = rog.ComponentName + " (collider)"; + } + + private TData GetData() + { + // if data is set, this is a full-fledged item + if (_data != null) { + return _data; + } + + // otherwise, retrieve data from parent + var go = gameObject; + var ac = go.GetComponent(); + if (ac == null && go.transform.parent != null) { + ac = go.transform.parent.GetComponent(); + } + + if (ac == null && go.transform.parent.transform.parent != null) { + ac = go.transform.parent.transform.parent.GetComponent(); + } + + if (ac != null) { + return ac.data; + } + + Debug.LogWarning("No same- or parent authoring component found."); + return null; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs index 0f458aeab..d485669f2 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs @@ -20,8 +20,7 @@ namespace VisualPinball.Unity { [AddComponentMenu("Visual Pinball/Collision/Rubber Collider")] - public class RubberColliderAuthoring : ItemColliderAuthoring + public class RubberColliderAuthoring : ItemColliderAuthoring { - } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs index 6c9849bcd..34e05ced0 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.Game; @@ -24,8 +25,23 @@ internal static class RubberExtensions { public static void SetupGameObject(this Engine.VPT.Rubber.Rubber rubber, GameObject obj, RenderObjectGroup rog) { - obj.AddComponent().SetItem(rubber); - obj.AddComponent(); + switch (rog.SubComponent) { + case RenderObjectGroup.ItemSubComponent.None: + + obj.AddComponent().SetItem(rubber); + obj.AddComponent(); + break; + + case RenderObjectGroup.ItemSubComponent.Collider: + obj.AddComponent().SetItem(rubber, rog); + break; + + case RenderObjectGroup.ItemSubComponent.Mesh: + break; + + default: + throw new ArgumentOutOfRangeException(); + } obj.AddComponent(); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs index d034d2d2d..b0e65995c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs @@ -20,8 +20,7 @@ namespace VisualPinball.Unity { [AddComponentMenu("Visual Pinball/Collision/Surface Collider")] - public class SurfaceColliderAuthoring : ItemColliderAuthoring + public class SurfaceColliderAuthoring : ItemColliderAuthoring { - } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs index 68f9a9696..50126a9de 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.Game; @@ -24,8 +25,23 @@ internal static class SurfaceExtensions { public static void SetupGameObject(this Engine.VPT.Surface.Surface surface, GameObject obj, RenderObjectGroup rog) { - obj.AddComponent().SetItem(surface); - obj.AddComponent(); + switch (rog.SubComponent) { + case RenderObjectGroup.ItemSubComponent.None: + + obj.AddComponent().SetItem(surface); + obj.AddComponent(); + break; + + case RenderObjectGroup.ItemSubComponent.Collider: + obj.AddComponent().SetItem(surface, rog); + break; + + case RenderObjectGroup.ItemSubComponent.Mesh: + break; + + default: + throw new ArgumentOutOfRangeException(); + } obj.AddComponent(); } } From c15a5a445f204617a26347bbe407d8aef8cffc9f Mon Sep 17 00:00:00 2001 From: freezy Date: Fri, 25 Sep 2020 00:43:48 +0200 Subject: [PATCH 022/124] import: Return created MonoBehaviour. --- .../Toolbox/ToolboxEditor.cs | 2 +- .../Import/VpxConverter.cs | 34 +++++++++++++------ .../VPT/Bumper/BumperAuthoring.cs | 4 +++ .../VPT/Flipper/FlipperAuthoring.cs | 4 +++ .../VPT/Gate/GateAuthoring.cs | 4 +++ .../VPT/HitTarget/HitTargetAuthoring.cs | 4 +++ .../VPT/IHittableAuthoring.cs | 2 ++ .../VPT/Kicker/KickerAuthoring.cs | 4 +++ .../VPT/Plunger/PlungerAuthoring.cs | 4 +++ .../VPT/Primitive/PrimitiveAuthoring.cs | 4 +++ .../VPT/Ramp/RampAuthoring.cs | 4 +++ .../VPT/Rubber/RubberAuthoring.cs | 8 +++++ .../VPT/Rubber/RubberExtensions.cs | 6 ++-- .../VPT/Spinner/SpinnerAuthoring.cs | 4 +++ .../VPT/Surface/SurfaceAuthoring.cs | 9 +++++ .../VPT/Surface/SurfaceExtensions.cs | 6 ++-- .../VPT/Trigger/TriggerAuthoring.cs | 4 +++ 17 files changed, 92 insertions(+), 15 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs index 1261a1a25..d381b2d79 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs @@ -185,7 +185,7 @@ private void CreateItem(Func create, string actionName) whe private GameObject CreateRenderable(IRenderable renderable) { var rog = renderable.GetRenderObjects(_tableAuthoring.Table, Origin.Original, false); - VpxConverter.ConvertRenderObjects(renderable, rog, GetOrCreateParent(_tableAuthoring, rog), _tableAuthoring, out var obj); + VpxConverter.ConvertRenderObjects(renderable, rog, GetOrCreateParent(_tableAuthoring, rog), _tableAuthoring, out var obj, out _); return obj; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index 1ae3c6390..56713843d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -131,7 +131,8 @@ private void ConvertGameItems(GameObject tableGameObject) private void ConvertRenderables(GameObject tableGameObject) { - var createdRootObjs = new Dictionary(); + var createMainObjs = new Dictionary(); + var createdMainMbs = new Dictionary(); var createdObjs = new Dictionary>>(); var renderObjects = from entry in _renderObjects orderby entry.Value.SubComponent select entry; @@ -148,19 +149,22 @@ private void ConvertRenderables(GameObject tableGameObject) } // create object(s) - createdObjs[renderable] = ConvertRenderObjects(renderable, rog, _parents[rog.Parent], _tableAuthoring, out var rootObj); + createdObjs[renderable] = ConvertRenderObjects(renderable, rog, _parents[rog.Parent], _tableAuthoring, + out var rootObj, out var rootMb); // if the object's names was parsed to be part of another object, re-link to other object. if (rog.SubComponent != RenderObjectGroup.ItemSubComponent.None) { - if (!createdRootObjs.ContainsKey(rog.ComponentName.ToLower())) { + if (!createMainObjs.ContainsKey(rog.ComponentName.ToLower())) { Logger.Warn($"Cannot find component \"{rog.ComponentName.ToLower()}\" that is supposed to be the parent of \"{rog.Name}\"."); } else { - var mainObj = createdRootObjs[rog.ComponentName.ToLower()]; + var mainObj = createMainObjs[rog.ComponentName.ToLower()]; + var mainMb = createdMainMbs[rog.ComponentName.ToLower()]; rootObj.transform.SetParent(mainObj.transform, false); } } else { - createdRootObjs[rog.Name.ToLower()] = rootObj; + createMainObjs[rog.Name.ToLower()] = rootObj; + createdMainMbs[rog.Name.ToLower()] = rootMb; } } @@ -172,7 +176,8 @@ private void ConvertRenderables(GameObject tableGameObject) } } - public static IEnumerable> ConvertRenderObjects(IRenderable item, RenderObjectGroup rog, GameObject parent, TableAuthoring tb, out GameObject obj) + public static IEnumerable> ConvertRenderObjects(IRenderable item, RenderObjectGroup rog, + GameObject parent, TableAuthoring tb, out GameObject obj, out MonoBehaviour mb) { obj = new GameObject(rog.Name); obj.transform.parent = parent.transform; @@ -184,7 +189,15 @@ public static IEnumerable> ConvertRenderObjects( // apply transformation obj.transform.SetFromMatrix(rog.TransformationMatrix.ToUnityMatrix()); - // add unity component + // add unity components + mb = SetupGameObjectComponents(item, obj, rog); + + return createdObjs; + } + + private static MonoBehaviour SetupGameObjectComponents(IRenderable item, GameObject obj, RenderObjectGroup rog) + { + MonoBehaviour mb = null; switch (item) { case Bumper bumper: bumper.SetupGameObject(obj, rog); break; case Flipper flipper: flipper.SetupGameObject(obj, rog); break; @@ -195,13 +208,14 @@ public static IEnumerable> ConvertRenderObjects( case Plunger plunger: plunger.SetupGameObject(obj, rog); break; case Primitive primitive: primitive.SetupGameObject(obj, rog); break; case Ramp ramp: ramp.SetupGameObject(obj, rog); break; - case Rubber rubber: rubber.SetupGameObject(obj, rog); break; + case Rubber rubber: mb = rubber.SetupGameObject(obj, rog); break; case Spinner spinner: spinner.SetupGameObject(obj, rog); break; - case Surface surface: surface.SetupGameObject(obj, rog); break; + case Surface surface: mb = surface.SetupGameObject(obj, rog); break; case Table table: table.SetupGameObject(obj, rog); break; case Trigger trigger: trigger.SetupGameObject(obj, rog); break; } - return createdObjs; + + return mb; } private static IEnumerable> SetupRenderObject(GameObject obj, RenderObjectGroup rog, TableAuthoring tb) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs index 90e7c7044..0f2154758 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs @@ -57,6 +57,10 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterBumper(Item, entity, gameObject); } + public void RemoveHittableComponent() + { + } + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() => data.Center.ToUnityVector3(0f); public override void SetEditorPosition(Vector3 pos) => data.Center = pos.ToVertex2Dxy(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs index e5df43b11..85220dff2 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs @@ -64,6 +64,10 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterFlipper(Item, entity, gameObject); } + public void RemoveHittableComponent() + { + } + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() => data.Center.ToUnityVector3(0f); public override void SetEditorPosition(Vector3 pos) => data.Center = pos.ToVertex2Dxy(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs index d099683f3..3c737f689 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs @@ -44,6 +44,10 @@ private void OnDestroy() } } + public void RemoveHittableComponent() + { + } + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; public override Vector3 GetEditorPosition() => data.Center.ToUnityVector3(data.Height); public override void SetEditorPosition(Vector3 pos) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs index 9f381a9aa..b321b9d77 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs @@ -68,6 +68,10 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterHitTarget(hitTarget, entity, gameObject); } + public void RemoveHittableComponent() + { + } + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; public override Vector3 GetEditorPosition() => data.Position.ToUnityVector3(); public override void SetEditorPosition(Vector3 pos) => data.Position = pos.ToVertex3D(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IHittableAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IHittableAuthoring.cs index 6cbf4d856..8ca1aea22 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IHittableAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IHittableAuthoring.cs @@ -21,5 +21,7 @@ namespace VisualPinball.Unity public interface IHittableAuthoring { IHittable Hittable { get; } + + void RemoveHittableComponent(); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs index 5028f458b..9bfa441e9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs @@ -87,6 +87,10 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterKicker(Item, entity, gameObject); } + public void RemoveHittableComponent() + { + } + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() => data.Center.ToUnityVector3(0f); public override void SetEditorPosition(Vector3 pos) => data.Center = pos.ToVertex2Dxy(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs index e522af94c..71f80309f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs @@ -94,6 +94,10 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio }); } + public void RemoveHittableComponent() + { + } + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() => data.Center.ToUnityVector3(0f); public override void SetEditorPosition(Vector3 pos) => data.Center = pos.ToVertex3D(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs index f6a1fec3b..ea1648996 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs @@ -41,6 +41,10 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterPrimitive(primitive, entity, gameObject); } + public void RemoveHittableComponent() + { + } + protected override Primitive GetItem() => new Primitive(data); public IHittable Hittable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs index 1b7bf8194..fca31461b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs @@ -47,6 +47,10 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterRamp(Item, entity, gameObject); } + public void RemoveHittableComponent() + { + } + private void OnDestroy() { if (!Application.isPlaying) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs index c91556d32..c5c109899 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs @@ -54,6 +54,14 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterRubber(Item, entity, gameObject); } + public void RemoveHittableComponent() + { + var hc = gameObject.GetComponent(); + if (hc != null) { + DestroyImmediate(hc); + } + } + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; public override Vector3 GetEditorPosition() { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs index 34e05ced0..7f98021d4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs @@ -23,12 +23,13 @@ namespace VisualPinball.Unity { internal static class RubberExtensions { - public static void SetupGameObject(this Engine.VPT.Rubber.Rubber rubber, GameObject obj, RenderObjectGroup rog) + public static MonoBehaviour SetupGameObject(this Engine.VPT.Rubber.Rubber rubber, GameObject obj, RenderObjectGroup rog) { + MonoBehaviour mb = null; switch (rog.SubComponent) { case RenderObjectGroup.ItemSubComponent.None: - obj.AddComponent().SetItem(rubber); + mb = obj.AddComponent().SetItem(rubber); obj.AddComponent(); break; @@ -43,6 +44,7 @@ public static void SetupGameObject(this Engine.VPT.Rubber.Rubber rubber, GameObj throw new ArgumentOutOfRangeException(); } obj.AddComponent(); + return mb; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs index 3c01fcc73..6c88c87d7 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs @@ -44,6 +44,10 @@ private void OnDestroy() } } + public void RemoveHittableComponent() + { + } + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; public override Vector3 GetEditorPosition() => data.Center.ToUnityVector3(data.Height); public override void SetEditorPosition(Vector3 pos) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs index 82ee7f2ce..a55c8b82d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs @@ -56,6 +56,15 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterSurface(Item, entity, gameObject); } + + public void RemoveHittableComponent() + { + var hc = gameObject.GetComponent(); + if (hc != null) { + DestroyImmediate(hc); + } + } + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() { if (data == null || data.DragPoints.Length == 0) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs index 50126a9de..da58c336a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs @@ -23,12 +23,13 @@ namespace VisualPinball.Unity { internal static class SurfaceExtensions { - public static void SetupGameObject(this Engine.VPT.Surface.Surface surface, GameObject obj, RenderObjectGroup rog) + public static MonoBehaviour SetupGameObject(this Engine.VPT.Surface.Surface surface, GameObject obj, RenderObjectGroup rog) { + MonoBehaviour mb = null; switch (rog.SubComponent) { case RenderObjectGroup.ItemSubComponent.None: - obj.AddComponent().SetItem(surface); + mb = obj.AddComponent().SetItem(surface); obj.AddComponent(); break; @@ -43,6 +44,7 @@ public static void SetupGameObject(this Engine.VPT.Surface.Surface surface, Game throw new ArgumentOutOfRangeException(); } obj.AddComponent(); + return mb; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs index c1db7c848..746faec5b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs @@ -66,6 +66,10 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterTrigger(trigger, entity, gameObject); } + public void RemoveHittableComponent() + { + } + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() => data.Center.ToUnityVector3(0f); From c26acbf10dc79d96dd738f498f2f2418ea367cc1 Mon Sep 17 00:00:00 2001 From: freezy Date: Fri, 25 Sep 2020 00:52:50 +0200 Subject: [PATCH 023/124] import: Remove collider component if overridden. --- .../Toolbox/ToolboxEditor.cs | 3 ++- .../Import/VpxConverter.cs | 19 ++++++++++--------- .../VPT/Rubber/RubberExtensions.cs | 2 +- .../VPT/Surface/SurfaceExtensions.cs | 6 +++++- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs index d381b2d79..7f78a5088 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs @@ -185,7 +185,8 @@ private void CreateItem(Func create, string actionName) whe private GameObject CreateRenderable(IRenderable renderable) { var rog = renderable.GetRenderObjects(_tableAuthoring.Table, Origin.Original, false); - VpxConverter.ConvertRenderObjects(renderable, rog, GetOrCreateParent(_tableAuthoring, rog), _tableAuthoring, out var obj, out _); + VpxConverter.ConvertRenderObjects(renderable, rog, GetOrCreateParent(_tableAuthoring, rog), _tableAuthoring, out var obj); + VpxConverter.SetupGameObjectComponents(renderable, obj, rog, null); return obj; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index 56713843d..ddb66f8cc 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -149,20 +149,23 @@ private void ConvertRenderables(GameObject tableGameObject) } // create object(s) - createdObjs[renderable] = ConvertRenderObjects(renderable, rog, _parents[rog.Parent], _tableAuthoring, - out var rootObj, out var rootMb); + createdObjs[renderable] = ConvertRenderObjects(renderable, rog, _parents[rog.Parent], + _tableAuthoring, out var rootObj); // if the object's names was parsed to be part of another object, re-link to other object. if (rog.SubComponent != RenderObjectGroup.ItemSubComponent.None) { if (!createMainObjs.ContainsKey(rog.ComponentName.ToLower())) { Logger.Warn($"Cannot find component \"{rog.ComponentName.ToLower()}\" that is supposed to be the parent of \"{rog.Name}\"."); + SetupGameObjectComponents(renderable, rootObj, rog); } else { var mainObj = createMainObjs[rog.ComponentName.ToLower()]; var mainMb = createdMainMbs[rog.ComponentName.ToLower()]; rootObj.transform.SetParent(mainObj.transform, false); + SetupGameObjectComponents(renderable, rootObj, rog, mainMb); } } else { + var rootMb = SetupGameObjectComponents(renderable, rootObj, rog); createMainObjs[rog.Name.ToLower()] = rootObj; createdMainMbs[rog.Name.ToLower()] = rootMb; } @@ -177,7 +180,7 @@ private void ConvertRenderables(GameObject tableGameObject) } public static IEnumerable> ConvertRenderObjects(IRenderable item, RenderObjectGroup rog, - GameObject parent, TableAuthoring tb, out GameObject obj, out MonoBehaviour mb) + GameObject parent, TableAuthoring tb, out GameObject obj) { obj = new GameObject(rog.Name); obj.transform.parent = parent.transform; @@ -189,13 +192,11 @@ public static IEnumerable> ConvertRenderObjects( // apply transformation obj.transform.SetFromMatrix(rog.TransformationMatrix.ToUnityMatrix()); - // add unity components - mb = SetupGameObjectComponents(item, obj, rog); - return createdObjs; } - private static MonoBehaviour SetupGameObjectComponents(IRenderable item, GameObject obj, RenderObjectGroup rog) + public static MonoBehaviour SetupGameObjectComponents(IRenderable item, GameObject obj, + RenderObjectGroup rog, MonoBehaviour mainMb = null) { MonoBehaviour mb = null; switch (item) { @@ -208,9 +209,9 @@ private static MonoBehaviour SetupGameObjectComponents(IRenderable item, GameObj case Plunger plunger: plunger.SetupGameObject(obj, rog); break; case Primitive primitive: primitive.SetupGameObject(obj, rog); break; case Ramp ramp: ramp.SetupGameObject(obj, rog); break; - case Rubber rubber: mb = rubber.SetupGameObject(obj, rog); break; + case Rubber rubber: mb = rubber.SetupGameObject(obj, rog, mainMb); break; case Spinner spinner: spinner.SetupGameObject(obj, rog); break; - case Surface surface: mb = surface.SetupGameObject(obj, rog); break; + case Surface surface: mb = surface.SetupGameObject(obj, rog, mainMb); break; case Table table: table.SetupGameObject(obj, rog); break; case Trigger trigger: trigger.SetupGameObject(obj, rog); break; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs index 7f98021d4..760c1cc69 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs @@ -23,7 +23,7 @@ namespace VisualPinball.Unity { internal static class RubberExtensions { - public static MonoBehaviour SetupGameObject(this Engine.VPT.Rubber.Rubber rubber, GameObject obj, RenderObjectGroup rog) + public static MonoBehaviour SetupGameObject(this Engine.VPT.Rubber.Rubber rubber, GameObject obj, RenderObjectGroup rog, MonoBehaviour mainMb) { MonoBehaviour mb = null; switch (rog.SubComponent) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs index da58c336a..86aede0c9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs @@ -23,7 +23,8 @@ namespace VisualPinball.Unity { internal static class SurfaceExtensions { - public static MonoBehaviour SetupGameObject(this Engine.VPT.Surface.Surface surface, GameObject obj, RenderObjectGroup rog) + public static MonoBehaviour SetupGameObject(this Engine.VPT.Surface.Surface surface, GameObject obj, + RenderObjectGroup rog, MonoBehaviour mainMb) { MonoBehaviour mb = null; switch (rog.SubComponent) { @@ -35,6 +36,9 @@ public static MonoBehaviour SetupGameObject(this Engine.VPT.Surface.Surface surf case RenderObjectGroup.ItemSubComponent.Collider: obj.AddComponent().SetItem(surface, rog); + if (mainMb != null && mainMb is IHittableAuthoring hittableAuthoring) { + hittableAuthoring.RemoveHittableComponent(); + } break; case RenderObjectGroup.ItemSubComponent.Mesh: From e4044c3bd3ccbdf0fcd2073c2060bc5050920f2f Mon Sep 17 00:00:00 2001 From: freezy Date: Fri, 25 Sep 2020 01:16:26 +0200 Subject: [PATCH 024/124] editor: Move inspectors into their own folder, and add link interface to authoring components. --- .../Toolbox/ToolboxEditor.cs | 2 +- .../VPT/Bumper.meta | 8 +++++++ .../Bumper}/BumperInspector.cs | 0 .../Bumper}/BumperInspector.cs.meta | 2 +- .../VPT/Flipper.meta | 8 +++++++ .../Flipper}/FlipperInspector.cs | 0 .../Flipper}/FlipperInspector.cs.meta | 2 +- .../VisualPinball.Unity.Editor/VPT/Gate.meta | 8 +++++++ .../{Inspectors => VPT/Gate}/GateInspector.cs | 0 .../Gate}/GateInspector.cs.meta | 2 +- .../VPT/HitTarget.meta | 8 +++++++ .../HitTarget}/HitTargetInspector.cs | 0 .../HitTarget}/HitTargetInspector.cs.meta | 2 +- .../VPT/ItemColliderInspector.cs | 1 - .../VPT/Kicker.meta | 8 +++++++ .../Kicker}/KickerInspector.cs | 0 .../Kicker}/KickerInspector.cs.meta | 2 +- .../VisualPinball.Unity.Editor/VPT/Light.meta | 8 +++++++ .../Light}/LightInspector.cs | 0 .../Light}/LightInspector.cs.meta | 2 +- .../VPT/Plunger.meta | 8 +++++++ .../Plunger}/PlungerInspector.cs | 0 .../Plunger}/PlungerInspector.cs.meta | 2 +- .../VPT/Primitive.meta | 8 +++++++ .../Primitive}/PrimitiveInspector.cs | 0 .../Primitive}/PrimitiveInspector.cs.meta | 2 +- .../VisualPinball.Unity.Editor/VPT/Ramp.meta | 8 +++++++ .../{Inspectors => VPT/Ramp}/RampInspector.cs | 0 .../Ramp}/RampInspector.cs.meta | 2 +- .../VPT/Spinner.meta | 8 +++++++ .../Spinner}/SpinnerInspector.cs | 0 .../Spinner}/SpinnerInspector.cs.meta | 2 +- .../VPT/Surface/SurfaceInspector.cs | 1 - .../VisualPinball.Unity.Editor/VPT/Table.meta | 8 +++++++ .../Table}/TableInspector.cs | 0 .../Table}/TableInspector.cs.meta | 2 +- .../{Inspectors => VPT}/TransformInspector.cs | 0 .../TransformInspector.cs.meta | 2 +- .../VPT/Trigger.meta | 8 +++++++ .../Trigger}/TriggerInspector.cs | 0 .../Trigger}/TriggerInspector.cs.meta | 2 +- .../Import/VpxConverter.cs | 5 ++--- .../VPT/Bumper/BumperAuthoring.cs | 4 ++++ .../VPT/Flipper/FlipperAuthoring.cs | 4 ++++ .../VPT/Gate/GateAuthoring.cs | 4 ++++ .../VPT/HitTarget/HitTargetAuthoring.cs | 4 ++++ .../VPT/IExtendableAuthoring.cs | 16 ++++++++++++++ .../VPT/IHittableAuthoring.cs | 2 +- .../VisualPinball.Unity/VPT/IItemAuthoring.cs | 22 +++++++++++++++++++ .../VisualPinball.Unity/VPT/ItemAuthoring.cs | 3 +-- .../VPT/ItemColliderAuthoring.cs | 9 +++++--- .../VPT/Kicker/KickerAuthoring.cs | 4 ++++ .../VPT/Plunger/PlungerAuthoring.cs | 4 ++++ .../VPT/Primitive/PrimitiveAuthoring.cs | 4 ++++ .../VPT/Ramp/RampAuthoring.cs | 4 ++++ .../VPT/Rubber/RubberAuthoring.cs | 5 +++++ .../VPT/Rubber/RubberColliderAuthoring.cs | 1 + .../VPT/Rubber/RubberExtensions.cs | 3 +++ .../VPT/Spinner/SpinnerAuthoring.cs | 4 ++++ .../VPT/Surface/SurfaceAuthoring.cs | 7 +++++- .../VPT/Surface/SurfaceColliderAuthoring.cs | 1 + .../VPT/Surface/SurfaceExtensions.cs | 3 ++- .../VPT/Trigger/TriggerAuthoring.cs | 4 ++++ 63 files changed, 216 insertions(+), 27 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper.meta rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Bumper}/BumperInspector.cs (100%) rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Bumper}/BumperInspector.cs.meta (83%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper.meta rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Flipper}/FlipperInspector.cs (100%) rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Flipper}/FlipperInspector.cs.meta (83%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate.meta rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Gate}/GateInspector.cs (100%) rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Gate}/GateInspector.cs.meta (83%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget.meta rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/HitTarget}/HitTargetInspector.cs (100%) rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/HitTarget}/HitTargetInspector.cs.meta (83%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker.meta rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Kicker}/KickerInspector.cs (100%) rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Kicker}/KickerInspector.cs.meta (83%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light.meta rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Light}/LightInspector.cs (100%) rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Light}/LightInspector.cs.meta (83%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger.meta rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Plunger}/PlungerInspector.cs (100%) rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Plunger}/PlungerInspector.cs.meta (83%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive.meta rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Primitive}/PrimitiveInspector.cs (100%) rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Primitive}/PrimitiveInspector.cs.meta (83%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp.meta rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Ramp}/RampInspector.cs (100%) rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Ramp}/RampInspector.cs.meta (83%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner.meta rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Spinner}/SpinnerInspector.cs (100%) rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Spinner}/SpinnerInspector.cs.meta (83%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Table.meta rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Table}/TableInspector.cs (100%) rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Table}/TableInspector.cs.meta (83%) rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT}/TransformInspector.cs (100%) rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT}/TransformInspector.cs.meta (83%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger.meta rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Trigger}/TriggerInspector.cs (100%) rename VisualPinball.Unity/VisualPinball.Unity.Editor/{Inspectors => VPT/Trigger}/TriggerInspector.cs.meta (83%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/IExtendableAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/IItemAuthoring.cs diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs index 7f78a5088..8b89cc2ef 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs @@ -185,7 +185,7 @@ private void CreateItem(Func create, string actionName) whe private GameObject CreateRenderable(IRenderable renderable) { var rog = renderable.GetRenderObjects(_tableAuthoring.Table, Origin.Original, false); - VpxConverter.ConvertRenderObjects(renderable, rog, GetOrCreateParent(_tableAuthoring, rog), _tableAuthoring, out var obj); + VpxConverter.ConvertRenderObjects(rog, GetOrCreateParent(_tableAuthoring, rog), _tableAuthoring, out var obj); VpxConverter.SetupGameObjectComponents(renderable, obj, rog, null); return obj; } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper.meta new file mode 100644 index 000000000..d7a1bc242 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7a1c4dabce776bd40a94c509abca3064 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/BumperInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs similarity index 100% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/BumperInspector.cs rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/BumperInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/BumperInspector.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs.meta index e6d827497..279608c40 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/BumperInspector.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: ea67d788d10619049987b819d321819c +guid: 3d8ffa86ab1e82245a5bb0746da8aa5f MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper.meta new file mode 100644 index 000000000..4f65bc023 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 40eddeabad51e3c4b9284d7e2a8d2604 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/FlipperInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs similarity index 100% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/FlipperInspector.cs rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/FlipperInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/FlipperInspector.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs.meta index 5ab137359..2beb9a3c2 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/FlipperInspector.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 6ed9f0658d923a04e8c17409cc34c70d +guid: 0710233447bade14f8b2988552dd62ef MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate.meta new file mode 100644 index 000000000..53ea53525 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 77765108c9e53b24a83fb1304ba73f55 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/GateInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateInspector.cs similarity index 100% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/GateInspector.cs rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateInspector.cs diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/GateInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateInspector.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/GateInspector.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateInspector.cs.meta index 3e36ace26..63f4fb3a0 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/GateInspector.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateInspector.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 5e06eb212eb1d6e4a9fd677d729cc69e +guid: 1c287583055cb644aa429805c440dd8d MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget.meta new file mode 100644 index 000000000..297e58ad5 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fc3dc11ec03f94147b0ed4cec79fd612 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/HitTargetInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetInspector.cs similarity index 100% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/HitTargetInspector.cs rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetInspector.cs diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/HitTargetInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetInspector.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/HitTargetInspector.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetInspector.cs.meta index be14cad75..40f4ed61f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/HitTargetInspector.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetInspector.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 70c8fd6d5b0f038439ab1c237c826cb4 +guid: 81453304846a37b4498b2cc59626ab6d MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs index 5bc993691..4c60df7cc 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -using UnityEditor; using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT; diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker.meta new file mode 100644 index 000000000..1975edbbc --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 93d245a0bae9b724fa358eae4d92760b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/KickerInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerInspector.cs similarity index 100% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/KickerInspector.cs rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerInspector.cs diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/KickerInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerInspector.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/KickerInspector.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerInspector.cs.meta index a6c3628dd..6e96c68ff 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/KickerInspector.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerInspector.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 408b911af692dcd44b7a82035baaa1c2 +guid: cf332b89d7d6f404ca0231447d8cbd17 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light.meta new file mode 100644 index 000000000..2cd336938 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 27482ca4ffcb7514688191854486a47d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/LightInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightInspector.cs similarity index 100% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/LightInspector.cs rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightInspector.cs diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/LightInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightInspector.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/LightInspector.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightInspector.cs.meta index 47101b3b2..8665fcbea 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/LightInspector.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightInspector.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 7257b8ff46e49624db55fbf1057a5c87 +guid: 5287c6c3bb1bd6b43ac50da3fbbfc97c MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger.meta new file mode 100644 index 000000000..010c72f86 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9e2948dcabbc9594bbec417057d8bbc9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/PlungerInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerInspector.cs similarity index 100% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/PlungerInspector.cs rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerInspector.cs diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/PlungerInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerInspector.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/PlungerInspector.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerInspector.cs.meta index 7b0d26e35..e152be953 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/PlungerInspector.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerInspector.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 310bf9118d22bef4d828eea7d0ce60c7 +guid: 408afb6ad2a66ca4f8ced194fbd6da86 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive.meta new file mode 100644 index 000000000..06072596f --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 719ad3887b7525c4d875259286768e66 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/PrimitiveInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveInspector.cs similarity index 100% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/PrimitiveInspector.cs rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveInspector.cs diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/PrimitiveInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveInspector.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/PrimitiveInspector.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveInspector.cs.meta index e08813e35..3fc5dc668 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/PrimitiveInspector.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveInspector.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 91e8a84d0471e2f4eb9f5cb0e5f41df7 +guid: 50cbd109facf82641a7c9b0e373d3648 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp.meta new file mode 100644 index 000000000..c38a59070 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4661797e031619c43af41da678709ed6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/RampInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs similarity index 100% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/RampInspector.cs rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/RampInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/RampInspector.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs.meta index 51ce1b829..84b271164 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/RampInspector.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 3d98179179b071b4a964a9e96434f229 +guid: bc7be19299161ee4790ba91f4248a832 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner.meta new file mode 100644 index 000000000..291c0492f --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1e1b430d93a7c6e4488adc187c12fbc8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/SpinnerInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerInspector.cs similarity index 100% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/SpinnerInspector.cs rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerInspector.cs diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/SpinnerInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerInspector.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/SpinnerInspector.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerInspector.cs.meta index 9b280b80c..b69fbb28c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/SpinnerInspector.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerInspector.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: f4d4a1d045babaa4a91ec345d5762b22 +guid: 7cbe3c7bc87806f4aba938575ddf70f9 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs index ad922b6f6..6a8353d61 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs @@ -26,7 +26,6 @@ public class SurfaceInspector : DragPointsItemInspector private SurfaceAuthoring _targetSurf; private bool _foldoutColorsAndFormatting = true; private bool _foldoutPosition = true; - private bool _foldoutPhysics = true; private bool _foldoutMisc = true; protected override void OnEnable() diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Table.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Table.meta new file mode 100644 index 000000000..d38413e9b --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Table.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3558274f30a3c5941ac2667f8b4c4dd4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TableInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Table/TableInspector.cs similarity index 100% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TableInspector.cs rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Table/TableInspector.cs diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TableInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Table/TableInspector.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TableInspector.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Table/TableInspector.cs.meta index a3bf3a265..6c16f4787 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TableInspector.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Table/TableInspector.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 4c30e1529e248fd4099bc19cebfa1091 +guid: f7506e8802932c04288bb52e9ef8609a MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TransformInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs similarity index 100% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TransformInspector.cs rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TransformInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TransformInspector.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs.meta index d41c09390..b9da64ab0 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TransformInspector.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 2f43f00366771174f8c09aa8dfb146fb +guid: 37d98137d4c873e468cf564e34f71658 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger.meta new file mode 100644 index 000000000..be3150936 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 494bfc67a455d4c438751f809ada31f2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TriggerInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerInspector.cs similarity index 100% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TriggerInspector.cs rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerInspector.cs diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TriggerInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerInspector.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TriggerInspector.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerInspector.cs.meta index 8737f94a9..d28b6d183 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TriggerInspector.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerInspector.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 27bb4e265c268544090b5451e14b7f67 +guid: 1062d80f8618f1a4ba159ac14443988a MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index ddb66f8cc..ef53be101 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -149,8 +149,7 @@ private void ConvertRenderables(GameObject tableGameObject) } // create object(s) - createdObjs[renderable] = ConvertRenderObjects(renderable, rog, _parents[rog.Parent], - _tableAuthoring, out var rootObj); + createdObjs[renderable] = ConvertRenderObjects(rog, _parents[rog.Parent], _tableAuthoring, out var rootObj); // if the object's names was parsed to be part of another object, re-link to other object. if (rog.SubComponent != RenderObjectGroup.ItemSubComponent.None) { @@ -179,7 +178,7 @@ private void ConvertRenderables(GameObject tableGameObject) } } - public static IEnumerable> ConvertRenderObjects(IRenderable item, RenderObjectGroup rog, + public static IEnumerable> ConvertRenderObjects(RenderObjectGroup rog, GameObject parent, TableAuthoring tb, out GameObject obj) { obj = new GameObject(rog.Name); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs index 0f2154758..770d36eb8 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs @@ -61,6 +61,10 @@ public void RemoveHittableComponent() { } + public void LinkChild(IItemAuthoring item) + { + } + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() => data.Center.ToUnityVector3(0f); public override void SetEditorPosition(Vector3 pos) => data.Center = pos.ToVertex2Dxy(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs index 85220dff2..92d0b2921 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs @@ -68,6 +68,10 @@ public void RemoveHittableComponent() { } + public void LinkChild(IItemAuthoring item) + { + } + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() => data.Center.ToUnityVector3(0f); public override void SetEditorPosition(Vector3 pos) => data.Center = pos.ToVertex2Dxy(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs index 3c737f689..e383a61d4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs @@ -48,6 +48,10 @@ public void RemoveHittableComponent() { } + public void LinkChild(IItemAuthoring item) + { + } + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; public override Vector3 GetEditorPosition() => data.Center.ToUnityVector3(data.Height); public override void SetEditorPosition(Vector3 pos) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs index b321b9d77..4ef43abb3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs @@ -72,6 +72,10 @@ public void RemoveHittableComponent() { } + public void LinkChild(IItemAuthoring item) + { + } + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; public override Vector3 GetEditorPosition() => data.Position.ToUnityVector3(); public override void SetEditorPosition(Vector3 pos) => data.Position = pos.ToVertex3D(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IExtendableAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IExtendableAuthoring.cs new file mode 100644 index 000000000..a5fddaefb --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IExtendableAuthoring.cs @@ -0,0 +1,16 @@ +using VisualPinball.Engine.VPT; + +namespace VisualPinball.Unity +{ + /// + /// This interface is for items that allow sub items to be linked to. + /// + /// For example, a Flipper might have a different mesh, and hence + /// a different item being linked to it (and translated/animated along + /// with it). + /// + public interface IExtendableAuthoring + { + void LinkChild(IItemAuthoring item); + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IHittableAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IHittableAuthoring.cs index 8ca1aea22..8ab911269 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IHittableAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IHittableAuthoring.cs @@ -18,7 +18,7 @@ namespace VisualPinball.Unity { - public interface IHittableAuthoring + public interface IHittableAuthoring : IExtendableAuthoring { IHittable Hittable { get; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemAuthoring.cs new file mode 100644 index 000000000..d43fb4d2a --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemAuthoring.cs @@ -0,0 +1,22 @@ +using UnityEngine; + +namespace VisualPinball.Unity +{ + /// + /// The non-typed version of ItemAuthoring. + /// + public interface IItemAuthoring + { + ItemDataTransformType EditorPositionType { get; } + Vector3 GetEditorPosition(); + void SetEditorPosition(Vector3 pos); + + ItemDataTransformType EditorRotationType { get; } + Vector3 GetEditorRotation(); + void SetEditorRotation(Vector3 rot); + + ItemDataTransformType EditorScaleType { get; } + Vector3 GetEditorScale(); + void SetEditorScale(Vector3 rot); + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs index 6cefa19d2..d320bd3b5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs @@ -35,7 +35,7 @@ namespace VisualPinball.Unity { - public abstract class ItemAuthoring : MonoBehaviour, IEditableItemAuthoring, IIdentifiableItemAuthoring, + public abstract class ItemAuthoring : MonoBehaviour, IItemAuthoring, IEditableItemAuthoring, IIdentifiableItemAuthoring, ILayerableItemAuthoring where TData : ItemData where TItem : Item, IRenderable { [SerializeField] @@ -193,7 +193,6 @@ protected virtual void OnDrawGizmosSelected() } } - private static void UpdateMesh(string childName, GameObject go, RenderObjectGroup rog, TableAuthoring table) { var mr = go.GetComponent(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs index 835c40ca9..1a713e354 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs @@ -20,21 +20,24 @@ namespace VisualPinball.Unity { - public class ItemColliderAuthoring : MonoBehaviour + public abstract class ItemColliderAuthoring : ItemAuthoring where TData : ItemData where TItem : Item, IHittable, IRenderable where TAuthoring : ItemAuthoring { public TData Data => GetData(); - private TData _data; + protected TData _data; - public void SetItem(TItem item, RenderObjectGroup rog) + public IItemAuthoring SetItem(TItem item, RenderObjectGroup rog) { _data = item.Data; name = rog.ComponentName + " (collider)"; + return this; } + protected override string[] Children => new string[0]; + private TData GetData() { // if data is set, this is a full-fledged item diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs index 9bfa441e9..a821dfbcf 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs @@ -91,6 +91,10 @@ public void RemoveHittableComponent() { } + public void LinkChild(IItemAuthoring item) + { + } + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() => data.Center.ToUnityVector3(0f); public override void SetEditorPosition(Vector3 pos) => data.Center = pos.ToVertex2Dxy(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs index 71f80309f..42e1f0a6d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs @@ -98,6 +98,10 @@ public void RemoveHittableComponent() { } + public void LinkChild(IItemAuthoring item) + { + } + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() => data.Center.ToUnityVector3(0f); public override void SetEditorPosition(Vector3 pos) => data.Center = pos.ToVertex3D(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs index ea1648996..d6be8749f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs @@ -45,6 +45,10 @@ public void RemoveHittableComponent() { } + public void LinkChild(IItemAuthoring item) + { + } + protected override Primitive GetItem() => new Primitive(data); public IHittable Hittable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs index fca31461b..087f171f2 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs @@ -51,6 +51,10 @@ public void RemoveHittableComponent() { } + public void LinkChild(IItemAuthoring item) + { + } + private void OnDestroy() { if (!Application.isPlaying) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs index c5c109899..a6e8a1954 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs @@ -25,6 +25,7 @@ using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; +using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Rubber; namespace VisualPinball.Unity @@ -62,6 +63,10 @@ public void RemoveHittableComponent() } } + public void LinkChild(IItemAuthoring item) + { + } + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; public override Vector3 GetEditorPosition() { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs index d485669f2..5cedc5c31 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs @@ -22,5 +22,6 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Rubber Collider")] public class RubberColliderAuthoring : ItemColliderAuthoring { + protected override Rubber GetItem() => new Rubber(_data); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs index 760c1cc69..a7865daa7 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs @@ -35,6 +35,9 @@ public static MonoBehaviour SetupGameObject(this Engine.VPT.Rubber.Rubber rubber case RenderObjectGroup.ItemSubComponent.Collider: obj.AddComponent().SetItem(rubber, rog); + if (mainMb != null && mainMb is IHittableAuthoring hittableAuthoring) { + hittableAuthoring.RemoveHittableComponent(); + } break; case RenderObjectGroup.ItemSubComponent.Mesh: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs index 6c88c87d7..6fbdfe87a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs @@ -48,6 +48,10 @@ public void RemoveHittableComponent() { } + public void LinkChild(IItemAuthoring item) + { + } + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; public override Vector3 GetEditorPosition() => data.Center.ToUnityVector3(data.Height); public override void SetEditorPosition(Vector3 pos) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs index a55c8b82d..705576aec 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs @@ -25,6 +25,7 @@ using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; +using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Surface; namespace VisualPinball.Unity @@ -56,7 +57,6 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterSurface(Item, entity, gameObject); } - public void RemoveHittableComponent() { var hc = gameObject.GetComponent(); @@ -65,6 +65,11 @@ public void RemoveHittableComponent() } } + public void LinkChild(IItemAuthoring item) + { + + } + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() { if (data == null || data.DragPoints.Length == 0) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs index b0e65995c..d937dec8b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs @@ -22,5 +22,6 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Surface Collider")] public class SurfaceColliderAuthoring : ItemColliderAuthoring { + protected override Surface GetItem() => new Surface(_data); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs index 86aede0c9..a999cc23e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs @@ -35,9 +35,10 @@ public static MonoBehaviour SetupGameObject(this Engine.VPT.Surface.Surface surf break; case RenderObjectGroup.ItemSubComponent.Collider: - obj.AddComponent().SetItem(surface, rog); + var ia = obj.AddComponent().SetItem(surface, rog); if (mainMb != null && mainMb is IHittableAuthoring hittableAuthoring) { hittableAuthoring.RemoveHittableComponent(); + hittableAuthoring.LinkChild(ia); } break; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs index 746faec5b..05cd95b04 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs @@ -70,6 +70,10 @@ public void RemoveHittableComponent() { } + public void LinkChild(IItemAuthoring item) + { + } + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() => data.Center.ToUnityVector3(0f); From 3df2bcc20406a4df2a5a5972a32ca0cdaf40c0c9 Mon Sep 17 00:00:00 2001 From: freezy Date: Sat, 26 Sep 2020 23:47:24 +0200 Subject: [PATCH 025/124] collider: Override colliders when generating. --- VisualPinball.Engine/VPT/Table/Table.cs | 38 +++++++++++++++++-- .../VPT/IExtendableAuthoring.cs.meta | 11 ++++++ .../VisualPinball.Unity/VPT/IItemAuthoring.cs | 2 + .../VPT/IItemAuthoring.cs.meta | 11 ++++++ .../VPT/IItemColliderAuthoring.cs | 7 ++++ .../VPT/IItemColliderAuthoring.cs.meta | 11 ++++++ .../VisualPinball.Unity/VPT/ItemAuthoring.cs | 15 +++++++- .../VPT/ItemColliderAuthoring.cs | 2 +- .../VPT/Rubber/RubberAuthoring.cs | 4 -- .../VPT/Rubber/RubberExtensions.cs | 6 ++- 10 files changed, 94 insertions(+), 13 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/IExtendableAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/IItemAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs.meta diff --git a/VisualPinball.Engine/VPT/Table/Table.cs b/VisualPinball.Engine/VPT/Table/Table.cs index a70b7baa7..12b16fdb7 100644 --- a/VisualPinball.Engine/VPT/Table/Table.cs +++ b/VisualPinball.Engine/VPT/Table/Table.cs @@ -36,8 +36,6 @@ public class Table : Item, IRenderable, IHittable { public override string ItemType => "Table"; - public readonly List Hittables2 = new List(); - public CustomInfoTags CustomInfoTags { get; set; } public int FileVersion { get; set; } public byte[] FileHash { get; set; } @@ -58,6 +56,36 @@ public class Table : Item, IRenderable, IHittable public readonly Dictionary Collections = new Dictionary(); public Mappings.Mappings Mappings = new Mappings.Mappings(); + #region Overrides + + private readonly Dictionary> _colliderOverrides = new Dictionary>(); + + public void AddColliderOverride(IItem item, IHittable childItem) + { + if (!_colliderOverrides.ContainsKey(item)) { + _colliderOverrides.Add(item, new List()); + } + _colliderOverrides[item].Add(childItem); + } + + private IEnumerable ApplyColliderOverrides(IHittable hittable) + { + if (hittable == null) { + throw new ArgumentNullException(); + } + + if (!(hittable is IItem item)) { + return new []{hittable}; + } + + if (_colliderOverrides.ContainsKey(item)) { + return _colliderOverrides[item]; + } + return new []{hittable}; + } + + #endregion + #region GameItems private readonly Dictionary _bumpers = new Dictionary(); @@ -157,7 +185,7 @@ public class Table : Item, IRenderable, IHittable .Concat(_timers.Values.Select(i => i.Data)) .Concat(_triggers.Values.Select(i => i.Data)); - public IEnumerable Hittables => new IHittable[] { this } + public IEnumerable Hittables => new IHittable[] {this} .Concat(_bumpers.Values) .Concat(_flippers.Values) .Concat(_gates.Values) @@ -169,7 +197,9 @@ public class Table : Item, IRenderable, IHittable .Concat(_rubbers.Values) .Concat(_spinners.Values) .Concat(_surfaces.Values) - .Concat(_triggers.Values); + .Concat(_triggers.Values) + .SelectMany(ApplyColliderOverrides); + public IEnumerable Playables => new IPlayable[0] .Concat(_bumpers.Values) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IExtendableAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/IExtendableAuthoring.cs.meta new file mode 100644 index 000000000..aa442fbae --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IExtendableAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e8c2d45cbf4c6664a941cef176d5b88f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemAuthoring.cs index d43fb4d2a..15068741b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemAuthoring.cs @@ -1,4 +1,5 @@ using UnityEngine; +using VisualPinball.Engine.VPT; namespace VisualPinball.Unity { @@ -7,6 +8,7 @@ namespace VisualPinball.Unity /// public interface IItemAuthoring { + IItem IItem { get; } ItemDataTransformType EditorPositionType { get; } Vector3 GetEditorPosition(); void SetEditorPosition(Vector3 pos); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemAuthoring.cs.meta new file mode 100644 index 000000000..e7743f13d --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9c3e512efe510bd429fe0776b63d24de +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs new file mode 100644 index 000000000..2bb6b49bf --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs @@ -0,0 +1,7 @@ +namespace VisualPinball.Unity +{ + public interface IItemColliderAuthoring + { + + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs.meta new file mode 100644 index 000000000..d487b18f7 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f13f168f0e1d8b64c94e7d9220bb4105 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs index d320bd3b5..b8162270a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs @@ -42,6 +42,8 @@ public abstract class ItemAuthoring : MonoBehaviour, IItemAuthorin public TData data; public TItem Item => _item ?? (_item = GetItem()); + public IItem IItem => _item; + public string ItemType => Item.ItemType; public bool IsLocked { get => data.IsLocked; set => data.IsLocked = value; } @@ -144,6 +146,14 @@ protected void Convert(Entity entity, EntityManager dstManager) Item.Version = entity.Version; } + + public void LinkChild(IItemAuthoring childItem) + { + if (childItem is IItemColliderAuthoring) { + Table.AddColliderOverride(Item, childItem.IItem as IHittable); + } + } + protected virtual void OnDrawGizmos() { // handle dirty whenever scene view draws just in case a field or dependant changed and our @@ -164,7 +174,8 @@ protected virtual void OnDrawGizmos() protected virtual void OnDrawGizmosSelected() { - if (PhysicsDebug.ShowAabbs || PhysicsDebug.ShowColliders) { + var isColliderComponent = this is IItemColliderAuthoring; + if (PhysicsDebug.ShowAabbs || PhysicsDebug.ShowColliders || isColliderComponent) { var ltw = transform.GetComponentInParent().gameObject.transform.localToWorldMatrix; if (Item is IHittable hittable) { @@ -185,7 +196,7 @@ protected virtual void OnDrawGizmosSelected() hit.CalcHitBBox(); DrawAabb(ltw, hit.HitBBox, i == PhysicsDebug.SelectedCollider); } - if (PhysicsDebug.ShowColliders) { + if (PhysicsDebug.ShowColliders || isColliderComponent) { DrawCollider(ltw, hit, i == PhysicsDebug.SelectedCollider); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs index 1a713e354..38293a73b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs @@ -20,7 +20,7 @@ namespace VisualPinball.Unity { - public abstract class ItemColliderAuthoring : ItemAuthoring + public abstract class ItemColliderAuthoring : ItemAuthoring, IItemColliderAuthoring where TData : ItemData where TItem : Item, IHittable, IRenderable where TAuthoring : ItemAuthoring diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs index a6e8a1954..4ef60cb92 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs @@ -63,10 +63,6 @@ public void RemoveHittableComponent() } } - public void LinkChild(IItemAuthoring item) - { - } - public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; public override Vector3 GetEditorPosition() { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs index a7865daa7..90b70e49f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs @@ -23,7 +23,8 @@ namespace VisualPinball.Unity { internal static class RubberExtensions { - public static MonoBehaviour SetupGameObject(this Engine.VPT.Rubber.Rubber rubber, GameObject obj, RenderObjectGroup rog, MonoBehaviour mainMb) + public static MonoBehaviour SetupGameObject(this Engine.VPT.Rubber.Rubber rubber, GameObject obj, + RenderObjectGroup rog, MonoBehaviour mainMb) { MonoBehaviour mb = null; switch (rog.SubComponent) { @@ -34,9 +35,10 @@ public static MonoBehaviour SetupGameObject(this Engine.VPT.Rubber.Rubber rubber break; case RenderObjectGroup.ItemSubComponent.Collider: - obj.AddComponent().SetItem(rubber, rog); + var ia = obj.AddComponent().SetItem(rubber, rog); if (mainMb != null && mainMb is IHittableAuthoring hittableAuthoring) { hittableAuthoring.RemoveHittableComponent(); + hittableAuthoring.LinkChild(ia); } break; From 42ffe5216e1c2372817e17c610acde726c4b7f5d Mon Sep 17 00:00:00 2001 From: freezy Date: Sun, 27 Sep 2020 23:24:15 +0200 Subject: [PATCH 026/124] editor: Refactor data handling. --- .../Managers/MaterialManager.cs | 12 +-- .../VPT/Bumper/BumperInspector.cs | 44 ++++----- .../VPT/Flipper/FlipperInspector.cs | 58 ++++++------ .../VPT/Gate/GateInspector.cs | 38 ++++---- .../VPT/HitTarget/HitTargetInspector.cs | 50 +++++------ .../VPT/ItemInspector.cs | 8 +- .../VPT/Kicker/KickerInspector.cs | 33 +++---- .../VPT/Light/LightInspector.cs | 28 +++--- .../VPT/Plunger/PlungerInspector.cs | 58 ++++++------ .../VPT/Primitive/PrimitiveInspector.cs | 70 +++++++-------- .../VPT/Ramp/RampInspector.cs | 60 ++++++------- .../VPT/Rubber/RubberInspector.cs | 22 ++--- .../VPT/Spinner/SpinnerInspector.cs | 30 +++---- .../VPT/Surface/SurfaceInspector.cs | 26 +++--- .../VPT/Table/TableInspector.cs | 2 +- .../VPT/Trigger/TriggerInspector.cs | 26 +++--- .../VisualPinball.Unity/Game/Player.cs | 2 +- .../VPT/Bumper/BumperAuthoring.cs | 20 ++--- .../VPT/Flipper/FlipperAuthoring.cs | 66 +++++++------- .../VPT/Gate/GateAuthoring.cs | 16 ++-- .../VPT/Gate/GateWireAuthoring.cs | 16 ++-- .../VPT/HitTarget/HitTargetAuthoring.cs | 26 +++--- .../VisualPinball.Unity/VPT/ItemAuthoring.cs | 90 +++++++++++++++---- .../VPT/ItemColliderAuthoring.cs | 29 +++--- .../VPT/Kicker/KickerAuthoring.cs | 24 ++--- .../VPT/Light/LightAuthoring.cs | 20 ++--- .../VPT/Plunger/PlungerAuthoring.cs | 16 ++-- .../VPT/Primitive/PrimitiveAuthoring.cs | 18 ++-- .../VPT/Ramp/RampAuthoring.cs | 24 ++--- .../VPT/Rubber/RubberAuthoring.cs | 32 +++---- .../VPT/Rubber/RubberColliderAuthoring.cs | 2 +- .../VPT/Spinner/SpinnerAuthoring.cs | 16 ++-- .../VPT/Spinner/SpinnerPlateAuthoring.cs | 17 ++-- .../VPT/Surface/SurfaceAuthoring.cs | 24 ++--- .../VPT/Surface/SurfaceColliderAuthoring.cs | 2 +- .../VPT/Table/TableAuthoring.cs | 10 +-- .../VPT/Trigger/TriggerAuthoring.cs | 28 +++--- 37 files changed, 560 insertions(+), 503 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/MaterialManager.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/MaterialManager.cs index 609989b6f..244c2ed3d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/MaterialManager.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/MaterialManager.cs @@ -152,20 +152,20 @@ private void VisualOptions() protected override void AddNewData(string undoName, string newName) { var newMat = new Engine.VPT.Material(newName); - _tableAuthoring.data.Materials = _tableAuthoring.data.Materials.Append(newMat).ToArray(); - _tableAuthoring.data.NumMaterials = _tableAuthoring.data.Materials.Length; + _tableAuthoring.Data.Materials = _tableAuthoring.Data.Materials.Append(newMat).ToArray(); + _tableAuthoring.Data.NumMaterials = _tableAuthoring.Data.Materials.Length; } protected override void RemoveData(string undoName, MaterialListData data) { - _tableAuthoring.data.Materials = _tableAuthoring.data.Materials.Where(m => m != data.Material).ToArray(); - _tableAuthoring.data.NumMaterials = _tableAuthoring.data.Materials.Length; + _tableAuthoring.Data.Materials = _tableAuthoring.Data.Materials.Where(m => m != data.Material).ToArray(); + _tableAuthoring.Data.NumMaterials = _tableAuthoring.Data.Materials.Length; } protected override void CloneData(string undoName, string newName, MaterialListData data) { var newMat = data.Material.Clone(newName); - _tableAuthoring.data.Materials = _tableAuthoring.data.Materials.Append(newMat).ToArray(); - _tableAuthoring.data.NumMaterials = _tableAuthoring.data.Materials.Length; + _tableAuthoring.Data.Materials = _tableAuthoring.Data.Materials.Append(newMat).ToArray(); + _tableAuthoring.Data.NumMaterials = _tableAuthoring.Data.Materials.Length; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs index 1df33d34e..e9f32ca31 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs @@ -38,40 +38,40 @@ public override void OnInspectorGUI() OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - MaterialField("Cap Material", ref _bumper.data.CapMaterial); - MaterialField("Base Material", ref _bumper.data.BaseMaterial); - MaterialField("Ring Material", ref _bumper.data.RingMaterial); - MaterialField("Skirt Material", ref _bumper.data.SocketMaterial); - ItemDataField("Radius", ref _bumper.data.Radius); - ItemDataField("Height Scale", ref _bumper.data.HeightScale); - ItemDataField("Orientation", ref _bumper.data.Orientation); - ItemDataField("Ring Speed", ref _bumper.data.RingSpeed, dirtyMesh: false); - ItemDataField("Ring Drop Offset", ref _bumper.data.RingDropOffset, dirtyMesh: false); - ItemDataField("Cap Visible", ref _bumper.data.IsCapVisible); - ItemDataField("Base Visible", ref _bumper.data.IsBaseVisible); - ItemDataField("Ring Visible", ref _bumper.data.IsRingVisible); - ItemDataField("Skirt Visible", ref _bumper.data.IsSocketVisible); + MaterialField("Cap Material", ref _bumper.Data.CapMaterial); + MaterialField("Base Material", ref _bumper.Data.BaseMaterial); + MaterialField("Ring Material", ref _bumper.Data.RingMaterial); + MaterialField("Skirt Material", ref _bumper.Data.SocketMaterial); + ItemDataField("Radius", ref _bumper.Data.Radius); + ItemDataField("Height Scale", ref _bumper.Data.HeightScale); + ItemDataField("Orientation", ref _bumper.Data.Orientation); + ItemDataField("Ring Speed", ref _bumper.Data.RingSpeed, dirtyMesh: false); + ItemDataField("Ring Drop Offset", ref _bumper.Data.RingDropOffset, dirtyMesh: false); + ItemDataField("Cap Visible", ref _bumper.Data.IsCapVisible); + ItemDataField("Base Visible", ref _bumper.Data.IsBaseVisible); + ItemDataField("Ring Visible", ref _bumper.Data.IsRingVisible); + ItemDataField("Skirt Visible", ref _bumper.Data.IsSocketVisible); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("", ref _bumper.data.Center); - SurfaceField("Surface", ref _bumper.data.Surface); + ItemDataField("", ref _bumper.Data.Center); + SurfaceField("Surface", ref _bumper.Data.Surface); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "Physics")) { - ItemDataField("Has Hit Event", ref _bumper.data.HitEvent, dirtyMesh: false); - ItemDataField("Force", ref _bumper.data.Force, dirtyMesh: false); - ItemDataField("Hit Threshold", ref _bumper.data.Threshold, dirtyMesh: false); - ItemDataField("Scatter Angle", ref _bumper.data.Scatter, dirtyMesh: false); - ItemDataField("Collidable", ref _bumper.data.IsCollidable, dirtyMesh: false); + ItemDataField("Has Hit Event", ref _bumper.Data.HitEvent, dirtyMesh: false); + ItemDataField("Force", ref _bumper.Data.Force, dirtyMesh: false); + ItemDataField("Hit Threshold", ref _bumper.Data.Threshold, dirtyMesh: false); + ItemDataField("Scatter Angle", ref _bumper.Data.Scatter, dirtyMesh: false); + ItemDataField("Collidable", ref _bumper.Data.IsCollidable, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _bumper.data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _bumper.data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref _bumper.Data.IsTimerEnabled, dirtyMesh: false); + ItemDataField("Timer Interval", ref _bumper.Data.TimerInterval, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs index 9d8e217a6..282a37300 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs @@ -41,47 +41,47 @@ public override void OnInspectorGUI() OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - TextureField("Image", ref _flipper.data.Image); - MaterialField("Material", ref _flipper.data.Material); - MaterialField("Rubber Material", ref _flipper.data.RubberMaterial); - ItemDataField("Rubber Thickness", ref _flipper.data.RubberThickness); - ItemDataField("Rubber Offset Height", ref _flipper.data.RubberHeight); - ItemDataField("Rubber Width", ref _flipper.data.RubberWidth); - ItemDataField("Visible", ref _flipper.data.IsVisible); - ItemDataField("Enabled", ref _flipper.data.IsEnabled); + TextureField("Image", ref _flipper.Data.Image); + MaterialField("Material", ref _flipper.Data.Material); + MaterialField("Rubber Material", ref _flipper.Data.RubberMaterial); + ItemDataField("Rubber Thickness", ref _flipper.Data.RubberThickness); + ItemDataField("Rubber Offset Height", ref _flipper.Data.RubberHeight); + ItemDataField("Rubber Width", ref _flipper.Data.RubberWidth); + ItemDataField("Visible", ref _flipper.Data.IsVisible); + ItemDataField("Enabled", ref _flipper.Data.IsEnabled); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("", ref _flipper.data.Center); - ItemDataField("Base Radius", ref _flipper.data.BaseRadius); - ItemDataField("End Radius", ref _flipper.data.EndRadius); - ItemDataField("Length", ref _flipper.data.FlipperRadius); - ItemDataField("Start Angle", ref _flipper.data.StartAngle); - ItemDataField("End Angle", ref _flipper.data.EndAngle); - ItemDataField("Height", ref _flipper.data.Height); - ItemDataField("Max. Difficulty Length", ref _flipper.data.FlipperRadiusMax); - SurfaceField("Surface", ref _flipper.data.Surface); + ItemDataField("", ref _flipper.Data.Center); + ItemDataField("Base Radius", ref _flipper.Data.BaseRadius); + ItemDataField("End Radius", ref _flipper.Data.EndRadius); + ItemDataField("Length", ref _flipper.Data.FlipperRadius); + ItemDataField("Start Angle", ref _flipper.Data.StartAngle); + ItemDataField("End Angle", ref _flipper.Data.EndAngle); + ItemDataField("Height", ref _flipper.Data.Height); + ItemDataField("Max. Difficulty Length", ref _flipper.Data.FlipperRadiusMax); + SurfaceField("Surface", ref _flipper.Data.Surface); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "Physics")) { - ItemDataField("Mass", ref _flipper.data.Mass, dirtyMesh: false); - ItemDataField("Strength", ref _flipper.data.Strength, dirtyMesh: false); - ItemDataField("Elasticity", ref _flipper.data.Elasticity, dirtyMesh: false); - ItemDataField("Elasticity Falloff", ref _flipper.data.ElasticityFalloff, dirtyMesh: false); - ItemDataField("Friction", ref _flipper.data.Friction, dirtyMesh: false); - ItemDataField("Return Strength", ref _flipper.data.Return, dirtyMesh: false); - ItemDataField("Coil Ramp Up", ref _flipper.data.RampUp, dirtyMesh: false); - ItemDataField("Scatter Angle", ref _flipper.data.Scatter, dirtyMesh: false); - ItemDataField("EOS Torque", ref _flipper.data.TorqueDamping, dirtyMesh: false); - ItemDataField("EOS Torque Angle", ref _flipper.data.TorqueDampingAngle, dirtyMesh: false); + ItemDataField("Mass", ref _flipper.Data.Mass, dirtyMesh: false); + ItemDataField("Strength", ref _flipper.Data.Strength, dirtyMesh: false); + ItemDataField("Elasticity", ref _flipper.Data.Elasticity, dirtyMesh: false); + ItemDataField("Elasticity Falloff", ref _flipper.Data.ElasticityFalloff, dirtyMesh: false); + ItemDataField("Friction", ref _flipper.Data.Friction, dirtyMesh: false); + ItemDataField("Return Strength", ref _flipper.Data.Return, dirtyMesh: false); + ItemDataField("Coil Ramp Up", ref _flipper.Data.RampUp, dirtyMesh: false); + ItemDataField("Scatter Angle", ref _flipper.Data.Scatter, dirtyMesh: false); + ItemDataField("EOS Torque", ref _flipper.Data.TorqueDamping, dirtyMesh: false); + ItemDataField("EOS Torque Angle", ref _flipper.Data.TorqueDampingAngle, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _flipper.data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _flipper.data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref _flipper.Data.IsTimerEnabled, dirtyMesh: false); + ItemDataField("Timer Interval", ref _flipper.Data.TimerInterval, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateInspector.cs index c9bd095a3..07176b317 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateInspector.cs @@ -71,37 +71,37 @@ public override void OnInspectorGUI() OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - DropDownField("Type", ref _gate.data.GateType, _gateTypeStrings, _gateTypeValues); - ItemDataField("Visible", ref _gate.data.IsVisible); - ItemDataField("Show Bracket", ref _gate.data.ShowBracket); - MaterialField("Material", ref _gate.data.Material); + DropDownField("Type", ref _gate.Data.GateType, _gateTypeStrings, _gateTypeValues); + ItemDataField("Visible", ref _gate.Data.IsVisible); + ItemDataField("Show Bracket", ref _gate.Data.ShowBracket); + MaterialField("Material", ref _gate.Data.Material); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("", ref _gate.data.Center); - ItemDataField("Length", ref _gate.data.Length); - ItemDataField("Height", ref _gate.data.Height); - ItemDataField("Rotation", ref _gate.data.Rotation); - ItemDataField("Open Angle", ref _gate.data.AngleMax, dirtyMesh: false); - ItemDataField("Close Angle", ref _gate.data.AngleMin, dirtyMesh: false); - SurfaceField("Surface", ref _gate.data.Surface); + ItemDataField("", ref _gate.Data.Center); + ItemDataField("Length", ref _gate.Data.Length); + ItemDataField("Height", ref _gate.Data.Height); + ItemDataField("Rotation", ref _gate.Data.Rotation); + ItemDataField("Open Angle", ref _gate.Data.AngleMax, dirtyMesh: false); + ItemDataField("Close Angle", ref _gate.Data.AngleMin, dirtyMesh: false); + SurfaceField("Surface", ref _gate.Data.Surface); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "Physics")) { - ItemDataField("Elasticity", ref _gate.data.Elasticity, dirtyMesh: false); - ItemDataField("Friction", ref _gate.data.Friction, dirtyMesh: false); - ItemDataField("Damping", ref _gate.data.Damping, dirtyMesh: false); - ItemDataField("Gravity Factor", ref _gate.data.GravityFactor, dirtyMesh: false); - ItemDataField("Collidable", ref _gate.data.IsCollidable, dirtyMesh: false); - ItemDataField(TwoWayLabel, ref _gate.data.TwoWay, dirtyMesh: false); + ItemDataField("Elasticity", ref _gate.Data.Elasticity, dirtyMesh: false); + ItemDataField("Friction", ref _gate.Data.Friction, dirtyMesh: false); + ItemDataField("Damping", ref _gate.Data.Damping, dirtyMesh: false); + ItemDataField("Gravity Factor", ref _gate.Data.GravityFactor, dirtyMesh: false); + ItemDataField("Collidable", ref _gate.Data.IsCollidable, dirtyMesh: false); + ItemDataField(TwoWayLabel, ref _gate.Data.TwoWay, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _gate.data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _gate.data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref _gate.Data.IsTimerEnabled, dirtyMesh: false); + ItemDataField("Timer Interval", ref _gate.Data.TimerInterval, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetInspector.cs index 566158b9b..48262222b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetInspector.cs @@ -62,58 +62,58 @@ public override void OnInspectorGUI() OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - DropDownField("Type", ref _target.data.TargetType, _targetTypeStrings, _targetTypeValues); - TextureField("Image", ref _target.data.Image); - MaterialField("Material", ref _target.data.Material); - ItemDataField("Drop Speed", ref _target.data.DropSpeed, dirtyMesh: false); - ItemDataField("Raise Delay", ref _target.data.RaiseDelay, dirtyMesh: false); - ItemDataField("Depth Bias", ref _target.data.DepthBias, dirtyMesh: false); - ItemDataField("Visible", ref _target.data.IsVisible); + DropDownField("Type", ref _target.Data.TargetType, _targetTypeStrings, _targetTypeValues); + TextureField("Image", ref _target.Data.Image); + MaterialField("Material", ref _target.Data.Material); + ItemDataField("Drop Speed", ref _target.Data.DropSpeed, dirtyMesh: false); + ItemDataField("Raise Delay", ref _target.Data.RaiseDelay, dirtyMesh: false); + ItemDataField("Depth Bias", ref _target.Data.DepthBias, dirtyMesh: false); + ItemDataField("Visible", ref _target.Data.IsVisible); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position & Translation")) { EditorGUILayout.LabelField("Position"); EditorGUI.indentLevel++; - ItemDataField("", ref _target.data.Position); + ItemDataField("", ref _target.Data.Position); EditorGUI.indentLevel--; EditorGUILayout.LabelField("Scale"); EditorGUI.indentLevel++; - ItemDataField("", ref _target.data.Size); + ItemDataField("", ref _target.Data.Size); EditorGUI.indentLevel--; - ItemDataField("Orientation", ref _target.data.RotZ); + ItemDataField("Orientation", ref _target.Data.RotZ); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "Physics")) { - ItemDataField("Has Hit Event", ref _target.data.UseHitEvent, dirtyMesh: false); - ItemDataField("Hit Threshold", ref _target.data.Threshold, dirtyMesh: false); + ItemDataField("Has Hit Event", ref _target.Data.UseHitEvent, dirtyMesh: false); + ItemDataField("Hit Threshold", ref _target.Data.Threshold, dirtyMesh: false); - EditorGUI.BeginDisabledGroup(_target.data.OverwritePhysics); - MaterialField("Physics Material", ref _target.data.PhysicsMaterial, dirtyMesh: false); + EditorGUI.BeginDisabledGroup(_target.Data.OverwritePhysics); + MaterialField("Physics Material", ref _target.Data.PhysicsMaterial, dirtyMesh: false); EditorGUI.EndDisabledGroup(); - ItemDataField("Overwrite Material Settings", ref _target.data.OverwritePhysics, dirtyMesh: false); + ItemDataField("Overwrite Material Settings", ref _target.Data.OverwritePhysics, dirtyMesh: false); - EditorGUI.BeginDisabledGroup(!_target.data.OverwritePhysics); - ItemDataField("Elasticity", ref _target.data.Elasticity, dirtyMesh: false); - ItemDataField("Elasticity Falloff", ref _target.data.ElasticityFalloff, dirtyMesh: false); - ItemDataField("Friction", ref _target.data.Friction, dirtyMesh: false); - ItemDataField("Scatter Angle", ref _target.data.Scatter, dirtyMesh: false); + EditorGUI.BeginDisabledGroup(!_target.Data.OverwritePhysics); + ItemDataField("Elasticity", ref _target.Data.Elasticity, dirtyMesh: false); + ItemDataField("Elasticity Falloff", ref _target.Data.ElasticityFalloff, dirtyMesh: false); + ItemDataField("Friction", ref _target.Data.Friction, dirtyMesh: false); + ItemDataField("Scatter Angle", ref _target.Data.Scatter, dirtyMesh: false); EditorGUI.EndDisabledGroup(); - ItemDataField("Legacy Mode", ref _target.data.IsLegacy, dirtyMesh: false); - ItemDataField("Collidable", ref _target.data.IsCollidable, dirtyMesh: false); - ItemDataField("Is Dropped", ref _target.data.IsDropped, dirtyMesh: false); + ItemDataField("Legacy Mode", ref _target.Data.IsLegacy, dirtyMesh: false); + ItemDataField("Collidable", ref _target.Data.IsCollidable, dirtyMesh: false); + ItemDataField("Is Dropped", ref _target.Data.IsDropped, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _target.data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _target.data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref _target.Data.IsTimerEnabled, dirtyMesh: false); + ItemDataField("Timer Interval", ref _target.Data.TimerInterval, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs index edd89345b..6e1f91b61 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs @@ -80,11 +80,11 @@ private void PopulateDropDownOptions() { if (_table == null) return; - if (_table.data.Materials != null) { - _allMaterials = new string[_table.data.Materials.Length + 1]; + if (_table.Data.Materials != null) { + _allMaterials = new string[_table.Data.Materials.Length + 1]; _allMaterials[0] = "- none -"; - for (var i = 0; i < _table.data.Materials.Length; i++) { - _allMaterials[i + 1] = _table.data.Materials[i].Name; + for (var i = 0; i < _table.Data.Materials.Length; i++) { + _allMaterials[i + 1] = _table.Data.Materials[i].Name; } Array.Sort(_allMaterials, 1, _allMaterials.Length - 1); } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerInspector.cs index 203785ea9..cb3040966 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerInspector.cs @@ -58,34 +58,35 @@ public override void OnInspectorGUI() OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - MaterialField("Material", ref _kicker.data.Material); - DropDownField("Display", ref _kicker.data.KickerType, _kickerTypeStrings, _kickerTypeValues); - ItemDataField("Radius", ref _kicker.data.Radius); - ItemDataField("Orientation", ref _kicker.data.Orientation); + MaterialField("Material", ref _kicker.Data.Material); + DropDownField("Display", ref _kicker.Data.KickerType, _kickerTypeStrings, _kickerTypeValues); + ItemDataField("Radius", ref _kicker.Data.Radius); + ItemDataField("Orientation", ref _kicker.Data.Orientation); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("", ref _kicker.data.Center); - SurfaceField("Surface", ref _kicker.data.Surface); + ItemDataField("", ref _kicker.Data.Center); + SurfaceField("Surface", ref _kicker.Data.Surface); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "State & Physics")) { - ItemDataField("Enabled", ref _kicker.data.IsEnabled, dirtyMesh: false); - ItemDataField("Fall Through", ref _kicker.data.FallThrough, dirtyMesh: false); - ItemDataField("Legacy", ref _kicker.data.LegacyMode, dirtyMesh: false); - ItemDataField("Scatter Angle", ref _kicker.data.Scatter, dirtyMesh: false); - ItemDataField("Hit Accuracy", ref _kicker.data.HitAccuracy, dirtyMesh: false); - ItemDataField("Hit Height", ref _kicker.data.HitHeight, dirtyMesh: false); - ItemDataField("Default Angle", ref _kicker.data.Angle, dirtyMesh: false); - ItemDataField("Default Speed", ref _kicker.data.Speed, dirtyMesh: false); + ItemDataField("Enabled", ref _kicker.Data.IsEnabled, dirtyMesh: false); + ItemDataField("Fall Through", ref _kicker.Data.FallThrough, dirtyMesh: false); + ItemDataField("Legacy", ref _kicker.Data.LegacyMode, dirtyMesh: false); + ItemDataField("Scatter Angle", ref _kicker.Data.Scatter, dirtyMesh: false); + ItemDataField("Hit Accuracy", ref _kicker.Data.HitAccuracy, dirtyMesh: false); + ItemDataField("Hit Height", ref _kicker.Data.HitHeight, dirtyMesh: false); + + ItemDataField("Default Angle", ref _kicker.Data.Angle, dirtyMesh: false); + ItemDataField("Default Speed", ref _kicker.Data.Speed, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _kicker.data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _kicker.data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref _kicker.Data.IsTimerEnabled, dirtyMesh: false); + ItemDataField("Timer Interval", ref _kicker.Data.TimerInterval, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightInspector.cs index 9250aea9f..643fb76bf 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightInspector.cs @@ -40,41 +40,41 @@ protected override void OnEnable() public override void OnInspectorGUI() { if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - ItemDataField("Falloff", ref _light.data.Falloff, dirtyMesh: false); - ItemDataField("Intensity", ref _light.data.Intensity, dirtyMesh: false); + ItemDataField("Falloff", ref _light.Data.Falloff, dirtyMesh: false); + ItemDataField("Intensity", ref _light.Data.Intensity, dirtyMesh: false); EditorGUILayout.LabelField("Fade Speed"); EditorGUI.indentLevel++; - ItemDataField("Up", ref _light.data.FadeSpeedUp, dirtyMesh: false); - ItemDataField("Down", ref _light.data.FadeSpeedDown, dirtyMesh: false); + ItemDataField("Up", ref _light.Data.FadeSpeedUp, dirtyMesh: false); + ItemDataField("Down", ref _light.Data.FadeSpeedDown, dirtyMesh: false); EditorGUI.indentLevel--; - ItemDataField("Color", ref _light.data.Color2, dirtyMesh: false); // Note: using color2 since that's the hot/center color in vpx + ItemDataField("Color", ref _light.Data.Color2, dirtyMesh: false); // Note: using color2 since that's the hot/center color in vpx EditorGUILayout.LabelField("Bulb"); EditorGUI.indentLevel++; - ItemDataField("Enable", ref _light.data.IsBulbLight, dirtyMesh: false); - ItemDataField("Scale Mesh", ref _light.data.MeshRadius, dirtyMesh: false); + ItemDataField("Enable", ref _light.Data.IsBulbLight, dirtyMesh: false); + ItemDataField("Scale Mesh", ref _light.Data.MeshRadius, dirtyMesh: false); EditorGUI.indentLevel--; } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("", ref _light.data.Center); - SurfaceField("Surface", ref _light.data.Surface); + ItemDataField("", ref _light.Data.Center); + SurfaceField("Surface", ref _light.Data.Surface); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutStateAndPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutStateAndPhysics, "State & Physics")) { - DropDownField("State", ref _light.data.State, _lightStateStrings, _lightStateValues); - ItemDataField("Blink Pattern", ref _light.data.BlinkPattern, dirtyMesh: false); - ItemDataField("Blink Interval", ref _light.data.BlinkInterval, dirtyMesh: false); + DropDownField("State", ref _light.Data.State, _lightStateStrings, _lightStateValues); + ItemDataField("Blink Pattern", ref _light.Data.BlinkPattern, dirtyMesh: false); + ItemDataField("Blink Interval", ref _light.Data.BlinkInterval, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _light.data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _light.data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref _light.Data.IsTimerEnabled, dirtyMesh: false); + ItemDataField("Timer Interval", ref _light.Data.TimerInterval, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerInspector.cs index f2d9a6e70..624a3dc59 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerInspector.cs @@ -44,50 +44,50 @@ public override void OnInspectorGUI() OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - DropDownField("Type", ref _plunger.data.Type, PlungerTypeStrings, PlungerTypeValues); - MaterialField("Material", ref _plunger.data.Material); - TextureField("Image", ref _plunger.data.Image); - ItemDataField("Flat Frames", ref _plunger.data.AnimFrames); - ItemDataField("Width", ref _plunger.data.Width); - ItemDataField("Z Adjustment", ref _plunger.data.ZAdjust); + DropDownField("Type", ref _plunger.Data.Type, PlungerTypeStrings, PlungerTypeValues); + MaterialField("Material", ref _plunger.Data.Material); + TextureField("Image", ref _plunger.Data.Image); + ItemDataField("Flat Frames", ref _plunger.Data.AnimFrames); + ItemDataField("Width", ref _plunger.Data.Width); + ItemDataField("Z Adjustment", ref _plunger.Data.ZAdjust); EditorGUILayout.LabelField("Custom Settings"); EditorGUI.indentLevel++; - ItemDataField("Rod Diameter", ref _plunger.data.RodDiam); - ItemDataField("Tip Shape", ref _plunger.data.TipShape); // TODO: break this down and provide individual fields - ItemDataField("Ring Gap", ref _plunger.data.RingGap); - ItemDataField("Ring Diam", ref _plunger.data.RingDiam); - ItemDataField("Ring Width", ref _plunger.data.RingWidth); - ItemDataField("Spring Diam", ref _plunger.data.SpringDiam); - ItemDataField("Spring Gauge", ref _plunger.data.SpringGauge); - ItemDataField("Spring Loops", ref _plunger.data.SpringLoops); - ItemDataField("End Loops", ref _plunger.data.SpringEndLoops); + ItemDataField("Rod Diameter", ref _plunger.Data.RodDiam); + ItemDataField("Tip Shape", ref _plunger.Data.TipShape); // TODO: break this down and provide individual fields + ItemDataField("Ring Gap", ref _plunger.Data.RingGap); + ItemDataField("Ring Diam", ref _plunger.Data.RingDiam); + ItemDataField("Ring Width", ref _plunger.Data.RingWidth); + ItemDataField("Spring Diam", ref _plunger.Data.SpringDiam); + ItemDataField("Spring Gauge", ref _plunger.Data.SpringGauge); + ItemDataField("Spring Loops", ref _plunger.Data.SpringLoops); + ItemDataField("End Loops", ref _plunger.Data.SpringEndLoops); EditorGUI.indentLevel--; } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("", ref _plunger.data.Center); - SurfaceField("Surface", ref _plunger.data.Surface); + ItemDataField("", ref _plunger.Data.Center); + SurfaceField("Surface", ref _plunger.Data.Surface); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutStateAndPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutStateAndPhysics, "State & Physics")) { - ItemDataField("Pull Speed", ref _plunger.data.SpeedPull, dirtyMesh: false); - ItemDataField("Release Speed", ref _plunger.data.SpeedFire, dirtyMesh: false); - ItemDataField("Stroke Length", ref _plunger.data.Stroke, dirtyMesh: false); - ItemDataField("Scatter Velocity", ref _plunger.data.ScatterVelocity, dirtyMesh: false); - ItemDataField("Enable Mechanical Plunger", ref _plunger.data.IsMechPlunger, dirtyMesh: false); - ItemDataField("Auto Plunger", ref _plunger.data.AutoPlunger, dirtyMesh: false); - ItemDataField("Visible", ref _plunger.data.IsVisible); - ItemDataField("Mech Strength", ref _plunger.data.MechStrength, dirtyMesh: false); - ItemDataField("Momentum Xfer", ref _plunger.data.MomentumXfer, dirtyMesh: false); - ItemDataField("Park Position (0..1)", ref _plunger.data.ParkPosition, dirtyMesh: false); + ItemDataField("Pull Speed", ref _plunger.Data.SpeedPull, dirtyMesh: false); + ItemDataField("Release Speed", ref _plunger.Data.SpeedFire, dirtyMesh: false); + ItemDataField("Stroke Length", ref _plunger.Data.Stroke, dirtyMesh: false); + ItemDataField("Scatter Velocity", ref _plunger.Data.ScatterVelocity, dirtyMesh: false); + ItemDataField("Enable Mechanical Plunger", ref _plunger.Data.IsMechPlunger, dirtyMesh: false); + ItemDataField("Auto Plunger", ref _plunger.Data.AutoPlunger, dirtyMesh: false); + ItemDataField("Visible", ref _plunger.Data.IsVisible); + ItemDataField("Mech Strength", ref _plunger.Data.MechStrength, dirtyMesh: false); + ItemDataField("Momentum Xfer", ref _plunger.Data.MomentumXfer, dirtyMesh: false); + ItemDataField("Park Position (0..1)", ref _plunger.Data.ParkPosition, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _plunger.data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _plunger.data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref _plunger.Data.IsTimerEnabled, dirtyMesh: false); + ItemDataField("Timer Interval", ref _plunger.Data.TimerInterval, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveInspector.cs index 293cfa4ba..9fa97bded 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveInspector.cs @@ -44,72 +44,72 @@ public override void OnInspectorGUI() if (GUILayout.Button("Export Mesh")) ExportMesh(); GUILayout.EndHorizontal(); - TextureField("Image", ref _prim.data.Image); - TextureField("Normal Map", ref _prim.data.NormalMap); + TextureField("Image", ref _prim.Data.Image); + TextureField("Normal Map", ref _prim.Data.NormalMap); EditorGUI.indentLevel++; - ItemDataField("Object Space", ref _prim.data.ObjectSpaceNormalMap); + ItemDataField("Object Space", ref _prim.Data.ObjectSpaceNormalMap); EditorGUI.indentLevel--; - MaterialField("Material", ref _prim.data.Material); + MaterialField("Material", ref _prim.Data.Material); - ItemDataField("Visible", ref _prim.data.IsVisible); + ItemDataField("Visible", ref _prim.Data.IsVisible); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position & Translation")) { EditorGUILayout.LabelField("Base Position"); EditorGUI.indentLevel++; - ItemDataField("", ref _prim.data.Position); + ItemDataField("", ref _prim.Data.Position); EditorGUI.indentLevel--; EditorGUILayout.LabelField("Base Size"); EditorGUI.indentLevel++; - ItemDataField("", ref _prim.data.Size); + ItemDataField("", ref _prim.Data.Size); EditorGUI.indentLevel--; EditorGUILayout.LabelField("Rotation and Transposition"); EditorGUI.indentLevel++; - ItemDataField("0: RotX", ref _prim.data.RotAndTra[0]); - ItemDataField("1: RotY", ref _prim.data.RotAndTra[1]); - ItemDataField("2: RotZ", ref _prim.data.RotAndTra[2]); - ItemDataField("3: TransX", ref _prim.data.RotAndTra[3]); - ItemDataField("4: TransY", ref _prim.data.RotAndTra[4]); - ItemDataField("5: TransZ", ref _prim.data.RotAndTra[5]); - ItemDataField("6: ObjRotX", ref _prim.data.RotAndTra[6]); - ItemDataField("7: ObjRotY", ref _prim.data.RotAndTra[7]); - ItemDataField("8: ObjRotZ", ref _prim.data.RotAndTra[8]); + ItemDataField("0: RotX", ref _prim.Data.RotAndTra[0]); + ItemDataField("1: RotY", ref _prim.Data.RotAndTra[1]); + ItemDataField("2: RotZ", ref _prim.Data.RotAndTra[2]); + ItemDataField("3: TransX", ref _prim.Data.RotAndTra[3]); + ItemDataField("4: TransY", ref _prim.Data.RotAndTra[4]); + ItemDataField("5: TransZ", ref _prim.Data.RotAndTra[5]); + ItemDataField("6: ObjRotX", ref _prim.Data.RotAndTra[6]); + ItemDataField("7: ObjRotY", ref _prim.Data.RotAndTra[7]); + ItemDataField("8: ObjRotZ", ref _prim.Data.RotAndTra[8]); EditorGUI.indentLevel--; } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "Physics")) { - EditorGUI.BeginDisabledGroup(_prim.data.IsToy || !_prim.data.IsCollidable); + EditorGUI.BeginDisabledGroup(_prim.Data.IsToy || !_prim.Data.IsCollidable); - ItemDataField("Has Hit Event", ref _prim.data.HitEvent, dirtyMesh: false); - EditorGUI.BeginDisabledGroup(!_prim.data.HitEvent); - ItemDataField("Has Hit Event", ref _prim.data.Threshold, dirtyMesh: false); + ItemDataField("Has Hit Event", ref _prim.Data.HitEvent, dirtyMesh: false); + EditorGUI.BeginDisabledGroup(!_prim.Data.HitEvent); + ItemDataField("Has Hit Event", ref _prim.Data.Threshold, dirtyMesh: false); EditorGUI.EndDisabledGroup(); - EditorGUI.BeginDisabledGroup(_prim.data.OverwritePhysics); - MaterialField("Physics Material", ref _prim.data.PhysicsMaterial, dirtyMesh: false); + EditorGUI.BeginDisabledGroup(_prim.Data.OverwritePhysics); + MaterialField("Physics Material", ref _prim.Data.PhysicsMaterial, dirtyMesh: false); EditorGUI.EndDisabledGroup(); - ItemDataField("Overwrite Material Settings", ref _prim.data.OverwritePhysics, dirtyMesh: false); - EditorGUI.BeginDisabledGroup(!_prim.data.OverwritePhysics); - ItemDataField("Elasticity", ref _prim.data.Elasticity, dirtyMesh: false); - ItemDataField("Elasticity Falloff", ref _prim.data.ElasticityFalloff, dirtyMesh: false); - ItemDataField("Friction", ref _prim.data.Friction, dirtyMesh: false); - ItemDataField("Scatter Angle", ref _prim.data.Scatter, dirtyMesh: false); + ItemDataField("Overwrite Material Settings", ref _prim.Data.OverwritePhysics, dirtyMesh: false); + EditorGUI.BeginDisabledGroup(!_prim.Data.OverwritePhysics); + ItemDataField("Elasticity", ref _prim.Data.Elasticity, dirtyMesh: false); + ItemDataField("Elasticity Falloff", ref _prim.Data.ElasticityFalloff, dirtyMesh: false); + ItemDataField("Friction", ref _prim.Data.Friction, dirtyMesh: false); + ItemDataField("Scatter Angle", ref _prim.Data.Scatter, dirtyMesh: false); EditorGUI.EndDisabledGroup(); EditorGUI.EndDisabledGroup(); - EditorGUI.BeginDisabledGroup(_prim.data.IsToy); - ItemDataField("Collidable", ref _prim.data.IsCollidable, dirtyMesh: false); + EditorGUI.BeginDisabledGroup(_prim.Data.IsToy); + ItemDataField("Collidable", ref _prim.Data.IsCollidable, dirtyMesh: false); EditorGUI.EndDisabledGroup(); - ItemDataField("Toy", ref _prim.data.IsToy, dirtyMesh: false); + ItemDataField("Toy", ref _prim.Data.IsToy, dirtyMesh: false); - EditorGUI.BeginDisabledGroup(_prim.data.IsToy); - ItemDataSlider("Reduce Polygons By", ref _prim.data.CollisionReductionFactor, 0f, 1f, dirtyMesh: false); + EditorGUI.BeginDisabledGroup(_prim.Data.IsToy); + ItemDataSlider("Reduce Polygons By", ref _prim.Data.CollisionReductionFactor, 0f, 1f, dirtyMesh: false); EditorGUI.EndDisabledGroup(); } EditorGUILayout.EndFoldoutHeaderGroup(); @@ -126,8 +126,8 @@ private void MeshImporterGui() var mesh = (Mesh)EditorGUILayout.ObjectField("Import Mesh", null, typeof(Mesh), false); if (mesh != null && EditorGUI.EndChangeCheck()) { FinishEdit("Import Mesh", true); - _prim.data.Use3DMesh = true; - _prim.data.Mesh = mesh.ToVpMesh(); + _prim.Data.Use3DMesh = true; + _prim.Data.Mesh = mesh.ToVpMesh(); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs index 93e648cd5..72ef4ccf0 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs @@ -64,68 +64,68 @@ public override void OnInspectorGUI() OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - DropDownField("Type", ref _ramp.data.RampType, _rampTypeStrings, _rampTypeValues); - TextureField("Image", ref _ramp.data.Image); - MaterialField("Material", ref _ramp.data.Material); - DropDownField("Image Mode", ref _ramp.data.ImageAlignment, _rampImageAlignmentStrings, _rampImageAlignmentValues); - ItemDataField("Apply Image To Wall", ref _ramp.data.ImageWalls); - ItemDataField("Visible", ref _ramp.data.IsVisible); - ItemDataField("Depth Bias", ref _ramp.data.DepthBias); + DropDownField("Type", ref _ramp.Data.RampType, _rampTypeStrings, _rampTypeValues); + TextureField("Image", ref _ramp.Data.Image); + MaterialField("Material", ref _ramp.Data.Material); + DropDownField("Image Mode", ref _ramp.Data.ImageAlignment, _rampImageAlignmentStrings, _rampImageAlignmentValues); + ItemDataField("Apply Image To Wall", ref _ramp.Data.ImageWalls); + ItemDataField("Visible", ref _ramp.Data.IsVisible); + ItemDataField("Depth Bias", ref _ramp.Data.DepthBias); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("Top Height", ref _ramp.data.HeightTop); - ItemDataField("Bottom Height", ref _ramp.data.HeightBottom); + ItemDataField("Top Height", ref _ramp.Data.HeightTop); + ItemDataField("Bottom Height", ref _ramp.Data.HeightBottom); EditorGUILayout.Space(10); - ItemDataField("Top Width", ref _ramp.data.WidthTop); - ItemDataField("Bottom Width", ref _ramp.data.WidthBottom); + ItemDataField("Top Width", ref _ramp.Data.WidthTop); + ItemDataField("Bottom Width", ref _ramp.Data.WidthBottom); EditorGUILayout.Space(10); EditorGUILayout.LabelField("Visible Wall"); EditorGUI.indentLevel++; - ItemDataField("Left Wall", ref _ramp.data.LeftWallHeightVisible); - ItemDataField("Right Wall", ref _ramp.data.RightWallHeightVisible); + ItemDataField("Left Wall", ref _ramp.Data.LeftWallHeightVisible); + ItemDataField("Right Wall", ref _ramp.Data.RightWallHeightVisible); EditorGUI.indentLevel--; EditorGUILayout.LabelField("Wire Ramp"); EditorGUI.indentLevel++; - ItemDataField("Diameter", ref _ramp.data.WireDiameter); - ItemDataField("Distance X", ref _ramp.data.WireDistanceX); - ItemDataField("Distance Y", ref _ramp.data.WireDistanceY); + ItemDataField("Diameter", ref _ramp.Data.WireDiameter); + ItemDataField("Distance X", ref _ramp.Data.WireDistanceX); + ItemDataField("Distance Y", ref _ramp.Data.WireDistanceY); EditorGUI.indentLevel--; } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "Physics")) { - ItemDataField("Has Hit Event", ref _ramp.data.HitEvent, dirtyMesh: false); - ItemDataField("Hit Threshold", ref _ramp.data.Threshold, dirtyMesh: false); + ItemDataField("Has Hit Event", ref _ramp.Data.HitEvent, dirtyMesh: false); + ItemDataField("Hit Threshold", ref _ramp.Data.Threshold, dirtyMesh: false); EditorGUILayout.LabelField("Physical Wall"); EditorGUI.indentLevel++; - ItemDataField("Left Wall", ref _ramp.data.LeftWallHeight); - ItemDataField("Right Wall", ref _ramp.data.RightWallHeight); + ItemDataField("Left Wall", ref _ramp.Data.LeftWallHeight); + ItemDataField("Right Wall", ref _ramp.Data.RightWallHeight); EditorGUI.indentLevel--; - EditorGUI.BeginDisabledGroup(_ramp.data.OverwritePhysics); - MaterialField("Physics Material", ref _ramp.data.PhysicsMaterial, dirtyMesh: false); + EditorGUI.BeginDisabledGroup(_ramp.Data.OverwritePhysics); + MaterialField("Physics Material", ref _ramp.Data.PhysicsMaterial, dirtyMesh: false); EditorGUI.EndDisabledGroup(); - ItemDataField("Overwrite Material Settings", ref _ramp.data.OverwritePhysics, dirtyMesh: false); + ItemDataField("Overwrite Material Settings", ref _ramp.Data.OverwritePhysics, dirtyMesh: false); - EditorGUI.BeginDisabledGroup(!_ramp.data.OverwritePhysics); - ItemDataField("Elasticity", ref _ramp.data.Elasticity, dirtyMesh: false); - ItemDataField("Friction", ref _ramp.data.Friction, dirtyMesh: false); - ItemDataField("Scatter Angle", ref _ramp.data.Scatter, dirtyMesh: false); + EditorGUI.BeginDisabledGroup(!_ramp.Data.OverwritePhysics); + ItemDataField("Elasticity", ref _ramp.Data.Elasticity, dirtyMesh: false); + ItemDataField("Friction", ref _ramp.Data.Friction, dirtyMesh: false); + ItemDataField("Scatter Angle", ref _ramp.Data.Scatter, dirtyMesh: false); EditorGUI.EndDisabledGroup(); - ItemDataField("Collidable", ref _ramp.data.IsCollidable, dirtyMesh: false); + ItemDataField("Collidable", ref _ramp.Data.IsCollidable, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _ramp.data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _ramp.data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref _ramp.Data.IsTimerEnabled, dirtyMesh: false); + ItemDataField("Timer Interval", ref _ramp.Data.TimerInterval, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs index 89ed10afe..4cfb01e49 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs @@ -39,28 +39,28 @@ public override void OnInspectorGUI() OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - TextureField("Image", ref _rubber.data.Image); - MaterialField("Material", ref _rubber.data.Material); - ItemDataField("Visible", ref _rubber.data.IsVisible); - ItemDataField("Static", ref _rubber.data.StaticRendering); + TextureField("Image", ref _rubber.Data.Image); + MaterialField("Material", ref _rubber.Data.Material); + ItemDataField("Visible", ref _rubber.Data.IsVisible); + ItemDataField("Static", ref _rubber.Data.StaticRendering); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("Height", ref _rubber.data.Height); - ItemDataField("Thickness", ref _rubber.data.Thickness); + ItemDataField("Height", ref _rubber.Data.Height); + ItemDataField("Thickness", ref _rubber.Data.Thickness); EditorGUILayout.LabelField("Orientation"); EditorGUI.indentLevel++; - ItemDataField("RotX", ref _rubber.data.RotX); - ItemDataField("RotY", ref _rubber.data.RotY); - ItemDataField("RotZ", ref _rubber.data.RotZ); + ItemDataField("RotX", ref _rubber.Data.RotX); + ItemDataField("RotY", ref _rubber.Data.RotY); + ItemDataField("RotZ", ref _rubber.Data.RotZ); EditorGUI.indentLevel--; } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _rubber.data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _rubber.data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref _rubber.Data.IsTimerEnabled, dirtyMesh: false); + ItemDataField("Timer Interval", ref _rubber.Data.TimerInterval, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerInspector.cs index 80bac6868..94c3e6394 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerInspector.cs @@ -38,33 +38,33 @@ public override void OnInspectorGUI() OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - ItemDataField("Visible", ref _spinner.data.IsVisible); - TextureField("Image", ref _spinner.data.Image); - MaterialField("Material", ref _spinner.data.Material); - ItemDataField("Show Bracket", ref _spinner.data.ShowBracket); + ItemDataField("Visible", ref _spinner.Data.IsVisible); + TextureField("Image", ref _spinner.Data.Image); + MaterialField("Material", ref _spinner.Data.Material); + ItemDataField("Show Bracket", ref _spinner.Data.ShowBracket); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("", ref _spinner.data.Center); - ItemDataField("Length", ref _spinner.data.Length); - ItemDataField("Height", ref _spinner.data.Height); - ItemDataField("Rotation", ref _spinner.data.Rotation); - ItemDataField("Angle Max", ref _spinner.data.AngleMax, dirtyMesh: false); - ItemDataField("Angle Min", ref _spinner.data.AngleMin, dirtyMesh: false); - ItemDataField("Elasticity", ref _spinner.data.Elasticity, dirtyMesh: false); - SurfaceField("Surface", ref _spinner.data.Surface); + ItemDataField("", ref _spinner.Data.Center); + ItemDataField("Length", ref _spinner.Data.Length); + ItemDataField("Height", ref _spinner.Data.Height); + ItemDataField("Rotation", ref _spinner.Data.Rotation); + ItemDataField("Angle Max", ref _spinner.Data.AngleMax, dirtyMesh: false); + ItemDataField("Angle Min", ref _spinner.Data.AngleMin, dirtyMesh: false); + ItemDataField("Elasticity", ref _spinner.Data.Elasticity, dirtyMesh: false); + SurfaceField("Surface", ref _spinner.Data.Surface); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "Physics")) { - ItemDataField("Damping", ref _spinner.data.Damping, dirtyMesh: false); + ItemDataField("Damping", ref _spinner.Data.Damping, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _spinner.data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _spinner.data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref _spinner.Data.IsTimerEnabled, dirtyMesh: false); + ItemDataField("Timer Interval", ref _spinner.Data.TimerInterval, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs index 6a8353d61..eec5658f1 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs @@ -39,28 +39,28 @@ public override void OnInspectorGUI() OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - ItemDataField("Top Visible", ref _targetSurf.data.IsTopBottomVisible); - TextureField("Top Image", ref _targetSurf.data.Image); - MaterialField("Top Material", ref _targetSurf.data.TopMaterial); - ItemDataField("Side Visible", ref _targetSurf.data.IsSideVisible); - TextureField("Side Image", ref _targetSurf.data.SideImage); - MaterialField("Side Material", ref _targetSurf.data.SideMaterial); - MaterialField("Slingshot Material", ref _targetSurf.data.SlingShotMaterial); - ItemDataField("Animate Slingshot", ref _targetSurf.data.SlingshotAnimation, dirtyMesh: false); - ItemDataField("Flipbook", ref _targetSurf.data.IsFlipbook, dirtyMesh: false); + ItemDataField("Top Visible", ref _targetSurf.Data.IsTopBottomVisible); + TextureField("Top Image", ref _targetSurf.Data.Image); + MaterialField("Top Material", ref _targetSurf.Data.TopMaterial); + ItemDataField("Side Visible", ref _targetSurf.Data.IsSideVisible); + TextureField("Side Image", ref _targetSurf.Data.SideImage); + MaterialField("Side Material", ref _targetSurf.Data.SideMaterial); + MaterialField("Slingshot Material", ref _targetSurf.Data.SlingShotMaterial); + ItemDataField("Animate Slingshot", ref _targetSurf.Data.SlingshotAnimation, dirtyMesh: false); + ItemDataField("Flipbook", ref _targetSurf.Data.IsFlipbook, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("Top Height", ref _targetSurf.data.HeightTop); - ItemDataField("Bottom Height", ref _targetSurf.data.HeightBottom); + ItemDataField("Top Height", ref _targetSurf.Data.HeightTop); + ItemDataField("Bottom Height", ref _targetSurf.Data.HeightBottom); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _targetSurf.data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _targetSurf.data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref _targetSurf.Data.IsTimerEnabled, dirtyMesh: false); + ItemDataField("Timer Interval", ref _targetSurf.Data.TimerInterval, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Table/TableInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Table/TableInspector.cs index b17ce9fdc..1c20d3d6f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Table/TableInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Table/TableInspector.cs @@ -37,7 +37,7 @@ public override void OnInspectorGUI() if (!EditorApplication.isPlaying) { DrawDefaultInspector(); if (GUILayout.Button("Export VPX")) { - var table = tableComponent.RecreateTable(); + var table = tableComponent.RecreateTable(tableComponent.Data); var path = EditorUtility.SaveFilePanel( "Export table as VPX", "", diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerInspector.cs index 11aa22532..ac2df30a0 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerInspector.cs @@ -58,31 +58,31 @@ public override void OnInspectorGUI() OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - ItemDataField("Visible", ref _trigger.data.IsVisible); - DropDownField("Shape", ref _trigger.data.Shape, _triggerShapeStrings, _triggerShapeValues); - ItemDataField("Wire Thickness", ref _trigger.data.WireThickness); - ItemDataField("Star Radius", ref _trigger.data.Radius); - ItemDataField("Rotation", ref _trigger.data.Rotation); - ItemDataField("Animation Speed", ref _trigger.data.AnimSpeed, dirtyMesh: false); - MaterialField("Material", ref _trigger.data.Material); + ItemDataField("Visible", ref _trigger.Data.IsVisible); + DropDownField("Shape", ref _trigger.Data.Shape, _triggerShapeStrings, _triggerShapeValues); + ItemDataField("Wire Thickness", ref _trigger.Data.WireThickness); + ItemDataField("Star Radius", ref _trigger.Data.Radius); + ItemDataField("Rotation", ref _trigger.Data.Rotation); + ItemDataField("Animation Speed", ref _trigger.Data.AnimSpeed, dirtyMesh: false); + MaterialField("Material", ref _trigger.Data.Material); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("", ref _trigger.data.Center); - SurfaceField("Surface", ref _trigger.data.Surface); + ItemDataField("", ref _trigger.Data.Center); + SurfaceField("Surface", ref _trigger.Data.Surface); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "State & Physics")) { - ItemDataField("Enabled", ref _trigger.data.IsEnabled, dirtyMesh: false); - ItemDataField("Hit Height", ref _trigger.data.HitHeight, dirtyMesh: false); + ItemDataField("Enabled", ref _trigger.Data.IsEnabled, dirtyMesh: false); + ItemDataField("Hit Height", ref _trigger.Data.HitHeight, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _trigger.data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _trigger.data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref _trigger.Data.IsTimerEnabled, dirtyMesh: false); + ItemDataField("Timer Interval", ref _trigger.Data.TimerInterval, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/Game/Player.cs b/VisualPinball.Unity/VisualPinball.Unity/Game/Player.cs index ac2eaa327..749418438 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Game/Player.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Game/Player.cs @@ -89,7 +89,7 @@ private void Awake() var tableComponent = gameObject.GetComponent(); var engineComponent = GetComponent(); - Table = tableComponent.CreateTable(); + Table = tableComponent.CreateTable(tableComponent.Data); BallManager = new BallManager(Table, TableToWorld); _inputManager = new InputManager(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs index 770d36eb8..87d57ba89 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs @@ -33,7 +33,7 @@ public class BumperAuthoring : ItemAuthoring, IHittableAutho { protected override string[] Children => new []{"Base", "Cap", "Ring", "Skirt"}; - protected override Bumper GetItem() => new Bumper(data); + protected override Bumper InstantiateItem(BumperData data) => new Bumper(data); public IHittable Hittable => Item; public ISwitchable Switchable => Item; @@ -49,9 +49,9 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio { Convert(entity, dstManager); dstManager.AddComponentData(entity, new BumperStaticData { - Force = data.Force, - HitEvent = data.HitEvent, - Threshold = data.Threshold + Force = Data.Force, + HitEvent = Data.HitEvent, + Threshold = Data.Threshold }); transform.GetComponentInParent().RegisterBumper(Item, entity, gameObject); @@ -66,15 +66,15 @@ public void LinkChild(IItemAuthoring item) } public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; - public override Vector3 GetEditorPosition() => data.Center.ToUnityVector3(0f); - public override void SetEditorPosition(Vector3 pos) => data.Center = pos.ToVertex2Dxy(); + public override Vector3 GetEditorPosition() => Data.Center.ToUnityVector3(0f); + public override void SetEditorPosition(Vector3 pos) => Data.Center = pos.ToVertex2Dxy(); public override ItemDataTransformType EditorRotationType => ItemDataTransformType.OneD; - public override Vector3 GetEditorRotation() => new Vector3(data.Orientation, 0, 0); - public override void SetEditorRotation(Vector3 rot) => data.Orientation = rot.x; + public override Vector3 GetEditorRotation() => new Vector3(Data.Orientation, 0, 0); + public override void SetEditorRotation(Vector3 rot) => Data.Orientation = rot.x; public override ItemDataTransformType EditorScaleType => ItemDataTransformType.OneD; - public override Vector3 GetEditorScale() => new Vector3(data.Radius, 0f, 0f); - public override void SetEditorScale(Vector3 scale) => data.Radius = scale.x; + public override Vector3 GetEditorScale() => new Vector3(Data.Radius, 0f, 0f); + public override void SetEditorScale(Vector3 scale) => Data.Radius = scale.x; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs index 92d0b2921..103d4797c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs @@ -36,7 +36,7 @@ public class FlipperAuthoring : ItemAuthoring, { protected override string[] Children => new []{ FlipperMeshGenerator.BaseName, FlipperMeshGenerator.RubberName }; - protected override Flipper GetItem() => new Flipper(data); + protected override Flipper InstantiateItem(FlipperData data) => new Flipper(data); public IHittable Hittable => Item; public ISwitchable Switchable => Item; @@ -73,30 +73,30 @@ public void LinkChild(IItemAuthoring item) } public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; - public override Vector3 GetEditorPosition() => data.Center.ToUnityVector3(0f); - public override void SetEditorPosition(Vector3 pos) => data.Center = pos.ToVertex2Dxy(); + public override Vector3 GetEditorPosition() => Data.Center.ToUnityVector3(0f); + public override void SetEditorPosition(Vector3 pos) => Data.Center = pos.ToVertex2Dxy(); public override ItemDataTransformType EditorRotationType => ItemDataTransformType.OneD; - public override Vector3 GetEditorRotation() => new Vector3(data.StartAngle, 0f, 0f); - public override void SetEditorRotation(Vector3 rot) => data.StartAngle = rot.x; + public override Vector3 GetEditorRotation() => new Vector3(Data.StartAngle, 0f, 0f); + public override void SetEditorRotation(Vector3 rot) => Data.StartAngle = rot.x; public override ItemDataTransformType EditorScaleType => ItemDataTransformType.ThreeD; - public override Vector3 GetEditorScale() => new Vector3(data.BaseRadius, data.FlipperRadius, data.Height); + public override Vector3 GetEditorScale() => new Vector3(Data.BaseRadius, Data.FlipperRadius, Data.Height); public override void SetEditorScale(Vector3 scale) { - if (data.BaseRadius > 0) { - float endRadiusRatio = data.EndRadius / data.BaseRadius; - data.EndRadius = scale.x * endRadiusRatio; + if (Data.BaseRadius > 0) { + float endRadiusRatio = Data.EndRadius / Data.BaseRadius; + Data.EndRadius = scale.x * endRadiusRatio; } - data.BaseRadius = scale.x; - data.FlipperRadius = scale.y; - if (data.Height > 0) { - float rubberHeightRatio = data.RubberHeight / data.Height; - data.RubberHeight = scale.z * rubberHeightRatio; - float rubberWidthRatio = data.RubberWidth / data.Height; - data.RubberWidth = scale.z * rubberWidthRatio; + Data.BaseRadius = scale.x; + Data.FlipperRadius = scale.y; + if (Data.Height > 0) { + float rubberHeightRatio = Data.RubberHeight / Data.Height; + Data.RubberHeight = scale.z * rubberHeightRatio; + float rubberWidthRatio = Data.RubberWidth / Data.Height; + Data.RubberWidth = scale.z * rubberWidthRatio; } - data.Height = scale.z; + Data.Height = scale.z; } protected override void OnDrawGizmosSelected() @@ -109,11 +109,11 @@ protected override void OnDrawGizmosSelected() Gizmos.matrix = Matrix4x4.identity; var baseRotation = math.normalize(math.mul( math.normalize(transform.rotation), - quaternion.EulerXYZ(0, 0, -math.radians(data.StartAngle)) + quaternion.EulerXYZ(0, 0, -math.radians(Data.StartAngle)) )); foreach (var mf in mfs) { var t = mf.transform; - var r = math.mul(baseRotation, quaternion.EulerXYZ(0, 0, math.radians(data.EndAngle))); + var r = math.mul(baseRotation, quaternion.EulerXYZ(0, 0, math.radians(Data.EndAngle))); Gizmos.DrawWireMesh(mf.sharedMesh, t.position, r, t.lossyScale); } } @@ -121,18 +121,18 @@ protected override void OnDrawGizmosSelected() private FlipperStaticData GetMaterialData() { float flipperRadius; - if (data.FlipperRadiusMin > 0 && data.FlipperRadiusMax > data.FlipperRadiusMin) { - flipperRadius = data.FlipperRadiusMax - (data.FlipperRadiusMax - data.FlipperRadiusMin) /* m_ptable->m_globalDifficulty*/; - flipperRadius = math.max(flipperRadius, data.BaseRadius - data.EndRadius + 0.05f); + if (Data.FlipperRadiusMin > 0 && Data.FlipperRadiusMax > Data.FlipperRadiusMin) { + flipperRadius = Data.FlipperRadiusMax - (Data.FlipperRadiusMax - Data.FlipperRadiusMin) /* m_ptable->m_globalDifficulty*/; + flipperRadius = math.max(flipperRadius, Data.BaseRadius - Data.EndRadius + 0.05f); } else { - flipperRadius = data.FlipperRadiusMax; + flipperRadius = Data.FlipperRadiusMax; } - var endRadius = math.max(data.EndRadius, 0.01f); // radius of flipper end + var endRadius = math.max(Data.EndRadius, 0.01f); // radius of flipper end flipperRadius = math.max(flipperRadius, 0.01f); // radius of flipper arc, center-to-center radius - var angleStart = math.radians(data.StartAngle); - var angleEnd = math.radians(data.EndAngle); + var angleStart = math.radians(Data.StartAngle); + var angleEnd = math.radians(Data.EndAngle); if (angleEnd == angleStart) { // otherwise hangs forever in collisions/updates @@ -142,18 +142,18 @@ private FlipperStaticData GetMaterialData() var tableData = Table.Data; // model inertia of flipper as that of rod of length flipper around its end - var mass = data.GetFlipperMass(tableData); + var mass = Data.GetFlipperMass(tableData); var inertia = (float) (1.0 / 3.0) * mass * (flipperRadius * flipperRadius); return new FlipperStaticData { Inertia = inertia, AngleStart = angleStart, AngleEnd = angleEnd, - Strength = data.GetStrength(tableData), - ReturnRatio = data.GetReturnRatio(tableData), - TorqueDamping = data.GetTorqueDamping(tableData), - TorqueDampingAngle = data.GetTorqueDampingAngle(tableData), - RampUpSpeed = data.GetRampUpSpeed(tableData), + Strength = Data.GetStrength(tableData), + ReturnRatio = Data.GetReturnRatio(tableData), + TorqueDamping = Data.GetTorqueDamping(tableData), + TorqueDampingAngle = Data.GetTorqueDampingAngle(tableData), + RampUpSpeed = Data.GetRampUpSpeed(tableData), EndRadius = endRadius, FlipperRadius = flipperRadius @@ -189,7 +189,7 @@ private static FlipperVelocityData GetVelocityData(FlipperStaticData d) private FlipperHitData GetHitData() { - var ratio = (math.max(data.BaseRadius, 0.01f) - math.max(data.EndRadius, 0.01f)) / math.max(data.FlipperRadius, 0.01f); + var ratio = (math.max(Data.BaseRadius, 0.01f) - math.max(Data.EndRadius, 0.01f)) / math.max(Data.FlipperRadius, 0.01f); var zeroAngNorm = new float2( math.sqrt(1.0f - ratio * ratio), // F2 Norm, used in Green's transform, in FPM time search // = sinf(faceNormOffset) -ratio // F1 norm, change sign of x component, i.e -zeroAngNorm.x // = -cosf(faceNormOffset) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs index e383a61d4..d4355b55e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs @@ -32,7 +32,7 @@ public class GateAuthoring : ItemAuthoring, IHittableAuthoring, { protected override string[] Children => new []{"Wire", "Bracket"}; - protected override Gate GetItem() => new Gate(data); + protected override Gate InstantiateItem(GateData data) => new Gate(data); public IHittable Hittable => Item; public ISwitchable Switchable => Item; @@ -53,19 +53,19 @@ public void LinkChild(IItemAuthoring item) } public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; - public override Vector3 GetEditorPosition() => data.Center.ToUnityVector3(data.Height); + public override Vector3 GetEditorPosition() => Data.Center.ToUnityVector3(Data.Height); public override void SetEditorPosition(Vector3 pos) { - data.Center = pos.ToVertex2Dxy(); - data.Height = pos.z; + Data.Center = pos.ToVertex2Dxy(); + Data.Height = pos.z; } public override ItemDataTransformType EditorRotationType => ItemDataTransformType.OneD; - public override Vector3 GetEditorRotation() => new Vector3(data.Rotation, 0f, 0f); - public override void SetEditorRotation(Vector3 rot) => data.Rotation = rot.x; + public override Vector3 GetEditorRotation() => new Vector3(Data.Rotation, 0f, 0f); + public override void SetEditorRotation(Vector3 rot) => Data.Rotation = rot.x; public override ItemDataTransformType EditorScaleType => ItemDataTransformType.OneD; - public override Vector3 GetEditorScale() => new Vector3(data.Length, 0f, 0f); - public override void SetEditorScale(Vector3 scale) => data.Length = scale.x; + public override Vector3 GetEditorScale() => new Vector3(Data.Length, 0f, 0f); + public override void SetEditorScale(Vector3 scale) => Data.Length = scale.x; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAuthoring.cs index 1a42eb121..d66deb041 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAuthoring.cs @@ -30,15 +30,15 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio Convert(entity, dstManager); dstManager.AddComponentData(entity, new GateStaticData { - AngleMin = data.AngleMin, - AngleMax = data.AngleMax, - Height = data.Height, - Damping = math.pow(data.Damping, (float)PhysicsConstants.PhysFactor), - GravityFactor = data.GravityFactor, - TwoWay = data.TwoWay + AngleMin = Data.AngleMin, + AngleMax = Data.AngleMax, + Height = Data.Height, + Damping = math.pow(Data.Damping, (float)PhysicsConstants.PhysFactor), + GravityFactor = Data.GravityFactor, + TwoWay = Data.TwoWay }); dstManager.AddComponentData(entity, new GateMovementData { - Angle = data.AngleMin, + Angle = Data.AngleMin, AngleSpeed = 0, ForcedMove = false, IsOpen = false @@ -49,7 +49,7 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterGate(gate, entity, gameObject); } - protected override Gate GetItem() + protected override Gate InstantiateItem(GateData data) { return transform.parent.gameObject.GetComponent().Item; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs index 4ef43abb3..6b7b2cd3a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs @@ -33,7 +33,7 @@ public class HitTargetAuthoring : ItemAuthoring, IConv { protected override string[] Children => null; - protected override HitTarget GetItem() => new HitTarget(data); + protected override HitTarget InstantiateItem(HitTargetData data) => new HitTarget(data); public IHittable Hittable => Item; public ISwitchable Switchable => Item; @@ -51,15 +51,15 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio var table = gameObject.GetComponentInParent().Item; dstManager.AddComponentData(entity, new HitTargetStaticData { - TargetType = data.TargetType, - DropSpeed = data.DropSpeed, - RaiseDelay = data.RaiseDelay, - UseHitEvent = data.UseHitEvent, - RotZ = data.RotZ, + TargetType = Data.TargetType, + DropSpeed = Data.DropSpeed, + RaiseDelay = Data.RaiseDelay, + UseHitEvent = Data.UseHitEvent, + RotZ = Data.RotZ, TableScaleZ = table.GetScaleZ() }); dstManager.AddComponentData(entity, new HitTargetAnimationData { - IsDropped = data.IsDropped + IsDropped = Data.IsDropped }); dstManager.AddComponentData(entity, new HitTargetMovementData()); @@ -77,15 +77,15 @@ public void LinkChild(IItemAuthoring item) } public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; - public override Vector3 GetEditorPosition() => data.Position.ToUnityVector3(); - public override void SetEditorPosition(Vector3 pos) => data.Position = pos.ToVertex3D(); + public override Vector3 GetEditorPosition() => Data.Position.ToUnityVector3(); + public override void SetEditorPosition(Vector3 pos) => Data.Position = pos.ToVertex3D(); public override ItemDataTransformType EditorRotationType => ItemDataTransformType.OneD; - public override Vector3 GetEditorRotation() => new Vector3(data.RotZ, 0f, 0f); - public override void SetEditorRotation(Vector3 rot) => data.RotZ = rot.x; + public override Vector3 GetEditorRotation() => new Vector3(Data.RotZ, 0f, 0f); + public override void SetEditorRotation(Vector3 rot) => Data.RotZ = rot.x; public override ItemDataTransformType EditorScaleType => ItemDataTransformType.ThreeD; - public override Vector3 GetEditorScale() => data.Size.ToUnityVector3(); - public override void SetEditorScale(Vector3 scale) => data.Size = scale.ToVertex3D(); + public override Vector3 GetEditorScale() => Data.Size.ToUnityVector3(); + public override void SetEditorScale(Vector3 scale) => Data.Size = scale.ToVertex3D(); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs index b8162270a..54a7b2c2a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs @@ -14,6 +14,8 @@ // 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 System.Collections.Generic; using System.Linq; @@ -35,19 +37,73 @@ namespace VisualPinball.Unity { + /// + /// The base class for all authoring components on the playfield.

+ ///

+ /// + /// public abstract class ItemAuthoring : MonoBehaviour, IItemAuthoring, IEditableItemAuthoring, IIdentifiableItemAuthoring, ILayerableItemAuthoring where TData : ItemData where TItem : Item, IRenderable { + /// + /// The serialized data. Having this set means it's a real game item + /// that ends up or is imported from game item in the VPX file. + /// + /// However, this can also be `null`, in which case the component only + /// deals with a sub set of the main component (collision, mesh generation, + /// or movement). + /// [SerializeField] - public TData data; - - public TItem Item => _item ?? (_item = GetItem()); + protected TData _data; + + /// + /// The game item object. This is not serialized and gets re-instantiated + /// and cached here. + /// + [NonSerialized] + protected TItem _item; + + /// + /// Returns the data object relevant for this component. If this + /// returns `null`, then it's wrongly attached to a game object + /// where it can't find its main component. + /// + /// + /// + /// The default implementation here represents the one of a main + /// component. It's overridden for the sub components (, etc) + /// + public virtual TData Data => _data; + + /// + /// Returns the item object for this component. If this + /// returns `null`, then it's wrongly attached to a game object + /// where it can't find its main component. + /// + /// + /// + /// For any game item, we only serialize its data and re-instantiate + /// the actual item on the fly (and cache it). So in , + /// which initializes the component after creation, + /// is only set to avoid a cache miss. + /// + public virtual TItem Item => _item ?? (_item = InstantiateItem(_data)); + + /// + /// A non-typed version of the item. + /// public IItem IItem => _item; + /// + /// The data-oriented version of the item. + /// + public ItemData ItemData => _data; + + public string ItemType => Item.ItemType; - public bool IsLocked { get => data.IsLocked; set => data.IsLocked = value; } - public ItemData ItemData => data; + public bool IsLocked { get => _data.IsLocked; set => _data.IsLocked = value; } + public List MaterialRefs => _materialRefs ?? (_materialRefs = GetMembersWithAttribute()); public List TextureRefs => _textureRefs ?? (_textureRefs = GetMembersWithAttribute()); @@ -55,7 +111,6 @@ public abstract class ItemAuthoring : MonoBehaviour, IItemAuthorin protected Table Table => _table ?? (_table = gameObject.transform.GetComponentInParent()?.Item); - private TItem _item; private List _materialRefs; private List _textureRefs; @@ -70,21 +125,21 @@ public abstract class ItemAuthoring : MonoBehaviour, IItemAuthorin public ItemAuthoring SetItem(TItem item, string gameObjectName = null) { _item = item; - data = item.Data; - name = gameObjectName ?? data.GetName(); + _data = item.Data; + name = gameObjectName ?? _data.GetName(); ItemDataChanged(); return this; } public void RebuildMeshes() { - if (data == null) { + if (_data == null) { _logger.Warn("Cannot retrieve data component for a {0}.", typeof(TItem).Name); return; } var table = transform.GetComponentInParent(); if (table == null) { - _logger.Warn("Cannot retrieve table component from {0}, not updating meshes.", data.GetName()); + _logger.Warn("Cannot retrieve table component from {0}, not updating meshes.", _data.GetName()); return; } @@ -175,9 +230,10 @@ protected virtual void OnDrawGizmos() protected virtual void OnDrawGizmosSelected() { var isColliderComponent = this is IItemColliderAuthoring; - if (PhysicsDebug.ShowAabbs || PhysicsDebug.ShowColliders || isColliderComponent) { + if (isColliderComponent) { var ltw = transform.GetComponentInParent().gameObject.transform.localToWorldMatrix; + // todo remove check because IItemColliderAuthoring should only be on IHittables if (Item is IHittable hittable) { hittable.Init(Table); var hits = hittable.GetHitShapes(); @@ -196,9 +252,9 @@ protected virtual void OnDrawGizmosSelected() hit.CalcHitBBox(); DrawAabb(ltw, hit.HitBBox, i == PhysicsDebug.SelectedCollider); } - if (PhysicsDebug.ShowColliders || isColliderComponent) { + //if (PhysicsDebug.ShowColliders && isColliderComponent) { DrawCollider(ltw, hit, i == PhysicsDebug.SelectedCollider); - } + //} } } } @@ -398,13 +454,13 @@ private List GetMembersWithAttribute() where TAttr: Attribute protected abstract string[] Children { get; } - protected abstract TItem GetItem(); + protected abstract TItem InstantiateItem(TData data); public string Name { get => Item.Name; set => Item.Name = value; } - public int EditorLayer { get => data.EditorLayer; set => data.EditorLayer = value; } - public string EditorLayerName { get => data.EditorLayerName; set => data.EditorLayerName = value; } - public bool EditorLayerVisibility { get => data.EditorLayerVisibility; set => data.EditorLayerVisibility = value; } + public int EditorLayer { get => _data.EditorLayer; set => _data.EditorLayer = value; } + public string EditorLayerName { get => _data.EditorLayerName; set => _data.EditorLayerName = value; } + public bool EditorLayerVisibility { get => _data.EditorLayerVisibility; set => _data.EditorLayerVisibility = value; } } /// diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs index 38293a73b..739706b0d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs @@ -25,9 +25,9 @@ public abstract class ItemColliderAuthoring : ItemAuth where TItem : Item, IHittable, IRenderable where TAuthoring : ItemAuthoring { - public TData Data => GetData(); + public override TData Data => _data ?? (_data = FindData()); - protected TData _data; + public override TItem Item => _item ?? (_item = FindItem()); public IItemAuthoring SetItem(TItem item, RenderObjectGroup rog) { @@ -38,14 +38,20 @@ public IItemAuthoring SetItem(TItem item, RenderObjectGroup rog) protected override string[] Children => new string[0]; - private TData GetData() + private TItem FindItem() { - // if data is set, this is a full-fledged item - if (_data != null) { - return _data; - } + var ac = FindParentAuthoring(); + return ac != null ? ac.Item : null; + } + + private TData FindData() + { + var ac = FindParentAuthoring(); + return ac != null ? ac.Data : null; + } - // otherwise, retrieve data from parent + private TAuthoring FindParentAuthoring() + { var go = gameObject; var ac = go.GetComponent(); if (ac == null && go.transform.parent != null) { @@ -56,12 +62,11 @@ private TData GetData() ac = go.transform.parent.transform.parent.GetComponent(); } - if (ac != null) { - return ac.data; + if (ac == null) { + Debug.LogWarning("No same- or parent authoring component found."); } - Debug.LogWarning("No same- or parent authoring component found."); - return null; + return ac; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs index a821dfbcf..280c9710a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs @@ -35,7 +35,7 @@ public class KickerAuthoring : ItemAuthoring, IConvertGameOb { protected override string[] Children => null; - protected override Kicker GetItem() => new Kicker(data); + protected override Kicker InstantiateItem(KickerData data) => new Kicker(data); public IHittable Hittable => Item; public ISwitchable Switchable => Item; @@ -55,19 +55,19 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio Item.Init(table); dstManager.AddComponentData(entity, new KickerStaticData { - Center = data.Center.ToUnityFloat2(), - FallThrough = data.FallThrough, - HitAccuracy = data.HitAccuracy, - Scatter = data.Scatter, - LegacyMode = data.LegacyMode, - ZLow = table.GetSurfaceHeight(data.Surface, data.Center.X, data.Center.Y) * table.GetScaleZ() + Center = Data.Center.ToUnityFloat2(), + FallThrough = Data.FallThrough, + HitAccuracy = Data.HitAccuracy, + Scatter = Data.Scatter, + LegacyMode = Data.LegacyMode, + ZLow = table.GetSurfaceHeight(Data.Surface, Data.Center.X, Data.Center.Y) * table.GetScaleZ() }); dstManager.AddComponentData(entity, new KickerCollisionData { BallEntity = Entity.Null, LastCapturedBallEntity = Entity.Null }); - if (!data.LegacyMode) { + if (!Data.LegacyMode) { using (var blobBuilder = new BlobBuilder(Allocator.Temp)) { ref var blobAsset = ref blobBuilder.ConstructRoot(); var vertices = blobBuilder.Allocate(ref blobAsset.Vertices, Item.KickerHit.HitMesh.Length); @@ -96,11 +96,11 @@ public void LinkChild(IItemAuthoring item) } public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; - public override Vector3 GetEditorPosition() => data.Center.ToUnityVector3(0f); - public override void SetEditorPosition(Vector3 pos) => data.Center = pos.ToVertex2Dxy(); + public override Vector3 GetEditorPosition() => Data.Center.ToUnityVector3(0f); + public override void SetEditorPosition(Vector3 pos) => Data.Center = pos.ToVertex2Dxy(); public override ItemDataTransformType EditorRotationType => ItemDataTransformType.OneD; - public override Vector3 GetEditorRotation() => new Vector3(data.Orientation, 0f, 0f); - public override void SetEditorRotation(Vector3 rot) => data.Orientation = rot.x; + public override Vector3 GetEditorRotation() => new Vector3(Data.Orientation, 0f, 0f); + public override void SetEditorRotation(Vector3 rot) => Data.Orientation = rot.x; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs index 425685b44..9a0286b28 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs @@ -22,6 +22,7 @@ using UnityEngine; using VisualPinball.Engine.VPT.Light; +using Light = VisualPinball.Engine.VPT.Light.Light; namespace VisualPinball.Unity { @@ -32,10 +33,7 @@ public class LightAuthoring : ItemAuthoring private UnityEngine.Light _unityLight; - protected override Engine.VPT.Light.Light GetItem() - { - return new Engine.VPT.Light.Light(data); - } + protected override Light InstantiateItem(LightData data) => new Light(data); protected override void ItemDataChanged() { @@ -54,9 +52,9 @@ protected override void ItemDataChanged() if (_unityLight != null) { // Set color and position - _unityLight.color = data.Color2.ToUnityColor(); - _unityLight.intensity = data.Intensity / 2f; - _unityLight.range = data.Falloff * 0.001f; + _unityLight.color = Data.Color2.ToUnityColor(); + _unityLight.intensity = Data.Intensity / 2f; + _unityLight.range = Data.Falloff * 0.001f; // TODO: vpe specific data for height _unityLight.transform.localPosition = new Vector3(0f, 0f, 25f); @@ -68,11 +66,11 @@ protected override void ItemDataChanged() } public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; - public override Vector3 GetEditorPosition() => data.Center.ToUnityVector2(); - public override void SetEditorPosition(Vector3 pos) => data.Center = pos.ToVertex2Dxy(); + public override Vector3 GetEditorPosition() => Data.Center.ToUnityVector2(); + public override void SetEditorPosition(Vector3 pos) => Data.Center = pos.ToVertex2Dxy(); public override ItemDataTransformType EditorScaleType => ItemDataTransformType.OneD; - public override Vector3 GetEditorScale() => new Vector3(data.MeshRadius, data.MeshRadius, data.MeshRadius); - public override void SetEditorScale(Vector3 scale) => data.MeshRadius = scale.x; + public override Vector3 GetEditorScale() => new Vector3(Data.MeshRadius, Data.MeshRadius, Data.MeshRadius); + public override void SetEditorScale(Vector3 scale) => Data.MeshRadius = scale.x; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs index 42e1f0a6d..b72f009ff 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs @@ -29,7 +29,7 @@ public class PlungerAuthoring : ItemAuthoring, IConvertGam PlungerMeshGenerator.FlatName, PlungerMeshGenerator.RodName, PlungerMeshGenerator.SpringName }; - protected override Plunger GetItem() => new Plunger(data); + protected override Plunger InstantiateItem(PlungerData data) => new Plunger(data); public IHittable Hittable => Item; @@ -51,14 +51,14 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio hit.SetIndex(entity.Index, entity.Version); dstManager.AddComponentData(entity, new PlungerStaticData { - MomentumXfer = data.MomentumXfer, - ScatterVelocity = data.ScatterVelocity, + MomentumXfer = Data.MomentumXfer, + ScatterVelocity = Data.ScatterVelocity, FrameStart = hit.FrameBottom, FrameEnd = hit.FrameTop, FrameLen = hit.FrameLen, RestPosition = hit.RestPos, - IsAutoPlunger = data.AutoPlunger, - SpeedFire = data.SpeedFire, + IsAutoPlunger = Data.AutoPlunger, + SpeedFire = Data.SpeedFire, NumFrames = Item.MeshGenerator.NumFrames }); @@ -90,7 +90,7 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio AutoFireTimer = 0, AddRetractMotion = false, RetractWaitLoop = 0, - MechStrength = data.MechStrength + MechStrength = Data.MechStrength }); } @@ -103,7 +103,7 @@ public void LinkChild(IItemAuthoring item) } public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; - public override Vector3 GetEditorPosition() => data.Center.ToUnityVector3(0f); - public override void SetEditorPosition(Vector3 pos) => data.Center = pos.ToVertex3D(); + public override Vector3 GetEditorPosition() => Data.Center.ToUnityVector3(0f); + public override void SetEditorPosition(Vector3 pos) => Data.Center = pos.ToVertex3D(); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs index d6be8749f..9d62dfc4b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs @@ -49,25 +49,25 @@ public void LinkChild(IItemAuthoring item) { } - protected override Primitive GetItem() => new Primitive(data); + protected override Primitive InstantiateItem(PrimitiveData data) => new Primitive(data); public IHittable Hittable => Item; public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; - public override Vector3 GetEditorPosition() => data.Position.ToUnityVector3(); - public override void SetEditorPosition(Vector3 pos) => data.Position = pos.ToVertex3D(); + public override Vector3 GetEditorPosition() => Data.Position.ToUnityVector3(); + public override void SetEditorPosition(Vector3 pos) => Data.Position = pos.ToVertex3D(); public override ItemDataTransformType EditorRotationType => ItemDataTransformType.ThreeD; - public override Vector3 GetEditorRotation() => new Vector3(data.RotAndTra[0], data.RotAndTra[1], data.RotAndTra[2]); + public override Vector3 GetEditorRotation() => new Vector3(Data.RotAndTra[0], Data.RotAndTra[1], Data.RotAndTra[2]); public override void SetEditorRotation(Vector3 rot) { - data.RotAndTra[0] = rot.x; - data.RotAndTra[1] = rot.y; - data.RotAndTra[2] = rot.z; + Data.RotAndTra[0] = rot.x; + Data.RotAndTra[1] = rot.y; + Data.RotAndTra[2] = rot.z; } public override ItemDataTransformType EditorScaleType => ItemDataTransformType.ThreeD; - public override Vector3 GetEditorScale() => data.Size.ToUnityVector3(); - public override void SetEditorScale(Vector3 scale) => data.Size = scale.ToVertex3D(); + public override Vector3 GetEditorScale() => Data.Size.ToUnityVector3(); + public override void SetEditorScale(Vector3 scale) => Data.Size = scale.ToVertex3D(); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs index 087f171f2..6b656292c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs @@ -35,7 +35,7 @@ public class RampAuthoring : ItemAuthoring, IDragPointsEditable, { protected override string[] Children => new[] { "Floor", "RightWall", "LeftWall", "Wire1", "Wire2", "Wire3", "Wire4" }; - protected override Ramp GetItem() => new Ramp(data); + protected override Ramp InstantiateItem(RampData data) => new Ramp(data); public IHittable Hittable => Item; @@ -65,32 +65,32 @@ private void OnDestroy() public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() { - if (data == null || data.DragPoints.Length == 0) { + if (Data == null || Data.DragPoints.Length == 0) { return Vector3.zero; } - return data.DragPoints[0].Center.ToUnityVector3(); + return Data.DragPoints[0].Center.ToUnityVector3(); } public override void SetEditorPosition(Vector3 pos) { - if (data == null || data.DragPoints.Length == 0) { + if (Data == null || Data.DragPoints.Length == 0) { return; } - var diff = pos.ToVertex3D().Sub(data.DragPoints[0].Center); + var diff = pos.ToVertex3D().Sub(Data.DragPoints[0].Center); diff.Z = 0f; - data.DragPoints[0].Center = pos.ToVertex3D(); - for (int i = 1; i < data.DragPoints.Length; i++) { - var pt = data.DragPoints[i]; + Data.DragPoints[0].Center = pos.ToVertex3D(); + for (int i = 1; i < Data.DragPoints.Length; i++) { + var pt = Data.DragPoints[i]; pt.Center = pt.Center.Add(diff); } } //IDragPointsEditable public bool DragPointEditEnabled { get; set; } - public DragPointData[] GetDragPoints() => data.DragPoints; - public void SetDragPoints(DragPointData[] dragPoints) { data.DragPoints = dragPoints; } - public Vector3 GetEditableOffset() => new Vector3(0.0f, 0.0f, data.HeightBottom); - public Vector3 GetDragPointOffset(float ratio) => new Vector3(0.0f, 0.0f, (data.HeightTop - data.HeightBottom) * ratio); + public DragPointData[] GetDragPoints() => Data.DragPoints; + public void SetDragPoints(DragPointData[] dragPoints) { Data.DragPoints = dragPoints; } + public Vector3 GetEditableOffset() => new Vector3(0.0f, 0.0f, Data.HeightBottom); + public Vector3 GetDragPointOffset(float ratio) => new Vector3(0.0f, 0.0f, (Data.HeightTop - Data.HeightBottom) * ratio); public bool PointsAreLooping() => false; public IEnumerable GetDragPointExposition() => new DragPointExposure[] { DragPointExposure.Smooth, DragPointExposure.SlingShot }; public ItemDataTransformType GetHandleType() => ItemDataTransformType.ThreeD; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs index 4ef60cb92..ff2bba133 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs @@ -36,7 +36,7 @@ public class RubberAuthoring : ItemAuthoring, IDragPointsEdi { protected override string[] Children => null; - protected override Rubber GetItem() => new Rubber(data); + protected override Rubber InstantiateItem(RubberData data) => new Rubber(data); public IHittable Hittable => Item; @@ -66,42 +66,42 @@ public void RemoveHittableComponent() public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; public override Vector3 GetEditorPosition() { - if (data == null || data.DragPoints.Length == 0) { + if (Data == null || Data.DragPoints.Length == 0) { return Vector3.zero; } - return data.DragPoints[0].Center.ToUnityVector3(data.Height); + return Data.DragPoints[0].Center.ToUnityVector3(Data.Height); } public override void SetEditorPosition(Vector3 pos) { - if (data == null || data.DragPoints.Length == 0) { + if (Data == null || Data.DragPoints.Length == 0) { return; } - data.Height = pos.z; + Data.Height = pos.z; pos.z = 0f; - var diff = pos.ToVertex3D().Sub(data.DragPoints[0].Center); + var diff = pos.ToVertex3D().Sub(Data.DragPoints[0].Center); diff.Z = 0f; - data.DragPoints[0].Center = pos.ToVertex3D(); - for (int i = 1; i < data.DragPoints.Length; i++) { - var pt = data.DragPoints[i]; + Data.DragPoints[0].Center = pos.ToVertex3D(); + for (int i = 1; i < Data.DragPoints.Length; i++) { + var pt = Data.DragPoints[i]; pt.Center = pt.Center.Add(diff); } } public override ItemDataTransformType EditorRotationType => ItemDataTransformType.ThreeD; - public override Vector3 GetEditorRotation() => new Vector3(data.RotX, data.RotY, data.RotZ); + public override Vector3 GetEditorRotation() => new Vector3(Data.RotX, Data.RotY, Data.RotZ); public override void SetEditorRotation(Vector3 rot) { - data.RotX = rot.x; - data.RotY = rot.y; - data.RotZ = rot.z; + Data.RotX = rot.x; + Data.RotY = rot.y; + Data.RotZ = rot.z; } //IDragPointsEditable public bool DragPointEditEnabled { get; set; } - public DragPointData[] GetDragPoints() => data.DragPoints; - public void SetDragPoints(DragPointData[] dragPoints) { data.DragPoints = dragPoints; } - public Vector3 GetEditableOffset() => new Vector3(0.0f, 0.0f, data.HitHeight); + public DragPointData[] GetDragPoints() => Data.DragPoints; + public void SetDragPoints(DragPointData[] dragPoints) { Data.DragPoints = dragPoints; } + public Vector3 GetEditableOffset() => new Vector3(0.0f, 0.0f, Data.HitHeight); public Vector3 GetDragPointOffset(float ratio) => Vector3.zero; public bool PointsAreLooping() => true; public IEnumerable GetDragPointExposition() => new[] { DragPointExposure.Smooth }; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs index 5cedc5c31..3587e103b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs @@ -22,6 +22,6 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Rubber Collider")] public class RubberColliderAuthoring : ItemColliderAuthoring { - protected override Rubber GetItem() => new Rubber(_data); + protected override Rubber InstantiateItem(RubberData data) => new Rubber(_data); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs index 6fbdfe87a..ee8e88a78 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs @@ -32,7 +32,7 @@ public class SpinnerAuthoring : ItemAuthoring, IHittableAu { protected override string[] Children => new [] { "Plate", "Bracket" }; - protected override Spinner GetItem() => new Spinner(data); + protected override Spinner InstantiateItem(SpinnerData data) => new Spinner(data); public IHittable Hittable => Item; public ISwitchable Switchable => Item; @@ -53,19 +53,19 @@ public void LinkChild(IItemAuthoring item) } public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; - public override Vector3 GetEditorPosition() => data.Center.ToUnityVector3(data.Height); + public override Vector3 GetEditorPosition() => Data.Center.ToUnityVector3(Data.Height); public override void SetEditorPosition(Vector3 pos) { - data.Center = pos.ToVertex2Dxy(); - data.Height = pos.z; + Data.Center = pos.ToVertex2Dxy(); + Data.Height = pos.z; } public override ItemDataTransformType EditorRotationType => ItemDataTransformType.OneD; - public override Vector3 GetEditorRotation() => new Vector3(data.Rotation, 0f, 0f); - public override void SetEditorRotation(Vector3 rot) => data.Rotation = rot.x; + public override Vector3 GetEditorRotation() => new Vector3(Data.Rotation, 0f, 0f); + public override void SetEditorRotation(Vector3 rot) => Data.Rotation = rot.x; public override ItemDataTransformType EditorScaleType => ItemDataTransformType.OneD; - public override Vector3 GetEditorScale() => new Vector3(data.Length, 0f, 0f); - public override void SetEditorScale(Vector3 scale) => data.Length = scale.x; + public override Vector3 GetEditorScale() => new Vector3(Data.Length, 0f, 0f); + public override void SetEditorScale(Vector3 scale) => Data.Length = scale.x; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAuthoring.cs index d5c4c2a27..c74d31f9c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAuthoring.cs @@ -30,15 +30,15 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio Convert(entity, dstManager); dstManager.AddComponentData(entity, new SpinnerStaticData { - AngleMax = math.radians(data.AngleMax), - AngleMin = math.radians(data.AngleMin), - Damping = math.pow(data.Damping, (float)PhysicsConstants.PhysFactor), - Elasticity = data.Elasticity, - Height = data.Height + AngleMax = math.radians(Data.AngleMax), + AngleMin = math.radians(Data.AngleMin), + Damping = math.pow(Data.Damping, (float)PhysicsConstants.PhysFactor), + Elasticity = Data.Elasticity, + Height = Data.Height }); dstManager.AddComponentData(entity, new SpinnerMovementData { - Angle = math.radians(math.clamp(0.0f, data.AngleMin, data.AngleMax)), + Angle = math.radians(math.clamp(0.0f, Data.AngleMin, Data.AngleMax)), AngleSpeed = 0f }); @@ -47,9 +47,6 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterSpinner(spinner, entity, gameObject); } - protected override Spinner GetItem() - { - return transform.parent.gameObject.GetComponent().Item; - } + protected override Spinner InstantiateItem(SpinnerData data) => transform.parent.gameObject.GetComponent().Item; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs index 705576aec..5712ba516 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs @@ -36,7 +36,7 @@ public class SurfaceAuthoring : ItemAuthoring, IHittableAu { protected override string[] Children => new [] { "Side", "Top" }; - protected override Surface GetItem() => new Surface(data); + protected override Surface InstantiateItem(SurfaceData data) => new Surface(data); public IHittable Hittable => Item; @@ -52,7 +52,7 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio Convert(entity, dstManager); dstManager.AddComponentData(entity, new LineSlingshotData { IsDisabled = false, - Threshold = data.SlingshotThreshold, + Threshold = Data.SlingshotThreshold, }); transform.GetComponentInParent().RegisterSurface(Item, entity, gameObject); } @@ -72,30 +72,30 @@ public void LinkChild(IItemAuthoring item) public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() { - if (data == null || data.DragPoints.Length == 0) { + if (Data == null || Data.DragPoints.Length == 0) { return Vector3.zero; } - return data.DragPoints[0].Center.ToUnityVector3(); + return Data.DragPoints[0].Center.ToUnityVector3(); } public override void SetEditorPosition(Vector3 pos) { - if (data == null || data.DragPoints.Length == 0) { + if (Data == null || Data.DragPoints.Length == 0) { return; } - var diff = pos.ToVertex3D().Sub(data.DragPoints[0].Center); + var diff = pos.ToVertex3D().Sub(Data.DragPoints[0].Center); diff.Z = 0f; - data.DragPoints[0].Center = pos.ToVertex3D(); - for (int i = 1; i < data.DragPoints.Length; i++) { - var pt = data.DragPoints[i]; + Data.DragPoints[0].Center = pos.ToVertex3D(); + for (int i = 1; i < Data.DragPoints.Length; i++) { + var pt = Data.DragPoints[i]; pt.Center = pt.Center.Add(diff); } } //IDragPointsEditable public bool DragPointEditEnabled { get; set; } - public DragPointData[] GetDragPoints() => data.DragPoints; - public void SetDragPoints(DragPointData[] dragPoints) { data.DragPoints = dragPoints; } - public Vector3 GetEditableOffset() => new Vector3(0.0f, 0.0f, data.HeightBottom); + public DragPointData[] GetDragPoints() => Data.DragPoints; + public void SetDragPoints(DragPointData[] dragPoints) { Data.DragPoints = dragPoints; } + public Vector3 GetEditableOffset() => new Vector3(0.0f, 0.0f, Data.HeightBottom); public Vector3 GetDragPointOffset(float ratio) => Vector3.zero; public bool PointsAreLooping() => true; public IEnumerable GetDragPointExposition() => new[] { DragPointExposure.Smooth , DragPointExposure.SlingShot , DragPointExposure.Texture }; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs index d937dec8b..a5f84141a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs @@ -22,6 +22,6 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Surface Collider")] public class SurfaceColliderAuthoring : ItemColliderAuthoring { - protected override Surface GetItem() => new Surface(_data); + protected override Surface InstantiateItem(SurfaceData data) => new Surface(_data); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs index ae03f6958..e48fc259e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs @@ -90,9 +90,9 @@ protected override void OnDrawGizmos() // that would just be everything at this level } - protected override Table GetItem() + protected override Table InstantiateItem(TableData data) { - return RecreateTable(); + return RecreateTable(data); } internal TableSidecar GetOrCreateSidecar() @@ -188,7 +188,7 @@ public UnityEngine.Material GetMaterial(PbrMaterial vpxMat) return null; } - public Table CreateTable() + public Table CreateTable(TableData data) { Logger.Info("Restoring table..."); // restore table data @@ -241,9 +241,9 @@ public Table CreateTable() return table; } - public Table RecreateTable() + public Table RecreateTable(TableData tableData) { - var table = CreateTable(); + var table = CreateTable(tableData); Logger.Info("Table restored."); return table; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs index 05cd95b04..ba5e7eb4e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs @@ -35,7 +35,7 @@ public class TriggerAuthoring : ItemAuthoring, IHittableAu { protected override string[] Children => null; - protected override Trigger GetItem() => new Trigger(data); + protected override Trigger InstantiateItem(TriggerData data) => new Trigger(data); public IHittable Hittable => Item; public ISwitchable Switchable => Item; @@ -55,9 +55,9 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio dstManager.AddComponentData(entity, new TriggerAnimationData()); dstManager.AddComponentData(entity, new TriggerMovementData()); dstManager.AddComponentData(entity, new TriggerStaticData { - AnimSpeed = data.AnimSpeed, - Radius = data.Radius, - Shape = data.Shape, + AnimSpeed = Data.AnimSpeed, + Radius = Data.Radius, + Shape = Data.Shape, TableScaleZ = table.GetScaleZ() }); @@ -76,28 +76,28 @@ public void LinkChild(IItemAuthoring item) public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; - public override Vector3 GetEditorPosition() => data.Center.ToUnityVector3(0f); + public override Vector3 GetEditorPosition() => Data.Center.ToUnityVector3(0f); public override void SetEditorPosition(Vector3 pos) { - if (data == null || data.DragPoints.Length == 0) { + if (Data == null || Data.DragPoints.Length == 0) { return; } - var diff = pos.ToVertex3D().Sub(data.Center); - foreach (var pt in data.DragPoints) { + var diff = pos.ToVertex3D().Sub(Data.Center); + foreach (var pt in Data.DragPoints) { pt.Center = pt.Center.Add(new Vertex3D(diff.X, diff.Y, 0f)); } - data.Center = pos.ToVertex2Dxy(); + Data.Center = pos.ToVertex2Dxy(); } public override ItemDataTransformType EditorRotationType => ItemDataTransformType.OneD; - public override Vector3 GetEditorRotation() => new Vector3(data.Rotation, 0f, 0f); - public override void SetEditorRotation(Vector3 rot) => data.Rotation = rot.x; + public override Vector3 GetEditorRotation() => new Vector3(Data.Rotation, 0f, 0f); + public override void SetEditorRotation(Vector3 rot) => Data.Rotation = rot.x; //IDragPointsEditable public bool DragPointEditEnabled { get; set; } - public DragPointData[] GetDragPoints() => data.DragPoints; - public void SetDragPoints(DragPointData[] dragPoints) { data.DragPoints = dragPoints; } - public Vector3 GetEditableOffset() => new Vector3(-data.Center.X, -data.Center.Y, 0.0f); + public DragPointData[] GetDragPoints() => Data.DragPoints; + public void SetDragPoints(DragPointData[] dragPoints) { Data.DragPoints = dragPoints; } + public Vector3 GetEditableOffset() => new Vector3(-Data.Center.X, -Data.Center.Y, 0.0f); public Vector3 GetDragPointOffset(float ratio) => Vector3.zero; public bool PointsAreLooping() => true; public IEnumerable GetDragPointExposition() => new[] { DragPointExposure.Smooth, DragPointExposure.SlingShot }; From 4a23a93c57419228091e9ef9ca92eecb6843106b Mon Sep 17 00:00:00 2001 From: freezy Date: Sun, 27 Sep 2020 23:52:52 +0200 Subject: [PATCH 027/124] editor: Fix data handling for sub components. --- .../VPT/ItemColliderAuthoring.cs | 68 ++++++++++++++++--- 1 file changed, 60 insertions(+), 8 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs index 739706b0d..dd6ed4617 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT; @@ -25,23 +26,57 @@ public abstract class ItemColliderAuthoring : ItemAuth where TItem : Item, IHittable, IRenderable where TAuthoring : ItemAuthoring { - public override TData Data => _data ?? (_data = FindData()); + /// + /// We're in a sub component here, so this will: + /// 1. Check if is set (e.g. it's a serialized item) + /// 2. Check if is set (e.g. the cached reference to the main component's data) + /// 3. Find the main component in the hierarchy and return its data. + /// + public override TData Data => GetData(); + /// + /// Since we're in a sub component, we don't instantiate the item, but + /// look for the main component and retrieve the item from there (which + /// will instantiate it itself if necessary). + /// + /// + /// + /// If no main component found, this yields to `null`, and in this case + /// the component is somewhere in the hierarchy where it doesn't make + /// sense, and a warning should be printed. + /// public override TItem Item => _item ?? (_item = FindItem()); + /// + /// The cached reference to the data of the main component, so we + /// don't have to find it on every access. + /// + [NonSerialized] + private TData _dataRef; + + protected override string[] Children => new string[0]; + public IItemAuthoring SetItem(TItem item, RenderObjectGroup rog) { + _item = item; _data = item.Data; + _dataRef = item.Data; name = rog.ComponentName + " (collider)"; return this; } - protected override string[] Children => new string[0]; - - private TItem FindItem() + private TData GetData() { - var ac = FindParentAuthoring(); - return ac != null ? ac.Item : null; + if (_data != null) { + return _data; + } + + if (_dataRef != null) { + return _dataRef; + } + + _dataRef = FindData(); + return _dataRef; } private TData FindData() @@ -50,15 +85,32 @@ private TData FindData() return ac != null ? ac.Data : null; } + private TItem FindItem() + { + var ac = FindParentAuthoring(); + return ac != null ? ac.Item : null; + } + private TAuthoring FindParentAuthoring() { var go = gameObject; + + // search on current game object var ac = go.GetComponent(); - if (ac == null && go.transform.parent != null) { + if (ac != null) { + return ac; + } + + // search on parent + if (go.transform.parent != null) { ac = go.transform.parent.GetComponent(); } + if (ac != null) { + return ac; + } - if (ac == null && go.transform.parent.transform.parent != null) { + // search on grand parent + if (go.transform.parent.transform.parent != null) { ac = go.transform.parent.transform.parent.GetComponent(); } From 20c1d58bc7e62455e0beeb0bef93f1f653adf0b3 Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 28 Sep 2020 00:08:28 +0200 Subject: [PATCH 028/124] editor: Don't cache data references for collider authoring components. --- .../VPT/ItemColliderInspector.cs | 1 + .../VPT/ItemColliderAuthoring.cs | 42 +++++++------------ 2 files changed, 15 insertions(+), 28 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs index 4c60df7cc..5bc993691 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using UnityEditor; using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs index dd6ed4617..07437e08d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -using System; using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT; @@ -27,12 +26,18 @@ public abstract class ItemColliderAuthoring : ItemAuth where TAuthoring : ItemAuthoring { /// - /// We're in a sub component here, so this will: - /// 1. Check if is set (e.g. it's a serialized item) - /// 2. Check if is set (e.g. the cached reference to the main component's data) - /// 3. Find the main component in the hierarchy and return its data. + /// We're in a sub component here, so in order to retrieve the data, + /// this will: + /// 1. Check if is set (e.g. it's a serialized item) + /// 2. Find the main component in the hierarchy and return its data. /// - public override TData Data => GetData(); + /// + /// + /// We deliberately don't cache this, because if we do we need to find + /// a way to invalidate the cache in case the game object gets + /// re-attached to another parent. + /// + public override TData Data => _data ?? FindData(); /// /// Since we're in a sub component, we don't instantiate the item, but @@ -45,14 +50,10 @@ public abstract class ItemColliderAuthoring : ItemAuth /// the component is somewhere in the hierarchy where it doesn't make /// sense, and a warning should be printed. /// - public override TItem Item => _item ?? (_item = FindItem()); + public override TItem Item => _item ?? FindItem(); - /// - /// The cached reference to the data of the main component, so we - /// don't have to find it on every access. - /// - [NonSerialized] - private TData _dataRef; + public bool ShowColliderMesh; + public bool ShowAabbs; protected override string[] Children => new string[0]; @@ -60,25 +61,10 @@ public IItemAuthoring SetItem(TItem item, RenderObjectGroup rog) { _item = item; _data = item.Data; - _dataRef = item.Data; name = rog.ComponentName + " (collider)"; return this; } - private TData GetData() - { - if (_data != null) { - return _data; - } - - if (_dataRef != null) { - return _dataRef; - } - - _dataRef = FindData(); - return _dataRef; - } - private TData FindData() { var ac = FindParentAuthoring(); From 7bbc372e912aa143b21324d4244ea375dc12b8ca Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 28 Sep 2020 00:19:45 +0200 Subject: [PATCH 029/124] editor: Move collider gizmos to collider authoring. --- .../VPT/ItemColliderInspector.cs | 44 ++++ .../VPT/Rubber/RubberColliderInspector.cs | 2 + .../VPT/Surface/SurfaceColliderInspector.cs | 2 + .../VPT/Flipper/FlipperAuthoring.cs | 4 +- .../VisualPinball.Unity/VPT/ItemAuthoring.cs | 197 ----------------- .../VPT/ItemColliderAuthoring.cs | 203 ++++++++++++++++++ .../VPT/Surface/SurfaceAuthoring.cs | 1 - 7 files changed, 253 insertions(+), 200 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs index 5bc993691..1ec2577bf 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs @@ -14,6 +14,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +// ReSharper disable AssignmentInConditionalExpression + +using System; using UnityEditor; using UnityEngine; using VisualPinball.Engine.Game; @@ -34,6 +37,47 @@ public TData Data { } } + private bool _foldoutSceneView = true; + + protected override void OnEnable() + { + if (target is TColliderAuthoring mb) { + mb.ShowGizmos = true; + } + base.OnEnable(); + } + + private void OnDestroy() + { + if (target is TColliderAuthoring mb) { + mb.ShowGizmos = false; + } + } + + public override void OnInspectorGUI() + { + var mb = target as TColliderAuthoring; + if (mb == null) { + return; + } + + if (_foldoutSceneView = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutSceneView, "Scene View")) { + + var showAabbs = EditorGUILayout.Toggle("Show Bounding Boxes", mb.ShowAabbs); + var refresh = showAabbs == mb.ShowAabbs; + mb.ShowAabbs = showAabbs; + + var showColliders = EditorGUILayout.Toggle("Show Colliders", mb.ShowColliderMesh); + refresh = refresh || showColliders == mb.ShowColliderMesh; + mb.ShowColliderMesh = showColliders; + + if (refresh) { + EditorWindow.GetWindow().Repaint(); + } + } + EditorGUILayout.EndFoldoutHeaderGroup(); + } + protected void NoDataPanel() { // todo add more details diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs index 5f27f6989..cbdf5976e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs @@ -63,6 +63,8 @@ public override void OnInspectorGUI() } EditorGUI.EndDisabledGroup(); + + base.OnInspectorGUI(); } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs index 808f80888..6deaf80b0 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs @@ -77,6 +77,8 @@ public override void OnInspectorGUI() EditorGUILayout.EndFoldoutHeaderGroup(); EditorGUI.EndDisabledGroup(); + + base.OnInspectorGUI(); } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs index 103d4797c..053d57550 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs @@ -99,9 +99,9 @@ public override void SetEditorScale(Vector3 scale) Data.Height = scale.z; } - protected override void OnDrawGizmosSelected() + protected void OnDrawGizmosSelected() { - base.OnDrawGizmosSelected(); + //base.OnDrawGizmosSelected(); // draw end position mesh var mfs = GetComponentsInChildren(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs index 54a7b2c2a..a05345ecf 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs @@ -24,15 +24,8 @@ using Unity.Entities; using UnityEngine; using VisualPinball.Engine.Game; -using VisualPinball.Engine.Math; -using VisualPinball.Engine.Physics; using VisualPinball.Engine.VPT; -using VisualPinball.Engine.VPT.Flipper; -using VisualPinball.Engine.VPT.Gate; -using VisualPinball.Engine.VPT.Plunger; -using VisualPinball.Engine.VPT.Spinner; using VisualPinball.Engine.VPT.Table; -using Color = UnityEngine.Color; using Logger = NLog.Logger; namespace VisualPinball.Unity @@ -227,39 +220,6 @@ protected virtual void OnDrawGizmos() } } - protected virtual void OnDrawGizmosSelected() - { - var isColliderComponent = this is IItemColliderAuthoring; - if (isColliderComponent) { - var ltw = transform.GetComponentInParent().gameObject.transform.localToWorldMatrix; - - // todo remove check because IItemColliderAuthoring should only be on IHittables - if (Item is IHittable hittable) { - hittable.Init(Table); - var hits = hittable.GetHitShapes(); - - // new hittable selected? - if (hittable != PhysicsDebug.SelectedHittable) { - PhysicsDebug.SelectedCollider = hits.Length == 1 ? 0 : -1; - PhysicsDebug.SelectedHittable = hittable; - PhysicsDebug.OnItemSelected(hittable); - } - - // draw aabbs and colliders - for (var i = 0; i < hits.Length; i++) { - var hit = hits[i]; - if (PhysicsDebug.ShowAabbs) { - hit.CalcHitBBox(); - DrawAabb(ltw, hit.HitBBox, i == PhysicsDebug.SelectedCollider); - } - //if (PhysicsDebug.ShowColliders && isColliderComponent) { - DrawCollider(ltw, hit, i == PhysicsDebug.SelectedCollider); - //} - } - } - } - } - private static void UpdateMesh(string childName, GameObject go, RenderObjectGroup rog, TableAuthoring table) { var mr = go.GetComponent(); @@ -284,163 +244,6 @@ private static void UpdateMesh(string childName, GameObject go, RenderObjectGrou } } - #region Physics Debug - - private static void DrawAabb(Matrix4x4 ltw, Rect3D aabb, bool isSelected) - { - var p00 = ltw.MultiplyPoint(new Vector3( aabb.Left, aabb.Top, aabb.ZHigh)); - var p01 = ltw.MultiplyPoint(new Vector3(aabb.Left, aabb.Bottom, aabb.ZHigh)); - var p02 = ltw.MultiplyPoint(new Vector3(aabb.Right, aabb.Bottom, aabb.ZHigh)); - var p03 = ltw.MultiplyPoint(new Vector3(aabb.Right, aabb.Top, aabb.ZHigh)); - - var p10 = ltw.MultiplyPoint(new Vector3( aabb.Left, aabb.Top, aabb.ZLow)); - var p11 = ltw.MultiplyPoint(new Vector3(aabb.Left, aabb.Bottom, aabb.ZLow)); - var p12 = ltw.MultiplyPoint(new Vector3(aabb.Right, aabb.Bottom, aabb.ZLow)); - var p13 = ltw.MultiplyPoint(new Vector3(aabb.Right, aabb.Top, aabb.ZLow)); - - Gizmos.color = isSelected ? PhysicsDebug.SelectedAabbColor : PhysicsDebug.AabbColor; - Gizmos.DrawLine(p00, p01); - Gizmos.DrawLine(p01, p02); - Gizmos.DrawLine(p02, p03); - Gizmos.DrawLine(p03, p00); - - Gizmos.DrawLine(p10, p11); - Gizmos.DrawLine(p11, p12); - Gizmos.DrawLine(p12, p13); - Gizmos.DrawLine(p13, p10); - - Gizmos.DrawLine(p00, p10); - Gizmos.DrawLine(p01, p11); - Gizmos.DrawLine(p02, p12); - Gizmos.DrawLine(p03, p13); - } - - private void DrawCollider(Matrix4x4 ltw, HitObject hitObject, bool isSelected) - { - Gizmos.color = isSelected ? PhysicsDebug.SelectedColliderColor : PhysicsDebug.ColliderColor; - switch (hitObject) { - - case HitPoint hitPoint: { - Gizmos.DrawSphere(ltw.MultiplyPoint(hitPoint.P.ToUnityVector3()), 0.001f); - break; - } - - case LineSeg lineSeg: { - const int num = 10; - var d = (lineSeg.HitBBox.ZHigh - lineSeg.HitBBox.ZLow) / num; - for (var i = 0; i < num; i++) { - Gizmos.DrawLine( - ltw.MultiplyPoint(lineSeg.V1.ToUnityVector3(lineSeg.HitBBox.ZLow + i * d)), - ltw.MultiplyPoint(lineSeg.V2.ToUnityVector3(lineSeg.HitBBox.ZLow + i * d)) - ); - } - break; - } - - case HitLine3D hitLine3D: { - Gizmos.DrawLine( - ltw.MultiplyPoint(hitLine3D.V1.ToUnityVector3()), - ltw.MultiplyPoint(hitLine3D.V2.ToUnityVector3()) - ); - break; - } - - case HitLineZ hitLineZ: { - Gizmos.DrawLine( - ltw.MultiplyPoint(hitLineZ.Xy.ToUnityVector3(hitLineZ.HitBBox.ZLow)), - ltw.MultiplyPoint(hitLineZ.Xy.ToUnityVector3(hitLineZ.HitBBox.ZHigh)) - ); - break; - } - - case HitTriangle hitTriangle: { - Gizmos.DrawLine( - ltw.MultiplyPoint(hitTriangle.Rgv[0].ToUnityVector3()), - ltw.MultiplyPoint(hitTriangle.Rgv[1].ToUnityVector3()) - ); - Gizmos.DrawLine( - ltw.MultiplyPoint(hitTriangle.Rgv[1].ToUnityVector3()), - ltw.MultiplyPoint(hitTriangle.Rgv[2].ToUnityVector3()) - ); - Gizmos.DrawLine( - ltw.MultiplyPoint(hitTriangle.Rgv[2].ToUnityVector3()), - ltw.MultiplyPoint(hitTriangle.Rgv[0].ToUnityVector3()) - ); - break; - } - - case HitCircle hitCircle: { - const int num = 20; - var d = (hitCircle.HitBBox.ZHigh - hitCircle.HitBBox.ZLow) / num; - for (var i = 0; i < num; i++) { - GizmoDrawCircle(ltw, hitCircle.Center.ToUnityVector3(hitCircle.HitBBox.ZLow + i * d), hitCircle.Radius); - } - break; - } - - case GateHit gateHit: { - DrawCollider(ltw, gateHit.LineSeg0, isSelected); - DrawCollider(ltw, gateHit.LineSeg1, isSelected); - break; - } - - case SpinnerHit spinnerHit: { - DrawCollider(ltw, spinnerHit.LineSeg0, isSelected); - DrawCollider(ltw, spinnerHit.LineSeg1, isSelected); - break; - } - - case FlipperHit flipperHit: { - var mfs = GetComponentsInChildren(); - foreach (var mf in mfs) { - if (mf.name == "Rubber") { - var t = mf.transform; - Gizmos.DrawWireMesh(mf.sharedMesh, t.position, t.rotation, t.lossyScale); - break; - } - } - break; - } - - case PlungerHit plungerHit: { - DrawCollider(ltw, plungerHit.LineSegBase, isSelected); - DrawCollider(ltw, plungerHit.LineSegEnd, isSelected); - DrawCollider(ltw, plungerHit.LineSegSide[0], isSelected); - DrawCollider(ltw, plungerHit.LineSegSide[1], isSelected); - DrawCollider(ltw, plungerHit.JointBase[0], isSelected); - DrawCollider(ltw, plungerHit.JointBase[1], isSelected); - DrawCollider(ltw, plungerHit.JointEnd[0], isSelected); - DrawCollider(ltw, plungerHit.JointEnd[1], isSelected); - break; - } - - } - } - - private static void GizmoDrawCircle(Matrix4x4 ltw, Vector3 center, float radius) - { - var theta = 0f; - var x = radius * MathF.Cos(theta); - var y = radius * MathF.Sin(theta); - var pos = center + new Vector3(x, y, 0f); - var lastPos = pos; - for (theta = 0.1f; theta < MathF.PI * 2; theta += 0.1f){ - x = radius * MathF.Cos(theta); - y = radius * MathF.Sin(theta); - var newPos = center + new Vector3(x, y, 0); - Gizmos.DrawLine( - ltw.MultiplyPoint(pos), - ltw.MultiplyPoint(newPos) - ); - pos = newPos; - } - Gizmos.DrawLine(pos, lastPos); - } - - - #endregion - - private List GetMembersWithAttribute() where TAttr: Attribute { List members = new List(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs index 07437e08d..9311a1a7c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs @@ -14,9 +14,16 @@ // 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.Game; +using VisualPinball.Engine.Math; +using VisualPinball.Engine.Physics; using VisualPinball.Engine.VPT; +using VisualPinball.Engine.VPT.Flipper; +using VisualPinball.Engine.VPT.Gate; +using VisualPinball.Engine.VPT.Plunger; +using VisualPinball.Engine.VPT.Spinner; namespace VisualPinball.Unity { @@ -52,6 +59,8 @@ public abstract class ItemColliderAuthoring : ItemAuth /// public override TItem Item => _item ?? FindItem(); + [NonSerialized] + public bool ShowGizmos; public bool ShowColliderMesh; public bool ShowAabbs; @@ -73,6 +82,13 @@ private TData FindData() private TItem FindItem() { + // if _data is set then it's an item of its own and we don't need to find the parent + if (_data != null) { + _item = InstantiateItem(_data); + return _item; + } + + // otherwise retrieve from parent var ac = FindParentAuthoring(); return ac != null ? ac.Item : null; } @@ -106,5 +122,192 @@ private TAuthoring FindParentAuthoring() return ac; } + + private void OnDrawGizmosSelected() + { + if (!ShowGizmos || !ShowAabbs && !ShowColliderMesh) { + return; + } + + // todo remove check because IItemColliderAuthoring should only be on IHittables + if (Item is IHittable hittable) { + var ltw = transform.GetComponentInParent().gameObject.transform.localToWorldMatrix; + hittable.Init(Table); + var hits = hittable.GetHitShapes(); + + // new hittable selected? + if (hittable != PhysicsDebug.SelectedHittable) { + PhysicsDebug.SelectedCollider = hits.Length == 1 ? 0 : -1; + PhysicsDebug.SelectedHittable = hittable; + PhysicsDebug.OnItemSelected(hittable); + } + + // draw aabbs and colliders + for (var i = 0; i < hits.Length; i++) { + var hit = hits[i]; + if (ShowAabbs) { + hit.CalcHitBBox(); + DrawAabb(ltw, hit.HitBBox, i == PhysicsDebug.SelectedCollider); + } + if (ShowColliderMesh) { + DrawCollider(ltw, hit, i == PhysicsDebug.SelectedCollider); + } + } + } + } + + #region Collider Gizmos + + private static void DrawAabb(Matrix4x4 ltw, Rect3D aabb, bool isSelected) + { + var p00 = ltw.MultiplyPoint(new Vector3( aabb.Left, aabb.Top, aabb.ZHigh)); + var p01 = ltw.MultiplyPoint(new Vector3(aabb.Left, aabb.Bottom, aabb.ZHigh)); + var p02 = ltw.MultiplyPoint(new Vector3(aabb.Right, aabb.Bottom, aabb.ZHigh)); + var p03 = ltw.MultiplyPoint(new Vector3(aabb.Right, aabb.Top, aabb.ZHigh)); + + var p10 = ltw.MultiplyPoint(new Vector3( aabb.Left, aabb.Top, aabb.ZLow)); + var p11 = ltw.MultiplyPoint(new Vector3(aabb.Left, aabb.Bottom, aabb.ZLow)); + var p12 = ltw.MultiplyPoint(new Vector3(aabb.Right, aabb.Bottom, aabb.ZLow)); + var p13 = ltw.MultiplyPoint(new Vector3(aabb.Right, aabb.Top, aabb.ZLow)); + + Gizmos.color = isSelected ? PhysicsDebug.SelectedAabbColor : PhysicsDebug.AabbColor; + Gizmos.DrawLine(p00, p01); + Gizmos.DrawLine(p01, p02); + Gizmos.DrawLine(p02, p03); + Gizmos.DrawLine(p03, p00); + + Gizmos.DrawLine(p10, p11); + Gizmos.DrawLine(p11, p12); + Gizmos.DrawLine(p12, p13); + Gizmos.DrawLine(p13, p10); + + Gizmos.DrawLine(p00, p10); + Gizmos.DrawLine(p01, p11); + Gizmos.DrawLine(p02, p12); + Gizmos.DrawLine(p03, p13); + } + + private void DrawCollider(Matrix4x4 ltw, HitObject hitObject, bool isSelected) + { + Gizmos.color = isSelected ? PhysicsDebug.SelectedColliderColor : PhysicsDebug.ColliderColor; + switch (hitObject) { + + case HitPoint hitPoint: { + Gizmos.DrawSphere(ltw.MultiplyPoint(hitPoint.P.ToUnityVector3()), 0.001f); + break; + } + + case LineSeg lineSeg: { + const int num = 10; + var d = (lineSeg.HitBBox.ZHigh - lineSeg.HitBBox.ZLow) / num; + for (var i = 0; i < num; i++) { + Gizmos.DrawLine( + ltw.MultiplyPoint(lineSeg.V1.ToUnityVector3(lineSeg.HitBBox.ZLow + i * d)), + ltw.MultiplyPoint(lineSeg.V2.ToUnityVector3(lineSeg.HitBBox.ZLow + i * d)) + ); + } + break; + } + + case HitLine3D hitLine3D: { + Gizmos.DrawLine( + ltw.MultiplyPoint(hitLine3D.V1.ToUnityVector3()), + ltw.MultiplyPoint(hitLine3D.V2.ToUnityVector3()) + ); + break; + } + + case HitLineZ hitLineZ: { + Gizmos.DrawLine( + ltw.MultiplyPoint(hitLineZ.Xy.ToUnityVector3(hitLineZ.HitBBox.ZLow)), + ltw.MultiplyPoint(hitLineZ.Xy.ToUnityVector3(hitLineZ.HitBBox.ZHigh)) + ); + break; + } + + case HitTriangle hitTriangle: { + Gizmos.DrawLine( + ltw.MultiplyPoint(hitTriangle.Rgv[0].ToUnityVector3()), + ltw.MultiplyPoint(hitTriangle.Rgv[1].ToUnityVector3()) + ); + Gizmos.DrawLine( + ltw.MultiplyPoint(hitTriangle.Rgv[1].ToUnityVector3()), + ltw.MultiplyPoint(hitTriangle.Rgv[2].ToUnityVector3()) + ); + Gizmos.DrawLine( + ltw.MultiplyPoint(hitTriangle.Rgv[2].ToUnityVector3()), + ltw.MultiplyPoint(hitTriangle.Rgv[0].ToUnityVector3()) + ); + break; + } + + case HitCircle hitCircle: { + const int num = 20; + var d = (hitCircle.HitBBox.ZHigh - hitCircle.HitBBox.ZLow) / num; + for (var i = 0; i < num; i++) { + GizmoDrawCircle(ltw, hitCircle.Center.ToUnityVector3(hitCircle.HitBBox.ZLow + i * d), hitCircle.Radius); + } + break; + } + + case GateHit gateHit: { + DrawCollider(ltw, gateHit.LineSeg0, isSelected); + DrawCollider(ltw, gateHit.LineSeg1, isSelected); + break; + } + + case SpinnerHit spinnerHit: { + DrawCollider(ltw, spinnerHit.LineSeg0, isSelected); + DrawCollider(ltw, spinnerHit.LineSeg1, isSelected); + break; + } + + case FlipperHit flipperHit: { + var mfs = GetComponentsInChildren(); + foreach (var mf in mfs) { + if (mf.name == "Rubber") { + var t = mf.transform; + Gizmos.DrawWireMesh(mf.sharedMesh, t.position, t.rotation, t.lossyScale); + break; + } + } + break; + } + + case PlungerHit plungerHit: { + DrawCollider(ltw, plungerHit.LineSegBase, isSelected); + DrawCollider(ltw, plungerHit.LineSegEnd, isSelected); + DrawCollider(ltw, plungerHit.LineSegSide[0], isSelected); + DrawCollider(ltw, plungerHit.LineSegSide[1], isSelected); + DrawCollider(ltw, plungerHit.JointBase[0], isSelected); + DrawCollider(ltw, plungerHit.JointBase[1], isSelected); + DrawCollider(ltw, plungerHit.JointEnd[0], isSelected); + DrawCollider(ltw, plungerHit.JointEnd[1], isSelected); + break; + } + } + } + + private static void GizmoDrawCircle(Matrix4x4 ltw, Vector3 center, float radius) + { + var theta = 0f; + var x = radius * MathF.Cos(theta); + var y = radius * MathF.Sin(theta); + var pos = center + new Vector3(x, y, 0f); + var lastPos = pos; + for (theta = 0.1f; theta < MathF.PI * 2; theta += 0.1f){ + x = radius * MathF.Cos(theta); + y = radius * MathF.Sin(theta); + var newPos = center + new Vector3(x, y, 0); + Gizmos.DrawLine( + ltw.MultiplyPoint(pos), + ltw.MultiplyPoint(newPos) + ); + pos = newPos; + } + Gizmos.DrawLine(pos, lastPos); + } + + #endregion } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs index 5712ba516..df81c4005 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs @@ -25,7 +25,6 @@ using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; -using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Surface; namespace VisualPinball.Unity From ac7dacfea3960ab5d8811ede6fac4b35f30de202 Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 28 Sep 2020 00:36:25 +0200 Subject: [PATCH 030/124] editor: Move physics debug window into collider inspector. --- .../Physics/PhysicsWindow.cs | 115 ------------------ .../Physics/PhysicsWindow.cs.meta | 11 -- .../VPT/ItemColliderInspector.cs | 69 +++++++---- .../VPT/Rubber/RubberColliderInspector.cs | 1 + .../VisualPinball.Unity/VPT/ItemAuthoring.cs | 42 ++----- .../VPT/ItemColliderAuthoring.cs | 66 ++++++---- .../VPT/Rubber/RubberExtensions.cs | 2 +- .../VPT/Surface/SurfaceExtensions.cs | 3 +- 8 files changed, 99 insertions(+), 210 deletions(-) delete mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Physics/PhysicsWindow.cs delete mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Physics/PhysicsWindow.cs.meta diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Physics/PhysicsWindow.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Physics/PhysicsWindow.cs deleted file mode 100644 index c3a3d2e84..000000000 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Physics/PhysicsWindow.cs +++ /dev/null @@ -1,115 +0,0 @@ -// 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; -using System.Linq; -using UnityEditor; -using UnityEngine; -using VisualPinball.Engine.Physics; - -namespace VisualPinball.Unity.Editor.Physics -{ - public class PhysicsWindow : EditorWindow - { - public static PhysicsWindow Window; - - private Vector2 _scrollPos; - - private IHittableAuthoring _currentHittable; - private string[] _currentColliders; - - [MenuItem("Visual Pinball/Physics Debug", false, 105)] - public static void ShowWindow() - { - Window = GetWindow("Physics Debug"); - Window.Show(); - } - - private void OnEnable() - { - PhysicsDebug.ShowAabbs = true; - PhysicsDebug.ItemSelected += OnItemSelected; - } - - - private void OnDisable() - { - PhysicsDebug.ShowAabbs = false; - PhysicsDebug.ItemSelected -= OnItemSelected; - } - - private void OnItemSelected(object sender, EventArgs e) - { - Repaint(); - } - - private void OnGUI() - { - - GUILayout.BeginHorizontal(); - - var showAabbs = EditorGUILayout.Toggle("Show Bounding Boxes", PhysicsDebug.ShowAabbs); - var refresh = showAabbs == PhysicsDebug.ShowAabbs; - PhysicsDebug.ShowAabbs = showAabbs; - - var showColliders = EditorGUILayout.Toggle("Show Colliders", PhysicsDebug.ShowColliders); - refresh = refresh || showColliders == PhysicsDebug.ShowColliders; - PhysicsDebug.ShowColliders = showColliders; - - GUILayout.EndHorizontal(); - GUILayout.Space(4); - - var selectedObject = Selection.activeObject as GameObject; - var hittableObj = selectedObject != null ? selectedObject.GetComponent() : null; - if (hittableObj != null) { - - var headerStyle = new GUIStyle(EditorStyles.largeLabel) { - fontStyle = FontStyle.Bold - }; - GUILayout.Label(selectedObject.name, headerStyle); - GUILayout.Space(2f); - - if (_currentHittable != hittableObj) { - var hitObjects = hittableObj.Hittable.GetHitShapes() ?? new HitObject[0]; - _currentColliders = hitObjects - .Where(h => h != null) - .Select((h, i) => $"[{i}] {h.GetType().Name} ({h.ObjType})") - .ToArray(); - - if (_currentColliders.Length == 0) { - GUILayout.Label("No colliders for this item."); - } - } - - _currentHittable = hittableObj; - _scrollPos = EditorGUILayout.BeginScrollView(_scrollPos, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); - var selectedCollider = GUILayout.SelectionGrid(PhysicsDebug.SelectedCollider, _currentColliders, 1); - refresh = refresh || selectedCollider == PhysicsDebug.SelectedCollider; - PhysicsDebug.SelectedCollider = selectedCollider; - EditorGUILayout.EndScrollView(); - - if (refresh) { - EditorWindow view = GetWindow(); - view.Repaint(); - } - - } else { - PhysicsDebug.SelectedCollider = -1; - GUILayout.Label("No collidable element selected."); - } - } - } -} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Physics/PhysicsWindow.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Physics/PhysicsWindow.cs.meta deleted file mode 100644 index 05949d26f..000000000 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Physics/PhysicsWindow.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 21294fb7194adee4f8fec08844ef22c5 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs index 1ec2577bf..8e7fc1ce9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs @@ -16,10 +16,11 @@ // ReSharper disable AssignmentInConditionalExpression -using System; +using System.Linq; using UnityEditor; using UnityEngine; using VisualPinball.Engine.Game; +using VisualPinball.Engine.Physics; using VisualPinball.Engine.VPT; namespace VisualPinball.Unity.Editor @@ -30,52 +31,78 @@ public class ItemColliderInspector where TItem : Item, IHittable, IRenderable where TAuthoring : ItemAuthoring { - public TData Data { - get { - var mb = target as TColliderAuthoring; - return mb == null ? null : mb.Data; - } - } + private TColliderAuthoring _colliderAuthoring; + + protected TData Data => _colliderAuthoring == null ? null : _colliderAuthoring.Data; private bool _foldoutSceneView = true; + private bool _foldoutColliders; + private string[] _currentColliders; + private Vector2 _scrollPos; protected override void OnEnable() { - if (target is TColliderAuthoring mb) { - mb.ShowGizmos = true; + _colliderAuthoring = target as TColliderAuthoring; + if (_colliderAuthoring != null) { + _colliderAuthoring.ShowGizmos = true; } base.OnEnable(); } private void OnDestroy() { - if (target is TColliderAuthoring mb) { - mb.ShowGizmos = false; + if (_colliderAuthoring != null) { + _colliderAuthoring.ShowGizmos = false; } } public override void OnInspectorGUI() { - var mb = target as TColliderAuthoring; - if (mb == null) { + if (_colliderAuthoring == null) { return; } + var refresh = false; + + // scene view toggles if (_foldoutSceneView = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutSceneView, "Scene View")) { - var showAabbs = EditorGUILayout.Toggle("Show Bounding Boxes", mb.ShowAabbs); - var refresh = showAabbs == mb.ShowAabbs; - mb.ShowAabbs = showAabbs; + var showAabbs = EditorGUILayout.Toggle("Show Bounding Boxes", _colliderAuthoring.ShowAabbs); + refresh = showAabbs == _colliderAuthoring.ShowAabbs; + _colliderAuthoring.ShowAabbs = showAabbs; - var showColliders = EditorGUILayout.Toggle("Show Colliders", mb.ShowColliderMesh); - refresh = refresh || showColliders == mb.ShowColliderMesh; - mb.ShowColliderMesh = showColliders; + var showColliders = EditorGUILayout.Toggle("Show Colliders", _colliderAuthoring.ShowColliderMesh); + refresh = refresh || showColliders == _colliderAuthoring.ShowColliderMesh; + _colliderAuthoring.ShowColliderMesh = showColliders; + } + EditorGUILayout.EndFoldoutHeaderGroup(); - if (refresh) { - EditorWindow.GetWindow().Repaint(); + // individual collider list + if (_foldoutColliders = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColliders, "Colliders")) { + + var hitObjects = _colliderAuthoring.HitObjects ?? new HitObject[0]; + _currentColliders = hitObjects + .Where(h => h != null) + .Select((h, i) => $"[{i}] {h.GetType().Name} ({h.ObjType})") + .ToArray(); + + if (_currentColliders.Length == 0) { + GUILayout.Label("No colliders for this item."); } + + _scrollPos = EditorGUILayout.BeginScrollView(_scrollPos, GUILayout.ExpandWidth(true), + GUILayout.ExpandHeight(true)); + var selectedCollider = GUILayout.SelectionGrid(_colliderAuthoring.SelectedCollider, _currentColliders, 1); + refresh = refresh || selectedCollider == _colliderAuthoring.SelectedCollider; + _colliderAuthoring.SelectedCollider = selectedCollider; + EditorGUILayout.EndScrollView(); } EditorGUILayout.EndFoldoutHeaderGroup(); + + // refresh scene view manually + if (refresh) { + EditorWindow.GetWindow().Repaint(); + } } protected void NoDataPanel() diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs index cbdf5976e..6799c46d7 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs @@ -61,6 +61,7 @@ public override void OnInspectorGUI() ItemDataField("Scatter Angle", ref _rubberData.Scatter, false); EditorGUI.EndDisabledGroup(); } + EditorGUILayout.EndFoldoutHeaderGroup(); EditorGUI.EndDisabledGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs index a05345ecf..d202b3455 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs @@ -39,13 +39,14 @@ public abstract class ItemAuthoring : MonoBehaviour, IItemAuthorin ILayerableItemAuthoring where TData : ItemData where TItem : Item, IRenderable { /// - /// The serialized data. Having this set means it's a real game item - /// that ends up or is imported from game item in the VPX file. - /// - /// However, this can also be `null`, in which case the component only - /// deals with a sub set of the main component (collision, mesh generation, - /// or movement). + /// The serialized data, as written to the .vpx file. /// + /// + /// + /// This might be "empty" (since Unity can't serialize it as `null`), so + /// the component authoring classes keep a flag whether to read the data + /// from this field or retrieve it from the parent in the hierarchy. + /// [SerializeField] protected TData _data; @@ -265,33 +266,4 @@ private List GetMembersWithAttribute() where TAttr: Attribute public string EditorLayerName { get => _data.EditorLayerName; set => _data.EditorLayerName = value; } public bool EditorLayerVisibility { get => _data.EditorLayerVisibility; set => _data.EditorLayerVisibility = value; } } - - /// - /// The intermediate class through which the physics debug window communicates. - /// - public static class PhysicsDebug - { - public static bool ShowAabbs; - - public static Color AabbColor = new Color32(255, 0, 252, 8); - - public static Color SelectedAabbColor = new Color32(255, 0, 252, 255); - - public static bool ShowColliders; - - public static IHittable SelectedHittable; - - public static int SelectedCollider; - - public static Color ColliderColor = new Color32(0, 255, 75, 8); - - public static Color SelectedColliderColor = new Color32(0, 255, 75, 255); - - public static event EventHandler ItemSelected; - - internal static void OnItemSelected(IHittable hittable) - { - ItemSelected?.Invoke(hittable, EventArgs.Empty); - } - } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs index 9311a1a7c..2377e298e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs @@ -24,6 +24,7 @@ using VisualPinball.Engine.VPT.Gate; using VisualPinball.Engine.VPT.Plunger; using VisualPinball.Engine.VPT.Spinner; +using Color = UnityEngine.Color; namespace VisualPinball.Unity { @@ -44,7 +45,7 @@ public abstract class ItemColliderAuthoring : ItemAuth /// a way to invalidate the cache in case the game object gets /// re-attached to another parent. /// - public override TData Data => _data ?? FindData(); + public override TData Data => _isSubComponent ? FindData() : _data; /// /// Since we're in a sub component, we don't instantiate the item, but @@ -63,17 +64,35 @@ public abstract class ItemColliderAuthoring : ItemAuth public bool ShowGizmos; public bool ShowColliderMesh; public bool ShowAabbs; + [NonSerialized] + public int SelectedCollider = -1; + public HitObject[] HitObjects { get; private set; } + + [SerializeField] + private bool _isSubComponent; protected override string[] Children => new string[0]; + private static readonly Color AabbColor = new Color32(255, 0, 252, 8); + private static readonly Color SelectedAabbColor = new Color32(255, 0, 252, 255); + private static readonly Color ColliderColor = new Color32(0, 255, 75, 8); + private static readonly Color SelectedColliderColor = new Color32(0, 255, 75, 255); + public IItemAuthoring SetItem(TItem item, RenderObjectGroup rog) { _item = item; _data = item.Data; + _isSubComponent = false; name = rog.ComponentName + " (collider)"; return this; } + public void SetMainItem(TItem item) + { + _item = item; + _isSubComponent = true; + } + private TData FindData() { var ac = FindParentAuthoring(); @@ -83,7 +102,7 @@ private TData FindData() private TItem FindItem() { // if _data is set then it's an item of its own and we don't need to find the parent - if (_data != null) { + if (!_isSubComponent) { _item = InstantiateItem(_data); return _item; } @@ -129,29 +148,24 @@ private void OnDrawGizmosSelected() return; } - // todo remove check because IItemColliderAuthoring should only be on IHittables - if (Item is IHittable hittable) { - var ltw = transform.GetComponentInParent().gameObject.transform.localToWorldMatrix; - hittable.Init(Table); - var hits = hittable.GetHitShapes(); - - // new hittable selected? - if (hittable != PhysicsDebug.SelectedHittable) { - PhysicsDebug.SelectedCollider = hits.Length == 1 ? 0 : -1; - PhysicsDebug.SelectedHittable = hittable; - PhysicsDebug.OnItemSelected(hittable); - } + var item = Item; + if (item == null) { + return; + } - // draw aabbs and colliders - for (var i = 0; i < hits.Length; i++) { - var hit = hits[i]; - if (ShowAabbs) { - hit.CalcHitBBox(); - DrawAabb(ltw, hit.HitBBox, i == PhysicsDebug.SelectedCollider); - } - if (ShowColliderMesh) { - DrawCollider(ltw, hit, i == PhysicsDebug.SelectedCollider); - } + var ltw = transform.GetComponentInParent().gameObject.transform.localToWorldMatrix; + item.Init(Table); + HitObjects = item.GetHitShapes(); + + // draw aabbs and colliders + for (var i = 0; i < HitObjects.Length; i++) { + var hit = HitObjects[i]; + if (ShowAabbs) { + hit.CalcHitBBox(); + DrawAabb(ltw, hit.HitBBox, i == SelectedCollider); + } + if (ShowColliderMesh) { + DrawCollider(ltw, hit, i == SelectedCollider); } } } @@ -170,7 +184,7 @@ private static void DrawAabb(Matrix4x4 ltw, Rect3D aabb, bool isSelected) var p12 = ltw.MultiplyPoint(new Vector3(aabb.Right, aabb.Bottom, aabb.ZLow)); var p13 = ltw.MultiplyPoint(new Vector3(aabb.Right, aabb.Top, aabb.ZLow)); - Gizmos.color = isSelected ? PhysicsDebug.SelectedAabbColor : PhysicsDebug.AabbColor; + Gizmos.color = isSelected ? SelectedAabbColor : AabbColor; Gizmos.DrawLine(p00, p01); Gizmos.DrawLine(p01, p02); Gizmos.DrawLine(p02, p03); @@ -189,7 +203,7 @@ private static void DrawAabb(Matrix4x4 ltw, Rect3D aabb, bool isSelected) private void DrawCollider(Matrix4x4 ltw, HitObject hitObject, bool isSelected) { - Gizmos.color = isSelected ? PhysicsDebug.SelectedColliderColor : PhysicsDebug.ColliderColor; + Gizmos.color = isSelected ? SelectedColliderColor : ColliderColor; switch (hitObject) { case HitPoint hitPoint: { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs index 90b70e49f..0d673d22b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs @@ -31,7 +31,7 @@ public static MonoBehaviour SetupGameObject(this Engine.VPT.Rubber.Rubber rubber case RenderObjectGroup.ItemSubComponent.None: mb = obj.AddComponent().SetItem(rubber); - obj.AddComponent(); + obj.AddComponent().SetMainItem(rubber); break; case RenderObjectGroup.ItemSubComponent.Collider: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs index a999cc23e..1f7a4106b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs @@ -26,12 +26,13 @@ internal static class SurfaceExtensions public static MonoBehaviour SetupGameObject(this Engine.VPT.Surface.Surface surface, GameObject obj, RenderObjectGroup rog, MonoBehaviour mainMb) { + MonoBehaviour mb = null; switch (rog.SubComponent) { case RenderObjectGroup.ItemSubComponent.None: mb = obj.AddComponent().SetItem(surface); - obj.AddComponent(); + obj.AddComponent().SetMainItem(surface);; break; case RenderObjectGroup.ItemSubComponent.Collider: From 6d451ef6a706107dc8ec3ffbf3e29dd34e6e5da3 Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 28 Sep 2020 00:44:24 +0200 Subject: [PATCH 031/124] editor: Test moving children with parent. --- .../VPT/IItemColliderAuthoring.cs | 8 +++++-- .../VisualPinball.Unity/VPT/ItemAuthoring.cs | 10 +++++++++ .../VPT/ItemColliderAuthoring.cs | 1 + .../VPT/Rubber/RubberAuthoring.cs | 4 ++-- .../VPT/Surface/SurfaceAuthoring.cs | 5 ----- .../VPT/Surface/SurfaceColliderAuthoring.cs | 21 +++++++++++++++++++ 6 files changed, 40 insertions(+), 9 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs index 2bb6b49bf..2d2361742 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs @@ -1,7 +1,11 @@ -namespace VisualPinball.Unity +using UnityEngine; + +namespace VisualPinball.Unity { public interface IItemColliderAuthoring { - + bool IsSubComponent { get; } + + void SetEditorPosition(Vector3 pos); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs index d202b3455..a7987b294 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs @@ -195,6 +195,16 @@ protected void Convert(Entity entity, EntityManager dstManager) Item.Version = entity.Version; } + protected void SetEditorPositionChildren(Vector3 pos) + { + var children = GetComponentsInChildren(); + foreach (var child in children) + { + if (!child.IsSubComponent) { + child.SetEditorPosition(pos); + } + } + } public void LinkChild(IItemAuthoring childItem) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs index 2377e298e..fd035b314 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs @@ -70,6 +70,7 @@ public abstract class ItemColliderAuthoring : ItemAuth [SerializeField] private bool _isSubComponent; + public bool IsSubComponent => _isSubComponent; protected override string[] Children => new string[0]; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs index ff2bba133..1e65fb46b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs @@ -25,7 +25,6 @@ using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; -using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Rubber; namespace VisualPinball.Unity @@ -73,6 +72,7 @@ public override Vector3 GetEditorPosition() } public override void SetEditorPosition(Vector3 pos) { + SetEditorPositionChildren(pos); if (Data == null || Data.DragPoints.Length == 0) { return; } @@ -82,7 +82,7 @@ public override void SetEditorPosition(Vector3 pos) var diff = pos.ToVertex3D().Sub(Data.DragPoints[0].Center); diff.Z = 0f; Data.DragPoints[0].Center = pos.ToVertex3D(); - for (int i = 1; i < Data.DragPoints.Length; i++) { + for (var i = 1; i < Data.DragPoints.Length; i++) { var pt = Data.DragPoints[i]; pt.Center = pt.Center.Add(diff); } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs index df81c4005..949764022 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs @@ -64,11 +64,6 @@ public void RemoveHittableComponent() } } - public void LinkChild(IItemAuthoring item) - { - - } - public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() { if (Data == null || Data.DragPoints.Length == 0) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs index a5f84141a..90fea2444 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs @@ -23,5 +23,26 @@ namespace VisualPinball.Unity public class SurfaceColliderAuthoring : ItemColliderAuthoring { protected override Surface InstantiateItem(SurfaceData data) => new Surface(_data); + + public override Vector3 GetEditorPosition() { + if (Data == null || Data.DragPoints.Length == 0) { + return Vector3.zero; + } + return Data.DragPoints[0].Center.ToUnityVector3(); + } + + public override void SetEditorPosition(Vector3 pos) { + if (Data == null || Data.DragPoints.Length == 0) { + return; + } + + var diff = pos.ToVertex3D().Sub(Data.DragPoints[0].Center); + diff.Z = 0f; + Data.DragPoints[0].Center = pos.ToVertex3D(); + for (var i = 1; i < Data.DragPoints.Length; i++) { + var pt = Data.DragPoints[i]; + pt.Center = pt.Center.Add(diff); + } + } } } From 056eef2ba247e9f7f94aa496fac4ce10dbdea54f Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 28 Sep 2020 23:28:08 +0200 Subject: [PATCH 032/124] components: Add some documentation. --- .../creators-guide/editor/unity-components.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md diff --git a/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md b/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md new file mode 100644 index 000000000..261f1bb70 --- /dev/null +++ b/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md @@ -0,0 +1,19 @@ +# Unity Components + +When loading or creating a table in Unity, what you're creating is a hierarchy of [GameObjects](https://docs.unity3d.com/Manual/GameObjects.html). By default we create a level for every game item type, but you can arrange them however you want. + +In order to give the GameObjects behavior during gameplay, we add [Components](https://docs.unity3d.com/Manual/Components.html) onto them. VPE comes with large amount of Components that are used to define the gameplay of the table. + +> [!note] +> During runtime, VPE converts the game objects and components into Unity's [DOTS](https://unity.com/dots) elements. We use Components in the editor to define the game logic implemented in DOTS. That's also why we call them *Authoring Components*. + +If you've never heard about GameObjects or Components, we strong suggest you read through the links in the first two paragraphs, they are short, to the point, and better than what we could provide here. + +## Components vs Game Items + +In Visual Pinball, Components would be what you see in the options panel when you click on a game item. You'll typically find sections for physics behavior, rendering, and form and shape of the game item you're editing. Internally, all those section belong to the same game item. + +In VPE, we have separate Components for separate things. For example, a rubber might be visible on the playfield, so its GameObject has a *Rubber Mesh Component*. And it also collides with the ball, so there is a *Rubber Collision Component* as well. And of course it has a position and a name, which are part of what we call the "main component", in this case the *Rubber Component*. + +In general, you don't have to manually manage all this. When creating a rubber via the toolbox, the created GameObject will already have all the necessary components. + From 1c4cbb94a51f3d87c91dd2ff4178eee1fcc5056d Mon Sep 17 00:00:00 2001 From: freezy Date: Tue, 29 Sep 2020 00:06:15 +0200 Subject: [PATCH 033/124] components: Update documentation. --- .../creators-guide/editor/unity-components.md | 35 ++++++++++++++++--- .../Documentation~/creators-guide/toc.yml | 2 ++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md b/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md index 261f1bb70..955be6b65 100644 --- a/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md +++ b/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md @@ -5,15 +5,40 @@ When loading or creating a table in Unity, what you're creating is a hierarchy o In order to give the GameObjects behavior during gameplay, we add [Components](https://docs.unity3d.com/Manual/Components.html) onto them. VPE comes with large amount of Components that are used to define the gameplay of the table. > [!note] -> During runtime, VPE converts the game objects and components into Unity's [DOTS](https://unity.com/dots) elements. We use Components in the editor to define the game logic implemented in DOTS. That's also why we call them *Authoring Components*. +> During runtime, VPE converts the game objects and components into Unity's [DOTS](https://unity.com/dots) elements. So we use Components in the editor to define the game logic implemented in DOTS. That's also why we call them *Authoring Components*. -If you've never heard about GameObjects or Components, we strong suggest you read through the links in the first two paragraphs, they are short, to the point, and better than what we could provide here. +If you've never heard about GameObjects or Components, we recommmend you read through the links in the first two paragraphs, they are short, to the point, and better than what we could provide here. ## Components vs Game Items -In Visual Pinball, Components would be what you see in the options panel when you click on a game item. You'll typically find sections for physics behavior, rendering, and form and shape of the game item you're editing. Internally, all those section belong to the same game item. +In Visual Pinball, Components would be what you see in the options panel when you click on a game item. You'll typically find sections for physics behavior, rendering, and form and shape of the game item you're editing. Internally, all those sections belong to the same game item. -In VPE, we have separate Components for separate things. For example, a rubber might be visible on the playfield, so its GameObject has a *Rubber Mesh Component*. And it also collides with the ball, so there is a *Rubber Collision Component* as well. And of course it has a position and a name, which are part of what we call the "main component", in this case the *Rubber Component*. +In VPE, we have separate Components for separate things. For example, a rubber might be visible on the playfield, so its GameObject includes a *Rubber Mesh Component*. And it also collides with the ball, so there is a *Rubber Collision Component* as well. And of course it has a position and a name, which are part of what we call the "main component", in this case the *Rubber Component*. + +This separation of logic comes with a lot of advantages, as you will see later. + +> [!note] +> In general, you don't have to manually manage all this. When creating game items via the toolbox, the created GameObject will already have all the necessary components. Also, importing a `.vpx` file applies the necessary components. + + +## Collider Types + +| | Mesh | Collision | Movement | +|------------|------|-----------------|----------| +| Bumper | | | | +| Flipper | | | | +| Gate | | | | +| Hit Target | | | | +| Kicker | | | | +| Light | | | | +| Plunger | | | | +| Primitive | | | | +| Ramp | | | | +| Rubber | | RubberCollider | | +| Spinner | | | | +| Surface | | SurfaceCollider | | +| Trigger | | | | + +*What we've implemented so far*. -In general, you don't have to manually manage all this. When creating a rubber via the toolbox, the created GameObject will already have all the necessary components. diff --git a/VisualPinball.Unity/Documentation~/creators-guide/toc.yml b/VisualPinball.Unity/Documentation~/creators-guide/toc.yml index 34fc9f959..88d3be812 100644 --- a/VisualPinball.Unity/Documentation~/creators-guide/toc.yml +++ b/VisualPinball.Unity/Documentation~/creators-guide/toc.yml @@ -16,6 +16,8 @@ - name: Editor items: + - name: Unity Components + href: editor/unity-components.md - name: Switch Manager href: editor/switch-manager.md - name: Coil Manager From a60af92dfbdb848892f0559d4fb0482af8b6f6d2 Mon Sep 17 00:00:00 2001 From: freezy Date: Tue, 29 Sep 2020 23:04:32 +0200 Subject: [PATCH 034/124] editor: Update colored icons. --- VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs | 4 ++-- .../VPT/Rubber/RubberColliderAuthoring.cs.meta | 2 +- .../VPT/Surface/SurfaceColliderAuthoring.cs.meta | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs index 2787ff5e2..a20763977 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs @@ -1,10 +1,10 @@ using System; -using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using UnityEditor; +using UnityEditor.Callbacks; using UnityEngine; using Object = UnityEngine.Object; @@ -124,7 +124,7 @@ public static Texture2D ByComponent(T mb, IconSize size = IconSize.Large, Ico } } - [UnityEditor.Callbacks.DidReloadScripts] + [DidReloadScripts] public static void OnScriptsReloaded() { DisableGizmo(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs.meta index 4d3812879..7d07cd65f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs.meta @@ -5,7 +5,7 @@ MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: ee9a0358dbff1c64989b8496a39a90f1, type: 3} userData: assetBundleName: assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs.meta index 1d727a671..6de36be1e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs.meta @@ -5,7 +5,7 @@ MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: f61f312b33275f0478c1c81dc0b69629, type: 3} userData: assetBundleName: assetBundleVariant: From de49047491fdb903f44e510e771ec0da6f480ae1 Mon Sep 17 00:00:00 2001 From: freezy Date: Thu, 1 Oct 2020 00:17:29 +0200 Subject: [PATCH 035/124] doc: Update component doc. --- .../creators-guide/editor/unity-components.md | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md b/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md index 955be6b65..767e34159 100644 --- a/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md +++ b/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md @@ -1,11 +1,11 @@ # Unity Components -When loading or creating a table in Unity, what you're creating is a hierarchy of [GameObjects](https://docs.unity3d.com/Manual/GameObjects.html). By default we create a level for every game item type, but you can arrange them however you want. +When loading or creating a table in Unity, what you're creating is a hierarchy of [GameObjects](https://docs.unity3d.com/Manual/GameObjects.html). By default we group game items by their type, but you can arrange them however you want. -In order to give the GameObjects behavior during gameplay, we add [Components](https://docs.unity3d.com/Manual/Components.html) onto them. VPE comes with large amount of Components that are used to define the gameplay of the table. +In order to give the GameObjects behavior during gameplay, we add [Components](https://docs.unity3d.com/Manual/Components.html) onto them. VPE comes with large amount of Components that are used to set up the game mechanics of the table. > [!note] -> During runtime, VPE converts the game objects and components into Unity's [DOTS](https://unity.com/dots) elements. So we use Components in the editor to define the game logic implemented in DOTS. That's also why we call them *Authoring Components*. +> During runtime, VPE converts the GameObjects and Components into Unity's [DOTS](https://unity.com/dots) elements. So we use Components in the editor to define the game logic implemented in DOTS. That's also why we call them *Authoring Components*. If you've never heard about GameObjects or Components, we recommmend you read through the links in the first two paragraphs, they are short, to the point, and better than what we could provide here. @@ -13,7 +13,7 @@ If you've never heard about GameObjects or Components, we recommmend you read th In Visual Pinball, Components would be what you see in the options panel when you click on a game item. You'll typically find sections for physics behavior, rendering, and form and shape of the game item you're editing. Internally, all those sections belong to the same game item. -In VPE, we have separate Components for separate things. For example, a rubber might be visible on the playfield, so its GameObject includes a *Rubber Mesh Component*. And it also collides with the ball, so there is a *Rubber Collision Component* as well. And of course it has a position and a name, which are part of what we call the "main component", in this case the *Rubber Component*. +In VPE, we have separate Components for separate things. For example, a rubber might be visible on the playfield, so its GameObject includes a *Rubber Mesh Component*. And it collides with the ball, so there is a *Rubber Collision Component* as well. And of course it has a position and a name, which are part of what we call the "main component", in this case the *Rubber Component*. This separation of logic comes with a lot of advantages, as you will see later. @@ -21,7 +21,9 @@ This separation of logic comes with a lot of advantages, as you will see later. > In general, you don't have to manually manage all this. When creating game items via the toolbox, the created GameObject will already have all the necessary components. Also, importing a `.vpx` file applies the necessary components. -## Collider Types +## Component Types + +Here's a quick overview of which Components VPE provides to set up your game items. | | Mesh | Collision | Movement | |------------|------|-----------------|----------| @@ -41,4 +43,14 @@ This separation of logic comes with a lot of advantages, as you will see later. *What we've implemented so far*. +As you can see, there are three types of Components for each game item: + +- **Mesh Components** generate meshes, i.e. the geometry used to render the object on the playfield. The result are procedurally generated visuals, e.g. a flipper mesh would be based on the length, inner- and outer radius and a few more attributes. +- **Collision Components** add physics behavior to the game item. They define how the ball collides with it, i.e. how the bounciness, friction and randomness is applied to the ball. +- **Movement Components** apply animation to parts of the game item. If the entire object is moved (for example a flipper), this is taken care of by the collision Component, but items where only parts move (e.g. the plate of a gate, or the socket of a bumper), these components apply the movement to the GameObject. + +## Combining Components + +VPE allows to mix and match the different types of components. That means, for a game item, you can use a collider or mesh from another type. +## Naming Conventions From 47d4781ec22624a55fe6192fc88f1daa522a056c Mon Sep 17 00:00:00 2001 From: freezy Date: Sun, 4 Oct 2020 00:36:52 +0200 Subject: [PATCH 036/124] editor: Set collider icons. --- .../VPT/Rubber/RubberColliderAuthoring.cs.meta | 2 +- .../VPT/Surface/SurfaceColliderAuthoring.cs.meta | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs.meta index 7d07cd65f..9f9eae27b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs.meta @@ -5,7 +5,7 @@ MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {fileID: 2800000, guid: ee9a0358dbff1c64989b8496a39a90f1, type: 3} + icon: {fileID: 2800000, guid: 4ec5b81cbc713694c89aa8ec32323c1b, type: 3} userData: assetBundleName: assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs.meta index 6de36be1e..0b3be775a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs.meta @@ -5,7 +5,7 @@ MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {fileID: 2800000, guid: f61f312b33275f0478c1c81dc0b69629, type: 3} + icon: {fileID: 2800000, guid: 5ab68bb59cf0664409fbc3a768ef563c, type: 3} userData: assetBundleName: assetBundleVariant: From de4a275d43eabd615e019bfd0aa562d1a8f8349e Mon Sep 17 00:00:00 2001 From: freezy Date: Sun, 4 Oct 2020 17:53:08 +0200 Subject: [PATCH 037/124] editor: Add main authoring base class. --- .../Managers/Switches/SwitchManager.cs | 1 + .../VisualPinball.Unity.Editor/Utils/Icons.cs | 2 ++ .../VisualPinball.Unity/VPT/ItemAuthoring.cs | 6 ++++-- .../VisualPinball.Unity/VPT/ItemMainAuthoring.cs | 12 ++++++++++++ .../VPT/Rubber/RubberAuthoring.cs | 2 +- .../VPT/Surface/SurfaceAuthoring.cs | 2 +- 6 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Switches/SwitchManager.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Switches/SwitchManager.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Switches/SwitchManager.cs new file mode 100644 index 000000000..5f282702b --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Switches/SwitchManager.cs @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs index a20763977..17c9d4da7 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs @@ -137,8 +137,10 @@ public static void OnScriptsReloaded() DisableGizmo(); DisableGizmo(); DisableGizmo(); + DisableGizmo(); DisableGizmo(); DisableGizmo(); + DisableGizmo(); DisableGizmo(); } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs index a7987b294..42b65bc66 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs @@ -35,8 +35,10 @@ namespace VisualPinball.Unity /// /// /// - public abstract class ItemAuthoring : MonoBehaviour, IItemAuthoring, IEditableItemAuthoring, IIdentifiableItemAuthoring, - ILayerableItemAuthoring where TData : ItemData where TItem : Item, IRenderable + public abstract class ItemAuthoring : MonoBehaviour, + IItemAuthoring, IEditableItemAuthoring, ILayerableItemAuthoring + where TData : ItemData + where TItem : Item, IRenderable { /// /// The serialized data, as written to the .vpx file. diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs new file mode 100644 index 000000000..c7c40a5cc --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs @@ -0,0 +1,12 @@ +using VisualPinball.Engine.Game; +using VisualPinball.Engine.VPT; + +namespace VisualPinball.Unity +{ + public abstract class ItemMainAuthoring : ItemAuthoring + where TItem : Item, IRenderable + where TData : ItemData + { + + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs index 1e65fb46b..f1561c074 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs @@ -31,7 +31,7 @@ namespace VisualPinball.Unity { [ExecuteAlways] [AddComponentMenu("Visual Pinball/Rubber")] - public class RubberAuthoring : ItemAuthoring, IDragPointsEditable, IHittableAuthoring, IConvertGameObjectToEntity + public class RubberAuthoring : ItemMainAuthoring, IDragPointsEditable, IHittableAuthoring, IConvertGameObjectToEntity { protected override string[] Children => null; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs index 949764022..d266081ef 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs @@ -31,7 +31,7 @@ namespace VisualPinball.Unity { [ExecuteAlways] [AddComponentMenu("Visual Pinball/Surface")] - public class SurfaceAuthoring : ItemAuthoring, IHittableAuthoring, IConvertGameObjectToEntity, IDragPointsEditable + public class SurfaceAuthoring : ItemMainAuthoring, IHittableAuthoring, IConvertGameObjectToEntity, IDragPointsEditable { protected override string[] Children => new [] { "Side", "Top" }; From de06a5f68f1d69852dc656e1e015bad73a5dd93b Mon Sep 17 00:00:00 2001 From: freezy Date: Sun, 4 Oct 2020 23:43:22 +0200 Subject: [PATCH 038/124] authoring: Split mesh creation into separate component. --- .../DragPoint/DragPointsHandler.cs | 4 +- .../DragPoint/DragPointsItemInspector.cs | 20 +- .../Managers/ImageManager.cs | 6 +- .../Managers/ManagerWindow.cs | 2 +- .../Managers/MaterialManager.cs | 6 +- .../VPT/Gate/GateInspector.cs | 2 +- .../VPT/ItemColliderInspector.cs | 6 +- .../VPT/ItemInspector.cs | 23 +- .../VPT/TransformInspector.cs | 35 +-- .../VPT/Bumper/BumperAuthoring.cs | 7 +- .../VPT/Flipper/FlipperAuthoring.cs | 4 +- .../VPT/Gate/GateAuthoring.cs | 5 +- .../VPT/Gate/GateWireAuthoring.cs | 4 +- .../VPT/HitTarget/HitTargetAuthoring.cs | 5 +- .../VPT/IExtendableAuthoring.cs | 16 -- .../VPT/IHittableAuthoring.cs | 2 +- .../VisualPinball.Unity/VPT/IItemAuthoring.cs | 13 +- .../VPT/IItemColliderAuthoring.cs | 3 - ...ItemAuthoring.cs => IItemMainAuthoring.cs} | 11 +- ...ing.cs.meta => IItemMainAuthoring.cs.meta} | 2 +- .../VPT/IItemMeshAuthoring.cs | 17 ++ ...ing.cs.meta => IItemMeshAuthoring.cs.meta} | 2 +- .../VisualPinball.Unity/VPT/IMeshAuthoring.cs | 27 +++ .../VPT/IMeshAuthoring.cs.meta | 11 + .../VPT/IRenderableAuthoring.cs | 7 + .../VPT/IRenderableAuthoring.cs.meta | 11 + .../VisualPinball.Unity/VPT/ItemAuthoring.cs | 212 +---------------- .../VPT/ItemColliderAuthoring.cs | 125 ++-------- .../VPT/ItemMainAuthoring.cs | 96 +++++++- .../VPT/ItemMainAuthoring.cs.meta | 11 + .../VPT/ItemMeshAuthoring.cs | 216 ++++++++++++++++++ .../VPT/ItemMeshAuthoring.cs.meta | 11 + .../VPT/ItemMovementAuthoring.cs | 38 +++ .../VPT/ItemMovementAuthoring.cs.meta | 11 + .../VPT/ItemSubAuthoring.cs | 112 +++++++++ .../VPT/ItemSubAuthoring.cs.meta | 11 + .../VPT/Kicker/KickerAuthoring.cs | 5 +- .../VPT/Light/LightAuthoring.cs | 4 +- .../VPT/Plunger/PlungerAuthoring.cs | 9 +- .../VPT/Primitive/PrimitiveAuthoring.cs | 4 +- .../VPT/Ramp/RampAuthoring.cs | 4 +- .../VPT/Rubber/RubberAuthoring.cs | 3 - .../VPT/Rubber/RubberColliderAuthoring.cs | 1 - .../VPT/Rubber/RubberExtensions.cs | 20 +- .../VPT/Rubber/RubberMeshAuthoring.cs | 28 +++ .../VPT/Rubber/RubberMeshAuthoring.cs.meta | 11 + .../VPT/Spinner/SpinnerAuthoring.cs | 5 +- .../VPT/Spinner/SpinnerPlateAuthoring.cs | 4 +- .../VPT/Surface/SurfaceAuthoring.cs | 5 +- .../VPT/Surface/SurfaceColliderAuthoring.cs | 22 -- .../VPT/Surface/SurfaceExtensions.cs | 21 +- .../VPT/Table/TableAuthoring.cs | 6 +- .../VPT/Trigger/TriggerAuthoring.cs | 5 +- 53 files changed, 761 insertions(+), 490 deletions(-) delete mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/IExtendableAuthoring.cs rename VisualPinball.Unity/VisualPinball.Unity/VPT/{IEditableItemAuthoring.cs => IItemMainAuthoring.cs} (79%) rename VisualPinball.Unity/VisualPinball.Unity/VPT/{IEditableItemAuthoring.cs.meta => IItemMainAuthoring.cs.meta} (83%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs rename VisualPinball.Unity/VisualPinball.Unity/VPT/{IExtendableAuthoring.cs.meta => IItemMeshAuthoring.cs.meta} (83%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/IMeshAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/IMeshAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/IRenderableAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/IRenderableAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberMeshAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberMeshAuthoring.cs.meta diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/DragPointsHandler.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/DragPointsHandler.cs index 6bdb97d20..81f4d85d1 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/DragPointsHandler.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/DragPointsHandler.cs @@ -31,7 +31,7 @@ public class DragPointsHandler /// /// Authoring item /// - public IEditableItemAuthoring Editable { get; private set; } + public IItemMainAuthoring Editable { get; private set; } /// /// Authoring item as IDragPointsEditable @@ -87,7 +87,7 @@ public class DragPointsHandler /// public DragPointsHandler(Object target) { - Editable = target as IEditableItemAuthoring + Editable = target as IItemMainAuthoring ?? throw new ArgumentException("Target must extend `IEditableItemAuthoring`."); DragPointEditable = target as IDragPointsEditable diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/DragPointsItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/DragPointsItemInspector.cs index 06e3484e6..e34cfdda6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/DragPointsItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/DragPointsItemInspector.cs @@ -98,7 +98,7 @@ public void PasteDragPoint(int controlId) /// True if game item is locked, false otherwise. public bool IsItemLocked() { - return !(target is IEditableItemAuthoring editable) || editable.IsLocked; + return !(target is IItemMainAuthoring editable) || editable.IsLocked; } /// @@ -138,8 +138,8 @@ public void FlipDragPoints(FlipAxis flipAxis) public void RemapControlPoints() { var rebuilt = DragPointsHandler.RemapControlPoints(); - if (rebuilt && target is IEditableItemAuthoring editable) { - editable.MeshDirty = true; + if (rebuilt && target is IItemMeshAuthoring meshAuthoring) { + meshAuthoring.MeshDirty = true; } } @@ -174,8 +174,8 @@ public void PrepareUndo(string message) // Set MeshDirty to true there so it'll trigger again after Undo var recordObjs = new List(); - if (target is IEditableItemAuthoring editable) { - editable.MeshDirty = true; + if (target is IItemMeshAuthoring meshAuthoring) { + meshAuthoring.MeshDirty = true; recordObjs.Add(this); } recordObjs.Add(target); @@ -186,7 +186,7 @@ public override void OnInspectorGUI() { base.OnInspectorGUI(); - var editable = target as IEditableItemAuthoring; + var editable = target as IItemMainAuthoring; var dragPointEditable = target as IDragPointsEditable; if (editable == null || dragPointEditable == null) { return; @@ -238,7 +238,7 @@ public override void OnInspectorGUI() private void UpdateDragPointsLock() { - if (target is IEditableItemAuthoring editable && DragPointsHandler.UpdateDragPointsLock(editable.IsLocked)) { + if (target is IItemMainAuthoring editable && DragPointsHandler.UpdateDragPointsLock(editable.IsLocked)) { HandleUtility.Repaint(); } } @@ -251,14 +251,14 @@ private void OnDragPointPositionChange(Vector3 newPos) private void OnUndoRedoPerformed() { RemapControlPoints(); - if (target is IEditableItemAuthoring item) { - item.MeshDirty = true; + if (target is IItemMeshAuthoring meshAuthoring) { + meshAuthoring.MeshDirty = true; } } protected virtual void OnSceneGUI() { - var editable = target as IEditableItemAuthoring; + var editable = target as IItemMainAuthoring; var dragPointEditable = target as IDragPointsEditable; var bh = target as Behaviour; diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/ImageManager.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/ImageManager.cs index 0ab18b651..21259fd16 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/ImageManager.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/ImageManager.cs @@ -81,7 +81,7 @@ protected override void RenameExistingItem(ImageListData data, string newName) // give each editable item a chance to update its fields string undoName = "Rename Image"; - foreach (var item in _tableAuthoring.GetComponentsInChildren()) { + foreach (var item in _tableAuthoring.GetComponentsInChildren()) { RenameReflectedFields(undoName, item, item.TextureRefs, oldName, newName); } RecordUndo(undoName, data.TextureData); @@ -95,7 +95,7 @@ protected override List CollectData() // collect list of in use textures List inUseTextures = new List(); - foreach (var item in _tableAuthoring.GetComponentsInChildren()) { + foreach (var item in _tableAuthoring.GetComponentsInChildren()) { var texRefs = item.TextureRefs; if (texRefs == null) { continue; } foreach (var texRef in texRefs) { @@ -140,7 +140,7 @@ private void OnDataChanged(string undoName, TextureData textureData) RecordUndo(undoName, textureData); // update any items using this tex - foreach (var item in _tableAuthoring.GetComponentsInChildren()) { + foreach (var item in _tableAuthoring.GetComponentsInChildren()) { if (IsReferenced(item.TextureRefs, item.ItemData, textureData.Name)) { item.MeshDirty = true; Undo.RecordObject(item as UnityEngine.Object, undoName); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/ManagerWindow.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/ManagerWindow.cs index 803f7509b..0e70bb41b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/ManagerWindow.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/ManagerWindow.cs @@ -377,7 +377,7 @@ protected bool IsReferenced(List mis, object instance, string refNam return false; } - protected void RenameReflectedFields(string undoName, IEditableItemAuthoring item, List mis, string oldName, string newName) + protected void RenameReflectedFields(string undoName, IItemMeshAuthoring item, List mis, string oldName, string newName) { foreach (var mi in mis) { string fieldVal = GetMemberValue(mi, item.ItemData); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/MaterialManager.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/MaterialManager.cs index 244c2ed3d..d2f95714c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/MaterialManager.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/MaterialManager.cs @@ -60,7 +60,7 @@ protected override void RenameExistingItem(MaterialListData data, string newName // give each editable item a chance to update its fields string undoName = "Rename Material"; - foreach (var item in _tableAuthoring.GetComponentsInChildren()) { + foreach (var item in _tableAuthoring.GetComponentsInChildren()) { RenameReflectedFields(undoName, item, item.MaterialRefs, oldName, newName); } Undo.RecordObject(_tableAuthoring, undoName); @@ -74,7 +74,7 @@ protected override List CollectData() // collect list of in use materials List inUseMaterials = new List(); - foreach (var item in _tableAuthoring.GetComponentsInChildren()) { + foreach (var item in _tableAuthoring.GetComponentsInChildren()) { var matRefs = item.MaterialRefs; if (matRefs == null) { continue; } foreach (var matRef in matRefs) { @@ -96,7 +96,7 @@ protected override List CollectData() protected override void OnDataChanged(string undoName, MaterialListData data) { - foreach (var item in _tableAuthoring.GetComponentsInChildren()) { + foreach (var item in _tableAuthoring.GetComponentsInChildren()) { if (IsReferenced(item.MaterialRefs, item.ItemData, data.Material.Name)) { item.MeshDirty = true; Undo.RecordObject(item as Object, undoName); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateInspector.cs index 07176b317..e1397b8c5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateInspector.cs @@ -42,7 +42,7 @@ protected override void OnEnable() protected virtual void OnSceneGUI() { - if (target is IEditableItemAuthoring editable) { + if (target is IItemMainAuthoring editable) { var position = editable.GetEditorPosition(); var transform = (target as MonoBehaviour).transform; if (transform != null && transform.parent != null) { diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs index 8e7fc1ce9..935646beb 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs @@ -25,11 +25,11 @@ namespace VisualPinball.Unity.Editor { - public class ItemColliderInspector : ItemInspector - where TColliderAuthoring : ItemColliderAuthoring + public class ItemColliderInspector : ItemInspector + where TColliderAuthoring : ItemColliderAuthoring where TData : ItemData where TItem : Item, IHittable, IRenderable - where TAuthoring : ItemAuthoring + where TMainAuthoring : ItemMainAuthoring { private TColliderAuthoring _colliderAuthoring; diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs index 6e1f91b61..0f5347cd8 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs @@ -60,18 +60,19 @@ protected virtual void OnDisable() public override void OnInspectorGUI() { - if (!(target is IEditableItemAuthoring item)) { + if (!(target is IItemMainAuthoring item)) { return; } - GUILayout.Space(10); - if( GUILayout.Button( "Force Update Mesh" ) ) { - item.MeshDirty = true; - } - - if (item.MeshDirty) { - item.RebuildMeshes(); - } + // todo move to generic mesh inspector + // GUILayout.Space(10); + // if( GUILayout.Button( "Force Update Mesh" ) ) { + // item.MeshDirty = true; + // } + // + // if (item.MeshDirty) { + // item.RebuildMeshes(); + // } } #endregion @@ -110,7 +111,7 @@ private void OnHierarchyChange() protected void OnPreInspectorGUI() { - if (!(target is IEditableItemAuthoring item)) { + if (!(target is IItemMainAuthoring item)) { return; } @@ -320,7 +321,7 @@ protected virtual void FinishEdit(string label, bool dirtyMesh = true) var undoLabel = $"[{target?.name}] Edit {label}"; if (dirtyMesh) { // set dirty flag true before recording object state for the undo so meshes will rebuild after the undo as well - if (target is IEditableItemAuthoring item) { + if (target is IItemMeshAuthoring item) { item.MeshDirty = true; Undo.RecordObject(this, undoLabel); } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs index 80d5f5f9f..359fd005d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs @@ -29,7 +29,7 @@ public class TransformInspector : UnityEditor.Editor { private UnityEditor.Editor _defaultEditor; private Transform _transform; - private IEditableItemAuthoring _primaryItem; + private IItemMainAuthoring _primaryItem; private List _secondaryItems = new List(); private ItemDataTransformType _positionType = ItemDataTransformType.ThreeD; private ItemDataTransformType _rotationType = ItemDataTransformType.ThreeD; @@ -48,7 +48,7 @@ protected virtual void OnEnable() bool useDefault = true; foreach (var t in targets) { - var item = (t as Transform)?.GetComponent(); + var item = (t as Transform)?.GetComponent(); if (item != null && !(item is TableAuthoring)) { useDefault = false; if (_primaryItem == null) { @@ -104,14 +104,15 @@ public override void OnInspectorGUI() private void RebuildMeshes() { - if (_primaryItem.MeshDirty) { - _primaryItem.RebuildMeshes(); - } - foreach (var secondary in _secondaryItems) { - if (secondary.Item.MeshDirty) { - secondary.Item.RebuildMeshes(); - } - } + // todo meshdirty + // if (_primaryItem.MeshDirty) { + // _primaryItem.RebuildMeshes(); + // } + // foreach (var secondary in _secondaryItems) { + // if (secondary.Item.MeshDirty) { + // secondary.Item.RebuildMeshes(); + // } + // } } protected virtual void OnSceneGUI() @@ -307,7 +308,8 @@ private void HandleScaleTool() private void FinishMove(Vector3 newPosition, bool isLocalPos = false) { - _primaryItem.MeshDirty = true; + // todo meshdirty + // _primaryItem.MeshDirty = true; string undoLabel = "Move " + _transform.gameObject.name; Undo.RecordObject(_primaryItem as UnityEngine.Object, undoLabel); Undo.RecordObject(_transform, undoLabel); @@ -320,7 +322,8 @@ private void FinishMove(Vector3 newPosition, bool isLocalPos = false) foreach (var secondary in _secondaryItems) { - secondary.Item.MeshDirty = true; + // todo meshdirty + // secondary.Item.MeshDirty = true; Undo.RecordObject(secondary.Item as UnityEngine.Object, undoLabel); Undo.RecordObject(secondary.Transform, undoLabel); secondary.Item.SetEditorPosition(finalPos + secondary.Offset); @@ -329,7 +332,8 @@ private void FinishMove(Vector3 newPosition, bool isLocalPos = false) private void FinishRotate(Vector3 newEuler) { - _primaryItem.MeshDirty = true; + // todo meshdirty + // _primaryItem.MeshDirty = true; string undoLabel = "Rotate " + _transform.gameObject.name; Undo.RecordObject(_primaryItem as UnityEngine.Object, undoLabel); Undo.RecordObject(_transform, undoLabel); @@ -338,7 +342,8 @@ private void FinishRotate(Vector3 newEuler) private void FinishScale(Vector3 newScale) { - _primaryItem.MeshDirty = true; + // todo meshdirty + // _primaryItem.MeshDirty = true; string undoLabel = "Scale " + _transform.gameObject.name; Undo.RecordObject(_primaryItem as UnityEngine.Object, undoLabel); Undo.RecordObject(_transform, undoLabel); @@ -348,7 +353,7 @@ private void FinishScale(Vector3 newScale) private class SecondaryItem { public Transform Transform; - public IEditableItemAuthoring Item; + public IItemMainAuthoring Item; public Vector3 Offset; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs index 87d57ba89..db7cb34b2 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs @@ -28,11 +28,10 @@ namespace VisualPinball.Unity { [ExecuteAlways] - [AddComponentMenu("Visual Pinball/Bumper")] - public class BumperAuthoring : ItemAuthoring, IHittableAuthoring, ISwitchAuthoring, IConvertGameObjectToEntity, ICoilAuthoring + [AddComponentMenu("Visual Pinball/Game Item/Bumper")] + public class BumperAuthoring : ItemMainAuthoring, + IHittableAuthoring, ISwitchAuthoring, ICoilAuthoring, IConvertGameObjectToEntity { - protected override string[] Children => new []{"Base", "Cap", "Ring", "Skirt"}; - protected override Bumper InstantiateItem(BumperData data) => new Bumper(data); public IHittable Hittable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs index 053d57550..7cb94b57d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs @@ -31,10 +31,10 @@ namespace VisualPinball.Unity [ExecuteAlways] [RequiresEntityConversion] [AddComponentMenu("Visual Pinball/Flipper")] - public class FlipperAuthoring : ItemAuthoring, + public class FlipperAuthoring : ItemMainAuthoring, IHittableAuthoring, ISwitchAuthoring, ICoilAuthoring, IConvertGameObjectToEntity { - protected override string[] Children => new []{ FlipperMeshGenerator.BaseName, FlipperMeshGenerator.RubberName }; + //protected override string[] Children => new []{ FlipperMeshGenerator.BaseName, FlipperMeshGenerator.RubberName }; protected override Flipper InstantiateItem(FlipperData data) => new Flipper(data); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs index d4355b55e..088e02df4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs @@ -28,10 +28,9 @@ namespace VisualPinball.Unity { [ExecuteAlways] [AddComponentMenu("Visual Pinball/Gate")] - public class GateAuthoring : ItemAuthoring, IHittableAuthoring, ISwitchAuthoring + public class GateAuthoring : ItemMainAuthoring, + IHittableAuthoring, ISwitchAuthoring { - protected override string[] Children => new []{"Wire", "Bracket"}; - protected override Gate InstantiateItem(GateData data) => new Gate(data); public IHittable Hittable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAuthoring.cs index d66deb041..4bca51d5f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAuthoring.cs @@ -21,10 +21,8 @@ namespace VisualPinball.Unity { - public class GateWireAuthoring : ItemAuthoring, IConvertGameObjectToEntity + public class GateWireAuthoring : ItemMainAuthoring, IConvertGameObjectToEntity { - protected override string[] Children => new string[0]; - public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { Convert(entity, dstManager); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs index 6b7b2cd3a..4b1c4472d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs @@ -29,10 +29,9 @@ namespace VisualPinball.Unity { [ExecuteAlways] [AddComponentMenu("Visual Pinball/Hit Target")] - public class HitTargetAuthoring : ItemAuthoring, IConvertGameObjectToEntity, IHittableAuthoring, ISwitchAuthoring + public class HitTargetAuthoring : ItemMainAuthoring, + IHittableAuthoring, ISwitchAuthoring, IConvertGameObjectToEntity { - protected override string[] Children => null; - protected override HitTarget InstantiateItem(HitTargetData data) => new HitTarget(data); public IHittable Hittable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IExtendableAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IExtendableAuthoring.cs deleted file mode 100644 index a5fddaefb..000000000 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IExtendableAuthoring.cs +++ /dev/null @@ -1,16 +0,0 @@ -using VisualPinball.Engine.VPT; - -namespace VisualPinball.Unity -{ - /// - /// This interface is for items that allow sub items to be linked to. - /// - /// For example, a Flipper might have a different mesh, and hence - /// a different item being linked to it (and translated/animated along - /// with it). - /// - public interface IExtendableAuthoring - { - void LinkChild(IItemAuthoring item); - } -} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IHittableAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IHittableAuthoring.cs index 8ab911269..8ca1aea22 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IHittableAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IHittableAuthoring.cs @@ -18,7 +18,7 @@ namespace VisualPinball.Unity { - public interface IHittableAuthoring : IExtendableAuthoring + public interface IHittableAuthoring { IHittable Hittable { get; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemAuthoring.cs index 15068741b..ad8cd4a02 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemAuthoring.cs @@ -8,17 +8,10 @@ namespace VisualPinball.Unity /// public interface IItemAuthoring { - IItem IItem { get; } - ItemDataTransformType EditorPositionType { get; } - Vector3 GetEditorPosition(); - void SetEditorPosition(Vector3 pos); + string Name { get; } - ItemDataTransformType EditorRotationType { get; } - Vector3 GetEditorRotation(); - void SetEditorRotation(Vector3 rot); + IItem IItem { get; } - ItemDataTransformType EditorScaleType { get; } - Vector3 GetEditorScale(); - void SetEditorScale(Vector3 rot); + ItemData ItemData { get; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs index 2d2361742..595380427 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs @@ -4,8 +4,5 @@ namespace VisualPinball.Unity { public interface IItemColliderAuthoring { - bool IsSubComponent { get; } - - void SetEditorPosition(Vector3 pos); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IEditableItemAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs similarity index 79% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/IEditableItemAuthoring.cs rename to VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs index 6cc8da259..ea5f0a7c8 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IEditableItemAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs @@ -14,22 +14,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -using System.Collections.Generic; -using System.Reflection; using UnityEngine; -using VisualPinball.Engine.VPT; namespace VisualPinball.Unity { - public interface IEditableItemAuthoring : IIdentifiableItemAuthoring + public interface IItemMainAuthoring : IItemAuthoring { bool IsLocked { get; set; } - bool MeshDirty { get; set; } - ItemData ItemData { get; } - List MaterialRefs { get; } - List TextureRefs { get; } - - void RebuildMeshes(); // the following interfaces allow each item behavior to define which axes should // be shown on the scene view gizmo, the gizmo itself will use the associated diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IEditableItemAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/IEditableItemAuthoring.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs.meta index 57e6939fe..fd0f77863 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IEditableItemAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 09f2a52604f6afc40a5ed1aac53e5366 +guid: d8798a785369a1649a76d27af109b747 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs new file mode 100644 index 000000000..8a3c3a14f --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using System.Reflection; +using VisualPinball.Engine.VPT; + +namespace VisualPinball.Unity +{ + public interface IItemMeshAuthoring : IItemAuthoring + { + bool MeshDirty { get; set; } + ItemData ItemData { get; } + + List MaterialRefs { get; } + List TextureRefs { get; } + + void RebuildMeshes(); + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IExtendableAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/IExtendableAuthoring.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs.meta index aa442fbae..d3e3df178 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IExtendableAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: e8c2d45cbf4c6664a941cef176d5b88f +guid: f921c2855cb983c41a7d73e730292c35 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IMeshAuthoring.cs new file mode 100644 index 000000000..dc3744f4e --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IMeshAuthoring.cs @@ -0,0 +1,27 @@ +// 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.Game; + +namespace VisualPinball.Unity +{ + public interface IMeshAuthoring + { + IRenderable Renderable { get; } + + void RemoveMeshComponent(); + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/IMeshAuthoring.cs.meta new file mode 100644 index 000000000..de81cf5cc --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c2515efbac260db4ba1d9459e79dabf3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IRenderableAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IRenderableAuthoring.cs new file mode 100644 index 000000000..a620d14f3 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IRenderableAuthoring.cs @@ -0,0 +1,7 @@ +namespace VisualPinball.Unity +{ + public interface IRenderableAuthoring + { + + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IRenderableAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/IRenderableAuthoring.cs.meta new file mode 100644 index 000000000..30c47c89e --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IRenderableAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2c737d363d13cd745a061836f6d99a43 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs index 42b65bc66..3a7a183c3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs @@ -16,17 +16,10 @@ // ReSharper disable InconsistentNaming -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using NLog; -using Unity.Entities; using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Table; -using Logger = NLog.Logger; namespace VisualPinball.Unity { @@ -35,29 +28,11 @@ namespace VisualPinball.Unity /// /// /// - public abstract class ItemAuthoring : MonoBehaviour, - IItemAuthoring, IEditableItemAuthoring, ILayerableItemAuthoring + public abstract class ItemAuthoring : MonoBehaviour where TData : ItemData where TItem : Item, IRenderable { - /// - /// The serialized data, as written to the .vpx file. - /// - /// - /// - /// This might be "empty" (since Unity can't serialize it as `null`), so - /// the component authoring classes keep a flag whether to read the data - /// from this field or retrieve it from the parent in the hierarchy. - /// - [SerializeField] - protected TData _data; - - /// - /// The game item object. This is not serialized and gets re-instantiated - /// and cached here. - /// - [NonSerialized] - protected TItem _item; + public string Name { get => Item.Name; set => Item.Name = value; } /// /// Returns the data object relevant for this component. If this @@ -69,7 +44,7 @@ public abstract class ItemAuthoring : MonoBehaviour, /// The default implementation here represents the one of a main /// component. It's overridden for the sub components (, etc) /// - public virtual TData Data => _data; + public abstract TData Data { get; } /// /// Returns the item object for this component. If this @@ -83,199 +58,28 @@ public abstract class ItemAuthoring : MonoBehaviour, /// which initializes the component after creation, /// is only set to avoid a cache miss. /// - public virtual TItem Item => _item ?? (_item = InstantiateItem(_data)); + public abstract TItem Item { get; } /// /// A non-typed version of the item. /// - public IItem IItem => _item; + public IItem IItem => Item; /// /// The data-oriented version of the item. /// - public ItemData ItemData => _data; - + public ItemData ItemData => Data; public string ItemType => Item.ItemType; - public bool IsLocked { get => _data.IsLocked; set => _data.IsLocked = value; } - - public List MaterialRefs => _materialRefs ?? (_materialRefs = GetMembersWithAttribute()); - public List TextureRefs => _textureRefs ?? (_textureRefs = GetMembersWithAttribute()); + public bool IsLocked { get => Data.IsLocked; set => Data.IsLocked = value; } private Table _table; protected Table Table => _table ?? (_table = gameObject.transform.GetComponentInParent()?.Item); - private List _materialRefs; - private List _textureRefs; - - private readonly Logger _logger = LogManager.GetCurrentClassLogger(); - - // for tracking if we need to rebuild the meshes (handled by the editor scripts) during undo/redo flows - [HideInInspector] - [SerializeField] - private bool _meshDirty; - public bool MeshDirty { get => _meshDirty; set => _meshDirty = value; } - - public ItemAuthoring SetItem(TItem item, string gameObjectName = null) - { - _item = item; - _data = item.Data; - name = gameObjectName ?? _data.GetName(); - ItemDataChanged(); - return this; - } - - public void RebuildMeshes() + protected virtual void ItemDataChanged() { - if (_data == null) { - _logger.Warn("Cannot retrieve data component for a {0}.", typeof(TItem).Name); - return; - } - var table = transform.GetComponentInParent(); - if (table == null) { - _logger.Warn("Cannot retrieve table component from {0}, not updating meshes.", _data.GetName()); - return; - } - - var rog = Item.GetRenderObjects(table.Table, Origin.Original, false); - var children = Children; - if (children == null) { - UpdateMesh(Item.Name, gameObject, rog, table); - } else { - foreach (var child in children) { - if (transform.childCount == 0) { - //Find the matching renderObject and Update it based on base gameObject - var ro = rog.RenderObjects.FirstOrDefault(r => r.Name == child); - if (ro != null) - { - UpdateMesh(child, gameObject, rog, table); - break; - } - } else { - Transform childTransform = transform.Find(child); - if (childTransform != null) { - UpdateMesh(child, childTransform.gameObject, rog, table); - } else { - // child hasn't been created yet (i.e. ramp might have changed type) - var ro = rog.RenderObjects.FirstOrDefault(r => r.Name == child); - if (ro != null) { - var subObj = new GameObject(ro.Name); - subObj.transform.SetParent(transform, false); - subObj.layer = VpxConverter.ChildObjectsLayer; - } - } - } - } - } - // update transform based on item data, but not for "Table" since its the effective "root" and the user might want to move it on their own - if (table != this) { - transform.SetFromMatrix(rog.TransformationMatrix.ToUnityMatrix()); - } - ItemDataChanged(); - _meshDirty = false; } - - protected virtual void ItemDataChanged() {} - - public virtual ItemDataTransformType EditorPositionType => ItemDataTransformType.None; - public virtual Vector3 GetEditorPosition() { return Vector3.zero; } - public virtual void SetEditorPosition(Vector3 pos) { } - - public virtual ItemDataTransformType EditorRotationType => ItemDataTransformType.None; - public virtual Vector3 GetEditorRotation() { return Vector3.zero; } - public virtual void SetEditorRotation(Vector3 rot) { } - - public virtual ItemDataTransformType EditorScaleType => ItemDataTransformType.None; - public virtual Vector3 GetEditorScale() { return Vector3.zero; } - public virtual void SetEditorScale(Vector3 rot) { } - - protected void Convert(Entity entity, EntityManager dstManager) - { - Item.Index = entity.Index; - Item.Version = entity.Version; - } - - protected void SetEditorPositionChildren(Vector3 pos) - { - var children = GetComponentsInChildren(); - foreach (var child in children) - { - if (!child.IsSubComponent) { - child.SetEditorPosition(pos); - } - } - } - - public void LinkChild(IItemAuthoring childItem) - { - if (childItem is IItemColliderAuthoring) { - Table.AddColliderOverride(Item, childItem.IItem as IHittable); - } - } - - protected virtual void OnDrawGizmos() - { - // handle dirty whenever scene view draws just in case a field or dependant changed and our - // custom inspector window isn't up to process it - if (_meshDirty) { - RebuildMeshes(); - } - - // Draw invisible gizmos over top of the sub meshes of this item so clicking in the scene view - // selects the item itself first, which is most likely what the user would want - var mfs = GetComponentsInChildren(); - Gizmos.color = Color.clear; - Gizmos.matrix = Matrix4x4.identity; - foreach (var mf in mfs) { - Gizmos.DrawMesh(mf.sharedMesh, mf.transform.position, mf.transform.rotation, mf.transform.lossyScale); - } - } - - private static void UpdateMesh(string childName, GameObject go, RenderObjectGroup rog, TableAuthoring table) - { - var mr = go.GetComponent(); - var ro = rog.RenderObjects.FirstOrDefault(r => r.Name == childName); - if (ro == null || !ro.IsVisible) { - if (mr != null) { - mr.enabled = false; - } - return; - } - var mf = go.GetComponent(); - if (mf != null) { - var unityMesh = mf.sharedMesh; - ro.Mesh.ApplyToUnityMesh(unityMesh); - } - - if (mr != null) { - if (table != null) { - mr.sharedMaterial = ro.Material.ToUnityMaterial(table); - } - mr.enabled = true; - } - } - - private List GetMembersWithAttribute() where TAttr: Attribute - { - List members = new List(); - foreach (var member in typeof(TData).GetMembers(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { - if (member.GetCustomAttribute() != null) { - members.Add(member); - } - } - return members; - } - - protected abstract string[] Children { get; } - - protected abstract TItem InstantiateItem(TData data); - - public string Name { get => Item.Name; set => Item.Name = value; } - - public int EditorLayer { get => _data.EditorLayer; set => _data.EditorLayer = value; } - public string EditorLayerName { get => _data.EditorLayerName; set => _data.EditorLayerName = value; } - public bool EditorLayerVisibility { get => _data.EditorLayerVisibility; set => _data.EditorLayerVisibility = value; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs index fd035b314..14414f7ee 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs @@ -28,120 +28,25 @@ namespace VisualPinball.Unity { - public abstract class ItemColliderAuthoring : ItemAuthoring, IItemColliderAuthoring + public abstract class ItemColliderAuthoring : ItemSubAuthoring, + IItemColliderAuthoring where TData : ItemData where TItem : Item, IHittable, IRenderable - where TAuthoring : ItemAuthoring + where TMainAuthoring : ItemMainAuthoring { - /// - /// We're in a sub component here, so in order to retrieve the data, - /// this will: - /// 1. Check if is set (e.g. it's a serialized item) - /// 2. Find the main component in the hierarchy and return its data. - /// - /// - /// - /// We deliberately don't cache this, because if we do we need to find - /// a way to invalidate the cache in case the game object gets - /// re-attached to another parent. - /// - public override TData Data => _isSubComponent ? FindData() : _data; - - /// - /// Since we're in a sub component, we don't instantiate the item, but - /// look for the main component and retrieve the item from there (which - /// will instantiate it itself if necessary). - /// - /// - /// - /// If no main component found, this yields to `null`, and in this case - /// the component is somewhere in the hierarchy where it doesn't make - /// sense, and a warning should be printed. - /// - public override TItem Item => _item ?? FindItem(); - [NonSerialized] public bool ShowGizmos; - public bool ShowColliderMesh; - public bool ShowAabbs; - [NonSerialized] - public int SelectedCollider = -1; - public HitObject[] HitObjects { get; private set; } [SerializeField] - private bool _isSubComponent; - public bool IsSubComponent => _isSubComponent; - - protected override string[] Children => new string[0]; - - private static readonly Color AabbColor = new Color32(255, 0, 252, 8); - private static readonly Color SelectedAabbColor = new Color32(255, 0, 252, 255); - private static readonly Color ColliderColor = new Color32(0, 255, 75, 8); - private static readonly Color SelectedColliderColor = new Color32(0, 255, 75, 255); - - public IItemAuthoring SetItem(TItem item, RenderObjectGroup rog) - { - _item = item; - _data = item.Data; - _isSubComponent = false; - name = rog.ComponentName + " (collider)"; - return this; - } - - public void SetMainItem(TItem item) - { - _item = item; - _isSubComponent = true; - } - - private TData FindData() - { - var ac = FindParentAuthoring(); - return ac != null ? ac.Data : null; - } - - private TItem FindItem() - { - // if _data is set then it's an item of its own and we don't need to find the parent - if (!_isSubComponent) { - _item = InstantiateItem(_data); - return _item; - } - - // otherwise retrieve from parent - var ac = FindParentAuthoring(); - return ac != null ? ac.Item : null; - } - - private TAuthoring FindParentAuthoring() - { - var go = gameObject; - - // search on current game object - var ac = go.GetComponent(); - if (ac != null) { - return ac; - } - - // search on parent - if (go.transform.parent != null) { - ac = go.transform.parent.GetComponent(); - } - if (ac != null) { - return ac; - } + public bool ShowColliderMesh; - // search on grand parent - if (go.transform.parent.transform.parent != null) { - ac = go.transform.parent.transform.parent.GetComponent(); - } + [SerializeField] + public bool ShowAabbs; - if (ac == null) { - Debug.LogWarning("No same- or parent authoring component found."); - } + [NonSerialized] + public int SelectedCollider = -1; - return ac; - } + public HitObject[] HitObjects { get; private set; } private void OnDrawGizmosSelected() { @@ -185,7 +90,7 @@ private static void DrawAabb(Matrix4x4 ltw, Rect3D aabb, bool isSelected) var p12 = ltw.MultiplyPoint(new Vector3(aabb.Right, aabb.Bottom, aabb.ZLow)); var p13 = ltw.MultiplyPoint(new Vector3(aabb.Right, aabb.Top, aabb.ZLow)); - Gizmos.color = isSelected ? SelectedAabbColor : AabbColor; + Gizmos.color = isSelected ? ColliderColor.SelectedAabb : ColliderColor.Aabb; Gizmos.DrawLine(p00, p01); Gizmos.DrawLine(p01, p02); Gizmos.DrawLine(p02, p03); @@ -204,7 +109,7 @@ private static void DrawAabb(Matrix4x4 ltw, Rect3D aabb, bool isSelected) private void DrawCollider(Matrix4x4 ltw, HitObject hitObject, bool isSelected) { - Gizmos.color = isSelected ? SelectedColliderColor : ColliderColor; + Gizmos.color = isSelected ? ColliderColor.SelectedCollider : ColliderColor.Collider; switch (hitObject) { case HitPoint hitPoint: { @@ -325,4 +230,12 @@ private static void GizmoDrawCircle(Matrix4x4 ltw, Vector3 center, float radius) #endregion } + + internal static class ColliderColor + { + internal static readonly Color Aabb = new Color32(255, 0, 252, 8); + internal static readonly Color SelectedAabb = new Color32(255, 0, 252, 255); + internal static readonly Color Collider = new Color32(0, 255, 75, 8); + internal static readonly Color SelectedCollider = new Color32(0, 255, 75, 255); + } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs index c7c40a5cc..2c3add2b9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs @@ -1,12 +1,104 @@ -using VisualPinball.Engine.Game; +using System; +using Unity.Entities; +using UnityEngine; +using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT; namespace VisualPinball.Unity { - public abstract class ItemMainAuthoring : ItemAuthoring + public abstract class ItemMainAuthoring : ItemAuthoring, + IItemMainAuthoring, ILayerableItemAuthoring where TItem : Item, IRenderable where TData : ItemData { + /// + /// Returns the serialized data. + /// + public override TData Data => _data; + /// + /// Instantiates a new item based on the serialized data, and caches it + /// for the next access. + /// + public override TItem Item => _item ?? (_item = InstantiateItem(_data)); + + /// + /// The serialized data, as written to the .vpx file. + /// + /// + /// + /// This might be "empty" (since Unity can't serialize it as `null`), so + /// the component authoring classes keep a flag whether to read the data + /// from this field or retrieve it from the parent in the hierarchy. + /// + [SerializeField] + private TData _data; + + /// + /// The game item object. This is not serialized and gets re-instantiated + /// and cached here. + /// + [NonSerialized] + private TItem _item; + + public ItemAuthoring SetItem(TItem item, string gameObjectName = null) + { + _item = item; + _data = item.Data; + name = gameObjectName ?? _data.GetName(); + ItemDataChanged(); + return this; + } + + /// + /// Instantiates a new item based on the item data. + /// + /// Item data + /// New item instance + protected abstract TItem InstantiateItem(TData data); + + protected void Convert(Entity entity, EntityManager dstManager) + { + Item.Index = entity.Index; + Item.Version = entity.Version; + } + + protected virtual void OnDrawGizmos() + { + // handle dirty whenever scene view draws just in case a field or dependant changed and our + // custom inspector window isn't up to process it + + // todo rebuild mesh sub components + // if (_meshDirty) { + // RebuildMeshes(); + // } + + // Draw invisible gizmos over top of the sub meshes of this item so clicking in the scene view + // selects the item itself first, which is most likely what the user would want + var mfs = GetComponentsInChildren(); + Gizmos.color = Color.clear; + Gizmos.matrix = Matrix4x4.identity; + foreach (var mf in mfs) { + Gizmos.DrawMesh(mf.sharedMesh, mf.transform.position, mf.transform.rotation, mf.transform.lossyScale); + } + } + + + public virtual ItemDataTransformType EditorPositionType => ItemDataTransformType.None; + public virtual Vector3 GetEditorPosition() => Vector3.zero; + public virtual void SetEditorPosition(Vector3 pos) { } + + public virtual ItemDataTransformType EditorRotationType => ItemDataTransformType.None; + public virtual Vector3 GetEditorRotation() => Vector3.zero; + public virtual void SetEditorRotation(Vector3 rot) { } + + public virtual ItemDataTransformType EditorScaleType => ItemDataTransformType.None; + public virtual Vector3 GetEditorScale() => Vector3.zero; + public virtual void SetEditorScale(Vector3 rot) { } + + + public int EditorLayer { get => Data.EditorLayer; set => Data.EditorLayer = value; } + public string EditorLayerName { get => Data.EditorLayerName; set => Data.EditorLayerName = value; } + public bool EditorLayerVisibility { get => Data.EditorLayerVisibility; set => Data.EditorLayerVisibility = value; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs.meta new file mode 100644 index 000000000..055c51755 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 11b6b07bb9cda194087b98b2b2d84dd4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs new file mode 100644 index 000000000..a768e3131 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs @@ -0,0 +1,216 @@ +// 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; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using NLog; +using UnityEngine; +using VisualPinball.Engine.Game; +using VisualPinball.Engine.VPT; +using Logger = NLog.Logger; + +namespace VisualPinball.Unity +{ + public abstract class ItemMeshAuthoring : ItemSubAuthoring + where TData : ItemData + where TItem : Item, IHittable, IRenderable + where TAuthoring : ItemMainAuthoring + { + + + #region Creation and destruction + + [HideInInspector] + [SerializeField] + private bool _meshCreated; + + private void Awake() + { + if (!_meshCreated && gameObject.GetComponent() == null) { + var ta = GetComponentInParent(); + + var rog = Item.GetRenderObjects(ta.Table); + var ro = rog.RenderObjects[0]; + var mesh = ro.Mesh.ToUnityMesh($"{gameObject.name}_Mesh"); + + // apply mesh to game object + var mf = gameObject.AddComponent(); + mf.sharedMesh = mesh; + + // apply material + if (ro.Mesh.AnimationFrames.Count > 0) { + var smr = gameObject.AddComponent(); + smr.sharedMaterial = ro.Material.ToUnityMaterial(ta); + smr.sharedMesh = mesh; + smr.enabled = ro.IsVisible; + } else { + var mr = gameObject.AddComponent(); + mr.sharedMaterial = ro.Material.ToUnityMaterial(ta); + mr.enabled = ro.IsVisible; + } + + _meshCreated = true; + } + } + + private void OnEnable() + { + var mr = gameObject.GetComponent(); + if (mr != null) { + mr.enabled = true; + } + } + + private void OnDisable() + { + var mr = gameObject.GetComponent(); + if (mr != null) { + mr.enabled = false; + } + } + + private void OnDestroy() + { + var mr = gameObject.GetComponent(); + if (mr != null) { + DestroyImmediate(mr); + } + + var mf = gameObject.GetComponent(); + if (mf != null) { + DestroyImmediate(mf); + } + } + + #endregion + + + + + + + + + + + + + + + + public List MaterialRefs => _materialRefs ?? (_materialRefs = GetMembersWithAttribute()); + public List TextureRefs => _textureRefs ?? (_textureRefs = GetMembersWithAttribute()); + + private List _materialRefs; + private List _textureRefs; + + private readonly Logger _logger = LogManager.GetCurrentClassLogger(); + + // for tracking if we need to rebuild the meshes (handled by the editor scripts) during undo/redo flows + [HideInInspector] + [SerializeField] + private bool _meshDirty; + public bool MeshDirty { get => _meshDirty; set => _meshDirty = value; } + + public void RebuildMeshes() + { + if (Data == null) { + _logger.Warn("Cannot retrieve data component for a {0}.", typeof(TItem).Name); + return; + } + var table = transform.GetComponentInParent(); + if (table == null) { + _logger.Warn("Cannot retrieve table component from {0}, not updating meshes.", Data.GetName()); + return; + } + + var rog = Item.GetRenderObjects(table.Table, Origin.Original, false); + + // todo can probably ditch this, because components now update themselves + // var children = Children; + // if (children == null) { + // UpdateMesh(Item.Name, gameObject, rog, table); + // } else { + // foreach (var child in children) { + // if (transform.childCount == 0) { + // //Find the matching renderObject and Update it based on base gameObject + // var ro = rog.RenderObjects.FirstOrDefault(r => r.Name == child); + // if (ro != null) + // { + // UpdateMesh(child, gameObject, rog, table); + // break; + // } + // } else { + // Transform childTransform = transform.Find(child); + // if (childTransform != null) { + // UpdateMesh(child, childTransform.gameObject, rog, table); + // } else { + // // child hasn't been created yet (i.e. ramp might have changed type) + // var ro = rog.RenderObjects.FirstOrDefault(r => r.Name == child); + // if (ro != null) { + // var subObj = new GameObject(ro.Name); + // subObj.transform.SetParent(transform, false); + // subObj.layer = VpxConverter.ChildObjectsLayer; + // } + // } + // } + // } + // } + + // update transform based on item data, but not for "Table" since its the effective "root" and the user might want to move it on their own + if (table != this) { + transform.SetFromMatrix(rog.TransformationMatrix.ToUnityMatrix()); + } + + ItemDataChanged(); + _meshDirty = false; + } + + private static void UpdateMesh(string childName, GameObject go, RenderObjectGroup rog, TableAuthoring table) + { + var mr = go.GetComponent(); + var ro = rog.RenderObjects.FirstOrDefault(r => r.Name == childName); + if (ro == null || !ro.IsVisible) { + if (mr != null) { + mr.enabled = false; + } + return; + } + var mf = go.GetComponent(); + if (mf != null) { + var unityMesh = mf.sharedMesh; + ro.Mesh.ApplyToUnityMesh(unityMesh); + } + + if (mr != null) { + if (table != null) { + mr.sharedMaterial = ro.Material.ToUnityMaterial(table); + } + mr.enabled = true; + } + } + + private static List GetMembersWithAttribute() where TAttr: Attribute + { + return typeof(TData) + .GetMembers(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + .Where(member => member.GetCustomAttribute() != null) + .ToList(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs.meta new file mode 100644 index 000000000..cc485e370 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5492eb275092e4f438c52375049a94bf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs new file mode 100644 index 000000000..9b6744857 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs @@ -0,0 +1,38 @@ +// 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; +using UnityEngine; +using VisualPinball.Engine.Game; +using VisualPinball.Engine.Math; +using VisualPinball.Engine.Physics; +using VisualPinball.Engine.VPT; +using VisualPinball.Engine.VPT.Flipper; +using VisualPinball.Engine.VPT.Gate; +using VisualPinball.Engine.VPT.Plunger; +using VisualPinball.Engine.VPT.Spinner; +using Color = UnityEngine.Color; + +namespace VisualPinball.Unity +{ + public abstract class ItemMovementAuthoring : ItemSubAuthoring, + IItemColliderAuthoring + where TData : ItemData + where TItem : Item, IHittable, IRenderable + where TMainAuthoring : ItemMainAuthoring + { + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs.meta new file mode 100644 index 000000000..d2cd66120 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 77aa9ac03dbd4cc489a4afeddb587ef0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs new file mode 100644 index 000000000..6d33f34c1 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs @@ -0,0 +1,112 @@ +using UnityEngine; +using VisualPinball.Engine.Game; +using VisualPinball.Engine.VPT; + +namespace VisualPinball.Unity +{ + /// + /// Sub-components only deal with a specific aspect of the component and + /// grab the data from their parent (which can sit on the same GameObject + /// or the parent or grand parent).

+ /// + /// Sub-components are collider- mesh- and movement components. + ///

+ /// + /// + /// Note we don't cache the data reference in order having to detect when + /// the component gets re-parented. + /// + /// Type of the item + /// Data type of the item + /// Type of the main component, where the data is. + public abstract class ItemSubAuthoring : ItemAuthoring + where TItem : Item, IRenderable + where TData : ItemData + where TMainAuthoring : ItemMainAuthoring + { + /// + /// We're in a sub component here, so in order to retrieve the data, + /// this will: + /// 1. Check if is set (e.g. it's a serialized item) + /// 2. Find the main component in the hierarchy and return its data. + /// + /// + /// + /// We deliberately don't cache this, because if we do we need to find + /// a way to invalidate the cache in case the game object gets + /// re-attached to another parent. + /// + public override TData Data => FindData(); + + /// + /// Since we're in a sub component, we don't instantiate the item, but + /// look for the main component and retrieve the item from there (which + /// will instantiate it itself if necessary). + /// + /// + /// + /// If no main component found, this yields to `null`, and in this case + /// the component is somewhere in the hierarchy where it doesn't make + /// sense, and a warning should be printed. + /// + public override TItem Item => FindItem(); + + // public IItemAuthoring SetItem(TItem item, RenderObjectGroup rog) + // { + // _item = item; + // _data = item.Data; + // _isSubComponent = false; + // name = rog.ComponentName + " (collider)"; + // return this; + // } + + // public void SetMainItem(TItem item) + // { + // _item = item; + // _isSubComponent = true; + // } + + private TData FindData() + { + var ac = FindMainAuthoring(); + return ac != null ? ac.Data : null; + } + + private TItem FindItem() + { + // otherwise retrieve from parent + var ac = FindMainAuthoring(); + return ac != null ? ac.Item : null; + } + + private TMainAuthoring FindMainAuthoring() + { + var go = gameObject; + + // search on current game object + var ac = go.GetComponent(); + if (ac != null) { + return ac; + } + + // search on parent + if (go.transform.parent != null) { + ac = go.transform.parent.GetComponent(); + } + if (ac != null) { + return ac; + } + + // search on grand parent + if (go.transform.parent.transform.parent != null) { + ac = go.transform.parent.transform.parent.GetComponent(); + } + + if (ac == null) { + Debug.LogWarning("No same- or parent authoring component found."); + } + + return ac; + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs.meta new file mode 100644 index 000000000..c089e09aa --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f51b00f0546c2d04fb291cb9ac44f9c3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs index 280c9710a..e471aebd1 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs @@ -31,10 +31,9 @@ namespace VisualPinball.Unity { [ExecuteAlways] [AddComponentMenu("Visual Pinball/Kicker")] - public class KickerAuthoring : ItemAuthoring, IConvertGameObjectToEntity, IHittableAuthoring, ISwitchAuthoring, ICoilAuthoring + public class KickerAuthoring : ItemMainAuthoring, + IHittableAuthoring, ISwitchAuthoring, ICoilAuthoring, IConvertGameObjectToEntity { - protected override string[] Children => null; - protected override Kicker InstantiateItem(KickerData data) => new Kicker(data); public IHittable Hittable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs index 9a0286b28..8d58becc0 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs @@ -27,9 +27,9 @@ namespace VisualPinball.Unity { [AddComponentMenu("Visual Pinball/Light")] - public class LightAuthoring : ItemAuthoring + public class LightAuthoring : ItemMainAuthoring { - protected override string[] Children => new[] { "Bulb", "Socket" }; + // protected override string[] Children => new[] { "Bulb", "Socket" }; private UnityEngine.Light _unityLight; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs index b72f009ff..3217f791c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs @@ -23,11 +23,12 @@ namespace VisualPinball.Unity { [ExecuteAlways] [AddComponentMenu("Visual Pinball/Plunger")] - public class PlungerAuthoring : ItemAuthoring, IConvertGameObjectToEntity, IHittableAuthoring, ICoilAuthoring + public class PlungerAuthoring : ItemMainAuthoring, + IHittableAuthoring, ICoilAuthoring, IConvertGameObjectToEntity { - protected override string[] Children => new [] { - PlungerMeshGenerator.FlatName, PlungerMeshGenerator.RodName, PlungerMeshGenerator.SpringName - }; + // protected override string[] Children => new [] { + // PlungerMeshGenerator.FlatName, PlungerMeshGenerator.RodName, PlungerMeshGenerator.SpringName + // }; protected override Plunger InstantiateItem(PlungerData data) => new Plunger(data); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs index 9d62dfc4b..7c9c8c25d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs @@ -28,10 +28,8 @@ namespace VisualPinball.Unity { [AddComponentMenu("Visual Pinball/Primitive")] - public class PrimitiveAuthoring : ItemAuthoring, IHittableAuthoring, IConvertGameObjectToEntity + public class PrimitiveAuthoring : ItemMainAuthoring, IHittableAuthoring, IConvertGameObjectToEntity { - protected override string[] Children => null; - public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { Convert(entity, dstManager); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs index 6b656292c..91e58bab0 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs @@ -31,9 +31,9 @@ namespace VisualPinball.Unity { [ExecuteAlways] [AddComponentMenu("Visual Pinball/Ramp")] - public class RampAuthoring : ItemAuthoring, IDragPointsEditable, IConvertGameObjectToEntity, IHittableAuthoring + public class RampAuthoring : ItemMainAuthoring, IDragPointsEditable, IConvertGameObjectToEntity, IHittableAuthoring { - protected override string[] Children => new[] { "Floor", "RightWall", "LeftWall", "Wire1", "Wire2", "Wire3", "Wire4" }; + //protected override string[] Children => new[] { "Floor", "RightWall", "LeftWall", "Wire1", "Wire2", "Wire3", "Wire4" }; protected override Ramp InstantiateItem(RampData data) => new Ramp(data); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs index f1561c074..561e0319c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs @@ -33,8 +33,6 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Rubber")] public class RubberAuthoring : ItemMainAuthoring, IDragPointsEditable, IHittableAuthoring, IConvertGameObjectToEntity { - protected override string[] Children => null; - protected override Rubber InstantiateItem(RubberData data) => new Rubber(data); public IHittable Hittable => Item; @@ -72,7 +70,6 @@ public override Vector3 GetEditorPosition() } public override void SetEditorPosition(Vector3 pos) { - SetEditorPositionChildren(pos); if (Data == null || Data.DragPoints.Length == 0) { return; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs index 3587e103b..d485669f2 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs @@ -22,6 +22,5 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Rubber Collider")] public class RubberColliderAuthoring : ItemColliderAuthoring { - protected override Rubber InstantiateItem(RubberData data) => new Rubber(_data); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs index 0d673d22b..d4eb6f63e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs @@ -26,24 +26,28 @@ internal static class RubberExtensions public static MonoBehaviour SetupGameObject(this Engine.VPT.Rubber.Rubber rubber, GameObject obj, RenderObjectGroup rog, MonoBehaviour mainMb) { - MonoBehaviour mb = null; + MonoBehaviour mb = obj.AddComponent().SetItem(rubber); switch (rog.SubComponent) { case RenderObjectGroup.ItemSubComponent.None: - - mb = obj.AddComponent().SetItem(rubber); - obj.AddComponent().SetMainItem(rubber); + obj.AddComponent(); + obj.AddComponent(); break; - case RenderObjectGroup.ItemSubComponent.Collider: - var ia = obj.AddComponent().SetItem(rubber, rog); + case RenderObjectGroup.ItemSubComponent.Collider: { + obj.AddComponent(); if (mainMb != null && mainMb is IHittableAuthoring hittableAuthoring) { hittableAuthoring.RemoveHittableComponent(); - hittableAuthoring.LinkChild(ia); } break; + } - case RenderObjectGroup.ItemSubComponent.Mesh: + case RenderObjectGroup.ItemSubComponent.Mesh: { + obj.AddComponent(); + if (mainMb != null && mainMb is IMeshAuthoring meshAuthoring) { + meshAuthoring.RemoveMeshComponent(); + } break; + } default: throw new ArgumentOutOfRangeException(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberMeshAuthoring.cs new file mode 100644 index 000000000..246f359df --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberMeshAuthoring.cs @@ -0,0 +1,28 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Rubber; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Rubber Mesh")] + public class RubberMeshAuthoring : ItemMeshAuthoring + { + + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberMeshAuthoring.cs.meta new file mode 100644 index 000000000..2c63ecc54 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bd020e551a441b14da4e1491aa555bac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: b52d87166f45e4241945d32c98d8abbf, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs index ee8e88a78..2613c7eac 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs @@ -28,10 +28,9 @@ namespace VisualPinball.Unity { [ExecuteAlways] [AddComponentMenu("Visual Pinball/Spinner")] - public class SpinnerAuthoring : ItemAuthoring, IHittableAuthoring, ISwitchAuthoring + public class SpinnerAuthoring : ItemMainAuthoring, + IHittableAuthoring, ISwitchAuthoring { - protected override string[] Children => new [] { "Plate", "Bracket" }; - protected override Spinner InstantiateItem(SpinnerData data) => new Spinner(data); public IHittable Hittable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAuthoring.cs index c74d31f9c..6b422573e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAuthoring.cs @@ -21,10 +21,8 @@ namespace VisualPinball.Unity { - internal class SpinnerPlateAuthoring : ItemAuthoring, IConvertGameObjectToEntity + internal class SpinnerPlateAuthoring : ItemMainAuthoring, IConvertGameObjectToEntity { - protected override string[] Children => new string[0]; - public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { Convert(entity, dstManager); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs index d266081ef..b7dd5230a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs @@ -31,10 +31,9 @@ namespace VisualPinball.Unity { [ExecuteAlways] [AddComponentMenu("Visual Pinball/Surface")] - public class SurfaceAuthoring : ItemMainAuthoring, IHittableAuthoring, IConvertGameObjectToEntity, IDragPointsEditable + public class SurfaceAuthoring : ItemMainAuthoring, + IHittableAuthoring, IConvertGameObjectToEntity, IDragPointsEditable { - protected override string[] Children => new [] { "Side", "Top" }; - protected override Surface InstantiateItem(SurfaceData data) => new Surface(data); public IHittable Hittable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs index 90fea2444..b0e65995c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs @@ -22,27 +22,5 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Surface Collider")] public class SurfaceColliderAuthoring : ItemColliderAuthoring { - protected override Surface InstantiateItem(SurfaceData data) => new Surface(_data); - - public override Vector3 GetEditorPosition() { - if (Data == null || Data.DragPoints.Length == 0) { - return Vector3.zero; - } - return Data.DragPoints[0].Center.ToUnityVector3(); - } - - public override void SetEditorPosition(Vector3 pos) { - if (Data == null || Data.DragPoints.Length == 0) { - return; - } - - var diff = pos.ToVertex3D().Sub(Data.DragPoints[0].Center); - diff.Z = 0f; - Data.DragPoints[0].Center = pos.ToVertex3D(); - for (var i = 1; i < Data.DragPoints.Length; i++) { - var pt = Data.DragPoints[i]; - pt.Center = pt.Center.Add(diff); - } - } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs index 1f7a4106b..cc4cd4a4e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs @@ -26,25 +26,28 @@ internal static class SurfaceExtensions public static MonoBehaviour SetupGameObject(this Engine.VPT.Surface.Surface surface, GameObject obj, RenderObjectGroup rog, MonoBehaviour mainMb) { - - MonoBehaviour mb = null; + MonoBehaviour mb = obj.AddComponent().SetItem(surface); switch (rog.SubComponent) { case RenderObjectGroup.ItemSubComponent.None: - - mb = obj.AddComponent().SetItem(surface); - obj.AddComponent().SetMainItem(surface);; + obj.AddComponent(); + //obj.AddComponent(); break; - case RenderObjectGroup.ItemSubComponent.Collider: - var ia = obj.AddComponent().SetItem(surface, rog); + case RenderObjectGroup.ItemSubComponent.Collider: { + obj.AddComponent(); if (mainMb != null && mainMb is IHittableAuthoring hittableAuthoring) { hittableAuthoring.RemoveHittableComponent(); - hittableAuthoring.LinkChild(ia); } break; + } - case RenderObjectGroup.ItemSubComponent.Mesh: + case RenderObjectGroup.ItemSubComponent.Mesh: { + //obj.AddComponent(); + if (mainMb != null && mainMb is IMeshAuthoring meshAuthoring) { + meshAuthoring.RemoveMeshComponent(); + } break; + } default: throw new ArgumentOutOfRangeException(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs index e48fc259e..ef23b889a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs @@ -53,7 +53,7 @@ namespace VisualPinball.Unity { [AddComponentMenu("Visual Pinball/Table")] - public class TableAuthoring : ItemAuthoring + public class TableAuthoring : ItemMainAuthoring { public Table Table => Item; public TableSerializedTextureContainer Textures => _sidecar?.textures; @@ -62,8 +62,8 @@ public class TableAuthoring : ItemAuthoring public MappingsData Mappings => _sidecar?.mappings; public Patcher.Patcher Patcher { get; internal set; } - protected override string[] Children => null; - + [HideInInspector] [SerializeField] public string physicsEngineId; + [HideInInspector] [SerializeField] public string debugUiId; [HideInInspector] [SerializeField] private TableSidecar _sidecar; private readonly Dictionary _unityTextures = new Dictionary(); // note: this cache needs to be keyed on the engine material itself so that when its recreated due to property changes the unity material diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs index ba5e7eb4e..d0b91de03 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs @@ -31,10 +31,9 @@ namespace VisualPinball.Unity { [ExecuteAlways] [AddComponentMenu("Visual Pinball/Trigger")] - public class TriggerAuthoring : ItemAuthoring, IHittableAuthoring, ISwitchAuthoring, IDragPointsEditable, IConvertGameObjectToEntity + public class TriggerAuthoring : ItemMainAuthoring, + IHittableAuthoring, ISwitchAuthoring, IDragPointsEditable, IConvertGameObjectToEntity { - protected override string[] Children => null; - protected override Trigger InstantiateItem(TriggerData data) => new Trigger(data); public IHittable Hittable => Item; From 25986e2d9eceed16dd3ac534410e4d5a18d255d0 Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 5 Oct 2020 01:02:04 +0200 Subject: [PATCH 039/124] bumper: Start splitting meshes. --- VisualPinball.Engine/Game/IRenderable.cs | 8 +- .../Game/RenderObjectGroup.cs | 28 --- VisualPinball.Engine/VPT/Bumper/Bumper.cs | 15 +- .../VPT/Bumper/BumperMeshGenerator.cs | 123 +++++---- .../VPT/Collection/Collection.cs | 3 +- VisualPinball.Engine/VPT/Decal/Decal.cs | 3 +- VisualPinball.Engine/VPT/DispReel/DispReel.cs | 3 +- VisualPinball.Engine/VPT/Flasher/Flasher.cs | 3 +- VisualPinball.Engine/VPT/Flipper/Flipper.cs | 15 +- VisualPinball.Engine/VPT/Gate/Gate.cs | 14 +- .../VPT/HitTarget/HitTarget.cs | 15 +- VisualPinball.Engine/VPT/IItem.cs | 7 + VisualPinball.Engine/VPT/Item.cs | 43 +++- VisualPinball.Engine/VPT/Kicker/Kicker.cs | 14 +- VisualPinball.Engine/VPT/Light/Light.cs | 14 +- VisualPinball.Engine/VPT/LightSeq/LightSeq.cs | 3 +- VisualPinball.Engine/VPT/Plunger/Plunger.cs | 15 +- .../VPT/Primitive/Primitive.cs | 15 +- VisualPinball.Engine/VPT/Ramp/Ramp.cs | 14 +- VisualPinball.Engine/VPT/Rubber/Rubber.cs | 14 +- VisualPinball.Engine/VPT/Sound/Sound.cs | 3 +- VisualPinball.Engine/VPT/Spinner/Spinner.cs | 17 +- VisualPinball.Engine/VPT/Surface/Surface.cs | 22 +- .../VPT/Surface/SurfaceMeshGenerator.cs | 3 + VisualPinball.Engine/VPT/Table/Table.cs | 14 +- VisualPinball.Engine/VPT/TextBox/TextBox.cs | 3 +- VisualPinball.Engine/VPT/Texture.cs | 3 +- VisualPinball.Engine/VPT/Timer/Timer.cs | 3 +- VisualPinball.Engine/VPT/Trigger/Trigger.cs | 14 +- .../Toolbox/ToolboxEditor.cs | 12 +- .../Import/VpxConverter.cs | 238 +++++++++--------- .../VPT/Bumper/BumperBaseMeshAuthoring.cs | 29 +++ .../Bumper/BumperBaseMeshAuthoring.cs.meta | 11 + .../VPT/Bumper/BumperCapMeshAuthoring.cs | 29 +++ .../VPT/Bumper/BumperCapMeshAuthoring.cs.meta | 11 + .../VPT/Bumper/BumperExtensions.cs | 13 +- .../VPT/Bumper/BumperRingMeshAuthoring.cs | 29 +++ .../Bumper/BumperRingMeshAuthoring.cs.meta | 11 + .../VPT/Bumper/BumperSkirtMeshAuthoring.cs | 29 +++ .../Bumper/BumperSkirtMeshAuthoring.cs.meta | 11 + .../VPT/Flipper/FlipperExtensions.cs | 2 +- .../VPT/Gate/GateExtensions.cs | 2 +- .../VPT/HitTarget/HitTargetExtensions.cs | 2 +- .../VisualPinball.Unity/VPT/ItemAuthoring.cs | 2 +- .../VPT/ItemMainAuthoring.cs | 2 +- .../VPT/ItemMeshAuthoring.cs | 8 +- .../VPT/Kicker/KickerExtensions.cs | 2 +- .../VPT/Light/LightExtensions.cs | 2 +- .../VPT/Plunger/PlungerExtensions.cs | 2 +- .../VPT/Primitive/PrimitiveExtensions.cs | 2 +- .../VPT/Ramp/RampExtensions.cs | 2 +- .../VPT/Rubber/RubberAuthoring.cs | 13 +- .../VPT/Rubber/RubberExtensions.cs | 21 +- .../VPT/Spinner/SpinnerExtensions.cs | 2 +- .../VPT/Surface/SurfaceExtensions.cs | 38 ++- .../VPT/Surface/SurfaceSideMeshAuthoring.cs | 30 +++ .../VPT/Surface/SurfaceTopMeshAuthoring.cs | 30 +++ .../VPT/Table/TableExtensions.cs | 2 +- .../VPT/Trigger/TriggerExtensions.cs | 2 +- 59 files changed, 755 insertions(+), 285 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceSideMeshAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceTopMeshAuthoring.cs diff --git a/VisualPinball.Engine/Game/IRenderable.cs b/VisualPinball.Engine/Game/IRenderable.cs index 95a9bbb76..5e6c3c1f2 100644 --- a/VisualPinball.Engine/Game/IRenderable.cs +++ b/VisualPinball.Engine/Game/IRenderable.cs @@ -14,13 +14,17 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using VisualPinball.Engine.Math; +using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Table; namespace VisualPinball.Engine.Game { - public interface IRenderable + public interface IRenderable : IItem { - string Name { get; } + Matrix3D TransformationMatrix(Origin origin); + + RenderObject GetRenderObject(Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true); RenderObjectGroup GetRenderObjects(Table table, Origin origin = Origin.Global, bool asRightHanded = true); } diff --git a/VisualPinball.Engine/Game/RenderObjectGroup.cs b/VisualPinball.Engine/Game/RenderObjectGroup.cs index 0d46ae671..9904468b9 100644 --- a/VisualPinball.Engine/Game/RenderObjectGroup.cs +++ b/VisualPinball.Engine/Game/RenderObjectGroup.cs @@ -30,10 +30,6 @@ public class RenderObjectGroup public readonly RenderObject[] RenderObjects; public readonly Matrix3D TransformationMatrix; - public readonly string ComponentName; - public readonly ItemSubComponent SubComponent; - public readonly string SubName; - public bool ForceChild { get; set; } public bool HasOnlyChild => RenderObjects.Length == 1; public bool HasChildren => RenderObjects.Length > 0; @@ -46,30 +42,6 @@ public RenderObjectGroup(string name, string parent, Matrix3D matrix, params Ren Parent = parent; RenderObjects = renderObjects; TransformationMatrix = matrix; - (ComponentName, SubComponent, SubName) = SplitName(); - } - - public enum ItemSubComponent - { - None, Collider, Mesh - } - - private (string, ItemSubComponent, string) SplitName() - { - var names = Name.Split(new[] {'_'}, 3, StringSplitOptions.None); - if (names.Length == 1) { - return (Name, ItemSubComponent.None, null); - } - switch (names[1].ToLower()) { - case "collider": - return (names[0], ItemSubComponent.Collider, names.Length > 2 ? names[2] : null); - - case "mesh": - return (names[0], ItemSubComponent.Mesh, names.Length > 2 ? names[2] : null); - - default: - return (Name, ItemSubComponent.None, null); - } } } } diff --git a/VisualPinball.Engine/VPT/Bumper/Bumper.cs b/VisualPinball.Engine/VPT/Bumper/Bumper.cs index b0a1e7fad..69456725a 100644 --- a/VisualPinball.Engine/VPT/Bumper/Bumper.cs +++ b/VisualPinball.Engine/VPT/Bumper/Bumper.cs @@ -16,13 +16,15 @@ using System.IO; using VisualPinball.Engine.Game; +using VisualPinball.Engine.Math; using VisualPinball.Engine.Physics; namespace VisualPinball.Engine.VPT.Bumper { public class Bumper : Item, IRenderable, IHittable, ISwitchable, ICoilable { - public override string ItemType => "Bumper"; + public override string ItemName { get; } = "Bumper"; + public override string ItemGroupName { get; } = "Bumpers"; public bool IsPulseSwitch => true; private readonly BumperMeshGenerator _meshGenerator; @@ -50,11 +52,22 @@ public void Init(Table.Table table) _hits = new HitObject[] {new BumperHit(Data, height, this)}; } + #region IRenderable + + Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + + public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) + { + return _meshGenerator.GetRenderObject(table, id, origin, asRightHanded); + } + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) { return _meshGenerator.GetRenderObjects(table, origin, asRightHanded); } + #endregion + public HitObject[] GetHitShapes() => _hits; public bool IsCollidable => Data.IsCollidable; public bool IsDualWound { get; set; } diff --git a/VisualPinball.Engine/VPT/Bumper/BumperMeshGenerator.cs b/VisualPinball.Engine/VPT/Bumper/BumperMeshGenerator.cs index c8c2d7d4e..bd3875fed 100644 --- a/VisualPinball.Engine/VPT/Bumper/BumperMeshGenerator.cs +++ b/VisualPinball.Engine/VPT/Bumper/BumperMeshGenerator.cs @@ -14,63 +14,78 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +// ReSharper disable CompareOfFloatsByEqualityOperator + using System; -using System.Collections.Generic; using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; using VisualPinball.Engine.Resources.Meshes; namespace VisualPinball.Engine.VPT.Bumper { - internal class BumperMeshGenerator + public class BumperMeshGenerator { - private static readonly Mesh BaseMesh = new Mesh("Base", BumperBase.Vertices, BumperBase.Indices); - private static readonly Mesh CapMesh = new Mesh("Cap", BumperCap.Vertices, BumperCap.Indices); - private static readonly Mesh RingMesh = new Mesh("Ring", BumperRing.Vertices, BumperRing.Indices); - private static readonly Mesh SocketMesh = new Mesh("Skirt", BumperSocket.Vertices, BumperSocket.Indices); + public const string Base = "Base"; + public const string Cap = "Cap"; + public const string Ring = "Ring"; + public const string Skirt = "Skirt"; - private readonly BumperData _data; + private static readonly Mesh BaseMesh = new Mesh(Base, BumperBase.Vertices, BumperBase.Indices); + private static readonly Mesh CapMesh = new Mesh(Cap, BumperCap.Vertices, BumperCap.Indices); + private static readonly Mesh RingMesh = new Mesh(Ring, BumperRing.Vertices, BumperRing.Indices); + private static readonly Mesh SocketMesh = new Mesh(Skirt, BumperSocket.Vertices, BumperSocket.Indices); - private Mesh _scaledBaseMesh; - private Mesh _scaledCapMesh; - private Mesh _scaledRingMesh; - private Mesh _scaledSocketMesh; - private float _generatedScale; + private readonly BumperData _data; internal BumperMeshGenerator(BumperData data) { _data = data; } + public RenderObject GetRenderObject(Table.Table table, string id, Origin origin, bool asRightHanded) + { + var mesh = GetMesh(id, table, origin); + switch (id) { + case Base: + return new RenderObject( + id, + asRightHanded ? mesh.Transform(Matrix3D.RightHanded) : mesh, + new PbrMaterial(table.GetMaterial(_data.BaseMaterial), Texture.BumperBase), + _data.IsBaseVisible + ); + case Cap: + return new RenderObject( + id, + asRightHanded ? mesh.Transform(Matrix3D.RightHanded) : mesh, + new PbrMaterial(table.GetMaterial(_data.CapMaterial), Texture.BumperCap), + _data.IsCapVisible + ); + case Ring: + return new RenderObject( + id, + asRightHanded ? mesh.Transform(Matrix3D.RightHanded) : mesh, + new PbrMaterial(table.GetMaterial(_data.RingMaterial), Texture.BumperRing), + _data.IsRingVisible + ); + case Skirt: + return new RenderObject( + "Skirt", + asRightHanded ? mesh.Transform(Matrix3D.RightHanded) : mesh, + new PbrMaterial(table.GetMaterial(_data.SocketMaterial), Texture.BumperSocket), + _data.IsSocketVisible + ); + } + throw new ArgumentException("Unknown bumper mesh \"" + id + "\"."); + } + + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) { - var meshes = GetMeshes(table, origin); var translationMatrix = GetPostMatrix(origin); - return new RenderObjectGroup(_data.Name, "Bumpers", translationMatrix, - new RenderObject( - "Base", - asRightHanded ? meshes["Base"].Transform(Matrix3D.RightHanded) : meshes["Base"], - new PbrMaterial(table.GetMaterial(_data.BaseMaterial), Texture.BumperBase), - _data.IsBaseVisible - ), - new RenderObject( - "Ring", - asRightHanded ? meshes["Ring"].Transform(Matrix3D.RightHanded) : meshes["Ring"], - new PbrMaterial(table.GetMaterial(_data.RingMaterial), Texture.BumperRing), - _data.IsRingVisible - ), - new RenderObject( - "Skirt", - asRightHanded ? meshes["Skirt"].Transform(Matrix3D.RightHanded) : meshes["Skirt"], - new PbrMaterial(table.GetMaterial(_data.SocketMaterial), Texture.BumperSocket), - _data.IsSocketVisible - ), - new RenderObject( - "Cap", - asRightHanded ? meshes["Cap"].Transform(Matrix3D.RightHanded) : meshes["Cap"], - new PbrMaterial(table.GetMaterial(_data.CapMaterial), Texture.BumperCap), - _data.IsCapVisible - ) + GetRenderObject(table, Base, origin, asRightHanded), + GetRenderObject(table, Cap, origin, asRightHanded), + GetRenderObject(table, Ring, origin, asRightHanded), + GetRenderObject(table, Skirt, origin, asRightHanded) ); } @@ -90,26 +105,34 @@ private Matrix3D GetPostMatrix(Origin origin) } } - private Dictionary GetMeshes(Table.Table table, Origin origin) { + private Mesh GetMesh(string id, Table.Table table, Origin origin) { if (_data.Center == null) { throw new InvalidOperationException($"Cannot export bumper {_data.Name} without center."); } + var matrix = Matrix3D.Identity; var height = table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y) * table.GetScaleZ(); - if (_generatedScale != _data.Radius) { - _scaledBaseMesh = BaseMesh.Clone().MakeScale(_data.Radius, _data.Radius, _data.HeightScale); - _scaledCapMesh = CapMesh.Clone().MakeScale(_data.Radius * 2, _data.Radius * 2, _data.HeightScale); - _scaledRingMesh = RingMesh.Clone().MakeScale(_data.Radius, _data.Radius, _data.HeightScale); - _scaledSocketMesh = SocketMesh.Clone().MakeScale(_data.Radius, _data.Radius, _data.HeightScale); + switch (id) { + case Base: { + var mesh = BaseMesh.Clone().MakeScale(_data.Radius, _data.Radius, _data.HeightScale); + return GenerateMesh(mesh, matrix, z => z * table.GetScaleZ() + height, origin); + } + case Cap: { + var mesh = CapMesh.Clone().MakeScale(_data.Radius * 2, _data.Radius * 2, _data.HeightScale); + return GenerateMesh(mesh, matrix, z => z * table.GetScaleZ() + height, origin); + } + case Ring: { + var mesh = RingMesh.Clone().MakeScale(_data.Radius, _data.Radius, _data.HeightScale); + return GenerateMesh(mesh, matrix, z => z * table.GetScaleZ() + (height + 5.0f), origin); + } + case Skirt: { + var mesh = SocketMesh.Clone().MakeScale(_data.Radius, _data.Radius, _data.HeightScale); + return GenerateMesh(mesh, matrix, z => (z + _data.HeightScale) * table.GetScaleZ() + height, origin); + } } - return new Dictionary { - { "Base", GenerateMesh(_scaledBaseMesh, matrix, z => z * table.GetScaleZ() + height, origin) }, - { "Ring", GenerateMesh(_scaledRingMesh, matrix, z => z * table.GetScaleZ() + height, origin) }, - { "Skirt", GenerateMesh(_scaledSocketMesh, matrix, z => z * table.GetScaleZ() + (height + 5.0f), origin) }, - { "Cap", GenerateMesh(_scaledCapMesh, matrix, z => (z + _data.HeightScale) * table.GetScaleZ() + height, origin) } - }; + throw new ArgumentException("Unknown bumper mesh \"" + id + "\"."); } private Mesh GenerateMesh(Mesh mesh, Matrix3D matrix, Func zPos, Origin origin) { diff --git a/VisualPinball.Engine/VPT/Collection/Collection.cs b/VisualPinball.Engine/VPT/Collection/Collection.cs index 17fa507f5..067fb2e41 100644 --- a/VisualPinball.Engine/VPT/Collection/Collection.cs +++ b/VisualPinball.Engine/VPT/Collection/Collection.cs @@ -20,7 +20,8 @@ namespace VisualPinball.Engine.VPT.Collection { public class Collection : Item { - public override string ItemType => "Collection"; + public override string ItemName { get; } = "Collection"; + public override string ItemGroupName { get; } = "Collections"; public Collection(CollectionData data) : base(data) { diff --git a/VisualPinball.Engine/VPT/Decal/Decal.cs b/VisualPinball.Engine/VPT/Decal/Decal.cs index 782cefcde..ecf1ff5e8 100644 --- a/VisualPinball.Engine/VPT/Decal/Decal.cs +++ b/VisualPinball.Engine/VPT/Decal/Decal.cs @@ -20,7 +20,8 @@ namespace VisualPinball.Engine.VPT.Decal { public class Decal : Item { - public override string ItemType => "Decal"; + public override string ItemName { get; } = "Decal"; + public override string ItemGroupName { get; } = "Decals"; public Decal(DecalData data) : base(data) { diff --git a/VisualPinball.Engine/VPT/DispReel/DispReel.cs b/VisualPinball.Engine/VPT/DispReel/DispReel.cs index fe38b9696..bc8bce2db 100644 --- a/VisualPinball.Engine/VPT/DispReel/DispReel.cs +++ b/VisualPinball.Engine/VPT/DispReel/DispReel.cs @@ -20,7 +20,8 @@ namespace VisualPinball.Engine.VPT.DispReel { public class DispReel : Item { - public override string ItemType => "Disp Reel"; + public override string ItemName { get; } = "Disp Reel"; + public override string ItemGroupName { get; } = "Disp Reels"; public DispReel(DispReelData data) : base(data) { diff --git a/VisualPinball.Engine/VPT/Flasher/Flasher.cs b/VisualPinball.Engine/VPT/Flasher/Flasher.cs index 2b3cac7ec..a0a99ae79 100644 --- a/VisualPinball.Engine/VPT/Flasher/Flasher.cs +++ b/VisualPinball.Engine/VPT/Flasher/Flasher.cs @@ -20,7 +20,8 @@ namespace VisualPinball.Engine.VPT.Flasher { public class Flasher : Item { - public override string ItemType => "Flasher"; + public override string ItemName { get; } = "Flasher"; + public override string ItemGroupName { get; } = "Flashers"; public Flasher(FlasherData data) : base(data) { diff --git a/VisualPinball.Engine/VPT/Flipper/Flipper.cs b/VisualPinball.Engine/VPT/Flipper/Flipper.cs index e46024c9f..993edd99d 100644 --- a/VisualPinball.Engine/VPT/Flipper/Flipper.cs +++ b/VisualPinball.Engine/VPT/Flipper/Flipper.cs @@ -16,13 +16,15 @@ using System.IO; using VisualPinball.Engine.Game; +using VisualPinball.Engine.Math; using VisualPinball.Engine.Physics; namespace VisualPinball.Engine.VPT.Flipper { public class Flipper : Item, IRenderable, IHittable, ISwitchable, ICoilable { - public override string ItemType => "Flasher"; + public override string ItemName { get; } = "Flasher"; + public override string ItemGroupName { get; } = "Flashers"; public bool IsPulseSwitch => false; @@ -49,11 +51,22 @@ public void Init(Table.Table table) _hit = new FlipperHit(Data, table, this); } + #region IRenderable + + Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + + public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) + { + throw new System.NotImplementedException(); + } + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) { return _meshGenerator.GetRenderObjects(table, origin, asRightHanded); } + #endregion + public HitObject[] GetHitShapes() => new HitObject[] { _hit }; public bool IsCollidable => true; public bool IsDualWound { get => Data.IsDualWound; set => Data.IsDualWound = value; } diff --git a/VisualPinball.Engine/VPT/Gate/Gate.cs b/VisualPinball.Engine/VPT/Gate/Gate.cs index 23660efc8..5bca8ef4b 100644 --- a/VisualPinball.Engine/VPT/Gate/Gate.cs +++ b/VisualPinball.Engine/VPT/Gate/Gate.cs @@ -24,7 +24,8 @@ namespace VisualPinball.Engine.VPT.Gate { public class Gate : Item, IRenderable, IHittable, ISwitchable { - public override string ItemType => "Gate"; + public override string ItemName { get; } = "Gate"; + public override string ItemGroupName { get; } = "Gates"; public bool IsPulseSwitch => true; @@ -61,11 +62,22 @@ public void Init(Table.Table table) _hitCircles = _hitGenerator.GenerateBracketHits(height, tangent, this); } + #region IRenderable + + Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + + public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) + { + throw new System.NotImplementedException(); + } + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) { return _meshGenerator.GetRenderObjects(table, origin, asRightHanded); } + #endregion + public HitObject[] GetHitShapes() { return new HitObject[] {_hitGate} diff --git a/VisualPinball.Engine/VPT/HitTarget/HitTarget.cs b/VisualPinball.Engine/VPT/HitTarget/HitTarget.cs index 127288101..04adffc67 100644 --- a/VisualPinball.Engine/VPT/HitTarget/HitTarget.cs +++ b/VisualPinball.Engine/VPT/HitTarget/HitTarget.cs @@ -16,13 +16,15 @@ using System.IO; using VisualPinball.Engine.Game; +using VisualPinball.Engine.Math; using VisualPinball.Engine.Physics; namespace VisualPinball.Engine.VPT.HitTarget { public class HitTarget : Item, IRenderable, IHittable, ISwitchable { - public override string ItemType => "Target"; + public override string ItemName { get; } = "Target"; + public override string ItemGroupName { get; } = "Targets"; public bool IsPulseSwitch => true; @@ -53,11 +55,22 @@ public void Init(Table.Table table) _hits = _hitGenerator.GenerateHitObjects(table, this); } + #region IRenderable + + Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + + public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) + { + throw new System.NotImplementedException(); + } + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) { return _meshGenerator.GetRenderObjects(table, origin, asRightHanded); } + #endregion + public bool IsCollidable => Data.IsCollidable; } } diff --git a/VisualPinball.Engine/VPT/IItem.cs b/VisualPinball.Engine/VPT/IItem.cs index e0cb8cb9c..7e0b04c6d 100644 --- a/VisualPinball.Engine/VPT/IItem.cs +++ b/VisualPinball.Engine/VPT/IItem.cs @@ -24,5 +24,12 @@ public interface IItem string Name { get; } int StorageIndex { get; set; } + + string ItemName { get; } + string ItemGroupName { get; } + + string ComponentName { get; } + ItemSubComponent SubComponent { get; } + string SubName { get; } } } diff --git a/VisualPinball.Engine/VPT/Item.cs b/VisualPinball.Engine/VPT/Item.cs index fef0cfdab..2f66f3712 100644 --- a/VisualPinball.Engine/VPT/Item.cs +++ b/VisualPinball.Engine/VPT/Item.cs @@ -14,26 +14,65 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; + namespace VisualPinball.Engine.VPT { + public enum ItemSubComponent + { + None, Collider, Mesh + } + /// /// The base class for all playfield items (including the table itself) /// /// Data class type this item is using public abstract class Item : IItem where TData : ItemData { - public abstract string ItemType { get; } + public abstract string ItemName { get; } + public abstract string ItemGroupName { get; } public readonly TData Data; - public string Name { get => Data.GetName(); set => Data.SetName(value); } + public string Name + { + get => Data.GetName(); + set + { + Data.SetName(value); + (ComponentName, SubComponent, SubName) = SplitName(); + } + } + public int Index { get; set; } public int Version { get; set; } public int StorageIndex { get => Data.StorageIndex; set => Data.StorageIndex = value; } + public string ComponentName { get; private set; } + public ItemSubComponent SubComponent { get; private set; } + public string SubName { get; private set; } + protected Item(TData data) { Data = data; } + + private (string, ItemSubComponent, string) SplitName() + { + var names = Name.Split(new[] {'_'}, 3, StringSplitOptions.None); + if (names.Length == 1) { + return (Name, ItemSubComponent.None, null); + } + switch (names[1].ToLower()) { + case "collider": + return (names[0], ItemSubComponent.Collider, names.Length > 2 ? names[2] : null); + + case "mesh": + return (names[0], ItemSubComponent.Mesh, names.Length > 2 ? names[2] : null); + + default: + return (Name, ItemSubComponent.None, null); + } + } } } diff --git a/VisualPinball.Engine/VPT/Kicker/Kicker.cs b/VisualPinball.Engine/VPT/Kicker/Kicker.cs index 24738e359..e3bb7aae1 100644 --- a/VisualPinball.Engine/VPT/Kicker/Kicker.cs +++ b/VisualPinball.Engine/VPT/Kicker/Kicker.cs @@ -23,7 +23,8 @@ namespace VisualPinball.Engine.VPT.Kicker { public class Kicker : Item, IRenderable, IBallCreationPosition, IHittable, ISwitchable, ICoilable { - public override string ItemType => "Kicker"; + public override string ItemName { get; } = "Kicker"; + public override string ItemGroupName { get; } = "Kickers"; public bool IsPulseSwitch => false; @@ -58,11 +59,22 @@ public void Init(Table.Table table) _hit = new KickerHit(Data, radius, height, table, this); // height of kicker hit cylinder } + #region IRenderable + + Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + + public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) + { + throw new System.NotImplementedException(); + } + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) { return _meshGenerator.GetRenderObjects(table, origin, asRightHanded); } + #endregion + public HitObject[] GetHitShapes() => new HitObject[] {_hit}; public bool IsCollidable => Data.IsEnabled; diff --git a/VisualPinball.Engine/VPT/Light/Light.cs b/VisualPinball.Engine/VPT/Light/Light.cs index 80ebc29d8..3aa00109f 100644 --- a/VisualPinball.Engine/VPT/Light/Light.cs +++ b/VisualPinball.Engine/VPT/Light/Light.cs @@ -22,7 +22,8 @@ namespace VisualPinball.Engine.VPT.Light { public class Light : Item, IRenderable { - public override string ItemType => "Light"; + public override string ItemName { get; } = "Light"; + public override string ItemGroupName { get; } = "Lights"; public const string BulbMaterialName = "__bulbMaterial"; public const string SocketMaterialName = "__bulbSocketMaterial"; @@ -57,9 +58,20 @@ public static Light GetDefault(Table.Table table) return new Light(lightData); } + #region IRenderable + + Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + + public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) + { + throw new System.NotImplementedException(); + } + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin, bool asRightHanded = true) { return _meshGenerator.GetRenderObjects(table, origin, asRightHanded); } + + #endregion } } diff --git a/VisualPinball.Engine/VPT/LightSeq/LightSeq.cs b/VisualPinball.Engine/VPT/LightSeq/LightSeq.cs index 2e15f8b97..482678d0e 100644 --- a/VisualPinball.Engine/VPT/LightSeq/LightSeq.cs +++ b/VisualPinball.Engine/VPT/LightSeq/LightSeq.cs @@ -20,7 +20,8 @@ namespace VisualPinball.Engine.VPT.LightSeq { public class LightSeq : Item { - public override string ItemType => "Light Sequence"; + public override string ItemName { get; } = "Light Sequence"; + public override string ItemGroupName { get; } = "Light Sequences"; public LightSeq(LightSeqData data) : base(data) { diff --git a/VisualPinball.Engine/VPT/Plunger/Plunger.cs b/VisualPinball.Engine/VPT/Plunger/Plunger.cs index 195285c97..678d72fc0 100644 --- a/VisualPinball.Engine/VPT/Plunger/Plunger.cs +++ b/VisualPinball.Engine/VPT/Plunger/Plunger.cs @@ -16,13 +16,15 @@ using System.IO; using VisualPinball.Engine.Game; +using VisualPinball.Engine.Math; using VisualPinball.Engine.Physics; namespace VisualPinball.Engine.VPT.Plunger { public class Plunger : Item, IRenderable, IHittable, ICoilable { - public override string ItemType => "Plunger"; + public override string ItemName { get; } = "Plunger"; + public override string ItemGroupName { get; } = "Plungers"; public PlungerHit PlungerHit { get; private set; } @@ -56,11 +58,22 @@ public void Init(Table.Table table) _hitObjects = new HitObject[] { PlungerHit }; } + #region IRenderable + + Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + + public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) + { + throw new System.NotImplementedException(); + } + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) { return MeshGenerator.GetRenderObjects(20, table, origin, asRightHanded); } + #endregion + public HitObject[] GetHitShapes() => _hitObjects; public bool IsCollidable => true; diff --git a/VisualPinball.Engine/VPT/Primitive/Primitive.cs b/VisualPinball.Engine/VPT/Primitive/Primitive.cs index 0216612ea..583c6a8bc 100644 --- a/VisualPinball.Engine/VPT/Primitive/Primitive.cs +++ b/VisualPinball.Engine/VPT/Primitive/Primitive.cs @@ -16,6 +16,7 @@ using System.IO; using VisualPinball.Engine.Game; +using VisualPinball.Engine.Math; using VisualPinball.Engine.Physics; namespace VisualPinball.Engine.VPT.Primitive @@ -28,7 +29,8 @@ namespace VisualPinball.Engine.VPT.Primitive /// public class Primitive : Item, IRenderable, IHittable { - public override string ItemType => "Primitive"; + public override string ItemName { get; } = "Primitive"; + public override string ItemGroupName { get; } = "Primitives"; public bool UseAsPlayfield; @@ -57,12 +59,23 @@ public static Primitive GetDefault(Table.Table table) return new Primitive(primitiveData); } + #region IRenderable + + Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin, bool asRightHanded, string parent, PbrMaterial material) => _meshGenerator.GetRenderObjects(table, origin, asRightHanded, parent, material); + public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) + { + throw new System.NotImplementedException(); + } + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) => _meshGenerator.GetRenderObjects(table, origin, asRightHanded); + #endregion + public HitObject[] GetHitShapes() => _hits; public bool IsCollidable => !Data.IsToy && Data.IsCollidable; diff --git a/VisualPinball.Engine/VPT/Ramp/Ramp.cs b/VisualPinball.Engine/VPT/Ramp/Ramp.cs index f0d65d3c1..8fffbb7ed 100644 --- a/VisualPinball.Engine/VPT/Ramp/Ramp.cs +++ b/VisualPinball.Engine/VPT/Ramp/Ramp.cs @@ -23,7 +23,8 @@ namespace VisualPinball.Engine.VPT.Ramp { public class Ramp : Item, IRenderable, IHittable { - public override string ItemType => "Ramp"; + public override string ItemName { get; } = "Ramp"; + public override string ItemGroupName { get; } = "Ramps"; public HitObject[] GetHitShapes() => _hits; @@ -60,11 +61,22 @@ public void Init(Table.Table table) _hits = _hitGenerator.GenerateHitObjects(table, this); } + #region IRenderable + + Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + + public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) + { + throw new System.NotImplementedException(); + } + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) { return _meshGenerator.GetRenderObjects(table, asRightHanded); } + #endregion + public bool IsCollidable => Data.IsCollidable; public float GetSurfaceHeight(float x, float y, Table.Table table) diff --git a/VisualPinball.Engine/VPT/Rubber/Rubber.cs b/VisualPinball.Engine/VPT/Rubber/Rubber.cs index 9703a9c04..918d1f11a 100644 --- a/VisualPinball.Engine/VPT/Rubber/Rubber.cs +++ b/VisualPinball.Engine/VPT/Rubber/Rubber.cs @@ -23,7 +23,8 @@ namespace VisualPinball.Engine.VPT.Rubber { public class Rubber : Item, IRenderable, IHittable { - public override string ItemType => "Rubber"; + public override string ItemName { get; } = "Rubber"; + public override string ItemGroupName { get; } = "Rubbers"; public HitObject[] GetHitShapes() => _hits; @@ -60,11 +61,22 @@ public static Rubber GetDefault(Table.Table table) return new Rubber(rubberData); } + #region IRenderable + + Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + + public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) + { + throw new System.NotImplementedException(); + } + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) { return _meshGenerator.GetRenderObjects(table, origin, asRightHanded); } + #endregion + public bool IsCollidable => Data.IsCollidable; public void Init(Table.Table table) diff --git a/VisualPinball.Engine/VPT/Sound/Sound.cs b/VisualPinball.Engine/VPT/Sound/Sound.cs index d247af27f..4aa684ca4 100644 --- a/VisualPinball.Engine/VPT/Sound/Sound.cs +++ b/VisualPinball.Engine/VPT/Sound/Sound.cs @@ -20,7 +20,8 @@ namespace VisualPinball.Engine.VPT.Sound { public class Sound : Item { - public override string ItemType => "Sound"; + public override string ItemName { get; } = "Sound"; + public override string ItemGroupName { get; } = "Sounds"; public Sound(string name) : this(new SoundData(name)) { diff --git a/VisualPinball.Engine/VPT/Spinner/Spinner.cs b/VisualPinball.Engine/VPT/Spinner/Spinner.cs index a187b9180..17b3f528c 100644 --- a/VisualPinball.Engine/VPT/Spinner/Spinner.cs +++ b/VisualPinball.Engine/VPT/Spinner/Spinner.cs @@ -17,13 +17,17 @@ using System.IO; using System.Linq; using VisualPinball.Engine.Game; +using VisualPinball.Engine.Math; using VisualPinball.Engine.Physics; namespace VisualPinball.Engine.VPT.Spinner { public class Spinner : Item, IRenderable, IHittable, ISwitchable { - public override string ItemType => "Spinner"; + public override string ItemName { get; } = "Spinner"; + public override string ItemGroupName { get; } = "Spinners"; + + public Matrix3D TransformationMatrix { get; } = Matrix3D.Identity; public bool IsPulseSwitch => true; @@ -59,11 +63,22 @@ public void Init(Table.Table table) _hitCircles = _hitGenerator.GetHitCircles(height, this); } + #region IRenderable + + Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + + public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) + { + throw new System.NotImplementedException(); + } + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) { return _meshGenerator.GetRenderObjects(table, origin, asRightHanded); } + #endregion + public HitObject[] GetHitShapes() { return new HitObject[] {_hitSpinner} diff --git a/VisualPinball.Engine/VPT/Surface/Surface.cs b/VisualPinball.Engine/VPT/Surface/Surface.cs index 5cd82153a..a1ca9f3c6 100644 --- a/VisualPinball.Engine/VPT/Surface/Surface.cs +++ b/VisualPinball.Engine/VPT/Surface/Surface.cs @@ -23,7 +23,8 @@ namespace VisualPinball.Engine.VPT.Surface { public class Surface : Item, IRenderable, IHittable { - public override string ItemType => "Wall"; + public override string ItemName { get; } = "Wall"; + public override string ItemGroupName { get; } = "Walls"; public HitObject[] GetHitShapes() => _hits; public bool IsCollidable => Data.IsCollidable; @@ -56,14 +57,25 @@ public static Surface GetDefault(Table.Table table) return new Surface(surfaceData); } - public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) + public void Init(Table.Table table) { - return _meshGenerator.GetRenderObjects(table, asRightHanded); + _hits = _hitGenerator.GenerateHitObjects(table, this); } - public void Init(Table.Table table) + #region IRenderable + + Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + + public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { - _hits = _hitGenerator.GenerateHitObjects(table, this); + throw new System.NotImplementedException(); } + + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) + { + return _meshGenerator.GetRenderObjects(table, asRightHanded); + } + + #endregion } } diff --git a/VisualPinball.Engine/VPT/Surface/SurfaceMeshGenerator.cs b/VisualPinball.Engine/VPT/Surface/SurfaceMeshGenerator.cs index 303bbe4f7..a2f8e803b 100644 --- a/VisualPinball.Engine/VPT/Surface/SurfaceMeshGenerator.cs +++ b/VisualPinball.Engine/VPT/Surface/SurfaceMeshGenerator.cs @@ -22,6 +22,9 @@ namespace VisualPinball.Engine.VPT.Surface { public class SurfaceMeshGenerator { + public const string Side = "Side"; + public const string Top = "Top"; + private readonly SurfaceData _data; public SurfaceMeshGenerator(SurfaceData data) diff --git a/VisualPinball.Engine/VPT/Table/Table.cs b/VisualPinball.Engine/VPT/Table/Table.cs index 12b16fdb7..b0ebeb038 100644 --- a/VisualPinball.Engine/VPT/Table/Table.cs +++ b/VisualPinball.Engine/VPT/Table/Table.cs @@ -34,7 +34,8 @@ namespace VisualPinball.Engine.VPT.Table ///
public class Table : Item, IRenderable, IHittable { - public override string ItemType => "Table"; + public override string ItemName { get; } = "Table"; + public override string ItemGroupName { get; } = "Tables"; public CustomInfoTags CustomInfoTags { get; set; } public int FileVersion { get; set; } @@ -496,11 +497,22 @@ public Table(TableData data) : base(data) public Table(BinaryReader reader) : this(new TableData(reader)) { } + #region IRenderable + + Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + + public RenderObject GetRenderObject(Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) + { + throw new NotImplementedException(); + } + public RenderObjectGroup GetRenderObjects(Table table, Origin origin = Origin.Global, bool asRightHanded = true) { return _meshGenerator.GetRenderObjects(table, origin, asRightHanded); } + #endregion + public HitObject[] GetHitShapes() => _hitGenerator.GenerateHitObjects(this).ToArray(); public bool IsCollidable => true; diff --git a/VisualPinball.Engine/VPT/TextBox/TextBox.cs b/VisualPinball.Engine/VPT/TextBox/TextBox.cs index f474a2357..aea62886c 100644 --- a/VisualPinball.Engine/VPT/TextBox/TextBox.cs +++ b/VisualPinball.Engine/VPT/TextBox/TextBox.cs @@ -20,7 +20,8 @@ namespace VisualPinball.Engine.VPT.TextBox { public class TextBox : Item { - public override string ItemType => "Text Box"; + public override string ItemName { get; } = "Text Box"; + public override string ItemGroupName { get; } = "Text Boxes"; public TextBox(TextBoxData data) : base(data) { diff --git a/VisualPinball.Engine/VPT/Texture.cs b/VisualPinball.Engine/VPT/Texture.cs index 1d6c32c91..dd1b804b6 100644 --- a/VisualPinball.Engine/VPT/Texture.cs +++ b/VisualPinball.Engine/VPT/Texture.cs @@ -25,7 +25,8 @@ namespace VisualPinball.Engine.VPT { public class Texture : Item { - public override string ItemType => "Texture"; + public override string ItemName { get; } = "Texture"; + public override string ItemGroupName { get; } = "Textures"; public static readonly Texture BallDebug = new Texture(Resource.BallDebug); public static readonly Texture BumperBase = new Texture(Resource.BumperBase); diff --git a/VisualPinball.Engine/VPT/Timer/Timer.cs b/VisualPinball.Engine/VPT/Timer/Timer.cs index ee419db7f..bd6999cba 100644 --- a/VisualPinball.Engine/VPT/Timer/Timer.cs +++ b/VisualPinball.Engine/VPT/Timer/Timer.cs @@ -20,7 +20,8 @@ namespace VisualPinball.Engine.VPT.Timer { public class Timer : Item { - public override string ItemType => "Timer"; + public override string ItemName { get; } = "Timer"; + public override string ItemGroupName { get; } = "Timers"; public Timer(TimerData data) : base(data) { diff --git a/VisualPinball.Engine/VPT/Trigger/Trigger.cs b/VisualPinball.Engine/VPT/Trigger/Trigger.cs index dd9de1435..acd934077 100644 --- a/VisualPinball.Engine/VPT/Trigger/Trigger.cs +++ b/VisualPinball.Engine/VPT/Trigger/Trigger.cs @@ -23,7 +23,8 @@ namespace VisualPinball.Engine.VPT.Trigger { public class Trigger : Item, IRenderable, IHittable, ISwitchable { - public override string ItemType => "Trigger"; + public override string ItemName { get; } = "Trigger"; + public override string ItemGroupName { get; } = "Triggers"; public bool IsPulseSwitch => false; @@ -63,9 +64,20 @@ public void Init(Table.Table table) _hits = _hitGenerator.GenerateHitObjects(table, this); } + #region IRenderable + + Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + + public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) + { + throw new System.NotImplementedException(); + } + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) { return _meshGenerator.GetRenderObjects(table, origin, asRightHanded); } + + #endregion } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs index 8b89cc2ef..8f535d849 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs @@ -184,17 +184,17 @@ private void CreateItem(Func create, string actionName) whe private GameObject CreateRenderable(IRenderable renderable) { - var rog = renderable.GetRenderObjects(_tableAuthoring.Table, Origin.Original, false); - VpxConverter.ConvertRenderObjects(rog, GetOrCreateParent(_tableAuthoring, rog), _tableAuthoring, out var obj); - VpxConverter.SetupGameObjectComponents(renderable, obj, rog, null); + //var rog = renderable.GetRenderObjects(_table.Table, Origin.Original, false); + var obj = VpxConverter.CreateGameObjects(renderable, GetOrCreateParent(_tableAuthoring, renderable), _tableAuthoring); + VpxConverter.SetupGameObjects(renderable, obj); return obj; } - private static GameObject GetOrCreateParent(Component tb, RenderObjectGroup rog) + private static GameObject GetOrCreateParent(Component tb, IItem renderable) { - var parent = tb.gameObject.transform.Find(rog.Parent)?.gameObject; + var parent = tb.gameObject.transform.Find(renderable.ItemGroupName)?.gameObject; if (parent == null) { - parent = new GameObject(rog.Parent); + parent = new GameObject(renderable.ItemGroupName); parent.transform.parent = tb.gameObject.transform; parent.transform.localPosition = Vector3.zero; parent.transform.localRotation = Quaternion.identity; diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index ef53be101..ae1f7d37b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -56,7 +56,7 @@ public class VpxConverter : MonoBehaviour private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - private readonly Dictionary _renderObjects = new Dictionary(); + //private readonly Dictionary _renderObjects = new Dictionary(); private readonly Dictionary _parents = new Dictionary(); private Table _table; @@ -75,13 +75,11 @@ public void Convert(string fileName, Table table, bool applyPatch = true, string MakeSerializable(go, table); - // set the gameobject name; this needs to happen after MakeSerializable because the name is set there as well - if( string.IsNullOrEmpty( tableName)) - { + // set the GameObject name; this needs to happen after MakeSerializable because the name is set there as well + if (string.IsNullOrEmpty(tableName)) { go.name = _table.Name; - } - else - { + + } else { go.name = tableName .Replace("%TABLENAME%", _table.Name) .Replace("%INFONAME%", _table.InfoName); @@ -90,15 +88,15 @@ public void Convert(string fileName, Table table, bool applyPatch = true, string _tableAuthoring.Patcher = new Patcher.Patcher(_table, fileName); // generate meshes and save (pbr) materials - var materials = new Dictionary(); - foreach (var r in _table.Renderables) { - _renderObjects[r] = r.GetRenderObjects(_table, Origin.Original, false); - foreach (var ro in _renderObjects[r].RenderObjects) { - if (!materials.ContainsKey(ro.Material.Id)) { - materials[ro.Material.Id] = ro.Material; - } - } - } + // var materials = new Dictionary(); + // foreach (var r in _table.Renderables) { + // _renderObjects[r] = r.GetRenderObjects(_table, Origin.Original, false); + // foreach (var ro in _renderObjects[r].RenderObjects) { + // if (!materials.ContainsKey(ro.Material.Id)) { + // materials[ro.Material.Id] = ro.Material; + // } + // } + // } // import ConvertGameItems(go); @@ -124,147 +122,137 @@ public void Convert(string fileName, Table table, bool applyPatch = true, string } private void ConvertGameItems(GameObject tableGameObject) - { - // convert game objects - ConvertRenderables(tableGameObject); - } - - private void ConvertRenderables(GameObject tableGameObject) { var createMainObjs = new Dictionary(); - var createdMainMbs = new Dictionary(); - var createdObjs = new Dictionary>>(); - var renderObjects = from entry - in _renderObjects orderby entry.Value.SubComponent select entry; - - foreach (var kv in renderObjects) { - var renderable = kv.Key; - var rog = kv.Value; - - // create item type parent - if (!_parents.ContainsKey(rog.Parent)) { - var parent = new GameObject(rog.Parent); + var createdMainMbs = new Dictionary(); + var renderables = from renderable in _table.Renderables + orderby renderable.SubComponent + select renderable; + + foreach (var renderable in renderables) { + + // create group parent if not created + if (!_parents.ContainsKey(renderable.ItemGroupName)) { + var parent = new GameObject(renderable.ItemGroupName); parent.transform.parent = gameObject.transform; - _parents[rog.Parent] = parent; + _parents[renderable.ItemGroupName] = parent; } // create object(s) - createdObjs[renderable] = ConvertRenderObjects(rog, _parents[rog.Parent], _tableAuthoring, out var rootObj); + var rootObj = CreateGameObjects(renderable, _parents[renderable.ItemGroupName], _tableAuthoring); // if the object's names was parsed to be part of another object, re-link to other object. - if (rog.SubComponent != RenderObjectGroup.ItemSubComponent.None) { - if (!createMainObjs.ContainsKey(rog.ComponentName.ToLower())) { - Logger.Warn($"Cannot find component \"{rog.ComponentName.ToLower()}\" that is supposed to be the parent of \"{rog.Name}\"."); - SetupGameObjectComponents(renderable, rootObj, rog); + if (renderable.SubComponent != ItemSubComponent.None) { - } else { - var mainObj = createMainObjs[rog.ComponentName.ToLower()]; - var mainMb = createdMainMbs[rog.ComponentName.ToLower()]; + var parentName = renderable.ComponentName.ToLower(); + if (createMainObjs.ContainsKey(parentName)) { + var mainObj = createMainObjs[parentName]; + var mainMb = createdMainMbs[parentName]; rootObj.transform.SetParent(mainObj.transform, false); - SetupGameObjectComponents(renderable, rootObj, rog, mainMb); + SetupGameObjects(renderable, rootObj, mainMb); + + } else { + Logger.Warn($"Cannot find component \"{parentName}\" that is supposed to be the parent of \"{renderable.Name}\"."); + SetupGameObjects(renderable, rootObj); } } else { - var rootMb = SetupGameObjectComponents(renderable, rootObj, rog); - createMainObjs[rog.Name.ToLower()] = rootObj; - createdMainMbs[rog.Name.ToLower()] = rootMb; + var rootMb = SetupGameObjects(renderable, rootObj); + createMainObjs[renderable.Name.ToLower()] = rootObj; + createdMainMbs[renderable.Name.ToLower()] = rootMb; } } // now we have all renderables imported, patch them. - foreach (var renderable in createdObjs.Keys) { - foreach (var (obj, ro) in createdObjs[renderable]) { - _tableAuthoring.Patcher.ApplyPatches(renderable, ro, obj, tableGameObject); - } - } + // foreach (var renderable in createdObjs.Keys) { + // foreach (var (obj, ro) in createdObjs[renderable]) { + // _tableAuthoring.Patcher.ApplyPatches(renderable, ro, obj, tableGameObject); + // } + // } } - public static IEnumerable> ConvertRenderObjects(RenderObjectGroup rog, - GameObject parent, TableAuthoring tb, out GameObject obj) + public static GameObject CreateGameObjects(IRenderable renderable, GameObject parent, TableAuthoring tb) { - obj = new GameObject(rog.Name); + var obj = new GameObject(renderable.Name); obj.transform.parent = parent.transform; - var createdObjs = rog.SubComponent == RenderObjectGroup.ItemSubComponent.Collider - ? new Tuple[0] - : SetupRenderObject(obj, rog, tb); + SetupGameObjects(renderable, obj); // apply transformation - obj.transform.SetFromMatrix(rog.TransformationMatrix.ToUnityMatrix()); + obj.transform.SetFromMatrix(renderable.TransformationMatrix(Origin.Original).ToUnityMatrix()); - return createdObjs; + return obj; } - public static MonoBehaviour SetupGameObjectComponents(IRenderable item, GameObject obj, - RenderObjectGroup rog, MonoBehaviour mainMb = null) + public static IItemMainAuthoring SetupGameObjects(IRenderable item, GameObject obj, IItemMainAuthoring parentAuthoring = null) { - MonoBehaviour mb = null; + IItemMainAuthoring mainAuthoring = null; switch (item) { - case Bumper bumper: bumper.SetupGameObject(obj, rog); break; - case Flipper flipper: flipper.SetupGameObject(obj, rog); break; - case Gate gate: gate.SetupGameObject(obj, rog); break; - case HitTarget hitTarget: hitTarget.SetupGameObject(obj, rog); break; - case Kicker kicker: kicker.SetupGameObject(obj, rog); break; - case Engine.VPT.Light.Light lt: lt.SetupGameObject(obj, rog); break; - case Plunger plunger: plunger.SetupGameObject(obj, rog); break; - case Primitive primitive: primitive.SetupGameObject(obj, rog); break; - case Ramp ramp: ramp.SetupGameObject(obj, rog); break; - case Rubber rubber: mb = rubber.SetupGameObject(obj, rog, mainMb); break; - case Spinner spinner: spinner.SetupGameObject(obj, rog); break; - case Surface surface: mb = surface.SetupGameObject(obj, rog, mainMb); break; - case Table table: table.SetupGameObject(obj, rog); break; - case Trigger trigger: trigger.SetupGameObject(obj, rog); break; - } - - return mb; - } - - private static IEnumerable> SetupRenderObject(GameObject obj, RenderObjectGroup rog, TableAuthoring tb) - { - var createdObjs = new Tuple[0]; - if (rog.HasOnlyChild && !rog.ForceChild) { - SetupMesh(obj, rog.RenderObjects[0], tb); - createdObjs = new[] { new Tuple(obj, rog.RenderObjects[0]) }; - - } else if (rog.HasChildren) { - createdObjs = new Tuple[rog.RenderObjects.Length]; - var i = 0; - foreach (var ro in rog.RenderObjects) { - var subObj = new GameObject(ro.Name); - subObj.transform.SetParent(obj.transform, false); - subObj.layer = ChildObjectsLayer; - SetupMesh(subObj, ro, tb); - createdObjs[i++] = new Tuple(subObj, ro); - } + case Bumper bumper: bumper.SetupGameObject(obj); break; + case Flipper flipper: flipper.SetupGameObject(obj); break; + case Gate gate: gate.SetupGameObject(obj); break; + case HitTarget hitTarget: hitTarget.SetupGameObject(obj); break; + case Kicker kicker: kicker.SetupGameObject(obj); break; + case Engine.VPT.Light.Light lt: lt.SetupGameObject(obj); break; + case Plunger plunger: plunger.SetupGameObject(obj); break; + case Primitive primitive: primitive.SetupGameObject(obj); break; + case Ramp ramp: ramp.SetupGameObject(obj); break; + case Rubber rubber: mainAuthoring = rubber.SetupGameObject(obj, parentAuthoring); break; + case Spinner spinner: spinner.SetupGameObject(obj); break; + case Surface surface: mainAuthoring = surface.SetupGameObject(obj, parentAuthoring); break; + case Table table: table.SetupGameObject(obj); break; + case Trigger trigger: trigger.SetupGameObject(obj); break; } - return createdObjs; + return mainAuthoring; } - private static void SetupMesh(GameObject obj, RenderObject ro, TableAuthoring ta) - { - if (ro.Mesh == null) { - Logger.Warn($"No mesh for object {obj.name}, skipping."); - return; - } - - var mesh = ro.Mesh.ToUnityMesh($"{obj.name}_mesh"); - - // apply mesh to game object - var mf = obj.AddComponent(); - mf.sharedMesh = mesh; - - // apply material - if (ro.Mesh.AnimationFrames.Count > 0) { - var smr = obj.AddComponent(); - smr.sharedMaterial = ro.Material.ToUnityMaterial(ta); - smr.sharedMesh = mesh; - smr.enabled = ro.IsVisible; - } else { - var mr = obj.AddComponent(); - mr.sharedMaterial = ro.Material.ToUnityMaterial(ta); - mr.enabled = ro.IsVisible; - } - } + // private static IEnumerable> SetupRenderObject(GameObject obj, RenderObjectGroup rog, TableAuthoring tb) + // { + // var createdObjs = new Tuple[0]; + // if (rog.HasOnlyChild && !rog.ForceChild) { + // SetupMesh(obj, rog.RenderObjects[0], tb); + // createdObjs = new[] { new Tuple(obj, rog.RenderObjects[0]) }; + // + // } else if (rog.HasChildren) { + // createdObjs = new Tuple[rog.RenderObjects.Length]; + // var i = 0; + // foreach (var ro in rog.RenderObjects) { + // var subObj = new GameObject(ro.Name); + // subObj.transform.SetParent(obj.transform, false); + // subObj.layer = ChildObjectsLayer; + // SetupMesh(subObj, ro, tb); + // createdObjs[i++] = new Tuple(subObj, ro); + // } + // } + // + // return createdObjs; + // } + + // private static void SetupMesh(GameObject obj, RenderObject ro, TableAuthoring ta) + // { + // if (ro.Mesh == null) { + // Logger.Warn($"No mesh for object {obj.name}, skipping."); + // return; + // } + // + // var mesh = ro.Mesh.ToUnityMesh($"{obj.name}_mesh"); + // + // // apply mesh to game object + // var mf = obj.AddComponent(); + // mf.sharedMesh = mesh; + // + // // apply material + // if (ro.Mesh.AnimationFrames.Count > 0) { + // var smr = obj.AddComponent(); + // smr.sharedMaterial = ro.Material.ToUnityMaterial(ta); + // smr.sharedMesh = mesh; + // smr.enabled = ro.IsVisible; + // } else { + // var mr = obj.AddComponent(); + // mr.sharedMaterial = ro.Material.ToUnityMaterial(ta); + // mr.enabled = ro.IsVisible; + // } + // } private void MakeSerializable(GameObject go, Table table) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs new file mode 100644 index 000000000..30e81674c --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs @@ -0,0 +1,29 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Bumper; +using VisualPinball.Engine.VPT.Rubber; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Bumper Base Mesh")] + public class BumperBaseMeshAuthoring : ItemMeshAuthoring + { + protected override string MeshId => BumperMeshGenerator.Base; + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs.meta new file mode 100644 index 000000000..4bee6d089 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 955bc2ef2a84c584aa03779c70557bc2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs new file mode 100644 index 000000000..634a087a0 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs @@ -0,0 +1,29 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Bumper; +using VisualPinball.Engine.VPT.Rubber; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Bumper Cap Mesh")] + public class BumperCapMeshAuthoring : ItemMeshAuthoring + { + protected override string MeshId => BumperMeshGenerator.Cap; + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs.meta new file mode 100644 index 000000000..af4ca1d0f --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eb55626f486f7194a8bc220d453410da +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs index 01614ede9..af51c1020 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs @@ -17,20 +17,27 @@ using Unity.Entities; using UnityEngine; using VisualPinball.Engine.Game; +using VisualPinball.Engine.VPT.Bumper; namespace VisualPinball.Unity { internal static class BumperExtensions { - public static BumperAuthoring SetupGameObject(this Engine.VPT.Bumper.Bumper bumper, GameObject obj, RenderObjectGroup rog) + public static BumperAuthoring SetupGameObject(this Engine.VPT.Bumper.Bumper bumper, GameObject obj) { var ic = obj.AddComponent().SetItem(bumper); obj.AddComponent(); - var ring = obj.transform.Find("Ring").gameObject; - var skirt = obj.transform.Find("Skirt").gameObject; + var bse = obj.transform.Find(BumperMeshGenerator.Base).gameObject; + var cap = obj.transform.Find(BumperMeshGenerator.Cap).gameObject; + var ring = obj.transform.Find(BumperMeshGenerator.Ring).gameObject; + var skirt = obj.transform.Find(BumperMeshGenerator.Skirt).gameObject; + bse.AddComponent(); + cap.AddComponent(); + ring.AddComponent(); + skirt.AddComponent(); ring.AddComponent(); skirt.AddComponent(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs new file mode 100644 index 000000000..8e454c3a1 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs @@ -0,0 +1,29 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Bumper; +using VisualPinball.Engine.VPT.Rubber; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Bumper Ring Mesh")] + public class BumperRingMeshAuthoring : ItemMeshAuthoring + { + protected override string MeshId => BumperMeshGenerator.Ring; + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs.meta new file mode 100644 index 000000000..60157d777 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 46a59794fbf90b54bb87efb8cb1a3bfa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs new file mode 100644 index 000000000..044dcfc67 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs @@ -0,0 +1,29 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Bumper; +using VisualPinball.Engine.VPT.Rubber; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Bumper Skirt Mesh")] + public class BumperSkirtMeshAuthoring : ItemMeshAuthoring + { + protected override string MeshId => BumperMeshGenerator.Skirt; + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs.meta new file mode 100644 index 000000000..a8efe229e --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1cba38e7e4ae1584196f6c9a0abcf4d1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs index 6207659c1..2a63fc5b4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs @@ -22,7 +22,7 @@ namespace VisualPinball.Unity { internal static class FlipperExtensions { - public static FlipperAuthoring SetupGameObject(this Engine.VPT.Flipper.Flipper flipper, GameObject obj, RenderObjectGroup rog) + public static FlipperAuthoring SetupGameObject(this Engine.VPT.Flipper.Flipper flipper, GameObject obj) { var ic = obj.AddComponent().SetItem(flipper); obj.AddComponent(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs index aa9b56f95..533be42eb 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs @@ -22,7 +22,7 @@ namespace VisualPinball.Unity { internal static class GateExtensions { - public static GateAuthoring SetupGameObject(this Engine.VPT.Gate.Gate gate, GameObject obj, RenderObjectGroup rog) + public static GateAuthoring SetupGameObject(this Engine.VPT.Gate.Gate gate, GameObject obj) { var ic = obj.AddComponent().SetItem(gate); obj.AddComponent(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs index 898aa0963..c5e2f3d2e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs @@ -22,7 +22,7 @@ namespace VisualPinball.Unity { internal static class HitTargetExtensions { - public static HitTargetAuthoring SetupGameObject(this Engine.VPT.HitTarget.HitTarget hitTarget, GameObject obj, RenderObjectGroup rog) + public static HitTargetAuthoring SetupGameObject(this Engine.VPT.HitTarget.HitTarget hitTarget, GameObject obj) { var ic = obj.AddComponent().SetItem(hitTarget); obj.AddComponent(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs index 3a7a183c3..62a8e1e35 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs @@ -70,7 +70,7 @@ public abstract class ItemAuthoring : MonoBehaviour ///
public ItemData ItemData => Data; - public string ItemType => Item.ItemType; + public string ItemType => Item.ItemName; public bool IsLocked { get => Data.IsLocked; set => Data.IsLocked = value; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs index 2c3add2b9..c32d079a0 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs @@ -41,7 +41,7 @@ public abstract class ItemMainAuthoring : ItemAuthoring SetItem(TItem item, string gameObjectName = null) + public IItemMainAuthoring SetItem(TItem item, string gameObjectName = null) { _item = item; _data = item.Data; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs index a768e3131..7b55cbfeb 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs @@ -26,12 +26,12 @@ namespace VisualPinball.Unity { - public abstract class ItemMeshAuthoring : ItemSubAuthoring + public abstract class ItemMeshAuthoring : ItemSubAuthoring, IItemMeshAuthoring where TData : ItemData where TItem : Item, IHittable, IRenderable where TAuthoring : ItemMainAuthoring { - + protected virtual string MeshId => null; #region Creation and destruction @@ -43,9 +43,7 @@ private void Awake() { if (!_meshCreated && gameObject.GetComponent() == null) { var ta = GetComponentInParent(); - - var rog = Item.GetRenderObjects(ta.Table); - var ro = rog.RenderObjects[0]; + var ro = Item.GetRenderObject(ta.Table, MeshId); var mesh = ro.Mesh.ToUnityMesh($"{gameObject.name}_Mesh"); // apply mesh to game object diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs index c2f05f43d..9fbd2d233 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs @@ -22,7 +22,7 @@ namespace VisualPinball.Unity { internal static class KickerExtensions { - public static KickerAuthoring SetupGameObject(this Engine.VPT.Kicker.Kicker kicker, GameObject obj, RenderObjectGroup rog) + public static KickerAuthoring SetupGameObject(this Engine.VPT.Kicker.Kicker kicker, GameObject obj) { var ic = obj.AddComponent().SetItem(kicker); obj.AddComponent(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs index 0fdd53c4e..42558e3e6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs @@ -21,7 +21,7 @@ namespace VisualPinball.Unity { internal static class LightExtensions { - public static LightAuthoring SetupGameObject(this Engine.VPT.Light.Light light, GameObject obj, RenderObjectGroup rog) + public static LightAuthoring SetupGameObject(this Engine.VPT.Light.Light light, GameObject obj) { var ic = obj.AddComponent().SetItem(light); return ic as LightAuthoring; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs index bf11d19c1..1225ff8d5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs @@ -23,7 +23,7 @@ namespace VisualPinball.Unity { internal static class PlungerExtensions { - public static PlungerAuthoring SetupGameObject(this Plunger plunger, GameObject obj, RenderObjectGroup rog) + public static PlungerAuthoring SetupGameObject(this Plunger plunger, GameObject obj) { var ic = obj.AddComponent().SetItem(plunger); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs index 242eba235..2c1825c00 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs @@ -23,7 +23,7 @@ namespace VisualPinball.Unity { internal static class PrimitiveExtensions { - public static PrimitiveAuthoring SetupGameObject(this Primitive primitive, GameObject obj, RenderObjectGroup rog) + public static PrimitiveAuthoring SetupGameObject(this Primitive primitive, GameObject obj) { var ic = obj.AddComponent().SetItem(primitive); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs index 3ca2085e8..d1ddca260 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs @@ -22,7 +22,7 @@ namespace VisualPinball.Unity { internal static class RampExtensions { - public static RampAuthoring SetupGameObject(this Engine.VPT.Ramp.Ramp ramp, GameObject obj, RenderObjectGroup rog) + public static RampAuthoring SetupGameObject(this Engine.VPT.Ramp.Ramp ramp, GameObject obj) { var ic = obj.AddComponent().SetItem(ramp); obj.AddComponent(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs index 561e0319c..b0f898ef4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs @@ -31,11 +31,13 @@ namespace VisualPinball.Unity { [ExecuteAlways] [AddComponentMenu("Visual Pinball/Rubber")] - public class RubberAuthoring : ItemMainAuthoring, IDragPointsEditable, IHittableAuthoring, IConvertGameObjectToEntity + public class RubberAuthoring : ItemMainAuthoring, + IDragPointsEditable, IHittableAuthoring, IMeshAuthoring, IConvertGameObjectToEntity { protected override Rubber InstantiateItem(RubberData data) => new Rubber(data); public IHittable Hittable => Item; + public IRenderable Renderable => Item; private void OnDestroy() { @@ -52,6 +54,14 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterRubber(Item, entity, gameObject); } + public void RemoveMeshComponent() + { + var rc = gameObject.GetComponent(); + if (rc != null) { + DestroyImmediate(rc); + } + } + public void RemoveHittableComponent() { var hc = gameObject.GetComponent(); @@ -103,5 +113,6 @@ public override void SetEditorRotation(Vector3 rot) public bool PointsAreLooping() => true; public IEnumerable GetDragPointExposition() => new[] { DragPointExposure.Smooth }; public ItemDataTransformType GetHandleType() => ItemDataTransformType.TwoD; + } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs index d4eb6f63e..a950c06ca 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs @@ -18,32 +18,33 @@ using Unity.Entities; using UnityEngine; using VisualPinball.Engine.Game; +using VisualPinball.Engine.VPT; namespace VisualPinball.Unity { internal static class RubberExtensions { - public static MonoBehaviour SetupGameObject(this Engine.VPT.Rubber.Rubber rubber, GameObject obj, - RenderObjectGroup rog, MonoBehaviour mainMb) + public static IItemMainAuthoring SetupGameObject(this Engine.VPT.Rubber.Rubber rubber, GameObject obj, IItemMainAuthoring parentAuthoring) { - MonoBehaviour mb = obj.AddComponent().SetItem(rubber); - switch (rog.SubComponent) { - case RenderObjectGroup.ItemSubComponent.None: + var mainAuthoring = obj.AddComponent().SetItem(rubber); + + switch (rubber.SubComponent) { + case ItemSubComponent.None: obj.AddComponent(); obj.AddComponent(); break; - case RenderObjectGroup.ItemSubComponent.Collider: { + case ItemSubComponent.Collider: { obj.AddComponent(); - if (mainMb != null && mainMb is IHittableAuthoring hittableAuthoring) { + if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { hittableAuthoring.RemoveHittableComponent(); } break; } - case RenderObjectGroup.ItemSubComponent.Mesh: { + case ItemSubComponent.Mesh: { obj.AddComponent(); - if (mainMb != null && mainMb is IMeshAuthoring meshAuthoring) { + if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { meshAuthoring.RemoveMeshComponent(); } break; @@ -53,7 +54,7 @@ public static MonoBehaviour SetupGameObject(this Engine.VPT.Rubber.Rubber rubber throw new ArgumentOutOfRangeException(); } obj.AddComponent(); - return mb; + return mainAuthoring; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs index 785619adf..e55bdd227 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs @@ -22,7 +22,7 @@ namespace VisualPinball.Unity { internal static class SpinnerExtensions { - public static SpinnerAuthoring SetupGameObject(this Engine.VPT.Spinner.Spinner spinner, GameObject obj, RenderObjectGroup rog) + public static SpinnerAuthoring SetupGameObject(this Engine.VPT.Spinner.Spinner spinner, GameObject obj) { var ic = obj.AddComponent().SetItem(spinner); obj.AddComponent(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs index cc4cd4a4e..bced8a0b1 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs @@ -17,33 +17,36 @@ using System; using Unity.Entities; using UnityEngine; -using VisualPinball.Engine.Game; +using VisualPinball.Engine.VPT; +using VisualPinball.Engine.VPT.Surface; namespace VisualPinball.Unity { internal static class SurfaceExtensions { - public static MonoBehaviour SetupGameObject(this Engine.VPT.Surface.Surface surface, GameObject obj, - RenderObjectGroup rog, MonoBehaviour mainMb) + public static IItemMainAuthoring SetupGameObject(this Surface surface, GameObject obj, IItemMainAuthoring parentAuthoring) { - MonoBehaviour mb = obj.AddComponent().SetItem(surface); - switch (rog.SubComponent) { - case RenderObjectGroup.ItemSubComponent.None: + var mainAuthoring = obj.AddComponent().SetItem(surface); + + switch (surface.SubComponent) { + case ItemSubComponent.None: obj.AddComponent(); - //obj.AddComponent(); + CreateChild(obj, SurfaceMeshGenerator.Side); + CreateChild(obj, SurfaceMeshGenerator.Top); break; - case RenderObjectGroup.ItemSubComponent.Collider: { + case ItemSubComponent.Collider: { obj.AddComponent(); - if (mainMb != null && mainMb is IHittableAuthoring hittableAuthoring) { + if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { hittableAuthoring.RemoveHittableComponent(); } break; } - case RenderObjectGroup.ItemSubComponent.Mesh: { - //obj.AddComponent(); - if (mainMb != null && mainMb is IMeshAuthoring meshAuthoring) { + case ItemSubComponent.Mesh: { + CreateChild(obj, SurfaceMeshGenerator.Side); + CreateChild(obj, SurfaceMeshGenerator.Top); + if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { meshAuthoring.RemoveMeshComponent(); } break; @@ -53,7 +56,16 @@ public static MonoBehaviour SetupGameObject(this Engine.VPT.Surface.Surface surf throw new ArgumentOutOfRangeException(); } obj.AddComponent(); - return mb; + return mainAuthoring; + } + + private static GameObject CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring + { + var subObj = new GameObject(name); + subObj.transform.SetParent(obj.transform, false); + subObj.AddComponent(); + //subObj.layer = ChildObjectsLayer; + return subObj; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceSideMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceSideMeshAuthoring.cs new file mode 100644 index 000000000..b2412eecc --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceSideMeshAuthoring.cs @@ -0,0 +1,30 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Bumper; +using VisualPinball.Engine.VPT.Rubber; +using VisualPinball.Engine.VPT.Surface; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Surface Side Mesh")] + public class SurfaceSideMeshAuthoring : ItemMeshAuthoring + { + protected override string MeshId => SurfaceMeshGenerator.Side; + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceTopMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceTopMeshAuthoring.cs new file mode 100644 index 000000000..5e5168364 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceTopMeshAuthoring.cs @@ -0,0 +1,30 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Bumper; +using VisualPinball.Engine.VPT.Rubber; +using VisualPinball.Engine.VPT.Surface; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Surface Top Mesh")] + public class SurfaceTopMeshAuthoring : ItemMeshAuthoring + { + protected override string MeshId => SurfaceMeshGenerator.Top; + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableExtensions.cs index 0ec06e0b9..177d8a57f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableExtensions.cs @@ -22,7 +22,7 @@ namespace VisualPinball.Unity { internal static class TableExtensions { - public static MonoBehaviour SetupGameObject(this Engine.VPT.Table.Table table, GameObject obj, RenderObjectGroup rog) + public static MonoBehaviour SetupGameObject(this Engine.VPT.Table.Table table, GameObject obj) { var ic = obj.AddComponent(); obj.AddComponent(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs index f5607242c..f714fe7f3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs @@ -22,7 +22,7 @@ namespace VisualPinball.Unity { internal static class TriggerExtensions { - public static TriggerAuthoring SetupGameObject(this Engine.VPT.Trigger.Trigger trigger, GameObject obj, RenderObjectGroup rog) + public static TriggerAuthoring SetupGameObject(this Engine.VPT.Trigger.Trigger trigger, GameObject obj) { var ic = obj.AddComponent().SetItem(trigger); obj.AddComponent(); From 6f7f38ec8a72f128ca1d9b260293840cf813ee1a Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 5 Oct 2020 01:14:31 +0200 Subject: [PATCH 040/124] bumper: Fix tests. --- .../VPT/Primitive/PrimitiveDataTests.cs | 12 +- .../VPT/Bumper/BumperMeshGenerator.cs | 96 +++++--- VisualPinball.Engine/VPT/Surface/Surface.cs | 2 +- .../VPT/Surface/SurfaceMeshGenerator.cs | 210 ++++++++++-------- 4 files changed, 200 insertions(+), 120 deletions(-) diff --git a/VisualPinball.Engine.Test/VPT/Primitive/PrimitiveDataTests.cs b/VisualPinball.Engine.Test/VPT/Primitive/PrimitiveDataTests.cs index a5ff79789..eb02341cb 100644 --- a/VisualPinball.Engine.Test/VPT/Primitive/PrimitiveDataTests.cs +++ b/VisualPinball.Engine.Test/VPT/Primitive/PrimitiveDataTests.cs @@ -14,13 +14,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -using FluentAssertions; - using NUnit.Framework; - using VisualPinball.Engine.Test.Test; - using VisualPinball.Engine.VPT.Primitive; - using VisualPinball.Engine.VPT.Table; +using FluentAssertions; +using NUnit.Framework; +using VisualPinball.Engine.Test.Test; +using VisualPinball.Engine.VPT.Primitive; +using VisualPinball.Engine.VPT.Table; - namespace VisualPinball.Engine.Test.VPT.Primitive +namespace VisualPinball.Engine.Test.VPT.Primitive { public class PrimitiveDataTests { diff --git a/VisualPinball.Engine/VPT/Bumper/BumperMeshGenerator.cs b/VisualPinball.Engine/VPT/Bumper/BumperMeshGenerator.cs index bd3875fed..d92f0d8aa 100644 --- a/VisualPinball.Engine/VPT/Bumper/BumperMeshGenerator.cs +++ b/VisualPinball.Engine/VPT/Bumper/BumperMeshGenerator.cs @@ -14,9 +14,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -// ReSharper disable CompareOfFloatsByEqualityOperator - using System; +using System.Collections.Generic; using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; using VisualPinball.Engine.Resources.Meshes; @@ -30,13 +29,19 @@ public class BumperMeshGenerator public const string Ring = "Ring"; public const string Skirt = "Skirt"; - private static readonly Mesh BaseMesh = new Mesh(Base, BumperBase.Vertices, BumperBase.Indices); - private static readonly Mesh CapMesh = new Mesh(Cap, BumperCap.Vertices, BumperCap.Indices); - private static readonly Mesh RingMesh = new Mesh(Ring, BumperRing.Vertices, BumperRing.Indices); - private static readonly Mesh SocketMesh = new Mesh(Skirt, BumperSocket.Vertices, BumperSocket.Indices); + private static readonly Mesh BaseMesh = new Mesh("Base", BumperBase.Vertices, BumperBase.Indices); + private static readonly Mesh CapMesh = new Mesh("Cap", BumperCap.Vertices, BumperCap.Indices); + private static readonly Mesh RingMesh = new Mesh("Ring", BumperRing.Vertices, BumperRing.Indices); + private static readonly Mesh SocketMesh = new Mesh("Skirt", BumperSocket.Vertices, BumperSocket.Indices); private readonly BumperData _data; + private Mesh _scaledBaseMesh; + private Mesh _scaledCapMesh; + private Mesh _scaledRingMesh; + private Mesh _scaledSocketMesh; + private float _generatedScale; + internal BumperMeshGenerator(BumperData data) { _data = data; } @@ -66,6 +71,7 @@ public RenderObject GetRenderObject(Table.Table table, string id, Origin origin, new PbrMaterial(table.GetMaterial(_data.RingMaterial), Texture.BumperRing), _data.IsRingVisible ); + case Skirt: return new RenderObject( "Skirt", @@ -77,34 +83,34 @@ public RenderObject GetRenderObject(Table.Table table, string id, Origin origin, throw new ArgumentException("Unknown bumper mesh \"" + id + "\"."); } - public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) { + var meshes = GetMeshes(table, origin); var translationMatrix = GetPostMatrix(origin); + return new RenderObjectGroup(_data.Name, "Bumpers", translationMatrix, GetRenderObject(table, Base, origin, asRightHanded), - GetRenderObject(table, Cap, origin, asRightHanded), - GetRenderObject(table, Ring, origin, asRightHanded), - GetRenderObject(table, Skirt, origin, asRightHanded) + new RenderObject( + "Ring", + asRightHanded ? meshes["Ring"].Transform(Matrix3D.RightHanded) : meshes["Ring"], + new PbrMaterial(table.GetMaterial(_data.RingMaterial), Texture.BumperRing), + _data.IsRingVisible + ), + new RenderObject( + "Skirt", + asRightHanded ? meshes["Skirt"].Transform(Matrix3D.RightHanded) : meshes["Skirt"], + new PbrMaterial(table.GetMaterial(_data.SocketMaterial), Texture.BumperSocket), + _data.IsSocketVisible + ), + new RenderObject( + "Cap", + asRightHanded ? meshes["Cap"].Transform(Matrix3D.RightHanded) : meshes["Cap"], + new PbrMaterial(table.GetMaterial(_data.CapMaterial), Texture.BumperCap), + _data.IsCapVisible + ) ); } - private Matrix3D GetPostMatrix(Origin origin) - { - switch (origin) { - case Origin.Original: - var rotMatrix = new Matrix3D().RotateZMatrix(MathF.DegToRad(_data.Orientation)); - var transMatrix = new Matrix3D().SetTranslation(_data.Center.X, _data.Center.Y, 0f); - return rotMatrix.Multiply(transMatrix); - - case Origin.Global: - return Matrix3D.Identity; - - default: - throw new ArgumentOutOfRangeException(nameof(origin), origin, "Unknown origin " + origin); - } - } - private Mesh GetMesh(string id, Table.Table table, Origin origin) { if (_data.Center == null) { throw new InvalidOperationException($"Cannot export bumper {_data.Name} without center."); @@ -135,6 +141,44 @@ private Mesh GetMesh(string id, Table.Table table, Origin origin) { throw new ArgumentException("Unknown bumper mesh \"" + id + "\"."); } + private Matrix3D GetPostMatrix(Origin origin) + { + switch (origin) { + case Origin.Original: + var rotMatrix = new Matrix3D().RotateZMatrix(MathF.DegToRad(_data.Orientation)); + var transMatrix = new Matrix3D().SetTranslation(_data.Center.X, _data.Center.Y, 0f); + return rotMatrix.Multiply(transMatrix); + + case Origin.Global: + return Matrix3D.Identity; + + default: + throw new ArgumentOutOfRangeException(nameof(origin), origin, "Unknown origin " + origin); + } + } + + private Dictionary GetMeshes(Table.Table table, Origin origin) { + if (_data.Center == null) { + throw new InvalidOperationException($"Cannot export bumper {_data.Name} without center."); + } + var matrix = Matrix3D.Identity; + var height = table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y) * table.GetScaleZ(); + + //if (_generatedScale != _data.Radius) { + _scaledBaseMesh = BaseMesh.Clone().MakeScale(_data.Radius, _data.Radius, _data.HeightScale); + _scaledCapMesh = CapMesh.Clone().MakeScale(_data.Radius * 2, _data.Radius * 2, _data.HeightScale); + _scaledRingMesh = RingMesh.Clone().MakeScale(_data.Radius, _data.Radius, _data.HeightScale); + _scaledSocketMesh = SocketMesh.Clone().MakeScale(_data.Radius, _data.Radius, _data.HeightScale); + //} + + return new Dictionary { + { "Base", GenerateMesh(_scaledBaseMesh, matrix, z => z * table.GetScaleZ() + height, origin) }, + { "Ring", GenerateMesh(_scaledRingMesh, matrix, z => z * table.GetScaleZ() + height, origin) }, + { "Skirt", GenerateMesh(_scaledSocketMesh, matrix, z => z * table.GetScaleZ() + (height + 5.0f), origin) }, + { "Cap", GenerateMesh(_scaledCapMesh, matrix, z => (z + _data.HeightScale) * table.GetScaleZ() + height, origin) } + }; + } + private Mesh GenerateMesh(Mesh mesh, Matrix3D matrix, Func zPos, Origin origin) { var generatedMesh = mesh.Clone(); foreach (var vertex in generatedMesh.Vertices) { diff --git a/VisualPinball.Engine/VPT/Surface/Surface.cs b/VisualPinball.Engine/VPT/Surface/Surface.cs index a1ca9f3c6..db52d5dbb 100644 --- a/VisualPinball.Engine/VPT/Surface/Surface.cs +++ b/VisualPinball.Engine/VPT/Surface/Surface.cs @@ -68,7 +68,7 @@ public void Init(Table.Table table) public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { - throw new System.NotImplementedException(); + return _meshGenerator.GetRenderObject(table, id, asRightHanded); } public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) diff --git a/VisualPinball.Engine/VPT/Surface/SurfaceMeshGenerator.cs b/VisualPinball.Engine/VPT/Surface/SurfaceMeshGenerator.cs index a2f8e803b..5fcac7b2a 100644 --- a/VisualPinball.Engine/VPT/Surface/SurfaceMeshGenerator.cs +++ b/VisualPinball.Engine/VPT/Surface/SurfaceMeshGenerator.cs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using System.Collections.Generic; using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; @@ -32,36 +33,138 @@ public SurfaceMeshGenerator(SurfaceData data) _data = data; } + public RenderObject GetRenderObject(Table.Table table, string id, bool asRightHanded, Mesh preGeneratedMesh = null) + { + var mesh = preGeneratedMesh ?? GenerateMesh(table, id); + switch (id) { + case Side: + return new RenderObject( + id, + asRightHanded ? mesh.Transform(Matrix3D.RightHanded) : mesh, + new PbrMaterial(table.GetMaterial(_data.SideMaterial), table.GetTexture(_data.SideImage)), + _data.IsSideVisible + ); + case Top: + return new RenderObject( + id, + asRightHanded ? mesh.Transform(Matrix3D.RightHanded) : mesh, + new PbrMaterial(table.GetMaterial(_data.TopMaterial), table.GetTexture(_data.Image)), + _data.IsTopBottomVisible + ); + default: + throw new ArgumentException($"Unknown mesh ID \"{id}\"."); + } + } + public RenderObjectGroup GetRenderObjects(Table.Table table, bool asRightHanded = true) { - var meshes = GenerateMeshes(table); var renderObjects = new List(); - - if (meshes.ContainsKey("Side")) { - renderObjects.Add(new RenderObject( - "Side", - asRightHanded ? meshes["Side"].Transform(Matrix3D.RightHanded) : meshes["Side"], - new PbrMaterial(table.GetMaterial(_data.SideMaterial), table.GetTexture(_data.SideImage)), - _data.IsSideVisible - )); + var sideMesh = GenerateSideMesh(table); + var topMesh = GenerateTopMesh(table); + if (sideMesh != null) { + renderObjects.Add(GetRenderObject(table, Side, asRightHanded, sideMesh)); } - - if (meshes.ContainsKey("Top")) { - renderObjects.Add(new RenderObject( - "Top", - asRightHanded ? meshes["Top"].Transform(Matrix3D.RightHanded) : meshes["Top"], - new PbrMaterial(table.GetMaterial(_data.TopMaterial), table.GetTexture(_data.Image)), - _data.IsTopBottomVisible - )); + if (topMesh != null) { + renderObjects.Add(GetRenderObject(table, Top, asRightHanded, topMesh)); } return new RenderObjectGroup(_data.Name, "Surfaces", Matrix3D.Identity, renderObjects.ToArray()); } - private Dictionary GenerateMeshes(Table.Table table) { + private Mesh GenerateMesh(Table.Table table, string id) + { + switch (id) { + case Top: return GenerateTopMesh(table); + case Side: return GenerateSideMesh(table); + default: + throw new ArgumentException($"Unknown mesh ID \"{id}\"."); + } + } + + private Mesh GenerateTopMesh(Table.Table table) { - var meshes = new Dictionary(); var topMesh = new Mesh("Top"); + var vVertex = DragPoint.GetRgVertex(_data.DragPoints); + + var numVertices = vVertex.Length; + var rgNormal = new Vertex2D[numVertices]; + + for (var i = 0; i < numVertices; i++) { + + var pv1 = vVertex[i]; + var pv2 = vVertex[i < numVertices - 1 ? i + 1 : 0]; + var dx = pv1.X - pv2.X; + var dy = pv1.Y - pv2.Y; + + var invLen = 1.0f / MathF.Sqrt(dx * dx + dy * dy); + + rgNormal[i] = new Vertex2D {X = dy * invLen, Y = dx * invLen}; + } + + // draw top + var vPoly = new List(new int[numVertices]); + for (var i = 0; i < numVertices; i++) { + vPoly[i] = i; + } + + topMesh.Indices = Mesh.PolygonToTriangles(vVertex, vPoly); + var numPolys = topMesh.Indices.Length / 3; + if (numPolys == 0) { + // no polys to render leave vertex buffer undefined + return null; + } + + var heightNotDropped = _data.HeightTop * table.GetScaleZ(); + var heightDropped = _data.HeightBottom * table.GetScaleZ() + 0.1; + + var invTableWidth = 1.0f / table.Width; + var invTableHeight = 1.0f / table.Height; + + Vertex3DNoTex2[][] vertsTop = { new Vertex3DNoTex2[numVertices], new Vertex3DNoTex2[numVertices], new Vertex3DNoTex2[numVertices]}; + for (var i = 0; i < numVertices; i++) { + + var pv0 = vVertex[i]; + + vertsTop[0][i] = new Vertex3DNoTex2 { + X = pv0.X, + Y = pv0.Y, + Z = heightNotDropped + table.TableHeight, + Tu = pv0.X * invTableWidth, + Tv = pv0.Y * invTableHeight, + Nx = 0, + Ny = 0, + Nz = 1.0f + }; + + vertsTop[1][i] = new Vertex3DNoTex2 { + X = pv0.X, + Y = pv0.Y, + Z = (float) heightDropped, + Tu = pv0.X * invTableWidth, + Tv = pv0.Y * invTableHeight, + Nx = 0, + Ny = 0, + Nz = 1.0f + }; + + vertsTop[2][i] = new Vertex3DNoTex2 { + X = pv0.X, + Y = pv0.Y, + Z = _data.HeightBottom, + Tu = pv0.X * invTableWidth, + Tv = pv0.Y * invTableHeight, + Nx = 0, + Ny = 0, + Nz = -1.0f + }; + } + topMesh.Vertices = vertsTop[0]; + + return topMesh; + } + + private Mesh GenerateSideMesh(Table.Table table) { + var sideMesh = new Mesh("Side"); var vVertex = DragPoint.GetRgVertex(_data.DragPoints); @@ -182,74 +285,7 @@ private Dictionary GenerateMeshes(Table.Table table) { offset2 += 4; } - // draw top - var vPoly = new List(new int[numVertices]); - for (var i = 0; i < numVertices; i++) { - vPoly[i] = i; - } - - topMesh.Indices = Mesh.PolygonToTriangles(vVertex, vPoly); - - var numPolys = topMesh.Indices.Length / 3; - if (numPolys == 0) { - // no polys to render leave vertex buffer undefined - return meshes; - } - - var heightNotDropped = _data.HeightTop * table.GetScaleZ(); - var heightDropped = _data.HeightBottom * table.GetScaleZ() + 0.1; - - var invTableWidth = 1.0f / table.Width; - var invTableHeight = 1.0f / table.Height; - - Vertex3DNoTex2[][] vertsTop = { new Vertex3DNoTex2[numVertices], new Vertex3DNoTex2[numVertices], new Vertex3DNoTex2[numVertices]}; - for (var i = 0; i < numVertices; i++) { - - var pv0 = vVertex[i]; - - vertsTop[0][i] = new Vertex3DNoTex2 { - X = pv0.X, - Y = pv0.Y, - Z = heightNotDropped + table.TableHeight, - Tu = pv0.X * invTableWidth, - Tv = pv0.Y * invTableHeight, - Nx = 0, - Ny = 0, - Nz = 1.0f - }; - - vertsTop[1][i] = new Vertex3DNoTex2 { - X = pv0.X, - Y = pv0.Y, - Z = (float) heightDropped, - Tu = pv0.X * invTableWidth, - Tv = pv0.Y * invTableHeight, - Nx = 0, - Ny = 0, - Nz = 1.0f - }; - - vertsTop[2][i] = new Vertex3DNoTex2 { - X = pv0.X, - Y = pv0.Y, - Z = _data.HeightBottom, - Tu = pv0.X * invTableWidth, - Tv = pv0.Y * invTableHeight, - Nx = 0, - Ny = 0, - Nz = -1.0f - }; - } - topMesh.Vertices = vertsTop[0]; - - if (topMesh.Vertices.Length > 0) { - meshes["Top"] = topMesh; - } - if (System.Math.Abs(top - bottom) > 0.00001f) { - meshes["Side"] = sideMesh; - } - return meshes; + return sideMesh; } } - } From 718181b2934c6379634362e675713b6e442e8932 Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 5 Oct 2020 20:12:13 +0200 Subject: [PATCH 041/124] bumper: Simplify mesh generator. --- .../VPT/Bumper/BumperMeshGenerator.cs | 75 +++---------------- 1 file changed, 11 insertions(+), 64 deletions(-) diff --git a/VisualPinball.Engine/VPT/Bumper/BumperMeshGenerator.cs b/VisualPinball.Engine/VPT/Bumper/BumperMeshGenerator.cs index d92f0d8aa..b5caa988c 100644 --- a/VisualPinball.Engine/VPT/Bumper/BumperMeshGenerator.cs +++ b/VisualPinball.Engine/VPT/Bumper/BumperMeshGenerator.cs @@ -15,7 +15,6 @@ // along with this program. If not, see . using System; -using System.Collections.Generic; using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; using VisualPinball.Engine.Resources.Meshes; @@ -36,12 +35,6 @@ public class BumperMeshGenerator private readonly BumperData _data; - private Mesh _scaledBaseMesh; - private Mesh _scaledCapMesh; - private Mesh _scaledRingMesh; - private Mesh _scaledSocketMesh; - private float _generatedScale; - internal BumperMeshGenerator(BumperData data) { _data = data; } @@ -85,29 +78,13 @@ public RenderObject GetRenderObject(Table.Table table, string id, Origin origin, public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) { - var meshes = GetMeshes(table, origin); var translationMatrix = GetPostMatrix(origin); return new RenderObjectGroup(_data.Name, "Bumpers", translationMatrix, GetRenderObject(table, Base, origin, asRightHanded), - new RenderObject( - "Ring", - asRightHanded ? meshes["Ring"].Transform(Matrix3D.RightHanded) : meshes["Ring"], - new PbrMaterial(table.GetMaterial(_data.RingMaterial), Texture.BumperRing), - _data.IsRingVisible - ), - new RenderObject( - "Skirt", - asRightHanded ? meshes["Skirt"].Transform(Matrix3D.RightHanded) : meshes["Skirt"], - new PbrMaterial(table.GetMaterial(_data.SocketMaterial), Texture.BumperSocket), - _data.IsSocketVisible - ), - new RenderObject( - "Cap", - asRightHanded ? meshes["Cap"].Transform(Matrix3D.RightHanded) : meshes["Cap"], - new PbrMaterial(table.GetMaterial(_data.CapMaterial), Texture.BumperCap), - _data.IsCapVisible - ) + GetRenderObject(table, Ring, origin, asRightHanded), + GetRenderObject(table, Skirt, origin, asRightHanded), + GetRenderObject(table, Base, origin, asRightHanded) ); } @@ -116,28 +93,26 @@ private Mesh GetMesh(string id, Table.Table table, Origin origin) { throw new InvalidOperationException($"Cannot export bumper {_data.Name} without center."); } - var matrix = Matrix3D.Identity; var height = table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y) * table.GetScaleZ(); switch (id) { case Base: { var mesh = BaseMesh.Clone().MakeScale(_data.Radius, _data.Radius, _data.HeightScale); - return GenerateMesh(mesh, matrix, z => z * table.GetScaleZ() + height, origin); + return TranslateMesh(mesh, z => z * table.GetScaleZ() + height, origin); } case Cap: { var mesh = CapMesh.Clone().MakeScale(_data.Radius * 2, _data.Radius * 2, _data.HeightScale); - return GenerateMesh(mesh, matrix, z => z * table.GetScaleZ() + height, origin); + return TranslateMesh(mesh, z => (z + _data.HeightScale) * table.GetScaleZ() + height, origin); } case Ring: { var mesh = RingMesh.Clone().MakeScale(_data.Radius, _data.Radius, _data.HeightScale); - return GenerateMesh(mesh, matrix, z => z * table.GetScaleZ() + (height + 5.0f), origin); + return TranslateMesh(mesh, z => z * table.GetScaleZ() + height, origin); } case Skirt: { var mesh = SocketMesh.Clone().MakeScale(_data.Radius, _data.Radius, _data.HeightScale); - return GenerateMesh(mesh, matrix, z => (z + _data.HeightScale) * table.GetScaleZ() + height, origin); + return TranslateMesh(mesh, z => z * table.GetScaleZ() + (height + 5.0f), origin); } } - throw new ArgumentException("Unknown bumper mesh \"" + id + "\"."); } @@ -157,42 +132,14 @@ private Matrix3D GetPostMatrix(Origin origin) } } - private Dictionary GetMeshes(Table.Table table, Origin origin) { - if (_data.Center == null) { - throw new InvalidOperationException($"Cannot export bumper {_data.Name} without center."); - } - var matrix = Matrix3D.Identity; - var height = table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y) * table.GetScaleZ(); - - //if (_generatedScale != _data.Radius) { - _scaledBaseMesh = BaseMesh.Clone().MakeScale(_data.Radius, _data.Radius, _data.HeightScale); - _scaledCapMesh = CapMesh.Clone().MakeScale(_data.Radius * 2, _data.Radius * 2, _data.HeightScale); - _scaledRingMesh = RingMesh.Clone().MakeScale(_data.Radius, _data.Radius, _data.HeightScale); - _scaledSocketMesh = SocketMesh.Clone().MakeScale(_data.Radius, _data.Radius, _data.HeightScale); - //} - - return new Dictionary { - { "Base", GenerateMesh(_scaledBaseMesh, matrix, z => z * table.GetScaleZ() + height, origin) }, - { "Ring", GenerateMesh(_scaledRingMesh, matrix, z => z * table.GetScaleZ() + height, origin) }, - { "Skirt", GenerateMesh(_scaledSocketMesh, matrix, z => z * table.GetScaleZ() + (height + 5.0f), origin) }, - { "Cap", GenerateMesh(_scaledCapMesh, matrix, z => (z + _data.HeightScale) * table.GetScaleZ() + height, origin) } - }; - } - - private Mesh GenerateMesh(Mesh mesh, Matrix3D matrix, Func zPos, Origin origin) { + private Mesh TranslateMesh(Mesh mesh, Func zPos, Origin origin) { var generatedMesh = mesh.Clone(); foreach (var vertex in generatedMesh.Vertices) { - var vert = new Vertex3D(vertex.X, vertex.Y, vertex.Z).MultiplyMatrix(matrix); if (origin == Origin.Global) { - vertex.X = vert.X + _data.Center.X; - vertex.Y = vert.Y + _data.Center.Y; + vertex.X += _data.Center.X; + vertex.Y += _data.Center.Y; } - vertex.Z = zPos(vert.Z); - - var normal = new Vertex3D(vertex.Nx, vertex.Ny, vertex.Nz).MultiplyMatrixNoTranslate(matrix); - vertex.Nx = normal.X; - vertex.Ny = normal.Y; - vertex.Nz = normal.Z; + vertex.Z = zPos(vertex.Z); } return generatedMesh; } From 8ec4765927493a58af0851e2fc97e18018df6be1 Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 5 Oct 2020 21:33:36 +0200 Subject: [PATCH 042/124] bumper: Fix mesh creation. --- .../Resources/Icons/small_blue/bumper_cap.png | Bin 0 -> 455 bytes .../Icons/small_blue/bumper_cap.png.meta | 106 ++++++++++++++++++ .../Icons/small_blue/bumper_ring.png | Bin 0 -> 472 bytes .../Icons/small_blue/bumper_ring.png.meta | 106 ++++++++++++++++++ .../Icons/small_blue/bumper_skirt.png | Bin 0 -> 461 bytes .../Icons/small_blue/bumper_skirt.png.meta | 106 ++++++++++++++++++ .../Icons/small_blue/bumper_socket.png | Bin 0 -> 465 bytes .../Icons/small_blue/bumper_socket.png.meta | 106 ++++++++++++++++++ .../Icons/small_blue/surface_side.png | Bin 0 -> 205 bytes .../Icons/small_blue/surface_side.png.meta | 106 ++++++++++++++++++ .../Icons/small_blue/surface_top.png | Bin 0 -> 201 bytes .../Icons/small_blue/surface_top.png.meta | 106 ++++++++++++++++++ .../Toolbox/ToolboxEditor.cs | 3 +- .../Import/VpxConverter.cs | 2 +- .../Bumper/BumperBaseMeshAuthoring.cs.meta | 2 +- .../VPT/Bumper/BumperCapMeshAuthoring.cs.meta | 2 +- .../VPT/Bumper/BumperExtensions.cs | 60 +++++++--- .../Bumper/BumperRingMeshAuthoring.cs.meta | 2 +- .../Bumper/BumperSkirtMeshAuthoring.cs.meta | 2 +- .../VPT/ItemMeshAuthoring.cs | 2 +- 20 files changed, 688 insertions(+), 23 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_cap.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_cap.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_ring.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_ring.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_skirt.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_skirt.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_socket.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_socket.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/surface_side.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/surface_side.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/surface_top.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/surface_top.png.meta diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_cap.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_cap.png new file mode 100644 index 0000000000000000000000000000000000000000..64bb625ed8834643fa8a939a92b067798091d597 GIT binary patch literal 455 zcmV;&0XY7NP)Q}4Cie);?Jf2_#@zY{ zm33R)WYvPKtVB#8wy>iYxHKeC?m`N8`8kq6etd-Q3rzAn#~5IvuneL-5JX)QL|ro) z(W$ACxR?XD2k-=7>B;2)U<2TjB9`i%Rb?VBZWXyZPjWVPiuAq`B`#tB?^l+y@k|k0 zmuoa0o?peuZSwm4S3K^IVK`ZNU;~e4Nj#Nr^-gKLv1J2~`~vtQJ5-D8E)vclpQS6Jx=$f{9zM^Qu7~L~b xMbcLkZDhJ^_>t?HAnKYR>Y56P)R=i=p@GSU0Lx4WFq5Mo;pfbS+=Q-v8nT4en9RM$C8!u{` z*@!MpgOu?AKnP$1VCBf=8$bder4h;W$*M9@#@C8m=t!=KRFVFyL@DDjfZLJfn%L8b zyqE82JUzdP!fo;J@hcwl{WP2!*^!Ayvm{>1Rh=q>mjKSk^}-i`S7m=y>qq6ndULLJ z%!OD$>PRi&%LBIK_!Vq*NvL^LhcdngaN}6=iAKbjCfiD=$OMPsoN64}vQO(b6Jwo0h#*5mj8XCfi*47qhAIUl7VeQHEW$PIv}k>z~siL=8c zM>o^+YuKtEi`UO@^~#^8;p8P}7vqVuUFua`8lEb`*~s2%)t`*(thFE2tAFfN$cZyE zczcxrgs(FZXCD9#as7Td>bYBVwa~)KlUt)Y)802n=b4FwTp2C&K`%6u ze4zZ!x;E3SBF-w`gU(*xi2glTY3Ww~b>&j$ctYB@&V9#7+q}>u(a5_*nO&*{Xq&5IR9 zAI|7ri5ilzj>tYLTQ+^j4NVdaO%e@F5)I8fL;?H&npu9cFrJ+H00000NkvXXu0mjf D0A0>_ literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_skirt.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_skirt.png.meta new file mode 100644 index 000000000..a338082f7 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_skirt.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: df752b28db516634697095aadd4f88c9 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_socket.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_socket.png new file mode 100644 index 0000000000000000000000000000000000000000..f831d8146858cb440ba657367a2befb011a8ffd1 GIT binary patch literal 465 zcmV;?0WSWDP){LWXAdtm%T^te~p%RJY0q~p$-~o_G zWMw6|;!tcIkr9Z<8a7OrO=h#nwhgn*WoAFsY|`vEr#Y82$nzXifK9^Ei=F^4>KZTV zn#qXH+7?O35WpP30zlN0O9o&IAR*3n=E*g6w&wo!GgZ?YAg< z6A4*N{r3RQj8oPEZNVJQzX3cFX9v6Bp@JW(n=d*Fb!Dq2`Nq4_K~WXOWsf7@PRX`L zw{6VpD~dK+qgxZzB*!o~*JS-4xvue|uJNL-@uIGohA4nvz9xUR?IeS{00000NkvXX Hu0mjfL>$lc literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_socket.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_socket.png.meta new file mode 100644 index 000000000..9f4915720 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_socket.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: cb3381fe680520f4d8d9dd1ce1ba4a98 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/surface_side.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/surface_side.png new file mode 100644 index 0000000000000000000000000000000000000000..e57a697fd9a679d3e4fb7af8adc22699d8d0ee01 GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^S|H591|*LjJ{b+9I14-?iy0W${Xm$pP}ST5C|K|5 z;usRq`u4gbZ;OKf>qUM?j!R)&7LHs(I}#a1ty>ftyk(b7uHw=%epynLv36H*=6I`X`WpF{#f|T_2yI3G~Ukqwb$YK!?Z=VvsWIOZ1vT|IkW8&&r(S*W1!^O tfLRN-1U>(B%klX1v&A!^0#XY-^TM2kMQ8a_;~&0ZXXbLZon?73o86^=0bmsK7UIDI)lN})z4*}Q$iB}yEaMt literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/surface_top.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/surface_top.png.meta new file mode 100644 index 000000000..dfcbcd4d3 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/surface_top.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 7415b0f1b56589a46a8453cdb2b1460f +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs index 8f535d849..82f5029b3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs @@ -184,9 +184,8 @@ private void CreateItem(Func create, string actionName) whe private GameObject CreateRenderable(IRenderable renderable) { - //var rog = renderable.GetRenderObjects(_table.Table, Origin.Original, false); + var rog = renderable.GetRenderObjects(_tableAuthoring.Table, Origin.Original, false); var obj = VpxConverter.CreateGameObjects(renderable, GetOrCreateParent(_tableAuthoring, renderable), _tableAuthoring); - VpxConverter.SetupGameObjects(renderable, obj); return obj; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index ae1f7d37b..ecde9f869 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -187,7 +187,7 @@ public static IItemMainAuthoring SetupGameObjects(IRenderable item, GameObject o { IItemMainAuthoring mainAuthoring = null; switch (item) { - case Bumper bumper: bumper.SetupGameObject(obj); break; + case Bumper bumper: mainAuthoring = bumper.SetupGameObject(obj, parentAuthoring); break; case Flipper flipper: flipper.SetupGameObject(obj); break; case Gate gate: gate.SetupGameObject(obj); break; case HitTarget hitTarget: hitTarget.SetupGameObject(obj); break; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs.meta index 4bee6d089..0101e8924 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs.meta @@ -5,7 +5,7 @@ MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: cb3381fe680520f4d8d9dd1ce1ba4a98, type: 3} userData: assetBundleName: assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs.meta index af4ca1d0f..66cca724c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs.meta @@ -5,7 +5,7 @@ MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: 8f712d4aa759b4c4abfb1d5ba7161485, type: 3} userData: assetBundleName: assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs index af51c1020..7a2226068 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs @@ -14,34 +14,64 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using Unity.Entities; using UnityEngine; -using VisualPinball.Engine.Game; +using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Bumper; +using VisualPinball.Engine.VPT.Surface; namespace VisualPinball.Unity { internal static class BumperExtensions { - public static BumperAuthoring SetupGameObject(this Engine.VPT.Bumper.Bumper bumper, GameObject obj) + + public static IItemMainAuthoring SetupGameObject(this Bumper bumper, GameObject obj, IItemMainAuthoring parentAuthoring) { - var ic = obj.AddComponent().SetItem(bumper); + var mainAuthoring = obj.AddComponent().SetItem(bumper); - obj.AddComponent(); + switch (bumper.SubComponent) { + case ItemSubComponent.None: + //obj.AddComponent(); + CreateChild(obj, BumperMeshGenerator.Base); + CreateChild(obj, BumperMeshGenerator.Cap); + var ring = CreateChild(obj, BumperMeshGenerator.Ring); + var skirt = CreateChild(obj, BumperMeshGenerator.Skirt); + ring.AddComponent(); + skirt.AddComponent(); - var bse = obj.transform.Find(BumperMeshGenerator.Base).gameObject; - var cap = obj.transform.Find(BumperMeshGenerator.Cap).gameObject; - var ring = obj.transform.Find(BumperMeshGenerator.Ring).gameObject; - var skirt = obj.transform.Find(BumperMeshGenerator.Skirt).gameObject; + break; - bse.AddComponent(); - cap.AddComponent(); - ring.AddComponent(); - skirt.AddComponent(); - ring.AddComponent(); - skirt.AddComponent(); + case ItemSubComponent.Collider: { + //obj.AddComponent(); + if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { + hittableAuthoring.RemoveHittableComponent(); + } + break; + } - return ic as BumperAuthoring; + case ItemSubComponent.Mesh: { + // todo + if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { + meshAuthoring.RemoveMeshComponent(); + } + break; + } + + default: + throw new ArgumentOutOfRangeException(); + } + obj.AddComponent(); + return mainAuthoring; + } + + private static GameObject CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring + { + var subObj = new GameObject(name); + subObj.transform.SetParent(obj.transform, false); + subObj.AddComponent(); + //subObj.layer = ChildObjectsLayer; + return subObj; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs.meta index 60157d777..6432080ed 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs.meta @@ -5,7 +5,7 @@ MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: 09d7b3838d082684caacf3e7458749c4, type: 3} userData: assetBundleName: assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs.meta index a8efe229e..caa247458 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs.meta @@ -5,7 +5,7 @@ MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: df752b28db516634697095aadd4f88c9, type: 3} userData: assetBundleName: assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs index 7b55cbfeb..aae5ff6e6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs @@ -43,7 +43,7 @@ private void Awake() { if (!_meshCreated && gameObject.GetComponent() == null) { var ta = GetComponentInParent(); - var ro = Item.GetRenderObject(ta.Table, MeshId); + var ro = Item.GetRenderObject(ta.Table, MeshId, asRightHanded: false); var mesh = ro.Mesh.ToUnityMesh($"{gameObject.name}_Mesh"); // apply mesh to game object From f61d0910a8be153c7f5bbda01c3a06bf3ea174e6 Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 5 Oct 2020 21:42:20 +0200 Subject: [PATCH 043/124] bumpers: Add animation icons. --- .../Icons/small_green/bumper_cap.png | Bin 0 -> 455 bytes .../Icons/small_green/bumper_cap.png.meta | 106 ++++++++++++++++++ .../Icons/small_green/bumper_ring.png | Bin 0 -> 471 bytes .../Icons/small_green/bumper_ring.png.meta | 106 ++++++++++++++++++ .../Icons/small_green/bumper_skirt.png | Bin 0 -> 459 bytes .../Icons/small_green/bumper_skirt.png.meta | 106 ++++++++++++++++++ .../Icons/small_green/bumper_socket.png | Bin 0 -> 468 bytes .../Icons/small_green/bumper_socket.png.meta | 106 ++++++++++++++++++ .../VisualPinball.Unity.Editor/Utils/Icons.cs | 9 ++ .../VPT/Bumper/BumperExtensions.cs | 4 +- ...ing.cs => BumperRingAnimationAuthoring.cs} | 3 +- ...a => BumperRingAnimationAuthoring.cs.meta} | 4 +- ...ng.cs => BumperSkirtAnimationAuthoring.cs} | 3 +- ... => BumperSkirtAnimationAuthoring.cs.meta} | 4 +- .../Surface/SurfaceSideMeshAuthoring.cs.meta | 11 ++ .../Surface/SurfaceTopMeshAuthoring.cs.meta | 11 ++ 16 files changed, 465 insertions(+), 8 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_cap.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_cap.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_ring.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_ring.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_skirt.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_skirt.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_socket.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_socket.png.meta rename VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/{BumperRingAuthoring.cs => BumperRingAnimationAuthoring.cs} (89%) rename VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/{BumperRingAuthoring.cs.meta => BumperRingAnimationAuthoring.cs.meta} (61%) rename VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/{BumperSkirtAuthoring.cs => BumperSkirtAnimationAuthoring.cs} (88%) rename VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/{BumperSkirtAuthoring.cs.meta => BumperSkirtAnimationAuthoring.cs.meta} (61%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceSideMeshAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceTopMeshAuthoring.cs.meta diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_cap.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_cap.png new file mode 100644 index 0000000000000000000000000000000000000000..bb056893153254cf4890ceec0faad93c3fe99e30 GIT binary patch literal 455 zcmeAS@N?(olHy`uVBq!ia0vp^S|H591|*LjJ{b+9I14-?iy0W${Xm$pP}SUmfq}8o z)5S3)qV??z#o}fIiMIRCw6xT;w6(Rr^KaX^^3Iz@Gj99OiWc3~y(;>(n)<}4Q#&}1 zh?RX|n%>58D%RtnUcWNulZVPR@d=ZjTOMPOY)ut-+oCj+v2vKyZLI;hEO%HNBRt%@%x24=j?V1=F}C+dwZ_xiN;j@^i|YMjHcY+q z^Zb@|elJgchzwq`hgY>QTQtY}hq304R~lEQx^P`DDqWr7Eb@Di;jU%5^VVzJGI0Cu u6Eg9OsH^l$J?Xk9AcG(%O=c0pKgKCsO)ME-Tzr8s!{F)a=d#Wzp$PySI>a#m literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_cap.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_cap.png.meta new file mode 100644 index 000000000..461eafe9c --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_cap.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 93135129f471ee848bc3bf39fe5aa631 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_ring.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_ring.png new file mode 100644 index 0000000000000000000000000000000000000000..15f49519dd99bdba5b14d990b3da609670f98d0a GIT binary patch literal 471 zcmV;|0Vw{7P)$=wNfY)zC2(%j$h7JmxP)}br`3601pF89zqfs(_~W#6`A1FpHqcXQ}${6W@4QB zN|m|?u+|RQb(GOXMAdnd+oB33hI4X^wZ1@}m?+YzHh=75$vC~!hLTIK;o3agI8oa; zQQKVf?}>3Ly8b5sSK3tE(PyLW{{naoNz{6swuJA=&R@TQZDQHUSH6{6MP(F)q}Q`# zK`Ld9(KWSsLq)L;V|33%70IEZSVyYMx*xf=aiX?yqPB6OwwZ@0fPWkMf=`}}cZdK0 N002ovPDHLkV1gwh%{u@9 literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_ring.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_ring.png.meta new file mode 100644 index 000000000..7c74a6f7b --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_ring.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: c0325eff5b0ee244f82be12735565a64 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_skirt.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_skirt.png new file mode 100644 index 0000000000000000000000000000000000000000..a2512260868fc1d202b577293f55ab5de0b45b52 GIT binary patch literal 459 zcmV;+0W|)JP)wF&|Y2MY%adxRlxbVh?a#E!881R1wR zIl^FJVPIik!RAb!oXBsehIo+`rG#NKMwUySptvmVv6f9h1oDdA@D zx&>dCgCeTdErl%!UuU9(e*rkf_50(j$L`SALJKQT?v3h92j3XIdnO^-#%Q5WdZL-+ zBjw+$b2H5w74EhSb_tWbrmJuYO$0+rfPF%~pSW)!h zjP8x7AsK6n?4z<}(~sQHB+<|$(aY5q6qf;pW30C=Q?cXq+9f*+}y&wC2>B~g=n<6Ws!R7G*=apc=7 z+1BW`jd{MJXrnc{HBn7+2!nG?HvEz6njq?$AnKYR>Y8zg0{8(T mb, IconSize size = IconSize.Large, Ico public static void OnScriptsReloaded() { DisableGizmo(); + DisableGizmo(); + DisableGizmo(); + DisableGizmo(); + DisableGizmo(); + DisableGizmo(); + DisableGizmo(); DisableGizmo(); DisableGizmo(); DisableGizmo(); @@ -137,10 +143,13 @@ public static void OnScriptsReloaded() DisableGizmo(); DisableGizmo(); DisableGizmo(); + DisableGizmo(); DisableGizmo(); DisableGizmo(); DisableGizmo(); DisableGizmo(); + DisableGizmo(); + DisableGizmo(); DisableGizmo(); } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs index 7a2226068..08503e1ff 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs @@ -37,8 +37,8 @@ public static IItemMainAuthoring SetupGameObject(this Bumper bumper, GameObject CreateChild(obj, BumperMeshGenerator.Cap); var ring = CreateChild(obj, BumperMeshGenerator.Ring); var skirt = CreateChild(obj, BumperMeshGenerator.Skirt); - ring.AddComponent(); - skirt.AddComponent(); + ring.AddComponent(); + skirt.AddComponent(); break; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs similarity index 89% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAuthoring.cs rename to VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs index 6a2145ae8..2360d53a3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs @@ -19,7 +19,8 @@ namespace VisualPinball.Unity { - public class BumperRingAuthoring : MonoBehaviour, IConvertGameObjectToEntity + [AddComponentMenu("Visual Pinball/Animation/Bumper Ring Animation")] + public class BumperRingAnimationAuthoring : MonoBehaviour, IConvertGameObjectToEntity { public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs.meta similarity index 61% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAuthoring.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs.meta index c00a740a8..4223a0d61 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs.meta @@ -1,11 +1,11 @@ fileFormatVersion: 2 -guid: e0aec670c1bcb244db546b1ad9400ce4 +guid: aff42798b4f4d7149b76ac24b29d83db MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: c0325eff5b0ee244f82be12735565a64, type: 3} userData: assetBundleName: assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs similarity index 88% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAuthoring.cs rename to VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs index 2b9f9dd77..e39819ef3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs @@ -20,7 +20,8 @@ namespace VisualPinball.Unity { - internal class BumperSkirtAuthoring : MonoBehaviour, IConvertGameObjectToEntity + [AddComponentMenu("Visual Pinball/Animation/Bumper Skirt Animation")] + public class BumperSkirtAnimationAuthoring : MonoBehaviour, IConvertGameObjectToEntity { public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs.meta similarity index 61% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAuthoring.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs.meta index 0df527079..10f9fcb20 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs.meta @@ -1,11 +1,11 @@ fileFormatVersion: 2 -guid: 8f406cc371c06b14faa6e5f143ee8968 +guid: bd0d18debfb7e9d4f96b044b58b0e9b9 MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: f15f3457805f33048934bfabb357d750, type: 3} userData: assetBundleName: assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceSideMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceSideMeshAuthoring.cs.meta new file mode 100644 index 000000000..68cff6c56 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceSideMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ed6ad111d870e3b43a828b6086c08607 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 863d6770defa46e4484aec4ea86f44fa, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceTopMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceTopMeshAuthoring.cs.meta new file mode 100644 index 000000000..9b25b8306 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceTopMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 75abfb7d4ccc1b14bb10b53cb3f60574 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7415b0f1b56589a46a8453cdb2b1460f, type: 3} + userData: + assetBundleName: + assetBundleVariant: From edb465e4484ef7c7c91f9479dfd59069154c38f2 Mon Sep 17 00:00:00 2001 From: freezy Date: Tue, 6 Oct 2020 00:20:42 +0200 Subject: [PATCH 044/124] authoring: Hookup manual mesh rebuild. --- .../VPT/Bumper/BumperInspector.cs | 2 + .../VPT/ItemInspector.cs | 21 ++-- .../VPT/TransformInspector.cs | 1 + .../VPT/Bumper/BumperAuthoring.cs | 3 + .../VPT/IItemMainAuthoring.cs | 6 + .../VPT/ItemMainAuthoring.cs | 26 +++- .../VPT/ItemMeshAuthoring.cs | 113 +++++++++--------- 7 files changed, 106 insertions(+), 66 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs index e9f32ca31..9a1ff376b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +// ReSharper disable AssignmentInConditionalExpression + using UnityEditor; namespace VisualPinball.Unity.Editor diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs index 0f5347cd8..b6e3cb1ac 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs @@ -64,15 +64,18 @@ public override void OnInspectorGUI() return; } - // todo move to generic mesh inspector - // GUILayout.Space(10); - // if( GUILayout.Button( "Force Update Mesh" ) ) { - // item.MeshDirty = true; - // } - // - // if (item.MeshDirty) { - // item.RebuildMeshes(); - // } + GUILayout.Space(10); + if (GUILayout.Button("Force Update Mesh")) { + foreach (var meshComponent in item.MeshComponents) { + meshComponent.MeshDirty = true; + } + } + + foreach (var meshComponent in item.MeshComponents) { + if (meshComponent.MeshDirty) { + meshComponent.RebuildMeshes(); + } + } } #endregion diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs index 359fd005d..03e454d7f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs @@ -37,6 +37,7 @@ public class TransformInspector : UnityEditor.Editor // work around for scale handle weirdness private float _scaleFactor = 1.0f; + // control when to rotate each axis of your custom rotation handle private Matrix4x4? _pauseAxisX = null; private Matrix4x4? _pauseAxisY = null; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs index db7cb34b2..893e23a0c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs @@ -20,6 +20,7 @@ // ReSharper disable MemberCanBePrivate.Global #endregion +using System; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.Game; @@ -34,6 +35,8 @@ public class BumperAuthoring : ItemMainAuthoring, { protected override Bumper InstantiateItem(BumperData data) => new Bumper(data); + protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + public IHittable Hittable => Item; public ISwitchable Switchable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs index ea5f0a7c8..2f681ea7b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System.Collections.Generic; using UnityEngine; namespace VisualPinball.Unity @@ -22,6 +23,11 @@ public interface IItemMainAuthoring : IItemAuthoring { bool IsLocked { get; set; } + /// + /// Returns all mesh sub components of this component + /// + IEnumerable MeshComponents { get; } + // the following interfaces allow each item behavior to define which axes should // be shown on the scene view gizmo, the gizmo itself will use the associated // get and set methods, which are expected to update item data directly diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs index c32d079a0..fc22d5361 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.Game; @@ -50,6 +52,27 @@ public IItemMainAuthoring SetItem(TItem item, string gameObjectName = null) return this; } + public IEnumerable MeshComponents => + GetComponentsInChildren(MeshAuthoringType, true) + .Select(c => (IItemMeshAuthoring) c) + .Where(ma => ma.ItemData == _data); + + public void MarkMeshesDirty() + { + foreach (var meshComponent in MeshComponents) { + meshComponent.MeshDirty = true; + } + } + + public void UpdateMeshes() + { + foreach (var meshComponent in MeshComponents) { + if (meshComponent.MeshDirty) { + meshComponent.RebuildMeshes(); + } + } + } + /// /// Instantiates a new item based on the item data. /// @@ -57,6 +80,8 @@ public IItemMainAuthoring SetItem(TItem item, string gameObjectName = null) /// New item instance protected abstract TItem InstantiateItem(TData data); + protected virtual Type MeshAuthoringType { get; } = null; + protected void Convert(Entity entity, EntityManager dstManager) { Item.Index = entity.Index; @@ -96,7 +121,6 @@ public virtual void SetEditorRotation(Vector3 rot) { } public virtual Vector3 GetEditorScale() => Vector3.zero; public virtual void SetEditorScale(Vector3 rot) { } - public int EditorLayer { get => Data.EditorLayer; set => Data.EditorLayer = value; } public string EditorLayerName { get => Data.EditorLayerName; set => Data.EditorLayerName = value; } public bool EditorLayerVisibility { get => Data.EditorLayerVisibility; set => Data.EditorLayerVisibility = value; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs index aae5ff6e6..c2411a948 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs @@ -42,26 +42,7 @@ public abstract class ItemMeshAuthoring : ItemSubAutho private void Awake() { if (!_meshCreated && gameObject.GetComponent() == null) { - var ta = GetComponentInParent(); - var ro = Item.GetRenderObject(ta.Table, MeshId, asRightHanded: false); - var mesh = ro.Mesh.ToUnityMesh($"{gameObject.name}_Mesh"); - - // apply mesh to game object - var mf = gameObject.AddComponent(); - mf.sharedMesh = mesh; - - // apply material - if (ro.Mesh.AnimationFrames.Count > 0) { - var smr = gameObject.AddComponent(); - smr.sharedMaterial = ro.Material.ToUnityMaterial(ta); - smr.sharedMesh = mesh; - smr.enabled = ro.IsVisible; - } else { - var mr = gameObject.AddComponent(); - mr.sharedMaterial = ro.Material.ToUnityMaterial(ta); - mr.enabled = ro.IsVisible; - } - + CreateMesh(); _meshCreated = true; } } @@ -97,10 +78,48 @@ private void OnDestroy() #endregion + private void CreateMesh() + { + var ta = GetComponentInParent(); + var ro = Item.GetRenderObject(ta.Table, MeshId, asRightHanded: false); + var mesh = ro.Mesh.ToUnityMesh($"{gameObject.name}_Mesh"); + + // apply mesh to game object + var mf = gameObject.AddComponent(); + mf.sharedMesh = mesh; + + // apply material + if (ro.Mesh.AnimationFrames.Count > 0) { + var smr = gameObject.AddComponent(); + smr.sharedMaterial = ro.Material.ToUnityMaterial(ta); + smr.sharedMesh = mesh; + smr.enabled = ro.IsVisible; + } else { + var mr = gameObject.AddComponent(); + mr.sharedMaterial = ro.Material.ToUnityMaterial(ta); + mr.enabled = ro.IsVisible; + } + } + private void UpdateMesh() + { + var ta = GetComponentInParent(); + var ro = Item.GetRenderObject(ta.Table, MeshId, asRightHanded: false); + var mr = GetComponent(); + var mf = GetComponent(); + if (mf != null) { + var unityMesh = mf.sharedMesh; + ro.Mesh.ApplyToUnityMesh(unityMesh); + } - + if (mr != null) { + if (ta != null) { + mr.sharedMaterial = ro.Material.ToUnityMaterial(ta); + } + mr.enabled = true; + } + } @@ -127,17 +146,18 @@ private void OnDestroy() public void RebuildMeshes() { - if (Data == null) { - _logger.Warn("Cannot retrieve data component for a {0}.", typeof(TItem).Name); - return; - } - var table = transform.GetComponentInParent(); - if (table == null) { - _logger.Warn("Cannot retrieve table component from {0}, not updating meshes.", Data.GetName()); - return; - } - - var rog = Item.GetRenderObjects(table.Table, Origin.Original, false); + UpdateMesh(); + // if (Data == null) { + // _logger.Warn("Cannot retrieve data component for a {0}.", typeof(TItem).Name); + // return; + // } + // var table = transform.GetComponentInParent(); + // if (table == null) { + // _logger.Warn("Cannot retrieve table component from {0}, not updating meshes.", Data.GetName()); + // return; + // } + // + // var rog = Item.GetRenderObjects(table.Table, Origin.Original, false); // todo can probably ditch this, because components now update themselves // var children = Children; @@ -171,37 +191,18 @@ public void RebuildMeshes() // } // update transform based on item data, but not for "Table" since its the effective "root" and the user might want to move it on their own - if (table != this) { - transform.SetFromMatrix(rog.TransformationMatrix.ToUnityMatrix()); + var ta = GetComponentInParent(); + if (ta != this) { + transform.SetFromMatrix(Item.TransformationMatrix(Origin.Original).ToUnityMatrix()); } ItemDataChanged(); _meshDirty = false; } - private static void UpdateMesh(string childName, GameObject go, RenderObjectGroup rog, TableAuthoring table) - { - var mr = go.GetComponent(); - var ro = rog.RenderObjects.FirstOrDefault(r => r.Name == childName); - if (ro == null || !ro.IsVisible) { - if (mr != null) { - mr.enabled = false; - } - return; - } - var mf = go.GetComponent(); - if (mf != null) { - var unityMesh = mf.sharedMesh; - ro.Mesh.ApplyToUnityMesh(unityMesh); - } - if (mr != null) { - if (table != null) { - mr.sharedMaterial = ro.Material.ToUnityMaterial(table); - } - mr.enabled = true; - } - } + + private static List GetMembersWithAttribute() where TAttr: Attribute { From a9d77ff7373172ad61915ef80d324c34970c23cf Mon Sep 17 00:00:00 2001 From: freezy Date: Tue, 6 Oct 2020 00:33:36 +0200 Subject: [PATCH 045/124] style: Minor comments. --- .../VPT/TransformInspector.cs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs index 03e454d7f..39abed9b8 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs @@ -29,8 +29,17 @@ public class TransformInspector : UnityEditor.Editor { private UnityEditor.Editor _defaultEditor; private Transform _transform; + + /// + /// The first selected item + /// private IItemMainAuthoring _primaryItem; - private List _secondaryItems = new List(); + + /// + /// On multi-selection, these are the other selected items. + /// + private readonly List _secondaryItems = new List(); + private ItemDataTransformType _positionType = ItemDataTransformType.ThreeD; private ItemDataTransformType _rotationType = ItemDataTransformType.ThreeD; private ItemDataTransformType _scaleType = ItemDataTransformType.ThreeD; @@ -47,8 +56,13 @@ protected virtual void OnEnable() { _transform = target as Transform; - bool useDefault = true; + // use default inspector. we do that when no vpe-authoring items are selected. + var useDefault = true; + + // loop through selected objects foreach (var t in targets) { + + // must be main but not the table itself var item = (t as Transform)?.GetComponent(); if (item != null && !(item is TableAuthoring)) { useDefault = false; @@ -164,7 +178,6 @@ private void HandleLockedTool() { handlePos = _transform.parent.TransformPoint(handlePos); } - Handles.color = Color.red; Handles.Button(handlePos, Quaternion.identity, HandleUtility.GetHandleSize(handlePos) * 0.25f, HandleUtility.GetHandleSize(handlePos) * 0.25f, Handles.SphereHandleCap); Handles.Label(handlePos + Vector3.right * HandleUtility.GetHandleSize(handlePos) * 0.3f, "LOCKED"); From 0cccb001cf970922ddde5e37d0c07d5f0a369088 Mon Sep 17 00:00:00 2001 From: freezy Date: Tue, 6 Oct 2020 21:53:24 +0200 Subject: [PATCH 046/124] editor: Update icons. --- .../Resources/Icons/small_blue/chip.png | Bin 0 -> 722 bytes .../Resources/Icons/small_blue/chip.png.meta | 106 ++++++++++++++++++ .../Icons/small_blue/flipper_base.png | Bin 0 -> 878 bytes .../Icons/small_blue/flipper_base.png.meta | 106 ++++++++++++++++++ .../Icons/small_blue/flipper_rubber.png | Bin 0 -> 906 bytes .../Icons/small_blue/flipper_rubber.png.meta | 106 ++++++++++++++++++ .../Icons/small_blue/gate_bracket.png | Bin 0 -> 404 bytes .../Icons/small_blue/gate_bracket.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_blue/gate_wire.png | Bin 0 -> 394 bytes .../Icons/small_blue/gate_wire.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_blue/playfield.png | Bin 0 -> 406 bytes .../Icons/small_blue/playfield.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_blue/switch_no.png | Bin 617 -> 616 bytes .../Resources/Icons/small_gray/bumper_cap.png | Bin 0 -> 457 bytes .../Icons/small_gray/bumper_cap.png.meta | 106 ++++++++++++++++++ .../Icons/small_gray/bumper_ring.png | Bin 0 -> 480 bytes .../Icons/small_gray/bumper_ring.png.meta | 106 ++++++++++++++++++ .../Icons/small_gray/bumper_skirt.png | Bin 0 -> 473 bytes .../Icons/small_gray/bumper_skirt.png.meta | 106 ++++++++++++++++++ .../Icons/small_gray/bumper_socket.png | Bin 0 -> 473 bytes .../Icons/small_gray/bumper_socket.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_gray/chip.png | Bin 0 -> 725 bytes .../Resources/Icons/small_gray/chip.png.meta | 106 ++++++++++++++++++ .../Icons/small_gray/flipper_base.png | Bin 0 -> 943 bytes .../Icons/small_gray/flipper_base.png.meta | 106 ++++++++++++++++++ .../Icons/small_gray/flipper_rubber.png | Bin 0 -> 945 bytes .../Icons/small_gray/flipper_rubber.png.meta | 106 ++++++++++++++++++ .../Icons/small_gray/gate_bracket.png | Bin 0 -> 407 bytes .../Icons/small_gray/gate_bracket.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_gray/gate_wire.png | Bin 0 -> 399 bytes .../Icons/small_gray/gate_wire.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_gray/playfield.png | Bin 0 -> 409 bytes .../Icons/small_gray/playfield.png.meta | 106 ++++++++++++++++++ .../Icons/small_gray/surface_side.png | Bin 0 -> 206 bytes .../Icons/small_gray/surface_side.png.meta | 106 ++++++++++++++++++ .../Icons/small_gray/surface_top.png | Bin 0 -> 205 bytes .../Icons/small_gray/surface_top.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_gray/switch_no.png | Bin 620 -> 622 bytes .../Resources/Icons/small_green/chip.png | Bin 0 -> 725 bytes .../Resources/Icons/small_green/chip.png.meta | 106 ++++++++++++++++++ .../Icons/small_green/flipper_base.png | Bin 0 -> 881 bytes .../Icons/small_green/flipper_base.png.meta | 106 ++++++++++++++++++ .../Icons/small_green/flipper_rubber.png | Bin 0 -> 910 bytes .../Icons/small_green/flipper_rubber.png.meta | 106 ++++++++++++++++++ .../Icons/small_green/gate_bracket.png | Bin 0 -> 408 bytes .../Icons/small_green/gate_bracket.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_green/gate_wire.png | Bin 0 -> 400 bytes .../Icons/small_green/gate_wire.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_green/playfield.png | Bin 0 -> 408 bytes .../Icons/small_green/playfield.png.meta | 106 ++++++++++++++++++ .../Icons/small_green/surface_side.png | Bin 0 -> 206 bytes .../Icons/small_green/surface_side.png.meta | 106 ++++++++++++++++++ .../Icons/small_green/surface_top.png | Bin 0 -> 206 bytes .../Icons/small_green/surface_top.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_green/switch_no.png | Bin 617 -> 618 bytes .../Icons/small_orange/bumper_cap.png | Bin 0 -> 461 bytes .../Icons/small_orange/bumper_cap.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/bumper_ring.png | Bin 0 -> 470 bytes .../Icons/small_orange/bumper_ring.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/bumper_skirt.png | Bin 0 -> 464 bytes .../Icons/small_orange/bumper_skirt.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/bumper_socket.png | Bin 0 -> 469 bytes .../Icons/small_orange/bumper_socket.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_orange/chip.png | Bin 0 -> 728 bytes .../Icons/small_orange/chip.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/flipper_base.png | Bin 0 -> 893 bytes .../Icons/small_orange/flipper_base.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/flipper_rubber.png | Bin 0 -> 924 bytes .../small_orange/flipper_rubber.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/gate_bracket.png | Bin 0 -> 406 bytes .../Icons/small_orange/gate_bracket.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/gate_wire.png | Bin 0 -> 399 bytes .../Icons/small_orange/gate_wire.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/playfield.png | Bin 0 -> 410 bytes .../Icons/small_orange/playfield.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/surface_side.png | Bin 0 -> 207 bytes .../Icons/small_orange/surface_side.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/surface_top.png | Bin 0 -> 206 bytes .../Icons/small_orange/surface_top.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/switch_no.png | Bin 620 -> 622 bytes .../VPT/TransformInspector.cs | 6 +- 81 files changed, 4031 insertions(+), 3 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/chip.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/chip.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/flipper_base.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/flipper_base.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/flipper_rubber.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/flipper_rubber.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/gate_bracket.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/gate_bracket.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/gate_wire.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/gate_wire.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/playfield.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/playfield.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/bumper_cap.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/bumper_cap.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/bumper_ring.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/bumper_ring.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/bumper_skirt.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/bumper_skirt.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/bumper_socket.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/bumper_socket.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/chip.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/chip.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/flipper_base.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/flipper_base.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/flipper_rubber.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/flipper_rubber.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/gate_bracket.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/gate_bracket.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/gate_wire.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/gate_wire.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/playfield.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/playfield.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/surface_side.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/surface_side.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/surface_top.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/surface_top.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/chip.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/chip.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/flipper_base.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/flipper_base.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/flipper_rubber.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/flipper_rubber.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/gate_bracket.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/gate_bracket.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/gate_wire.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/gate_wire.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/playfield.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/playfield.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/surface_side.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/surface_side.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/surface_top.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/surface_top.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/bumper_cap.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/bumper_cap.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/bumper_ring.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/bumper_ring.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/bumper_skirt.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/bumper_skirt.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/bumper_socket.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/bumper_socket.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/chip.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/chip.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/flipper_base.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/flipper_base.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/flipper_rubber.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/flipper_rubber.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/gate_bracket.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/gate_bracket.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/gate_wire.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/gate_wire.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/playfield.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/playfield.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/surface_side.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/surface_side.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/surface_top.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/surface_top.png.meta diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/chip.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/chip.png new file mode 100644 index 0000000000000000000000000000000000000000..7145b444715e2cf2ca2dc7e07284a9376a73ab66 GIT binary patch literal 722 zcmV;@0xkWCP)>U3m&Sh|&Q|P&!Zt+Eie7V5b7B z14|u{7x5~0AQd1ov*Nl&cixuj+?lhL$W47ELV|VRxdrWzF z9^C)p=S$ce8*FQb5bu1K<~7D|nm25aullI8H_GlLLO9a-~FA=QV8msQZ>3d4d8;2cD^<=$1b+VB+==Ovul@+P2?pfoJx;{(>B&Tt!(kUaOvYL%Y z^&Cu@v7`EV&n2G5i&K;|sz>AXxvsi}_)tW5lo)b_qx1UM$?tJ^$<+~yMo+LYHB!w1 z_l`akn8))g(X#r<*~v)y{46AW;P5o%T+bE!ce(c3aTt);!QsL;)1CGDM;#KR9t_o; zn}ECx@^kMfF*8@#zQXr>q!0W%y{E2i!j{ll^7aoxs$VG^y{EDYe&7N~og&10dGz+4 zB(~-Qq|t&B1 zd6{`LvmWOLg8`NSW+_-65X}HfL-f$J7i<_60OWbOX9KgBJ*{!XX1xugB7h2jQp_15 z+5ynsPtqeqZ5WZ~>Hvx<&u`nnY-h$!;4e`QaYKaJL598$pr`h`0G`^w&|bDg*^?WB z5dACzxCG#^IJr4^eIH|sJlhuQJ||h%2T>zP<^{SXOCyYlu_V@)~ax!hdjO!kSHTd%&4R#}G{B!@tioJB#peF5N$ zu+wARjy0OG8$Q>%+JuVapfAM7l%c3YeJREJxE8oGlBEE4z)GGk|0cmqJfn~{T+W-In07*qoM6N<$ Ef_B=D5dZ)H literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/flipper_base.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/flipper_base.png.meta new file mode 100644 index 000000000..6dff0f26f --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/flipper_base.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 6714381f547802a468a239c711283e11 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/flipper_rubber.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/flipper_rubber.png new file mode 100644 index 0000000000000000000000000000000000000000..334a47c50f841044fde6ea23d4a6860ecf39fa3b GIT binary patch literal 906 zcmV;519kj~P)V1No}i z*`3{Q-hS`LzMX0|n-~YEv0ynNngYg#=)QgzXcNu@nBl{k4pc3DTAhgXdTqiifC7NU zm^I%3lmV1RNxF@wHsK7DIOn+jo(_~wjh%(RMEMn00300f9vc91I#9bQ^87=TEm;#J zzXNy$;0u7CJU0s<1K=!x{noX60J1tzTWJxEy#BEuxd~tiz(%>3OMxtETcIvU((x)g%zXeagoWwa=Ky|Kb2mxr z+JqUOM9HG`3XkzId3=?}WRWEuD4Q7RnRI$v+=u3J01jJod+cNtA4HW!66`<`Dw1T2 zXrRc-(rN0f^Uu~C>2_V4&`bD|DYV{YED@(a+SF={zKhy~WsWS~h)#DIOY}NN&iDjC z!;8y@oMF=~|WD|uj#hE3-QENP>P1r`3N#^@lGy+NI z8Cy64>2_J0urw%9@_KskvNg9NEJ1qw#1&M=k)*^a0GGwwK&h9A%JkXb*VfCKl7KdO zHEHTqydzsTbffER1)m^eJmfMlLX>(7eJyHLPo$f>;(VPGz?R5J!(!mnE9+4T&c&GP z8cg_Yml&D^Cz$X7Yi*Tv+fk5rRQMe0No9C$G zO(yNC ztmEvc;~gHK5$Dd2yfyBiV~GbkP=$Zm!|$VG%K2Ics`WMSU;J!fS!AssPYzbLOTNip g5#N{)^$GyL0bDLte_%}U@Bjb+07*qoM6N<$f9Gs6N!-}lHtA`8l#Kug&?)&Le0U>T~DmFR{CN&tHR zo8)Mps@3+^oTJowS$_f04#r&qI7NzoRQnZxt?9zAeN;A&D9u$?qEPW(HF6l7s%0gd za`eth7!X4TdZA%4$}2|pRUczUYlmyz(t&oGu(HvK@SoeC`XG5a>@qEVLuBfM?nRRS<-WmXrLGfNK?tt&XyAM&jxDEpw!9(6u=WC_DNLUy#G=F0000uUh#-n!k`CQm0PMX<5Zt#IPXGV_07*qoM6N<$f)lEyzW@LL literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/gate_wire.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/gate_wire.png.meta new file mode 100644 index 000000000..afe4ca25c --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/gate_wire.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: cdb4c35e9bc1b2a4592c2e1bb07fa147 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/playfield.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/playfield.png new file mode 100644 index 0000000000000000000000000000000000000000..f93d3c2aac4a2d2b919ffc3bc3877e8d88b7c3dc GIT binary patch literal 406 zcmV;H0crk;P)7#DXUdO{cDda$~9Ay*d*hTa@QE}FSZ(91d&H!~qn#)XeG z7tKZ!^#+R0MnRixEZb-ACsD@5?~Y3+NP3l>hgC?TK5K_P5Ky1B!yefrYJJx;E{;U> zc1>l_iPgo&^y6HjA!>)b=0HQ#4teb+(W_gQ^YaU}ArE@Udjjfn<3y!n&?OojRL7tLjrn{U z8S+fDJ8XS!oT$q2!9Pwkg*2rGEZKsl@JEswu&6CG@WzQsZKnN1Q%X}xG4(-HdOoET zQ%C51n2~iIe!{SL_t(oh3%Nlal$YVg&&?wt}z{uqfgL5+(AMGNjjhel|To9 z4&ai=!bx3{4NZVwflJ`?JjgSn+=+vq!E+=Zq8v;l~oR4 z44}_LQvf5CB|pA4ql2oldI9ie3_k-%0X+HIjk@&~NUg^Z+keqOk3a@13h0TDpCLYi zK^-EgLi_}QIzYavESZJ)@&67|^6@ZD#l9l=FUYn=Nit6#iv)r8w$$ltZJy;%@Q=nuMvjgSD z3(@hM3zBxL0Do|Iv)Q0%&3vuI@Dodtxu!>Bpw}gwF#xmoJ-^A&|mPPeis(b2G=*{-q;M1&07*qo IM6N<$f_MlGv;Y7A delta 571 zcmV-B0>u631nC5jIe!~TL_t(oh3%NlQNu70g&!J*D@h0Ds1tNRIv}Y4=pZF*3F&~O zgK*{m=^&hZBy^B8;4m^PW+SW+OR_^|{BHW&{k)P^lFzo=Et(SL#RGsF(rO&*qA^g0 zeB$Daw0elKr_x~U%7HYxr@WZP*h~&u0cjNln-p{pq?Li4gn!sh26_Ob)iT6>63`lu zkEB)5^hblX0f|`9wjdD$+9o7ILEDBz2R~Ixb<{-Hi06o*1te`@Ed^Zh9NUP zMlb*9`VL@VVSnWsoe0Q{aSotQTAcwH0r-rCWK9L6u{mNNefGKGwrgf8RYsJ*@mMh7yv+LzFOn5=N zkUeLO?wdNF7~4m7no(A4TcQ>z0_tmg0hKBfrgoTB@lg=rgEPSUiB~LyxuhctFaB6Av-6txWHVGLv z-jKDf;@9KloU(huq1d`Ul?n3wAL0@wJ-0k|phRR^+!ppdD{_IzP1)+Qsga%-!#hSB z#t6$IONJXvKe`Sngj%mYb!5kmsZZX?oSb>X`;z@sjmJuCAIefKh0g~{C97}MO)1>S@}Vg8;&lz4 zz9MJchnE}X2CpqHTczSNRgXB?;*d*PvS z!&0M^%NL{18hkSHE?v5L$;Y?Lgo7uYGx^)DH?41~_vK$C^N x?`E!0d8yT`mo#4`W@ literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/bumper_cap.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/bumper_cap.png.meta new file mode 100644 index 000000000..28e289f5b --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/bumper_cap.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 9195d4094e58c4d47b58f805f51fa0cd +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/bumper_ring.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/bumper_ring.png new file mode 100644 index 0000000000000000000000000000000000000000..4860fce9ab01725f3d19b65ae51e10f3184ff271 GIT binary patch literal 480 zcmV<60U!Q}P)Q>~)jazW_D>vNVae>cyfm5z1zgTwqDAicFIJE<_1s5rF%i z<*HbvN&LS5jYh-sE6CkW!;4G)ns0{Tq{aXE{K_T+kLI3eDpqwS4PFB{@7D`I0A8hY zztoS4h4p4#?T{lJhhZjMR?VD5y!j=Wtz|AG~V11%I0cmO_TVsjU}N>ozLYO zeOcG$nZ}8l#)+DyQF?z?pJs)6yqY&i?=`(QB^oDu4d8iT zIU74h$)TL1>+$(jY{bR&>h4~A@`rIa8M*oV`p#yh@yOZC<*LpUPZ8m0U~jSNPs)AN z*pJH9|LR?>&X!T42Ctd$WjaWQ@%tmyC1I;fjFJxk2QON6j&keq}(ETuL|UuW2r|5hq-4J$HRa*ygz= zh`J_-x~9{=r#RtaQ~hR0XV$!DK|j{~0C;DV{F{%vBz*Cbr=CK6*^6S(mhi2gUPdwV zAPG4}CdV{l+UEI+q77qoYodyzuOqUJT$c?$a$OTdT@yrI6GUAz4N(BUQ=Nd1FpieyygWUW`ex}BW>PKJl{UnPl%P1vg}M;$O}zwJ&;@*u_m3AqFl%jz-DB* zHnxnC_u?51r{`Dl=XMrcUFWy?ZW>OF_#dBN@p9tPEC^RBt7C03PbzO*FXUODXvcnS z9#z?YKe$?zry|=6Y6V|iup3Pg*qM@O>r9N2S5?P`CQ^IXIMhP7#&dFN618U|2j7{v zkiOPJIe;7ElFOd*-^TG0{hFc7{7ez!J=H;6W&Sskm`d_+5`>02Wly*b)N+tQOdtOwH4td z@M++~ES$qYAE{?b8+4o>18?33bLTL+0w*IwZaxrE7nrq<8957vgwJe@Nxb1)q^LTR z>}-_C{;~_D&6u8klA?O!u#>5ttk)M#Hu47DL|7iZVyy_<6V-Y<{QEgn|x0(MF2Od$IJYo+|#53WQW>9258r({DSz2OejosBYK~+c10kW~(5|-B0$1 z#e}&3t?_FkmZ-HS_x_Jz4Q&ty?*gJt+PQHp%t`zq*0%5y{SeqNm3cpZ00000NkvXX Hu0mjfF+@?G literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/chip.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/chip.png.meta new file mode 100644 index 000000000..e47645f64 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/chip.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 0d67a07588ce3f64a9122be24f5ad913 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/flipper_base.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/flipper_base.png new file mode 100644 index 0000000000000000000000000000000000000000..97fce3d3362eda6bb4b0061afc033a8746877d4b GIT binary patch literal 943 zcmV;g15o^lP)<) zo!Oau`{tW(-oA`=IvwlfPALy~YDfXn@I%)KCt zN@)=tFHAe6$Lpf)wxLE(@E=9^H@6k4wfaQ0R&P2^v2BxRhL>1jQX}~Rz)jzC#{e7! z@BqM1(VyoBJ0sd?zWE@GCTtQNdloE_Hr1qedGipy(3k2K#LN3WX0BIcS>n3Io2+Sr zXhx9C3X+6}aX#sL?mB>{F>{e-eNDF%*@`Wq3OTKBJz-q0C{3}&$+;>)82RihR*338 zn540!K5~Uy0M3cF0!LR5hA|{j^1xr>dLeES-X!yVzTmL1FohhG9m>Ko+A_WqpJ#(G z>LSY|>Bu}{I6vhJcQoD31z|KZC{fz=B{qEUlHS+uq20gCR#X{)qy+iw3oR%E9laUO zgw)Nn%OmZcQ%rt#NRr?ajv{+Ow9$hvnCf;sT6*5D*6Ke1INbIfz*hig0UR8XST9WS z!9me%b3S~rTC2Alr}!;tpv<0TSW^mFwwuemlWn5O2ZT&w$PQO}NkPv?E388uWHr;8 z<%|l_?Mnck#5^0U+Z_kZjtrkQGt(n6p|;Ziu39Ag2Ec1^O%Yx8J-3laR3lv0k`@JW zhw}g~^+*K=#Yc7)x$IqU4}B{o?42bhtsjFnb-c-BrEVJ>-Ij4lhtKK)YdG!*wWZ@o zdwXd5p1U|y?I{SO0!KJ49j~z~C@hauBs0))k!3NAj%8#wtW@(1bzF`~C6ho0&tuhZ zwd`o9<0*Cw6FgCyE4BKlfsRiCxRx*l9SD!qMe2pz5p*my+Ss*WBD`JNlqui-uOhawPt+;^`~j5cHoCHj R5!CvxUh>B zo}FOf{RfGama!1hgeW4uhp)JFTIGU;LHvqk(+Y z?(DwZZ)d;xv9n$4>+9GK$ZZRjJ47?UwjsJZ?gV4q0DvCetp&bU%bwOoL`J=_t^lA6 zU?^hEcK{UtqgzS3fvB;rhe@1Exc+Y7dn1{#6ZlJ%UvU+{zBaEh4WJnK-g1UK{}5$Q z))dJf0A2z33Sfjon*2drLY`V zmJl-4^cm|K$TG=Nj7LL|bS!%~1nG9dSU1`(QHpxH@r1BFR-Pa|e&!A;pOB=+DFBz1 zt*z3V-z^mRy*@QxiIbxVy;EvasE{6tbWRKu^a7t#d1rH9-mh6qb< zIqp8Pdm`Q3QOE0C0A^K1+AJl73VR{-o6>nUDJf$vpX5>49S^b;BqrIr%ZW!iT&wBHM^qydA`Kl=3cRGg9;O4|D|9q_ zGS(H@!&&IKmpv={*_)dhk|ogbM{fPv)iLSzw(#s+D$~4#I-X(DNp*Y?!0B)&)v;qj z9lr*!m_WyQ`KB_Pk0#LZ6o91`I;Mi)Wll6ihdQQ!x-K+2xn&dQggRd0?KA4w`7Ixf zC(yCRgTVL7|8#~QqhqT1BZ2Sz{u=l%em1Zy3L?oyR6|QgoK}+FZ*VO1(LRH5rY;{P{stBUaq$dfaL^OhH8pDYla6> z00#iu;Ao#J#nx-iQEGM8R{-k4xGMl>Pw`J;zXq^VUHG++UamJU&9%t0M8xZAiz2mtQVKGod?|z|775EdXVTqIa-vHQ#w!%`&mFa3d(8Bl%9h`Yw@mc49YR1Caq~V{&J!NtzDL6 z8ad^t5>%|h_r#!1no5o~x|EoIHc)E@rB)oE0Ny|yO0;~43^xD(002ovPDHLkV1hkg BqjvxR literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/gate_bracket.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/gate_bracket.png.meta new file mode 100644 index 000000000..1b07139a3 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/gate_bracket.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 2280b465ae0bc8d478632fbd4a7e8849 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/gate_wire.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/gate_wire.png new file mode 100644 index 0000000000000000000000000000000000000000..abe6191ac2a080acfa804d3eb140f5ee97172a10 GIT binary patch literal 399 zcmV;A0dW3_P)9kT()H>eI z1!}YY5rNYyh7I&a!!jtZ7}-~Sj2&%9%y}zij(W)kdXEsBBu8U_l2m;j?MX?&UQE6* z{^C%=xvO5S2@cRnwWuLb&dT?8D;21>TdAxk1?4OzQtKzBBst;hfX002ovPDHLkV1mf{qOkw~ literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/gate_wire.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/gate_wire.png.meta new file mode 100644 index 000000000..a2f6ad6e2 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/gate_wire.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 0da5c3d87f0c01b4885755d34a622d24 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/playfield.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/playfield.png new file mode 100644 index 0000000000000000000000000000000000000000..b099c3fd3d3896a0780971efa9dd2e2c46f52053 GIT binary patch literal 409 zcmV;K0cQS*P)S1hbAqH-)_7QjB%j) zL~qwr1|6&N@iF~4mS~9DA+Ise5Vb>In@RNImSw(|5fnLuUCZWaOEhHdqnT}~nrDM<~x;m(iK?l0# z^J!#AGtuU-^|^7P%K8U?KhYS{lwiAshO)16H294?Y zlu}Gdg2rEcfKQ8ar9Mf@L}RR7>dz)YW2{}OAR_t#VYEfDjx$-L00000NkvXXu0mjf D9!ItW literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/playfield.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/playfield.png.meta new file mode 100644 index 000000000..a28281180 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/playfield.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 488d89d465de76e498f53de708806529 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/surface_side.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/surface_side.png new file mode 100644 index 0000000000000000000000000000000000000000..f354eb6b0f46099f1d128c4580ff836076b7ef51 GIT binary patch literal 206 zcmeAS@N?(olHy`uVBq!ia0vp^S|H591|*LjJ{b+9I14-?iy0W${Xm$pP}ST5DA?fX z;usRq`u6%k&K3s&){E;UIu_zopr0F$an?f?J) literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/surface_side.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/surface_side.png.meta new file mode 100644 index 000000000..bea0ef58f --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/surface_side.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 60fd30638251c1647985752052016404 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/surface_top.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/surface_top.png new file mode 100644 index 0000000000000000000000000000000000000000..4f431315063f0f2028a3244a95b42a06ced91814 GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^S|H591|*LjJ{b+9I14-?iy0W${Xm$pP}ST5C|K|5 z;usRq`u6%k&chBotQY5RXx+JG$z++_0)9`~5@ literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/surface_top.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/surface_top.png.meta new file mode 100644 index 000000000..7f53302f8 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/surface_top.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: e66832c816a4c904f82f241e452f481d +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/switch_no.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/switch_no.png index fcee7e100a44f672fb3f22bc1e27b8f3674502e7..416af36f2342741daa8dc05ff9a8855c23c57624 100644 GIT binary patch delta 576 zcmV-G0>Az21nvZoIe#EYL_t(oh3%NlZNfkhg&$FrYfJ@kDu52+4iY3w_AR6XN}vQf zh;y?gAK;urpaW7tpo35W(V|&2ti0g;Az;bxf>`hF`@BCh1D)-5izeu%5tIOK&oOCU zlo5alfF3n{02rl7{A)X>chI~jhXCG{=2rj#fEU|&y>7h*Qh(~%Wo~bvCm@~W1+*sQ zw~L1}sKH8(U3{EC4ItmrB%Zo>S%VrvX0|?3R-pe42^-K$K*ALCQjjnKy(A=bDKsz2 z5P$&dv*tRP#RxJl%08u4@hR$n6@V;F;+5L>pv=pQQsm>zGTqgNBp(s3o-|!%Vxf2u zvj?TYb5`-33x87V))K(|iLN4(MG}^uQC^m9ggJn2n#3Id0|0ARNK(ci#he53=#uA# zp7n@nr`?LuTmCS}P^}#`D{guwMVt|+e)D+^p|{;qU7s4LrCx_aw7M0h5$|a%_Kqj7Jo##&UsPtty^07?Z+r{sp1R= zx1MjqgbuU{87ODerflP5#z%Z6>KGnJGx`w*y7}TjPsQP;w-d8Y&@edLY*NRxP|g4PZAmEp?(R1H5mRR?@(h$wyOv~YoBJ|WGe(@c%Am4E55 zq9mm7usNh-U~_@AvMx%lS&fUMSFaY-w^~r&YC(Og1@)~K)VG=e3g8bbLG(?aGD;@^ O0000S<61ndNmIe#8WL_t(oh3%N%ZNe}R#y_g6uZ0PkPCz$kHYiAuoHytOjKBzN zQ2Lfgc?i#aC~QC{C~N=|P&qoI!^J7F9iURaxA@Q9FX!{cPHVT@p)Mt9HU#h#i)iHP zqBc;1e51$rSVTh?dpCZt4y8d#4U#mQy4ds%dIVC*3DzrU34f%Lgq_&f_6B+aq|(yH zz8BC6kgu_btd`#y^c;|I1w9ueTtLqW30u%}L&6615|F40dMQX$0lg%o)U5$308pHK zSo6yX_9{UpX(sLW$j=7A3cxfL(MlhCaC%D8tStwg2xSdPesTcMh9NTj5nN3*4iGaT%C zz6=veXdSYxAmQMoY&)VZaE&Si4b+snxh)W3*DWQ=^7k~EvM zLcgZXn-ie&qjvoMnr&0?kCv|rpnCZ+>3G4XhLApACM{ebnV*1cnKaXD?9o3Z>`)R= zd00{!SU24uO|m|eT(kaN9ld%rpuW|B`c?z#TMejhHK4xrKR^Ne03YTEoy587`~Uy| M07*qoM6N<$f-IH~7ytkO diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/chip.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/chip.png new file mode 100644 index 0000000000000000000000000000000000000000..b7a7bc7fff5499d422046563f44bce5d2c71cf46 GIT binary patch literal 725 zcmV;`0xJE9P)0{hFc7{Fez!J=H>ftKvjCx2^U2-78`Pbk*`VnQ zUt@ED*c(V2I2+glm?};=78iz0D#ntcpdUa$IFaIK-Y?Hk*LBj^o)^XTyvY2u+w&sF z5s+uNCUrjn2{2YI0pK10c6_z5Dks^Fo}D}+`8};|jU=J~;5Pf>$qN9O(kPfbXLEZc z+B-%=^a>3%2C}V!M#iS)q+Z0H$!7p?P0x=2aG>Xmss022C0la@fQ=OTE{P~P!-j3# zH7Wp@OQDaUeS)f|lkAfu(24J2FDDWCl95DJt(Y1w4bA+P!3r%>FXw10#Mojfl7^|WN-vXr+devq@LzMC_Pi=X8 z34HDNFmvxP&_~LNu?ijMSI3*T!PGm9roa(o$khiT>I1XZL6EaxNVs8RNa7XeB86^D zvawMj``0dvRYQ9EQ40OSVMkLvIj_&XY!nQ-Jz-|7TC=TgQR5SKeV7hNj^mo8Q$%5` znvX~I7)+6|r}|~jB_7A4SCl-d9-h3uV}I(}VN+J023K z9*otU`-r>^%GcgWq36D^b%h`LNFVq-y{FVRVM}l=1^Wjv)o+-M-Wsc-AGiQ=uLucV z9)rCniml}UX|$3;2QQXE)lXU00000NkvXX Hu0mjfn~G2b literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/chip.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/chip.png.meta new file mode 100644 index 000000000..d488ed8a0 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/chip.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 55bfd6cf0cb47064c8d134819a5f271a +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/flipper_base.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/flipper_base.png new file mode 100644 index 0000000000000000000000000000000000000000..10efbb39ed9fa2ab7be666d27129915cde7a1632 GIT binary patch literal 881 zcmV-%1CIQOP)4h-z3jp%G-1SVbn?0>j#AbaM`9%N~0Hv5S zM6?5-y`Q9qh=!3*o~r{WraZspnP4k3b^?Eia)=uu%oZ~AeE>bR-v#i*GXd>oOO!pi zAqdgWGJuN!4yrRd0Nw)lB%Tq;P0s}SpKu17^=pdcbpTglND__%xW@bP%$+du%UKc4 zz4(2j$RW45HHAhg?5~s@wgI$UOTlo6Elw+v9|5d;CddIe3g8}qA7Y>0y$Rryct-Xb zVdNiiNt8TF+O$S*bMg?r(I3?%h{O9K#uj6ScObw$*op!T*C&W-cZ3hQ0ks)mtY=gQ)Qs1|>c#*+4^D)<0a#j_H7S34s$ zBvH!TpJKfcXM~fa5w|CBNR%*(0+XGogc%jacjEV}VdM{yWs=k~52v(W;c_Q+yB0=% zZCav~^<^&j;E>)`?@;zPxfE5WASv++z%%8Psah`))$MbY!LDk_Lfb))Y z{Fy6@4ExZhhl!ICuAOBjt=phW9q%w%soM^Fx1V~X!@au18jfqBu5|oVeR}A6CfJ;5 z_Qd6^lA(^5^HS=#5_6SI!gl}e@Kn~$c@@d*Hz6HHJ;cwiTq4|3L&Qs`KNhHVo!<36|1z3bn9@nr+cq9{DPH`KGoQJraV3BO4)#b485YY?buR@7e#qJJM*tn5*zLm+#CYfwzqk;RX z+1Z`lZ{B|I$G)9twOSYlsIg$VOEd+H4beUQE(k(B3t);5>z?xK>C@^&tk(yj&H^X^ zn2%ZW4L}({X_Tbfhz6maViIR8*WdA!Urddifxkrg6;}c5AMhS)0CJx4w^HQ!hbUXJ zE=Ya{@B+XW06%$d8bAiXX#jhTYqtSpJ>_qtMKtpIhl1offJFfB4U&WgpL@U?i$H7N z2BFTUMRcO_>nb_Usv!B?a{V~~b7F3p9MQED$fBkd8iFJpudu`11@KH*n67;a;D<4H zowOc=I^&WkS(IMk5k4l5ukn~Hvgj$_Bu08Bo!%7pp}8D@gT~x8J6Y8QQDu+>J5YqG zBuVg;Pga&r(_o!{Hs(mTt3jxpgfE#w8(qc{ar&c8t;FbiAqaJuBa1VllU>FVz0Q#{ zJ_67*=H^+qv#y99GRD%IcMyb{NcMZ+R{)Pi2s_SX6NNCvnI*zuV>}atx{WN8%=fWq z1d`4Zwr~W}?NSix(x61i>*>Ku#@w>71nKb;S5O&Ck`gBXToiKyrCuT`(`S=kTQ6ry z0@~!|q^Vc&j!fOqjWk=qCCC`}xlD`@rQSkciyGAv>E^aL-{1tWAu`gi7&!IHdX$3m zLdw!303U_JB?YD4O8^cS>q)nHPxQ1n|K^#~JfYrPd#{&@p{bZuZbIC4?)f6OE8i$K+7g z42@Ps)^WDf@g|Q?iF0R1-Ws>ivBW)3`GtSl!|$VG%K1f4`8!_&|HaP+mPOVG^5kG; kv*g?TE8-fvM4bY_Z(^b literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/flipper_rubber.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/flipper_rubber.png.meta new file mode 100644 index 000000000..5da3376e0 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/flipper_rubber.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 6632056569cc11d4799f873c08a37a50 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/gate_bracket.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/gate_bracket.png new file mode 100644 index 0000000000000000000000000000000000000000..ad12094c494784d74e89bfb1850a7451a9b87a7b GIT binary patch literal 408 zcmV;J0cZY+P)ssu%{PzX4VtvfqL`AsCt@;&+Aoor{*bsbWWNP;pY(Cpe4djQ)7unbj8q3Yp4 z2H*_f5FPDPCjixOWX(}(_10ei+y?9RW4l1{@A{hqD5oZ7QmD&#@Y)vD@9DIXLRC86 z(FSU={uzMNDTWF3LBldBrx?jseTW^cXUuskW{x_^1lk0MO_HM_KuM}TjrJskVlO7w z7=Ljn;oMcH)&vXaqFU4xC}-t6yA=!6*{xXClY(*<6RGu!Qj{GXUxnw$2r7k2raghF z^1Ymj0qW(H4V1%v7Eq3Y@>(;a=O9t8@A|VrId*hTYbwVN5;oAr=SXIeSB_4C>QngF ulTQpSB}Z%hCTi6Bvw>PGD7Df61@Ho^&`La+Qm%;r0000P8} znzLr3iFyM?XQQCyI+pdb_me0W?03hx6C}Oz*25|!QJ=NL9tfz<+F_4m61BeTxnM^k zdb_4F=u~C($MoY=q9JOByrw`y)DC&=Cef=~mgQbXP~;GHEt{t;(U7%IdfGsPCu;Ld zJ5es!nTQInNO~2m_eiEhx2WCfZ35k*cB^;tiH1DrA@32W&y5q6jzO2`=Ab$T9q5+N zr;#DeMBBsG=f;UDA0GU}L}N%(s>hNnXbgWOsUC~kLIZD{sMKcKO*E!7r4&;aG^XcM zN--q~8h`ZxJ}oYl`Xnh6jj?vAKbr)Nv39AFi0BJC>_%s+S(oJi0000qUM?j$PkcMCUAEWc6@h(<i-uHXg8^z~qoDH~T{MEhj+~u<_)n>t+>ZPwT+b;1emGm;6k_MEV twa~;lbLqLKTbujzXFoTB3Ya=gzH_czsNTp*3g{FD22WQ%mvv4FO#m=kNd5o- literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/surface_side.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/surface_side.png.meta new file mode 100644 index 000000000..4733eca4e --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/surface_side.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 77df35743e514d14cb78611f3f80c9a2 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/surface_top.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/surface_top.png new file mode 100644 index 0000000000000000000000000000000000000000..649d9071eccd5a3de85c41ca7c2a95f395ddf989 GIT binary patch literal 206 zcmeAS@N?(olHy`uVBq!ia0vp^S|H591|*LjJ{b+9I14-?iy0W${Xm$pP}ST5DA?fX z;usRq`u6%o&cg;gY!CMzZBFg;yPP*ka+8CVliI50mkf0~*}31T{czw|=>FbTv}#&_ zTITWhTXi4IDBY^^{MNDhR5$%8ej0ag{PJgf{w{Tq^z@gpjIXX;=3FZ5r4E#s8(_7t w#OYzopr0Q1^S82|tP literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/surface_top.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/surface_top.png.meta new file mode 100644 index 000000000..cf72647d7 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/surface_top.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: f46b65ae5116c744a81083e0d9bf4a62 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/switch_no.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/switch_no.png index b4533b21b887ce65d173a3852a48164b5e907955..12187217e4ec1151f3a9571f414a107f41e9ce79 100644 GIT binary patch delta 572 zcmV-C0>l031nLBkIe#2UL_t(oh3%Nlal$YVg&&?wt}z{u3ZR2fffKI2BD1iGK-w3{gNR@lYTQPP`L#|(|^NxnaZsz9Q^IqXts1ohJ#x# zw_(Z$T8E6aGwRZ|$u*NBex~}G9Vl0VIZx1STT{tYhWPCZapPA>lo`*mNxWvo(`2hq zktJVTrsa*Ft19J^@GH|-T~(wXld2Ow4-C0{nY8kO6n=UlvQ>K5b8O{bI-)7*aeAO_ zUnEiHay5aBa&AhlS&hr1SFaW{v|7;6YC%J*1r4nhG_;xl3g8bnK=q!aWiI3Z0000< KMNUMnLSTYnRt>oT delta 571 zcmV-B0>u651nC5jIe!~TL_t(oh3%Njal$YVhJQ4fTmv0A6_5@>1qxh!3F&|mD1i0&~rf|1oWJc@C7|LBz!ceAqb3el)eg^g!1KMN_ zbC(w>)RYzPOG1KY5zCe>&d@|vPmwBQK=~AOTz;}V<$qJ>a{=Cuv25Am3V%4h{TdHW5!;fZo75t5$M)Cu-13z z)*K;YwkAv+J2Ga>P)iIQ7%EW_JtD{05G3P()#}F6~!qSU&fETrm z7q!h`L?^mN!PyMJ1Au1$3r8+{0BZo-Ac|A9^HiAxXSb5vy(2jjJ4yQcBq}%y0eoCp z&csU)#jA3ShW+z9adaE~yxkR#`?DWTMjppKk7h|Yp|^S`HQt!AfkXZP{7Ta;D*I8v z*&M*@l||o!C_cyym4r_NHcqw9*{G5*Ri+?{zW^j|{f;CwcZIqVS|r@cops28=G0RA z%|xYiMu$%T=E{&&OK&y9$jdC%mClmdx0_B(NjlT?@7q`k&eW#t(rfr_o^8CSZM>*$ zF8cQ*I9t-rf2wq~N>7^4nj+<`gD7sSf=vm3N`lLlLTyP%xRR?IMQfti6}8dTZS!13 z(S$a-XQGm%t0=Ueq?j5C!lLA!mbZ75lyg00000NkvXXu0mjf Dl6uN0 literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/bumper_cap.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/bumper_cap.png.meta new file mode 100644 index 000000000..bf6976903 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/bumper_cap.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: a9825ee77904e0349b778294bc0bb8d9 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/bumper_ring.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/bumper_ring.png new file mode 100644 index 0000000000000000000000000000000000000000..34869bcc58c5a56bb06a1c148eb3a0930e74762e GIT binary patch literal 470 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 Ef`!?xa{vGU literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/playfield.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/playfield.png.meta new file mode 100644 index 000000000..b6d760ed5 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/playfield.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: d2cadd0664cbae64db585a1713f66a10 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/surface_side.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/surface_side.png new file mode 100644 index 0000000000000000000000000000000000000000..183bb5d9e4cc645bc6b86e98d7560e4511734128 GIT binary patch literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^S|H591|*LjJ{b+9I14-?iy0W${Xm$pP}ST5DA?%f z;usRq`u4gbZ;OKf>qUM?4zDooFpCGwnjQ{p)2|w|C^UG>E}LA%rDgoGq$*?W(x#0r zsgqvr|ND&3YF|w7q^0kVh0k1XJ|#`#?aW_`9iG2TTVy+X<&nu&Urn4d+b;1emGm+O wN}dgvwQx(&^G~-Nk59i_JQFG)wa_zf!a~8*Nl`mxfR17CboFyt=akR{0P3(!4FCWD literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/surface_side.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/surface_side.png.meta new file mode 100644 index 000000000..b12294205 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/surface_side.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: fa06d89f2588f2e40b50eddad11d166d +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/surface_top.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/surface_top.png new file mode 100644 index 0000000000000000000000000000000000000000..d34797cf4d95537b13691eaef02176877c6d41f2 GIT binary patch literal 206 zcmeAS@N?(olHy`uVBq!ia0vp^S|H591|*LjJ{b+9I14-?iy0W${Xm$pP}ST5DA?fX z;usRq`u6%k&chBotQY5RD4jWFn#`Sc>q4&r<&}wNCoz39Y8O2d^1*>)q5FGV(W+?y zYMJ|Mt92jDDBY^^{MNDhR5$%8ej0ag{PJgf{xEfs^z@gpjIXX;=3FZ5r4E#s8(_7t x#OYAz21nvZoIe#EYL_t(oh3%NlZNfkhg&$FrYm8h#oC=@<#~mb85Yhp6U%2>A z2XQ)pa}EJlKq?3nU@25Uv}hI$D=&C|2w3vFAlAG4KJU-WKxez%q6xZb1SNpmb4*%h zaROihphry~07hY2{Mydx9kk5iA%J(K`4vC_;Kg=cuUoHylz)15ncExa2}oyo0j&x7 z?c(7KYOs=H7au231IV{9Ev7DB)}V%vxvh_s73hCM!UpsbkT3*$w!2%Cry``SSVh^ z>_KVpoK-yMf`1gdwFGc~qN~VciG<~6l$T{2VGf`hrbP$90KnQ6l9V$@G3S6hy5zZ` zXFX!tX}6;EmOl(KQfo)eikqHEQKx><*Mk*Pd{*pb9>tlJE6VG{$^w_#c)tF$xZT`m ze8gv@j**}Ndob6zDEa!%5E49!oXGv0AwZLUGf7as1%HXIbD70_>y{RN`!UK~syM^J zt>@b?p#!Z#2Fe+=Dcks%@e!YiI)=y5oPLCXZoW9sQ*pTI?Zw~+dcFwLLc8+ERA%v< z1^P8z-YEe}A9>?H!n7EwpmhU&W%x1xRl|=?)d8Ox5=vh>EnFa(PegO+G*e@2dtrpa`T2S9=L4B(Q^{r-r0{8S<61ndNmIe#8WL_t(oh3%Nlal$YVg&&zrt}){R;#81S;Lt&!0!Rnkec|Fe z9fWjX&N&2J0jVHRfM=irGV-jLwSpWh$p&WpZr0E4=hbR0xwGHzQJ1nf907RtqjYTR zqBc;1e5c0`KT1b7_HNu@6{SE54YN3$+1PXrdIVC+3f3uT34f%NfSsDyb_RL^q}0m9 zz7x<2kZ*pJ8ZEyyXcLgI1#JovHlR&H!W6V=NSJ`00}@q1&jpDppyz}Xy464h0P>R$ zYkob!UM0vZ4u$m;)PET1JdSc*-P{xqtCjs!H88R1v@}qS72b3l+ z06f(U8PI3+{(qmL-vD|Nmgne{LGFZe09`*yI{*d%HnxzY8G{ry2jrtmK6ljjL`=Ez zh|*jBFvx(19r}n@&B-2sFM2FQO!2d3FY_pJRz|eX#*Wp=Lew^4O`it4oBNrR_!+Bn zB&f$a7CJ9}lqT%)t|BCO6;W)d;tU?@x{A~x3CfqCr+@R4#UWohlLPQ!j$%s{XDIA? zz6?`JXcf{^afBL6CnCA&?ZxB=>RkCv|rplbQi>3G4Xh8}&sbXwX#GCu*?(rK>N*rR_+*r6n# z^01;bFgLnE>STNgJ7S}mw+wVh!=lssI20 M07*qoM6N<$f|C&tu>b%7 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs index 39abed9b8..bc5c37b1d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs @@ -48,9 +48,9 @@ public class TransformInspector : UnityEditor.Editor private float _scaleFactor = 1.0f; // control when to rotate each axis of your custom rotation handle - private Matrix4x4? _pauseAxisX = null; - private Matrix4x4? _pauseAxisY = null; - private Matrix4x4? _pauseAxisZ = null; + private Matrix4x4? _pauseAxisX; + private Matrix4x4? _pauseAxisY; + private Matrix4x4? _pauseAxisZ; protected virtual void OnEnable() { From aa45570169416c07011db23b97e73c40ede0283e Mon Sep 17 00:00:00 2001 From: freezy Date: Tue, 6 Oct 2020 23:15:39 +0200 Subject: [PATCH 047/124] playfield: Add components. --- VisualPinball.Engine/VPT/Table/Table.cs | 4 +- .../VPT/Table/TableMeshGenerator.cs | 6 + .../Resources/Icons/small_blue/table.png | Bin 0 -> 468 bytes .../Resources/Icons/small_blue/table.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_gray/table.png | Bin 0 -> 473 bytes .../Resources/Icons/small_gray/table.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_green/table.png | Bin 0 -> 471 bytes .../Icons/small_green/table.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_orange/table.png | Bin 0 -> 473 bytes .../Icons/small_orange/table.png.meta | 106 ++++++++++++++++++ .../Toolbox/ToolboxEditor.cs | 4 +- .../VisualPinball.Unity.Editor/Utils/Icons.cs | 6 + .../VPT/Table/TableInspector.cs | 2 - .../Game/DefaultGameEngineAuthoring.cs.meta | 2 +- .../Import/VpxConverter.cs | 36 +++--- .../VPT/Flipper/FlipperAuthoring.cs | 2 +- .../VPT/Gate/GateAuthoring.cs | 2 +- .../VPT/HitTarget/HitTargetAuthoring.cs | 2 +- .../VPT/Kicker/KickerAuthoring.cs | 2 +- .../VPT/Light/LightAuthoring.cs | 2 +- .../VPT/Playfield/PlayfieldAuthoring.cs | 57 ++++++++++ .../PlayfieldAuthoring.cs.meta} | 4 +- .../PlayfieldColliderAuthoring.cs} | 12 +- .../PlayfieldColliderAuthoring.cs.meta | 11 ++ .../PlayfieldExtensions.cs} | 16 ++- .../PlayfieldExtensions.cs.meta} | 2 +- .../VPT/Playfield/PlayfieldMeshAuthoring.cs | 11 ++ .../Playfield/PlayfieldMeshAuthoring.cs.meta | 11 ++ .../VPT/Plunger/PlungerAuthoring.cs | 2 +- .../VPT/Primitive/PrimitiveAuthoring.cs | 2 +- .../VPT/Ramp/RampAuthoring.cs | 2 +- .../VPT/Rubber/RubberAuthoring.cs | 2 +- .../VPT/Rubber/RubberExtensions.cs | 4 +- .../VPT/Spinner/SpinnerAuthoring.cs | 2 +- .../VPT/Surface/SurfaceAuthoring.cs | 2 +- .../VPT/Table/TableAuthoring.cs.meta | 2 +- .../VPT/Trigger/TriggerAuthoring.cs | 2 +- 37 files changed, 579 insertions(+), 59 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/table.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/table.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/table.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/table.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/table.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/table.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/table.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/table.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs rename VisualPinball.Unity/VisualPinball.Unity/VPT/{Table/TableExtensions.cs.meta => Playfield/PlayfieldAuthoring.cs.meta} (61%) rename VisualPinball.Unity/VisualPinball.Unity/VPT/{Table/TableExtensions.cs => Playfield/PlayfieldColliderAuthoring.cs} (69%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldColliderAuthoring.cs.meta rename VisualPinball.Unity/VisualPinball.Unity/VPT/{Table/PlayfieldAuthoring.cs => Playfield/PlayfieldExtensions.cs} (60%) rename VisualPinball.Unity/VisualPinball.Unity/VPT/{Table/PlayfieldAuthoring.cs.meta => Playfield/PlayfieldExtensions.cs.meta} (83%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldMeshAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldMeshAuthoring.cs.meta diff --git a/VisualPinball.Engine/VPT/Table/Table.cs b/VisualPinball.Engine/VPT/Table/Table.cs index b0ebeb038..1e10a1b74 100644 --- a/VisualPinball.Engine/VPT/Table/Table.cs +++ b/VisualPinball.Engine/VPT/Table/Table.cs @@ -35,7 +35,7 @@ namespace VisualPinball.Engine.VPT.Table public class Table : Item, IRenderable, IHittable { public override string ItemName { get; } = "Table"; - public override string ItemGroupName { get; } = "Tables"; + public override string ItemGroupName { get; } = "Playfield"; public CustomInfoTags CustomInfoTags { get; set; } public int FileVersion { get; set; } @@ -503,7 +503,7 @@ public Table(BinaryReader reader) : this(new TableData(reader)) { } public RenderObject GetRenderObject(Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { - throw new NotImplementedException(); + return _meshGenerator.GetRenderObject(asRightHanded); } public RenderObjectGroup GetRenderObjects(Table table, Origin origin = Origin.Global, bool asRightHanded = true) diff --git a/VisualPinball.Engine/VPT/Table/TableMeshGenerator.cs b/VisualPinball.Engine/VPT/Table/TableMeshGenerator.cs index 9aa191d95..aacb52d7f 100644 --- a/VisualPinball.Engine/VPT/Table/TableMeshGenerator.cs +++ b/VisualPinball.Engine/VPT/Table/TableMeshGenerator.cs @@ -34,6 +34,12 @@ public TableMeshGenerator(Table table) _table = table; } + public RenderObject GetRenderObject(bool asRightHanded = true) + { + var material = new PbrMaterial(_table.GetMaterial(_data.PlayfieldMaterial), _table.GetTexture(_data.Image)); + return GetFromTableDimensions(asRightHanded, material); + } + public RenderObjectGroup GetRenderObjects(Table table, Origin origin, bool asRightHanded = true) { var material = new PbrMaterial(table.GetMaterial(_data.PlayfieldMaterial), table.GetTexture(_data.Image)); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/table.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/table.png new file mode 100644 index 0000000000000000000000000000000000000000..47ad11eeb268bb1d499c1a36347cf7e25b16fd3c GIT binary patch literal 468 zcmV;_0W1EAP)okqlaV}V!zaW29$hK1R}xt{PNpz^3b*|eCWC<0epE5Ip{)7y^SP5NuS`B zM7Igr2$Djy5_UW?sEXc)s4mn`8WlgWq8n+!6S1OME<1)KnkAoz71f2xGKV5kbeGU0 zNQ`KP<-&yn{*Cjh)X=04w@#exF&+EFW=xUtJG~-}OO-R(v zPu52d7j{J@R_%QlGx|?X@j9D_xf#v%R-`jt+=^Z`pBOWm8UTM34P^E^+X$cl0000< KMNUMnLSTZt0mmx< literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/table.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/table.png.meta new file mode 100644 index 000000000..da9a5e1c8 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/table.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 1c79eb0667e42444089590373be7ae81 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/table.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/table.png new file mode 100644 index 0000000000000000000000000000000000000000..c3d3fbecc8d8c47443e6206b5f7d99b258ce9880 GIT binary patch literal 473 zcmV;~0Ve*5P)6IioDl zumMa!*`O?tAftz58DhWGelAt=NfC$y=kv>N$H`sWws283MF!x@amXQ8<%6@42q@_j z+>+=fLK|LUh}Oc6Ck9o~{~?;I@;i=-n^4iUwBVUg(Il50LlRArPlSr*s!TG6B2aW2 z(ZfrKXtI1_6cr#ubWUs4Bybkaa{wP6nKe~d&jNL>%AeTs9MLxbi=OT7NqR%#!7;fH zZJ>ik0I#&^&K|6a_nv>HD#~GNRo!`)<5cuXKvFZM?L^fSd!yfEtf4RVcBRXXqBhH}SlqA79n5w2Q^Z5y2N#FJF zGh^S(%JOq;dEclvWtP^hZ^bzQb=K9X%-T1xj%SGmLn|q>gPr&Jswrx^8W%IoIGAGN z6E*Xb^wGnHT~UcudmqM({*rUNF6LowMpL~N>5Lb*qJNrCj2Vp$fFp=BWkJzRq@(}< N002ovPDHLkV1f>U(X{{o literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/table.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/table.png.meta new file mode 100644 index 000000000..70cd9289c --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/table.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 7d32030c97474654e9510c65bf348037 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/table.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/table.png new file mode 100644 index 0000000000000000000000000000000000000000..731841f6c0222afccf5459e4538763ee76a69eb8 GIT binary patch literal 473 zcmV;~0Ve*5P)`wWL$VC9Uur*>DmhXFBEdO+xpth4nx=t`x=1qsUzS5oNnSl!8wtRJ z^a<`sbQ_=zCm}>jVaGGQs_6d^P4a3VM#YY==tf%bg0Ei3zpZ)RlqCA7S2)ax=!r`g!8ym;7M7^Pvl-|MC`+QxbC0&iHnPwPF zp>c`o`HA}IVZyGc#HzguLq>neC0(Func create, string actionName) whe private GameObject CreateRenderable(IRenderable renderable) { - var rog = renderable.GetRenderObjects(_tableAuthoring.Table, Origin.Original, false); - var obj = VpxConverter.CreateGameObjects(renderable, GetOrCreateParent(_tableAuthoring, renderable), _tableAuthoring); + //var rog = renderable.GetRenderObjects(_table.Table, Origin.Original, false); + var (obj, _) = VpxConverter.CreateGameObjects(renderable, GetOrCreateParent(_tableAuthoring, renderable)); return obj; } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs index 0551ff2b2..f5d5521f4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs @@ -6,6 +6,7 @@ using UnityEditor; using UnityEditor.Callbacks; using UnityEngine; +using VisualPinball.Unity.Playfield; using Object = UnityEngine.Object; namespace VisualPinball.Unity.Editor @@ -134,11 +135,15 @@ public static void OnScriptsReloaded() DisableGizmo(); DisableGizmo(); DisableGizmo(); + DisableGizmo(); DisableGizmo(); DisableGizmo(); DisableGizmo(); DisableGizmo(); DisableGizmo(); + DisableGizmo(); + DisableGizmo(); + DisableGizmo(); DisableGizmo(); DisableGizmo(); DisableGizmo(); @@ -150,6 +155,7 @@ public static void OnScriptsReloaded() DisableGizmo(); DisableGizmo(); DisableGizmo(); + DisableGizmo(); DisableGizmo(); } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Table/TableInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Table/TableInspector.cs index 1c20d3d6f..9e098552a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Table/TableInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Table/TableInspector.cs @@ -49,8 +49,6 @@ public override void OnInspectorGUI() } } } - - base.OnInspectorGUI(); } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/Game/DefaultGameEngineAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/Game/DefaultGameEngineAuthoring.cs.meta index e741094c0..5687a8b9d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Game/DefaultGameEngineAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/Game/DefaultGameEngineAuthoring.cs.meta @@ -5,7 +5,7 @@ MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: 5d2f099f5d6bcdd47ad8b5cd9f62e65c, type: 3} userData: assetBundleName: assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index ecde9f869..e36606c17 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -123,7 +123,7 @@ public void Convert(string fileName, Table table, bool applyPatch = true, string private void ConvertGameItems(GameObject tableGameObject) { - var createMainObjs = new Dictionary(); + var createdMainObjs = new Dictionary(); var createdMainMbs = new Dictionary(); var renderables = from renderable in _table.Renderables orderby renderable.SubComponent @@ -138,27 +138,25 @@ orderby renderable.SubComponent _parents[renderable.ItemGroupName] = parent; } - // create object(s) - var rootObj = CreateGameObjects(renderable, _parents[renderable.ItemGroupName], _tableAuthoring); + if (renderable.SubComponent == ItemSubComponent.None) { + // create object(s) + var (rootObj, rootMb) = CreateGameObjects(renderable, _parents[renderable.ItemGroupName]); - // if the object's names was parsed to be part of another object, re-link to other object. - if (renderable.SubComponent != ItemSubComponent.None) { + createdMainObjs[renderable.Name.ToLower()] = rootObj; + createdMainMbs[renderable.Name.ToLower()] = rootMb; + } else { + // if the object's names was parsed to be part of another object, re-link to other object. var parentName = renderable.ComponentName.ToLower(); - if (createMainObjs.ContainsKey(parentName)) { - var mainObj = createMainObjs[parentName]; + if (createdMainObjs.ContainsKey(parentName)) { + var mainObj = createdMainObjs[parentName]; var mainMb = createdMainMbs[parentName]; + var (rootObj, _) = CreateGameObjects(renderable, _parents[renderable.ItemGroupName], mainMb); rootObj.transform.SetParent(mainObj.transform, false); - SetupGameObjects(renderable, rootObj, mainMb); } else { - Logger.Warn($"Cannot find component \"{parentName}\" that is supposed to be the parent of \"{renderable.Name}\"."); - SetupGameObjects(renderable, rootObj); + throw new InvalidOperationException($"Cannot find component \"{parentName}\" that is supposed to be the parent of \"{renderable.Name}\"."); } - } else { - var rootMb = SetupGameObjects(renderable, rootObj); - createMainObjs[renderable.Name.ToLower()] = rootObj; - createdMainMbs[renderable.Name.ToLower()] = rootMb; } } @@ -170,20 +168,20 @@ orderby renderable.SubComponent // } } - public static GameObject CreateGameObjects(IRenderable renderable, GameObject parent, TableAuthoring tb) + public static (GameObject, IItemMainAuthoring) CreateGameObjects(IRenderable renderable, GameObject parent, IItemMainAuthoring parentAuthoring = null) { var obj = new GameObject(renderable.Name); obj.transform.parent = parent.transform; - SetupGameObjects(renderable, obj); + var mb = SetupGameObjects(renderable, obj, parentAuthoring); // apply transformation obj.transform.SetFromMatrix(renderable.TransformationMatrix(Origin.Original).ToUnityMatrix()); - return obj; + return (obj, mb); } - public static IItemMainAuthoring SetupGameObjects(IRenderable item, GameObject obj, IItemMainAuthoring parentAuthoring = null) + private static IItemMainAuthoring SetupGameObjects(IRenderable item, GameObject obj, IItemMainAuthoring parentAuthoring = null) { IItemMainAuthoring mainAuthoring = null; switch (item) { @@ -199,7 +197,7 @@ public static IItemMainAuthoring SetupGameObjects(IRenderable item, GameObject o case Rubber rubber: mainAuthoring = rubber.SetupGameObject(obj, parentAuthoring); break; case Spinner spinner: spinner.SetupGameObject(obj); break; case Surface surface: mainAuthoring = surface.SetupGameObject(obj, parentAuthoring); break; - case Table table: table.SetupGameObject(obj); break; + case Table table: table.SetupGameObject(obj, parentAuthoring); break; case Trigger trigger: trigger.SetupGameObject(obj); break; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs index 7cb94b57d..f77ea457e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs @@ -30,7 +30,7 @@ namespace VisualPinball.Unity { [ExecuteAlways] [RequiresEntityConversion] - [AddComponentMenu("Visual Pinball/Flipper")] + [AddComponentMenu("Visual Pinball/Game Item/Flipper")] public class FlipperAuthoring : ItemMainAuthoring, IHittableAuthoring, ISwitchAuthoring, ICoilAuthoring, IConvertGameObjectToEntity { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs index 088e02df4..5b3519aaf 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs @@ -27,7 +27,7 @@ namespace VisualPinball.Unity { [ExecuteAlways] - [AddComponentMenu("Visual Pinball/Gate")] + [AddComponentMenu("Visual Pinball/Game Item/Gate")] public class GateAuthoring : ItemMainAuthoring, IHittableAuthoring, ISwitchAuthoring { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs index 4b1c4472d..75b90f3b5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs @@ -28,7 +28,7 @@ namespace VisualPinball.Unity { [ExecuteAlways] - [AddComponentMenu("Visual Pinball/Hit Target")] + [AddComponentMenu("Visual Pinball/Game Item/Hit Target")] public class HitTargetAuthoring : ItemMainAuthoring, IHittableAuthoring, ISwitchAuthoring, IConvertGameObjectToEntity { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs index e471aebd1..e8f5b98ae 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs @@ -30,7 +30,7 @@ namespace VisualPinball.Unity { [ExecuteAlways] - [AddComponentMenu("Visual Pinball/Kicker")] + [AddComponentMenu("Visual Pinball/Game Item/Kicker")] public class KickerAuthoring : ItemMainAuthoring, IHittableAuthoring, ISwitchAuthoring, ICoilAuthoring, IConvertGameObjectToEntity { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs index 8d58becc0..6d7b4bff3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs @@ -26,7 +26,7 @@ namespace VisualPinball.Unity { - [AddComponentMenu("Visual Pinball/Light")] + [AddComponentMenu("Visual Pinball/Game Item/Light")] public class LightAuthoring : ItemMainAuthoring { // protected override string[] Children => new[] { "Bulb", "Socket" }; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs new file mode 100644 index 000000000..d8f20ef85 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs @@ -0,0 +1,57 @@ +// 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; +using Unity.Entities; +using VisualPinball.Engine.Game; +using VisualPinball.Engine.VPT.Table; +using VisualPinball.Unity.Playfield; + +namespace VisualPinball.Unity +{ + public class PlayfieldAuthoring : ItemMainAuthoring, + IHittableAuthoring, IMeshAuthoring, IConvertGameObjectToEntity + { + public IRenderable Renderable => Table; + + public IHittable Hittable => Table; + + protected override Table InstantiateItem(TableData data) => throw new InvalidOperationException("Table is not instantiated via authoring component."); + + public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) + { + var table = gameObject.GetComponentInParent().Item; + table.Index = entity.Index; + table.Version = entity.Version; + } + + public void RemoveHittableComponent() + { + var rc = gameObject.GetComponent(); + if (rc != null) { + DestroyImmediate(rc); + } + } + + public void RemoveMeshComponent() + { + var rc = gameObject.GetComponent(); + if (rc != null) { + DestroyImmediate(rc); + } + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableExtensions.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs.meta similarity index 61% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableExtensions.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs.meta index 760edd4b8..c74ebc1b3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableExtensions.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs.meta @@ -1,11 +1,11 @@ fileFormatVersion: 2 -guid: d624ee55abceeb741be902bd20946b72 +guid: 7390cd1bbd9b18440927b4b5783d0508 MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: d2cadd0664cbae64db585a1713f66a10, type: 3} userData: assetBundleName: assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldColliderAuthoring.cs similarity index 69% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableExtensions.cs rename to VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldColliderAuthoring.cs index 177d8a57f..c71007a0f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldColliderAuthoring.cs @@ -14,19 +14,13 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -using Unity.Entities; using UnityEngine; -using VisualPinball.Engine.Game; +using VisualPinball.Engine.VPT.Table; namespace VisualPinball.Unity { - internal static class TableExtensions + [AddComponentMenu("Visual Pinball/Collision/Playfield Collider")] + public class PlayfieldColliderAuthoring : ItemColliderAuthoring { - public static MonoBehaviour SetupGameObject(this Engine.VPT.Table.Table table, GameObject obj) - { - var ic = obj.AddComponent(); - obj.AddComponent(); - return ic; - } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldColliderAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldColliderAuthoring.cs.meta new file mode 100644 index 000000000..41a1ac535 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldColliderAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cadafc60dfc23e1459f751b53eb23fc6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: f63edb05ae86a0143b878ca31a160d89, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/PlayfieldAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs similarity index 60% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/Table/PlayfieldAuthoring.cs rename to VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs index f9fb5747b..172d3af6d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/PlayfieldAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs @@ -1,4 +1,4 @@ -// Visual Pinball Engine +// Visual Pinball Engine // Copyright (C) 2020 freezy and VPE Team // // This program is free software: you can redistribute it and/or modify @@ -16,16 +16,20 @@ using Unity.Entities; using UnityEngine; +using VisualPinball.Engine.VPT.Table; +using VisualPinball.Unity.Playfield; namespace VisualPinball.Unity { - public class PlayfieldAuthoring : MonoBehaviour, IConvertGameObjectToEntity + internal static class PlayfieldExtensions { - public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) + public static void SetupGameObject(this Table table, GameObject obj, IItemMainAuthoring parentAuthoring) { - var table = gameObject.GetComponentInParent().Item; - table.Index = entity.Index; - table.Version = entity.Version; + obj.AddComponent().SetItem(table); + obj.AddComponent(); + obj.AddComponent(); + obj.AddComponent(); + obj.name = "Default Playfield"; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/PlayfieldAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/Table/PlayfieldAuthoring.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs.meta index bd372eef0..914ec3993 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/PlayfieldAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 1e0f92d4d85af904a85fc150f50431a6 +guid: 8aa8dd251b7f9a34183b8ae054a53435 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldMeshAuthoring.cs new file mode 100644 index 000000000..f4c19fcd8 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldMeshAuthoring.cs @@ -0,0 +1,11 @@ +using UnityEngine; +using VisualPinball.Engine.VPT.Table; + +namespace VisualPinball.Unity.Playfield +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Playfield Mesh")] + public class PlayfieldMeshAuthoring : ItemMeshAuthoring + { + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldMeshAuthoring.cs.meta new file mode 100644 index 000000000..9341dad70 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2313a60d1c21395489a39c29cf9be78e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 83133eb5125b2c345a5df8b2da7817a0, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs index 3217f791c..35f32988b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs @@ -22,7 +22,7 @@ namespace VisualPinball.Unity { [ExecuteAlways] - [AddComponentMenu("Visual Pinball/Plunger")] + [AddComponentMenu("Visual Pinball/Game Item/Plunger")] public class PlungerAuthoring : ItemMainAuthoring, IHittableAuthoring, ICoilAuthoring, IConvertGameObjectToEntity { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs index 7c9c8c25d..e6c166b7e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs @@ -27,7 +27,7 @@ namespace VisualPinball.Unity { - [AddComponentMenu("Visual Pinball/Primitive")] + [AddComponentMenu("Visual Pinball/Game Item/Primitive")] public class PrimitiveAuthoring : ItemMainAuthoring, IHittableAuthoring, IConvertGameObjectToEntity { public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs index 91e58bab0..1a225eec6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs @@ -30,7 +30,7 @@ namespace VisualPinball.Unity { [ExecuteAlways] - [AddComponentMenu("Visual Pinball/Ramp")] + [AddComponentMenu("Visual Pinball/Game Item/Ramp")] public class RampAuthoring : ItemMainAuthoring, IDragPointsEditable, IConvertGameObjectToEntity, IHittableAuthoring { //protected override string[] Children => new[] { "Floor", "RightWall", "LeftWall", "Wire1", "Wire2", "Wire3", "Wire4" }; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs index b0f898ef4..f00e8fd82 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs @@ -30,7 +30,7 @@ namespace VisualPinball.Unity { [ExecuteAlways] - [AddComponentMenu("Visual Pinball/Rubber")] + [AddComponentMenu("Visual Pinball/Game Item/Rubber")] public class RubberAuthoring : ItemMainAuthoring, IDragPointsEditable, IHittableAuthoring, IMeshAuthoring, IConvertGameObjectToEntity { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs index a950c06ca..f66496329 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs @@ -17,14 +17,14 @@ using System; using Unity.Entities; using UnityEngine; -using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT; +using VisualPinball.Engine.VPT.Rubber; namespace VisualPinball.Unity { internal static class RubberExtensions { - public static IItemMainAuthoring SetupGameObject(this Engine.VPT.Rubber.Rubber rubber, GameObject obj, IItemMainAuthoring parentAuthoring) + public static IItemMainAuthoring SetupGameObject(this Rubber rubber, GameObject obj, IItemMainAuthoring parentAuthoring) { var mainAuthoring = obj.AddComponent().SetItem(rubber); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs index 2613c7eac..65095302e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs @@ -27,7 +27,7 @@ namespace VisualPinball.Unity { [ExecuteAlways] - [AddComponentMenu("Visual Pinball/Spinner")] + [AddComponentMenu("Visual Pinball/Game Item/Spinner")] public class SpinnerAuthoring : ItemMainAuthoring, IHittableAuthoring, ISwitchAuthoring { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs index b7dd5230a..178b73130 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs @@ -30,7 +30,7 @@ namespace VisualPinball.Unity { [ExecuteAlways] - [AddComponentMenu("Visual Pinball/Surface")] + [AddComponentMenu("Visual Pinball/Game Item/Surface")] public class SurfaceAuthoring : ItemMainAuthoring, IHittableAuthoring, IConvertGameObjectToEntity, IDragPointsEditable { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs.meta index 481b1779c..396632119 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs.meta @@ -5,7 +5,7 @@ MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: 9d233d228acb6fa46b6a3cc394debd67, type: 3} userData: assetBundleName: assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs index d0b91de03..624dae81c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs @@ -30,7 +30,7 @@ namespace VisualPinball.Unity { [ExecuteAlways] - [AddComponentMenu("Visual Pinball/Trigger")] + [AddComponentMenu("Visual Pinball/Game Item/Trigger")] public class TriggerAuthoring : ItemMainAuthoring, IHittableAuthoring, ISwitchAuthoring, IDragPointsEditable, IConvertGameObjectToEntity { From 1de56f99524c5d704db3522538b85dfe1559df0d Mon Sep 17 00:00:00 2001 From: freezy Date: Tue, 6 Oct 2020 23:38:54 +0200 Subject: [PATCH 048/124] editor: Update icons. --- .../Icons/large_blue/bumper.png.meta | 4 +- .../Resources/Icons/large_blue/chip.png | Bin 0 -> 6541 bytes .../Resources/Icons/large_blue/chip.png.meta | 106 ++++++++++++++++++ .../Icons/large_blue/flipper.png.meta | 4 +- .../Resources/Icons/large_blue/gate.png.meta | 4 +- .../Icons/large_blue/keyboard.png.meta | 4 +- .../Icons/large_blue/kicker.png.meta | 4 +- .../Resources/Icons/large_blue/light.png.meta | 4 +- .../Icons/large_blue/plunger.png.meta | 4 +- .../Icons/large_blue/primitive.png.meta | 4 +- .../Resources/Icons/large_blue/ramp.png.meta | 4 +- .../Icons/large_blue/rubber.png.meta | 4 +- .../Icons/large_blue/spinner.png.meta | 4 +- .../Icons/large_blue/surface.png.meta | 4 +- .../Icons/large_blue/switch_nc.png.meta | 4 +- .../Resources/Icons/large_blue/switch_no.png | Bin 7327 -> 7621 bytes .../Icons/large_blue/switch_no.png.meta | 4 +- .../Resources/Icons/large_blue/table.png | Bin 0 -> 5237 bytes .../Resources/Icons/large_blue/table.png.meta | 106 ++++++++++++++++++ .../Icons/large_blue/target.png.meta | 4 +- .../Icons/large_blue/trigger.png.meta | 4 +- .../Resources/Icons/large_gray/chip.png | Bin 0 -> 6510 bytes .../Resources/Icons/large_gray/chip.png.meta | 106 ++++++++++++++++++ .../Icons/large_gray/keyboard.png.meta | 4 +- .../Icons/large_gray/switch_nc.png.meta | 4 +- .../Resources/Icons/large_gray/switch_no.png | Bin 7338 -> 7638 bytes .../Icons/large_gray/switch_no.png.meta | 4 +- .../Resources/Icons/large_gray/table.png | Bin 0 -> 5257 bytes .../Resources/Icons/large_gray/table.png.meta | 106 ++++++++++++++++++ .../Icons/large_green/bumper.png.meta | 4 +- .../Resources/Icons/large_green/chip.png | Bin 0 -> 6570 bytes .../Resources/Icons/large_green/chip.png.meta | 106 ++++++++++++++++++ .../Icons/large_green/flipper.png.meta | 4 +- .../Resources/Icons/large_green/gate.png.meta | 4 +- .../Icons/large_green/keyboard.png.meta | 4 +- .../Icons/large_green/kicker.png.meta | 4 +- .../Icons/large_green/light.png.meta | 4 +- .../Icons/large_green/plunger.png.meta | 4 +- .../Icons/large_green/primitive.png.meta | 4 +- .../Resources/Icons/large_green/ramp.png.meta | 4 +- .../Icons/large_green/rubber.png.meta | 4 +- .../Icons/large_green/spinner.png.meta | 4 +- .../Icons/large_green/surface.png.meta | 4 +- .../Icons/large_green/switch_nc.png.meta | 4 +- .../Resources/Icons/large_green/switch_no.png | Bin 7317 -> 7618 bytes .../Icons/large_green/switch_no.png.meta | 4 +- .../Resources/Icons/large_green/table.png | Bin 0 -> 5250 bytes .../Icons/large_green/table.png.meta | 106 ++++++++++++++++++ .../Icons/large_green/target.png.meta | 4 +- .../Icons/large_green/trigger.png.meta | 4 +- .../Resources/Icons/large_orange/chip.png | Bin 0 -> 6567 bytes .../Icons/large_orange/chip.png.meta | 106 ++++++++++++++++++ .../Icons/large_orange/flipper.png.meta | 4 +- .../Icons/large_orange/gate.png.meta | 4 +- .../Icons/large_orange/keyboard.png.meta | 4 +- .../Icons/large_orange/kicker.png.meta | 4 +- .../Icons/large_orange/light.png.meta | 4 +- .../Icons/large_orange/plunger.png.meta | 4 +- .../Icons/large_orange/primitive.png.meta | 4 +- .../Icons/large_orange/ramp.png.meta | 4 +- .../Icons/large_orange/rubber.png.meta | 4 +- .../Icons/large_orange/spinner.png.meta | 4 +- .../Icons/large_orange/surface.png.meta | 4 +- .../Icons/large_orange/switch_nc.png.meta | 4 +- .../Icons/large_orange/switch_no.png | Bin 7343 -> 7642 bytes .../Icons/large_orange/switch_no.png.meta | 4 +- .../Resources/Icons/large_orange/table.png | Bin 0 -> 5257 bytes .../Icons/large_orange/table.png.meta | 106 ++++++++++++++++++ .../Icons/large_orange/target.png.meta | 4 +- .../Icons/large_orange/trigger.png.meta | 4 +- .../Toolbox/ToolboxEditor.cs | 14 +-- .../VisualPinball.Unity.Editor/Utils/Icons.cs | 20 ++-- 72 files changed, 968 insertions(+), 114 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_blue/chip.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_blue/chip.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_blue/table.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_blue/table.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_gray/chip.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_gray/chip.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_gray/table.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_gray/table.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/chip.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/chip.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/table.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/table.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/chip.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/chip.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/table.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/table.png.meta diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_blue/bumper.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_blue/bumper.png.meta index c51d65c8d..a7d975bb1 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_blue/bumper.png.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_blue/bumper.png.meta @@ -63,7 +63,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -75,7 +75,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_blue/chip.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_blue/chip.png new file mode 100644 index 0000000000000000000000000000000000000000..e2a5603cd1b3273cce5effc9b6c7768c25e303de GIT binary patch literal 6541 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 w7rx9Tyr1V>=bY=zb)D``fDv-%j4w z^vnAZEXJ@9w^3E7$fx^l-3h}v9Gg45L%5~~QEHKx!Vz(jWuqXh;;OOLb z{~rUzHLOxD+ku)djxVcaa1Jl38IAKVW@NA-bk>9F`SDO@eUr}+t7QJgPzRN@^wBJo zFJSpIW1Y%M;i@03`Euk<(NT(snWHdM(9N0W)Jl(4M3|_0Arkc3kUT|-@n539t&6u& z=ZpC)q~n4FPN!o4@p9C2yzFcI>}_`SDdC7iqJHOK(nIDoUUr5S((>!Y;v+NDxiAg& z6eQ5A@U2Q4pzh^`d^(I0bwjw_kth%hn>Ne-L+#(ee(<->%=F4fGK27{MFb3F8qPta ztTc$ygljkn^7M6qd301Y^lbhGHE^wI>6w|SQ3xf0+}8`hiLN`)sB|hs;nhX--jxQ# z`+U$)md46xT0RKu5d=<_B+nuZMdr&qekYJ80b7a^%_V8j9zYqk-1!3Vv$KFOq^aqf z?BN6mXC!6W*MeB*e}^abCbbfIWBB znGyLY;^jaFE2!?Z((p!c7_^EZMZQfm^j{DK%zL;=I=H2fW;c@75nMYQAh zPV`X@{&Ncn7A)xz9}b(}e++=JI9m&k2DRdoBJYU+c!{%XcfyYn@Z%!@vc=f7CTKvj zY{%wWBY>kgz04HF$UaU<*cON<}U4c7Xx^8H3_iedkdt& zF&nz$;)Thg?0i>v$4vTmW^fnXmcEDv|A?|Jz1MrJ9L3`u0(%94qC7L>R}PHr5Cp|! zytY9fq|1v2igL`17mw4=L4$*?2DaWRq>uuP17 zf)6iw1VNDALY6QG8;3b7nA<|uFt?4v!ReCTLiPwkH$SA7Y?e_D%sXKJ?L`<22);wB zIZV$J>ccE1PDqNk|~U(GPV3L^x$Bv@~N3P&u|~Y*H2tF!IdGZEPAq0W>ExI=n6S z?BQ^HFjCw^wI~>I^lFu01m_3lxKQ9IN3T`^Mq7HkFxt{nh7m_E61FVNkw(H>LYTv8 z!9LbFoR%1jwm5kdh}q(FV6?>{P@r*(6NS+h2bW#h-J20;X`?`!`Q|)|VIQ&_snc~N zSm(?`X_pB-hOHg0RAD{$B2s7X5kcXbZR zhmqnI=M3C;ZgDWeY;i8YU2uzo(N>Vst{`tKIC$^m>2stgxPobLPzsEcwm4^yw`+@o z(N=gU7mz2k#lZ-*rRNHQA8zKMqg@rQNt-j!kUom=kt3}YM-iO2 zkS@$^Nu^+J3mKpY*ErJ1TQ%b(JXOZ~7OnyJHTv66$Jm+mwAOL@3>HVt&OT+f_F<)R z_1sW2DF_-D5NC&0`Bpi8$6tN6L@h8`rjjy>K1@uk_E=G6|E}kWqWrqg^x)c-{)8qu zUfg92Iq{^DFJCq0gH8OQ&rAgT?URvXwz$E^(Go?`2Fl@YtEwEWlk2`_C4vdgL24<8 zHka33#JepOij-2IOFrun@PRzI(Dvr97@Jw_TSdyMqr}+d$uBgm?h)qE3@iFm4D>Y1 zh9mGh&&?u74&s?Iy|SuScCuL=;lp}?xAi*E2i(`Sl*pX(@wZk--Y z&}I(fMoWO6V$5>=yFtctOS-be%u3o4C4M(AGU5>*e1N@rJfsR%!|Z+)x|ya~T}{Rx z7G)+3MVqOw42pzY*L)<%EJ<9?$wfLjlRVc2&aY?M(v@@M=+qsJOBrnXlZg4SAI0GK zHdodw1suHn#M3><85XbcLs|+0#`;bVkxowDO%ujF{Zf38#m46ilWy*M0(OY6V07)h zGeBQYHCvd*doj~~Y-=}5Z~k|t%ff(q|D~`0QSt^MT@{FDl(41B7?+c2j`CmF%mUWc zxXwsVO0N%3c`2}a;#;+E=W0D_vWQT^e#QKX#TNF{68e*nT8Zu-uAZ|B5@yjz@+!bGspqt6btrSB`C)hv3bHwRdu$v4k5kkbCv3c*gI2KP<+ zPONM1ujfMf@kWV6RI)}=X}-;QF>M(32m0>r;Kpe+f<{-B3I0LX1J+or=UUy}XMy_N z3QX}?xA`I6@rZGgHzca zm}gocKg1olLaeDYo_g)zIF#YK^TE{Xw|3o!7!*ki!K&A<3p!zUmH!Bu+ovx zOu{lC{AocG{?3EH@DcQ!wj0`$s~C}ibgoB(^mCWJFJ%*~R6us{iX_RPZf@1`ZEd=a z-onaEAde{=``xtx%*UX(IYOK2(O6wt$20b&{aB4TZ zeYA{?&njV$?EJ8Q#XSIaPz=UIcds=r-(J`Uj}46o7A;5R#$Urs79Hc_^|Y?%32k@@6ML6tAg<`)&{=e6?|M zB4MX^s`l@iI_MKku{&me9%9((ugSzh8MEo*?AbdEG4|WzrWbt1&W7G~cB<+ptW4Zq*yw>mHzPT^_FBH>jk@ZS{P4=#STRCT#P#o=zCU`R`=H=YcO+a_ zB(mAACU43v@M{Td!w{}mLBAGH?BW{TC)9d3j2~(}zmo<1^Gh{G!j|AcAcFYg8{VV8 z&mR1xX`TL=ybt!2Ey`}WD=U7gk2P16(78R%b8?Qb($6=GA(-8HIA{E}RZL&f;B(%_ zXfDlBJ^ZZKvJ0iMSEMSvj`o=LzKo<;>k8PzBeo8!EJb(ICm%POb~9C_yAA60J(gs6 zy{$}XORqC)SV0kKeeA%ul~-d$t4IyIoao9@GpV-Y%j><-zp!1y?#n+8qAgs#3BDP3+i=}L<>nh)w2k=Xt)@^{1gAOMg5W`nS_ZG`dQkU z7b!k!IJ#FSRkAm^ETC}Hi^@sMd-T449sVv6#YQ_z??T3Vqn(IAak-Uj)lg3@x0u3< zWnWDhwSsb+nf;lRn`l|goj1up;`g(;l@NqWO$ozRgHk)n~t^c1RkH_ zI_lRKIj?*q0+ZvTuB|NV@BjG1DN$l=t_8 zD_+}9@#>U096@aN%}V>K{&70n;buAMwtI0H*`M5VI&@b)Qp?nsVQ8a=TSpQ*_fux0 zcXofdtqP`ezwv6B`p>_?5SBa^bZ?3ozmx_xp0!jq#)8DU=m0dC{!sll*9o1!edAcH z2iGm{;xO~btPV~TNY?qPC2aWIueJwb*d&j|hxZkdBQA}_V^N}kw6QBcOk%FaeVJHt$B1QJcwYxDh{rZ)SWY^w^!)ao?u z442*O%`-}@nSw6lAsO?JOh@jqf`+0YlOF<`Z5uxR(t#f#>h9@{kkRj^_dXqsv_G8_ zHx!09fB(dLfAMg8WtBK|t}AWu6c%l6Qe*UiFkJHm@*z44%Tyt2OW>yPRB%I$KF6Dh zbYqy?!-Y}{1f9yJt9(0j=!+{*ifMNhz^`36MbWP=S!w@`7>G`cc+}bWN<}+0R|TkM zczi)RJ^Ga})jAQ5UR)@HS}HsDPZIrN%e8YIG=AjWdIm5Bb06uk{z2uEyr?iWoz%br zHuWE06zwTF#N;AZM&U}zDJuk}+GW(DA}oIG%tFBiPR^%TJ=oO`W(W9(K|%_f5xVa+kdTW_*asU zl!cFUo{bKKuU`5EOlPOM+S^RKUC)okiH(|w?9~q}dnnqAQzp9@Gj)xbtTQJrRVX|P z89M#v*6@BCZ(+k(AJItC_Pw?R4C*uNwt#&=sT`NOYux{k+4`e_cTite{_x?7u;~X2 zlNXD&E7(4iw?4S%u_j!y{*(>8ADN_H_lnPL?P+q=HYuClznoA!I@V|XmMh6%M2b78 z2r-LJTaJZ~H;g@LI<^QGG!vB~g67%RD~QAR`&XpkudVO~{1Pz7$Loc18=!obsZk`x zf~LTJR$pJAuub^hiGZTiMRq*Tn+buoY5Po8Md?0Jyz+@Q-&;lUt@6cqPY-r|C#@J8 zkEVx}emX*QqVK9h}mK3)4=OAOh$#oWgQp}xZH&|{EnQxAMn z#kN&m4M`@I;Dw$2C5ahgwZoMuYH6erNC-_X->@-ehVi?PeMZzZS4_{1+uvl5cy)OY zG^-^&$1cxppE{ocWtBjV39D=tBX`^}x^7$f%H=t)4xTGtu-FgmXT+?ogGx2?-}L^& zj7`wzop+m$MHQWh8j5sG8dSoJH2-pbD+ABP79al@glcioS~A-2fv_DhnG-W@I}9IA zuU4O-i;P94*L@nxO--2nHddtawdPAl^TyRK8Y#wzb}D%!u}8mcc)So96RtzGfz_0Y~c*+CO|Z+OX??*OhwzbJHFXXHN3;m27il z9l_;yv@EFDOG%X5L-4YVhc zHC!QIA~2EH>{3mb|JpOwdAUJKX^1a$VR}ZWVDM!K-QnSjg>2O>Q(ASRD+6_?rRQc!c^>0^S zVNU$T?S9$(LRWU-(o;EM5H5mz*i&?IJFnxEE=IqkM=-(^C5zkN^JQ87X!c|bUvhH|3Y5E=7SIsDlxk9Ak z2%@W%tC88v%{RBtK{v8T?!OM}oS7|W(`V%w_p~HYegRQ?zu69Yc#hlR@_@X2G^v3^hhP44`Dhn$fzo`JV}IBSL0z4DKr{ZNz^JGUk zgH2?}+}wcVnQ!GAS4oEUbfT~Q-+QNdh{QZ(t2-^HIYzrc%^C`8uR zR8M;T47n(u2p_sUlMjH2Gro-gS{)@#dp@2BD7;9f~VTQ_n?woKLK z`xGPD3pxv9H7TZdq|Qds>o^k z!!SuROEZJ%Hm^@)qOiEJ+MqTJAtgQK$OE%)g%i|2*~9rSKTP}{*1|^-2Q0PeYY$;k z6Zax(V!~tKr8@j?lH#-n0Jq@#a=@?pU+~`~{C6e%?{|Sc+=F9ph4k7#B-5|M|H}ev MO9zYU!+uHs1KE2jPyhe` literal 7327 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 wxPE3Od6ysqn<>vhg~9f^+iN5zo} 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 T9Df=HpwBT2d-JNp-f{m0`TZ-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_gray/switch_no.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_gray/switch_no.png.meta index 6c9b410c9..b9b44962b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_gray/switch_no.png.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_gray/switch_no.png.meta @@ -63,7 +63,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -75,7 +75,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_gray/table.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_gray/table.png new file mode 100644 index 0000000000000000000000000000000000000000..cccc6bc8306c447d8a046665591718fa2c783e3f GIT binary patch literal 5257 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 literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_gray/table.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_gray/table.png.meta new file mode 100644 index 000000000..c5357dfd4 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_gray/table.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 2670959f8bdb5f54fabae24086085f3d +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + 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 + 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: 512 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/bumper.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/bumper.png.meta index 7741388ea..0eb997967 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/bumper.png.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/bumper.png.meta @@ -63,7 +63,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -75,7 +75,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/chip.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/chip.png new file mode 100644 index 0000000000000000000000000000000000000000..ca497cc866e15d3b4cc1e2b22e20e5aa57103b3b GIT binary patch literal 6570 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 DEgOL^ literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/chip.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/chip.png.meta new file mode 100644 index 000000000..fe7bb6dbe --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/chip.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 7b7096e95e670b0459f127c46f657f06 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + 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 + 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: 512 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/flipper.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/flipper.png.meta index 2de44e643..ce1d40787 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/flipper.png.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/flipper.png.meta @@ -63,7 +63,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -75,7 +75,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/gate.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/gate.png.meta index 898f48f61..0d594ca2d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/gate.png.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/gate.png.meta @@ -63,7 +63,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -75,7 +75,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/keyboard.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/keyboard.png.meta index b6603a858..7bf6ad2ed 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/keyboard.png.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/keyboard.png.meta @@ -63,7 +63,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -75,7 +75,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/kicker.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/kicker.png.meta index 790152d0a..d17653729 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/kicker.png.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/kicker.png.meta @@ -63,7 +63,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -75,7 +75,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/light.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/light.png.meta index 2a6c6f732..30df68302 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/light.png.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/light.png.meta @@ -63,7 +63,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -75,7 +75,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/plunger.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/plunger.png.meta index 6ee59cffb..b74657cd4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/plunger.png.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/plunger.png.meta @@ -63,7 +63,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -75,7 +75,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/primitive.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/primitive.png.meta index 114b6a6b9..4cf000e2d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/primitive.png.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/primitive.png.meta @@ -63,7 +63,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -75,7 +75,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/ramp.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/ramp.png.meta index 68e2ee25f..02d135e47 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/ramp.png.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/ramp.png.meta @@ -63,7 +63,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -75,7 +75,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/rubber.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/rubber.png.meta index 87b1df76a..e7af4c08c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/rubber.png.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/rubber.png.meta @@ -63,7 +63,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -75,7 +75,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/spinner.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/spinner.png.meta index adedad3d2..376316af3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/spinner.png.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/spinner.png.meta @@ -63,7 +63,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -75,7 +75,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/surface.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/surface.png.meta index 7a6495104..20a62b0f3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/surface.png.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/surface.png.meta @@ -63,7 +63,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -75,7 +75,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/switch_nc.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/switch_nc.png.meta index d0a0e3600..c2a7aa41c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/switch_nc.png.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/switch_nc.png.meta @@ -63,7 +63,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -75,7 +75,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/switch_no.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/switch_no.png index 38ef0fd3b857b9353173f0fc91b21dae20adf100..aa2cc214da89f68e1ec5cd2951a43b5ffae2e521 100644 GIT binary patch literal 7618 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

am_eZ1xaR{uo?=> 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 MO!b(OJ4q7xf29A0IRF3v literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/table.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/table.png.meta new file mode 100644 index 000000000..04ca0bf81 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/table.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 96cc61c00e6d7fc4a934b116456297e3 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + 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 + 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: 512 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/target.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/target.png.meta index 9fe020750..cbee65842 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/target.png.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/target.png.meta @@ -63,7 +63,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -75,7 +75,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/trigger.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/trigger.png.meta index c59af7d42..b83ca9880 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/trigger.png.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/trigger.png.meta @@ -63,7 +63,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -75,7 +75,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/chip.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/chip.png new file mode 100644 index 0000000000000000000000000000000000000000..4681acf2fd03dae367945cabbc928494c92ccd19 GIT binary patch literal 6567 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 M#O`ppsaO2}01OgMF#rGn literal 7343 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 ZiS21kE~lEEss-@p*in1)YE$31{{vCIa%KPk diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/switch_no.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/switch_no.png.meta index 5bfe9f35c..f4cea32e7 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/switch_no.png.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/switch_no.png.meta @@ -63,7 +63,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -75,7 +75,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/table.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/table.png new file mode 100644 index 0000000000000000000000000000000000000000..5cef7486e5c30e2dc9e78030538d03f560417bd3 GIT binary patch literal 5257 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 literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/table.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/table.png.meta new file mode 100644 index 000000000..aff2296cb --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/table.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 50569535e846a204dbb40c81fe9106a6 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + 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 + 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: 512 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/target.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/target.png.meta index 9305c0321..e86bca711 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/target.png.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/target.png.meta @@ -63,7 +63,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -75,7 +75,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/trigger.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/trigger.png.meta index c31ca7f02..abe124723 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/trigger.png.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/trigger.png.meta @@ -63,7 +63,7 @@ TextureImporter: platformSettings: - serializedVersion: 3 buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 @@ -75,7 +75,7 @@ TextureImporter: forceMaximumCompressionQuality_BC6H_BC7: 0 - serializedVersion: 3 buildTarget: Standalone - maxTextureSize: 2048 + maxTextureSize: 512 resizeAlgorithm: 0 textureFormat: -1 textureCompression: 1 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs index 0172c117e..206ff5aec 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs @@ -63,6 +63,11 @@ protected override void SetTable(TableAuthoring table) { } private void OnGUI() { const IconColor iconColor = IconColor.Gray; + var iconSize = position.width / 2f - 4.5f; + var buttonStyle = new GUIStyle(GUI.skin.button) { + alignment = TextAnchor.MiddleCenter, + imagePosition = ImagePosition.ImageAbove + }; if (GUILayout.Button("New Table")) { const string tableName = "Table1"; @@ -79,13 +84,8 @@ private void OnGUI() return; } - GUILayout.Label(_tableAuthoring.name); - - var iconSize = position.width / 2f - 4.5f; - var buttonStyle = new GUIStyle(GUI.skin.button) { - alignment = TextAnchor.MiddleCenter, - imagePosition = ImagePosition.ImageAbove - }; + EditorGUILayout.Space(); + GUILayout.Label(_tableAuthoring.name, new GUIStyle(GUI.skin.label) { fontStyle = FontStyle.Bold }); GUILayout.BeginHorizontal(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs index f5d5521f4..36dca8be5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs @@ -25,15 +25,15 @@ public class Icons { private readonly struct IconVariant { - private readonly string _name; - private readonly IconSize _size; - private readonly IconColor _color; + public readonly string Name; + public readonly IconSize Size; + public readonly IconColor Color; public IconVariant(string name, IconSize size, IconColor color) { - _name = name; - _size = size; - _color = color; + Name = name; + Size = size; + Color = color; } } @@ -49,6 +49,7 @@ public IconVariant(string name, IconSize size, IconColor color) private const string SpinnerName = "spinner"; private const string SurfaceName = "surface"; private const string HitTargetName = "target"; + private const string TableName = "table"; private const string TriggerName = "trigger"; private const string SwitchNcName = "switch_nc"; private const string SwitchNoName = "switch_no"; @@ -56,7 +57,7 @@ public IconVariant(string name, IconSize size, IconColor color) private static readonly string[] Names = { BumperName, FlipperName, GateName, KickerName, LightName, PlungerName, PrimitiveName, RampName, RubberName, - SpinnerName, SurfaceName, HitTargetName, TriggerName, SwitchNcName, SwitchNoName, KeyName + SpinnerName, SurfaceName, HitTargetName, TableName, TriggerName, SwitchNcName, SwitchNoName, KeyName }; private readonly Dictionary _icons = new Dictionary(); @@ -99,6 +100,7 @@ private Icons() public static Texture2D Rubber(IconSize size = IconSize.Large, IconColor color = IconColor.Gray) => Instance.GetItem(RubberName, size, color); public static Texture2D Spinner(IconSize size = IconSize.Large, IconColor color = IconColor.Gray) => Instance.GetItem(SpinnerName, size, color); public static Texture2D Surface(IconSize size = IconSize.Large, IconColor color = IconColor.Gray) => Instance.GetItem(SurfaceName, size, color); + public static Texture2D Table(IconSize size = IconSize.Large, IconColor color = IconColor.Gray) => Instance.GetItem(TableName, size, color); public static Texture2D Target(IconSize size = IconSize.Large, IconColor color = IconColor.Gray) => Instance.GetItem(HitTargetName, size, color); public static Texture2D Trigger(IconSize size = IconSize.Large, IconColor color = IconColor.Gray) => Instance.GetItem(TriggerName, size, color); public static Texture2D Switch(bool normallyClosed, IconSize size = IconSize.Large, IconColor color = IconColor.Gray) => Instance.GetItem(normallyClosed ? SwitchNcName : SwitchNoName, size, color); @@ -184,6 +186,10 @@ private Texture2D GetItem(string name, IconSize size, IconColor color) variant = new IconVariant(name, IconSize.Large, IconColor.Gray); } + if (!_icons.ContainsKey(variant)) { + throw new InvalidOperationException($"Cannot find {variant.Size} {variant.Name} icon of color {variant.Color}."); + } + return _icons[variant]; } From 55afa8604e32b597535cc1f0c2fcba73d67b07dd Mon Sep 17 00:00:00 2001 From: freezy Date: Tue, 6 Oct 2020 23:51:58 +0200 Subject: [PATCH 049/124] editor: Restore mesh regeneration during transform. --- .../VPT/ItemInspector.cs | 10 ++------ .../VPT/TransformInspector.cs | 25 ++++++------------- .../VPT/IItemMainAuthoring.cs | 5 ++-- .../VPT/ItemMainAuthoring.cs | 18 ++++++------- 4 files changed, 20 insertions(+), 38 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs index b6e3cb1ac..c977d3f40 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs @@ -66,16 +66,10 @@ public override void OnInspectorGUI() GUILayout.Space(10); if (GUILayout.Button("Force Update Mesh")) { - foreach (var meshComponent in item.MeshComponents) { - meshComponent.MeshDirty = true; - } + item.SetMeshDirty(); } - foreach (var meshComponent in item.MeshComponents) { - if (meshComponent.MeshDirty) { - meshComponent.RebuildMeshes(); - } - } + item.RebuildMeshIfDirty(); } #endregion diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs index bc5c37b1d..d5d0a9bb9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs @@ -119,15 +119,10 @@ public override void OnInspectorGUI() private void RebuildMeshes() { - // todo meshdirty - // if (_primaryItem.MeshDirty) { - // _primaryItem.RebuildMeshes(); - // } - // foreach (var secondary in _secondaryItems) { - // if (secondary.Item.MeshDirty) { - // secondary.Item.RebuildMeshes(); - // } - // } + _primaryItem.RebuildMeshIfDirty(); + foreach (var secondary in _secondaryItems) { + secondary.Item.RebuildMeshIfDirty(); + } } protected virtual void OnSceneGUI() @@ -322,8 +317,7 @@ private void HandleScaleTool() private void FinishMove(Vector3 newPosition, bool isLocalPos = false) { - // todo meshdirty - // _primaryItem.MeshDirty = true; + _primaryItem.SetMeshDirty(); string undoLabel = "Move " + _transform.gameObject.name; Undo.RecordObject(_primaryItem as UnityEngine.Object, undoLabel); Undo.RecordObject(_transform, undoLabel); @@ -336,8 +330,7 @@ private void FinishMove(Vector3 newPosition, bool isLocalPos = false) foreach (var secondary in _secondaryItems) { - // todo meshdirty - // secondary.Item.MeshDirty = true; + secondary.Item.SetMeshDirty(); Undo.RecordObject(secondary.Item as UnityEngine.Object, undoLabel); Undo.RecordObject(secondary.Transform, undoLabel); secondary.Item.SetEditorPosition(finalPos + secondary.Offset); @@ -346,8 +339,7 @@ private void FinishMove(Vector3 newPosition, bool isLocalPos = false) private void FinishRotate(Vector3 newEuler) { - // todo meshdirty - // _primaryItem.MeshDirty = true; + _primaryItem.SetMeshDirty(); string undoLabel = "Rotate " + _transform.gameObject.name; Undo.RecordObject(_primaryItem as UnityEngine.Object, undoLabel); Undo.RecordObject(_transform, undoLabel); @@ -356,8 +348,7 @@ private void FinishRotate(Vector3 newEuler) private void FinishScale(Vector3 newScale) { - // todo meshdirty - // _primaryItem.MeshDirty = true; + _primaryItem.SetMeshDirty(); string undoLabel = "Scale " + _transform.gameObject.name; Undo.RecordObject(_primaryItem as UnityEngine.Object, undoLabel); Undo.RecordObject(_transform, undoLabel); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs index 2f681ea7b..6f79be989 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs @@ -24,9 +24,10 @@ public interface IItemMainAuthoring : IItemAuthoring bool IsLocked { get; set; } ///

- /// Returns all mesh sub components of this component + /// Sets the mesh of all mesh sub components to dirty. /// - IEnumerable MeshComponents { get; } + void SetMeshDirty(); + void RebuildMeshIfDirty(); // the following interfaces allow each item behavior to define which axes should // be shown on the scene view gizmo, the gizmo itself will use the associated diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs index fc22d5361..cf6dbaab2 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs @@ -52,19 +52,19 @@ public IItemMainAuthoring SetItem(TItem item, string gameObjectName = null) return this; } - public IEnumerable MeshComponents => + private IEnumerable MeshComponents => MeshAuthoringType != null ? GetComponentsInChildren(MeshAuthoringType, true) .Select(c => (IItemMeshAuthoring) c) - .Where(ma => ma.ItemData == _data); + .Where(ma => ma.ItemData == _data) : new IItemMeshAuthoring[0]; - public void MarkMeshesDirty() + public void SetMeshDirty() { foreach (var meshComponent in MeshComponents) { meshComponent.MeshDirty = true; } } - public void UpdateMeshes() + public void RebuildMeshIfDirty() { foreach (var meshComponent in MeshComponents) { if (meshComponent.MeshDirty) { @@ -92,11 +92,7 @@ protected virtual void OnDrawGizmos() { // handle dirty whenever scene view draws just in case a field or dependant changed and our // custom inspector window isn't up to process it - - // todo rebuild mesh sub components - // if (_meshDirty) { - // RebuildMeshes(); - // } + RebuildMeshIfDirty(); // Draw invisible gizmos over top of the sub meshes of this item so clicking in the scene view // selects the item itself first, which is most likely what the user would want @@ -104,11 +100,11 @@ protected virtual void OnDrawGizmos() Gizmos.color = Color.clear; Gizmos.matrix = Matrix4x4.identity; foreach (var mf in mfs) { - Gizmos.DrawMesh(mf.sharedMesh, mf.transform.position, mf.transform.rotation, mf.transform.lossyScale); + var t = mf.transform; + Gizmos.DrawMesh(mf.sharedMesh, t.position, t.rotation, t.lossyScale); } } - public virtual ItemDataTransformType EditorPositionType => ItemDataTransformType.None; public virtual Vector3 GetEditorPosition() => Vector3.zero; public virtual void SetEditorPosition(Vector3 pos) { } From 0e3fe2ede247a5da8c66003de6a605b24dbe0b44 Mon Sep 17 00:00:00 2001 From: freezy Date: Wed, 7 Oct 2020 00:20:26 +0200 Subject: [PATCH 050/124] editor: Hide gizmos of child items. --- .../VPT/TransformInspector.cs | 3 ++- .../VPT/ItemMeshAuthoring.cs | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs index d5d0a9bb9..7f98fc015 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs @@ -64,8 +64,9 @@ protected virtual void OnEnable() // must be main but not the table itself var item = (t as Transform)?.GetComponent(); + useDefault = useDefault && (t as Transform)?.GetComponent() == null; if (item != null && !(item is TableAuthoring)) { - useDefault = false; + if (_primaryItem == null) { _primaryItem = item; _positionType = item.EditorPositionType; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs index c2411a948..83a81fc74 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs @@ -121,7 +121,24 @@ private void UpdateMesh() } } + protected virtual void OnDrawGizmos() + { + // handle dirty whenever scene view draws just in case a field or dependant changed and our + // custom inspector window isn't up to process it + if (_meshDirty) { + RebuildMeshes(); + } + // Draw invisible gizmos over top of the sub meshes of this item so clicking in the scene view + // selects the item itself first, which is most likely what the user would want + var mfs = GetComponentsInChildren(); + Gizmos.color = Color.clear; + Gizmos.matrix = Matrix4x4.identity; + foreach (var mf in mfs) { + var t = mf.transform; + Gizmos.DrawMesh(mf.sharedMesh, t.position, t.rotation, t.lossyScale); + } + } From bd6c227c68db799ee3f2cec02836be5dd67910e6 Mon Sep 17 00:00:00 2001 From: freezy Date: Wed, 7 Oct 2020 00:30:51 +0200 Subject: [PATCH 051/124] editor: Regenenerate child meshes on property change. --- .../VPT/ItemInspector.cs | 8 ++++-- .../VisualPinball.Unity/VPT/ItemAuthoring.cs | 10 +++----- .../VPT/ItemMainAuthoring.cs | 25 +++++++++++++------ 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs index c977d3f40..8ae8c1263 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs @@ -318,8 +318,12 @@ protected virtual void FinishEdit(string label, bool dirtyMesh = true) var undoLabel = $"[{target?.name}] Edit {label}"; if (dirtyMesh) { // set dirty flag true before recording object state for the undo so meshes will rebuild after the undo as well - if (target is IItemMeshAuthoring item) { - item.MeshDirty = true; + if (target is IItemMeshAuthoring meshItem) { + meshItem.MeshDirty = true; + Undo.RecordObject(this, undoLabel); + } + if (target is IItemMainAuthoring mainItem) { + mainItem.SetMeshDirty(); Undo.RecordObject(this, undoLabel); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs index 62a8e1e35..53e45a979 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs @@ -47,16 +47,12 @@ public abstract class ItemAuthoring : MonoBehaviour public abstract TData Data { get; } /// - /// Returns the item object for this component. If this - /// returns `null`, then it's wrongly attached to a game object - /// where it can't find its main component. + /// Returns the item object for this component. /// /// /// - /// For any game item, we only serialize its data and re-instantiate - /// the actual item on the fly (and cache it). So in , - /// which initializes the component after creation, - /// is only set to avoid a cache miss. + /// If this returns `null`, then it's wrongly attached to a game object + /// where it can't find its main component. /// public abstract TItem Item { get; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs index cf6dbaab2..69f13d78a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs @@ -43,6 +43,14 @@ public abstract class ItemMainAuthoring : ItemAuthoring + /// Returns all child mesh components linked to this data. + /// + private IEnumerable MeshComponents => MeshAuthoringType != null ? + GetComponentsInChildren(MeshAuthoringType, true) + .Select(c => (IItemMeshAuthoring) c) + .Where(ma => ma.ItemData == _data) : new IItemMeshAuthoring[0]; + public IItemMainAuthoring SetItem(TItem item, string gameObjectName = null) { _item = item; @@ -52,11 +60,6 @@ public IItemMainAuthoring SetItem(TItem item, string gameObjectName = null) return this; } - private IEnumerable MeshComponents => MeshAuthoringType != null ? - GetComponentsInChildren(MeshAuthoringType, true) - .Select(c => (IItemMeshAuthoring) c) - .Where(ma => ma.ItemData == _data) : new IItemMeshAuthoring[0]; - public void SetMeshDirty() { foreach (var meshComponent in MeshComponents) { @@ -73,6 +76,12 @@ public void RebuildMeshIfDirty() } } + /// + /// Authoring type of the child class. + /// todo make this abstract + /// + protected virtual Type MeshAuthoringType { get; } = null; + /// /// Instantiates a new item based on the item data. /// @@ -80,8 +89,6 @@ public void RebuildMeshIfDirty() /// New item instance protected abstract TItem InstantiateItem(TData data); - protected virtual Type MeshAuthoringType { get; } = null; - protected void Convert(Entity entity, EntityManager dstManager) { Item.Index = entity.Index; @@ -105,6 +112,8 @@ protected virtual void OnDrawGizmos() } } + #region Tools + public virtual ItemDataTransformType EditorPositionType => ItemDataTransformType.None; public virtual Vector3 GetEditorPosition() => Vector3.zero; public virtual void SetEditorPosition(Vector3 pos) { } @@ -117,6 +126,8 @@ public virtual void SetEditorRotation(Vector3 rot) { } public virtual Vector3 GetEditorScale() => Vector3.zero; public virtual void SetEditorScale(Vector3 rot) { } + #endregion + public int EditorLayer { get => Data.EditorLayer; set => Data.EditorLayer = value; } public string EditorLayerName { get => Data.EditorLayerName; set => Data.EditorLayerName = value; } public bool EditorLayerVisibility { get => Data.EditorLayerVisibility; set => Data.EditorLayerVisibility = value; } From da5e226f803d1af91927359defc2738ef23f6a77 Mon Sep 17 00:00:00 2001 From: freezy Date: Wed, 7 Oct 2020 00:38:14 +0200 Subject: [PATCH 052/124] bumper: Add mesh inspectors. --- .../VPT/Bumper/BumperBaseMeshInspector.cs | 48 +++++++++++++++ .../Bumper/BumperBaseMeshInspector.cs.meta | 11 ++++ .../VPT/Bumper/BumperCapMeshInspector.cs | 48 +++++++++++++++ .../VPT/Bumper/BumperCapMeshInspector.cs.meta | 11 ++++ .../VPT/Bumper/BumperInspector.cs | 8 --- .../VPT/Bumper/BumperRingMeshInspector.cs | 48 +++++++++++++++ .../Bumper/BumperRingMeshInspector.cs.meta | 11 ++++ .../VPT/Bumper/BumperSkirtMeshInspector.cs | 48 +++++++++++++++ .../Bumper/BumperSkirtMeshInspector.cs.meta | 11 ++++ .../VPT/ItemMeshInspector.cs | 58 +++++++++++++++++++ .../VPT/ItemMeshInspector.cs.meta | 11 ++++ .../VisualPinball.Unity/VPT/Playfield.meta | 8 +++ 12 files changed, 313 insertions(+), 8 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperBaseMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperBaseMeshInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperCapMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperCapMeshInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMeshInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperSkirtMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperSkirtMeshInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield.meta diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperBaseMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperBaseMeshInspector.cs new file mode 100644 index 000000000..0b3a34770 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperBaseMeshInspector.cs @@ -0,0 +1,48 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Bumper; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(BumperBaseMeshAuthoring))] + public class BumperBaseMeshInspector : ItemMeshInspector + { + private BumperData _data; + + protected override void OnEnable() + { + base.OnEnable(); + _data = Data; + } + + public override void OnInspectorGUI() + { + if (Data == null) { + NoDataPanel(); + return; + } + + ItemDataField("Is Visible", ref _data.IsBaseVisible); + MaterialField("Base Material", ref _data.BaseMaterial); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperBaseMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperBaseMeshInspector.cs.meta new file mode 100644 index 000000000..99f52d60c --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperBaseMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 61da64ec5a7ec1e4e9095a673341ec35 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperCapMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperCapMeshInspector.cs new file mode 100644 index 000000000..fcdc52830 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperCapMeshInspector.cs @@ -0,0 +1,48 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Bumper; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(BumperCapMeshAuthoring))] + public class BumperCapMeshInspector : ItemMeshInspector + { + private BumperData _data; + + protected override void OnEnable() + { + base.OnEnable(); + _data = Data; + } + + public override void OnInspectorGUI() + { + if (Data == null) { + NoDataPanel(); + return; + } + + ItemDataField("Is Visible", ref _data.IsCapVisible); + MaterialField("Cap Material", ref _data.CapMaterial); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperCapMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperCapMeshInspector.cs.meta new file mode 100644 index 000000000..6a1f81b79 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperCapMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 509fdb1e6998e094d914c89297662ca1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs index 9a1ff376b..1f0e61033 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs @@ -40,19 +40,11 @@ public override void OnInspectorGUI() OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - MaterialField("Cap Material", ref _bumper.Data.CapMaterial); - MaterialField("Base Material", ref _bumper.Data.BaseMaterial); - MaterialField("Ring Material", ref _bumper.Data.RingMaterial); - MaterialField("Skirt Material", ref _bumper.Data.SocketMaterial); ItemDataField("Radius", ref _bumper.Data.Radius); ItemDataField("Height Scale", ref _bumper.Data.HeightScale); ItemDataField("Orientation", ref _bumper.Data.Orientation); ItemDataField("Ring Speed", ref _bumper.Data.RingSpeed, dirtyMesh: false); ItemDataField("Ring Drop Offset", ref _bumper.Data.RingDropOffset, dirtyMesh: false); - ItemDataField("Cap Visible", ref _bumper.Data.IsCapVisible); - ItemDataField("Base Visible", ref _bumper.Data.IsBaseVisible); - ItemDataField("Ring Visible", ref _bumper.Data.IsRingVisible); - ItemDataField("Skirt Visible", ref _bumper.Data.IsSocketVisible); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMeshInspector.cs new file mode 100644 index 000000000..977d43142 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMeshInspector.cs @@ -0,0 +1,48 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Bumper; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(BumperRingMeshAuthoring))] + public class BumperRingMeshInspector : ItemMeshInspector + { + private BumperData _data; + + protected override void OnEnable() + { + base.OnEnable(); + _data = Data; + } + + public override void OnInspectorGUI() + { + if (Data == null) { + NoDataPanel(); + return; + } + + ItemDataField("Is Visible", ref _data.IsRingVisible); + MaterialField("Ring Material", ref _data.RingMaterial); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMeshInspector.cs.meta new file mode 100644 index 000000000..677ff702b --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8b8cc6a60c9b1804389fe3f009102fd4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperSkirtMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperSkirtMeshInspector.cs new file mode 100644 index 000000000..eb77919c6 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperSkirtMeshInspector.cs @@ -0,0 +1,48 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Bumper; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(BumperSkirtMeshAuthoring))] + public class BumperSkirtMeshInspector : ItemMeshInspector + { + private BumperData _data; + + protected override void OnEnable() + { + base.OnEnable(); + _data = Data; + } + + public override void OnInspectorGUI() + { + if (Data == null) { + NoDataPanel(); + return; + } + + ItemDataField("Is Visible", ref _data.IsSocketVisible); + MaterialField("Skirt Material", ref _data.SocketMaterial); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperSkirtMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperSkirtMeshInspector.cs.meta new file mode 100644 index 000000000..cfc616169 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperSkirtMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 388f80ba165ac734eaa54c2d62c9a2e9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs new file mode 100644 index 000000000..a7365974c --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs @@ -0,0 +1,58 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using System.Linq; +using UnityEditor; +using UnityEngine; +using VisualPinball.Engine.Game; +using VisualPinball.Engine.Physics; +using VisualPinball.Engine.VPT; + +namespace VisualPinball.Unity.Editor +{ + public class ItemMeshInspector : ItemInspector + where TMeshAuthoring : ItemMeshAuthoring + where TData : ItemData + where TItem : Item, IHittable, IRenderable + where TMainAuthoring : ItemMainAuthoring + { + private TMeshAuthoring _meshAuthoring; + + protected TData Data => _meshAuthoring == null ? null : _meshAuthoring.Data; + + protected override void OnEnable() + { + _meshAuthoring = target as TMeshAuthoring; + base.OnEnable(); + } + + public override void OnInspectorGUI() + { + if (_meshAuthoring == null) { + return; + } + + } + + protected void NoDataPanel() + { + // todo add more details + GUILayout.Label("No data! Parent missing?"); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs.meta new file mode 100644 index 000000000..19a38a474 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 27842e934a76b3b4ab170822a15ea029 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield.meta new file mode 100644 index 000000000..f8d57a6ad --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3630d3b0e48a1ba4e89d31274b8df4e9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: From 04bcaa2c084d0b968b18f74938b2711a25290107 Mon Sep 17 00:00:00 2001 From: freezy Date: Wed, 7 Oct 2020 23:14:01 +0200 Subject: [PATCH 053/124] fix: Set default physics engine. --- .../VisualPinball.Unity/Game/DebugBallCreator.cs | 3 +++ .../VisualPinball.Unity/VPT/ItemMeshAuthoring.cs | 4 ++-- .../VisualPinball.Unity/VPT/Table/TableAuthoring.cs | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/Game/DebugBallCreator.cs b/VisualPinball.Unity/VisualPinball.Unity/Game/DebugBallCreator.cs index 72f6fb838..50784d721 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Game/DebugBallCreator.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Game/DebugBallCreator.cs @@ -54,6 +54,9 @@ public Vertex3D GetBallCreationPosition(Table table) if (_x < 0 || _y < 0) { _x = table.Width / 2f; _y = table.Height / 3f; + + // _x = Random.Range(table.Width / 6f, table.Width / 6f * 5f); + // _y = Random.Range(table.Height / 8f, table.Height / 2f); } return new Vertex3D(_x, _y, 0); } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs index 83a81fc74..0880da865 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs @@ -66,12 +66,12 @@ private void OnDisable() private void OnDestroy() { var mr = gameObject.GetComponent(); - if (mr != null) { + if (mr != null && !Application.isPlaying) { DestroyImmediate(mr); } var mf = gameObject.GetComponent(); - if (mf != null) { + if (mf != null && !Application.isPlaying) { DestroyImmediate(mf); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs index ef23b889a..7dd0b53a8 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs @@ -62,7 +62,7 @@ public class TableAuthoring : ItemMainAuthoring public MappingsData Mappings => _sidecar?.mappings; public Patcher.Patcher Patcher { get; internal set; } - [HideInInspector] [SerializeField] public string physicsEngineId; + [HideInInspector] [SerializeField] public string physicsEngineId = "VisualPinball.Unity.DefaultPhysicsEngine"; [HideInInspector] [SerializeField] public string debugUiId; [HideInInspector] [SerializeField] private TableSidecar _sidecar; private readonly Dictionary _unityTextures = new Dictionary(); From 09bb9a4e166d816dbc72201eccd8b1ca1d7a96d9 Mon Sep 17 00:00:00 2001 From: freezy Date: Wed, 7 Oct 2020 23:41:20 +0200 Subject: [PATCH 054/124] editor: Add parent class to moveable components. --- .../VPT/Bumper/BumperExtensions.cs | 2 -- .../VPT/Bumper/BumperRingAnimationAuthoring.cs | 9 +++++---- .../VPT/Bumper/BumperSkirtAnimationAuthoring.cs | 7 ++++--- .../VisualPinball.Unity/VPT/ItemAuthoring.cs | 2 +- .../VisualPinball.Unity/VPT/ItemMovementAuthoring.cs | 11 +++++++++++ .../VisualPinball.Unity/VPT/ItemSubAuthoring.cs | 5 +++++ 6 files changed, 26 insertions(+), 10 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs index 08503e1ff..4c3fd3283 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs @@ -19,13 +19,11 @@ using UnityEngine; using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Bumper; -using VisualPinball.Engine.VPT.Surface; namespace VisualPinball.Unity { internal static class BumperExtensions { - public static IItemMainAuthoring SetupGameObject(this Bumper bumper, GameObject obj, IItemMainAuthoring parentAuthoring) { var mainAuthoring = obj.AddComponent().SetItem(bumper); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs index 2360d53a3..c548e6768 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs @@ -16,17 +16,18 @@ using Unity.Entities; using UnityEngine; +using VisualPinball.Engine.VPT.Bumper; namespace VisualPinball.Unity { [AddComponentMenu("Visual Pinball/Animation/Bumper Ring Animation")] - public class BumperRingAnimationAuthoring : MonoBehaviour, IConvertGameObjectToEntity + public class BumperRingAnimationAuthoring : ItemMovementAuthoring, IConvertGameObjectToEntity { public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { - var table = gameObject.GetComponentInParent().Item; - var bumper = transform.parent.gameObject.GetComponent().Item; - var bumperEntity = new Entity {Index = bumper.Index, Version = bumper.Version}; + var table = Table; + var bumper = Item; + var bumperEntity = Entity; // update parent var bumperStaticData = dstManager.GetComponentData(bumperEntity); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs index e39819ef3..5dee1788a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs @@ -17,16 +17,17 @@ using Unity.Entities; using Unity.Mathematics; using UnityEngine; +using VisualPinball.Engine.VPT.Bumper; namespace VisualPinball.Unity { [AddComponentMenu("Visual Pinball/Animation/Bumper Skirt Animation")] - public class BumperSkirtAnimationAuthoring : MonoBehaviour, IConvertGameObjectToEntity + public class BumperSkirtAnimationAuthoring : ItemMovementAuthoring, IConvertGameObjectToEntity { public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { - var bumper = transform.parent.gameObject.GetComponent().Item; - var bumperEntity = new Entity {Index = bumper.Index, Version = bumper.Version}; + var bumper = Item; + var bumperEntity = Entity; // update parent var bumperStaticData = dstManager.GetComponentData(bumperEntity); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs index 53e45a979..6ac1ac491 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs @@ -72,7 +72,7 @@ public abstract class ItemAuthoring : MonoBehaviour private Table _table; - protected Table Table => _table ?? (_table = gameObject.transform.GetComponentInParent()?.Item); + protected Table Table => _table ?? (_table = GetComponentInParent()?.Item); protected virtual void ItemDataChanged() { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs index 9b6744857..435e75c30 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs @@ -15,6 +15,7 @@ // along with this program. If not, see . using System; +using Unity.Entities; using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; @@ -34,5 +35,15 @@ public abstract class ItemMovementAuthoring : Item where TItem : Item, IHittable, IRenderable where TMainAuthoring : ItemMainAuthoring { + protected Entity Entity { + get { + var ma = MainAuthoring; + if (ma == null) { + throw new InvalidOperationException("Cannot find main authoring component of " + name + "."); + } + var item = ma.Item; + return new Entity { Index = item.Index, Version = item.Version }; + } + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs index 6d33f34c1..df72751a7 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs @@ -51,6 +51,11 @@ public abstract class ItemSubAuthoring : ItemAutho /// public override TItem Item => FindItem(); + /// + /// Finds the main authoring component in the parent. + /// + protected TMainAuthoring MainAuthoring => FindMainAuthoring(); + // public IItemAuthoring SetItem(TItem item, RenderObjectGroup rog) // { // _item = item; From a91bcd0e38462f70453e3ebefd62484104426768 Mon Sep 17 00:00:00 2001 From: freezy Date: Fri, 9 Oct 2020 00:04:56 +0200 Subject: [PATCH 055/124] ecs: Parent mesh children. --- .../VPT/Bumper/BumperRingAnimationAuthoring.cs | 2 ++ .../VPT/Bumper/BumperSkirtAnimationAuthoring.cs | 3 +++ .../VisualPinball.Unity/VPT/ItemMeshAuthoring.cs | 13 ------------- .../VPT/ItemMovementAuthoring.cs | 7 +++++++ .../VisualPinball.Unity/VPT/ItemSubAuthoring.cs | 15 --------------- 5 files changed, 12 insertions(+), 28 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs index c548e6768..c886f9eb2 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs @@ -49,6 +49,8 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio Speed = bumper.Data.RingSpeed, ScaleZ = table.GetScaleZ() }); + + LinkToParentEntity(entity, dstManager); } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs index 5dee1788a..210c6f91c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs @@ -16,6 +16,7 @@ using Unity.Entities; using Unity.Mathematics; +using Unity.Transforms; using UnityEngine; using VisualPinball.Engine.VPT.Bumper; @@ -45,6 +46,8 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio HitEvent = bumper.Data.HitEvent, Center = bumper.Data.Center.ToUnityFloat2() }); + + LinkToParentEntity(entity, dstManager); } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs index 0880da865..10782db07 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs @@ -63,19 +63,6 @@ private void OnDisable() } } - private void OnDestroy() - { - var mr = gameObject.GetComponent(); - if (mr != null && !Application.isPlaying) { - DestroyImmediate(mr); - } - - var mf = gameObject.GetComponent(); - if (mf != null && !Application.isPlaying) { - DestroyImmediate(mf); - } - } - #endregion private void CreateMesh() diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs index 435e75c30..d90a5a953 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs @@ -16,6 +16,7 @@ using System; using Unity.Entities; +using Unity.Transforms; using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; @@ -45,5 +46,11 @@ protected Entity Entity { return new Entity { Index = item.Index, Version = item.Version }; } } + + protected void LinkToParentEntity(Entity entity, EntityManager dstManager) + { + dstManager.AddComponentData(entity, new Parent {Value = Entity}); + dstManager.AddComponentData(entity, new LocalToParent()); + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs index df72751a7..3fca35259 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs @@ -56,21 +56,6 @@ public abstract class ItemSubAuthoring : ItemAutho /// protected TMainAuthoring MainAuthoring => FindMainAuthoring(); - // public IItemAuthoring SetItem(TItem item, RenderObjectGroup rog) - // { - // _item = item; - // _data = item.Data; - // _isSubComponent = false; - // name = rog.ComponentName + " (collider)"; - // return this; - // } - - // public void SetMainItem(TItem item) - // { - // _item = item; - // _isSubComponent = true; - // } - private TData FindData() { var ac = FindMainAuthoring(); From d3b0b5163a8bb3cf380b2b56337056944d49a563 Mon Sep 17 00:00:00 2001 From: freezy Date: Fri, 9 Oct 2020 00:44:39 +0200 Subject: [PATCH 056/124] components: Fix initial matrix tranformation. --- VisualPinball.Engine/VPT/Bumper/Bumper.cs | 17 ++++++- .../VPT/Bumper/BumperInspector.cs | 2 - .../VPT/Bumper/BumperRingMovementInspector.cs | 48 +++++++++++++++++++ .../BumperRingMovementInspector.cs.meta | 11 +++++ .../VPT/ItemInspector.cs | 7 ++- .../VPT/ItemMovementInspector.cs | 47 ++++++++++++++++++ .../VPT/ItemMovementInspector.cs.meta | 11 +++++ .../VPT/IItemColliderAuthoring.cs | 16 ++++++- .../VPT/IItemMainAuthoring.cs | 1 - .../VPT/IItemMeshAuthoring.cs | 18 ++++++- .../VPT/IItemMovementAuthoring.cs | 22 +++++++++ .../VPT/IItemMovementAuthoring.cs.meta | 11 +++++ .../VPT/ItemMeshAuthoring.cs | 4 +- .../VPT/ItemMovementAuthoring.cs | 2 +- 14 files changed, 206 insertions(+), 11 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMovementInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMovementInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMovementInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMovementInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMovementAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMovementAuthoring.cs.meta diff --git a/VisualPinball.Engine/VPT/Bumper/Bumper.cs b/VisualPinball.Engine/VPT/Bumper/Bumper.cs index 69456725a..f6032d212 100644 --- a/VisualPinball.Engine/VPT/Bumper/Bumper.cs +++ b/VisualPinball.Engine/VPT/Bumper/Bumper.cs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using System.IO; using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; @@ -54,7 +55,21 @@ public void Init(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Origin origin) + { + switch (origin) { + case Origin.Original: + var rotMatrix = new Matrix3D().RotateZMatrix(MathF.DegToRad(Data.Orientation)); + var transMatrix = new Matrix3D().SetTranslation(Data.Center.X, Data.Center.Y, 0f); + return rotMatrix.Multiply(transMatrix); + + case Origin.Global: + return Matrix3D.Identity; + + default: + throw new ArgumentOutOfRangeException(nameof(origin), origin, "Unknown origin " + origin); + } + } public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs index 1f0e61033..a63c77eb4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs @@ -43,8 +43,6 @@ public override void OnInspectorGUI() ItemDataField("Radius", ref _bumper.Data.Radius); ItemDataField("Height Scale", ref _bumper.Data.HeightScale); ItemDataField("Orientation", ref _bumper.Data.Orientation); - ItemDataField("Ring Speed", ref _bumper.Data.RingSpeed, dirtyMesh: false); - ItemDataField("Ring Drop Offset", ref _bumper.Data.RingDropOffset, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMovementInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMovementInspector.cs new file mode 100644 index 000000000..0c5c2c47e --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMovementInspector.cs @@ -0,0 +1,48 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Bumper; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(BumperRingAnimationAuthoring))] + public class BumperRingMovementInspector : ItemMovementInspector + { + private BumperData _data; + + protected override void OnEnable() + { + base.OnEnable(); + _data = Data; + } + + public override void OnInspectorGUI() + { + if (Data == null) { + NoDataPanel(); + return; + } + + ItemDataField("Ring Speed", ref _data.RingSpeed, false); + ItemDataField("Ring Drop Offset", ref _data.RingDropOffset, false); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMovementInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMovementInspector.cs.meta new file mode 100644 index 000000000..6a2fe4fb3 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMovementInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 775c279142ff11240b3c4f44e8abfc8d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs index 8ae8c1263..fda51e694 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs @@ -43,8 +43,11 @@ protected virtual void OnEnable() // // we're opting to due this here as opposed to at import time since modifying objects // // in this way caused them to not be part of the created object undo stack // if (target != null && target is MonoBehaviour mb) { -// int numComp = mb.GetComponents().Length; -// for (int i = 0; i <= numComp; i++) { +// var numComp = mb.GetComponents().Length; +// if (mb is IItemColliderAuthoring || mb is IItemMeshAuthoring || mb is IItemMovementAuthoring) { +// numComp--; +// } +// for (var i = 0; i <= numComp; i++) { // UnityEditorInternal.ComponentUtility.MoveComponentUp(mb); // } // } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMovementInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMovementInspector.cs new file mode 100644 index 000000000..aa5f2229e --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMovementInspector.cs @@ -0,0 +1,47 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEngine; +using VisualPinball.Engine.Game; +using VisualPinball.Engine.VPT; + +namespace VisualPinball.Unity.Editor +{ + public class ItemMovementInspector : ItemInspector + where TMovementAuthoring : ItemMovementAuthoring + where TData : ItemData + where TItem : Item, IHittable, IRenderable + where TMainAuthoring : ItemMainAuthoring + { + private TMovementAuthoring _movementAuthoring; + + protected TData Data => _movementAuthoring == null ? null : _movementAuthoring.Data; + + protected override void OnEnable() + { + _movementAuthoring = target as TMovementAuthoring; + base.OnEnable(); + } + + protected void NoDataPanel() + { + // todo add more details + GUILayout.Label("No data! Parent missing?"); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMovementInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMovementInspector.cs.meta new file mode 100644 index 000000000..093195870 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMovementInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b3ade9bf51966ad49a313e3686589a50 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs index 595380427..4dabbc457 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs @@ -1,4 +1,18 @@ -using UnityEngine; +// 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 . namespace VisualPinball.Unity { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs index 6f79be989..7afa270da 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -using System.Collections.Generic; using UnityEngine; namespace VisualPinball.Unity diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs index 8a3c3a14f..923bc5ccd 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs @@ -1,4 +1,20 @@ -using System.Collections.Generic; +// 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 System.Reflection; using VisualPinball.Engine.VPT; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMovementAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMovementAuthoring.cs new file mode 100644 index 000000000..2cbcd959b --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMovementAuthoring.cs @@ -0,0 +1,22 @@ +// 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 . + +namespace VisualPinball.Unity +{ + public interface IItemMovementAuthoring + { + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMovementAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMovementAuthoring.cs.meta new file mode 100644 index 000000000..3ad3a21b1 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMovementAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 73a8933e2b1bcc740b97b383ff67cb95 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs index 10782db07..1a64e9869 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs @@ -68,7 +68,7 @@ private void OnDisable() private void CreateMesh() { var ta = GetComponentInParent(); - var ro = Item.GetRenderObject(ta.Table, MeshId, asRightHanded: false); + var ro = Item.GetRenderObject(ta.Table, MeshId, Origin.Original, false); var mesh = ro.Mesh.ToUnityMesh($"{gameObject.name}_Mesh"); // apply mesh to game object @@ -91,7 +91,7 @@ private void CreateMesh() private void UpdateMesh() { var ta = GetComponentInParent(); - var ro = Item.GetRenderObject(ta.Table, MeshId, asRightHanded: false); + var ro = Item.GetRenderObject(ta.Table, MeshId, Origin.Original, false); var mr = GetComponent(); var mf = GetComponent(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs index d90a5a953..932556f02 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs @@ -31,7 +31,7 @@ namespace VisualPinball.Unity { public abstract class ItemMovementAuthoring : ItemSubAuthoring, - IItemColliderAuthoring + IItemMovementAuthoring where TData : ItemData where TItem : Item, IHittable, IRenderable where TMainAuthoring : ItemMainAuthoring From 6f22e00c19277e3506308b15558e4953a28f9bc3 Mon Sep 17 00:00:00 2001 From: freezy Date: Fri, 9 Oct 2020 22:32:15 +0200 Subject: [PATCH 057/124] editor: Fix translation. --- .../VPT/ItemMeshInspector.cs | 3 + .../VPT/TransformInspector.cs | 82 +++++++++---------- .../VPT/ItemMainAuthoring.cs | 6 ++ .../VPT/ItemMeshAuthoring.cs | 48 ----------- 4 files changed, 49 insertions(+), 90 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs index a7365974c..082b5d088 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs @@ -47,6 +47,9 @@ public override void OnInspectorGUI() return; } + if (GUILayout.Button("Force Update Mesh")) { + _meshAuthoring.RebuildMeshes(); + } } protected void NoDataPanel() diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs index 7f98fc015..8cbc55106 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs @@ -14,13 +14,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +// ReSharper disable SwitchStatementMissingSomeEnumCasesNoDefault + using System; using System.Collections.Generic; using System.Reflection; using UnityEditor; using UnityEngine; - namespace VisualPinball.Unity.Editor { [CustomEditor(typeof(Transform))] @@ -72,6 +73,7 @@ protected virtual void OnEnable() _positionType = item.EditorPositionType; _rotationType = item.EditorRotationType; _scaleType = item.EditorScaleType; + } else { // only transform on axes supported by all if (item.EditorPositionType < _positionType) { @@ -108,15 +110,15 @@ protected virtual void OnDisable() Tools.hidden = false; } - public override void OnInspectorGUI() - { - if (_defaultEditor != null) { - _defaultEditor.OnInspectorGUI(); - return; - } - - GUILayout.Label("VPE item transforms driven by data on the component below."); - } + // public override void OnInspectorGUI() + // { + // if (_defaultEditor != null) { + // _defaultEditor.OnInspectorGUI(); + // return; + // } + // + // GUILayout.Label("VPE item transforms driven by data on the component below."); + // } private void RebuildMeshes() { @@ -138,17 +140,14 @@ protected virtual void OnSceneGUI() return; } - bool dragPointEditEnabled = (_primaryItem as IDragPointsEditable)?.DragPointEditEnabled ?? false; + var dragPointEditEnabled = (_primaryItem as IDragPointsEditable)?.DragPointEditEnabled ?? false; if (!dragPointEditEnabled) { - if (_primaryItem.IsLocked) - { + if (_primaryItem.IsLocked) { HandleLockedTool(); - } - else - { - switch (Tools.current) - { + + } else { + switch (Tools.current) { case Tool.Rotate: HandleRotationTool(); break; @@ -170,8 +169,7 @@ protected virtual void OnSceneGUI() private void HandleLockedTool() { var handlePos = _primaryItem.GetEditorPosition(); - if (_transform.parent != null) - { + if (_transform.parent != null) { handlePos = _transform.parent.TransformPoint(handlePos); } Handles.color = Color.red; @@ -213,7 +211,7 @@ private void HandleRotationTool() if (_transform.parent != null) { baseMatrix = Matrix4x4.TRS(handlePos, _transform.parent.transform.rotation, Vector3.one); } - Matrix4x4 currentRotTran = Matrix4x4.identity; + var currentRotTran = Matrix4x4.identity; currentRotTran *= Matrix4x4.Rotate(Quaternion.Euler(currentRot.x, 0, 0)); currentRotTran *= Matrix4x4.Rotate(Quaternion.Euler(0, currentRot.y, 0)); @@ -232,9 +230,9 @@ private void HandleRotationTool() if (EditorGUI.EndChangeCheck()) { // check which axis had the biggest change (they'll all change slightly due to float precision) // and pause that axis' local rotation so the gizmo doesn't flip out - float xDiff = System.Math.Abs(rotX.eulerAngles.y - currentRot.x); - float yDiff = System.Math.Abs(rotY.eulerAngles.y - currentRot.y); - float zDiff = System.Math.Abs(rotZ.eulerAngles.y - currentRot.z); + var xDiff = System.Math.Abs(rotX.eulerAngles.y - currentRot.x); + var yDiff = System.Math.Abs(rotY.eulerAngles.y - currentRot.y); + var zDiff = System.Math.Abs(rotZ.eulerAngles.y - currentRot.z); if (_pauseAxisX == null && xDiff > yDiff && xDiff > zDiff) { _pauseAxisX = currentRotTran; } else if (_pauseAxisY == null && yDiff > xDiff && yDiff > zDiff) { @@ -254,13 +252,14 @@ private void HandleRotationTool() private void HandleMoveTool() { - Quaternion parentRot = Quaternion.identity; - Vector3 handlePos = _primaryItem.GetEditorPosition(); - if (_transform.parent != null) - { - handlePos = _transform.parent.TransformPoint(handlePos); - parentRot = _transform.parent.transform.rotation; + var parentRot = Quaternion.identity; + var handlePos = _primaryItem.GetEditorPosition(); + if (_transform.parent != null) { + var pt = _transform.parent; + handlePos = pt.TransformPoint(handlePos); + parentRot = pt.transform.rotation; } + EditorGUI.BeginChangeCheck(); handlePos = HandlesUtils.HandlePosition(handlePos, _primaryItem.EditorPositionType, parentRot); if (EditorGUI.EndChangeCheck()) { @@ -285,18 +284,20 @@ private void HandleScaleTool() var handleRot = _transform.rotation; var handleScale = HandleUtility.GetHandleSize(handlePos); switch (_primaryItem.EditorScaleType) { + case ItemDataTransformType.OneD: { EditorGUI.BeginChangeCheck(); - float scale = Handles.ScaleSlider(_primaryItem.GetEditorScale().x, handlePos, _transform.right, handleRot, handleScale, 0f); + var scale = Handles.ScaleSlider(_primaryItem.GetEditorScale().x, handlePos, _transform.right, handleRot, handleScale, 0f); if (EditorGUI.EndChangeCheck()) { FinishScale(new Vector3(scale, 0f, 0f)); } break; } + case ItemDataTransformType.ThreeD: { EditorGUI.BeginChangeCheck(); - Vector3 oldScale = _primaryItem.GetEditorScale(); - Vector3 newScale = Handles.ScaleHandle(oldScale, handlePos, handleRot, handleScale); + var oldScale = _primaryItem.GetEditorScale(); + var newScale = Handles.ScaleHandle(oldScale, handlePos, handleRot, handleScale); if (Mathf.Abs(newScale.x - oldScale.x) > Mathf.Epsilon && Mathf.Abs(newScale.y - oldScale.y) > Mathf.Epsilon && Mathf.Abs(newScale.z - oldScale.z) > Mathf.Epsilon) { // the center bit of the scale handle appears to be doing some extra multiplying, not totally sure what's going on, but experimentally // it seems like its a factor of one of the axes too much, so (on click) we'll update a factor and adjust accordingly @@ -311,26 +312,23 @@ private void HandleScaleTool() } break; } - default: - break; } } private void FinishMove(Vector3 newPosition, bool isLocalPos = false) { _primaryItem.SetMeshDirty(); - string undoLabel = "Move " + _transform.gameObject.name; + var undoLabel = "Move " + _transform.gameObject.name; Undo.RecordObject(_primaryItem as UnityEngine.Object, undoLabel); Undo.RecordObject(_transform, undoLabel); var finalPos = newPosition; - if (_transform.parent != null && !isLocalPos) - { + + if (_transform.parent != null && !isLocalPos) { finalPos = _transform.parent.InverseTransformPoint(newPosition); } _primaryItem.SetEditorPosition(finalPos); - foreach (var secondary in _secondaryItems) - { + foreach (var secondary in _secondaryItems) { secondary.Item.SetMeshDirty(); Undo.RecordObject(secondary.Item as UnityEngine.Object, undoLabel); Undo.RecordObject(secondary.Transform, undoLabel); @@ -341,7 +339,7 @@ private void FinishMove(Vector3 newPosition, bool isLocalPos = false) private void FinishRotate(Vector3 newEuler) { _primaryItem.SetMeshDirty(); - string undoLabel = "Rotate " + _transform.gameObject.name; + var undoLabel = "Rotate " + _transform.gameObject.name; Undo.RecordObject(_primaryItem as UnityEngine.Object, undoLabel); Undo.RecordObject(_transform, undoLabel); _primaryItem.SetEditorRotation(newEuler); @@ -350,7 +348,7 @@ private void FinishRotate(Vector3 newEuler) private void FinishScale(Vector3 newScale) { _primaryItem.SetMeshDirty(); - string undoLabel = "Scale " + _transform.gameObject.name; + var undoLabel = "Scale " + _transform.gameObject.name; Undo.RecordObject(_primaryItem as UnityEngine.Object, undoLabel); Undo.RecordObject(_transform, undoLabel); _primaryItem.SetEditorScale(newScale); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs index 69f13d78a..09dd17b21 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs @@ -74,6 +74,12 @@ public void RebuildMeshIfDirty() meshComponent.RebuildMeshes(); } } + + // update transform based on item data, but not for "Table" since its the effective "root" and the user might want to move it on their own + var ta = GetComponentInParent(); + if (ta != this) { + transform.SetFromMatrix(Item.TransformationMatrix(Origin.Original).ToUnityMatrix()); + } } /// diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs index 1a64e9869..77ef4376e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs @@ -151,54 +151,6 @@ protected virtual void OnDrawGizmos() public void RebuildMeshes() { UpdateMesh(); - // if (Data == null) { - // _logger.Warn("Cannot retrieve data component for a {0}.", typeof(TItem).Name); - // return; - // } - // var table = transform.GetComponentInParent(); - // if (table == null) { - // _logger.Warn("Cannot retrieve table component from {0}, not updating meshes.", Data.GetName()); - // return; - // } - // - // var rog = Item.GetRenderObjects(table.Table, Origin.Original, false); - - // todo can probably ditch this, because components now update themselves - // var children = Children; - // if (children == null) { - // UpdateMesh(Item.Name, gameObject, rog, table); - // } else { - // foreach (var child in children) { - // if (transform.childCount == 0) { - // //Find the matching renderObject and Update it based on base gameObject - // var ro = rog.RenderObjects.FirstOrDefault(r => r.Name == child); - // if (ro != null) - // { - // UpdateMesh(child, gameObject, rog, table); - // break; - // } - // } else { - // Transform childTransform = transform.Find(child); - // if (childTransform != null) { - // UpdateMesh(child, childTransform.gameObject, rog, table); - // } else { - // // child hasn't been created yet (i.e. ramp might have changed type) - // var ro = rog.RenderObjects.FirstOrDefault(r => r.Name == child); - // if (ro != null) { - // var subObj = new GameObject(ro.Name); - // subObj.transform.SetParent(transform, false); - // subObj.layer = VpxConverter.ChildObjectsLayer; - // } - // } - // } - // } - // } - - // update transform based on item data, but not for "Table" since its the effective "root" and the user might want to move it on their own - var ta = GetComponentInParent(); - if (ta != this) { - transform.SetFromMatrix(Item.TransformationMatrix(Origin.Original).ToUnityMatrix()); - } ItemDataChanged(); _meshDirty = false; From e119d375efffc8720c17f06e366fda9ae83b53c8 Mon Sep 17 00:00:00 2001 From: freezy Date: Fri, 9 Oct 2020 22:44:30 +0200 Subject: [PATCH 058/124] editor: Exclude playfield from being transformed. --- .../VisualPinball.Unity.Editor/VPT/TransformInspector.cs | 4 ++++ .../VisualPinball.Unity/VPT/IItemMainAuthoring.cs | 2 ++ .../VisualPinball.Unity/VPT/ItemMainAuthoring.cs | 2 ++ .../VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs | 2 ++ 4 files changed, 10 insertions(+) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs index 8cbc55106..68f61e7c4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs @@ -140,6 +140,10 @@ protected virtual void OnSceneGUI() return; } + if (!_primaryItem.CanBeTransformed) { + return; + } + var dragPointEditEnabled = (_primaryItem as IDragPointsEditable)?.DragPointEditEnabled ?? false; if (!dragPointEditEnabled) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs index 7afa270da..c0622484e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs @@ -22,6 +22,8 @@ public interface IItemMainAuthoring : IItemAuthoring { bool IsLocked { get; set; } + bool CanBeTransformed { get; } + /// /// Sets the mesh of all mesh sub components to dirty. /// diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs index 09dd17b21..82e9e0248 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs @@ -24,6 +24,8 @@ public abstract class ItemMainAuthoring : ItemAuthoring public override TItem Item => _item ?? (_item = InstantiateItem(_data)); + public virtual bool CanBeTransformed => true; + /// /// The serialized data, as written to the .vpx file. /// diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs index d8f20ef85..abaa6b13c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs @@ -29,6 +29,8 @@ public class PlayfieldAuthoring : ItemMainAuthoring, public IHittable Hittable => Table; + public override bool CanBeTransformed => false; + protected override Table InstantiateItem(TableData data) => throw new InvalidOperationException("Table is not instantiated via authoring component."); public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) From 6bf41bf3bc67f6de0f2ec51618108fce936c29e3 Mon Sep 17 00:00:00 2001 From: freezy Date: Fri, 9 Oct 2020 22:59:25 +0200 Subject: [PATCH 059/124] bumper: Add collider authoring component. --- .../VisualPinball.Unity.Editor/Utils/Icons.cs | 1 + .../VPT/Bumper/BumperColliderInspector.cs | 57 +++++++++++++++++++ .../VPT/Bumper/BumperInspector.cs | 9 --- .../VPT/Bumper/BumperColliderAuthoring.cs | 27 +++++++++ .../VPT/Bumper/BumperExtensions.cs | 4 +- .../VPT/ItemColliderAuthoring.cs | 4 +- 6 files changed, 89 insertions(+), 13 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperColliderAuthoring.cs diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs index 36dca8be5..031a04dad 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs @@ -133,6 +133,7 @@ public static void OnScriptsReloaded() DisableGizmo(); DisableGizmo(); DisableGizmo(); + DisableGizmo(); DisableGizmo(); DisableGizmo(); DisableGizmo(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs new file mode 100644 index 000000000..fcd23ee3e --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs @@ -0,0 +1,57 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Bumper; +using VisualPinball.Engine.VPT.Rubber; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(BumperColliderAuthoring))] + public class BumperColliderInspector : ItemColliderInspector + { + private BumperData _bumperData; + + private bool _foldoutMaterial = true; + + protected override void OnEnable() + { + base.OnEnable(); + _bumperData = Data; + } + + public override void OnInspectorGUI() + { + if (_bumperData == null) { + NoDataPanel(); + return; + } + + ItemDataField("Collidable", ref _bumperData.IsCollidable, dirtyMesh: false); + + EditorGUI.BeginDisabledGroup(!_bumperData.IsCollidable); + ItemDataField("Has Hit Event", ref _bumperData.HitEvent, dirtyMesh: false); + ItemDataField("Force", ref _bumperData.Force, dirtyMesh: false); + ItemDataField("Hit Threshold", ref _bumperData.Threshold, dirtyMesh: false); + ItemDataField("Scatter Angle", ref _bumperData.Scatter, dirtyMesh: false); + EditorGUI.EndDisabledGroup(); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs index a63c77eb4..15cd31968 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs @@ -52,15 +52,6 @@ public override void OnInspectorGUI() } EditorGUILayout.EndFoldoutHeaderGroup(); - if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "Physics")) { - ItemDataField("Has Hit Event", ref _bumper.Data.HitEvent, dirtyMesh: false); - ItemDataField("Force", ref _bumper.Data.Force, dirtyMesh: false); - ItemDataField("Hit Threshold", ref _bumper.Data.Threshold, dirtyMesh: false); - ItemDataField("Scatter Angle", ref _bumper.Data.Scatter, dirtyMesh: false); - ItemDataField("Collidable", ref _bumper.Data.IsCollidable, dirtyMesh: false); - } - EditorGUILayout.EndFoldoutHeaderGroup(); - if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { ItemDataField("Timer Enabled", ref _bumper.Data.IsTimerEnabled, dirtyMesh: false); ItemDataField("Timer Interval", ref _bumper.Data.TimerInterval, dirtyMesh: false); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperColliderAuthoring.cs new file mode 100644 index 000000000..39ef6e1f8 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperColliderAuthoring.cs @@ -0,0 +1,27 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Bumper; +using VisualPinball.Engine.VPT.Rubber; + +namespace VisualPinball.Unity +{ + [AddComponentMenu("Visual Pinball/Collision/Bumper Collider")] + public class BumperColliderAuthoring : ItemColliderAuthoring + { + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs index 4c3fd3283..437e727f1 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs @@ -30,7 +30,7 @@ public static IItemMainAuthoring SetupGameObject(this Bumper bumper, GameObject switch (bumper.SubComponent) { case ItemSubComponent.None: - //obj.AddComponent(); + obj.AddComponent(); CreateChild(obj, BumperMeshGenerator.Base); CreateChild(obj, BumperMeshGenerator.Cap); var ring = CreateChild(obj, BumperMeshGenerator.Ring); @@ -41,7 +41,7 @@ public static IItemMainAuthoring SetupGameObject(this Bumper bumper, GameObject break; case ItemSubComponent.Collider: { - //obj.AddComponent(); + obj.AddComponent(); if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { hittableAuthoring.RemoveHittableComponent(); } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs index 14414f7ee..912457d2a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs @@ -233,9 +233,9 @@ private static void GizmoDrawCircle(Matrix4x4 ltw, Vector3 center, float radius) internal static class ColliderColor { - internal static readonly Color Aabb = new Color32(255, 0, 252, 8); + internal static readonly Color Aabb = new Color32(255, 0, 252, 50); internal static readonly Color SelectedAabb = new Color32(255, 0, 252, 255); - internal static readonly Color Collider = new Color32(0, 255, 75, 8); + internal static readonly Color Collider = new Color32(0, 255, 75, 50); internal static readonly Color SelectedCollider = new Color32(0, 255, 75, 255); } } From 34375d4f1fa4f81d620a6b2c05d87c2ee0caf100 Mon Sep 17 00:00:00 2001 From: freezy Date: Fri, 9 Oct 2020 23:37:24 +0200 Subject: [PATCH 060/124] surface: Add mesh component inspectors. --- .../Bumper/BumperColliderInspector.cs.meta | 11 +++++ .../VPT/Surface/SurfaceInspector.cs | 6 --- .../VPT/Surface/SurfaceSideMeshInspector.cs | 49 +++++++++++++++++++ .../Surface/SurfaceSideMeshInspector.cs.meta | 11 +++++ .../VPT/Surface/SurfaceTopMeshInspector.cs | 49 +++++++++++++++++++ .../Surface/SurfaceTopMeshInspector.cs.meta | 11 +++++ .../VPT/Bumper/BumperAuthoring.cs | 4 -- .../Bumper/BumperColliderAuthoring.cs.meta | 11 +++++ .../VPT/Flipper/FlipperAuthoring.cs | 4 -- .../VPT/Gate/GateAuthoring.cs | 4 -- .../VPT/HitTarget/HitTargetAuthoring.cs | 4 -- .../VPT/Kicker/KickerAuthoring.cs | 4 -- .../VPT/Plunger/PlungerAuthoring.cs | 4 -- .../VPT/Primitive/PrimitiveAuthoring.cs | 4 -- .../VPT/Ramp/RampAuthoring.cs | 4 -- .../VPT/Spinner/SpinnerAuthoring.cs | 4 -- .../VPT/Surface/SurfaceAuthoring.cs | 5 +- .../VPT/Trigger/TriggerAuthoring.cs | 4 -- 18 files changed, 146 insertions(+), 47 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceSideMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceSideMeshInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceTopMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceTopMeshInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperColliderAuthoring.cs.meta diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs.meta new file mode 100644 index 000000000..2ad2d81b9 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9f0a870ad98f2984982ab141727c206d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs index eec5658f1..9d9f802d5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs @@ -39,12 +39,6 @@ public override void OnInspectorGUI() OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - ItemDataField("Top Visible", ref _targetSurf.Data.IsTopBottomVisible); - TextureField("Top Image", ref _targetSurf.Data.Image); - MaterialField("Top Material", ref _targetSurf.Data.TopMaterial); - ItemDataField("Side Visible", ref _targetSurf.Data.IsSideVisible); - TextureField("Side Image", ref _targetSurf.Data.SideImage); - MaterialField("Side Material", ref _targetSurf.Data.SideMaterial); MaterialField("Slingshot Material", ref _targetSurf.Data.SlingShotMaterial); ItemDataField("Animate Slingshot", ref _targetSurf.Data.SlingshotAnimation, dirtyMesh: false); ItemDataField("Flipbook", ref _targetSurf.Data.IsFlipbook, dirtyMesh: false); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceSideMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceSideMeshInspector.cs new file mode 100644 index 000000000..b67ea5057 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceSideMeshInspector.cs @@ -0,0 +1,49 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Surface; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(SurfaceSideMeshAuthoring))] + public class SurfaceSideMeshInspector : ItemMeshInspector + { + private SurfaceData _data; + + protected override void OnEnable() + { + base.OnEnable(); + _data = Data; + } + + public override void OnInspectorGUI() + { + if (Data == null) { + NoDataPanel(); + return; + } + + ItemDataField("Side Visible", ref _data.IsSideVisible); + TextureField("Side Image", ref _data.SideImage); + MaterialField("Side Material", ref _data.SideMaterial); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceSideMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceSideMeshInspector.cs.meta new file mode 100644 index 000000000..780e31811 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceSideMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 09c62ee1f4afba743831e23b299b9f95 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceTopMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceTopMeshInspector.cs new file mode 100644 index 000000000..4a11eb465 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceTopMeshInspector.cs @@ -0,0 +1,49 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Surface; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(SurfaceTopMeshAuthoring))] + public class SurfaceTopMeshInspector : ItemMeshInspector + { + private SurfaceData _data; + + protected override void OnEnable() + { + base.OnEnable(); + _data = Data; + } + + public override void OnInspectorGUI() + { + if (Data == null) { + NoDataPanel(); + return; + } + + ItemDataField("Top Visible", ref _data.IsTopBottomVisible); + TextureField("Top Image", ref _data.Image); + MaterialField("Top Material", ref _data.TopMaterial); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceTopMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceTopMeshInspector.cs.meta new file mode 100644 index 000000000..bbb5a046e --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceTopMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: adc8f9ec5caf7a443ad19ceb2d4e0ff5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs index 893e23a0c..69c69effc 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs @@ -63,10 +63,6 @@ public void RemoveHittableComponent() { } - public void LinkChild(IItemAuthoring item) - { - } - public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() => Data.Center.ToUnityVector3(0f); public override void SetEditorPosition(Vector3 pos) => Data.Center = pos.ToVertex2Dxy(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperColliderAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperColliderAuthoring.cs.meta new file mode 100644 index 000000000..004407014 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperColliderAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 52e9ef1b7475b784ba8d5896143fe3b1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 8b5b2f118ce4f0146aea1850279a2d51, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs index f77ea457e..a77c4fdd6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs @@ -68,10 +68,6 @@ public void RemoveHittableComponent() { } - public void LinkChild(IItemAuthoring item) - { - } - public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() => Data.Center.ToUnityVector3(0f); public override void SetEditorPosition(Vector3 pos) => Data.Center = pos.ToVertex2Dxy(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs index 5b3519aaf..ececbc08c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs @@ -47,10 +47,6 @@ public void RemoveHittableComponent() { } - public void LinkChild(IItemAuthoring item) - { - } - public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; public override Vector3 GetEditorPosition() => Data.Center.ToUnityVector3(Data.Height); public override void SetEditorPosition(Vector3 pos) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs index 75b90f3b5..5766dddec 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs @@ -71,10 +71,6 @@ public void RemoveHittableComponent() { } - public void LinkChild(IItemAuthoring item) - { - } - public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; public override Vector3 GetEditorPosition() => Data.Position.ToUnityVector3(); public override void SetEditorPosition(Vector3 pos) => Data.Position = pos.ToVertex3D(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs index e8f5b98ae..4da901d97 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs @@ -90,10 +90,6 @@ public void RemoveHittableComponent() { } - public void LinkChild(IItemAuthoring item) - { - } - public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() => Data.Center.ToUnityVector3(0f); public override void SetEditorPosition(Vector3 pos) => Data.Center = pos.ToVertex2Dxy(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs index 35f32988b..068ef6a55 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs @@ -99,10 +99,6 @@ public void RemoveHittableComponent() { } - public void LinkChild(IItemAuthoring item) - { - } - public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() => Data.Center.ToUnityVector3(0f); public override void SetEditorPosition(Vector3 pos) => Data.Center = pos.ToVertex3D(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs index e6c166b7e..6b07ac5cc 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs @@ -43,10 +43,6 @@ public void RemoveHittableComponent() { } - public void LinkChild(IItemAuthoring item) - { - } - protected override Primitive InstantiateItem(PrimitiveData data) => new Primitive(data); public IHittable Hittable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs index 1a225eec6..d7790f3a6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs @@ -51,10 +51,6 @@ public void RemoveHittableComponent() { } - public void LinkChild(IItemAuthoring item) - { - } - private void OnDestroy() { if (!Application.isPlaying) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs index 65095302e..c98378b58 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs @@ -47,10 +47,6 @@ public void RemoveHittableComponent() { } - public void LinkChild(IItemAuthoring item) - { - } - public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; public override Vector3 GetEditorPosition() => Data.Center.ToUnityVector3(Data.Height); public override void SetEditorPosition(Vector3 pos) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs index 178b73130..f7c60c5a9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs @@ -20,6 +20,7 @@ // ReSharper disable MemberCanBePrivate.Global #endregion +using System; using System.Collections.Generic; using Unity.Entities; using UnityEngine; @@ -36,6 +37,8 @@ public class SurfaceAuthoring : ItemMainAuthoring, { protected override Surface InstantiateItem(SurfaceData data) => new Surface(data); + protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + public IHittable Hittable => Item; private void OnDestroy() @@ -78,7 +81,7 @@ public override void SetEditorPosition(Vector3 pos) { var diff = pos.ToVertex3D().Sub(Data.DragPoints[0].Center); diff.Z = 0f; Data.DragPoints[0].Center = pos.ToVertex3D(); - for (int i = 1; i < Data.DragPoints.Length; i++) { + for (var i = 1; i < Data.DragPoints.Length; i++) { var pt = Data.DragPoints[i]; pt.Center = pt.Center.Add(diff); } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs index 624dae81c..cd4676dac 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs @@ -69,10 +69,6 @@ public void RemoveHittableComponent() { } - public void LinkChild(IItemAuthoring item) - { - } - public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() => Data.Center.ToUnityVector3(0f); From 6a1cba8173f454167880b30077a528796217bf7d Mon Sep 17 00:00:00 2001 From: freezy Date: Sat, 10 Oct 2020 00:14:01 +0200 Subject: [PATCH 061/124] gate: Refactor mesh generator. --- VisualPinball.Engine/Game/IRenderable.cs | 2 +- VisualPinball.Engine/VPT/Bumper/Bumper.cs | 2 +- VisualPinball.Engine/VPT/Flipper/Flipper.cs | 2 +- VisualPinball.Engine/VPT/Gate/Gate.cs | 4 +- .../VPT/Gate/GateMeshGenerator.cs | 44 ++++++++++++++----- .../VPT/HitTarget/HitTarget.cs | 2 +- VisualPinball.Engine/VPT/Kicker/Kicker.cs | 2 +- VisualPinball.Engine/VPT/Light/Light.cs | 2 +- VisualPinball.Engine/VPT/Mappings/Mappings.cs | 4 +- VisualPinball.Engine/VPT/MeshGenerator.cs | 2 +- VisualPinball.Engine/VPT/Plunger/Plunger.cs | 2 +- .../VPT/Primitive/Primitive.cs | 2 +- VisualPinball.Engine/VPT/Ramp/Ramp.cs | 2 +- VisualPinball.Engine/VPT/Rubber/Rubber.cs | 2 +- VisualPinball.Engine/VPT/Spinner/Spinner.cs | 2 +- VisualPinball.Engine/VPT/Surface/Surface.cs | 2 +- VisualPinball.Engine/VPT/Table/Table.cs | 2 +- VisualPinball.Engine/VPT/Trigger/Trigger.cs | 2 +- .../Toolbox/ToolboxEditor.cs | 2 +- .../Import/VpxConverter.cs | 8 ++-- .../VPT/ItemMainAuthoring.cs | 2 +- 21 files changed, 58 insertions(+), 36 deletions(-) diff --git a/VisualPinball.Engine/Game/IRenderable.cs b/VisualPinball.Engine/Game/IRenderable.cs index 5e6c3c1f2..592440365 100644 --- a/VisualPinball.Engine/Game/IRenderable.cs +++ b/VisualPinball.Engine/Game/IRenderable.cs @@ -22,7 +22,7 @@ namespace VisualPinball.Engine.Game { public interface IRenderable : IItem { - Matrix3D TransformationMatrix(Origin origin); + Matrix3D TransformationMatrix(Table table, Origin origin); RenderObject GetRenderObject(Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true); diff --git a/VisualPinball.Engine/VPT/Bumper/Bumper.cs b/VisualPinball.Engine/VPT/Bumper/Bumper.cs index f6032d212..185f4c599 100644 --- a/VisualPinball.Engine/VPT/Bumper/Bumper.cs +++ b/VisualPinball.Engine/VPT/Bumper/Bumper.cs @@ -55,7 +55,7 @@ public void Init(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Origin origin) + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) { switch (origin) { case Origin.Original: diff --git a/VisualPinball.Engine/VPT/Flipper/Flipper.cs b/VisualPinball.Engine/VPT/Flipper/Flipper.cs index 993edd99d..b597efa35 100644 --- a/VisualPinball.Engine/VPT/Flipper/Flipper.cs +++ b/VisualPinball.Engine/VPT/Flipper/Flipper.cs @@ -53,7 +53,7 @@ public void Init(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => Matrix3D.Identity; public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { diff --git a/VisualPinball.Engine/VPT/Gate/Gate.cs b/VisualPinball.Engine/VPT/Gate/Gate.cs index 5bca8ef4b..3be8064db 100644 --- a/VisualPinball.Engine/VPT/Gate/Gate.cs +++ b/VisualPinball.Engine/VPT/Gate/Gate.cs @@ -64,11 +64,11 @@ public void Init(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => _meshGenerator.GetPostMatrix(table, origin); public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { - throw new System.NotImplementedException(); + return _meshGenerator.GetRenderObject(table, id, origin, asRightHanded); } public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) diff --git a/VisualPinball.Engine/VPT/Gate/GateMeshGenerator.cs b/VisualPinball.Engine/VPT/Gate/GateMeshGenerator.cs index beffe12d6..1b1e2b596 100644 --- a/VisualPinball.Engine/VPT/Gate/GateMeshGenerator.cs +++ b/VisualPinball.Engine/VPT/Gate/GateMeshGenerator.cs @@ -24,6 +24,11 @@ namespace VisualPinball.Engine.VPT.Gate { public class GateMeshGenerator : MeshGenerator { + + public const string Wire = "Wire"; + public const string Bracket = "Bracket"; + + private readonly GateData _data; protected override Vertex3D Position => new Vertex3D(_data.Center.X, _data.Center.Y, _data.Height); @@ -37,22 +42,36 @@ public GateMeshGenerator(GateData data) _data = data; } + public RenderObject GetRenderObject(Table.Table table, string id, Origin origin, bool asRightHanded) + { + var (preMatrix, _) = GetPreMatrix(table, origin, asRightHanded); + switch (id) { + case Wire: + return new RenderObject( + id, + GetBaseMesh().Transform(preMatrix), + new PbrMaterial(table.GetMaterial(_data.Material)), + _data.IsVisible + ); + case Bracket: + return new RenderObject( + id, + GateBracketMesh.Clone().Transform(preMatrix), + new PbrMaterial(table.GetMaterial(_data.Material)), + _data.IsVisible && _data.ShowBracket + ); + default: + throw new ArgumentException("Unknown gate mesh \"" + id + "\"."); + } + } + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin, bool asRightHanded) { var (preMatrix, _) = GetPreMatrix(table, origin, asRightHanded); var postMatrix = GetPostMatrix(table, origin); - return new RenderObjectGroup(_data.Name, "Gates", postMatrix, new RenderObject( - "Wire", - GetBaseMesh().Transform(preMatrix), - new PbrMaterial(table.GetMaterial(_data.Material)), - _data.IsVisible - ), - new RenderObject( - "Bracket", - GateBracketMesh.Clone().Transform(preMatrix), - new PbrMaterial(table.GetMaterial(_data.Material)), - _data.IsVisible && _data.ShowBracket - ) + return new RenderObjectGroup(_data.Name, "Gates", postMatrix, + GetRenderObject(table, Wire, origin, asRightHanded), + GetRenderObject(table, Bracket, origin, asRightHanded) ); } @@ -83,5 +102,6 @@ private Mesh GetBaseMesh() private static readonly Mesh GateBracketMesh = new Mesh("Bracket", GateBracket.Vertices, GateBracket.Indices); #endregion + } } diff --git a/VisualPinball.Engine/VPT/HitTarget/HitTarget.cs b/VisualPinball.Engine/VPT/HitTarget/HitTarget.cs index 04adffc67..c91de7738 100644 --- a/VisualPinball.Engine/VPT/HitTarget/HitTarget.cs +++ b/VisualPinball.Engine/VPT/HitTarget/HitTarget.cs @@ -57,7 +57,7 @@ public void Init(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => Matrix3D.Identity; public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { diff --git a/VisualPinball.Engine/VPT/Kicker/Kicker.cs b/VisualPinball.Engine/VPT/Kicker/Kicker.cs index e3bb7aae1..208b277a9 100644 --- a/VisualPinball.Engine/VPT/Kicker/Kicker.cs +++ b/VisualPinball.Engine/VPT/Kicker/Kicker.cs @@ -61,7 +61,7 @@ public void Init(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => Matrix3D.Identity; public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { diff --git a/VisualPinball.Engine/VPT/Light/Light.cs b/VisualPinball.Engine/VPT/Light/Light.cs index 3aa00109f..67dae31ed 100644 --- a/VisualPinball.Engine/VPT/Light/Light.cs +++ b/VisualPinball.Engine/VPT/Light/Light.cs @@ -60,7 +60,7 @@ public static Light GetDefault(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => Matrix3D.Identity; public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { diff --git a/VisualPinball.Engine/VPT/Mappings/Mappings.cs b/VisualPinball.Engine/VPT/Mappings/Mappings.cs index 562d9e766..e62c2950e 100644 --- a/VisualPinball.Engine/VPT/Mappings/Mappings.cs +++ b/VisualPinball.Engine/VPT/Mappings/Mappings.cs @@ -26,7 +26,8 @@ namespace VisualPinball.Engine.VPT.Mappings { public class Mappings : Item { - public override string ItemType => "Mappings"; + public override string ItemName { get; } = "Mapping"; + public override string ItemGroupName { get; } = "Mappings"; public Mappings() : this(new MappingsData("Mappings")) { @@ -252,5 +253,6 @@ private static ICoilable GuessPlayfieldCoil(Dictionary coils, } #endregion + } } diff --git a/VisualPinball.Engine/VPT/MeshGenerator.cs b/VisualPinball.Engine/VPT/MeshGenerator.cs index f30bee48a..15099ac0b 100644 --- a/VisualPinball.Engine/VPT/MeshGenerator.cs +++ b/VisualPinball.Engine/VPT/MeshGenerator.cs @@ -46,7 +46,7 @@ protected Tuple GetPreMatrix(Table.Table table, Origin origi } } - protected Matrix3D GetPostMatrix(Table.Table table, Origin origin) + internal Matrix3D GetPostMatrix(Table.Table table, Origin origin) { switch (origin) { case Origin.Original: return GetTransformationMatrix(table).Item1; diff --git a/VisualPinball.Engine/VPT/Plunger/Plunger.cs b/VisualPinball.Engine/VPT/Plunger/Plunger.cs index 678d72fc0..5af6b2bc3 100644 --- a/VisualPinball.Engine/VPT/Plunger/Plunger.cs +++ b/VisualPinball.Engine/VPT/Plunger/Plunger.cs @@ -60,7 +60,7 @@ public void Init(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => Matrix3D.Identity; public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { diff --git a/VisualPinball.Engine/VPT/Primitive/Primitive.cs b/VisualPinball.Engine/VPT/Primitive/Primitive.cs index 583c6a8bc..b8ddbc98f 100644 --- a/VisualPinball.Engine/VPT/Primitive/Primitive.cs +++ b/VisualPinball.Engine/VPT/Primitive/Primitive.cs @@ -61,7 +61,7 @@ public static Primitive GetDefault(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => Matrix3D.Identity; public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin, bool asRightHanded, string parent, PbrMaterial material) => _meshGenerator.GetRenderObjects(table, origin, asRightHanded, parent, material); diff --git a/VisualPinball.Engine/VPT/Ramp/Ramp.cs b/VisualPinball.Engine/VPT/Ramp/Ramp.cs index 8fffbb7ed..9f29b88ed 100644 --- a/VisualPinball.Engine/VPT/Ramp/Ramp.cs +++ b/VisualPinball.Engine/VPT/Ramp/Ramp.cs @@ -63,7 +63,7 @@ public void Init(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => Matrix3D.Identity; public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { diff --git a/VisualPinball.Engine/VPT/Rubber/Rubber.cs b/VisualPinball.Engine/VPT/Rubber/Rubber.cs index 918d1f11a..ee2a789f0 100644 --- a/VisualPinball.Engine/VPT/Rubber/Rubber.cs +++ b/VisualPinball.Engine/VPT/Rubber/Rubber.cs @@ -63,7 +63,7 @@ public static Rubber GetDefault(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => Matrix3D.Identity; public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { diff --git a/VisualPinball.Engine/VPT/Spinner/Spinner.cs b/VisualPinball.Engine/VPT/Spinner/Spinner.cs index 17b3f528c..c6e26a8da 100644 --- a/VisualPinball.Engine/VPT/Spinner/Spinner.cs +++ b/VisualPinball.Engine/VPT/Spinner/Spinner.cs @@ -65,7 +65,7 @@ public void Init(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => Matrix3D.Identity; public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { diff --git a/VisualPinball.Engine/VPT/Surface/Surface.cs b/VisualPinball.Engine/VPT/Surface/Surface.cs index db52d5dbb..ca1e3ce37 100644 --- a/VisualPinball.Engine/VPT/Surface/Surface.cs +++ b/VisualPinball.Engine/VPT/Surface/Surface.cs @@ -64,7 +64,7 @@ public void Init(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => Matrix3D.Identity; public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { diff --git a/VisualPinball.Engine/VPT/Table/Table.cs b/VisualPinball.Engine/VPT/Table/Table.cs index 1e10a1b74..60a786209 100644 --- a/VisualPinball.Engine/VPT/Table/Table.cs +++ b/VisualPinball.Engine/VPT/Table/Table.cs @@ -499,7 +499,7 @@ public Table(BinaryReader reader) : this(new TableData(reader)) { } #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Table table, Origin origin) => Matrix3D.Identity; public RenderObject GetRenderObject(Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { diff --git a/VisualPinball.Engine/VPT/Trigger/Trigger.cs b/VisualPinball.Engine/VPT/Trigger/Trigger.cs index acd934077..4e0148466 100644 --- a/VisualPinball.Engine/VPT/Trigger/Trigger.cs +++ b/VisualPinball.Engine/VPT/Trigger/Trigger.cs @@ -66,7 +66,7 @@ public void Init(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => Matrix3D.Identity; public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs index 206ff5aec..c2723853e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs @@ -185,7 +185,7 @@ private void CreateItem(Func create, string actionName) whe private GameObject CreateRenderable(IRenderable renderable) { //var rog = renderable.GetRenderObjects(_table.Table, Origin.Original, false); - var (obj, _) = VpxConverter.CreateGameObjects(renderable, GetOrCreateParent(_tableAuthoring, renderable)); + var (obj, _) = VpxConverter.CreateGameObjects(_tableAuthoring.Table, renderable, GetOrCreateParent(_tableAuthoring, renderable)); return obj; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index e36606c17..c8120ad3d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -140,7 +140,7 @@ orderby renderable.SubComponent if (renderable.SubComponent == ItemSubComponent.None) { // create object(s) - var (rootObj, rootMb) = CreateGameObjects(renderable, _parents[renderable.ItemGroupName]); + var (rootObj, rootMb) = CreateGameObjects(_table, renderable, _parents[renderable.ItemGroupName]); createdMainObjs[renderable.Name.ToLower()] = rootObj; createdMainMbs[renderable.Name.ToLower()] = rootMb; @@ -151,7 +151,7 @@ orderby renderable.SubComponent if (createdMainObjs.ContainsKey(parentName)) { var mainObj = createdMainObjs[parentName]; var mainMb = createdMainMbs[parentName]; - var (rootObj, _) = CreateGameObjects(renderable, _parents[renderable.ItemGroupName], mainMb); + var (rootObj, _) = CreateGameObjects(_table, renderable, _parents[renderable.ItemGroupName], mainMb); rootObj.transform.SetParent(mainObj.transform, false); } else { @@ -168,7 +168,7 @@ orderby renderable.SubComponent // } } - public static (GameObject, IItemMainAuthoring) CreateGameObjects(IRenderable renderable, GameObject parent, IItemMainAuthoring parentAuthoring = null) + public static (GameObject, IItemMainAuthoring) CreateGameObjects(Table table, IRenderable renderable, GameObject parent, IItemMainAuthoring parentAuthoring = null) { var obj = new GameObject(renderable.Name); obj.transform.parent = parent.transform; @@ -176,7 +176,7 @@ public static (GameObject, IItemMainAuthoring) CreateGameObjects(IRenderable ren var mb = SetupGameObjects(renderable, obj, parentAuthoring); // apply transformation - obj.transform.SetFromMatrix(renderable.TransformationMatrix(Origin.Original).ToUnityMatrix()); + obj.transform.SetFromMatrix(renderable.TransformationMatrix(table, Origin.Original).ToUnityMatrix()); return (obj, mb); } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs index 82e9e0248..2f7b1e702 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs @@ -80,7 +80,7 @@ public void RebuildMeshIfDirty() // update transform based on item data, but not for "Table" since its the effective "root" and the user might want to move it on their own var ta = GetComponentInParent(); if (ta != this) { - transform.SetFromMatrix(Item.TransformationMatrix(Origin.Original).ToUnityMatrix()); + transform.SetFromMatrix(Item.TransformationMatrix(Table, Origin.Original).ToUnityMatrix()); } } From bcfdaacd9463ba174cc324b856c75f21d92b074b Mon Sep 17 00:00:00 2001 From: freezy Date: Sat, 10 Oct 2020 22:47:14 +0200 Subject: [PATCH 062/124] editor: Update icons. --- .../Resources/Icons/small_blue/bumper_cap.png | Bin 455 -> 458 bytes .../Icons/small_blue/bumper_ring.png | Bin 472 -> 472 bytes .../Icons/small_blue/bumper_skirt.png | Bin 461 -> 461 bytes .../Icons/small_blue/bumper_socket.png | Bin 465 -> 451 bytes .../Icons/small_blue/gate_bracket.png | Bin 404 -> 394 bytes .../Resources/Icons/small_blue/gate_wire.png | Bin 394 -> 404 bytes .../Icons/small_green/bumper_cap.png | Bin 455 -> 455 bytes .../Icons/small_green/bumper_ring.png | Bin 471 -> 469 bytes .../Icons/small_green/bumper_skirt.png | Bin 459 -> 459 bytes .../Icons/small_green/bumper_socket.png | Bin 468 -> 453 bytes .../Icons/small_green/gate_bracket.png | Bin 408 -> 400 bytes .../Resources/Icons/small_green/gate_wire.png | Bin 400 -> 408 bytes .../Icons/small_orange/bumper_cap.png | Bin 461 -> 464 bytes .../Icons/small_orange/bumper_ring.png | Bin 470 -> 473 bytes .../Icons/small_orange/bumper_skirt.png | Bin 464 -> 464 bytes .../Icons/small_orange/bumper_socket.png | Bin 469 -> 457 bytes .../Icons/small_orange/gate_bracket.png | Bin 406 -> 399 bytes .../Icons/small_orange/gate_wire.png | Bin 399 -> 406 bytes .../VPT/Gate/GateBracketMeshAuthoring.cs | 29 ++++++++++++++++++ .../VPT/Gate/GateWireMeshAuthoring.cs | 28 +++++++++++++++++ 20 files changed, 57 insertions(+) create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateBracketMeshAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireMeshAuthoring.cs diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_cap.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_cap.png index 64bb625ed8834643fa8a939a92b067798091d597..7179ef89e4cad096e93cfd02ce4d91df7cad5076 100644 GIT binary patch delta 411 zcmV;M0c8Hi1Ih!CIe&afL_t(oh3%L-Qo}G5MQ=0|DN|CWjJqrWIy$lhvl6ruyaedd zK}nekyL3tE(hW8vc=9;~Bw8J#Y&BcHs;epgmc0}w@hGaJz>(;&~A z6@VK6I{@o}TuK1X0N!}QD)nIZ9OZelCNUv+KaiY_7a=Ufd4IynPL$_O3gBsEIU5f= zVVPW`>Gb?Me%uz1A7A3Hew~Jsm0LFPYD!X3(OIMtEj`iQKX#QfdACcn2R@y!AKI+P zUX_HcGx3DI11JWRlN5Aq4Oa^lT|(;+0jcPkMw|(sTIq^D-T}B)PRTCxR@eS#Z<$r5 z)+sUe`cCxsi+>eK*M{TTT5`^pH|kJ*?i?}Z`6i0`CW`tdiuxvs`o`Hp6_)A%W!L|p z&1vK0YexzuA@}zsZHt{r?NoZ&QffN;m;aHP0`uV_QJyzTs^TWFph`j2)smWN&$J=Q z&{ecilkCwB<4Ba&<8~xLl|z5s#&`I>iK4!VqFw>;4HT;Ffvg95e&7HA002ovPDHLk FV1gPH!z2Iz delta 408 zcmV;J0cZZo1IGi9Ie&RcL_t(oh3%N3a)U4!$N$Y$R7_M>Ru;E6*ybkp2+Zv*_C3bj z`UsVETis;Uf~>4WOdz(fqZha|Bv9@`3U~QAl0bfZgzpPX@;t{FV56`MqCF5qT@yrI zGaAvUsgbyt1Goq91YqgOYY_(A}($fxjRpCHh*@C^u7`$E@A-hSC+H! zOc7g`Ycw97U&YC7^7{Q(JnoNSI9YjM1CM4&Je6vtlNbJu7pp+&;2-C2(u<(x(uznNqy zoy)^V01Iu%x__g$o?+BwmYPauN#olsPfVqBX6Qe3u_P|^rtH#dgl(Q{f~aePsB13z z_e5N*QJ5-D8E)vclpQS6Jx=$f{9zM^Qu z7~L~bMbcLkZDhJ^_>t?HAnKYR>Y54=7lqo53=OZK?U3`RGffM8%g(HxTE;#~Kh5^Z~$PIHv-=>d(giuvR^hRF44Odsn;Wi30Iqj?@A^U$7m< zuV8CS!i=LfB-I|kbI+1*6o|$!*_A?dBsksAsm7@*`gB(KB-M&Dm1e^W&1CmW8Cygz zm;)c{)S0y1*ngPoE78l1i6Na?=WBDR^LdwrYLeXg3}5EC#*4bfi@L^(y2gvTrZa_F z)QV|NtN-EV0{zErM{c7dqd0L*!kuRNXHjmWH$Ai_y4X4Bwz%zrMp51=i3Zq+i23cd z@065~RBM(Ts=>=xHZ}*ZM0q}rrF}k{^VaX-yT*&U#u@$)0GWlQ7aagEY8x+Vo7spiO@oy2 z06+*}17PLI^vS9+QO4JbT#4$(}=v6?`S+d zzly?b@$m609`pS)oEq7YiAS>}UdmOSDub5*&d2q_7l2n~e^u*8<-&S%u6E3YSU~DX zE#b=pw&VB}Y;{Sfc~ploz6WsQSn`QR#F!@AN~p*LhvA%R9NMx^>o*f+JXEUGHGs8t z$gZc1E+VSVvwz$cRVX!_Q(&z1mFWM8sUn?e^DliYDdSh#P zRsde7;bbLe6OU$1CPlMpxH!o=-4k&!g;dBXWySe{&V)}XI|BF!s?}zvOTt!}C}m%2 z9t(|}H+QCIx=QF4z%ig`sh(-X+2N~dRhQ6504wd3e4xyWwtt>xWnG0#SZh80Q=n9D zDy2L1*OW`n`+sqvA3F8DM{M(a6GeR!MST-ReG^4}<1C>XYrWPJ7Y_q{5^evs?}ZmX zJF3P+HXly|rTX$Io0Us7-}%=Q7aO(4zLuoq9>AWscypa(jA(!;+OS5qyA%l%MH_W= zH~M%hqQpgFXl}=%wZMzt@O=|SeG^5!0^k>l`Fo^TJr0}g00000NkvXXu0mjfw-fGpKjO(nmAJwaW>{Q5!Gc$PYg0IU# z5moD&!j^=uGZAMW01k2eemUy7TXeP1!pf6dqdL>xH%I50iG*AkE%ZSzG?RRw{LZ>I z)2t%SD&K?7UVq<+{ykV}=~n-Bz)VuSn~zojX3+a9``BuYLLf)LPL31&7iB`dtbedVi`dadX7@h>BP0oixov5&gfo= z8j`V&$UZ7tHhstqO%e@F5)Dlf4b4160sH`(S$?xHo(`P)00000NkvXXu0mjf6Mw}? diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_socket.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/bumper_socket.png index f831d8146858cb440ba657367a2befb011a8ffd1..85a9b8f9633bf9c87abd516ef6f647bfdd351054 100644 GIT binary patch delta 404 zcmV;F0c-xz1H%K5Ie&FYL_t(oh3%NJR)a7UhJSJ#I`$ECYc@7V9UU1ReG~7abad?4 zQ8(R~44XUxBa6X9&xHelP|-l)oP0}Z3eA_0lY4K1qA0Ki#40Sk=mdCC*Q`eLs;`lh z-T=4;umiB2$t44j07yxS-2AcLM@i`|i&cV`Y!7H#A# y+o~{HqP!lLQkBNdb?eXYUE@Vv<3*hU;0J8veVb`$#SJ0=0000^G-5mo&)p98-Wz!qSVL059qq zFY21fh|by;Nyreu9KZrV)RRjFU<)82&UWU>sxy(0=bGHSCx1B`i6)&^q9kMtU^%dy zjTLeBQ9h&b`1~sV+=7SCpWs_tRQiF-8EGx_ z1;C|o$wf!`FMs3s9l(wHoDpZ)zeIIN$X5VYwKdLyE|w&ux!D_Wc74ou{g~$(FX|dE z>YAg<6A4*N{r3RQj8oPEZNVJQzX3cFX9v6Bp@JW(n=d*Fb!Dq2`Nq4_K~WXOWsf7@ zPRX`Lw{6VpD~dK+qgxZzB*!o~*JS-4xvue|uJNL-@f)J9nT9BUU%n=Pw(TT?y8r+H M07*qoM6N<$f|vlx#{d8T diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/gate_bracket.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/gate_bracket.png index 728bd59dab4fc0814506295b4a5ee2350c9203a0..f0c88757ade4ac084207a00c68f5fd0ffc4c863f 100644 GIT binary patch delta 346 zcmV-g0j2(w1BwHXIe$D!L_t(oh3%QK4Z<)GML(7YV1%@mDA)itVU=S8M#w0PKu4RB zl9Gy`NEQkK$FX&1$0)yvWLdr^|GSgztlG9k2~tH+mISKl`rHCo&w!<`hKy?Z0~){y zz%D!5r;Y%qKeFT~w>s-<0O#Ji-Pk5k{EPio01jglH5pY82Y>1Mq~FtdMMja0xA%d% ztbZin42t0bz45S&Dkw(rRi9!X zN+fqRs5QX@I;$2n1}a(k!EWUO4R$M+^{k+h#l&j;tdwO(hgab#a)Odk#k3~~ReqFH zIY6VF@_|a&FH-_4QBYB9YJLtDRranw8B}6Nr?jTS@Ik@{dXG7hc@&kSqoDQ_{`KUO sLvzW|#=eOm0PMX<5Zt#IPXGV_07*qoM6N<$f@vh6)Bpeg delta 356 zcmV-q0h|7c1C#@hIe$h;L_t(oh3%O=4uU`sg&!LV3kyq2TRM+m=`lQlN7%xH;SIE+ z#T(!S#F%Uh68G1cUDogtLc-6^mwhwC0!82V$U!0t%A7z;**w+&7876@s*{!Ih6hRj zdjOl{XrHRp_ST%E)OuNe0niS{T>>~oihor56@abj!moW)Hh+&O%~e*SQ1M@qEVLuBfM?nRRS<-WmXrLGfNK?tt&XyAM&jxDEpw!9(6u=WC_DNLUy#G=F0000>~oihor56@abj!moW)Hh+&O%~e*SQ1M@qEVLuBfM?nRRS<-WmXrLGfNK?tt&XyAM&jxDEpw!9(6u=WC_DNLUy#G=F0000s-<0O#Ji-Pk5k{EPio01jglH5pY82Y>1Mq~FtdMMja0xA%d% ztbZin42t0bz45S&Dkw(rRi9!X zN+fqRs5QX@I;$2n1}a(k!EWUO4R$M+^{k+h#l&j;tdwO(hgab#a)Odk#k3~~ReqFH zIY6VF@_|a&FH-_4QBYB9YJLtDRranw8B}6Nr?jTS@Ik@{dXG7hc@&kSqoDQ_{`KUO sLvzW|#=eOm0PMX<5Zt#IPXGV_07*qoM6N<$f@vh6)Bpeg diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_cap.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_cap.png index bb056893153254cf4890ceec0faad93c3fe99e30..2d62c1cee1fd9eea02bd6386f4d7b3ee433b7a87 100644 GIT binary patch delta 399 zcmV;A0dW4u1IGi9LVqoDgFqBTZ+0RgBP$~#^AlQEMQe+qzpN;9gNkcqWh4?=iNtit zZ09XQ_A5!de9i1}0Rks458hoCP19fwuvu6J(H;n*zL|~a(zG$>@fyHAfM)=kfm})e z?*Kj{mR0J`_BopKctc`B@M$198+#!v#3PoKt!U2U1i;(Ka(^~nBbKGIN0aIKwfwp* z_CGJ;ul|^Zla&WH@oGvEQPEkX5-mN^-9L7fQ+c;bvW-|`uGUoPB|pK(Od2P?@pUlrqL-e&Uy)bu_Ec( zuwUyX7demBy?^z!=Lj*+H$l`lLDV-v)HgxYH_j2Nuu?ZrcKr|9Ic;2g?MT6-&-Hyt z%VK9zyOf@Gl$x&o<$t86zD%PDHLkV1ho3z8e4l delta 399 zcmV;A0dW4u1IGi9LVqE1gD@C|-{vYRCMqi{EB6n!xvAXjqL|xHnp+jRi>h1eCMS`V zm52$%7IyRkmxct&T}a_Bk0S}>;Uj!sV3OxK#sC?GWf1LwAnKYR>YCArPECzmusMKx z08apxo?H$9HUM^%#Hrp{RVFUjts-~lNzTSzk^ZhkxnL21_kSzP*?6HOUYBb$8lGRp z$!+rS_gp;g&tW)Oc_0IiW=S-aZ}nbjys>2ikNg7oQKnng_M=>|1%THpi@s43AJv9h z!j}WKUbW8I>XNWkCQ9Nj0Eu6}6N#L=MpFqb5^n9zdgLhQG}8FZBunXB9zFtCXhYT= zz4Z*EF0<5BI)6(V-)?zgDy1_+|DlT|7ff%;F1<$B=D8+_x+aLa=AwU3T(Fhg`Ombj zPU*?;SyQCE4JC1F6>LlRGby<0DAbii3fFRVt7tD%PDHLkV1ifLy7mA7 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_ring.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_ring.png index 15f49519dd99bdba5b14d990b3da609670f98d0a..5c2079b9fb2080126dc775f539ce6533d192c86a 100644 GIT binary patch delta 422 zcmV;X0a^an1JwhNIe&*qL_t(oh3%NDlEN?)hJP{$ByuGZ*+@d~^Vsv4qj zyN`gZEDl*&vni9#X(yzYWp_i<&g3(c^fKSH$+=`!6a}ULn}nqoeF9$8Hj@#Zw+#x( z7XVfO)&Q0Rxnuwm0BOkL+&o#wQ6c$~#416Tl)~yaWN}uD3V+E10Fh(4E)F4!&($0a z#^+a4y3LN?AL>(Y$Klk;o{ju%Rs{1F(H8&ekD6o5_%jp5t1JOybmmS3|ZV7Ci_yTiUgPEIW@TSMW5aZUr4^9Or_Y+ zLets*QpOZf3xDQB$0~KET{pJo`U<)+)ueOdd}A*4K?_wUee@Z=%(IObwT&0GjTg0z z7qv}q3N>gH)09^K!@~vokK2yaMn_t4Vw;pY&Fs&j)JAUxXiZeHb5d<_*9EPjv{Mo} z*oa8z?RM{!R0zq}B$2`= QbpQYW07*qoM6N<$f;7;^n*aa+ delta 424 zcmV;Z0ayOj1J?tPIe&>sL_t(oh3%LvZ-g)y$N$%yAX6tMP9je-KQTGQrk1Q~U*W#d zDa6!W)#Qo!?Hm$0F)_7ZR+f@NdZoaTl((cm1uZYXJkaNPV3B1R<^Y+6r4#J|Cu$of zYMa@JE=_}sQxAX-U;|(^kjoE%7(fz|DAgy+%EUNbD{}roa({Isiu6}0$~X-GJdP|^ z$37&{XYq~()AK9I-4=(xXYrU{rr}h}j!Zn71;J9T>O>j51#msC7rp_!EBmWTKPng2 z$KYz`+=vCFj#Lu9JYYMHU(QySgqlZn7^iyx4+BdcLJ}F%WK#(hnc&o)Q-xDg_G$cP zVx0O)mAVJ8)_)G!b(GOXMAdnd+oB33hI4X^wZ1@}m?+YzHh=75$vC~!hLTIK;o3ag zI8oa;QQKVf?}>3Ly8b5sSK3tE(PyLW{{naoNz{6swuJA=&R@TQZDQHUSH6{6MP(F) zq}Q`#K`Ld9(KWSsLq)L;V|33%70IEZSVyYMx*xf=aUr6%aiX?yqPCfbD1d((`hriM SjdzFu00005`HoV>vdE}w$x&Y{v4BBOCKoVMJ=kU_dK$kjV&d7Uw_TfyXpDW{JAYYeqL4p z-lpMXB_k8BW<{z*(`mRkNn72MkZcN5A)|!n=U=oId`kEcz-LgcCOcCSwq&A&f9rKD zG-}=4bzRdHp<4jQfTD%IW+%=LU#C?Sp^pGo#v$22nO9@~e3}(i3Uy)4di+m;Lf@&9 zZsl*+Tyh~KGk-@a>@1O7Cz1T2{88dhFVFAUS=DuoB|sKonMChE5)Dlf4b5Ui*RG2~vJAi$ zz$1W7B$o=n89+%1zuGt3&LkvzFyyw8$YSv$j^Q^NT)w6%D^Ko?>P!dU7`=NYA=$=gp-+0EndBqo->h>p z%_>TG<$KWC>wg>cgO!%<^j}vl^&up)?_P(#BQ5hnlSD(4L_;&^-;(b+zbE!002ovPDHLkV1j)5#hL&B diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_socket.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/bumper_socket.png index 93efb0b60b0e2afb8d46ac02f52476e457bdaac8..b1f0e5da9a81f6b2f2bb72e81028db19bd8d46fd 100644 GIT binary patch delta 406 zcmV;H0crl!1H}W7Ie&LaL_t(oh3%L>Q-d%VhkxW8I`$*z){)IoN2eU4X7ZzT$~o3d z9d*-;Q?AgL+(-5vkw39t4Etaqp_MFMI-q6|b>4xL1T1}2^N!TJ2 zXYzygvbjm9?+!yD^gz*KE;8z~m%$95qLm4uF92>^x7>^z#8>P4CxAz~&P)^#(!8UE!v&Eb0+V9^Q=$vT;oMu<3(NLMP1`XUDI1GTiCRlDR=!3o&U6P zHr7*O5>XjF1u0dUgPGd7?5QkM9>$FPkK~jv$D>5)q$Ik)K}15cYdy5%9TrdY1*voF3Z}xJZeq5=DBx$|8$c)&oKtbC@h2M5eTBL z38JnUjp(#(QAid6m;smrh&{P%03-lXO8C}1S#>5M*|{b+^M52~Bh{p{N>oU;0I)o< zoQ)MF{HuIM7sKCi$zjJr}aXS^_g}YH|9~5 z{rBG0>O7U%UeYM|>Voyj6oIuV30r5Pgny_y=9@(A-C$P>T^Y~GvB}h)t?Ybf5|YJQ z3w;4_XY5q6qf;pW30C=Q?cXq+9f*+}y&wC2>B~g=n<6Ws!R7G*= zapc=7+1BW`jd{MJXrnc{HBn7+2!nG?HvEz6njq?$ARg+PAnKZNhywTnD`kL}b@_?s P00000NkvXXu0mjfzEsaQ diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/gate_bracket.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/gate_bracket.png index ad12094c494784d74e89bfb1850a7451a9b87a7b..220c60d76d519e04e7729f3732c3051ec3e483bd 100644 GIT binary patch delta 352 zcmV-m0iXVu1CRrdIe$V)L_t(oh3%QK4Z<)GML$*sV1x`n!3Hpa2S}4u!Ul{$-J;2K=JSTn*%7PCVys9sLOcp+7{LC>9mqU zRXX0$25PeY8GzF%h6(gR!!jwS7|B zJ%Oq6y_|{x>RIKK4V1%v7Eq3Y@>(;a=O9t8@A|VrId*hTYbwVN5;oAr=SXIeSB_4C y>QngFlTQpSB}Z%hCTi6Bvw>PGD7Df61@Ho^&`La+Qm%;r0000;OB!4zK|+CL4mp{dH!SHN1q7@U!z}-^{Q;)^#0HkVt|uCD8oxJgfmMCcrXOTZpn9 z9>@Xg0c@h9eX5dMuQ^Al^|rnS&;OB!4zK|+CL4mp{dH!SHN1q7@U!z}-^{Q;)^#0HkVt|uCD8oxJgfmMCcrXOTZpn9 z9>@Xg0c@h9eX5dMuQ^Al^|rnS&-J;2K=JSTn*%7PCVys9sLOcp+7{LC>9mqU zRXX0$25PeY8GzF%h6(gR!!jwS7|B zJ%Oq6y_|{x>RIKK4V1%v7Eq3Y@>(;a=O9t8@A|VrId*hTYbwVN5;oAr=SXIeSB_4C y>QngFlTQpSB}Z%hCTi6Bvw>PGD7Df61@Ho^&`La+Qm%;r0000cgeNlED>3P4oug`Poi}pERd4!{>N-@a{0H>l#yFJ_$=N+5ukFHIos& z(QRZ&xCC$yU<+W?lS={M4Zvp*XQe#Yyhm9Qu1JgvKJ_GL;(whBbMYX~ibj+rVFciH zU^x@dL7b(cMx*ihHT=5GzF+S6t^OE?laYt{$Y)a!anap4T&(Pr^h8hp(6gM1r(K}D z@M(vA-)1fLvLsBMDTuQ#0C|scf}F0cU~8egODG+pLrS`)7Hh(%R=T90j{t6^UD7MP z<=Q{C%B4&Yf?Lxo;H-4F8=3#q@uulxJr~I;euvy-LardPP3~d zHQkzNO_E*DqKS%RPgWQwqEwHYfdpj^?Yi~f@Ll6YT^i#>odVzos3(C5uk|^J00000 LNkvXXu0mjfWy{S7 delta 414 zcmV;P0b%~o1I+`FIe&jiL_t(oh3%LzZi6rshW|tvGIWT_FMQ4u{N$Jh`gI{nFMFIl7HO2BRLa0N&5RFDmV)P zd|X-1#7hvxt8$Ho{qs9+b8W=S}qw|XZv-k7q1L;e8#O4BVW z`%%H!9Kh?9Mc;!cKFAG~giixDPPNY2sFE;MrXY&H03>exjwCd9g}M@2B;3lKb;yC{ z)KdG+M5S~_hks81=E{&&OK&y9$jdC%mClmdx0_B(NjlT?@7q`k&eW#t(rfr_o^8CS zZM>*$F8cQ*I9t-rf2wq~N>7^4nj+<`gD7sSf=vm3N`lLlLTyP%xRR?IMQfti6}8dT zZS!13(S$a-XQGm%t0=Ueq?j5EljT4&PVq5CceqeDB-J0zh_Grd`q+UR8mt%+_u_PQ-@nouiB zHzi>Y7ZEY7Zu3n^fs%Ydl6^IJCz6fL!81|Xk3(sn4_HL@uIHrqD}$u3lgM( UcmD4#mH+?%07*qoM6N<$f;ZmCy#N3J delta 423 zcmV;Y0a*Uo1J(nOIe&;rL_t(oh3%LjZ-YP-$Nz0A$W#+1Dv_1UZ>Q%rHQldJjhWbe zkLsz;Rg?Lx4vC!TB~uHI<(h+Bj{{0_9FW{k!Ev-d9^88mW_g}t3d|>A=|p?LiJHcV znr1Sh3*8{2!~+ljSOZvEa`^?207(5P&eVftWnz@9B)PznTz?&@B>hv0GD<=K&jZWV zvG=3+yLd*!@%fdU-Dan^2Y#D3<8Z2FHy?R43&Mq1)u}Xi58!rKFPs2;O8d)7KPnd1 zmvyyE?)U8Ai!QEvU1 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/bumper_skirt.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/bumper_skirt.png index c6370645733ef0039c4f9aa16ca9dce5fa7580d0..999e36429a744889e054e899d8ade0da9b64c0e1 100644 GIT binary patch delta 408 zcmV;J0cZZu1JDDILVuxd!!Q&@Z>xd9N+yMYg@GgU2FF%7I5;?NI{!yLp>VJ>8Z0af zESROhvP|BbsBvO9kz6;Ce59yKoirz}mhVeuWm#eh%qL+PMK3@U_042NZ)^jS(-i=< zEdsd|0QLZK!o<-Wtk+S==|YPo`tzFPT6#~IC~8q%y_YM?*?-s&CU(^vy&Ioj&7a%s z=i`0};B6dERYpl|o%uvmXCb zpwM@!q+9vhHGh{}NKVbsW8dG1ZJuwUsBfaEZ=$GgqNs125o)k9vtDxgIM63C_HX;1 zc=olUZcJ43@jOtfFJG!zIhXm)zg}{>*3a0Nl2kkZ*hx;`T?chmG(Z(?SgYHrXrLauqEN^OoWLq0Ef7Ke;oDL9r{{mVdcrSQJrb;8>4s6BspChE%Z@OG?RR! z{EKyNrddUpsDFG9I(vPCez4Ngo&M{}r9LF5_TBT)ccf)rXp(4Xl4xiK{d1T$^dmPkNi;M`G&D&xH1iMz@CzV(e-ZuJ(wc_=0000&-_q1g>d%hlbB?_%%diGEtFUyUBj7}Bvl`K> zu0}2S7Qi)tJ%HUrE(w4LK+J?nn?IKOsFr+3Vuj$GoQ3mGCVx~?ifYMy0Kv?1CXP&~ zuvnx1^88B9Zr=CHUH+<{m*HgOuvz$Q7Wk_XZDmhd@+B;V0~0E)HncW;y5TgbR-IE* z5~j$+g!-VpY-%FvyG36JJyNuoiiG;?q&LH-XjO#JR{*z-TW$sp;;Zrf6TlN)Cq)z* zELufN{s!Q_+JDA`@`hMy$(xOdE1~FBdy_wpj>?to(9*2zlkEE0^hl51vq$HT(AR?mKHJ_9eXvy~^ zIrc1?NJ+LUUJl_;Q^TRNlth`MI9?gIjpJ_s_v&*-n8;2N)sdWj0JzoH2opgYOUbFZ*(YJ*?wIfTG0!z# z)HPnzHAj^v$!Rh5KLNNfPFV}I1#>vx0C*ux9PEOJ3Vx_=zGx}bmRL>lwRfe1qAH5Z z4oAMNl5LD`)0o#)6m2v{cSlr{9KztdBkTXjb&VHwjUN|vjTd#zI79*b0ppp0rGHgk Q<^TWy07*qoM6N<$g8NI%X#fBK diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/gate_bracket.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/gate_bracket.png index c3f54bdc0abc947d19864c3815834151030dd3fe..9e78e2f9114ad69f5ae2f1985e5b37488f0144c4 100644 GIT binary patch delta 351 zcmV-l0igbt1CIlcIe$S(L_t(oh3%QK4Z<)GML#G5AbEidK*0pSCK<#{DAF?mqaaVf z2q|fhDCvTbEMx+XW9!b2QGOH2vV2eecPHCfbX|uWw9JAsC(z>7Y&QT_6JRmb3aMIi zpa5_LuuG2isRMx89GP>JS}*HQ0M5p`ud#Kc_!s>x0aQa13x6TisXusYw)OAnv=UO) zI^Ny|YP0?kfzvC74fIOGGAOSY*;jpx9c@RnEioJKDbrkC7ErNR>@{ z0#oG&Ih6u5$XF>CD2M$lpd1Aiv}QriL84OM^+$tp?C6-*RP`SuT%h-mBbh@%IXVcc xPvKurJ}ESn9BuWRs8#dN25QZq)XD=Cz!PAOOQeZ@EqDL`002ovPDHLkV1oH5nYaJ| delta 358 zcmV-s0h#`f1C|4jIe$n=L_t(oh3%Qm4T3-rg&&542M;D(JX(Sk7>|}=3EsJCUq}Vm z0Ty6_6<|m<1d03W%r0wq2_fNU=gYpCVS%J=Tg0G66qGT6rqAns17JA;mZ6#~FPq_k z6u=R{HaOa+3bFN?bCg=0^%a16FzyP##Z&yV*slTXR2P2jqkqrq-b-`M@-h+ex*9nR zP8C^R8s+GVmCzxE478$QQOYVt^i}U;Mhk;$ddWZ=$?;&4fz}>?NOIH%sFiCWt^XY~ z%S-lRvW@W1DY|}=3EsJCUq}Vm z0Ty6_6<|m<1d03W%r0wq2_fNU=gYpCVS%J=Tg0G66qGT6rqAns17JA;mZ6#~FPq_k z6u=R{HaOa+3bFN?bCg=0^%a16FzyP##Z&yV*slTXR2P2jqkqrq-b-`M@-h+ex*9nR zP8C^R8s+GVmCzxE478$QQOYVt^i}U;Mhk;$ddWZ=$?;&4fz}>?NOIH%sFiCWt^XY~ z%S-lRvW@W1DY7Y&QT_6JRmb3aMIi zpa5_LuuG2isRMx89GP>JS}*HQ0M5p`ud#Kc_!s>x0aQa13x6TisXusYw)OAnv=UO) zI^Ny|YP0?kfzvC74fIOGGAOSY*;jpx9c@RnEioJKDbrkC7ErNR>@{ z0#oG&Ih6u5$XF>CD2M$lpd1Aiv}QriL84OM^+$tp?C6-*RP`SuT%h-mBbh@%IXVcc xPvKurJ}ESn9BuWRs8#dN25QZq)XD=Cz!PAOOQeZ@EqDL`002ovPDHLkV1oH5nYaJ| diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateBracketMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateBracketMeshAuthoring.cs new file mode 100644 index 000000000..30e81674c --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateBracketMeshAuthoring.cs @@ -0,0 +1,29 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Bumper; +using VisualPinball.Engine.VPT.Rubber; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Bumper Base Mesh")] + public class BumperBaseMeshAuthoring : ItemMeshAuthoring + { + protected override string MeshId => BumperMeshGenerator.Base; + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireMeshAuthoring.cs new file mode 100644 index 000000000..76d8429c4 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireMeshAuthoring.cs @@ -0,0 +1,28 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Gate; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Gate Bracket Mesh")] + public class GateBracketMeshAuthoring : ItemMeshAuthoring + { + protected override string MeshId => GateMeshGenerator.Bracket; + } +} From c0b3daea3a640275505b19c2397fc90df4ed5927 Mon Sep 17 00:00:00 2001 From: freezy Date: Sat, 10 Oct 2020 22:48:00 +0200 Subject: [PATCH 063/124] gate: Add mesh authoring components. --- VisualPinball.Engine/VPT/Gate/GateMeshGenerator.cs | 3 --- .../VPT/Gate/GateBracketMeshAuthoring.cs | 9 ++++----- .../VPT/Gate/GateBracketMeshAuthoring.cs.meta | 11 +++++++++++ .../VPT/Gate/GateWireMeshAuthoring.cs | 6 +++--- .../VPT/Gate/GateWireMeshAuthoring.cs.meta | 11 +++++++++++ 5 files changed, 29 insertions(+), 11 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateBracketMeshAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireMeshAuthoring.cs.meta diff --git a/VisualPinball.Engine/VPT/Gate/GateMeshGenerator.cs b/VisualPinball.Engine/VPT/Gate/GateMeshGenerator.cs index 1b1e2b596..34e8818e7 100644 --- a/VisualPinball.Engine/VPT/Gate/GateMeshGenerator.cs +++ b/VisualPinball.Engine/VPT/Gate/GateMeshGenerator.cs @@ -24,11 +24,9 @@ namespace VisualPinball.Engine.VPT.Gate { public class GateMeshGenerator : MeshGenerator { - public const string Wire = "Wire"; public const string Bracket = "Bracket"; - private readonly GateData _data; protected override Vertex3D Position => new Vertex3D(_data.Center.X, _data.Center.Y, _data.Height); @@ -67,7 +65,6 @@ public RenderObject GetRenderObject(Table.Table table, string id, Origin origin, public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin, bool asRightHanded) { - var (preMatrix, _) = GetPreMatrix(table, origin, asRightHanded); var postMatrix = GetPostMatrix(table, origin); return new RenderObjectGroup(_data.Name, "Gates", postMatrix, GetRenderObject(table, Wire, origin, asRightHanded), diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateBracketMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateBracketMeshAuthoring.cs index 30e81674c..76d8429c4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateBracketMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateBracketMeshAuthoring.cs @@ -15,15 +15,14 @@ // along with this program. If not, see . using UnityEngine; -using VisualPinball.Engine.VPT.Bumper; -using VisualPinball.Engine.VPT.Rubber; +using VisualPinball.Engine.VPT.Gate; namespace VisualPinball.Unity { [ExecuteInEditMode] - [AddComponentMenu("Visual Pinball/Mesh/Bumper Base Mesh")] - public class BumperBaseMeshAuthoring : ItemMeshAuthoring + [AddComponentMenu("Visual Pinball/Mesh/Gate Bracket Mesh")] + public class GateBracketMeshAuthoring : ItemMeshAuthoring { - protected override string MeshId => BumperMeshGenerator.Base; + protected override string MeshId => GateMeshGenerator.Bracket; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateBracketMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateBracketMeshAuthoring.cs.meta new file mode 100644 index 000000000..1154d9aa2 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateBracketMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e5ac89d955ca6b64081d63b54fbc897d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: f3392be5e92d7984d87dadb6020d974a, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireMeshAuthoring.cs index 76d8429c4..13b824b58 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireMeshAuthoring.cs @@ -20,9 +20,9 @@ namespace VisualPinball.Unity { [ExecuteInEditMode] - [AddComponentMenu("Visual Pinball/Mesh/Gate Bracket Mesh")] - public class GateBracketMeshAuthoring : ItemMeshAuthoring + [AddComponentMenu("Visual Pinball/Mesh/Gate Wire Mesh")] + public class GateWireMeshAuthoring : ItemMeshAuthoring { - protected override string MeshId => GateMeshGenerator.Bracket; + protected override string MeshId => GateMeshGenerator.Wire; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireMeshAuthoring.cs.meta new file mode 100644 index 000000000..920b2e928 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dc4472b271d55204884a3c599b1ae8a8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: cdb4c35e9bc1b2a4592c2e1bb07fa147, type: 3} + userData: + assetBundleName: + assetBundleVariant: From 973f0449484909bc7f535f3b70ede2a1d24795c1 Mon Sep 17 00:00:00 2001 From: freezy Date: Sat, 10 Oct 2020 22:48:19 +0200 Subject: [PATCH 064/124] rubber: Properly generate mesh. --- VisualPinball.Engine/VPT/Rubber/Rubber.cs | 4 ++-- .../VPT/Rubber/RubberMeshGenerator.cs | 13 ++++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/VisualPinball.Engine/VPT/Rubber/Rubber.cs b/VisualPinball.Engine/VPT/Rubber/Rubber.cs index ee2a789f0..474477201 100644 --- a/VisualPinball.Engine/VPT/Rubber/Rubber.cs +++ b/VisualPinball.Engine/VPT/Rubber/Rubber.cs @@ -63,11 +63,11 @@ public static Rubber GetDefault(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => _meshGenerator.GetPostMatrix(table, origin); public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { - throw new System.NotImplementedException(); + return _meshGenerator.GetRenderObject(table, origin, asRightHanded); } public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) diff --git a/VisualPinball.Engine/VPT/Rubber/RubberMeshGenerator.cs b/VisualPinball.Engine/VPT/Rubber/RubberMeshGenerator.cs index e1e0f1b71..680b318ac 100644 --- a/VisualPinball.Engine/VPT/Rubber/RubberMeshGenerator.cs +++ b/VisualPinball.Engine/VPT/Rubber/RubberMeshGenerator.cs @@ -37,6 +37,18 @@ public RubberMeshGenerator(RubberData data) _data = data; } + public RenderObject GetRenderObject(Table.Table table, Origin origin, bool asRightHanded) + { + var mesh = GetMesh(table); + var (preVertexMatrix, preNormalsMatrix) = GetPreMatrix(table, origin, asRightHanded); + return new RenderObject( + _data.Name, + mesh.Transform(preVertexMatrix, preNormalsMatrix), + new PbrMaterial(table.GetMaterial(_data.Material), table.GetTexture(_data.Image)), + _data.IsVisible + ); + } + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin, bool asRightHanded = true) { var mesh = GetMesh(table); @@ -230,6 +242,5 @@ protected override float BaseHeight(Table.Table table) { return 0f; } - } } From dbc4186f42a126cfd63864d0ffcf7a45b42ccc80 Mon Sep 17 00:00:00 2001 From: freezy Date: Sun, 11 Oct 2020 00:07:05 +0200 Subject: [PATCH 065/124] gate: Move main authoring back up to main object. --- .../EditorTool.meta | 8 --- .../VisualPinball.Unity.Editor/Utils/Icons.cs | 4 ++ .../Import/VpxConverter.cs | 2 +- .../Collision/StaticCollisionSystem.cs | 4 +- .../Bumper/BumperSkirtAnimationAuthoring.cs | 1 - .../VPT/Flipper/FlipperAuthoring.cs | 5 +- .../VPT/Gate/GateAuthoring.cs | 25 +++++++++- .../VPT/Gate/GateColliderAuthoring.cs | 26 ++++++++++ ....cs.meta => GateColliderAuthoring.cs.meta} | 4 +- .../VPT/Gate/GateDisplacementSystem.cs | 5 +- .../VPT/Gate/GateExtensions.cs | 49 ++++++++++++++++--- .../VPT/Gate/GateMovementSystem.cs | 2 +- .../VPT/Gate/GateStaticData.cs | 1 + .../VPT/Gate/GateVelocitySystem.cs | 6 ++- ...oring.cs => GateWireAnimationAuthoring.cs} | 29 ++++------- .../Gate/GateWireAnimationAuthoring.cs.meta | 11 +++++ .../VPT/HitTarget/HitTargetAuthoring.cs | 3 ++ .../VPT/ItemMainAuthoring.cs | 3 +- .../VPT/Kicker/KickerAuthoring.cs | 3 ++ .../VPT/Light/LightAuthoring.cs | 7 +-- .../VPT/Playfield/PlayfieldAuthoring.cs | 2 + .../VPT/Plunger/PlungerAuthoring.cs | 3 ++ .../VPT/Primitive/PrimitiveAuthoring.cs | 8 ++- .../VPT/Ramp/RampAuthoring.cs | 5 +- .../VPT/Rubber/RubberAuthoring.cs | 3 ++ .../VPT/Spinner/SpinnerAuthoring.cs | 3 ++ .../VPT/Spinner/SpinnerPlateAuthoring.cs | 4 ++ .../VPT/Table/TableAuthoring.cs | 9 ++-- .../VPT/Trigger/TriggerAuthoring.cs | 3 ++ 29 files changed, 177 insertions(+), 61 deletions(-) delete mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/EditorTool.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateColliderAuthoring.cs rename VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/{GateWireAuthoring.cs.meta => GateColliderAuthoring.cs.meta} (61%) rename VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/{GateWireAuthoring.cs => GateWireAnimationAuthoring.cs} (56%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAnimationAuthoring.cs.meta diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/EditorTool.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/EditorTool.meta deleted file mode 100644 index a95ea7baf..000000000 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/EditorTool.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 54e53840a863e3d4eb0d2a4ec749e73b -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs index 031a04dad..88be60f32 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs @@ -141,6 +141,10 @@ public static void OnScriptsReloaded() DisableGizmo(); DisableGizmo(); DisableGizmo(); + DisableGizmo(); + DisableGizmo(); + DisableGizmo(); + DisableGizmo(); DisableGizmo(); DisableGizmo(); DisableGizmo(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index c8120ad3d..d566b312f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -187,7 +187,7 @@ private static IItemMainAuthoring SetupGameObjects(IRenderable item, GameObject switch (item) { case Bumper bumper: mainAuthoring = bumper.SetupGameObject(obj, parentAuthoring); break; case Flipper flipper: flipper.SetupGameObject(obj); break; - case Gate gate: gate.SetupGameObject(obj); break; + case Gate gate: mainAuthoring = gate.SetupGameObject(obj, parentAuthoring); break; case HitTarget hitTarget: hitTarget.SetupGameObject(obj); break; case Kicker kicker: kicker.SetupGameObject(obj); break; case Engine.VPT.Light.Light lt: lt.SetupGameObject(obj); break; diff --git a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/StaticCollisionSystem.cs b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/StaticCollisionSystem.cs index 54760f2bf..eb0a7e268 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/StaticCollisionSystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/StaticCollisionSystem.cs @@ -116,13 +116,13 @@ protected override void OnUpdate() break; case ColliderType.Gate: - var gateMovementData = GetComponent(coll.Entity); var gateStaticData = GetComponent(coll.Entity); + var gateMovementData = GetComponent(gateStaticData.WireEntity); GateCollider.Collide( ref ballData, ref collEvent, ref gateMovementData, ref events, in coll, in gateStaticData ); - SetComponent(coll.Entity, gateMovementData); + SetComponent(gateStaticData.WireEntity, gateMovementData); break; case ColliderType.LineSlingShot: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs index 210c6f91c..9b632e3ac 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs @@ -16,7 +16,6 @@ using Unity.Entities; using Unity.Mathematics; -using Unity.Transforms; using UnityEngine; using VisualPinball.Engine.VPT.Bumper; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs index a77c4fdd6..bc50f710c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs @@ -20,6 +20,7 @@ // ReSharper disable MemberCanBePrivate.Global #endregion +using System; using Unity.Entities; using Unity.Mathematics; using UnityEngine; @@ -34,10 +35,10 @@ namespace VisualPinball.Unity public class FlipperAuthoring : ItemMainAuthoring, IHittableAuthoring, ISwitchAuthoring, ICoilAuthoring, IConvertGameObjectToEntity { - //protected override string[] Children => new []{ FlipperMeshGenerator.BaseName, FlipperMeshGenerator.RubberName }; - protected override Flipper InstantiateItem(FlipperData data) => new Flipper(data); + protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + public IHittable Hittable => Item; public ISwitchable Switchable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs index ececbc08c..5ca980a08 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs @@ -20,7 +20,11 @@ // ReSharper disable MemberCanBePrivate.Global #endregion +using System; +using Unity.Entities; +using Unity.Mathematics; using UnityEngine; +using VisualPinball.Engine.Common; using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT.Gate; @@ -29,13 +33,32 @@ namespace VisualPinball.Unity [ExecuteAlways] [AddComponentMenu("Visual Pinball/Game Item/Gate")] public class GateAuthoring : ItemMainAuthoring, - IHittableAuthoring, ISwitchAuthoring + IHittableAuthoring, ISwitchAuthoring, IConvertGameObjectToEntity { protected override Gate InstantiateItem(GateData data) => new Gate(data); + protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + public IHittable Hittable => Item; public ISwitchable Switchable => Item; + public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) + { + Convert(entity, dstManager); + + dstManager.AddComponentData(entity, new GateStaticData { + AngleMin = Data.AngleMin, + AngleMax = Data.AngleMax, + Height = Data.Height, + Damping = math.pow(Data.Damping, (float)PhysicsConstants.PhysFactor), + GravityFactor = Data.GravityFactor, + TwoWay = Data.TwoWay + }); + + // register + transform.GetComponentInParent().RegisterGate(Item, entity, gameObject); + } + private void OnDestroy() { if (!Application.isPlaying) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateColliderAuthoring.cs new file mode 100644 index 000000000..08ffededf --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateColliderAuthoring.cs @@ -0,0 +1,26 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Gate; + +namespace VisualPinball.Unity +{ + [AddComponentMenu("Visual Pinball/Collision/Gate Collider")] + public class GateColliderAuthoring : ItemColliderAuthoring + { + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateColliderAuthoring.cs.meta similarity index 61% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAuthoring.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateColliderAuthoring.cs.meta index fec6452a0..a250a4bd3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateColliderAuthoring.cs.meta @@ -1,11 +1,11 @@ fileFormatVersion: 2 -guid: 7924a3f312d4b3c4188efef312d64bee +guid: 4c3661524092a5e4e96c5eb92caaa50d MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: 745c85c0a7ac66341a306f36125ecb3b, type: 3} userData: assetBundleName: assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateDisplacementSystem.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateDisplacementSystem.cs index efe867bc3..78c31498d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateDisplacementSystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateDisplacementSystem.cs @@ -52,10 +52,12 @@ protected override void OnUpdate() Entities .WithName("GateDisplacementJob") - .ForEach((Entity entity, ref GateMovementData movementData, in GateStaticData data) => { + .ForEach((Entity entity, in GateStaticData data) => { marker.Begin(); + var movementData = GetComponent(data.WireEntity); + if (data.TwoWay) { if (math.abs(movementData.Angle) > data.AngleMax) { if (movementData.Angle < 0.0) { @@ -117,6 +119,7 @@ protected override void OnUpdate() } movementData.Angle += movementData.AngleSpeed * dTime; + SetComponent(data.WireEntity, movementData); marker.End(); }).Run(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs index 533be42eb..bfa960c36 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs @@ -14,23 +14,58 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using Unity.Entities; using UnityEngine; -using VisualPinball.Engine.Game; +using VisualPinball.Engine.VPT; +using VisualPinball.Engine.VPT.Gate; namespace VisualPinball.Unity { internal static class GateExtensions { - public static GateAuthoring SetupGameObject(this Engine.VPT.Gate.Gate gate, GameObject obj) + public static IItemMainAuthoring SetupGameObject(this Gate gate, GameObject obj, IItemMainAuthoring parentAuthoring) { - var ic = obj.AddComponent().SetItem(gate); - obj.AddComponent(); + var mainAuthoring = obj.AddComponent().SetItem(gate); + + switch (gate.SubComponent) { + case ItemSubComponent.None: + obj.AddComponent(); + CreateChild(obj, GateMeshGenerator.Bracket); + var wire = CreateChild(obj, GateMeshGenerator.Wire); + wire.AddComponent(); + break; - var wire = obj.transform.Find("Wire").gameObject; - wire.AddComponent().SetItem(gate, "Wire"); + case ItemSubComponent.Collider: { + obj.AddComponent(); + if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { + hittableAuthoring.RemoveHittableComponent(); + } + break; + } - return ic as GateAuthoring; + case ItemSubComponent.Mesh: { + // todo + if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { + meshAuthoring.RemoveMeshComponent(); + } + break; + } + + default: + throw new ArgumentOutOfRangeException(); + } + obj.AddComponent(); + return mainAuthoring; + } + + private static GameObject CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring + { + var subObj = new GameObject(name); + subObj.transform.SetParent(obj.transform, false); + subObj.AddComponent(); + //subObj.layer = ChildObjectsLayer; + return subObj; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateMovementSystem.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateMovementSystem.cs index 7a4ea3329..702496545 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateMovementSystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateMovementSystem.cs @@ -29,7 +29,7 @@ internal class GateMovementSystem : SystemBase protected override void OnUpdate() { var marker = PerfMarker; - Entities.WithName("GateMovementJob").ForEach((ref Rotation rot, in GateStaticData data, in GateMovementData movementData) => { + Entities.WithName("GateMovementJob").ForEach((ref Rotation rot, in GateMovementData movementData) => { marker.Begin(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateStaticData.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateStaticData.cs index cb39904f5..c807e099f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateStaticData.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateStaticData.cs @@ -26,5 +26,6 @@ internal struct GateStaticData : IComponentData public float GravityFactor; public float Damping; public bool TwoWay; + public Entity WireEntity; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateVelocitySystem.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateVelocitySystem.cs index d518a7e6e..c67b7b308 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateVelocitySystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateVelocitySystem.cs @@ -33,10 +33,12 @@ protected override void OnUpdate() var marker = PerfMarker; Entities .WithName("GateVelocityJob") - .ForEach((ref GateMovementData movementData, in GateStaticData data) => { + .ForEach((in GateStaticData data) => { marker.Begin(); + var movementData = GetComponent(data.WireEntity); + if (!movementData.IsOpen) { if (math.abs(movementData.Angle) < data.AngleMin + 0.01f && math.abs(movementData.AngleSpeed) < 0.01f) { // stop a bit earlier to prevent a nearly endless animation (especially for slow balls) @@ -49,6 +51,8 @@ protected override void OnUpdate() } } + SetComponent(data.WireEntity, movementData); + marker.End(); }).Run(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAnimationAuthoring.cs similarity index 56% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAuthoring.cs rename to VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAnimationAuthoring.cs index 4bca51d5f..ffeb00c3f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAnimationAuthoring.cs @@ -15,26 +15,22 @@ // along with this program. If not, see . using Unity.Entities; -using Unity.Mathematics; -using VisualPinball.Engine.Common; using VisualPinball.Engine.VPT.Gate; namespace VisualPinball.Unity { - public class GateWireAuthoring : ItemMainAuthoring, IConvertGameObjectToEntity + public class GateWireAnimationAuthoring : ItemMovementAuthoring, IConvertGameObjectToEntity { public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { - Convert(entity, dstManager); + var gateEntity = Entity; - dstManager.AddComponentData(entity, new GateStaticData { - AngleMin = Data.AngleMin, - AngleMax = Data.AngleMax, - Height = Data.Height, - Damping = math.pow(Data.Damping, (float)PhysicsConstants.PhysFactor), - GravityFactor = Data.GravityFactor, - TwoWay = Data.TwoWay - }); + // update parent + var gateStaticData = dstManager.GetComponentData(gateEntity); + gateStaticData.WireEntity = entity; + dstManager.SetComponentData(gateEntity, gateStaticData); + + // add movement data dstManager.AddComponentData(entity, new GateMovementData { Angle = Data.AngleMin, AngleSpeed = 0, @@ -42,14 +38,7 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio IsOpen = false }); - // register - var gate = transform.parent.gameObject.GetComponent().Item; - transform.GetComponentInParent().RegisterGate(gate, entity, gameObject); - } - - protected override Gate InstantiateItem(GateData data) - { - return transform.parent.gameObject.GetComponent().Item; + LinkToParentEntity(entity, dstManager); } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAnimationAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAnimationAuthoring.cs.meta new file mode 100644 index 000000000..d42c09631 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAnimationAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a3246946b24b0f940b90770737255e03 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7ed17b152a617404297b1b6602052295, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs index 5766dddec..c06a86115 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs @@ -20,6 +20,7 @@ // ReSharper disable MemberCanBePrivate.Global #endregion +using System; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.Game; @@ -34,6 +35,8 @@ public class HitTargetAuthoring : ItemMainAuthoring, { protected override HitTarget InstantiateItem(HitTargetData data) => new HitTarget(data); + protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + public IHittable Hittable => Item; public ISwitchable Switchable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs index 2f7b1e702..59db0752f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs @@ -86,9 +86,8 @@ public void RebuildMeshIfDirty() /// /// Authoring type of the child class. - /// todo make this abstract /// - protected virtual Type MeshAuthoringType { get; } = null; + protected abstract Type MeshAuthoringType { get; } /// /// Instantiates a new item based on the item data. diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs index 4da901d97..df3eba7a5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs @@ -20,6 +20,7 @@ // ReSharper disable MemberCanBePrivate.Global #endregion +using System; using Unity.Collections; using Unity.Entities; using Unity.Mathematics; @@ -36,6 +37,8 @@ public class KickerAuthoring : ItemMainAuthoring, { protected override Kicker InstantiateItem(KickerData data) => new Kicker(data); + protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + public IHittable Hittable => Item; public ISwitchable Switchable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs index 6d7b4bff3..4a0905eb7 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs @@ -20,6 +20,7 @@ // ReSharper disable MemberCanBePrivate.Global #endregion +using System; using UnityEngine; using VisualPinball.Engine.VPT.Light; using Light = VisualPinball.Engine.VPT.Light.Light; @@ -27,14 +28,14 @@ namespace VisualPinball.Unity { [AddComponentMenu("Visual Pinball/Game Item/Light")] - public class LightAuthoring : ItemMainAuthoring + public class LightAuthoring : ItemMainAuthoring { - // protected override string[] Children => new[] { "Bulb", "Socket" }; - private UnityEngine.Light _unityLight; protected override Light InstantiateItem(LightData data) => new Light(data); + protected override Type MeshAuthoringType { get; } = null; + protected override void ItemDataChanged() { base.ItemDataChanged(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs index abaa6b13c..87cb6c4f9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs @@ -33,6 +33,8 @@ public class PlayfieldAuthoring : ItemMainAuthoring, protected override Table InstantiateItem(TableData data) => throw new InvalidOperationException("Table is not instantiated via authoring component."); + protected override Type MeshAuthoringType { get; } = null; + public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { var table = gameObject.GetComponentInParent().Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs index 068ef6a55..b9cb99c92 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.Game; @@ -32,6 +33,8 @@ public class PlungerAuthoring : ItemMainAuthoring, protected override Plunger InstantiateItem(PlungerData data) => new Plunger(data); + protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + public IHittable Hittable => Item; private void OnDestroy() diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs index 6b07ac5cc..deb4caac4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs @@ -20,6 +20,7 @@ // ReSharper disable MemberCanBePrivate.Global #endregion +using System; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.Game; @@ -30,6 +31,11 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Game Item/Primitive")] public class PrimitiveAuthoring : ItemMainAuthoring, IHittableAuthoring, IConvertGameObjectToEntity { + + protected override Primitive InstantiateItem(PrimitiveData data) => new Primitive(data); + + protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { Convert(entity, dstManager); @@ -43,8 +49,6 @@ public void RemoveHittableComponent() { } - protected override Primitive InstantiateItem(PrimitiveData data) => new Primitive(data); - public IHittable Hittable => Item; public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs index d7790f3a6..4ddd827b3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs @@ -20,6 +20,7 @@ // ReSharper disable MemberCanBePrivate.Global #endregion +using System; using System.Collections.Generic; using Unity.Entities; using UnityEngine; @@ -33,10 +34,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Game Item/Ramp")] public class RampAuthoring : ItemMainAuthoring, IDragPointsEditable, IConvertGameObjectToEntity, IHittableAuthoring { - //protected override string[] Children => new[] { "Floor", "RightWall", "LeftWall", "Wire1", "Wire2", "Wire3", "Wire4" }; - protected override Ramp InstantiateItem(RampData data) => new Ramp(data); + protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + public IHittable Hittable => Item; public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs index f00e8fd82..72a32692b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs @@ -20,6 +20,7 @@ // ReSharper disable MemberCanBePrivate.Global #endregion +using System; using System.Collections.Generic; using Unity.Entities; using UnityEngine; @@ -36,6 +37,8 @@ public class RubberAuthoring : ItemMainAuthoring, { protected override Rubber InstantiateItem(RubberData data) => new Rubber(data); + protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + public IHittable Hittable => Item; public IRenderable Renderable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs index c98378b58..7651ff637 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs @@ -20,6 +20,7 @@ // ReSharper disable MemberCanBePrivate.Global #endregion +using System; using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT.Spinner; @@ -33,6 +34,8 @@ public class SpinnerAuthoring : ItemMainAuthoring, { protected override Spinner InstantiateItem(SpinnerData data) => new Spinner(data); + protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + public IHittable Hittable => Item; public ISwitchable Switchable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAuthoring.cs index 6b422573e..7e0c73f27 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAuthoring.cs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using Unity.Entities; using Unity.Mathematics; using VisualPinball.Engine.Common; @@ -23,6 +24,9 @@ namespace VisualPinball.Unity { internal class SpinnerPlateAuthoring : ItemMainAuthoring, IConvertGameObjectToEntity { + + protected override Type MeshAuthoringType { get; } = null; + public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { Convert(entity, dstManager); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs index 7dd0b53a8..376496380 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs @@ -55,6 +55,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Table")] public class TableAuthoring : ItemMainAuthoring { + protected override Table InstantiateItem(TableData data) => RecreateTable(data); + + protected override Type MeshAuthoringType { get; } = null; + public Table Table => Item; public TableSerializedTextureContainer Textures => _sidecar?.textures; public TableSerializedSoundContainer Sounds => _sidecar?.sounds; @@ -90,11 +94,6 @@ protected override void OnDrawGizmos() // that would just be everything at this level } - protected override Table InstantiateItem(TableData data) - { - return RecreateTable(data); - } - internal TableSidecar GetOrCreateSidecar() { if (_sidecar == null) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs index cd4676dac..96bce7117 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs @@ -20,6 +20,7 @@ // ReSharper disable MemberCanBePrivate.Global #endregion +using System; using System.Collections.Generic; using Unity.Entities; using UnityEngine; @@ -36,6 +37,8 @@ public class TriggerAuthoring : ItemMainAuthoring, { protected override Trigger InstantiateItem(TriggerData data) => new Trigger(data); + protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + public IHittable Hittable => Item; public ISwitchable Switchable => Item; From d948e3e3ca3151f5ab94712aa6c49a5e491ede29 Mon Sep 17 00:00:00 2001 From: freezy Date: Sun, 11 Oct 2020 00:59:25 +0200 Subject: [PATCH 066/124] spinner: Move main authoring back up and split components. --- VisualPinball.Engine/VPT/Spinner/Spinner.cs | 4 +- .../VPT/Spinner/SpinnerMeshGenerator.cs | 26 +++++ .../Icons/small_blue/spinner_bracket.png | Bin 0 -> 334 bytes .../Icons/small_blue/spinner_bracket.png.meta | 106 ++++++++++++++++++ .../Icons/small_blue/spinner_plate.png | Bin 0 -> 365 bytes .../Icons/small_blue/spinner_plate.png.meta | 106 ++++++++++++++++++ .../Icons/small_gray/spinner_bracket.png | Bin 0 -> 353 bytes .../Icons/small_gray/spinner_bracket.png.meta | 106 ++++++++++++++++++ .../Icons/small_gray/spinner_plate.png | Bin 0 -> 366 bytes .../Icons/small_gray/spinner_plate.png.meta | 106 ++++++++++++++++++ .../Icons/small_green/spinner_bracket.png | Bin 0 -> 338 bytes .../small_green/spinner_bracket.png.meta | 106 ++++++++++++++++++ .../Icons/small_green/spinner_plate.png | Bin 0 -> 367 bytes .../Icons/small_green/spinner_plate.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/spinner_bracket.png | Bin 0 -> 338 bytes .../small_orange/spinner_bracket.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/spinner_plate.png | Bin 0 -> 368 bytes .../Icons/small_orange/spinner_plate.png.meta | 106 ++++++++++++++++++ .../VisualPinball.Unity.Editor/Utils/Icons.cs | 4 + .../Import/VpxConverter.cs | 2 +- .../Collision/StaticCollisionSystem.cs | 4 +- .../VPT/Gate/GateDisplacementSystem.cs | 1 + .../VPT/Spinner/SpinnerAuthoring.cs | 21 +++- .../Spinner/SpinnerBracketMeshAuthoring.cs | 29 +++++ ...ta => SpinnerBracketMeshAuthoring.cs.meta} | 4 +- .../VPT/Spinner/SpinnerColliderAuthoring.cs | 26 +++++ .../Spinner/SpinnerColliderAuthoring.cs.meta | 11 ++ .../VPT/Spinner/SpinnerDisplacementSystem.cs | 6 +- .../VPT/Spinner/SpinnerExtensions.cs | 49 ++++++-- .../VPT/Spinner/SpinnerMovementSystem.cs | 2 +- ...g.cs => SpinnerPlateAnimationAuthoring.cs} | 26 ++--- .../SpinnerPlateAnimationAuthoring.cs.meta | 11 ++ .../VPT/Spinner/SpinnerPlateMeshAuthoring.cs | 29 +++++ .../Spinner/SpinnerPlateMeshAuthoring.cs.meta | 11 ++ .../VPT/Spinner/SpinnerStaticData.cs | 1 + .../VPT/Spinner/SpinnerVelocitySystem.cs | 6 +- 36 files changed, 1084 insertions(+), 37 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/spinner_bracket.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/spinner_bracket.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/spinner_plate.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/spinner_plate.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/spinner_bracket.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/spinner_bracket.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/spinner_plate.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/spinner_plate.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/spinner_bracket.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/spinner_bracket.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/spinner_plate.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/spinner_plate.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/spinner_bracket.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/spinner_bracket.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/spinner_plate.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/spinner_plate.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerBracketMeshAuthoring.cs rename VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/{SpinnerPlateAuthoring.cs.meta => SpinnerBracketMeshAuthoring.cs.meta} (61%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerColliderAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerColliderAuthoring.cs.meta rename VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/{SpinnerPlateAuthoring.cs => SpinnerPlateAnimationAuthoring.cs} (55%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAnimationAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateMeshAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateMeshAuthoring.cs.meta diff --git a/VisualPinball.Engine/VPT/Spinner/Spinner.cs b/VisualPinball.Engine/VPT/Spinner/Spinner.cs index c6e26a8da..ed3f9bd94 100644 --- a/VisualPinball.Engine/VPT/Spinner/Spinner.cs +++ b/VisualPinball.Engine/VPT/Spinner/Spinner.cs @@ -65,11 +65,11 @@ public void Init(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => _meshGenerator.GetPostMatrix(table, origin); public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { - throw new System.NotImplementedException(); + return _meshGenerator.GetRenderObject(table, id, origin, asRightHanded); } public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) diff --git a/VisualPinball.Engine/VPT/Spinner/SpinnerMeshGenerator.cs b/VisualPinball.Engine/VPT/Spinner/SpinnerMeshGenerator.cs index e8dcca305..403464c9d 100644 --- a/VisualPinball.Engine/VPT/Spinner/SpinnerMeshGenerator.cs +++ b/VisualPinball.Engine/VPT/Spinner/SpinnerMeshGenerator.cs @@ -23,6 +23,9 @@ namespace VisualPinball.Engine.VPT.Spinner { public class SpinnerMeshGenerator : MeshGenerator { + public const string Plate = "Plate"; + public const string Bracket = "Bracket"; + private readonly SpinnerData _data; protected override Vertex3D Position => new Vertex3D(_data.Center.X, _data.Center.Y, _data.Height); @@ -34,6 +37,29 @@ public SpinnerMeshGenerator(SpinnerData data) _data = data; } + public RenderObject GetRenderObject(Table.Table table, string id, Origin origin, bool asRightHanded) + { + var (preMatrix, _) = GetPreMatrix(table, origin, asRightHanded); + switch (id) { + case Plate: + return new RenderObject( + id, + SpinnerPlateMesh.Clone().Transform(preMatrix), + new PbrMaterial(table.GetMaterial(_data.Material), table.GetTexture(_data.Image)), + _data.IsVisible + ); + case Bracket: + return new RenderObject( + id, + SpinnerBracketMesh.Clone().Transform(preMatrix), + new PbrMaterial(GetBracketMaterial(), table.GetTexture(_data.Image)), + _data.IsVisible && _data.ShowBracket + ); + default: + throw new ArgumentException("Unknown spinner mesh \"" + id + "\"."); + } + } + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin, bool asRightHanded) { var (preMatrix, _) = GetPreMatrix(table, origin, asRightHanded); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/spinner_bracket.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/spinner_bracket.png new file mode 100644 index 0000000000000000000000000000000000000000..cb67f3f18adcee8a27d45b25a6961cd294845655 GIT binary patch literal 334 zcmeAS@N?(olHy`uVBq!ia0vp^S|H591|*LjJ{b+9I14-?iy0W${Xm$pP}SUmfq{|1 z)5S3)qV?@eTfRdEJZ|=j_eT*k19Y*tHv%_B^w4?PPl4TK?a9VhBT;Yiac(w|7aK&du+r zyWPTf+u@wxl_amN8BS}Gi?Vu)oPGcHcE}1}%jA9FcO?D%uPmYBeNVSZUtlZhyA`$g z&I%24ty8^SMZ(pG*9%*@^vZre8zS|pBU)r_U|z@+>A>5;^?`LM4?dm!kRH3VpBJRw d$c1qa=xgha><1 literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/spinner_bracket.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/spinner_bracket.png.meta new file mode 100644 index 000000000..f331c62c2 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/spinner_bracket.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 36f94afb76b80eb47ae63d3f578c9d5f +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/spinner_plate.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/spinner_plate.png new file mode 100644 index 0000000000000000000000000000000000000000..42812f0b6571e75005bf0fb21447bd5eee0f0d71 GIT binary patch literal 365 zcmV-z0h0cSP)q#n53;*bCf z;L%^lGlk};G>K!rwI^<`cB3O|ve*kzlUG-wK`(s=lUMH(o(zS_;?>ZgQKCR2`to-t zCmUc;RF5ZVf)R~AzK`}sY3lxyW85<^o5*1gY#seO;OFvPv^P^a;ilBAq2UkmZ#Um^dUrt)Feo_f@LT2M>eJ}X~k_WEE9p~TqM8n+9 z@ZL$G?asRm1$q~MuvmSLL(9{8k)QrwhQsa=lI{mzzyq>1*t^z<4>(*ejRfJ8!(3y<9Eh(`UyX z>&olme`k1II`!c6Dz|5Ewy3)A6b#IBnIbLt)NT8r<*TIiwj8@A)Vp}Xu19IEMIhm0 vD<7}aoMOx!^J|O!HPKI-8$n{cfeiWD!iKggyTVI>VaDL;>gTe~DWM4fIn0gr literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/spinner_bracket.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/spinner_bracket.png.meta new file mode 100644 index 000000000..886d30dd4 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/spinner_bracket.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 51ea5a0cec31e8645a9ac7036e2bd082 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/spinner_plate.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/spinner_plate.png new file mode 100644 index 0000000000000000000000000000000000000000..de55087dccfe75c6f2ed205a225b50bf64ec5522 GIT binary patch literal 366 zcmV-!0g?WRP)CA|)e7;3z#pw>oML zQEost#*B<%V+#sGstHbs#7||T|EAco>?ique_I(;RYeF4gRl%qG%{H}0Y)CU{KYW> zmcZ0s$1{b-s5FsdzHd+5UhT$>Xqv=ch?*?F5)FFmZ!lTD>hWYK(j@-4H>i^+P>U`e zcXF};?uzR1Buy})gHQ8iCrVxSXO3|%z_=%e1F&`U?|}W~yJ#lUsK=yfW8AW4VK+2J zrD<+`9TRVkHQs@FPYyr8+R?wX8%@!ptJa$=FU9qKDO=VIv(~GqG%6~Mic0fbPmz|} zjTD{c?j)Kfv8%-WD;lHHsHikS9Z%cl`@|FMJ8G#v8>CTDX~GZ%PSvV33^BIz?f?J) M07*qoM6N<$f)ZDjV*mgE literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/spinner_plate.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/spinner_plate.png.meta new file mode 100644 index 000000000..ccefdbb9a --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/spinner_plate.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: db880f07350afef4da1450a1cb1022bd +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/spinner_bracket.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/spinner_bracket.png new file mode 100644 index 0000000000000000000000000000000000000000..272a7ca092631fd1a3151388095fb4f422f76ce3 GIT binary patch literal 338 zcmV-Y0j>UtP)q`0Az>SDiIsioajvSO5S307*qoM6N<$g3XwT{{R30 literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/spinner_bracket.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/spinner_bracket.png.meta new file mode 100644 index 000000000..bb8e554a0 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/spinner_bracket.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 3b42d400cd06e8d4e98804233aa038a4 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/spinner_plate.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/spinner_plate.png new file mode 100644 index 0000000000000000000000000000000000000000..af214aa21178ddb6af6dd3e829d463078987ae9c GIT binary patch literal 367 zcmV-#0g(QQP)nSpD zyOCnl+@nO3AhVUYKSg6y8WokstK+HYzfT;&yrWk7vq2gamBtTI;0&WYG#Qf}2LJ#7 N002ovPDHLkV1ff^pQiu- literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/spinner_plate.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/spinner_plate.png.meta new file mode 100644 index 000000000..8925188b3 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/spinner_plate.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 1bda21d8e6afb9949b02a1a1bdae2472 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/spinner_bracket.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/spinner_bracket.png new file mode 100644 index 0000000000000000000000000000000000000000..750cc3040731bc977d4c7f1a1e1a41123698734c GIT binary patch literal 338 zcmeAS@N?(olHy`uVBq!ia0vp^S|H591|*LjJ{b+9I14-?iy0W${Xm$pP}SUmfq{|5 z)5S3)qV?^}y}XAE1l;TcxV)B_Xi7G6`ka<{Gm%N-jxkemfRkE6%alx=r9R>!tNzUC zR6RFQ_wMVQ$bITR-{q*T-j*xK{8~dNS;)61teW9ALrh(uIzt`<-$SdqO3%Kc$pXJ) znG3DIvkPA|(bwyK6=4v?>$2GH7w5d_h`G;>R_9HetkK|C@_oOsCuc%f$Sq;>k7AQA zzH(V}+Quqn+6?9uNuNSZ%*^x*Ro!bk}Ure0Y3BpQ@iJO@GtTz=vb z015EmuH%(LV^o^JGT)mcZqH_;BO0Z-6QX4ne-rh3>pPTL{4(OnP(*3IyEkZ%DA0(m ze(z*u58M^i<4GECL?`dtrI{#A-G8)96o@9rT+w+zrKrhGKC{1O&_zKH4C$$ zF)B@a>zkNZTh@35o1VB1QE60E8Wol1e?3Kd zZZ}d4ntPCFl;*Y)_orx#N~5CEcy&A-+V2xbFz=|9{%nv&MWyjW6!-)xuQR{3QaSJd O0000(); DisableGizmo(); DisableGizmo(); + DisableGizmo(); + DisableGizmo(); + DisableGizmo(); + DisableGizmo(); DisableGizmo(); DisableGizmo(); DisableGizmo(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index d566b312f..ef4cf13e2 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -195,7 +195,7 @@ private static IItemMainAuthoring SetupGameObjects(IRenderable item, GameObject case Primitive primitive: primitive.SetupGameObject(obj); break; case Ramp ramp: ramp.SetupGameObject(obj); break; case Rubber rubber: mainAuthoring = rubber.SetupGameObject(obj, parentAuthoring); break; - case Spinner spinner: spinner.SetupGameObject(obj); break; + case Spinner spinner: mainAuthoring = spinner.SetupGameObject(obj, parentAuthoring); break; case Surface surface: mainAuthoring = surface.SetupGameObject(obj, parentAuthoring); break; case Table table: table.SetupGameObject(obj, parentAuthoring); break; case Trigger trigger: trigger.SetupGameObject(obj); break; diff --git a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/StaticCollisionSystem.cs b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/StaticCollisionSystem.cs index eb0a7e268..b48d36478 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/StaticCollisionSystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/StaticCollisionSystem.cs @@ -142,13 +142,13 @@ protected override void OnUpdate() break; case ColliderType.Spinner: - var spinnerMovementData = GetComponent(coll.Entity); var spinnerStaticData = GetComponent(coll.Entity); + var spinnerMovementData = GetComponent(spinnerStaticData.PlateEntity); SpinnerCollider.Collide( in ballData, ref collEvent, ref spinnerMovementData, in spinnerStaticData ); - SetComponent(coll.Entity, spinnerMovementData); + SetComponent(spinnerStaticData.PlateEntity, spinnerMovementData); break; case ColliderType.TriggerCircle: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateDisplacementSystem.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateDisplacementSystem.cs index 78c31498d..d913a1235 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateDisplacementSystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateDisplacementSystem.cs @@ -120,6 +120,7 @@ protected override void OnUpdate() movementData.Angle += movementData.AngleSpeed * dTime; SetComponent(data.WireEntity, movementData); + marker.End(); }).Run(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs index 7651ff637..98a20e0b9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs @@ -21,7 +21,10 @@ #endregion using System; +using Unity.Entities; +using Unity.Mathematics; using UnityEngine; +using VisualPinball.Engine.Common; using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT.Spinner; @@ -30,7 +33,7 @@ namespace VisualPinball.Unity [ExecuteAlways] [AddComponentMenu("Visual Pinball/Game Item/Spinner")] public class SpinnerAuthoring : ItemMainAuthoring, - IHittableAuthoring, ISwitchAuthoring + IHittableAuthoring, ISwitchAuthoring, IConvertGameObjectToEntity { protected override Spinner InstantiateItem(SpinnerData data) => new Spinner(data); @@ -39,6 +42,22 @@ public class SpinnerAuthoring : ItemMainAuthoring, public IHittable Hittable => Item; public ISwitchable Switchable => Item; + public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) + { + Convert(entity, dstManager); + + dstManager.AddComponentData(entity, new SpinnerStaticData { + AngleMax = math.radians(Data.AngleMax), + AngleMin = math.radians(Data.AngleMin), + Damping = math.pow(Data.Damping, (float)PhysicsConstants.PhysFactor), + Elasticity = Data.Elasticity, + Height = Data.Height + }); + + // register + transform.GetComponentInParent().RegisterSpinner(Item, entity, gameObject); + } + private void OnDestroy() { if (!Application.isPlaying) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerBracketMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerBracketMeshAuthoring.cs new file mode 100644 index 000000000..92399e98e --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerBracketMeshAuthoring.cs @@ -0,0 +1,29 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Gate; +using VisualPinball.Engine.VPT.Spinner; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Spinner Bracket Mesh")] + public class SpinnerBracketMeshAuthoring : ItemMeshAuthoring + { + protected override string MeshId => SpinnerMeshGenerator.Bracket; + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerBracketMeshAuthoring.cs.meta similarity index 61% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAuthoring.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerBracketMeshAuthoring.cs.meta index c00e1f5c7..fb67bd28a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerBracketMeshAuthoring.cs.meta @@ -1,11 +1,11 @@ fileFormatVersion: 2 -guid: 8d44396402ed43d42b0a9a46741ff735 +guid: 44e92bd564840cc4882370b66da69368 MonoImporter: externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: 36f94afb76b80eb47ae63d3f578c9d5f, type: 3} userData: assetBundleName: assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerColliderAuthoring.cs new file mode 100644 index 000000000..16d6035f7 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerColliderAuthoring.cs @@ -0,0 +1,26 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Spinner; + +namespace VisualPinball.Unity +{ + [AddComponentMenu("Visual Pinball/Collision/Spinner Collider")] + public class SpinnerColliderAuthoring : ItemColliderAuthoring + { + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerColliderAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerColliderAuthoring.cs.meta new file mode 100644 index 000000000..76d34dfd0 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerColliderAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8553b3859894f50408c92febb78bedbe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: a70efc3c7801045438e9e2bc198aaa77, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerDisplacementSystem.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerDisplacementSystem.cs index f9f5bd97e..78b0c7f2f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerDisplacementSystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerDisplacementSystem.cs @@ -55,10 +55,12 @@ protected override void OnUpdate() Entities .WithName("SpinnerDisplacementJob") - .ForEach((Entity entity, ref SpinnerMovementData movementData, in SpinnerStaticData data) => { + .ForEach((Entity entity, in SpinnerStaticData data) => { marker.Begin(); + var movementData = GetComponent(data.PlateEntity); + // those are already converted to radian during authoring. var angleMin = data.AngleMin; var angleMax = data.AngleMax; @@ -119,6 +121,8 @@ protected override void OnUpdate() } } + SetComponent(data.PlateEntity, movementData); + marker.End(); }).Run(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs index e55bdd227..71f248de9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs @@ -14,23 +14,58 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using Unity.Entities; using UnityEngine; -using VisualPinball.Engine.Game; +using VisualPinball.Engine.VPT; +using VisualPinball.Engine.VPT.Spinner; namespace VisualPinball.Unity { internal static class SpinnerExtensions { - public static SpinnerAuthoring SetupGameObject(this Engine.VPT.Spinner.Spinner spinner, GameObject obj) + public static IItemMainAuthoring SetupGameObject(this Spinner spinner, GameObject obj, IItemMainAuthoring parentAuthoring) { - var ic = obj.AddComponent().SetItem(spinner); - obj.AddComponent(); + var mainAuthoring = obj.AddComponent().SetItem(spinner); + + switch (spinner.SubComponent) { + case ItemSubComponent.None: + obj.AddComponent(); + CreateChild(obj, SpinnerMeshGenerator.Bracket); + var wire = CreateChild(obj, SpinnerMeshGenerator.Plate); + wire.AddComponent(); + break; - var wire = obj.transform.Find("Plate").gameObject; - wire.AddComponent().SetItem(spinner, "Plate"); + case ItemSubComponent.Collider: { + obj.AddComponent(); + if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { + hittableAuthoring.RemoveHittableComponent(); + } + break; + } - return ic as SpinnerAuthoring; + case ItemSubComponent.Mesh: { + // todo + if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { + meshAuthoring.RemoveMeshComponent(); + } + break; + } + + default: + throw new ArgumentOutOfRangeException(); + } + obj.AddComponent(); + return mainAuthoring; + } + + private static GameObject CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring + { + var subObj = new GameObject(name); + subObj.transform.SetParent(obj.transform, false); + subObj.AddComponent(); + //subObj.layer = ChildObjectsLayer; + return subObj; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerMovementSystem.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerMovementSystem.cs index 0f4044e56..fb2069ca1 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerMovementSystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerMovementSystem.cs @@ -29,7 +29,7 @@ internal class SpinnerMovementSystem : SystemBase protected override void OnUpdate() { var marker = PerfMarker; - Entities.WithName("SpinnerMovementJob").ForEach((ref Rotation rot, in SpinnerStaticData data, in SpinnerMovementData movementData) => { + Entities.WithName("SpinnerMovementJob").ForEach((ref Rotation rot, in SpinnerMovementData movementData) => { marker.Begin(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAnimationAuthoring.cs similarity index 55% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAuthoring.cs rename to VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAnimationAuthoring.cs index 7e0c73f27..901a7eca6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAnimationAuthoring.cs @@ -14,41 +14,29 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -using System; using Unity.Entities; using Unity.Mathematics; -using VisualPinball.Engine.Common; using VisualPinball.Engine.VPT.Spinner; namespace VisualPinball.Unity { - internal class SpinnerPlateAuthoring : ItemMainAuthoring, IConvertGameObjectToEntity + public class SpinnerPlateAnimationAuthoring : ItemMovementAuthoring, IConvertGameObjectToEntity { - - protected override Type MeshAuthoringType { get; } = null; - public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { - Convert(entity, dstManager); + var spinnerEntity = Entity; - dstManager.AddComponentData(entity, new SpinnerStaticData { - AngleMax = math.radians(Data.AngleMax), - AngleMin = math.radians(Data.AngleMin), - Damping = math.pow(Data.Damping, (float)PhysicsConstants.PhysFactor), - Elasticity = Data.Elasticity, - Height = Data.Height - }); + // update parent + var spinnerStaticData = dstManager.GetComponentData(spinnerEntity); + spinnerStaticData.PlateEntity = entity; + dstManager.SetComponentData(spinnerEntity, spinnerStaticData); dstManager.AddComponentData(entity, new SpinnerMovementData { Angle = math.radians(math.clamp(0.0f, Data.AngleMin, Data.AngleMax)), AngleSpeed = 0f }); - // register - var spinner = transform.parent.gameObject.GetComponent().Item; - transform.GetComponentInParent().RegisterSpinner(spinner, entity, gameObject); + LinkToParentEntity(entity, dstManager); } - - protected override Spinner InstantiateItem(SpinnerData data) => transform.parent.gameObject.GetComponent().Item; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAnimationAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAnimationAuthoring.cs.meta new file mode 100644 index 000000000..b3bce0adc --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAnimationAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 26ac83bc80303f644a2cbae02033861d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 1bda21d8e6afb9949b02a1a1bdae2472, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateMeshAuthoring.cs new file mode 100644 index 000000000..606bd5a3c --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateMeshAuthoring.cs @@ -0,0 +1,29 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Gate; +using VisualPinball.Engine.VPT.Spinner; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Spinner Plate Mesh")] + public class SpinnerPlateMeshAuthoring : ItemMeshAuthoring + { + protected override string MeshId => SpinnerMeshGenerator.Plate; + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateMeshAuthoring.cs.meta new file mode 100644 index 000000000..ca8039df1 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f0c8bf6190760ae4da2f35183c5fde3a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 62ac3e09665f8054aa6656fc679ed7f5, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerStaticData.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerStaticData.cs index 4f21738d6..f676bc5ee 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerStaticData.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerStaticData.cs @@ -25,5 +25,6 @@ internal struct SpinnerStaticData : IComponentData public float Height; public float Damping; public float Elasticity; + public Entity PlateEntity; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerVelocitySystem.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerVelocitySystem.cs index c0b78157e..36c81652a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerVelocitySystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerVelocitySystem.cs @@ -31,14 +31,18 @@ protected override void OnUpdate() var marker = PerfMarker; Entities .WithName("SpinnerVelocityJob") - .ForEach((ref SpinnerMovementData movementData, in SpinnerStaticData data) => { + .ForEach((in SpinnerStaticData data) => { marker.Begin(); + var movementData = GetComponent(data.PlateEntity); + // Center of gravity towards bottom of object, makes it stop vertical movementData.AngleSpeed -= math.sin(movementData.Angle) * (float)(0.0025 * PhysicsConstants.PhysFactor); movementData.AngleSpeed *= data.Damping; + SetComponent(data.PlateEntity, movementData); + marker.End(); }).Run(); From 5ee2f98782d7a2f90bb6e9b9fa68185bfe6381ec Mon Sep 17 00:00:00 2001 From: freezy Date: Sun, 11 Oct 2020 23:22:28 +0200 Subject: [PATCH 067/124] ramp: Split components. --- VisualPinball.Engine/VPT/Mesh.cs | 16 ++- VisualPinball.Engine/VPT/Ramp/Ramp.cs | 8 +- .../VPT/Ramp/RampMeshGenerator.cs | 64 ++++++++++- .../DragPoint/DragPointsItemInspector.cs | 12 +- .../Resources/Icons/small_blue/ramp_floor.png | Bin 0 -> 545 bytes .../Icons/small_blue/ramp_floor.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_blue/ramp_wall.png | Bin 0 -> 536 bytes .../Icons/small_blue/ramp_wall.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_blue/ramp_wires.png | Bin 0 -> 779 bytes .../Icons/small_blue/ramp_wires.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_gray/ramp_floor.png | Bin 0 -> 550 bytes .../Icons/small_gray/ramp_floor.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_gray/ramp_wall.png | Bin 0 -> 544 bytes .../Icons/small_gray/ramp_wall.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_gray/ramp_wires.png | Bin 0 -> 793 bytes .../Icons/small_gray/ramp_wires.png.meta | 106 ++++++++++++++++++ .../Icons/small_green/ramp_floor.png | Bin 0 -> 548 bytes .../Icons/small_green/ramp_floor.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_green/ramp_wall.png | Bin 0 -> 543 bytes .../Icons/small_green/ramp_wall.png.meta | 106 ++++++++++++++++++ .../Icons/small_green/ramp_wires.png | Bin 0 -> 784 bytes .../Icons/small_green/ramp_wires.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/ramp_floor.png | Bin 0 -> 550 bytes .../Icons/small_orange/ramp_floor.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/ramp_wall.png | Bin 0 -> 543 bytes .../Icons/small_orange/ramp_wall.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/ramp_wires.png | Bin 0 -> 787 bytes .../Icons/small_orange/ramp_wires.png.meta | 106 ++++++++++++++++++ .../VisualPinball.Unity.Editor/Utils/Icons.cs | 4 + .../VPT/ItemInspector.cs | 4 +- .../VPT/Ramp/RampInspector.cs | 2 +- .../Import/VpxConverter.cs | 2 +- .../VPT/Ramp/RampAuthoring.cs | 31 +++++ .../VPT/Ramp/RampColliderAuthoring.cs | 27 +++++ .../VPT/Ramp/RampColliderAuthoring.cs.meta | 11 ++ .../VPT/Ramp/RampExtensions.cs | 50 ++++++++- .../VPT/Ramp/RampFloorMeshAuthoring.cs | 29 +++++ .../VPT/Ramp/RampFloorMeshAuthoring.cs.meta | 11 ++ .../VPT/Ramp/RampWallMeshAuthoring.cs | 29 +++++ .../VPT/Ramp/RampWallMeshAuthoring.cs.meta | 11 ++ .../VPT/Ramp/RampWireMeshAuthoring.cs | 29 +++++ .../VPT/Ramp/RampWireMeshAuthoring.cs.meta | 11 ++ 42 files changed, 1603 insertions(+), 20 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/ramp_floor.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/ramp_floor.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/ramp_wall.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/ramp_wall.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/ramp_wires.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/ramp_wires.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/ramp_floor.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/ramp_floor.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/ramp_wall.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/ramp_wall.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/ramp_wires.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/ramp_wires.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/ramp_floor.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/ramp_floor.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/ramp_wall.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/ramp_wall.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/ramp_wires.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/ramp_wires.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/ramp_floor.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/ramp_floor.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/ramp_wall.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/ramp_wall.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/ramp_wires.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/ramp_wires.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampColliderAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampColliderAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampFloorMeshAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampFloorMeshAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWallMeshAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWallMeshAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWireMeshAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWireMeshAuthoring.cs.meta diff --git a/VisualPinball.Engine/VPT/Mesh.cs b/VisualPinball.Engine/VPT/Mesh.cs index 7e119cb04..3c6294488 100644 --- a/VisualPinball.Engine/VPT/Mesh.cs +++ b/VisualPinball.Engine/VPT/Mesh.cs @@ -101,6 +101,21 @@ public Mesh MakeTranslation(float x, float y, float z) return this; } + public Mesh Merge(Mesh mesh) + { + if (Vertices == null) { + Vertices = mesh.Vertices; + Indices = mesh.Indices; + + } else { + var numVert = Vertices.Length; + Vertices = Vertices.Concat(mesh.Vertices).ToArray(); + Indices = Indices.Concat(mesh.Indices.Select(i => i + numVert).ToArray()).ToArray(); + } + + return this; + } + public Mesh Clone(string name = null) { var mesh = new Mesh { @@ -440,7 +455,6 @@ public Vertex3DNoTex2 ToVertex3DNoTex2() } } #endregion - } } diff --git a/VisualPinball.Engine/VPT/Ramp/Ramp.cs b/VisualPinball.Engine/VPT/Ramp/Ramp.cs index 9f29b88ed..e9e954337 100644 --- a/VisualPinball.Engine/VPT/Ramp/Ramp.cs +++ b/VisualPinball.Engine/VPT/Ramp/Ramp.cs @@ -28,6 +28,12 @@ public class Ramp : Item, IRenderable, IHittable public HitObject[] GetHitShapes() => _hits; + public bool IsHabitrail => Data.RampType == RampType.RampType4Wire + || Data.RampType == RampType.RampType1Wire + || Data.RampType == RampType.RampType2Wire + || Data.RampType == RampType.RampType3WireLeft + || Data.RampType == RampType.RampType3WireRight; + private readonly RampMeshGenerator _meshGenerator; private readonly RampHitGenerator _hitGenerator; private HitObject[] _hits; @@ -67,7 +73,7 @@ public void Init(Table.Table table) public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { - throw new System.NotImplementedException(); + return _meshGenerator.GetRenderObject(table, id, origin, asRightHanded); } public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) diff --git a/VisualPinball.Engine/VPT/Ramp/RampMeshGenerator.cs b/VisualPinball.Engine/VPT/Ramp/RampMeshGenerator.cs index 1cb6e31a1..7723bc4c4 100644 --- a/VisualPinball.Engine/VPT/Ramp/RampMeshGenerator.cs +++ b/VisualPinball.Engine/VPT/Ramp/RampMeshGenerator.cs @@ -29,6 +29,10 @@ namespace VisualPinball.Engine.VPT.Ramp { public class RampMeshGenerator { + public const string Wall = "Wall"; + public const string Floor = "Floor"; + public const string Wires = "Wires"; + private readonly RampData _data; public RampMeshGenerator(RampData data) @@ -36,6 +40,51 @@ public RampMeshGenerator(RampData data) _data = data; } + public RenderObject GetRenderObject(Table.Table table, string id, Origin origin, bool asRightHanded) + { + var mesh = new Mesh(); + if (id == Wires) { + var meshes = GenerateWireMeshes(table); + + for (var i = 1; i <= 4; i++) { + var name = $"Wire{i}"; + if (meshes.ContainsKey(name)) { + mesh.Merge(meshes[name]); + } + } + + } else { + var rv = GetRampVertex(table, -1, true); + switch (id) { + case Floor: + mesh = GenerateFlatFloorMesh(table, rv); + break; + + case Wall: + if (_data.RightWallHeightVisible > 0.0) { + mesh = mesh.Merge(GenerateFlatRightWall(table, rv)); + } + + if (_data.LeftWallHeightVisible > 0.0) { + mesh = mesh.Merge(GenerateFlatLeftWall(table, rv)); + } + break; + } + + if (mesh.Vertices == null) { + mesh.Vertices = new Vertex3DNoTex2[0]; + mesh.Indices = new int[0]; + } + } + + return new RenderObject( + id, + asRightHanded ? mesh.Transform(Matrix3D.RightHanded) : mesh, + new PbrMaterial(table.GetMaterial(_data.Material), table.GetTexture(_data.Image)), + _data.IsVisible + ); + } + public RenderObjectGroup GetRenderObjects(Table.Table table, bool asRightHanded = true) { var meshes = GenerateMeshes(table); @@ -69,13 +118,18 @@ private RenderObject GetRenderObject(Table.Table table, IReadOnlyDictionary GenerateMeshes(Table.Table table) { - if (!IsHabitrail()) { - return GenerateFlatMesh(table); - } + return !IsHabitrail() + ? GenerateFlatMesh(table) + : GenerateWireMeshes(table); + } + + private Dictionary GenerateWireMeshes(Table.Table table) + { var meshes = new Dictionary(); - var (wireMeshA, wireMeshB) = GenerateWireMeshes(table); + var (wireMeshA, wireMeshB) = GenerateBaseWires(table); switch (_data.RampType) { case RampType.RampType1Wire: { wireMeshA.Name = "Wire1"; @@ -323,7 +377,7 @@ private Mesh GenerateFlatRightWall(Table.Table table, RampVertex rv) return mesh; } - private Tuple GenerateWireMeshes(Table.Table table) + private Tuple GenerateBaseWires(Table.Table table) { int accuracy; if (table.GetDetailLevel() < 5) { diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/DragPointsItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/DragPointsItemInspector.cs index e34cfdda6..db9e7ca09 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/DragPointsItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/DragPointsItemInspector.cs @@ -138,8 +138,8 @@ public void FlipDragPoints(FlipAxis flipAxis) public void RemapControlPoints() { var rebuilt = DragPointsHandler.RemapControlPoints(); - if (rebuilt && target is IItemMeshAuthoring meshAuthoring) { - meshAuthoring.MeshDirty = true; + if (rebuilt && target is IItemMainAuthoring meshAuthoring) { + meshAuthoring.SetMeshDirty(); } } @@ -174,8 +174,8 @@ public void PrepareUndo(string message) // Set MeshDirty to true there so it'll trigger again after Undo var recordObjs = new List(); - if (target is IItemMeshAuthoring meshAuthoring) { - meshAuthoring.MeshDirty = true; + if (target is IItemMainAuthoring meshAuthoring) { + meshAuthoring.SetMeshDirty(); recordObjs.Add(this); } recordObjs.Add(target); @@ -251,8 +251,8 @@ private void OnDragPointPositionChange(Vector3 newPos) private void OnUndoRedoPerformed() { RemapControlPoints(); - if (target is IItemMeshAuthoring meshAuthoring) { - meshAuthoring.MeshDirty = true; + if (target is IItemMainAuthoring meshAuthoring) { + meshAuthoring.SetMeshDirty(); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/ramp_floor.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/ramp_floor.png new file mode 100644 index 0000000000000000000000000000000000000000..66ea54a3e3ad32ebbe98b9a405eabfbbbee00da6 GIT binary patch literal 545 zcmV++0^a?JP)O|4 z+Kd3q_;`}5kV$Ft1mFcgmrv~hEYu*|+cBNy@Q#3e0Am3Cv#)6Rsj9g>(MUy=HeCiB zUKmPM-J$M^vM3{ll!V58qt1%5AY)$EkQ}R8c||>>^R3KzZUx9io&1Z9mqDVm9eRK(6+Jq>QoV?u8X5WM;g3P^dp>>N=3Y29Dy*pK%y!|6Lbz0EW jX+cw`1x=mX00r;^r?voC{ewze00000NkvXXu0mjfd7bQP literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/ramp_floor.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/ramp_floor.png.meta new file mode 100644 index 000000000..039940af5 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/ramp_floor.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: eb4d247fdf4201544bff6b3910bbdcb8 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/ramp_wall.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/ramp_wall.png new file mode 100644 index 0000000000000000000000000000000000000000..850fc77d61954f0a57778330e107975af2849887 GIT binary patch literal 536 zcmV+z0_XjSP)~if zfQ*l4nT1RuEuI1F0o?LWIe1cW< zLNCME6=hMVQm?vQ07MwGqAZBuVeONus)JWlA&PFksG5TheTyhv`KIY1LNBRZYwaAg zhbYaQsGkVEL+x5y0QA5|XP^e6$mBdV_Hy0ihb6#3HgW=LA<732vjn7veFCs)Hnak@ z6omkfe4Q0naQ9yaBT$|@djnBUY;s)`3Ak$O*bCG`l$QS7=cb9N-t2yqHK7WwM5YZor5S^p!6O!n1?D+2yp8f zP{wCrbl=Y^QFaVDXnY>NsH3VXQ6!+XC_1UW@OiC#SF|5R6pbW*TM>~KG@SRfK5t`* zq61oAN6GrnDMZo9+2)QG`zb`xNTS?@jxCB2D9ds)8In5L@<*=gETFElfV$2C>N=MJ a3g8zJy!Yi*QZ4oX0000jw91aKk4^oWHNX}2m`MccjMg=A3 zR{$OXyv>Cj#r5R;C4e=6*TK?~%Hoq{kCTIv^D}{b-m&~0z>Labo7(53t|#XSz?TRl z%M*aTWv^$$qWuS&es4PTUUencAg(9p*>%^EWp?#~%3=+@ zR8_*(z8nY?U-lHY*iF^BvXd#%X;5#AhR|q~Ds+d(8(z->759C#{L~PSI|+?r zXNpt~-gjySO+bDV$SNLFR==+ocS9%JnUYCrUJQ~gGYyhP>+j0|vWoW@BwLh{$&^Th z2eITHdJ#w0q$G#BQx3J0{hw6O1Z3zwP51c2n!a`@gq0%-YK1h!S7`N=exsAApb5z1 zN#&>75E5E_B1sn0Z&|*QRx%|Zml=?^9Z9p*4ka<%f<$Oh17uamQ!{7dE@ViWcT^VY zW$y@@2^njjt@tuDiB>#DK?j5k%a68iqe-OX;^ym*sZ2FvLblpx5|mqLq^4OR!}ggP zL^x?yIgqGNPvrc%R@@PW7|NGrgtTabk3vVru%;d5{X;rO5n~8se%gBT*fpjWMkSNQgSbM<|G?h%nuOf zghb{`$>Lm)=;8Ws@ErvbJ>H&XlGPX!k|hgNpcs}XrqLh);3t`&_EHV*mc#%6002ov JPDHLkV1iLCW)A=W literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/ramp_wires.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/ramp_wires.png.meta new file mode 100644 index 000000000..865116af0 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/ramp_wires.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 5120f7d02b422cf40820c94bab47f2ea +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/ramp_floor.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/ramp_floor.png new file mode 100644 index 0000000000000000000000000000000000000000..d05947365f14096a7cdaab04d6335d53fd929a69 GIT binary patch literal 550 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 literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/ramp_wall.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/ramp_wall.png.meta new file mode 100644 index 000000000..cfd34587c --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/ramp_wall.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: ad07443544b620e43b69e91160a9ab3f +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/ramp_wires.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/ramp_wires.png new file mode 100644 index 0000000000000000000000000000000000000000..c7beddc001305c2eb0ba7db42e66aa87cb255901 GIT binary patch literal 784 zcmV+r1MmEaP)+cY}gj zXBGe+0lZIz9mMt4nM(jG0I$8Jd0A9nG<%#J)H*X^$mc!F-vLa@qT0mvIjQTdGfMzp z1CS(70Ct+ap5;aRE$nJ?>03eVx-6=tcF*jfl+_IRGN3~4o|Z+mM*C2^vZ!XEeY3jW zIx_{Z79bx0j2e&>zZldETC zQLP}Cs#?g}msvp-Kix9q27lt0^j`$@f5mU#!qG8mof+}zLy-5)8p-kZC_uL2*O#L# z%9dFR_3?9AREvhb6dLG>U-A^S*md2xl9MUYY0zwoiqL44D)fiP8(L2SW%u1`eyWJa zEr-UTGX*LK?K@V3Mj*d2WF3z&tKT(?yP}hARmsFPF9b=J8GA`1_4m04S;u<_k}SH6 zCQ~F49@vsQ$VD7|lM)~5MmW@#_kR*WBapuPB;CUg8~W0r;8%_ys1{NYU%u62`mIhT zf<_<@C*_|?Lx^wn5hqzlzhn7YI>{7)oF_nD_ax0mIuyrn2NJ$T6_9lykIkH|yO1Jj zK9ofzUiJ>4iIAc8*@-Vjljy`_5HusCUw)*0TTLP+7xzEjjd`jW60*}iqoCA612s(x z>9^0=AVNvANP$Fida}-}8nsOe*|JP(xk`~{d7AN$PX#$Y7824tdICt*(@jW1ohbz} zmSoe=_2REVX>7{`sd`t^Nbfw#Zo2zdAQ8ERE*S3YkRm8UO?gbyLbj&;oRWIEQzuz& zQ9nSO6B3CpC9`uu;t1FKgYO`aIO6ST!dZ0@?kEP)e%Gj;!3@w9q z9-)uWkuhRo3pAqx!LdcxQ5(b1!V(TAV#aZ ziw8AY^#P3e{U{e9lhNuCz%zh0U)lkfC6mR@j%n40cL3}H7y#&=d_>DnRZZ=MS}JO^ zYBON(%uuT87FAc2Md>r7BsA_DRaTS*8St`(Jw$mRV*xuB!^%4yjKoA<0}zG zkm>JH#Arpm+Hvkls}e;5>h7a+0HZoYk>u!bN1J^eq6jkeocEZping9R*07*qoM6N<$g4Yu0xBvhE literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/ramp_floor.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/ramp_floor.png.meta new file mode 100644 index 000000000..c9378fef5 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/ramp_floor.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: c483a745b2fe62d4db28f13f8d56ab48 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/ramp_wall.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/ramp_wall.png new file mode 100644 index 0000000000000000000000000000000000000000..2ea0bd16c13cac05ed1dee142ea421a73e46c5b5 GIT binary patch literal 543 zcmV+)0^t3LP)R9J=Wm_2TTFc^m4Rt(u1iKSc9En72Yq8&T-2F(%J8JZ64 zxj~bYlyZXf2IK%prqfnpaw}pZ$5a? zH1vD`34fkt5Hh8q_X1!C;Eun_04&@f{t<1Q{_qOGCjeUjj~AD20Qh{ZNG}ylLvO(l zuQg5Y-5^fTbwybes??ie7aGh4T~?F@+48hDNm13-D=HC1HD6TC)~CKgl)8M=@^FJV zD&1>t9khWcmpM^CH;DJ8d#wP_fRENdHAE4~cxmj!zR80nz=ddJ1=K*415dL6q`^J| zSY9?X0yPwc0FQj18CP)qUk5EvUOPJtQBG`fSrh>{tLoSY)IgMsD<~61`nIG6S`x)? zxDJ&>u>zWg-iCinN0hDDu&YEd0_C-{??MzU&^|^9 z&WBQ;_pU@y0WI&NWc_C!qNwETa7UYcAEGEElAc1l7DWq`Wx4GQNuFf-BiD8&P}`Y6 hZD#_topFEy_yr?L=@La`Rh<9;002ovPDHLkV1jvZ+ok{j literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/ramp_wall.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/ramp_wall.png.meta new file mode 100644 index 000000000..75135aecd --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/ramp_wall.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 612711610d8c694418898845d046376e +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/ramp_wires.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/ramp_wires.png new file mode 100644 index 0000000000000000000000000000000000000000..522bdabe66dd3f4a4fdf06327c5161e4885b1e4c GIT binary patch literal 787 zcmV+u1MK{XP)$Q zP*7*h0>C|hH>t3LxZYWF319`_rMEOM%IdRbkCTHsYbFf&q-XgDfJsqSo7g@lb-lA@ z3E*o0lH>uvPP5nJylB6LT}>{1EvQ`=Wwq4qnH`j}njxPBRLI@aqO8_vA8J>W)hx7c zR@XagrU2FgsP4}wa|)f~U?di0+6C07>LJ8Q^wSAk`6 z^{gnX735M?3t9UzE2!e9TZY`=PyCYp(}4c3`0ZObI!2u}BR+iy@=LQua{S#3kgfRj znkQZ=1zk(aE-|Wa63^f+Wj~y`+))``m-9<2?jP z7F|Y@DUt|xY{?zuB96XEi4S!n9BRw^KZu|aNZ);u?%{_Ged$o}D@PDi3#o`N-|8{_ zRwoldBanxa@=v89#JBp0lPsj)v3xC^WQst}6Ckg9l4c_vietC~3E!d$$hwfnX3o}K zNRc#ei?R|gdk4@&$WZ(2#FwH;bmB1xni0}3KhnOfCJ~d1@9$rXd8!!_veQ1JpwvPG zHBAfYx6jxhLP@hofkbn9a@MRGwM`4zvP^2ZN|9!Hn(>cM1vx(!64E?+0!Y=x$Gy8Txm5xIpf81C$lA}B*mc}&wnwx<1@l6tvQ zCs}S$KR}!l5{WM*vvWb>2-o|A?;wyk;_Yd|S&bnfNs>SriePDC8VnKuegb$Y^{t?e RQ$7Fy002ovPDHLkV1kgXYpehO literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/ramp_wires.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/ramp_wires.png.meta new file mode 100644 index 000000000..9e48dc2f2 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/ramp_wires.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 24ebcd9b33c055d4386f33f50c9a59a1 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs index d92c8f078..df81ab6fa 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs @@ -154,6 +154,10 @@ public static void OnScriptsReloaded() DisableGizmo(); DisableGizmo(); DisableGizmo(); + DisableGizmo(); + DisableGizmo(); + DisableGizmo(); + DisableGizmo(); DisableGizmo(); DisableGizmo(); DisableGizmo(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs index fda51e694..250ee7d27 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs @@ -254,7 +254,7 @@ protected void SurfaceField(string label, ref string field, bool dirtyMesh = tru } } - protected void DropDownField(string label, ref T field, string[] optionStrings, T[] optionValues, bool dirtyMesh = true) where T : IEquatable + protected void DropDownField(string label, ref T field, string[] optionStrings, T[] optionValues, bool dirtyMesh = true, Action onChanged = null) where T : IEquatable { if (optionStrings == null || optionValues == null || optionStrings.Length != optionValues.Length) { return; @@ -271,7 +271,9 @@ protected void DropDownField(string label, ref T field, string[] optionString selectedIndex = EditorGUILayout.Popup(label, selectedIndex, optionStrings); if (EditorGUI.EndChangeCheck() && selectedIndex >= 0 && selectedIndex < optionValues.Length) { FinishEdit(label, dirtyMesh); + var fieldBefore = field; field = optionValues[selectedIndex]; + onChanged?.Invoke(fieldBefore, field); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs index 72ef4ccf0..871308d21 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs @@ -64,7 +64,7 @@ public override void OnInspectorGUI() OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - DropDownField("Type", ref _ramp.Data.RampType, _rampTypeStrings, _rampTypeValues); + DropDownField("Type", ref _ramp.Data.RampType, _rampTypeStrings, _rampTypeValues, onChanged: _ramp.UpdateMeshComponents); TextureField("Image", ref _ramp.Data.Image); MaterialField("Material", ref _ramp.Data.Material); DropDownField("Image Mode", ref _ramp.Data.ImageAlignment, _rampImageAlignmentStrings, _rampImageAlignmentValues); diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index ef4cf13e2..4879d76a8 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -193,7 +193,7 @@ private static IItemMainAuthoring SetupGameObjects(IRenderable item, GameObject case Engine.VPT.Light.Light lt: lt.SetupGameObject(obj); break; case Plunger plunger: plunger.SetupGameObject(obj); break; case Primitive primitive: primitive.SetupGameObject(obj); break; - case Ramp ramp: ramp.SetupGameObject(obj); break; + case Ramp ramp: mainAuthoring = ramp.SetupGameObject(obj, parentAuthoring); break; case Rubber rubber: mainAuthoring = rubber.SetupGameObject(obj, parentAuthoring); break; case Spinner spinner: mainAuthoring = spinner.SetupGameObject(obj, parentAuthoring); break; case Surface surface: mainAuthoring = surface.SetupGameObject(obj, parentAuthoring); break; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs index 4ddd827b3..7a40cc4e4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs @@ -26,6 +26,7 @@ using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; +using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Ramp; namespace VisualPinball.Unity @@ -59,6 +60,35 @@ private void OnDestroy() } } + public void UpdateMeshComponents(int rampTypeBefore, int rampTypeAfter) + { + var rampFlatBefore = rampTypeBefore == RampType.RampTypeFlat; + var rampFlatAfter = rampTypeAfter == RampType.RampTypeFlat; + if (rampFlatBefore == rampFlatAfter) { + return; + } + + if (rampFlatAfter) { + var flatRampAuthoring = GetComponentInChildren(); + if (flatRampAuthoring != null) { + DestroyImmediate(flatRampAuthoring.gameObject); + } + RampExtensions.CreateChild(gameObject, RampMeshGenerator.Floor); + RampExtensions.CreateChild(gameObject, RampMeshGenerator.Wall); + + } else { + var flatFloorAuthoring = GetComponentInChildren(); + if (flatFloorAuthoring != null) { + DestroyImmediate(flatFloorAuthoring.gameObject); + } + var flatWallAuthoring = GetComponentInChildren(); + if (flatWallAuthoring != null) { + DestroyImmediate(flatWallAuthoring.gameObject); + } + RampExtensions.CreateChild(gameObject, RampMeshGenerator.Wires); + } + } + public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() { @@ -84,6 +114,7 @@ public override void SetEditorPosition(Vector3 pos) //IDragPointsEditable public bool DragPointEditEnabled { get; set; } + public DragPointData[] GetDragPoints() => Data.DragPoints; public void SetDragPoints(DragPointData[] dragPoints) { Data.DragPoints = dragPoints; } public Vector3 GetEditableOffset() => new Vector3(0.0f, 0.0f, Data.HeightBottom); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampColliderAuthoring.cs new file mode 100644 index 000000000..8b050d105 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampColliderAuthoring.cs @@ -0,0 +1,27 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Gate; +using VisualPinball.Engine.VPT.Ramp; + +namespace VisualPinball.Unity +{ + [AddComponentMenu("Visual Pinball/Collision/Ramp Collider")] + public class RampColliderAuthoring : ItemColliderAuthoring + { + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampColliderAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampColliderAuthoring.cs.meta new file mode 100644 index 000000000..97f524bb5 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampColliderAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 942438599f3b95749abf2456a9aea56c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: ece1ef9789dcece4cb775858de387375, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs index d1ddca260..99ad1421f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs @@ -14,19 +14,61 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using Unity.Entities; using UnityEngine; -using VisualPinball.Engine.Game; +using VisualPinball.Engine.VPT; +using VisualPinball.Engine.VPT.Ramp; namespace VisualPinball.Unity { internal static class RampExtensions { - public static RampAuthoring SetupGameObject(this Engine.VPT.Ramp.Ramp ramp, GameObject obj) + public static IItemMainAuthoring SetupGameObject(this Ramp ramp, GameObject obj, IItemMainAuthoring parentAuthoring) { - var ic = obj.AddComponent().SetItem(ramp); + var mainAuthoring = obj.AddComponent().SetItem(ramp); + + switch (ramp.SubComponent) { + case ItemSubComponent.None: + if (ramp.IsHabitrail) { + CreateChild(obj, RampMeshGenerator.Wires); + } else { + CreateChild(obj, RampMeshGenerator.Floor); + CreateChild(obj, RampMeshGenerator.Wall); + } + obj.AddComponent(); + break; + + case ItemSubComponent.Collider: { + obj.AddComponent(); + if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { + hittableAuthoring.RemoveHittableComponent(); + } + break; + } + + case ItemSubComponent.Mesh: { + // todo + if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { + meshAuthoring.RemoveMeshComponent(); + } + break; + } + + default: + throw new ArgumentOutOfRangeException(); + } obj.AddComponent(); - return ic as RampAuthoring; + return mainAuthoring; + } + + public static GameObject CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring + { + var subObj = new GameObject(name); + subObj.transform.SetParent(obj.transform, false); + subObj.AddComponent(); + //subObj.layer = ChildObjectsLayer; + return subObj; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampFloorMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampFloorMeshAuthoring.cs new file mode 100644 index 000000000..9accf50f3 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampFloorMeshAuthoring.cs @@ -0,0 +1,29 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Gate; +using VisualPinball.Engine.VPT.Ramp; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Ramp Floor Mesh")] + public class RampFloorMeshAuthoring : ItemMeshAuthoring + { + protected override string MeshId => RampMeshGenerator.Floor; + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampFloorMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampFloorMeshAuthoring.cs.meta new file mode 100644 index 000000000..7c3e27f2c --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampFloorMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4f415a8bce1d6404e914122b72e420ca +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: eb4d247fdf4201544bff6b3910bbdcb8, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWallMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWallMeshAuthoring.cs new file mode 100644 index 000000000..7db757084 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWallMeshAuthoring.cs @@ -0,0 +1,29 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Gate; +using VisualPinball.Engine.VPT.Ramp; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Ramp Wall Mesh")] + public class RampWallMeshAuthoring : ItemMeshAuthoring + { + protected override string MeshId => RampMeshGenerator.Wall; + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWallMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWallMeshAuthoring.cs.meta new file mode 100644 index 000000000..a658747c1 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWallMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 96191c0bd78913d4da1df786720fbffd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: a982d33318420e54f947962c305d9571, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWireMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWireMeshAuthoring.cs new file mode 100644 index 000000000..69afd9c6f --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWireMeshAuthoring.cs @@ -0,0 +1,29 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Gate; +using VisualPinball.Engine.VPT.Ramp; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Ramp Wire Mesh")] + public class RampWireMeshAuthoring : ItemMeshAuthoring + { + protected override string MeshId => RampMeshGenerator.Wires; + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWireMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWireMeshAuthoring.cs.meta new file mode 100644 index 000000000..94ec13299 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWireMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fb775e2709cbb994e8b981aad06a08c2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 5120f7d02b422cf40820c94bab47f2ea, type: 3} + userData: + assetBundleName: + assetBundleVariant: From 289f68f0a8ddaa45012592730fe5583d80a013ed Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 12 Oct 2020 23:47:25 +0200 Subject: [PATCH 068/124] flipper: Split components. --- VisualPinball.Engine/VPT/Flipper/Flipper.cs | 4 +- .../VPT/Flipper/FlipperMeshGenerator.cs | 54 ++++++++++++++----- .../VisualPinball.Unity.Editor/Utils/Icons.cs | 3 ++ .../Import/VpxConverter.cs | 2 +- .../VPT/Flipper/FlipperBaseMeshAuthoring.cs | 28 ++++++++++ .../Flipper/FlipperBaseMeshAuthoring.cs.meta | 11 ++++ .../VPT/Flipper/FlipperColliderAuthoring.cs | 26 +++++++++ .../Flipper/FlipperColliderAuthoring.cs.meta | 11 ++++ .../VPT/Flipper/FlipperExtensions.cs | 46 ++++++++++++++-- .../VPT/Flipper/FlipperRubberMeshAuthoring.cs | 28 ++++++++++ .../FlipperRubberMeshAuthoring.cs.meta | 11 ++++ 11 files changed, 203 insertions(+), 21 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperBaseMeshAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperBaseMeshAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperColliderAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperColliderAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperRubberMeshAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperRubberMeshAuthoring.cs.meta diff --git a/VisualPinball.Engine/VPT/Flipper/Flipper.cs b/VisualPinball.Engine/VPT/Flipper/Flipper.cs index b597efa35..4d5bd8955 100644 --- a/VisualPinball.Engine/VPT/Flipper/Flipper.cs +++ b/VisualPinball.Engine/VPT/Flipper/Flipper.cs @@ -53,11 +53,11 @@ public void Init(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => _meshGenerator.GetPostMatrix(table, origin); public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { - throw new System.NotImplementedException(); + return _meshGenerator.GetRenderObject(table, id, origin, asRightHanded); } public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) diff --git a/VisualPinball.Engine/VPT/Flipper/FlipperMeshGenerator.cs b/VisualPinball.Engine/VPT/Flipper/FlipperMeshGenerator.cs index 1b78deb00..bc49786b1 100644 --- a/VisualPinball.Engine/VPT/Flipper/FlipperMeshGenerator.cs +++ b/VisualPinball.Engine/VPT/Flipper/FlipperMeshGenerator.cs @@ -26,10 +26,10 @@ namespace VisualPinball.Engine.VPT.Flipper { public class FlipperMeshGenerator : MeshGenerator { - public const string BaseName = "Base"; - public const string RubberName = "Rubber"; + public const string Base = "Base"; + public const string Rubber = "Rubber"; - private static readonly Mesh FlipperBaseMesh = new Mesh(BaseName, FlipperBase.Vertices, FlipperBase.Indices); + private static readonly Mesh FlipperBaseMesh = new Mesh(Base, FlipperBase.Vertices, FlipperBase.Indices); private readonly FlipperData _data; @@ -42,6 +42,32 @@ public FlipperMeshGenerator(FlipperData data) _data = data; } + public RenderObject GetRenderObject(Table.Table table, string id, Origin origin, bool asRightHanded) + { + var meshes = GenerateMeshes(table); + var (preVertexMatrix, preNormalsMatrix) = GetPreMatrix(table, origin, asRightHanded); + switch (id) { + case Base: + return new RenderObject( + id, + meshes[Base].Transform(preVertexMatrix, preNormalsMatrix), + new PbrMaterial(table.GetMaterial(_data.Material), table.GetTexture(_data.Image)), + _data.IsVisible + ); + case Rubber: + if (meshes.ContainsKey(Rubber)) { + return new RenderObject( + id, + meshes[Rubber].Transform(preVertexMatrix, preNormalsMatrix), + new PbrMaterial(table.GetMaterial(_data.RubberMaterial)), + _data.IsVisible + ); + } + break; + } + return null; + } + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin, bool asRightHanded = true) { var meshes = GenerateMeshes(table); @@ -49,19 +75,19 @@ public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin, bool var postMatrix = GetPostMatrix(table, origin); var renderObjects = new List { new RenderObject( - BaseName, - meshes[BaseName].Transform(preVertexMatrix, preNormalsMatrix), + Base, + meshes[Base].Transform(preVertexMatrix, preNormalsMatrix), new PbrMaterial(table.GetMaterial(_data.Material), table.GetTexture(_data.Image)), _data.IsVisible ) }; - if (meshes.ContainsKey(RubberName)) { + if (meshes.ContainsKey(Rubber)) { renderObjects.Add(new RenderObject( - name: RubberName, - mesh: meshes[RubberName].Transform(preVertexMatrix, preNormalsMatrix), - material: new PbrMaterial(table.GetMaterial(_data.RubberMaterial)), - isVisible: _data.IsVisible + Rubber, + meshes[Rubber].Transform(preVertexMatrix, preNormalsMatrix), + new PbrMaterial(table.GetMaterial(_data.RubberMaterial)), + _data.IsVisible )); } @@ -119,7 +145,7 @@ void ApplyFix(Vertex3DNoTex2 vert, Vertex2D center, float midAngle, float radius } // base and tip - var baseMesh = FlipperBaseMesh.Clone(BaseName); + var baseMesh = FlipperBaseMesh.Clone(Base); for (var t = 0; t < 13; t++) { foreach (var v in baseMesh.Vertices) @@ -147,12 +173,12 @@ void ApplyFix(Vertex3DNoTex2 vert, Vertex2D center, float midAngle, float radius } baseMesh.Transform(fullMatrix, null, z => z * _data.Height * table.GetScaleZ() + height); - meshes[BaseName] = baseMesh; + meshes[Base] = baseMesh; // rubber if (_data.RubberThickness > 0.0) { - var rubberMesh = FlipperBaseMesh.Clone(RubberName); + var rubberMesh = FlipperBaseMesh.Clone(Rubber); for (var t = 0; t < 13; t++) { foreach (var v in rubberMesh.Vertices) @@ -181,7 +207,7 @@ void ApplyFix(Vertex3DNoTex2 vert, Vertex2D center, float midAngle, float radius rubberMesh.Transform(fullMatrix, null, z => z * _data.RubberWidth * table.GetScaleZ() + (height + _data.RubberHeight)); - meshes[RubberName] = rubberMesh; + meshes[Rubber] = rubberMesh; } return meshes; diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs index df81ab6fa..919b6842e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs @@ -140,6 +140,9 @@ public static void OnScriptsReloaded() DisableGizmo(); DisableGizmo(); DisableGizmo(); + DisableGizmo(); + DisableGizmo(); + DisableGizmo(); DisableGizmo(); DisableGizmo(); DisableGizmo(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index 4879d76a8..b4cdab06d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -186,7 +186,7 @@ private static IItemMainAuthoring SetupGameObjects(IRenderable item, GameObject IItemMainAuthoring mainAuthoring = null; switch (item) { case Bumper bumper: mainAuthoring = bumper.SetupGameObject(obj, parentAuthoring); break; - case Flipper flipper: flipper.SetupGameObject(obj); break; + case Flipper flipper: mainAuthoring = flipper.SetupGameObject(obj, parentAuthoring); break; case Gate gate: mainAuthoring = gate.SetupGameObject(obj, parentAuthoring); break; case HitTarget hitTarget: hitTarget.SetupGameObject(obj); break; case Kicker kicker: kicker.SetupGameObject(obj); break; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperBaseMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperBaseMeshAuthoring.cs new file mode 100644 index 000000000..0c83da850 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperBaseMeshAuthoring.cs @@ -0,0 +1,28 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Flipper; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Flipper Base Mesh")] + public class FlipperBaseMeshAuthoring : ItemMeshAuthoring + { + protected override string MeshId => FlipperMeshGenerator.Base; + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperBaseMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperBaseMeshAuthoring.cs.meta new file mode 100644 index 000000000..16edd731f --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperBaseMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 89e3c1c147bb7a049b0510709f1ad9f2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 6714381f547802a468a239c711283e11, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperColliderAuthoring.cs new file mode 100644 index 000000000..c007f84ce --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperColliderAuthoring.cs @@ -0,0 +1,26 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Flipper; + +namespace VisualPinball.Unity +{ + [AddComponentMenu("Visual Pinball/Collision/Flipper Collider")] + public class FlipperColliderAuthoring : ItemColliderAuthoring + { + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperColliderAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperColliderAuthoring.cs.meta new file mode 100644 index 000000000..d0ecf89df --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperColliderAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1a6867661ef306b40958372e88a16b2a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: aadd1961195e36246959e08c0ea8395d, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs index 2a63fc5b4..475f7ef64 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs @@ -14,19 +14,57 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using Unity.Entities; using UnityEngine; -using VisualPinball.Engine.Game; +using VisualPinball.Engine.VPT; +using VisualPinball.Engine.VPT.Flipper; namespace VisualPinball.Unity { internal static class FlipperExtensions { - public static FlipperAuthoring SetupGameObject(this Engine.VPT.Flipper.Flipper flipper, GameObject obj) + public static IItemMainAuthoring SetupGameObject(this Flipper flipper, GameObject obj, IItemMainAuthoring parentAuthoring) { - var ic = obj.AddComponent().SetItem(flipper); + var mainAuthoring = obj.AddComponent().SetItem(flipper); + + switch (flipper.SubComponent) { + case ItemSubComponent.None: + obj.AddComponent(); + CreateChild(obj, FlipperMeshGenerator.Base); + CreateChild(obj, FlipperMeshGenerator.Rubber); + break; + + case ItemSubComponent.Collider: { + obj.AddComponent(); + if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { + hittableAuthoring.RemoveHittableComponent(); + } + break; + } + + case ItemSubComponent.Mesh: { + // todo + if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { + meshAuthoring.RemoveMeshComponent(); + } + break; + } + + default: + throw new ArgumentOutOfRangeException(); + } obj.AddComponent(); - return ic as FlipperAuthoring; + return mainAuthoring; + } + + private static GameObject CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring + { + var subObj = new GameObject(name); + subObj.transform.SetParent(obj.transform, false); + subObj.AddComponent(); + //subObj.layer = ChildObjectsLayer; + return subObj; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperRubberMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperRubberMeshAuthoring.cs new file mode 100644 index 000000000..9a0b9f896 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperRubberMeshAuthoring.cs @@ -0,0 +1,28 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Flipper; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Flipper Base Mesh")] + public class FlipperRubberMeshAuthoring : ItemMeshAuthoring + { + protected override string MeshId => FlipperMeshGenerator.Rubber; + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperRubberMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperRubberMeshAuthoring.cs.meta new file mode 100644 index 000000000..5608d1ea1 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperRubberMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8e6fc321830c03547890119a04997404 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 07c5ef6cfd6189a4e8a3db817ece3e26, type: 3} + userData: + assetBundleName: + assetBundleVariant: From 376395132e3e5a26513ecd25b226901e9307529b Mon Sep 17 00:00:00 2001 From: freezy Date: Tue, 13 Oct 2020 00:13:48 +0200 Subject: [PATCH 069/124] flipper: Handle mesh generator when rubber width is 0. --- VisualPinball.Engine/VPT/Flipper/Flipper.cs | 4 ++-- .../VPT/Flipper/FlipperInspector.cs | 2 +- .../VPT/ItemInspector.cs | 4 +++- .../VPT/Flipper/FlipperAuthoring.cs | 19 +++++++++++++++++++ .../VPT/Flipper/FlipperExtensions.cs | 2 +- .../VPT/ItemMeshAuthoring.cs | 9 +++++++++ 6 files changed, 35 insertions(+), 5 deletions(-) diff --git a/VisualPinball.Engine/VPT/Flipper/Flipper.cs b/VisualPinball.Engine/VPT/Flipper/Flipper.cs index 4d5bd8955..225cc9ab4 100644 --- a/VisualPinball.Engine/VPT/Flipper/Flipper.cs +++ b/VisualPinball.Engine/VPT/Flipper/Flipper.cs @@ -23,8 +23,8 @@ namespace VisualPinball.Engine.VPT.Flipper { public class Flipper : Item, IRenderable, IHittable, ISwitchable, ICoilable { - public override string ItemName { get; } = "Flasher"; - public override string ItemGroupName { get; } = "Flashers"; + public override string ItemName { get; } = "Flipper"; + public override string ItemGroupName { get; } = "Flippers"; public bool IsPulseSwitch => false; diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs index 282a37300..16a856060 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs @@ -44,7 +44,7 @@ public override void OnInspectorGUI() TextureField("Image", ref _flipper.Data.Image); MaterialField("Material", ref _flipper.Data.Material); MaterialField("Rubber Material", ref _flipper.Data.RubberMaterial); - ItemDataField("Rubber Thickness", ref _flipper.Data.RubberThickness); + ItemDataField("Rubber Thickness", ref _flipper.Data.RubberThickness, onChanged: _flipper.OnRubberWidthUpdated); ItemDataField("Rubber Offset Height", ref _flipper.Data.RubberHeight); ItemDataField("Rubber Width", ref _flipper.Data.RubberWidth); ItemDataField("Visible", ref _flipper.Data.IsVisible); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs index 250ee7d27..f4156c5a7 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs @@ -142,13 +142,15 @@ protected void OnPreInspectorGUI() #region Data Fields - protected void ItemDataField(string label, ref float field, bool dirtyMesh = true) + protected void ItemDataField(string label, ref float field, bool dirtyMesh = true, Action onChanged = null) { EditorGUI.BeginChangeCheck(); var val = EditorGUILayout.FloatField(label, field); if (EditorGUI.EndChangeCheck()) { FinishEdit(label, dirtyMesh); + var fieldBefore = field; field = val; + onChanged?.Invoke(fieldBefore, field); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs index bc50f710c..d75dd3a1e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs @@ -65,6 +65,24 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterFlipper(Item, entity, gameObject); } + public void OnRubberWidthUpdated(float before, float after) + { + if (before != 0 && after != 0f) { + return; + } + + if (before == 0) { + FlipperExtensions.CreateChild(gameObject, FlipperMeshGenerator.Rubber); + } + + if (after == 0) { + var rubberAuthoring = GetComponentInChildren(); + if (rubberAuthoring != null) { + DestroyImmediate(rubberAuthoring.gameObject); + } + } + } + public void RemoveHittableComponent() { } @@ -78,6 +96,7 @@ public void RemoveHittableComponent() public override void SetEditorRotation(Vector3 rot) => Data.StartAngle = rot.x; public override ItemDataTransformType EditorScaleType => ItemDataTransformType.ThreeD; + public override Vector3 GetEditorScale() => new Vector3(Data.BaseRadius, Data.FlipperRadius, Data.Height); public override void SetEditorScale(Vector3 scale) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs index 475f7ef64..b9bab4a16 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs @@ -58,7 +58,7 @@ public static IItemMainAuthoring SetupGameObject(this Flipper flipper, GameObjec return mainAuthoring; } - private static GameObject CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring + public static GameObject CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring { var subObj = new GameObject(name); subObj.transform.SetParent(obj.transform, false); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs index 77ef4376e..79e139f7b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs @@ -69,6 +69,9 @@ private void CreateMesh() { var ta = GetComponentInParent(); var ro = Item.GetRenderObject(ta.Table, MeshId, Origin.Original, false); + if (ro?.Mesh == null) { + return; + } var mesh = ro.Mesh.ToUnityMesh($"{gameObject.name}_Mesh"); // apply mesh to game object @@ -92,6 +95,12 @@ private void UpdateMesh() { var ta = GetComponentInParent(); var ro = Item.GetRenderObject(ta.Table, MeshId, Origin.Original, false); + + // mesh generator can return null - but in this case the main component + // will take care of removing the mesh component. + if (ro == null) { + return; + } var mr = GetComponent(); var mf = GetComponent(); From 029d1e290c2f106a65fd38d895d71ccc4a08d5f3 Mon Sep 17 00:00:00 2001 From: freezy Date: Tue, 13 Oct 2020 00:16:02 +0200 Subject: [PATCH 070/124] flipper: Fix rubber component name. --- .../VPT/Flipper/FlipperRubberMeshAuthoring.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperRubberMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperRubberMeshAuthoring.cs index 9a0b9f896..d76b8f9a3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperRubberMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperRubberMeshAuthoring.cs @@ -20,7 +20,7 @@ namespace VisualPinball.Unity { [ExecuteInEditMode] - [AddComponentMenu("Visual Pinball/Mesh/Flipper Base Mesh")] + [AddComponentMenu("Visual Pinball/Mesh/Flipper Rubber Mesh")] public class FlipperRubberMeshAuthoring : ItemMeshAuthoring { protected override string MeshId => FlipperMeshGenerator.Rubber; From 1d3a3f85c8d4bd5dc6cbc98ff5fab83e2ba68e44 Mon Sep 17 00:00:00 2001 From: freezy Date: Tue, 13 Oct 2020 00:34:41 +0200 Subject: [PATCH 071/124] plunger: Add separate mesh generation. --- VisualPinball.Engine/VPT/Plunger/Plunger.cs | 2 +- .../VPT/Plunger/PlungerMeshGenerator.cs | 50 ++++++++++++++++--- .../Game/DebugBallCreator.cs | 1 - .../VPT/Bumper/BumperBaseMeshAuthoring.cs | 1 - .../VPT/Bumper/BumperCapMeshAuthoring.cs | 1 - .../VPT/Bumper/BumperColliderAuthoring.cs | 1 - .../VPT/Bumper/BumperRingMeshAuthoring.cs | 1 - .../VPT/Bumper/BumperSkirtMeshAuthoring.cs | 1 - .../VPT/HitTarget/HitTargetExtensions.cs | 1 - .../VisualPinball.Unity/VPT/IItemAuthoring.cs | 1 - .../VPT/ItemMovementAuthoring.cs | 8 --- .../VPT/Kicker/KickerExtensions.cs | 1 - .../VPT/Light/LightExtensions.cs | 1 - .../VPT/Plunger/PlungerColliderAuthoring.cs | 26 ++++++++++ .../Plunger/PlungerColliderAuthoring.cs.meta | 11 ++++ .../VPT/Plunger/PlungerExtensions.cs | 7 ++- .../VPT/Primitive/PrimitiveExtensions.cs | 1 - .../VPT/Ramp/RampColliderAuthoring.cs | 1 - .../VPT/Ramp/RampFloorMeshAuthoring.cs | 1 - .../VPT/Ramp/RampWallMeshAuthoring.cs | 1 - .../VPT/Ramp/RampWireMeshAuthoring.cs | 1 - .../Spinner/SpinnerBracketMeshAuthoring.cs | 1 - .../VPT/Spinner/SpinnerPlateMeshAuthoring.cs | 1 - .../VPT/Surface/SurfaceSideMeshAuthoring.cs | 2 - .../VPT/Surface/SurfaceTopMeshAuthoring.cs | 2 - .../VPT/Trigger/TriggerExtensions.cs | 1 - 26 files changed, 84 insertions(+), 42 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerColliderAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerColliderAuthoring.cs.meta diff --git a/VisualPinball.Engine/VPT/Plunger/Plunger.cs b/VisualPinball.Engine/VPT/Plunger/Plunger.cs index 5af6b2bc3..830379032 100644 --- a/VisualPinball.Engine/VPT/Plunger/Plunger.cs +++ b/VisualPinball.Engine/VPT/Plunger/Plunger.cs @@ -64,7 +64,7 @@ public void Init(Table.Table table) public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { - throw new System.NotImplementedException(); + return MeshGenerator.GetRenderObject(20, table, id, origin, asRightHanded); } public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) diff --git a/VisualPinball.Engine/VPT/Plunger/PlungerMeshGenerator.cs b/VisualPinball.Engine/VPT/Plunger/PlungerMeshGenerator.cs index 01133636e..8ccf0534f 100644 --- a/VisualPinball.Engine/VPT/Plunger/PlungerMeshGenerator.cs +++ b/VisualPinball.Engine/VPT/Plunger/PlungerMeshGenerator.cs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using NLog; using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; @@ -22,9 +23,9 @@ namespace VisualPinball.Engine.VPT.Plunger { public class PlungerMeshGenerator { - public const string FlatName = "Flat"; - public const string RodName = "Rod"; - public const string SpringName = "Spring"; + public const string Flat = "Flat"; + public const string Rod = "Rod"; + public const string Spring = "Spring"; public int NumFrames { get; set; } @@ -93,6 +94,41 @@ public void Init(Table.Table table) _desc = GetPlungerDesc(); } + public RenderObject GetRenderObject(int frame, Table.Table table, string id, Origin origin, bool asRightHanded) + { + var material = new PbrMaterial(table.GetMaterial(_data.Material), table.GetTexture(_data.Image)); + switch (id) { + case Flat: + var flatMesh = BuildFlatMesh(frame); + return new RenderObject( + id, + asRightHanded ? flatMesh.Transform(Matrix3D.RightHanded) : flatMesh, + material, + true + ); + case Rod: + CalculateArraySizes(); + var rodMesh = BuildRodMesh(frame); + return new RenderObject( + id, + asRightHanded ? rodMesh.Transform(Matrix3D.RightHanded) : rodMesh, + material, + true + ); + case Spring: + CalculateArraySizes(); + var springMesh = BuildSpringMesh(frame); + return new RenderObject( + id, + asRightHanded ? springMesh.Transform(Matrix3D.RightHanded) : springMesh, + material, + true + ); + default: + throw new ArgumentException("Unknown plunger mesh \"" + id + "\"."); + } + } + public RenderObjectGroup GetRenderObjects(int frame, Table.Table table, Origin origin, bool asRightHanded = true) { Init(table); @@ -106,7 +142,7 @@ public RenderObjectGroup GetRenderObjects(int frame, Table.Table table, Origin o var flatMesh = BuildFlatMesh(frame); return new RenderObjectGroup(_data.Name, "Plungers", translationMatrix, new RenderObject( - FlatName, + Flat, asRightHanded ? flatMesh.Transform(Matrix3D.RightHanded) : flatMesh, material, true @@ -123,13 +159,13 @@ public RenderObjectGroup GetRenderObjects(int frame, Table.Table table, Origin o return new RenderObjectGroup(_data.Name, "Plungers", translationMatrix, new RenderObject( - RodName, + Rod, asRightHanded ? rodMesh.Transform(Matrix3D.RightHanded) : rodMesh, material, true ), new RenderObject( - SpringName, + Spring, asRightHanded ? springMesh.Transform(Matrix3D.RightHanded) : springMesh, material, true @@ -140,7 +176,7 @@ public RenderObjectGroup GetRenderObjects(int frame, Table.Table table, Origin o // modern plunger return new RenderObjectGroup(_data.Name, "Plungers", translationMatrix, new RenderObject( - RodName, + Rod, asRightHanded ? rodMesh.Transform(Matrix3D.RightHanded) : rodMesh, material, true diff --git a/VisualPinball.Unity/VisualPinball.Unity/Game/DebugBallCreator.cs b/VisualPinball.Unity/VisualPinball.Unity/Game/DebugBallCreator.cs index 50784d721..42687b412 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Game/DebugBallCreator.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Game/DebugBallCreator.cs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; using VisualPinball.Engine.VPT.Table; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs index 30e81674c..5deffd6ff 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs @@ -16,7 +16,6 @@ using UnityEngine; using VisualPinball.Engine.VPT.Bumper; -using VisualPinball.Engine.VPT.Rubber; namespace VisualPinball.Unity { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs index 634a087a0..a3eff7356 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs @@ -16,7 +16,6 @@ using UnityEngine; using VisualPinball.Engine.VPT.Bumper; -using VisualPinball.Engine.VPT.Rubber; namespace VisualPinball.Unity { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperColliderAuthoring.cs index 39ef6e1f8..12063b505 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperColliderAuthoring.cs @@ -16,7 +16,6 @@ using UnityEngine; using VisualPinball.Engine.VPT.Bumper; -using VisualPinball.Engine.VPT.Rubber; namespace VisualPinball.Unity { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs index 8e454c3a1..365abc56c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs @@ -16,7 +16,6 @@ using UnityEngine; using VisualPinball.Engine.VPT.Bumper; -using VisualPinball.Engine.VPT.Rubber; namespace VisualPinball.Unity { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs index 044dcfc67..2d030090a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs @@ -16,7 +16,6 @@ using UnityEngine; using VisualPinball.Engine.VPT.Bumper; -using VisualPinball.Engine.VPT.Rubber; namespace VisualPinball.Unity { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs index c5e2f3d2e..1c64ff0c9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs @@ -16,7 +16,6 @@ using Unity.Entities; using UnityEngine; -using VisualPinball.Engine.Game; namespace VisualPinball.Unity { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemAuthoring.cs index ad8cd4a02..b05e3faba 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemAuthoring.cs @@ -1,4 +1,3 @@ -using UnityEngine; using VisualPinball.Engine.VPT; namespace VisualPinball.Unity diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs index 932556f02..07b96a9d9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs @@ -17,16 +17,8 @@ using System; using Unity.Entities; using Unity.Transforms; -using UnityEngine; using VisualPinball.Engine.Game; -using VisualPinball.Engine.Math; -using VisualPinball.Engine.Physics; using VisualPinball.Engine.VPT; -using VisualPinball.Engine.VPT.Flipper; -using VisualPinball.Engine.VPT.Gate; -using VisualPinball.Engine.VPT.Plunger; -using VisualPinball.Engine.VPT.Spinner; -using Color = UnityEngine.Color; namespace VisualPinball.Unity { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs index 9fbd2d233..93b5347ff 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs @@ -16,7 +16,6 @@ using Unity.Entities; using UnityEngine; -using VisualPinball.Engine.Game; namespace VisualPinball.Unity { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs index 42558e3e6..1d30f05cd 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs @@ -15,7 +15,6 @@ // along with this program. If not, see . using UnityEngine; -using VisualPinball.Engine.Game; namespace VisualPinball.Unity { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerColliderAuthoring.cs new file mode 100644 index 000000000..5d89ed1f6 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerColliderAuthoring.cs @@ -0,0 +1,26 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Plunger; + +namespace VisualPinball.Unity +{ + [AddComponentMenu("Visual Pinball/Collision/Plunger Collider")] + public class PlungerColliderAuthoring : ItemColliderAuthoring + { + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerColliderAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerColliderAuthoring.cs.meta new file mode 100644 index 000000000..04f50d507 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerColliderAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2b804d1deff43db4482e740209bb910a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs index 1225ff8d5..044f19c6c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs @@ -16,7 +16,6 @@ using Unity.Entities; using UnityEngine; -using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT.Plunger; namespace VisualPinball.Unity @@ -27,17 +26,17 @@ public static PlungerAuthoring SetupGameObject(this Plunger plunger, GameObject { var ic = obj.AddComponent().SetItem(plunger); - var rod = obj.transform.Find(PlungerMeshGenerator.RodName); + var rod = obj.transform.Find(PlungerMeshGenerator.Rod); if (rod != null) { rod.gameObject.AddComponent(); } - var spring = obj.transform.Find(PlungerMeshGenerator.SpringName); + var spring = obj.transform.Find(PlungerMeshGenerator.Spring); if (spring != null) { spring.gameObject.AddComponent(); } - var flat = obj.transform.Find(PlungerMeshGenerator.FlatName); + var flat = obj.transform.Find(PlungerMeshGenerator.Flat); if (flat != null) { flat.gameObject.AddComponent(); } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs index 2c1825c00..c7777a4f8 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs @@ -16,7 +16,6 @@ using Unity.Entities; using UnityEngine; -using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT.Primitive; namespace VisualPinball.Unity diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampColliderAuthoring.cs index 8b050d105..114a4a384 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampColliderAuthoring.cs @@ -15,7 +15,6 @@ // along with this program. If not, see . using UnityEngine; -using VisualPinball.Engine.VPT.Gate; using VisualPinball.Engine.VPT.Ramp; namespace VisualPinball.Unity diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampFloorMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampFloorMeshAuthoring.cs index 9accf50f3..a0fa7ac65 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampFloorMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampFloorMeshAuthoring.cs @@ -15,7 +15,6 @@ // along with this program. If not, see . using UnityEngine; -using VisualPinball.Engine.VPT.Gate; using VisualPinball.Engine.VPT.Ramp; namespace VisualPinball.Unity diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWallMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWallMeshAuthoring.cs index 7db757084..d455707cd 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWallMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWallMeshAuthoring.cs @@ -15,7 +15,6 @@ // along with this program. If not, see . using UnityEngine; -using VisualPinball.Engine.VPT.Gate; using VisualPinball.Engine.VPT.Ramp; namespace VisualPinball.Unity diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWireMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWireMeshAuthoring.cs index 69afd9c6f..2740f0205 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWireMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWireMeshAuthoring.cs @@ -15,7 +15,6 @@ // along with this program. If not, see . using UnityEngine; -using VisualPinball.Engine.VPT.Gate; using VisualPinball.Engine.VPT.Ramp; namespace VisualPinball.Unity diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerBracketMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerBracketMeshAuthoring.cs index 92399e98e..63b1ecfce 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerBracketMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerBracketMeshAuthoring.cs @@ -15,7 +15,6 @@ // along with this program. If not, see . using UnityEngine; -using VisualPinball.Engine.VPT.Gate; using VisualPinball.Engine.VPT.Spinner; namespace VisualPinball.Unity diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateMeshAuthoring.cs index 606bd5a3c..962e629eb 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateMeshAuthoring.cs @@ -15,7 +15,6 @@ // along with this program. If not, see . using UnityEngine; -using VisualPinball.Engine.VPT.Gate; using VisualPinball.Engine.VPT.Spinner; namespace VisualPinball.Unity diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceSideMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceSideMeshAuthoring.cs index b2412eecc..fc88dc232 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceSideMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceSideMeshAuthoring.cs @@ -15,8 +15,6 @@ // along with this program. If not, see . using UnityEngine; -using VisualPinball.Engine.VPT.Bumper; -using VisualPinball.Engine.VPT.Rubber; using VisualPinball.Engine.VPT.Surface; namespace VisualPinball.Unity diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceTopMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceTopMeshAuthoring.cs index 5e5168364..7a2412375 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceTopMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceTopMeshAuthoring.cs @@ -15,8 +15,6 @@ // along with this program. If not, see . using UnityEngine; -using VisualPinball.Engine.VPT.Bumper; -using VisualPinball.Engine.VPT.Rubber; using VisualPinball.Engine.VPT.Surface; namespace VisualPinball.Unity diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs index f714fe7f3..8a28cedba 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs @@ -16,7 +16,6 @@ using Unity.Entities; using UnityEngine; -using VisualPinball.Engine.Game; namespace VisualPinball.Unity { From 8d47148f6c1b762bed7a7ecb3ad47857965632f0 Mon Sep 17 00:00:00 2001 From: freezy Date: Tue, 13 Oct 2020 00:53:28 +0200 Subject: [PATCH 072/124] unity: Add remaining authoring components. --- .../VPT/HitTarget/HitTarget.cs | 4 +- .../VPT/HitTarget/HitTargetMeshGenerator.cs | 12 ++++ VisualPinball.Engine/VPT/Kicker/Kicker.cs | 4 +- .../VPT/Kicker/KickerMeshGenerator.cs | 11 +++ VisualPinball.Engine/VPT/Light/Light.cs | 4 +- .../VPT/Light/LightMeshGenerator.cs | 72 ++++++++++++++----- .../VPT/Primitive/Primitive.cs | 4 +- .../VPT/Primitive/PrimitiveMeshGenerator.cs | 14 ++++ VisualPinball.Engine/VPT/Trigger/Trigger.cs | 4 +- .../VPT/Trigger/TriggerMeshGenerator.cs | 11 +++ .../HitTarget/HitTargetColliderAuthoring.cs | 26 +++++++ .../HitTargetColliderAuthoring.cs.meta | 11 +++ .../VPT/HitTarget/HitTargetMeshAuthoring.cs | 28 ++++++++ .../HitTarget/HitTargetMeshAuthoring.cs.meta | 11 +++ .../VPT/ItemMeshAuthoring.cs | 2 +- .../VPT/Kicker/KickerColliderAuthoring.cs | 26 +++++++ .../Kicker/KickerColliderAuthoring.cs.meta | 11 +++ .../VPT/Kicker/KickerMeshAuthoring.cs | 27 +++++++ .../VPT/Kicker/KickerMeshAuthoring.cs.meta | 11 +++ .../VPT/Light/LightBulbMeshAuthoring.cs | 29 ++++++++ .../LightBulbMeshAuthoring.cs.meta} | 2 +- .../VPT/Light/LightSocketMeshAuthoring.cs | 29 ++++++++ .../LightSocketMeshAuthoring.cs.meta} | 2 +- .../Plunger/PlungerColliderAuthoring.cs.meta | 2 +- .../VPT/Plunger/PlungerExtensions.cs | 6 +- ...thoring.cs => PlungerFlatMeshAuthoring.cs} | 7 +- ....meta => PlungerFlatMeshAuthoring.cs.meta} | 2 +- ...ldAuthoring.cs => PlungerMeshAuthoring.cs} | 2 +- ...g.cs.meta => PlungerMeshAuthoring.cs.meta} | 2 +- ...uthoring.cs => PlungerRodMeshAuthoring.cs} | 5 +- .../Plunger/PlungerRodMeshAuthoring.cs.meta | 11 +++ ...oring.cs => PlungerSpringMeshAuthoring.cs} | 5 +- .../PlungerSpringMeshAuthoring.cs.meta | 11 +++ .../Primitive/PrimitiveColliderAuthoring.cs | 26 +++++++ .../PrimitiveColliderAuthoring.cs.meta | 11 +++ .../VPT/Primitive/PrimitiveMeshAuthoring.cs | 27 +++++++ .../Primitive/PrimitiveMeshAuthoring.cs.meta | 11 +++ .../VPT/Rubber/RubberMeshAuthoring.cs | 1 - .../VPT/Trigger/TriggerColliderAuthoring.cs | 26 +++++++ .../Trigger/TriggerColliderAuthoring.cs.meta | 11 +++ .../VPT/Trigger/TriggerMeshAuthoring.cs | 27 +++++++ .../VPT/Trigger/TriggerMeshAuthoring.cs.meta | 11 +++ 42 files changed, 517 insertions(+), 42 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetColliderAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetColliderAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetMeshAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetMeshAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerColliderAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerColliderAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerMeshAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerMeshAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightBulbMeshAuthoring.cs rename VisualPinball.Unity/VisualPinball.Unity/VPT/{Plunger/PlungerRodAuthoring.cs.meta => Light/LightBulbMeshAuthoring.cs.meta} (83%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightSocketMeshAuthoring.cs rename VisualPinball.Unity/VisualPinball.Unity/VPT/{Plunger/PlungerChildAuthoring.cs.meta => Light/LightSocketMeshAuthoring.cs.meta} (83%) rename VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/{PlungerFlatAuthoring.cs => PlungerFlatMeshAuthoring.cs} (85%) rename VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/{PlungerSpringAuthoring.cs.meta => PlungerFlatMeshAuthoring.cs.meta} (83%) rename VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/{PlungerChildAuthoring.cs => PlungerMeshAuthoring.cs} (92%) rename VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/{PlungerFlatAuthoring.cs.meta => PlungerMeshAuthoring.cs.meta} (83%) rename VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/{PlungerRodAuthoring.cs => PlungerRodMeshAuthoring.cs} (85%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodMeshAuthoring.cs.meta rename VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/{PlungerSpringAuthoring.cs => PlungerSpringMeshAuthoring.cs} (85%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringMeshAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerColliderAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerColliderAuthoring.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerMeshAuthoring.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerMeshAuthoring.cs.meta diff --git a/VisualPinball.Engine/VPT/HitTarget/HitTarget.cs b/VisualPinball.Engine/VPT/HitTarget/HitTarget.cs index c91de7738..88f0dfd10 100644 --- a/VisualPinball.Engine/VPT/HitTarget/HitTarget.cs +++ b/VisualPinball.Engine/VPT/HitTarget/HitTarget.cs @@ -57,11 +57,11 @@ public void Init(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => _meshGenerator.GetPostMatrix(table, origin); public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { - throw new System.NotImplementedException(); + return _meshGenerator.GetRenderObject(table, origin, asRightHanded); } public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) diff --git a/VisualPinball.Engine/VPT/HitTarget/HitTargetMeshGenerator.cs b/VisualPinball.Engine/VPT/HitTarget/HitTargetMeshGenerator.cs index 3d3a1a857..3b860c55e 100644 --- a/VisualPinball.Engine/VPT/HitTarget/HitTargetMeshGenerator.cs +++ b/VisualPinball.Engine/VPT/HitTarget/HitTargetMeshGenerator.cs @@ -34,6 +34,18 @@ public HitTargetMeshGenerator(HitTargetData data) _data = data; } + public RenderObject GetRenderObject(Table.Table table, Origin origin, bool asRightHanded) + { + var mesh = GetBaseMesh(); + var (preMatrix, _) = GetPreMatrix(table, origin, asRightHanded); + return new RenderObject( + _data.Name, + mesh.Transform(preMatrix), + new PbrMaterial(table.GetMaterial(_data.Material), table.GetTexture(_data.Image)), + _data.IsVisible + ); + } + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin, bool asRightHanded) { var mesh = GetBaseMesh(); diff --git a/VisualPinball.Engine/VPT/Kicker/Kicker.cs b/VisualPinball.Engine/VPT/Kicker/Kicker.cs index 208b277a9..a130521ba 100644 --- a/VisualPinball.Engine/VPT/Kicker/Kicker.cs +++ b/VisualPinball.Engine/VPT/Kicker/Kicker.cs @@ -61,11 +61,11 @@ public void Init(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => _meshGenerator.GetPostMatrix(table, origin); public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { - throw new System.NotImplementedException(); + return _meshGenerator.GetRenderObject(table, origin, asRightHanded); } public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) diff --git a/VisualPinball.Engine/VPT/Kicker/KickerMeshGenerator.cs b/VisualPinball.Engine/VPT/Kicker/KickerMeshGenerator.cs index bf5cb6143..3359c6143 100644 --- a/VisualPinball.Engine/VPT/Kicker/KickerMeshGenerator.cs +++ b/VisualPinball.Engine/VPT/Kicker/KickerMeshGenerator.cs @@ -46,6 +46,17 @@ public KickerMeshGenerator(KickerData data) _data = data; } + public RenderObject GetRenderObject(Table.Table table, Origin origin, bool asRightHanded) + { + var (preMatrix, _) = GetPreMatrix(table, origin, asRightHanded); + return new RenderObject( + _data.Name, + GetBaseMesh().Transform(preMatrix), + new PbrMaterial(table.GetMaterial(_data.Material)), + _data.KickerType != KickerType.KickerInvisible + ); + } + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin, bool asRightHanded) { var (preMatrix, _) = GetPreMatrix(table, origin, asRightHanded); diff --git a/VisualPinball.Engine/VPT/Light/Light.cs b/VisualPinball.Engine/VPT/Light/Light.cs index 67dae31ed..4ef6cc200 100644 --- a/VisualPinball.Engine/VPT/Light/Light.cs +++ b/VisualPinball.Engine/VPT/Light/Light.cs @@ -60,11 +60,11 @@ public static Light GetDefault(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => _meshGenerator.GetPostMatrix(table, origin); public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { - throw new System.NotImplementedException(); + return _meshGenerator.GetRenderObject(table, id, origin, asRightHanded); } public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin, bool asRightHanded = true) diff --git a/VisualPinball.Engine/VPT/Light/LightMeshGenerator.cs b/VisualPinball.Engine/VPT/Light/LightMeshGenerator.cs index b1fd72df9..380d9583d 100644 --- a/VisualPinball.Engine/VPT/Light/LightMeshGenerator.cs +++ b/VisualPinball.Engine/VPT/Light/LightMeshGenerator.cs @@ -22,10 +22,13 @@ namespace VisualPinball.Engine.VPT.Light { - internal class LightMeshGenerator + public class LightMeshGenerator { - private static readonly Mesh Bulb = new Mesh("Bulb", BulbMesh.Vertices, BulbMesh.Indices); - private static readonly Mesh Socket = new Mesh("Socket", BulbSocket.Vertices, BulbSocket.Indices); + public const string Bulb = "Bulb"; + public const string Socket = "Socket"; + + private static readonly Mesh BulbMesh = new Mesh("Bulb", Resources.Meshes.BulbMesh.Vertices, Resources.Meshes.BulbMesh.Indices); + private static readonly Mesh SocketMesh = new Mesh("Socket", BulbSocket.Vertices, BulbSocket.Indices); private readonly LightData _data; @@ -34,30 +37,57 @@ internal LightMeshGenerator(LightData data) _data = data; } + public RenderObject GetRenderObject(Table.Table table, string id, Origin origin, bool asRightHanded) + { + switch (id) + { + case Bulb: + var bulbMesh = GetBulbMesh(table, origin); + return new RenderObject( + id, + asRightHanded ? bulbMesh.Transform(Matrix3D.RightHanded) : bulbMesh, + new PbrMaterial(GetBulbMaterial()), + true + ); + case Socket: + var socketMesh = GetSocketMesh(table, origin); + return new RenderObject( + id, + asRightHanded ? socketMesh.Transform(Matrix3D.RightHanded) : socketMesh, + new PbrMaterial(GetSocketMaterial()), + true + ); + default: + throw new ArgumentException("Unknown light mesh \"" + id + "\"."); + } + } + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin, bool asRightHanded = true) { var translationMatrix = GetPostMatrix(table, origin); if (!RenderBulb()) { return new RenderObjectGroup(_data.Name, "Lights", translationMatrix); } - var meshes = GetMeshes(table, origin); + + var bulbMesh = GetBulbMesh(table, origin); + var socketMesh = GetSocketMesh(table, origin); return new RenderObjectGroup(_data.Name, "Lights", translationMatrix, new RenderObject( - "Bulb", - asRightHanded ? meshes["Bulb"].Transform(Matrix3D.RightHanded) : meshes["Bulb"], + Bulb, + asRightHanded ? bulbMesh.Transform(Matrix3D.RightHanded) : bulbMesh, new PbrMaterial(GetBulbMaterial()), true ), new RenderObject( - "Socket", - asRightHanded ? meshes["Socket"].Transform(Matrix3D.RightHanded) : meshes["Socket"], + Socket, + asRightHanded ? socketMesh.Transform(Matrix3D.RightHanded) : socketMesh, new PbrMaterial(GetSocketMaterial()), true ) ); } - private Matrix3D GetPostMatrix(Table.Table table, Origin origin) + public Matrix3D GetPostMatrix(Table.Table table, Origin origin) { switch (origin) { case Origin.Original: @@ -111,30 +141,36 @@ private static Material GetSocketMaterial() }; } - private Dictionary GetMeshes(Table.Table table, Origin origin) + private Mesh GetBulbMesh(Table.Table table, Origin origin) { - var lightMesh = Bulb.Clone(); + var bulbMesh = BulbMesh.Clone(); var height = table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y) * table.GetScaleZ(); var transX = origin == Origin.Global ? _data.Center.X : 0f; var transY = origin == Origin.Global ? _data.Center.Y : 0f; var transZ = origin == Origin.Global ? height : 0f; - foreach (var vertex in lightMesh.Vertices) { + foreach (var vertex in bulbMesh.Vertices) { vertex.X = vertex.X * _data.MeshRadius + transX; vertex.Y = vertex.Y * _data.MeshRadius + transY; vertex.Z = vertex.Z * _data.MeshRadius * table.GetScaleZ() + transZ; } - var socketMesh = Socket.Clone(); + return bulbMesh; + } + + private Mesh GetSocketMesh(Table.Table table, Origin origin) + { + var socketMesh = SocketMesh.Clone(); + var height = table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y) * table.GetScaleZ(); + var transX = origin == Origin.Global ? _data.Center.X : 0f; + var transY = origin == Origin.Global ? _data.Center.Y : 0f; + var transZ = origin == Origin.Global ? height : 0f; + foreach (var vertex in socketMesh.Vertices) { vertex.X = vertex.X * _data.MeshRadius + transX; vertex.Y = vertex.Y * _data.MeshRadius + transY; vertex.Z = vertex.Z * _data.MeshRadius * table.GetScaleZ() + transZ; } - - return new Dictionary { - { "Bulb", lightMesh }, - { "Socket", socketMesh }, - }; + return socketMesh; } private bool RenderBulb() diff --git a/VisualPinball.Engine/VPT/Primitive/Primitive.cs b/VisualPinball.Engine/VPT/Primitive/Primitive.cs index b8ddbc98f..06717d982 100644 --- a/VisualPinball.Engine/VPT/Primitive/Primitive.cs +++ b/VisualPinball.Engine/VPT/Primitive/Primitive.cs @@ -61,14 +61,14 @@ public static Primitive GetDefault(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => _meshGenerator.GetPostMatrix(table, origin); public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin, bool asRightHanded, string parent, PbrMaterial material) => _meshGenerator.GetRenderObjects(table, origin, asRightHanded, parent, material); public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { - throw new System.NotImplementedException(); + return _meshGenerator.GetRenderObject(table, origin, asRightHanded); } public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) => diff --git a/VisualPinball.Engine/VPT/Primitive/PrimitiveMeshGenerator.cs b/VisualPinball.Engine/VPT/Primitive/PrimitiveMeshGenerator.cs index 438fbb5fa..66f05c50b 100644 --- a/VisualPinball.Engine/VPT/Primitive/PrimitiveMeshGenerator.cs +++ b/VisualPinball.Engine/VPT/Primitive/PrimitiveMeshGenerator.cs @@ -34,6 +34,20 @@ public PrimitiveMeshGenerator(PrimitiveData data) _data = data; } + public RenderObject GetRenderObject(Table.Table table, Origin origin, bool asRightHanded) + { + return new RenderObject( + _data.Name, + GetTransformedMesh(table, origin, asRightHanded), + new PbrMaterial( + table.GetMaterial(_data.Material), + table.GetTexture(_data.Image), + table.GetTexture(_data.NormalMap) + ), + _data.IsVisible + ); + } + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin, bool asRightHanded = true, string parent = null, PbrMaterial material = null) { diff --git a/VisualPinball.Engine/VPT/Trigger/Trigger.cs b/VisualPinball.Engine/VPT/Trigger/Trigger.cs index 4e0148466..eebbad381 100644 --- a/VisualPinball.Engine/VPT/Trigger/Trigger.cs +++ b/VisualPinball.Engine/VPT/Trigger/Trigger.cs @@ -66,11 +66,11 @@ public void Init(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => Matrix3D.Identity; + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => _meshGenerator.GetPostMatrix(table, origin); public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { - throw new System.NotImplementedException(); + return _meshGenerator.GetRenderObject(table, origin, asRightHanded); } public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) diff --git a/VisualPinball.Engine/VPT/Trigger/TriggerMeshGenerator.cs b/VisualPinball.Engine/VPT/Trigger/TriggerMeshGenerator.cs index 7d07a819f..f0e121806 100644 --- a/VisualPinball.Engine/VPT/Trigger/TriggerMeshGenerator.cs +++ b/VisualPinball.Engine/VPT/Trigger/TriggerMeshGenerator.cs @@ -34,6 +34,17 @@ public TriggerMeshGenerator(TriggerData data) _data = data; } + public RenderObject GetRenderObject(Table.Table table, Origin origin, bool asRightHanded) + { + var (preMatrix, _) = GetPreMatrix(table, origin, asRightHanded); + return new RenderObject( + _data.Name, + GetMesh().Transform(preMatrix), + new PbrMaterial(table.GetMaterial(_data.Material)), + _data.IsVisible && _data.Shape != TriggerShape.TriggerNone + ); + } + public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin, bool asRightHanded) { var (preMatrix, _) = GetPreMatrix(table, origin, asRightHanded); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetColliderAuthoring.cs new file mode 100644 index 000000000..1020288e3 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetColliderAuthoring.cs @@ -0,0 +1,26 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.HitTarget; + +namespace VisualPinball.Unity +{ + [AddComponentMenu("Visual Pinball/Collision/Hit Target Collider")] + public class HitTargetColliderAuthoring : ItemColliderAuthoring + { + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetColliderAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetColliderAuthoring.cs.meta new file mode 100644 index 000000000..30dea73cb --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetColliderAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 328fafb8204ab504cbf452845e451d54 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c7d68deff6e0c8949830bdbd494e0642, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetMeshAuthoring.cs new file mode 100644 index 000000000..8891fa52c --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetMeshAuthoring.cs @@ -0,0 +1,28 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Bumper; +using VisualPinball.Engine.VPT.HitTarget; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Hit Target Mesh")] + public class HitTargetMeshAuthoring : ItemMeshAuthoring + { + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetMeshAuthoring.cs.meta new file mode 100644 index 000000000..9a0fc8470 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ae014d558c6dc1b4cb29ab1146a3e2e4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 1b46a9d79b9498f40bbced0f30509e85, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs index 79e139f7b..b7114946a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs @@ -28,7 +28,7 @@ namespace VisualPinball.Unity { public abstract class ItemMeshAuthoring : ItemSubAuthoring, IItemMeshAuthoring where TData : ItemData - where TItem : Item, IHittable, IRenderable + where TItem : Item, IRenderable where TAuthoring : ItemMainAuthoring { protected virtual string MeshId => null; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerColliderAuthoring.cs new file mode 100644 index 000000000..811c56aea --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerColliderAuthoring.cs @@ -0,0 +1,26 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Kicker; + +namespace VisualPinball.Unity +{ + [AddComponentMenu("Visual Pinball/Collision/Kicker Collider")] + public class KickerColliderAuthoring : ItemColliderAuthoring + { + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerColliderAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerColliderAuthoring.cs.meta new file mode 100644 index 000000000..3bbef3422 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerColliderAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5693908cb88108f45a2fe3f59adeeabb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 13e6f3ad58a450046958abbd9019685c, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerMeshAuthoring.cs new file mode 100644 index 000000000..dc8d82be9 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerMeshAuthoring.cs @@ -0,0 +1,27 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Kicker; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Kicker Bracket Mesh")] + public class KickerMeshAuthoring : ItemMeshAuthoring + { + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerMeshAuthoring.cs.meta new file mode 100644 index 000000000..a3bc436a3 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 318cf40f101662748b991206ed1596da +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: a6a075975c9f5544ca9e95383646c26e, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightBulbMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightBulbMeshAuthoring.cs new file mode 100644 index 000000000..dd8cceba1 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightBulbMeshAuthoring.cs @@ -0,0 +1,29 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Light; +using Light = VisualPinball.Engine.VPT.Light.Light; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Light Bulb Mesh")] + public class LightBulbMeshAuthoring : ItemMeshAuthoring + { + protected override string MeshId => LightMeshGenerator.Bulb; + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightBulbMeshAuthoring.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodAuthoring.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightBulbMeshAuthoring.cs.meta index d1d2abf0a..a30ffb311 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightBulbMeshAuthoring.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 9261f994f652b014a9fa5ada4c1dd908 +guid: 781f8b80e4ca70b4590a344c2fa77706 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightSocketMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightSocketMeshAuthoring.cs new file mode 100644 index 000000000..0a412f4b8 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightSocketMeshAuthoring.cs @@ -0,0 +1,29 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Light; +using Light = VisualPinball.Engine.VPT.Light.Light; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Light Socket Mesh")] + public class LightSocketMeshAuthoring : ItemMeshAuthoring + { + protected override string MeshId => LightMeshGenerator.Socket; + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerChildAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightSocketMeshAuthoring.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerChildAuthoring.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightSocketMeshAuthoring.cs.meta index 66d698af9..b25cd16f8 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerChildAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightSocketMeshAuthoring.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 1a2c0badf2005fe46b78a95528a7a943 +guid: 87afd9cb614eab4468087193d5e30b1b MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerColliderAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerColliderAuthoring.cs.meta index 04f50d507..cb7973dc8 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerColliderAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerColliderAuthoring.cs.meta @@ -5,7 +5,7 @@ MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: 1af95e9069c968748bca1eb7ab4ee6d3, type: 3} userData: assetBundleName: assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs index 044f19c6c..f48f2cbc4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs @@ -28,17 +28,17 @@ public static PlungerAuthoring SetupGameObject(this Plunger plunger, GameObject var rod = obj.transform.Find(PlungerMeshGenerator.Rod); if (rod != null) { - rod.gameObject.AddComponent(); + rod.gameObject.AddComponent(); } var spring = obj.transform.Find(PlungerMeshGenerator.Spring); if (spring != null) { - spring.gameObject.AddComponent(); + spring.gameObject.AddComponent(); } var flat = obj.transform.Find(PlungerMeshGenerator.Flat); if (flat != null) { - flat.gameObject.AddComponent(); + flat.gameObject.AddComponent(); } obj.AddComponent(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerFlatAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerFlatMeshAuthoring.cs similarity index 85% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerFlatAuthoring.cs rename to VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerFlatMeshAuthoring.cs index 2da9de37e..43f45ef48 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerFlatAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerFlatMeshAuthoring.cs @@ -17,13 +17,18 @@ using System.Collections.Generic; using Unity.Entities; using Unity.Mathematics; +using UnityEngine; using VisualPinball.Engine.Math; using VisualPinball.Engine.VPT.Plunger; namespace VisualPinball.Unity { - public class PlungerFlatAuthoring : PlungerChildAuthoring + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Plunger Flat Mesh")] + public class PlungerFlatMeshAuthoring : PlungerMeshAuthoring { + protected override string MeshId => PlungerMeshGenerator.Flat; + internal override void SetChildEntity(ref PlungerStaticData staticData, Entity entity) { staticData.FlatEntity = entity; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerFlatMeshAuthoring.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringAuthoring.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerFlatMeshAuthoring.cs.meta index f1d2cdf2b..ca77a6782 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerFlatMeshAuthoring.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 4485ae0a7d910564dad93335d4075674 +guid: 7b85b7237c8f9ac4e9b290b6e446d5e8 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerChildAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerMeshAuthoring.cs similarity index 92% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerChildAuthoring.cs rename to VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerMeshAuthoring.cs index f92cdc407..b73fdedd2 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerChildAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerMeshAuthoring.cs @@ -23,7 +23,7 @@ namespace VisualPinball.Unity { - public abstract class PlungerChildAuthoring : MonoBehaviour, IConvertGameObjectToEntity + public abstract class PlungerMeshAuthoring : ItemMeshAuthoring, IConvertGameObjectToEntity { internal abstract void SetChildEntity(ref PlungerStaticData staticData, Entity entity); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerFlatAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerMeshAuthoring.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerFlatAuthoring.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerMeshAuthoring.cs.meta index dab14baa0..9390de5d9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerFlatAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerMeshAuthoring.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 7a114cbed30a31e48b46ddc8c8f8adbf +guid: ee03bfeb25720934c9ce512621cdd53a MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodMeshAuthoring.cs similarity index 85% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodAuthoring.cs rename to VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodMeshAuthoring.cs index 6c4e5582b..21cbff73c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodMeshAuthoring.cs @@ -16,12 +16,15 @@ using System.Collections.Generic; using Unity.Entities; +using UnityEngine; using VisualPinball.Engine.Math; using VisualPinball.Engine.VPT.Plunger; namespace VisualPinball.Unity { - public class PlungerRodAuthoring : PlungerChildAuthoring + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Plunger Flat Mesh")] + public class PlungerRodMeshAuthoring : PlungerMeshAuthoring { internal override void SetChildEntity(ref PlungerStaticData staticData, Entity entity) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodMeshAuthoring.cs.meta new file mode 100644 index 000000000..23b0973b6 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6e7622b4c6837354c8190ee471830c31 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringMeshAuthoring.cs similarity index 85% rename from VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringAuthoring.cs rename to VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringMeshAuthoring.cs index 6afce4d24..ba661c005 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringMeshAuthoring.cs @@ -16,12 +16,15 @@ using System.Collections.Generic; using Unity.Entities; +using UnityEngine; using VisualPinball.Engine.Math; using VisualPinball.Engine.VPT.Plunger; namespace VisualPinball.Unity { - public class PlungerSpringAuthoring : PlungerChildAuthoring + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Plunger Spring Mesh")] + public class PlungerSpringMeshAuthoring : PlungerMeshAuthoring { internal override void SetChildEntity(ref PlungerStaticData staticData, Entity entity) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringMeshAuthoring.cs.meta new file mode 100644 index 000000000..57bd7ffff --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8506b0486aacff543b92dd7de914f936 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderAuthoring.cs new file mode 100644 index 000000000..28f8c80b3 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderAuthoring.cs @@ -0,0 +1,26 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Primitive; + +namespace VisualPinball.Unity +{ + [AddComponentMenu("Visual Pinball/Collision/Primitive Collider")] + public class PrimitiveColliderAuthoring : ItemColliderAuthoring + { + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderAuthoring.cs.meta new file mode 100644 index 000000000..e4221f124 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 67cab808aae52b443ba94f88828afcfb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 5dbfaee5cc1c57642899b18f76ebe3e7, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs new file mode 100644 index 000000000..50a0d4a1f --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs @@ -0,0 +1,27 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Primitive; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Primitive Mesh")] + public class PrimitiveMeshAuthoring : ItemMeshAuthoring + { + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs.meta new file mode 100644 index 000000000..14753cbca --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 882edbbe53953ef4ab3b3f846c4a5d9a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: c58fe86c7ca8cee4dae3a63686530e0c, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberMeshAuthoring.cs index 246f359df..73766afb3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberMeshAuthoring.cs @@ -23,6 +23,5 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Rubber Mesh")] public class RubberMeshAuthoring : ItemMeshAuthoring { - } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerColliderAuthoring.cs new file mode 100644 index 000000000..599bbd2ac --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerColliderAuthoring.cs @@ -0,0 +1,26 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Trigger; + +namespace VisualPinball.Unity +{ + [AddComponentMenu("Visual Pinball/Collision/Trigger Collider")] + public class TriggerColliderAuthoring : ItemColliderAuthoring + { + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerColliderAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerColliderAuthoring.cs.meta new file mode 100644 index 000000000..d4c8c0b53 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerColliderAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: aa0a7cf5285df584398ad5f9d98e10c0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: fe5a34c853bb88e4298ea10370cd38f3, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerMeshAuthoring.cs new file mode 100644 index 000000000..cd0ffad5c --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerMeshAuthoring.cs @@ -0,0 +1,27 @@ +// 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 UnityEngine; +using VisualPinball.Engine.VPT.Trigger; + +namespace VisualPinball.Unity +{ + [ExecuteInEditMode] + [AddComponentMenu("Visual Pinball/Mesh/Trigger Mesh")] + public class TriggerMeshAuthoring : ItemMeshAuthoring + { + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerMeshAuthoring.cs.meta new file mode 100644 index 000000000..220ff5103 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerMeshAuthoring.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 12ec3c1d7933a674b867fada1788b0f4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 904767dfec06b58419ff6c4f6af2e4bc, type: 3} + userData: + assetBundleName: + assetBundleVariant: From 4a9f811d213b0707b5d2290ca766cb3df88ad9d6 Mon Sep 17 00:00:00 2001 From: freezy Date: Tue, 13 Oct 2020 23:38:49 +0200 Subject: [PATCH 073/124] editor: Add missing mesh icons. --- .../Resources/Icons/small_blue/coil.png | Bin 0 -> 572 bytes .../Resources/Icons/small_blue/coil.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_blue/light_bulb.png | Bin 0 -> 542 bytes .../Icons/small_blue/light_bulb.png.meta | 106 ++++++++++++++++++ .../Icons/small_blue/light_socket.png | Bin 0 -> 519 bytes .../Icons/small_blue/light_socket.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_blue/plug.png | Bin 0 -> 400 bytes .../Resources/Icons/small_blue/plug.png.meta | 106 ++++++++++++++++++ .../Icons/small_blue/plunger_flat.png | Bin 0 -> 503 bytes .../Icons/small_blue/plunger_flat.png.meta | 106 ++++++++++++++++++ .../Icons/small_blue/plunger_rod.png | Bin 0 -> 500 bytes .../Icons/small_blue/plunger_rod.png.meta | 106 ++++++++++++++++++ .../Icons/small_blue/plunger_spring.png | Bin 0 -> 516 bytes .../Icons/small_blue/plunger_spring.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_blue/ramp_wires.png | Bin 779 -> 900 bytes .../Resources/Icons/small_gray/coil.png | Bin 0 -> 580 bytes .../Resources/Icons/small_gray/coil.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_gray/light_bulb.png | Bin 0 -> 545 bytes .../Icons/small_gray/light_bulb.png.meta | 106 ++++++++++++++++++ .../Icons/small_gray/light_socket.png | Bin 0 -> 522 bytes .../Icons/small_gray/light_socket.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_gray/plug.png | Bin 0 -> 405 bytes .../Resources/Icons/small_gray/plug.png.meta | 106 ++++++++++++++++++ .../Icons/small_gray/plunger_flat.png | Bin 0 -> 504 bytes .../Icons/small_gray/plunger_flat.png.meta | 106 ++++++++++++++++++ .../Icons/small_gray/plunger_rod.png | Bin 0 -> 505 bytes .../Icons/small_gray/plunger_rod.png.meta | 106 ++++++++++++++++++ .../Icons/small_gray/plunger_spring.png | Bin 0 -> 517 bytes .../Icons/small_gray/plunger_spring.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_gray/ramp_wires.png | Bin 793 -> 901 bytes .../Resources/Icons/small_green/coil.png | Bin 0 -> 575 bytes .../Resources/Icons/small_green/coil.png.meta | 106 ++++++++++++++++++ .../Icons/small_green/light_bulb.png | Bin 0 -> 543 bytes .../Icons/small_green/light_bulb.png.meta | 106 ++++++++++++++++++ .../Icons/small_green/light_socket.png | Bin 0 -> 523 bytes .../Icons/small_green/light_socket.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_green/plug.png | Bin 0 -> 404 bytes .../Resources/Icons/small_green/plug.png.meta | 106 ++++++++++++++++++ .../Icons/small_green/plunger_flat.png | Bin 0 -> 505 bytes .../Icons/small_green/plunger_flat.png.meta | 106 ++++++++++++++++++ .../Icons/small_green/plunger_rod.png | Bin 0 -> 503 bytes .../Icons/small_green/plunger_rod.png.meta | 106 ++++++++++++++++++ .../Icons/small_green/plunger_spring.png | Bin 0 -> 516 bytes .../Icons/small_green/plunger_spring.png.meta | 106 ++++++++++++++++++ .../Icons/small_green/ramp_wires.png | Bin 784 -> 906 bytes .../Resources/Icons/small_orange/coil.png | Bin 0 -> 577 bytes .../Icons/small_orange/coil.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/light_bulb.png | Bin 0 -> 546 bytes .../Icons/small_orange/light_bulb.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/light_socket.png | Bin 0 -> 525 bytes .../Icons/small_orange/light_socket.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_orange/plug.png | Bin 0 -> 406 bytes .../Icons/small_orange/plug.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/plunger_flat.png | Bin 0 -> 507 bytes .../Icons/small_orange/plunger_flat.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/plunger_rod.png | Bin 0 -> 505 bytes .../Icons/small_orange/plunger_rod.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/plunger_spring.png | Bin 0 -> 520 bytes .../small_orange/plunger_spring.png.meta | 106 ++++++++++++++++++ .../Icons/small_orange/ramp_wires.png | Bin 787 -> 908 bytes .../VPT/Light/LightBulbMeshAuthoring.cs.meta | 2 +- .../Light/LightSocketMeshAuthoring.cs.meta | 2 +- .../Plunger/PlungerFlatMeshAuthoring.cs.meta | 2 +- .../Plunger/PlungerRodMeshAuthoring.cs.meta | 2 +- .../PlungerSpringMeshAuthoring.cs.meta | 2 +- 65 files changed, 2973 insertions(+), 5 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/coil.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/coil.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/light_bulb.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/light_bulb.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/light_socket.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/light_socket.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/plug.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/plug.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/plunger_flat.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/plunger_flat.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/plunger_rod.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/plunger_rod.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/plunger_spring.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/plunger_spring.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/coil.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/coil.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/light_bulb.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/light_bulb.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/light_socket.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/light_socket.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/plug.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/plug.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/plunger_flat.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/plunger_flat.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/plunger_rod.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/plunger_rod.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/plunger_spring.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/plunger_spring.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/coil.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/coil.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/light_bulb.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/light_bulb.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/light_socket.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/light_socket.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/plug.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/plug.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/plunger_flat.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/plunger_flat.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/plunger_rod.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/plunger_rod.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/plunger_spring.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/plunger_spring.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/coil.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/coil.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/light_bulb.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/light_bulb.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/light_socket.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/light_socket.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/plug.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/plug.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/plunger_flat.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/plunger_flat.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/plunger_rod.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/plunger_rod.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/plunger_spring.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/plunger_spring.png.meta diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/coil.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/coil.png new file mode 100644 index 0000000000000000000000000000000000000000..0486767be2d6e25c4ef20ff403081f5d86eacbfd GIT binary patch literal 572 zcmV-C0>k}@P)+Fc60SMtz43n%6v$4ax@X2#nATYBpd5Mqq=& z2H`2M=?1VsQdv4nCkwbUzEp~oUy6c~*!dja{b!4pVHhw4y;?E4wl4vE0$8%kdsh{m zMgJyWlpq@bi|E!BKy3kAQK+7lZsbvK^x@J&o&7jtr45(O{$jl{+ zSw6bw+I}sx@1&xjDWMwx--_q%X$9a%cxEdVhB-#9rJ4FYfFu3(u~-9G)A?3?*XoxR zGX6M7Z8V@hk-iA*%>c>|x^Y!;N$EfX>c8GcLZ4>_<$;chHllJD&L;-tEk*_9+PS(=L7)R5(_eb{ai3^{(yX?9WX! zajT*&p)~_5Goa2PbW*c_%o1vv{Z`xMQv{_=v@ly2X&|YfJo|$sX`y0E;@Q8IGG7CF zWM4|PKUZ2(k~H>occd))N3kR>_0*4GNljEl@<3hN`>fw(tdv6bch4?JRG<`RTF4Xg zNwWnBGVLkXl6V;Hs8nZxb_8W@NlDUV{hn6&5)@Ce(!!FslBYh({xZ{&cmc@+rI^|n zSW*n;&msHs?a5$Y&$XbCh{Iyu*Z;e;i;}S=zGE`~GfiXa0sH}ur@Xv_T~a3i0000< KMNUMnLSTY_YX4pU literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/coil.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/coil.png.meta new file mode 100644 index 000000000..54cf91d6f --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/coil.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 9a17ccee81ecc1d498631cbb36cc38e0 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/light_bulb.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/light_bulb.png new file mode 100644 index 0000000000000000000000000000000000000000..7feecb385d6b022bba378482548239972ca89d16 GIT binary patch literal 542 zcmV+(0^$9MP)FGMJg3Z+m{ar_Xk~9oit*3d%Nto?99VMcDz+ zm!GTP-NwqcdXI*p8~_*r7y`JgHE#jT0ZfB;kADIhin1F40Nf`Id5Rwtyj$nYmjx`MU2bGI?rUa{M#$-}#2z`(^t<_d+C5r-;Bw}O$I%2bb`pp!) zi~DNAj;m-QHYjN_{FqPPki%Yrcm0HZ-=ukk<|HZEiA^?W#w|dd^18I|dL{_a`?9KI zf>Lj!x>TUDlqomBM6>L$C_o%br&W8BXLM7xzOkr5S=64cB&=REborFp(}!jri>2=! zfP}R5w3D1vAva}7Rm%3+bbh$)3lK`wJb~H(W`g0|I8kQ g|B=aB?EnSv1@V50p>-O)SpWb407*qoM6N<$f|o?^J^%m! literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/light_bulb.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/light_bulb.png.meta new file mode 100644 index 000000000..6dd3e0c76 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/light_bulb.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 039bc0850ebe18a4c8127063deb4ed27 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/light_socket.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/light_socket.png new file mode 100644 index 0000000000000000000000000000000000000000..4aabe1627f961e8e32bb2f0ea17e2bbd946192d0 GIT binary patch literal 519 zcmV+i0{H!jP)vbd_0S-8VwGNkPNnKEfPGZjsCPrkYPclTZ$4hM`uVHA{O0=@P$qo$nzxZ}TD ziec~NZJwjlv{L{DfEj>E?{xxQ1E?v6&7Xi$)7}D@1DIxZNuVo=VW;_?3Y4Sx^g{%H zQ;P6X6J7CQqNYuAuv9>T`;_bS zOOlAr93jP?642ajNTO^{38=^1RC}IfL{%q>m*-i6nv#kEt#cbnKx;3$j{HG6>+yuG zC7G1;2z}uU$f`YiWlNTnd}Zt_2hf!?`i%N@m#hHb0py5+uN zS#F`r6ZQF&8dR|hh*o)D)_c9=5D?GHu1*Q6nbY4gf$~u1>;RQz*x^xtIF&A|_QVB= zp(J=?E$6_g_LOd>uK;can!E#epcqUEjmOZ>k3fRo&8;7~s6uYekec&YGbqK7(!Rx! zCJSz3lG{E?O`BHseedxb#o%(y_AHG*^RFxNGXFoByfqF`03Xg7g!8v$RGk0-002ov JPDHLkV1k|f>skN+ literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/light_socket.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/light_socket.png.meta new file mode 100644 index 000000000..e82be4d70 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/light_socket.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: f08d55a443ff6344784eeb959c60f311 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/plug.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/plug.png new file mode 100644 index 0000000000000000000000000000000000000000..7c97db9cc32c6cafe6a81a1c2f9ea8b844b62f44 GIT binary patch literal 400 zcmeAS@N?(olHy`uVBq!ia0vp^S|H591|*LjJ{b+9I14-?iy0W${Xm$pP}SUmfq~J< z)5S3)qV?^Ji@8jOJZ<%hs`ay;yK1I4AU5%O`X!X z$J*%nFAXR6Pk92}K^@r))eQXMm$E)huUK`|b?I_}%X<6%DXcuSzT9Mb^>Lr~nnzLv zs~>M;Zn3>({^rRtA?Zmr;bB3)wmyh_Vt=!E^8X?m*-N+2_`cIP;_AG9?&lj5b}PL< zwehmcba(esl|SllIIgByrPtcJ=9*|Lrn+d+ zPL2oK_jg5jc+IbSGIM4%LxEP(_nlKFl&f0?lsGkCiCxvX7O?Rc zJVLjw?PfOEU?C{zB1Ko*_1)Q(kn%}Uq{_9w#POeVj@q^br&<3rJ3q#m0;mHmKIllM zIiKu|e=HQ@Tmo1EnC)rz3E&ODN;{B6^aj91V%t*y*K}d80KTMyP2_%mNF;~M0o-Z^ z)QB#Wl09>}vm!L2OM|4k4~^)V;y;`jB}Fn)(NF|w5cMS$72SoLXjlCx8e$a9%_y3i zQ8YLIMpRmlZU8(Ka)~ldeQu;v-&H(UMh8b*k(FfACl#Gig}#q>lG)JNX?CL)(IH!p zgh?ibRJ4j)r@$krub}v| tEqaY=M17GIlF5ctw7Xk(rDTEt_yq&-UQn2doz4IN002ovPDHLkV1f+x(&zvH literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/plunger_flat.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/plunger_flat.png.meta new file mode 100644 index 000000000..969c27419 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/plunger_flat.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 766a202bc6a0ae14cae40af04c122577 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/plunger_rod.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/plunger_rod.png new file mode 100644 index 0000000000000000000000000000000000000000..865824aea1e750df1bd4b9608e51057206cfe975 GIT binary patch literal 500 zcmVU*@dLI8A{Yxmx>?>R9$S3QoW#wXw|Qx7g$BLSw*#3MYZ`i zqAEN5C0K`En|r1{V_ga0In$v9&;j^j9!V%s02=@ggiI4Y{rO4qtTe!i#{7{OjvN_H zQ7`pws-nwjH0rk>g2DaiPvjHb*coO^2KkBOY29~ReGB9>7@y6U$}KbFk3>QlsN zKrOngp-(WC25s&Fl!%^1l9tRR7T=UaX+Zt3Ifg!!2IB=-hiNjesIhJ;l4eT-Njx2b z*rG_{Nh&!`gO(|*IY-YTY4}bf4Or1Qtbb)RUM5^)(RdoA!K@qSTV$ppshpVG)NPa& qHP)pfX-Y;7HlBQM(Ju8mvSMl;84{cso%fJr*Widw8GY(RCMh~Y5>;ujZ*`Moy@>)K&4MJXRX>WhFp5eu zib^wzO7m|-MRxc@Fy4A;4k`7_?&*fDVX literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/plunger_spring.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/plunger_spring.png.meta new file mode 100644 index 000000000..92f02a35b --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/plunger_spring.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 3d4af1611b5690d4aaafcdecd17b00a8 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/ramp_wires.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/ramp_wires.png index 0bccb23998ee1bc917b4c89a7a0f2b89ea92c1ba..58fe21f1bc1222063ff65559f23d2fd5f18ab79a 100644 GIT binary patch delta 857 zcmV-f1E&0o280KYIDZ2+Nkl{El6L$)lbi6(Cm-k_I3hhzfjN zK|}?%D+sP2&_IG;qDMmqP(b9&CFhch%kdzTZ*!NT%65qo1(V>9;GPHVnb>>^&Kfng;N#V0A>Jc0Drmw@_2}U+R4?=UqZMH zz!<;ZUSJ$zBs^EOj})mN)m<@I9u`#!&G!t zeZco{RaJ!%pnoAn8O5koR`gHjyMu{uwA%RUI)2OqfdVB?(%nSlGJQ^BYr+G3IqBNf^HbXq|&9T#xsr z@`Ju2Nf_|GlqS(+$_4woCNZUH?QK453uh_HjCmf+`+wlF*W8DOrVxJ{S3ko6nsjp}TFMZJ=j_GXjgVQ`&;9lQ%=6_xVutl}KInm3;zD>jWJA2>;c zzm_CC%YHAmUFHP*{>ql#Jl;>JPaCx`*ysHXRjyZ6J=(tBnU6WoM_#}3`i`-+wa&4Q zegNUZ-ki~5;4)!O@Mo$X{Q!dTa>^yo>7XF&%zr&wQ8d;`iNRHO5q|r#k^rKBt|`>5 zAXo73Zui@c3d**rQ2*q1ze`o4p5{qWP8d6Tw9gxtv3~Hib9JiNr+K#IT~<(Yg4YQQ zLPtM#T%IW~Vc3%UQ=0{7^n+X}$^ld8HM5h&Q3ZeGYv-@wAa|*v?i>hNBj|GZUlVA9 z+fp0rr_MC$(LtFeAJ|PDXp>cx)&%+KmNAam1}ynBzl#*5g)7h;@LE7~f-S0hNy4+E jqyPWDdFl2xKmq&)gNj!PT?rSs00000NkvXXu0mjfCgP<8 delta 735 zcmV<50wDc_2a5)fIDZ1YNklF~RDe@K>E!P1h-;*({MlY^4;Gl6{Gv48v>z>Labo7(53t|#XS zz?TRl%M*aTWv^$$qWuS&es4PTUUencAg(9p*>%^EWp?#~ z%3=+@R8_*(zJDAP)bP`tKyL9Tep&xTME_U(b}jUdQF4AFr;kB?uGdJ3zefeK5x=4I zvZz>QqtwR_R2Hk6z7`tjh+p;;x7bb9xw4Zf(P>a`i-yo>lqz(G#~WVH0u}dtwEWZ% zk2?vCV`qv~4&HZa22DVI6UZtaQ&zvP7k5J^+nJI{YJXk~k}We0l1A(A%K);9_ZTEw zl#khdL4v(*kIG2DVgXi)=XRmf8_XX7qp zNSb$47Juqx?+BU+8Ec=d_%bw!Ry;;Q2ZRjEkG5~4Nu=cB=If8COf_Rdw%TVBlv`+| zrdc7w_L&+)IB8Znkf={jLm)=;8Ws@ErvbJ>H&XlGPX!k|hgNpcs}XrqLh);3t`&_EHV* Rmc#%6002ovPDHLkV1h0PVV(d0 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/coil.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/coil.png new file mode 100644 index 0000000000000000000000000000000000000000..9ec168027e4a592b33715a31e19576c4c67a3165 GIT binary patch literal 580 zcmV-K0=xZ*P)7Fc60SR((%5C>xXw+6~$VBzVjS-Jr<^86l4# z@z4#LY(O@k8zd8?vUHYCR_LAaQ3;7(LPUVgXYBj$tlV9%SIj{VR*ZGiW&qv+JhIFC zsw{eo{!P9pL3RLE!L18`+yeGKwFA=T1|;a(#^ME5pxMZKYFU9!t_9Ru3#heb11cIm znYm;!I{?oE_f7ylg!a9Z6f`Mx4d7Gp+>qP=zJ+JDQes%vsI@dxzXx!j->x#s0ld=r zR({v&hYA^Yd`WFIpcw^&1A8)na)a)wvN*?dpaFGX?=7Ow6N7R<2SpoEsfF{AK{<<2 zLDfy0(+v6Jt164#Uv0FY7dCA@eW^|f<=1mY=a(Cgi31cttFqW=i(dxikD(+Gtx;27 zH*FaGsevYLRYXuqp*aJ~5};0g>BL6=lqu9S`mMIh#{fzjXnwZN(m-NCdGvcr(n5un z#G`*JMZN~~z`m4ff3CEoC~53zaHK5yC$S_h_0&&bNnMac(m?B`T~h@=wo>xZ-;XUw zRG_rZw2(*UlV$}8674C~lK3*(QL0V??Fq`-lA@%E`aMS59&oqyz2k;Bkt-uNA SfPe`A0000jXal literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/coil.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/coil.png.meta new file mode 100644 index 000000000..bc7f16776 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/coil.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: cc5b6463382a19347bc4ae0512d1f32e +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/light_bulb.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/light_bulb.png new file mode 100644 index 0000000000000000000000000000000000000000..1db70ae8d8d9e7bf09c6006ff430495cf99c1408 GIT binary patch literal 545 zcmV++0^a?JP)>$xH6epadY%azGNwLQ$E)w+5B$vXE%GY-EPqZopyqU2@ZeAK9v;Vdmj=y?((l1%cA|!EoHa{k00kO!Y#Kx2v z5bRMoJa4gNExHOlT#QG@nuM%P26Pn1qGOW*?ZvU^*knLMFLp-3HW|?OUjPlZ$$&k`kTRM1w}$0@NvQD)n8@1Oa+q z)^$iw>W$P?5~wU?$PJLCEITv`5Qoxn)t=-T-IlGdHEK{AwWmu7tLH6UKBe~bkus0Q z(hv4PLfQtYlN?ncH)KhZmK_?P&YD*Mi#=Ty(kDqOOYf|C@~3-8(^}e+rCA#HUcGJn jr}iNHk4)O?1}K0px+ITrF!}L~00000NkvXXu0mjf`M&Nq literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/light_bulb.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/light_bulb.png.meta new file mode 100644 index 000000000..56d56bd1c --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/light_bulb.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: afe13153fabc7c84abbeb8e0e34950f2 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/light_socket.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/light_socket.png new file mode 100644 index 0000000000000000000000000000000000000000..d4a08a96310c0622802cb85a5685d78371f3020e GIT binary patch literal 522 zcmV+l0`>igP)SlF__jg@usbTviM+WG#dQ`#M=pox9*>H6>bUhVgLOhMO^pqvuujip(v>KTB0 z`r8NZc2?f%IU1{a4xj+A05BW9PM~W5UGQ%6C!n#a?*J?T%rmNE#S0VJqTNggb*Kxwg*0>H6K^2!!BqEEs|jx{4Mdr(?Dg_dxj zf;_XtiRi)*lI_U>&E1AL%J$@dTFgzc=UGNnbfQ>!o+YR%sW_l@ZbJ@eXGJ%VJt$>8 zmarWslj0tsuap64wIi==u|O$fZwx>iZuZYk^MZG2UbWnQ1GVJAlIU_5yi3E@3%d5y zmo3dLG@hu>m&BlgU4XU9$I{;GIfnpyUJi9iP|2MBmI{=HGG_;9HNy^z0>r6wS+yrB zNE}LnH`;OzjA~EmX8H!;_CS*l0FS{tRYGGi^vffVpm$5{M=q+6n=_>9JXQ@Fyh~}{ z>PV9nwNc4zAB|O=R`$c_@ius8a?Q3ZjX%?Gs23~q|C7mD(*OnV2_?~ovuA6?!2kdN M07*qoM6N<$g7QG=+W-In literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/light_socket.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/light_socket.png.meta new file mode 100644 index 000000000..a6f151226 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/light_socket.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: b9a6e962e2fde91428678f3acb5afcc8 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/plug.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/plug.png new file mode 100644 index 0000000000000000000000000000000000000000..3b18a67a3eb848a255a0f35261330eb6221381c2 GIT binary patch literal 405 zcmeAS@N?(olHy`uVBq!ia0vp^S|H591|*LjJ{b+9I14-?iy0W${Xm$pP}SUmfq~K8 z)5S3)qV?^JgTBm$0y%b z<1nq!(3o?L$$N`grExZ!le5zwTO@Ja@i`Ras^8G%wRq8`6)Q~U9;vcBV%Z>fK$-3;(s+YwZAUgkHN*D%ORhfI|7f3B`qX>vGs-^xWcL)T+q-z@o&Fr;H+a_6eqD^JelFT8jmd;ZSs z6S0=rr#4=8neOghs`5wu3&+$ntMuBuPm!;ifBNi;%I}Wx;@I;`;Pe`kd1{94=5{Wh zBA#??dZyG+ysvcPgDG}@PcR#PXLt~DWL>dl;k7w69oCE9%&RuqSal_GGwX*Vk_2xE`H1_Kgoa1_|!7O=Gv zhu{c3Lc4_xHkg8fUZm*NcKv?am5}mDQKZVXzr^vM=NvRm1I=Rj_OSJ1m=S=9r^Tln z(cIo#Z;gLs6w;gnm;)H^X!ix+9l(kmC`I%Nz*%J569AWTVG97?*1-<#et%db`%K%J zWd>wKXQX7uRPL+^Ms%JaN%z5so)Z7jj3p_ev5NX4h{4pCRn&ABa>B0qLDa_}nwvp1 zH-l(y{*9=$9$f=?EaVbonEKpUr@pOtE)pGT*@~K>#mfH7XZK4;a*S!Y=6@L0000B?p-_Y5RWu5(z1f6jiBe`>B84+RaVdwn)WTw+8SqQq7?(@sJhr5rFuaV(W+lW&#;JUvxsW5 zh-&k1L{)b9bFd7(Hg`;Y#<~o^Q=&r+paJm397!lq04o6Zgv=ql`un5gtkl7Z#{7}! zt`r$fQ7`pg7I~A>XxQC1Og)puQ;_jj7EPH|xc5}d9}_7<-z~1bL@c9*bk(otK9)?i z>c@!FfLe4(LqEb$8q}!^P$GH~Nm?@Jn0-?cr2+NDrWpFMH0UqDDom4UMU8bsku+Hv zNaAT1#AZbjPg2Q#8q`c-%{h7!N!@!IX~2rcVf`zk@i5^Mv&K^|4JO?0Y&K)KT9zI(XjUhZ;G6b1UClJo?C-%uux zqcHC~MlVs7q%#2X7ReGVx{Ranl{*$&R3+&Gz>L`KLwAj%a7P{QklF!!NlgG?!5Nb* zs**HdN|sE`BSV5Sqw^k;>>3==DWgvn-y}t6NTMo9_pNS{tTRynq*;)JwdzOF7DiEN zMp0=-QEC2-sK^d~2*z74%@L)Z**)Dd9WDTzTHC~jI0~P;b|#6M-BZx=zi(Yro=iOe zXEoO<%D_}n)JS;d`!S_t&6RJ-Z z{RHr0N#y3^9FFLcAr)9{xe(XZ9oUQHGfGW^38gqybYk9;cvfaQk0vlguK?URa%shN zJZ&qHlv(ZI@w73mEhC-=oK^o+3GhMSh*IAgH>JV*(D76!p?|v+sQn97^c=vAE15Pp zqSpfB>NNOvDN12evnR0A;B83JIvFQvKo!-q@JLy$A^`XSl$CI2ZYG}B00000NkvXX Hu0mjfn2_Pe literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/plunger_spring.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/plunger_spring.png.meta new file mode 100644 index 000000000..d406b6ddb --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/plunger_spring.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 429c13cb488527645aa9878c6856dde6 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/ramp_wires.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/ramp_wires.png index da6a7f7c2dda0fc7dd32d5dd0a89f5ab0bf292ef..fbda10b17198943c21e14ee68db6da9deae269ad 100644 GIT binary patch delta 858 zcmV-g1Eu_#289QZIDZ2-Nkl?q+O`eJ*3^x}qzuO@_K9dgM1L(J8WK@#5AmNh6O%@O z3yH`jqI-Zc+z&jr4%z_RK*15tbcafDoPTQva&rW$nNk9uO1LtPJWZxK9XKtneHWAy$iw zpn8sbxv~|3?-iFEz)qQ`RGlIT6iB5nf$wplB4O+P#NU{sj~T9c;Cr)6fI8@u;YPR@ zm0uY$@VyM*xo`yo=D=pREL71$0lL zE(JM*|5m%-zEx1zp+fzu+Wl@+wR)PDn6yCb9Kk;)Dr5b@XLr1)Y@g=Iln+rsEdlNT zm;i14*l}~FfP^7au1{^&pwpM`NB{r;07*qoM6N<$g8HhPuK)l5 delta 749 zcmVVJcRDs2`3ZUDSbg&oB8N}DqPD*$h-PxGoQzDd?NI)A9rX2Ot99G`yym{eu4 ziLG-~*DGz70DgENNp1n`Bx^m+i}pv@)#TE50kw;&ESAzWvx8DrGvrH;3b}h)mBkwE zL+z@vnEBSt>UyQk6u>$Fc@1FHfTZ}{u;tH{HeS$d$;74SQ$VHVYL4HJ4!u{d6RfkxQ}1bf9lb{i(l7=-Z84Q8S&|Tkl&j% zlH>0t0NILPTY6cPEwc{P$In$+EE@Wu(10U;$y3x~*LCMgPNqnwL9;CiLZelx;0}+s z^gRib-S<_psURM=92$qtOf&9skbv(wbet*?0?t)IX6(tkbJRc-kW^5%* zsK3uG$U5GAkYv$iG?^laaLtz7AzZ}anw0oZmw`iVdHvfUXav%BUr6_`VM9N3DA<+5 z3o3;a#FuULn0~911wkW_hm-QAp&`V!`iPUvr{A%BEuCbFK+Y2&FC0m;2_1@KxC05> zq5{aekblQ!&emN>kTf5vvIt)G4xovUzV_LPFF}*&#G@B9Bcxq^LhH7gL`)t%d;Wqp z|1vNnCCzJJJi6qrg?eh56w+>=u|b5AX3^~NVo=^-)u?S!$kt$yTCP&0S)OLR@v$K1 zeIXH=M~?t0db;t6uQR1U#*%F6yI%Y?D2;8IAZA7HN)mC-qwJ=ue+3eeTj+w}P7WCa zWvD5SX;R46w4YN_FL&Z3%Pryuh*Lr$@ug&TDoFHjy*>C20*M}PPZQ2+3<*h+1jYM( diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/coil.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/coil.png new file mode 100644 index 0000000000000000000000000000000000000000..50b6ded46082c07bc381be139c8a718513021252 GIT binary patch literal 575 zcmV-F0>J%=P)+Fc60SMtz43nhnSXWrDQNd18caP}qPGc*--% z0)-922I&T{K&UL8rIQ8R8DAumouvuycr1cF*(6zP23#>r%C-13c1vo0EMk)+bj9N=G^*aCu`t4$|0I;O)kU@CR(Sy;5rvB4q#o N002ovPDHLkV1j6a0S5p8 literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/coil.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/coil.png.meta new file mode 100644 index 000000000..a33143077 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/coil.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: d631e1f5853805547a7cb4dfc01d6ce0 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/light_bulb.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/light_bulb.png new file mode 100644 index 0000000000000000000000000000000000000000..00a6e854338bc1b8953b2f86386194ee893c1cb5 GIT binary patch literal 543 zcmV+)0^t3LP)R9J=Wn6FX;F%ZT-G6)=%$l~fK4o9CLQ+=wBz@xNp(3cbh-E*^}*di#Eu$g0fAZrwNG;aXR0ZhFM_kRLfRz)`g0Ju#Y@(@4ByRgccFAG$> zIN#yH?-V^e%<(P_T2@8egHP;44PAQ|mdpSOR1V83!;?)#&vu!^#$Hcj14xLCF*6|9 zqjGp&bIJDTGWBpV9vxZ|vNjpeK^}{ZO$M}+$6{lX0ZqNw8713fK;M16sTEyK_Mmbx&y-+w&6rGz4WV}ur?uLMtz=Q4l0=LQKu2u$PrsSG z3vpjf*l{&Y#0Dizh9C3ED{|PgccGuq?~63A(3~VCJF&?I&A0`qQ{I&JUC#sodSBM{ zo1oMisVNnxEM>|KFwrbKED8|6rQ@nS$uoLiw!XHgL0QzEE+nj;?dkF%wWoK@JQhpe zI{*o3>uD!BszPqclB$*+7NFjR7XXU`T^7&CKwb}s+;1lqtj=SM7l%D_q002ovPDHLkV1nB}>V^OS literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/light_bulb.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/light_bulb.png.meta new file mode 100644 index 000000000..f942e005e --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/light_bulb.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 5170da6564fb34c4d935c14c6cd71983 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/light_socket.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/light_socket.png new file mode 100644 index 0000000000000000000000000000000000000000..ddabcf3478b77388a2c46ed4712009afa479c405 GIT binary patch literal 523 zcmV+m0`&cfP)HwW|h)% zMM;^`Wy+*W30*21EgB)q!eQq}MoxHAirBl)pJxAN=c;X6OhIlElv4t|wlu4nJOgk? ze-GY;qm{RMj#f=R1F!%v2axq%N6;;R+Pkp(6VR&3ZviX;%o4jq(9*l`F8Q7al%n|b zLj-?QjPP0#UG`$Cnmo?ILI4TsQ;-KsEKpi3g#fUxg1nN&jp(B=l6__5We-Y=XQ3tR zXhEJy;zV?A2+8*3fTnIk93^{lKrQB`*z+tSDmqcDJkJtTl~fF9o7#{AT3gX|WDiPN zk0or)$)vbP=qqJFS{=zNSu9Y>*h>S@lAHar(>(7&oL3uezm7KK!IJ25=Us@yb`W$u zP+zt*x6t)SeZC|H73>16Ro<8OUe7rM*z>ZhF+nAB`dcbc8p@O%V51p!SQH?}(q+}2 zs30+v1n;!v92nJ};?498z|BCD4*(C|1yw?0G4#t5kf3)O58r>RpIw z-|9q@6}3^xY#*(fJg)5f-s8P@!Q`54SsH()Uso?y=Km*?wWa|I;1dkAhfDNNc{Bh3 N002ovPDHLkV1hpP<6Hm$ literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/light_socket.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/light_socket.png.meta new file mode 100644 index 000000000..d6d5ac678 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/light_socket.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 380b05bc5322b914ea1d33a47c43133f +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/plug.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/plug.png new file mode 100644 index 0000000000000000000000000000000000000000..6a0bb1899e838dc09b2e675dc311bf6bab0641a0 GIT binary patch literal 404 zcmV;F0c-w=P){RLN^D5-R9Q~x*NkV8|71^1{>$-nNN+PWxeL)fH1yhM z?i+Gf*7$PlG|}bJQ5^~Y2|Yrkna)|Cn|#*#U_O&?*4rYN5&~}_x-u(`r%BAwO^A*> z7CEAY2^bLz90fMG1uTe} z6L5qcq20m;8!QABy-3lk?fU(;DSdUfaA!vhXBsy!d?J;SqB^0{r<2>_L%~> zWCmnJXQX7uRPL+^Ms%JaN%z5s9ufc1Oe86yv5NX4h{4pCRn&ABa>B0qLDa_}nwvp1 zH-l(y{*9=$9$f;sE94SnnEKpUr+!`WoF+OnvK3iaHhosnu~g{Wco&(aoEv60nj+d~ z<&a2{31JmoOFb~VNJS-mME7GAwFp*n)bhy8h^R(O)Ji5B?5eNiqr%Q8 zwd#HJ)4;UoQm5X9D-D{|1;~hgdm<@WCInNI+$WCNrGe?fN=!XGX`mP2&f-Z&l1nBV zOg!BHI4B_#f{7x^&ol`QrNU{_@2iES@q3qUUE*#h{Gv`LFvXP$(T z9osNvC?q|4h>#T5ArXBMlo_%KNpUljsC8y4f+SFNu{}!lf+nI>zldI75!Gf9)n*aZ z=HG~_?C|Gc8G3E*nfk0VIe_O#hZ;Zw;EOquP@(`<03HaLD!lspljN+_!HV|zBhg(k zGMb`Z>b=OyCZ^G_yKk6!lEqVy@mJoPGOKX!IWm7t#0-76xP}sa88xJlDWj}o047{P+u&?&`+hoZ~-2}G)XIJof(UyWN9FY zr+pBc6-hivC5LHHGlezh=vgFn?`fm~E7}k1Um1;u3D=l4o(5@R1@E^>q<&G+TIh>!=$l{WX?!zK4}mxH1x&=-}*#{hzcGFjv$ zS>G{wiK;xF0hqT)mT1v+?6ib^wz zN;8T|^KV2&cKAau-g;>cDfP_m>4xcW4&cPvCf-M0^4PUAN!09~!j}I7>zeXp>H|2f zxpqkzm@0}I3EzA_V$|vkRa74#?pz8r!I@DiU*=q&0@#@&vu>aNLUe0Mz>-OY>XSu3 z0X$g}nfW+}Bf4ftg;rZG#24!h>_ze!rKZ7zQk*I}F>gtHD>I!(6BweG0B#+*wBkCR zwv|Xqt#Y4ARDJk?3)-!24d|3Vc#190t1rVWnh zmB6?<4ZdB9QrOh&3G6g@8&b4R#z`7bMfEH^P*$r50Db_{0^?bqyk6<$PFkYZ_x{+15rVs zf`|%izvwlf27((%a0P}Apn!f5vTZ`T*g*s z2AbtjE6bzWd2#l)GDYtIJY{)Q^$jWQ(sr^u5;#$@1z--K0)Lp7_?y z?SQ*yzheNKSspb!a>9i!ofqH~yv?gV^XgC!f(tt#)Q{#=+en4Kx-US z;JUn5l^+E%bm@@q1vH5UQ!dy)G>I8a>&51?vvAJxD1T<22lGC->=pB&u`0yhCdH4k z^3q8(II*UAMI1B^U3!NDZEuCoN=ogq%XHeKIaCe}%%+iJY9=+|7}k95Lzi~S1}X!s z5>6GEaqyv0N7Z`Ca%)>~brL%3SN=W-T^b(^YJg(`S`|lBX1veC3t22Mle6a2;_n*v zZkT+I2YBKe3Vc6w=~nhT*>;%|u=^`rdi8iap#g1F!{C7Tw^X@SRP}88dSgE7JRf=e&g(nI z*5)q9I{N{H3404hi=oMc3Bk8iJ^KL!J?o`29mLD;!@wxOu6lM;n1?jr2=XCnc4 z0o_rkYe6pHKh5s9sC%$&|8V+*TD$34*kQIWi zmstNbf!4Xb(SBe|qvjoyY4VZXz<@SbMM+JNT$YS+&NgJpC;7dX<&lOf&>ZkuKof$k ps{7ETTSrI#|9x}n_BKEP`~e;iR&(*>ur2@q002ovPDHLkV1lw=qD=q* delta 740 zcmV&sQ{+} zLIok0Jv(Xur-IlWgbqvr$UFnHW>>o!jf}j8xoTGXYW}5*{eF-CL5iUntutfm%uVWd zgMwOT762XryibK4#P!yhO8_eXuf3&tSyW#%dz>89Ix}I&=YKuR-vLa@qT0mvIjQTd zGfMzp1CS(70Ct+ap5;aRE$nJ?>03eVx-6=tcF*jfl+_IRGN3~4o|Z+mM*C2^vZ!XE zeY3jWIx_{Z79bx0j2e&>zZ zldETCQLP}Cs()I@+Lu{D6+hiFEXtNy3-$4HSyYRLz7!hhiC^**wb*stxssD9(rM6ai;B=_l`8ay#~WHt0%iBz zYJRGS$1R7(p)&<42kkpngGL~~F=QQ&F{|G-i@TzeZGTnC#5FGjNtPLVNh9_5xd&Ot zdkB&&x{M}MBoQ9ik~_#n9DS1#AL>Rp)Ry;u5+< zoUOZ%B7bQcM1vx(!64E?+0!Y=< zO-MqWDFrf?WYf^~;;%tzY|8|xdRNj&?>x$Gx?THMAQ8ERE*S3YkRm8UO?gbyLbj&; zoRWIEQzuz&Q9nSO6B3CpC9`uu;t1FKgYO`aIO6ST!dZ1r;P)+Fc60SR(%I412h|u3DR!Rj=%_g&qLuM?~K3* zY*5GqVS{vlNH77FrL%OhfIH($rAYauC@6`Y&+*-Vws^W+E*OJetQh;c%mI7?n6t~< ztZF)o{!P9pLAC&9!L2iZ!UFa=wFA=X3MA;-%Hjo9p!tLM)UpB{Tob6ZCQxgQ22`v} zWag5^%+)S_-$_M5Q$m*jz7@~i(gMJb@XT5&3{#9+OEdLb0DJoFVzB`5PUma& zU8`SO$hc!Cwb6jOMEWAIR|6>tFExYScWfF-p-5lI8>>(XWYCSj%Iv%ha#2|~Sqd3&jN9ZH;5%AIHdvDOb z!O2R9!ciQK;xISUI$W8|thhOPC10|XxhbD(lWcys`Lmln*>1P!f=)X@*(K03O=DG_ z^#Baz=h9fW*0PtdFJ=vGdod3H^#apGk^k>!?KF-WK-U=ede&S*V9x15@KV@ z3<&n99GGdLzE_X!##auV5(!1NhRzsuw# zlANlnoE&bZ3AnkEBX3C4&~fjdlyu`sCf43P{pG!X@4Xjo+hPj3oCM{RK(8##nljG- z+|u8@^Wk9St)8Pzna=<$0L%eoz1IK)zK^V!tGV-zqrNy(* z5_Ys8&m?goIyZ!5dvZWiw;_&_JvpEjb5rbjk`Wc1C{~^)393pe2DD9W$N{ab=sL0o zrL4yiw&r9~+#~dbG9axE990Kfl+0~e!k~#e?6(|j5$_`Lzh8-3Kh_Q5D zwI?b_3?;!kZ8--PgRf9So zV%oPl(qu(#R5IH~n=+3p`>yx+&G}$*&9*F!KhdwNXDjpnlgV1s00r;~kU@$Yh&%bs P00000NkvXXu0mjfL4M%j literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/light_socket.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/light_socket.png.meta new file mode 100644 index 000000000..2b1ec7d73 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/light_socket.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 6ba01b11570df3048bf28e067a084556 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/plug.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/plug.png new file mode 100644 index 0000000000000000000000000000000000000000..42031427778e4496a9a043c566a35c06928ee4b6 GIT binary patch literal 406 zcmV;H0crk;P)Ar#<4D%i-956ChwW+s7^<{d|~&WmSuZ0&3uM@)g6Nm#1r1yE6GR8$%jm8O$e zFM2x%&;wWkm{(E;^hec`HjfzU6qSC0SG%6~Mii!f@3X2RNfC`z)E7YvroODArn`_6cGVA}J_ga; z45GOiM04|RM6LDc0>E7%mmtH`=f*nqtBU6=(V>y8$lS8&vx<(SLf^!@$SmaCFuTzd z(LPIuM3PJhtLRGVk=aEmD(NG-AFHTEu#%&eM`kML?i;|fJQ_trHCm!pGTC5PeI*|i zwnnK{@1vgvrbU-J^)6g#(4;OvM)b!MNy#!Hn4;t%am+3aOcz#S>fuQPy#TisPdbuZ zGTC6_=^DU(37HT~Jh75G4VsdoA#@rvJ+b68VBYmhhfMUMU}37Kr-bqPX;8FqjzLFK xS3&7#+w>Y`L|u{OlgWlvbal6`O38Qu@C&hFUQk~^n*#s<002ovPDHLkV1mlJ*x~>H literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/plunger_flat.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/plunger_flat.png.meta new file mode 100644 index 000000000..d77b8ad2c --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/plunger_flat.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 7d8608b786c96084697a7aa040794cdc +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/plunger_rod.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/plunger_rod.png new file mode 100644 index 0000000000000000000000000000000000000000..d9dc7031e35b685ea7234bfd58c037220c5fe89d GIT binary patch literal 505 zcmV&^-%_C619J za0PM#j!?ENmO5q&vg9C>CT-u(Um_vpk)kS9Z9nzTTf4bw+ZL%fYt{fBMyfevMRiDR zBT3X*vjeaPu(|NjZvbyuQI*oR#G=j`-{>n@>=VFCR#Zo}y<4^b3iqCp`C}qw=)1+$mxyK5kgodm+{cos zR{a=p8c>TaY3N57N`pFe0ZK$qB1uc;9J6mqqBNks*c3xQmInO=ScYjbt*EnRD3T^i z14%sXg4nD`;z=smPlK8%tT{(dBB^^%BMn&5IIMqVG#(~gV%B)-rNN{d=WAq!A}Jr3 v+tkk}E$XZpi=-hLHQ0Fay+uDLNCvQ(ulV|~8M(p+hVCl!{mO9=(wFCH)iV(np zGbULyPoj`1Suxd*3<=JR&Id@cYj8xTj6QV&ofN$xiRMYPYju-kt%(94&4MJXRqsSQ zaH7&UQE8m0H2+3aWQRWn?$%3lK&hv9PuEO`GXTfNHu27n)5pG@Nuql96n6X{7}r!M zQxCvN!?jDwz*JE*NO=1DA){7rsG{l!acfhk4bF^G`O@e548T?&nN|Dz7orX0)Tn(^|KtjCdMwR{cXQz(;{2N_}hGmIm)*$5WGp`t4kx_AgY?Qvg@C zWV+ypUJ8t>(%{>sD1~*yp1@3lw=qSVWUQnCRaDKwJ!Q3u0N@AONp9xs-90@30000< KMNUMnLSTYeaOdj) literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/plunger_spring.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/plunger_spring.png.meta new file mode 100644 index 000000000..0607a5ea1 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/plunger_spring.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 9278d5a7d9035ff43901a5adbf58b93d +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/ramp_wires.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/ramp_wires.png index 522bdabe66dd3f4a4fdf06327c5161e4885b1e4c..37047d67d2de2f9b6bdb373322f8dd2c6d44ff0c 100644 GIT binary patch delta 865 zcmV-n1D^bo28;)gIDZ2^NklM zf>b}(tbk+%B`YX+0WDcU;Jub$1yq-wOE2bMq6|nKDY6G!<8RK~znR?3=W|>`D_jNT zF3>FY>sjoV&x^CY?Nam+z-t!!CD)MBZfz%veSs4d>j0(zihlr_01|hIf7;EjFYnrf z3jvG(+ynRoK$QFnVB$roa}$uI4*)c%qAC}1>1P6-#eU$Ja{=1ty~0VW0H~U0ZAW~| zR@ead#D3EN*0R{II^;ybi_&QhPQe?z>NBSfrQylKjR6eVZyUgxOIuxldQm#a!ReAW z7^a-7Y6HH7%YUodW(25YvG2sOR*I4=_C?tm6%=#$&PNZ7wLSJbqAu;*320#8-ZEr~ z!V^Y>#5ftK`hfR(l{WUGbo|div8w8jNnp%W`s_ui6e=3F?hpLNgky|&9e7bXIt6H% zg9==W_p0)XKzdQy=X(K7qRNyD_V-OnGp~q)hF+9DVo%#z;j@xbdu%bCwrLKO$o4W?u z1zIAUDlp;TeWQ-5b;xpSn{jm#I_qct-u0q1JQ~yhhXk}LK2w>&HV@BbvA|5unopg- zYuI~W@_#uV6o1tXSqtn^ZfNeOoD9_C#oKdHV@CLuFu2LVj^2f`iVFBw$~nirX3b~7 zicKQPdrnf|J6@EoWxtbcmpK8uztW{wkGB)*(nd85c6r~U%H_POXWQ2s^HJyd!0R_& z-!Qh;HaXVW4gboVAPR+9wMO~egC|rIQVYfdk z3BU>HhC*EnasmHgcE5F}plsU;^^a!vyHwTbXP+TA4__2a^VnIDZ1gNklC;a%8#lY=^ICVve1q-XgDfJsqSo7g@l zb-lA@3E*o0lH>uvPP5nJylB6LT}>{1EvQ`=Wwq4qnH`j}njxPBRLI@aqO8_vA8J>W z)hx7cR@XagrU2FgsP4}wa|)f~U?di0+6C07>LJ8Q^w zSAk`6^{gnX6@TPXRSQ}BGApR!r(1^H;7|OL{?mZ|ulVg-I66k1H6uQK2=Ys_Msob! z3y`h&_2npwvSrpnef(II)uN#}niqm3%Z$CGk^1}G zgRJ8{1W6WMMw2O$2zPAB9poa8zDbD>bt4>V%lkiwpb<#leUk3shYfw{Q1B~95L64P zh%evjG5uC26G0=8hm-P8r6I((`iPS(q~Ec8EuCbFK+Y2&uX~baBOQukxC05_q6)~m zkjG}u)_+|{ku-0MvJx+Q2hc>wQ2Xq}m!e5@;xP!C5z;R|(!Q-G5tEDW?_Z30su>cp z(>|l1)ItL_O$+I_&)6VBNwY|SM00v_)~p(}O$*twOlrAGk!E?C@sCdhIX@N>(mZ+s zNY&F#NJ5<{1u~Xo)6n(euR&>S%LJ)2-o|A?;wyk;_Yd|S&bnfNs>SriePDC8VnKu Zegb$Y^{t?eQ$7Fy002ovPDHLkV1kUXXHx(G diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightBulbMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightBulbMeshAuthoring.cs.meta index a30ffb311..f9b5d08e1 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightBulbMeshAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightBulbMeshAuthoring.cs.meta @@ -5,7 +5,7 @@ MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: 039bc0850ebe18a4c8127063deb4ed27, type: 3} userData: assetBundleName: assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightSocketMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightSocketMeshAuthoring.cs.meta index b25cd16f8..1be55c370 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightSocketMeshAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightSocketMeshAuthoring.cs.meta @@ -5,7 +5,7 @@ MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: f08d55a443ff6344784eeb959c60f311, type: 3} userData: assetBundleName: assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerFlatMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerFlatMeshAuthoring.cs.meta index ca77a6782..a46216443 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerFlatMeshAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerFlatMeshAuthoring.cs.meta @@ -5,7 +5,7 @@ MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: 766a202bc6a0ae14cae40af04c122577, type: 3} userData: assetBundleName: assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodMeshAuthoring.cs.meta index 23b0973b6..505951eb1 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodMeshAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodMeshAuthoring.cs.meta @@ -5,7 +5,7 @@ MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: c70e9494b0d70704bb400b4fb9ac4a2d, type: 3} userData: assetBundleName: assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringMeshAuthoring.cs.meta index 57bd7ffff..d6226ffdb 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringMeshAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringMeshAuthoring.cs.meta @@ -5,7 +5,7 @@ MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: 3d4af1611b5690d4aaafcdecd17b00a8, type: 3} userData: assetBundleName: assetBundleVariant: From 3adf075735f17182e20c284496086117076d9eb3 Mon Sep 17 00:00:00 2001 From: freezy Date: Wed, 14 Oct 2020 00:07:17 +0200 Subject: [PATCH 074/124] trigger: Create authoring components. --- .../Import/VpxConverter.cs | 2 +- .../VPT/Trigger/TriggerExtensions.cs | 35 +++++++++++++++++-- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index b4cdab06d..7c6e1ecbb 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -198,7 +198,7 @@ private static IItemMainAuthoring SetupGameObjects(IRenderable item, GameObject case Spinner spinner: mainAuthoring = spinner.SetupGameObject(obj, parentAuthoring); break; case Surface surface: mainAuthoring = surface.SetupGameObject(obj, parentAuthoring); break; case Table table: table.SetupGameObject(obj, parentAuthoring); break; - case Trigger trigger: trigger.SetupGameObject(obj); break; + case Trigger trigger: mainAuthoring = trigger.SetupGameObject(obj, parentAuthoring); break; } return mainAuthoring; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs index 8a28cedba..5dba714a6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs @@ -14,18 +14,47 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using Unity.Entities; using UnityEngine; +using VisualPinball.Engine.VPT; +using VisualPinball.Engine.VPT.Trigger; namespace VisualPinball.Unity { internal static class TriggerExtensions { - public static TriggerAuthoring SetupGameObject(this Engine.VPT.Trigger.Trigger trigger, GameObject obj) + public static IItemMainAuthoring SetupGameObject(this Trigger trigger, GameObject obj, IItemMainAuthoring parentAuthoring) { - var ic = obj.AddComponent().SetItem(trigger); + var mainAuthoring = obj.AddComponent().SetItem(trigger); + + switch (trigger.SubComponent) { + case ItemSubComponent.None: + obj.AddComponent(); + obj.AddComponent(); + break; + + case ItemSubComponent.Collider: { + obj.AddComponent(); + if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { + hittableAuthoring.RemoveHittableComponent(); + } + break; + } + + case ItemSubComponent.Mesh: { + obj.AddComponent(); + if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { + meshAuthoring.RemoveMeshComponent(); + } + break; + } + + default: + throw new ArgumentOutOfRangeException(); + } obj.AddComponent(); - return ic as TriggerAuthoring; + return mainAuthoring; } } } From 9b4d84cb80906b3f54e072f7d301927b87d28f36 Mon Sep 17 00:00:00 2001 From: freezy Date: Wed, 14 Oct 2020 00:09:36 +0200 Subject: [PATCH 075/124] kicker: Create authoring components. --- .../Import/VpxConverter.cs | 2 +- .../VPT/Kicker/KickerExtensions.cs | 35 +++++++++++++++++-- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index 7c6e1ecbb..7eb886a73 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -189,7 +189,7 @@ private static IItemMainAuthoring SetupGameObjects(IRenderable item, GameObject case Flipper flipper: mainAuthoring = flipper.SetupGameObject(obj, parentAuthoring); break; case Gate gate: mainAuthoring = gate.SetupGameObject(obj, parentAuthoring); break; case HitTarget hitTarget: hitTarget.SetupGameObject(obj); break; - case Kicker kicker: kicker.SetupGameObject(obj); break; + case Kicker kicker: mainAuthoring = kicker.SetupGameObject(obj, parentAuthoring); break; case Engine.VPT.Light.Light lt: lt.SetupGameObject(obj); break; case Plunger plunger: plunger.SetupGameObject(obj); break; case Primitive primitive: primitive.SetupGameObject(obj); break; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs index 93b5347ff..5117dc56b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs @@ -14,18 +14,47 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using Unity.Entities; using UnityEngine; +using VisualPinball.Engine.VPT; +using VisualPinball.Engine.VPT.Kicker; namespace VisualPinball.Unity { internal static class KickerExtensions { - public static KickerAuthoring SetupGameObject(this Engine.VPT.Kicker.Kicker kicker, GameObject obj) + public static IItemMainAuthoring SetupGameObject(this Kicker kicker, GameObject obj, IItemMainAuthoring parentAuthoring) { - var ic = obj.AddComponent().SetItem(kicker); + var mainAuthoring = obj.AddComponent().SetItem(kicker); + + switch (kicker.SubComponent) { + case ItemSubComponent.None: + obj.AddComponent(); + obj.AddComponent(); + break; + + case ItemSubComponent.Collider: { + obj.AddComponent(); + if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { + hittableAuthoring.RemoveHittableComponent(); + } + break; + } + + case ItemSubComponent.Mesh: { + obj.AddComponent(); + if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { + meshAuthoring.RemoveMeshComponent(); + } + break; + } + + default: + throw new ArgumentOutOfRangeException(); + } obj.AddComponent(); - return ic as KickerAuthoring; + return mainAuthoring; } } } From b28adeee37c376979b38bebc2098f76c07d36411 Mon Sep 17 00:00:00 2001 From: freezy Date: Wed, 14 Oct 2020 00:11:38 +0200 Subject: [PATCH 076/124] target: Create authoring components. --- .../Import/VpxConverter.cs | 2 +- .../VPT/HitTarget/HitTargetExtensions.cs | 35 +++++++++++++++++-- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index 7eb886a73..d9b5ea6f9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -188,7 +188,7 @@ private static IItemMainAuthoring SetupGameObjects(IRenderable item, GameObject case Bumper bumper: mainAuthoring = bumper.SetupGameObject(obj, parentAuthoring); break; case Flipper flipper: mainAuthoring = flipper.SetupGameObject(obj, parentAuthoring); break; case Gate gate: mainAuthoring = gate.SetupGameObject(obj, parentAuthoring); break; - case HitTarget hitTarget: hitTarget.SetupGameObject(obj); break; + case HitTarget hitTarget: mainAuthoring = hitTarget.SetupGameObject(obj, parentAuthoring); break; case Kicker kicker: mainAuthoring = kicker.SetupGameObject(obj, parentAuthoring); break; case Engine.VPT.Light.Light lt: lt.SetupGameObject(obj); break; case Plunger plunger: plunger.SetupGameObject(obj); break; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs index 1c64ff0c9..f69ba738c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs @@ -14,18 +14,47 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using Unity.Entities; using UnityEngine; +using VisualPinball.Engine.VPT; +using VisualPinball.Engine.VPT.HitTarget; namespace VisualPinball.Unity { internal static class HitTargetExtensions { - public static HitTargetAuthoring SetupGameObject(this Engine.VPT.HitTarget.HitTarget hitTarget, GameObject obj) + public static IItemMainAuthoring SetupGameObject(this HitTarget hitTarget, GameObject obj, IItemMainAuthoring parentAuthoring) { - var ic = obj.AddComponent().SetItem(hitTarget); + var mainAuthoring = obj.AddComponent().SetItem(hitTarget); + + switch (hitTarget.SubComponent) { + case ItemSubComponent.None: + obj.AddComponent(); + obj.AddComponent(); + break; + + case ItemSubComponent.Collider: { + obj.AddComponent(); + if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { + hittableAuthoring.RemoveHittableComponent(); + } + break; + } + + case ItemSubComponent.Mesh: { + obj.AddComponent(); + if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { + meshAuthoring.RemoveMeshComponent(); + } + break; + } + + default: + throw new ArgumentOutOfRangeException(); + } obj.AddComponent(); - return ic as HitTargetAuthoring; + return mainAuthoring; } } } From bc0921accc3383b40642750ad93c8ca9fac72938 Mon Sep 17 00:00:00 2001 From: freezy Date: Wed, 14 Oct 2020 00:14:14 +0200 Subject: [PATCH 077/124] primitive: Create authoring components. --- .../Import/VpxConverter.cs | 2 +- .../VPT/Primitive/PrimitiveExtensions.cs | 33 +++++++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index d9b5ea6f9..c3b8d52a1 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -192,7 +192,7 @@ private static IItemMainAuthoring SetupGameObjects(IRenderable item, GameObject case Kicker kicker: mainAuthoring = kicker.SetupGameObject(obj, parentAuthoring); break; case Engine.VPT.Light.Light lt: lt.SetupGameObject(obj); break; case Plunger plunger: plunger.SetupGameObject(obj); break; - case Primitive primitive: primitive.SetupGameObject(obj); break; + case Primitive primitive: mainAuthoring = primitive.SetupGameObject(obj, parentAuthoring); break; case Ramp ramp: mainAuthoring = ramp.SetupGameObject(obj, parentAuthoring); break; case Rubber rubber: mainAuthoring = rubber.SetupGameObject(obj, parentAuthoring); break; case Spinner spinner: mainAuthoring = spinner.SetupGameObject(obj, parentAuthoring); break; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs index c7777a4f8..8f00cd9dd 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs @@ -14,20 +14,47 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using Unity.Entities; using UnityEngine; +using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Primitive; namespace VisualPinball.Unity { internal static class PrimitiveExtensions { - public static PrimitiveAuthoring SetupGameObject(this Primitive primitive, GameObject obj) + public static IItemMainAuthoring SetupGameObject(this Primitive primitive, GameObject obj, IItemMainAuthoring parentAuthoring) { - var ic = obj.AddComponent().SetItem(primitive); + var mainAuthoring = obj.AddComponent().SetItem(primitive); + switch (primitive.SubComponent) { + case ItemSubComponent.None: + obj.AddComponent(); + obj.AddComponent(); + break; + + case ItemSubComponent.Collider: { + obj.AddComponent(); + if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { + hittableAuthoring.RemoveHittableComponent(); + } + break; + } + + case ItemSubComponent.Mesh: { + obj.AddComponent(); + if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { + meshAuthoring.RemoveMeshComponent(); + } + break; + } + + default: + throw new ArgumentOutOfRangeException(); + } obj.AddComponent(); - return ic as PrimitiveAuthoring; + return mainAuthoring; } } } From a304b2b1f527d26dbc6b00181ef44b9d76492cb7 Mon Sep 17 00:00:00 2001 From: freezy Date: Wed, 14 Oct 2020 00:18:09 +0200 Subject: [PATCH 078/124] editor: Disable gizmos for latest icons. --- .../VisualPinball.Unity.Editor/Utils/Icons.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs index 919b6842e..e8e92d7c7 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs @@ -149,13 +149,25 @@ public static void OnScriptsReloaded() DisableGizmo(); DisableGizmo(); DisableGizmo(); + DisableGizmo(); + DisableGizmo(); DisableGizmo(); + DisableGizmo(); + DisableGizmo(); DisableGizmo(); + DisableGizmo(); + DisableGizmo(); DisableGizmo(); DisableGizmo(); DisableGizmo(); DisableGizmo(); + DisableGizmo(); + DisableGizmo(); + DisableGizmo(); + DisableGizmo(); DisableGizmo(); + DisableGizmo(); + DisableGizmo(); DisableGizmo(); DisableGizmo(); DisableGizmo(); @@ -175,6 +187,8 @@ public static void OnScriptsReloaded() DisableGizmo(); DisableGizmo(); DisableGizmo(); + DisableGizmo(); + DisableGizmo(); } public static void ApplyToComponent(Object target, Texture2D tex) where T : MonoBehaviour From 57da186761457e0b3960d0d723da7775127f1992 Mon Sep 17 00:00:00 2001 From: freezy Date: Wed, 14 Oct 2020 00:43:49 +0200 Subject: [PATCH 079/124] plunger: Create authoring components. --- .../Import/VpxConverter.cs | 2 +- .../VPT/Plunger/PlungerExtensions.cs | 69 +++++++++++++++---- .../VPT/Plunger/PlungerRodMeshAuthoring.cs | 4 +- .../VPT/Plunger/PlungerSpringMeshAuthoring.cs | 2 + .../VPT/Ramp/RampExtensions.cs | 18 +++-- 5 files changed, 73 insertions(+), 22 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index c3b8d52a1..6252b1745 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -191,7 +191,7 @@ private static IItemMainAuthoring SetupGameObjects(IRenderable item, GameObject case HitTarget hitTarget: mainAuthoring = hitTarget.SetupGameObject(obj, parentAuthoring); break; case Kicker kicker: mainAuthoring = kicker.SetupGameObject(obj, parentAuthoring); break; case Engine.VPT.Light.Light lt: lt.SetupGameObject(obj); break; - case Plunger plunger: plunger.SetupGameObject(obj); break; + case Plunger plunger: mainAuthoring = plunger.SetupGameObject(obj, parentAuthoring); break; case Primitive primitive: mainAuthoring = primitive.SetupGameObject(obj, parentAuthoring); break; case Ramp ramp: mainAuthoring = ramp.SetupGameObject(obj, parentAuthoring); break; case Rubber rubber: mainAuthoring = rubber.SetupGameObject(obj, parentAuthoring); break; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs index f48f2cbc4..bcb0e466e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs @@ -14,35 +14,76 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using Unity.Entities; using UnityEngine; +using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Plunger; namespace VisualPinball.Unity { internal static class PlungerExtensions { - public static PlungerAuthoring SetupGameObject(this Plunger plunger, GameObject obj) + + public static IItemMainAuthoring SetupGameObject(this Plunger plunger, GameObject obj, IItemMainAuthoring parentAuthoring) { - var ic = obj.AddComponent().SetItem(plunger); + var mainAuthoring = obj.AddComponent().SetItem(plunger); - var rod = obj.transform.Find(PlungerMeshGenerator.Rod); - if (rod != null) { - rod.gameObject.AddComponent(); - } + switch (plunger.SubComponent) { + case ItemSubComponent.None: + CreateMeshComponents(plunger, obj); + obj.AddComponent(); + break; + + case ItemSubComponent.Collider: { + obj.AddComponent(); + if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { + hittableAuthoring.RemoveHittableComponent(); + } + break; + } + + case ItemSubComponent.Mesh: { + CreateMeshComponents(plunger, obj); + if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { + meshAuthoring.RemoveMeshComponent(); + } + break; + } - var spring = obj.transform.Find(PlungerMeshGenerator.Spring); - if (spring != null) { - spring.gameObject.AddComponent(); + default: + throw new ArgumentOutOfRangeException(); } + obj.AddComponent(); + return mainAuthoring; + } + + private static void CreateMeshComponents(Plunger plunger, GameObject obj) + { + switch (plunger.Data.Type) { + case PlungerType.PlungerTypeFlat: + CreateChild(obj, PlungerMeshGenerator.Flat); + break; + + case PlungerType.PlungerTypeCustom: + CreateChild(obj, PlungerMeshGenerator.Spring); + CreateChild(obj, PlungerMeshGenerator.Rod); + break; + + case PlungerType.PlungerTypeModern: + CreateChild(obj, PlungerMeshGenerator.Rod); + break; - var flat = obj.transform.Find(PlungerMeshGenerator.Flat); - if (flat != null) { - flat.gameObject.AddComponent(); } + } - obj.AddComponent(); - return ic as PlungerAuthoring; + public static GameObject CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring + { + var subObj = new GameObject(name); + subObj.transform.SetParent(obj.transform, false); + subObj.AddComponent(); + //subObj.layer = ChildObjectsLayer; + return subObj; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodMeshAuthoring.cs index 21cbff73c..7e924a9aa 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodMeshAuthoring.cs @@ -23,9 +23,11 @@ namespace VisualPinball.Unity { [ExecuteInEditMode] - [AddComponentMenu("Visual Pinball/Mesh/Plunger Flat Mesh")] + [AddComponentMenu("Visual Pinball/Mesh/Plunger Rod Mesh")] public class PlungerRodMeshAuthoring : PlungerMeshAuthoring { + protected override string MeshId => PlungerMeshGenerator.Rod; + internal override void SetChildEntity(ref PlungerStaticData staticData, Entity entity) { staticData.RodEntity = entity; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringMeshAuthoring.cs index ba661c005..6468d3abc 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringMeshAuthoring.cs @@ -26,6 +26,8 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Plunger Spring Mesh")] public class PlungerSpringMeshAuthoring : PlungerMeshAuthoring { + protected override string MeshId => PlungerMeshGenerator.Spring; + internal override void SetChildEntity(ref PlungerStaticData staticData, Entity entity) { staticData.SpringEntity = entity; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs index 99ad1421f..60692b46b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs @@ -30,12 +30,7 @@ public static IItemMainAuthoring SetupGameObject(this Ramp ramp, GameObject obj, switch (ramp.SubComponent) { case ItemSubComponent.None: - if (ramp.IsHabitrail) { - CreateChild(obj, RampMeshGenerator.Wires); - } else { - CreateChild(obj, RampMeshGenerator.Floor); - CreateChild(obj, RampMeshGenerator.Wall); - } + CreateMeshComponents(ramp, obj); obj.AddComponent(); break; @@ -49,6 +44,7 @@ public static IItemMainAuthoring SetupGameObject(this Ramp ramp, GameObject obj, case ItemSubComponent.Mesh: { // todo + CreateMeshComponents(ramp, obj); if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { meshAuthoring.RemoveMeshComponent(); } @@ -62,6 +58,16 @@ public static IItemMainAuthoring SetupGameObject(this Ramp ramp, GameObject obj, return mainAuthoring; } + private static void CreateMeshComponents(Ramp ramp, GameObject obj) + { + if (ramp.IsHabitrail) { + CreateChild(obj, RampMeshGenerator.Wires); + } else { + CreateChild(obj, RampMeshGenerator.Floor); + CreateChild(obj, RampMeshGenerator.Wall); + } + } + public static GameObject CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring { var subObj = new GameObject(name); From ce7194450bd0d3e751da49fa53dfba867cf6e46f Mon Sep 17 00:00:00 2001 From: freezy Date: Wed, 14 Oct 2020 01:04:11 +0200 Subject: [PATCH 080/124] plunger: Update game objects on type change. --- .../VPT/Plunger/PlungerInspector.cs | 2 +- .../VPT/Plunger/PlungerAuthoring.cs | 64 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerInspector.cs index 624a3dc59..84791d676 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerInspector.cs @@ -44,7 +44,7 @@ public override void OnInspectorGUI() OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - DropDownField("Type", ref _plunger.Data.Type, PlungerTypeStrings, PlungerTypeValues); + DropDownField("Type", ref _plunger.Data.Type, PlungerTypeStrings, PlungerTypeValues, onChanged: _plunger.OnTypeChanged); MaterialField("Material", ref _plunger.Data.Material); TextureField("Image", ref _plunger.Data.Image); ItemDataField("Flat Frames", ref _plunger.Data.AnimFrames); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs index b9cb99c92..468fa18a5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs @@ -18,6 +18,7 @@ using Unity.Entities; using UnityEngine; using VisualPinball.Engine.Game; +using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Plunger; namespace VisualPinball.Unity @@ -98,6 +99,69 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio }); } + public void OnTypeChanged(int plungerTypeBefore, int plungerTypeAfter) + { + if (plungerTypeBefore == plungerTypeAfter) { + return; + } + + switch (plungerTypeBefore) { + case PlungerType.PlungerTypeFlat: + // remove flat + var flatPlungerAuthoring = GetComponentInChildren(); + if (flatPlungerAuthoring != null) { + DestroyImmediate(flatPlungerAuthoring.gameObject); + } + + // create rod + PlungerExtensions.CreateChild(gameObject, PlungerMeshGenerator.Rod); + + if (plungerTypeAfter == PlungerType.PlungerTypeCustom) { + // create spring + PlungerExtensions.CreateChild(gameObject, PlungerMeshGenerator.Spring); + } + break; + + case PlungerType.PlungerTypeModern: + if (plungerTypeAfter == PlungerType.PlungerTypeCustom) { + // create spring + PlungerExtensions.CreateChild(gameObject, PlungerMeshGenerator.Spring); + } + + if (plungerTypeAfter == PlungerType.PlungerTypeFlat) { + // remove rod + var rodPlungerAuthoring = GetComponentInChildren(); + if (rodPlungerAuthoring != null) { + DestroyImmediate(rodPlungerAuthoring.gameObject); + } + // create flat + PlungerExtensions.CreateChild(gameObject, PlungerMeshGenerator.Flat); + } + break; + + case PlungerType.PlungerTypeCustom: + // remove spring + var springPlungerAuthoring = GetComponentInChildren(); + if (springPlungerAuthoring != null) { + DestroyImmediate(springPlungerAuthoring.gameObject); + } + + if (plungerTypeAfter == PlungerType.PlungerTypeFlat) { + // remove rod + var rodPlungerAuthoring = GetComponentInChildren(); + if (rodPlungerAuthoring != null) { + DestroyImmediate(rodPlungerAuthoring.gameObject); + } + + // create flat + PlungerExtensions.CreateChild(gameObject, PlungerMeshGenerator.Flat); + } + + break; + + } + } + public void RemoveHittableComponent() { } From aedc6a4e6b69ffe1e0af219743b0b3f52051c991 Mon Sep 17 00:00:00 2001 From: freezy Date: Wed, 14 Oct 2020 23:22:04 +0200 Subject: [PATCH 081/124] plunger: Fix mesh generation. --- .../VPT/Plunger/PlungerMeshGenerator.cs | 65 ++++++++++--------- .../VPT/ItemMeshAuthoring.cs | 1 + .../VPT/Plunger/PlungerAuthoring.cs | 4 -- .../VPT/Plunger/PlungerMeshAuthoring.cs | 3 - 4 files changed, 34 insertions(+), 39 deletions(-) diff --git a/VisualPinball.Engine/VPT/Plunger/PlungerMeshGenerator.cs b/VisualPinball.Engine/VPT/Plunger/PlungerMeshGenerator.cs index 8ccf0534f..bff02f2cd 100644 --- a/VisualPinball.Engine/VPT/Plunger/PlungerMeshGenerator.cs +++ b/VisualPinball.Engine/VPT/Plunger/PlungerMeshGenerator.cs @@ -62,40 +62,9 @@ public PlungerMeshGenerator(PlungerData data) Init(null); } - public void Init(Table.Table table) - { - var stroke = _data.Stroke; - _beginY = _data.Center.Y; - _endY = _data.Center.Y - stroke; - NumFrames = (int)(stroke * (float)(PlungerFrameCount / 80.0)) + 1; // 25 frames per 80 units travel - _invScale = NumFrames > 1 ? 1.0f / (NumFrames - 1) : 0.0f; - _dyPerFrame = (_endY - _beginY) * _invScale; - _circlePoints = _data.Type == PlungerType.PlungerTypeFlat ? 0 : 24; - _springLoops = 0.0f; - _springEndLoops = 0.0f; - _springGauge = 0.0f; - _springRadius = 0.0f; - _springMinSpacing = 2.2f; - _rodY = _beginY + _data.Height; - - // note the number of cells in the source image - _srcCells = _data.AnimFrames; - if (_srcCells < 1) { - _srcCells = 1; - } - - // figure the width in relative units (0..1) of each cell - _cellWid = 1.0f / _srcCells; - - if (table != null) { - _zHeight = table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y) + _data.ZAdjust; - _zScale = table.GetScaleZ(); - } - _desc = GetPlungerDesc(); - } - public RenderObject GetRenderObject(int frame, Table.Table table, string id, Origin origin, bool asRightHanded) { + Init(table); var material = new PbrMaterial(table.GetMaterial(_data.Material), table.GetTexture(_data.Image)); switch (id) { case Flat: @@ -184,6 +153,38 @@ public RenderObjectGroup GetRenderObjects(int frame, Table.Table table, Origin o ) { ForceChild = true }; } + private void Init(Table.Table table) + { + var stroke = _data.Stroke; + _beginY = _data.Center.Y; + _endY = _data.Center.Y - stroke; + NumFrames = (int)(stroke * (float)(PlungerFrameCount / 80.0)) + 1; // 25 frames per 80 units travel + _invScale = NumFrames > 1 ? 1.0f / (NumFrames - 1) : 0.0f; + _dyPerFrame = (_endY - _beginY) * _invScale; + _circlePoints = _data.Type == PlungerType.PlungerTypeFlat ? 0 : 24; + _springLoops = 0.0f; + _springEndLoops = 0.0f; + _springGauge = 0.0f; + _springRadius = 0.0f; + _springMinSpacing = 2.2f; + _rodY = _beginY + _data.Height; + + // note the number of cells in the source image + _srcCells = _data.AnimFrames; + if (_srcCells < 1) { + _srcCells = 1; + } + + // figure the width in relative units (0..1) of each cell + _cellWid = 1.0f / _srcCells; + + if (table != null) { + _zHeight = table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y) + _data.ZAdjust; + _zScale = table.GetScaleZ(); + } + _desc = GetPlungerDesc(); + } + private PlungerDesc GetPlungerDesc() { switch (_data.Type) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs index b7114946a..1a2806cc2 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs @@ -22,6 +22,7 @@ using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT; +using VisualPinball.Engine.VPT.Table; using Logger = NLog.Logger; namespace VisualPinball.Unity diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs index 468fa18a5..d2739d8c6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs @@ -28,10 +28,6 @@ namespace VisualPinball.Unity public class PlungerAuthoring : ItemMainAuthoring, IHittableAuthoring, ICoilAuthoring, IConvertGameObjectToEntity { - // protected override string[] Children => new [] { - // PlungerMeshGenerator.FlatName, PlungerMeshGenerator.RodName, PlungerMeshGenerator.SpringName - // }; - protected override Plunger InstantiateItem(PlungerData data) => new Plunger(data); protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerMeshAuthoring.cs index b73fdedd2..37de8940b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerMeshAuthoring.cs @@ -17,7 +17,6 @@ using System.Collections.Generic; using Unity.Entities; using Unity.Mathematics; -using UnityEngine; using VisualPinball.Engine.Math; using VisualPinball.Engine.VPT.Plunger; @@ -31,10 +30,8 @@ public abstract class PlungerMeshAuthoring : ItemMeshAuthoring().Item; var plunger = transform.parent.gameObject.GetComponent().Item; var plungerEntity = new Entity {Index = plunger.Index, Version = plunger.Version}; - plunger.MeshGenerator.Init(table); // update parent var plungerStaticData = dstManager.GetComponentData(plungerEntity); From b59a327d4ad149716dbdd981b73aef537ad24ea4 Mon Sep 17 00:00:00 2001 From: freezy Date: Thu, 15 Oct 2020 00:27:30 +0200 Subject: [PATCH 082/124] light: Create authoring components. --- .../VPT/ItemInspector.cs | 4 ++- .../VPT/Light/LightInspector.cs | 4 ++- .../Import/VpxConverter.cs | 2 +- .../VPT/Light/LightAuthoring.cs | 22 +++++++++++++ .../VPT/Light/LightExtensions.cs | 32 +++++++++++++++++-- .../VPT/Plunger/PlungerExtensions.cs | 1 - 6 files changed, 58 insertions(+), 7 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs index f4156c5a7..86e94b579 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs @@ -194,13 +194,15 @@ protected void ItemDataField(string label, ref string field, bool dirtyMesh = tr } } - protected void ItemDataField(string label, ref bool field, bool dirtyMesh = true) + protected void ItemDataField(string label, ref bool field, bool dirtyMesh = true, Action onChanged = null) { EditorGUI.BeginChangeCheck(); var val = EditorGUILayout.Toggle(label, field); if (EditorGUI.EndChangeCheck()) { FinishEdit(label, dirtyMesh); + var fieldBefore = field; field = val; + onChanged?.Invoke(fieldBefore, field); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightInspector.cs index 643fb76bf..c776bfee4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightInspector.cs @@ -14,6 +14,8 @@ // 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; @@ -53,7 +55,7 @@ public override void OnInspectorGUI() EditorGUILayout.LabelField("Bulb"); EditorGUI.indentLevel++; - ItemDataField("Enable", ref _light.Data.IsBulbLight, dirtyMesh: false); + ItemDataField("Enable", ref _light.Data.ShowBulbMesh, false, onChanged: _light.OnBulbEnabled); ItemDataField("Scale Mesh", ref _light.Data.MeshRadius, dirtyMesh: false); EditorGUI.indentLevel--; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index 6252b1745..60a8f8858 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -190,7 +190,7 @@ private static IItemMainAuthoring SetupGameObjects(IRenderable item, GameObject case Gate gate: mainAuthoring = gate.SetupGameObject(obj, parentAuthoring); break; case HitTarget hitTarget: mainAuthoring = hitTarget.SetupGameObject(obj, parentAuthoring); break; case Kicker kicker: mainAuthoring = kicker.SetupGameObject(obj, parentAuthoring); break; - case Engine.VPT.Light.Light lt: lt.SetupGameObject(obj); break; + case Engine.VPT.Light.Light lt: mainAuthoring = lt.SetupGameObject(obj, parentAuthoring); break; case Plunger plunger: mainAuthoring = plunger.SetupGameObject(obj, parentAuthoring); break; case Primitive primitive: mainAuthoring = primitive.SetupGameObject(obj, parentAuthoring); break; case Ramp ramp: mainAuthoring = ramp.SetupGameObject(obj, parentAuthoring); break; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs index 4a0905eb7..0a7007df4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs @@ -36,6 +36,28 @@ public class LightAuthoring : ItemMainAuthoring protected override Type MeshAuthoringType { get; } = null; + + public void OnBulbEnabled(bool bulbEnabledBefore, bool bulbEnabledAfter) + { + if (bulbEnabledBefore == bulbEnabledAfter) { + return; + } + + if (bulbEnabledAfter) { + LightExtensions.CreateChild(gameObject, LightMeshGenerator.Bulb); + LightExtensions.CreateChild(gameObject, LightMeshGenerator.Socket); + } else { + var bulbMeshAuthoring = GetComponentInChildren(); + if (bulbMeshAuthoring != null) { + DestroyImmediate(bulbMeshAuthoring.gameObject); + } + var socketMeshAuthoring = GetComponentInChildren(); + if (socketMeshAuthoring != null) { + DestroyImmediate(socketMeshAuthoring.gameObject); + } + } + } + protected override void ItemDataChanged() { base.ItemDataChanged(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs index 1d30f05cd..809e4a13e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs @@ -15,15 +15,41 @@ // along with this program. If not, see . using UnityEngine; +using VisualPinball.Engine.VPT; +using VisualPinball.Engine.VPT.Light; +using Light = VisualPinball.Engine.VPT.Light.Light; namespace VisualPinball.Unity { internal static class LightExtensions { - public static LightAuthoring SetupGameObject(this Engine.VPT.Light.Light light, GameObject obj) + public static IItemMainAuthoring SetupGameObject(this Light light, GameObject obj, IItemMainAuthoring parentAuthoring) { - var ic = obj.AddComponent().SetItem(light); - return ic as LightAuthoring; + var mainAuthoring = obj.AddComponent().SetItem(light); + if (!light.Data.ShowBulbMesh) { + return mainAuthoring; + } + + CreateChild(obj, LightMeshGenerator.Bulb); + CreateChild(obj, LightMeshGenerator.Socket); + + if (light.SubComponent == ItemSubComponent.Mesh) { + if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { + meshAuthoring.RemoveMeshComponent(); + } + } + + //obj.AddComponent(); + return mainAuthoring; + } + + public static GameObject CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring + { + var subObj = new GameObject(name); + subObj.transform.SetParent(obj.transform, false); + subObj.AddComponent(); + //subObj.layer = ChildObjectsLayer; + return subObj; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs index bcb0e466e..e60c2e82c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs @@ -24,7 +24,6 @@ namespace VisualPinball.Unity { internal static class PlungerExtensions { - public static IItemMainAuthoring SetupGameObject(this Plunger plunger, GameObject obj, IItemMainAuthoring parentAuthoring) { var mainAuthoring = obj.AddComponent().SetItem(plunger); From ce94a152c06f38657a5e8e334bb5784d3a6caabf Mon Sep 17 00:00:00 2001 From: freezy Date: Thu, 15 Oct 2020 23:17:21 +0200 Subject: [PATCH 083/124] editor: Add player icon. --- .../VisualPinball.Unity.Editor/Physics.meta | 8 -- .../Resources/Icons/large_green/player.png | Bin 0 -> 406 bytes .../Icons/large_green/player.png.meta | 94 ++++++++++++++++ .../Resources/Icons/small_blue/player.png | Bin 0 -> 400 bytes .../Icons/small_blue/player.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_gray/player.png | Bin 0 -> 405 bytes .../Icons/small_gray/player.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_green/player.png | Bin 0 -> 406 bytes .../Icons/small_green/player.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_orange/player.png | Bin 0 -> 406 bytes .../Icons/small_orange/player.png.meta | 106 ++++++++++++++++++ .../VisualPinball.Unity/Game/Player.cs.meta | 2 +- 12 files changed, 519 insertions(+), 9 deletions(-) delete mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Physics.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/player.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/player.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/player.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/player.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/player.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/player.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/player.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/player.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/player.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/player.png.meta diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Physics.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Physics.meta deleted file mode 100644 index d33f32471..000000000 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Physics.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: bc5d6741d2874ff46b86b8e79b30972b -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/player.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/player.png new file mode 100644 index 0000000000000000000000000000000000000000..1b572c953b268d2662f23c6c95b7556b74596c9b GIT binary patch literal 406 zcmV;H0crk;P)&!KP2EYw~4**qJw9Q|H-U8U3d@SHven45YpTUHhDbMH?fM)=mb*8e; zTvBBxVHDF6z>|V&eN5 I^6bQF_|n$4 zQ^2uTrU5L4_uzA3swGrf+u8@5daWP8)o&-xW+=Hx{QaZnhE!1R!6r8JRe?L-3u8gg z1`Y`g-N-0d7VUoOjY2^;`VV%j8#18>-38Q4;1CA%pp(7;gH8HVpi#FXW1*c^ZnDiC zWOFz6c=@_p`JB%@@{3${GL)SRWhX<~nFkcWH@8#oik8$_YybcN07*qoM6N<$f^p=m Ab^rhX literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/player.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/player.png.meta new file mode 100644 index 000000000..f3d632404 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/player.png.meta @@ -0,0 +1,94 @@ +fileFormatVersion: 2 +guid: 5f054f396d23cb9418ac17cee5149eb4 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + 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: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/player.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/player.png new file mode 100644 index 0000000000000000000000000000000000000000..f9fe45c7b5294711d134546a91ac73a378222563 GIT binary patch literal 400 zcmV;B0dM|^P)uKK>m98%3fS)dV8pzIVVJO2|Z&M)Ip zPG{80B+lOfXaTGM?Ddq?Rr?pA_W-s>rxo1j7m&L8iYBy7c}H&nJOk*&c@gJtsIsFl zifI90ZQ#aU6MC3cuiz&DpW=MW2FGeo55K^aP7%A0D)>#D-&sLkoKy{8+uC*tIQ7aj zfVJ=*LvGBqglcPh2?6I`>j$u$yKpu`$#v$>A3ZnZf(8#ZsiCh1+=bql3VJbcNNngv zM?tBp_o)wx1>M*$*s&hSgdS`c&@h2R7|?@F`U;FT=}&FBHh0j?-PmLO u@x2VWo_Ul%a@i?Rb_$f80%d0&Pyjz-t@15+Q=%0B0000RcNT`PrH@|Iy{7bo1N&2uO`& z4OMm&MloFjcu{bpj|n}@su%DxfKOvx%La#PPme#qlui-4j|%wRShv-JJUg)(zO=Q? z6maa7X#h*%J^5UiY6+Frw(!dHhV3Yn7Xw&!KP2EYw~4**qJw9Q|H-U8U3d@SHven45YpTUHhDbMH?fM)=mb*8e; zTvBBxVHDF6z>|V&eN5 I^6bQF_|n$4 zQ^2uTrU5L4_uzA3swGrf+u8@5daWP8)o&-xW+=Hx{QaZnhE!1R!6r8JRe?L-3u8gg z1`Y`g-N-0d7VUoOjY2^;`VV%j8#18>-38Q4;1CA%pp(7;gH8HVpi#FXW1*c^ZnDiC zWOFz6c=@_p`JB%@@{3${GL)SRWhX<~nFkcWH@8#oik8$_YybcN07*qoM6N<$f^p=m Ab^rhX literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/player.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/player.png.meta new file mode 100644 index 000000000..70657b7a0 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/player.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 9145010d8db49964382e1e13c31ac85d +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/player.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/player.png new file mode 100644 index 0000000000000000000000000000000000000000..53deb202da79052d523a1e3314935b47582aa58c GIT binary patch literal 406 zcmV;H0crk;P)scm~ipYbs~W z6;*Z=MloFicv5h!j|n}@su%DhfSt3ZVS_`pr-yG~N~Z|jM+N-mtl4Too}5?>U)tJc z3OM%4G=Qb>mOdAzT0*6@z4(Aruk{1C`t8Ko3?&zdzkl@HkP7NO*u;juDsbz2VJzs$ zz#*ZbYZ(QLvVEU=qfpSb{(~LshD_*QcL6mMID`S+>!dHhV3Yn7Xw|`iA^MC?407@?GVB|5IrT_o{07*qoM6N<$g2#8Q AmH+?% literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/player.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/player.png.meta new file mode 100644 index 000000000..f32cf183e --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/player.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 8e6db07529498ff48ac0464cfd7fcf54 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/Game/Player.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/Game/Player.cs.meta index bf1fa3d8f..5a580a837 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Game/Player.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/Game/Player.cs.meta @@ -5,7 +5,7 @@ MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: 8e6db07529498ff48ac0464cfd7fcf54, type: 3} userData: assetBundleName: assetBundleVariant: From 396e35865bda0139fa36718e22dc2c34a78e24b4 Mon Sep 17 00:00:00 2001 From: freezy Date: Fri, 16 Oct 2020 00:18:24 +0200 Subject: [PATCH 084/124] mesh: Add abstract visibility and clean up authoring component. --- .../VPT/Bumper/BumperBaseMeshInspector.cs | 2 +- .../VPT/Bumper/BumperCapMeshInspector.cs | 2 +- .../VPT/ItemMeshInspector.cs | 10 +-- .../VPT/Bumper/BumperBaseMeshAuthoring.cs | 5 ++ .../VPT/Bumper/BumperCapMeshAuthoring.cs | 4 ++ .../VPT/Bumper/BumperRingMeshAuthoring.cs | 5 +- .../VPT/Bumper/BumperSkirtMeshAuthoring.cs | 4 ++ .../VPT/Flipper/FlipperBaseMeshAuthoring.cs | 4 ++ .../VPT/Flipper/FlipperRubberMeshAuthoring.cs | 4 ++ .../VPT/Gate/GateBracketMeshAuthoring.cs | 4 ++ .../VPT/Gate/GateWireMeshAuthoring.cs | 4 ++ .../VPT/HitTarget/HitTargetMeshAuthoring.cs | 4 ++ .../VPT/ItemMeshAuthoring.cs | 64 ++++++++----------- .../VPT/Kicker/KickerMeshAuthoring.cs | 4 ++ .../VPT/Light/LightBulbMeshAuthoring.cs | 4 ++ .../VPT/Light/LightSocketMeshAuthoring.cs | 4 ++ .../VPT/Playfield/PlayfieldMeshAuthoring.cs | 4 ++ .../VPT/Plunger/PlungerMeshAuthoring.cs | 5 ++ .../VPT/Primitive/PrimitiveMeshAuthoring.cs | 4 ++ .../VPT/Ramp/RampFloorMeshAuthoring.cs | 5 ++ .../VPT/Ramp/RampWallMeshAuthoring.cs | 4 ++ .../VPT/Ramp/RampWireMeshAuthoring.cs | 4 ++ .../VPT/Rubber/RubberMeshAuthoring.cs | 4 ++ .../Spinner/SpinnerBracketMeshAuthoring.cs | 4 ++ .../VPT/Spinner/SpinnerPlateMeshAuthoring.cs | 4 ++ .../VPT/Surface/SurfaceSideMeshAuthoring.cs | 4 ++ .../VPT/Surface/SurfaceTopMeshAuthoring.cs | 4 ++ .../VPT/Trigger/TriggerMeshAuthoring.cs | 4 ++ 28 files changed, 134 insertions(+), 44 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperBaseMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperBaseMeshInspector.cs index 0b3a34770..c7af68f0a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperBaseMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperBaseMeshInspector.cs @@ -39,7 +39,7 @@ public override void OnInspectorGUI() return; } - ItemDataField("Is Visible", ref _data.IsBaseVisible); + ItemDataField("Is Visible", ref _data.IsBaseVisible, onChanged: MeshAuthoring.OnVisibilityChanged); MaterialField("Base Material", ref _data.BaseMaterial); base.OnInspectorGUI(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperCapMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperCapMeshInspector.cs index fcdc52830..977b3ccb1 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperCapMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperCapMeshInspector.cs @@ -39,7 +39,7 @@ public override void OnInspectorGUI() return; } - ItemDataField("Is Visible", ref _data.IsCapVisible); + ItemDataField("Is Visible", ref _data.IsCapVisible, onChanged: MeshAuthoring.OnVisibilityChanged); MaterialField("Cap Material", ref _data.CapMaterial); base.OnInspectorGUI(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs index 082b5d088..132a9959d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs @@ -31,24 +31,24 @@ public class ItemMeshInspector : I where TItem : Item, IHittable, IRenderable where TMainAuthoring : ItemMainAuthoring { - private TMeshAuthoring _meshAuthoring; + protected TMeshAuthoring MeshAuthoring; - protected TData Data => _meshAuthoring == null ? null : _meshAuthoring.Data; + protected TData Data => MeshAuthoring == null ? null : MeshAuthoring.Data; protected override void OnEnable() { - _meshAuthoring = target as TMeshAuthoring; + MeshAuthoring = target as TMeshAuthoring; base.OnEnable(); } public override void OnInspectorGUI() { - if (_meshAuthoring == null) { + if (MeshAuthoring == null) { return; } if (GUILayout.Button("Force Update Mesh")) { - _meshAuthoring.RebuildMeshes(); + MeshAuthoring.RebuildMeshes(); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs index 5deffd6ff..3fe4167f4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using Unity.Entities; using UnityEngine; using VisualPinball.Engine.VPT.Bumper; @@ -24,5 +25,9 @@ namespace VisualPinball.Unity public class BumperBaseMeshAuthoring : ItemMeshAuthoring { protected override string MeshId => BumperMeshGenerator.Base; + protected override bool IsVisible { + get => Data.IsBaseVisible; + set => Data.IsBaseVisible = value; + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs index a3eff7356..a4a8b5bed 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs @@ -24,5 +24,9 @@ namespace VisualPinball.Unity public class BumperCapMeshAuthoring : ItemMeshAuthoring { protected override string MeshId => BumperMeshGenerator.Cap; + protected override bool IsVisible { + get => Data.IsCapVisible; + set => Data.IsCollidable = value; + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs index 365abc56c..d87d13f7a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs @@ -23,6 +23,9 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Bumper Ring Mesh")] public class BumperRingMeshAuthoring : ItemMeshAuthoring { - protected override string MeshId => BumperMeshGenerator.Ring; + protected override string MeshId => BumperMeshGenerator.Ring;protected override bool IsVisible { + get => Data.IsRingVisible; + set => Data.IsRingVisible = value; + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs index 2d030090a..baf63c263 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs @@ -24,5 +24,9 @@ namespace VisualPinball.Unity public class BumperSkirtMeshAuthoring : ItemMeshAuthoring { protected override string MeshId => BumperMeshGenerator.Skirt; + protected override bool IsVisible { + get => Data.IsSocketVisible; + set => Data.IsSocketVisible = value; + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperBaseMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperBaseMeshAuthoring.cs index 0c83da850..df25d8f0d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperBaseMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperBaseMeshAuthoring.cs @@ -24,5 +24,9 @@ namespace VisualPinball.Unity public class FlipperBaseMeshAuthoring : ItemMeshAuthoring { protected override string MeshId => FlipperMeshGenerator.Base; + protected override bool IsVisible { + get => Data.IsVisible; + set => Data.IsVisible = value; + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperRubberMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperRubberMeshAuthoring.cs index d76b8f9a3..cb7a07e4a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperRubberMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperRubberMeshAuthoring.cs @@ -24,5 +24,9 @@ namespace VisualPinball.Unity public class FlipperRubberMeshAuthoring : ItemMeshAuthoring { protected override string MeshId => FlipperMeshGenerator.Rubber; + protected override bool IsVisible { + get => Data.IsVisible; + set => Data.IsVisible = value; + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateBracketMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateBracketMeshAuthoring.cs index 76d8429c4..55404cad5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateBracketMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateBracketMeshAuthoring.cs @@ -24,5 +24,9 @@ namespace VisualPinball.Unity public class GateBracketMeshAuthoring : ItemMeshAuthoring { protected override string MeshId => GateMeshGenerator.Bracket; + protected override bool IsVisible { + get => Data.IsVisible; + set => Data.IsVisible = value; + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireMeshAuthoring.cs index 13b824b58..669bc53b9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireMeshAuthoring.cs @@ -24,5 +24,9 @@ namespace VisualPinball.Unity public class GateWireMeshAuthoring : ItemMeshAuthoring { protected override string MeshId => GateMeshGenerator.Wire; + protected override bool IsVisible { + get => Data.IsVisible; + set => Data.IsVisible = value; + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetMeshAuthoring.cs index 8891fa52c..45c1ccc9c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetMeshAuthoring.cs @@ -24,5 +24,9 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Hit Target Mesh")] public class HitTargetMeshAuthoring : ItemMeshAuthoring { + protected override bool IsVisible { + get => Data.IsVisible; + set => Data.IsVisible = value; + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs index 1a2806cc2..7308ff3eb 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs @@ -18,12 +18,9 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; -using NLog; using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT; -using VisualPinball.Engine.VPT.Table; -using Logger = NLog.Logger; namespace VisualPinball.Unity { @@ -32,7 +29,20 @@ public abstract class ItemMeshAuthoring : ItemSubAutho where TItem : Item, IRenderable where TAuthoring : ItemMainAuthoring { + public bool MeshDirty { get => _meshDirty; set => _meshDirty = value; } + public List MaterialRefs => _materialRefs ?? (_materialRefs = GetMembersWithAttribute()); + public List TextureRefs => _textureRefs ?? (_textureRefs = GetMembersWithAttribute()); + protected virtual string MeshId => null; + protected abstract bool IsVisible { get; set; } + + private List _materialRefs; + private List _textureRefs; + + // for tracking if we need to rebuild the meshes (handled by the editor scripts) during undo/redo flows + [HideInInspector] + [SerializeField] + private bool _meshDirty; #region Creation and destruction @@ -66,6 +76,21 @@ private void OnDisable() #endregion + public void OnVisibilityChanged(bool before, bool after) + { + if (before == after) { + return; + } + enabled = after; + } + + public void RebuildMeshes() + { + UpdateMesh(); + ItemDataChanged(); + _meshDirty = false; + } + private void CreateMesh() { var ta = GetComponentInParent(); @@ -137,39 +162,6 @@ protected virtual void OnDrawGizmos() } } - - - - - - - - public List MaterialRefs => _materialRefs ?? (_materialRefs = GetMembersWithAttribute()); - public List TextureRefs => _textureRefs ?? (_textureRefs = GetMembersWithAttribute()); - - private List _materialRefs; - private List _textureRefs; - - private readonly Logger _logger = LogManager.GetCurrentClassLogger(); - - // for tracking if we need to rebuild the meshes (handled by the editor scripts) during undo/redo flows - [HideInInspector] - [SerializeField] - private bool _meshDirty; - public bool MeshDirty { get => _meshDirty; set => _meshDirty = value; } - - public void RebuildMeshes() - { - UpdateMesh(); - - ItemDataChanged(); - _meshDirty = false; - } - - - - - private static List GetMembersWithAttribute() where TAttr: Attribute { return typeof(TData) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerMeshAuthoring.cs index dc8d82be9..6f86dae9f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerMeshAuthoring.cs @@ -23,5 +23,9 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Kicker Bracket Mesh")] public class KickerMeshAuthoring : ItemMeshAuthoring { + protected override bool IsVisible { + get => true; + set { } + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightBulbMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightBulbMeshAuthoring.cs index dd8cceba1..7a9111eb8 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightBulbMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightBulbMeshAuthoring.cs @@ -25,5 +25,9 @@ namespace VisualPinball.Unity public class LightBulbMeshAuthoring : ItemMeshAuthoring { protected override string MeshId => LightMeshGenerator.Bulb; + protected override bool IsVisible { + get => Data.ShowBulbMesh; + set => Data.ShowBulbMesh = value; + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightSocketMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightSocketMeshAuthoring.cs index 0a412f4b8..114b3a383 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightSocketMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightSocketMeshAuthoring.cs @@ -25,5 +25,9 @@ namespace VisualPinball.Unity public class LightSocketMeshAuthoring : ItemMeshAuthoring { protected override string MeshId => LightMeshGenerator.Socket; + protected override bool IsVisible { + get => Data.ShowBulbMesh; + set => Data.ShowBulbMesh = value; + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldMeshAuthoring.cs index f4c19fcd8..25d65cdff 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldMeshAuthoring.cs @@ -7,5 +7,9 @@ namespace VisualPinball.Unity.Playfield [AddComponentMenu("Visual Pinball/Mesh/Playfield Mesh")] public class PlayfieldMeshAuthoring : ItemMeshAuthoring { + protected override bool IsVisible { + get => true; + set { } + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerMeshAuthoring.cs index 37de8940b..0b8f47ae8 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerMeshAuthoring.cs @@ -28,6 +28,11 @@ public abstract class PlungerMeshAuthoring : ItemMeshAuthoring GetVertices(PlungerMeshGenerator meshGenerator, int frame); + protected override bool IsVisible { + get => Data.IsVisible; + set => Data.IsVisible = value; + } + public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { var plunger = transform.parent.gameObject.GetComponent().Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs index 50a0d4a1f..70aa6bc03 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs @@ -23,5 +23,9 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Primitive Mesh")] public class PrimitiveMeshAuthoring : ItemMeshAuthoring { + protected override bool IsVisible { + get => Data.IsVisible; + set => Data.IsVisible = value; + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampFloorMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampFloorMeshAuthoring.cs index a0fa7ac65..409183306 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampFloorMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampFloorMeshAuthoring.cs @@ -24,5 +24,10 @@ namespace VisualPinball.Unity public class RampFloorMeshAuthoring : ItemMeshAuthoring { protected override string MeshId => RampMeshGenerator.Floor; + + protected override bool IsVisible { + get => true; + set { } + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWallMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWallMeshAuthoring.cs index d455707cd..2d6e7ef74 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWallMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWallMeshAuthoring.cs @@ -24,5 +24,9 @@ namespace VisualPinball.Unity public class RampWallMeshAuthoring : ItemMeshAuthoring { protected override string MeshId => RampMeshGenerator.Wall; + protected override bool IsVisible { + get => true; + set { } + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWireMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWireMeshAuthoring.cs index 2740f0205..e75151596 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWireMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWireMeshAuthoring.cs @@ -24,5 +24,9 @@ namespace VisualPinball.Unity public class RampWireMeshAuthoring : ItemMeshAuthoring { protected override string MeshId => RampMeshGenerator.Wires; + protected override bool IsVisible { + get => true; + set { } + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberMeshAuthoring.cs index 73766afb3..cfbc92cd8 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberMeshAuthoring.cs @@ -23,5 +23,9 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Rubber Mesh")] public class RubberMeshAuthoring : ItemMeshAuthoring { + protected override bool IsVisible { + get => Data.IsVisible; + set => Data.IsVisible = value; + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerBracketMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerBracketMeshAuthoring.cs index 63b1ecfce..6ea158d68 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerBracketMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerBracketMeshAuthoring.cs @@ -24,5 +24,9 @@ namespace VisualPinball.Unity public class SpinnerBracketMeshAuthoring : ItemMeshAuthoring { protected override string MeshId => SpinnerMeshGenerator.Bracket; + protected override bool IsVisible { + get => Data.ShowBracket; + set => Data.ShowBracket = value; + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateMeshAuthoring.cs index 962e629eb..c88d9ddb1 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateMeshAuthoring.cs @@ -24,5 +24,9 @@ namespace VisualPinball.Unity public class SpinnerPlateMeshAuthoring : ItemMeshAuthoring { protected override string MeshId => SpinnerMeshGenerator.Plate; + protected override bool IsVisible { + get => Data.IsVisible; + set => Data.IsVisible = value; + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceSideMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceSideMeshAuthoring.cs index fc88dc232..bc2068343 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceSideMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceSideMeshAuthoring.cs @@ -24,5 +24,9 @@ namespace VisualPinball.Unity public class SurfaceSideMeshAuthoring : ItemMeshAuthoring { protected override string MeshId => SurfaceMeshGenerator.Side; + protected override bool IsVisible { + get => Data.IsSideVisible; + set => Data.IsSideVisible = value; + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceTopMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceTopMeshAuthoring.cs index 7a2412375..d3a27b88c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceTopMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceTopMeshAuthoring.cs @@ -24,5 +24,9 @@ namespace VisualPinball.Unity public class SurfaceTopMeshAuthoring : ItemMeshAuthoring { protected override string MeshId => SurfaceMeshGenerator.Top; + protected override bool IsVisible { + get => Data.IsTopBottomVisible; + set => Data.IsTopBottomVisible = value; + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerMeshAuthoring.cs index cd0ffad5c..f2222cc2f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerMeshAuthoring.cs @@ -23,5 +23,9 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Trigger Mesh")] public class TriggerMeshAuthoring : ItemMeshAuthoring { + protected override bool IsVisible { + get => Data.IsVisible; + set => Data.IsVisible = value; + } } } From e04720a2ffbe720e49454d49bacb30522fdb52eb Mon Sep 17 00:00:00 2001 From: freezy Date: Wed, 21 Oct 2020 21:26:25 +0200 Subject: [PATCH 085/124] coils: Add icon to manager. --- .../VisualPinball.Unity.Editor/Managers/Switches.meta | 8 ++++++++ .../Managers/Switches/SwitchManager.cs.meta | 11 +++++++++++ 2 files changed, 19 insertions(+) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Switches.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Switches/SwitchManager.cs.meta diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Switches.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Switches.meta new file mode 100644 index 000000000..cb5c259bf --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Switches.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 53fdb2d40e5e4ad4586e0ce3129fdc6f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Switches/SwitchManager.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Switches/SwitchManager.cs.meta new file mode 100644 index 000000000..f3ffa96ae --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Switches/SwitchManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e73f39298f8f483428ea5662cf0a1471 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 192ac3cad4e9350e44a7805d37e669948060eee5 Mon Sep 17 00:00:00 2001 From: freezy Date: Wed, 21 Oct 2020 21:28:04 +0200 Subject: [PATCH 086/124] chore: Remove unused imports. --- .../Game/RenderObjectGroup.cs | 1 - .../VPT/Light/LightMeshGenerator.cs | 1 - .../Managers/Coil/CoilListData.cs | 2 - .../Managers/Coil/CoilListViewItemRenderer.cs | 1 - .../Managers/Coil/CoilManager.cs | 4 +- .../Managers/Collections/CollectionManager.cs | 2 - .../Managers/SoundManager.cs | 3 - .../Switch/SwitchListViewItemRenderer.cs | 1 - .../Managers/Switch/SwitchManager.cs | 2 - .../Resources/Icons/small_gray/coil.png | Bin 580 -> 564 bytes .../VisualPinball.Unity.Editor/Utils/Icons.cs | 9 +- .../VPT/Bumper/BumperColliderInspector.cs | 1 - .../VPT/ItemMeshInspector.cs | 3 - .../VPT/Surface/SurfaceColliderInspector.cs | 1 - .../VPT/Table/TableInspector.cs | 2 - .../Patcher/Common/Defaults.cs | 2 - .../Patcher/Common/PatcherUtil.cs | 81 ++++---- .../RenderPipelinePatcher/HdrpPatcher.cs | 177 +++++++++--------- .../IRenderPipelinePatcher.cs | 93 +++++---- .../Physics/Collider/QuadTreeTests.cs | 4 - .../Physics/DOTS/DynamicStructTests.cs | 4 - .../Game/Engine/DefaultGamelogicEngine.cs | 1 - .../Game/Engine/IGamelogicEngineWithCoils.cs | 1 - .../Engine/IGamelogicEngineWithSwitches.cs | 1 - .../VPT/Bumper/BumperBaseMeshAuthoring.cs | 1 - .../VPT/HitTarget/HitTargetMeshAuthoring.cs | 1 - .../VisualPinball.Unity/VPT/ItemApi.cs | 2 - 27 files changed, 180 insertions(+), 221 deletions(-) diff --git a/VisualPinball.Engine/Game/RenderObjectGroup.cs b/VisualPinball.Engine/Game/RenderObjectGroup.cs index 9904468b9..6998b7bd4 100644 --- a/VisualPinball.Engine/Game/RenderObjectGroup.cs +++ b/VisualPinball.Engine/Game/RenderObjectGroup.cs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -using System; using System.Linq; using VisualPinball.Engine.Math; diff --git a/VisualPinball.Engine/VPT/Light/LightMeshGenerator.cs b/VisualPinball.Engine/VPT/Light/LightMeshGenerator.cs index 380d9583d..f6fe2011d 100644 --- a/VisualPinball.Engine/VPT/Light/LightMeshGenerator.cs +++ b/VisualPinball.Engine/VPT/Light/LightMeshGenerator.cs @@ -15,7 +15,6 @@ // along with this program. If not, see . using System; -using System.Collections.Generic; using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; using VisualPinball.Engine.Resources.Meshes; diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Coil/CoilListData.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Coil/CoilListData.cs index 0e89b195b..0a6d45378 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Coil/CoilListData.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Coil/CoilListData.cs @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -using System.Linq; -using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Mappings; namespace VisualPinball.Unity.Editor diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Coil/CoilListViewItemRenderer.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Coil/CoilListViewItemRenderer.cs index 3bef5608e..77a22b58f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Coil/CoilListViewItemRenderer.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Coil/CoilListViewItemRenderer.cs @@ -21,7 +21,6 @@ using UnityEditor.IMGUI.Controls; using VisualPinball.Engine.VPT; using System.Linq; -using VisualPinball.Engine; using VisualPinball.Engine.Game.Engines; namespace VisualPinball.Unity.Editor diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Coil/CoilManager.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Coil/CoilManager.cs index d101f0828..ae9de4421 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Coil/CoilManager.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Coil/CoilManager.cs @@ -19,7 +19,6 @@ using NLog; using UnityEditor; using UnityEngine; -using VisualPinball.Engine; using VisualPinball.Engine.Game.Engines; using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Mappings; @@ -61,8 +60,7 @@ public static void ShowWindow() protected override void OnEnable() { - titleContent = new GUIContent("Coil Manager"); - + titleContent = new GUIContent("Coil Manager", Icons.Coil(IconSize.Small)); RowHeight = 22; base.OnEnable(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Collections/CollectionManager.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Collections/CollectionManager.cs index 6e1fc4219..43f715903 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Collections/CollectionManager.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Collections/CollectionManager.cs @@ -21,9 +21,7 @@ using UnityEditor; using UnityEditor.IMGUI.Controls; using UnityEngine; -using VisualPinball.Engine.Common; using VisualPinball.Engine.VPT.Collection; -using VisualPinball.Engine.VPT.Table; namespace VisualPinball.Unity.Editor { diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/SoundManager.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/SoundManager.cs index 23a1fe411..f65d65409 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/SoundManager.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/SoundManager.cs @@ -21,9 +21,6 @@ using VisualPinball.Engine.VPT.Sound; using VisualPinball.Engine.VPT; using VisualPinball.Unity.Editor.Utils; -using System; -using UnityEngine.SceneManagement; -using System.Linq; namespace VisualPinball.Unity.Editor { diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Switch/SwitchListViewItemRenderer.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Switch/SwitchListViewItemRenderer.cs index f2e96b64a..a1092047c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Switch/SwitchListViewItemRenderer.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Switch/SwitchListViewItemRenderer.cs @@ -21,7 +21,6 @@ using UnityEditor.IMGUI.Controls; using VisualPinball.Engine.VPT; using System.Linq; -using VisualPinball.Engine; using VisualPinball.Engine.Game.Engines; namespace VisualPinball.Unity.Editor diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Switch/SwitchManager.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Switch/SwitchManager.cs index 3cf8cdc20..2069d125d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Switch/SwitchManager.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Managers/Switch/SwitchManager.cs @@ -18,9 +18,7 @@ using NLog; using UnityEditor; using UnityEngine; -using VisualPinball.Engine; using VisualPinball.Engine.Game.Engines; -using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Mappings; using Logger = NLog.Logger; diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/coil.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/coil.png index 9ec168027e4a592b33715a31e19576c4c67a3165..466bebf32c1c4aee7dc0a3f8e07b10d6b191ab18 100644 GIT binary patch delta 517 zcmV+g0{Z>L1hfQ@Ie+F!L_t(oh3%O!Zi7G&MSr4nF5(;5Mfz}qKJA~W-dKY$=(k@aHAr01QwJ@{nP$2OoB#T|(u{-m37C+Q=jVb6!i!sgeHGmHQ zOXKu$lf-9@`>Tv7L6!iXt)?4*NCWmU^aiB80}^y@ukipa(0}#7HnFroN7oFhtr=8X zlL2K7pUj-Im@fdY9c>kW9drGeTNETq=oY}IpkJ4o7x-rS9JqyHj!{oVTzART9|05r z5HF5nVfA5)78aC(TvYv}S^iFm7t!%1xemZJ7?gpEjH4^-Io(u7G|loQ!I)sHVNAGC z-FiQywW?%9cYg!zsiKi8DaIQpc8a^CwH2wXQ4%K~h0t}A#HBXqj|J8H00XEmgbsAS zAkd;*0Q!0hLP&^mDKFKM>o-WqZiG9+s)E1j0?tU%vq@bZb$t|_vF-mXBe(g|R zYW+bwpw`wXg+NtWMTu?RAwD@cgvQ)6nLc^;fpSR#x@6k_0GtTumwun@PLxz#QrU%a z`O<09L`R3xM1L_CB=((&h#v=-S5O1y-Qh$bWlkS%FTj1=Ly#sI_JT zDjGhSxnwar0M7&WP5?fH_Pvx8G%0iq;8XG3klX;ig=e->Vp!IwwKP+|2XLU@t}@C2 zywdqre%I=U3K@5NNo_Qs83ls_doqA>gYK%bILCCL0d-&REuzm8gK|IzMH^A6h4Ya? zIg3$2)lHkz41f9Kt164#Uv0FY7dCA@eW^|f<=1mY=a(Cgi31cttFqW=i(dxikD(+G ztx;27H*FaGsevYLRYXuqp*aJ~5};0g>BL6=lqu9S`mMIh#{fzjXnwZN(m-NCdGvcr z(n5un#G`*JMZN~~z`m4ff3CEoC~53zaHK5yC$S_h^?%e)U`bt&MAAU(rd?A7Kekfx z(ch0PNK~M-&a{w6=96Xx2@>ro)spx!+EJ=b0__RP+LEHAiTXWN`4SWlvdqGgxT2>% zi2f|ml6V411En>!Hn5}+%$<{907*qoM6N<$f;-CpTL1t6 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs index e8e92d7c7..404e496a3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs @@ -38,8 +38,10 @@ public IconVariant(string name, IconSize size, IconColor color) } private const string BumperName = "bumper"; + private const string CoilName = "coil"; private const string FlipperName = "flipper"; private const string GateName = "gate"; + private const string KeyName = "keyboard"; private const string KickerName = "kicker"; private const string LightName = "light"; private const string PlungerName = "plunger"; @@ -53,11 +55,11 @@ public IconVariant(string name, IconSize size, IconColor color) private const string TriggerName = "trigger"; private const string SwitchNcName = "switch_nc"; private const string SwitchNoName = "switch_no"; - private const string KeyName = "keyboard"; private static readonly string[] Names = { - BumperName, FlipperName, GateName, KickerName, LightName, PlungerName, PrimitiveName, RampName, RubberName, - SpinnerName, SurfaceName, HitTargetName, TableName, TriggerName, SwitchNcName, SwitchNoName, KeyName + BumperName, CoilName, FlipperName, GateName, KeyName, KickerName, LightName, PlungerName, PrimitiveName, + RampName, RubberName, SpinnerName, SurfaceName, HitTargetName, TableName, TriggerName, SwitchNcName, + SwitchNoName, }; private readonly Dictionary _icons = new Dictionary(); @@ -104,6 +106,7 @@ private Icons() public static Texture2D Target(IconSize size = IconSize.Large, IconColor color = IconColor.Gray) => Instance.GetItem(HitTargetName, size, color); public static Texture2D Trigger(IconSize size = IconSize.Large, IconColor color = IconColor.Gray) => Instance.GetItem(TriggerName, size, color); public static Texture2D Switch(bool normallyClosed, IconSize size = IconSize.Large, IconColor color = IconColor.Gray) => Instance.GetItem(normallyClosed ? SwitchNcName : SwitchNoName, size, color); + public static Texture2D Coil(IconSize size = IconSize.Large, IconColor color = IconColor.Gray) => Instance.GetItem(CoilName, size, color); public static Texture2D Key(IconSize size = IconSize.Large, IconColor color = IconColor.Gray) => Instance.GetItem(KeyName, size, color); public static Texture2D ByComponent(T mb, IconSize size = IconSize.Large, IconColor color = IconColor.Gray) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs index fcd23ee3e..6369d29ef 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs @@ -18,7 +18,6 @@ using UnityEditor; using VisualPinball.Engine.VPT.Bumper; -using VisualPinball.Engine.VPT.Rubber; namespace VisualPinball.Unity.Editor { diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs index 132a9959d..f4629ed94 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs @@ -16,11 +16,8 @@ // ReSharper disable AssignmentInConditionalExpression -using System.Linq; -using UnityEditor; using UnityEngine; using VisualPinball.Engine.Game; -using VisualPinball.Engine.Physics; using VisualPinball.Engine.VPT; namespace VisualPinball.Unity.Editor diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs index 6deaf80b0..2ffba9150 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs @@ -17,7 +17,6 @@ // ReSharper disable AssignmentInConditionalExpression using UnityEditor; -using VisualPinball.Engine.VPT.Rubber; using VisualPinball.Engine.VPT.Surface; namespace VisualPinball.Unity.Editor diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Table/TableInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Table/TableInspector.cs index 9e098552a..433dcac07 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Table/TableInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Table/TableInspector.cs @@ -18,10 +18,8 @@ // ReSharper disable UnusedMember.Local // ReSharper disable UnusedType.Global -using System.Linq; using UnityEditor; using UnityEngine; -using VisualPinball.Engine.Common; namespace VisualPinball.Unity.Editor { diff --git a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Common/Defaults.cs b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Common/Defaults.cs index 7309de9d1..b2691ec17 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Common/Defaults.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Common/Defaults.cs @@ -15,9 +15,7 @@ // along with this program. If not, see . using UnityEngine; -using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT.Primitive; -using VisualPinball.Engine.VPT.Table; namespace VisualPinball.Unity.Patcher { diff --git a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Common/PatcherUtil.cs b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Common/PatcherUtil.cs index cc9f544ff..3f9aae22d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Common/PatcherUtil.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Common/PatcherUtil.cs @@ -1,41 +1,40 @@ -using NLog; -using UnityEngine; -using RenderPipeline = VisualPinball.Unity.Patcher.Matcher.RenderPipeline; -using Logger = NLog.Logger; - -namespace VisualPinball.Unity.Patcher -{ - /// - /// Common methods for patching a table during import. - /// - static class PatcherUtil - { - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - - /// - /// Hide the gameobject. - /// - /// - public static void Hide(GameObject gameObject) - { - gameObject.SetActive(false); - } - - /// - /// Set a new parent for the given child while keeping the position and rotation. - /// - /// - /// - public static void Reparent(GameObject child, GameObject parent) - { - var rot = child.transform.rotation; - var pos = child.transform.position; - - // re-parent the child - child.transform.SetParent(parent.transform, false); - - child.transform.rotation = rot; - child.transform.position = pos; - } - } -} +using NLog; +using UnityEngine; +using Logger = NLog.Logger; + +namespace VisualPinball.Unity.Patcher +{ + /// + /// Common methods for patching a table during import. + /// + static class PatcherUtil + { + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + /// + /// Hide the gameobject. + /// + /// + public static void Hide(GameObject gameObject) + { + gameObject.SetActive(false); + } + + /// + /// Set a new parent for the given child while keeping the position and rotation. + /// + /// + /// + public static void Reparent(GameObject child, GameObject parent) + { + var rot = child.transform.rotation; + var pos = child.transform.position; + + // re-parent the child + child.transform.SetParent(parent.transform, false); + + child.transform.rotation = rot; + child.transform.position = pos; + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/RenderPipelinePatcher/HdrpPatcher.cs b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/RenderPipelinePatcher/HdrpPatcher.cs index 27bef4e86..3880b8785 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/RenderPipelinePatcher/HdrpPatcher.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/RenderPipelinePatcher/HdrpPatcher.cs @@ -1,89 +1,88 @@ -using NLog; -using UnityEngine; -using Logger = NLog.Logger; - -namespace VisualPinball.Unity.Patcher.RenderPipelinePatcher -{ - public class HdrpPatcher : IRenderPipelinePatcher - { - private static readonly NLog.Logger Logger = LogManager.GetCurrentClassLogger(); - - public void SetOpaque(GameObject gameObject) - { - var material = gameObject.GetComponent().sharedMaterial; - - material.SetFloat("_SurfaceType", 0); - - material.SetFloat("_DstBlend", 0); - material.SetFloat("_ZWrite", 1); - - material.DisableKeyword("_ALPHATEST_ON"); - material.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); - material.DisableKeyword("_BLENDMODE_PRE_MULTIPLY"); - material.DisableKeyword("_BLENDMODE_PRESERVE_SPECULAR_LIGHTING"); - } - - public void SetDoubleSided(GameObject gameObject) - { - - var material = gameObject.GetComponent().sharedMaterial; - - material.EnableKeyword("_DOUBLESIDED_ON"); - material.EnableKeyword("_NORMALMAP_TANGENT_SPACE"); - - material.SetInt("_DoubleSidedEnable", 1); - material.SetInt("_DoubleSidedNormalMode", 1); - - material.SetInt("_CullMode", 0); - material.SetInt("_CullModeForward", 0); - } - - public void SetTransparentDepthPrepassEnabled(GameObject gameObject) - { - var material = gameObject.GetComponent().sharedMaterial; - - material.EnableKeyword("_DISABLE_SSR_TRANSPARENT"); - - material.SetInt("_TransparentDepthPrepassEnable", 1); - material.SetInt("_AlphaDstBlend", 10); - material.SetInt("_ZTestModeDistortion", 4); - - material.SetShaderPassEnabled("TransparentDepthPrepass", true); - material.SetShaderPassEnabled("RayTracingPrepass", true); - - } - - public void SetAlphaCutOff(GameObject gameObject, float value) - { - var material = gameObject.GetComponent().sharedMaterial; - - // enable the property - SetAlphaCutOffEnabled(gameObject); - - // set the cut-off value - material.SetFloat("_AlphaCutoff", value); - } - - public void SetAlphaCutOffEnabled(GameObject gameObject) - { - var material = gameObject.GetComponent().sharedMaterial; - - material.EnableKeyword("_ALPHATEST_ON"); - material.SetInt("_AlphaCutoffEnable", 1); - } - - public void SetNormalMapDisabled(GameObject gameObject) - { - var material = gameObject.GetComponent().sharedMaterial; - - material.SetTexture("_NormalMap", null); - material.DisableKeyword("_NORMALMAP"); - } - - public void SetMetallic(GameObject gameObject, float value) - { - var material = gameObject.GetComponent().sharedMaterial; - material.SetFloat("_Metallic", value); - } - } -} +using NLog; +using UnityEngine; + +namespace VisualPinball.Unity.Patcher.RenderPipelinePatcher +{ + public class HdrpPatcher : IRenderPipelinePatcher + { + private static readonly NLog.Logger Logger = LogManager.GetCurrentClassLogger(); + + public void SetOpaque(GameObject gameObject) + { + var material = gameObject.GetComponent().sharedMaterial; + + material.SetFloat("_SurfaceType", 0); + + material.SetFloat("_DstBlend", 0); + material.SetFloat("_ZWrite", 1); + + material.DisableKeyword("_ALPHATEST_ON"); + material.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); + material.DisableKeyword("_BLENDMODE_PRE_MULTIPLY"); + material.DisableKeyword("_BLENDMODE_PRESERVE_SPECULAR_LIGHTING"); + } + + public void SetDoubleSided(GameObject gameObject) + { + + var material = gameObject.GetComponent().sharedMaterial; + + material.EnableKeyword("_DOUBLESIDED_ON"); + material.EnableKeyword("_NORMALMAP_TANGENT_SPACE"); + + material.SetInt("_DoubleSidedEnable", 1); + material.SetInt("_DoubleSidedNormalMode", 1); + + material.SetInt("_CullMode", 0); + material.SetInt("_CullModeForward", 0); + } + + public void SetTransparentDepthPrepassEnabled(GameObject gameObject) + { + var material = gameObject.GetComponent().sharedMaterial; + + material.EnableKeyword("_DISABLE_SSR_TRANSPARENT"); + + material.SetInt("_TransparentDepthPrepassEnable", 1); + material.SetInt("_AlphaDstBlend", 10); + material.SetInt("_ZTestModeDistortion", 4); + + material.SetShaderPassEnabled("TransparentDepthPrepass", true); + material.SetShaderPassEnabled("RayTracingPrepass", true); + + } + + public void SetAlphaCutOff(GameObject gameObject, float value) + { + var material = gameObject.GetComponent().sharedMaterial; + + // enable the property + SetAlphaCutOffEnabled(gameObject); + + // set the cut-off value + material.SetFloat("_AlphaCutoff", value); + } + + public void SetAlphaCutOffEnabled(GameObject gameObject) + { + var material = gameObject.GetComponent().sharedMaterial; + + material.EnableKeyword("_ALPHATEST_ON"); + material.SetInt("_AlphaCutoffEnable", 1); + } + + public void SetNormalMapDisabled(GameObject gameObject) + { + var material = gameObject.GetComponent().sharedMaterial; + + material.SetTexture("_NormalMap", null); + material.DisableKeyword("_NORMALMAP"); + } + + public void SetMetallic(GameObject gameObject, float value) + { + var material = gameObject.GetComponent().sharedMaterial; + material.SetFloat("_Metallic", value); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/RenderPipelinePatcher/IRenderPipelinePatcher.cs b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/RenderPipelinePatcher/IRenderPipelinePatcher.cs index 998660078..76ff807b8 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/RenderPipelinePatcher/IRenderPipelinePatcher.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/RenderPipelinePatcher/IRenderPipelinePatcher.cs @@ -1,48 +1,45 @@ -using System; -using System.Collections.Generic; -using System.Text; -using UnityEngine; - -namespace VisualPinball.Unity.Patcher.RenderPipelinePatcher -{ - public interface IRenderPipelinePatcher - { - /// - /// Set the material of the gameobject to opaque. - /// - /// - void SetOpaque(GameObject gameObject); - - /// - /// Set the material of the gameobject to double sided. - /// - /// - void SetDoubleSided(GameObject gameObject); - - void SetTransparentDepthPrepassEnabled(GameObject gameObject); - - /// - /// Set the AlphaCutOff value for the material of the gameobject. - /// - /// - void SetAlphaCutOff(GameObject gameObject, float value); - - /// - /// Enable AlphaCutOff for the material of the gameobject. - /// - /// - void SetAlphaCutOffEnabled(GameObject gameObject); - - /// - /// Disable NormalMap for the material of the gameobject. - /// - /// - void SetNormalMapDisabled(GameObject gameObject); - - /// - /// Set the Metallic value for the material of the gameobject. - /// - /// - void SetMetallic(GameObject gameObject, float value); - } -} +using UnityEngine; + +namespace VisualPinball.Unity.Patcher.RenderPipelinePatcher +{ + public interface IRenderPipelinePatcher + { + /// + /// Set the material of the gameobject to opaque. + /// + /// + void SetOpaque(GameObject gameObject); + + /// + /// Set the material of the gameobject to double sided. + /// + /// + void SetDoubleSided(GameObject gameObject); + + void SetTransparentDepthPrepassEnabled(GameObject gameObject); + + /// + /// Set the AlphaCutOff value for the material of the gameobject. + /// + /// + void SetAlphaCutOff(GameObject gameObject, float value); + + /// + /// Enable AlphaCutOff for the material of the gameobject. + /// + /// + void SetAlphaCutOffEnabled(GameObject gameObject); + + /// + /// Disable NormalMap for the material of the gameobject. + /// + /// + void SetNormalMapDisabled(GameObject gameObject); + + /// + /// Set the Metallic value for the material of the gameobject. + /// + /// + void SetMetallic(GameObject gameObject, float value); + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Test/Physics/Collider/QuadTreeTests.cs b/VisualPinball.Unity/VisualPinball.Unity.Test/Physics/Collider/QuadTreeTests.cs index 2fe9e81f3..66dc8fb34 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Test/Physics/Collider/QuadTreeTests.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Test/Physics/Collider/QuadTreeTests.cs @@ -14,11 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -using System.Collections.Generic; using NUnit.Framework; -using VisualPinball.Engine.Math; -using VisualPinball.Engine.Physics; -using VisualPinball.Engine.VPT; namespace VisualPinball.Unity.Test { diff --git a/VisualPinball.Unity/VisualPinball.Unity.Test/Physics/DOTS/DynamicStructTests.cs b/VisualPinball.Unity/VisualPinball.Unity.Test/Physics/DOTS/DynamicStructTests.cs index 1ca25e38a..7a56137fa 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Test/Physics/DOTS/DynamicStructTests.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Test/Physics/DOTS/DynamicStructTests.cs @@ -14,15 +14,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -using System.Collections.Generic; using NUnit.Framework; using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; using Unity.Entities; using Unity.Mathematics; -using VisualPinball.Engine.Math; -using VisualPinball.Engine.Physics; -using VisualPinball.Engine.VPT; namespace VisualPinball.Unity.Test { diff --git a/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/DefaultGamelogicEngine.cs b/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/DefaultGamelogicEngine.cs index 01fff7877..9a64353a7 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/DefaultGamelogicEngine.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/DefaultGamelogicEngine.cs @@ -18,7 +18,6 @@ using System.Collections.Generic; using System.Diagnostics; using NLog; -using VisualPinball.Engine; using VisualPinball.Engine.Common; using VisualPinball.Engine.Game.Engines; diff --git a/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/IGamelogicEngineWithCoils.cs b/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/IGamelogicEngineWithCoils.cs index 800ff182b..2e21da0ae 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/IGamelogicEngineWithCoils.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/IGamelogicEngineWithCoils.cs @@ -15,7 +15,6 @@ // along with this program. If not, see . using System; -using VisualPinball.Engine; using VisualPinball.Engine.Game.Engines; namespace VisualPinball.Unity diff --git a/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/IGamelogicEngineWithSwitches.cs b/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/IGamelogicEngineWithSwitches.cs index 116dc03c3..def5e299c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/IGamelogicEngineWithSwitches.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/IGamelogicEngineWithSwitches.cs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -using VisualPinball.Engine; using VisualPinball.Engine.Game.Engines; namespace VisualPinball.Unity diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs index 3fe4167f4..45b4f692b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -using Unity.Entities; using UnityEngine; using VisualPinball.Engine.VPT.Bumper; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetMeshAuthoring.cs index 45c1ccc9c..0059a083f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetMeshAuthoring.cs @@ -15,7 +15,6 @@ // along with this program. If not, see . using UnityEngine; -using VisualPinball.Engine.VPT.Bumper; using VisualPinball.Engine.VPT.HitTarget; namespace VisualPinball.Unity diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemApi.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemApi.cs index 852624a48..249388033 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemApi.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemApi.cs @@ -14,10 +14,8 @@ // 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; using VisualPinball.Engine.VPT.Table; From 26a6d4d52ef4d113e8039e01cd99a884a1b9492b Mon Sep 17 00:00:00 2001 From: freezy Date: Wed, 21 Oct 2020 22:12:23 +0200 Subject: [PATCH 087/124] patcher: Re-enable patching. --- .../Matcher/Item/ItemMatchAttribute.cs | 2 +- .../Matcher/Item/NameMatchAttribute.cs | 2 +- .../Matcher/Item/RenderPipelineAttribute.cs | 2 +- .../Matcher/RenderPipeline.cs | 2 +- .../Patcher/Common/Defaults.cs | 2 +- .../Patcher/Patcher.cs | 4 +- .../Patcher/Tables/Mississippi.cs | 114 +++++++++--------- .../Import/VpxConverter.cs | 16 +-- 8 files changed, 73 insertions(+), 71 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Matcher/Item/ItemMatchAttribute.cs b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Matcher/Item/ItemMatchAttribute.cs index a9e5e413b..fcc0d7690 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Matcher/Item/ItemMatchAttribute.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Matcher/Item/ItemMatchAttribute.cs @@ -28,6 +28,6 @@ public abstract class ItemMatchAttribute : Attribute /// public string Ref; - public abstract bool Matches(Engine.VPT.Table.Table table, IRenderable item, RenderObject ro, GameObject obj); + public abstract bool Matches(Engine.VPT.Table.Table table, IRenderable item, GameObject obj); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Matcher/Item/NameMatchAttribute.cs b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Matcher/Item/NameMatchAttribute.cs index 3c97331ab..011474ac2 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Matcher/Item/NameMatchAttribute.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Matcher/Item/NameMatchAttribute.cs @@ -34,7 +34,7 @@ public NameMatchAttribute(string name) _name = name; } - public override bool Matches(Engine.VPT.Table.Table table, IRenderable item, RenderObject ro, GameObject obj) + public override bool Matches(Engine.VPT.Table.Table table, IRenderable item, GameObject obj) { return IgnoreCase ? string.Equals(item.Name, _name, StringComparison.CurrentCultureIgnoreCase) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Matcher/Item/RenderPipelineAttribute.cs b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Matcher/Item/RenderPipelineAttribute.cs index 4c772feff..6eaea0d00 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Matcher/Item/RenderPipelineAttribute.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Matcher/Item/RenderPipelineAttribute.cs @@ -31,7 +31,7 @@ public RenderPipelineAttribute(RenderPipelineType type) _type = type; } - public override bool Matches(Engine.VPT.Table.Table table, IRenderable item, RenderObject ro, GameObject obj) + public override bool Matches(Engine.VPT.Table.Table table, IRenderable item, GameObject obj) { return RenderPipeline.Current == _type; } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Matcher/RenderPipeline.cs b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Matcher/RenderPipeline.cs index f0f44970b..e5060edfb 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Matcher/RenderPipeline.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Matcher/RenderPipeline.cs @@ -40,7 +40,7 @@ public static RenderPipelineType Current return RenderPipelineType.Hdrp; } } - return RenderPipelineType.BuiltIn; + return RenderPipelineType.BuiltIn; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Common/Defaults.cs b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Common/Defaults.cs index b2691ec17..7ded02606 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Common/Defaults.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Common/Defaults.cs @@ -44,7 +44,7 @@ public void RemoveFlipperShadow(GameObject gameObject) [NameMatch("Ruler_mm")] [NameMatch("Ruler_inches")] [NameMatch("Ruler_inches_and_mm")] - public void RemoveColliders(GameObject gameObject, Primitive item) + public void RemoveColliders(Primitive item) { item.Data.IsCollidable = false; item.Data.IsToy = true; diff --git a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Patcher.cs b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Patcher.cs index 511459f27..4e56cdc2f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Patcher.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Patcher.cs @@ -53,7 +53,7 @@ public Patcher(Table table, string fileName) Logger.Info("Table will be patched using the following patchers: [ {0} ]", string.Join(", ", _patchers.Select(o => o.GetType().Name))); } - public void ApplyPatches(IRenderable item, RenderObject renderObject, GameObject gameObject, GameObject tableGameObject) + public void ApplyPatches(IRenderable item, GameObject gameObject, GameObject tableGameObject) { foreach (var patcher in _patchers) { var methods = patcher.GetType().GetMembers().Where(member => member.MemberType == MemberTypes.Method); @@ -67,7 +67,7 @@ public void ApplyPatches(IRenderable item, RenderObject renderObject, GameObject if (methodInfo != null) { foreach (var methodMatcher in methodMatchers) { var validArgs = true; - if (methodMatcher.Matches(_table, item, renderObject, gameObject)) { + if (methodMatcher.Matches(_table, item, gameObject)) { var patcherParamInfos = methodInfo.GetParameters(); var patcherParams = new object[patcherParamInfos.Length]; diff --git a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Tables/Mississippi.cs b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Tables/Mississippi.cs index 97f18bd8f..452c54ac1 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Tables/Mississippi.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Tables/Mississippi.cs @@ -1,57 +1,57 @@ -// 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 . - -// ReSharper disable StringLiteralTypo - -using UnityEngine; -using VisualPinball.Unity.Patcher.Matcher; - -namespace VisualPinball.Unity.Patcher -{ - [MetaMatch(TableName = "Mississipi", AuthorName = "jpsalas, akiles50000, Loserman")] - public class Mississippi - { - [NameMatch("lrail1", Ref = "Ramps/lrail1/LeftWall")] // left outside wall to the left - [NameMatch("rrail1", Ref = "Ramps/rrail1/LeftWall")] // left inside wall to the right - public void SetDoubleSided(GameObject gameObject, ref GameObject child) - { - if (gameObject == child) - RenderPipeline.Patcher.SetDoubleSided(gameObject); - } - - /// - /// Activate depth prepass or else the image visibility changes depending on distance - /// - /// - /// - [NameMatch("wall13", Ref = "Surfaces/wall13/Top")] - [NameMatch("wall14", Ref = "Surfaces/wall14/Top")] - [NameMatch("wall15", Ref = "Surfaces/wall15/Top")] - [NameMatch("wall18", Ref = "Surfaces/wall18/Top")] - [NameMatch("wall19", Ref = "Surfaces/wall19/Top")] - [NameMatch("wall22", Ref = "Surfaces/wall22/Top")] - [NameMatch("wall23", Ref = "Surfaces/wall23/Top")] - [NameMatch("wall359", Ref = "Surfaces/wall359/Top")] - [NameMatch("apron", Ref = "Surfaces/apron/Top")] - public void SetTransparentDepthPrepassEnabled(GameObject gameObject, ref GameObject child) - { - if (gameObject == child) - { - RenderPipeline.Patcher.SetTransparentDepthPrepassEnabled(gameObject); - } - } - } -} +// 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 . + +// ReSharper disable StringLiteralTypo + +using UnityEngine; +using VisualPinball.Unity.Patcher.Matcher; + +namespace VisualPinball.Unity.Patcher +{ + [MetaMatch(TableName = "Mississipi", AuthorName = "jpsalas, akiles50000, Loserman")] + public class Mississippi + { + [NameMatch("lrail1", Ref = "Ramps/lrail1/LeftWall")] // left outside wall to the left + [NameMatch("rrail1", Ref = "Ramps/rrail1/LeftWall")] // left inside wall to the right + public void SetDoubleSided(GameObject gameObject, ref GameObject child) + { + if (gameObject == child) + RenderPipeline.Patcher.SetDoubleSided(gameObject); + } + + /// + /// Activate depth prepass or else the image visibility changes depending on distance + /// + /// + /// + [NameMatch("wall13", Ref = "Surfaces/wall13/Top")] + [NameMatch("wall14", Ref = "Surfaces/wall14/Top")] + [NameMatch("wall15", Ref = "Surfaces/wall15/Top")] + [NameMatch("wall18", Ref = "Surfaces/wall18/Top")] + [NameMatch("wall19", Ref = "Surfaces/wall19/Top")] + [NameMatch("wall22", Ref = "Surfaces/wall22/Top")] + [NameMatch("wall23", Ref = "Surfaces/wall23/Top")] + [NameMatch("wall359", Ref = "Surfaces/wall359/Top")] + [NameMatch("apron", Ref = "Surfaces/apron/Top")] + public void SetTransparentDepthPrepassEnabled(GameObject gameObject, ref GameObject child) + { + if (gameObject == child) + { + RenderPipeline.Patcher.SetTransparentDepthPrepassEnabled(gameObject); + } + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index 60a8f8858..646c68b8a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -125,12 +125,16 @@ private void ConvertGameItems(GameObject tableGameObject) { var createdMainObjs = new Dictionary(); var createdMainMbs = new Dictionary(); + var renderableLookup = new Dictionary(); var renderables = from renderable in _table.Renderables orderby renderable.SubComponent select renderable; foreach (var renderable in renderables) { + var lookupName = renderable.Name.ToLower(); + renderableLookup[lookupName] = renderable; + // create group parent if not created if (!_parents.ContainsKey(renderable.ItemGroupName)) { var parent = new GameObject(renderable.ItemGroupName); @@ -142,8 +146,8 @@ orderby renderable.SubComponent // create object(s) var (rootObj, rootMb) = CreateGameObjects(_table, renderable, _parents[renderable.ItemGroupName]); - createdMainObjs[renderable.Name.ToLower()] = rootObj; - createdMainMbs[renderable.Name.ToLower()] = rootMb; + createdMainObjs[lookupName] = rootObj; + createdMainMbs[lookupName] = rootMb; } else { // if the object's names was parsed to be part of another object, re-link to other object. @@ -161,11 +165,9 @@ orderby renderable.SubComponent } // now we have all renderables imported, patch them. - // foreach (var renderable in createdObjs.Keys) { - // foreach (var (obj, ro) in createdObjs[renderable]) { - // _tableAuthoring.Patcher.ApplyPatches(renderable, ro, obj, tableGameObject); - // } - // } + foreach (var lookupName in createdMainObjs.Keys) { + _tableAuthoring.Patcher.ApplyPatches(renderableLookup[lookupName], createdMainObjs[lookupName], tableGameObject); + } } public static (GameObject, IItemMainAuthoring) CreateGameObjects(Table table, IRenderable renderable, GameObject parent, IItemMainAuthoring parentAuthoring = null) From 1fc8b565bbe0899440ff3bff5d7a9d52f4231219 Mon Sep 17 00:00:00 2001 From: freezy Date: Wed, 21 Oct 2020 22:39:51 +0200 Subject: [PATCH 088/124] import: Patch item-only patchers before creating game object. --- .../Matcher/Item/ItemMatchAttribute.cs | 2 +- .../Patcher/Patcher.cs | 41 +++++++++++++++++++ .../Import/VpxConverter.cs | 13 +----- .../VPT/Primitive/PrimitiveExtensions.cs | 4 +- 4 files changed, 47 insertions(+), 13 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Matcher/Item/ItemMatchAttribute.cs b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Matcher/Item/ItemMatchAttribute.cs index fcc0d7690..4ccc0a941 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Matcher/Item/ItemMatchAttribute.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Matcher/Item/ItemMatchAttribute.cs @@ -28,6 +28,6 @@ public abstract class ItemMatchAttribute : Attribute /// public string Ref; - public abstract bool Matches(Engine.VPT.Table.Table table, IRenderable item, GameObject obj); + public abstract bool Matches(Engine.VPT.Table.Table table, IRenderable item, GameObject obj); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Patcher.cs b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Patcher.cs index 4e56cdc2f..e18ab3a4a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Patcher.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Patcher.cs @@ -53,6 +53,47 @@ public Patcher(Table table, string fileName) Logger.Info("Table will be patched using the following patchers: [ {0} ]", string.Join(", ", _patchers.Select(o => o.GetType().Name))); } + public void ApplyPrePatches(IRenderable item) + { + foreach (var patcher in _patchers) { + var methods = patcher.GetType().GetMembers().Where(member => member.MemberType == MemberTypes.Method); + foreach (var method in methods) { + var methodMatchers = Attribute + .GetCustomAttributes(method, typeof(ItemMatchAttribute)) + .Select(a => a as ItemMatchAttribute) + .Where(a => a != null); + + var methodInfo = method as MethodInfo; + if (methodInfo != null) { + foreach (var methodMatcher in methodMatchers) { + var validArgs = true; + if (methodMatcher.Matches(_table, item, null)) { + var patcherParamInfos = methodInfo.GetParameters(); + var patcherParams = new object[patcherParamInfos.Length]; + + foreach (var pi in patcherParamInfos) { + if (pi.ParameterType.GetInterfaces().Contains(typeof(IItem)) && item.GetType() == pi.ParameterType) { + patcherParams[pi.Position] = item; + + } else if (pi.ParameterType == typeof(IRenderable) && item.GetType().GetInterfaces().Contains(typeof(IRenderable))) { + patcherParams[pi.Position] = item; + + } else { + validArgs = false; + } + } + + if (validArgs) { + Logger.Info($"Patching element {item.Name} based on match by {patcher.GetType().Name}.{method.Name}"); + methodInfo.Invoke(patcher, patcherParams); + } + } + } + } + } + } + } + public void ApplyPatches(IRenderable item, GameObject gameObject, GameObject tableGameObject) { foreach (var patcher in _patchers) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index 646c68b8a..42edd6bf6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -87,17 +87,6 @@ public void Convert(string fileName, Table table, bool applyPatch = true, string _tableAuthoring.Patcher = new Patcher.Patcher(_table, fileName); - // generate meshes and save (pbr) materials - // var materials = new Dictionary(); - // foreach (var r in _table.Renderables) { - // _renderObjects[r] = r.GetRenderObjects(_table, Origin.Original, false); - // foreach (var ro in _renderObjects[r].RenderObjects) { - // if (!materials.ContainsKey(ro.Material.Id)) { - // materials[ro.Material.Id] = ro.Material; - // } - // } - // } - // import ConvertGameItems(go); @@ -132,6 +121,8 @@ orderby renderable.SubComponent foreach (var renderable in renderables) { + _tableAuthoring.Patcher.ApplyPrePatches(renderable); + var lookupName = renderable.Name.ToLower(); renderableLookup[lookupName] = renderable; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs index 8f00cd9dd..8fffc9c38 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs @@ -30,7 +30,9 @@ public static IItemMainAuthoring SetupGameObject(this Primitive primitive, GameO switch (primitive.SubComponent) { case ItemSubComponent.None: - obj.AddComponent(); + if (!primitive.Data.IsToy) { + obj.AddComponent(); + } obj.AddComponent(); break; From 4edfc709940cc80ed5df885847df8b722e8540ee Mon Sep 17 00:00:00 2001 From: freezy Date: Wed, 21 Oct 2020 23:06:57 +0200 Subject: [PATCH 089/124] debug: Print collider count. --- VisualPinball.Engine/Game/IHittable.cs | 2 +- .../Physics/Collision/QuadTreeCreationSystem.cs | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/VisualPinball.Engine/Game/IHittable.cs b/VisualPinball.Engine/Game/IHittable.cs index 9bb2be7af..1ebf34754 100644 --- a/VisualPinball.Engine/Game/IHittable.cs +++ b/VisualPinball.Engine/Game/IHittable.cs @@ -19,7 +19,7 @@ namespace VisualPinball.Engine.Game { public interface IHittable : IPlayable { - + string Name { get; } int Index { get; } int Version { get; } HitObject[] GetHitShapes(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/QuadTreeCreationSystem.cs b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/QuadTreeCreationSystem.cs index 0b627d98a..4c4f4b59f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/QuadTreeCreationSystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/QuadTreeCreationSystem.cs @@ -40,14 +40,18 @@ public static void Create(EntityManager entityManager) var hittables = table.Hittables.Where(hittable => hittable.IsCollidable).ToArray(); var hitObjects = new List(); var id = 0; + var log = ""; foreach (var item in hittables) { - foreach (var hitObject in item.GetHitShapes()) { + var hitShapes = item.GetHitShapes(); + log += item.Name + ": " + hitShapes.Length + "\n"; + foreach (var hitObject in hitShapes) { hitObject.SetIndex(item.Index, item.Version); hitObject.Id = id++; hitObject.CalcHitBBox(); hitObjects.Add(hitObject); } } + Logger.Info("Collider Count:\n" + log); // construct quad tree var quadTree = new Engine.Physics.QuadTree(hitObjects, table.BoundingBox); From 97e038dc55784b452babaf7f69131c5e7ed6b677 Mon Sep 17 00:00:00 2001 From: freezy Date: Thu, 22 Oct 2020 01:07:20 +0200 Subject: [PATCH 090/124] components: Start working on parenting. --- VisualPinball.Engine/VPT/Item.cs | 1 + .../Import/VpxConverter.cs | 50 +---------------- .../VPT/Bumper/BumperAuthoring.cs | 3 +- .../VPT/Bumper/BumperExtensions.cs | 55 +++++++++++++++---- .../VPT/Flipper/FlipperAuthoring.cs | 3 +- .../VPT/Flipper/FlipperExtensions.cs | 36 ++++++++---- .../VPT/Gate/GateAuthoring.cs | 3 +- .../VPT/Gate/GateExtensions.cs | 8 +-- .../VPT/HitTarget/HitTargetAuthoring.cs | 3 +- .../VPT/HitTarget/HitTargetExtensions.cs | 8 +-- .../VPT/IHittableAuthoring.cs | 27 --------- .../VPT/IHittableAuthoring.cs.meta | 11 ---- .../VPT/IItemColliderAuthoring.cs | 2 +- .../VPT/IItemMainAuthoring.cs | 2 + .../VPT/IItemMeshAuthoring.cs | 1 - .../VisualPinball.Unity/VPT/IMeshAuthoring.cs | 27 --------- .../VPT/IMeshAuthoring.cs.meta | 11 ---- .../VPT/ItemMainAuthoring.cs | 39 +++++++++++++ .../VPT/Kicker/KickerAuthoring.cs | 3 +- .../VPT/Kicker/KickerExtensions.cs | 8 +-- .../VPT/Light/LightAuthoring.cs | 3 +- .../VPT/Light/LightExtensions.cs | 4 +- .../VPT/Playfield/PlayfieldAuthoring.cs | 3 +- .../VPT/Plunger/PlungerAuthoring.cs | 6 +- .../VPT/Plunger/PlungerExtensions.cs | 8 +-- .../VPT/Primitive/PrimitiveAuthoring.cs | 3 +- .../VPT/Primitive/PrimitiveExtensions.cs | 32 +++++++---- .../VPT/Ramp/RampAuthoring.cs | 5 +- .../VPT/Ramp/RampExtensions.cs | 8 +-- .../VPT/Rubber/RubberAuthoring.cs | 4 +- .../VPT/Rubber/RubberExtensions.cs | 31 ++++++++--- .../VPT/Spinner/SpinnerAuthoring.cs | 3 +- .../VPT/Spinner/SpinnerExtensions.cs | 8 +-- .../VPT/Surface/SurfaceAuthoring.cs | 5 +- .../VPT/Surface/SurfaceExtensions.cs | 8 +-- .../VPT/Table/TableAuthoring.cs | 1 + .../VPT/Trigger/TriggerAuthoring.cs | 4 +- .../VPT/Trigger/TriggerExtensions.cs | 8 +-- 38 files changed, 218 insertions(+), 227 deletions(-) delete mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/IHittableAuthoring.cs delete mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/IHittableAuthoring.cs.meta delete mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/IMeshAuthoring.cs delete mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/IMeshAuthoring.cs.meta diff --git a/VisualPinball.Engine/VPT/Item.cs b/VisualPinball.Engine/VPT/Item.cs index 2f66f3712..14cb07048 100644 --- a/VisualPinball.Engine/VPT/Item.cs +++ b/VisualPinball.Engine/VPT/Item.cs @@ -55,6 +55,7 @@ public string Name protected Item(TData data) { Data = data; + (ComponentName, SubComponent, SubName) = SplitName(); } private (string, ItemSubComponent, string) SplitName() diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index 42edd6bf6..7bb1a8745 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -147,7 +147,7 @@ orderby renderable.SubComponent var mainObj = createdMainObjs[parentName]; var mainMb = createdMainMbs[parentName]; var (rootObj, _) = CreateGameObjects(_table, renderable, _parents[renderable.ItemGroupName], mainMb); - rootObj.transform.SetParent(mainObj.transform, false); + rootObj.transform.SetParent(mainObj.transform, true); } else { throw new InvalidOperationException($"Cannot find component \"{parentName}\" that is supposed to be the parent of \"{renderable.Name}\"."); @@ -197,54 +197,6 @@ private static IItemMainAuthoring SetupGameObjects(IRenderable item, GameObject return mainAuthoring; } - // private static IEnumerable> SetupRenderObject(GameObject obj, RenderObjectGroup rog, TableAuthoring tb) - // { - // var createdObjs = new Tuple[0]; - // if (rog.HasOnlyChild && !rog.ForceChild) { - // SetupMesh(obj, rog.RenderObjects[0], tb); - // createdObjs = new[] { new Tuple(obj, rog.RenderObjects[0]) }; - // - // } else if (rog.HasChildren) { - // createdObjs = new Tuple[rog.RenderObjects.Length]; - // var i = 0; - // foreach (var ro in rog.RenderObjects) { - // var subObj = new GameObject(ro.Name); - // subObj.transform.SetParent(obj.transform, false); - // subObj.layer = ChildObjectsLayer; - // SetupMesh(subObj, ro, tb); - // createdObjs[i++] = new Tuple(subObj, ro); - // } - // } - // - // return createdObjs; - // } - - // private static void SetupMesh(GameObject obj, RenderObject ro, TableAuthoring ta) - // { - // if (ro.Mesh == null) { - // Logger.Warn($"No mesh for object {obj.name}, skipping."); - // return; - // } - // - // var mesh = ro.Mesh.ToUnityMesh($"{obj.name}_mesh"); - // - // // apply mesh to game object - // var mf = obj.AddComponent(); - // mf.sharedMesh = mesh; - // - // // apply material - // if (ro.Mesh.AnimationFrames.Count > 0) { - // var smr = obj.AddComponent(); - // smr.sharedMaterial = ro.Material.ToUnityMaterial(ta); - // smr.sharedMesh = mesh; - // smr.enabled = ro.IsVisible; - // } else { - // var mr = obj.AddComponent(); - // mr.sharedMaterial = ro.Material.ToUnityMaterial(ta); - // mr.enabled = ro.IsVisible; - // } - // } - private void MakeSerializable(GameObject go, Table table) { // add table component (plus other data) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs index 69c69effc..d0706ae2a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs @@ -31,11 +31,12 @@ namespace VisualPinball.Unity [ExecuteAlways] [AddComponentMenu("Visual Pinball/Game Item/Bumper")] public class BumperAuthoring : ItemMainAuthoring, - IHittableAuthoring, ISwitchAuthoring, ICoilAuthoring, IConvertGameObjectToEntity + ISwitchAuthoring, ICoilAuthoring, IConvertGameObjectToEntity { protected override Bumper InstantiateItem(BumperData data) => new Bumper(data); protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); public IHittable Hittable => Item; public ISwitchable Switchable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs index 437e727f1..8de10d7fa 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs @@ -31,10 +31,12 @@ public static IItemMainAuthoring SetupGameObject(this Bumper bumper, GameObject switch (bumper.SubComponent) { case ItemSubComponent.None: obj.AddComponent(); - CreateChild(obj, BumperMeshGenerator.Base); - CreateChild(obj, BumperMeshGenerator.Cap); - var ring = CreateChild(obj, BumperMeshGenerator.Ring); - var skirt = CreateChild(obj, BumperMeshGenerator.Skirt); + + CreateBaseMeshComponent(bumper, obj); + CreateCapMeshComponent(bumper, obj); + + var ring = CreateRingMeshComponent(bumper, obj); + var skirt = CreateSkirtMeshComponent(bumper, obj); ring.AddComponent(); skirt.AddComponent(); @@ -42,16 +44,19 @@ public static IItemMainAuthoring SetupGameObject(this Bumper bumper, GameObject case ItemSubComponent.Collider: { obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { - hittableAuthoring.RemoveHittableComponent(); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyColliderComponent(); } break; } case ItemSubComponent.Mesh: { - // todo - if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { - meshAuthoring.RemoveMeshComponent(); + CreateBaseMeshComponent(bumper, obj); + CreateCapMeshComponent(bumper, obj); + CreateRingMeshComponent(bumper, obj); + CreateSkirtMeshComponent(bumper, obj); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyMeshComponent(); } break; } @@ -63,13 +68,39 @@ public static IItemMainAuthoring SetupGameObject(this Bumper bumper, GameObject return mainAuthoring; } - private static GameObject CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring + private static void CreateBaseMeshComponent(Bumper rubber, GameObject obj) + { + var meshComp = CreateChild(obj, BumperMeshGenerator.Base); + meshComp.enabled = rubber.Data.IsBaseVisible; + } + + private static void CreateCapMeshComponent(Bumper rubber, GameObject obj) + { + var meshComp = CreateChild(obj, BumperMeshGenerator.Cap); + meshComp.enabled = rubber.Data.IsBaseVisible; + } + + private static GameObject CreateRingMeshComponent(Bumper rubber, GameObject obj) + { + var meshComp = CreateChild(obj, BumperMeshGenerator.Ring); + meshComp.enabled = rubber.Data.IsRingVisible; + return meshComp.gameObject; + } + + private static GameObject CreateSkirtMeshComponent(Bumper rubber, GameObject obj) + { + var meshComp = CreateChild(obj, BumperMeshGenerator.Skirt); + meshComp.enabled = rubber.Data.IsSocketVisible; + return meshComp.gameObject; + } + + private static T CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring { var subObj = new GameObject(name); subObj.transform.SetParent(obj.transform, false); - subObj.AddComponent(); + var comp = subObj.AddComponent(); //subObj.layer = ChildObjectsLayer; - return subObj; + return comp; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs index d75dd3a1e..3ea3d8f45 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs @@ -33,11 +33,12 @@ namespace VisualPinball.Unity [RequiresEntityConversion] [AddComponentMenu("Visual Pinball/Game Item/Flipper")] public class FlipperAuthoring : ItemMainAuthoring, - IHittableAuthoring, ISwitchAuthoring, ICoilAuthoring, IConvertGameObjectToEntity + ISwitchAuthoring, ICoilAuthoring, IConvertGameObjectToEntity { protected override Flipper InstantiateItem(FlipperData data) => new Flipper(data); protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); public IHittable Hittable => Item; public ISwitchable Switchable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs index b9bab4a16..29151f8b4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs @@ -15,15 +15,19 @@ // along with this program. If not, see . using System; +using NLog; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Flipper; +using Logger = NLog.Logger; namespace VisualPinball.Unity { internal static class FlipperExtensions { + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + public static IItemMainAuthoring SetupGameObject(this Flipper flipper, GameObject obj, IItemMainAuthoring parentAuthoring) { var mainAuthoring = obj.AddComponent().SetItem(flipper); @@ -31,22 +35,30 @@ public static IItemMainAuthoring SetupGameObject(this Flipper flipper, GameObjec switch (flipper.SubComponent) { case ItemSubComponent.None: obj.AddComponent(); - CreateChild(obj, FlipperMeshGenerator.Base); - CreateChild(obj, FlipperMeshGenerator.Rubber); + + // if invisible in main component, we skip creation entirely, because we think users won't dynamically toggle visibility. + if (flipper.Data.IsVisible) { + CreateChild(obj, FlipperMeshGenerator.Base); + CreateChild(obj, FlipperMeshGenerator.Rubber); + } break; case ItemSubComponent.Collider: { - obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { - hittableAuthoring.RemoveHittableComponent(); - } + Logger.Error("Cannot parent a flipper collider to a different object than a flipper!"); break; } case ItemSubComponent.Mesh: { - // todo - if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { - meshAuthoring.RemoveMeshComponent(); + + // if invisible in sub component, the mesh is explicitly created, so just disable it if invisible. + var baseComp = CreateChild(obj, FlipperMeshGenerator.Base); + var rubberComp = CreateChild(obj, FlipperMeshGenerator.Rubber); + baseComp.enabled = flipper.Data.IsVisible; + rubberComp.enabled = flipper.Data.IsVisible; + + CreateChild(obj, FlipperMeshGenerator.Rubber); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyMeshComponent(); } break; } @@ -58,13 +70,13 @@ public static IItemMainAuthoring SetupGameObject(this Flipper flipper, GameObjec return mainAuthoring; } - public static GameObject CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring + public static T CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring { var subObj = new GameObject(name); subObj.transform.SetParent(obj.transform, false); - subObj.AddComponent(); + var comp = subObj.AddComponent(); //subObj.layer = ChildObjectsLayer; - return subObj; + return comp; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs index 5ca980a08..3dd5173ec 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs @@ -33,11 +33,12 @@ namespace VisualPinball.Unity [ExecuteAlways] [AddComponentMenu("Visual Pinball/Game Item/Gate")] public class GateAuthoring : ItemMainAuthoring, - IHittableAuthoring, ISwitchAuthoring, IConvertGameObjectToEntity + ISwitchAuthoring, IConvertGameObjectToEntity { protected override Gate InstantiateItem(GateData data) => new Gate(data); protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); public IHittable Hittable => Item; public ISwitchable Switchable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs index bfa960c36..dd43d90ad 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs @@ -38,16 +38,16 @@ public static IItemMainAuthoring SetupGameObject(this Gate gate, GameObject obj, case ItemSubComponent.Collider: { obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { - hittableAuthoring.RemoveHittableComponent(); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyColliderComponent(); } break; } case ItemSubComponent.Mesh: { // todo - if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { - meshAuthoring.RemoveMeshComponent(); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyMeshComponent(); } break; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs index c06a86115..1c4d50bfb 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs @@ -31,11 +31,12 @@ namespace VisualPinball.Unity [ExecuteAlways] [AddComponentMenu("Visual Pinball/Game Item/Hit Target")] public class HitTargetAuthoring : ItemMainAuthoring, - IHittableAuthoring, ISwitchAuthoring, IConvertGameObjectToEntity + ISwitchAuthoring, IConvertGameObjectToEntity { protected override HitTarget InstantiateItem(HitTargetData data) => new HitTarget(data); protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); public IHittable Hittable => Item; public ISwitchable Switchable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs index f69ba738c..bfbe5630e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs @@ -36,16 +36,16 @@ public static IItemMainAuthoring SetupGameObject(this HitTarget hitTarget, GameO case ItemSubComponent.Collider: { obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { - hittableAuthoring.RemoveHittableComponent(); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyColliderComponent(); } break; } case ItemSubComponent.Mesh: { obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { - meshAuthoring.RemoveMeshComponent(); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyMeshComponent(); } break; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IHittableAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IHittableAuthoring.cs deleted file mode 100644 index 8ca1aea22..000000000 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IHittableAuthoring.cs +++ /dev/null @@ -1,27 +0,0 @@ -// 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.Game; - -namespace VisualPinball.Unity -{ - public interface IHittableAuthoring - { - IHittable Hittable { get; } - - void RemoveHittableComponent(); - } -} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IHittableAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/IHittableAuthoring.cs.meta deleted file mode 100644 index 97a6c35d3..000000000 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IHittableAuthoring.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9d53a596163c0304798ea242ed2bf8f8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs index 4dabbc457..c7eaa590f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs @@ -16,7 +16,7 @@ namespace VisualPinball.Unity { - public interface IItemColliderAuthoring + public interface IItemColliderAuthoring : IItemAuthoring { } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs index c0622484e..2a792cb52 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs @@ -29,6 +29,8 @@ public interface IItemMainAuthoring : IItemAuthoring /// void SetMeshDirty(); void RebuildMeshIfDirty(); + void DestroyMeshComponent(); + void DestroyColliderComponent(); // the following interfaces allow each item behavior to define which axes should // be shown on the scene view gizmo, the gizmo itself will use the associated diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs index 923bc5ccd..3dc4ac397 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs @@ -23,7 +23,6 @@ namespace VisualPinball.Unity public interface IItemMeshAuthoring : IItemAuthoring { bool MeshDirty { get; set; } - ItemData ItemData { get; } List MaterialRefs { get; } List TextureRefs { get; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IMeshAuthoring.cs deleted file mode 100644 index dc3744f4e..000000000 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IMeshAuthoring.cs +++ /dev/null @@ -1,27 +0,0 @@ -// 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.Game; - -namespace VisualPinball.Unity -{ - public interface IMeshAuthoring - { - IRenderable Renderable { get; } - - void RemoveMeshComponent(); - } -} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IMeshAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/IMeshAuthoring.cs.meta deleted file mode 100644 index de81cf5cc..000000000 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IMeshAuthoring.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c2515efbac260db4ba1d9459e79dabf3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs index 59db0752f..fc47f024d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs @@ -53,6 +53,11 @@ public abstract class ItemMainAuthoring : ItemAuthoring (IItemMeshAuthoring) c) .Where(ma => ma.ItemData == _data) : new IItemMeshAuthoring[0]; + private IEnumerable ColliderComponents => ColliderAuthoringType != null ? + GetComponentsInChildren(ColliderAuthoringType, true) + .Select(c => (IItemColliderAuthoring) c) + .Where(ca => ca.ItemData == _data) : new IItemColliderAuthoring[0]; + public IItemMainAuthoring SetItem(TItem item, string gameObjectName = null) { _item = item; @@ -84,11 +89,45 @@ public void RebuildMeshIfDirty() } } + public void DestroyMeshComponent() + { + foreach (var component in MeshComponents) { + var mb = component as MonoBehaviour; + + // if game object is the same, remove component + if (mb.gameObject == gameObject) { + DestroyImmediate(mb); + + } else { + // otherwise, destroy entire game object + DestroyImmediate(mb.gameObject); + } + } + } + + public void DestroyColliderComponent() + { + foreach (var component in ColliderComponents) { + var mb = component as MonoBehaviour; + + // if game object is the same, remove component + if (mb.gameObject == gameObject) { + DestroyImmediate(mb); + + } else { + // otherwise, destroy entire game object + DestroyImmediate(mb.gameObject); + } + } + } + /// /// Authoring type of the child class. /// protected abstract Type MeshAuthoringType { get; } + protected abstract Type ColliderAuthoringType { get; } + /// /// Instantiates a new item based on the item data. /// diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs index df3eba7a5..8147f656f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs @@ -33,11 +33,12 @@ namespace VisualPinball.Unity [ExecuteAlways] [AddComponentMenu("Visual Pinball/Game Item/Kicker")] public class KickerAuthoring : ItemMainAuthoring, - IHittableAuthoring, ISwitchAuthoring, ICoilAuthoring, IConvertGameObjectToEntity + ISwitchAuthoring, ICoilAuthoring, IConvertGameObjectToEntity { protected override Kicker InstantiateItem(KickerData data) => new Kicker(data); protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); public IHittable Hittable => Item; public ISwitchable Switchable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs index 5117dc56b..2b0981aec 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs @@ -36,16 +36,16 @@ public static IItemMainAuthoring SetupGameObject(this Kicker kicker, GameObject case ItemSubComponent.Collider: { obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { - hittableAuthoring.RemoveHittableComponent(); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyColliderComponent(); } break; } case ItemSubComponent.Mesh: { obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { - meshAuthoring.RemoveMeshComponent(); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyMeshComponent(); } break; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs index 0a7007df4..b42bf3bd9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs @@ -34,7 +34,8 @@ public class LightAuthoring : ItemMainAuthoring protected override Light InstantiateItem(LightData data) => new Light(data); - protected override Type MeshAuthoringType { get; } = null; + protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + protected override Type ColliderAuthoringType { get; } = null; public void OnBulbEnabled(bool bulbEnabledBefore, bool bulbEnabledAfter) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs index 809e4a13e..783472e8e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs @@ -34,8 +34,8 @@ public static IItemMainAuthoring SetupGameObject(this Light light, GameObject ob CreateChild(obj, LightMeshGenerator.Socket); if (light.SubComponent == ItemSubComponent.Mesh) { - if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { - meshAuthoring.RemoveMeshComponent(); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyMeshComponent(); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs index 87cb6c4f9..36ff39e2f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs @@ -23,7 +23,7 @@ namespace VisualPinball.Unity { public class PlayfieldAuthoring : ItemMainAuthoring, - IHittableAuthoring, IMeshAuthoring, IConvertGameObjectToEntity + IConvertGameObjectToEntity { public IRenderable Renderable => Table; @@ -34,6 +34,7 @@ public class PlayfieldAuthoring : ItemMainAuthoring, protected override Table InstantiateItem(TableData data) => throw new InvalidOperationException("Table is not instantiated via authoring component."); protected override Type MeshAuthoringType { get; } = null; + protected override Type ColliderAuthoringType { get; } = null; public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs index d2739d8c6..f7cce6b3b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs @@ -17,7 +17,6 @@ using System; using Unity.Entities; using UnityEngine; -using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Plunger; @@ -26,13 +25,12 @@ namespace VisualPinball.Unity [ExecuteAlways] [AddComponentMenu("Visual Pinball/Game Item/Plunger")] public class PlungerAuthoring : ItemMainAuthoring, - IHittableAuthoring, ICoilAuthoring, IConvertGameObjectToEntity + ICoilAuthoring, IConvertGameObjectToEntity { protected override Plunger InstantiateItem(PlungerData data) => new Plunger(data); protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); - - public IHittable Hittable => Item; + protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); private void OnDestroy() { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs index e60c2e82c..9306708f6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs @@ -36,16 +36,16 @@ public static IItemMainAuthoring SetupGameObject(this Plunger plunger, GameObjec case ItemSubComponent.Collider: { obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { - hittableAuthoring.RemoveHittableComponent(); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyColliderComponent(); } break; } case ItemSubComponent.Mesh: { CreateMeshComponents(plunger, obj); - if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { - meshAuthoring.RemoveMeshComponent(); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyMeshComponent(); } break; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs index deb4caac4..bb89acd38 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs @@ -29,12 +29,13 @@ namespace VisualPinball.Unity { [AddComponentMenu("Visual Pinball/Game Item/Primitive")] - public class PrimitiveAuthoring : ItemMainAuthoring, IHittableAuthoring, IConvertGameObjectToEntity + public class PrimitiveAuthoring : ItemMainAuthoring, IConvertGameObjectToEntity { protected override Primitive InstantiateItem(PrimitiveData data) => new Primitive(data); protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs index 8fffc9c38..587082058 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs @@ -30,24 +30,22 @@ public static IItemMainAuthoring SetupGameObject(this Primitive primitive, GameO switch (primitive.SubComponent) { case ItemSubComponent.None: - if (!primitive.Data.IsToy) { - obj.AddComponent(); - } - obj.AddComponent(); + obj.AddMeshComponent(primitive); + obj.AddColliderComponent(primitive); break; case ItemSubComponent.Collider: { - obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { - hittableAuthoring.RemoveHittableComponent(); + obj.AddColliderComponent(primitive); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyColliderComponent(); } break; } case ItemSubComponent.Mesh: { - obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { - meshAuthoring.RemoveMeshComponent(); + obj.AddMeshComponent(primitive); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyMeshComponent(); } break; } @@ -58,5 +56,19 @@ public static IItemMainAuthoring SetupGameObject(this Primitive primitive, GameO obj.AddComponent(); return mainAuthoring; } + + private static void AddMeshComponent(this GameObject obj, Primitive primitive) + { + var comp = obj.AddComponent(); + comp.enabled = primitive.Data.IsVisible; + } + + private static void AddColliderComponent(this GameObject obj, Primitive primitive) + { + if (!primitive.Data.IsToy) { + var comp = obj.AddComponent(); + comp.enabled = primitive.IsCollidable; + } + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs index 7a40cc4e4..6e66b6b7e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs @@ -33,13 +33,12 @@ namespace VisualPinball.Unity { [ExecuteAlways] [AddComponentMenu("Visual Pinball/Game Item/Ramp")] - public class RampAuthoring : ItemMainAuthoring, IDragPointsEditable, IConvertGameObjectToEntity, IHittableAuthoring + public class RampAuthoring : ItemMainAuthoring, IDragPointsEditable, IConvertGameObjectToEntity { protected override Ramp InstantiateItem(RampData data) => new Ramp(data); protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); - - public IHittable Hittable => Item; + protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs index 60692b46b..d52bbaeb6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs @@ -36,8 +36,8 @@ public static IItemMainAuthoring SetupGameObject(this Ramp ramp, GameObject obj, case ItemSubComponent.Collider: { obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { - hittableAuthoring.RemoveHittableComponent(); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyColliderComponent(); } break; } @@ -45,8 +45,8 @@ public static IItemMainAuthoring SetupGameObject(this Ramp ramp, GameObject obj, case ItemSubComponent.Mesh: { // todo CreateMeshComponents(ramp, obj); - if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { - meshAuthoring.RemoveMeshComponent(); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyMeshComponent(); } break; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs index 72a32692b..69fdd8f56 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs @@ -33,14 +33,14 @@ namespace VisualPinball.Unity [ExecuteAlways] [AddComponentMenu("Visual Pinball/Game Item/Rubber")] public class RubberAuthoring : ItemMainAuthoring, - IDragPointsEditable, IHittableAuthoring, IMeshAuthoring, IConvertGameObjectToEntity + IDragPointsEditable, IConvertGameObjectToEntity { protected override Rubber InstantiateItem(RubberData data) => new Rubber(data); protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); public IHittable Hittable => Item; - public IRenderable Renderable => Item; private void OnDestroy() { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs index f66496329..6db4565c2 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs @@ -29,23 +29,24 @@ public static IItemMainAuthoring SetupGameObject(this Rubber rubber, GameObject var mainAuthoring = obj.AddComponent().SetItem(rubber); switch (rubber.SubComponent) { - case ItemSubComponent.None: - obj.AddComponent(); - obj.AddComponent(); + case ItemSubComponent.None: { + AddColliderComponent(rubber, obj); + AddMeshComponent(rubber, obj); break; + } case ItemSubComponent.Collider: { - obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { - hittableAuthoring.RemoveHittableComponent(); + AddColliderComponent(rubber, obj); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyColliderComponent(); } break; } case ItemSubComponent.Mesh: { - obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { - meshAuthoring.RemoveMeshComponent(); + AddMeshComponent(rubber, obj); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyMeshComponent(); } break; } @@ -53,8 +54,20 @@ public static IItemMainAuthoring SetupGameObject(this Rubber rubber, GameObject default: throw new ArgumentOutOfRangeException(); } + obj.AddComponent(); return mainAuthoring; } + + private static void AddMeshComponent(Rubber rubber, GameObject obj) + { + var meshComponent = obj.AddComponent(); + meshComponent.enabled = rubber.Data.IsVisible; + } + + private static void AddColliderComponent(Rubber rubber, GameObject obj) + { + obj.AddComponent(); + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs index 98a20e0b9..4e713bac5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs @@ -33,11 +33,12 @@ namespace VisualPinball.Unity [ExecuteAlways] [AddComponentMenu("Visual Pinball/Game Item/Spinner")] public class SpinnerAuthoring : ItemMainAuthoring, - IHittableAuthoring, ISwitchAuthoring, IConvertGameObjectToEntity + ISwitchAuthoring, IConvertGameObjectToEntity { protected override Spinner InstantiateItem(SpinnerData data) => new Spinner(data); protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); public IHittable Hittable => Item; public ISwitchable Switchable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs index 71f248de9..c01b13e62 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs @@ -38,16 +38,16 @@ public static IItemMainAuthoring SetupGameObject(this Spinner spinner, GameObjec case ItemSubComponent.Collider: { obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { - hittableAuthoring.RemoveHittableComponent(); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyColliderComponent(); } break; } case ItemSubComponent.Mesh: { // todo - if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { - meshAuthoring.RemoveMeshComponent(); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyMeshComponent(); } break; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs index f7c60c5a9..36adf0f41 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs @@ -33,13 +33,12 @@ namespace VisualPinball.Unity [ExecuteAlways] [AddComponentMenu("Visual Pinball/Game Item/Surface")] public class SurfaceAuthoring : ItemMainAuthoring, - IHittableAuthoring, IConvertGameObjectToEntity, IDragPointsEditable + IConvertGameObjectToEntity, IDragPointsEditable { protected override Surface InstantiateItem(SurfaceData data) => new Surface(data); protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); - - public IHittable Hittable => Item; + protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); private void OnDestroy() { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs index bced8a0b1..3caba0fe7 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs @@ -37,8 +37,8 @@ public static IItemMainAuthoring SetupGameObject(this Surface surface, GameObjec case ItemSubComponent.Collider: { obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { - hittableAuthoring.RemoveHittableComponent(); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyColliderComponent(); } break; } @@ -46,8 +46,8 @@ public static IItemMainAuthoring SetupGameObject(this Surface surface, GameObjec case ItemSubComponent.Mesh: { CreateChild(obj, SurfaceMeshGenerator.Side); CreateChild(obj, SurfaceMeshGenerator.Top); - if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { - meshAuthoring.RemoveMeshComponent(); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyMeshComponent(); } break; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs index 376496380..0b74ce376 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs @@ -58,6 +58,7 @@ public class TableAuthoring : ItemMainAuthoring protected override Table InstantiateItem(TableData data) => RecreateTable(data); protected override Type MeshAuthoringType { get; } = null; + protected override Type ColliderAuthoringType { get; } = null; public Table Table => Item; public TableSerializedTextureContainer Textures => _sidecar?.textures; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs index 96bce7117..c90efe3e7 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs @@ -33,13 +33,13 @@ namespace VisualPinball.Unity [ExecuteAlways] [AddComponentMenu("Visual Pinball/Game Item/Trigger")] public class TriggerAuthoring : ItemMainAuthoring, - IHittableAuthoring, ISwitchAuthoring, IDragPointsEditable, IConvertGameObjectToEntity + ISwitchAuthoring, IDragPointsEditable, IConvertGameObjectToEntity { protected override Trigger InstantiateItem(TriggerData data) => new Trigger(data); protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); + protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); - public IHittable Hittable => Item; public ISwitchable Switchable => Item; private void OnDestroy() diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs index 5dba714a6..e90b7c1c5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs @@ -36,16 +36,16 @@ public static IItemMainAuthoring SetupGameObject(this Trigger trigger, GameObjec case ItemSubComponent.Collider: { obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IHittableAuthoring hittableAuthoring) { - hittableAuthoring.RemoveHittableComponent(); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyColliderComponent(); } break; } case ItemSubComponent.Mesh: { obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IMeshAuthoring meshAuthoring) { - meshAuthoring.RemoveMeshComponent(); + if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { + parentMainAuthoring.DestroyMeshComponent(); } break; } From 71da13082fb76bd441c4633f18f14b68fbed58c5 Mon Sep 17 00:00:00 2001 From: freezy Date: Thu, 22 Oct 2020 11:28:33 +0200 Subject: [PATCH 091/124] components: Move children into parent space. --- VisualPinball.Engine/Game/IRenderable.cs | 4 ++++ VisualPinball.Engine/VPT/Bumper/Bumper.cs | 4 ++++ VisualPinball.Engine/VPT/Flipper/Flipper.cs | 3 +++ VisualPinball.Engine/VPT/Gate/Gate.cs | 3 +++ VisualPinball.Engine/VPT/HitTarget/HitTarget.cs | 3 +++ VisualPinball.Engine/VPT/Item.cs | 1 + VisualPinball.Engine/VPT/Kicker/Kicker.cs | 3 +++ VisualPinball.Engine/VPT/Light/Light.cs | 3 +++ VisualPinball.Engine/VPT/Plunger/Plunger.cs | 3 +++ VisualPinball.Engine/VPT/Primitive/Primitive.cs | 2 ++ VisualPinball.Engine/VPT/Ramp/Ramp.cs | 3 +++ VisualPinball.Engine/VPT/Rubber/Rubber.cs | 3 +++ VisualPinball.Engine/VPT/Spinner/Spinner.cs | 3 +++ VisualPinball.Engine/VPT/Surface/Surface.cs | 3 +++ VisualPinball.Engine/VPT/Table/Table.cs | 3 +++ VisualPinball.Engine/VPT/Trigger/Trigger.cs | 3 +++ .../VisualPinball.Unity/Import/VpxConverter.cs | 9 ++++++++- 17 files changed, 55 insertions(+), 1 deletion(-) diff --git a/VisualPinball.Engine/Game/IRenderable.cs b/VisualPinball.Engine/Game/IRenderable.cs index 592440365..e65565ffe 100644 --- a/VisualPinball.Engine/Game/IRenderable.cs +++ b/VisualPinball.Engine/Game/IRenderable.cs @@ -27,5 +27,9 @@ public interface IRenderable : IItem RenderObject GetRenderObject(Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true); RenderObjectGroup GetRenderObjects(Table table, Origin origin = Origin.Global, bool asRightHanded = true); + + Vertex3D Position { get; set; } + + float RotationY { get; set; } } } diff --git a/VisualPinball.Engine/VPT/Bumper/Bumper.cs b/VisualPinball.Engine/VPT/Bumper/Bumper.cs index 185f4c599..1acf45da0 100644 --- a/VisualPinball.Engine/VPT/Bumper/Bumper.cs +++ b/VisualPinball.Engine/VPT/Bumper/Bumper.cs @@ -26,6 +26,10 @@ public class Bumper : Item, IRenderable, IHittable, ISwitchable, ICo { public override string ItemName { get; } = "Bumper"; public override string ItemGroupName { get; } = "Bumpers"; + + public Vertex3D Position { get => new Vertex3D(Data.Center.X, Data.Center.Y, 0); set => Data.Center = new Vertex2D(value.X, value.Y); } + public float RotationY { get => Data.Orientation; set => Data.Orientation = value; } + public bool IsPulseSwitch => true; private readonly BumperMeshGenerator _meshGenerator; diff --git a/VisualPinball.Engine/VPT/Flipper/Flipper.cs b/VisualPinball.Engine/VPT/Flipper/Flipper.cs index 225cc9ab4..fb7bfc212 100644 --- a/VisualPinball.Engine/VPT/Flipper/Flipper.cs +++ b/VisualPinball.Engine/VPT/Flipper/Flipper.cs @@ -26,6 +26,9 @@ public class Flipper : Item, IRenderable, IHittable, ISwitchable, I public override string ItemName { get; } = "Flipper"; public override string ItemGroupName { get; } = "Flippers"; + public Vertex3D Position { get => new Vertex3D(Data.Center.X, Data.Center.Y, 0); set => Data.Center = new Vertex2D(value.X, value.Y); } + public float RotationY { get => Data.StartAngle; set => Data.StartAngle = value; } + public bool IsPulseSwitch => false; private readonly FlipperMeshGenerator _meshGenerator; diff --git a/VisualPinball.Engine/VPT/Gate/Gate.cs b/VisualPinball.Engine/VPT/Gate/Gate.cs index 3be8064db..fa391afcb 100644 --- a/VisualPinball.Engine/VPT/Gate/Gate.cs +++ b/VisualPinball.Engine/VPT/Gate/Gate.cs @@ -27,6 +27,9 @@ public class Gate : Item, IRenderable, IHittable, ISwitchable public override string ItemName { get; } = "Gate"; public override string ItemGroupName { get; } = "Gates"; + public Vertex3D Position { get => new Vertex3D(Data.Center.X, Data.Center.Y, 0); set => Data.Center = new Vertex2D(value.X, value.Y); } + public float RotationY { get => Data.Rotation; set => Data.Rotation = value; } + public bool IsPulseSwitch => true; private readonly GateMeshGenerator _meshGenerator; diff --git a/VisualPinball.Engine/VPT/HitTarget/HitTarget.cs b/VisualPinball.Engine/VPT/HitTarget/HitTarget.cs index 88f0dfd10..a1f72e8d8 100644 --- a/VisualPinball.Engine/VPT/HitTarget/HitTarget.cs +++ b/VisualPinball.Engine/VPT/HitTarget/HitTarget.cs @@ -26,6 +26,9 @@ public class HitTarget : Item, IRenderable, IHittable, ISwitchabl public override string ItemName { get; } = "Target"; public override string ItemGroupName { get; } = "Targets"; + public Vertex3D Position { get => Data.Position; set => Data.Position = value; } + public float RotationY { get => Data.RotZ; set => Data.RotZ = value; } + public bool IsPulseSwitch => true; public HitObject[] GetHitShapes() => _hits; diff --git a/VisualPinball.Engine/VPT/Item.cs b/VisualPinball.Engine/VPT/Item.cs index 14cb07048..0941a60ea 100644 --- a/VisualPinball.Engine/VPT/Item.cs +++ b/VisualPinball.Engine/VPT/Item.cs @@ -15,6 +15,7 @@ // along with this program. If not, see . using System; +using VisualPinball.Engine.Math; namespace VisualPinball.Engine.VPT { diff --git a/VisualPinball.Engine/VPT/Kicker/Kicker.cs b/VisualPinball.Engine/VPT/Kicker/Kicker.cs index a130521ba..272ba2a84 100644 --- a/VisualPinball.Engine/VPT/Kicker/Kicker.cs +++ b/VisualPinball.Engine/VPT/Kicker/Kicker.cs @@ -26,6 +26,9 @@ public class Kicker : Item, IRenderable, IBallCreationPosition, IHit public override string ItemName { get; } = "Kicker"; public override string ItemGroupName { get; } = "Kickers"; + public Vertex3D Position { get => new Vertex3D(Data.Center.X, Data.Center.Y, 0); set => Data.Center = new Vertex2D(value.X, value.Y); } + public float RotationY { get => Data.Angle; set => Data.Angle = value; } + public bool IsPulseSwitch => false; public KickerHit KickerHit => _hit; diff --git a/VisualPinball.Engine/VPT/Light/Light.cs b/VisualPinball.Engine/VPT/Light/Light.cs index 4ef6cc200..e946bf27e 100644 --- a/VisualPinball.Engine/VPT/Light/Light.cs +++ b/VisualPinball.Engine/VPT/Light/Light.cs @@ -25,6 +25,9 @@ public class Light : Item, IRenderable public override string ItemName { get; } = "Light"; public override string ItemGroupName { get; } = "Lights"; + public Vertex3D Position { get => new Vertex3D(Data.Center.X, Data.Center.Y, 0); set => Data.Center = new Vertex2D(value.X, value.Y); } + public float RotationY { get => 0; set { } } + public const string BulbMaterialName = "__bulbMaterial"; public const string SocketMaterialName = "__bulbSocketMaterial"; diff --git a/VisualPinball.Engine/VPT/Plunger/Plunger.cs b/VisualPinball.Engine/VPT/Plunger/Plunger.cs index 830379032..654e79d56 100644 --- a/VisualPinball.Engine/VPT/Plunger/Plunger.cs +++ b/VisualPinball.Engine/VPT/Plunger/Plunger.cs @@ -26,6 +26,9 @@ public class Plunger : Item, IRenderable, IHittable, ICoilable public override string ItemName { get; } = "Plunger"; public override string ItemGroupName { get; } = "Plungers"; + public Vertex3D Position { get => new Vertex3D(Data.Center.X, Data.Center.Y, 0); set => Data.Center = new Vertex2D(value.X, value.Y); } + public float RotationY { get => 0; set { } } + public PlungerHit PlungerHit { get; private set; } public const float PlungerHeight = 50.0f; diff --git a/VisualPinball.Engine/VPT/Primitive/Primitive.cs b/VisualPinball.Engine/VPT/Primitive/Primitive.cs index 06717d982..7274b37c9 100644 --- a/VisualPinball.Engine/VPT/Primitive/Primitive.cs +++ b/VisualPinball.Engine/VPT/Primitive/Primitive.cs @@ -37,6 +37,8 @@ public class Primitive : Item, IRenderable, IHittable private readonly PrimitiveMeshGenerator _meshGenerator; private readonly PrimitiveHitGenerator _hitGenerator; private HitObject[] _hits; + public Vertex3D Position { get => Data.Position; set => Data.Position = value; } + public float RotationY { get => Data.RotAndTra[1]; set => Data.RotAndTra[1] = value; } public Primitive(PrimitiveData data) : base(data) { diff --git a/VisualPinball.Engine/VPT/Ramp/Ramp.cs b/VisualPinball.Engine/VPT/Ramp/Ramp.cs index e9e954337..119f9f07a 100644 --- a/VisualPinball.Engine/VPT/Ramp/Ramp.cs +++ b/VisualPinball.Engine/VPT/Ramp/Ramp.cs @@ -26,6 +26,9 @@ public class Ramp : Item, IRenderable, IHittable public override string ItemName { get; } = "Ramp"; public override string ItemGroupName { get; } = "Ramps"; + public Vertex3D Position { get => new Vertex3D(0, 0, 0); set { } } + public float RotationY { get => 0; set { } } + public HitObject[] GetHitShapes() => _hits; public bool IsHabitrail => Data.RampType == RampType.RampType4Wire diff --git a/VisualPinball.Engine/VPT/Rubber/Rubber.cs b/VisualPinball.Engine/VPT/Rubber/Rubber.cs index 474477201..85aa94ca9 100644 --- a/VisualPinball.Engine/VPT/Rubber/Rubber.cs +++ b/VisualPinball.Engine/VPT/Rubber/Rubber.cs @@ -26,6 +26,9 @@ public class Rubber : Item, IRenderable, IHittable public override string ItemName { get; } = "Rubber"; public override string ItemGroupName { get; } = "Rubbers"; + public Vertex3D Position { get => new Vertex3D(0, 0, 0); set { } } + public float RotationY { get => 0; set { } } + public HitObject[] GetHitShapes() => _hits; private readonly RubberMeshGenerator _meshGenerator; diff --git a/VisualPinball.Engine/VPT/Spinner/Spinner.cs b/VisualPinball.Engine/VPT/Spinner/Spinner.cs index ed3f9bd94..2dfd4f498 100644 --- a/VisualPinball.Engine/VPT/Spinner/Spinner.cs +++ b/VisualPinball.Engine/VPT/Spinner/Spinner.cs @@ -29,6 +29,9 @@ public class Spinner : Item, IRenderable, IHittable, ISwitchable public Matrix3D TransformationMatrix { get; } = Matrix3D.Identity; + public Vertex3D Position { get => new Vertex3D(Data.Center.X, Data.Center.Y, 0); set => Data.Center = new Vertex2D(value.X, value.Y); } + public float RotationY { get => Data.Rotation; set => Data.Rotation = value; } + public bool IsPulseSwitch => true; public const string BracketMaterialName = "__spinnerBracketMaterial"; diff --git a/VisualPinball.Engine/VPT/Surface/Surface.cs b/VisualPinball.Engine/VPT/Surface/Surface.cs index ca1e3ce37..6335f0771 100644 --- a/VisualPinball.Engine/VPT/Surface/Surface.cs +++ b/VisualPinball.Engine/VPT/Surface/Surface.cs @@ -26,6 +26,9 @@ public class Surface : Item, IRenderable, IHittable public override string ItemName { get; } = "Wall"; public override string ItemGroupName { get; } = "Walls"; + public Vertex3D Position { get => new Vertex3D(0, 0, 0); set { } } + public float RotationY { get => 0; set { } } + public HitObject[] GetHitShapes() => _hits; public bool IsCollidable => Data.IsCollidable; diff --git a/VisualPinball.Engine/VPT/Table/Table.cs b/VisualPinball.Engine/VPT/Table/Table.cs index 60a786209..e96883fe3 100644 --- a/VisualPinball.Engine/VPT/Table/Table.cs +++ b/VisualPinball.Engine/VPT/Table/Table.cs @@ -37,6 +37,9 @@ public class Table : Item, IRenderable, IHittable public override string ItemName { get; } = "Table"; public override string ItemGroupName { get; } = "Playfield"; + public Vertex3D Position { get => new Vertex3D(0, 0, 0); set { } } + public float RotationY { get => 0; set { } } + public CustomInfoTags CustomInfoTags { get; set; } public int FileVersion { get; set; } public byte[] FileHash { get; set; } diff --git a/VisualPinball.Engine/VPT/Trigger/Trigger.cs b/VisualPinball.Engine/VPT/Trigger/Trigger.cs index eebbad381..4a7fa7a6b 100644 --- a/VisualPinball.Engine/VPT/Trigger/Trigger.cs +++ b/VisualPinball.Engine/VPT/Trigger/Trigger.cs @@ -26,6 +26,9 @@ public class Trigger : Item, IRenderable, IHittable, ISwitchable public override string ItemName { get; } = "Trigger"; public override string ItemGroupName { get; } = "Triggers"; + public Vertex3D Position { get => new Vertex3D(Data.Center.X, Data.Center.Y, 0); set => Data.Center = new Vertex2D(value.X, value.Y); } + public float RotationY { get => Data.Rotation; set => Data.Rotation = value; } + public bool IsPulseSwitch => false; public HitObject[] GetHitShapes() => _hits; diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index 7bb1a8745..735eaeefc 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -146,8 +146,15 @@ orderby renderable.SubComponent if (createdMainObjs.ContainsKey(parentName)) { var mainObj = createdMainObjs[parentName]; var mainMb = createdMainMbs[parentName]; + + // move and rotate into parent + if (mainMb.IItem is IRenderable parentRenderable) { + renderable.Position.Sub(parentRenderable.Position); + renderable.RotationY -= parentRenderable.RotationY; + } + var (rootObj, _) = CreateGameObjects(_table, renderable, _parents[renderable.ItemGroupName], mainMb); - rootObj.transform.SetParent(mainObj.transform, true); + rootObj.transform.SetParent(mainObj.transform, false); } else { throw new InvalidOperationException($"Cannot find component \"{parentName}\" that is supposed to be the parent of \"{renderable.Name}\"."); From 6578c6e4931aec7486c8c1dea26b600a87a5afcb Mon Sep 17 00:00:00 2001 From: freezy Date: Fri, 23 Oct 2020 00:20:37 +0200 Subject: [PATCH 092/124] flipper: Add inspector for collider and properly generate collision preview mesh. --- .../VPT/Flipper/FlipperColliderInspector.cs | 53 +++++++++++++++++++ .../Flipper/FlipperColliderInspector.cs.meta | 11 ++++ .../VPT/Flipper/FlipperInspector.cs | 2 +- .../VPT/ItemColliderInspector.cs | 4 +- .../VPT/ItemColliderAuthoring.cs | 26 ++++++--- 5 files changed, 86 insertions(+), 10 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperColliderInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperColliderInspector.cs.meta diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperColliderInspector.cs new file mode 100644 index 000000000..7987b5b30 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperColliderInspector.cs @@ -0,0 +1,53 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Flipper; +using VisualPinball.Engine.VPT.Surface; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(FlipperColliderAuthoring))] + public class FlipperColliderInspector : ItemColliderInspector + { + private FlipperData _flipperData; + + private bool _foldoutMaterial = true; + private bool _foldoutSlingshot = true; + + protected override void OnEnable() + { + base.OnEnable(); + _flipperData = Data; + } + + public override void OnInspectorGUI() + { + if (_flipperData == null) { + NoDataPanel(); + return; + } + + ItemDataField("Base Radius", ref _flipperData.BaseRadius); + ItemDataField("End Radius", ref _flipperData.EndRadius); + ItemDataField("Length", ref _flipperData.FlipperRadius); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperColliderInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperColliderInspector.cs.meta new file mode 100644 index 000000000..177305dd2 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperColliderInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d134c7acfede1f041b6bc3af0d5eaad2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs index 16a856060..40a0a61a5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs @@ -56,7 +56,7 @@ public override void OnInspectorGUI() ItemDataField("", ref _flipper.Data.Center); ItemDataField("Base Radius", ref _flipper.Data.BaseRadius); ItemDataField("End Radius", ref _flipper.Data.EndRadius); - ItemDataField("Length", ref _flipper.Data.FlipperRadius); + //ItemDataField("Length", ref _flipper.Data.FlipperRadius); ItemDataField("Start Angle", ref _flipper.Data.StartAngle); ItemDataField("End Angle", ref _flipper.Data.EndAngle); ItemDataField("Height", ref _flipper.Data.Height); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs index 935646beb..20c474da3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs @@ -35,7 +35,7 @@ public class ItemColliderInspector _colliderAuthoring == null ? null : _colliderAuthoring.Data; - private bool _foldoutSceneView = true; + private bool _foldoutDebug = true; private bool _foldoutColliders; private string[] _currentColliders; private Vector2 _scrollPos; @@ -65,7 +65,7 @@ public override void OnInspectorGUI() var refresh = false; // scene view toggles - if (_foldoutSceneView = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutSceneView, "Scene View")) { + if (_foldoutDebug = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutDebug, "Debug")) { var showAabbs = EditorGUILayout.Toggle("Show Bounding Boxes", _colliderAuthoring.ShowAabbs); refresh = showAabbs == _colliderAuthoring.ShowAabbs; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs index 912457d2a..0d225806c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs @@ -25,6 +25,7 @@ using VisualPinball.Engine.VPT.Plunger; using VisualPinball.Engine.VPT.Spinner; using Color = UnityEngine.Color; +using Mesh = UnityEngine.Mesh; namespace VisualPinball.Unity { @@ -182,15 +183,26 @@ private void DrawCollider(Matrix4x4 ltw, HitObject hitObject, bool isSelected) break; } - case FlipperHit flipperHit: { - var mfs = GetComponentsInChildren(); - foreach (var mf in mfs) { - if (mf.name == "Rubber") { - var t = mf.transform; - Gizmos.DrawWireMesh(mf.sharedMesh, t.position, t.rotation, t.lossyScale); - break; + case FlipperHit _: { + + Mesh mesh = null; + + // first see if we already have a mesh + var meshAuthoring = GetComponentInChildren(); + if (meshAuthoring != null) { + var meshComponent = meshAuthoring.gameObject.GetComponent(); + if (meshComponent != null) { + mesh = meshComponent.sharedMesh; } } + + if (mesh == null) { + var ro = Item.GetRenderObject(Table, FlipperMeshGenerator.Rubber, Origin.Original); + mesh = ro.Mesh.ToUnityMesh(); + } + + var t = gameObject.transform; + Gizmos.DrawWireMesh(mesh, t.position, t.rotation, t.lossyScale); break; } From a5cf9170c8b9c17835d88c5ef3aafc4a4b0a0c32 Mon Sep 17 00:00:00 2001 From: freezy Date: Fri, 23 Oct 2020 01:31:56 +0200 Subject: [PATCH 093/124] flipper: Fix collider changes in inspector. --- .../VPT/Flipper/FlipperMover.cs | 15 +++--- .../VPT/Flipper/FlipperBaseMeshIInspector.cs | 53 +++++++++++++++++++ .../Flipper/FlipperBaseMeshIInspector.cs.meta | 11 ++++ .../VPT/ItemColliderInspector.cs | 4 +- .../VPT/ItemInspector.cs | 6 ++- .../VPT/IItemMeshAuthoring.cs | 1 - 6 files changed, 79 insertions(+), 11 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshIInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshIInspector.cs.meta diff --git a/VisualPinball.Engine/VPT/Flipper/FlipperMover.cs b/VisualPinball.Engine/VPT/Flipper/FlipperMover.cs index eaecab060..8434e808c 100644 --- a/VisualPinball.Engine/VPT/Flipper/FlipperMover.cs +++ b/VisualPinball.Engine/VPT/Flipper/FlipperMover.cs @@ -56,13 +56,14 @@ public FlipperMover(FlipperData data, Table.Table table, IItem item) { var tableData = table.Data; - if (data.FlipperRadiusMin > 0 && data.FlipperRadiusMax > data.FlipperRadiusMin) { - data.FlipperRadius = data.FlipperRadiusMax - (data.FlipperRadiusMax - data.FlipperRadiusMin) /* m_ptable->m_globalDifficulty*/; - data.FlipperRadius = MathF.Max(data.FlipperRadius, data.BaseRadius - data.EndRadius + 0.05f); - - } else { - data.FlipperRadius = data.FlipperRadiusMax; - } + // todo enable this at runtime (or not) + // if (data.FlipperRadiusMin > 0 && data.FlipperRadiusMax > data.FlipperRadiusMin) { + // data.FlipperRadius = data.FlipperRadiusMax - (data.FlipperRadiusMax - data.FlipperRadiusMin) /* m_ptable->m_globalDifficulty*/; + // data.FlipperRadius = MathF.Max(data.FlipperRadius, data.BaseRadius - data.EndRadius + 0.05f); + // + // } else { + // data.FlipperRadius = data.FlipperRadiusMax; + // } EndRadius = MathF.Max(data.EndRadius, 0.01f); // radius of flipper end FlipperRadius = MathF.Max(data.FlipperRadius, 0.01f); // radius of flipper arc, center-to-center radius diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshIInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshIInspector.cs new file mode 100644 index 000000000..903498a26 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshIInspector.cs @@ -0,0 +1,53 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Flipper; +using VisualPinball.Engine.VPT.Surface; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(FlipperBaseMeshAuthoring))] + public class FlipperBaseMeshIInspector : ItemMeshInspector + { + private FlipperData _flipperData; + + private bool _foldoutMaterial = true; + private bool _foldoutSlingshot = true; + + protected override void OnEnable() + { + base.OnEnable(); + _flipperData = Data; + } + + public override void OnInspectorGUI() + { + if (_flipperData == null) { + NoDataPanel(); + return; + } + + ItemDataField("Base Radius", ref _flipperData.BaseRadius); + ItemDataField("End Radius", ref _flipperData.EndRadius); + ItemDataField("Length", ref _flipperData.FlipperRadius); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshIInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshIInspector.cs.meta new file mode 100644 index 000000000..8cdcfd4da --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshIInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bb00109678203874dbc5aceebad74865 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs index 20c474da3..c9a4b5974 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs @@ -68,11 +68,11 @@ public override void OnInspectorGUI() if (_foldoutDebug = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutDebug, "Debug")) { var showAabbs = EditorGUILayout.Toggle("Show Bounding Boxes", _colliderAuthoring.ShowAabbs); - refresh = showAabbs == _colliderAuthoring.ShowAabbs; + refresh = showAabbs != _colliderAuthoring.ShowAabbs; _colliderAuthoring.ShowAabbs = showAabbs; var showColliders = EditorGUILayout.Toggle("Show Colliders", _colliderAuthoring.ShowColliderMesh); - refresh = refresh || showColliders == _colliderAuthoring.ShowColliderMesh; + refresh = refresh || showColliders != _colliderAuthoring.ShowColliderMesh; _colliderAuthoring.ShowColliderMesh = showColliders; } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs index 86e94b579..dfbad7ec2 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs @@ -324,13 +324,17 @@ protected void MaterialField(string label, ref string field, bool dirtyMesh = tr protected virtual void FinishEdit(string label, bool dirtyMesh = true) { - var undoLabel = $"[{target?.name}] Edit {label}"; + var undoLabel = $"Edit {label} of {target?.name}"; if (dirtyMesh) { // set dirty flag true before recording object state for the undo so meshes will rebuild after the undo as well if (target is IItemMeshAuthoring meshItem) { meshItem.MeshDirty = true; Undo.RecordObject(this, undoLabel); } + if (target is IItemColliderAuthoring) { + Undo.RecordObject(target, undoLabel); + EditorUtility.SetDirty(target); + } if (target is IItemMainAuthoring mainItem) { mainItem.SetMeshDirty(); Undo.RecordObject(this, undoLabel); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs index 3dc4ac397..05d5adcc6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs @@ -16,7 +16,6 @@ using System.Collections.Generic; using System.Reflection; -using VisualPinball.Engine.VPT; namespace VisualPinball.Unity { From e7093751aeb8fd785baca0cf95de46961e8a6152 Mon Sep 17 00:00:00 2001 From: freezy Date: Fri, 23 Oct 2020 21:19:33 +0200 Subject: [PATCH 094/124] components: Update scene when editing collider props. --- .../VisualPinball.Unity.Editor/VPT/ItemInspector.cs | 3 ++- .../VisualPinball.Unity/VPT/IItemColliderAuthoring.cs | 1 + .../VisualPinball.Unity/VPT/ItemColliderAuthoring.cs | 2 ++ .../VisualPinball.Unity/VPT/ItemSubAuthoring.cs | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs index dfbad7ec2..fb77b1407 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs @@ -331,7 +331,8 @@ protected virtual void FinishEdit(string label, bool dirtyMesh = true) meshItem.MeshDirty = true; Undo.RecordObject(this, undoLabel); } - if (target is IItemColliderAuthoring) { + if (target is IItemColliderAuthoring colliderItem) { + colliderItem.MainAuthoring.SetMeshDirty(); Undo.RecordObject(target, undoLabel); EditorUtility.SetDirty(target); } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs index c7eaa590f..ad7574a9a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs @@ -18,5 +18,6 @@ namespace VisualPinball.Unity { public interface IItemColliderAuthoring : IItemAuthoring { + IItemMainAuthoring MainAuthoring { get; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs index 0d225806c..431b7239a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs @@ -49,6 +49,8 @@ public abstract class ItemColliderAuthoring : Item public HitObject[] HitObjects { get; private set; } + public new IItemMainAuthoring MainAuthoring => base.MainAuthoring; + private void OnDrawGizmosSelected() { if (!ShowGizmos || !ShowAabbs && !ShowColliderMesh) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs index 3fca35259..1452b6ccb 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs @@ -54,7 +54,7 @@ public abstract class ItemSubAuthoring : ItemAutho /// /// Finds the main authoring component in the parent. /// - protected TMainAuthoring MainAuthoring => FindMainAuthoring(); + public TMainAuthoring MainAuthoring => FindMainAuthoring(); private TData FindData() { From 76ae172c9a65065d8ed11f1fd5298f823f0d2885 Mon Sep 17 00:00:00 2001 From: freezy Date: Fri, 23 Oct 2020 21:56:06 +0200 Subject: [PATCH 095/124] flipper: Add remaining inspectors. --- ...spector.cs => FlipperBaseMeshInspector.cs} | 8 ++- ....meta => FlipperBaseMeshInspector.cs.meta} | 2 +- .../VPT/Flipper/FlipperColliderInspector.cs | 16 +++--- .../VPT/Flipper/FlipperInspector.cs | 43 ++++++++------- .../VPT/Flipper/FlipperRubberMeshInspector.cs | 53 +++++++++++++++++++ .../FlipperRubberMeshInspector.cs.meta | 11 ++++ .../VPT/ItemInspector.cs | 41 +++++++------- .../VPT/TransformInspector.cs | 18 +++---- .../VPT/IItemMeshAuthoring.cs | 2 + .../VPT/ItemMeshAuthoring.cs | 2 + 10 files changed, 139 insertions(+), 57 deletions(-) rename VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/{FlipperBaseMeshIInspector.cs => FlipperBaseMeshInspector.cs} (76%) rename VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/{FlipperBaseMeshIInspector.cs.meta => FlipperBaseMeshInspector.cs.meta} (83%) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperRubberMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperRubberMeshInspector.cs.meta diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshIInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshInspector.cs similarity index 76% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshIInspector.cs rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshInspector.cs index 903498a26..038ed53a3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshIInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshInspector.cs @@ -18,12 +18,11 @@ using UnityEditor; using VisualPinball.Engine.VPT.Flipper; -using VisualPinball.Engine.VPT.Surface; namespace VisualPinball.Unity.Editor { [CustomEditor(typeof(FlipperBaseMeshAuthoring))] - public class FlipperBaseMeshIInspector : ItemMeshInspector + public class FlipperBaseMeshInspector : ItemMeshInspector { private FlipperData _flipperData; @@ -43,9 +42,8 @@ public override void OnInspectorGUI() return; } - ItemDataField("Base Radius", ref _flipperData.BaseRadius); - ItemDataField("End Radius", ref _flipperData.EndRadius); - ItemDataField("Length", ref _flipperData.FlipperRadius); + TextureField("Image", ref _flipperData.Image); + MaterialField("Material", ref _flipperData.Material); base.OnInspectorGUI(); } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshIInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshInspector.cs.meta similarity index 83% rename from VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshIInspector.cs.meta rename to VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshInspector.cs.meta index 8cdcfd4da..d278bad20 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshIInspector.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshInspector.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: bb00109678203874dbc5aceebad74865 +guid: 81605cd817554c648b188088ddcbd6b6 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperColliderInspector.cs index 7987b5b30..0bb801459 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperColliderInspector.cs @@ -27,9 +27,6 @@ public class FlipperColliderInspector : ItemColliderInspector. + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Flipper; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(FlipperRubberMeshAuthoring))] + public class FlipperRubberMeshInspector : ItemMeshInspector + { + private FlipperData _flipperData; + + private bool _foldoutMaterial = true; + private bool _foldoutSlingshot = true; + + protected override void OnEnable() + { + base.OnEnable(); + _flipperData = Data; + } + + public override void OnInspectorGUI() + { + if (_flipperData == null) { + NoDataPanel(); + return; + } + + MaterialField("Rubber Material", ref _flipperData.RubberMaterial); + ItemDataField("Rubber Thickness", ref _flipperData.RubberThickness); + ItemDataField("Rubber Offset Height", ref _flipperData.RubberHeight); + ItemDataField("Rubber Width", ref _flipperData.RubberWidth); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperRubberMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperRubberMeshInspector.cs.meta new file mode 100644 index 000000000..81b5cd922 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperRubberMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 336d98959d48e4f4589b010e997ebb9c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs index fb77b1407..306dbba3b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs @@ -115,12 +115,12 @@ protected void OnPreInspectorGUI() return; } - EditorGUI.BeginChangeCheck(); - var val = EditorGUILayout.TextField("Name", item.ItemData.GetName()); - if (EditorGUI.EndChangeCheck()) { - FinishEdit("Name", false); - item.ItemData.SetName(val); - } + // EditorGUI.BeginChangeCheck(); + // var val = EditorGUILayout.TextField("Name", item.ItemData.GetName()); + // if (EditorGUI.EndChangeCheck()) { + // FinishEdit("Name", false); + // item.ItemData.SetName(val); + // } EditorGUI.BeginChangeCheck(); var newLock = EditorGUILayout.Toggle("IsLocked", item.IsLocked); @@ -327,19 +327,24 @@ protected virtual void FinishEdit(string label, bool dirtyMesh = true) var undoLabel = $"Edit {label} of {target?.name}"; if (dirtyMesh) { // set dirty flag true before recording object state for the undo so meshes will rebuild after the undo as well - if (target is IItemMeshAuthoring meshItem) { - meshItem.MeshDirty = true; - Undo.RecordObject(this, undoLabel); - } - if (target is IItemColliderAuthoring colliderItem) { - colliderItem.MainAuthoring.SetMeshDirty(); - Undo.RecordObject(target, undoLabel); - EditorUtility.SetDirty(target); - } - if (target is IItemMainAuthoring mainItem) { - mainItem.SetMeshDirty(); - Undo.RecordObject(this, undoLabel); + switch (target) { + + case IItemMeshAuthoring meshItem: + meshItem.MainAuthoring.SetMeshDirty(); + Undo.RecordObject(this, undoLabel); + break; + + case IItemColliderAuthoring colliderItem: + colliderItem.MainAuthoring.SetMeshDirty(); + Undo.RecordObject(target, undoLabel); + break; + + case IItemMainAuthoring mainItem: + mainItem.SetMeshDirty(); + Undo.RecordObject(this, undoLabel); + break; } + EditorUtility.SetDirty(target); } Undo.RecordObject(target, undoLabel); } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs index 68f61e7c4..63ce747d0 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/TransformInspector.cs @@ -110,15 +110,15 @@ protected virtual void OnDisable() Tools.hidden = false; } - // public override void OnInspectorGUI() - // { - // if (_defaultEditor != null) { - // _defaultEditor.OnInspectorGUI(); - // return; - // } - // - // GUILayout.Label("VPE item transforms driven by data on the component below."); - // } + public override void OnInspectorGUI() + { + if (_defaultEditor != null) { + _defaultEditor.OnInspectorGUI(); + return; + } + + GUILayout.Label("VPE item transforms driven by data on the component below."); + } private void RebuildMeshes() { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs index 05d5adcc6..2b1981635 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs @@ -26,6 +26,8 @@ public interface IItemMeshAuthoring : IItemAuthoring List MaterialRefs { get; } List TextureRefs { get; } + IItemMainAuthoring MainAuthoring { get; } + void RebuildMeshes(); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs index 7308ff3eb..b55b0aebe 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs @@ -33,6 +33,8 @@ public abstract class ItemMeshAuthoring : ItemSubAutho public List MaterialRefs => _materialRefs ?? (_materialRefs = GetMembersWithAttribute()); public List TextureRefs => _textureRefs ?? (_textureRefs = GetMembersWithAttribute()); + public new IItemMainAuthoring MainAuthoring => base.MainAuthoring; + protected virtual string MeshId => null; protected abstract bool IsVisible { get; set; } From 5b4a4eed0cdeadc4304b250c0e6e037327607e17 Mon Sep 17 00:00:00 2001 From: freezy Date: Fri, 23 Oct 2020 23:25:26 +0200 Subject: [PATCH 096/124] doc: Add lightbox for images. --- VisualPinball.Unity/Documentation~/docfx.json | 3 ++- .../partials/head.tmpl.partial | 20 +++++++++++++++++++ .../partials/scripts.tmpl.partial | 7 +++++++ .../styles/plugin-featherlight.js | 15 ++++++++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 VisualPinball.Unity/Documentation~/template/lightbox-featherlight/partials/head.tmpl.partial create mode 100644 VisualPinball.Unity/Documentation~/template/lightbox-featherlight/partials/scripts.tmpl.partial create mode 100644 VisualPinball.Unity/Documentation~/template/lightbox-featherlight/styles/plugin-featherlight.js diff --git a/VisualPinball.Unity/Documentation~/docfx.json b/VisualPinball.Unity/Documentation~/docfx.json index c759aaee3..349209ee1 100644 --- a/VisualPinball.Unity/Documentation~/docfx.json +++ b/VisualPinball.Unity/Documentation~/docfx.json @@ -70,7 +70,8 @@ "fileMetadataFiles": [], "template": [ "default", - "template/vpe" + "template/vpe", + "template/lightbox-featherlight" ], "postProcessors": [ "ExtractSearchIndex" ], "globalMetadata": { diff --git a/VisualPinball.Unity/Documentation~/template/lightbox-featherlight/partials/head.tmpl.partial b/VisualPinball.Unity/Documentation~/template/lightbox-featherlight/partials/head.tmpl.partial new file mode 100644 index 000000000..c330cda31 --- /dev/null +++ b/VisualPinball.Unity/Documentation~/template/lightbox-featherlight/partials/head.tmpl.partial @@ -0,0 +1,20 @@ +{{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}} + + + + + {{#title}}{{title}}{{/title}}{{^title}}{{>partials/title}}{{/title}} {{#_appTitle}}| {{_appTitle}} {{/_appTitle}} + + + + {{#_description}}{{/_description}} + + + + + + + + {{#_enableSearch}}{{/_enableSearch}} + {{#_enableNewTab}}{{/_enableNewTab}} + \ No newline at end of file diff --git a/VisualPinball.Unity/Documentation~/template/lightbox-featherlight/partials/scripts.tmpl.partial b/VisualPinball.Unity/Documentation~/template/lightbox-featherlight/partials/scripts.tmpl.partial new file mode 100644 index 000000000..16b384b48 --- /dev/null +++ b/VisualPinball.Unity/Documentation~/template/lightbox-featherlight/partials/scripts.tmpl.partial @@ -0,0 +1,7 @@ +{{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}} + + + + + + diff --git a/VisualPinball.Unity/Documentation~/template/lightbox-featherlight/styles/plugin-featherlight.js b/VisualPinball.Unity/Documentation~/template/lightbox-featherlight/styles/plugin-featherlight.js new file mode 100644 index 000000000..846494cf3 --- /dev/null +++ b/VisualPinball.Unity/Documentation~/template/lightbox-featherlight/styles/plugin-featherlight.js @@ -0,0 +1,15 @@ +$(document).ready(function() { + //find all images, but not the logo, and add the lightbox + $('img').not('#logo').each(function(){ + var $img = $(this); + var filename = $img.attr('src') + //add cursor + $img.css('cursor','zoom-in'); + $img.css('cursor','-moz-zoom-in'); + $img.css('cursor','-webkit-zoom-in'); + + //add featherlight + $img.attr('alt', filename); + $img.featherlight(filename); + }); +}); \ No newline at end of file From 752c842cff3bf3d1f80808a4812149d87937bbe7 Mon Sep 17 00:00:00 2001 From: freezy Date: Fri, 23 Oct 2020 23:25:43 +0200 Subject: [PATCH 097/124] doc: Update components doc. --- .../editor/properties-vpe-vs-vp.png | Bin 0 -> 353776 bytes .../creators-guide/editor/unity-components.md | 72 ++++++++++-------- .../VPT/Flipper/FlipperExtensions.cs | 4 +- 3 files changed, 42 insertions(+), 34 deletions(-) create mode 100644 VisualPinball.Unity/Documentation~/creators-guide/editor/properties-vpe-vs-vp.png diff --git a/VisualPinball.Unity/Documentation~/creators-guide/editor/properties-vpe-vs-vp.png b/VisualPinball.Unity/Documentation~/creators-guide/editor/properties-vpe-vs-vp.png new file mode 100644 index 0000000000000000000000000000000000000000..e3b76848f076b017695e4555c5da2ab483fe884e GIT binary patch literal 353776 zcmZU4WmuKb)-B!LNH<7#cPS~Nv~+iOcO%WFL&2ay8aCZ*Qo6fSy6%gf^F80amml!( z)~dPYnsbaXqu!~=qoce+fr5fUfBQz}JropD859(}91;R>MPp`u6$*+H>aC3A2hZ%o zRzzPti`1v*#qayATGfj-qzg__$pWp{p()BRw6rYEDOiKmwP7pAFsMTaS_HG9P^b^c zyxLMIZ{K{H@NpsSYt=1J`aNVR$L;c*x071VMLrrUSHvc|lCZNeKFoUJcan3T>jSyS zHTn4Q;~bQsHbE$s6cSY^QNnB;r&U$J^OF&`_0OL_&G=ENfIE>+BaU+;tgNhckSTl$H?~PtM-FkbnD)S+Gf|o|HHc}I7 zv%>y8O-+_!CHr#m@16hkD^`Hqt?~c8YD`F+L zsmKAzCg`__Y&*`4tC!v*&%2LGK##jSybvPgigu5W`JPL>**;tTU(I%ZE(rXBC8gwx z@anV7i4ZBFQ~_3IRu(oIg4r^?z>0-&F$^XXLV#!Ivwo))m0=;T1HByP^{#T zAOzZRVL49`a&EE1#YWr+3^E~OFS8vSsmLfvS{z9MQaLj-y6w@tgq9YO3x09cP#NZb z--*Qj`tv7hv-=SjG#aG)l>!lEL6PnDFsOfUa3Tu-5ifxkA=PEJ+Grk<_KRC!iI5fox@YIt3KZ)>SvmY4JV z?o0h6?`Ry{X2m%(L*QmmXco!%&mlnA#W?E+%yBF8kGQw!}XYpVyDMBCozNmvkREf}tSl@>kuXH6N0T5SB$3EEMI=lkRx z(Odfm*ut+Q8*0eN5Zw#B4urQ)5~=Y}K%(dohVZSJGK+i^q1k@OFUA)+E(!gX3Lz3E z$(WRLEYMU$ZyMy;S=BKYjzvx0ypy*TZg;zS-E8P@rGXb2K28?fZtiS06dcVFT@_B_ zc4y^Bv9jdU7SxX#VHj|o$MmU+UyJgx-b55At z;w(C~{Vl~RInlwvFfMP(%F1Tz9Vqy0XASjD&Y&~72`gI86)v8h?oax*N3!I9i8AE* zazO+(&@P_lEb@93*;{#j9D!^bYMkFWJ!tp8etqKPtwZntPv_|67b(|?^oyrG%OJF{ zW#jWl{W$50CyK(Q4(vU;K66rxj%ex94ck)6W^KTrZ4{^+Rv>oflBQ_l7k&{y z6w|~jw@eu0#HlLikc#E+jkD}AgJ$>uMIpQ`+M%Echa_wGbk!7C&9cfoWcP65jyg)Q zd#m3fZ)L@l#;Tj9k>IGYe=#cVuskz0m4WE}UQ;u|?O+;oJz1jKwTfFeG01qGE`nWtr&)wxg-&DcG*)bgI&C|55 z1KF>-;cP+NbbW8Dl@(ubz_b71{4blSc^;4A92RF`<(#sg$tO+ILlw=kGlwqgpk?KRVMJMFF#zSXfNyM}uwRI{^{IWF&5RRiB)9M}e2lCr`HfH_ z)mV~og+$B-`#QTP3;Gs*Ojy;E`mu5J59YAxO7)yH6pUxE{E&K1W{L)jh_K>B5Qh+( z;gXgG{o8=rU%xH|S9XR$ll99B4&bF7-#lTDa;KK$+lw6%iysp{D1g6l;Mh72Bh-&n zR~6+gOPdr7c)Xn104}tfB#82vbI}XLU*B98K~MVkb&b;M5EEA`yiVkI;}du;w|wH- zRL#Ro@AK(y6P;^h%nTs)h3_dA!D7;_epS}YU*Ogkj?GHQLy)*6Qu}2g56@-MZRXQ# zwb{^(P`iJm_>%->;PdtKlL2_^r>E#Aml0lh->XHJ(YW~rTpvI1!}$>4_BoM(xBv9p z6Brj3y?E|OnbW7E;03_8`3meDVCzmCI@hkCni!R0=jAo(^OC{Q&o1W}aLjLjYF_z||>(W8nB&4u^DZ+Zu!7DLyd+SV)vK_q$AY1c;h zSGwOa*xp{j?p4e#QhX*=*#_V7H!?OoMzEBItk4&%l+kz%cRNEgg z{UN6M17*4J0eg5;t!F9P^`2`eH!*`wo=2#W?j;!C67U(3Bu`G9FWa1ZRyLbT-x#`7|$!9tsN z&F-xJ0Tx(GxqA)gCz|Ui`_wlfR1MNbGTta-$eh~)TD6@YQnTqYtXRFp`khJksw;O} z^YDhAU3+i5ZqdV-R1e|Va+fcNb$P*9Hzj6#{;fTo^9YoM24)m!z7LxW;&1Q#gsg;g zb#zXT90C@GYt=sa1N&+NyO=Kl6UBbM78!gy;t+phJDMxH-E()qtWmmqpN(;|)a-$& zICy~>aMRU0y`NCwfB6$ReU<2_y%gSK*=y%>JtuKC@!e?`CWTs70M{r1nN_pkPuFPd zA9#>s>{7TaOp}eA`a&;VRk_qA{yfQp;}L-;W^vw5d{qsM*P1yo#Ul;{CeJFHN}zC* zYtXhsxo}$JSue>*jPE*b9udJ>^x<|v*yCHZXlV_NG;H#!VYrp%C3`)m9{igQOn(le zctLDZ@%K?0=jZ1WY-&K*Llbnky(Z~igM~{3cxx;v+OX>Y{>9y3;TFu1d%m?_>3r*7 z=Lt+x@hIylQQ3r14j6-q;1`^;l3c_L;KV#voxN7wn}=6eaF3lEM=Zn~@Wh6~IP}av zYL@Cw#8baQrooA#h9P7bf=^fo9x|gE1SjY$%kfOaF%F5$a|}_+?g=l%Q@+B;dhf2* zVAROsDN;A5%Cpahf40a*Qb~j4A+IESi1t`)y#Be$l8y*1bH288GzVEPec=ru_`Vfh zH(BY<7Fk;!WHEUjsLEbDei@($mti z%)UZLN0 z*4>~WHH5btUi;s3V{x;QN2}3D*^k@q?Q84nvv4S@ARe7|V@Bd>2h|C^p1p>)0ori% zs5Ex`+()%T2O$h43`>4KM;flA0$ev8!^|VP(}liXs;2`-qf!H$eO>7Wv1xV(pFio_ zDIoDW7(~ST2^%Iz7RZ(wnhCtPGm*K^4~M?$2HZr%AZrl?(?r=Dj(+X zPs~ebB}mbNfk`TmZ^1}KPYE1CgmWWON+0k(e~@^OMD^b2`evaJdv@+)q()wxN%4pE z#e=lfn=SP<%&=8tS&7j|J2U9=_jnfd#@kcMTF+PhH^FLf)fR<4^`w2}8R4TE9w1x2 z#;@@Gdv%`=E}_X$mrYqCT??C;qa~(n9wG&`3Eod<$IK#mgpK1vQ>(>0eOFkSllTT3 zRE{Kd+Ie(I$q*yI&MT#;xsuy?I{yhNlxF+lo7wmMC0cruag>6Zs&C)=MOrXIW#R{) zcB8SghMA!F=uW{S>`D)Y+PkpjStcglVy7{21oKS{_f{0IG%EC$G);1N?*qV&+0<1tn{9sgN=KW#Hq)e4 zzK2g*B)NT#lgj+W^5VA-JL2N`P>H~4aRzS@!_`lK32VRm=)cw(wk_IM_{(O79u3Nw zB!+;sv&ros{Lc-da2NNS(tA#!*e^?H8#}JV77Ta6?8t|k4J8s{`P-v?`0TR}geHDPhzbEK`VYZWhfBPK;KX7tHW? zTD|EzpuB1-GTc`UxSPzsmqX&L`@F;wiUleR{PN!68<7%A>5IJBPdKGNn1cQAXr63NF);toR(gioi{A1DI*hf$CWCe%xn%c z{38EuZsAp^=G2Fbfq{G(=F%R0An^O~;|FwEpBsWs-(!v(YC5EH%?(-;Qe9Ou(wRm; zNeW-R*uJk|sI7f|Day85%Ov5I7MEvRSqYZj3YLR`EZ*PriTkIRfG!_EosTo%r(fUC zC`Kh_Hk?ZXMzzz=91(U`9+y_u&iW|$A%`+!R`=rx{!_ykI6#sjD6pMjfw_?j{vrVph?_KatS}x)ThB-jQZ<|3i8(45stmvm(gawAZ zFq@+y2yq7n+$-Fa5U^r`=-D^7Te2b4kEJ5G=m!R}GixD?+0Agdha&21jHJ6nmo*u0 zDsc=l4Mn)-j?B$9o$`_B^c$qqdT)2~@*J0}CX3g$vmE$lIu0tp%Rm&I>U%et$49KZ zZUk0?>za^Rd49ScpPF**#tAtpF@2{e3r$k9UaHrKbG_{2U{Fko7_a(}+j2E;Bd`{V zn`F=-T zXM8<>Z$Xv%x+1^(X3t$O!>+rL3_Eae@y%9(cG!mash6JXF<$8(*sp@DfgXgJ^dJU3G&TCbwGxC+hsG)!Z&s-)wL*>khjfM?V@rx1no&a>LxeBJW%p zWeMXw!O^?^&F%D7S@5+Kv?*d2l1*$zEt*2Dl)!y7QzQt6hb+Uo0ZgnLHM@*bY6GW{ z0^Q@ks@^xRH3>z!TglPf-W%=Qo)a$PVT66k&TRYO)Eu^h0afr;=Y1}8)Q5O;F-lBX zg%3i;jX6LTHt_|WosqF!a3?!ta8O|btM$0)K&jPmx^C1}w3xocWXfsEez5^tRs6B` zHXbsq$kx~`0L9j@3bR4GeSJ2@IdoKA$2AG&{&l6LqR9+^8K)c>GZd~Z+&zLrs*c$L z2cqpB@r}Pdb3%TRHlDv2zV)vU6UX>rTKb{4n-cD{8*o_iw z{vHmhsKj$AzhOKthREgnQ#ijaDcUY&9#LvG^}Ik)YdhqrJzkuxCsWmj&g8FvJq<>=pfCDf&g#e+^=|cQOl{ZkV%Qxz zLGI0vuA^IoT8*u+(80{cFNXcI>3N-6(n%Nt`^EDE8qf6teyppM{L??Ao6T26mq#8| zPXkA@Gq2<{C80B}dBqpeWe%{ut%UO%ECdZMx+^iQgcOI^RBcB=EiYA(ER{@kIeU$h zyBBnmY5q`AvPNLlDVU7=UZR~WOx9paud) zzmt#XF3XKSnDuAz5jOtj#zuDU*cu8RntV11T*$MVzQj+-U}4pk-ID8{XxL+|Jz3)0 z>`YBo6`O+_W0HH*ZE2>Jxa8|9jA+8Ij&>G8@j$uef#>qh7k4FZk)b9mB|SasfX00V z{QP(_@)*`x2ta4aBmJN))hflqIxlgCqobo@8C*qjwN-3`U>n9eCVY1ALp65FyH&{o z`BKZU#~RNw;|u@ir$_k|0n=?34r z5)8cHpJ!a57^Y?!ue=S(=3|UCInN;t&_f&P0Z)|v4})2ruW>pCQ)^cD4%>z6k0d99 z1O={&_*b)kUvSXDe5gAK#n+4Bb?{his()Qq+v1rg@v+%ntW3F~=l0>`dM$$JYXKu@J6r&s+$SWY6R&LajmzVF%tlMjkah1kB9jRyW zHBOAPYLqA^ge52y*z^pvF^9cCv3sx$32Q1>%i<6!Sc^^7)c4wol>Wk%#mZ_j$$ppiC&jBs;M(D})uDURdEN7T$8X4rAPr2%ej;Jtq}aRb@G_ z&a6>S?r?no(y`{DZ$6KmLg9hp>lG%taEyWRHiEmR3;ehM23<#WGvfZDeaBLrwKDXo z%SX3#*68|pX*(6^Db2X&Qx%x?Dx@nKpIM3H_Z$W{vD#@;WWjF92S?w6%E)^oxoiLs z$+8vLOi@?igf{qNuKiZF_-MG+z_>tyPNPz4*>eM355Ps}Cs7RWumPO2ds6~P&ZNFb zK)?O#t+ZB`QhrGAM<8T$L)bhjR69^LrxG5j1vBdQsk2?5L`n-s;S>Y6ZSg{LJ3=t+ zyCHX?vtCP8mIDx3O&*dSd>0PUwR6>t4#Ya+zKfArFas3xtIinJ3RxQ;&h1alXg%gE zHA>im`KUR{%~cyc(vf&6hWEr<{i9bj`xrD}OB4kHz0j{aY<*kmf$!r{I@nxY!?CJZ zE|MTl=UlXf_?;>31LkVoY}{Jb3qcO8W=2k&j>cheU%!fi)Va1A-mg-m&C3R z3sIedG0MnP=FZ4A^9$_rB+*d+pmDdPmC{r2QK&7j~YgQxR!zW^T*@?^3wGyja= z;f3htG!)(=Q|5jaZ0JB|a^`V{1lEgpC)+ddLw``}d{CVrw|@)a3sw1?vPrq4+H z^Q^XSRrmC|2kCcEIiYY?b#Za=3ZGN&ibT#JU?cS8Xn%^G+qfC;!q|N~h6%2TN8dR& zlqFL0eZA9qQ;~}VDYanrFXof4;MT7>S}~zL+&+%y<7v4^fr-G(w>*AN^V-U8B{2T6 zd6k__UZv;5rg9d4zMZ$rg_`rQ0*!{%{0)6Iv(4%Vt3+4$4EDDL;cr)5Ca__Q@d9)j zU%2LpHB9+2%a)Xkx~9u?6K-P7Y#7IG_BFxL4-dZTI@@28RrZH?q?~$w&FI^}6r91} zqqsLUH;-_gk&5{ec`Q0bFlkE%p?VLAo-KFJ;A`p`RmXDFys-_4lMz?@(#iFP#jCsS z)L+c!%63xh9Ej+zm?H;kb3j*$ET9xNT&Y+Cpm~bwtgs9?M#}FmfF^Co^&d-q>T*(7 zGyI|kQznhP0D3mzI>v!VXZEpoF`_wC4K(F#oP`eBVn5{zD_i|#qJOSlXy%K|NFm$K zelmhvB6wJK_Eb>h6lRFE)MXwckWp0O3%*qch=`!`7MY=RBX@nc@j3!6M4hn=3P~3y zswPF4{_|N!cwy{#nQ?O;sGm53srXt#2U;v5?yrgo=8+;=BRAQl+^0#0bJx4j0*Evi zBd;JFg#^Pll--}BG{%H!QXp*1$LodCHjLG!-O^`+xmUSBI7I*{MPSP^DjMUjtd_L3 zOQdM9YK!|py6U0JTI+%7<-$PcD#Xy~)LY2^=qCcJoe%`q$8;Vc{!p-@E$li0pwUIx^C66j{8VniYH}prFtpPMZFX5JY8A=4imvMTU@@ zb?4E0%8Sd20J0kM5iUAsBCV|<>~j|V79xt`B1?7jHYDpG4`T7Bh0KXjb?%vCYZ0#v14l>s82U|{m@+L=WL|M@;sseA(pcT z)fgFcOx(R~ds%^GH^-Mke2C+QZB=x1G>zDf#e=#Ao* z6)h+vr$&Mpj+WwK6)_n>rZH}f$Vcp94U+=9-4r2M#`k_<<=8_vdprQ(STMXuWVZoO zhV%%d(Cps3cE(;BlCswiz*vXXuR}9Q-hsCTZ&0EWb$N#(HCt|bDw9%lqQVX|NdpKn z>q}*U^eCFJJdl9_b0lkq@)e}z@vJj-c9fyo5WYGqf!e+JX)u-fetE@x!EUzEWd}Rv z{_(rI{d-EOL{x)a)>LVy;oq7Dc2Bwd4!L`TSIBaed0OuK)kAFDh4^U)PVpg9q-pzm z2_1DV`H$40887*?RAdJbQUYUrsx+FzmZ70?MQk4HNi1NFwB)d@HU@Ea9z~F$&@fw< z(82BKGDZGZ3s7r^nzj|Ra1fCIs;+K5y%3`iiabt3uyrFeR5ijdC%jWj#SK~+sp>SL zFD3is>jGP+<2Cy!GXkU@!^t}uGV%#}^WNNWzZ$h_|I2$?$WQ}?sKdEXyW(dDBd>NHRespxgf}7$FwK~(g@XRRBJnP1dGxrqDpzKGD2D@&yZC! z3yOXqlOW&mlF?dNh=h!IcC69hK0p%T1NpA&3cbKV@?IO+bcI2{)HY)E3%z7V`Xdyg zUrd;wtT|%mcW6Sv&8XqY)-!)UtFMt_VfB%=WyPPq|tK=4dU1qvIols<7%d{zf z+dx|1VHam6XR;^^Fevw2^dk3%HN}`ciLtdyq{#5&8qMfAh}Z2|nxTu|YZ7%uaSOH? zrOK2o7m{NR&%bY{s?P;{#|}^2 zewODA$K5fii+JL|Y%T%YpCZQr>6eC_7c+8K$rxA09hnXum3_R)&Ew0t@rrWqR~*-zoE6U ze}r8oF}W&6p)=eL>Gw&`(6aN?$IUgrtvSY#n046-!a8BXIWOe2il040x$j9|S9F@i zSeSU<^BvA!Q(oCF2JWl~AqoyDIH?hQ_L&-&9Wlf@`u!dyF`A07Y;0T>u}ED#>*RLs z&E!0K%R+y8nD`MCTb@-G%j>ygaw_M5sZE$XEz_cIhqVGx3C~STBdPX?N9Kx_2?1G9 za3;o|no+UlQ6@#ieG-Qjr>O!A(^gFbKm46+mw3>bbjgv0*ah(e;Ouz0Jzq03JDv3q z7XA1!$fDR+4)>yGASLQI3yg-z!ZS$Vd58I*SFb`I=gP>#9rxLYmv~jG8;7x3r-YsHW?3j=1wxZ;$c;dIXpae zEocKHtHEl?+)~mM7M-x;I&--F>mo}?l4Oj=81sjLp`imGapDXXckZFlMb}AXzW`x6 zx?{5`nCS%kWTPCS2A$sT~mG?&o_Xg%Jbanl(_MF!RvLf+zgmd{D+%majR zTHyKN;(mJL%0zJ|)>NExj3nzVJrNqc$Y@mm%gG&sW$aAT?B)3azY+`v;(mMQ#xTwFEOj9tBJaM+mV;-|$X!@@2y&SwgbxhkQ~t?yq*{0Xt7%L2O5 zZDDo(T1bDznx@59kYM;{duQWizo=Hsx}m81kyWRnDh~}7_+gu|vyZiFaZ8cIN0K;R zbSmfyx8|%ftGV)W4$(>V25X)m3IeMQ(ifoMl?9|JwN zG@FiOg-eWzI_+B{(Fq=eAOnZ0Q!Q3U^VB#qv-Vm&%I3VHlJlEPK|c3-T~EcfrdZGG zB@blq+D=kt!VB^cBw>ugmKClw+y){7T2eUPgb! z)-?SiNr8gqBQ&Y4FWOTQ%BFG-Y=Dy>AU1hhug-BmL=$|rjgO(daNMvFPqi@ZX;?iw zGQ3y?U{GIHBD#zw%^B_y0mi4~&its4!a`R!i|H%3NpEaX-DNv0X2w0g>?^cFe*isI zX##6?%)Yt89eT&nm8AYUHW>d{oQ%uPq8RYjSim_<{=%yu{L{uDr3Dt9CYa5^>{=qu zmti$&&yS>}#Td}J-?F*ZE+B=sB1PQB*-h6kY43(pXpie`*0;v;Pm^_4)Zd>iuvCEZ z*HIdc-0+JGujaI#&Qcq0N}X8-4MJeEmSy}m6u&LG5`h(JABMRrA58kzS}xK}+}kiy z*VwWz2Qb?oSJh{)`*Us%3*Dv>}y~}iI}Fa>cr&|>GDj|;=qlI$vr|FY#evuf8AW{iZMjjlh(9$ z)c}ql_wN7mQG{krbyW14lnwmgd?B_pA%Ov^b>Vn9j~9WQ(A$(Bm2+I}g*cO;_N0lU z3}%s8FwPwrVmRqDVkh{S=96p4v_U zUwyt^u+KuF(Gij3LoVHw`RQAX)^4npqqd4qS0pv+((!l3@8#V;ep7{ts3()=VFdyL zJ+tyC8SZL&u7{D+2=yFPJ>iAkx2d9_Q=BtP*3*l)>dJ{QZi*bxXC=)07=wq-mL0Tr z#mo*?R-7t(o?M^U$%U-<1dPzHArKXA7d37;fH(dUvT(#lhkIk3d7;H{4e(`v0tMmX z)rigmnu0L&{D+{!aq}-W7d0#>-f)y%=CvO+HC10VgCL6L%1oJHw8oFzIhbqbo{68d zLz2Rn*C2y?x=&+2RWr{eg2G`1Zq7HD>W|=zt7~c^E{R}*0&m5~(YC9C54VHXoEw!u zl;%ilobP=T+4N@iDAHEfnjXZ-dKJaZ{_>pvoa$}{qq~cuqN2fK&*--YdG49wrU1SuV+|M=z*UV<`T}V{`X5IXET?VNIUmygXbAgbfsLg$AE<4 z&Ux{MeP{hV4DF3r951+)(Bt6-U!?jM^ti9M$k|YyC#U_x&ZJ{UmAbM-HKQX@|56;8 zs(7^c@)HrcJ518}a^RPWSByfqiVz`!dOd7e??NcH@IbzN?=;2I1!R_L*0EGPS`a+Y@8=->(8 z;SA$0L=r^I*~q2`Mnz9w<7)K}A54|!nG)Sk5=!dGZq|fQCp};QsZmuv(zkwumhxP) z%;0wQds;1GlwASUJ}+{Baw{^z6&F?qbT4lZ#fU0&>me<@uU+e25I&P9--$V~MGOy4 z-`Tpjce>pB%iaWS!ETHhRrw_{@ARpJu8t*kIz;KKnHAkq>zYfX5x&^;o&9e#bt%So*ZO;( z9V>BJ7p4miPJ{fLL%+V!stbj7hm^mvUPFOrUaYHOe|i5!-{kdQIRdsWPB{s5GUIQ# zP`c^TCxw3P)}gMH&ms7d`3ni9hCuEb>gWNLQzq%!kU6$E6-tjsL!x#QvSj%56G<;p zru8(_FBBWuEx(4G_*g^i<63@^>=Ve_OV!BTH%+-$}B6EP#o-`s|SB77pK0_ zgd#)qpuySQ9db-UNn@V_2Y^8ZqKj4mjsG(yvVWlf3JJkUCpIPC0kxv{vr=74+`F;h zrK7MFUVK^gE&(H6#fgvkA|$)hunwK&BrZx%cZoc{JhXJB#2?rY+?w>Vj-c6=Wx&LO9Dq~r2G0spi#LEok zKoj`Ma;7bK*Pp^bte}MxNvy%Bwbs_l1;9psAJ5qRi!T~y5Zk_OdP*ZShN}da^x;cB zhh>q=`hQ(5Ok3P`7g)m@b4jr{-{&s<}tuP{D z9zc|!cj|u}^rD&d`MlAmMzp?goKQ`9lCTMYMueO#4Y_2$i$t%|9vee{2nSld~8&!j(vE7mkO1bY5dr z0YYHdFmN6twNb_lHtmBII?yIUyxCU^$N%S5<2S&Ik!t`@&w2HRpK`B#t7x22s^If& zs0n-@!p@7t+&B>;Ks6ryKb?HpAXL&Xip>nYFU)#QaB+Z!`P=vJoCjMwJ6%WaStojI z>E)!rZHd!m$PP@~`?&v4pN{iS#4QWx)7Oz+39_+#YMP2gZftBk^=>`&6v5#Gk_fnv z>&No)@;0>Cf!-*waRnfhDu@0z%|?C5#q zn}q`%RU++`DNgkYf=csn&6t^p$4K$;==vE!`0|-ZWW|!9Frhrmtm>L7dj6S~I&+JI z(7!@|Bu>b`kcdkF^xwbZ{*?bU>~5lPsqL79gOP)^XcS+M zX%<%-`r?1{uz~THXgU9EFTq7_w(_F1S8ck!!^SVmo}LQTy*liO)emd^_iR){Z8?VG z!o1`CpFPjE1}#50LwgH`cwp02^w`-kqK18V|8i7e8N=W@HY>j!VQp;G%F1)lUoaj# zibedpa#5p($Cs}dfZ-a_$};2qT&xUuescuO4{#;cr5F+B=6HML=93$*zlh)67m=LT z-+{USz)Zac;$?<6#oHjlzO#S2Jej@|$NZI5zRcT)*hov+VEn(+lgJcLCI|{;{?B_< zI0Z?Wf7crrSGY|>LIhn9t=7NVgOH#r+M~e%sDulTlNOqee|Gu?S#IS9`(24 zzg^lZqck9vw%v4>mu~^FB7r}bT_y;gG89X?XRRw@e11NfBW`9O4Gz5JV+5j(n3Q)QSS+eBYnA&orRbX@SIUY)zlfCT~ zL`TO}s4WDRK2l3SLkPnFnD*qXY|E*XDLo>j)x$J`?70apHbv{#FJ&jV$$vXk)xL3- zab|RXb!2I48@h7BzmU?P2KaUMKQ>`qMky&NhP|=G{R0D>0SOJ3TYvBhQ%e*SUW^Hi z38?G=WQe?-aORGN^oWAua^x6%!-i6vFtW%1yKXM=3U&7tF-h!}jZ7?=B?I~7a(qql zY_bIpukyE=uYY?9s6@zq$;!(1-ZEzabv5+-Sw04suCA-nCv7pw?@f0}V(57BUrKYL z27vmNs8ymh_vR57tiFgGVUNtqM!Pm1U=MZQglL_Lpbx~A#VpW$` zt6cZ&Mg+G-W|Cl(c@h`*04EvQtN?U5$;--icOrVrSHA!Fk**5ZIgvC1pR;04ay_Zb z7n|^BDh$N!75>-cCaF37$ ze3Jk52P>xi4+s)SoS|bJ^et;qRYBY_(Xd#fqn4;Ru5q!Vz4N@(z2ui-6i+%j(Wsad zDzkN8%gS)2{bnLahL?e@WBjm&L{g%XW1S0qH`L9`GA@jOophG10EI*qPPDv>WN{Q(72+b6eZidx zEM`{hS70%fE&1tj%ihsGf^|%F$F~QS`RSc-5=OMK}%$^c4DWTiVg-G3{%g37qyP|)Og~bX7tRr ztf554DRS<%+ysyWU}54Q32)?nD826cQpw+k`r_!`gjc^vM8s%MZZ9VN z`Co(S0t{xa{gTO_3D8`1hM_7CPyyRvgT#Dee|MJyM0l&v4WJ$h&CSXFGpm>T)qsi* zxc@lux$ujrRrsEHAI?h~L@0wpLuy)Dk$|LX>i6&Os=$WD8PCXxBP>zrA^!CX8PmJ; zze6P7gQJ}cg7I(5NR3$loB-$3n&?s^n88F#hItuJVenWIP2+DP#^+->ospL+foP(C z+du>KybXKBSsZ?Mf7;4?4|G?gbahDp9jl%7&`a5Z-^xe^CoIMNY@d=~_=0`2GR7)) zFdaKiPJ(G(%pahlt`ndg#wR9%`IkLS+C@EHpfl}`GmainSwleF%pa64gLZlHb|!=f zt>U951AbZT@Bf+wO-`U`lOxISdSTM~-yYwz`*;UzbOBQn4lCADL$5F5N}|_aP;=_=eB}@~xo#nTuRV|X2~^I|?MWjpz9N7>Abipi(%ajcBJa2!#gOU!1e7Rr z19e&mZnYLUZfS4TGNOSx8YZKx+2cu7aWZZTh>X5I`ToJd89-|qAI<;jss@`@va1NJ z!42mK&(wxoqg~M~j2q1NXxEq%m#|o{J2}qQSYYP*UCpJ`IB^RecS!YJ0M#GE8u~s* zyc@O3vWL7qb-%v$>wIPdlp*acUKe9aOL2V^0lr!gWDAm0fpoS{*5-09q#NDg`!J%QKI`dOLck)DrlsofY*p7RIZ(*Q^_8H! zVI2ivdv79FudDjVZOm&gdNME2`eW82uB;0$5)WMx#lC+1T8!y&G@qJixz&lv&NE6e zkZ%$(JxP|IA&n;-v0RcbEIZ62o@3HHwLHJT-v%2`Otq2UK$7v0Sl%k z-jJ*9yemdKqzl0mr~p3+k^7!X;#!iT#|v%~ZCI}U1Tc3bD^j9|4GULS4k!x6AD5vS zZ#Xg_wH0Wmqj};K&llp)$$xf2tWhCx7VGzH=EfcRk zwj+uKqOvu#{~^g~`!2%_%Ec9`dp@Ih9)BP(E|~P)=#AU6WsQMa1Pvnej_XoLN9k zrIHd6ZHZyn)nLFwU%(gMvo&CJ{8#w0b+sQuu|!24|4hoUtOK>7aU;r!g7Eu)CVijp zSNJ!ctaNr&w zTHP*vFLX?#rD#!n_pXchIQtB;3T1KE-3i5F(P;-HXr}5>bici&lz5ICcgTI$Pz^W= z@uSfNP({e25tpyqu0g6GbkoY3o(%M07@X){ptRxm%TN#MV8*~Y#nT!^Y+w-gA){fw zdXkDHiWsBNO-aBV!@~if4#egT;aW1_0yOAKc~u6CkbCg+y*LjqFL4Ldg5+7JCiw27 z@1CN86eEO678^kpuLZma&>=u=R*V&iEEApu#}F<&PF2k>nQ>`j;)}5bF-O{r7FzUMZnCjzX*#3C({B$z%oB-5?VPm{an_d$QUx!|H zfe4?7h}`WKh0GhgW@|p=!o4Z^OsT=s?p}F_Vlm@f$EtYy&T&;@=k?52!!Vd=tqzL& z9BR~PlydNsHw}i~TQKXJwAsi;AtSAF)!PIosU^Ndb635{k!N z`H^{2MaKAtZGNyI%g$!D3xpE}yDt54H%0tMSsCxfLRtN?HQXl__Deu)fBEh4+(R0O z2M<G7cF+~c zb%#w%u$ziCQIs>at#F=4dFz!9OkgywAmvh9@5@|R`hQ+sQJvKvI5pceIdib#h8M!AHQYj zh73xvGv3x?!BIa%!+8Ez3ov47v)g_ADB9V+Pb|wga-DVW^Ss^;g*6wm-AZygh$^92 zK*G%SDRATd6MGP4bukj1AOTA)m1Be0fRn(@&6lv22dHA@rBG4j=F@d%KA1+e(zZ${ zH+-{i3%KxlbK9N@6Jq2*ilrMXJg&gC+w#JtIS$aJ6In>T9!JTc@jWe>jF4P#&8BsI z?T8>o7V2v6)Ow?Rsuzv{>wi4_x&$`}BUFnaSlv4agF^@#r;IVT zn6X5~S5}5agDwlL^lR7_pU}X!YG8J?T|&GEB^3Hk0pqnS167pr?IHyp1_vEaz{!i| zH$f*8ykzjWuX!_F-)1HQQ?(wabd`>RBJ+kC8}@`oNm+Tk0|*e}vEIA`zJ#zq!K~%9 zIxK0vz4{pZs8ZE$81KWl=C18;0c1bOVUaCzyJ!}3#3;%LunF~TZOf*6^OZ&+*!O5N zf(4W@fZ8NLU{G=dJhzi~zqq61o-MOrzQ8DD%+w+S($b=i+6lW?CX81v9Z)6rzga7q zHm0a~W@<1>%W>rjK5M$q0^gEcexd-#Mvp5IROToSyz)L*$0>`{0PykY0 zK`ttbR%>S|+&fPJR7kb22+AI^fID|g5zQI4E+l>HT4x_0?`FWgK>bIeSaV#m1f%yc z=Dg@4Lf!%Ry7h#(!-=}>riVS#hw>WNz}+eT2!gjv0rE?#b3F9dGES*8JTxWuA64@E zgU_*{{~(&Z%SVJqo0~+;pY;xSb%-a|ZEvW1Rrs zJ4XpItI;+)oK-;F70#<%Ns|*SlD=i1oGE-W6OwT}YFNg>U()ptG%wxvc5j zyNKC)=)6SF9Hhjgg1W3pEX?8rn536ICBr2YxT`^`cL7I!H{#-H`bd80fLc%{JmKSD zHrIkOEbxS)_wbd(X%5*ezho+gfbx%!JGc>DyphCmG%MzM#TN#mrDrs~`<%NE!$Psx zX1losJ1#=uYp?ly(1S{SvAuduqPbSvNZwFI7BM3djfhJg0edv|Rja{P%>GWET_knu zG)?|<0@NV2gYhWADkKjP`+TIEmp?CXa`NA%QX&E*HWr~Y^h1&&u6F{3X<7`(2bhzb z$&6U?C4v?$+?5ANs#x3`;a|B)iN2ZdYYFWO4&}a7t@E$=x~y;k!m`epwkzI?T({)C zcEwtK7FfIb8d0HD|EG(*tahu?qEJXzAGr@2d)tlib`EPdW&Y${Lcl}OKz#Qhx+~m; zw;RmT!_rxO&pCs1kc%o&WMpXYtIk9G0U3Q)B6Ul-Gq@T9j)nxZ>vR;0=K(kom0Qs4 zT==0h0{V@Q>UR6iISVrPhd$91j@h>i2k88ZhQ|T63ET(C*D`5*)R-ct?fGHKc&1}s zBA-E#plsa#!_`{=)e$w_q6rSc-QC??g1fuBySqEV-Q696yAvR|1qmA5-Qf=3|9|(s zdQ~SW3TEca%-*}ZclTPWql`5mBBqWXx57aM4jiv}>u+^^Ah68TB}0GqiUbyzIOr5; zgxSim|4bFa8u%j5&4?-3j}(m1P*Mh92gIv=f8`Tj)HO-tQLYx{$3B3-9B4oU_R9}} zjUz`MVSYCssnmGMdLT5r-RWl2BnPFR-Xa@zXke#i;ckeL)5d~|3%%zY1&?)XaATU_ zcF>&?!7w5gUJEd$`H6gu6=%%q-+MUu$gV*dq1j**`UE$hT7nt#Qb3t{FWIQn1*#i& zW?r8Y=(|DDhJPUdJD}_%jdM3D@a{N}NcVd7^Ojx|tVxkm`LGkmC1fz*kAOiqpCfPO`?c4;cUBG9g&^*o_&fV_N4l-u}+q zS!~5IsvoOf@wwOhZ32>ukn5jnS%Mg`%aV74Tfp_gvGUf3v=-3-I?)HO@>?F~NC4Oh zP#kFjX|>O-g@hOeVl5j8z+?RrfZ@j0udWubzM*7?4juszuiR>fX%Kp%c$Xa`rf7yw zh58UUbnF;>{Q54O2l?VrwdgqvJhzUkT2=58*6`CEQkjN1gZ8pJg~v%mVCUF7l#fd>wWoq5$iPPVD|fy zS)Xdkm|%p)ZJ0{0yUH<0r`CpyfX7_deV-{gD|LYMvC(9iq)CleW>k76b}@JcAW98) z8Mhx`!5BFO#gQhgW-JF8kD`)QJI6%*0z7>?td*})Vl$RXhJF=-pWauu2mo&#+cw==$!oR(?d>w{C zx7jlRhx~(>8-aku?%vKT5dR|BFh?Du{2#juJHtOFHHJ0+Ho1B-YndOz`oU150$J2cCOsZqF7 z9%_w(iSP^ahMJ)n%0Ob=)k9r>lQ&_#55*fiZG%KX0Z9b;>4bG{`v|RY*2Y++P-otQ zUXPI|O;eU-xRQc|KJ;0K22SQdtRJLZI2i>C*`nuI@g}F<6(-fI$K9g(q*ueHBVMfR zV2m+jnRVLFI4T**CA-)h+Pw_eC>hJVp9ID%`;5X=acN1F>7t<%K*lIz^TS~sVQ5Bp zljwp6lqjXwaR<GW(QTuFT5*}X{l(Tw&A^y&=)$+w`!YIQx4bsj(aK&7T zmSBrP#Lf{qO6rTdBeay1Pq%ejf-Wc8((R4o?_?>R*MbMBx$b3h3LJH)c`J6KQEl(- zlc+)#cXqAUQRA^fW}j^uzLho@Dd)*6Ac+2-wT0RgiL34sp#0e2_x9X_wFghjB8UW; zRuDgw0VhI%1X`MHC<>`#;|a(8BybfepRR*6*u+uu7+mgF{i z51Avj`F8I9A_YAgC~B&n588-!y=U01 z1cD%+UjULe0t1GVoAh4F^c2BoZdPGDroF(flserpNAmp%pb`8ciyfuNRG5OdwbNKzXaL_1xPLh~FaBg2s_@F?rjc<5J6BhAf zT!xqEmYiKV7dd1AUM=TP~TS)9i9!FT+^=JLXR?L}CQ* z{8aZ_Z=28~O36E5saP7FZ})3)i0UjPFu}!L7(9h&8%2*;X&;}AxsVX}?3Af9$F406 zOl$i&^gZ9i2RfJm%?%><^wE4=X${h#AWj%Hz;!q`2+BiTdB~duBxQV4g;9?9ZJ<{2 zD3dE^kbO_eLNokBjj`{J(k@>kme`GdcSJziS^G8Dh!w_@3P17y*xvot;FO(37~X4I zv$z>Cd)V@gc%TznV@WNraOYM46F~yW+ujAIIizbIH+__ueyLXm32Wi=1=UG=&?@tt z+Wd_=0Szj*gce@#t8pj(u*+oC{=9ES5mQ z@IOu^3QmNizB@DmUDZHp#VOl!g^RO_{9f*Z`W~EMkY>{#CyPVt&x?E2EGz-F4wA=T z_E$d~#ffie6Kgaeu!QSQh~BLPL;b08E{>Qxx~oo~cyx+R*ibS-83tGoE=>pX7eqML z0_U~eKMOgbBW8q%E?8GZ0=-bf$_Iv0rtDD}eO0@NnXUGHOC0R^B}f*qV3z~>AP#uD zqIMf*r`*ZmgPOpi>!;T7IJ4yBs_EQco}RQas%@oO8@ zc1)Gn%xH^(RN?Z!TH(QTU(v^elS^J`1)N~Y@{OigWvH&x&%m=l%WZ#)G0sFGf9Sb@ z2mSGG`|>L*DD%m*oOYbqxKJCT3o$7dnnY{+l!$u(%A90aNF0&?21_Fv!w)faY@1mI zL53(oc`$<|@UY2fi%zXRXk(7o<&cGtH=Y?5lxW^kDOsXph6|cZNlZ8%>qRwRs@<>XIBuLJ6sr(?C590Z8=PdvPo?9{3V+Z>6Ge3a@uPClE zU_+DLAaQ^R7`o{U{!DmzZo}TUGy7c{{U<4XzQ=yt2Zugme_&%NW97NDYEGDJ>+yOu z8t3#cmK5-Q09?yIh&D=phDPKFaDQ!sCTtE<9OjenK;}U*U6cal5VaRjuKAq_D>WJ? ze08~g$%_P$oMI{((E#b6_Ub!ghOosKtXV{^)lM4_Su7&%=5zvRkoA!ow+uMy^ z;5W>svS48NZi!?wr5VnFT5MjM^WMG*?DlZDZ5x0={jnpFx<&sjGel2MzDjAAH_R>iX^}P>)8%_CwNak2m$Jo(c2qCYwH24-)pjFBrUU zW$yL94D}2Bu*mM(cZEu$%+VKQFc%7|}mwmo` zLcgl&Op=5>wr1&1wQk@6l5au5JE2}BIJ}$J7k6~()aKOOUl>n}LX^UumzbmV3mtA$oqtKrYM(hf|PL2Kq?#m+VZfFw>f?8YkA6mvIN>zcd zsOg1D^MACq8MzYei?in&D$~6`y0G0Z*A7-J_KxF6TaM?YMw0mqqD>H@m zIO|>r$#{+AScJl#{J9o@HE=4WF!#IO&XG%eB&^y!-Kzd=B1bTlSuhwS=Oq3rD2`Sz z9}b`V_&hGG$ij=3(XtkJWP}1ve-vF193|+?%|oh%R0NIZ zprL{&m_2ocGX#v!U+`66nW@CjzkGm9GNzg&~i*x==D3)tFwO>8F zoSyI}2UB({tlxlp`6bwxsSf46cGsNZ8_@^^t}}`$g~O?!nOH>l$}1-At}m6_J%4Kw z?R=nd-A`U2S~-X0d)r0>{EM8c6*Y?!WWO}p!?6Hb(5a?1K#b97YsO55tak5)!4_dP zprJ4&u=XH%?%xglS(wPo`}evU6a?Gaej%Rh5;courC$f@>W?-tV47-(${?)sZe>46 z0_0VXe>dDwUKY_E{_*{tD)a$<(cA#|{Fft~eBbf=o1Z|*Ys@6%A77I1IIT`F(Te9- z)22sv{(~nIRxla^mjkl`v4<{;@cwslRn9XxRW%mXPA>e9kJB8;Y#r67_q>di+>R{# zITU0eXi=?z86kTRBTzw+l1Sp=D71b8|L@?%5g^os<){htN}%NnGeU6jU=mPAS!bOr zHy=Lo`?N`8IRM-!ZTjuP7;2S#+*q?KWv%>b_3g=(>>Y?ro8cNlB4Q))>QOZ_$CH*_dPb&@NXD7PJ2S zYgp^&ttX$ieUYB#W3ASK&p*^?S6ih^nO}_2?=p2LH71pB(h3KqS$3<%=S}(*k_Hrb zU_wx^hz6H}1mh<03TCE=cQ=y!NeU0HL*L%MWSls9GlRp^{V_!S28r*Hk5V1qw(}yf zLanyErz|7d$EZ6KAHcfjb*SxdBY~a(a3}caEo4?wK2CpjLy@@M;b||8ClJmT zx8EeM{P$hgw@`#r-#r?A$Gm{@QU!SRmBb0Qt2aBR_Hsf8>p+{;R0E0!IO8u>PEJPGsE>`K#P4B-CZ!}CoB|w@uE8g#ej8-O%`&oxp-y)< za@0`lh(s)#f;Qn1p)IS;ipmJh-Rqo?+pcTv(()k#7nN{ zO)IsDT?D_Rn6G})HP7s_@p~>_>E_?;J!pw6p(O_ypBWs3HlxA^qQWQ8sBp>yg~ROD zAvwBAQxWtQyBd|c1$^4}Q&TL9*XmTZ8^2;RG7_tfvbF7#_} z!LPfg?#HH#q}3*B=`Cc**DS~)M5~(WR7R^%cHFatZajxC`E!cYspnOnA#6w;_()R?G)QjAx4sJUv?iS@j*vPWH2t0HZ=jwheZR7y(Eu?H`% zqNG^*D>F`|-6R1b+=|s9kHKDG5K#ER7-kKqWVVojh)rq^qS>aDXz5~wxFMzLAGlU-E0t+3j@HKVxpRWl6;+kLkw zSzy)wcCdVOA>Uh2w%k=F??Yahny3Y*;aE0s5`O#_smwYYv}InthfxDXY-fZ`rUCauIimS_5fL~ z)}vs|dff=+yr_-u8epEU96l#pw%!TV;IGJp@10}S-bTNeWa53?3O>)&bs8g+;}m|o zSxCfN>1!S_4Zi?C^8=)8%u7YPfDY-IFXWqvLpeWfDSETKcPz@0nQ63F2{>B@>+OP39 z-lCp-3w|~Kef7&&EhxIsYauj}@*5$92oWZSrvZ1{CN>_oNHD^2dS zz1{``u{q5<+|s*3OQXvb$eg+@BplV9YIGVB(N%}ht?$O&?|MI~=dEctmP7s`EcTDe zFK?G9Q5i>Bu@+sM^4%#(oD?yojO;{-7Fk(aDvb46VmA&8W;QRo;BiIx)e2TxFCHcy z+`eE4%r&M7%tX1aQM0ojYcqbxLOkqCWM^WRtz-2z~OW0qPX)3bxz}#;Qi%cm99y_UcSw@>$DBr zc(;h$;P=B>RD)Mhu9jjeDz#RcxsUl+vTf}u2#u?qhy1aM8p(FzkHBBY=DL{axDH?G zxVM}9XkP@#2voK1`jGZ$l-)3I(X^! zUd{+3m^O{U4M6fJsWXx$;oeH>{hjKi`tkib&IEUl3d#m)ooGca=&iN)&30p2S(n#t zkkak(d`GPR0~!;hZzyLwnq|r%7HQp>zfH@+M}b?{)?pm(5(Y#N@To%!w$&Ti-)tiKZ{LhS3-A-wu{`ZEjvY$odMZ;b6*u%?lmI@V6{Y%8 zMl>&5Cn&|7_C1zx@WZ!12pn7>Z>lA0Gj3OA8GgtZ=Bw>9VE&c$Kc1JHPii|m(r3a6 z03i?xPsNWW%lSFKG@ljaBLCoD(clQcAKI(|bO{~9dfk7+r@3vZa@9)G4z1v2zS;*p z?E>pfO7-F{6{3_Xn=MK>-1cVj-y6c>_{}l*nf!9f;wh31TC>oj+SrP`=Ti=9V_ZJVxXG*xxA zef+^4PRS!+6=K1{M^yuKf&?2kq0mZIB*v=NUPZfV;aF;;d2CU39=qm;s`X?(S7zG{ z<=IEOZPV^P8`gT8-aOAuT19n+MQ}+go{p#XLxL1ztI_D>JGVv1XcyW|zsORhwg4-#@J1YlJzJ-yVxtiTQP%TdHU1 zK^yTP;RX-wZ-2BGA;cn`O0)(=kP-;e8OPc%39YF?NEtt{|jeq#y zwi=?+MD#dR8<1fyElMR143v5SfDdE{_0=)E3|xYd!S%k#XA|NQWyfQRsr$10owdcKVYkC!P-! z9Zs^3dNY2cCQshfO#;6B%ikuRO%TxyHRX*09VziP$a7K#azbBX8^wJH0718)K4Vyr zG_*vB{YE1fj-T#-o8M4;xrR$7QbS=JFxkhX`YGHUw+4==(Daq)(ei!|Zqw-c3ksx1 z~^FqA)$sSc!S&qjViyjTWS?1`tA}7im*eV!|Z>P zwP|uk6;S}s|7dX5G%x416$r_W)b1>Rdfa9yT;$&W5d9()nHNL)zwuMFjo=|By`l!E zD1f&5VcqP|FH(c2Sj6CO+u??nb?Ft=Y==p5=u3hWnu(3}WKe=VVA##$LNgp@SK??) zvp~-f%O)8^XJr>jjs1g0E)VMmwH~*I?c!QxrIWKQf2oc#vEK_jl}>@j)0f3$F;yjG zHPMIwrR3)aKzrLY4=<**vbjW2aTv|gS|zD+K|!-7b9>EtdT`$=&+%wLt6Av;xyHsq zQIfTAWC(M%hwVu)IiUnCYRRUwF=`f@i}7Dq7r$Aulvwo4LM8j~@}gApq?WR3#Xiw4 ztC2|98RQ6Roo>wxq;->(go<@Ioa)Icglfu=4o}PQo|sUmSe4ZRrLBNxshJ&*Vo}%# zT3jj(w?`^9On27uo~sgmXZAN_(nt%m=L(J9>1_?Q~S~0*KV>%aMm0e zyS>T#cqO0y1?3|Tz(;)noP(XaB^9b3Z}=|E8@6-3%icuCNt)e#W+*5O37)0^ zDhNSoE8ChW?R4ix0EOLC?S*h^z%aA{215}YjL^&6#wh!FgrlcHaqPrrYa(iHq#bHG zCU>v>AlI3p2s9Bnk*K?j?Z@Wax47zM>2KDo&TB`juEz>7=I|tW0sW}O=b7Ir zJj;CH_8yb7>+Ne+X*uQ=rx9PVPmvRuHrPa)goK!%9fh1c_Cx+9|LK5(9@_{0MI~gQ zBr0nmLyt8_hWxvhi!Vrxl^Ul&@tU{v-#lN4$cNw8Q93o$9|CKs1! zGQt%58Yy04QM5|TR*A|A%(D9JZ2Od%`sSAT5>a$peT11f17PV%v z-Sb!F(L@E-QV(qvCis;YI-C}J=~iEDm8&Im(Y5166=ogl@Y6EMpVJG=er_4HFN1d- z+hHfJZ+E@(fRaejrrwQz$LqDS>p921MXMwmcC%aec-Ha4`fB+|%<2Rqtg-R)Ff*(g zI?^Sf$9wy<@6;lRS#xK20Kx#G+AV;=LpkfExDubs_Vs`0+-x^#g5*&L0RdwSQp+sa zQSTuMAi~U(jVE5-Wsf!r`$8gU7*q#E1_etI>Acj ze-q3_DdYIRH6MtX3-&#RUMg zBYj}A(?9#!Si#j8Vwq<#hU~99tcN@@I4LK6$6=w|UuRqnNvf#>p#8*I+9veiVI1KG zd7wBmz2+m-YpkagBGi+Qz8e5qKLjdQE@Lv!{LiYi*GI}oy5zzH!NzE0%lvOg@|}Ln zo_f(QgkuVcQ_FhZHQw@rjNFj)V!Zy$kS6fLR2bQu4*drB5hp;**#7gyvG?O?+TYFD zRK%)>mhuL1UlA%;@-gXgx@5u7eCv=f&KVU;Zbgvwkx7)f%)G95&`?-Bdg{$*GH4VLjX0If0RSVAU|QqTRx z=mnldN;-NRusb=OVI7NcG9t*2~1UBt*=V#9H1ml!qF48v*XScE=3q=l98rJ zNVM1`$J09dpV&tF0}}c z4Cb;G-6f(RgbANeRbtivg=Dw>U9R4A+5VuqfvTiDHVQq~7?W)R3xpOC&N)_!tV$*1 zxKd)Ln!_*EwqYt7W%f*wLswgQ{UP}O6c(j<7@{)E*TH|V1C*1Fx zk$udQ#N#62=bf&hLP#mesT5q^j_U;Fu4hu+ip(NEtRO5_XPj)=2`jG|?eP>jEne7Y z?!-*$(PJS_vcyE2p3*d(C`^;?9=Zof3a@7xvmo8*( z2qLl)LPy*T0Elb8v?21qbw#XDo!B+TD6B+{jlaA1YxW4dN@~hC#51x+$JY}K2u%r7 zsRFBz^*{!fXwQ%swDD>aga})%(0yr^AS!fN9!azBcXs zx`WaC=ieWvC*BsaCj>AN-_5=QUAGm}T7*^qk2hT`^m~#vxg&z0Kct`%=%3<4ICzkP z`XKEQ8&F;(=!FEtk$qf5M)~qYTRCwz=L{};ne|TSUx{~+b(AHhkWIv94s$dmlpdKW zDn9ipYpc-<$9^#M{OKl$BvMmxnv_@~e%*O4=58*2iQO(2W)5JA+2sdhi0AYqdjul1 zc*p2zz&0mMhZ&y{NC(p?l71D*8&&5c5N1gEix?$5IUz<+AJt(VAblkt#C-z#us9U< znRwWb0Ffilr0;n&7Rx%PcwV&eH)GT{Oy4YMHCPh&w&`>dX7h(wr{8oAQi2XScGVZB ze!RjYUpRLnNU{luRt%w$*j`-2s|ap1MOrzDuG?=-GY)HaOI1j2xcI~UQs=nw!F-_J zm82!fgR9U+!w<2TgsCIM5NinY4d^v3fW)8(3GXMAKhJ5v`hs=B^9=xZ9ya|np#Kyr zmg61L!A`5U!DWiT(FFi5=jkiqPwYa{wSP(Ccz5=1p7uYDf%k~PsVQygq->MXtraa% z#`du$ko$;!pMn@oipKzBU#_&1t=Tb#pec^5%xuZwcU|SFd^*VLcpUG%yY$aQYkzf+ zU9*W0D%q=y5=XPNRkS($-fY7r6)d1rcqZT>L_kZwyt)`3Nfw0TQyng~9f-|buVb1J zpNaH1%yWXAh^aiFIJ~r6u~$RRw!l$dP|Uksu2djcLX;B19!;nFquR~^KlcBdwj_^X zBdWN9YxZdpkx!0U2sef}nlFN|c+5}7r=d~qGRd!mfVAoLiOh|No(WGHJvy}ISWaGD zZgv=}@hWo*!}omt0{6!%2p*m{w;X5Qh{#!u36_KhhFHroLPRCypHw1juYH7z|17f_ zp)Sy-!p@cFD`e1L{6s&nIVF@OFrnJ^eQfpGKs4qt*Kkh(5SpD?j1Tf=~HX+I)&XCOFoA~C?ML_#q1{1Ws#3ky3A@Gs5 zAo_vVF#dZ4oC@!Oicr8pnyw)2NVjx8>me?%vHQ2^Sn&n|l56jKqHTvpBsl%=VfUv5 zZsQJbIXYjYKu~*xKUCB67pj3INCF>+q?BXb|AxH~V01nLZRBI7Arg-!*y@-lZR~#v zE&zc?Il|qVN9fp}429|WbNoj=#%=zdYo6)8 z#ap9dKQkel+?qzHc~B)3m*yE~OHgPP^a^!FUV^EkgZW2`k{USX!%$CF03^rw6i=oX zvgsd^m(1!Ct{KeHJuroIQVM}B#*55yo^1U{j2=OHHoJZZb{pA4VHmNqDG zJoVC>{cJ?Y67Ij0M6YT)J!AK8$%yr3!7ar(4*ElTWWPd38ND!4<6%dT6T=KKalEqA zjb_!F*`;M;;H+#k>b&68QXnXq-DqUFc0h-ZPh3V(>JBR?PF$Atg{c49Ho0ZCNf9)K zH1#xS+AbEU=y%t&lw%eSx_OKYd+Yn3!q?E{l%5UFMa)=LJfYF~xTU04;}?z32BX2X zQmrqQrlztthp;E7zNELEU>GaD)3?f^rqQTM6il*~dxf;%UKQ(UY1frq)GECWVo%~e zhw*Ey7w!#BlxRA%q2?w-8*0P#|yEYmw>KL35x>i74%|P`CFj1g~x0<#QiNR_xJ0U_@W* z*;1wBsL&t!!!htA@&&GU*I9cVMT!wvM^JK&T$_X%RO1tjFvIn*n@6gq{nl^MTb|D1 zH^L!qf+b_ToA39n98Y+)3TZk{koA;^N<=u6@^6 zgf>_4Vu^EWo6On&t=i%Fw!-+X=L8;rjAPMh)Dt=|WGf^i>g?m>W(9@Zgw4Lx|8Mbh z4k>AeE~)n8^YvMff`bnOeB zu6|kn$v~w(pIQ;Qn#GiQi^|dF`Fyv#ZlU(aYAF#>1ubgQfUT7^Udi(%|Ek+DV{-~? zMRkKD+zHO&%=p1bqKJ3J=wfl|61gawM#-uYNh$sEy06_*rZ>UN8-_sfnt1eFYNxD% z=m}?cLz9j+?2is7yCd(}n9bgbW|10O9G%YNPY1)zQ0!SJRIBNf^;_ zVw~){!aXJB7^_nJe7xy(P4RPHA?;{Cy(&FlF<~{nQqgbxPHSn!b^@mQXOGQiE|=Ly znQCgK{e$jH_~yQfd#!KU1nW=QZzq9bd`k2wk4^R~9u;N+wyhug+y{rMFe#%=Jr$aF z1?bIo3woaxLK$&(e4vtA*1`(rb*(83g07?3u*C-&Yah8N3O^1>sENs!SQ@>1Yq&9hGC$FH5mgyjjST^v)!qfU>LeCg%I#c3~wR+oAGi{ zkxFpH=BBUIeTYAXjGk{RNO|_C@QFmlE~=!vpE;fGAxUYn+@4hIK4`(L>far)TIM=o zb2%i9p~kEIinfUD@F#Fply0^CNK;f_vjAPap+?e5t7`S|OAQ|4-1XN%R63l}ZIV@1 z?+0|Yv{FC2V@KOkM`0;cC+!7`%YU}b6A7JGrV?7rb%OT8Z&x-Iy8Fr2OX$07wcJl{ zN>>*QXC2}hTGAxgOg_Q&v#PVO!)#q0s05s!Yy;dJ$^AS2!# zi9cy>t^gI3D{wrKOnRLs4xdj8;EOs7C~L8li_{om;{V^e)V83~lN)yHqzj&aRFqgH ztJ6=xDM9M&E^(8HrWM7^rz5WCF*`>#F={rm9mEuM6^m9!TWY$Bxro^UkxUnY7(Nf} zH;YbJE&b)w@y_9sjg-{&+R;4iTKg%2QUqZVG`ckz6mpfLM-=0zFdB~cb=lY-y(Cua z-z~N@RL?Hq&e-lfWZz^|?xPBU@8Mpfkb#O_D9BdCX6T_|Sd*Z&R8i0* zb`th`HY7*vD4_35+;X6t+V|95#@n`(Xg+QMX>&uBr_NeIS;uNQ)r+HcJDAPXMyDj| zlc2MG2_gb!$bfBk7?dTX9~<(B|x3>@;}xQ-$GHyP6wdA|3KrYp%3`!RStOK-gX?>^l? zNZ}S5>0tY|bcIrpTAd*$vPbG}l!dVQkz6+BCY7<-l`p zeE~@EgDF4mF1<$taWzh#h8UR*pe3axu)_?COJraW<^v1|S$#FaCJ%QjODzr;s8%hl z#y7)&?RT|hcji)8U9)SARYVHq>PB!%2OK0kUSSQ84?2!SVe9fLgn);)^fHjB4Bn-# zQ5w6{#OA@}GNylgSSG*dB@$61V(YE;aMn0sQ&cr}pE(u2Uw%iKyZzPRRne|DNj<;% zixdvGJJ^lK#Q!YK?j;TofRajq�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%0D|&5l0K5ys92`75FRoj1+y} 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

5HXEHuxj2ZsORCO$CdaRo zT@H=j6gf&FhXsuEpU;)Z{eKi(2*de@T&zRul{#hWDR7A1eSP71M~eJ=j!G4{3YveE zU&ud~edVn~F03JX#!HQ*04-^dQ+lF@k8SjILtp6};e1ax>D!11BLsUv${)lOBK&2KJC@D}q~Fl`ucukroNcyrzLTIGPlr_>wSv|M_fT z%5^>(fwY3=gC(D01o?Srw1k|O5*bBYTje!5jM(LAzsTpwcN@OJ7Nlm)=gI0{$WHK= z%RGXR2yon<>&k_-^ckGboda3=73H(X-vQ9ujl8{k@J94PrbdQ(s%qwwxh9W&+kGpU zFepUc&Q7Ic(;{X!)vrtOmXED^?r`6b{NO=tg>tf!FnZLCFs+V(BaXKevUnsJ3>E{*3h#KVE^s+vtulW7aFsoklH)FA5B{c?_N&*bI>-gz#CWB zF~NE6Gu+$4 zJe`OfW#&H95_j(C+kv|`Z71#{Cw51wT8%hVyKD?vAj$L9_1Ig}0H+9{jWAQUH5s>9 z{$d~Mj!A86_A?iFNnXu?0I-%yOS{}vaBUGx(kvwRWNxb$xgnJ_aQ2Rs$K-Cti5kC^i>F#7c80bIUf;f(YWOW}!PHPnP07uo>3~e5zv?eCwF&paAz=#QW?W5R zR8j%wydQb==C0*~8>68y@l*1zNTpHAG6|O~9UK-1Ef8SQ$|z{&BU9OL$da6u@}e#K zc>quJ*>IJw1N2XrD=B^_bAnMc+UADh?b|gB ziDzQOXmjBH)^x~yC{JzqD<(SlMzF-WgS{JK*<3dME{Qd1f@o8^LER3cJ(swK7akRi zgUZHbhCZt8TM-P9RFV%0$6|H@wK6M3(C~Qk^L{+mkUnDREGQP2Y@*fA1{`Guj=7>NaTp+J?pifhHUT zRVJsP{p-({F^}xk&wMD;`EtpxKe3p?{H?lP^9Yu@Q0tC6FGxN!P4Cri7HWzdd-QNQpo#>sK z$m4q}?WF;?Y?cnHF5Byb=Tnfsei|iGW-fxND;;u zda_J`S)IIcAHq)Y1ddk)T`QHe(2i&IT1{#O%|nT~Hekso+Z zdyw|5ZN2umF#Ft>w;~pk+fPo?sgtZGZy@$)Bu7#w%KHq6A>WljG%;*Ye{oaXvlCa` zC>h#or0Akn3K!w`X#!S%9ww6o7Pb&KpTo9Oa>=H&J!)F54vfvZ#!2N#`p|niN{Hst zrtJ}RY_`TD9|WD{nS=XS7bzHpYTw=Ns%Q)=?)=!#U|Cp+)eT6xwhoIiLj3DpL}U2W zS>3}CMzAd|>{N^nFJH_Jn^`T;O)@bA8^Xc}m{8$Mj;WX_ofk6`^aGVaU<1@EPr7>e zqQKPVbg=?}QRyHRULe;X8d>_PyU~$&%8a9PAD@p|n^D)C-gTN%R95o4&{H}_AkXBV z*6T!Ta2e3`ha07(Fgpyt>*Y}>stKx5SxT}jX}vj>N`G@cPb`0`{-wj5b<3`QhG4>H zQc~xa@93f-l3_i5zYzph8QesFuz?Ki?$#uQfo5T$7-cIW%ogv(JbDar z>rB3YShcAU#Ien2O!v^*EA0Y)vf6&Ww}ZzKvHo;lN~-_DFu{6`0LYSd{*L+2F!qJB zN?DA)!mc}RhE!y-H0niQ#2dKj05WcX#}=!YU)c?d&kvnZE9MgdDFs0o3mt}2Mq(!z^z3eRXx?Z`0fX?%22o08`0Kq2M_tiGZ181@)YZTP&Z(|wHmfC`x)q5+rd9a zOz2Y@Cyc$T?ojg*UnT3&RN$&+A(|q@Z zGYqzqH+P;7o)O92@Nwa8`5LHM?0S9ndSck#TS)M@b{K)(Jp`YPcnFPfAN-qQE0T?uH8xvHHoMCTjT5XApX0vxBlEZy1%!4 z;zLN0%SVAJtsl`FoW>!=??21ujhv(72>hX2-}`+7Ym0rTabIlA`#6dp zOG32ID$r>@YKD05=M@(eTkfPmDu+bBI5Td6tqK<#^8yx17J7;CnnsHWHF5=ChZCmOSjX}og z4bYWMnB8Iq?A-#l17%44ZyWFVH)qeH${pJGOUL|==G@wFNnfWM+dt;nuPVu>VUh&V z7&qazY}~E@OV#zRWJB8bzc4aCuW_qf+SceqUU|Vwp@u$Mo5^SYTpIl6cx1}q-qbKq z?_zTjZ-vkO6@=y*rqS!kpCObq>{(ajmBp9ZmzUzhmANe06|RI{;xW=d`T<8Z+BBVt zM7Ny{v4ivO$BQ(e!g&?c{9;6wUI+bli)LymCIGz15?}W6U9LR~W2hu@5T)=-chgY< zNa2Tog9BaG)PJT~h`4rhsd`@7{jDXvHU{LMzI$$ClU5AgHxHI(0l%v@C_?a8Wk>gq zrm1|#8?xT;RZmuqYt;J#AUp!4fV5g9)an__K-c1Me5yUE#kz80#rtJ|sERxv@hRzK zEY)Ma=g06swEKij>ZxbX6ZxFhd0P|>Z{D{+8$ z2oEt?{MwH%F;IUyF7xN&Jr)3PZQyeaU~047n*J3_eRCzoEq^NLaA&Ebka=fXdQt(8 z#W;~h*(4)H|6wIsgV*4l{@{}b5tCLQgS-*gRWN+GrUL1Lc80B3cq+H-+_#$j(c3iY zHNya#J@k|bmu~Mw@Qln_P8Xx|XPZx6~{UnIX+8~y^30a3|K z3cYX2TRqpUHkT++iQkBq)UtYetUJM=c+mQQz6zcYr+&X3~-@Q9NoB&nH6OI%j?oHiDq9%)d#L7UZzM& zHwb(K?mVz($AP$pXTssBU|FWG#Qx?eQbD|0;d-hHxpuRldL4iuYbcvizCVmBzb5pr zj;H32j%TCGf&an*IdADB#E_1yq;&{D^p6Y9!S19ap1bc-aJ2PPn68hn9?ghkiS#@X z%3kql*mJ7j*;$Y8Fwv>gS?4mIzsg~iRQF?JqD<@gmt?Ve9i4%&oAV82`D1A>9Y(r; zlA0f+-jS{Wqe)FU2zr|%IK%s)if&$nhPXDTBj7JVAmTA(?-0H8SiX2IS)@J0lobYE zhIXI;GS8kmi>ItsE{(pC$k*Q;p|d<;9Qz_!WN1z6+B4XA8UOS(StrVvK<+Wo zaZ2}io*EG*#V(&(-g{v7?_`jueL$X&!Vvzv zh(o&Wi}CO?k^C=~$C|B;io35nE&Y1cW_rG*{Ovn#)aYX7ehNo6Ck&AJ%ck;Af?%Lne0i##^-5r4l(>Ece9^VRe1J?X-}G0Vl>f9O#90{fOr!VqV^E z+a!>VccJ`#Dlcj}=oVNY^TD)vha$to4fT~{mnv04{^Frh&}cdQIB#5t3tls9hwY?j zDX={B9y^G3P@1v+8mpJJr+c7&EE%$|xHfo;x!_0u?V(sB+BCWX?Snz9niH90uf%UnHzcB8Of?V(cVj>cjk6--sJ-^&M=*Dg z($jJf<~25oZ9LpieBpb=vTRL*uC$q<7ZAlhWNHvt^(}SCxR-NAl@3vtsjOQ?bi4+h zwfLsFmJcG+L38diP|mcwfi(j94DRs#gIT8zK`rC$V$k?l=`vkX3*kQ$o6kcv% z;B<|m8~IbxD;Svli=~{M+K02ZU-mNc{?t;^k6>f^i;Zr98M(j@O4K6r2gK$02Yf*q zDzaVU>K1I+0`gRzQmR1a9R04+HN)?qw#u3v0-d&U#ITpEFRdGH3JP^Q+VUs5bX{vs z8JhJik*{<6S#(RbAc@lwVf1%WXP4Z&aUc=sb9>HDCB|IN4Wh@5WzpQn2Gt=l^xH`w zmvHaDEMCz!QCcz7tA`n+cjS4}!4R3#I{qX@Q$C#2NGvP!S)T^u7wixtdUak-mdG*U z|Ks;i{`#ty!l6@1(bepHaaF7^B`0uiy`aLrlAP>{>-ZZM>=uS7l2wMJ7j+-k@5LZ` zaOsFVlifz}Gz^q^ooYR%z#~0QA#gcG_zq-!&2X=ncgHq~?{GKuRRC^UAmOp{aj5W7 zAhGyJ+6lzsp465Q?#w;6M@dqYWYsC>WR0YMUv)J;Pp4AFnLRQoYeYZ6+xp~h^}!e& zmZL?H_TH{QE}|7-Qg&!Teiq^?eot#ooNt`mFu| zLg~}$)FRN`$8P`)%RIEkucQVKy;BySF8?_IpgiV;V*PO}A^O!|?)FnhJ=Llmkb-;x zv3w86CFaX@nJy@34AWB_;s?kw^7xylV4hiTS5q!pH+OA(v?Fk860wi?Y1C$++0Eko zE~(lx=(FGBZ-3)`6PfDrq*4FxErt#)zPGAI*IF`#4|+Jx!K-CW0#Cv^OjhqD5 zeszs5zJ)6n_w>o>rvIQuwOsqfQCYFS79X%uL`4%!!XNME6(ie!{*pXL@oNadRW2ER ze-XQN54ID#22ca)zAOS4Nd|0-XDT?Rrv-4lmFRN`yl?!}1O^bP!|XZ{wSUl4Ldn57 z`{m#ul1(mh(1ll?cAD+@9a*RBuhe)I73KDB(%Ww7CV0wjmJho;re^n7PXt~+n!tf3 zMR|L&khZ=ZEa_emiJPq$6542NoNLVSjTzXO{UjtJ;uzCYWH7PszAy{9lQCUyVr!0) zkklx9`D##Mn>f&?7B&Y@Er^<>4N90{89qG~%SwO7v-3WWT3P<#i}A#FYExIGz`_zKg42c+WZ#xlUa_cFStot6RmMBdoUX&I3smb|` zAU3Re)J+SWbe-t^vXnX$Y%`u!@wPT*Jde+BsNrm_h{th<=BP)U>&>H&7F2J1y%uMv zj>!)`w33}MwQHc;lOb_@C*9VxcvEo}sQ@0Y%o=~VB6`+cIbWA0YlI6oRl0#J&Pg}w z7>1woyFaJ!CfH+L*KI*ea3$jhmCvZ21U2J^ux3X7zSnErhO8B_;%>fuwr4Rzokh5* z>u}RiN^sKyOAkKmEtU1eh79#oFn5~^M2F`$(rK)sxKrAB43p&Jeyv;>+$rO6Sy34D z-jZZ}rCx>pZBz28{1ZUdqfTOqS={)*Yc(@YiwB?gW4uSppev&j_QKa`7t>-{pK7%u z>MwT$n)k%tH=rDlB7Y~tzXzM(3Mah`<;t{3V)FFJ7sAwT#BUde**C48E}%Aa%YH}~ zNmk6k{jmFN8ALV|QspaHlabxdm{{9y+u;x2(6XGQTpjHCoNU{W`YEl`MZd4*dGgs^ zp_b=rP|#$tWXfOrU1Nj{ha35&$ul~J~PBvIjD!t<%(64CT9Z(|;u91h=3 ziTEsRQP1GclTAvy_$CwvVnt<(n*>N^+OcOO1%@S zP`ZX6!{#!PJw!C|wA}oAWgCO_Il2_T{AXy6Xof1;xrQ)H3|3zORl`QUBr0S~rpC95 zN7zy|^^?t5?U}3`wu;T~yt|tLs@6sjP%%iHeJ!$3`&kU=!&(L@t`mg15yzoWbs-IT zj#-6w1W4_BZ7=lq(;}&*AQPdP!pQmpW8;)ZL-9VX^`1#}!Zgn2B{7*W643a7NK15I z1a+jQH3oZ(BHFwN?phC`M{WDaZ#pvD14dy@#TI_7NkFFl8&l7Rld^Y1=*L;l&OZ

DolT-h6UnjXoI$X$cT2@dHe6|0+I5`9w;Dl#YMKCC zqZiRQyeDD}Wsb9b5-2yLH$VYE1`@aBn9Q@yJO%&r`9m;yPXTtn3B#d9TsN~3Ga6(S zI5HFRgJ&p^JTH(8+Cr?yGelOF0kI3>QyJs@gh6n`BZ*!J^vOhpsMyPZQ@IHW#}bf4 zxr!kmPQh;kpvnLNdQ@lDn%NHPBRu(zI=d|PqGkD(kqGb{Wy0S8Y!Q2fm!~0?;x!}# z@?fLRnYtoz`t_XY_-Ry3En-ebAP;~o8q-8%VqoOaI;5p;|0>Mi0p#OF z-h05eH%mb$`nzcDLnrRz(e`&1nmhcks=8MWw|b%JIkj@2!JKVNc~kJ0sx=o@_-fVj z8<6#h0L{tl3E^s)ARV{bc&A&>>}y1WrY3s;hy9n8+~nf|k$X+}5MS zAORaWgPx$FDi;pT)|XQ7wJ7UKghI=r1D@0 z6Q{lT=r46SNO9S#d|(fsC;DOtC(p!Q#I&b+hob4G#l!&-pnOljs}SwxrV3j=(}-E( zYy8nE9Q{%s$YCG#|Bo;xUZ$1A0T}f%-B52f`uH5nMim=${nF%C>zd<57*^>LZbIZ_Q8&chtxIp zl6m@Y)=)p1Q!W4|?|r~HajTz`$C_l&dUO4pa?->oVzt{<6>6e%9Ht8cRhJZM;yS|z zw&9-r&&U9dxBS;KW=@&O;vK{R+FV@VY56lTHTOia;!kzf+Lm*c{8%~X*EG3V&phrAIYqY z%nbu*AKgY};J&vLZ-4mzuDE9$&+wJgm=`h~3?sfZ{2XOa(=sPALBx#x;-FZ4sTpG~ zL=RKu`{dtlk>~h{zHTC(cTq)vrXkJj>hGNdx0AC$jagpH%@Z|zv1-IVGF0H8t+Pk+ z_I`c+ZorflqLorMg@m1gdMdIyM5TKu7XmO4X8r~bvWp`kuynw}#jOYqxge@@0k)&e zTNS_6(W|h6d{$cWjBf{5kZ3#POH%kmh8xXkh^170)xM~RqOVjF?odd? zGPy3@{wU#5z6V2Dm!62U?3z_40q79_h&Di;iw7(ojdx#fW>mkusG-KWe6X8xd=3)P zNl;ahS7J>>>fe73AFt~fLDBB!3s;_ah+JH4$mz2xvVL%KILVTc-IcNrljQM0W*Z>c z?9d);?n2A|sv&EQfC@aChxNsQbDW93MbV44A(CL@!$gj~&^{q^cx*DpF}C2MHt^8N z@|?s(KG^Hxlshi077~j-xhxdr8`htVOLj9EDlZG?dC(~>pyQ#`mqbdAk|&rz1!fyI zvs9@_ zpsBIHqzmnOAm;HHHaDuoT}lb9cUk4jeMLL#ThtP&#P?oX`x}HXEXD)F887fy-atk{za_(0K!{E`<4k-X;%z zq6^5{`B`#WR(yx@>IZa^Ne{eES}+rN4rz!1pEA_(AVe>ZN9sGz;^6N%olAz~lywOR z(O-wzY(3zr8I{NjCT7CM%-<=@(c{3Qn(9sDuC>D90}RzK{=7$ANfD0IAx*84FJx9` z{S2pKhqQ?bF*MQiMGP}ESHV(Qxi+mH`%elo^sS^F7RHpJO!7QO7S%MAS8vq@)S5qh zR4bvMNcF^WjP(c`7}IiKP=zy=I*&o6_Tmw3e7m?@h7%FQkCkB{{ddWJ3JlTb7uX&| zAYER5)1r6t3CPEDLG9Z&sgid#V{|7th;L2p4T3$COGInV&bOz&v$`Ap5N0mWryWg* z!|}W&W=tg;@>kpkd0oov+0L}dcLNSQ34!4bR0ReKl<%zfP{2ILkT*=@O+aCJCSL6>Y7@R7{ItTnz1B!GqmCTWNwMHe9?2?+ z%=2e`ikIg?x%m9L<7y%sUW2`NJ6x&V`|itO#ABxGzBL{-p;p4AsFp1=@1jojc&3EHc#CSXrUPa7%QdU%)PmO?n{Lb&n&}+Kk>gooD@G(woaOEB& zf-ncHJAZ9RZ%F&TH!+X1*55G}dM4Oo2Y(@+fL>}2)FC~i1@}Z!Z)#->*j5u-MDWdm zJKYKm33I9HJtZ3Tfc&PPrbVYo0^)e-PX-K?SMmQ`=gJi@gG>%cwWx)2bhKh|s6rzD z{_cKa@xbP^q>|Jv1;Iq#*DfTI#pvc{`6y=h?2k7s|9W0-rF^T>2sn^M%?z`8faV7b z>o%XjU*w3bb2}*O*q&f8w;y{IlV=sTHc-+fKiO=h8^>byHHt6Nu}&tR4NHc zvW$KC-S5tMp6C0U>-_Uv=Uk7^eCEB}_x;*vII5ut+U_XD0d5cTfZy&tnJ$D6I$?3E zNk2pKRq=4ksYs=_vtrHg{aRxNl%P3*Rg;}V?@fKCr@+PD4(sYVQbnIAay{T_(pR*&I-zU#1 zqG$QSwcYd!pl-ZiUG~DZP8?Ghk)*Mt+Mb-e))~U5>=U)=ELSx?LvOMW*u1}mB`b>! zvq|hR0>t>v2Gwjs%D0lu4EmBxyGi44VD9)_DLFnTXnf>(sz-nOI;lipiYI-`2T;&D zSW`I}v*tH3JU@Fz@zcBGccsrQgwQFX$LgqUciq{uz8r#QVTg#2WZWlwH6f;bXLfq{ zzWm>onp4d2v7fyHrX&s$%TDVe1{vT)uZ@+*MFx}KGl_~v&^~RK>+JiW!tE1w@Ej zN<7HCldlw2q<4ks+huI3q#RytVz3^2`N5%K`K|F#dDHcf*^`ajd7vAp^+sQlfiDw( zI}>e1@R%+srn*ZaT8g>x(Wcz}!4jp^y_D8X4C7P{ElE${r`@>|l(#e=!Rc}F&VgFZ zs~lkWzdyCrQoS1{S?m^@7(}u+_WS6zXT7>PS$p_gp-(uclneMw4G0`PEr}z1A^(*> z2;D`rLtXCOfF2&MDiyHo*A(8JRf0FrQ)1L-xaxx!N>fo5P)_t2sOc#fY?XKMyTl-> zFCIpdJ+=i*CG-2Ot1IeE^AmQc`W^iGk$A~o;9_wUlObRI92_uBXGh+O+R;1})0EH( zX3%hFIn3p->iO?G>uFe19IsH#Hk$o`{^hO9E?wF+%SuCk82?uH@oX%>jJ!IWufh9) z0(ye1uKMgNVCceN_Qz9E?7g9R(?5g|_-`sKg(wynEg*qTf=x^n==2BRL^J=a1tY&A z7zu=gf{q2OTf-_gGB-8#L_;M6s@-y6D)md`KK#~PaO(hDR^3Rn2ELN| z%67pd;7*QXAA%`lW7@yCq|0W#Ql5%IVTihyc>Uky8h z?jV|@hEY)X5=;!vIfN`_PfbDl@(cOZ!w}92%pnWG1`UBES#!3)NW3#S2VIu`DQF?2 zpSmA~k=EbOxN+Fln`vWOUk~0&7~DN6PSVmC0WY$JVy3T*cwkUmrOHfdNrFil1qtJs zpMYuN9Urye*9ctpxDPb2A5VURx0MzA+sS0F`Z6f97B3#{xLlzQLZ#VWQE<;{sp8N% zKgw*#Sjmt8Viw`uR;+U?$d3cn=AbS2mxzRME!+5A+l$d{a=t$a^|61~BwPn_J|P4r zEbq1tsGs?35Hy!lmVH+X3ro3WXQC>hJ&|d2X3@>L;Aj72xg^Yn1 zWnm*8S*H5f6K#18p1KP1oI~^XlB}T%VRMzVt3iv4X-S!6bS4uF!!`yL#-A~SXP-`6U7 zy-`9e#U~-oq!9cJAi8QoGji8OjpdG^xrvg7Dj4Uikh?$>_D4>h>5fmBqGvi#udU&C z=K6gE;!jl*saa!C3v#rA6SVBc5?sOo$?49>5?YhP^qFpv)|?~SJ-zk8fr3I1|JSVI z#^>9i%e@pp7p&jfP5)X9XYab^DLClLf_Gdzrj9p5BILAjm{ZkxIPMDwf*-6GoT9Tt#{rj#B`Iz_#!uD7T9|!J%-_UPdlZrLZ;;!7%xo8gaYXo(2)Qr$pUswNrR+f4=6CoOwLJ#cG(mk{`|z6X*RCOx3@q`m7Z9US zV%jl`)$t>&XyZw1O9C8U2_u|kCBdqlj+gQ zJg{h6@fxVdRp*U5bt9|3+@-Jt9Z`(*@HOAdjdOn-SFFU_Q34s{?c9O9bG_QOe_vms zE3Z+9^cIV)JNd>&@we5q&gHgqAk53+>BSM16eDJa^n=-x8&Mnga#}AP$KwS2n zve%-}>b62Ghl$(iqJogM<@Jmc5`@Y*Q>NW5_XI!!AhQAoevl1R&~=fn7R9#Xj$EGz zG19WLn?>Isc&E+6Mf{O@&WSx~w3mxz>3^sG=#iYWpIv(;!R3Pwybpip4=!8crrtPT zwalvna9!$iyRE4A0+Zku60)vtPSiReoKD?!!zF@bb^(yx{&dZ2g)k~9drIGQa-*yS zeEQ&ur+7;vV+~k=O_EC8K%VzP!e-dX0g@TeBy`zq=bwPRe&Np-&Cr|a7qAmO&~oRHaj5n!1E|OiCI(J{ zCX)Uvl9qh}TBw415zXd%5`P20zd@kf`Ma3~)Pm0H4R#1s{{>|qb61Zf*{J-Y*2lq- z+FIcQ+cT!7eV>tZH8iQGR~Dw)W@3phx?u{z?DjyOEOuZgTALn>{qHj-w>JFDsp5ev z=;Wep=H^-5U~eTA!IXkqYH5w1H>l;%H#3NbbShVrpKTNH`q~9a+-$`@zdwGs^C^F) z;ay3~*3bjnVk%%P`E?lcz%?16{K$Ip0dn4J$j3!&{Zje+V=G&ti2LnqLp^YctG4rg z&NPo~Q(GSO4KIJI0pqnabtNCVUS2s;=$X2pE(^M#dzg$EfQUW}zCjjZ_QYd`(lp;< z3vL6%NH0s8WU|&2k;NKTJp5sPY{gs764)K9{;qYjKXyDZZ$r{uJC6=RE55jr4qxu_ zTZvqek0$(=Ag*s=_>f_9CarU#|9#8qG?X>Yz~rp}dfv-hH98dyA10xY61Q^WC*5XK zUu|!2cEu}icNbI(I+E>z-QB@_8^$dzZem%@ToDG}E4qvyAf} za-)Npz6%eqmWDxQk}54o0n!RLIOM?jxL>jzJZ^yZIJ?Tz5j5@d5mA;N!z)Al$h%S* zhov3hdUGf-Cj5N~4C#xk6b+=79lfFOS`{2o;Agg%;-ikcA4axQRsheaM6uJ>cN3Uy z*IJ01Hr)g3?M4405UDIX0nK6hl0C|x8p3F!HFuKt-2H=&;SFqXqRT)ZY}2^*5!x74 zV8^Nzb7td~18U*e@PDA5+RCav{gM+YMA=Fuw%mzoJvjs(wq-w8;fL|g4tCWYw+k-A zQ#e{!%Cg+S408Re0ak#E&oocRL8v=N$B~1{8rsi0E}qNO%n?HL2$X;e!R?W9L_)`^ zSgIej4(9*%tUs)NFdIIA$=M({p1J;YUA?~dd?}34{GyDcgS&U@6T);Ivr?=TdiohiE1P+d~0e?%;6wv^X46x{ZL7;4dcsBh(y?FJvjqUwZ2HSw8IvBq-riUy1vhx9M2h@h6&S>(_bVzF4Ng`goBvWXVSv6 z*_1K?Na-Nt7~LJI#7CVN-UmsTC;X;=BR6A!y%sJc9z2jaeIN4X7Au^AkVL(3*BNW3 zFx0TI=A~XzC?|pgSRb!|-k9J|_2sesD;;qm&TtGZJf9*+WUm0b;`8xXp05yEB$cU? zQvYP^8UbBJPgTIf@pE|=z#Yh_tzRM7-w$|Do{A1Qg{zI*x?e~%# zysCV&g!3Ryos%6x@K=FSd8X|Aa$|<9_5<~wP^r)E{bwb`JjPFJ!;t2-&ZuMa&Ar^) zvbQLYW{oSe6)OJDFpO%|bYrl69)GU*=>c<5&K9eNkT|wTR}I_I1Z|_m#ia_tB-3f( z56hfP##-dvs)8vc>wxW?Zqr>j{Q5K8@#!wkL!vY-(x+*CP2r(;yD&&67*ppf?x(McX@7j+X z!5?>+MTypb!ryb4ng&!(d3=6uy(_Q;D+dD5*$rnEUGR_+#hY7@d({ z34afztUFtdl8My0ru}NbEk&QJ3HwQ`I-VK|-XYMX_0RTwd91}rt13EpqgAZ({HKA< zSkm!pBktHNns^2_xFW%TC*DM7)^+W}``opBDC3ybIEvKO+S!Zv4!L!TlsI1)p;#_g zAU}hGD=?5ACsWj5wlp@+Qq09h zGo)g~GF024-kb#ASbCLBG>ut8YUa-iwv`L`hLAO>F5klI!~3_q;dha<91&fZEHRK$<{hwbJ6oV8r#4M;+lZFLs8g;7T3cK&@@PK z8@ufxI}q$_uF>I$p0?WzkUU5jK0b5Q(t<>>hj?~#WuSd#dvEilQTj6({oKG zgSvQA>GK$+uH?zL7%Ot(uD7PTcM+uSl)=;j&az)tuni5UO;gV)jjqbveSDxnoV=YY z)pXl=Vsm@Qxn$v5j-mIY7rPD4p=c1EtR7j|4dClmr_#5@QV2g8}R)%phUxI*Vu zhs=kNA^V2iXtfX0lBxcAwprjOzLK5zaB((m!^0>^YC3ENPQk#5z)D?!Hxd@*Irh06Hg`QgpA)2FPG~^S+S>a!-Jfy#v52evO|YE-p=}x*;Zk( zXKsO&qDV)NHF`1eQT6I$IfghSnTQmJ`^#HPIIg{1gtWAuxB7MT*7m~;0^tW8z3rbT zf;Gb+^B`#T|9pLcdiZ`Y4Oabi+YTG0bR_8p zc!2s$z>w##JE5=>C7F-b1kl}4Y-hvnfwZxiuXIzUolKj#jN9iv*3OGBYX#CiZaq0y zZw1i#dk6tS0uo|;caG6i^6C+>^o9GMCull}uEDfj$cgAL(L$I7acH)~1`-u=_&dExa56IWF791K zxtMF?aQ>%ev62wN(W91)l+1F$xKqj5`uK5eX-!YM@Z-da)nfVXMJ~ zPP0&@==bjye@v*;B_@1Fe!7AirWj|??=}HH{5)g@=;b8oL5cJS9G>uBe3*2_pVHDY zoFy0-qQ{)ejgMR!;YaV5K*qWA59-dD&sKS5gNw8zzHq;j~8F zgW^B2wbQTmuCG?8P1+>((h)ad;gRdg6y8m@&HDKsRW`Cy;{?aN9?>58b*KyafyHc7 zs$l1}a9dhdW?E85F%6;N#rhnOTFlcEXh(?vFxdmP#lkq|(zxpVzTKKI%3D~dU?hOQ zt6O0;KK)A%L{0n@rlAW=di?;Pbb9FU!UW&$xVx9h@<{?@>S64jq7})I&vI>$ce`b~ zR>p0c^G}HsTj$vL9lKRMQZbKzc% zEe!z|0$Eu%<0|04(s+J}AXoSCYzP!Mycg)R2j4@o3>_ao;EmgsO5=18}=Z z9Vg>#j<+8#QHS{E+j$ACpqL46=sB)OF`YXkt3}2#Ss-KQV=z=YRA=&HnqmnM`wI<&Z!ISOT4s+Dye!s$$E0lu(jlP*xL#O!<-iDG7`2NqHy zq-Z+EgNcD(6U8s1Gpf}jU&}yY7YAu5Vq5WC4UX*bx%R{0j`6ccaF zn4^QWkf~q%W<{oqO(zI)y?$Ff68HI$@Ck}IA3A}U;RGTZI^5e6@sFdCMhHfegJ^{J zh2DZJ?vt^}o9UpGnVZh+cY?Jhw<9t`4FNW9KTJC(A%?XADQFw_lR}^}M%P#~Zo6Q? z*!qou<*|BP3d)(anTy!=Y%Zum{Xx#DTR(PaJrjX@Ivhe+o=U1@Ue<>3Xlx}*U;S96 zMau!=%?{}ZQoI1E!qxHbZl2c&_+>RhaD<*T@dP>_|M|F`+{8&V1lmm`3JqQlgn5E$ z_iaOcEnzm|{*H^nN2qkTlzY}864!5R1e)DS`sAQe*G0_fRmc*V|Jg_rN|549@K_Ue zrZ&^fS4v`JU@lfJV^{6h#6z^{SbkAm8H*!S!0~1?>uO*02sW0$E7P7kyZTuNjddov z)Xp_1lq5Zh#Yl$H@DUifX|3!%lW9Lt?9g9MNDw0Uv;ijB;hQ@>G|PBkD1_|pHmbaX!0 znudLd2NG2%*DX9baS^u@;~O#G)A3fkx&boT*(`LJt7Z#u`c(S4v=_@*o{n|NtMX6~ z3id+-{e-QeAUg(^_)uUuz!q6GxmB?=>=w}{6egl#V z0Dtr&Q=G$K#ZjI1b*z}hk&~=H5RaIh8mSsQKTB6xo9pTY#g`Kaiez!C|NX8_T6xap zfeYu8!IhR7ryx{>CvPpr&Ws_61q=cKS)I(-*0F|i4WMuw=@F_(g)Z6#N~k*Nc$}gX z@KBhmw3#@Iyg;K-1tSv&wTNR}uiK>w=i93|i;xUQK)xer*-nXg*&i|Pj(&vR5_NbU z8&b66av()^m`BrCd~D#dCX}0+PO^((>@&LV%EOjEX36R9!gk@x%kzKVEr`!g5IBw38B!z+1m+k zr%tR~9~id{nr=dtiO93JFx&vT)?dJ;n@?{+KHs2feSnf>X0Ag1HNy&6(RqS}QQ0LD zDQ)2MnC)F$H54mr?NhW{95^L$odnl4S}X@HZi{e#h6@}9T!AVf-s%+}I#eE5hH*$2 ztniM-omc1G-Qo10IGEUfTsjJwzC&1?Mb0QUjpnKvaBCpc(|mNUqIO=aW<)x3%@m-0 zPcYB?Y+)enI2X`$JsXBFrc%QpDop8!`Y~DJ!zWJQ7?{x+_p1S~DAgy_G)zo>LVTmB zsWhqL&z~DV`qt1*sEhRnu-?g0mdR?arZ-d30jX*(|NAoG1&(Dsha&P(qC69WkfE3o zJ(PTY+VbzAuCcEpo{S40%h~k?MrQ74UZ4@_@-DaiEwb+b8P>WL%N22j62om665@@# z*b`v8c@lFb4;vT02TZ|kk~J#ofj_r=3b{fR!JVRZq(mr2i~m8+rPHLi-_0fJ%BM<} ze9U!`{pF(5K$Sq(mk@>i(|dZP2yb*|^TKa1iefg5R_C=3?^)}1LPoGdbnb(2Yi6lg zP$HJ-fq)4Hk*Jf+B|z2{a_Bjul_$0w;O0QDMdc)lYunfX``dpngoaHu*oUe*kb@N* z%KP*N`(_D#8k)RyvPZ=HR>_Jaj4!$vUx;A%##J-l?tfaOO#OLG*ox|cRgN~(6$^caELYGc8+uli1*O5j;Wfc>hU`ToL5%FDsGdmxu`rp zSD$BwZtTS%KJ-1-XV+tKD^F5iq4~?j%(kN*sI&g=Db2T2f##vtvK@XFxVqsHAH~l^|^5 z3W!R0IZBAv?V3Aeh}HMGK+LnH_9_CZOrICRP+Up7iZIlxky^ZOT0Px@9aA#s23Bg- zC#dw%GXc8T)(0TMs;{|Z_Sgg#_jJtnZ|?)r+k$fO{>+iaiF;iW zndz}P|4@PCW4E9-_O$yR%X;WtaqC0q!MqE(Xe``jBga=S3cKD;ri+r)KAKdm6LOl3 z6ha~Uywrr{4itM8Gx&)_VANT|X}h|xwzAMny7~PFT^J33t~&p1kmsoXmSCFrN;V>o z8)U!T+;iyFP63sB1x0zHw~~n4lJOGRBKmY+^FX0W`wm?v{PCgIBQNS#XN-Ua8e$N76u)I$b>PuilXJa=_Yt!) z&a=)EA?U-cv_vmpM6decwn^hzNecnDnI@B7>bIeG^mU(Nszmm)$7n7W@rHZb5} zl{+^gRq}7rF>LCVZNOs6{Hm zPs)TC@QEO~ZYpkA4*)Mlvz$6!AWFPXIo6jN@H0QcA!&}hgp&T?dXnuL24=@2_$@vl zL3XlQa6r-sSAcoLXK3%818g^v;QzG|(B4E(w(qqvP!aw8G~Z|~pvBxGsk{A32Sleg z&vbu-w;#NrRlCl3EfDx8Lc~p00~f7Rl+#W-d7B8Lok?ggcez_a)fVzvXVe;n+7WmUKJ0Mtbdit{qgTyiv z`@fnWYl&g5Zb2*ui(?SN`RB`9@QO4+$wD60S|o7#pMLfhFz#_8AnV6I02~=flBt_B zL$FSvOWR)#$(?^WBomwVd_d4JI4#xJ0mI1}VkQ3K<1->N)hhq~OnkB#`yy%f1@xz_ z?`Z>uz=v6DJSFqe$P4+pZ9_ai{TuKF@?E`2%L&jQ^T4MgEr~n0vJpA)JO^$z_!hW#GHpIdtC7CTs4{G*TG|Q6T65nBF zG6-ig=WlZ=-F=W`(WW~Ys30x2T$<+sor&q2`bFQ|85K^}iQY(VRZEU;agTthDzBl> zkCnl5M#{!gSCnXBhSw?bqh??$Ys~hvAT8s4M#<;E#yAfZ*sPQ8hD;tV#--xVZNyQz z?6Gy(ZUPZhEWHi5l;2GJo4v{4UF)i%@to^s9RZQRxC3lQ&mFG6I)}xLj~!=VWr*L| z`R$G#%jpO>6A$^uJKs$E-Rp1<1-Qf(Ek9AXk(7-lTHLUY=Q#=S_9VMh@D=7BJ|A0+R#Rd zXhcHts070JYU|!Wiq#pI$;}ul@}3feo^`6EQ9;8Ik4=YR0d+1l2`|wke~X=n>6FWs zwM=3+>k71Hoq-=~0EJl;8a1aD+Se(&W$#xlcCyWoDLTaa|E&i%K8>)gDQTjGW-8-e zd@>}&+A~7Cpa7xjn+0e-)c7bIP24KM-0cw(P=Oy~A>12ke~O+vt))h3iSm9Afy%w^ z6TTZo*@t0?ct5bfak}=s6NYj_B}TG!-LK*V(_DmXu8r|}^aWsdmBr%NX+E7rHcC*e zoyuvC$;rpvV3Zt4rPW3F{@na(2@KafO>fctY5ehOQSPDCqPW(hqkIkdDKX)iZ%CL; zWP_q>gbe+!MIhgOSyebp?3Op`F$r0pO|yY2QGW71qcjR=dd!0%Ea_atBt(omuCJ01 z#SeXAFj_mBxI=BweouZC;huqV_&^QzLM1UHIRxCyplMb+Qsge>pRFi59fqyMbfzx> z?5x7VA(&|TOuLI1hTx9(3Z(+#ejJRFN$fBE0Y$B?i^kRDX&L7Iq~dQ?<%i9?o@$bR z`?L<`gvf5ee?|>LfSLN@#|6Qu^OD%3>e{!XT3-H$V7HN?&_7}3DrRoJ< zg;!S>aH3W|O@)jStu9KEnuHBK!=(0~pkhR#;b`j-B$6ZjJ`kN*r2QH-p6K>c#K$;9 zFnw8uUqNP!d$FFU%kEt}=C?Q^8#>-|1E@fbq03!q<-ZK(RDol#@c}HbQ{1XyCI$dZ z$jac*asxZCv1f)4)HY)STEK(NCCGiXLDb*wziWz-XvM0;C8&I*_(mfAPJ=Xq5Pz00 zE5i=Mg5{X=n50+`c))#(g1O33f4@}4Pj=FIe(&M;>`tRyy|<-woNo8-*SL_$*5S^Y zh0%k;vmE7#!MLX;tNCiU2S5NP7jbz_Ndu8?b})RHZ8vm%fo*hrlh=47V(HrdUR!fA zP-y)sq2MXIVRgsuSIpclMjVZC9e$Zt%FMe!70Tt?l;hO|VHLHW?I_~_YdUkNf~tAJ zAIc~X&}e*UEns8x$8H^dw3o}Wg){v~HN@H$LL{ufL4Oz!-`QFL1Dj#>p3{=ngEA-? zd1JeDi564lUyjdD^7u41?*H7mCKx&KJnFWy3y_;N%)6Z8tsT(if6!O24iZS9a^pR;F#eogwpETNbxzP31 zh*<@&kbbtXS=<8|gQHSVK*#?}81w2jb9qes_~t9XqFsA&rTp1FnymHlCr$E6UCawG zLI_-x>`(+PWb?h=r$8w^(e?j5YwkmzPJ@v1=A*}mWu#%8@b{~8nGN}*K^V#P+l*WR z!!L9jJQt}f&E3KE?@>wGfcS=^RlzHlZGfQO$#xP-KzbUjJw8?~Y6P;fTYjO0MifK= zm{!U`3hmU*-a1s6fqWV&WBTY|wh?zAh@5I;P9)-v1E#!xP@1o0cFV0?q>X`M*Abon z7|9R(%}J)4+`x~l7h?P-h8h~`0OYp*fgCG`xCFrG*~Q~2YPaG>(bR1nEZ)vo8^=v- zUIl#EiIPMeeBbilNUrH~J2-3hAbno*<3?9az{A#tIQYFD$lm@xJLOKR15Gsk)gB)Qq9vRfn!5+y zWO3iLbbEJ#+Z*PBuVnx1oSa#*K^$gMgoOeR;*NZhsre-@_|d}p&=S-pR=2 z**8#vjP-DTgLvjJ@5(*ZK+&j;xwiGmoywu;PG&_<6qd3u2|1brF#Wi+u`3;S5Q)Xv zu8=J4H%o?X9ma+qg&@L7XhYf*POhwjaB~2NH=%~gl^-6n zo?;;K-`nEZbk1xp*dOEg!OM?w;@@DvRnN|-^$^|?cj#`@(t4Ms@i)_GN6}hPRCVr_ zAAQ`gR+IuWRW+WXbp6Dwv0w>l=hb}s9nzmsNEL;&%wHcKiH#hLH2jV-*(D|O_@f&o z!#e*)grFG5rTHNG*FWIdH+wa<%CauN*QBKwyyOa$UA=3CQpNE7iHp75`(gGS8)=mg zZDGX9^<|*k<%XqZC-V%@3|F|wp8$uvoh@&cjyVp8#JrPk3%N8p+yT=lLhDaV`?uL- zfUk$Yc3!v?k?b49caQI{xQvkw^EqD&eEPC4AX?J>^mlG{FPldBe)s9@4^cbwHUZU{ zS}ak>v_J@WfB}RI_Uxm+LG1Cz?8?*ZjYaIfj`_-+o;9UiG|X>X(5DKV_J_`m zqxDYTDC_sT(3>ni@cFen3n=D`W%*TBm_%{MR1EP%XQUs|3#w$x;)R3gCrDWFSenV| zqNYh|`xX=dC9tpXXbqc(fbw+x7Pcbnvp?X8I;vJ=q_YC8sTGnSZNe* z0<^91ijrFbbj2mb z^AXNl=Qkc1GOClso$)!W?>zLmu6cFp{QsF-HTfywZJ}WviKvLR{<$rB;1XW})cc)Y z&4wHIf4;EQ>+ku z`XwRDfi*Um^yGPu_mqLy?qNtFRS$ff3;HZ3N#FI z3+A+$q91PcI9wuQynS=+l0>y&(gk*B+~84g-Lyf3J(;y&`eT!Bcm8qB&|_;mj)E{| z{Cc|~`y6o322sW_u!2#*0XjFKt$K5X;IagK^3erkYuoZj;yxP}_UpEPTYCI1t%>M6 z#>#I7t8@1$Yos|`t94Z8T8#RwXZ+v42oILX2kz5(DBlYfe-rMld%d_5@Br*`=wI(@vy4l|7{V`*hsiRi`29%_hDpc#3pRBT+iF;n zXh;Kv?1Q#D9`zqFD;XA@a5&Cp!yq1HXBPBJPv2BsDr^~f44hN(0W@F%D(QS$bcCTQ z?Z6NWAJjif4Tsy=MHLJy7&beC$8#+P=5^x!EJa+7sMAPR`!fC_B}4$kU8xEB$Ck@8 z+GC1eLn10TgNsI^PASWf`y}dLp@%pVx;iX43GCA8O?1?{vFxwc($6(c@%YtW22F7= z+hf;*s_GGIi-0J4etQ{Rf4nk$YVdK1m)>KYTfR?MEeP|Qb(3F7LlfYI7=cgHlm!dZ z&5@dQ;9N;1C>587Ve3`_1?8n0$m~zdF2GPvux}dZIfepSl5QH7dz!`K!hFntzQ6IU zE-=DhDzVx+TlLpG_D2rRRF{^zA9dXi{C|T92;1V}rsU!QVE=>32#!G?^_g z)@+F1=aPB~7f5*pGX`s+hTKLI1;2I|S7}-ihM(AYKE(R%9{!}%auE_Il<-t#-V#NXfdtYJNS;Y zgElY<>jtF5SQ9*5=Vqo_@OHV$OcdU{=Yx~arSSL z;Sq*nv@K=lKPd|y^a5FW1DE>+L<(;xiD56Yc|4Dip|t{hL{K=gG2JXU2*z`(a!mM& zTQFY_V9>=%RNU0jTGZ*POhxQDL{3NDY+EpBdj`N2Z!$)*IEtvxs+qhxFr=|*?_?m< z5@1PhA#k-rQQJ>cs$}v2Nv&Fy>D(MIr>%rP$fw<5SVL`)g=DS}WC7T)HGu6pMm50e zWtUUHhPAB=P}lMD|4Ulq+Ll4Sg$vIcFxW-*=*IMD@2mPp5?HzjL3N+Pvz{~w#padTa&X8B0wV3*qUQ4RPxOvenT_LA|9 zfzRZ_#cP4ArXl}-;OKBhPIv8#U!HA3ey}P)hVWt1&~c0f@8&?=U1T|hhVz(v?;we3 z)LatI0-$m;8*{zwuRM1b718zeFw|YFR`lpc&WAH@ym@SziG&D@EVLY@z{(i}(FSUP zEa2d?N=^eHupb8J!4KwZ04At+SbEx!#4gq0gbvpvL-@imM4+}TunDSpAeR5pOFtIR z6|6=q_;>8oUuN9!3EiB6aHUEVuF&SVxLrj6T z6c6XXX15jIcWiNbWQ;8D_cYKMM&ePE2NTCf&>Ad1MA3kj#-@WpYhW}`foK~;3zjPx z4DZ0--AR)(SZUkjjkz@s5G&U6R|=ZdP$3=QENLBJ?s7zT{f9!vW!pZd)5hNv$9OUz zbZiYdq8tOxK@s#CtJ#|vGz|Z8dwz1(f|U1Iz?``35e6ZN6t12PY_-I9xFbN`s5xoW zeOZs9Tfe@1&g&8?@?iLw;$p>*`z=?aOK-+ceeZC=ffV;?HV$acw&V{FSL#9gpvb+LLi3Vg?=T%Ur z&SF}{Z8N=3urQL>I>_#z>MM@C0L?*p|EzX^Ig4%>*IGraq6NJB*d?u;+W&9?Dhn}l z_4p@-!eV60>dTXF9bkfx1^z%+wK8NCaocFJud0=`9X?8IV`YfSy^~6NmCZ@r!jEpa z?@748F_lC{LCm?iUmp$`1*U^ya(Q6~lLA5X<-V5u_pK+DJ~@MxUP$4$XxEUGL5wDQ z3(qslQz9K#xGO(&EMsL1e0EB0(bf{>WYSjfQc*>Wf3|C`pVQOlEeE51d*#(qFZm-M z2Y3SmP>gt(sL}~i71U&b$Fb=r{Z8Iq@1D^UP9$&RUcO|?GXhQDI}SrrSHmfO{&O%m z9Yu@sA{o95;}vjs+GwQ8et@aTzCtJ~3^(+~oQsU3mJLR&W4>`m`W8paovFukDiQ2xd}JILXBVA=RQ8bbR?U zL#xOtOK7-D2pNXrk!*skomF}nA!JCdNcY@5zwYi&KI@ZeQsT%`F?JSa0Vt9QNe0>4 zT=z!f-lhAQdK*69UHR0^NSrBi&K@rG*E`VdX}ic+C|kJ&(L38Wxc@EJE@}^na+Tum zeZz}v5o|Rfw;#{j#UVm6{u;Zgb{9MFGlC|Op+&Ab3ML0$9h|gM*FlKgqPtb^Ix%~^ zFLRu!t|6>9B`^G@z2)SM#zTl5dKrL823y8_vY&#Qf;buN< zbApS?LNvL!pWxiVP(w2k-%e#PQ1P^x9Y0+>rdZ*C2@yw(s4OdT43Jg)Y6OYm(Vf*G zOY%a1;{RntxgX#iW5YTFV}JenWp&{roJoBb-Oaf?Wx4+2qBFIDl*TYiukt#Sy9P6; zKs@&9oPg;U+#Yf&%5iO)fn)tbo0FG?tw*1c ztcJW0C?}*cIdoX8L}+unQi`AZ6OSJSu@WNE0xFqs0!vajs1E*JL(HCH1Lb-Y3m*iv z)j@HiHWmu;m(~CfJ_=qUW}gO8Q2j61z2AFIa0zs%jrfLEqQF1;(p-SJ6(?!KRn>6` zLMeytLh_d8FW()MbHEPpLNh`T3w8+9ZoyCp38sMs;3E;}Z5Sralukt|tFsR;T(`X3 z0cTIT^ZyDI{c{~}g{s}~wv-d8!Sf%i=#)Ibtv&!juLy9@^*k+JUOd}^bb0HT57TKh z>GQ<@%K}O|nWEftz$BHgAdfoIeL!y|U2}1)p6P3SxEKtmVpIhj?u!tj{!1nr5G0;` z)3Sb@h9kwzKZWgAf0AhzVh-hw7I>l?5abswAa|*Rb1a|KyOTj0UIT`ov zNP^&Zdd6=UFtsX1Ka5$m7sU6^F!R5a~!nJv0O&x0a+rkqX>T2`r6i_(Yc^XTd2H{i>p9DhobMg zbWIfTm~?!~*n#VI+o1z)|n^1(^HSW1hN_T&;CZWjnKA2~wFPL*wo)fxfxe!tDz|~Z zzlqQ5XH(#y=i?>rWK<^t-1Xfu5UF$#o*pJeIaddz!A0VpY*Z*dtPh&NaM0y?xi1!7 z=`VF$C)+#FDkc}}U;VS{^aU~Q;^`T)nfVsy@Iw0u1r{y|?Ku57GDdoL{zDFRyRX~r zH1d*;w_6w6}qMy{VSw-q#oyku6@+NH}a`jcu*K2>3-+6EK2L)mM@cw|>v&o5oz zD}MF#?aPLklreuo9$whOT9kt&q7cSaJi(^QXt@Q3PT#WZTt{GH z{r-|}0#!@!ivy4lg9ek)PO?HQQntdpx;{8iCoIpuhTXe*FAb!U4#5cVLxXIy&jpAo z$DM&1nzT<}U#xyiUO_y`66GvLP+^_TS2afNKR0x`%s<%s z9IKX)q9zYmOaxH|c-(@I+T~?my+PWXuN#LeM9$%TMM4Jf<6m;3l~Ql;i5Wi}8y%=f zb@e;mGR}8jW(MXucO6)AW-pP9S1501Z-%DA`_-Tsf2YWM?WJ-=E}trX8GxH}v|r<{ zw1wipNpNN}@fJ(8PY3gAd$m}iU$^|S-8lW%m{BZgMdAF%{!x`2wRC9Om+lo7dSja99*PO@diEjXRajt zYc0*4Op@g_ZUXQ3YVCG>IyS6XKA!I(+p#PX5_~keRd8VYh)XCDtNR$J<$;o-#CJS^ z_*%ZtgTS%2%-M_iYD3O#C=l$m!2pr;#sra7pjh(Df2ko@XbCVD;A3>QiD|AGd}SnT z>!xs_a^M>O#}#6|Cg2(bbI{AiF^}^s^J;e}lNV z2S;A#yK^OVKZxQ~jw0FIHGGMgv^k_1nanqr9KxrW)fr>hr0i>-jIGJtuHsrZs}Trh z1zXTKPPHAX#j+jMZ-FgNye*2wZ98|tvQdYeq*0Cehcd+=?y78(eaS-EnO8+ovbO$75w}O9B;o+J~+7jDh?hVsSqTMf)PX!6hHPPc~e(itSgt5 z>FE%dge=W6GsusvNkMaWi+tkS_%w9i)=+1y@#r6}pbj6$#&F@g*2IIycLw`o34bSk zQ29J)y)^!?uyqBx%s=<4a-JEwcHA*96;T@O3h#h! znF@`-EPamc7x*~@Z=>gpHr?H5I^|~s+Y$I34IIS7PBvW+wZ)*X`x4Pe|r<&g*?bEHP8Fs$IE5gStdt-z&sHrlGdk z?ygV7$G=HT3#lu|Huf7NWEmPMQCOL?z8Gj{d28lBPcXaN*S_RVzkNN}@P*3AXF)vu z&x)i0&4LINI2bMtAKXX&2m=CL2e!jX4SUoge+obC;bw7(1zg2~kfEimSkY*ex*Cb* zGJULtr$7SzRjFa=5Uyt{v8?O0|7bvR@q+1S?LiG|0Fk2ImR%7APvu|MT`Ke2CksGdiNdH4-?tn z_QL`nj^7Ul+l`*%dG;JLS#S5akHYLV?!_32D0T!hAV-kC$<;Py+77FlbubZp++-pw zcEX^v9ds4mfI;xm^qr7 z&#vsrbYy4&mbOF4!VLZ0)Z_lkor9q;5F(T*Z>T4_ttxMafP z*JOUYU^0Jw!a=anHInb5{`MwY-yY&un8xP^GY|Cv?06*PcN<9Wyg@(kYO3VLmcQ>` z#DMfEJBDwfxaNEz%_TZnDBU04La>%>H31HyjuKV$$tj83bqb^sfMj;rm4V_B-)Fev=vf_u{X*jdsbQBxjz5(fbzXI{h4!6tBUVNU-3djvGbn`T zS@_Zj%>JcaCqBR%djYhmMgXCHo&ep-!^L#oElQs+jed%Eo&k$*{++N2OPd7(BY^*U zk@EHWkqi~Ek=257>;*_l`S04$PES1d)`@UtDZqPP|AP@_%-7jZ#Bl2pR0e_3!xV|{w{g+V(;oqSo2if6)%@l8wHFKZ3w2ieWN$cz^TEbm@Gcq z7j{_*KiNm*pad`e=DYBc-LYY9zTlC_y4tVO7vCmM+`VzD!~a_{va&N1!m&j* zp&kwy9mmYbDrE1i#8DKPmDwpfGBP8wLn0%ybjZla%3iN`W#~DZFA+=CKTD^%jU=~j0pQ^M9>@Z<@B*^yRGAmhj=mc(xZd)e)cSNZlh}(NDi)1IPpFME_M!FV5v)1PI z6ow((OX8Gd7+0uE3H*ojg-ygFXLI6G4N;>|An(@Inc(y@zvjS@NY0z;sxkyciz8H7!ZR^59`bIBV-&qFa7v*Z%F^JVg} zD&>Pjes+)~i-N-9ypSf@GtO!z_k21Q$71DKIHk#x62wn1(CaZBMEpEu`BZ4SQ#NzS zF)uNa8$F(0$*V0`wXoo4OSbkYRq~b5X0g>h&(XrG@Pi#P!%r~;s;=9yms$2|tJZKi zJ;UZ_E8r^5n2YE?d2Mz|yV~(*Z!sveM)307lG@(ttc8kOl}QyY!54oF^?v%6r{1=* zy*4emvxfO~$d&0}u)unY5K6>;z0eIHBR&e=IEa}>%S!pW#8U?QhQvzm31 zB#_RfPJSipH|}%cv?hLh2YHvksCX9cY%WH_h{v+3!0Il&D~;)=rPzOWTYZ6FM_rZf z6dzGi?efSs=fA2FAhSrw>&wQ&jn}Mfg{eaI>ZR@~8sYS)ZqWj=CgT4dOy&SF=gCkM zw%Q0VDRSxMN&;@~AN46PCr1wK0=o5eWRAyx^$B;mC(eLQ#}u6B%pq2gmPkOR3AW`r zRtl05gvq&il)#Ef;{`vp6A8GH&d$HUa2#W@Kcb2f8s?C(kpz2_gEHQ)kSZ9zY!30- z1r;h({(9fyGEIN4zPJ{?+Kiq1^I7P`E8p*Kn1oW2i@X6jYfam$e%RodU%l?hwz9hd zmE0bOCg#nA&2Y-&zkeUsFWz%EOpW>GKLZaY+ql?t&~f=!1Y#2Yee2M@$x)AwCzj+@ zy_ieLPhl~N<<@6W75Ml6{`n&ZZ%V5F{yN_u%VY-?p&cNrV+jEF^;0Is>d$$u+s_4d zl(S>91Wn5LkkOFHeJIc94unVtnhLn+En0|{w0$b=W`(>{X?ZnX^9)cr)bv2`V9Yaa zbiOS-k~a{2=)48fohOHKO`mGUC0v4F-bX_J_X+l`O6<~;48ub2$DD;mvnkBHRh`73)0HD zs|v2)-*4@KWp&Oio*P|GUa0QC0BAN9*dpAJGzvM>I4t#}iam>ldyiit7oQj!$#X&h zrUdngLi@TEU05-KDgdk7imWx{Q?68Fa$Zrb*@Kt&>4jU`NaoRGKYX&4;|Ph(m!U>b)?u_03d%vqzPx#Z?o)==rn^C>$>^ znZ))BGKiS7x?HM&({>|0hxh?wKfDwYjhIJK?<1Afkhe9<0cbr(A4IR$2-@k1nomlH zd&T3yyDguv@+!x(Ur{xjo>skK3&^G0+^g4bQI1duy0M3&Fx(VoR03~iM;|NtglQgZ zXB^5bfXvlzFm#X<5A*$aOam6n#cJKb3D7oEN>cWaN$ecRXHf`vN;JcZj{72rGvL-A z14h=WJBC7POw{~gz-b{gD(sL;)^nDc#nPH<@x_&20?4mie{qbI3iU)DdMme8sG6%c zwln*Gq6+cz*Itu}VN{ogUnEn}BiReAK<*p<{+bs@=JY?Mb(`j2zIa5e;vGo)K0@XV zWecQn?#UK;9M7=4lPjuhn+W2o2ymY%)q#7es0R{yrI%Eebmq$e%)tSv9)@Hd%=l8P zaFSmL-rEudhF-SQdPkR5*YYirk|__7Q7ii(t1n=4&q}~Q$i%GpnZVrNJyVPs-ypJf z1d2hu&W`NoD{Jar3`!Ak+t$o-B z2E_BG;CQoyK!XRI%sA4xj&QtB0`UTc*}QqEHbR z-p~34rk}dLKT6!(JxLY3e6JWpwqJ}<<1sKCQxunn_|TMKh2&k!hv;TFV||Za%K!`C z0M0;qSP3!$n}BNEC=54Xnk<3h)e^jBC0HAf%XJYhru?S`*td#HC+^E^cDJTau_#&3 z4a3ARGKOeT6w=9lN|Zh@HA)ZO`6>2P#f8*gqQ`@a2s0O87VdUeb%~}!{U)3LEPh2! zD~3M*iv(70X0(5k_M0r^5H@i}u+k`TNSOY&qVma|U-t=b1CGb4 zVWC=>OGrTEON+Gya!n_ZDb7(&+K$H;>nPh_xN|*S@3c4&_nsTId-=%VnOuh42*Lii zR?{)btTm`dO)ltvUB1NKPs&Nx+l#ZrkFg6Z(dpsXgWiB|Dwx1^e zb{%t9up`yo^4sI6rR-0Yc}wHYHH(cp!K?8`b&2V6Am{x}d-l)U*{|Yejijg$V5CQ6 zQwlXZ`tB2nW*z^uXl-)hW{Lm+oGLg%MPuYw)wcj(ZvtwI{T0^6&EpUjLBYG~4Cmzw z3P&NEec0 zBY5;RRP!S`cm8b57@}(fVcJ1?G^9;W8JXGdYY1LVF+U}#8tqcj!ax8(I9fIMa3LC&zasEelAlkYypcv-W}KHSnd{H;R(IxU86l4e>t z#X8?6_Di^*Xpt^0t7!2#*pwXfz3_<|-;dpkViMNQCBtY8-RV~tpk;a)i&s`Jy(J)& zS)!-ckuJt|rh>QMRNC!xqkPr(??G5gzOYmL8k(!|oVR*g)a$%D(ky~t>(U}Kp-Xnj zJ!5`<`+`DDlD{c4*P?|molNxh#_^&Os@~uq$3!7opl%1H82K)J>6rc@hw9>YPzdQc ziEG^^;4i-xQF$fYrK%}Mezk5{O3iNR7oR8fQ zT&`4bI;8ouTJtG-;W!%9lZUJ_;sya9I;84%zF0#R$cjRki*xl|#PKdl;;#j*KQRRC*B|cI z3%u>lKSQ9zjS?pI;K1sv;gQ!l-T>zWLz{NiDmo}xc09W-1auiIYst(!f6E7~-CZF<5A=!=$T}si zc4i5ZNm>RW=JciiU<^%Mm=?(k*Af-JP+A2Qz7yxb@0jYkyI2_k6kXA5;M{epX>_g? z2=&MT>-G57(*a!svq-b_%8zpeam)dx%#kQzIB~oMYuXRe#BDX?v!SFRzwT77Keh?J z1Vh$iClmGs%Q%K_t-pKSxFvtj`tjmGT+139jFfVVWqNy*2{eCR?496mP-4Tq%$$C5 z{Xy7!bVZ~`T_i8*Vl?*2_vsxtMOa6*Jj6Vy=~GB6Y{t8n${4dWX!Bm0l68b7=XVe1 z({Xn1Fyvo~O;ehGhBCGhC{|Crbmb?4047%a0yY4Lh`Wv$=F4lZJB)NfdT6BvaleGZ zrjjpouNWgeRe=*6b!%x$&9r+;kO}1#%9J{L!JChsA@{v9H793k;}tSSB4liGfnA*F z$vI?q_Eq_Zhemq>*sRk?*T-b_{pQ7xCv#Pk(NTBlzdXXDdx=glvXfs?;fVvFI}A|q z*LG*#VZPj3)*>sE-}-*fOZe&g;P=q%U;F&q!#YOOIu$qpvEoLe^8?nUlV336zn@x1 zKj@=g;5?&!2d7rDZ!|uS3LLv;LCy0nJ-bLpZ{~X5`k(p_jp@9y%PTdq{S3F+ZpCDW zi)w}D$clvvpMVwP(RaWb#JnAxc4-{Nq!`W)9xOPEO0|?MXwdHV7+EfuJgA zA$J#vsSTcf1M+OPB|TjQg>YREW;PmyCvUi^ptiGf-pbbllpF3qUI-^P!L2G<_M1$+UBnv_VDroCaAdsbijt?!I4-5ZcXZ8>-wy|#kos!{ml z?=nS2R18bd>6Unp1onO2=y?1YdoO#0Y!QD|b(eE76N|>1#W~P=zP9#f&x<^@c-ixE zW*-6Ib1UBWjzsj0Jf6WevPr5uNfN)QV*=+>%(@r$>|fqA2W@q9;!AshnaX(IvpPu*$D1ty|DNS7OI7I1BlG<)G z$2(SOo|H+B?$U^)0NvL)*0zSu*mB6#|z2t^_Lx2vEMb$Io( zN3p$Yqfc8-h|*0PG|f5+`lHTQS>_Nb?hlwf=FvUi7m}Z^Lac;iu#&;raV|IdBka@C zPWHOZ@bI=0^tc3oc}WmR*wEDNiuCOBdsf$PkyWWrT{em&LsdI%hMD*Z8LH;ML%Us( zU(>0D);vfp5XPbk~84gJ$1;`L8pO7ui5j3 z@|$iw?&mFQBx3v-B>cR$MW07`|93`N zSp`s{W9E7O>lSO3hwgQ7=e@&uD~y=rxyI#Z^-Hl8(f)%s^8}))vnKs&4Rp?1a{9*p z8w+Pbc#Bn7K0^Uw6;TBmwn2lRTJx7?!?(px_~)mpsMU?FlSno-&s^7;*5Y{r$}Rda zZTO-*lLDajzIu-e9b}?9zyVRxF%K%bLLYWhQP-o5lK{g%wBU|6RDIvHL;W z!cK8`#{R-YiSNpUbgd_N$tIR(%d{|A;r1l2`zzVA1PvVu=vpW6b5r%lp_wTE2WNn( z;?}2WpQy%0i!pLWgH$$RDQGDG57r|ubK9q9ai=DJM3<{~E{N;RIw6)kO*So&%&2m}}{gU^H+c_+XRrHzEmzv;M@$-gGlw)^+3 zF1z`Bgp@#sv&ebF>7+m024vspa?SX@u)%z`zX;(-Bg#PibEQ!Da|~Z+$K*g~hz^kY z`Exj8*{KA*$n2mquVGIO~vt+t}N{h4XE z;Dn33`x4;CV?1Gnr5Qi7KUT6X{VgkclkaX^9&rIT0sAOp6z7-r)hJx{WJJ2a`$@kI#moH{hB_1`#9-NswYX(eBm8=F@Du4vG)+VrmC|29u-n2u5c_ zxQpTfw)fWJZG@l#WW?g0OTv><_SDR17AfI{`ojY^Hjo*7d2TCl1*tn-YkLpA0uo?l zbe=PJ83E>3ZVd!Vw+5b+J~*L*;R}0D&-prVT!{J{L9XGJ?D%GW$(qpMf3M4qCV@6o z09(LE_YbRNe!&jy*rcZ23a4x73>wt(?PHISfUb)8<)amVmaexO!J?RV3wQH1tTJ5cxC z%l@gbWZObO`0${Xg@Bc9t=9+F#{F5{KXAI44#31Id4TQn(VY$jaICe$v1a*H`iuzA zRwfRus+8zoTHA1vrJ0bzG*g+tS*#xI1E{pN#i#A0-Tk;sTtL7?bLdigx?#5H(nsSr zk>xuKuiPAOm%y3RuYQVAa0@4Tl4?ZMJ_oN5Q}NOBcw$8*j$E!c>-J!1kA5)KRha*(4C6d@RY$6yB~+A%o}D>VOv6v&rZMCx z3yvl+UZ>JFIFlX`e{aw{pwO|?F&DXLzRd&uKDUzo$GRjuRP(0_!v6VKIri_%8kgyE zJ^zEUZ9skp?G4T!mt3C%leglfFVe^>Pkt9j$QEV}lh23e+B-8|W z@N=Vk=k5g@J)xJ&-MxP&3}iCYR@c@iqZ$t-hr9^>3pR_j~c>yQKViNZr?Gbr7(@xqP1EV$+L8*2FVBeTy3kgX%^+iH zf|Kqv_~>S$uMI!`cd!S`rkEUzg8UqL&;yMT;l(K%Ci(^B>TMO&NGKo*z0fK3V&V3e4*@Ip0TcR z77U=Wgt&~75i*5YHUa&(gs5+3*dJDQGAOSVEa zXp<)0MG1wno#&0)5R5UY6H^FElmF0FxS1yRsO{{4ghS}by)zE!dg~fT6JgeXEM&!< zJ87sg?T3ytLH!?k^EQbJ`3e0b5es%?3pq}?=TwD%dm6J1sShfkU}yp*56f|M-W)>E z!lOWUIUrCYqWu6h_l0T^v;GH&!3y+itue55is}cZ4(cg=(BX| zA-z0_j0WxE^~iq9Jjvam7mgIq)lC;Nix>Y`^9sG;KrA zBmdr=enE9#kK?7VHHZrf>~j)g2!r82<2^+d^*sO@R8g>N!b>d*k98tR(3nQVn@>~SuB8~hi~1nu z`7LU~Klz^FSE9xYkx$lWeB^^VrE7VlOzm3GbKUD$)tsV)1%JBhgDUfec5=EMYbzrH zVMES?th@N?jQ~xVx+#NCixUbTBQ|MG2yco%|HBdv%8?w~r4s`UDysdfTI0q6o^TL+OhH521%okT44owR`$dzM6Ukja=Ltq#-c z@46pv78CeX*k^xkG#ZnxqntE7MAcP3e!XKws8YkxF!>f)0ivFA1O!9Ki;*uzqD+sO z1{qFQGE%*Wf*OW!XcUJMHj{8`6hve4_Ci$QQZac|!QXNF2pJE@2*Y?eNRYyz+$`F_ zIU68XUB(V#pHp!7#HeP`uzxU9oG)Lj7;PmZ^Q3P&uAQ*|1vG@M*Q<+Ucw;*758Q zhSzxdPv~{LGpmicX!@T}AY@nW(xb*(_woe*JC`Usht6j{h~deb5LD*-v-~nOCZ+|O zMv;s|OK?NDp%M4ukW2l(6$v-R-FOMl9S!un@|_<5h6MS-B&#Nfhi?K&_B>W^7~cOz z$w5=vi1G6u-s=kEv#rRMc#Fkh$CF+J-r@|RR@~YFfTIbSVB})8c45e}7_+_Plo!?RoI#@F*gm# zn~@r}iQh_}E)b0W`pq*HbZSvdW1Izg(H)%Coeh<4$WP5;LOsVi)EJq2lc4lDqS@Md z-owfm`QJTCznpIQdE?2ul=+TumX&W*JM!EJ)@iyaN^z7Fh0UBve&gV3Vvt|Zuq=pW zM<-sW+WuI9#MTjzIdzTT*JTF3%`~EPW5O7f**7aBst8O{M<~_uD@=|WIaupJZ zMgeJ6E~)1?xA!;4m5?`C?1%@Xrw>q4UG~kSQBEp*cfyWjMpx1Xo+TAW(C=$i&=O6$ zcV3g>_L2DsMTb8Alzt?^C>-?-_|(im;MPi!et~vq2T)!v5C>#s`eEFcVU$?Z&sC6q zl~33%B?tIn%JH{a5PDJMEkt3?d*q&;_gp(zUwy8RLtVr;|>Fo>5as(T(``Fr27z^zq*TiZzLp+U*GHW4L~ z#A@<$u*l--*R}7N2k`7%R{h26xYs7QGu)H~-pSj0DT~nfpZX1};S&SGI}#w3lN7;V z1qVlTk#1HRIv9t5FWeDq-bR9j=x#dU1K11UA9kPQSkJ)@ar4#g0Nd#p{II z^&ivZq;RR`{y(#1yVtfSw?VE@hF<%Ngt4&Sk6#6aXu%5VGR(V-zzN` z2e&zUFeIk5MRDfm+2~vO_0HXi>W&hA%V(g1S0;#rY-=t^s#rI`E#WwB0mF2ZVI-0O zGxkjQxAV0zQOG>-<`Vyz?hKBZ08ojyx!r(qyuDQmtx3#@f9@%!Q(2C-ff%KFHCcim z95~VyB3T`5_?yflc4r(SD)^S!({;Ae-XD>ghvAIx^kwzLGO3$pd%kJb(4@V<@Lm~7 z^<~3);wP~i+jRXOt`y%H#K_T)UYb!)w_#&xo{I-s?i38BcaUp?{XVI`b&D(C!q?7ogPpOJAb*iSz?CIwsv|O5u2u{Z+?q| zE?FrX_PL&DKZSWFSgUZq!HQB!q)SsJ#2aKf;UzsP&x|h?diq z0(noG{C(rg{5hE#9v$kg1vGjL*L$2+IV*qZ`fnfs8bP?ro}->9&15i>eEanS!ZA9f zY3={C0HGXXLpd1Hh9mi;OAxEz<{wI0%kk5%kuuBsxrXv_72*QgrVY_l%7zH+8Qc_Y zfu&5?8HAB%a_3yQ^xSG|nNad*G5^);$h-9H!!ys)ohDpV#1Sn?!NRdd`m$GI4>8`p zDVPeS>%-?4Bg%po4jpY-f_axOwM+%hU-|wrbyw0*_I22kAsnVM<ni%ZyG{#;ltN8o>DwJVlq z_gd|p6OVJqCA~%rq0ACe4jb(pe@gTi^-w2l)EeSOHTik+Y9Yb+3{7CyNlM( zYM(?gVSd^>YUS}*lbqfAsS}dFFUY$GaEDJ@lr8SJy}F$(()%l|y^C0yLX-@3AcBZ+ zsu*tV`73McbvRp|=)RV5F#~ENVPvpRiFIGnb>}luk5NPNYNB`U9Fdy#)2XY#Iw&?ZWhR=AZCNh=K^z1!e9A!7Ozaj6kejBEv#6kk;o6w#+f6X@CP zeKWA_VIBMhpqwu;%My;*?n(N%Yk$F7nrEX8pkr$e(xP@Qq3Lbu``4VO}oARtNt5nPh9G=C)KIL0*-+h!z3+I!dSlTHulK5 z+{Pf%X!I|4W2O9SYyQ@#&zTyik5866*aH@>&3J8eLuM_Lk`xHx{&~4skHFxCU-0xa zAINu=^@*JQGa$^g+*&|reU%gVk6D@#)wL+hS@i96Lb9qQ`x z5WTm{kaQPQ@6r3=ftg8$O6SWmj?PiQJ>~>s=+=P}uI+fNGQ3y=)|AOEAK^xfNitTR zM_8sI$pjT@Lq6CoCq-Nw%O&*Q#+ z8(Zg+j}1!OZxZ7#Ghf&YOf>FYs_wj!oZNv?R-Aj_M~&Lu2d4ei{@&EDL5Yy*&Q-nlnLTdYADi}1 z9W%t5Tk<^*>+b`B^Na7Kly0;IgDnWJbK zk2uZ5_%Shc54T25l5kolVIvrC_0`up#g*)C0^;5{dF3g`Qx4v_)c#FKgE{DWnuov1 z7q{a&;RE$io0pAWs-ycc^qGHJf7qBIjuoQ=5k^Kbm<8ofyV5*$8gY$*_(>lGEpemH;Q zlH4kYJ^G|CcLJ!*GFoUCp^<336$ECoM}41zJNHo6*yIXDsDg8ZQnanGb2mRMB8mlV zwNa1!OX)%B``8o6j#@e>gcQLNL+M(2s^{+dznsV?Y)USVifLt=O`xybr#_vs4$LAS@i*kwze zD{E{y!n2R4@O(?tsOR{8{NcnCLFOPpX&guMA$39Qaytm}nP4_Mjo#bNY>3b3yss3~r0h9u#|4fy+h}79)F})kn7Bv$jsaZpgt*$QPVJ@3JyJn-cJis)Z*=3ctq#lSxc1;5INjpl zbZcy9WMtlc?0%jngNl)K_`Qahsl0A$One>qE&Ef4V#97S_x2|!2$s*Oa$@y37aFf% zoo^74FEvS!>s`JRjt_Mg8@slVnMixxd1#GY+the)C%;pD9M?Y|)*T`irlryqZk@L! zb$7M!a4Y7JNfjl(6`WOKc4lxLu%ANpC5FHKX^>piaJN=aeooItf2d&ofI^o@XJ^~i z$Zt2U@!yZljAZeov)SSZ7T2nnJIQ$rb%&bdIWx)8qqrd68?Jp?QZ4z7&%Zvge2{yV zd?Z)z$P1YGg3dkjI^4D|{R)e#7=KutlZ$rer_I2)!qm9@ptD3mzR{dvvx3ihyxU}_ zoDEG}MkagRPqkN??{yv6Dh_k5Z>RknB3@sNzQ$6#@)cVcWzb#auNb>QL6`eWwhB0TI5b6welxXX>*?yUBUVe|Xf_svB49EcH5gh-@+Cp&GzGYUKKfyFxEcPAb;CK;?>t zz0}QGjXW8f02;b@|C6rD=J^oaA3*>n;*o+iBKt*L15Bob7fE6_&bZG*8}?|NKZ4}% zf;I{2Ie9rpQFiUx(eO_}NbxyVrzu>`t;pygdoX1{!by%u0+tbJONFr+IQ;%v09|q& z_mP&PTtCSEW!77=w3oBK>cyP>Q6HCj~N>)|M( z%rim-(vI)NNGOW9&}f(UX~%ZM>TKPqCsw0pTUExe^xkSXt zH1ek7j0t*INS_tW_TGIk;^K}#QLXq%-2<3LpkQ#;(kP^YOHN@Pj2VMC#0+e36@N~g z5Y-FI`6GMsV4`^`-6rjN_zwKB(mCJ-@Ae!S*!Dog+n>2HyMd*BW004fBicl09fwjLs4ulq2GMSgu>*8BA zzT4E*LD}EYF2eh=i#|IxSv5bk?2j72#Q&XcR+i~+X~GMqu_`yB2;u+`E?ZGYJE#Fd z1QCqU8^5H@PFmook)5!L&fzrWEV#jzC4%5XoQ1-r!4{1|1T zOEC#wjSIy0H{m6CwE>}$mnL@X0uX(Gx z(KMnut0^c`^gQy??9n>m-2(B3h-H$5LLUHbDdkPOnbFVeKfEk+9-caVfKMj3eEO%| zzTol=QF6*65guYg%6#{Kl9r2#B*o^Z+rWLU9vIFuZCZKGHFiynjXsB$FFt^E$T|PT z8*_U(yQ1!|-4tJoI4>;F^_}h@_{r{ELnmLnW^T<^0q&ill0;pKwIY{lgBze}1&djt zy!7x%Qm59;0tsO|1O@k{$)J*2&^z-X@PS*Ni5tG1=nKPj$I~q2RqsDui6N@vFdfs= zE~Co}J*{v$($ddV@MZw&4?n@3_cpWm*rHmV0w0B;>L@K+5{OnTn(GnHc#DSD1v3~2SDdyMrM4MzdS zw}myqsEc;EZ`B9^4wZFf$41UNenQiPL*@L{L-56Z(eB;=F~>!>ccga_b47_2IVV*p zT>(e^ttXpc83;#kEd<6jb!(w7$Fq+t8>t-=U{wp{IU&~@{DGn%bNtle;MiGWRaP?? z=Vl2I8K3W%M`emG#ehXs#$&c${59-ZzXs`63BD`CBY-VT))ClSln&RF27fUIudCFUp5gS+pcoz%ALCR1< zcf#7}8>rYBbYwlAL?E#Z2ZD4CvHA3jh6(7eh$O(}A;|b|Ckhe#>U{nvFzgDjX5lAs z{kP9EGFFFKib8^!62djWKmEw(C#g_312=2NAF(tn$*Tnj)aPi_{rpEsIn=6;HuAYO z-O=N+=2P~CFQmPI#x8jdG5m!;8pD8E%SdTM&D#%|X=|Mr>&PP478cZ4 zmo1dGOibeY<5h9ouHT2RMb&*dJ)~_>elv2vsz)g{Bu5)0>_f7HlFbxHyUXn5j42aM zbFaonbAd?gGWI&5A)s_Oe6VjOe!KKA5_uvl7bN`i_de}p-N7<+yA_b>2g0&Jg~PHz zyz#!`8aoG|9wA4h`Dtg{Axm!p&Hr;5R8eK0$T5-WVG6tnz|RWX`+-mN5u?ob;lbwQ zYU!jcC6nmclP1zK+ytRQ=UM&tw^C09)KMiEYB4=YihE`{BxWWoJpIRh4iwq)IE;-c zxy-xe2U@RYbJE|_$l!5Sk>51Jq9LpC8O?FY53gvV5eXCg)8`%0tLD$Rel7g*u|8#}hBt;|YyJ!4^GT2Y7SbVbIZK-vEAI=X3? z*0nt?-AUUrBIDq9j++^2Y4I<6=uuyGMQiZZMrdb|T2jH0t*Xn@&$o>s_@+%=Cy(cIcnv z#o9J%Gz?HH+)wMK-HoxOyY5`K?m$u}a3a&F5=hH}Rqgaic9Pw57Pm|h+K$Pj{a$<} zAf{5^NNzdmYDj1Uyqd1-9;$XWoVFeStOEBq&GM72Uo#!Y|3m>Oh<>qo8*5G?)o;vh z@2PFX3&D6gtI~PXu}OyGy1W?47lJ6uLdX#3N5(^x)beuD)ZNabA)_~{GU{xZKXKg^ z;N8LC!73wUr?;-w^7mK(MI_-KmEwKITvI_0v5zfmQ*xmB8Q-b?>o3T+D$B?w;~S1d z4RsdE{`BH1u3(5fw^1 z|3>*y;AmQs-uO=cru^=!p^aOEy#1cDAEkmuln}qd=XGnpve9dtVdJ36W*luIy^7!n z-u~7~r(w~$kx}@?Z)o!GO4cY8XyzYa#=Y-3$mi{g?{1Smi<>SGGwyKrs3)dq*!cYU@#OoJ=T4GQpQ=3HE&`{Q zY5=8^7Yf?gv0a9zEGl?762I1*@JM8@)W<1l1 z^-w*;N3cgqjb#ncPxjNCCDb&9n|lwjtJs9quX2tx`ot}n{Mvkoubh2`#Jx0^rem$q zRqr*d`)-0l{m-)aIl8HpqitEJqF+Et{)4K~Jla<52N3z|^gg!q`?)$;1F( zj-xEH)2EjSfCPn-E!GEi3jOxa16D1?73{<~Bw0hdJPcc!E1?=7eD_?iVdC|=+U1?W z69wRG4l9T5_;mL|?s<%`2pA4swF8#Q4F}lNwfWG#@&4JS7I_2Oe8wN{{ba!~iwMQU z8#G?vFBj5(1xH7-WVfM;IEVkSp1wOb(7&inw{^wBR~$X!4~zpdo{G%B_ldmoaI!!H z)493P{D5dsEWrF(WAlYuU8pZ)h6N1nP1l!@eFkz<1h>xX3*#vgy_rW;?KQJZNEgM* zx+H9T7(k5$3$HR$tF)xt!r>J_OU;dvYvyxtU&V;ceWb{_EtXt4H4EP0q ze}5MQ56*nm$&XM``SN3W6Kg7ooQfWvLqEm|7)3Rwn;%KoD#sO^>nxtVc!0Wr@)*krP9{qED7<^_bJIuk-jPm*uam0Mu#vD|o0+^% z&W#(9-@4II9RhJ5zXH&hmNNH2jeLpDvOh8pu(iT~fZiRKkW+;Pxiuyl$`r@gL2&{> zOuox<-TL#7b;BzJHm@y?=FJU2cze(EQiw>^fdGU}&T7P=08P(~yxlh)5+(cjDST7?UQ|Z(0G;KdL;=GuIBCp>do%emA7Wi<+&Nw~dFRU( z2DS5W25#FPcv%EEMG(Vjl>iDDdbMr!9?k#rp*OF~__{VMy7(OKdw|9i&GS5$r z_f`<$tfQh8N74k*`FtR`LA?eR6^{g8E08Y8h@erpLtf01IP#Egzb=YVsF=$(`Y+iJy^xSUeUw3;H`+F@A<>{OyQNrTbazQa_G>SvstWP3u+F6IyvN-7 z4-pB_3(%?J|CKYXOhok8F~Z$2m3R#j=JS+7YFU5$$G0nVUe}5jtoLf-`xb_YHdRMs zxl~8hI4A_76=e&gS3fMTf0BzxRPcWsX3^)9fyL%O?2_C9T^XDI`W!vviP2~1t>fSD z4cxYmvS^8<#}6zFmP|1|$d87{v7#jKD`r<{3ij{;Kj+@v9jM?OfG{hj$Now+=)93gYsj;bH9tZAyaw(YAl?-Dacg?h=QI!q#)-<}4H- zk~TrpDp60+N#YD=6?8=W{rix(3cGLzQ|#2a+CP0ROiC%DBvjT@RPdoO+vUmPJY@h2 z6d!=4vr(D2Is$IspM`oI;y#QZJsT0O4S^q@;uR?FCJyf-c6rxHm^rU%RQ4eac^v!; z%WX=y=#ax2Ih8n+jHTrtXGZPi$P#BQD}YW7NHrJ9PV=r5*%Q<0X^eq80Y3w!JTJwP|pef!@f|Y zo?H&X?AMnfycZiIxuWmK6cLk?2!P#Ekrz#72{Zp1O)lIF`$Bs@3|>p75yd@M5^R-_ zRfOCUxy9ZO-d_r^u^HP#ZUHh><(CceGvc@7cT%^_U%RcoKNT&5#mMx)+F$#x~ve|a~1&gUg}-UK-R|9l|y zVW|e2;~cUO{26Ze%4@!Op+lgF(dR3@fpfY3VxQ-8$ne#-gUM6K%QG+U8$E~`Zb#MZ zO&g_iOVS~OU)?>l6E5fJsdQK%xBXeg)iplE@9sJ_@>GoLO!jzi{4<@n3AlLwNFAkIj z06?(hdo6YzW-*W>^RayqWi=p{D^5i>quPjufhlJ}j7~@djt~SNU*~+B zPIiU}8d4P>z=@FA9{(tZ1T!^+KhlV>v+qcCrq5eIO(l#3$C4oiU9 ztXu8cK`4dQsQBVbSbbkmYc3BLRuMVss3}kx^HsGJ7l+Okm{yA`f_#xM-uq>;HN0YT zJR_v=SB*%R+^^-QfP7{{FanI*i3@2&Q)cxzp*XNjQagQ7;W9+aiiR?GMgW+-6KV7_A@h zL+Oj-C(m%wjW{4ySy6vZ`J#jWv;ea3Kr7;N7kFbL)o@(z?1UG zC`(M*L`pH1He1LprD!l?7m4g^_H5ayC>cr#W1EISvI}KtA=&p`k!_U9zJ2Gdr|18E z-*^AspZBddGxvSn*K(f6d7Q^l0zAShTBBnDqCAA?3F{bKH-reE{bc`6YdhdGU5D`M zI-=f($*3ip`+rcudo zAX7DnV74R=@~bBTx=JS){21v8;53RN{JXu^XU#X9N1qC@Bhx|*4SiyqrYu<~O9?LFZ`qUp^@4qRh*aYj zdhO1%OOMRP9w2G!br7rGg@7hPi2`ErLCjM8|6H~b-3N{JG@Qx*(MM9QCdoRJk?MW^ z*FsRa5a>e>HdUSev$|~#*C`4LGO%15JJ&1QS7^%#nuweT$FBSOccj-ek?Vz%Vsdbo zHA4mHCsYF`YfFE@3EIix(&^M@e==r2gVuxVP@vq6botJ3j5W){bLK|LL>f@r6|EtPi7ro-pTO%NZWKRm*~TrL2m*$TfLr+kng*#FEw2+<$@lW^5Gl*Dg3=1@-kNk_XaGvV`l zIEZB{_i;B<6ewWhf^LJCU-r~Aw~Z?qS{E5e&_W8f{~TV#C-SxLT7Tr5STx8Hm_j2m zba?A;KnH0x^sTaj%LgkWVVQ@}BZ_c=r-e>7o~Sr^e#+2+FC#uJJJ+KpeR#u)@O8)> zZh;z1ZC^ZKQ^Vv5Gy8CCxUa)s&Q{M9hPF_&@y zfTfMB4sH5%17>FvbTaMdi^o5CKX&d(3;Dhy~ z@}vW=xXCdJA^WS(_AKTJjXxQ0bka(6|4Smq5 zy&)gup7a$_d82t2aJI~<2AD(t`+a-Wf+ra$HTRX7*H0Y16BmCTQXm@je0DCap_@D0 ztMaPhqc4=Ii3zfOAGKmetJn@Y8i9uX80&IO8rp!WC@8S=;rW+W5y>qj#{S?9$dPIg zQcPK5UNsV)B2KX(2;b9v;z&jc{@C}Uzuye)O5GmFJZ3NiI_2j>?RGi{>E|C4IWbaw zXHSgL#nZ8joch56;{8rFdc83Zc1-Iffw*Vw-IF4*8%>+ba`ai$uWb+3adx*4lx@C( z@tdf4^RxSAkw2nbDy8Q99AJX1VB7)k*H@tfNpj}XRuQ}n_c3(12H}l##h<#bR`aqJ zgm0#PJA54Vl06$7yz~jW=mp;UEZ+-BXhtXTDQf#%AYZBdcC_yY659aGbOtMK#6o;{ zuv_F&;Bi+Y675vGt5fRzm}JJ9SqY-MF=328eK;~rs<%+^wOrgu4-+^VZx*7dPA>xxW*e~!T7XMDU%p{n-CS$hY-cRO?Ttb6 z$Su8PF{|ScF)i7-A2fryL3F_^{La&!HDit7QwY@v;S@-5vQ1t%rw|T1i)5w7Dc<(j z7irbN4V+=StRJ_>ASLq+?5bvOf@sH%DXL&ZqNWb279LqmXCO{`rnjK2Hn5aDbK-4sMpRIFMsf;jo?f$c z+InRr_C}?(XR@(-51-#)zLH7{S>Z(&qHm+q`3EgqiL=N$!hS4;>x3aAUtf;WQ!BIs z?s^CoTR>!np2$kXXgLfhMkhlx6&szt6`cJk^(#e-NpAB;m|QKkt$+-iy^K zrTW+7(>I_!)rd8WkuGuJaT7x3+srVIc#nv97cBb^mp@+$t*l#B#1q^#+FKvspt7Gfk$LPemkgR=>sObbWjONJ8+~m^4Jm0AHuq|{JV zrMBG@qC@i-Uz<4QgD4w|Dh#KTDhdXl`bh}6ba7R?^cW}R@XpY@fmostUqK)Os0Gv` z4fHjK@u!Z=)C8SsK*EfZ1^KJRhx*#u*N2+d<=>!w`+blQ+BN;A?5mEU0EV*!@Apw+ z2xQ3K-)+awYR_Nh+zbi*aS5jAzC2`(Zf<aklh-C-`f%)4+_`U`{62s4sRAOd@aZet_zDXT zfH&9ep*c%1<3TQ-6?~8Ws+Vj2AZTZ>7w6uB7SEii@ap}Q=W&yfM`b^eaN!Hn%T=@) zMyKc8Ie8HoZI$xI1tu%N6Ut*`KVEX`1HiS$ACyP-(WDV8MWfq1Au6JB1SWq7mF_OS zrI_7S6ryyK>V?sXRwW<|%b(jQ;74BV@{eMD(Sn67zE9o__No1LK}P$t_lqt64nO+@De8zfO2HX|Jv z~W~&s`Z7H{_H5QCFT%HKDLsQyC9GD zc_GY^g4r6sfZi`k0==9s{9=YQqb!<@LLj=O1W%);3jXNSzdO zB;4y-`~^?y$?P`}nSM%Nd<;K%5f!u;5gLLKO;(D+->y z`H7$H0?v(@uhDJT3#1tpYIdyL;X&VweZRPw&GK96(h+Xs-!~lKcs` zsXa8>_it<>9A6EqlNXlJ=lmEH_68S`On*yi8 ztR2rDJ{+kQfTJo6a*QfLX6nS~)zP-fGyZ$P01$=atTnPyF)7>L=Sr3tg}us%elOAB znV7B46YI5j@7>z@vWM1Bku^5nYZ+&r-358b4Ua*u%&c%NsBBv~`g31ok26$zR@*M2x*TV`McR#B{D`BAv5&=24>kpu3 zzqCK{qhCqj;RNv?X_q$rhd((-K zAjg?zXK|fo+hK3>BnN%+Ib~;7$iwjzujM(8=W}1Orrb9-){RT*inS3tQ5(ZgAv$Vp zoU@S1H$g!`MAt@>j~o2dP0X^vCZycf_hVOd(9~#Edsejdsg*m!S@+tHhv4v2T5_SC zxhC8$mweJAe)hh=o#H8}8{6E10<2e-&g1p<_1ITNQfDtj zKk;*N>?;x`jpa=F%uDSPw|o3F%$toNHIbW?pS3j_$W%a)hC_!;vfhLS9z};N`94SA zvPz=9YbhC7TD}AxibfA=!{o6p`6O(vU4Kc7AC$4m9wpGVGDBVNwNbp zOUkDR--HXRRj#~4Nb3psJUJB$OpwMpq_TR8deM`kO2Y7+^7c&JN2A#ci|k&4N>}~5 z)jl~tpC=*L%H65uIx2Cvk6!fBzky13`v5&oP11*SEd!yG3)zE zp`(cgO_t2%GQKOnox3XW=BM5kDS1(Dtm+1<`SkYCa@|g<6HbG3&tdl{qW)EUlpjy7 zQEBUWiJ%HUm15f^L}fZwX?G^&7lB{>x+JL3P6$2*&5TmRE~?@C)IUy0xVs#?G{ra) zo5dXmWuD6USFRe~VcjhlUCmF?A@M{ENsxVsfIqm=IzavDsP2gVYT(f)COkBD!n_lq z>{^lClilFKLeo6}$6GlVQ}hzpy8JE|O0?$hFg#4}C>o`BLP`@iO@1WV5qj~8P)Nl%wU!F9q0+5Q@u0Al3%_>XI4|{Z6 z9m{?Zcbk?_IZ)xlDlW^;fbxi<8| z=J8a<%jJn_c%1H$D3ClX-3%fScNTNiYZGZE`=NjJ)_J4(8#r1NM`+6vb^}M^n`fX0 z?#z@jWpoukIMefLV0sZ?jh7&hTTtusyXyJV137bQZNC?Knb zc9R#%HFScuS?AYpM4!Kj)Z4RSV&dX-975tKt$ymXTUs5&)`nEK7Afn2f+!H`3-^W6 zwu4EAM!lAp{g4L#1FVzWk2l*F*1!7?B?hF|3!+PqZ!Q#esJ}FExs1X`E(@icAjgtU zI+CYB6{jRG&|oK62{o*HYHAr1B|&9m(r+i3_z4=PFMrbAwzIH9Gd+ZReL^({9ihlo zNxP@Diuh;Rp8kn=sO;|I^rP3?SSYUQf$H+8nri29`qKp)0K{b(`iDq@Nh-@e`g85F zbthAqTXPKxDW6*7in*#^)Gy=;B^D-g--1q}J4`h@TJx)*nmp^A^?6=-%pUx9AwCs* zdd4D>DVhIAIu{+9Wm!if_w~=n+k_H?_M@1-(|<-ipf^)KOp(tLWVK`2Eut2LtcLY8-t+$7H5 zwkkhRpjU3n5JlC0^)5soKc@U;#a+5=!qFIyscRc5Yy7-nZ@Cy<1QtGp^sQ@zQk5h7 zP3Dvv=0RSfWJ;jdgtDGtAe-ov?yK+T<&$;vey*>nfoh}fVk-OI!ta+?Ke{O<#ijgS z0$*#FUsR@!w}`>g$sF%wXxZu_NNN^Ffy7t|>)lN5?P@hyqk*9UG9xdJjRw*)*@6DJ z!Z(Bsk%2%nh^L6HLk3-nXKV>X#z5FX#6vq?u!WR{RB8oD=W65hr`BlI!=u z0qSL*^(D=ShBx*)4{5mP6uZs(W|lJ{j2sVI)(ag5dK0hb+4qSrmP|NPB4Fq%AhDPY zD=Ml`Pq(8P&jMZk`)r)~EEKIIIAz$clb`Lk1el|WWHsLwHrz00S;ieT00mki9P zQp)Sz_!o1~#W^_!{%X;=>?n|$GkPlJMll9;Acv~Q)lvscR`qM({H_9V?a@x@ zQ+9}}QF~nQy?eVB8wnlal!jJ|2F1_TwLeA*H%tYsb6JBZ_a+#EV}5Qh`AAObQtoCj zt{oYjWC$5g9eMaEw}?y^5wmFEzy79`h1WjlBC(ju#%5Lb1ic4x#BrK=&6a)({9HEOr~84F$d8uGYO&gC4*>_wNZfUzVvOgUO&3uWYab&d&m!E zYPtAIVt3oQ;faSwiGD-m*`}R5aUrWwkBskpDU^SWgfNN~yQn-Hlb56XJRQ38j!cwA z9Xi)a@YNL1D2!HUq*x(_meI{fID=d4xM@}Q`S7lehzqiLqxL=db;3$KiJoNkUOIsi z66L7WM-2?2y|@2r=A-W`3$*EtYsC(US>q&hW7&657$}_tAA+fITgxo9Y2|Zs#jCjc zaW8+bo!{M6r0scusNMcfbu;XM$u9!Y`hF%mJ74!thJz+Y4xE<-Th$$42dWI#>B+}J zbVe!XS$S6GGGFa;y;+SAAu}xQ`Nc*Z5UXFO7G3(Y<)F+SG3R4{j2QZ?cFOdsk|WEd zqlDnG5TKHsA+QL@Y*)>b*{-J#O@V^(`7YK=x>QWH}9P&=}c08F4IFG z^ngLMp?aZ;4cK_E-iDfJk?g0QKC*1(74T_BE?lCkdu5;iSSothd+C6`*mw@l-Ox#? z2iVk!UH--m(4aB{)RcV4YP&+zM6cXoWCCi^UB8D7V+2 zaN0<>=1zDwSEF>FTk_hmUo2v>$XE33r1FTo@UXjiGb4-KnySj;5gL@)$0=-J4#npa z7uooxGPAfRR}^wznZTJJJjAvOxid_9azt*17TZXMpzrPB%{xcpO^a8njvD9Seldw% zOZ#;q52DL}ve0JqXk5L|6zM@Q{4^LlxxSw@{4ntb!AiyQ7UBu6td?{T`8?JrIZX<5 zuIE@RL8^=`sAyNb*hX=S$|WOFDvvkZUyg{L2 zRoA~EJ3P-J?lYQBbqrUrinJOr;X6n+mh28U$cmw4w}Mk-Lt~>`hfcv+d1;vFJJS+t zDId~1T`28a`{`KA_nkD$){k05#^*~zM^LO+e^-*RMPJWn4#o}h?L^?n}w2Q~kYg-rHMsP?H`Kl2uYk~dcQ&mETakt?f?0;VwabA7!F zgVnqogXOk%UGxibYbm8$+_v)*{fbWq-0KuCxC{Te0v>-gT;0csCyO$qmS*r_>(+io9IKpxzjDpemqyJK8yU`7-MIwO(4_a*6702CQ(7LXywiO_CnUFIQx&poBg<@bapr+Et3 zKLJ*h`wQmYL%+TU0ZB%8dZ4@*iF>rPwFm59bJC%v&cKtB6vr4qYR=xv%gfFQC4aH^ zBdG~(%;ADq00vx~;CYEfbL`z))*QK@QfS}T2_~M^3)@*Sy_wF?077O^=Fri6DoRuB zDfh^Q#aIn{uQdo42r@T2(FvfEMUEEG@nGAPv>AB7i*w@h^Dh10vB!37Jpx!}a|!>k z%*F@jiVtrW1XB7-sB7o#-liNvCwT7MIftqXqSi^bAxp8F?xZe2D|Y#!yfNNhtp>(* z8vMq|&ZVWLvrI1D-es#XSM=yntdX)uwY0R1N;IYQgieInBXf$!jN+8M{k@d68tpXR z8igXMoEYXWAgvF#SYf^jk|%t>!!9-J=k|1v$(nHoDjXB6gK95XTl4YY#A;qNg%4%) zy*6=c%N-D_SjFe6`83%|R~m(@5;#U;mvp1DyR0!j6Dz#h&!B^+x&srZ=z7gRx|8W( zHaHW;fU1pEJ}iO~Qx|Z&q^4$OxE;l-vpwk`Q}+tooBUeaTLZ37^Q&nno&$J$BhC;V zSKg@Hf>FbGf&_PX%cWFMVD#Wzr>=u<7Yg+xGAx@w`}w}`1Q2oy*rkR>SZ~ULSQat!-)W2_vgZ&<<@x-(X6K4 z$cYNDy4%yN23l;{Fq1lAzgYBlcQ3LZDC-cn?==qz3F+`Q0SvGJO05PuI&tTrE}Qf0 zsi<{pEi@L~1XEC?z9U5Px)1g617bG#ad$rZXfElS$X@*`%W=(J|D{>TZK0ZTKzXG? zM&|xwSOF+D#ua@!b63)t7%aHOYP&NYw!~|Yngegf zLObKiO9+_b_b-5qTO0jl2;{V>*AW8(J(y+vd`FMg&|gloZp#q&Tl16#i~HIXB6Rwf z1kI)JJEd;_jg%psB{O7y^jUz7*tM8!ZCk}*e zNTc-&`@chiWu$lEdL)Pyl^KkeI*llDy3ZXDwHoeJz#NB`z|rc{P|wU=pq!RBPP_IL z^zicBAQX0obq!CI4`vGnu-n+Trd<+|T!0>-9#9Ig0fx)SX=IuIxdJ3v&w{q)?t{Hh zG#jTAd@A8sgoICV@$tH5&!BYB4NjfbU*6q+1(5n6f%f6kr|h4;-@bnB289=$vE>~G zuWqV4*Tu<$kj*PZEh2|L%3vHEU&sdEImvgyOo2ux2$Q)OS~}87Q~=y6@3$R;C0z_| zIb~go(Bt&s#?HTYgF-p;oYv7nH0Yf=G{9EF64AG>-=UL6CV!BHblebpSon?~FDv35 z;oq4Wc^u}KE7f1I<+Z4cm{{SvF6|B@Xam~5=m7{#O;jIAg=xAq{Vr1pn8cR!k2%6n z%-MrXkh^f4Xml$~I&%oypM%@V$91lcYrm_;Gu0$Mek^t;#&s)ma>b)PcwHnD zHh}RfGmZ)<*~6ZKA=KmQb`g$f=B3HNiY-LM9wziCLN35#D3=fK-5_^7s6Id`LJlVI zM^C5#$R~&IlKq@Qf~koN)O}4s!J%~3kQRbCo4?bQ&jeqO*?^5)zxk{)3S80$H^!}ng@~rLm5||nCa{5i^Iz8D{)Tk>+C&F871-D4Lk)A*vYd^Am-hJ zM0!vdbxApFKQvfzyWIU`!U8xH+@PlUO;5R`2yrL3+MdSqs24l-7JMXdx2|r3Sm)0r zF9ch-3sDPBDRbC?3ZW6BoITvlP*RFf_q~s+qB{h+{d2+^pXgDwj~?%&re$W9+tTY$ z4u~QOIs*(Vpw4B~0DJ3eaKq?^5{8sS6vd6dMDrj5L(I;@LBuy}d?&U+r2G@t8-Hk- zv4`!TuI6{$I9Tu8!U*DxzXB&z@YPqF<<#w)(0j6}eaJ>LK&cJVfn}uE&S9V;g8f9< zDt;`XH3bu5P;ezZQ$K@lnc}$7Uk%m>gmQay`6j+^D~g&uY{ZX--ip(OZg(X z`=Ge%`!bMA6!4&Xsc~k3_+6=G?ogs$_Kkx`d+$`#^hEbw48)0Zygoj!qME~sVjXU4 zYogDBKxIw3?qvoYW$F!3=wQ-~Q%?!)O|}sL#)s>ok(4JXXu;+xfU)Z@luheC`&sJ) zfVNr=?Gy^}Mt72c&XcN)*-Nm|6x##ay-LJ`Fd@CXH^!Fc<~tI2NI^7(JQ^9*FrkMlxeIV-!i6?E z6sw~dsWmbtQ%lNROVcLgC_=RQ;Pt}(Gjy}iK;5PQ9BQiGbzZ_;(RePSzgA_iRsfEz zlF6x*<8KW(xX!uM8VAnteT8E-h*?)U&9rUh6mGI!gk*CTdp2{dZS8XWv$h5F1%-X; zSrl<(BL|3_U^J@4rKidZ~DV!&a`CLfb@OYQnG0>8g#a zes-yjy%SKqE&xG(L*V2JojlpZm38Uj#o?E5REIp4T$z^3n}2JB0j8p}Hn^f4{c7Y+ z>m9?!0D#D{MkzXqR-t+;Qm2tx47M_uG^QnnAqHq?anPSCcx~fu?vvU;=O}^$wAiO*R~Rz1PRq;7vkS1tgbXOkzTUfU;qRK~*~_0tij$SnAwGXT z8>LOI-hfU;WHAWe+NDY)zy!Yu4UPF=P*Ar{{URxKTKD}O$+zq%){|zV?CRWaNTwGE zOGUhDDWRm3yQRW&_9~PGA1uZ~t$M`ZmnRT*UxM!YXRgOXz@Yn(_Xz}9X5bLWixW27 zJCt!!z{WRqGPe1C+|Sl3zdn`n#LFcp)Y89%JAZEMQy@VxXiFQ~ctwUV7 zX&aNabE;H4lUP$&u_A#RsvB?ekjlx{^-}RY)n`eWr~@8DJ|0HOTy*12N#8Xz_HrSR z=Dh(RhFV~=S@pJ|YM<8X>2VWu5IYlLNHq{G7nk>75)rTd_|#j3?6qgCotay9CP&(R zW}k}z*S;=>4M+uTvc+(x%5ss?#qRx5u4LO)?Os?E1HxcoT?h=8x)7ZLjY?{?TAj+H zYB|_s-8bs(^!l=z*P$t!X8a)7rysFnnX;6!@Rdn`0jrn zBtY+L&MBr2giqVSf|@lLiNvh*=yFLJpKK_?GE6qO=Y6Y~ zaNlhL+t2;Nng1sI0iQY|Z1jdutQ&BShG?g#R;AebG3+S_95IKzsVIoP#UC8=?3o>q z+5jZ%vEVcKI8kFT)(UccvhgwlRsL1r*_m7`gTJQ!mX$DqI7s!srh~oq6TLyZJHp9o zxu&App@Vlz2R2&HS3@4^qh0$>C4X`)Q*Yq5_dcW+7LMl|hj;4Xe-e0{B)%1(-WXS1 zpjSiOZ*M+F{{$iP=E~K9?`7}3fzQgjV@iiS`23Mlu+qC!g&VT4ntT{=B(jnv0YCqy+eEb zC52S*_)rx+d0yw_>mPwk$0i%Pp{-(iJd@|{IPu{_&9$W|*?GweH%eK#AYmv5@qk8% z0!GyiQz~=;h`HVGD}A!CR_n(W)&kQoz;jqIhl7Jd&%hu-`iQQpOW~iD)6Q@jW1wlO z@)i>!CQ`NL!g;1e!T#zt2EvVHXx%hgI`%j_TZnUqrV0aL7Pqsu?anQN)H1vgTSvY| zI}rX9!Kcn^(_=#Pl(%t(I3K_Id`3~QEL>3YMg+imH~2s&*nbG{P&bV6&;C+ikGkT>)6xtwpsfmqpW5^FEmn1CT^ zy3C%xi>YKZ`a1vX(PejeWG2olC|6#&XzpP>8G0 zG<+lO(If4Y$&PCmQ^FzHD0!o-l9{V+gTA`-wF4F4SZhQkH6N17TkuK%5|IW z3Nu=K^PO0Eplk5cm4$KSjy2;FiG;LAwXW9Pc`4}`8D;BENO`Sed%@LS=&E4pR7R-~$F>h`y3!SBe0J!{Nt8aPcfwx6p}+h7!H+Ihe(F!fn7sT|n{o^- zI#bK!jt1!Mot4&b*V!8_Je9at*x*<#KAqV5yT-if`FY~=YbHGHQ785a>=+J0x!tL6 zpVTt`J(ecb`LZmYsU;;Def@7t2u~L7c$y0UxWCsFn!u~su}9jlLODKxQb4+FX2xqD zj6$8h-;548ka_Y`?7|k90RO)BERBH$1TDCts;Ff_d^XYJhC5!e97eG=?4%}Fe|~oE z2EZV0IW!G8=GKPdE$7KXaBbv6`tS9-6#2?zKden}`yNHww}y``%qO1jM@?}MWUSlC z4>24Z-5{%I6#f+=e0P9r4lq(DHVVG415s&K_O}OdHZ_^&cV6gjK{)%S;#y_sK zL%hDSZXL|Y5#jvgtEme``)7<)6pA;!X=@Lk*VZg|kIS>T-0XI>ySOP^iDBy-X{!#s z1uwWDKm*;0k?LdUxb7aCuN{pH*9$h4SBDNtILySQ zgyrOhe4RTBPa5t-$)BR+k+?)CBm~w-_LI8xmOgGDZ$V6nyZwjeNaoI|#T`dHQ7w>? zT0&7NAJDR1Nal^LRA_g6oYKpdogx>C1@mHv#4&97#6tZJ-5BWmIXCkuSwSWVg%Se< zHGq8a^5s`EGj^Ot0y}kYvZ4ZBwLjVq-zL9~moy9Jt6IJZ59YIK|LWz9hW?z$?dYoM zWU9t9ie2G06!{*~-45EOG)Of(w5QiE-XSKC^Y>i*)wMq1d$pmt$lg$*fVB8@ZMOVK z7{=Jg*-cmkg|hhnV4o(>-HMo`nNg^8>#)ertXj6`2vf*mgOd{|*rV2JvS||`w;X{< zyzMZzPf9Y|S7SxEg=#1P`RnC51tV1WKLmpo#;25=)@=Q=i+&tb-{HzKH9)}JX8U^x z*IF3U4B{?U3r0M75+`G+@nOVLq>P*pzYi7Q&jVoG|DvZmzk%cZO#uNZw2^yuAl>EV zxoBGL=0@(SE`zySAYMZwO3c2u9VX5VB)h)jS@;d0p61)1k(dmQ9}oZ4BKZ~>FYQHQ zOw8yY6TwYw1S5Re>%iuO>dh2IzxxL_O>QTfeg{4ie*1s$Qh?OAPqh(ok~c0i*V#Z% zla8csS)$+YHbEgFSIqAAJ*fz*q<|Dz1^CJ>;y(y1W;_O+xz4mG+pPK$MIY}WAmDT~ z9c{5%akXV7aXr07E7UafgEy%BAJ~ig#&ONx7v@ab+BbiLYig00wT7yapgPEfZ(->1 z*X0@Rx3#t!_3^-H(qG`Ic2}` zZ&|V$zATpc2cJXVcr|u6^li)}d{cjJC(vc$=>GFq6B|nY{>VY;05V`h4+I-2KZ6Si zylg0($7J@g#NF+$y>8jIW$cdTK;}sk*HTZD(DjddY|9)?KJ0G!k>~-{>sv&9^a+iE zYRGP{TnMe--M-k!fO3%Y(Nws@_kF97aA=zIo~xv zkHWdxR{r9eb}4EE#7!&$`J4}*KNq#P<2kRj^!$>#d(ES!F-SjJ|}>>{>{G#A_>DO|4oU5+fg>nEt`v*b{!Kfoe%EsLWRdDi;D&% z#3dztpFMK!+!G|kHttpNU_R+{V$X3DuJN<$j8*2KXALv>Nj%+) zVkK+=!GNrlmtO?r7VeGr-PW%LoH?#hutpT54#ydGi=%MrXn+;jO?<9fzKgbeM28|p zZNao860i6fR^}oF1lE|>)LeA zIj@~4oFO3F|6XQM%=yospL#3o-WrLCdu{iGPuSQ7d6i~2GkRWV%aBn#yAO0fxwlL3 z(5W|Q)q8nuHDQJ$Z|>L~K*=Y{|F<4k+gyKia0Mia-)BIAhwvk(ISnppXcR%qh(16T zNCm@vs$Bp8&pfJec_)mhE<@ZYSu1JiKdOs+@W2%Emm)~y+n>zaw5CNMfvd(dNyNWY zpG%JyA75LmeDIWMz&ua~TU%R&q^0}LZ-NA`!rdc(9|XSiEW}rn5Mm$&JHTQIH@hJo zv4>z4sxLy)`V1@aP@wHTbLI@ByC&2I1n5*wy$gbD$voQYXCG?p0G-G`6u0(Sk3;$8%rpbFb&YxA)enrhW01TnCb z1*k)4GT{D?O*Ocn8=G1Hwz=@(Xmm;E)qF63HhgvS{&}#=oINM$^7Y~>xHfwIjd|g_ zd6*%)Rq4QUJd<>ribX`>6yBfn{!JD(Drv3+kFnm;Z_f{k7qsSGSF#-_D=gP3jC=O% zS$JG3@D)1qEiMc4^E*+k0}GF6)rB8dPbj&|ZMM7wMuDy9nhy(|t}u5SW2tQY!2Od)T8 z0@K#O;#l~O9V_w8b$92^7AaHbM9Ft7FY0i`k5ph#tm>!P4Cb~)lSrgIssd>F4~vY9 zLq^oq4H>SnUTt5cZ#lvP$)PBn0wsznONwVrgjW|2M)6-h&4Y-gvnNCV)OIoPot1$koz!H z$l2=>S|_0aF2cGXDj_pz5pt=c1{;wuE+X_{B4(6$yrnCxnF? zLsU5Oa2CWZ7GIv`2j#a9L6Y}9y$FZhPSNYtJIbMfWkrOam&EDbVZQ$g8liO~R2upqq$%IrSfv41#-jnB z5chqd&#_pCYEU{4Xr3@zHlyk`I(lQ#$_#>}YJm}8t!0m(*h#cApI0@9;=~cb zpA+uq<3JG3Bbx7DWH(?%X_c!mTKhz|wcN{GJ$2YPDbd*MiKUo@s_BYO4@L+_GZ1Xz zZ3H}3>2MI%ir*(W5-W>mi*WRvHWbOrcc&S21uDzg&CIYIEquBRQMfi4y&vMREf< zDW?E4b}R|FF9FNBm<#$3_kt?@`}#u@U1tQ0enC=NR&)t7l9de|mieC2fOaYh9@q=9 zlepr_2zhm0IQ}=EB@{Yx3>u*+LhVZKbxJ+yO=PEbhv{0`gmWqA>)Wp_&0!2SwnnGo zbJ}a3NbcG93|lit-iK*d8risfL7#GwfMX?TjC#irN93D>{VY!J6?F z@Y)Ecc8VgJeN49}NShcV{VKnTteKRrmZxk4S~IV5H+=pq!lw7~RXX1$VD_cX_;jT^ z4E|0=U1*63al%c;G#egxUt47*#AIFklcpxcm9!xB@#@kjL!Ko@fZClXMp+k6N$V7*22CE5;zJIr1%KID#d+yXVbAgOe`^(HR}$3j`Am z+14@}zdLs@OrAy{I-|%b9;xhRC!uTt;Y4{8AUk0dj*03ww$ZA$9vsD5Rp5_XWx{B+ zRQ4gtXWzeTuSUKp8b$?Be$fIrbS|l@yM3?lW+@7|4$P|H$168C!BDIORR`r(qn(Px z^X(*6&JcabD9yS3mQtAXc4)~fa0oH(%Jy8zTL+#Z_itGYc_*e7m(JP}=HaG=Q{sqZ zbbI$^sw2yIN%3uT>j+cG1?EGNxDh_BdCo#jt-^hTD|2|N@}h)Y_o?CmIZ!Z9Zp%8B ziG3YAu3d_hu}s{7zP@dbCLz|8aJ68z_n(J4hA*bvm1xZx|48@I@gI_V#`Q03Fn4uz zvEZccD!ZGa8MMiJwQu8zQqV#=lq(i)KYkI&N{joiz*`-lqMyX> z6?)9hICOwNuRgLEI+tCP1V^wI{LNzPvS#;cSC6Qc zRP0uih6-5v!V)u;EI{4K<`>o<3r~zRh{Sl zq?vV?-V+j7&9T+r4TnX{zZh04lf;V-Qaz(kONeV7ez!DzfkXSRM3C`jae!HyVkt;|nb?mi&ubW02K#EHY^MO1SnOIk3K zV1ZQ&@91*JJ9njyWi@G=MNAa;;hZyn?h7><7APo%qdXdP-Hi&Dt>D!4cn>fE9kO{H ziG{jV$%5>3S1!xB=eciiWsM&IAm}d~e+kut@b9`*CvyO@#GyKPrpEU}Y8jWTPj{nc zhx}T8muOWEdesNSffc?BLy>$I%)+{&CP9Xypt`ymE8GEQH3M$Ycc?UI2}#7!=O*@c z68J>A3sN^OV0<{V5YqbDs|5X)TME}x;edMCfnXPKKCv;!(aFWJk{3Exg*DWw+jpd>tRCn%2Ij);R$bus!XdvMl)n1hPZV0NawwFkqqF`jy(FpOgaUq){;M%hr_);XL zFS2OZD{)eNsPvYl1WSlupeBzJ#-KfBLRD_%Vb%ue)P2Vwc83y^Ya!yUn-$*k`AFCS zHMmJ^47AO+(VrKc1;8}xwXZKqWhD8h)geMfi+5&5h7Lb|4>-f$GQy2P3E1g+jC}8L z8zon8tWXurwQ`ieCxID8A7J)35#|RHz#z3{I9X;3Ck>U6s`ISdzY7O>_;40@k1th z^&c((LoEx`hmjUXV>g7*!$$D+f;$?JQ3}!d3P*)&n~gr9=gW_gnz|I?&rsVz#C&t^ zCpLJ5>%4b6#HXepHJ9_#y<y{RbY@rVa}#g%iRG~xEZS4x9=;kKKWmhsZ+ zu;{234RIoQB(wn9OPK<*bC$HqC~oXk)A9LYL)LtUq=7C0^MZu~2g>2)M&VAv(k?gMnafi886g5Mc{<)a-WUhFLjZpRFo0YA zB#aB12$+PzB<I|qf^1df4G7KDeH(xO00wt_aH@_E&8{GGBr-zuA9}BhG%^DS?AIV zvge?~oQ49X8oRX;wtlbj9 z4Qqi_PrkB6|35e5KHmsm5j59NfjiuDkD^2l14OrzJlY6*hCO)Ei+lYvKX}e14T@R~ z!co0)g+Q}kuQ01a8**oep{6Q>gLkN{{`ufq0gr%m4(5wUrW3v+1=CJ}Hmlk*XU`g| z5W&u?8_88(OP2Y9m{EvbLW5%ixm8wai<}f(tyCMpKv3%_xgc+xJU7U4bx5hR2y7 zGP}YcEhm*O%442jCxmc^<@DImw1$^Z>_V@2# zHoqKn{O=tgf33{*A7x|fU;Y37Y<%YFA$ie%d6hRo60iWknxgZlD4#4y%nD`7*IS96a|6u_y(=8g{UF7HF^;4QcMJ@7vOko5fKp)_x!mALSl^hm&Euo zIr$B+81HW}W8oL%pQ(MlLyv2NV%)&_V<%3qL%~;BIf-+nf9olcA9HsR^vq-Bx3vf7 zrAwFW?BF#n{r7+KRKi2xzC^+RfB5fLV5I*Ka6g}VqGoqNHb z61>%aKKj&gzn%jgNO9-pk@9#T<5#y`9Vr2oQRI@zpUX_rt zCZ`}%tq0@)vZ1nV5sFl6MRuOKHGZWJAspOBZ2Ay@sxhko;qbvJX9qEv`_Hc*!#km< zqUrwm+&AUdyUiig3D#ka=b%IICu6eEgKLJ~>YL*dRq$I;1kVm|Hb4SSpx-4BOMGFy z7lE1-lxO`cfmmUYQ4S6!LVSFDGp{k;f9S&hz78V$*%XW;1Qt1Jiu?>LhlS3j!7#al zZ>b)9oN==G^3Sm%%cjG+d@3nyQ0IZI|DYvsq!vKpBkqYR1RDKL1cRQ}Uay{pG3#X6 z1W}5OK+d+a%HN+e8|l?Ru&uG22IzCZjVCWbcxnltmh&{(O_&Bvv4n1K`GMHjSaYNR z$P`K&tmq4=T9_TMg=4fB#$O+tv$tsSK>83Rb;V^a3+zl?Zc36H3c(}WD>langt>E8 zB4xm5g)gJ+cF47-KrLQ?I%(K5f0Zn#4*qv-9D#mVP`7>wpRFq6R};G1xNZkmuuk_^ z5O{ed&B`?a4kHCf{8WDe>7tRg%E1B2*#c*30a5Dgutzc!fXZ}^0%svN>no|A8G+17 z8!{-T(vilz5FHm67o?Mj*sUl(vmctPnI4lXx}ep5G?34|DF4B=U%+ZCnTPPAaHeHi zObfwYZVzDZW$@g~Tx2ag)arvV@&ZSi89=E-4$lhmSbISX^8W0fM$@gwu#q==?bt4u zQ&L^{OH(Bn(bKk|6V$@v%|VH}QdmE~7M6uEQ?fiIgM{X%eEJD|M}~?dga=a3kAC_L z0ur$b0|kNPM-Lxf2aHLm4bAtUQ?mxhv06U15Ly@+#+eE~c5ODP!F*tRmYdPFnUF;P zNkU9a?5nS!Oqw%nk@dzb14-{x*R+{yX~u?@i#hO>JnG2x&o?2zUFT5DStMh{=$Fn0)@L}meZ=H!oM$t!Us-+hoBs@OB(djDl8GKE`>eh zIGi^FG}-jb3Az-lZ4=;k0$UI72C zk}N=~hsX##C2V|sLmZztp~MM|&_+QZH!@_J8>ftm`kBMN6#(;0*! zeLC~aH@g1^56i{b^4Ern7?+idwcnD!=UpkDK9|y!{+#_`u+DF9W}WMN4|0KoWqPNz zt!=;`O`UK9$nabFH!>Fcf=iFg`oFNRi!+zO9K&;rp5_PMJ!nV%g3(M2LHCJ-<8wrU zDQ8c(A_s*`a;_mKoBtQQSK0i9p(no+bzA1`(oQv zKxH5n~t0C-H@R@&bamjhTU~shVE)A)4gN#qvsW6chlea`DNR+D`ABoF4 zPEJq*Ly{Rt=3s%kyFU?&>ZS1qlXMi)t;<^PU`i1*v#=LMbaiY z*r=!d2*CDDY^X8Z!S`IKAw2v7nFc@mDS5kJRIlGM%&Noyp=4uS0$H&IjIh6qBbG_= zUbLkJdGEm&`Sl3TdAdS3_uA|ki1>8fCcvO+xaSYXwzd3-9Jf+1Lu$uj0i@+%LAVj+ zBEIrchvagS#G65ZVT29~@@Os!4}N_HaZlT3mFsa3==K0#dV<+OHHhvIY3f)?r!x>k z9Q1)9Q+*}{Q^+m_N%IqH$V4rL4U1ec{OvJ(`{>Omf(0atM-aP*WE;Kmp0`=-&Z^&? zLR^Z8js4o0`5GjXglS41_fSgfi!nM zN+mozCoomr2x|B{$_$0J3676QKQ8i9G*WN@l*_b)TYWJkF@NhK7+0s<1nVEV?c&S z@3kpsw+=zenQ&iYOovn*bL}QQgW4~J1o+>?@`0;~QiPFJ<$-a*6E6mIB>g-~)Gm+s zK*xU(_#S>JtX%;;y-7t&qTAOGY!VhK6v_Wtduox>aHD5@p!+%p^8tFF&3=7rVgZH! z&xuqRnw*ttm~D3*b$6yiypm)50l=%8!6cRD@wBo-2#oXs;-VsmhLUe}-0`D_qNk~C zveVi&FX}CRn>OvTsR&A$-eXpEIJ2DzM0vmSAXL(-uue*jxpvE&h7dOM^YiPot0>tM zUOCM%)m9icxRXApAkv@~ws6;Ejd#M=(|a8hgFXqjL8UJ!>Wko+Wg9T=`+EgMUcR?z zKOTgIJ|pLpSR7vLE8y#{+oEAP5y@(#PC1wr>4@Knf?$XzqCDXLB1TDc$+Qv5L{upH zDSUUX4QHE`!jt(P1Ef(ptOn(TyIn6t3EBMWv_Ot~nj!yBci$O^b^pFC)t$R;av3EF zk*p+z%!_2p$WBR!E<2lSQ8r~}?>!oqy&_U7GcF-yBrDmQ|M^kw-|u-|{a-w1R|Cvg)-Enb2+4W$?&}eh?@`RD!lsck99P zy|)7+3EDv!v`T@l8d`T9nQzWx6So(^_4Dl~LcHHA&SFpdcEAYu- z7H$PCr|qFyg+r{opZOpldVpwqt86qg&eCRzMz)KI3U{4I=1P3P zDvTTYdmuX7^s$81i-BRJ$+L2klW5$zRX`LL^}#9$AizG@=o*ms;y?#vYiS^(Rn~S) zrI_--3g1^>9r`TBO2V#~$HF-6h=?xC-;5G(uIm+XkrJFTCf4jh$=n0n_Nl}LFWB;E zimVEC+mJxSvFmAb+F?%Ey=rav6=V_6CEXVB{i(1|;9$? z@(3BW{A4WSaA(7%IEWv9o?YP2QS3+N09t+yowzr!cgB9V8eo&uf4ZBxRm-j(Kc$@n z%Vd4~Vqni_&x4hp76`&Zs&0T6hII0PMBe*#8x09c6lxR$E`#3$+L@=z8O^Y>+Eke9 zt3%BGdL9(XpNdW9`jSy{;5J<(v>UG0DN_eDo>jqVenO2><8__OCWkOj`nhZc~IaA zBr4!-f9l(ygx?L&U+w0LdI=aV=!P+ckv&I#LxpZ~yhcVwU!W$?^$h@> zOGVq`EJja`E9&20SCo7Kzed(d@F<#w0!;(`%8AG+n%R*JbHkZVOemsk%sb7RmY7PNVkH&qd-Ri3??@MwT{#zKN^3Mbz zI|oqp)>MQ<{8XMwnaMLLw&1)dI!Ryrb-pM;HoHC~cY#fWV!B)-_V$O|A8B)WalINj z6#-=%jMD~%AWW??_e_f{vlDyAj8z`d(bj~<%+!h zyAL01Eqpi>I`abLbi*MmKz1)!&QPs9t???G&DWX3#Ur=SYhB?=q-;G$V(*jg^mBgrRKPvH64#!f;AP-XULyGMF|X-EL25CMMN}6??+I_uD}`nLPq!NCI`iX z6%-YVp>FDdS<5*wv7}3&K-QnImH59P5qZ$LGQmh2dI{aeNN;aqej%ddTZct{QwIQQ zTm_x5xOz61N}guHIk?aS(W0oMQc_apu0-O0!waYo(>fn=RR1O9BM6O1GLlT(hWuYF zi-;&pd$#odxErYD1KLw}1eqDk0&`2fP@-OD#d}p+B|vKggR96c$ilFM+&b#>U28fWgLT_O|SQ^}D;@ zxeEyWFF0A~o9A{3s(+|gFB=*p6_k}(^NEQ_L2tEk+G3V-u<@5V7IvCO|F z&Ne|}5&Ea$;eY4DCz{%N#LaT=Du3VFU}3j)d}UyI`Wb$H(Br!9eL0);*e~(4n&Cwa zBEG`xY(L;^WjioGI?A0m272fICEyOrKiE4-1Z{Ja@XqMyT{Pl^ z3hNWP&A>Z*35HF5P|$!giyO607EH->OifLFGjEjJWI!0xz|n3FjyTLU9={16Pr>c# zUYHE1-Yb!Z1PSXQ^c{v9{su8t>*Q;Su0qtuHRS?*xv-!OvW*1)xX1u-wMO`Zjof)il$F?1H-tY_8GO4u8JfhcGS z<8Q}rS?hE<*OPz1Z0QxiEs?!YmBRVJ_#jR)QvOI0Ap-M&Deq|1N-%4xa)Qq^1$m@z+uMY2sr*+%9pN z8}=hmrcAuhQeZt8MP;gbA^Toy;!o?VUz3|8BkxmbudR6OtWebPYA6W-7wbrIzs(0O z0Ol_e`2XuzllM`KY|SAnxLd+WPc!t1Z*~JrGUu)?RCzW`ED?Zo69qWgKPPP%1L#oPF~|SJ6F$g z`;HF1XbC{g7_KK#x*AUE6Eb~m5+8+CyQ+03DT-w}Y=^tFc061hiSHUYXC2uzqBi;B zs7_9PfW_~mf9#We!3v+x=ve#vU$XRPbhkhn0NI&9IE*s^SXS^1 zxgxJG<7-2Z>e7W$eG39Y*M$Ut_yo(;v>!r-%0!?k8vY7K%z-Z-_vIL><&!B7XWdsS zmkR4)m)a6t?m3lS7 zlZn&IDX?>cLpXr!i!;NOvE?*){~ZMWRKyiPz{zGQ-((C*7KmTam`KIO!jdJJZ$CptGbmluj>yY3tJ zGSrksi)nN~ZhW;D_5qL`-CRrBaeipQdFU!I6FX;02NV15rjD^lGtPi0v9#bH2CRr1 zppr^3JG*0fB8Q8Z98gv@cdG-8aLS*8JwQZh!1G36X~jG|j#)-%>%0&oeAZwFG3;Y4 zS~CTcLg@U*ZG&IS#J_=G;8$wD;w}fw4!kt_Fc~!UC-o)I2{Tjn5r^(T02lDT_j!E99^@RVF&AAi+dtHz*+fI z9Vmc|)0-GPs%UPLK&ok;+Fon*z+Nt!&g02aPca&U8_DLb*`L%TlUaK+g;!)*2(ExV-t52~EErsU=Mi{Z5AS@~g~q@~ z%O{A*htKqLHtjtcuP9`vZUTk4#XRkwY@D6<34DPb@8CpDfPpHa>ME+kA(0}Q&VIP> z*uYKlv^xe7AMarop3!~xyD1Vf)ZAZgyAV1VoSf3mTa;|*@$Npl{Vg&x&*N(yE-&Cd_-=pCSzz~AS!3kE|s z)$NmF>x5(aK}eU}ve53(4n*w!mlPwoNlLGnC{=+{B$KcE9t*a%pIHAy~DI|xy9XMDr&1% zXY1K{UQYH6Zab`_{h5nXu(omwDgb4Vh07k{z)A>{(U*F&N0xZ}n4f^BP~=!T`1j#d z`}F0ljyrWVR3%&%1U70fUlQ|%0vM=XE`((h*aW){IpnBcC@V-yx%&9`1sEdb3t`L*2r~uyr*a7RZW;mIRW0-dP3D~%|=J6 zRG?}6H|SG4j)Ief9oP_z?{pj3Y1wxFnOA#WRf{`P(2yMqRHd^Pl~9>%UM4=Ns6pb* zYm~0C8ACtAX&vZUheFj&c?0tnw0@fYoe{qrq>lw-484ggue;=HrrvYI-904-eYbvc zI#H&CM3EFouChx0x~CW0dzX?+z&G6y^pNR=#RN^%Tgf~rKQl|& zptPK?KQRU8bDoeZLJ<==H}=a>XJ!e-mwQg4@ka#bzeM=N8aTP*Pq83?>2LErS&9bXukB)BF{+g+;aNnI}x6=dAC~e^g+N9->)?DRiu;W`+G{K zXrz|_h9xZ4sgj+6h4Q_*E)w$B@uHj(sK&EeYc(dJ8~Ndt%}j zp(M=6^m%O#RPpLjW`R%mLEY*=7JUn%+8V6_NX$`N9X!aKU5waIn>N)q~vDF_&glkKh)O?hso+K(-ix4NC* zYSi15s;T9+{$%~p_sH?@jEaWf{_sqXi}w|sAIU})@RtSeP#C5%U8C@dS*-yFRv}bt zoDU&4ogD9bI%UHa*sg^D z26rqVQ?>0qb3FG8Mf{HjzD8$y93xZxag6#2VF&Z=!l-~^KOV^!SjF}Zblau^ z%z}S)fiAgg@k^^af9S|0Xb&v4*?q#0DRjxi)Sv!)$O8qVnb%h>Fc+Y<zF!LjU$9;2^mVnWJ2B^|^#!od3_xfr* zcIf)qg9s+qe4?51sZPgf*M8^k_zVo65IfkvH0~*POUB1_SeQD^Z+Kmy)={xtb*kf- zWHPJ7y><@Dq^1{5^l`01+i@X0dUFY8=bry&EE9?Mbyz}s>M|UZ#+9BSvN4&LV^Z438pFs{6f9G4PAWgzBC7`TmCsWr|G3&9_%UzB`u z-bpz}tjv?iA#o0Qm&V#>S~%+(Ol$UT3@WLiMMQdLu7qJ>twC*eA~KJJl z%R+STHqshLRn#;zsKq|xS8qs}$??AD)$(y(UU7mjX!<3PEu6%tAtuwAbo2Ew#S124 zgiNj?1zRb`aTOBpefRG#nWgKS>5jKxksUG-5pJZn^zB6L*J87WMG0m0d9(jK&cLOj z2e=buU_dfd#wpT_jDVN3<{lJBOhoJ0Tw+05gDpy}pWMA-@sk9&+*g&3%Hf2fqLt!> z?jq&ZrJpk{Z}eGXEx|P*3cHk}oB<`CkRoi5t%k$7cF{2YGt7Dxwoq{apbPzVJ2x6?nw^v(k8&dxg-y4HH0mh{#biJ`9d#4p|3T0KdkBDzBc}UvI~`tgWh(i zTw0d)_pj)KUvaTEl}V%6Dk-G5y0XO#eNuWr*K{)*mDNk&|A`DHI--+rqcB_}B>=<{ z`n6d=S2{t$ceL&mS18G4DO^THg%0kZ=h-#AJk5+2QXdgVyp@&6Z-+Fxzj{l%S+1Gg zJ)nXwaIJaSvGVwh4n81XuNDioz~BAI@_m3UhPGtk0Us8TX7B!sh}Py!EMIU*{Y6HFLB5L zo@3b{^_zgrOYaLf0oht8-><@JH{P;1vNEVVc%$?@AHVGRZMU^7Y1*ybTj*Jm)&&=~ z@|aX%gx|`NH{v3+F^h9YvF~<5zmQaXEXtNO6LM7Qa&LR|Mm6Ygz)2#Rk`R~Wba!Eg z^!A%2>HbrM@wq2(*G=pcHSH#z?zsK_^y%nz`0x}X9zSV?c-=heyroM68Q9M2RPqBF zo{XKFZC+hr*}Z`KPPnC=E{_LAw&C4E(Cub_9cf|s-~cb<=!DEa#ADSP#GG1mBG{oj}t znVOM_4!a)%T_GgYMURc81vmJ%E48x(?w!i(cm8~no{^ajd(W2|xAj40>GW}zCHe6p zy`-~+dPzdF12dd|5#9IcYp-#O?X7ftP~ted`5WvOsEQQDt6nG`ZSv!R8)6;DpP_cy zN-3?>TyD!@TK3e+^jz0|B7tifrDoCHc0c34YpJK-_*#+iPj|8V~RZuaV*s7aLE51{&=7n|^Z#`Dce|MGV{UrsqCAEJX*H#*?b z0?35vlI<)cC)&%Fw-UxzroV)PkMc8^x`hqEx+*;6XHBtf$i6Y)FVxO~ln}cwf&NqX zaT!n@n*cQs8CIHr3^k{sqM|D*-(zQc;^l|)W_EET&#PccH{s8k_-_%@rje6VK^}Jen@MdedBD~ix5z#ulR^-e8X=oBc zBle$zvE}V`q+zg_0IQRyXb;u!2>9{|odS{9M9`&{cQf3;PnCt4v=N}zYO$B@Ddi>X z-8Z67gw&KsZ-A2#HvRoqb8{qTCt$5NH)(ht;kGx|_!2=?X1rT9*b{W4vGY$tN5>0m z)+ZNRgl9*?6t0E{O=f=v40-diH~(%CQVtGY%(Xkfxw{5bB?b6Wp<^XLXBmKBQ?+^k zT+VkpGzuO)!OT@B7<}6=WBM9iR5;Ei?iaMKBHsw!dJH4UtOQ|4{;A*b3vP9Dj)ny1 zL27Dh#GN#OJTF+K8p0?=HxgaDX|(?Ka?KO47YGLv#aQfmduS$rAB8O?Ft)u0R&{c; zusXofm>ts4H6%O&%OuUTrhw#kuy8N#ZOEycuIDAVG4aoM45brhSg*x|6_yPLxOxCp zX#!TDWY0Z_hcL7?GdzOY06yXiJnj>)Zdeg`Cv4c`Uh&Ajc>>0bO7{|-jomE)37i0G z4zAf|?~u?@&3v$KBY7-2gdA*~eN@Z>hvZFgX}s#HCmbPKc|2Vt&vGdz~2kJZFE4@vTE)vtykm)7z)@y`4(xUyZ6&|nJOvJT0(DUov=`owl)g0 z5GCYTe{^*+)rduc_p~>M7<}LX1c1}~MV|hEe#AV|es8RUBYiw`?HP27w4uypsu#er zad?X)@$)fKcHg!Su&Zh^=;&b}N6G^uHqZ7WPMn?QlJT{`TOWW461bA~C4*d>-3g}P zHZi{=AB5xrHkZz3cv?POr2hf?+zRKMkp1okfPvftwZQ$dCCW%ykuj8qakwdOsSoaQ z4maCN^Di%lw`iu+graaBjqZnGvT^$!xAitWV35-f+0p&EZJsvlH*rQtN;lmC62674 zZhqKEIE+E)=9`P?@HcLtZClvZGbKf*bYRz`LUmu%UpJV3Q5d?(@4vK>#_QSHW_|Jj z{huE=q@o_xCVv16{m2bwfsS6(CJkc%=2soTLCoSRi56MzF*Jc^FgQ`st>8j?jcQWI zICDHyUtOb|!C?w+Okt`dg%Kr%5vD(!_pb8l^}I)#Oy(HF|aYL39@wO=GsD>n*$ubj~jj~(X=2)n!6rE&T)!Vz4rp;Y*7K!GE4NFEu|pM zU)x5Y4y;zWF|q_aH~t)+y-+@+a^0i2X44q4*u zrvyDbc=xUK&(Jv7ee*q@2}FkP7R(n^2a6kurNuMBbz6{z(qqILXwvgj=!l{YFnFaQ zCKXQeXW)jrwpjP0KK)KB;Dt|Rh#Fs*KE8`ULDw2eG z8Uib<{07Tgicj%^m%w4*dHalEB_j3i23+75e%SZayDSQK85T=t(VnuRN{PuUtl&t1 zRhf;+@4-WGeq)$!5@?65qjPdlHM^6=`hemf9jzy0xFo^3L z4^e#@13)@;%?HI%q0zCup?vZ`y`Z3EYpnrKyC0a!0dxY<(Pn;}O3L!~WaDa5rqK5o z!};tK;7N`ST~m{0mbxil#ahpg*%WNEmT#}W2$h5D&J!7WIgq4H?wdJEl+5KXZnN7P zfdT|xo>%oE9^!kPl1t8cGh@{K`?gnMdbm&^$V5e1a841E5)-Z@#7+vMkfad=q|?p@ z5EQP;@Z|n3C5ecJRKT0!FG;pB*s#qN!ia)0%5|WUaG4ye^@tU)Hn9Gz5`@u#l@3p8 z?(W_7(=ATP{KHUX$Z6fOmf|T>O~ScAZ|njd>v0WC(^@}9%X4Fh?L+7DaBzXZRkO-83p=V1LNcYdBdo3TYBtk)* zgkOL{v?dJ{lbYpr`mavPHFSp@poFFOK>Bny0A z2{fmvzD2>U8JjtJrs^W>aee<@={B6W|bQ z-myKh$qgQ#uG>6hIms_yUJPYMvE$)5C1Lq{oK+@-!}EuX>q~2v3h3_2xjej(wA#Qr z@51z4l{}c|#USjgF|8%$-+Nwjim!4W#1ujuCG!AIxb3^U9`JepIuk1=ao{ZAY<)kL z5i;5VKE(@L0uDJa>gIQw3)DMTQW6o+{S;^C-!6gSH3@FVVzSrz$FW*fiQYgl%>rS; zi@K5sZ=B3pM|6$)>{^o3E9rMq$-_v%wt}ZxNmvq&K>TX2hs8 zChOu&UtZ(Ze$EK%&qPBN0xrnmn3Hdj|(E{^L0pbfwzM4$W=OIO9!8G}^^9%$q z&H)domjiLSU5S=!HaJe6NToYLd_;S5m$*sa#GgOtAu>rhe#rX+%`PM3D6H?A^=`}x!5M{0+G z1g&Ry4RNA6q4AAPbQ<>mYjCe&e$H)VrQ_fBW;^5%wD}wZ+`N&~p+GS{K1ltEqqwmr z1!N3k*QHb1OgmJeMAPV33;LSF^>(p=HUWOl50q4m1VeKSUpk3IxQw4LhtEg2z zJKL*GI}eF=?1gN503~6&tH_-%^zQ)MV0!@ll+tGRI_#e4m%f_dpr7!N3}&t^D=RW4 zZAQ=sZn&KXDi_zlV2Q=e>b?l9UWJx%b#|0sg?2MB5hOpGu0bOc@T}GhsxW5oYOA`qwt59@Q7ijqe3kvVhx4<)9(}&Yzec0h{XS?D3WjpmZzgt=1p!P=+Pn$8`6& zl|%2^a#JEvJ@i~&!50hTgNT!|A%fpyL@K_cei@YXIgWiK_NdczuKa~Se7(T8(GovK zd?=MEFA63cv}t)upD>qAkv_0+y8C8Z{jY;2dBW z3xuk`M7=9MZcJ?IBu5&vQ?xtLMXgyM@E#T!-Yb5IV$;N)`&AW7#oAQXg z0`|bVu5|kXz*nh?<{CSq1FsJsuhn+NO0e>@WZnTtfN%MFZ!QI@TZgsd;XvVG3U;jW zkqYg_XBYG(5;P;%TXH_5PR11l2fCN+)H6INt5*R3%jR|Z^3;Y6gyVFuwPyJWZHP11 z5rh0rGzBxnt3V}n^N!Ts)6J|H$X_6ttq+k&@QkXI$y-Pj`(L3Q0kq~gIZQ0-Rq2%} zQESm6G?m{U^%Clh&(KcwKUF0$o$f8>L?&Kq{fD7Icrtk0g0-EBVqYlE;0u62mRQsa zS@(&-X!VdtcXo*Y+P0hYkllKtS*zwLFr8wXHXG(zK@sj+({A3;wlT8l0{u&$5(=xE z+n|Taf@dfTF_TE?1TI*e+!y`b{aE|mOF(jP6_X}HyE_#?yXa0vXy~Qt=BG7WzPI=r zDF$kNps%LEUBv^MsiYajqOf#t0>*pt_u{Rkv8ud*L8pXETCOuU>_!#{#snv9>>UG! z_O}%Kf=Qfiftta7Kn$k8w1&Pq@<9UV+}kjo@n&y_<)&v3!i?UM%%7^TsAlQ`Q2#o? zStPzl)SJ^fk4xelX|S^CN3>I-s#ZG=gcuoU#du5ioM01Q#3Qf0FcmxL*|c9u_#H47 z!7PunnL=C6Wk2On(M1(9%Lba%UPUHYry++Lvh^&F^(;D(oK}RI9d-ZpuwO@Yqbf~w z6xMYpR)8thO|A$Ga{yvhslzsbku?}UX2O8LDrttz`m6Oe?BRHjun_u0+Inm50lo?5 z9J<5RFdSWt2>2emS~Ux{2d)6;{(fzweFc9J8zCm?NxTLsGw7E(0kfm)@MBc8tv`#V zJZTP4**^vMyO@=BosnP|wg&*Nc3Z^3ws8$G%}W~U>gmw7jm=%-qAu}28&kg~<;gKe?B@1=CzwUKP5rn75GEjGWGROUaEAd [!note] -> During runtime, VPE converts the GameObjects and Components into Unity's [DOTS](https://unity.com/dots) elements. So we use Components in the editor to define the game logic implemented in DOTS. That's also why we call them *Authoring Components*. +> During runtime, VPE converts the GameObjects and components into Unity's [DOTS](https://unity.com/dots) entities. So we use components in the editor to define the game logic implemented in DOTS. That's also why we call them *Authoring Components*. -If you've never heard about GameObjects or Components, we recommmend you read through the links in the first two paragraphs, they are short, to the point, and better than what we could provide here. +If you've never heard about GameObjects or components, we recommmend you read through the links in the first two paragraphs. They are short, to the point, and better than what we could provide here. ## Components vs Game Items -In Visual Pinball, Components would be what you see in the options panel when you click on a game item. You'll typically find sections for physics behavior, rendering, and form and shape of the game item you're editing. Internally, all those sections belong to the same game item. +In *Visual Pinball*, components would be what you see in the options panel when you click on a game item. You'll typically find sections for physics behavior, visuals, and form and shape of the game item you're editing. Internally, those sections belong to the same game item. -In VPE, we have separate Components for separate things. For example, a rubber might be visible on the playfield, so its GameObject includes a *Rubber Mesh Component*. And it collides with the ball, so there is a *Rubber Collision Component* as well. And of course it has a position and a name, which are part of what we call the "main component", in this case the *Rubber Component*. +In *VPE*, we have separate components for separate things. There are four different types of components: -This separation of logic comes with a lot of advantages, as you will see later. +1. The **Main Component** represents the actual game item. +2. The **Collider Component** adds physical behavior to the game item. It defines how the ball collides with it, i.e. how the bounciness, friction and randomness is applied to the ball. +3. **Mesh Components** generate meshes, i.e. the geometry used to render the object on the playfield. The result are procedurally generated visuals. +4. **Animation components** apply movement to the game item. If the entire object is moved (for example a flipper), this is taken care of by the collision component, but items where only parts move (e.g. the plate of a gate, or the ring of a bumper), these components apply the movement to the GameObject. + +Let's look at a flipper: + +![VPE vs VP](properties-vpe-vs-vp.png) + +Here, we see the main component (*Flipper*), the collider component (*Flipper Collider*), and two mesh components (*Flipper Base Mesh* and *Flipper Rubber Mesh*). While the main- and collider component sit on the same GameObject, the mesh components have each their own child. This is how Unity works - a GameObject has at most one mesh component. > [!note] -> In general, you don't have to manually manage all this. When creating game items via the toolbox, the created GameObject will already have all the necessary components. Also, importing a `.vpx` file applies the necessary components. +> Internally, VPE still keeps a single set of data. That's why you see the collapsed *Base Mesh*, *Rubber Mesh* and *Physics* sections in the main component. When you change values there, the corresponding values in the other components will update at the same time. +This separation of logic comes with a few advantages. First, it's more obvious how a game item behaves. No collider component? That means the game item is not collidable. No mesh component? It's (permanently) invisible. But there are other advantages, as you will see in the next section. -## Component Types +> [!note] +> In general, you don't have to manually manage all this. When creating game items via the toolbox, the created GameObject will already have all the necessary components (as will importing a `.vpx` file). -Here's a quick overview of which Components VPE provides to set up your game items. +## Combining Components -| | Mesh | Collision | Movement | -|------------|------|-----------------|----------| -| Bumper | | | | -| Flipper | | | | -| Gate | | | | -| Hit Target | | | | -| Kicker | | | | -| Light | | | | -| Plunger | | | | -| Primitive | | | | -| Ramp | | | | -| Rubber | | RubberCollider | | -| Spinner | | | | -| Surface | | SurfaceCollider | | -| Trigger | | | | +VPE allows to mix and match components of different game items. For example, for a given game item, you can assign a collider or mesh from another type. The most common use case is replacing built-in meshes with primitives. For this, you would remove the original mesh component and replace it with a primitive mesh component. But there are other usages, like using a primitive collider on a rubber. You can also have multiple children with colliders (or meshes) for a game item. -*What we've implemented so far*. +The advantage compared to Visual Pinball where you would create multiple game items is that VPE treats them as one single logical entity. For example, VPE will automatically rotate a primitive flipper item when it's parented under a flipper. Or events from multiple colliders will be emitted on the same parent object. -As you can see, there are three types of Components for each game item: +### Supported Combinations -- **Mesh Components** generate meshes, i.e. the geometry used to render the object on the playfield. The result are procedurally generated visuals, e.g. a flipper mesh would be based on the length, inner- and outer radius and a few more attributes. -- **Collision Components** add physics behavior to the game item. They define how the ball collides with it, i.e. how the bounciness, friction and randomness is applied to the ball. -- **Movement Components** apply animation to parts of the game item. If the entire object is moved (for example a flipper), this is taken care of by the collision Component, but items where only parts move (e.g. the plate of a gate, or the socket of a bumper), these components apply the movement to the GameObject. +Not every game item's components can be re-used in other game items. For example it doesn't make much sense to use a flipper collider for a bumper. In fact, most of the combinations are unsupported. Here's what VPE does support so far: -## Combining Components +| | Supported Meshes | Supported Colliders | Supported Animators | +|------------------|---------------------------------------------------------------|----------------------------|---------------------------| +| **Bumper** | Bumper Base, Bumper Cap, Bumper Ring, Bumper Skirt, Primitive | Bumper | Bumper Ring, Bumper Skirt | +| **Flipper** | Flipper Base, Flipper Rubber, Primitive | Flipper | | +| **Gate** | Gate Bracket, Gate Wire, Primitive | Gate | Gate Wire | +| **Hit Target** | Hit Target, Primitive | Hit Target | Hit Target, Drop Target | +| **Kicker** | Kicker, Primitive | Kicker | | +| **Light** (bulb) | Light, Primitive | | | +| **Plunger** | Flat Plunger, Plunger Rod, Plunger Spring | Plunger | Plunger | +| **Primitive** | Primitive | Primitive, Ramp, Wall | | +| **Ramp** | Ramp, Primitive | Ramp | | +| **Rubber** | Rubber, Primitive | Rubber, Surface, Primitive | | +| **Spinner** | Spinner Bracket, Spinner Plate, Primitive | Spinner | Spinner Plate | +| **Surface** | Surface, Primitive | Surface, Primitive | | +| **Trigger** | Trigger, Primitive | Trigger | Trigger | -VPE allows to mix and match the different types of components. That means, for a game item, you can use a collider or mesh from another type. -## Naming Conventions +## Naming Conventions \ No newline at end of file diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs index 29151f8b4..acf8e073a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs @@ -49,10 +49,10 @@ public static IItemMainAuthoring SetupGameObject(this Flipper flipper, GameObjec } case ItemSubComponent.Mesh: { - - // if invisible in sub component, the mesh is explicitly created, so just disable it if invisible. var baseComp = CreateChild(obj, FlipperMeshGenerator.Base); var rubberComp = CreateChild(obj, FlipperMeshGenerator.Rubber); + + // if invisible in sub component, the mesh is explicitly created, so just disable it if invisible. baseComp.enabled = flipper.Data.IsVisible; rubberComp.enabled = flipper.Data.IsVisible; From 79e48236ca847a9b7fd49f9f6e575ddd20789084 Mon Sep 17 00:00:00 2001 From: freezy Date: Sat, 24 Oct 2020 22:36:42 +0200 Subject: [PATCH 098/124] events: Emit on parent if available. --- VisualPinball.Engine/Game/IHittable.cs | 2 ++ VisualPinball.Engine/Physics/HitObject.cs | 7 ++++++- .../VPT/Flipper/FlipperHit.cs | 6 +++--- VisualPinball.Engine/VPT/Gate/GateHit.cs | 8 ++++---- VisualPinball.Engine/VPT/IItem.cs | 3 +++ VisualPinball.Engine/VPT/Item.cs | 3 +++ .../VPT/Plunger/PlungerHit.cs | 20 +++++++++---------- .../VPT/Spinner/SpinnerHit.cs | 8 ++++---- .../VPT/ItemInspector.cs | 12 +++++------ .../Game/Engine/DefaultGamelogicEngine.cs | 12 +++++++++++ .../Physics/Collider/Collider.cs | 3 ++- .../Physics/Collider/LineSlingshotCollider.cs | 2 +- .../Physics/Collision/ColliderHeader.cs | 4 ++++ .../Collision/QuadTreeCreationSystem.cs | 2 +- .../Collision/StaticNarrowPhaseSystem.cs | 3 --- .../VPT/Bumper/BumperCollider.cs | 2 +- .../Bumper/BumperRingAnimationAuthoring.cs | 2 +- .../Bumper/BumperSkirtAnimationAuthoring.cs | 2 +- .../VPT/Flipper/FlipperCollider.cs | 4 ++-- .../VPT/Gate/GateWireAnimationAuthoring.cs | 2 +- .../VisualPinball.Unity/VPT/IApi.cs | 5 +++++ .../VisualPinball.Unity/VPT/ItemApi.cs | 4 +++- .../VPT/ItemMainAuthoring.cs | 11 ++++++++++ .../VPT/ItemMovementAuthoring.cs | 4 ++-- .../VPT/Plunger/PlungerAuthoring.cs | 2 +- .../Spinner/SpinnerPlateAnimationAuthoring.cs | 2 +- .../VPT/Trigger/TriggerCollider.cs | 4 ++-- 27 files changed, 92 insertions(+), 47 deletions(-) diff --git a/VisualPinball.Engine/Game/IHittable.cs b/VisualPinball.Engine/Game/IHittable.cs index 1ebf34754..1d7fdcf5d 100644 --- a/VisualPinball.Engine/Game/IHittable.cs +++ b/VisualPinball.Engine/Game/IHittable.cs @@ -22,6 +22,8 @@ public interface IHittable : IPlayable { string Name { get; } int Index { get; } int Version { get; } + int ParentIndex { get; } + int ParentVersion { get; } HitObject[] GetHitShapes(); bool IsCollidable { get; } } diff --git a/VisualPinball.Engine/Physics/HitObject.cs b/VisualPinball.Engine/Physics/HitObject.cs index d42ddc485..72382f55f 100644 --- a/VisualPinball.Engine/Physics/HitObject.cs +++ b/VisualPinball.Engine/Physics/HitObject.cs @@ -66,6 +66,9 @@ public abstract class HitObject public int ItemIndex; public int ItemVersion; + public int ParentItemIndex; + public int ParentItemVersion; + protected HitObject(ItemType objType, IItem item) { ObjType = objType; @@ -130,10 +133,12 @@ public void ApplyPhysics(IPhysicalData data, Table table) SetEnabled(data.GetIsCollidable()); } - public virtual void SetIndex(int index, int version) + public virtual void SetIndex(int index, int version, int parentIndex, int parentVersion) { ItemIndex = index; ItemVersion = version; + ParentItemIndex = parentIndex; + ParentItemVersion = parentVersion; } } } diff --git a/VisualPinball.Engine/VPT/Flipper/FlipperHit.cs b/VisualPinball.Engine/VPT/Flipper/FlipperHit.cs index a9d35ae22..60996bc56 100644 --- a/VisualPinball.Engine/VPT/Flipper/FlipperHit.cs +++ b/VisualPinball.Engine/VPT/Flipper/FlipperHit.cs @@ -41,10 +41,10 @@ public FlipperHit(FlipperData data, Table.Table table, IItem item) : base(ItemTy UpdatePhysicsFromFlipper(); } - public override void SetIndex(int index, int version) + public override void SetIndex(int index, int version, int parentIndex, int parentVersion) { - base.SetIndex(index, version); - HitCircleBase.SetIndex(index, version); + base.SetIndex(index, version, parentIndex, parentVersion); + HitCircleBase.SetIndex(index, version, parentIndex, parentVersion); } public override void CalcHitBBox() diff --git a/VisualPinball.Engine/VPT/Gate/GateHit.cs b/VisualPinball.Engine/VPT/Gate/GateHit.cs index 65273d9fe..96b66e468 100644 --- a/VisualPinball.Engine/VPT/Gate/GateHit.cs +++ b/VisualPinball.Engine/VPT/Gate/GateHit.cs @@ -63,11 +63,11 @@ public GateHit(GateData data, float height, IItem item) : base(ItemType.Gate, it TwoWay = false; } - public override void SetIndex(int index, int version) + public override void SetIndex(int index, int version, int parentIndex, int parentVersion) { - base.SetIndex(index, version); - LineSeg0.SetIndex(index, version); - LineSeg1.SetIndex(index, version); + base.SetIndex(index, version, parentIndex, parentVersion); + LineSeg0.SetIndex(index, version, parentIndex, parentVersion); + LineSeg1.SetIndex(index, version, parentIndex, parentVersion); } public override void CalcHitBBox() diff --git a/VisualPinball.Engine/VPT/IItem.cs b/VisualPinball.Engine/VPT/IItem.cs index 7e0b04c6d..5ed8cd690 100644 --- a/VisualPinball.Engine/VPT/IItem.cs +++ b/VisualPinball.Engine/VPT/IItem.cs @@ -25,6 +25,9 @@ public interface IItem int StorageIndex { get; set; } + int Index { get; } + int Version { get; } + string ItemName { get; } string ItemGroupName { get; } diff --git a/VisualPinball.Engine/VPT/Item.cs b/VisualPinball.Engine/VPT/Item.cs index 0941a60ea..30f6cf984 100644 --- a/VisualPinball.Engine/VPT/Item.cs +++ b/VisualPinball.Engine/VPT/Item.cs @@ -47,6 +47,9 @@ public string Name public int Index { get; set; } public int Version { get; set; } + public int ParentIndex { get; set; } + public int ParentVersion { get; set; } + public int StorageIndex { get => Data.StorageIndex; set => Data.StorageIndex = value; } public string ComponentName { get; private set; } diff --git a/VisualPinball.Engine/VPT/Plunger/PlungerHit.cs b/VisualPinball.Engine/VPT/Plunger/PlungerHit.cs index 03900ff93..7fed4c8cb 100644 --- a/VisualPinball.Engine/VPT/Plunger/PlungerHit.cs +++ b/VisualPinball.Engine/VPT/Plunger/PlungerHit.cs @@ -65,17 +65,17 @@ public PlungerHit(PlungerData data, float zHeight, IItem item) : base(ItemType.P JointEnd[1] = new HitLineZ(new Vertex2D(_x2, Position), zHeight, zHeight + Plunger.PlungerHeight, ItemType.Plunger, item); } - public override void SetIndex(int index, int version) + public override void SetIndex(int index, int version, int parentIndex, int parentVersion) { - base.SetIndex(index, version); - LineSegBase.SetIndex(index, version); - LineSegEnd.SetIndex(index, version); - LineSegSide[0].SetIndex(index, version); - LineSegSide[1].SetIndex(index, version); - JointEnd[0].SetIndex(index, version); - JointEnd[1].SetIndex(index, version); - JointBase[0].SetIndex(index, version); - JointBase[1].SetIndex(index, version); + base.SetIndex(index, version, parentIndex, parentVersion); + LineSegBase.SetIndex(index, version, parentIndex, parentVersion); + LineSegEnd.SetIndex(index, version, parentIndex, parentVersion); + LineSegSide[0].SetIndex(index, version, parentIndex, parentVersion); + LineSegSide[1].SetIndex(index, version, parentIndex, parentVersion); + JointEnd[0].SetIndex(index, version, parentIndex, parentVersion); + JointEnd[1].SetIndex(index, version, parentIndex, parentVersion); + JointBase[0].SetIndex(index, version, parentIndex, parentVersion); + JointBase[1].SetIndex(index, version, parentIndex, parentVersion); } public override void CalcHitBBox() diff --git a/VisualPinball.Engine/VPT/Spinner/SpinnerHit.cs b/VisualPinball.Engine/VPT/Spinner/SpinnerHit.cs index 189fe37d2..c81a23ee2 100644 --- a/VisualPinball.Engine/VPT/Spinner/SpinnerHit.cs +++ b/VisualPinball.Engine/VPT/Spinner/SpinnerHit.cs @@ -46,11 +46,11 @@ public SpinnerHit(SpinnerData data, float height, IItem item) : base(ItemType.Sp LineSeg1 = new LineSeg(v2.Clone(), v1.Clone(), height, height + 2.0f * PhysicsConstants.PhysSkin, ItemType.Spinner, item); } - public override void SetIndex(int index, int version) + public override void SetIndex(int index, int version, int parentIndex, int parentVersion) { - base.SetIndex(index, version); - LineSeg0.SetIndex(index, version); - LineSeg1.SetIndex(index, version); + base.SetIndex(index, version, parentIndex, parentVersion); + LineSeg0.SetIndex(index, version, parentIndex, parentVersion); + LineSeg1.SetIndex(index, version, parentIndex, parentVersion); } public override void CalcHitBBox() diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs index 306dbba3b..f0128c73c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs @@ -115,12 +115,12 @@ protected void OnPreInspectorGUI() return; } - // EditorGUI.BeginChangeCheck(); - // var val = EditorGUILayout.TextField("Name", item.ItemData.GetName()); - // if (EditorGUI.EndChangeCheck()) { - // FinishEdit("Name", false); - // item.ItemData.SetName(val); - // } + EditorGUI.BeginChangeCheck(); + var val = EditorGUILayout.TextField("Name", item.ItemData.GetName()); + if (EditorGUI.EndChangeCheck()) { + FinishEdit("Name", false); + item.ItemData.SetName(val); + } EditorGUI.BeginChangeCheck(); var newLock = EditorGUILayout.Toggle("IsLocked", item.IsLocked); diff --git a/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/DefaultGamelogicEngine.cs b/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/DefaultGamelogicEngine.cs index 9a64353a7..e781dbf8c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/DefaultGamelogicEngine.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/DefaultGamelogicEngine.cs @@ -20,6 +20,7 @@ using NLog; using VisualPinball.Engine.Common; using VisualPinball.Engine.Game.Engines; +using Debug = UnityEngine.Debug; namespace VisualPinball.Unity { @@ -87,6 +88,15 @@ public void OnInit(TableApi tableApi, BallManager ballManager) // debug print stuff OnCoilChanged += DebugPrintCoil; + + _tableApi.Rubber("Rubber1").Hit += LogHit; + _tableApi.Surface("Collider").Hit += LogHit; + } + + private void LogHit(object sender, EventArgs e) + { + var api = sender as IApi; + Debug.Log("Hit by " + api?.Name + "!"); } public void OnUpdate() @@ -96,6 +106,8 @@ public void OnUpdate() public void OnDestroy() { OnCoilChanged -= DebugPrintCoil; + _tableApi.Rubber("Rubber1").Hit -= LogHit; + _tableApi.Surface("Collider").Hit -= LogHit; } public event EventHandler OnCoilChanged; diff --git a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collider/Collider.cs b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collider/Collider.cs index a1d98e0e4..9421c7c85 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collider/Collider.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collider/Collider.cs @@ -43,6 +43,7 @@ internal struct Collider : IComponentData public int Id => Header.Id; public Entity Entity => Header.Entity; + public Entity ParentEntity => Header.ParentEntity; public ColliderType Type => Header.Type; public PhysicsMaterialData Material => Header.Material; public float Threshold => Header.Threshold; @@ -217,7 +218,7 @@ public static void FireHitEvent(ref BallData ball, ref NativeQueue.Pa // must be a new place if only by a little if (distLs > normalDist) { - events.Enqueue(new EventData(EventId.HitEventsHit, collHeader.Entity, true)); + events.Enqueue(new EventData(EventId.HitEventsHit, collHeader.ParentEntity, true)); } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collider/LineSlingshotCollider.cs b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collider/LineSlingshotCollider.cs index 965a5c22e..b080ec841 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collider/LineSlingshotCollider.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collider/LineSlingshotCollider.cs @@ -113,7 +113,7 @@ public void Collide(ref BallData ball, ref NativeQueue.ParallelWriter // !! magic distance, must be a new place if only by a little if (distLs > 0.25f) { - events.Enqueue(new EventData(EventId.SurfaceEventsSlingshot, _header.Entity, true)); + events.Enqueue(new EventData(EventId.SurfaceEventsSlingshot, _header.ParentEntity, true)); // todo slingshot animation // m_slingshotanim.m_TimeReset = g_pplayer->m_time_msec + 100; diff --git a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/ColliderHeader.cs b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/ColliderHeader.cs index a554d159b..1760e9e6d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/ColliderHeader.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/ColliderHeader.cs @@ -32,6 +32,7 @@ internal struct ColliderHeader public ItemType ItemType; public int Id; public Entity Entity; + public Entity ParentEntity; public PhysicsMaterialData Material; public float Threshold; @@ -62,6 +63,9 @@ public void Init(ColliderType type, HitObject src) ItemType = src.ObjType; Id = src.Id; Entity = new Entity {Index = src.ItemIndex, Version = src.ItemVersion}; + ParentEntity = src.ParentItemIndex > 0 || src.ParentItemVersion > 0 + ? new Entity {Index = src.ParentItemIndex, Version = src.ParentItemVersion} + : Entity; Material = new PhysicsMaterialData { Elasticity = src.Elasticity, ElasticityFalloff = src.ElasticityFalloff, diff --git a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/QuadTreeCreationSystem.cs b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/QuadTreeCreationSystem.cs index 4c4f4b59f..9d28bf49a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/QuadTreeCreationSystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/QuadTreeCreationSystem.cs @@ -45,7 +45,7 @@ public static void Create(EntityManager entityManager) var hitShapes = item.GetHitShapes(); log += item.Name + ": " + hitShapes.Length + "\n"; foreach (var hitObject in hitShapes) { - hitObject.SetIndex(item.Index, item.Version); + hitObject.SetIndex(item.Index, item.Version, item.ParentIndex, item.ParentVersion); hitObject.Id = id++; hitObject.CalcHitBBox(); hitObjects.Add(hitObject); diff --git a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/StaticNarrowPhaseSystem.cs b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/StaticNarrowPhaseSystem.cs index 5d290a594..dd90532a5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/StaticNarrowPhaseSystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/StaticNarrowPhaseSystem.cs @@ -16,7 +16,6 @@ using Unity.Collections; using Unity.Entities; -using Unity.Jobs; using Unity.Profiling; namespace VisualPinball.Unity @@ -24,8 +23,6 @@ namespace VisualPinball.Unity [DisableAutoCreation] internal class StaticNarrowPhaseSystem : SystemBase { - public JobHandle Deps { get; private set; } - private SimulateCycleSystemGroup _simulateCycleSystemGroup; private EntityQuery _collDataEntityQuery; private static readonly ProfilerMarker PerfMarker = new ProfilerMarker("StaticNarrowPhaseSystem"); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCollider.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCollider.cs index c286d5833..932d4bc53 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCollider.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCollider.cs @@ -41,7 +41,7 @@ public static void Collide(ref BallData ball, ref NativeQueue.Paralle skirtData.HitEvent = true; skirtData.BallPosition = ball.Position; - events.Enqueue(new EventData(EventId.HitEventsHit, collider.Entity, true)); + events.Enqueue(new EventData(EventId.HitEventsHit, collider.ParentEntity, true)); } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs index c886f9eb2..7c2e84474 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs @@ -27,7 +27,7 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio { var table = Table; var bumper = Item; - var bumperEntity = Entity; + var bumperEntity = MainEntity; // update parent var bumperStaticData = dstManager.GetComponentData(bumperEntity); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs index 9b632e3ac..46d33c785 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs @@ -27,7 +27,7 @@ public class BumperSkirtAnimationAuthoring : ItemMovementAuthoring(bumperEntity); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperCollider.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperCollider.cs index 9d7227553..86cd19539 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperCollider.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperCollider.cs @@ -762,11 +762,11 @@ public void Collide(ref BallData ball, ref CollisionEventData collEvent, ref Fli var flipperHit = hitData.HitMomentBit ? -1.0f : -bnv; // move event processing to end of collision handler... if (flipperHit < 0f) { // simple hit event - events.Enqueue(new EventData(EventId.HitEventsHit, _header.Entity, true)); + events.Enqueue(new EventData(EventId.HitEventsHit, _header.ParentEntity, true)); } else { // collision velocity (normal to face) - events.Enqueue(new EventData(EventId.FlipperEventsCollide, _header.Entity, flipperHit)); + events.Enqueue(new EventData(EventId.FlipperEventsCollide, _header.ParentEntity, flipperHit)); } } movementData.LastHitTime = timeMsec; // keep resetting until idle for 250 milliseconds diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAnimationAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAnimationAuthoring.cs index ffeb00c3f..343ff79ba 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAnimationAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAnimationAuthoring.cs @@ -23,7 +23,7 @@ public class GateWireAnimationAuthoring : ItemMovementAuthoring(gateEntity); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IApi.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IApi.cs index 981312a92..2adaa90bb 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IApi.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IApi.cs @@ -16,6 +16,11 @@ namespace VisualPinball.Unity { + public interface IApi + { + string Name { get; } + } + internal interface IApiInitializable { void OnInit(BallManager ballManager); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemApi.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemApi.cs index 249388033..032aa22e8 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemApi.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemApi.cs @@ -21,8 +21,10 @@ namespace VisualPinball.Unity { - public abstract class ItemApi where T : Item where TData : ItemData + public abstract class ItemApi : IApi where T : Item where TData : ItemData { + public string Name => Item.Name; + protected readonly T Item; internal readonly Entity Entity; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs index fc47f024d..8680f1b24 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs @@ -45,6 +45,9 @@ public abstract class ItemMainAuthoring : ItemAuthoring> _children = new List>(); + ///

/// Returns all child mesh components linked to this data. /// @@ -58,6 +61,8 @@ public abstract class ItemMainAuthoring : ItemAuthoring (IItemColliderAuthoring) c) .Where(ca => ca.ItemData == _data) : new IItemColliderAuthoring[0]; + private IItemMainAuthoring ParentAuthoring => transform.parent.GetComponent(); + public IItemMainAuthoring SetItem(TItem item, string gameObjectName = null) { _item = item; @@ -139,6 +144,12 @@ protected void Convert(Entity entity, EntityManager dstManager) { Item.Index = entity.Index; Item.Version = entity.Version; + + var parentAuthoring = ParentAuthoring; + if (parentAuthoring != null && !(parentAuthoring is TableAuthoring)) { + Item.ParentIndex = parentAuthoring.IItem.Index; + Item.ParentVersion = parentAuthoring.IItem.Version; + } } protected virtual void OnDrawGizmos() diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs index 07b96a9d9..8a6750717 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMovementAuthoring.cs @@ -28,7 +28,7 @@ public abstract class ItemMovementAuthoring : Item where TItem : Item, IHittable, IRenderable where TMainAuthoring : ItemMainAuthoring { - protected Entity Entity { + protected Entity MainEntity { get { var ma = MainAuthoring; if (ma == null) { @@ -41,7 +41,7 @@ protected Entity Entity { protected void LinkToParentEntity(Entity entity, EntityManager dstManager) { - dstManager.AddComponentData(entity, new Parent {Value = Entity}); + dstManager.AddComponentData(entity, new Parent {Value = MainEntity}); dstManager.AddComponentData(entity, new LocalToParent()); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs index f7cce6b3b..1cb74bcc5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs @@ -47,7 +47,7 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio Item.Init(table); var hit = Item.PlungerHit; - hit.SetIndex(entity.Index, entity.Version); + hit.SetIndex(entity.Index, entity.Version, 0, 0); dstManager.AddComponentData(entity, new PlungerStaticData { MomentumXfer = Data.MomentumXfer, diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAnimationAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAnimationAuthoring.cs index 901a7eca6..f381f0cb8 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAnimationAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAnimationAuthoring.cs @@ -24,7 +24,7 @@ public class SpinnerPlateAnimationAuthoring : ItemMovementAuthoring(spinnerEntity); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerCollider.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerCollider.cs index 850600e41..048189aed 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerCollider.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerCollider.cs @@ -49,7 +49,7 @@ private static void Collide(ref BallData ball, ref NativeQueue.Parall animationData.HitEvent = true; } - events.Enqueue(new EventData(EventId.HitEventsHit, coll.Entity, true)); + events.Enqueue(new EventData(EventId.HitEventsHit, coll.ParentEntity, true)); } else { BallData.SetOutsideOf(ref insideOfs, coll.Entity); @@ -57,7 +57,7 @@ private static void Collide(ref BallData ball, ref NativeQueue.Parall animationData.UnHitEvent = true; } - events.Enqueue(new EventData(EventId.HitEventsUnhit, coll.Entity, true)); + events.Enqueue(new EventData(EventId.HitEventsUnhit, coll.ParentEntity, true)); } } } From 216af0065d149067e4c2daff0b3f181df0d19178 Mon Sep 17 00:00:00 2001 From: freezy Date: Sat, 24 Oct 2020 22:43:21 +0200 Subject: [PATCH 099/124] editor: Add trough icon. --- .../Resources/Icons/large_blue/trough.png | Bin 0 -> 7652 bytes .../Icons/large_blue/trough.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/large_gray/trough.png | Bin 0 -> 7704 bytes .../Icons/large_gray/trough.png.meta | 106 ++++++++++++++++++ .../Icons/large_green/player.png.meta | 16 ++- .../Resources/Icons/large_green/trough.png | Bin 0 -> 7670 bytes .../Icons/large_green/trough.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/large_orange/trough.png | Bin 0 -> 7689 bytes .../Icons/large_orange/trough.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_blue/trough.png | Bin 0 -> 747 bytes .../Icons/small_blue/trough.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_gray/trough.png | Bin 0 -> 759 bytes .../Icons/small_gray/trough.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_green/trough.png | Bin 0 -> 753 bytes .../Icons/small_green/trough.png.meta | 106 ++++++++++++++++++ .../Resources/Icons/small_orange/trough.png | Bin 0 -> 759 bytes .../Icons/small_orange/trough.png.meta | 106 ++++++++++++++++++ 17 files changed, 862 insertions(+), 2 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_blue/trough.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_blue/trough.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_gray/trough.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_gray/trough.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/trough.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/trough.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/trough.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/trough.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/trough.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/trough.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/trough.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/trough.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/trough.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/trough.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/trough.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/trough.png.meta diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_blue/trough.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_blue/trough.png new file mode 100644 index 0000000000000000000000000000000000000000..98cbf91be53af929026e7352025062e1544f12ac GIT binary patch literal 7652 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 literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_blue/trough.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_blue/trough.png.meta new file mode 100644 index 000000000..09442d1fb --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_blue/trough.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 62d9cc09d846a5744ba955f55e848c23 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + 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 + 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: 512 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_gray/trough.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_gray/trough.png new file mode 100644 index 0000000000000000000000000000000000000000..7668c8196be3f40479e2ea89cf04d012d6c99854 GIT binary patch literal 7704 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 QZ2*7HoVGbtVd|0aKeU~LZ~y=R literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/trough.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/trough.png.meta new file mode 100644 index 000000000..bc57d4f3e --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_green/trough.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: a5c2f60a2f3cd7f41abc085a0d021f0c +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + 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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + 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 + 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: 512 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/trough.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/trough.png new file mode 100644 index 0000000000000000000000000000000000000000..d9b8e7998540876d2107d72de0b9fe125ed5b6ae GIT binary patch literal 7689 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 literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/trough.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/trough.png.meta new file mode 100644 index 000000000..d07b9fc36 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_blue/trough.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: b5a09839ee0d35a4e92594631780c884 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/trough.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/trough.png new file mode 100644 index 0000000000000000000000000000000000000000..6c0ca0135f7cd8893883d391b2f018fe2448c462 GIT binary patch literal 759 zcmVhU?zcbaVz=AjE#TdoVA&Jx z06o#R(GzVOJ<+yt>H9q))d;`@z!<;~zyd&#CUJQVqRtj7q{;x?de+kcz_mry+swX%c6~T9Qh}avAW~O8|MA#QCX*vOPKtSbMM) zQqlVd05=9n!WDp@LaK$3YIq7!JDJ7-Yd`Sj5s|5}CBk!;BRCQx{W(oyr>yMIhYqLL z6j~zP(EgLI8cZLi&>j_1Q4~rCNw9Qog;W(?+eAZZAA*w0S5pjF zCQn552PT_yl58A5M&ACGCh?SQOOKro#SwDZ+w1Z)7gAlZ?iSX`M{K_^BE9ax#<>qbE?J9T?fK8*B~MnrS&(QRXC zkzYH=W}bRV2cMX0h-k^$>>68BF8mx?!?`|GVRN};!-!vFe%5u3V=&;PHQVOK(z-X% zd=q|TkdHh)xht$J@}-xk3p`Yto(~yDPQf-!;^EQPj>arHHlAHbh8o4h`!BQ(Ts9VF z0p}WNdc6(FgoXZC7<$*953MlQlw@bQaW?d>pD*eCJw@+TT#Z|LH%sIuP2&B0@oMkz pS?|N(@^o(Ww|Q-&C)z3i`~&Ei3vUszfqDP{002ovPDHLkV1oMyULODe literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/trough.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/trough.png.meta new file mode 100644 index 000000000..46ef42bd9 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_gray/trough.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: eb32dca48cf4f064e9a44f9cdad762eb +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 64 + 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: 64 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/trough.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/trough.png new file mode 100644 index 0000000000000000000000000000000000000000..13c85e864120711d5198cd5c29f7d9a288f519e4 GIT binary patch literal 753 zcmVZXj*J`7S&1Qr5An`6JJJ1uT z18rL!Xxr*Q+ty|1`;?YF00RJh011E@fJr9G>KvfnBUEXb1Go>&nF1JQqI^C%ouz+L zue2P$0!jM9(fzNgMO0}?Y5vs^;72CP+?q>P$=NPf{O37zIH)lYUG0JYm8DJ zJ8``1)1A_C6apP{=$j~SIIbq%culjgdq)j46Xg=X$UCL3$4rzHPJN6jE?-S`#Wr~X zH6IwZ;7zjfd>KXidnU>ukF5gZLYf?4m+g2{p2kYcYxdpDS$U5KF9W4x*zk~;(tM?5 zBdo%^1mGLj#or7)GO%1yYGU}Wd)_m*YG~~7yWQXy(?7Q{$0j({75{9bPYnv& zC+9=M?C1s8#9gW3#XdEB*Q2o+fl|bN#w^jJg$=*2738wB@13+CdZtSw(1OqCwl#O) zmmb(WP)}*$1A7jER_x7FYi-+wpNZ3)n?+4r76R?@iIMVzw85#-mR63}gBvZ>;indS z8aR_rrG*1u1wnn{rrM5tOfzzf)|n`igRdQ}UbJsLPhlB4C_6@TqEtM zw_%yM)E_F#?>WP)J&7() j=T>){*S0#)Rt4ZMbgT^bF{h3P00000NkvXXu0mjfrKw%+ literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/trough.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/trough.png.meta new file mode 100644 index 000000000..cfa9691cb --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_green/trough.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: 9a2cb2a8ab09823409fb1ab2312bf360 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/trough.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/trough.png new file mode 100644 index 0000000000000000000000000000000000000000..d76a65a93a376f9e648e0bed877dd11bf0083318 GIT binary patch literal 759 zcmV-u+^!=WaVgz6UU<_agU;!YHlA=5ZQD+NPQltQGJ!|d(OrxZD?3|r} ze?qUMm_I|3@QJl7hngt094JQBtJFT9Qi2avAW~O8{Av6xpeVvOPKtSbMNl zQqcPc05=9n!WDp@N{WS&Vt5KsJDJ7-Yv1waF_EdUCBk!;BRCQx{W(esr>yMIhYqLL z6j~zP(Efw28cZLi&>mG%P!viBNw9Qol@t|S+eAZZ9&OOKro`4Mv2+w1Z)S5jQD?iSX`M{K%Z!MU$9{wy(SemozHSucvQxJw<-G_ah

b9q!=E3?P$!RW8>L{WT;V0y#GS$z-41$ z7I3bSrq|n$OjziTg`s!t`Ope;O-Xi^8)rlB`uUvR-%|8m#MQW^ce6xpqNLc*7cce> ppY=WrE>Gu1f1B4fdZMiYz+YJ@3GS3Ol!*WU002ovPDHLkV1iR}WVHYQ literal 0 HcmV?d00001 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/trough.png.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/trough.png.meta new file mode 100644 index 000000000..4bdd2ef0e --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/small_orange/trough.png.meta @@ -0,0 +1,106 @@ +fileFormatVersion: 2 +guid: b40cab9a7ee497648bc7d70ea4717888 +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 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: -1 + 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 + 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: 64 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + 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: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: From a04519bd0521a458634a080e7892790cadb76f45 Mon Sep 17 00:00:00 2001 From: Eli Curtz Date: Sat, 24 Oct 2020 16:13:45 -0700 Subject: [PATCH 100/124] More empty boilerplate trough classes --- VisualPinball.Engine/VPT/Trough/TroughData.cs | 23 ++-- .../Inspectors/TroughInspector.cs | 5 +- .../Resources/Icons/large_orange/trough.png | Bin 0 -> 7689 bytes .../Icons/large_orange/trough.png.meta | 106 ++++++++++++++++++ .../VPT/Trough/TroughAuthoring.cs | 42 +++---- .../VPT/Trough/TroughAuthoring.cs.meta | 2 +- .../VPT/Trough/TroughBallData.cs | 25 +++++ .../VPT/Trough/TroughBallData.cs.meta | 11 ++ .../VPT/Trough/TroughDisplacementSystem.cs | 51 +++++++++ .../Trough/TroughDisplacementSystem.cs.meta | 11 ++ .../VPT/Trough/TroughStaticData.cs | 30 +++++ .../VPT/Trough/TroughStaticData.cs.meta | 11 ++ 12 files changed, 275 insertions(+), 42 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/trough.png create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/trough.png.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughBallData.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughBallData.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughDisplacementSystem.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughDisplacementSystem.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughStaticData.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughStaticData.cs.meta diff --git a/VisualPinball.Engine/VPT/Trough/TroughData.cs b/VisualPinball.Engine/VPT/Trough/TroughData.cs index b86eab083..080ae3d22 100644 --- a/VisualPinball.Engine/VPT/Trough/TroughData.cs +++ b/VisualPinball.Engine/VPT/Trough/TroughData.cs @@ -39,15 +39,15 @@ public class TroughData : ItemData [BiffString("NAME", IsWideString = true, Pos = 9)] public string Name; - [BiffVertex("ENTR", Pos = 1)] - public Vertex2D Entrance; + [BiffString("ENTK", Pos = 1)] + public string EntryKicker = string.Empty; - [BiffFloat("EXIT", Pos = 10)] - public float ExitOffset = 200.0f; + [BiffString("ENTS", Pos = 2)] + public string EntrySwitch = string.Empty; + + [BiffString("EXIT", Pos = 10)] + public string ExitKicker = string.Empty; - [BiffFloat("ORIN", Pos = 10)] - public float Orientation = 0.0f; - [BiffInt("BCNT", Pos = 3)] public int BallCount = 3; @@ -57,15 +57,6 @@ public class TroughData : ItemData [BiffFloat("TIME", Pos = 5)] public float SettleTime = 0.1f; - [BiffFloat("FORC", Pos = 6)] - public float Force = 15f; - - [BiffFloat("BSCT", Pos = 7)] - public float Scatter = 0f; - - [BiffString("SURF", Pos = 16)] - public string Surface = string.Empty; - #region BIFF static TroughData() diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TroughInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TroughInspector.cs index 27d9eca9e..61fdd8cc6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TroughInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TroughInspector.cs @@ -36,10 +36,7 @@ public override void OnInspectorGUI() OnPreInspectorGUI(); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("", ref _trough.data.Entrance); - ItemDataField("Rotation", ref _trough.data.Orientation); - ItemDataField("Exit Offset", ref _trough.data.ExitOffset); - SurfaceField("Surface", ref _trough.data.Surface); + //ItemDataField("", ref _trough.data.Entrance); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/trough.png b/VisualPinball.Unity/VisualPinball.Unity.Editor/Resources/Icons/large_orange/trough.png new file mode 100644 index 0000000000000000000000000000000000000000..d9b8e7998540876d2107d72de0b9fe125ed5b6ae GIT binary patch literal 7689 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 } } - - public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) - { - //Convert(entity, dstManager); - //dstManager.AddComponentData(entity, new LineSlingshotData - //{ - // IsDisabled = false, - // Threshold = data.SlingshotThreshold, - //}); - //transform.GetComponentInParent().RegisterTrough(Item, entity, gameObject); - } - - public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; - public override Vector3 GetEditorPosition() => data.Entrance.ToUnityVector3(0f); - public override void SetEditorPosition(Vector3 pos) => data.Entrance = pos.ToVertex2Dxy(); - public override ItemDataTransformType EditorRotationType => ItemDataTransformType.OneD; - public override Vector3 GetEditorRotation() => new Vector3(data.Orientation, 0, 0); - public override void SetEditorRotation(Vector3 rot) => data.Orientation = rot.x; + public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) + { + Convert(entity, dstManager); + dstManager.AddComponentData(entity, new TroughStaticData + { + BallCount = data.BallCount, + SwitchCount = data.SwitchCount, + SettleTime = data.SettleTime + }); + } + + //public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; + //public override Vector3 GetEditorPosition() => data.Entrance.ToUnityVector3(0f); + //public override void SetEditorPosition(Vector3 pos) => data.Entrance = pos.ToVertex2Dxy(); + + //public override ItemDataTransformType EditorRotationType => ItemDataTransformType.OneD; + //public override Vector3 GetEditorRotation() => new Vector3(data.Orientation, 0, 0); + //public override void SetEditorRotation(Vector3 rot) => data.Orientation = rot.x; - public override ItemDataTransformType EditorScaleType => ItemDataTransformType.OneD; - public override Vector3 GetEditorScale() => new Vector3(data.ExitOffset, 0f, 0f); - public override void SetEditorScale(Vector3 scale) => data.ExitOffset = scale.x; + //public override ItemDataTransformType EditorScaleType => ItemDataTransformType.OneD; + //public override Vector3 GetEditorScale() => new Vector3(data.ExitOffset, 0f, 0f); + //public override void SetEditorScale(Vector3 scale) => data.ExitOffset = scale.x; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughAuthoring.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughAuthoring.cs.meta index 7309dfe10..5041f2d42 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughAuthoring.cs.meta +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughAuthoring.cs.meta @@ -5,7 +5,7 @@ MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: f9918981bd2cf4e179f31abf058bb4a5, type: 3} userData: assetBundleName: assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughBallData.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughBallData.cs new file mode 100644 index 000000000..435a783f5 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughBallData.cs @@ -0,0 +1,25 @@ +// 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 Unity.Entities; + +namespace VisualPinball.Unity +{ + internal struct TroughBallData : IComponentData + { + public Entity Ball; + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughBallData.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughBallData.cs.meta new file mode 100644 index 000000000..9b65fbf04 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughBallData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 22afee6ab190949a08a93c66465d711b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughDisplacementSystem.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughDisplacementSystem.cs new file mode 100644 index 000000000..e0ab18633 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughDisplacementSystem.cs @@ -0,0 +1,51 @@ +// 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 NLog; +using Unity.Entities; +using Unity.Mathematics; +using Unity.Profiling; + +namespace VisualPinball.Unity +{ + [UpdateInGroup(typeof(UpdateDisplacementSystemGroup))] + internal class TroughDisplacementSystem : SystemBase + { + private SimulateCycleSystemGroup _simulateCycleSystemGroup; + + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private static readonly ProfilerMarker PerfMarker = new ProfilerMarker("TroughDisplacementSystem"); + + protected override void OnCreate() + { + _simulateCycleSystemGroup = World.GetOrCreateSystem(); + } + + protected override void OnUpdate() + { + var dTime = _simulateCycleSystemGroup.HitTime; + var marker = PerfMarker; + + Entities.WithName("TroughDisplacementJob").ForEach((in TroughStaticData trough) => { + + marker.Begin(); + + marker.End(); + + }).Run(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughDisplacementSystem.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughDisplacementSystem.cs.meta new file mode 100644 index 000000000..24a841b9c --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughDisplacementSystem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4c944133fe2574256a389450992e3f12 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughStaticData.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughStaticData.cs new file mode 100644 index 000000000..fea127129 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughStaticData.cs @@ -0,0 +1,30 @@ +// 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 Unity.Entities; + +namespace VisualPinball.Unity +{ + internal struct TroughStaticData : IComponentData + { + public Entity EntrySwitch; + public Entity EntryKicker; + public Entity ExitKicker; + public int BallCount; + public int SwitchCount; + public float SettleTime; + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughStaticData.cs.meta b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughStaticData.cs.meta new file mode 100644 index 000000000..84b238a5d --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughStaticData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c4aafd68e91904edebd1ff37bb96b3fb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 92afde823300a9d5784ae3b3635c49b6ef3463d8 Mon Sep 17 00:00:00 2001 From: freezy Date: Sun, 25 Oct 2020 01:38:34 +0200 Subject: [PATCH 101/124] components: Show error for flipper components in editor when no data or wrongly parented. --- VisualPinball.Engine/VPT/BinaryData.cs | 4 +- VisualPinball.Engine/VPT/Bumper/BumperData.cs | 2 +- .../VPT/Collection/CollectionData.cs | 2 +- VisualPinball.Engine/VPT/Decal/DecalData.cs | 2 +- .../VPT/DispReel/DispReelData.cs | 2 +- .../VPT/Flasher/FlasherData.cs | 2 +- .../VPT/Flipper/FlipperData.cs | 2 +- VisualPinball.Engine/VPT/Gate/GateData.cs | 2 +- .../VPT/HitTarget/HitTargetData.cs | 2 +- VisualPinball.Engine/VPT/Item.cs | 2 +- VisualPinball.Engine/VPT/Kicker/KickerData.cs | 2 +- VisualPinball.Engine/VPT/Light/LightData.cs | 2 +- .../VPT/LightSeq/LightSeqData.cs | 2 +- .../VPT/Mappings/MappingsData.cs | 2 +- .../VPT/Plunger/PlungerData.cs | 2 +- .../VPT/Primitive/PrimitiveData.cs | 2 +- VisualPinball.Engine/VPT/Ramp/RampData.cs | 2 +- VisualPinball.Engine/VPT/Rubber/RubberData.cs | 2 +- .../VPT/Spinner/SpinnerData.cs | 2 +- .../VPT/Surface/SurfaceData.cs | 2 +- VisualPinball.Engine/VPT/Table/TableData.cs | 2 +- .../VPT/TextBox/TextBoxData.cs | 2 +- VisualPinball.Engine/VPT/TextureData.cs | 2 +- VisualPinball.Engine/VPT/Timer/TimerData.cs | 2 +- .../VPT/Trigger/TriggerData.cs | 2 +- .../VPT/Bumper/BumperColliderInspector.cs | 2 +- .../VPT/Flipper/FlipperColliderInspector.cs | 37 +++++----- .../VPT/Flipper/FlipperInspector.cs | 74 +++++++++---------- .../VPT/ItemColliderInspector.cs | 53 +++++++------ .../VPT/ItemInspector.cs | 2 + .../VPT/ItemMainInspector.cs | 56 ++++++++++++++ .../VPT/ItemMainInspector.cs.meta | 11 +++ .../VPT/Rubber/RubberColliderInspector.cs | 2 +- .../VPT/Surface/SurfaceColliderInspector.cs | 2 +- .../VPT/Bumper/BumperColliderAuthoring.cs | 3 + .../VPT/Bumper/BumperRingMeshAuthoring.cs | 3 +- .../VPT/Flipper/FlipperAuthoring.cs | 6 +- .../VPT/Flipper/FlipperBaseMeshAuthoring.cs | 6 ++ .../VPT/Flipper/FlipperColliderAuthoring.cs | 4 + .../VPT/ItemColliderAuthoring.cs | 12 +++ .../VPT/ItemMainAuthoring.cs | 14 +++- .../VPT/ItemMeshAuthoring.cs | 2 + 42 files changed, 227 insertions(+), 114 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMainInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMainInspector.cs.meta diff --git a/VisualPinball.Engine/VPT/BinaryData.cs b/VisualPinball.Engine/VPT/BinaryData.cs index 6b1e4e2c6..6ea6c4bff 100644 --- a/VisualPinball.Engine/VPT/BinaryData.cs +++ b/VisualPinball.Engine/VPT/BinaryData.cs @@ -39,10 +39,10 @@ public class BinaryData : ItemData, IImageData public override void SetName(string name) { Name = name; } [BiffString("NAME", HasExplicitLength = true, Pos = 1)] - public string Name; + public string Name = string.Empty; [BiffString("INME", Pos = 2)] - public string InternalName; + public string InternalName = string.Empty; [BiffString("PATH", Pos = 3)] public string Path; diff --git a/VisualPinball.Engine/VPT/Bumper/BumperData.cs b/VisualPinball.Engine/VPT/Bumper/BumperData.cs index 56d23cf1a..c0526de98 100644 --- a/VisualPinball.Engine/VPT/Bumper/BumperData.cs +++ b/VisualPinball.Engine/VPT/Bumper/BumperData.cs @@ -37,7 +37,7 @@ public class BumperData : ItemData public override void SetName(string name) { Name = name; } [BiffString("NAME", IsWideString = true, Pos = 17)] - public string Name; + public string Name = string.Empty; [BiffVertex("VCEN", Pos = 1)] public Vertex2D Center; diff --git a/VisualPinball.Engine/VPT/Collection/CollectionData.cs b/VisualPinball.Engine/VPT/Collection/CollectionData.cs index eb4f26a5e..e76ad027d 100644 --- a/VisualPinball.Engine/VPT/Collection/CollectionData.cs +++ b/VisualPinball.Engine/VPT/Collection/CollectionData.cs @@ -36,7 +36,7 @@ public class CollectionData : ItemData public override void SetName(string name) { Name = name; } [BiffString("NAME", IsWideString = true, Pos = 1)] - public string Name; + public string Name = string.Empty; [BiffString("ITEM", IsWideString = true, TagAll = true, Pos = 2)] public string[] ItemNames; diff --git a/VisualPinball.Engine/VPT/Decal/DecalData.cs b/VisualPinball.Engine/VPT/Decal/DecalData.cs index 722b16130..454a0a916 100644 --- a/VisualPinball.Engine/VPT/Decal/DecalData.cs +++ b/VisualPinball.Engine/VPT/Decal/DecalData.cs @@ -37,7 +37,7 @@ public class DecalData : ItemData public override void SetName(string name) { Name = name; } [BiffString("NAME", IsWideString = true, Pos = 7)] - public string Name; + public string Name = string.Empty; [BiffVertex("VCEN", Pos = 1)] public Vertex2D Center; diff --git a/VisualPinball.Engine/VPT/DispReel/DispReelData.cs b/VisualPinball.Engine/VPT/DispReel/DispReelData.cs index 92d2fac88..a395bcf6c 100644 --- a/VisualPinball.Engine/VPT/DispReel/DispReelData.cs +++ b/VisualPinball.Engine/VPT/DispReel/DispReelData.cs @@ -37,7 +37,7 @@ public class DispReelData : ItemData public override void SetName(string name) { Name = name; } [BiffString("NAME", IsWideString = true, Pos = 9)] - public string Name; + public string Name = string.Empty; [BiffVertex("VER1", Pos = 1)] public Vertex2D V1; diff --git a/VisualPinball.Engine/VPT/Flasher/FlasherData.cs b/VisualPinball.Engine/VPT/Flasher/FlasherData.cs index d0f8f7ffe..c3296b3b9 100644 --- a/VisualPinball.Engine/VPT/Flasher/FlasherData.cs +++ b/VisualPinball.Engine/VPT/Flasher/FlasherData.cs @@ -38,7 +38,7 @@ public class FlasherData : ItemData public override void SetName(string name) { Name = name; } [BiffString("NAME", IsWideString = true, Pos = 10)] - public string Name; + public string Name = string.Empty; [BiffFloat("FHEI", Pos = 1)] public float Height = 50.0f; diff --git a/VisualPinball.Engine/VPT/Flipper/FlipperData.cs b/VisualPinball.Engine/VPT/Flipper/FlipperData.cs index 2f45572a1..671c87108 100644 --- a/VisualPinball.Engine/VPT/Flipper/FlipperData.cs +++ b/VisualPinball.Engine/VPT/Flipper/FlipperData.cs @@ -41,7 +41,7 @@ public class FlipperData : ItemData public override void SetName(string name) { Name = name; } [BiffString("NAME", IsWideString = true, Pos = 14)] - public string Name; + public string Name = string.Empty; [BiffFloat("BASR", Pos = 2)] public float BaseRadius = 21.5f; diff --git a/VisualPinball.Engine/VPT/Gate/GateData.cs b/VisualPinball.Engine/VPT/Gate/GateData.cs index 9d72db9e9..37554094b 100644 --- a/VisualPinball.Engine/VPT/Gate/GateData.cs +++ b/VisualPinball.Engine/VPT/Gate/GateData.cs @@ -37,7 +37,7 @@ public class GateData : ItemData public override void SetName(string name) { Name = name; } [BiffString("NAME", IsWideString = true, Pos = 18)] - public string Name; + public string Name = string.Empty; [BiffFloat("GAMA", Pos = 12)] public float AngleMax = MathF.PI / 2.0f; diff --git a/VisualPinball.Engine/VPT/HitTarget/HitTargetData.cs b/VisualPinball.Engine/VPT/HitTarget/HitTargetData.cs index b2ce81849..2e8378e98 100644 --- a/VisualPinball.Engine/VPT/HitTarget/HitTargetData.cs +++ b/VisualPinball.Engine/VPT/HitTarget/HitTargetData.cs @@ -37,7 +37,7 @@ public class HitTargetData : ItemData, IPhysicalData public override void SetName(string name) { Name = name; } [BiffString("NAME", IsWideString = true, Pos = 6)] - public string Name; + public string Name = string.Empty; [BiffFloat("PIDB", Pos = 20)] public float DepthBias; diff --git a/VisualPinball.Engine/VPT/Item.cs b/VisualPinball.Engine/VPT/Item.cs index 30f6cf984..1d164497d 100644 --- a/VisualPinball.Engine/VPT/Item.cs +++ b/VisualPinball.Engine/VPT/Item.cs @@ -37,7 +37,7 @@ public abstract class Item : IItem where TData : ItemData public string Name { - get => Data.GetName(); + get => Data.GetName() ?? string.Empty; set { Data.SetName(value); diff --git a/VisualPinball.Engine/VPT/Kicker/KickerData.cs b/VisualPinball.Engine/VPT/Kicker/KickerData.cs index da6ca2d89..c270575b7 100644 --- a/VisualPinball.Engine/VPT/Kicker/KickerData.cs +++ b/VisualPinball.Engine/VPT/Kicker/KickerData.cs @@ -38,7 +38,7 @@ public class KickerData : ItemData public override void SetName(string name) { Name = name; } [BiffString("NAME", IsWideString = true, Pos = 8)] - public string Name; + public string Name = string.Empty; [BiffInt("TYPE", Pos = 9)] public int KickerType = VisualPinball.Engine.VPT.KickerType.KickerHole; diff --git a/VisualPinball.Engine/VPT/Light/LightData.cs b/VisualPinball.Engine/VPT/Light/LightData.cs index a2a6818b0..45a5c9a5a 100644 --- a/VisualPinball.Engine/VPT/Light/LightData.cs +++ b/VisualPinball.Engine/VPT/Light/LightData.cs @@ -38,7 +38,7 @@ public class LightData : ItemData public override void SetName(string name) { Name = name; } [BiffString("NAME", IsWideString = true, Pos = 15)] - public string Name; + public string Name = string.Empty; [BiffVertex("VCEN", Pos = 1)] public Vertex2D Center; diff --git a/VisualPinball.Engine/VPT/LightSeq/LightSeqData.cs b/VisualPinball.Engine/VPT/LightSeq/LightSeqData.cs index 33fc43ebb..a8e000542 100644 --- a/VisualPinball.Engine/VPT/LightSeq/LightSeqData.cs +++ b/VisualPinball.Engine/VPT/LightSeq/LightSeqData.cs @@ -36,7 +36,7 @@ public class LightSeqData : ItemData public override void SetName(string name) { Name = name; } [BiffString("NAME", IsWideString = true, Pos = 8)] - public string Name; + public string Name = string.Empty; [BiffString("COLC", IsWideString = true, Pos = 2)] public string Collection; diff --git a/VisualPinball.Engine/VPT/Mappings/MappingsData.cs b/VisualPinball.Engine/VPT/Mappings/MappingsData.cs index ce9ffd11f..f3cbd64d5 100644 --- a/VisualPinball.Engine/VPT/Mappings/MappingsData.cs +++ b/VisualPinball.Engine/VPT/Mappings/MappingsData.cs @@ -37,7 +37,7 @@ public class MappingsData : ItemData public override void SetName(string name) { Name = name; } [BiffString("NAME", IsWideString = true, Pos = 1)] - public string Name; + public string Name = string.Empty; [BiffMappingsSwitchAttribute("MSWT", TagAll = true, Pos = 1000)] public MappingsSwitchData[] Switches = Array.Empty(); diff --git a/VisualPinball.Engine/VPT/Plunger/PlungerData.cs b/VisualPinball.Engine/VPT/Plunger/PlungerData.cs index 668795bcf..a60c70462 100644 --- a/VisualPinball.Engine/VPT/Plunger/PlungerData.cs +++ b/VisualPinball.Engine/VPT/Plunger/PlungerData.cs @@ -36,7 +36,7 @@ public class PlungerData : ItemData public override void SetName(string name) { Name = name; } [BiffString("NAME", IsWideString = true, Pos = 23)] - public string Name; + public string Name = string.Empty; [BiffInt("TYPE", Pos = 8)] public int Type = PlungerType.PlungerTypeModern; diff --git a/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs b/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs index 038c9a1d6..7fa13b368 100644 --- a/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs +++ b/VisualPinball.Engine/VPT/Primitive/PrimitiveData.cs @@ -37,7 +37,7 @@ public class PrimitiveData : ItemData, IPhysicalData public override void SetName(string name) { Name = name; } [BiffString("NAME", IsWideString = true, Pos = 15)] - public string Name; + public string Name = string.Empty; [BiffVertex("VPOS", IsPadded = true, Pos = 1)] public Vertex3D Position; diff --git a/VisualPinball.Engine/VPT/Ramp/RampData.cs b/VisualPinball.Engine/VPT/Ramp/RampData.cs index bb9af4350..b8d6d67dc 100644 --- a/VisualPinball.Engine/VPT/Ramp/RampData.cs +++ b/VisualPinball.Engine/VPT/Ramp/RampData.cs @@ -37,7 +37,7 @@ public class RampData : ItemData, IPhysicalData public override void SetName(string name) { Name = name; } [BiffString("NAME", IsWideString = true, Pos = 9)] - public string Name; + public string Name = string.Empty; [BiffFloat("RADB", Pos = 24)] public float DepthBias = 0f; diff --git a/VisualPinball.Engine/VPT/Rubber/RubberData.cs b/VisualPinball.Engine/VPT/Rubber/RubberData.cs index fb9946068..f50d20617 100644 --- a/VisualPinball.Engine/VPT/Rubber/RubberData.cs +++ b/VisualPinball.Engine/VPT/Rubber/RubberData.cs @@ -37,7 +37,7 @@ public class RubberData : ItemData, IPhysicalData public override void SetName(string name) { Name = name; } [BiffString("NAME", IsWideString = true, Pos = 8)] - public string Name; + public string Name = string.Empty; [BiffFloat("HTTP", Pos = 1)] public float Height = 25f; diff --git a/VisualPinball.Engine/VPT/Spinner/SpinnerData.cs b/VisualPinball.Engine/VPT/Spinner/SpinnerData.cs index 0e1159995..7aa70a6c9 100644 --- a/VisualPinball.Engine/VPT/Spinner/SpinnerData.cs +++ b/VisualPinball.Engine/VPT/Spinner/SpinnerData.cs @@ -37,7 +37,7 @@ public class SpinnerData : ItemData public override void SetName(string name) { Name = name; } [BiffString("NAME", IsWideString = true, Pos = 16)] - public string Name; + public string Name = string.Empty; [BiffVertex("VCEN", Pos = 1)] public Vertex2D Center; diff --git a/VisualPinball.Engine/VPT/Surface/SurfaceData.cs b/VisualPinball.Engine/VPT/Surface/SurfaceData.cs index f0d258b41..5b1ab4b3c 100644 --- a/VisualPinball.Engine/VPT/Surface/SurfaceData.cs +++ b/VisualPinball.Engine/VPT/Surface/SurfaceData.cs @@ -37,7 +37,7 @@ public class SurfaceData : ItemData, IPhysicalData public override void SetName(string name) { Name = name; } [BiffString("NAME", IsWideString = true, Pos = 16)] - public string Name; + public string Name = string.Empty; [BiffBool("HTEV", Pos = 1)] public bool HitEvent = false; diff --git a/VisualPinball.Engine/VPT/Table/TableData.cs b/VisualPinball.Engine/VPT/Table/TableData.cs index 6034e522e..119978d96 100644 --- a/VisualPinball.Engine/VPT/Table/TableData.cs +++ b/VisualPinball.Engine/VPT/Table/TableData.cs @@ -37,7 +37,7 @@ public class TableData : ItemData [BiffString("NAME", IsWideString = true, Pos = 112)] - public string Name; + public string Name = string.Empty; [BiffFloat("LEFT", Pos = 1)] public float Left; diff --git a/VisualPinball.Engine/VPT/TextBox/TextBoxData.cs b/VisualPinball.Engine/VPT/TextBox/TextBoxData.cs index 462f2ef23..fcee61db5 100644 --- a/VisualPinball.Engine/VPT/TextBox/TextBoxData.cs +++ b/VisualPinball.Engine/VPT/TextBox/TextBoxData.cs @@ -37,7 +37,7 @@ public class TextBoxData : ItemData public override void SetName(string name) { Name = name; } [BiffString("NAME", IsWideString = true, Pos = 9)] - public string Name; + public string Name = string.Empty; [BiffVertex("VER1", Pos = 1)] public Vertex2D V1; diff --git a/VisualPinball.Engine/VPT/TextureData.cs b/VisualPinball.Engine/VPT/TextureData.cs index 6daa14071..59281d76e 100644 --- a/VisualPinball.Engine/VPT/TextureData.cs +++ b/VisualPinball.Engine/VPT/TextureData.cs @@ -38,7 +38,7 @@ public class TextureData : ItemData public override void SetName(string name) { Name = name; } [BiffString("NAME", HasExplicitLength = true, Pos = 1)] - public string Name; + public string Name = string.Empty; [BiffString("INME", Pos = 2)] public string InternalName; diff --git a/VisualPinball.Engine/VPT/Timer/TimerData.cs b/VisualPinball.Engine/VPT/Timer/TimerData.cs index 81ce467cd..4c064b1ff 100644 --- a/VisualPinball.Engine/VPT/Timer/TimerData.cs +++ b/VisualPinball.Engine/VPT/Timer/TimerData.cs @@ -36,7 +36,7 @@ public class TimerData : ItemData public override void SetName(string name) { Name = name; } [BiffString("NAME", IsWideString = true, Pos = 4)] - public string Name; + public string Name = string.Empty; [BiffVertex("VCEN", Pos = 1)] public Vertex2D Center; diff --git a/VisualPinball.Engine/VPT/Trigger/TriggerData.cs b/VisualPinball.Engine/VPT/Trigger/TriggerData.cs index 0fbfc51b4..36c8da296 100644 --- a/VisualPinball.Engine/VPT/Trigger/TriggerData.cs +++ b/VisualPinball.Engine/VPT/Trigger/TriggerData.cs @@ -37,7 +37,7 @@ public class TriggerData : ItemData public override void SetName(string name) { Name = name; } [BiffString("NAME", IsWideString = true, Pos = 14)] - public string Name; + public string Name = string.Empty; [BiffDragPoint("DPNT", TagAll = true, Pos = 2000)] public DragPointData[] DragPoints; diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs index 6369d29ef..df8060ccc 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs @@ -37,7 +37,7 @@ protected override void OnEnable() public override void OnInspectorGUI() { if (_bumperData == null) { - NoDataPanel(); + NoDataError(); return; } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperColliderInspector.cs index 0bb801459..05874a46c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperColliderInspector.cs @@ -25,31 +25,28 @@ namespace VisualPinball.Unity.Editor [CustomEditor(typeof(FlipperColliderAuthoring))] public class FlipperColliderInspector : ItemColliderInspector { - private FlipperData _flipperData; - - protected override void OnEnable() - { - base.OnEnable(); - _flipperData = Data; - } - public override void OnInspectorGUI() { - if (_flipperData == null) { - NoDataPanel(); + if (Data == null) { + NoDataError(); + return; + } + + if (!ColliderAuthoring.IsCorrectlyParented) { + InvalidParentError(); return; } - ItemDataField("Mass", ref _flipperData.Mass, false); - ItemDataField("Strength", ref _flipperData.Strength, false); - ItemDataField("Elasticity", ref _flipperData.Elasticity, false); - ItemDataField("Elasticity Falloff", ref _flipperData.ElasticityFalloff, false); - ItemDataField("Friction", ref _flipperData.Friction, false); - ItemDataField("Return Strength", ref _flipperData.Return, false); - ItemDataField("Coil Ramp Up", ref _flipperData.RampUp, false); - ItemDataField("Scatter Angle", ref _flipperData.Scatter, false); - ItemDataField("EOS Torque", ref _flipperData.TorqueDamping, false); - ItemDataField("EOS Torque Angle", ref _flipperData.TorqueDampingAngle, false); + ItemDataField("Mass", ref Data.Mass, false); + ItemDataField("Strength", ref Data.Strength, false); + ItemDataField("Elasticity", ref Data.Elasticity, false); + ItemDataField("Elasticity Falloff", ref Data.ElasticityFalloff, false); + ItemDataField("Friction", ref Data.Friction, false); + ItemDataField("Return Strength", ref Data.Return, false); + ItemDataField("Coil Ramp Up", ref Data.RampUp, false); + ItemDataField("Scatter Angle", ref Data.Scatter, false); + ItemDataField("EOS Torque", ref Data.TorqueDamping, false); + ItemDataField("EOS Torque Angle", ref Data.TorqueDampingAngle, false); base.OnInspectorGUI(); } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs index fae83f2b7..d8c07cf37 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs @@ -17,11 +17,12 @@ // ReSharper disable AssignmentInConditionalExpression using UnityEditor; +using VisualPinball.Engine.VPT.Flipper; namespace VisualPinball.Unity.Editor { [CustomEditor(typeof(FlipperAuthoring))] - public class FlipperInspector : ItemInspector + public class FlipperInspector : ItemMainInspector { private bool _foldoutPosition = true; private bool _foldoutBaseMesh; @@ -29,66 +30,63 @@ public class FlipperInspector : ItemInspector private bool _foldoutPhysics; private bool _foldoutMisc; - private FlipperAuthoring _flipper; - - protected override void OnEnable() - { - base.OnEnable(); - _flipper = (FlipperAuthoring)target; - } - public override void OnInspectorGUI() { - ItemDataField("Position", ref _flipper.Data.Center); - SurfaceField("Surface", ref _flipper.Data.Surface); + if (!ItemAuthoring.IsCorrectlyParented) { + InvalidParentError(); + return; + } + + ItemDataField("Position", ref Data.Center); + SurfaceField("Surface", ref Data.Surface); OnPreInspectorGUI(); - ItemDataField("Enabled", ref _flipper.Data.IsEnabled); - ItemDataField("Visible", ref _flipper.Data.IsVisible); + ItemDataField("Enabled", ref Data.IsEnabled); + ItemDataField("Visible", ref Data.IsVisible); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Geometry")) { - ItemDataField("Base Radius", ref _flipper.Data.BaseRadius); - ItemDataField("End Radius", ref _flipper.Data.EndRadius); - ItemDataField("Length", ref _flipper.Data.FlipperRadius); - ItemDataField("Start Angle", ref _flipper.Data.StartAngle); - ItemDataField("End Angle", ref _flipper.Data.EndAngle); - ItemDataField("Height", ref _flipper.Data.Height); - ItemDataField("Max. Difficulty Length", ref _flipper.Data.FlipperRadiusMax); + ItemDataField("Base Radius", ref Data.BaseRadius); + ItemDataField("End Radius", ref Data.EndRadius); + ItemDataField("Length", ref Data.FlipperRadius); + ItemDataField("Start Angle", ref Data.StartAngle); + ItemDataField("End Angle", ref Data.EndAngle); + ItemDataField("Height", ref Data.Height); + ItemDataField("Max. Difficulty Length", ref Data.FlipperRadiusMax); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutBaseMesh = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutBaseMesh, "Base Mesh")) { - TextureField("Image", ref _flipper.Data.Image); - MaterialField("Material", ref _flipper.Data.Material); + TextureField("Image", ref Data.Image); + MaterialField("Material", ref Data.Material); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutRubberMesh = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutRubberMesh, "Rubber Mesh")) { - MaterialField("Rubber Material", ref _flipper.Data.RubberMaterial); - ItemDataField("Rubber Thickness", ref _flipper.Data.RubberThickness, onChanged: _flipper.OnRubberWidthUpdated); - ItemDataField("Rubber Offset Height", ref _flipper.Data.RubberHeight); - ItemDataField("Rubber Width", ref _flipper.Data.RubberWidth); + MaterialField("Rubber Material", ref Data.RubberMaterial); + ItemDataField("Rubber Thickness", ref Data.RubberThickness, onChanged: ItemAuthoring.OnRubberWidthUpdated); + ItemDataField("Rubber Offset Height", ref Data.RubberHeight); + ItemDataField("Rubber Width", ref Data.RubberWidth); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "Physics")) { - ItemDataField("Mass", ref _flipper.Data.Mass, dirtyMesh: false); - ItemDataField("Strength", ref _flipper.Data.Strength, dirtyMesh: false); - ItemDataField("Elasticity", ref _flipper.Data.Elasticity, dirtyMesh: false); - ItemDataField("Elasticity Falloff", ref _flipper.Data.ElasticityFalloff, dirtyMesh: false); - ItemDataField("Friction", ref _flipper.Data.Friction, dirtyMesh: false); - ItemDataField("Return Strength", ref _flipper.Data.Return, dirtyMesh: false); - ItemDataField("Coil Ramp Up", ref _flipper.Data.RampUp, dirtyMesh: false); - ItemDataField("Scatter Angle", ref _flipper.Data.Scatter, dirtyMesh: false); - ItemDataField("EOS Torque", ref _flipper.Data.TorqueDamping, dirtyMesh: false); - ItemDataField("EOS Torque Angle", ref _flipper.Data.TorqueDampingAngle, dirtyMesh: false); + ItemDataField("Mass", ref Data.Mass, false); + ItemDataField("Strength", ref Data.Strength, false); + ItemDataField("Elasticity", ref Data.Elasticity, false); + ItemDataField("Elasticity Falloff", ref Data.ElasticityFalloff, false); + ItemDataField("Friction", ref Data.Friction, false); + ItemDataField("Return Strength", ref Data.Return, false); + ItemDataField("Coil Ramp Up", ref Data.RampUp, false); + ItemDataField("Scatter Angle", ref Data.Scatter, false); + ItemDataField("EOS Torque", ref Data.TorqueDamping, false); + ItemDataField("EOS Torque Angle", ref Data.TorqueDampingAngle, false); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _flipper.Data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _flipper.Data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref Data.IsTimerEnabled, false); + ItemDataField("Timer Interval", ref Data.TimerInterval, false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs index c9a4b5974..01728c567 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs @@ -31,9 +31,9 @@ public class ItemColliderInspector, IHittable, IRenderable where TMainAuthoring : ItemMainAuthoring { - private TColliderAuthoring _colliderAuthoring; + protected TColliderAuthoring ColliderAuthoring; - protected TData Data => _colliderAuthoring == null ? null : _colliderAuthoring.Data; + protected TData Data => ColliderAuthoring == null ? null : ColliderAuthoring.Data; private bool _foldoutDebug = true; private bool _foldoutColliders; @@ -42,23 +42,23 @@ public class ItemColliderInspector h != null) .Select((h, i) => $"[{i}] {h.GetType().Name} ({h.ObjType})") @@ -92,9 +92,9 @@ public override void OnInspectorGUI() _scrollPos = EditorGUILayout.BeginScrollView(_scrollPos, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); - var selectedCollider = GUILayout.SelectionGrid(_colliderAuthoring.SelectedCollider, _currentColliders, 1); - refresh = refresh || selectedCollider == _colliderAuthoring.SelectedCollider; - _colliderAuthoring.SelectedCollider = selectedCollider; + var selectedCollider = GUILayout.SelectionGrid(ColliderAuthoring.SelectedCollider, _currentColliders, 1); + refresh = refresh || selectedCollider == ColliderAuthoring.SelectedCollider; + ColliderAuthoring.SelectedCollider = selectedCollider; EditorGUILayout.EndScrollView(); } EditorGUILayout.EndFoldoutHeaderGroup(); @@ -105,10 +105,21 @@ public override void OnInspectorGUI() } } - protected void NoDataPanel() + protected void NoDataError() { - // todo add more details - GUILayout.Label("No data! Parent missing?"); + EditorGUILayout.HelpBox($"Cannot find main component!\n\nYou must have a {typeof(TMainAuthoring).Name} component on either this GameObject, its parent or grand parent.", MessageType.Error); + } + + protected void InvalidParentError() + { + var validParentTypes = ColliderAuthoring.ValidParents.ToArray(); + var typeMessage = validParentTypes.Length > 0 + ? $"Supported parents are: [ {string.Join(", ", validParentTypes.Select(t => t.Name))} ]." + : $"In this case, colliders for {ColliderAuthoring.Item.ItemName} don't support any parenting at all."; + EditorGUILayout.HelpBox($"Invalid parent. This {ColliderAuthoring.Item.ItemName} is parented to a {ColliderAuthoring.ParentAuthoring.IItem.ItemName}, which VPE doesn't support.\n{typeMessage}", MessageType.Error); + if (GUILayout.Button("Open Documentation", EditorStyles.linkLabel)) { + Application.OpenURL("https://docs.visualpinball.org/creators-guide/editor/unity-components.html"); + } } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs index f0128c73c..a416d807f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs @@ -18,7 +18,9 @@ using System.Linq; using UnityEditor; using UnityEngine; +using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; +using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Surface; namespace VisualPinball.Unity.Editor diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMainInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMainInspector.cs new file mode 100644 index 000000000..b96e25e34 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMainInspector.cs @@ -0,0 +1,56 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using System.Linq; +using UnityEditor; +using UnityEngine; +using VisualPinball.Engine.Game; +using VisualPinball.Engine.VPT; + +namespace VisualPinball.Unity.Editor +{ + public class ItemMainInspector : ItemInspector + where TData : ItemData + where TItem : Item, IHittable, IRenderable + where TMainAuthoring : ItemMainAuthoring + { + protected TMainAuthoring ItemAuthoring; + protected TItem Item; + protected TData Data; + + protected override void OnEnable() + { + ItemAuthoring = (TMainAuthoring)target; + Item = ItemAuthoring.Item; + Data = ItemAuthoring.Data; + base.OnEnable(); + } + + protected void InvalidParentError() + { + var validParentTypes = ItemAuthoring.ValidParents.ToArray(); + var typeMessage = validParentTypes.Length > 0 + ? $"Supported parents are: [ {string.Join(", ", validParentTypes.Select(t => t.Name))} ]." + : $"In this case, {Item.ItemName} doesn't support any parenting at all."; + EditorGUILayout.HelpBox($"Invalid parent. This {Item.ItemName} is parented to a {ItemAuthoring.ParentAuthoring.IItem.ItemName}, which VPE doesn't support.\n{typeMessage}", MessageType.Error); + if (GUILayout.Button("Open Documentation", EditorStyles.linkLabel)) { + Application.OpenURL("https://docs.visualpinball.org/creators-guide/editor/unity-components.html"); + } + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMainInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMainInspector.cs.meta new file mode 100644 index 000000000..3601fcceb --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMainInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 043c8eabdcb8cd146b1aba4c0dd877e9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs index 6799c46d7..5d26418f2 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs @@ -37,7 +37,7 @@ protected override void OnEnable() public override void OnInspectorGUI() { if (_rubberData == null) { - NoDataPanel(); + NoDataError(); return; } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs index 2ffba9150..e2ffd2e65 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs @@ -38,7 +38,7 @@ protected override void OnEnable() public override void OnInspectorGUI() { if (_surfaceData == null) { - NoDataPanel(); + NoDataError(); return; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperColliderAuthoring.cs index 12063b505..f9045fa0b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperColliderAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Bumper; @@ -22,5 +24,6 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Bumper Collider")] public class BumperColliderAuthoring : ItemColliderAuthoring { + public override IEnumerable ValidParents => new[]{typeof(BumperAuthoring)}; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs index d87d13f7a..e33084d06 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs @@ -23,7 +23,8 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Bumper Ring Mesh")] public class BumperRingMeshAuthoring : ItemMeshAuthoring { - protected override string MeshId => BumperMeshGenerator.Ring;protected override bool IsVisible { + protected override string MeshId => BumperMeshGenerator.Ring; + protected override bool IsVisible { get => Data.IsRingVisible; set => Data.IsRingVisible = value; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs index 3ea3d8f45..10783cdf1 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs @@ -21,6 +21,8 @@ #endregion using System; +using System.Collections.Generic; +using System.Linq; using Unity.Entities; using Unity.Mathematics; using UnityEngine; @@ -39,8 +41,10 @@ public class FlipperAuthoring : ItemMainAuthoring, protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); + public override IEnumerable ValidParents => FlipperColliderAuthoring.ValidParentTypes + .Concat(FlipperBaseMeshAuthoring.ValidParentTypes) + .Distinct(); - public IHittable Hittable => Item; public ISwitchable Switchable => Item; private static readonly Color EndAngleMeshColor = new Color32(0, 255, 248, 10); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperBaseMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperBaseMeshAuthoring.cs index df25d8f0d..28474d1a3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperBaseMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperBaseMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Flipper; @@ -23,10 +25,14 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Flipper Base Mesh")] public class FlipperBaseMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + protected override string MeshId => FlipperMeshGenerator.Base; protected override bool IsVisible { get => Data.IsVisible; set => Data.IsVisible = value; } + + public override IEnumerable ValidParents => ValidParentTypes; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperColliderAuthoring.cs index c007f84ce..62137032a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperColliderAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Flipper; @@ -22,5 +24,7 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Flipper Collider")] public class FlipperColliderAuthoring : ItemColliderAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + public override IEnumerable ValidParents => ValidParentTypes; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs index 431b7239a..edb89bb23 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs @@ -15,6 +15,8 @@ // along with this program. If not, see . using System; +using System.Collections.Generic; +using System.Linq; using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; @@ -50,6 +52,16 @@ public abstract class ItemColliderAuthoring : Item public HitObject[] HitObjects { get; private set; } public new IItemMainAuthoring MainAuthoring => base.MainAuthoring; + public IItemMainAuthoring ParentAuthoring => base.MainAuthoring.ParentAuthoring; + + public virtual IEnumerable ValidParents { get; } = new Type[0]; + + public bool IsCorrectlyParented { + get { + var parentAuthoring = ParentAuthoring; + return parentAuthoring == null || ValidParents.Any(validParent => parentAuthoring.GetType() == validParent); + } + } private void OnDrawGizmosSelected() { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs index 8680f1b24..186d2a8bc 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs @@ -26,6 +26,8 @@ public abstract class ItemMainAuthoring : ItemAuthoring true; + public virtual IEnumerable ValidParents { get; } = new Type[0]; + ///

/// The serialized data, as written to the .vpx file. /// @@ -45,9 +47,6 @@ public abstract class ItemMainAuthoring : ItemAuthoring> _children = new List>(); - /// /// Returns all child mesh components linked to this data. /// @@ -61,7 +60,14 @@ public abstract class ItemMainAuthoring : ItemAuthoring (IItemColliderAuthoring) c) .Where(ca => ca.ItemData == _data) : new IItemColliderAuthoring[0]; - private IItemMainAuthoring ParentAuthoring => transform.parent.GetComponent(); + public IItemMainAuthoring ParentAuthoring => transform.parent.GetComponent(); + + public bool IsCorrectlyParented { + get { + var parentAuthoring = ParentAuthoring; + return parentAuthoring == null || ValidParents.Any(validParent => parentAuthoring.GetType() == validParent); + } + } public IItemMainAuthoring SetItem(TItem item, string gameObjectName = null) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs index b55b0aebe..ae680cd5c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs @@ -35,6 +35,8 @@ public abstract class ItemMeshAuthoring : ItemSubAutho public new IItemMainAuthoring MainAuthoring => base.MainAuthoring; + public virtual IEnumerable ValidParents { get; } = new Type[0]; + protected virtual string MeshId => null; protected abstract bool IsVisible { get; set; } From 4f3ba8564cbb7a3f012609206e7ed4138519c85d Mon Sep 17 00:00:00 2001 From: freezy Date: Sun, 25 Oct 2020 22:50:06 +0100 Subject: [PATCH 102/124] components: Add parenting API to all components. --- .../VPT/Bumper/BumperAuthoring.cs | 10 +++++++++- .../VPT/Bumper/BumperBaseMeshAuthoring.cs | 6 ++++++ .../VPT/Bumper/BumperCapMeshAuthoring.cs | 6 ++++++ .../VPT/Bumper/BumperColliderAuthoring.cs | 4 +++- .../VPT/Bumper/BumperRingAnimationAuthoring.cs | 4 ++++ .../VPT/Bumper/BumperRingMeshAuthoring.cs | 6 ++++++ .../VPT/Bumper/BumperSkirtAnimationAuthoring.cs | 4 ++++ .../VPT/Bumper/BumperSkirtMeshAuthoring.cs | 6 ++++++ .../VPT/Flipper/FlipperAuthoring.cs | 1 + .../VPT/Flipper/FlipperBaseMeshAuthoring.cs | 4 ++-- .../VPT/Flipper/FlipperRubberMeshAuthoring.cs | 6 ++++++ .../VPT/Gate/GateAuthoring.cs | 7 +++++++ .../VPT/Gate/GateBracketMeshAuthoring.cs | 6 ++++++ .../VPT/Gate/GateColliderAuthoring.cs | 5 +++++ .../VPT/Gate/GateWireAnimationAuthoring.cs | 4 ++++ .../VPT/Gate/GateWireMeshAuthoring.cs | 6 ++++++ .../VPT/HitTarget/HitTargetAuthoring.cs | 7 ++++++- .../VPT/HitTarget/HitTargetColliderAuthoring.cs | 5 +++++ .../VPT/HitTarget/HitTargetMeshAuthoring.cs | 6 ++++++ .../VPT/ItemColliderAuthoring.cs | 12 ------------ .../VisualPinball.Unity/VPT/ItemMainAuthoring.cs | 2 +- .../VisualPinball.Unity/VPT/ItemMeshAuthoring.cs | 2 -- .../VisualPinball.Unity/VPT/ItemSubAuthoring.cs | 16 +++++++++++++++- .../VPT/Kicker/KickerAuthoring.cs | 7 ++++++- .../VPT/Kicker/KickerColliderAuthoring.cs | 5 +++++ .../VPT/Kicker/KickerMeshAuthoring.cs | 6 ++++++ .../VPT/Light/LightAuthoring.cs | 5 +++++ .../VPT/Light/LightBulbMeshAuthoring.cs | 6 ++++++ .../VPT/Light/LightSocketMeshAuthoring.cs | 6 ++++++ .../VPT/Playfield/PlayfieldAuthoring.cs | 6 ++++++ .../VPT/Playfield/PlayfieldColliderAuthoring.cs | 5 +++++ .../VPT/Playfield/PlayfieldMeshAuthoring.cs | 8 +++++++- .../VPT/Plunger/PlungerAuthoring.cs | 8 ++++++++ .../VPT/Plunger/PlungerColliderAuthoring.cs | 6 ++++++ .../VPT/Plunger/PlungerFlatMeshAuthoring.cs | 5 +++++ .../VPT/Plunger/PlungerRodMeshAuthoring.cs | 5 +++++ .../VPT/Plunger/PlungerSpringMeshAuthoring.cs | 5 +++++ .../VPT/Primitive/PrimitiveAuthoring.cs | 6 ++++++ .../VPT/Primitive/PrimitiveColliderAuthoring.cs | 5 +++++ .../VPT/Primitive/PrimitiveMeshAuthoring.cs | 6 ++++++ .../VPT/Ramp/RampAuthoring.cs | 7 +++++++ .../VPT/Ramp/RampColliderAuthoring.cs | 5 +++++ .../VPT/Ramp/RampFloorMeshAuthoring.cs | 6 ++++++ .../VPT/Ramp/RampWallMeshAuthoring.cs | 6 ++++++ .../VPT/Ramp/RampWireMeshAuthoring.cs | 6 ++++++ .../VPT/Rubber/RubberAuthoring.cs | 5 +++++ .../VPT/Rubber/RubberColliderAuthoring.cs | 5 +++++ .../VPT/Rubber/RubberMeshAuthoring.cs | 6 ++++++ .../VPT/Spinner/SpinnerAuthoring.cs | 7 +++++++ .../VPT/Spinner/SpinnerBracketMeshAuthoring.cs | 6 ++++++ .../VPT/Spinner/SpinnerColliderAuthoring.cs | 5 +++++ .../Spinner/SpinnerPlateAnimationAuthoring.cs | 4 ++++ .../VPT/Spinner/SpinnerPlateMeshAuthoring.cs | 6 ++++++ .../VPT/Surface/SurfaceAuthoring.cs | 6 ++++++ .../VPT/Surface/SurfaceColliderAuthoring.cs | 5 +++++ .../VPT/Surface/SurfaceSideMeshAuthoring.cs | 6 ++++++ .../VPT/Surface/SurfaceTopMeshAuthoring.cs | 6 ++++++ .../VPT/Table/TableAuthoring.cs | 1 + .../VPT/Trigger/TriggerAuthoring.cs | 5 +++++ .../VPT/Trigger/TriggerColliderAuthoring.cs | 5 +++++ .../VPT/Trigger/TriggerMeshAuthoring.cs | 6 ++++++ 61 files changed, 326 insertions(+), 23 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs index d0706ae2a..74533995f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs @@ -21,6 +21,8 @@ #endregion using System; +using System.Collections.Generic; +using System.Linq; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.Game; @@ -38,7 +40,13 @@ public class BumperAuthoring : ItemMainAuthoring, protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); - public IHittable Hittable => Item; + public override IEnumerable ValidParents => BumperBaseMeshAuthoring.ValidParentTypes + .Concat(BumperCapMeshAuthoring.ValidParentTypes) + .Concat(BumperRingMeshAuthoring.ValidParentTypes) + .Concat(BumperSkirtMeshAuthoring.ValidParentTypes) + .Concat(BumperColliderAuthoring.ValidParentTypes) + .Distinct(); + public ISwitchable Switchable => Item; private void OnDestroy() diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs index 45b4f692b..8b2e85485 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperBaseMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Bumper; @@ -23,6 +25,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Bumper Base Mesh")] public class BumperBaseMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override string MeshId => BumperMeshGenerator.Base; protected override bool IsVisible { get => Data.IsBaseVisible; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs index a4a8b5bed..bfab317ea 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperCapMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Bumper; @@ -23,6 +25,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Bumper Cap Mesh")] public class BumperCapMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override string MeshId => BumperMeshGenerator.Cap; protected override bool IsVisible { get => Data.IsCapVisible; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperColliderAuthoring.cs index f9045fa0b..39989e148 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperColliderAuthoring.cs @@ -24,6 +24,8 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Bumper Collider")] public class BumperColliderAuthoring : ItemColliderAuthoring { - public override IEnumerable ValidParents => new[]{typeof(BumperAuthoring)}; + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs index 7c2e84474..a6de5683e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingAnimationAuthoring.cs @@ -14,6 +14,8 @@ // 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.Bumper; @@ -23,6 +25,8 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Animation/Bumper Ring Animation")] public class BumperRingAnimationAuthoring : ItemMovementAuthoring, IConvertGameObjectToEntity { + public override IEnumerable ValidParents { get; } = new Type[0]; // animation components only apply to their own + public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { var table = Table; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs index e33084d06..c669d354e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperRingMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Bumper; @@ -23,6 +25,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Bumper Ring Mesh")] public class BumperRingMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override string MeshId => BumperMeshGenerator.Ring; protected override bool IsVisible { get => Data.IsRingVisible; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs index 46d33c785..3920d0076 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtAnimationAuthoring.cs @@ -14,6 +14,8 @@ // 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 Unity.Mathematics; using UnityEngine; @@ -24,6 +26,8 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Animation/Bumper Skirt Animation")] public class BumperSkirtAnimationAuthoring : ItemMovementAuthoring, IConvertGameObjectToEntity { + public override IEnumerable ValidParents { get; } = new Type[0]; // animation components only apply to their own + public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { var bumper = Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs index baf63c263..438ea2b4f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperSkirtMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Bumper; @@ -23,6 +25,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Bumper Skirt Mesh")] public class BumperSkirtMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override string MeshId => BumperMeshGenerator.Skirt; protected override bool IsVisible { get => Data.IsSocketVisible; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs index 10783cdf1..9f8fb2514 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs @@ -43,6 +43,7 @@ public class FlipperAuthoring : ItemMainAuthoring, protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); public override IEnumerable ValidParents => FlipperColliderAuthoring.ValidParentTypes .Concat(FlipperBaseMeshAuthoring.ValidParentTypes) + .Concat(FlipperRubberMeshAuthoring.ValidParentTypes) .Distinct(); public ISwitchable Switchable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperBaseMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperBaseMeshAuthoring.cs index 28474d1a3..0e6dec591 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperBaseMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperBaseMeshAuthoring.cs @@ -27,12 +27,12 @@ public class FlipperBaseMeshAuthoring : ItemMeshAuthoring ValidParents => ValidParentTypes; + protected override string MeshId => FlipperMeshGenerator.Base; protected override bool IsVisible { get => Data.IsVisible; set => Data.IsVisible = value; } - - public override IEnumerable ValidParents => ValidParentTypes; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperRubberMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperRubberMeshAuthoring.cs index cb7a07e4a..280a85884 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperRubberMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperRubberMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Flipper; @@ -23,6 +25,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Flipper Rubber Mesh")] public class FlipperRubberMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override string MeshId => FlipperMeshGenerator.Rubber; protected override bool IsVisible { get => Data.IsVisible; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs index 3dd5173ec..36211a119 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs @@ -21,6 +21,8 @@ #endregion using System; +using System.Collections.Generic; +using System.Linq; using Unity.Entities; using Unity.Mathematics; using UnityEngine; @@ -40,6 +42,11 @@ public class GateAuthoring : ItemMainAuthoring, protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); + public override IEnumerable ValidParents => GateColliderAuthoring.ValidParentTypes + .Concat(GateBracketMeshAuthoring.ValidParentTypes) + .Concat(GateWireMeshAuthoring.ValidParentTypes) + .Distinct(); + public IHittable Hittable => Item; public ISwitchable Switchable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateBracketMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateBracketMeshAuthoring.cs index 55404cad5..e4303fd0f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateBracketMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateBracketMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Gate; @@ -23,6 +25,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Gate Bracket Mesh")] public class GateBracketMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override string MeshId => GateMeshGenerator.Bracket; protected override bool IsVisible { get => Data.IsVisible; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateColliderAuthoring.cs index 08ffededf..7cda14ed6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateColliderAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Gate; @@ -22,5 +24,8 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Gate Collider")] public class GateColliderAuthoring : ItemColliderAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAnimationAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAnimationAuthoring.cs index 343ff79ba..3afbbabf0 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAnimationAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireAnimationAuthoring.cs @@ -14,6 +14,8 @@ // 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 VisualPinball.Engine.VPT.Gate; @@ -21,6 +23,8 @@ namespace VisualPinball.Unity { public class GateWireAnimationAuthoring : ItemMovementAuthoring, IConvertGameObjectToEntity { + public override IEnumerable ValidParents { get; } = new Type[0]; // animation components only apply to their own + public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { var gateEntity = MainEntity; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireMeshAuthoring.cs index 669bc53b9..f815ba2af 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateWireMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Gate; @@ -23,6 +25,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Gate Wire Mesh")] public class GateWireMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override string MeshId => GateMeshGenerator.Wire; protected override bool IsVisible { get => Data.IsVisible; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs index 1c4d50bfb..642cb5e08 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs @@ -21,6 +21,8 @@ #endregion using System; +using System.Collections.Generic; +using System.Linq; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.Game; @@ -38,7 +40,10 @@ public class HitTargetAuthoring : ItemMainAuthoring, protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); - public IHittable Hittable => Item; + public override IEnumerable ValidParents => HitTargetColliderAuthoring.ValidParentTypes + .Concat(HitTargetMeshAuthoring.ValidParentTypes) + .Distinct(); + public ISwitchable Switchable => Item; private void OnDestroy() diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetColliderAuthoring.cs index 1020288e3..fde901f66 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetColliderAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.HitTarget; @@ -22,5 +24,8 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Hit Target Collider")] public class HitTargetColliderAuthoring : ItemColliderAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetMeshAuthoring.cs index 0059a083f..ec304dba6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.HitTarget; @@ -23,6 +25,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Hit Target Mesh")] public class HitTargetMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override bool IsVisible { get => Data.IsVisible; set => Data.IsVisible = value; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs index edb89bb23..431b7239a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemColliderAuthoring.cs @@ -15,8 +15,6 @@ // along with this program. If not, see . using System; -using System.Collections.Generic; -using System.Linq; using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; @@ -52,16 +50,6 @@ public abstract class ItemColliderAuthoring : Item public HitObject[] HitObjects { get; private set; } public new IItemMainAuthoring MainAuthoring => base.MainAuthoring; - public IItemMainAuthoring ParentAuthoring => base.MainAuthoring.ParentAuthoring; - - public virtual IEnumerable ValidParents { get; } = new Type[0]; - - public bool IsCorrectlyParented { - get { - var parentAuthoring = ParentAuthoring; - return parentAuthoring == null || ValidParents.Any(validParent => parentAuthoring.GetType() == validParent); - } - } private void OnDrawGizmosSelected() { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs index 186d2a8bc..17dd18be1 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs @@ -26,7 +26,7 @@ public abstract class ItemMainAuthoring : ItemAuthoring true; - public virtual IEnumerable ValidParents { get; } = new Type[0]; + public abstract IEnumerable ValidParents { get; } /// /// The serialized data, as written to the .vpx file. diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs index ae680cd5c..b55b0aebe 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs @@ -35,8 +35,6 @@ public abstract class ItemMeshAuthoring : ItemSubAutho public new IItemMainAuthoring MainAuthoring => base.MainAuthoring; - public virtual IEnumerable ValidParents { get; } = new Type[0]; - protected virtual string MeshId => null; protected abstract bool IsVisible { get; set; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs index 1452b6ccb..b7b396cc5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemSubAuthoring.cs @@ -1,4 +1,7 @@ -using UnityEngine; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT; @@ -56,6 +59,17 @@ public abstract class ItemSubAuthoring : ItemAutho /// public TMainAuthoring MainAuthoring => FindMainAuthoring(); + public IItemMainAuthoring ParentAuthoring => MainAuthoring.ParentAuthoring; + + public abstract IEnumerable ValidParents { get; } + + public bool IsCorrectlyParented { + get { + var parentAuthoring = ParentAuthoring; + return parentAuthoring == null || ValidParents.Any(validParent => parentAuthoring.GetType() == validParent); + } + } + private TData FindData() { var ac = FindMainAuthoring(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs index 8147f656f..2e3efe2e5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs @@ -21,6 +21,8 @@ #endregion using System; +using System.Collections.Generic; +using System.Linq; using Unity.Collections; using Unity.Entities; using Unity.Mathematics; @@ -40,7 +42,10 @@ public class KickerAuthoring : ItemMainAuthoring, protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); - public IHittable Hittable => Item; + public override IEnumerable ValidParents => KickerColliderAuthoring.ValidParentTypes + .Concat(KickerMeshAuthoring.ValidParentTypes) + .Distinct(); + public ISwitchable Switchable => Item; private void OnDestroy() diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerColliderAuthoring.cs index 811c56aea..1903bcc83 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerColliderAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Kicker; @@ -22,5 +24,8 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Kicker Collider")] public class KickerColliderAuthoring : ItemColliderAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerMeshAuthoring.cs index 6f86dae9f..29848f061 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Kicker; @@ -23,6 +25,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Kicker Bracket Mesh")] public class KickerMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override bool IsVisible { get => true; set { } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs index b42bf3bd9..6ce3a0ef5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs @@ -21,6 +21,8 @@ #endregion using System; +using System.Collections.Generic; +using System.Linq; using UnityEngine; using VisualPinball.Engine.VPT.Light; using Light = VisualPinball.Engine.VPT.Light.Light; @@ -37,6 +39,9 @@ public class LightAuthoring : ItemMainAuthoring protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); protected override Type ColliderAuthoringType { get; } = null; + public override IEnumerable ValidParents => LightBulbMeshAuthoring.ValidParentTypes + .Concat(LightSocketMeshAuthoring.ValidParentTypes) + .Distinct(); public void OnBulbEnabled(bool bulbEnabledBefore, bool bulbEnabledAfter) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightBulbMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightBulbMeshAuthoring.cs index 7a9111eb8..b0fd8f3c3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightBulbMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightBulbMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Light; using Light = VisualPinball.Engine.VPT.Light.Light; @@ -24,6 +26,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Light Bulb Mesh")] public class LightBulbMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override string MeshId => LightMeshGenerator.Bulb; protected override bool IsVisible { get => Data.ShowBulbMesh; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightSocketMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightSocketMeshAuthoring.cs index 114b3a383..2eff8bdcb 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightSocketMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightSocketMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Light; using Light = VisualPinball.Engine.VPT.Light.Light; @@ -24,6 +26,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Light Socket Mesh")] public class LightSocketMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override string MeshId => LightMeshGenerator.Socket; protected override bool IsVisible { get => Data.ShowBulbMesh; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs index 36ff39e2f..608aebaba 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs @@ -15,6 +15,8 @@ // along with this program. If not, see . using System; +using System.Collections.Generic; +using System.Linq; using Unity.Entities; using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT.Table; @@ -36,6 +38,10 @@ public class PlayfieldAuthoring : ItemMainAuthoring, protected override Type MeshAuthoringType { get; } = null; protected override Type ColliderAuthoringType { get; } = null; + public override IEnumerable ValidParents => PlayfieldColliderAuthoring.ValidParentTypes + .Concat(PlayfieldMeshAuthoring.ValidParentTypes) + .Distinct(); + public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { var table = gameObject.GetComponentInParent().Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldColliderAuthoring.cs index c71007a0f..44068d683 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldColliderAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Table; @@ -22,5 +24,8 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Playfield Collider")] public class PlayfieldColliderAuthoring : ItemColliderAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldMeshAuthoring.cs index 25d65cdff..25a566cf3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldMeshAuthoring.cs @@ -1,4 +1,6 @@ -using UnityEngine; +using System; +using System.Collections.Generic; +using UnityEngine; using VisualPinball.Engine.VPT.Table; namespace VisualPinball.Unity.Playfield @@ -7,6 +9,10 @@ namespace VisualPinball.Unity.Playfield [AddComponentMenu("Visual Pinball/Mesh/Playfield Mesh")] public class PlayfieldMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override bool IsVisible { get => true; set { } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs index 1cb74bcc5..d8116a997 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs @@ -15,6 +15,8 @@ // along with this program. If not, see . using System; +using System.Collections.Generic; +using System.Linq; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.VPT; @@ -32,6 +34,12 @@ public class PlungerAuthoring : ItemMainAuthoring, protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); + public override IEnumerable ValidParents => PlungerColliderAuthoring.ValidParentTypes + .Concat(PlungerFlatMeshAuthoring.ValidParentTypes) + .Concat(PlungerRodMeshAuthoring.ValidParentTypes) + .Concat(PlungerSpringMeshAuthoring.ValidParentTypes) + .Distinct(); + private void OnDestroy() { if (!Application.isPlaying) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerColliderAuthoring.cs index 5d89ed1f6..daf70b47a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerColliderAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Plunger; @@ -22,5 +24,9 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Plunger Collider")] public class PlungerColliderAuthoring : ItemColliderAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerFlatMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerFlatMeshAuthoring.cs index 43f45ef48..e784f191e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerFlatMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerFlatMeshAuthoring.cs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using System.Collections.Generic; using Unity.Entities; using Unity.Mathematics; @@ -27,6 +28,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Plunger Flat Mesh")] public class PlungerFlatMeshAuthoring : PlungerMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override string MeshId => PlungerMeshGenerator.Flat; internal override void SetChildEntity(ref PlungerStaticData staticData, Entity entity) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodMeshAuthoring.cs index 7e924a9aa..6c4651b9b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerRodMeshAuthoring.cs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using System.Collections.Generic; using Unity.Entities; using UnityEngine; @@ -26,6 +27,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Plunger Rod Mesh")] public class PlungerRodMeshAuthoring : PlungerMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override string MeshId => PlungerMeshGenerator.Rod; internal override void SetChildEntity(ref PlungerStaticData staticData, Entity entity) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringMeshAuthoring.cs index 6468d3abc..db58eaa62 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerSpringMeshAuthoring.cs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using System.Collections.Generic; using Unity.Entities; using UnityEngine; @@ -26,6 +27,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Plunger Spring Mesh")] public class PlungerSpringMeshAuthoring : PlungerMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override string MeshId => PlungerMeshGenerator.Spring; internal override void SetChildEntity(ref PlungerStaticData staticData, Entity entity) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs index bb89acd38..01e555409 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs @@ -21,6 +21,8 @@ #endregion using System; +using System.Collections.Generic; +using System.Linq; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.Game; @@ -37,6 +39,10 @@ public class PrimitiveAuthoring : ItemMainAuthoring, I protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); + public override IEnumerable ValidParents => PrimitiveColliderAuthoring.ValidParentTypes + .Concat(PrimitiveMeshAuthoring.ValidParentTypes) + .Distinct(); + public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { Convert(entity, dstManager); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderAuthoring.cs index 28f8c80b3..440f8e756 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Primitive; @@ -22,5 +24,8 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Primitive Collider")] public class PrimitiveColliderAuthoring : ItemColliderAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs index 70aa6bc03..6616ba72c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Primitive; @@ -23,6 +25,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Primitive Mesh")] public class PrimitiveMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override bool IsVisible { get => Data.IsVisible; set => Data.IsVisible = value; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs index 6e66b6b7e..91d91e07d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs @@ -22,6 +22,7 @@ using System; using System.Collections.Generic; +using System.Linq; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.Game; @@ -40,6 +41,12 @@ public class RampAuthoring : ItemMainAuthoring, IDragPointsEdita protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); + public override IEnumerable ValidParents => RampColliderAuthoring.ValidParentTypes + .Concat(RampFloorMeshAuthoring.ValidParentTypes) + .Concat(RampWallMeshAuthoring.ValidParentTypes) + .Concat(RampWireMeshAuthoring.ValidParentTypes) + .Distinct(); + public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { Convert(entity, dstManager); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampColliderAuthoring.cs index 114a4a384..134107a7f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampColliderAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Ramp; @@ -22,5 +24,8 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Ramp Collider")] public class RampColliderAuthoring : ItemColliderAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampFloorMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampFloorMeshAuthoring.cs index 409183306..de56f268d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampFloorMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampFloorMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Ramp; @@ -23,6 +25,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Ramp Floor Mesh")] public class RampFloorMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override string MeshId => RampMeshGenerator.Floor; protected override bool IsVisible { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWallMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWallMeshAuthoring.cs index 2d6e7ef74..ecd88903b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWallMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWallMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Ramp; @@ -23,6 +25,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Ramp Wall Mesh")] public class RampWallMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override string MeshId => RampMeshGenerator.Wall; protected override bool IsVisible { get => true; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWireMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWireMeshAuthoring.cs index e75151596..98a44a12e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWireMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampWireMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Ramp; @@ -23,6 +25,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Ramp Wire Mesh")] public class RampWireMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override string MeshId => RampMeshGenerator.Wires; protected override bool IsVisible { get => true; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs index 69fdd8f56..10d130673 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs @@ -22,6 +22,7 @@ using System; using System.Collections.Generic; +using System.Linq; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.Game; @@ -40,6 +41,10 @@ public class RubberAuthoring : ItemMainAuthoring, protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); + public override IEnumerable ValidParents => RubberColliderAuthoring.ValidParentTypes + .Concat(RubberMeshAuthoring.ValidParentTypes) + .Distinct(); + public IHittable Hittable => Item; private void OnDestroy() diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs index d485669f2..c12833a90 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberColliderAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Rubber; @@ -22,5 +24,8 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Rubber Collider")] public class RubberColliderAuthoring : ItemColliderAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberMeshAuthoring.cs index cfbc92cd8..34fcbd82e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Rubber; @@ -23,6 +25,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Rubber Mesh")] public class RubberMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override bool IsVisible { get => Data.IsVisible; set => Data.IsVisible = value; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs index 4e713bac5..fb63d6f04 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs @@ -21,6 +21,8 @@ #endregion using System; +using System.Collections.Generic; +using System.Linq; using Unity.Entities; using Unity.Mathematics; using UnityEngine; @@ -40,6 +42,11 @@ public class SpinnerAuthoring : ItemMainAuthoring, protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); + public override IEnumerable ValidParents => SpinnerColliderAuthoring.ValidParentTypes + .Concat(SpinnerBracketMeshAuthoring.ValidParentTypes) + .Concat(SpinnerPlateMeshAuthoring.ValidParentTypes) + .Distinct(); + public IHittable Hittable => Item; public ISwitchable Switchable => Item; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerBracketMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerBracketMeshAuthoring.cs index 6ea158d68..858e90390 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerBracketMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerBracketMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Spinner; @@ -23,6 +25,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Spinner Bracket Mesh")] public class SpinnerBracketMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override string MeshId => SpinnerMeshGenerator.Bracket; protected override bool IsVisible { get => Data.ShowBracket; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerColliderAuthoring.cs index 16d6035f7..5b217bfa6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerColliderAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Spinner; @@ -22,5 +24,8 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Spinner Collider")] public class SpinnerColliderAuthoring : ItemColliderAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAnimationAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAnimationAuthoring.cs index f381f0cb8..86b9a634b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAnimationAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateAnimationAuthoring.cs @@ -14,6 +14,8 @@ // 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 Unity.Mathematics; using VisualPinball.Engine.VPT.Spinner; @@ -22,6 +24,8 @@ namespace VisualPinball.Unity { public class SpinnerPlateAnimationAuthoring : ItemMovementAuthoring, IConvertGameObjectToEntity { + public override IEnumerable ValidParents { get; } = new Type[0]; // animation components only apply to their own + public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { var spinnerEntity = MainEntity; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateMeshAuthoring.cs index c88d9ddb1..c3dcb3d0c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerPlateMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Spinner; @@ -23,6 +25,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Spinner Plate Mesh")] public class SpinnerPlateMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override string MeshId => SpinnerMeshGenerator.Plate; protected override bool IsVisible { get => Data.IsVisible; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs index 36adf0f41..39c1558af 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs @@ -22,6 +22,7 @@ using System; using System.Collections.Generic; +using System.Linq; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.Game; @@ -40,6 +41,11 @@ public class SurfaceAuthoring : ItemMainAuthoring, protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); + public override IEnumerable ValidParents => SurfaceColliderAuthoring.ValidParentTypes + .Concat(SurfaceSideMeshAuthoring.ValidParentTypes) + .Concat(SurfaceTopMeshAuthoring.ValidParentTypes) + .Distinct(); + private void OnDestroy() { if (!Application.isPlaying) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs index b0e65995c..3e03b80c6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Surface; @@ -22,5 +24,8 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Surface Collider")] public class SurfaceColliderAuthoring : ItemColliderAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceSideMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceSideMeshAuthoring.cs index bc2068343..d93f1429d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceSideMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceSideMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Surface; @@ -23,6 +25,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Surface Side Mesh")] public class SurfaceSideMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override string MeshId => SurfaceMeshGenerator.Side; protected override bool IsVisible { get => Data.IsSideVisible; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceTopMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceTopMeshAuthoring.cs index d3a27b88c..4acd6a9be 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceTopMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceTopMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Surface; @@ -23,6 +25,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Surface Top Mesh")] public class SurfaceTopMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override string MeshId => SurfaceMeshGenerator.Top; protected override bool IsVisible { get => Data.IsTopBottomVisible; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs index 0b74ce376..adeda2ee0 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs @@ -60,6 +60,7 @@ public class TableAuthoring : ItemMainAuthoring protected override Type MeshAuthoringType { get; } = null; protected override Type ColliderAuthoringType { get; } = null; + public override IEnumerable ValidParents => new Type[0]; public Table Table => Item; public TableSerializedTextureContainer Textures => _sidecar?.textures; public TableSerializedSoundContainer Sounds => _sidecar?.sounds; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs index c90efe3e7..a8001c9cc 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs @@ -22,6 +22,7 @@ using System; using System.Collections.Generic; +using System.Linq; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.Game; @@ -40,6 +41,10 @@ public class TriggerAuthoring : ItemMainAuthoring, protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); protected override Type ColliderAuthoringType { get; } = typeof(ItemColliderAuthoring); + public override IEnumerable ValidParents => TriggerColliderAuthoring.ValidParentTypes + .Concat(TriggerMeshAuthoring.ValidParentTypes) + .Distinct(); + public ISwitchable Switchable => Item; private void OnDestroy() diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerColliderAuthoring.cs index 599bbd2ac..77f89ecb3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerColliderAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Trigger; @@ -22,5 +24,8 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Trigger Collider")] public class TriggerColliderAuthoring : ItemColliderAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerMeshAuthoring.cs index f2222cc2f..88719c003 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerMeshAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; using VisualPinball.Engine.VPT.Trigger; @@ -23,6 +25,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Trigger Mesh")] public class TriggerMeshAuthoring : ItemMeshAuthoring { + public static readonly Type[] ValidParentTypes = new Type[0]; + + public override IEnumerable ValidParents => ValidParentTypes; + protected override bool IsVisible { get => Data.IsVisible; set => Data.IsVisible = value; From 0cb1d6e328b04d9b42046c9ff512d36e55be3775 Mon Sep 17 00:00:00 2001 From: freezy Date: Sun, 25 Oct 2020 23:55:55 +0100 Subject: [PATCH 103/124] primitive: Add inspectors. --- .../VPT/Bumper/BumperBaseMeshInspector.cs | 3 +- .../VPT/Bumper/BumperCapMeshInspector.cs | 3 +- .../VPT/Bumper/BumperRingMeshInspector.cs | 3 +- .../VPT/Bumper/BumperRingMovementInspector.cs | 3 +- .../VPT/Bumper/BumperSkirtMeshInspector.cs | 3 +- .../VPT/Flipper/FlipperBaseMeshInspector.cs | 18 +-- .../VPT/Flipper/FlipperColliderInspector.cs | 9 +- .../VPT/Flipper/FlipperInspector.cs | 3 +- .../VPT/Flipper/FlipperRubberMeshInspector.cs | 22 +--- .../VPT/ItemColliderInspector.cs | 17 ++- .../VPT/ItemInspector.cs | 4 +- .../VPT/ItemMainInspector.cs | 10 ++ .../VPT/ItemMeshInspector.cs | 34 ++++- .../VPT/ItemMovementInspector.cs | 17 ++- .../Primitive/PrimitiveColliderInspector.cs | 66 ++++++++++ .../PrimitiveColliderInspector.cs.meta | 11 ++ .../VPT/Primitive/PrimitiveInspector.cs | 100 +++++++-------- .../VPT/Primitive/PrimitiveMeshInspector.cs | 116 ++++++++++++++++++ .../Primitive/PrimitiveMeshInspector.cs.meta | 11 ++ .../VPT/Surface/SurfaceSideMeshInspector.cs | 3 +- .../VPT/Surface/SurfaceTopMeshInspector.cs | 3 +- .../VPT/IItemMeshAuthoring.cs | 2 +- .../VPT/ItemMainAuthoring.cs | 31 ++++- .../VPT/ItemMeshAuthoring.cs | 2 +- .../VPT/Primitive/PrimitiveMeshAuthoring.cs | 4 +- 25 files changed, 377 insertions(+), 121 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveColliderInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveColliderInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveMeshInspector.cs.meta diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperBaseMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperBaseMeshInspector.cs index c7af68f0a..57196eec7 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperBaseMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperBaseMeshInspector.cs @@ -34,8 +34,7 @@ protected override void OnEnable() public override void OnInspectorGUI() { - if (Data == null) { - NoDataPanel(); + if (HasErrors()) { return; } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperCapMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperCapMeshInspector.cs index 977b3ccb1..cb95be549 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperCapMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperCapMeshInspector.cs @@ -34,8 +34,7 @@ protected override void OnEnable() public override void OnInspectorGUI() { - if (Data == null) { - NoDataPanel(); + if (HasErrors()) { return; } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMeshInspector.cs index 977d43142..2324c4235 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMeshInspector.cs @@ -34,8 +34,7 @@ protected override void OnEnable() public override void OnInspectorGUI() { - if (Data == null) { - NoDataPanel(); + if (HasErrors()) { return; } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMovementInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMovementInspector.cs index 0c5c2c47e..435cc0c39 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMovementInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMovementInspector.cs @@ -34,8 +34,7 @@ protected override void OnEnable() public override void OnInspectorGUI() { - if (Data == null) { - NoDataPanel(); + if (HasErrors()) { return; } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperSkirtMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperSkirtMeshInspector.cs index eb77919c6..8494d85ab 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperSkirtMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperSkirtMeshInspector.cs @@ -34,8 +34,7 @@ protected override void OnEnable() public override void OnInspectorGUI() { - if (Data == null) { - NoDataPanel(); + if (HasErrors()) { return; } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshInspector.cs index 038ed53a3..6b557a8a9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperBaseMeshInspector.cs @@ -24,26 +24,14 @@ namespace VisualPinball.Unity.Editor [CustomEditor(typeof(FlipperBaseMeshAuthoring))] public class FlipperBaseMeshInspector : ItemMeshInspector { - private FlipperData _flipperData; - - private bool _foldoutMaterial = true; - private bool _foldoutSlingshot = true; - - protected override void OnEnable() - { - base.OnEnable(); - _flipperData = Data; - } - public override void OnInspectorGUI() { - if (_flipperData == null) { - NoDataPanel(); + if (HasErrors()) { return; } - TextureField("Image", ref _flipperData.Image); - MaterialField("Material", ref _flipperData.Material); + TextureField("Image", ref Data.Image); + MaterialField("Material", ref Data.Material); base.OnInspectorGUI(); } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperColliderInspector.cs index 05874a46c..87f560040 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperColliderInspector.cs @@ -18,7 +18,6 @@ using UnityEditor; using VisualPinball.Engine.VPT.Flipper; -using VisualPinball.Engine.VPT.Surface; namespace VisualPinball.Unity.Editor { @@ -27,13 +26,7 @@ public class FlipperColliderInspector : ItemColliderInspector { - private FlipperData _flipperData; - - private bool _foldoutMaterial = true; - private bool _foldoutSlingshot = true; - - protected override void OnEnable() - { - base.OnEnable(); - _flipperData = Data; - } - public override void OnInspectorGUI() { - if (_flipperData == null) { - NoDataPanel(); + if (HasErrors()) { return; } - MaterialField("Rubber Material", ref _flipperData.RubberMaterial); - ItemDataField("Rubber Thickness", ref _flipperData.RubberThickness); - ItemDataField("Rubber Offset Height", ref _flipperData.RubberHeight); - ItemDataField("Rubber Width", ref _flipperData.RubberWidth); + MaterialField("Rubber Material", ref Data.RubberMaterial); + ItemDataField("Rubber Thickness", ref Data.RubberThickness); + ItemDataField("Rubber Offset Height", ref Data.RubberHeight); + ItemDataField("Rubber Width", ref Data.RubberWidth); base.OnInspectorGUI(); } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs index 01728c567..9a63f89df 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs @@ -105,12 +105,27 @@ public override void OnInspectorGUI() } } + protected bool HasErrors() + { + if (Data == null) { + NoDataError(); + return true; + } + + if (!ColliderAuthoring.IsCorrectlyParented) { + InvalidParentError(); + return true; + } + + return false; + } + protected void NoDataError() { EditorGUILayout.HelpBox($"Cannot find main component!\n\nYou must have a {typeof(TMainAuthoring).Name} component on either this GameObject, its parent or grand parent.", MessageType.Error); } - protected void InvalidParentError() + private void InvalidParentError() { var validParentTypes = ColliderAuthoring.ValidParents.ToArray(); var typeMessage = validParentTypes.Length > 0 diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs index a416d807f..125a56063 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs @@ -18,9 +18,7 @@ using System.Linq; using UnityEditor; using UnityEngine; -using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; -using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Surface; namespace VisualPinball.Unity.Editor @@ -332,7 +330,7 @@ protected virtual void FinishEdit(string label, bool dirtyMesh = true) switch (target) { case IItemMeshAuthoring meshItem: - meshItem.MainAuthoring.SetMeshDirty(); + meshItem.IMainAuthoring.SetMeshDirty(); Undo.RecordObject(this, undoLabel); break; diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMainInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMainInspector.cs index b96e25e34..12cc85c29 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMainInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMainInspector.cs @@ -41,6 +41,16 @@ protected override void OnEnable() base.OnEnable(); } + protected bool HasErrors() + { + if (!ItemAuthoring.IsCorrectlyParented) { + InvalidParentError(); + return true; + } + + return false; + } + protected void InvalidParentError() { var validParentTypes = ItemAuthoring.ValidParents.ToArray(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs index f4629ed94..7942a0d18 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs @@ -16,6 +16,8 @@ // ReSharper disable AssignmentInConditionalExpression +using System.Linq; +using UnityEditor; using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT; @@ -49,10 +51,36 @@ public override void OnInspectorGUI() } } - protected void NoDataPanel() + protected bool HasErrors() { - // todo add more details - GUILayout.Label("No data! Parent missing?"); + if (Data == null) { + NoDataError(); + return true; + } + + if (!MeshAuthoring.IsCorrectlyParented) { + InvalidParentError(); + return true; + } + + return false; + } + + private static void NoDataError() + { + EditorGUILayout.HelpBox($"Cannot find main component!\n\nYou must have a {typeof(TMainAuthoring).Name} component on either this GameObject, its parent or grand parent.", MessageType.Error); + } + + private void InvalidParentError() + { + var validParentTypes = MeshAuthoring.ValidParents.ToArray(); + var typeMessage = validParentTypes.Length > 0 + ? $"Supported parents are: [ {string.Join(", ", validParentTypes.Select(t => t.Name))} ]." + : $"In this case, meshes for {MeshAuthoring.Item.ItemName} don't support any parenting at all."; + EditorGUILayout.HelpBox($"Invalid parent. This {MeshAuthoring.Item.ItemName} is parented to a {MeshAuthoring.ParentAuthoring.IItem.ItemName}, which VPE doesn't support.\n{typeMessage}", MessageType.Error); + if (GUILayout.Button("Open Documentation", EditorStyles.linkLabel)) { + Application.OpenURL("https://docs.visualpinball.org/creators-guide/editor/unity-components.html"); + } } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMovementInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMovementInspector.cs index aa5f2229e..840bee477 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMovementInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMovementInspector.cs @@ -16,7 +16,7 @@ // ReSharper disable AssignmentInConditionalExpression -using UnityEngine; +using UnityEditor; using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT; @@ -38,10 +38,19 @@ protected override void OnEnable() base.OnEnable(); } - protected void NoDataPanel() + protected bool HasErrors() { - // todo add more details - GUILayout.Label("No data! Parent missing?"); + if (Data == null) { + NoDataError(); + return true; + } + + return false; + } + + private static void NoDataError() + { + EditorGUILayout.HelpBox($"Cannot find main component!\n\nYou must have a {typeof(TMainAuthoring).Name} component on either this GameObject, its parent or grand parent.", MessageType.Error); } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveColliderInspector.cs new file mode 100644 index 000000000..0264114fc --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveColliderInspector.cs @@ -0,0 +1,66 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Primitive; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(PrimitiveColliderAuthoring))] + public class PrimitiveColliderInspector : ItemColliderInspector + { + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + EditorGUI.BeginDisabledGroup(Data.IsToy || !Data.IsCollidable); + + ItemDataField("Has Hit Event", ref Data.HitEvent, false); + EditorGUI.BeginDisabledGroup(!Data.HitEvent); + ItemDataField("Has Hit Event", ref Data.Threshold, false); + EditorGUI.EndDisabledGroup(); + + EditorGUI.BeginDisabledGroup(Data.OverwritePhysics); + MaterialField("Physics Material", ref Data.PhysicsMaterial, false); + EditorGUI.EndDisabledGroup(); + ItemDataField("Overwrite Material Settings", ref Data.OverwritePhysics, false); + EditorGUI.BeginDisabledGroup(!Data.OverwritePhysics); + ItemDataField("Elasticity", ref Data.Elasticity, false); + ItemDataField("Elasticity Falloff", ref Data.ElasticityFalloff, false); + ItemDataField("Friction", ref Data.Friction, false); + ItemDataField("Scatter Angle", ref Data.Scatter, false); + EditorGUI.EndDisabledGroup(); + + EditorGUI.EndDisabledGroup(); + + EditorGUI.BeginDisabledGroup(Data.IsToy); + ItemDataField("Collidable", ref Data.IsCollidable, false); + EditorGUI.EndDisabledGroup(); + + ItemDataField("Toy", ref Data.IsToy, false); + + EditorGUI.BeginDisabledGroup(Data.IsToy); + ItemDataSlider("Reduce Polygons By", ref Data.CollisionReductionFactor, 0f, 1f, false); + EditorGUI.EndDisabledGroup(); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveColliderInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveColliderInspector.cs.meta new file mode 100644 index 000000000..1be84615f --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveColliderInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8bec3b11b94c2d24fb88517b33b59be3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveInspector.cs index 9fa97bded..c540d7c28 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveInspector.cs @@ -14,28 +14,28 @@ // 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 UnityEngine; using VisualPinball.Engine.Game; +using VisualPinball.Engine.VPT.Primitive; namespace VisualPinball.Unity.Editor { [CustomEditor(typeof(PrimitiveAuthoring))] - public class PrimitiveInspector : ItemInspector + public class PrimitiveInspector : ItemMainInspector { - private PrimitiveAuthoring _prim; - private bool _foldoutColorsAndFormatting = true; - private bool _foldoutPosition = true; - private bool _foldoutPhysics = true; - - protected override void OnEnable() - { - base.OnEnable(); - _prim = target as PrimitiveAuthoring; - } + private bool _foldoutColorsAndFormatting; + private bool _foldoutPosition; + private bool _foldoutPhysics; public override void OnInspectorGUI() { + if (HasErrors()) { + return; + } + OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { @@ -44,72 +44,72 @@ public override void OnInspectorGUI() if (GUILayout.Button("Export Mesh")) ExportMesh(); GUILayout.EndHorizontal(); - TextureField("Image", ref _prim.Data.Image); - TextureField("Normal Map", ref _prim.Data.NormalMap); + TextureField("Image", ref Data.Image); + TextureField("Normal Map", ref Data.NormalMap); EditorGUI.indentLevel++; - ItemDataField("Object Space", ref _prim.Data.ObjectSpaceNormalMap); + ItemDataField("Object Space", ref Data.ObjectSpaceNormalMap); EditorGUI.indentLevel--; - MaterialField("Material", ref _prim.Data.Material); + MaterialField("Material", ref Data.Material); - ItemDataField("Visible", ref _prim.Data.IsVisible); + ItemDataField("Visible", ref Data.IsVisible); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position & Translation")) { EditorGUILayout.LabelField("Base Position"); EditorGUI.indentLevel++; - ItemDataField("", ref _prim.Data.Position); + ItemDataField("", ref Data.Position); EditorGUI.indentLevel--; EditorGUILayout.LabelField("Base Size"); EditorGUI.indentLevel++; - ItemDataField("", ref _prim.Data.Size); + ItemDataField("", ref Data.Size); EditorGUI.indentLevel--; EditorGUILayout.LabelField("Rotation and Transposition"); EditorGUI.indentLevel++; - ItemDataField("0: RotX", ref _prim.Data.RotAndTra[0]); - ItemDataField("1: RotY", ref _prim.Data.RotAndTra[1]); - ItemDataField("2: RotZ", ref _prim.Data.RotAndTra[2]); - ItemDataField("3: TransX", ref _prim.Data.RotAndTra[3]); - ItemDataField("4: TransY", ref _prim.Data.RotAndTra[4]); - ItemDataField("5: TransZ", ref _prim.Data.RotAndTra[5]); - ItemDataField("6: ObjRotX", ref _prim.Data.RotAndTra[6]); - ItemDataField("7: ObjRotY", ref _prim.Data.RotAndTra[7]); - ItemDataField("8: ObjRotZ", ref _prim.Data.RotAndTra[8]); + ItemDataField("0: RotX", ref Data.RotAndTra[0]); + ItemDataField("1: RotY", ref Data.RotAndTra[1]); + ItemDataField("2: RotZ", ref Data.RotAndTra[2]); + ItemDataField("3: TransX", ref Data.RotAndTra[3]); + ItemDataField("4: TransY", ref Data.RotAndTra[4]); + ItemDataField("5: TransZ", ref Data.RotAndTra[5]); + ItemDataField("6: ObjRotX", ref Data.RotAndTra[6]); + ItemDataField("7: ObjRotY", ref Data.RotAndTra[7]); + ItemDataField("8: ObjRotZ", ref Data.RotAndTra[8]); EditorGUI.indentLevel--; } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "Physics")) { - EditorGUI.BeginDisabledGroup(_prim.Data.IsToy || !_prim.Data.IsCollidable); + EditorGUI.BeginDisabledGroup(Data.IsToy || !Data.IsCollidable); - ItemDataField("Has Hit Event", ref _prim.Data.HitEvent, dirtyMesh: false); - EditorGUI.BeginDisabledGroup(!_prim.Data.HitEvent); - ItemDataField("Has Hit Event", ref _prim.Data.Threshold, dirtyMesh: false); + ItemDataField("Has Hit Event", ref Data.HitEvent, dirtyMesh: false); + EditorGUI.BeginDisabledGroup(!Data.HitEvent); + ItemDataField("Has Hit Event", ref Data.Threshold, dirtyMesh: false); EditorGUI.EndDisabledGroup(); - EditorGUI.BeginDisabledGroup(_prim.Data.OverwritePhysics); - MaterialField("Physics Material", ref _prim.Data.PhysicsMaterial, dirtyMesh: false); + EditorGUI.BeginDisabledGroup(Data.OverwritePhysics); + MaterialField("Physics Material", ref Data.PhysicsMaterial, dirtyMesh: false); EditorGUI.EndDisabledGroup(); - ItemDataField("Overwrite Material Settings", ref _prim.Data.OverwritePhysics, dirtyMesh: false); - EditorGUI.BeginDisabledGroup(!_prim.Data.OverwritePhysics); - ItemDataField("Elasticity", ref _prim.Data.Elasticity, dirtyMesh: false); - ItemDataField("Elasticity Falloff", ref _prim.Data.ElasticityFalloff, dirtyMesh: false); - ItemDataField("Friction", ref _prim.Data.Friction, dirtyMesh: false); - ItemDataField("Scatter Angle", ref _prim.Data.Scatter, dirtyMesh: false); + ItemDataField("Overwrite Material Settings", ref Data.OverwritePhysics, dirtyMesh: false); + EditorGUI.BeginDisabledGroup(!Data.OverwritePhysics); + ItemDataField("Elasticity", ref Data.Elasticity, dirtyMesh: false); + ItemDataField("Elasticity Falloff", ref Data.ElasticityFalloff, dirtyMesh: false); + ItemDataField("Friction", ref Data.Friction, dirtyMesh: false); + ItemDataField("Scatter Angle", ref Data.Scatter, dirtyMesh: false); EditorGUI.EndDisabledGroup(); EditorGUI.EndDisabledGroup(); - EditorGUI.BeginDisabledGroup(_prim.Data.IsToy); - ItemDataField("Collidable", ref _prim.Data.IsCollidable, dirtyMesh: false); + EditorGUI.BeginDisabledGroup(Data.IsToy); + ItemDataField("Collidable", ref Data.IsCollidable, dirtyMesh: false); EditorGUI.EndDisabledGroup(); - ItemDataField("Toy", ref _prim.Data.IsToy, dirtyMesh: false); + ItemDataField("Toy", ref Data.IsToy, dirtyMesh: false); - EditorGUI.BeginDisabledGroup(_prim.Data.IsToy); - ItemDataSlider("Reduce Polygons By", ref _prim.Data.CollisionReductionFactor, 0f, 1f, dirtyMesh: false); + EditorGUI.BeginDisabledGroup(Data.IsToy); + ItemDataSlider("Reduce Polygons By", ref Data.CollisionReductionFactor, 0f, 1f, dirtyMesh: false); EditorGUI.EndDisabledGroup(); } EditorGUILayout.EndFoldoutHeaderGroup(); @@ -126,8 +126,8 @@ private void MeshImporterGui() var mesh = (Mesh)EditorGUILayout.ObjectField("Import Mesh", null, typeof(Mesh), false); if (mesh != null && EditorGUI.EndChangeCheck()) { FinishEdit("Import Mesh", true); - _prim.Data.Use3DMesh = true; - _prim.Data.Mesh = mesh.ToVpMesh(); + Data.Use3DMesh = true; + Data.Mesh = mesh.ToVpMesh(); } } @@ -136,13 +136,13 @@ private void MeshImporterGui() /// private void ExportMesh() { - var table = _prim.GetComponentInParent(); + var table = ItemAuthoring.GetComponentInParent(); if (table != null) { - var rog = _prim.Item.GetRenderObjects(table.Table, Origin.Original, false); + var rog = Item.GetRenderObjects(table.Table, Origin.Original, false); if (rog != null && rog.RenderObjects.Length > 0) { - var unityMesh = rog.RenderObjects[0].Mesh?.ToUnityMesh(_prim.name); + var unityMesh = rog.RenderObjects[0].Mesh?.ToUnityMesh(Item.Name); if (unityMesh != null) { - string savePath = EditorUtility.SaveFilePanelInProject("Export Mesh", _prim.name, "asset", "Export Mesh"); + string savePath = EditorUtility.SaveFilePanelInProject("Export Mesh", Item.Name, "asset", "Export Mesh"); AssetDatabase.CreateAsset(unityMesh, savePath); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveMeshInspector.cs new file mode 100644 index 000000000..192018b54 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveMeshInspector.cs @@ -0,0 +1,116 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using UnityEngine; +using VisualPinball.Engine.Game; +using VisualPinball.Engine.VPT.Primitive; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(PrimitiveMeshAuthoring))] + public class PrimitiveMeshInspector : ItemMeshInspector + { + private bool _foldoutColorsAndFormatting = true; + private bool _foldoutPosition = true; + + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { + GUILayout.BeginHorizontal(); + MeshImporterGui(); + if (GUILayout.Button("Export Mesh")) ExportMesh(); + GUILayout.EndHorizontal(); + + TextureField("Image", ref Data.Image); + TextureField("Normal Map", ref Data.NormalMap); + EditorGUI.indentLevel++; + ItemDataField("Object Space", ref Data.ObjectSpaceNormalMap); + EditorGUI.indentLevel--; + MaterialField("Material", ref Data.Material); + } + EditorGUILayout.EndFoldoutHeaderGroup(); + + if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position & Translation")) { + EditorGUILayout.LabelField("Base Position"); + EditorGUI.indentLevel++; + ItemDataField("", ref Data.Position); + EditorGUI.indentLevel--; + + EditorGUILayout.LabelField("Base Size"); + EditorGUI.indentLevel++; + ItemDataField("", ref Data.Size); + EditorGUI.indentLevel--; + + EditorGUILayout.LabelField("Rotation and Transposition"); + EditorGUI.indentLevel++; + ItemDataField("0: RotX", ref Data.RotAndTra[0]); + ItemDataField("1: RotY", ref Data.RotAndTra[1]); + ItemDataField("2: RotZ", ref Data.RotAndTra[2]); + ItemDataField("3: TransX", ref Data.RotAndTra[3]); + ItemDataField("4: TransY", ref Data.RotAndTra[4]); + ItemDataField("5: TransZ", ref Data.RotAndTra[5]); + ItemDataField("6: ObjRotX", ref Data.RotAndTra[6]); + ItemDataField("7: ObjRotY", ref Data.RotAndTra[7]); + ItemDataField("8: ObjRotZ", ref Data.RotAndTra[8]); + EditorGUI.indentLevel--; + } + EditorGUILayout.EndFoldoutHeaderGroup(); + + base.OnInspectorGUI(); + } + + /// + /// Shows a gui to bring a unity mesh into the table data. This immediately "bakes" right in the VPX data structures + /// + private void MeshImporterGui() + { + EditorGUI.BeginChangeCheck(); + var mesh = (Mesh)EditorGUILayout.ObjectField("Import Mesh", null, typeof(Mesh), false); + if (mesh != null && EditorGUI.EndChangeCheck()) { + FinishEdit("Import Mesh", true); + Data.Use3DMesh = true; + Data.Mesh = mesh.ToVpMesh(); + } + } + + /// + /// Pop a dialog to save the primitive's mesh as a unity asset + /// + private void ExportMesh() + { + var table = MeshAuthoring.GetComponentInParent(); + if (table != null) { + var rog = MeshAuthoring.MainAuthoring.Item.GetRenderObjects(table.Table, Origin.Original, false); + if (rog != null && rog.RenderObjects.Length > 0) { + var unityMesh = rog.RenderObjects[0].Mesh?.ToUnityMesh(MeshAuthoring.IMainAuthoring.Name); + if (unityMesh != null) { + var savePath = EditorUtility.SaveFilePanelInProject("Export Mesh", MeshAuthoring.IMainAuthoring.Name, "asset", "Export Mesh"); + if (!string.IsNullOrEmpty(savePath)) { + AssetDatabase.CreateAsset(unityMesh, savePath); + } + } + } + } + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveMeshInspector.cs.meta new file mode 100644 index 000000000..622bb076a --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6c919686f2015a44796035dcf067c311 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceSideMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceSideMeshInspector.cs index b67ea5057..0ff4a63aa 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceSideMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceSideMeshInspector.cs @@ -34,8 +34,7 @@ protected override void OnEnable() public override void OnInspectorGUI() { - if (Data == null) { - NoDataPanel(); + if (HasErrors()) { return; } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceTopMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceTopMeshInspector.cs index 4a11eb465..44021a27c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceTopMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceTopMeshInspector.cs @@ -34,8 +34,7 @@ protected override void OnEnable() public override void OnInspectorGUI() { - if (Data == null) { - NoDataPanel(); + if (HasErrors()) { return; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs index 2b1981635..dd62cca56 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs @@ -26,7 +26,7 @@ public interface IItemMeshAuthoring : IItemAuthoring List MaterialRefs { get; } List TextureRefs { get; } - IItemMainAuthoring MainAuthoring { get; } + IItemMainAuthoring IMainAuthoring { get; } void RebuildMeshes(); } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs index 17dd18be1..f1b06715d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs @@ -60,7 +60,7 @@ public abstract class ItemMainAuthoring : ItemAuthoring (IItemColliderAuthoring) c) .Where(ca => ca.ItemData == _data) : new IItemColliderAuthoring[0]; - public IItemMainAuthoring ParentAuthoring => transform.parent.GetComponent(); + public IItemMainAuthoring ParentAuthoring => FindParentAuthoring(); public bool IsCorrectlyParented { get { @@ -175,6 +175,35 @@ protected virtual void OnDrawGizmos() } } + private IItemMainAuthoring FindParentAuthoring() + { + IItemMainAuthoring ma = null; + var go = gameObject; + + // search on parent + if (go.transform.parent != null) { + ma = go.transform.parent.GetComponent(); + } + + if (ma is MonoBehaviour mb && mb.GetComponent() != null) { + return null; + } + if (ma != null) { + return ma; + } + + // search on grand parent + if (go.transform.parent.transform.parent != null) { + ma = go.transform.parent.transform.parent.GetComponent(); + } + + if (ma is MonoBehaviour mb2 && mb2.GetComponent() != null) { + return null; + } + + return ma; + } + #region Tools public virtual ItemDataTransformType EditorPositionType => ItemDataTransformType.None; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs index b55b0aebe..e351806ec 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs @@ -33,7 +33,7 @@ public abstract class ItemMeshAuthoring : ItemSubAutho public List MaterialRefs => _materialRefs ?? (_materialRefs = GetMembersWithAttribute()); public List TextureRefs => _textureRefs ?? (_textureRefs = GetMembersWithAttribute()); - public new IItemMainAuthoring MainAuthoring => base.MainAuthoring; + public IItemMainAuthoring IMainAuthoring => MainAuthoring; protected virtual string MeshId => null; protected abstract bool IsVisible { get; set; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs index 6616ba72c..c6a34a8fb 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs @@ -25,7 +25,9 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Mesh/Primitive Mesh")] public class PrimitiveMeshAuthoring : ItemMeshAuthoring { - public static readonly Type[] ValidParentTypes = new Type[0]; + public static readonly Type[] ValidParentTypes = { + typeof(BumperAuthoring), + }; public override IEnumerable ValidParents => ValidParentTypes; From 069ece347ea7210a88018e1e1903a75cdc4eba08 Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 26 Oct 2020 00:17:07 +0100 Subject: [PATCH 104/124] gate: Add inspectors. --- .../creators-guide/editor/unity-components.md | 24 ++++- .../DragPoint/DragPointMenuItems.cs | 46 ++++------ .../DragPoint/DragPointsItemInspector.cs | 11 ++- .../DragPoint/IDragPointsItemInspector.cs | 87 +++++++++++++++++++ .../IDragPointsItemInspector.cs.meta | 11 +++ .../VPT/Gate/GateBracketMeshInspector.cs | 37 ++++++++ .../VPT/Gate/GateBracketMeshInspector.cs.meta | 11 +++ .../VPT/Gate/GateColliderInspector.cs | 44 ++++++++++ .../VPT/Gate/GateColliderInspector.cs.meta | 11 +++ .../VPT/Gate/GateInspector.cs | 84 +++++++++--------- .../VPT/Gate/GateWireMeshInspector.cs | 37 ++++++++ .../VPT/Gate/GateWireMeshInspector.cs.meta | 11 +++ .../VPT/ItemColliderInspector.cs | 2 +- .../Primitive/PrimitiveColliderInspector.cs | 2 +- .../VPT/Primitive/PrimitiveInspector.cs | 45 +++++----- .../VPT/Ramp/RampInspector.cs | 80 ++++++++--------- .../VPT/Rubber/RubberInspector.cs | 32 +++---- .../VPT/Surface/SurfaceInspector.cs | 31 +++---- .../VPT/Trigger/TriggerInspector.cs | 42 ++++----- 19 files changed, 441 insertions(+), 207 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/IDragPointsItemInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/IDragPointsItemInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateBracketMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateBracketMeshInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateColliderInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateColliderInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateWireMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateWireMeshInspector.cs.meta diff --git a/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md b/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md index f7a31c652..433040551 100644 --- a/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md +++ b/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md @@ -36,13 +36,15 @@ This separation of logic comes with a few advantages. First, it's more obvious h ## Combining Components -VPE allows to mix and match components of different game items. For example, for a given game item, you can assign a collider or mesh from another type. The most common use case is replacing built-in meshes with primitives. For this, you would remove the original mesh component and replace it with a primitive mesh component. But there are other usages, like using a primitive collider on a rubber. You can also have multiple children with colliders (or meshes) for a game item. +VPE allows to mix and match components of different game items. For example, for a given game item, you can assign a collider or mesh from another type. The most common use case is replacing built-in meshes with primitives. For this, you would remove the original mesh component and replace it with a primitive mesh component. But there are other usages, like using a primitive collider on a rubber. You can also have *multiple* children with colliders (or meshes) for a game item. -The advantage compared to Visual Pinball where you would create multiple game items is that VPE treats them as one single logical entity. For example, VPE will automatically rotate a primitive flipper item when it's parented under a flipper. Or events from multiple colliders will be emitted on the same parent object. +We call this **parenting**. The game item that overrides a given behavior is still created, but *parented* to another game item. + +The advantage compared to Visual Pinball where you would create individual game items is that VPE treats them as one single logical entity. For example, VPE will automatically rotate a primitive flipper item when it's parented under a flipper. Or events from multiple colliders will be emitted on the same parent object. ### Supported Combinations -Not every game item's components can be re-used in other game items. For example it doesn't make much sense to use a flipper collider for a bumper. In fact, most of the combinations are unsupported. Here's what VPE does support so far: +Not every game item can be parented any other game items. For example it doesn't make much sense to use a flipper collider for a bumper. In fact, most of the combinations are unsupported. Here's what VPE does support so far: | | Supported Meshes | Supported Colliders | Supported Animators | |------------------|---------------------------------------------------------------|----------------------------|---------------------------| @@ -61,4 +63,18 @@ Not every game item's components can be re-used in other game items. For example | **Trigger** | Trigger, Primitive | Trigger | Trigger | -## Naming Conventions \ No newline at end of file +## Naming Conventions + +In order to keep backward compatibility with Visual Pinball, VPE relies on naming conventions to parent a game item to another. + +There are two suffixes (text you add *after* the game item's name) that have special meaning in VPE: + +- `_Mesh` applies the game item's mesh to its parent +- `_Collider` applies the game item's collider to its parent + +For example, if in Visual Pinball, you name a primitive `LeftFlipper_Mesh`, VPE will look for a `LeftFlipper` game item and replace its mesh with the mesh of `LeftFlipper_Mesh`. In other words, it will *parent* `LeftFlipper_Mesh` to `LeftFlipper` and disable `LeftFlipper`'s mesh. + +Another example: If in Visual Pinball, you name a rubber `LeftSlingshot` and two primitives `LeftSlingshot_Collider_Soft` and `LeftSlingshot_Collider_Hard`, VPE will disable the collider of `LeftSlingshot` and use the colliders of both primitives. During gameplay when the ball hits either `LeftSlingshot_Collider_Soft` or `LeftSlingshot_Collider_Hard`, the `Hit` event will be emitted on `LeftSlingshot`. + +> [!warning] +> When you *export* to `.vpx` and you have parented items but didn't follow the naming convention, the parenting will get lost when re-importing the table into VPE. In the future, VPE might propose to rename the parented children or just do it on export, but that's still on our TODO list. diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/DragPointMenuItems.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/DragPointMenuItems.cs index 692c252cb..b05aac0a4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/DragPointMenuItems.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/DragPointMenuItems.cs @@ -24,17 +24,16 @@ public static class DragPointMenuItems public const string ControlPointsMenuPath = "CONTEXT/DragPointsItemInspector/ControlPoint"; public const string CurveTravellerMenuPath = "CONTEXT/DragPointsItemInspector/CurveTraveller"; - private static DragPointData RetrieveDragPoint(DragPointsItemInspector inspector, int controlId) + private static DragPointData RetrieveDragPoint(IDragPointsItemInspector inspector, int controlId) { - return inspector == null ? null : inspector.GetDragPoint(controlId); + return inspector?.GetDragPoint(controlId); } // Drag Points [MenuItem(ControlPointsMenuPath + "/IsSlingshot", false, 1)] private static void SlingShot(MenuCommand command) { - var inspector = command.context as DragPointsItemInspector; - if (inspector == null) { + if (!(command.context is IDragPointsItemInspector inspector)) { return; } @@ -48,8 +47,7 @@ private static void SlingShot(MenuCommand command) [MenuItem(ControlPointsMenuPath + "/IsSlingshot", true)] private static bool SlingshotValidate(MenuCommand command) { - var inspector = command.context as DragPointsItemInspector; - if (inspector == null || inspector.IsItemLocked()) { + if (!(command.context is IDragPointsItemInspector inspector) || inspector.IsItemLocked()) { return false; } @@ -69,7 +67,7 @@ private static bool SlingshotValidate(MenuCommand command) [MenuItem(ControlPointsMenuPath + "/IsSmooth", false, 1)] private static void Smooth(MenuCommand command) { - var inspector = command.context as DragPointsItemInspector; + var inspector = command.context as IDragPointsItemInspector; if (inspector == null) { return; } @@ -84,8 +82,7 @@ private static void Smooth(MenuCommand command) [MenuItem(ControlPointsMenuPath + "/IsSmooth", true)] private static bool SmoothValidate(MenuCommand command) { - var inspector = command.context as DragPointsItemInspector; - if (inspector == null || inspector.IsItemLocked()) { + if (!(command.context is IDragPointsItemInspector inspector) || inspector.IsItemLocked()) { return false; } @@ -105,8 +102,7 @@ private static bool SmoothValidate(MenuCommand command) [MenuItem(ControlPointsMenuPath + "/Remove Point", false, 101)] private static void Remove(MenuCommand command) { - var inspector = command.context as DragPointsItemInspector; - if (inspector == null) { + if (!(command.context is IDragPointsItemInspector inspector)) { return; } @@ -118,8 +114,7 @@ private static void Remove(MenuCommand command) [MenuItem(ControlPointsMenuPath + "/Remove Point", true)] private static bool RemoveValidate(MenuCommand command) { - var inspector = command.context as DragPointsItemInspector; - if (inspector == null || inspector.IsItemLocked()) { + if (!(command.context is IDragPointsItemInspector inspector) || inspector.IsItemLocked()) { return false; } @@ -134,8 +129,7 @@ private static bool RemoveValidate(MenuCommand command) [MenuItem(ControlPointsMenuPath + "/Copy Point", false, 301)] private static void Copy(MenuCommand command) { - var inspector = command.context as DragPointsItemInspector; - if (inspector == null) { + if (!(command.context is IDragPointsItemInspector inspector)) { return; } @@ -145,8 +139,7 @@ private static void Copy(MenuCommand command) [MenuItem(ControlPointsMenuPath + "/Paste Point", false, 302)] private static void Paste(MenuCommand command) { - var inspector = command.context as DragPointsItemInspector; - if (inspector == null) { + if (!(command.context is IDragPointsItemInspector inspector)) { return; } @@ -156,20 +149,14 @@ private static void Paste(MenuCommand command) [MenuItem(ControlPointsMenuPath + "/Paste Point", true)] private static bool PasteValidate(MenuCommand command) { - var inspector = command.context as DragPointsItemInspector; - if (inspector == null || inspector.IsItemLocked()) { - return false; - } - - return true; + return command.context is IDragPointsItemInspector inspector && !inspector.IsItemLocked(); } //Curve Traveller [MenuItem(CurveTravellerMenuPath + "/Add Point", false, 1)] private static void Add(MenuCommand command) { - var inspector = command.context as DragPointsItemInspector; - if (inspector == null) { + if (!(command.context is IDragPointsItemInspector inspector)) { return; } @@ -180,8 +167,7 @@ private static void Add(MenuCommand command) [MenuItem(ControlPointsMenuPath + "/Flip Drag Points/X", false, 201)] private static void FlipX(MenuCommand command) { - var inspector = command.context as DragPointsItemInspector; - if (inspector == null) { + if (!(command.context is IDragPointsItemInspector inspector)) { return; } @@ -192,8 +178,7 @@ private static void FlipX(MenuCommand command) [MenuItem(ControlPointsMenuPath + "/Flip Drag Points/Y", false, 202)] private static void FlipY(MenuCommand command) { - var inspector = command.context as DragPointsItemInspector; - if (inspector == null) { + if (!(command.context is IDragPointsItemInspector inspector)) { return; } @@ -204,8 +189,7 @@ private static void FlipY(MenuCommand command) [MenuItem(ControlPointsMenuPath + "/Flip Drag Points/Z", false, 203)] private static void FlipZ(MenuCommand command) { - var inspector = command.context as DragPointsItemInspector; - if (inspector == null) { + if (!(command.context is IDragPointsItemInspector inspector)) { return; } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/DragPointsItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/DragPointsItemInspector.cs index db9e7ca09..bb1e939a4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/DragPointsItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/DragPointsItemInspector.cs @@ -18,11 +18,16 @@ using System.Linq; using UnityEditor; using UnityEngine; +using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; +using VisualPinball.Engine.VPT; namespace VisualPinball.Unity.Editor { - public abstract class DragPointsItemInspector : ItemInspector + public abstract class DragPointsItemInspector : ItemMainInspector, IDragPointsItemInspector + where TData : ItemData + where TItem : Item, IHittable, IRenderable + where TMainAuthoring : ItemMainAuthoring { /// /// Catmull Curve Handler @@ -192,8 +197,8 @@ public override void OnInspectorGUI() return; } - var enabledString = dragPointEditable.DragPointEditEnabled ? $"(ON), Stored Coordinates {_storedControlPoint}" : "(OFF)"; - if (GUILayout.Button($"Edit Drag Points {enabledString}")) { + var editButtonText = dragPointEditable.DragPointEditEnabled ? "Stop Editing Drag Points" : "Edit Drag Points"; + if (GUILayout.Button(editButtonText)) { dragPointEditable.DragPointEditEnabled = !dragPointEditable.DragPointEditEnabled; SceneView.RepaintAll(); } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/IDragPointsItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/IDragPointsItemInspector.cs new file mode 100644 index 000000000..a246d4c8b --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/IDragPointsItemInspector.cs @@ -0,0 +1,87 @@ +// 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.Unity.Editor +{ + /// + /// A non-generic interface for DragPointsItemInspector we can use for all + /// types of items. + /// + public interface IDragPointsItemInspector + { + /// + /// Catmull Curve Handler + /// + DragPointsHandler DragPointsHandler { get; } + + /// + /// Returns a reference to the drag point data for a given control ID. + /// + /// Control ID of the drag point + /// Drag point data or null if no linked data. + DragPointData GetDragPoint(int controlId); + + /// + /// Sets an UNDO point before the next operation. + /// + /// Message to appear in the UNDO menu + void PrepareUndo(string message); + + /// + /// Returns true if the game item is locked. + /// + /// True if game item is locked, false otherwise. + bool IsItemLocked(); + + /// + /// Returns whether this game item has a given drag point exposure. + /// + /// Exposure to check + /// True if exposed, false otherwise. + bool HasDragPointExposure(DragPointExposure exposure); + + /// + /// Removes a drag point of a given control ID. + /// + /// Control ID of the drag point to remove. + void RemoveDragPoint(int controlId); + + /// + /// Copies the position of a drag point. + /// + /// Control ID of the drag point + void CopyDragPoint(int controlId); + + /// + /// Sets the position of a previously copied drag point to another drag point. + /// + /// Control ID of the drag point to which the new position is applied. + void PasteDragPoint(int controlId); + + /// + /// Adds a new drag point at the traveller's current position. + /// + void AddDragPointOnTraveller(); + + /// + /// Flips all drag points on a given axis. + /// + /// Axis to flip on + void FlipDragPoints(FlipAxis flipAxis); + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/IDragPointsItemInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/IDragPointsItemInspector.cs.meta new file mode 100644 index 000000000..e0d27d079 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/DragPoint/IDragPointsItemInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 747d367bff8d4ce4e988bc6ba5503021 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateBracketMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateBracketMeshInspector.cs new file mode 100644 index 000000000..3fe209584 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateBracketMeshInspector.cs @@ -0,0 +1,37 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Gate; +using VisualPinball.Engine.VPT.Primitive; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(GateBracketMeshAuthoring))] + public class GateBracketMeshInspector : ItemMeshInspector + { + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateBracketMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateBracketMeshInspector.cs.meta new file mode 100644 index 000000000..4d5d9037b --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateBracketMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 19928bd3d78177f4daa7e8026233b07d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateColliderInspector.cs new file mode 100644 index 000000000..bc7fd6086 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateColliderInspector.cs @@ -0,0 +1,44 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Gate; +using VisualPinball.Engine.VPT.Primitive; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(GateColliderAuthoring))] + public class GateColliderInspector : ItemColliderInspector + { + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + ItemDataField("Elasticity", ref Data.Elasticity, false); + ItemDataField("Friction", ref Data.Friction, false); + ItemDataField("Damping", ref Data.Damping, false); + ItemDataField("Gravity Factor", ref Data.GravityFactor, false); + ItemDataField("Collidable", ref Data.IsCollidable, false); + ItemDataField(GateInspector.TwoWayLabel, ref Data.TwoWay, false); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateColliderInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateColliderInspector.cs.meta new file mode 100644 index 000000000..cf88e3d1b --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateColliderInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 843dae0964e2cc448a862c9c74449728 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateInspector.cs index e1397b8c5..be36d4ca9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateInspector.cs @@ -14,33 +14,29 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +// ReSharper disable AssignmentInConditionalExpression + using UnityEngine; using UnityEditor; using VisualPinball.Engine.VPT; +using VisualPinball.Engine.VPT.Gate; namespace VisualPinball.Unity.Editor { [CustomEditor(typeof(GateAuthoring))] - public class GateInspector : ItemInspector + public class GateInspector : ItemMainInspector { - private GateAuthoring _gate; private bool _foldoutColorsAndFormatting = true; private bool _foldoutPosition = true; - private bool _foldoutPhysics = true; - private bool _foldoutMisc = true; - - private static string[] _gateTypeStrings = { "Wire: 'W'", "Wire: Rectangle", "Plate", "Long Plate" }; - private static int[] _gateTypeValues = { GateType.GateWireW, GateType.GateWireRectangle, GateType.GatePlate, GateType.GateLongPlate }; + private bool _foldoutPhysics; + private bool _foldoutMisc; - private static readonly string TwoWayLabel = "Two Way"; + private static readonly string[] GateTypeLabels = { "Wire: 'W'", "Wire: Rectangle", "Plate", "Long Plate" }; + private static readonly int[] GateTypeValues = { GateType.GateWireW, GateType.GateWireRectangle, GateType.GatePlate, GateType.GateLongPlate }; - protected override void OnEnable() - { - base.OnEnable(); - _gate = target as GateAuthoring; - } + public const string TwoWayLabel = "Two Way"; - protected virtual void OnSceneGUI() + protected void OnSceneGUI() { if (target is IItemMainAuthoring editable) { var position = editable.GetEditorPosition(); @@ -49,7 +45,7 @@ protected virtual void OnSceneGUI() position = transform.parent.TransformPoint(position); var axis = transform.TransformDirection(-Vector3.up); //Local direction of the gate gameObject is -up var worldScale = 0.5f * VpxConverter.GlobalScale; - var scale = _gate.Item.Data.Length * worldScale; + var scale = Data.Length * worldScale; Handles.color = Color.white; Handles.DrawWireDisc(position, axis, scale); Color col = Color.grey; @@ -57,51 +53,60 @@ protected virtual void OnSceneGUI() Handles.color = col; Handles.DrawSolidDisc(position, axis, scale); - var arrowscale = worldScale * 100.0f; + var arrowScale = worldScale * 100.0f; Handles.color = Color.white; - Handles.ArrowHandleCap(-1, position, Quaternion.LookRotation(axis), arrowscale, EventType.Repaint); - if (_gate.Item.Data.TwoWay) { - Handles.ArrowHandleCap(-1, position, Quaternion.LookRotation(-axis), arrowscale, EventType.Repaint); + Handles.ArrowHandleCap(-1, position, Quaternion.LookRotation(axis), arrowScale, EventType.Repaint); + if (Data.TwoWay) { + Handles.ArrowHandleCap(-1, position, Quaternion.LookRotation(-axis), arrowScale, EventType.Repaint); } } } } + public override void OnInspectorGUI() { + if (HasErrors()) { + return; + } + + ItemDataField("Position", ref Data.Center); + SurfaceField("Surface", ref Data.Surface); + OnPreInspectorGUI(); + ItemDataField("Visible", ref Data.IsVisible); + if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - DropDownField("Type", ref _gate.Data.GateType, _gateTypeStrings, _gateTypeValues); - ItemDataField("Visible", ref _gate.Data.IsVisible); - ItemDataField("Show Bracket", ref _gate.Data.ShowBracket); - MaterialField("Material", ref _gate.Data.Material); + DropDownField("Type", ref Data.GateType, GateTypeLabels, GateTypeValues); + ItemDataField("Show Bracket", ref Data.ShowBracket); + MaterialField("Material", ref Data.Material); } EditorGUILayout.EndFoldoutHeaderGroup(); - if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("", ref _gate.Data.Center); - ItemDataField("Length", ref _gate.Data.Length); - ItemDataField("Height", ref _gate.Data.Height); - ItemDataField("Rotation", ref _gate.Data.Rotation); - ItemDataField("Open Angle", ref _gate.Data.AngleMax, dirtyMesh: false); - ItemDataField("Close Angle", ref _gate.Data.AngleMin, dirtyMesh: false); - SurfaceField("Surface", ref _gate.Data.Surface); + if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Geometry")) { + + ItemDataField("Length", ref Data.Length); + ItemDataField("Height", ref Data.Height); + ItemDataField("Rotation", ref Data.Rotation); + ItemDataField("Open Angle", ref Data.AngleMax, false); + ItemDataField("Close Angle", ref Data.AngleMin, false); + } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "Physics")) { - ItemDataField("Elasticity", ref _gate.Data.Elasticity, dirtyMesh: false); - ItemDataField("Friction", ref _gate.Data.Friction, dirtyMesh: false); - ItemDataField("Damping", ref _gate.Data.Damping, dirtyMesh: false); - ItemDataField("Gravity Factor", ref _gate.Data.GravityFactor, dirtyMesh: false); - ItemDataField("Collidable", ref _gate.Data.IsCollidable, dirtyMesh: false); - ItemDataField(TwoWayLabel, ref _gate.Data.TwoWay, dirtyMesh: false); + ItemDataField("Elasticity", ref Data.Elasticity, false); + ItemDataField("Friction", ref Data.Friction, false); + ItemDataField("Damping", ref Data.Damping, false); + ItemDataField("Gravity Factor", ref Data.GravityFactor, false); + ItemDataField("Collidable", ref Data.IsCollidable, false); + ItemDataField(TwoWayLabel, ref Data.TwoWay, false); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _gate.Data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _gate.Data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref Data.IsTimerEnabled, false); + ItemDataField("Timer Interval", ref Data.TimerInterval, false); } EditorGUILayout.EndFoldoutHeaderGroup(); @@ -115,6 +120,5 @@ protected override void FinishEdit(string label, bool dirtyMesh = true) } base.FinishEdit(label, dirtyMesh); } - } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateWireMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateWireMeshInspector.cs new file mode 100644 index 000000000..9c26245c6 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateWireMeshInspector.cs @@ -0,0 +1,37 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Gate; +using VisualPinball.Engine.VPT.Primitive; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(GateWireMeshAuthoring))] + public class GateWireMeshInspector : ItemMeshInspector + { + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateWireMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateWireMeshInspector.cs.meta new file mode 100644 index 000000000..5429fc616 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateWireMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a1e9d9039ec13404fb21712092021cb9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs index 9a63f89df..4b69e3e8a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs @@ -35,7 +35,7 @@ public class ItemColliderInspector ColliderAuthoring == null ? null : ColliderAuthoring.Data; - private bool _foldoutDebug = true; + private bool _foldoutDebug; private bool _foldoutColliders; private string[] _currentColliders; private Vector2 _scrollPos; diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveColliderInspector.cs index 0264114fc..15b3de785 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveColliderInspector.cs @@ -34,7 +34,7 @@ public override void OnInspectorGUI() ItemDataField("Has Hit Event", ref Data.HitEvent, false); EditorGUI.BeginDisabledGroup(!Data.HitEvent); - ItemDataField("Has Hit Event", ref Data.Threshold, false); + ItemDataField("Hit Threshold", ref Data.Threshold, false); EditorGUI.EndDisabledGroup(); EditorGUI.BeginDisabledGroup(Data.OverwritePhysics); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveInspector.cs index c540d7c28..5682938fa 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveInspector.cs @@ -36,6 +36,16 @@ public override void OnInspectorGUI() return; } + EditorGUILayout.LabelField("Base Position"); + EditorGUI.indentLevel++; + ItemDataField("", ref Data.Position); + EditorGUI.indentLevel--; + + EditorGUILayout.LabelField("Base Size"); + EditorGUI.indentLevel++; + ItemDataField("", ref Data.Size); + EditorGUI.indentLevel--; + OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { @@ -56,18 +66,6 @@ public override void OnInspectorGUI() EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position & Translation")) { - EditorGUILayout.LabelField("Base Position"); - EditorGUI.indentLevel++; - ItemDataField("", ref Data.Position); - EditorGUI.indentLevel--; - - EditorGUILayout.LabelField("Base Size"); - EditorGUI.indentLevel++; - ItemDataField("", ref Data.Size); - EditorGUI.indentLevel--; - - EditorGUILayout.LabelField("Rotation and Transposition"); - EditorGUI.indentLevel++; ItemDataField("0: RotX", ref Data.RotAndTra[0]); ItemDataField("1: RotY", ref Data.RotAndTra[1]); ItemDataField("2: RotZ", ref Data.RotAndTra[2]); @@ -77,39 +75,38 @@ public override void OnInspectorGUI() ItemDataField("6: ObjRotX", ref Data.RotAndTra[6]); ItemDataField("7: ObjRotY", ref Data.RotAndTra[7]); ItemDataField("8: ObjRotZ", ref Data.RotAndTra[8]); - EditorGUI.indentLevel--; } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "Physics")) { EditorGUI.BeginDisabledGroup(Data.IsToy || !Data.IsCollidable); - ItemDataField("Has Hit Event", ref Data.HitEvent, dirtyMesh: false); + ItemDataField("Has Hit Event", ref Data.HitEvent, false); EditorGUI.BeginDisabledGroup(!Data.HitEvent); - ItemDataField("Has Hit Event", ref Data.Threshold, dirtyMesh: false); + ItemDataField("Hit Threshold", ref Data.Threshold, false); EditorGUI.EndDisabledGroup(); EditorGUI.BeginDisabledGroup(Data.OverwritePhysics); - MaterialField("Physics Material", ref Data.PhysicsMaterial, dirtyMesh: false); + MaterialField("Physics Material", ref Data.PhysicsMaterial, false); EditorGUI.EndDisabledGroup(); - ItemDataField("Overwrite Material Settings", ref Data.OverwritePhysics, dirtyMesh: false); + ItemDataField("Overwrite Material Settings", ref Data.OverwritePhysics, false); EditorGUI.BeginDisabledGroup(!Data.OverwritePhysics); - ItemDataField("Elasticity", ref Data.Elasticity, dirtyMesh: false); - ItemDataField("Elasticity Falloff", ref Data.ElasticityFalloff, dirtyMesh: false); - ItemDataField("Friction", ref Data.Friction, dirtyMesh: false); - ItemDataField("Scatter Angle", ref Data.Scatter, dirtyMesh: false); + ItemDataField("Elasticity", ref Data.Elasticity, false); + ItemDataField("Elasticity Falloff", ref Data.ElasticityFalloff, false); + ItemDataField("Friction", ref Data.Friction, false); + ItemDataField("Scatter Angle", ref Data.Scatter, false); EditorGUI.EndDisabledGroup(); EditorGUI.EndDisabledGroup(); EditorGUI.BeginDisabledGroup(Data.IsToy); - ItemDataField("Collidable", ref Data.IsCollidable, dirtyMesh: false); + ItemDataField("Collidable", ref Data.IsCollidable, false); EditorGUI.EndDisabledGroup(); - ItemDataField("Toy", ref Data.IsToy, dirtyMesh: false); + ItemDataField("Toy", ref Data.IsToy, false); EditorGUI.BeginDisabledGroup(Data.IsToy); - ItemDataSlider("Reduce Polygons By", ref Data.CollisionReductionFactor, 0f, 1f, dirtyMesh: false); + ItemDataSlider("Reduce Polygons By", ref Data.CollisionReductionFactor, 0f, 1f, false); EditorGUI.EndDisabledGroup(); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs index 871308d21..ef92ee7df 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs @@ -14,21 +14,23 @@ // 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; +using VisualPinball.Engine.VPT.Ramp; namespace VisualPinball.Unity.Editor { [CustomEditor(typeof(RampAuthoring))] - public class RampInspector : DragPointsItemInspector + public class RampInspector : DragPointsItemInspector { - private RampAuthoring _ramp; private bool _foldoutColorsAndFormatting = true; private bool _foldoutPosition = true; private bool _foldoutPhysics = true; private bool _foldoutMisc = true; - private static string[] _rampTypeStrings = { + private static readonly string[] RampTypeLabels = { "Flat", "1 Wire", "2 Wire", @@ -36,7 +38,7 @@ public class RampInspector : DragPointsItemInspector "3 Wire Right", "4 Wire", }; - private static int[] _rampTypeValues = { + private static readonly int[] RampTypeValues = { RampType.RampTypeFlat, RampType.RampType1Wire, RampType.RampType2Wire, @@ -44,88 +46,82 @@ public class RampInspector : DragPointsItemInspector RampType.RampType3WireRight, RampType.RampType4Wire, }; - private static string[] _rampImageAlignmentStrings = { + private static readonly string[] RampImageAlignmentLabels = { "World", "Wrap", }; - private static int[] _rampImageAlignmentValues = { + private static readonly int[] RampImageAlignmentValues = { RampImageAlignment.ImageModeWorld, RampImageAlignment.ImageModeWrap, }; - protected override void OnEnable() - { - base.OnEnable(); - _ramp = target as RampAuthoring; - } - public override void OnInspectorGUI() { OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - DropDownField("Type", ref _ramp.Data.RampType, _rampTypeStrings, _rampTypeValues, onChanged: _ramp.UpdateMeshComponents); - TextureField("Image", ref _ramp.Data.Image); - MaterialField("Material", ref _ramp.Data.Material); - DropDownField("Image Mode", ref _ramp.Data.ImageAlignment, _rampImageAlignmentStrings, _rampImageAlignmentValues); - ItemDataField("Apply Image To Wall", ref _ramp.Data.ImageWalls); - ItemDataField("Visible", ref _ramp.Data.IsVisible); - ItemDataField("Depth Bias", ref _ramp.Data.DepthBias); + DropDownField("Type", ref Data.RampType, RampTypeLabels, RampTypeValues, onChanged: ItemAuthoring.UpdateMeshComponents); + TextureField("Image", ref Data.Image); + MaterialField("Material", ref Data.Material); + DropDownField("Image Mode", ref Data.ImageAlignment, RampImageAlignmentLabels, RampImageAlignmentValues); + ItemDataField("Apply Image To Wall", ref Data.ImageWalls); + ItemDataField("Visible", ref Data.IsVisible); + ItemDataField("Depth Bias", ref Data.DepthBias); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("Top Height", ref _ramp.Data.HeightTop); - ItemDataField("Bottom Height", ref _ramp.Data.HeightBottom); + ItemDataField("Top Height", ref Data.HeightTop); + ItemDataField("Bottom Height", ref Data.HeightBottom); EditorGUILayout.Space(10); - ItemDataField("Top Width", ref _ramp.Data.WidthTop); - ItemDataField("Bottom Width", ref _ramp.Data.WidthBottom); + ItemDataField("Top Width", ref Data.WidthTop); + ItemDataField("Bottom Width", ref Data.WidthBottom); EditorGUILayout.Space(10); EditorGUILayout.LabelField("Visible Wall"); EditorGUI.indentLevel++; - ItemDataField("Left Wall", ref _ramp.Data.LeftWallHeightVisible); - ItemDataField("Right Wall", ref _ramp.Data.RightWallHeightVisible); + ItemDataField("Left Wall", ref Data.LeftWallHeightVisible); + ItemDataField("Right Wall", ref Data.RightWallHeightVisible); EditorGUI.indentLevel--; EditorGUILayout.LabelField("Wire Ramp"); EditorGUI.indentLevel++; - ItemDataField("Diameter", ref _ramp.Data.WireDiameter); - ItemDataField("Distance X", ref _ramp.Data.WireDistanceX); - ItemDataField("Distance Y", ref _ramp.Data.WireDistanceY); + ItemDataField("Diameter", ref Data.WireDiameter); + ItemDataField("Distance X", ref Data.WireDistanceX); + ItemDataField("Distance Y", ref Data.WireDistanceY); EditorGUI.indentLevel--; } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "Physics")) { - ItemDataField("Has Hit Event", ref _ramp.Data.HitEvent, dirtyMesh: false); - ItemDataField("Hit Threshold", ref _ramp.Data.Threshold, dirtyMesh: false); + ItemDataField("Has Hit Event", ref Data.HitEvent, false); + ItemDataField("Hit Threshold", ref Data.Threshold, false); EditorGUILayout.LabelField("Physical Wall"); EditorGUI.indentLevel++; - ItemDataField("Left Wall", ref _ramp.Data.LeftWallHeight); - ItemDataField("Right Wall", ref _ramp.Data.RightWallHeight); + ItemDataField("Left Wall", ref Data.LeftWallHeight); + ItemDataField("Right Wall", ref Data.RightWallHeight); EditorGUI.indentLevel--; - EditorGUI.BeginDisabledGroup(_ramp.Data.OverwritePhysics); - MaterialField("Physics Material", ref _ramp.Data.PhysicsMaterial, dirtyMesh: false); + EditorGUI.BeginDisabledGroup(Data.OverwritePhysics); + MaterialField("Physics Material", ref Data.PhysicsMaterial, false); EditorGUI.EndDisabledGroup(); - ItemDataField("Overwrite Material Settings", ref _ramp.Data.OverwritePhysics, dirtyMesh: false); + ItemDataField("Overwrite Material Settings", ref Data.OverwritePhysics, false); - EditorGUI.BeginDisabledGroup(!_ramp.Data.OverwritePhysics); - ItemDataField("Elasticity", ref _ramp.Data.Elasticity, dirtyMesh: false); - ItemDataField("Friction", ref _ramp.Data.Friction, dirtyMesh: false); - ItemDataField("Scatter Angle", ref _ramp.Data.Scatter, dirtyMesh: false); + EditorGUI.BeginDisabledGroup(!Data.OverwritePhysics); + ItemDataField("Elasticity", ref Data.Elasticity, false); + ItemDataField("Friction", ref Data.Friction, false); + ItemDataField("Scatter Angle", ref Data.Scatter, false); EditorGUI.EndDisabledGroup(); - ItemDataField("Collidable", ref _ramp.Data.IsCollidable, dirtyMesh: false); + ItemDataField("Collidable", ref Data.IsCollidable, false); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _ramp.Data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _ramp.Data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref Data.IsTimerEnabled, false); + ItemDataField("Timer Interval", ref Data.TimerInterval, false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs index 4cfb01e49..97d0a6e2d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs @@ -17,50 +17,44 @@ // ReSharper disable AssignmentInConditionalExpression using UnityEditor; +using VisualPinball.Engine.VPT.Rubber; namespace VisualPinball.Unity.Editor { [CustomEditor(typeof(RubberAuthoring))] - public class RubberInspector : DragPointsItemInspector + public class RubberInspector : DragPointsItemInspector { - private RubberAuthoring _rubber; private bool _foldoutColorsAndFormatting = true; private bool _foldoutPosition = true; private bool _foldoutMisc = true; - protected override void OnEnable() - { - base.OnEnable(); - _rubber = target as RubberAuthoring; - } - public override void OnInspectorGUI() { OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - TextureField("Image", ref _rubber.Data.Image); - MaterialField("Material", ref _rubber.Data.Material); - ItemDataField("Visible", ref _rubber.Data.IsVisible); - ItemDataField("Static", ref _rubber.Data.StaticRendering); + TextureField("Image", ref Data.Image); + MaterialField("Material", ref Data.Material); + ItemDataField("Visible", ref Data.IsVisible); + ItemDataField("Static", ref Data.StaticRendering); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("Height", ref _rubber.Data.Height); - ItemDataField("Thickness", ref _rubber.Data.Thickness); + ItemDataField("Height", ref Data.Height); + ItemDataField("Thickness", ref Data.Thickness); EditorGUILayout.LabelField("Orientation"); EditorGUI.indentLevel++; - ItemDataField("RotX", ref _rubber.Data.RotX); - ItemDataField("RotY", ref _rubber.Data.RotY); - ItemDataField("RotZ", ref _rubber.Data.RotZ); + ItemDataField("RotX", ref Data.RotX); + ItemDataField("RotY", ref Data.RotY); + ItemDataField("RotZ", ref Data.RotZ); EditorGUI.indentLevel--; } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _rubber.Data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _rubber.Data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref Data.IsTimerEnabled, false); + ItemDataField("Timer Interval", ref Data.TimerInterval, false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs index 9d9f802d5..8d4ed1756 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs @@ -17,44 +17,37 @@ // ReSharper disable AssignmentInConditionalExpression using UnityEditor; +using VisualPinball.Engine.VPT.Surface; namespace VisualPinball.Unity.Editor { [CustomEditor(typeof(SurfaceAuthoring))] - public class SurfaceInspector : DragPointsItemInspector + public class SurfaceInspector : DragPointsItemInspector { - private SurfaceAuthoring _targetSurf; private bool _foldoutColorsAndFormatting = true; private bool _foldoutPosition = true; - private bool _foldoutMisc = true; - - protected override void OnEnable() - { - base.OnEnable(); - _targetSurf = target as SurfaceAuthoring; - } + private bool _foldoutMisc; public override void OnInspectorGUI() { OnPreInspectorGUI(); - if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - MaterialField("Slingshot Material", ref _targetSurf.Data.SlingShotMaterial); - ItemDataField("Animate Slingshot", ref _targetSurf.Data.SlingshotAnimation, dirtyMesh: false); - ItemDataField("Flipbook", ref _targetSurf.Data.IsFlipbook, dirtyMesh: false); + if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { + ItemDataField("Top Height", ref Data.HeightTop); + ItemDataField("Bottom Height", ref Data.HeightBottom); } - EditorGUILayout.EndFoldoutHeaderGroup(); - if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("Top Height", ref _targetSurf.Data.HeightTop); - ItemDataField("Bottom Height", ref _targetSurf.Data.HeightBottom); + if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { + MaterialField("Slingshot Material", ref Data.SlingShotMaterial); + ItemDataField("Animate Slingshot", ref Data.SlingshotAnimation, false); + ItemDataField("Flipbook", ref Data.IsFlipbook, false); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _targetSurf.Data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _targetSurf.Data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref Data.IsTimerEnabled, false); + ItemDataField("Timer Interval", ref Data.TimerInterval, false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerInspector.cs index ac2df30a0..1b970950d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerInspector.cs @@ -14,21 +14,23 @@ // 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; +using VisualPinball.Engine.VPT.Trigger; namespace VisualPinball.Unity.Editor { [CustomEditor(typeof(TriggerAuthoring))] - public class TriggerInspector : DragPointsItemInspector + public class TriggerInspector : DragPointsItemInspector { - private TriggerAuthoring _trigger; private bool _foldoutColorsAndFormatting = true; private bool _foldoutPosition = true; private bool _foldoutPhysics = true; private bool _foldoutMisc = true; - private static string[] _triggerShapeStrings = { + private static readonly string[] TriggerShapeLabels = { "None", "Button", "Star", @@ -37,7 +39,7 @@ public class TriggerInspector : DragPointsItemInspector "Wire C", "Wire D", }; - private static int[] _triggerShapeValues = { + private static readonly int[] TriggerShapeValues = { TriggerShape.TriggerNone, TriggerShape.TriggerButton, TriggerShape.TriggerStar, @@ -47,42 +49,36 @@ public class TriggerInspector : DragPointsItemInspector TriggerShape.TriggerWireD, }; - protected override void OnEnable() - { - base.OnEnable(); - _trigger = target as TriggerAuthoring; - } - public override void OnInspectorGUI() { OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - ItemDataField("Visible", ref _trigger.Data.IsVisible); - DropDownField("Shape", ref _trigger.Data.Shape, _triggerShapeStrings, _triggerShapeValues); - ItemDataField("Wire Thickness", ref _trigger.Data.WireThickness); - ItemDataField("Star Radius", ref _trigger.Data.Radius); - ItemDataField("Rotation", ref _trigger.Data.Rotation); - ItemDataField("Animation Speed", ref _trigger.Data.AnimSpeed, dirtyMesh: false); - MaterialField("Material", ref _trigger.Data.Material); + ItemDataField("Visible", ref Data.IsVisible); + DropDownField("Shape", ref Data.Shape, TriggerShapeLabels, TriggerShapeValues); + ItemDataField("Wire Thickness", ref Data.WireThickness); + ItemDataField("Star Radius", ref Data.Radius); + ItemDataField("Rotation", ref Data.Rotation); + ItemDataField("Animation Speed", ref Data.AnimSpeed, false); + MaterialField("Material", ref Data.Material); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("", ref _trigger.Data.Center); - SurfaceField("Surface", ref _trigger.Data.Surface); + ItemDataField("", ref Data.Center); + SurfaceField("Surface", ref Data.Surface); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "State & Physics")) { - ItemDataField("Enabled", ref _trigger.Data.IsEnabled, dirtyMesh: false); - ItemDataField("Hit Height", ref _trigger.Data.HitHeight, dirtyMesh: false); + ItemDataField("Enabled", ref Data.IsEnabled, false); + ItemDataField("Hit Height", ref Data.HitHeight, false); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _trigger.Data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _trigger.Data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref Data.IsTimerEnabled, false); + ItemDataField("Timer Interval", ref Data.TimerInterval, false); } EditorGUILayout.EndFoldoutHeaderGroup(); From bc78ed34ef6accc6815e69e8ee2d08a7cb7557fc Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 26 Oct 2020 00:39:43 +0100 Subject: [PATCH 105/124] components: Add remaining inspectors. --- .../VPT/Bumper/BumperColliderInspector.cs | 25 ++-- .../VPT/Gate/GateBracketMeshInspector.cs | 1 - .../VPT/Gate/GateColliderInspector.cs | 1 - .../VPT/Gate/GateWireMeshInspector.cs | 1 - .../HitTarget/HitTargetColliderInspector.cs | 56 +++++++++ .../HitTargetColliderInspector.cs.meta | 11 ++ .../VPT/HitTarget/HitTargetInspector.cs | 114 +++++++----------- .../VPT/HitTarget/HitTargetMeshInspector.cs | 65 ++++++++++ .../HitTarget/HitTargetMeshInspector.cs.meta | 11 ++ .../VPT/ItemColliderInspector.cs | 2 +- .../VPT/ItemMainInspector.cs | 2 +- .../VPT/ItemMeshInspector.cs | 2 +- .../VPT/Kicker/KickerColliderInspector.cs | 46 +++++++ .../Kicker/KickerColliderInspector.cs.meta | 11 ++ .../VPT/Kicker/KickerInspector.cs | 82 +++++-------- .../VPT/Kicker/KickerMeshInspector.cs | 61 ++++++++++ .../VPT/Kicker/KickerMeshInspector.cs.meta | 11 ++ .../VPT/Light/LightBulbMeshInspector.cs | 36 ++++++ .../VPT/Light/LightBulbMeshInspector.cs.meta | 11 ++ .../VPT/Light/LightInspector.cs | 57 ++++----- .../VPT/Light/LightSocketMeshInspector.cs | 36 ++++++ .../Light/LightSocketMeshInspector.cs.meta | 11 ++ .../VPT/Plunger/PlungerColliderInspector.cs | 48 ++++++++ .../Plunger/PlungerColliderInspector.cs.meta | 11 ++ .../VPT/Plunger/PlungerFlatMeshInspector.cs | 36 ++++++ .../Plunger/PlungerFlatMeshInspector.cs.meta | 11 ++ .../VPT/Plunger/PlungerInspector.cs | 84 ++++++------- .../VPT/Plunger/PlungerRodMeshInspector.cs | 36 ++++++ .../Plunger/PlungerRodMeshInspector.cs.meta | 11 ++ .../VPT/Plunger/PlungerSpringMeshInspector.cs | 36 ++++++ .../PlungerSpringMeshInspector.cs.meta | 11 ++ .../VPT/Ramp/RampColliderInspector.cs | 60 +++++++++ .../VPT/Ramp/RampColliderInspector.cs.meta | 11 ++ .../VPT/Ramp/RampFloorMeshInspector.cs | 36 ++++++ .../VPT/Ramp/RampFloorMeshInspector.cs.meta | 11 ++ .../VPT/Ramp/RampInspector.cs | 12 +- .../VPT/Ramp/RampWallMeshInspector.cs | 36 ++++++ .../VPT/Ramp/RampWallMeshInspector.cs.meta | 11 ++ .../VPT/Rubber/RubberColliderInspector.cs | 35 ++---- .../VPT/Rubber/RubberInspector.cs | 28 +++-- .../VPT/Rubber/RubberMeshInspector.cs | 42 +++++++ .../VPT/Rubber/RubberMeshInspector.cs.meta | 11 ++ .../Spinner/SpinnerBracketMeshInspector.cs | 36 ++++++ .../VPT/Spinner/SpinnerColliderInspector.cs | 38 ++++++ .../VPT/Spinner/SpinnerInspector.cs | 60 ++++----- .../VPT/Spinner/SpinnerPlateMeshInspector.cs | 41 +++++++ .../VPT/Surface/SurfaceColliderInspector.cs | 43 +++---- .../VPT/Surface/SurfaceInspector.cs | 4 + .../VPT/Trigger/TriggerColliderInspector.cs | 39 ++++++ .../Trigger/TriggerColliderInspector.cs.meta | 11 ++ .../VPT/Trigger/TriggerInspector.cs | 41 ++----- .../VPT/Trigger/TriggerMeshInspector.cs | 62 ++++++++++ .../VPT/Trigger/TriggerMeshInspector.cs.meta | 11 ++ .../VPT/Kicker/KickerMeshAuthoring.cs | 2 +- 54 files changed, 1270 insertions(+), 348 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetColliderInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetColliderInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetMeshInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerColliderInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerColliderInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerMeshInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightBulbMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightBulbMeshInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightSocketMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightSocketMeshInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerColliderInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerColliderInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerFlatMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerFlatMeshInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerRodMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerRodMeshInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerSpringMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerSpringMeshInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampColliderInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampColliderInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampFloorMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampFloorMeshInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampWallMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampWallMeshInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberMeshInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerBracketMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerColliderInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerPlateMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerColliderInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerColliderInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerMeshInspector.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerMeshInspector.cs.meta diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs index df8060ccc..07bd320ab 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs @@ -24,30 +24,19 @@ namespace VisualPinball.Unity.Editor [CustomEditor(typeof(BumperColliderAuthoring))] public class BumperColliderInspector : ItemColliderInspector { - private BumperData _bumperData; - - private bool _foldoutMaterial = true; - - protected override void OnEnable() - { - base.OnEnable(); - _bumperData = Data; - } - public override void OnInspectorGUI() { - if (_bumperData == null) { - NoDataError(); + if (HasErrors()) { return; } - ItemDataField("Collidable", ref _bumperData.IsCollidable, dirtyMesh: false); + ItemDataField("Collidable", ref Data.IsCollidable, dirtyMesh: false); - EditorGUI.BeginDisabledGroup(!_bumperData.IsCollidable); - ItemDataField("Has Hit Event", ref _bumperData.HitEvent, dirtyMesh: false); - ItemDataField("Force", ref _bumperData.Force, dirtyMesh: false); - ItemDataField("Hit Threshold", ref _bumperData.Threshold, dirtyMesh: false); - ItemDataField("Scatter Angle", ref _bumperData.Scatter, dirtyMesh: false); + EditorGUI.BeginDisabledGroup(!Data.IsCollidable); + ItemDataField("Has Hit Event", ref Data.HitEvent, dirtyMesh: false); + ItemDataField("Force", ref Data.Force, dirtyMesh: false); + ItemDataField("Hit Threshold", ref Data.Threshold, dirtyMesh: false); + ItemDataField("Scatter Angle", ref Data.Scatter, dirtyMesh: false); EditorGUI.EndDisabledGroup(); base.OnInspectorGUI(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateBracketMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateBracketMeshInspector.cs index 3fe209584..dda5e80f5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateBracketMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateBracketMeshInspector.cs @@ -18,7 +18,6 @@ using UnityEditor; using VisualPinball.Engine.VPT.Gate; -using VisualPinball.Engine.VPT.Primitive; namespace VisualPinball.Unity.Editor { diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateColliderInspector.cs index bc7fd6086..ea6c77099 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateColliderInspector.cs @@ -18,7 +18,6 @@ using UnityEditor; using VisualPinball.Engine.VPT.Gate; -using VisualPinball.Engine.VPT.Primitive; namespace VisualPinball.Unity.Editor { diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateWireMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateWireMeshInspector.cs index 9c26245c6..d63252bfe 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateWireMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateWireMeshInspector.cs @@ -18,7 +18,6 @@ using UnityEditor; using VisualPinball.Engine.VPT.Gate; -using VisualPinball.Engine.VPT.Primitive; namespace VisualPinball.Unity.Editor { diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetColliderInspector.cs new file mode 100644 index 000000000..0bf444482 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetColliderInspector.cs @@ -0,0 +1,56 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.HitTarget; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(HitTargetColliderAuthoring))] + public class HitTargetColliderInspector : ItemColliderInspector + { + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + ItemDataField("Has Hit Event", ref Data.UseHitEvent, false); + ItemDataField("Hit Threshold", ref Data.Threshold, false); + + EditorGUI.BeginDisabledGroup(Data.OverwritePhysics); + MaterialField("Physics Material", ref Data.PhysicsMaterial, false); + EditorGUI.EndDisabledGroup(); + + ItemDataField("Overwrite Material Settings", ref Data.OverwritePhysics, false); + + EditorGUI.BeginDisabledGroup(!Data.OverwritePhysics); + ItemDataField("Elasticity", ref Data.Elasticity, false); + ItemDataField("Elasticity Falloff", ref Data.ElasticityFalloff, false); + ItemDataField("Friction", ref Data.Friction, false); + ItemDataField("Scatter Angle", ref Data.Scatter, false); + EditorGUI.EndDisabledGroup(); + + ItemDataField("Legacy Mode", ref Data.IsLegacy, false); + ItemDataField("Collidable", ref Data.IsCollidable, false); + ItemDataField("Is Dropped", ref Data.IsDropped, false); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetColliderInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetColliderInspector.cs.meta new file mode 100644 index 000000000..916ba6431 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetColliderInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3b168bcc345eeb6418bd2dc8ae64082d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetInspector.cs index 48262222b..da9b29d05 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetInspector.cs @@ -14,106 +14,78 @@ // 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; +using VisualPinball.Engine.VPT.HitTarget; namespace VisualPinball.Unity.Editor { [CustomEditor(typeof(HitTargetAuthoring))] - public class HitTargetInspector : ItemInspector + public class HitTargetInspector : ItemMainInspector { - private HitTargetAuthoring _target; private bool _foldoutColorsAndFormatting = true; - private bool _foldoutPosition = true; - private bool _foldoutPhysics = true; - private bool _foldoutMisc = true; - - private static string[] _targetTypeStrings = { - "Drop Target: Beveled", - "Drop Target: Simple", - "Drop Target: Flat Simple", - "Hit Target: Rectangle", - "Hit Target: Fat Rectangle", - "Hit Target: Round", - "Hit Target: Slim", - "Hit Target: Fat Slim", - "Hit Target: Fat Square", - }; - private static int[] _targetTypeValues = { - TargetType.DropTargetBeveled, - TargetType.DropTargetSimple, - TargetType.DropTargetFlatSimple, - TargetType.HitTargetRectangle, - TargetType.HitFatTargetRectangle, - TargetType.HitTargetRound, - TargetType.HitTargetSlim, - TargetType.HitFatTargetSlim, - TargetType.HitFatTargetSquare, - }; - - protected override void OnEnable() - { - base.OnEnable(); - _target = target as HitTargetAuthoring; - } + private bool _foldoutMesh; + private bool _foldoutPhysics; + private bool _foldoutMisc; public override void OnInspectorGUI() { - OnPreInspectorGUI(); - - if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - DropDownField("Type", ref _target.Data.TargetType, _targetTypeStrings, _targetTypeValues); - TextureField("Image", ref _target.Data.Image); - MaterialField("Material", ref _target.Data.Material); - ItemDataField("Drop Speed", ref _target.Data.DropSpeed, dirtyMesh: false); - ItemDataField("Raise Delay", ref _target.Data.RaiseDelay, dirtyMesh: false); - ItemDataField("Depth Bias", ref _target.Data.DepthBias, dirtyMesh: false); - ItemDataField("Visible", ref _target.Data.IsVisible); + if (HasErrors()) { + return; } - EditorGUILayout.EndFoldoutHeaderGroup(); - if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position & Translation")) { - EditorGUILayout.LabelField("Position"); - EditorGUI.indentLevel++; - ItemDataField("", ref _target.Data.Position); - EditorGUI.indentLevel--; + ItemDataField("Position", ref Data.Position); + ItemDataField("Scale", ref Data.Size); + ItemDataField("Orientation", ref Data.RotZ); + + OnPreInspectorGUI(); - EditorGUILayout.LabelField("Scale"); - EditorGUI.indentLevel++; - ItemDataField("", ref _target.Data.Size); - EditorGUI.indentLevel--; + if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Behavior")) { - ItemDataField("Orientation", ref _target.Data.RotZ); + ItemDataField("Drop Speed", ref Data.DropSpeed, false); + ItemDataField("Raise Delay", ref Data.RaiseDelay, false); + ItemDataField("Depth Bias", ref Data.DepthBias, false); + ItemDataField("Visible", ref Data.IsVisible); + } + EditorGUILayout.EndFoldoutHeaderGroup(); + // mesh + if (_foldoutMesh = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMesh, "Mesh")) { + DropDownField("Type", ref Data.TargetType, HitTargetMeshInspector.TargetTypeLabels, HitTargetMeshInspector.TargetTypeValues); + TextureField("Image", ref Data.Image); + MaterialField("Material", ref Data.Material); } EditorGUILayout.EndFoldoutHeaderGroup(); + // physics if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "Physics")) { - ItemDataField("Has Hit Event", ref _target.Data.UseHitEvent, dirtyMesh: false); - ItemDataField("Hit Threshold", ref _target.Data.Threshold, dirtyMesh: false); + ItemDataField("Has Hit Event", ref Data.UseHitEvent, false); + ItemDataField("Hit Threshold", ref Data.Threshold, false); - EditorGUI.BeginDisabledGroup(_target.Data.OverwritePhysics); - MaterialField("Physics Material", ref _target.Data.PhysicsMaterial, dirtyMesh: false); + EditorGUI.BeginDisabledGroup(Data.OverwritePhysics); + MaterialField("Physics Material", ref Data.PhysicsMaterial, false); EditorGUI.EndDisabledGroup(); - ItemDataField("Overwrite Material Settings", ref _target.Data.OverwritePhysics, dirtyMesh: false); + ItemDataField("Overwrite Material Settings", ref Data.OverwritePhysics, false); - EditorGUI.BeginDisabledGroup(!_target.Data.OverwritePhysics); - ItemDataField("Elasticity", ref _target.Data.Elasticity, dirtyMesh: false); - ItemDataField("Elasticity Falloff", ref _target.Data.ElasticityFalloff, dirtyMesh: false); - ItemDataField("Friction", ref _target.Data.Friction, dirtyMesh: false); - ItemDataField("Scatter Angle", ref _target.Data.Scatter, dirtyMesh: false); + EditorGUI.BeginDisabledGroup(!Data.OverwritePhysics); + ItemDataField("Elasticity", ref Data.Elasticity, false); + ItemDataField("Elasticity Falloff", ref Data.ElasticityFalloff, false); + ItemDataField("Friction", ref Data.Friction, false); + ItemDataField("Scatter Angle", ref Data.Scatter, false); EditorGUI.EndDisabledGroup(); - ItemDataField("Legacy Mode", ref _target.Data.IsLegacy, dirtyMesh: false); - ItemDataField("Collidable", ref _target.Data.IsCollidable, dirtyMesh: false); - ItemDataField("Is Dropped", ref _target.Data.IsDropped, dirtyMesh: false); + ItemDataField("Legacy Mode", ref Data.IsLegacy, false); + ItemDataField("Collidable", ref Data.IsCollidable, false); + ItemDataField("Is Dropped", ref Data.IsDropped, false); } EditorGUILayout.EndFoldoutHeaderGroup(); + // misc if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _target.Data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _target.Data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref Data.IsTimerEnabled, false); + ItemDataField("Timer Interval", ref Data.TimerInterval, false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetMeshInspector.cs new file mode 100644 index 000000000..9a613a289 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetMeshInspector.cs @@ -0,0 +1,65 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT; +using VisualPinball.Engine.VPT.HitTarget; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(HitTargetMeshAuthoring))] + public class HitTargetMeshInspector : ItemMeshInspector + { + public static readonly string[] TargetTypeLabels = { + "Drop Target: Beveled", + "Drop Target: Simple", + "Drop Target: Flat Simple", + "Hit Target: Rectangle", + "Hit Target: Fat Rectangle", + "Hit Target: Round", + "Hit Target: Slim", + "Hit Target: Fat Slim", + "Hit Target: Fat Square", + }; + + public static readonly int[] TargetTypeValues = { + TargetType.DropTargetBeveled, + TargetType.DropTargetSimple, + TargetType.DropTargetFlatSimple, + TargetType.HitTargetRectangle, + TargetType.HitFatTargetRectangle, + TargetType.HitTargetRound, + TargetType.HitTargetSlim, + TargetType.HitFatTargetSlim, + TargetType.HitFatTargetSquare, + }; + + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + DropDownField("Type", ref Data.TargetType, TargetTypeLabels, TargetTypeValues); + TextureField("Image", ref Data.Image); + MaterialField("Material", ref Data.Material); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetMeshInspector.cs.meta new file mode 100644 index 000000000..4c55ba0ac --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 30868c688d57d1c42bfc64e62a20aeac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs index 4b69e3e8a..b66014bdd 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemColliderInspector.cs @@ -120,7 +120,7 @@ protected bool HasErrors() return false; } - protected void NoDataError() + private void NoDataError() { EditorGUILayout.HelpBox($"Cannot find main component!\n\nYou must have a {typeof(TMainAuthoring).Name} component on either this GameObject, its parent or grand parent.", MessageType.Error); } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMainInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMainInspector.cs index 12cc85c29..4409c0ffc 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMainInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMainInspector.cs @@ -26,7 +26,7 @@ namespace VisualPinball.Unity.Editor { public class ItemMainInspector : ItemInspector where TData : ItemData - where TItem : Item, IHittable, IRenderable + where TItem : Item, IRenderable where TMainAuthoring : ItemMainAuthoring { protected TMainAuthoring ItemAuthoring; diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs index 7942a0d18..ead513f38 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemMeshInspector.cs @@ -27,7 +27,7 @@ namespace VisualPinball.Unity.Editor public class ItemMeshInspector : ItemInspector where TMeshAuthoring : ItemMeshAuthoring where TData : ItemData - where TItem : Item, IHittable, IRenderable + where TItem : Item, IRenderable where TMainAuthoring : ItemMainAuthoring { protected TMeshAuthoring MeshAuthoring; diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerColliderInspector.cs new file mode 100644 index 000000000..79ab30964 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerColliderInspector.cs @@ -0,0 +1,46 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Kicker; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(KickerColliderAuthoring))] + public class KickerColliderInspector : ItemColliderInspector + { + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + ItemDataField("Enabled", ref Data.IsEnabled, false); + ItemDataField("Fall Through", ref Data.FallThrough, false); + ItemDataField("Legacy", ref Data.LegacyMode, false); + ItemDataField("Scatter Angle", ref Data.Scatter, false); + ItemDataField("Hit Accuracy", ref Data.HitAccuracy, false); + ItemDataField("Hit Height", ref Data.HitHeight, false); + + ItemDataField("Default Angle", ref Data.Angle, false); + ItemDataField("Default Speed", ref Data.Speed, false); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerColliderInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerColliderInspector.cs.meta new file mode 100644 index 000000000..442837468 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerColliderInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6a8324a10990f9a4eb19ecf814079871 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerInspector.cs index cb3040966..1297a03c9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerInspector.cs @@ -14,79 +14,55 @@ // 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; +using VisualPinball.Engine.VPT.Kicker; namespace VisualPinball.Unity.Editor { [CustomEditor(typeof(KickerAuthoring))] - public class KickerInspector : ItemInspector + public class KickerInspector : ItemMainInspector { - private KickerAuthoring _kicker; - private bool _foldoutColorsAndFormatting = true; - private bool _foldoutPosition = true; - private bool _foldoutPhysics = true; - private bool _foldoutMisc = true; - - private static string[] _kickerTypeStrings = { - "Invisible", - "Cup", - "Cup 2", - "Hole", - "Hole Simple", - "Gottlieb", - "Williams", - }; - private static int[] _kickerTypeValues = { - KickerType.KickerInvisible, - KickerType.KickerCup, - KickerType.KickerCup2, - KickerType.KickerHole, - KickerType.KickerHoleSimple, - KickerType.KickerGottlieb, - KickerType.KickerWilliams, - }; - - protected override void OnEnable() - { - base.OnEnable(); - _kicker = target as KickerAuthoring; - } + private bool _foldoutMesh; + private bool _foldoutPhysics; + private bool _foldoutMisc; public override void OnInspectorGUI() { - OnPreInspectorGUI(); - - if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - MaterialField("Material", ref _kicker.Data.Material); - DropDownField("Display", ref _kicker.Data.KickerType, _kickerTypeStrings, _kickerTypeValues); - ItemDataField("Radius", ref _kicker.Data.Radius); - ItemDataField("Orientation", ref _kicker.Data.Orientation); + if (HasErrors()) { + return; } - EditorGUILayout.EndFoldoutHeaderGroup(); - if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("", ref _kicker.Data.Center); - SurfaceField("Surface", ref _kicker.Data.Surface); + ItemDataField("Position", ref Data.Center); + SurfaceField("Surface", ref Data.Surface); + + OnPreInspectorGUI(); + + if (_foldoutMesh = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMesh, "Mesh")) { + MaterialField("Material", ref Data.Material); + DropDownField("Display", ref Data.KickerType, KickerMeshInspector.KickerTypeLabels, KickerMeshInspector.KickerTypeValues); + ItemDataField("Radius", ref Data.Radius); + ItemDataField("Orientation", ref Data.Orientation); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "State & Physics")) { - ItemDataField("Enabled", ref _kicker.Data.IsEnabled, dirtyMesh: false); - ItemDataField("Fall Through", ref _kicker.Data.FallThrough, dirtyMesh: false); - ItemDataField("Legacy", ref _kicker.Data.LegacyMode, dirtyMesh: false); - ItemDataField("Scatter Angle", ref _kicker.Data.Scatter, dirtyMesh: false); - ItemDataField("Hit Accuracy", ref _kicker.Data.HitAccuracy, dirtyMesh: false); - ItemDataField("Hit Height", ref _kicker.Data.HitHeight, dirtyMesh: false); + ItemDataField("Enabled", ref Data.IsEnabled, false); + ItemDataField("Fall Through", ref Data.FallThrough, false); + ItemDataField("Legacy", ref Data.LegacyMode, false); + ItemDataField("Scatter Angle", ref Data.Scatter, false); + ItemDataField("Hit Accuracy", ref Data.HitAccuracy, false); + ItemDataField("Hit Height", ref Data.HitHeight, false); - ItemDataField("Default Angle", ref _kicker.Data.Angle, dirtyMesh: false); - ItemDataField("Default Speed", ref _kicker.Data.Speed, dirtyMesh: false); + ItemDataField("Default Angle", ref Data.Angle, false); + ItemDataField("Default Speed", ref Data.Speed, false); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _kicker.Data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _kicker.Data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref Data.IsTimerEnabled, false); + ItemDataField("Timer Interval", ref Data.TimerInterval, false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerMeshInspector.cs new file mode 100644 index 000000000..65583b200 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerMeshInspector.cs @@ -0,0 +1,61 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT; +using VisualPinball.Engine.VPT.Kicker; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(KickerMeshAuthoring))] + public class KickerMeshInspector : ItemMeshInspector + { + public static readonly string[] KickerTypeLabels = { + "Invisible", + "Cup", + "Cup 2", + "Hole", + "Hole Simple", + "Gottlieb", + "Williams", + }; + public static readonly int[] KickerTypeValues = { + KickerType.KickerInvisible, + KickerType.KickerCup, + KickerType.KickerCup2, + KickerType.KickerHole, + KickerType.KickerHoleSimple, + KickerType.KickerGottlieb, + KickerType.KickerWilliams, + }; + + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + MaterialField("Material", ref Data.Material); + DropDownField("Display", ref Data.KickerType, KickerTypeLabels, KickerTypeValues); + ItemDataField("Radius", ref Data.Radius); + ItemDataField("Orientation", ref Data.Orientation); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerMeshInspector.cs.meta new file mode 100644 index 000000000..8be600dfb --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Kicker/KickerMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5e733764f2632bf41aa60a5d5ad65191 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightBulbMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightBulbMeshInspector.cs new file mode 100644 index 000000000..f27ab88a7 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightBulbMeshInspector.cs @@ -0,0 +1,36 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Light; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(LightBulbMeshAuthoring))] + public class LightBulbMeshInspector : ItemMeshInspector + { + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightBulbMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightBulbMeshInspector.cs.meta new file mode 100644 index 000000000..3aff7ca41 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightBulbMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0f01dd6f620ff3a4392fd9812a91b389 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightInspector.cs index c776bfee4..c62cb5631 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightInspector.cs @@ -18,65 +18,60 @@ using UnityEditor; using VisualPinball.Engine.VPT; +using VisualPinball.Engine.VPT.Light; namespace VisualPinball.Unity.Editor { [CustomEditor(typeof(LightAuthoring))] - public class LightInspector : ItemInspector + public class LightInspector : ItemMainInspector { - private LightAuthoring _light; private bool _foldoutColorsAndFormatting = true; - private bool _foldoutPosition = true; - private bool _foldoutStateAndPhysics = true; - private bool _foldoutMisc = true; + private bool _foldoutState = true; + private bool _foldoutMisc; - private static string[] _lightStateStrings = { "Off", "On", "Blinking" }; - private static int[] _lightStateValues = { LightStatus.LightStateOff, LightStatus.LightStateOn, LightStatus.LightStateBlinking }; - - protected override void OnEnable() - { - base.OnEnable(); - _light = target as LightAuthoring; - } + private static readonly string[] LightStateLabels = { "Off", "On", "Blinking" }; + private static readonly int[] LightStateValues = { LightStatus.LightStateOff, LightStatus.LightStateOn, LightStatus.LightStateBlinking }; public override void OnInspectorGUI() { + if (HasErrors()) { + return; + } + + ItemDataField("Position", ref Data.Center); + SurfaceField("Surface", ref Data.Surface); + if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - ItemDataField("Falloff", ref _light.Data.Falloff, dirtyMesh: false); - ItemDataField("Intensity", ref _light.Data.Intensity, dirtyMesh: false); + ItemDataField("Falloff", ref Data.Falloff, false); + ItemDataField("Intensity", ref Data.Intensity, false); EditorGUILayout.LabelField("Fade Speed"); EditorGUI.indentLevel++; - ItemDataField("Up", ref _light.Data.FadeSpeedUp, dirtyMesh: false); - ItemDataField("Down", ref _light.Data.FadeSpeedDown, dirtyMesh: false); + ItemDataField("Up", ref Data.FadeSpeedUp, false); + ItemDataField("Down", ref Data.FadeSpeedDown, false); EditorGUI.indentLevel--; - ItemDataField("Color", ref _light.Data.Color2, dirtyMesh: false); // Note: using color2 since that's the hot/center color in vpx + ItemDataField("Color", ref Data.Color2, false); // Note: using color2 since that's the hot/center color in vpx EditorGUILayout.LabelField("Bulb"); EditorGUI.indentLevel++; - ItemDataField("Enable", ref _light.Data.ShowBulbMesh, false, onChanged: _light.OnBulbEnabled); - ItemDataField("Scale Mesh", ref _light.Data.MeshRadius, dirtyMesh: false); + ItemDataField("Enable", ref Data.ShowBulbMesh, false, onChanged: ItemAuthoring.OnBulbEnabled); + ItemDataField("Scale Mesh", ref Data.MeshRadius, false); EditorGUI.indentLevel--; } EditorGUILayout.EndFoldoutHeaderGroup(); - if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("", ref _light.Data.Center); - SurfaceField("Surface", ref _light.Data.Surface); - } - EditorGUILayout.EndFoldoutHeaderGroup(); - if (_foldoutStateAndPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutStateAndPhysics, "State & Physics")) { - DropDownField("State", ref _light.Data.State, _lightStateStrings, _lightStateValues); - ItemDataField("Blink Pattern", ref _light.Data.BlinkPattern, dirtyMesh: false); - ItemDataField("Blink Interval", ref _light.Data.BlinkInterval, dirtyMesh: false); + if (_foldoutState = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutState, "State")) { + DropDownField("State", ref Data.State, LightStateLabels, LightStateValues); + ItemDataField("Blink Pattern", ref Data.BlinkPattern, false); + ItemDataField("Blink Interval", ref Data.BlinkInterval, false); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _light.Data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _light.Data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref Data.IsTimerEnabled, false); + ItemDataField("Timer Interval", ref Data.TimerInterval, false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightSocketMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightSocketMeshInspector.cs new file mode 100644 index 000000000..a38c4084d --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightSocketMeshInspector.cs @@ -0,0 +1,36 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Light; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(LightSocketMeshAuthoring))] + public class LightSocketMeshInspector : ItemMeshInspector + { + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightSocketMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightSocketMeshInspector.cs.meta new file mode 100644 index 000000000..a2cdee279 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Light/LightSocketMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 40dc5c6a5b246cc40874a9195e22dfbd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerColliderInspector.cs new file mode 100644 index 000000000..7f8ccab75 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerColliderInspector.cs @@ -0,0 +1,48 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Kicker; +using VisualPinball.Engine.VPT.Plunger; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(PlungerColliderAuthoring))] + public class PlungerColliderInspector : ItemColliderInspector + { + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + ItemDataField("Pull Speed", ref Data.SpeedPull, false); + ItemDataField("Release Speed", ref Data.SpeedFire, false); + ItemDataField("Stroke Length", ref Data.Stroke, false); + ItemDataField("Scatter Velocity", ref Data.ScatterVelocity, false); + ItemDataField("Enable Mechanical Plunger", ref Data.IsMechPlunger, false); + ItemDataField("Auto Plunger", ref Data.AutoPlunger, false); + ItemDataField("Visible", ref Data.IsVisible); + ItemDataField("Mech Strength", ref Data.MechStrength, false); + ItemDataField("Momentum Xfer", ref Data.MomentumXfer, false); + ItemDataField("Park Position (0..1)", ref Data.ParkPosition, false); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerColliderInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerColliderInspector.cs.meta new file mode 100644 index 000000000..dd913bfac --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerColliderInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 958dd340ea1e43146906e365c3d5eb2b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerFlatMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerFlatMeshInspector.cs new file mode 100644 index 000000000..e057382a4 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerFlatMeshInspector.cs @@ -0,0 +1,36 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Plunger; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(PlungerFlatMeshAuthoring))] + public class PlungerFlatMeshInspector : ItemMeshInspector + { + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerFlatMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerFlatMeshInspector.cs.meta new file mode 100644 index 000000000..50b496579 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerFlatMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3a0fe38a17936e54d8cf1595f0b5b5f7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerInspector.cs index 84791d676..d5d0cc07f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerInspector.cs @@ -18,76 +18,70 @@ using UnityEditor; using VisualPinball.Engine.VPT; +using VisualPinball.Engine.VPT.Plunger; namespace VisualPinball.Unity.Editor { [CustomEditor(typeof(PlungerAuthoring))] - public class PlungerInspector : ItemInspector + public class PlungerInspector : ItemMainInspector { - private PlungerAuthoring _plunger; private bool _foldoutColorsAndFormatting = true; - private bool _foldoutPosition = true; - private bool _foldoutStateAndPhysics = true; - private bool _foldoutMisc = true; + private bool _foldoutStateAndPhysics; + private bool _foldoutMisc; - private static readonly string[] PlungerTypeStrings = { "Modern", "Flat", "Custom" }; + private static readonly string[] PlungerTypeLabels = { "Modern", "Flat", "Custom" }; private static readonly int[] PlungerTypeValues = { PlungerType.PlungerTypeModern, PlungerType.PlungerTypeFlat, PlungerType.PlungerTypeCustom }; - protected override void OnEnable() - { - base.OnEnable(); - _plunger = target as PlungerAuthoring; - } - public override void OnInspectorGUI() { + if (HasErrors()) { + return; + } + + ItemDataField("Position", ref Data.Center); + SurfaceField("Surface", ref Data.Surface); + OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - DropDownField("Type", ref _plunger.Data.Type, PlungerTypeStrings, PlungerTypeValues, onChanged: _plunger.OnTypeChanged); - MaterialField("Material", ref _plunger.Data.Material); - TextureField("Image", ref _plunger.Data.Image); - ItemDataField("Flat Frames", ref _plunger.Data.AnimFrames); - ItemDataField("Width", ref _plunger.Data.Width); - ItemDataField("Z Adjustment", ref _plunger.Data.ZAdjust); + DropDownField("Type", ref Data.Type, PlungerTypeLabels, PlungerTypeValues, onChanged: ItemAuthoring.OnTypeChanged); + MaterialField("Material", ref Data.Material); + TextureField("Image", ref Data.Image); + ItemDataField("Flat Frames", ref Data.AnimFrames); + ItemDataField("Width", ref Data.Width); + ItemDataField("Z Adjustment", ref Data.ZAdjust); EditorGUILayout.LabelField("Custom Settings"); EditorGUI.indentLevel++; - ItemDataField("Rod Diameter", ref _plunger.Data.RodDiam); - ItemDataField("Tip Shape", ref _plunger.Data.TipShape); // TODO: break this down and provide individual fields - ItemDataField("Ring Gap", ref _plunger.Data.RingGap); - ItemDataField("Ring Diam", ref _plunger.Data.RingDiam); - ItemDataField("Ring Width", ref _plunger.Data.RingWidth); - ItemDataField("Spring Diam", ref _plunger.Data.SpringDiam); - ItemDataField("Spring Gauge", ref _plunger.Data.SpringGauge); - ItemDataField("Spring Loops", ref _plunger.Data.SpringLoops); - ItemDataField("End Loops", ref _plunger.Data.SpringEndLoops); + ItemDataField("Rod Diameter", ref Data.RodDiam); + ItemDataField("Tip Shape", ref Data.TipShape); // TODO: break this down and provide individual fields + ItemDataField("Ring Gap", ref Data.RingGap); + ItemDataField("Ring Diam", ref Data.RingDiam); + ItemDataField("Ring Width", ref Data.RingWidth); + ItemDataField("Spring Diam", ref Data.SpringDiam); + ItemDataField("Spring Gauge", ref Data.SpringGauge); + ItemDataField("Spring Loops", ref Data.SpringLoops); + ItemDataField("End Loops", ref Data.SpringEndLoops); EditorGUI.indentLevel--; } EditorGUILayout.EndFoldoutHeaderGroup(); - if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("", ref _plunger.Data.Center); - SurfaceField("Surface", ref _plunger.Data.Surface); - } - EditorGUILayout.EndFoldoutHeaderGroup(); - if (_foldoutStateAndPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutStateAndPhysics, "State & Physics")) { - ItemDataField("Pull Speed", ref _plunger.Data.SpeedPull, dirtyMesh: false); - ItemDataField("Release Speed", ref _plunger.Data.SpeedFire, dirtyMesh: false); - ItemDataField("Stroke Length", ref _plunger.Data.Stroke, dirtyMesh: false); - ItemDataField("Scatter Velocity", ref _plunger.Data.ScatterVelocity, dirtyMesh: false); - ItemDataField("Enable Mechanical Plunger", ref _plunger.Data.IsMechPlunger, dirtyMesh: false); - ItemDataField("Auto Plunger", ref _plunger.Data.AutoPlunger, dirtyMesh: false); - ItemDataField("Visible", ref _plunger.Data.IsVisible); - ItemDataField("Mech Strength", ref _plunger.Data.MechStrength, dirtyMesh: false); - ItemDataField("Momentum Xfer", ref _plunger.Data.MomentumXfer, dirtyMesh: false); - ItemDataField("Park Position (0..1)", ref _plunger.Data.ParkPosition, dirtyMesh: false); + ItemDataField("Pull Speed", ref Data.SpeedPull, false); + ItemDataField("Release Speed", ref Data.SpeedFire, false); + ItemDataField("Stroke Length", ref Data.Stroke, false); + ItemDataField("Scatter Velocity", ref Data.ScatterVelocity, false); + ItemDataField("Enable Mechanical Plunger", ref Data.IsMechPlunger, false); + ItemDataField("Auto Plunger", ref Data.AutoPlunger, false); + ItemDataField("Visible", ref Data.IsVisible); + ItemDataField("Mech Strength", ref Data.MechStrength, false); + ItemDataField("Momentum Xfer", ref Data.MomentumXfer, false); + ItemDataField("Park Position (0..1)", ref Data.ParkPosition, false); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _plunger.Data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _plunger.Data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref Data.IsTimerEnabled, false); + ItemDataField("Timer Interval", ref Data.TimerInterval, false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerRodMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerRodMeshInspector.cs new file mode 100644 index 000000000..c9f4e5bcb --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerRodMeshInspector.cs @@ -0,0 +1,36 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Plunger; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(PlungerRodMeshAuthoring))] + public class PlungerRodMeshInspector : ItemMeshInspector + { + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerRodMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerRodMeshInspector.cs.meta new file mode 100644 index 000000000..489423bca --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerRodMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 17ea10e740eb9294987c9ed57d8794d4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerSpringMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerSpringMeshInspector.cs new file mode 100644 index 000000000..91fa7f786 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerSpringMeshInspector.cs @@ -0,0 +1,36 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Plunger; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(PlungerSpringMeshAuthoring))] + public class PlungerSpringMeshInspector : ItemMeshInspector + { + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerSpringMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerSpringMeshInspector.cs.meta new file mode 100644 index 000000000..ab6e3a304 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerSpringMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c1803ab94d6bdfb46af052f14bdf0769 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampColliderInspector.cs new file mode 100644 index 000000000..1888161b0 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampColliderInspector.cs @@ -0,0 +1,60 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Kicker; +using VisualPinball.Engine.VPT.Ramp; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(RampColliderAuthoring))] + public class RampColliderInspector : ItemColliderInspector + { + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + ItemDataField("Has Hit Event", ref Data.HitEvent, false); + ItemDataField("Hit Threshold", ref Data.Threshold, false); + + EditorGUILayout.LabelField("Physical Wall"); + EditorGUI.indentLevel++; + ItemDataField("Left Wall", ref Data.LeftWallHeight); + ItemDataField("Right Wall", ref Data.RightWallHeight); + EditorGUI.indentLevel--; + + EditorGUI.BeginDisabledGroup(Data.OverwritePhysics); + MaterialField("Physics Material", ref Data.PhysicsMaterial, false); + EditorGUI.EndDisabledGroup(); + + ItemDataField("Overwrite Material Settings", ref Data.OverwritePhysics, false); + + EditorGUI.BeginDisabledGroup(!Data.OverwritePhysics); + ItemDataField("Elasticity", ref Data.Elasticity, false); + ItemDataField("Friction", ref Data.Friction, false); + ItemDataField("Scatter Angle", ref Data.Scatter, false); + EditorGUI.EndDisabledGroup(); + + ItemDataField("Collidable", ref Data.IsCollidable, false); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampColliderInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampColliderInspector.cs.meta new file mode 100644 index 000000000..e0855fee1 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampColliderInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4e69bf80d8a67a8428e8c667ff3d05d8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampFloorMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampFloorMeshInspector.cs new file mode 100644 index 000000000..0f67786e6 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampFloorMeshInspector.cs @@ -0,0 +1,36 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Ramp; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(RampFloorMeshAuthoring))] + public class RampFloorMeshInspector : ItemMeshInspector + { + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampFloorMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampFloorMeshInspector.cs.meta new file mode 100644 index 000000000..7f67e1162 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampFloorMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ded7b04e61fe8c9469875bc2665da582 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs index ef92ee7df..0258fbc8d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs @@ -26,9 +26,9 @@ namespace VisualPinball.Unity.Editor public class RampInspector : DragPointsItemInspector { private bool _foldoutColorsAndFormatting = true; - private bool _foldoutPosition = true; - private bool _foldoutPhysics = true; - private bool _foldoutMisc = true; + private bool _foldoutGeometry = true; + private bool _foldoutPhysics; + private bool _foldoutMisc; private static readonly string[] RampTypeLabels = { "Flat", @@ -57,6 +57,10 @@ public class RampInspector : DragPointsItemInspector. + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Ramp; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(RampWallMeshAuthoring))] + public class RampWallMeshInspector : ItemMeshInspector + { + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampWallMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampWallMeshInspector.cs.meta new file mode 100644 index 000000000..e93091b54 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampWallMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0c30049f0df075b479db975f980ddd92 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs index 5d26418f2..7b74728ee 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs @@ -24,41 +24,32 @@ namespace VisualPinball.Unity.Editor [CustomEditor(typeof(RubberColliderAuthoring))] public class RubberColliderInspector : ItemColliderInspector { - private RubberData _rubberData; - private bool _foldoutMaterial = true; - protected override void OnEnable() - { - base.OnEnable(); - _rubberData = Data; - } - public override void OnInspectorGUI() { - if (_rubberData == null) { - NoDataError(); + if (HasErrors()) { return; } - ItemDataField("Collidable", ref _rubberData.IsCollidable, false); + ItemDataField("Collidable", ref Data.IsCollidable, false); - EditorGUI.BeginDisabledGroup(!_rubberData.IsCollidable); - ItemDataField("Has Hit Event", ref _rubberData.HitEvent, false); - ItemDataField("Hit Height", ref _rubberData.HitHeight, false); + EditorGUI.BeginDisabledGroup(!Data.IsCollidable); + ItemDataField("Has Hit Event", ref Data.HitEvent, false); + ItemDataField("Hit Height", ref Data.HitHeight, false); if (_foldoutMaterial = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMaterial, "Physics Material")) { - EditorGUI.BeginDisabledGroup(_rubberData.OverwritePhysics); - MaterialField("Preset", ref _rubberData.PhysicsMaterial, false); + EditorGUI.BeginDisabledGroup(Data.OverwritePhysics); + MaterialField("Preset", ref Data.PhysicsMaterial, false); EditorGUI.EndDisabledGroup(); - ItemDataField("Overwrite Preset", ref _rubberData.OverwritePhysics, false); + ItemDataField("Overwrite Preset", ref Data.OverwritePhysics, false); - EditorGUI.BeginDisabledGroup(!_rubberData.OverwritePhysics); - ItemDataField("Elasticity", ref _rubberData.Elasticity, false); - ItemDataField("Elasticity Falloff", ref _rubberData.ElasticityFalloff, false); - ItemDataField("Friction", ref _rubberData.Friction, false); - ItemDataField("Scatter Angle", ref _rubberData.Scatter, false); + EditorGUI.BeginDisabledGroup(!Data.OverwritePhysics); + ItemDataField("Elasticity", ref Data.Elasticity, false); + ItemDataField("Elasticity Falloff", ref Data.ElasticityFalloff, false); + ItemDataField("Friction", ref Data.Friction, false); + ItemDataField("Scatter Angle", ref Data.Scatter, false); EditorGUI.EndDisabledGroup(); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs index 97d0a6e2d..c43799ddb 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs @@ -24,23 +24,19 @@ namespace VisualPinball.Unity.Editor [CustomEditor(typeof(RubberAuthoring))] public class RubberInspector : DragPointsItemInspector { - private bool _foldoutColorsAndFormatting = true; - private bool _foldoutPosition = true; - private bool _foldoutMisc = true; + private bool _foldoutGeometry = true; + private bool _foldoutMesh; + private bool _foldoutMisc; public override void OnInspectorGUI() { - OnPreInspectorGUI(); - - if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - TextureField("Image", ref Data.Image); - MaterialField("Material", ref Data.Material); - ItemDataField("Visible", ref Data.IsVisible); - ItemDataField("Static", ref Data.StaticRendering); + if (HasErrors()) { + return; } - EditorGUILayout.EndFoldoutHeaderGroup(); - if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { + OnPreInspectorGUI(); + + if (_foldoutGeometry = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutGeometry, "Geometry")) { ItemDataField("Height", ref Data.Height); ItemDataField("Thickness", ref Data.Thickness); EditorGUILayout.LabelField("Orientation"); @@ -52,6 +48,14 @@ public override void OnInspectorGUI() } EditorGUILayout.EndFoldoutHeaderGroup(); + if (_foldoutMesh = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMesh, "Mesh")) { + TextureField("Image", ref Data.Image); + MaterialField("Material", ref Data.Material); + ItemDataField("Visible", ref Data.IsVisible); + ItemDataField("Static", ref Data.StaticRendering); + } + EditorGUILayout.EndFoldoutHeaderGroup(); + if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { ItemDataField("Timer Enabled", ref Data.IsTimerEnabled, false); ItemDataField("Timer Interval", ref Data.TimerInterval, false); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberMeshInspector.cs new file mode 100644 index 000000000..bb12eca94 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberMeshInspector.cs @@ -0,0 +1,42 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Kicker; +using VisualPinball.Engine.VPT.Rubber; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(RubberMeshAuthoring))] + public class RubberMeshInspector : ItemMeshInspector + { + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + TextureField("Image", ref Data.Image); + MaterialField("Material", ref Data.Material); + ItemDataField("Visible", ref Data.IsVisible); + ItemDataField("Static", ref Data.StaticRendering); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberMeshInspector.cs.meta new file mode 100644 index 000000000..f5cea3e20 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d57ea4fa645e4614fb3b9c35d976e649 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerBracketMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerBracketMeshInspector.cs new file mode 100644 index 000000000..6328c61c3 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerBracketMeshInspector.cs @@ -0,0 +1,36 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Spinner; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(SpinnerBracketMeshAuthoring))] + public class SpinnerBracketMeshInspector : ItemMeshInspector + { + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerColliderInspector.cs new file mode 100644 index 000000000..a0e803f6f --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerColliderInspector.cs @@ -0,0 +1,38 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Spinner; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(SpinnerColliderAuthoring))] + public class SpinnerColliderInspector : ItemColliderInspector + { + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + ItemDataField("Damping", ref Data.Damping, false); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerInspector.cs index 94c3e6394..25a5bd52a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerInspector.cs @@ -14,57 +14,59 @@ // 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.Spinner; namespace VisualPinball.Unity.Editor { [CustomEditor(typeof(SpinnerAuthoring))] - public class SpinnerInspector : ItemInspector + public class SpinnerInspector : ItemMainInspector { - private SpinnerAuthoring _spinner; - private bool _foldoutColorsAndFormatting = true; - private bool _foldoutPosition = true; - private bool _foldoutPhysics = true; - private bool _foldoutMisc = true; - - protected override void OnEnable() - { - base.OnEnable(); - _spinner = target as SpinnerAuthoring; - } + private bool _foldoutGeometry = true; + private bool _foldoutMesh; + private bool _foldoutPhysics; + private bool _foldoutMisc; public override void OnInspectorGUI() { + if (HasErrors()) { + return; + } + + ItemDataField("Position", ref Data.Center); + SurfaceField("Surface", ref Data.Surface); + OnPreInspectorGUI(); - if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - ItemDataField("Visible", ref _spinner.Data.IsVisible); - TextureField("Image", ref _spinner.Data.Image); - MaterialField("Material", ref _spinner.Data.Material); - ItemDataField("Show Bracket", ref _spinner.Data.ShowBracket); + if (_foldoutGeometry = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutGeometry, "Geometry")) { + + ItemDataField("Length", ref Data.Length); + ItemDataField("Height", ref Data.Height); + ItemDataField("Rotation", ref Data.Rotation); + ItemDataField("Angle Max", ref Data.AngleMax, false); + ItemDataField("Angle Min", ref Data.AngleMin, false); + ItemDataField("Elasticity", ref Data.Elasticity, false); } EditorGUILayout.EndFoldoutHeaderGroup(); - if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("", ref _spinner.Data.Center); - ItemDataField("Length", ref _spinner.Data.Length); - ItemDataField("Height", ref _spinner.Data.Height); - ItemDataField("Rotation", ref _spinner.Data.Rotation); - ItemDataField("Angle Max", ref _spinner.Data.AngleMax, dirtyMesh: false); - ItemDataField("Angle Min", ref _spinner.Data.AngleMin, dirtyMesh: false); - ItemDataField("Elasticity", ref _spinner.Data.Elasticity, dirtyMesh: false); - SurfaceField("Surface", ref _spinner.Data.Surface); + if (_foldoutMesh = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMesh, "Mesh")) { + ItemDataField("Visible", ref Data.IsVisible); + TextureField("Image", ref Data.Image); + MaterialField("Material", ref Data.Material); + ItemDataField("Show Bracket", ref Data.ShowBracket); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "Physics")) { - ItemDataField("Damping", ref _spinner.Data.Damping, dirtyMesh: false); + ItemDataField("Damping", ref Data.Damping, false); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _spinner.Data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _spinner.Data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref Data.IsTimerEnabled, false); + ItemDataField("Timer Interval", ref Data.TimerInterval, false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerPlateMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerPlateMeshInspector.cs new file mode 100644 index 000000000..038aa1741 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerPlateMeshInspector.cs @@ -0,0 +1,41 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Spinner; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(SpinnerPlateMeshAuthoring))] + public class SpinnerPlateMeshInspector : ItemMeshInspector + { + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + ItemDataField("Visible", ref Data.IsVisible); + TextureField("Image", ref Data.Image); + MaterialField("Material", ref Data.Material); + ItemDataField("Show Bracket", ref Data.ShowBracket); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs index e2ffd2e65..c71d2407e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs @@ -24,53 +24,44 @@ namespace VisualPinball.Unity.Editor [CustomEditor(typeof(SurfaceColliderAuthoring))] public class SurfaceColliderInspector : ItemColliderInspector { - private SurfaceData _surfaceData; - private bool _foldoutMaterial = true; private bool _foldoutSlingshot = true; - protected override void OnEnable() - { - base.OnEnable(); - _surfaceData = Data; - } - public override void OnInspectorGUI() { - if (_surfaceData == null) { - NoDataError(); + if (HasErrors()) { return; } - ItemDataField("Collidable", ref _surfaceData.IsCollidable, false); + ItemDataField("Collidable", ref Data.IsCollidable, false); - EditorGUI.BeginDisabledGroup(!_surfaceData.IsCollidable); + EditorGUI.BeginDisabledGroup(!Data.IsCollidable); - ItemDataField("Has Hit Event", ref _surfaceData.HitEvent, false); - EditorGUI.BeginDisabledGroup(!_surfaceData.HitEvent); - ItemDataField("Hit Threshold", ref _surfaceData.Threshold, false); + ItemDataField("Has Hit Event", ref Data.HitEvent, false); + EditorGUI.BeginDisabledGroup(!Data.HitEvent); + ItemDataField("Hit Threshold", ref Data.Threshold, false); EditorGUI.EndDisabledGroup(); - ItemDataField("Can Drop", ref _surfaceData.IsDroppable, false); - ItemDataField("Is Bottom Collidable", ref _surfaceData.IsBottomSolid, false); + ItemDataField("Can Drop", ref Data.IsDroppable, false); + ItemDataField("Is Bottom Collidable", ref Data.IsBottomSolid, false); if (_foldoutSlingshot = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutSlingshot, "Slingshot")) { - ItemDataField("Slingshot Force", ref _surfaceData.SlingshotForce, false); - ItemDataField("Slingshot Threshold", ref _surfaceData.SlingshotThreshold, false); + ItemDataField("Slingshot Force", ref Data.SlingshotForce, false); + ItemDataField("Slingshot Threshold", ref Data.SlingshotThreshold, false); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMaterial = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMaterial, "Physics Material")) { - EditorGUI.BeginDisabledGroup(_surfaceData.OverwritePhysics); - MaterialField("Preset", ref _surfaceData.PhysicsMaterial, false); + EditorGUI.BeginDisabledGroup(Data.OverwritePhysics); + MaterialField("Preset", ref Data.PhysicsMaterial, false); EditorGUI.EndDisabledGroup(); - ItemDataField("Overwrite Preset", ref _surfaceData.OverwritePhysics, false); + ItemDataField("Overwrite Preset", ref Data.OverwritePhysics, false); - EditorGUI.BeginDisabledGroup(!_surfaceData.OverwritePhysics); - ItemDataField("Elasticity", ref _surfaceData.Elasticity, false); - ItemDataField("Friction", ref _surfaceData.Friction, false); - ItemDataField("Scatter Angle", ref _surfaceData.Scatter, false); + EditorGUI.BeginDisabledGroup(!Data.OverwritePhysics); + ItemDataField("Elasticity", ref Data.Elasticity, false); + ItemDataField("Friction", ref Data.Friction, false); + ItemDataField("Scatter Angle", ref Data.Scatter, false); EditorGUI.EndDisabledGroup(); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs index 8d4ed1756..07567de21 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceInspector.cs @@ -30,6 +30,10 @@ public class SurfaceInspector : DragPointsItemInspector. + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT.Trigger; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(TriggerColliderAuthoring))] + public class TriggerColliderInspector : ItemColliderInspector + { + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + ItemDataField("Enabled", ref Data.IsEnabled, false); + ItemDataField("Hit Height", ref Data.HitHeight, false); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerColliderInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerColliderInspector.cs.meta new file mode 100644 index 000000000..6edc292e1 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerColliderInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 40c14b690481f6547a311c2dfaf431ee +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerInspector.cs index 1b970950d..b2edaf22c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerInspector.cs @@ -26,36 +26,23 @@ namespace VisualPinball.Unity.Editor public class TriggerInspector : DragPointsItemInspector { private bool _foldoutColorsAndFormatting = true; - private bool _foldoutPosition = true; - private bool _foldoutPhysics = true; - private bool _foldoutMisc = true; - - private static readonly string[] TriggerShapeLabels = { - "None", - "Button", - "Star", - "Wire A", - "Wire B", - "Wire C", - "Wire D", - }; - private static readonly int[] TriggerShapeValues = { - TriggerShape.TriggerNone, - TriggerShape.TriggerButton, - TriggerShape.TriggerStar, - TriggerShape.TriggerWireA, - TriggerShape.TriggerWireB, - TriggerShape.TriggerWireC, - TriggerShape.TriggerWireD, - }; + private bool _foldoutPhysics; + private bool _foldoutMisc; public override void OnInspectorGUI() { + if (HasErrors()) { + return; + } + + ItemDataField("", ref Data.Center); + SurfaceField("Surface", ref Data.Surface); + OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { ItemDataField("Visible", ref Data.IsVisible); - DropDownField("Shape", ref Data.Shape, TriggerShapeLabels, TriggerShapeValues); + DropDownField("Shape", ref Data.Shape, TriggerMeshInspector.TriggerShapeLabels, TriggerMeshInspector.TriggerShapeValues); ItemDataField("Wire Thickness", ref Data.WireThickness); ItemDataField("Star Radius", ref Data.Radius); ItemDataField("Rotation", ref Data.Rotation); @@ -64,13 +51,7 @@ public override void OnInspectorGUI() } EditorGUILayout.EndFoldoutHeaderGroup(); - if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("", ref Data.Center); - SurfaceField("Surface", ref Data.Surface); - } - EditorGUILayout.EndFoldoutHeaderGroup(); - - if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "State & Physics")) { + if (_foldoutPhysics = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPhysics, "Physics")) { ItemDataField("Enabled", ref Data.IsEnabled, false); ItemDataField("Hit Height", ref Data.HitHeight, false); } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerMeshInspector.cs new file mode 100644 index 000000000..32077a3fa --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerMeshInspector.cs @@ -0,0 +1,62 @@ +// 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 . + +// ReSharper disable AssignmentInConditionalExpression + +using UnityEditor; +using VisualPinball.Engine.VPT; +using VisualPinball.Engine.VPT.Trigger; + +namespace VisualPinball.Unity.Editor +{ + [CustomEditor(typeof(TriggerMeshAuthoring))] + public class TriggerMeshInspector : ItemMeshInspector + { + public static readonly string[] TriggerShapeLabels = { + "None", + "Button", + "Star", + "Wire A", + "Wire B", + "Wire C", + "Wire D", + }; + public static readonly int[] TriggerShapeValues = { + TriggerShape.TriggerNone, + TriggerShape.TriggerButton, + TriggerShape.TriggerStar, + TriggerShape.TriggerWireA, + TriggerShape.TriggerWireB, + TriggerShape.TriggerWireC, + TriggerShape.TriggerWireD, + }; + + public override void OnInspectorGUI() + { + if (HasErrors()) { + return; + } + + ItemDataField("Visible", ref Data.IsVisible); + DropDownField("Shape", ref Data.Shape, TriggerShapeLabels, TriggerShapeValues); + ItemDataField("Wire Thickness", ref Data.WireThickness); + ItemDataField("Star Radius", ref Data.Radius); + MaterialField("Material", ref Data.Material); + + base.OnInspectorGUI(); + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerMeshInspector.cs.meta new file mode 100644 index 000000000..6fffa232e --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b9e42e2725f27084093627d5262ea529 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerMeshAuthoring.cs index 29848f061..d51782fda 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerMeshAuthoring.cs @@ -22,7 +22,7 @@ namespace VisualPinball.Unity { [ExecuteInEditMode] - [AddComponentMenu("Visual Pinball/Mesh/Kicker Bracket Mesh")] + [AddComponentMenu("Visual Pinball/Mesh/Kicker Mesh")] public class KickerMeshAuthoring : ItemMeshAuthoring { public static readonly Type[] ValidParentTypes = new Type[0]; From 78b8531c20bacc67aa1ff20cd93e23d77a9efa5d Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 26 Oct 2020 01:04:15 +0100 Subject: [PATCH 106/124] components: Update name and visibility when restoring based on hierarchy. --- .../VPT/Bumper/BumperBaseMeshInspector.cs | 11 +---- .../VPT/Bumper/BumperCapMeshInspector.cs | 10 +---- .../VPT/Bumper/BumperColliderInspector.cs | 13 +++--- .../VPT/Bumper/BumperInspector.cs | 41 ++++++++---------- .../VPT/Bumper/BumperRingMeshInspector.cs | 11 +---- .../VPT/Bumper/BumperRingMovementInspector.cs | 12 +----- .../VPT/Bumper/BumperSkirtMeshInspector.cs | 11 +---- .../VPT/Flipper/FlipperInspector.cs | 1 - .../VPT/Gate/GateColliderInspector.cs | 1 - .../VPT/Gate/GateInspector.cs | 2 - .../HitTarget/HitTargetColliderInspector.cs | 1 - .../VPT/HitTarget/HitTargetInspector.cs | 1 - .../VPT/Plunger/PlungerInspector.cs | 1 - .../VPT/Primitive/PrimitiveInspector.cs | 14 +------ .../VPT/Ramp/RampColliderInspector.cs | 2 - .../VPT/Ramp/RampInspector.cs | 3 -- .../VPT/Rubber/RubberColliderInspector.cs | 5 --- .../VPT/Rubber/RubberInspector.cs | 1 - .../VPT/Rubber/RubberMeshInspector.cs | 1 - .../SpinnerBracketMeshInspector.cs.meta | 11 +++++ .../Spinner/SpinnerColliderInspector.cs.meta | 11 +++++ .../Spinner/SpinnerPlateMeshInspector.cs.meta | 11 +++++ .../VPT/Surface/SurfaceColliderInspector.cs | 6 --- .../VPT/Surface/SurfaceSideMeshInspector.cs | 1 - .../VPT/Surface/SurfaceTopMeshInspector.cs | 1 - .../VPT/Trigger/TriggerInspector.cs | 3 +- .../VPT/Trigger/TriggerMeshInspector.cs | 1 - .../Game/Engine/DefaultGamelogicEngine.cs | 11 ----- .../VPT/Bumper/BumperAuthoring.cs | 34 ++++++++++++++- .../VPT/Flipper/FlipperAuthoring.cs | 25 +++++++++-- .../VPT/Gate/GateAuthoring.cs | 36 +++++++++++++--- .../VPT/HitTarget/HitTargetAuthoring.cs | 22 +++++++++- .../VPT/ItemMainAuthoring.cs | 9 +++- .../VPT/Kicker/KickerAuthoring.cs | 7 +++- .../VPT/Light/LightAuthoring.cs | 19 +++++++++ .../VPT/Playfield/PlayfieldAuthoring.cs | 15 +------ .../VPT/Plunger/PlungerAuthoring.cs | 37 +++++++++++----- .../VPT/Primitive/PrimitiveAuthoring.cs | 29 +++++++++++-- .../VPT/Ramp/RampAuthoring.cs | 28 ++++++++++++- .../VPT/Rubber/RubberAuthoring.cs | 28 ++++++++----- .../VPT/Spinner/SpinnerAuthoring.cs | 30 ++++++++++--- .../VPT/Surface/SurfaceAuthoring.cs | 42 ++++++++++++++----- .../VPT/Table/TableAuthoring.cs | 14 ++++++- .../VPT/Trigger/TriggerAuthoring.cs | 31 ++++++++++---- 44 files changed, 393 insertions(+), 211 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerBracketMeshInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerColliderInspector.cs.meta create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerPlateMeshInspector.cs.meta diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperBaseMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperBaseMeshInspector.cs index 57196eec7..4ae1da97f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperBaseMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperBaseMeshInspector.cs @@ -24,22 +24,13 @@ namespace VisualPinball.Unity.Editor [CustomEditor(typeof(BumperBaseMeshAuthoring))] public class BumperBaseMeshInspector : ItemMeshInspector { - private BumperData _data; - - protected override void OnEnable() - { - base.OnEnable(); - _data = Data; - } - public override void OnInspectorGUI() { if (HasErrors()) { return; } - ItemDataField("Is Visible", ref _data.IsBaseVisible, onChanged: MeshAuthoring.OnVisibilityChanged); - MaterialField("Base Material", ref _data.BaseMaterial); + MaterialField("Base Material", ref Data.BaseMaterial); base.OnInspectorGUI(); } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperCapMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperCapMeshInspector.cs index cb95be549..7b868540f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperCapMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperCapMeshInspector.cs @@ -24,13 +24,6 @@ namespace VisualPinball.Unity.Editor [CustomEditor(typeof(BumperCapMeshAuthoring))] public class BumperCapMeshInspector : ItemMeshInspector { - private BumperData _data; - - protected override void OnEnable() - { - base.OnEnable(); - _data = Data; - } public override void OnInspectorGUI() { @@ -38,8 +31,7 @@ public override void OnInspectorGUI() return; } - ItemDataField("Is Visible", ref _data.IsCapVisible, onChanged: MeshAuthoring.OnVisibilityChanged); - MaterialField("Cap Material", ref _data.CapMaterial); + MaterialField("Cap Material", ref Data.CapMaterial); base.OnInspectorGUI(); } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs index 07bd320ab..c1a705815 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperColliderInspector.cs @@ -24,20 +24,17 @@ namespace VisualPinball.Unity.Editor [CustomEditor(typeof(BumperColliderAuthoring))] public class BumperColliderInspector : ItemColliderInspector { + public override void OnInspectorGUI() { if (HasErrors()) { return; } - ItemDataField("Collidable", ref Data.IsCollidable, dirtyMesh: false); - - EditorGUI.BeginDisabledGroup(!Data.IsCollidable); - ItemDataField("Has Hit Event", ref Data.HitEvent, dirtyMesh: false); - ItemDataField("Force", ref Data.Force, dirtyMesh: false); - ItemDataField("Hit Threshold", ref Data.Threshold, dirtyMesh: false); - ItemDataField("Scatter Angle", ref Data.Scatter, dirtyMesh: false); - EditorGUI.EndDisabledGroup(); + ItemDataField("Has Hit Event", ref Data.HitEvent, false); + ItemDataField("Force", ref Data.Force, false); + ItemDataField("Hit Threshold", ref Data.Threshold, false); + ItemDataField("Scatter Angle", ref Data.Scatter, false); base.OnInspectorGUI(); } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs index 15cd31968..5a8113158 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperInspector.cs @@ -17,44 +17,37 @@ // ReSharper disable AssignmentInConditionalExpression using UnityEditor; +using VisualPinball.Engine.VPT.Bumper; namespace VisualPinball.Unity.Editor { [CustomEditor(typeof(BumperAuthoring))] - public class BumperInspector : ItemInspector + public class BumperInspector : ItemMainInspector { - private BumperAuthoring _bumper; - private bool _foldoutColorsAndFormatting = true; - private bool _foldoutPosition = true; - private bool _foldoutPhysics = true; - private bool _foldoutMisc = true; - - protected override void OnEnable() - { - base.OnEnable(); - _bumper = target as BumperAuthoring; - } + private bool _foldoutGeometry = true; + private bool _foldoutMisc; public override void OnInspectorGUI() { - OnPreInspectorGUI(); - - if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - ItemDataField("Radius", ref _bumper.Data.Radius); - ItemDataField("Height Scale", ref _bumper.Data.HeightScale); - ItemDataField("Orientation", ref _bumper.Data.Orientation); + if (HasErrors()) { + return; } - EditorGUILayout.EndFoldoutHeaderGroup(); - if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemDataField("", ref _bumper.Data.Center); - SurfaceField("Surface", ref _bumper.Data.Surface); + ItemDataField("Position", ref Data.Center); + SurfaceField("Surface", ref Data.Surface); + + OnPreInspectorGUI(); + + if (_foldoutGeometry = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutGeometry, "Geometry")) { + ItemDataField("Radius", ref Data.Radius); + ItemDataField("Height Scale", ref Data.HeightScale); + ItemDataField("Orientation", ref Data.Orientation); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Timer Enabled", ref _bumper.Data.IsTimerEnabled, dirtyMesh: false); - ItemDataField("Timer Interval", ref _bumper.Data.TimerInterval, dirtyMesh: false); + ItemDataField("Timer Enabled", ref Data.IsTimerEnabled, false); + ItemDataField("Timer Interval", ref Data.TimerInterval, false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMeshInspector.cs index 2324c4235..f433ca952 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMeshInspector.cs @@ -24,22 +24,13 @@ namespace VisualPinball.Unity.Editor [CustomEditor(typeof(BumperRingMeshAuthoring))] public class BumperRingMeshInspector : ItemMeshInspector { - private BumperData _data; - - protected override void OnEnable() - { - base.OnEnable(); - _data = Data; - } - public override void OnInspectorGUI() { if (HasErrors()) { return; } - ItemDataField("Is Visible", ref _data.IsRingVisible); - MaterialField("Ring Material", ref _data.RingMaterial); + MaterialField("Ring Material", ref Data.RingMaterial); base.OnInspectorGUI(); } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMovementInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMovementInspector.cs index 435cc0c39..775c0701f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMovementInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperRingMovementInspector.cs @@ -24,22 +24,14 @@ namespace VisualPinball.Unity.Editor [CustomEditor(typeof(BumperRingAnimationAuthoring))] public class BumperRingMovementInspector : ItemMovementInspector { - private BumperData _data; - - protected override void OnEnable() - { - base.OnEnable(); - _data = Data; - } - public override void OnInspectorGUI() { if (HasErrors()) { return; } - ItemDataField("Ring Speed", ref _data.RingSpeed, false); - ItemDataField("Ring Drop Offset", ref _data.RingDropOffset, false); + ItemDataField("Ring Speed", ref Data.RingSpeed, false); + ItemDataField("Ring Drop Offset", ref Data.RingDropOffset, false); base.OnInspectorGUI(); } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperSkirtMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperSkirtMeshInspector.cs index 8494d85ab..161121e9f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperSkirtMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Bumper/BumperSkirtMeshInspector.cs @@ -24,22 +24,13 @@ namespace VisualPinball.Unity.Editor [CustomEditor(typeof(BumperSkirtMeshAuthoring))] public class BumperSkirtMeshInspector : ItemMeshInspector { - private BumperData _data; - - protected override void OnEnable() - { - base.OnEnable(); - _data = Data; - } - public override void OnInspectorGUI() { if (HasErrors()) { return; } - ItemDataField("Is Visible", ref _data.IsSocketVisible); - MaterialField("Skirt Material", ref _data.SocketMaterial); + MaterialField("Skirt Material", ref Data.SocketMaterial); base.OnInspectorGUI(); } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs index b5e233db5..9fe38cf36 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Flipper/FlipperInspector.cs @@ -42,7 +42,6 @@ public override void OnInspectorGUI() OnPreInspectorGUI(); ItemDataField("Enabled", ref Data.IsEnabled); - ItemDataField("Visible", ref Data.IsVisible); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Geometry")) { ItemDataField("Base Radius", ref Data.BaseRadius); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateColliderInspector.cs index ea6c77099..2f1d57b38 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateColliderInspector.cs @@ -34,7 +34,6 @@ public override void OnInspectorGUI() ItemDataField("Friction", ref Data.Friction, false); ItemDataField("Damping", ref Data.Damping, false); ItemDataField("Gravity Factor", ref Data.GravityFactor, false); - ItemDataField("Collidable", ref Data.IsCollidable, false); ItemDataField(GateInspector.TwoWayLabel, ref Data.TwoWay, false); base.OnInspectorGUI(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateInspector.cs index be36d4ca9..039d7029e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Gate/GateInspector.cs @@ -74,8 +74,6 @@ public override void OnInspectorGUI() OnPreInspectorGUI(); - ItemDataField("Visible", ref Data.IsVisible); - if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { DropDownField("Type", ref Data.GateType, GateTypeLabels, GateTypeValues); ItemDataField("Show Bracket", ref Data.ShowBracket); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetColliderInspector.cs index 0bf444482..60d60e9d2 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetColliderInspector.cs @@ -47,7 +47,6 @@ public override void OnInspectorGUI() EditorGUI.EndDisabledGroup(); ItemDataField("Legacy Mode", ref Data.IsLegacy, false); - ItemDataField("Collidable", ref Data.IsCollidable, false); ItemDataField("Is Dropped", ref Data.IsDropped, false); base.OnInspectorGUI(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetInspector.cs index da9b29d05..fe93c8d47 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/HitTarget/HitTargetInspector.cs @@ -46,7 +46,6 @@ public override void OnInspectorGUI() ItemDataField("Drop Speed", ref Data.DropSpeed, false); ItemDataField("Raise Delay", ref Data.RaiseDelay, false); ItemDataField("Depth Bias", ref Data.DepthBias, false); - ItemDataField("Visible", ref Data.IsVisible); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerInspector.cs index d5d0cc07f..aa3b6bdab 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Plunger/PlungerInspector.cs @@ -72,7 +72,6 @@ public override void OnInspectorGUI() ItemDataField("Scatter Velocity", ref Data.ScatterVelocity, false); ItemDataField("Enable Mechanical Plunger", ref Data.IsMechPlunger, false); ItemDataField("Auto Plunger", ref Data.AutoPlunger, false); - ItemDataField("Visible", ref Data.IsVisible); ItemDataField("Mech Strength", ref Data.MechStrength, false); ItemDataField("Momentum Xfer", ref Data.MomentumXfer, false); ItemDataField("Park Position (0..1)", ref Data.ParkPosition, false); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveInspector.cs index 5682938fa..8dc8a3600 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Primitive/PrimitiveInspector.cs @@ -36,15 +36,8 @@ public override void OnInspectorGUI() return; } - EditorGUILayout.LabelField("Base Position"); - EditorGUI.indentLevel++; - ItemDataField("", ref Data.Position); - EditorGUI.indentLevel--; - - EditorGUILayout.LabelField("Base Size"); - EditorGUI.indentLevel++; - ItemDataField("", ref Data.Size); - EditorGUI.indentLevel--; + ItemDataField("Position", ref Data.Position); + ItemDataField("Size", ref Data.Size); OnPreInspectorGUI(); @@ -60,8 +53,6 @@ public override void OnInspectorGUI() ItemDataField("Object Space", ref Data.ObjectSpaceNormalMap); EditorGUI.indentLevel--; MaterialField("Material", ref Data.Material); - - ItemDataField("Visible", ref Data.IsVisible); } EditorGUILayout.EndFoldoutHeaderGroup(); @@ -100,7 +91,6 @@ public override void OnInspectorGUI() EditorGUI.EndDisabledGroup(); EditorGUI.BeginDisabledGroup(Data.IsToy); - ItemDataField("Collidable", ref Data.IsCollidable, false); EditorGUI.EndDisabledGroup(); ItemDataField("Toy", ref Data.IsToy, false); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampColliderInspector.cs index 1888161b0..222ea5289 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampColliderInspector.cs @@ -52,8 +52,6 @@ public override void OnInspectorGUI() ItemDataField("Scatter Angle", ref Data.Scatter, false); EditorGUI.EndDisabledGroup(); - ItemDataField("Collidable", ref Data.IsCollidable, false); - base.OnInspectorGUI(); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs index 0258fbc8d..922b8a23c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Ramp/RampInspector.cs @@ -69,7 +69,6 @@ public override void OnInspectorGUI() MaterialField("Material", ref Data.Material); DropDownField("Image Mode", ref Data.ImageAlignment, RampImageAlignmentLabels, RampImageAlignmentValues); ItemDataField("Apply Image To Wall", ref Data.ImageWalls); - ItemDataField("Visible", ref Data.IsVisible); ItemDataField("Depth Bias", ref Data.DepthBias); } EditorGUILayout.EndFoldoutHeaderGroup(); @@ -118,8 +117,6 @@ public override void OnInspectorGUI() ItemDataField("Friction", ref Data.Friction, false); ItemDataField("Scatter Angle", ref Data.Scatter, false); EditorGUI.EndDisabledGroup(); - - ItemDataField("Collidable", ref Data.IsCollidable, false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs index 7b74728ee..48a308e36 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberColliderInspector.cs @@ -32,9 +32,6 @@ public override void OnInspectorGUI() return; } - ItemDataField("Collidable", ref Data.IsCollidable, false); - - EditorGUI.BeginDisabledGroup(!Data.IsCollidable); ItemDataField("Has Hit Event", ref Data.HitEvent, false); ItemDataField("Hit Height", ref Data.HitHeight, false); @@ -54,8 +51,6 @@ public override void OnInspectorGUI() } EditorGUILayout.EndFoldoutHeaderGroup(); - EditorGUI.EndDisabledGroup(); - base.OnInspectorGUI(); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs index c43799ddb..9098d8bba 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberInspector.cs @@ -51,7 +51,6 @@ public override void OnInspectorGUI() if (_foldoutMesh = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMesh, "Mesh")) { TextureField("Image", ref Data.Image); MaterialField("Material", ref Data.Material); - ItemDataField("Visible", ref Data.IsVisible); ItemDataField("Static", ref Data.StaticRendering); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberMeshInspector.cs index bb12eca94..419f21f7b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Rubber/RubberMeshInspector.cs @@ -33,7 +33,6 @@ public override void OnInspectorGUI() TextureField("Image", ref Data.Image); MaterialField("Material", ref Data.Material); - ItemDataField("Visible", ref Data.IsVisible); ItemDataField("Static", ref Data.StaticRendering); base.OnInspectorGUI(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerBracketMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerBracketMeshInspector.cs.meta new file mode 100644 index 000000000..77053c6e6 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerBracketMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a5a0382d3cb181c4b94df3a39552c663 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerColliderInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerColliderInspector.cs.meta new file mode 100644 index 000000000..89ab51e2b --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerColliderInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ebd26a284357f2b4ea35b6e8b263f292 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerPlateMeshInspector.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerPlateMeshInspector.cs.meta new file mode 100644 index 000000000..2aff7b362 --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Spinner/SpinnerPlateMeshInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 041be3b40e0fc51469a164794c20bb21 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs index c71d2407e..a56797a08 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceColliderInspector.cs @@ -33,10 +33,6 @@ public override void OnInspectorGUI() return; } - ItemDataField("Collidable", ref Data.IsCollidable, false); - - EditorGUI.BeginDisabledGroup(!Data.IsCollidable); - ItemDataField("Has Hit Event", ref Data.HitEvent, false); EditorGUI.BeginDisabledGroup(!Data.HitEvent); ItemDataField("Hit Threshold", ref Data.Threshold, false); @@ -66,8 +62,6 @@ public override void OnInspectorGUI() } EditorGUILayout.EndFoldoutHeaderGroup(); - EditorGUI.EndDisabledGroup(); - base.OnInspectorGUI(); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceSideMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceSideMeshInspector.cs index 0ff4a63aa..5574bf9de 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceSideMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceSideMeshInspector.cs @@ -38,7 +38,6 @@ public override void OnInspectorGUI() return; } - ItemDataField("Side Visible", ref _data.IsSideVisible); TextureField("Side Image", ref _data.SideImage); MaterialField("Side Material", ref _data.SideMaterial); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceTopMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceTopMeshInspector.cs index 44021a27c..0e4027f42 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceTopMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Surface/SurfaceTopMeshInspector.cs @@ -38,7 +38,6 @@ public override void OnInspectorGUI() return; } - ItemDataField("Top Visible", ref _data.IsTopBottomVisible); TextureField("Top Image", ref _data.Image); MaterialField("Top Material", ref _data.TopMaterial); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerInspector.cs index b2edaf22c..a0782e96a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerInspector.cs @@ -35,13 +35,12 @@ public override void OnInspectorGUI() return; } - ItemDataField("", ref Data.Center); + ItemDataField("Position", ref Data.Center); SurfaceField("Surface", ref Data.Surface); OnPreInspectorGUI(); if (_foldoutColorsAndFormatting = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutColorsAndFormatting, "Colors & Formatting")) { - ItemDataField("Visible", ref Data.IsVisible); DropDownField("Shape", ref Data.Shape, TriggerMeshInspector.TriggerShapeLabels, TriggerMeshInspector.TriggerShapeValues); ItemDataField("Wire Thickness", ref Data.WireThickness); ItemDataField("Star Radius", ref Data.Radius); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerMeshInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerMeshInspector.cs index 32077a3fa..1bc97e2aa 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerMeshInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/Trigger/TriggerMeshInspector.cs @@ -50,7 +50,6 @@ public override void OnInspectorGUI() return; } - ItemDataField("Visible", ref Data.IsVisible); DropDownField("Shape", ref Data.Shape, TriggerShapeLabels, TriggerShapeValues); ItemDataField("Wire Thickness", ref Data.WireThickness); ItemDataField("Star Radius", ref Data.Radius); diff --git a/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/DefaultGamelogicEngine.cs b/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/DefaultGamelogicEngine.cs index e781dbf8c..de2803975 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/DefaultGamelogicEngine.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/DefaultGamelogicEngine.cs @@ -88,15 +88,6 @@ public void OnInit(TableApi tableApi, BallManager ballManager) // debug print stuff OnCoilChanged += DebugPrintCoil; - - _tableApi.Rubber("Rubber1").Hit += LogHit; - _tableApi.Surface("Collider").Hit += LogHit; - } - - private void LogHit(object sender, EventArgs e) - { - var api = sender as IApi; - Debug.Log("Hit by " + api?.Name + "!"); } public void OnUpdate() @@ -106,8 +97,6 @@ public void OnUpdate() public void OnDestroy() { OnCoilChanged -= DebugPrintCoil; - _tableApi.Rubber("Rubber1").Hit -= LogHit; - _tableApi.Surface("Collider").Hit -= LogHit; } public event EventHandler OnCoilChanged; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs index 74533995f..fa684d1ae 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperAuthoring.cs @@ -68,8 +68,40 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterBumper(Item, entity, gameObject); } - public void RemoveHittableComponent() + public override void Restore() { + // update the name + Item.Name = name; + + // update visibility + Data.IsBaseVisible = false; + Data.IsCapVisible = false; + Data.IsRingVisible = false; + Data.IsSocketVisible = false; + foreach (var meshComponent in MeshComponents) { + switch (meshComponent) { + case BumperBaseMeshAuthoring baseMeshAuthoring: + Data.IsCapVisible = baseMeshAuthoring.gameObject.activeInHierarchy; + break; + case BumperCapMeshAuthoring capMeshAuthoring: + Data.IsCapVisible = capMeshAuthoring.gameObject.activeInHierarchy; + break; + case BumperRingMeshAuthoring ringMeshAuthoring: + Data.IsRingVisible = ringMeshAuthoring.gameObject.activeInHierarchy; + break; + case BumperSkirtMeshAuthoring skirtMeshAuthoring: + Data.IsSocketVisible = skirtMeshAuthoring.gameObject.activeInHierarchy; + break; + } + } + + // update collision + Data.IsCollidable = false; + foreach (var colliderComponent in ColliderComponents) { + if (colliderComponent is BumperColliderAuthoring colliderAuthoring) { + Data.IsCollidable = colliderAuthoring.gameObject.activeInHierarchy; + } + } } public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs index 9f8fb2514..c7bd2b306 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperAuthoring.cs @@ -71,6 +71,27 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterFlipper(Item, entity, gameObject); } + public override void Restore() + { + // update the name + Item.Name = name; + + // update visibility + Data.IsVisible = false; + foreach (var meshComponent in MeshComponents) { + switch (meshComponent) { + case FlipperBaseMeshAuthoring baseMeshAuthoring: + Data.IsVisible = Data.IsVisible || baseMeshAuthoring.gameObject.activeInHierarchy; + break; + case FlipperRubberMeshAuthoring rubberMeshAuthoring: + Data.IsVisible = Data.IsVisible || rubberMeshAuthoring.gameObject.activeInHierarchy; + break; + } + } + + // collision: flipper is always collidable + } + public void OnRubberWidthUpdated(float before, float after) { if (before != 0 && after != 0f) { @@ -89,10 +110,6 @@ public void OnRubberWidthUpdated(float before, float after) } } - public void RemoveHittableComponent() - { - } - public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; public override Vector3 GetEditorPosition() => Data.Center.ToUnityVector3(0f); public override void SetEditorPosition(Vector3 pos) => Data.Center = pos.ToVertex2Dxy(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs index 36211a119..fc814ede5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateAuthoring.cs @@ -47,7 +47,6 @@ public class GateAuthoring : ItemMainAuthoring, .Concat(GateWireMeshAuthoring.ValidParentTypes) .Distinct(); - public IHittable Hittable => Item; public ISwitchable Switchable => Item; public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) @@ -67,15 +66,42 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterGate(Item, entity, gameObject); } - private void OnDestroy() + public override void Restore() { - if (!Application.isPlaying) { - Table?.Remove(Name); + // update the name + Item.Name = name; + + // update visibility + Data.IsVisible = false; + Data.ShowBracket = false; + foreach (var meshComponent in MeshComponents) { + switch (meshComponent) { + case GateBracketMeshAuthoring bracketMeshAuthoring: + var bracketMeshAuthoringEnabled = bracketMeshAuthoring.gameObject.activeInHierarchy; + Data.IsVisible = Data.IsVisible || bracketMeshAuthoringEnabled; + Data.ShowBracket = bracketMeshAuthoringEnabled; + break; + + case GateWireMeshAuthoring wireMeshAuthoring: + Data.IsVisible = wireMeshAuthoring.gameObject.activeInHierarchy; + break; + } + } + + // update collision + Data.IsCollidable = false; + foreach (var colliderComponent in ColliderComponents) { + if (colliderComponent is GateColliderAuthoring colliderAuthoring) { + Data.IsCollidable = colliderAuthoring.gameObject.activeInHierarchy; + } } } - public void RemoveHittableComponent() + private void OnDestroy() { + if (!Application.isPlaying) { + Table?.Remove(Name); + } } public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs index 642cb5e08..572ea9e49 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetAuthoring.cs @@ -76,8 +76,28 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterHitTarget(hitTarget, entity, gameObject); } - public void RemoveHittableComponent() + public override void Restore() { + // update the name + Item.Name = name; + + // update visibility + Data.IsVisible = false; + foreach (var meshComponent in MeshComponents) { + switch (meshComponent) { + case HitTargetMeshAuthoring meshAuthoring: + Data.IsVisible = meshAuthoring.gameObject.activeInHierarchy; + break; + } + } + + // update collision + Data.IsCollidable = false; + foreach (var colliderComponent in ColliderComponents) { + if (colliderComponent is HitTargetColliderAuthoring colliderAuthoring) { + Data.IsCollidable = colliderAuthoring.gameObject.activeInHierarchy; + } + } } public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs index f1b06715d..f7f50bce5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs @@ -28,6 +28,11 @@ public abstract class ItemMainAuthoring : ItemAuthoring ValidParents { get; } + public virtual void Restore() + { + // todo make abstract + } + /// /// The serialized data, as written to the .vpx file. /// @@ -50,12 +55,12 @@ public abstract class ItemMainAuthoring : ItemAuthoring /// Returns all child mesh components linked to this data. /// - private IEnumerable MeshComponents => MeshAuthoringType != null ? + protected IEnumerable MeshComponents => MeshAuthoringType != null ? GetComponentsInChildren(MeshAuthoringType, true) .Select(c => (IItemMeshAuthoring) c) .Where(ma => ma.ItemData == _data) : new IItemMeshAuthoring[0]; - private IEnumerable ColliderComponents => ColliderAuthoringType != null ? + protected IEnumerable ColliderComponents => ColliderAuthoringType != null ? GetComponentsInChildren(ColliderAuthoringType, true) .Select(c => (IItemColliderAuthoring) c) .Where(ca => ca.ItemData == _data) : new IItemColliderAuthoring[0]; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs index 2e3efe2e5..b68491ecc 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerAuthoring.cs @@ -95,8 +95,13 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterKicker(Item, entity, gameObject); } - public void RemoveHittableComponent() + public override void Restore() { + // update the name + Item.Name = name; + + // visibility is set by the type + // and it's always collidable } public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs index 6ce3a0ef5..0434a87ab 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightAuthoring.cs @@ -43,6 +43,25 @@ public class LightAuthoring : ItemMainAuthoring .Concat(LightSocketMeshAuthoring.ValidParentTypes) .Distinct(); + public override void Restore() + { + // update the name + Item.Name = name; + + // update visibility + Data.ShowBulbMesh = false; + foreach (var meshComponent in MeshComponents) { + switch (meshComponent) { + case LightBulbMeshAuthoring bulbMeshAuthoring: + Data.ShowBulbMesh = Data.ShowBulbMesh || bulbMeshAuthoring.gameObject.activeInHierarchy; + break; + case LightSocketMeshAuthoring socketMeshAuthoring: + Data.ShowBulbMesh = Data.ShowBulbMesh || socketMeshAuthoring.gameObject.activeInHierarchy; + break; + } + } + } + public void OnBulbEnabled(bool bulbEnabledBefore, bool bulbEnabledAfter) { if (bulbEnabledBefore == bulbEnabledAfter) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs index 608aebaba..3c754b7a6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs @@ -49,20 +49,9 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio table.Version = entity.Version; } - public void RemoveHittableComponent() + public override void Restore() { - var rc = gameObject.GetComponent(); - if (rc != null) { - DestroyImmediate(rc); - } - } - - public void RemoveMeshComponent() - { - var rc = gameObject.GetComponent(); - if (rc != null) { - DestroyImmediate(rc); - } + // todo } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs index d8116a997..556dea095 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerAuthoring.cs @@ -40,13 +40,6 @@ public class PlungerAuthoring : ItemMainAuthoring, .Concat(PlungerSpringMeshAuthoring.ValidParentTypes) .Distinct(); - private void OnDestroy() - { - if (!Application.isPlaying) { - Table?.Remove(Name); - } - } - public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { Convert(entity, dstManager); @@ -101,6 +94,28 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio }); } + public override void Restore() + { + // update the name + Item.Name = name; + + // update visibility + Data.IsVisible = false; + foreach (var meshComponent in MeshComponents) { + switch (meshComponent) { + case PlungerFlatMeshAuthoring flatMeshAuthoring: + Data.IsVisible = flatMeshAuthoring.gameObject.activeInHierarchy; + break; + case PlungerRodMeshAuthoring rodMeshAuthoring: + Data.IsVisible = Data.IsVisible || rodMeshAuthoring.gameObject.activeInHierarchy; + break; + case PlungerSpringMeshAuthoring springMeshAuthoring: + Data.IsVisible = Data.IsVisible || springMeshAuthoring.gameObject.activeInHierarchy; + break; + } + } + } + public void OnTypeChanged(int plungerTypeBefore, int plungerTypeAfter) { if (plungerTypeBefore == plungerTypeAfter) { @@ -158,14 +173,16 @@ public void OnTypeChanged(int plungerTypeBefore, int plungerTypeAfter) // create flat PlungerExtensions.CreateChild(gameObject, PlungerMeshGenerator.Flat); } - break; - } } - public void RemoveHittableComponent() + + private void OnDestroy() { + if (!Application.isPlaying) { + Table?.Remove(Name); + } } public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs index 01e555409..767f29d39 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs @@ -52,11 +52,34 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterPrimitive(primitive, entity, gameObject); } - public void RemoveHittableComponent() + public override void Restore() { - } + // update the name + Item.Name = name; + + // update visibility + Data.IsVisible = false; + foreach (var meshComponent in MeshComponents) { + switch (meshComponent) { + case PrimitiveMeshAuthoring meshAuthoring: + Data.IsVisible = meshAuthoring.gameObject.activeInHierarchy; + break; + } + } - public IHittable Hittable => Item; + // update collision + // todo at some point we need to be able to toggle collidable during gameplay, + // todo but for now let's keep things static. + Data.IsToy = true; + Data.IsCollidable = false; + foreach (var colliderComponent in ColliderComponents) { + if (colliderComponent is PrimitiveColliderAuthoring colliderAuthoring) { + var active = colliderAuthoring.gameObject.activeInHierarchy; + Data.IsCollidable = active; + Data.IsToy = !active; + } + } + } public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; public override Vector3 GetEditorPosition() => Data.Position.ToUnityVector3(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs index 91d91e07d..306b443e3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs @@ -55,8 +55,34 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterRamp(Item, entity, gameObject); } - public void RemoveHittableComponent() + public override void Restore() { + // update the name + Item.Name = name; + + // update visibility + Data.IsVisible = false; + foreach (var meshComponent in MeshComponents) { + switch (meshComponent) { + case RampFloorMeshAuthoring meshAuthoring: + Data.IsVisible = Data.IsVisible || meshAuthoring.gameObject.activeInHierarchy; + break; + case RampWallMeshAuthoring meshAuthoring: + Data.IsVisible = Data.IsVisible || meshAuthoring.gameObject.activeInHierarchy; + break; + case RampWireMeshAuthoring meshAuthoring: + Data.IsVisible = meshAuthoring.gameObject.activeInHierarchy; + break; + } + } + + // update collision + Data.IsCollidable = false; + foreach (var colliderComponent in ColliderComponents) { + if (colliderComponent is RampColliderAuthoring colliderAuthoring) { + Data.IsCollidable = colliderAuthoring.gameObject.activeInHierarchy; + } + } } private void OnDestroy() diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs index 10d130673..36716bf2c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs @@ -62,19 +62,27 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterRubber(Item, entity, gameObject); } - public void RemoveMeshComponent() + public override void Restore() { - var rc = gameObject.GetComponent(); - if (rc != null) { - DestroyImmediate(rc); + // update the name + Item.Name = name; + + // update visibility + Data.IsVisible = false; + foreach (var meshComponent in MeshComponents) { + switch (meshComponent) { + case RubberMeshAuthoring meshAuthoring: + Data.IsVisible = meshAuthoring.gameObject.activeInHierarchy; + break; + } } - } - public void RemoveHittableComponent() - { - var hc = gameObject.GetComponent(); - if (hc != null) { - DestroyImmediate(hc); + // update collision + Data.IsCollidable = false; + foreach (var colliderComponent in ColliderComponents) { + if (colliderComponent is RubberColliderAuthoring colliderAuthoring) { + Data.IsCollidable = colliderAuthoring.gameObject.activeInHierarchy; + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs index fb63d6f04..ca209384d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerAuthoring.cs @@ -47,7 +47,6 @@ public class SpinnerAuthoring : ItemMainAuthoring, .Concat(SpinnerPlateMeshAuthoring.ValidParentTypes) .Distinct(); - public IHittable Hittable => Item; public ISwitchable Switchable => Item; public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) @@ -66,15 +65,36 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterSpinner(Item, entity, gameObject); } - private void OnDestroy() + public override void Restore() { - if (!Application.isPlaying) { - Table?.Remove(Name); + // update the name + Item.Name = name; + + // update visibility + Data.IsVisible = false; + Data.ShowBracket = false; + foreach (var meshComponent in MeshComponents) { + switch (meshComponent) { + case SpinnerBracketMeshAuthoring bracketMeshAuthoring: + var bracketMeshAuthoringEnabled = bracketMeshAuthoring.gameObject.activeInHierarchy; + Data.IsVisible = Data.IsVisible || bracketMeshAuthoringEnabled; + Data.ShowBracket = bracketMeshAuthoringEnabled; + break; + + case SpinnerPlateMeshAuthoring plateMeshAuthoring: + Data.IsVisible = plateMeshAuthoring.gameObject.activeInHierarchy; + break; + } } + + // collision: spinners are always collidable } - public void RemoveHittableComponent() + private void OnDestroy() { + if (!Application.isPlaying) { + Table?.Remove(Name); + } } public override ItemDataTransformType EditorPositionType => ItemDataTransformType.ThreeD; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs index 39c1558af..d759ded08 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs @@ -46,13 +46,6 @@ public class SurfaceAuthoring : ItemMainAuthoring, .Concat(SurfaceTopMeshAuthoring.ValidParentTypes) .Distinct(); - private void OnDestroy() - { - if (!Application.isPlaying) { - Table?.Remove(Name); - } - } - public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { Convert(entity, dstManager); @@ -63,11 +56,38 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterSurface(Item, entity, gameObject); } - public void RemoveHittableComponent() + public override void Restore() { - var hc = gameObject.GetComponent(); - if (hc != null) { - DestroyImmediate(hc); + // update the name + Item.Name = name; + + // update visibility + Data.IsSideVisible = false; + Data.IsTopBottomVisible = false; + foreach (var meshComponent in MeshComponents) { + switch (meshComponent) { + case SurfaceSideMeshAuthoring meshAuthoring: + Data.IsSideVisible = meshAuthoring.gameObject.activeInHierarchy; + break; + case SurfaceTopMeshAuthoring meshAuthoring: + Data.IsTopBottomVisible = meshAuthoring.gameObject.activeInHierarchy; + break; + } + } + + // update collision + Data.IsCollidable = false; + foreach (var colliderComponent in ColliderComponents) { + if (colliderComponent is SurfaceColliderAuthoring colliderAuthoring) { + Data.IsCollidable = colliderAuthoring.gameObject.activeInHierarchy; + } + } + } + + private void OnDestroy() + { + if (!Application.isPlaying) { + Table?.Remove(Name); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs index adeda2ee0..da36d2657 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Table/TableAuthoring.cs @@ -148,6 +148,12 @@ private bool CheckDirty(string name, Func action = null) where T : IIte return false; } + public override void Restore() + { + // update the name + Item.Name = name; + } + public Texture2D GetTexture(string name) { var lowerName = name.ToLower(); @@ -250,9 +256,13 @@ public Table RecreateTable(TableData tableData) return table; } - private void Restore(Table table) where TData : ItemData where TItem : Item, IRenderable where TComp : ItemAuthoring + private void Restore(Table table) where TData : ItemData + where TItem : Item, IRenderable + where TComp : ItemMainAuthoring { - foreach (var component in GetComponentsInChildren(true)) { + foreach (var component in GetComponentsInChildren(true)) + { + component.Restore(); table.Add(component.Item); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs index a8001c9cc..546d81773 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerAuthoring.cs @@ -47,13 +47,6 @@ public class TriggerAuthoring : ItemMainAuthoring, public ISwitchable Switchable => Item; - private void OnDestroy() - { - if (!Application.isPlaying) { - Table?.Remove(Name); - } - } - public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { Convert(entity, dstManager); @@ -73,8 +66,30 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio transform.GetComponentInParent().RegisterTrigger(trigger, entity, gameObject); } - public void RemoveHittableComponent() + public override void Restore() { + // update the name + Item.Name = name; + + // update visibility + Data.IsVisible = false; + foreach (var meshComponent in MeshComponents) { + switch (meshComponent) { + case TriggerMeshAuthoring meshAuthoring: + Data.IsVisible = meshAuthoring.gameObject.activeInHierarchy; + break; + } + } + + // triggers are always collidable + // todo handle IsEnabled + } + + private void OnDestroy() + { + if (!Application.isPlaying) { + Table?.Remove(Name); + } } public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD; From 9f4ff8648d2b148aa7ad104284bbb62421b869d8 Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 26 Oct 2020 01:10:38 +0100 Subject: [PATCH 107/124] doc: Update components doc. --- .../Documentation~/creators-guide/editor/unity-components.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md b/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md index 433040551..3da6366ba 100644 --- a/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md +++ b/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md @@ -78,3 +78,7 @@ Another example: If in Visual Pinball, you name a rubber `LeftSlingshot` and two > [!warning] > When you *export* to `.vpx` and you have parented items but didn't follow the naming convention, the parenting will get lost when re-importing the table into VPE. In the future, VPE might propose to rename the parented children or just do it on export, but that's still on our TODO list. + +## Visibility + +In order to determine whether a game item is visible, VPE looks at the hierarchy and the mesh components of its game object. If a game item has no mesh component, its visibility is automatically set to *invisible*. It's also invisible if the game object is set to inactive (the top left checkbox in the inspector). From 88f387e141cdd95231f76e705ff8df665ae64c39 Mon Sep 17 00:00:00 2001 From: Eli Curtz Date: Mon, 26 Oct 2020 12:37:43 -0700 Subject: [PATCH 108/124] Copyedit pass on Unity Components document --- .../creators-guide/editor/unity-components.md | 49 +++++++++---------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md b/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md index 3da6366ba..fdb1b72b8 100644 --- a/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md +++ b/VisualPinball.Unity/Documentation~/creators-guide/editor/unity-components.md @@ -1,50 +1,47 @@ # Unity Components -When loading or creating a table in Unity, what you're creating is a hierarchy of [GameObjects](https://docs.unity3d.com/Manual/GameObjects.html). By default we group game items by their type, but you can arrange them however you want. +When loading or creating a table in Unity, what you're creating is a hierarchy of [GameObjects](https://docs.unity3d.com/Manual/GameObjects.html), the basic building blocks of Unity scenes. By default we group game items by their type when importing, but you can arrange them however you want. -In order to give the GameObjects behavior during gameplay, we add [components](https://docs.unity3d.com/Manual/Components.html) onto them. VPE comes with large amount of components that are used to set up the game mechanisms of the table. +To give the GameObjects behavior during gameplay, we add [components](https://docs.unity3d.com/Manual/Components.html) onto them. VPE comes with large number of components that are used to set up and control the game mechanisms of the table, and advanced programmers can contibute new ones. > [!note] -> During runtime, VPE converts the GameObjects and components into Unity's [DOTS](https://unity.com/dots) entities. So we use components in the editor to define the game logic implemented in DOTS. That's also why we call them *Authoring Components*. +> During runtime, VPE converts the GameObjects and components into entities in Unity's [DOTS workflow](https://unity.com/dots). There are special components used to control this conversion which we call *Authoring Components*. -If you've never heard about GameObjects or components, we recommmend you read through the links in the first two paragraphs. They are short, to the point, and better than what we could provide here. +If you've never heard about GameObjects or components, we recommmend you read through the links in the first two paragraphs. They are short, to the point, and a much better introduction than we could provide here. ## Components vs Game Items -In *Visual Pinball*, components would be what you see in the options panel when you click on a game item. You'll typically find sections for physics behavior, visuals, and form and shape of the game item you're editing. Internally, those sections belong to the same game item. +In *Visual Pinball*, components are what you see in the options panel when you click on a game item. You'll typically find sections for adjusting physical behavior, visual display, and geometric shape of the game item you're editing. Internally, all of these sections belong to the same game item. -In *VPE*, we have separate components for separate things. There are four different types of components: +In *VPE*, we have separate components for each of these sections. There are four different types of components: 1. The **Main Component** represents the actual game item. -2. The **Collider Component** adds physical behavior to the game item. It defines how the ball collides with it, i.e. how the bounciness, friction and randomness is applied to the ball. -3. **Mesh Components** generate meshes, i.e. the geometry used to render the object on the playfield. The result are procedurally generated visuals. -4. **Animation components** apply movement to the game item. If the entire object is moved (for example a flipper), this is taken care of by the collision component, but items where only parts move (e.g. the plate of a gate, or the ring of a bumper), these components apply the movement to the GameObject. +2. A **Collider Component** adds physical behavior to the game item. It defines how the item interacts with other objects, for example what bounciness, friction and randomness is applied to a pinball hitting the item. +3. **Mesh Components** generate meshes, i.e. the geometry used to render the object on the playfield. The results are the procedurally generated 3d objects rendered in the scene. +4. **Animation components** apply movement to the game item. If the entire object is moving (for example a flipper), that is handled by the collision component, but for items where only parts move (e.g. the plate of a gate, or the ring of a bumper) these components apply the movement to the GameObject. Let's look at a flipper: ![VPE vs VP](properties-vpe-vs-vp.png) -Here, we see the main component (*Flipper*), the collider component (*Flipper Collider*), and two mesh components (*Flipper Base Mesh* and *Flipper Rubber Mesh*). While the main- and collider component sit on the same GameObject, the mesh components have each their own child. This is how Unity works - a GameObject has at most one mesh component. +Here, we see the main component (*Flipper*), the collider component (*Flipper Collider*), and two mesh components (*Flipper Base Mesh* and *Flipper Rubber Mesh*) inside VPE compared to Visual Pinball. While the main and collider component sit on the base GameObject, each mesh component is on its own child GameObject. This is how Unity works - a GameObject only contains one component of each type. > [!note] -> Internally, VPE still keeps a single set of data. That's why you see the collapsed *Base Mesh*, *Rubber Mesh* and *Physics* sections in the main component. When you change values there, the corresponding values in the other components will update at the same time. +> Internally, VPE still keeps a single set of data. That's why you see the collapsed *Base Mesh*, *Rubber Mesh* and *Physics* sections in the main component. When you change values there, the corresponding values in the other components will update at the same time. In general, you don't have to manually manage all this. When creating game items via the toolbox, the new GameObject will already have all the necessary components, as will the items created when importing a `.vpx` file. -This separation of logic comes with a few advantages. First, it's more obvious how a game item behaves. No collider component? That means the game item is not collidable. No mesh component? It's (permanently) invisible. But there are other advantages, as you will see in the next section. - -> [!note] -> In general, you don't have to manually manage all this. When creating game items via the toolbox, the created GameObject will already have all the necessary components (as will importing a `.vpx` file). +This separation of logic has a few advantages. First, it's more obvious how a game item behaves. No collider component? That means the game item is not collidable. No mesh component? It's (permanently) invisible. But there are other advantages, as you will see in the next section. ## Combining Components -VPE allows to mix and match components of different game items. For example, for a given game item, you can assign a collider or mesh from another type. The most common use case is replacing built-in meshes with primitives. For this, you would remove the original mesh component and replace it with a primitive mesh component. But there are other usages, like using a primitive collider on a rubber. You can also have *multiple* children with colliders (or meshes) for a game item. +VPE allows you to mix and match components onto game items. For example, for a given game item, you could assign a collider or mesh from another type. The most common use case is replacing built-in meshes with primitives, removing the original mesh component and replacing it with a generated version. But there are other usages, like using a primitive collider on a rubber. You can also add *multiple* children with colliders (or meshes) for a game item. -We call this **parenting**. The game item that overrides a given behavior is still created, but *parented* to another game item. +We call this **parenting**. The game item that overrides a given behavior is still created, but serves as a *parent* container to other game items. -The advantage compared to Visual Pinball where you would create individual game items is that VPE treats them as one single logical entity. For example, VPE will automatically rotate a primitive flipper item when it's parented under a flipper. Or events from multiple colliders will be emitted on the same parent object. +The advantage compared to Visual Pinball, where you would create individual game items, is that VPE treats them as one single logical entity. For example, VPE will automatically rotate a primitive flipper item when it's parented under a flipper, and events from multiple colliders will be emitted from the same parent object. ### Supported Combinations -Not every game item can be parented any other game items. For example it doesn't make much sense to use a flipper collider for a bumper. In fact, most of the combinations are unsupported. Here's what VPE does support so far: +Not every game item can be parented to any other game item. It doesn't make much sense to use a flipper collider for a bumper. In fact, most of the combinations are unsupported. Here's what VPE does support so far: | | Supported Meshes | Supported Colliders | Supported Animators | |------------------|---------------------------------------------------------------|----------------------------|---------------------------| @@ -53,7 +50,7 @@ Not every game item can be parented any other game items. For example it doesn't | **Gate** | Gate Bracket, Gate Wire, Primitive | Gate | Gate Wire | | **Hit Target** | Hit Target, Primitive | Hit Target | Hit Target, Drop Target | | **Kicker** | Kicker, Primitive | Kicker | | -| **Light** (bulb) | Light, Primitive | | | +| **Light** | Light, Primitive | | | | **Plunger** | Flat Plunger, Plunger Rod, Plunger Spring | Plunger | Plunger | | **Primitive** | Primitive | Primitive, Ramp, Wall | | | **Ramp** | Ramp, Primitive | Ramp | | @@ -65,20 +62,20 @@ Not every game item can be parented any other game items. For example it doesn't ## Naming Conventions -In order to keep backward compatibility with Visual Pinball, VPE relies on naming conventions to parent a game item to another. +In order to maintain backward compatibility with Visual Pinball, VPE relies on naming conventions to parent one game item to another. -There are two suffixes (text you add *after* the game item's name) that have special meaning in VPE: +There are two suffixes that have special meaning for VPE: - `_Mesh` applies the game item's mesh to its parent - `_Collider` applies the game item's collider to its parent -For example, if in Visual Pinball, you name a primitive `LeftFlipper_Mesh`, VPE will look for a `LeftFlipper` game item and replace its mesh with the mesh of `LeftFlipper_Mesh`. In other words, it will *parent* `LeftFlipper_Mesh` to `LeftFlipper` and disable `LeftFlipper`'s mesh. +For example, if in Visual Pinball you name a primitive `LeftFlipper_Mesh`, VPE will look for a `LeftFlipper` game item and replace its mesh with the mesh of that primitive. In other words, it will *parent* `LeftFlipper_Mesh` to `LeftFlipper` and disable `LeftFlipper`'s original mesh. -Another example: If in Visual Pinball, you name a rubber `LeftSlingshot` and two primitives `LeftSlingshot_Collider_Soft` and `LeftSlingshot_Collider_Hard`, VPE will disable the collider of `LeftSlingshot` and use the colliders of both primitives. During gameplay when the ball hits either `LeftSlingshot_Collider_Soft` or `LeftSlingshot_Collider_Hard`, the `Hit` event will be emitted on `LeftSlingshot`. +Another example: If in Visual Pinball you name a rubber `LeftSlingshot` and two primitives `LeftSlingshot_Collider_Soft` and `LeftSlingshot_Collider_Hard`, VPE will disable the collider of `LeftSlingshot` and use both the other colliders instead. During gameplay when the ball hits either `LeftSlingshot_Collider_Soft` or `LeftSlingshot_Collider_Hard`, the `Hit` event will be emitted on `LeftSlingshot`. > [!warning] -> When you *export* to `.vpx` and you have parented items but didn't follow the naming convention, the parenting will get lost when re-importing the table into VPE. In the future, VPE might propose to rename the parented children or just do it on export, but that's still on our TODO list. +> When you *export* to `.vpx` and you have parented items that don't follow the naming convention, the parenting will get lost when re-importing the table into VPE. In the future, VPE may offer to (or even automatically) rename the parented children on export, but that's still on our TODO list. ## Visibility -In order to determine whether a game item is visible, VPE looks at the hierarchy and the mesh components of its game object. If a game item has no mesh component, its visibility is automatically set to *invisible*. It's also invisible if the game object is set to inactive (the top left checkbox in the inspector). +In order to determine whether a game item is visible, VPE looks at the hierarchy and the mesh components of its GameObject. If a game item has no mesh component, its automatically set to *invisible*. It's also invisible if the GameObject is set to inactive (the checkbox at the top left in the Inspector). From 749d6183b2fd512c2c84f9908636c31f80fb7828 Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 26 Oct 2020 22:25:02 +0100 Subject: [PATCH 109/124] fix: Set mesh invisible, if it's... invisible. --- VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs index e351806ec..4501768a2 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMeshAuthoring.cs @@ -101,6 +101,7 @@ private void CreateMesh() return; } var mesh = ro.Mesh.ToUnityMesh($"{gameObject.name}_Mesh"); + enabled = ro.IsVisible; // apply mesh to game object var mf = gameObject.AddComponent(); From e85f4c8d88b26aa8675840fabf990da2d14fbda2 Mon Sep 17 00:00:00 2001 From: freezy Date: Mon, 26 Oct 2020 23:19:45 +0100 Subject: [PATCH 110/124] fix: Only add active colliders. --- .../Physics/Collision/QuadTreeCreationSystem.cs | 4 +++- .../VPT/Bumper/BumperExtensions.cs | 11 +++++++++-- .../VisualPinball.Unity/VPT/Gate/GateExtensions.cs | 12 ++++++++++-- .../VPT/HitTarget/HitTargetExtensions.cs | 11 +++++++++-- .../VPT/Primitive/PrimitiveExtensions.cs | 5 ++--- .../VisualPinball.Unity/VPT/Ramp/RampExtensions.cs | 11 +++++++++-- .../VPT/Rubber/RubberExtensions.cs | 10 ++++++---- .../VPT/Surface/SurfaceExtensions.cs | 11 +++++++++-- 8 files changed, 57 insertions(+), 18 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/QuadTreeCreationSystem.cs b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/QuadTreeCreationSystem.cs index 9d28bf49a..04b318fdf 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/QuadTreeCreationSystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/QuadTreeCreationSystem.cs @@ -41,9 +41,11 @@ public static void Create(EntityManager entityManager) var hitObjects = new List(); var id = 0; var log = ""; + var c = 0; foreach (var item in hittables) { var hitShapes = item.GetHitShapes(); log += item.Name + ": " + hitShapes.Length + "\n"; + c += hitShapes.Length; foreach (var hitObject in hitShapes) { hitObject.SetIndex(item.Index, item.Version, item.ParentIndex, item.ParentVersion); hitObject.Id = id++; @@ -51,7 +53,7 @@ public static void Create(EntityManager entityManager) hitObjects.Add(hitObject); } } - Logger.Info("Collider Count:\n" + log); + Logger.Info("Collider Count:\n" + log + "\nTotal: " + c); // construct quad tree var quadTree = new Engine.Physics.QuadTree(hitObjects, table.BoundingBox); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs index 8de10d7fa..84843e240 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs @@ -30,7 +30,7 @@ public static IItemMainAuthoring SetupGameObject(this Bumper bumper, GameObject switch (bumper.SubComponent) { case ItemSubComponent.None: - obj.AddComponent(); + obj.AddColliderComponent(bumper); CreateBaseMeshComponent(bumper, obj); CreateCapMeshComponent(bumper, obj); @@ -43,7 +43,7 @@ public static IItemMainAuthoring SetupGameObject(this Bumper bumper, GameObject break; case ItemSubComponent.Collider: { - obj.AddComponent(); + obj.AddColliderComponent(bumper); if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { parentMainAuthoring.DestroyColliderComponent(); } @@ -68,6 +68,13 @@ public static IItemMainAuthoring SetupGameObject(this Bumper bumper, GameObject return mainAuthoring; } + private static void AddColliderComponent(this GameObject obj, Bumper bumper) + { + if (bumper.Data.IsCollidable) { + obj.AddComponent(); + } + } + private static void CreateBaseMeshComponent(Bumper rubber, GameObject obj) { var meshComp = CreateChild(obj, BumperMeshGenerator.Base); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs index dd43d90ad..960cfba62 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs @@ -17,6 +17,7 @@ using System; using Unity.Entities; using UnityEngine; +using VisualPinball.Engine.Resources.Meshes; using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Gate; @@ -30,14 +31,14 @@ public static IItemMainAuthoring SetupGameObject(this Gate gate, GameObject obj, switch (gate.SubComponent) { case ItemSubComponent.None: - obj.AddComponent(); + obj.AddColliderComponent(gate); CreateChild(obj, GateMeshGenerator.Bracket); var wire = CreateChild(obj, GateMeshGenerator.Wire); wire.AddComponent(); break; case ItemSubComponent.Collider: { - obj.AddComponent(); + obj.AddColliderComponent(gate); if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { parentMainAuthoring.DestroyColliderComponent(); } @@ -59,6 +60,13 @@ public static IItemMainAuthoring SetupGameObject(this Gate gate, GameObject obj, return mainAuthoring; } + private static void AddColliderComponent(this GameObject obj, Gate gate) + { + if (gate.Data.IsCollidable) { + obj.AddComponent(); + } + } + private static GameObject CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring { var subObj = new GameObject(name); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs index bfbe5630e..43be891a9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs @@ -30,12 +30,12 @@ public static IItemMainAuthoring SetupGameObject(this HitTarget hitTarget, GameO switch (hitTarget.SubComponent) { case ItemSubComponent.None: - obj.AddComponent(); + obj.AddColliderComponent(hitTarget); obj.AddComponent(); break; case ItemSubComponent.Collider: { - obj.AddComponent(); + obj.AddColliderComponent(hitTarget); if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { parentMainAuthoring.DestroyColliderComponent(); } @@ -56,5 +56,12 @@ public static IItemMainAuthoring SetupGameObject(this HitTarget hitTarget, GameO obj.AddComponent(); return mainAuthoring; } + + private static void AddColliderComponent(this GameObject obj, HitTarget hitTarget) + { + if (hitTarget.Data.IsCollidable) { + obj.AddComponent(); + } + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs index 587082058..0fd3aa8c2 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs @@ -65,9 +65,8 @@ private static void AddMeshComponent(this GameObject obj, Primitive primitive) private static void AddColliderComponent(this GameObject obj, Primitive primitive) { - if (!primitive.Data.IsToy) { - var comp = obj.AddComponent(); - comp.enabled = primitive.IsCollidable; + if (!primitive.Data.IsToy && primitive.IsCollidable) { // todo handle dynamic collision + obj.AddComponent(); } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs index d52bbaeb6..18ce13217 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs @@ -31,11 +31,11 @@ public static IItemMainAuthoring SetupGameObject(this Ramp ramp, GameObject obj, switch (ramp.SubComponent) { case ItemSubComponent.None: CreateMeshComponents(ramp, obj); - obj.AddComponent(); + obj.AddColliderComponent(ramp); break; case ItemSubComponent.Collider: { - obj.AddComponent(); + obj.AddColliderComponent(ramp); if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { parentMainAuthoring.DestroyColliderComponent(); } @@ -58,6 +58,13 @@ public static IItemMainAuthoring SetupGameObject(this Ramp ramp, GameObject obj, return mainAuthoring; } + private static void AddColliderComponent(this GameObject obj, Ramp ramp) + { + if (ramp.Data.IsCollidable) { + obj.AddComponent(); + } + } + private static void CreateMeshComponents(Ramp ramp, GameObject obj) { if (ramp.IsHabitrail) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs index 6db4565c2..64ce55b82 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs @@ -30,13 +30,13 @@ public static IItemMainAuthoring SetupGameObject(this Rubber rubber, GameObject switch (rubber.SubComponent) { case ItemSubComponent.None: { - AddColliderComponent(rubber, obj); + obj.AddColliderComponent(rubber); AddMeshComponent(rubber, obj); break; } case ItemSubComponent.Collider: { - AddColliderComponent(rubber, obj); + obj.AddColliderComponent(rubber); if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { parentMainAuthoring.DestroyColliderComponent(); } @@ -65,9 +65,11 @@ private static void AddMeshComponent(Rubber rubber, GameObject obj) meshComponent.enabled = rubber.Data.IsVisible; } - private static void AddColliderComponent(Rubber rubber, GameObject obj) + private static void AddColliderComponent(this GameObject obj, Rubber rubber) { - obj.AddComponent(); + if (rubber.Data.IsCollidable) { + obj.AddComponent(); + } } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs index 3caba0fe7..c4e8f5d2b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs @@ -30,13 +30,13 @@ public static IItemMainAuthoring SetupGameObject(this Surface surface, GameObjec switch (surface.SubComponent) { case ItemSubComponent.None: - obj.AddComponent(); + obj.AddColliderComponent(surface); CreateChild(obj, SurfaceMeshGenerator.Side); CreateChild(obj, SurfaceMeshGenerator.Top); break; case ItemSubComponent.Collider: { - obj.AddComponent(); + obj.AddColliderComponent(surface); if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { parentMainAuthoring.DestroyColliderComponent(); } @@ -59,6 +59,13 @@ public static IItemMainAuthoring SetupGameObject(this Surface surface, GameObjec return mainAuthoring; } + private static void AddColliderComponent(this GameObject obj, Surface surface) + { + if (surface.Data.IsCollidable) { + obj.AddComponent(); + } + } + private static GameObject CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring { var subObj = new GameObject(name); From b2fb8bae132cfac39c22f8cfbbba0e43c3028691 Mon Sep 17 00:00:00 2001 From: freezy Date: Tue, 27 Oct 2020 00:03:38 +0100 Subject: [PATCH 111/124] physics: Measure and print kd-tree creation. --- .../Physics/Collision/QuadTreeCreationSystem.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/QuadTreeCreationSystem.cs b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/QuadTreeCreationSystem.cs index 04b318fdf..510ca5cf0 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/QuadTreeCreationSystem.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Physics/Collision/QuadTreeCreationSystem.cs @@ -15,6 +15,7 @@ // along with this program. If not, see . using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using NLog; using Unity.Entities; @@ -31,7 +32,9 @@ internal static class QuadTreeCreationSystem public static void Create(EntityManager entityManager) { var table = Object.FindObjectOfType().Table; + var stopWatch = new Stopwatch(); + stopWatch.Start(); foreach (var playable in table.Playables) { playable.Init(table); } @@ -42,6 +45,7 @@ public static void Create(EntityManager entityManager) var id = 0; var log = ""; var c = 0; + foreach (var item in hittables) { var hitShapes = item.GetHitShapes(); log += item.Name + ": " + hitShapes.Length + "\n"; @@ -53,7 +57,8 @@ public static void Create(EntityManager entityManager) hitObjects.Add(hitObject); } } - Logger.Info("Collider Count:\n" + log + "\nTotal: " + c); + stopWatch.Stop(); + Logger.Info("Collider Count:\n" + log + "\nTotal: " + c + " colliders in " + stopWatch.ElapsedMilliseconds + "ms"); // construct quad tree var quadTree = new Engine.Physics.QuadTree(hitObjects, table.BoundingBox); From fc404aaf743c93091dd80037871faec663827919 Mon Sep 17 00:00:00 2001 From: freezy Date: Tue, 27 Oct 2020 00:28:05 +0100 Subject: [PATCH 112/124] components: Fix patcher. --- .../Toolbox/ToolboxEditor.cs | 2 +- .../Patcher/Tables/WipeOut.cs | 38 +++++++++++ .../Patcher/Tables/WipeOut.cs.meta | 11 ++++ .../Import/VpxConverter.cs | 54 +++++++++------- .../VPT/Bumper/BumperExtensions.cs | 64 ++++++------------- .../VPT/Flipper/FlipperExtensions.cs | 22 ++----- .../VPT/Gate/GateExtensions.cs | 39 ++++++----- .../VPT/HitTarget/HitTargetExtensions.cs | 23 +++---- .../VPT/IItemMeshAuthoring.cs | 3 + .../VPT/Kicker/KickerExtensions.cs | 23 +++---- .../VPT/Light/LightExtensions.cs | 21 +++--- .../VPT/Playfield/PlayfieldExtensions.cs | 5 +- .../VPT/Plunger/PlungerExtensions.cs | 64 +++++++++---------- .../Primitive/PrimitiveColliderAuthoring.cs | 5 +- .../VPT/Primitive/PrimitiveExtensions.cs | 20 +++--- .../VPT/Primitive/PrimitiveMeshAuthoring.cs | 10 +++ .../VPT/Ramp/RampColliderAuthoring.cs | 4 +- .../VPT/Ramp/RampExtensions.cs | 39 ++++++----- .../VPT/Rubber/RubberExtensions.cs | 16 ++--- .../VPT/Spinner/SpinnerExtensions.cs | 34 +++++----- .../VPT/Surface/SurfaceColliderAuthoring.cs | 5 +- .../VPT/Surface/SurfaceExtensions.cs | 20 +++--- .../VPT/Trigger/TriggerExtensions.cs | 22 +++---- 23 files changed, 295 insertions(+), 249 deletions(-) create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Tables/WipeOut.cs create mode 100644 VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Tables/WipeOut.cs.meta diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs index c2723853e..893f517e7 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs @@ -185,7 +185,7 @@ private void CreateItem(Func create, string actionName) whe private GameObject CreateRenderable(IRenderable renderable) { //var rog = renderable.GetRenderObjects(_table.Table, Origin.Original, false); - var (obj, _) = VpxConverter.CreateGameObjects(_tableAuthoring.Table, renderable, GetOrCreateParent(_tableAuthoring, renderable)); + var (obj, _, _) = VpxConverter.CreateGameObjects(_tableAuthoring.Table, renderable, GetOrCreateParent(_tableAuthoring, renderable)); return obj; } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Tables/WipeOut.cs b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Tables/WipeOut.cs new file mode 100644 index 000000000..75fd0c79c --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Tables/WipeOut.cs @@ -0,0 +1,38 @@ +// 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 . + +// ReSharper disable StringLiteralTypo + +using UnityEngine; +using VisualPinball.Engine.VPT.Primitive; + +namespace VisualPinball.Unity.Patcher +{ + [MetaMatch(TableName = "Wipe Out Premier 1993", AuthorName = "Edizzle & Kiwi")] + public class WipeOut + { + [NameMatch("Prim_RightFlipper", Ref="Flippers/RightFlipper")] + [NameMatch("Prim_LeftFlipper", Ref="Flippers/LeftFlipper")] + public void ReparentFlippers(Primitive flipper, GameObject gameObject, ref GameObject parent) + { + PatcherUtil.Reparent(gameObject, parent); + gameObject.transform.localPosition = new Vector3(0, 0, 0); + gameObject.transform.localRotation = Quaternion.identity; + flipper.Data.Position.X = 0; + flipper.Data.Position.Y = 0; + } + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Tables/WipeOut.cs.meta b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Tables/WipeOut.cs.meta new file mode 100644 index 000000000..c3ff3e83a --- /dev/null +++ b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Tables/WipeOut.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 940ba5c21acb5234993a0616942a8353 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index 735eaeefc..1c2990a2f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -114,6 +114,7 @@ private void ConvertGameItems(GameObject tableGameObject) { var createdMainObjs = new Dictionary(); var createdMainMbs = new Dictionary(); + var createdMeshMbs = new Dictionary>(); var renderableLookup = new Dictionary(); var renderables = from renderable in _table.Renderables orderby renderable.SubComponent @@ -135,10 +136,11 @@ orderby renderable.SubComponent if (renderable.SubComponent == ItemSubComponent.None) { // create object(s) - var (rootObj, rootMb) = CreateGameObjects(_table, renderable, _parents[renderable.ItemGroupName]); + var (rootObj, rootMb, meshMbs) = CreateGameObjects(_table, renderable, _parents[renderable.ItemGroupName]); createdMainObjs[lookupName] = rootObj; createdMainMbs[lookupName] = rootMb; + createdMeshMbs[lookupName] = meshMbs; } else { // if the object's names was parsed to be part of another object, re-link to other object. @@ -153,7 +155,10 @@ orderby renderable.SubComponent renderable.RotationY -= parentRenderable.RotationY; } - var (rootObj, _) = CreateGameObjects(_table, renderable, _parents[renderable.ItemGroupName], mainMb); + var (rootObj, rootMb, meshMbs) = CreateGameObjects(_table, renderable, _parents[renderable.ItemGroupName], mainMb); + + createdMeshMbs[lookupName] = meshMbs; + rootObj.transform.SetParent(mainObj.transform, false); } else { @@ -163,45 +168,46 @@ orderby renderable.SubComponent } // now we have all renderables imported, patch them. - foreach (var lookupName in createdMainObjs.Keys) { - _tableAuthoring.Patcher.ApplyPatches(renderableLookup[lookupName], createdMainObjs[lookupName], tableGameObject); + foreach (var lookupName in createdMeshMbs.Keys) { + foreach (var meshMb in createdMeshMbs[lookupName]) { + _tableAuthoring.Patcher.ApplyPatches(renderableLookup[lookupName], meshMb.gameObject, tableGameObject); + } } } - public static (GameObject, IItemMainAuthoring) CreateGameObjects(Table table, IRenderable renderable, GameObject parent, IItemMainAuthoring parentAuthoring = null) + public static (GameObject, IItemMainAuthoring, IEnumerable) CreateGameObjects(Table table, IRenderable renderable, GameObject parent, IItemMainAuthoring parentAuthoring = null) { var obj = new GameObject(renderable.Name); obj.transform.parent = parent.transform; - var mb = SetupGameObjects(renderable, obj, parentAuthoring); + var (mainAuthoring, meshAuthoring) = SetupGameObjects(renderable, obj, parentAuthoring); // apply transformation obj.transform.SetFromMatrix(renderable.TransformationMatrix(table, Origin.Original).ToUnityMatrix()); - return (obj, mb); + return (obj, mainAuthoring, meshAuthoring); } - private static IItemMainAuthoring SetupGameObjects(IRenderable item, GameObject obj, IItemMainAuthoring parentAuthoring = null) + private static (IItemMainAuthoring, IEnumerable) SetupGameObjects(IRenderable item, GameObject obj, IItemMainAuthoring parentAuthoring = null) { - IItemMainAuthoring mainAuthoring = null; switch (item) { - case Bumper bumper: mainAuthoring = bumper.SetupGameObject(obj, parentAuthoring); break; - case Flipper flipper: mainAuthoring = flipper.SetupGameObject(obj, parentAuthoring); break; - case Gate gate: mainAuthoring = gate.SetupGameObject(obj, parentAuthoring); break; - case HitTarget hitTarget: mainAuthoring = hitTarget.SetupGameObject(obj, parentAuthoring); break; - case Kicker kicker: mainAuthoring = kicker.SetupGameObject(obj, parentAuthoring); break; - case Engine.VPT.Light.Light lt: mainAuthoring = lt.SetupGameObject(obj, parentAuthoring); break; - case Plunger plunger: mainAuthoring = plunger.SetupGameObject(obj, parentAuthoring); break; - case Primitive primitive: mainAuthoring = primitive.SetupGameObject(obj, parentAuthoring); break; - case Ramp ramp: mainAuthoring = ramp.SetupGameObject(obj, parentAuthoring); break; - case Rubber rubber: mainAuthoring = rubber.SetupGameObject(obj, parentAuthoring); break; - case Spinner spinner: mainAuthoring = spinner.SetupGameObject(obj, parentAuthoring); break; - case Surface surface: mainAuthoring = surface.SetupGameObject(obj, parentAuthoring); break; - case Table table: table.SetupGameObject(obj, parentAuthoring); break; - case Trigger trigger: mainAuthoring = trigger.SetupGameObject(obj, parentAuthoring); break; + case Bumper bumper: return bumper.SetupGameObject(obj, parentAuthoring); + case Flipper flipper: return flipper.SetupGameObject(obj, parentAuthoring); + case Gate gate: return gate.SetupGameObject(obj, parentAuthoring); + case HitTarget hitTarget: return hitTarget.SetupGameObject(obj, parentAuthoring); + case Kicker kicker: return kicker.SetupGameObject(obj, parentAuthoring); + case Engine.VPT.Light.Light lt: return lt.SetupGameObject(obj, parentAuthoring); + case Plunger plunger: return plunger.SetupGameObject(obj, parentAuthoring); + case Primitive primitive: return primitive.SetupGameObject(obj, parentAuthoring); + case Ramp ramp: return ramp.SetupGameObject(obj, parentAuthoring); + case Rubber rubber: return rubber.SetupGameObject(obj, parentAuthoring); + case Spinner spinner: return spinner.SetupGameObject(obj, parentAuthoring); + case Surface surface: return surface.SetupGameObject(obj, parentAuthoring); + case Table table: return table.SetupGameObject(obj, parentAuthoring); + case Trigger trigger: return trigger.SetupGameObject(obj, parentAuthoring); } - return mainAuthoring; + throw new InvalidOperationException("Unknown item " + item + " to setup!"); } private void MakeSerializable(GameObject go, Table table) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs index 84843e240..b86bfec52 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs @@ -15,49 +15,48 @@ // along with this program. If not, see . using System; +using System.Collections.Generic; +using NLog; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Bumper; +using Logger = NLog.Logger; namespace VisualPinball.Unity { internal static class BumperExtensions { - public static IItemMainAuthoring SetupGameObject(this Bumper bumper, GameObject obj, IItemMainAuthoring parentAuthoring) + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Bumper bumper, GameObject obj, IItemMainAuthoring parentAuthoring) { + var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(bumper); switch (bumper.SubComponent) { case ItemSubComponent.None: obj.AddColliderComponent(bumper); + meshAuthoring.Add(CreateChild(obj, BumperMeshGenerator.Base)); + meshAuthoring.Add(CreateChild(obj, BumperMeshGenerator.Cap)); - CreateBaseMeshComponent(bumper, obj); - CreateCapMeshComponent(bumper, obj); + var ring = CreateChild(obj, BumperMeshGenerator.Ring); + var skirt = CreateChild(obj, BumperMeshGenerator.Skirt); - var ring = CreateRingMeshComponent(bumper, obj); - var skirt = CreateSkirtMeshComponent(bumper, obj); - ring.AddComponent(); - skirt.AddComponent(); + ring.gameObject.AddComponent(); + skirt.gameObject.AddComponent(); + meshAuthoring.Add(ring); + meshAuthoring.Add(skirt); break; case ItemSubComponent.Collider: { - obj.AddColliderComponent(bumper); - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyColliderComponent(); - } + Logger.Error("Bumper collider cannot be parented to anything else than bumpers."); break; } case ItemSubComponent.Mesh: { - CreateBaseMeshComponent(bumper, obj); - CreateCapMeshComponent(bumper, obj); - CreateRingMeshComponent(bumper, obj); - CreateSkirtMeshComponent(bumper, obj); - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyMeshComponent(); - } + Logger.Error("Bumper mesh cannot be parented to anything else than bumpers."); break; } @@ -65,7 +64,8 @@ public static IItemMainAuthoring SetupGameObject(this Bumper bumper, GameObject throw new ArgumentOutOfRangeException(); } obj.AddComponent(); - return mainAuthoring; + + return (mainAuthoring, meshAuthoring); } private static void AddColliderComponent(this GameObject obj, Bumper bumper) @@ -75,32 +75,6 @@ private static void AddColliderComponent(this GameObject obj, Bumper bumper) } } - private static void CreateBaseMeshComponent(Bumper rubber, GameObject obj) - { - var meshComp = CreateChild(obj, BumperMeshGenerator.Base); - meshComp.enabled = rubber.Data.IsBaseVisible; - } - - private static void CreateCapMeshComponent(Bumper rubber, GameObject obj) - { - var meshComp = CreateChild(obj, BumperMeshGenerator.Cap); - meshComp.enabled = rubber.Data.IsBaseVisible; - } - - private static GameObject CreateRingMeshComponent(Bumper rubber, GameObject obj) - { - var meshComp = CreateChild(obj, BumperMeshGenerator.Ring); - meshComp.enabled = rubber.Data.IsRingVisible; - return meshComp.gameObject; - } - - private static GameObject CreateSkirtMeshComponent(Bumper rubber, GameObject obj) - { - var meshComp = CreateChild(obj, BumperMeshGenerator.Skirt); - meshComp.enabled = rubber.Data.IsSocketVisible; - return meshComp.gameObject; - } - private static T CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring { var subObj = new GameObject(name); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs index acf8e073a..6c454c823 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs @@ -15,6 +15,7 @@ // along with this program. If not, see . using System; +using System.Collections.Generic; using NLog; using Unity.Entities; using UnityEngine; @@ -28,8 +29,9 @@ internal static class FlipperExtensions { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public static IItemMainAuthoring SetupGameObject(this Flipper flipper, GameObject obj, IItemMainAuthoring parentAuthoring) + public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Flipper flipper, GameObject obj, IItemMainAuthoring parentAuthoring) { + var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(flipper); switch (flipper.SubComponent) { @@ -38,8 +40,8 @@ public static IItemMainAuthoring SetupGameObject(this Flipper flipper, GameObjec // if invisible in main component, we skip creation entirely, because we think users won't dynamically toggle visibility. if (flipper.Data.IsVisible) { - CreateChild(obj, FlipperMeshGenerator.Base); - CreateChild(obj, FlipperMeshGenerator.Rubber); + meshAuthoring.Add(CreateChild(obj, FlipperMeshGenerator.Base)); + meshAuthoring.Add(CreateChild(obj, FlipperMeshGenerator.Rubber)); } break; @@ -49,17 +51,7 @@ public static IItemMainAuthoring SetupGameObject(this Flipper flipper, GameObjec } case ItemSubComponent.Mesh: { - var baseComp = CreateChild(obj, FlipperMeshGenerator.Base); - var rubberComp = CreateChild(obj, FlipperMeshGenerator.Rubber); - - // if invisible in sub component, the mesh is explicitly created, so just disable it if invisible. - baseComp.enabled = flipper.Data.IsVisible; - rubberComp.enabled = flipper.Data.IsVisible; - - CreateChild(obj, FlipperMeshGenerator.Rubber); - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyMeshComponent(); - } + Logger.Error("Cannot parent a flipper mesh to a different object than a flipper!"); break; } @@ -67,7 +59,7 @@ public static IItemMainAuthoring SetupGameObject(this Flipper flipper, GameObjec throw new ArgumentOutOfRangeException(); } obj.AddComponent(); - return mainAuthoring; + return (mainAuthoring, meshAuthoring); } public static T CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs index 960cfba62..9bee0ff44 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs @@ -15,41 +15,46 @@ // along with this program. If not, see . using System; +using System.Collections.Generic; +using NLog; using Unity.Entities; using UnityEngine; -using VisualPinball.Engine.Resources.Meshes; using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Gate; +using Logger = NLog.Logger; namespace VisualPinball.Unity { internal static class GateExtensions { - public static IItemMainAuthoring SetupGameObject(this Gate gate, GameObject obj, IItemMainAuthoring parentAuthoring) + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Gate gate, GameObject obj, IItemMainAuthoring parentAuthoring) { + var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(gate); switch (gate.SubComponent) { case ItemSubComponent.None: + // collider obj.AddColliderComponent(gate); - CreateChild(obj, GateMeshGenerator.Bracket); - var wire = CreateChild(obj, GateMeshGenerator.Wire); - wire.AddComponent(); + + // bracket mesh + meshAuthoring.Add(CreateChild(obj, GateMeshGenerator.Bracket)); + + // wire mesh + var wireMeshAuth = CreateChild(obj, GateMeshGenerator.Wire); + wireMeshAuth.gameObject.AddComponent(); + meshAuthoring.Add(wireMeshAuth); break; case ItemSubComponent.Collider: { - obj.AddColliderComponent(gate); - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyColliderComponent(); - } + Logger.Error("Cannot parent a gate collider to a different object than a gate!"); break; } case ItemSubComponent.Mesh: { - // todo - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyMeshComponent(); - } + Logger.Error("Cannot parent a gate mesh to a different object than a gate!"); break; } @@ -57,7 +62,7 @@ public static IItemMainAuthoring SetupGameObject(this Gate gate, GameObject obj, throw new ArgumentOutOfRangeException(); } obj.AddComponent(); - return mainAuthoring; + return (mainAuthoring, meshAuthoring); } private static void AddColliderComponent(this GameObject obj, Gate gate) @@ -67,13 +72,13 @@ private static void AddColliderComponent(this GameObject obj, Gate gate) } } - private static GameObject CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring + private static T CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring { var subObj = new GameObject(name); subObj.transform.SetParent(obj.transform, false); - subObj.AddComponent(); + var comp = subObj.AddComponent(); //subObj.layer = ChildObjectsLayer; - return subObj; + return comp; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs index 43be891a9..9a5cd58ee 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs @@ -15,38 +15,38 @@ // along with this program. If not, see . using System; +using System.Collections.Generic; +using NLog; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.HitTarget; +using Logger = NLog.Logger; namespace VisualPinball.Unity { internal static class HitTargetExtensions { - public static IItemMainAuthoring SetupGameObject(this HitTarget hitTarget, GameObject obj, IItemMainAuthoring parentAuthoring) + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this HitTarget hitTarget, GameObject obj, IItemMainAuthoring parentAuthoring) { + var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(hitTarget); switch (hitTarget.SubComponent) { case ItemSubComponent.None: obj.AddColliderComponent(hitTarget); - obj.AddComponent(); + meshAuthoring.Add(obj.AddComponent()); break; case ItemSubComponent.Collider: { - obj.AddColliderComponent(hitTarget); - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyColliderComponent(); - } + Logger.Error("Cannot parent a target collider to a different object than a target!"); break; } case ItemSubComponent.Mesh: { - obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyMeshComponent(); - } + Logger.Error("Cannot parent a target mesh to a different object than a target!"); break; } @@ -54,7 +54,8 @@ public static IItemMainAuthoring SetupGameObject(this HitTarget hitTarget, GameO throw new ArgumentOutOfRangeException(); } obj.AddComponent(); - return mainAuthoring; + + return (mainAuthoring, meshAuthoring); } private static void AddColliderComponent(this GameObject obj, HitTarget hitTarget) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs index dd62cca56..9ee6533a6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs @@ -16,6 +16,7 @@ using System.Collections.Generic; using System.Reflection; +using UnityEngine; namespace VisualPinball.Unity { @@ -28,6 +29,8 @@ public interface IItemMeshAuthoring : IItemAuthoring IItemMainAuthoring IMainAuthoring { get; } + GameObject gameObject { get; } + void RebuildMeshes(); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs index 2b0981aec..6cacb8b66 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs @@ -15,38 +15,38 @@ // along with this program. If not, see . using System; +using System.Collections.Generic; +using NLog; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Kicker; +using Logger = NLog.Logger; namespace VisualPinball.Unity { internal static class KickerExtensions { - public static IItemMainAuthoring SetupGameObject(this Kicker kicker, GameObject obj, IItemMainAuthoring parentAuthoring) + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Kicker kicker, GameObject obj, IItemMainAuthoring parentAuthoring) { + var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(kicker); switch (kicker.SubComponent) { case ItemSubComponent.None: obj.AddComponent(); - obj.AddComponent(); + meshAuthoring.Add(obj.AddComponent()); break; case ItemSubComponent.Collider: { - obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyColliderComponent(); - } + Logger.Error("Cannot parent a kicker collider to a different object than a kicker!"); break; } case ItemSubComponent.Mesh: { - obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyMeshComponent(); - } + Logger.Error("Cannot parent a kicker collider to a different object than a kicker!"); break; } @@ -54,7 +54,8 @@ public static IItemMainAuthoring SetupGameObject(this Kicker kicker, GameObject throw new ArgumentOutOfRangeException(); } obj.AddComponent(); - return mainAuthoring; + + return (mainAuthoring, meshAuthoring); } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs index 783472e8e..056d3286d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System.Collections.Generic; using UnityEngine; using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Light; @@ -23,15 +24,18 @@ namespace VisualPinball.Unity { internal static class LightExtensions { - public static IItemMainAuthoring SetupGameObject(this Light light, GameObject obj, IItemMainAuthoring parentAuthoring) + + public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Light light, GameObject obj, IItemMainAuthoring parentAuthoring) { + var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(light); + if (!light.Data.ShowBulbMesh) { - return mainAuthoring; + return (mainAuthoring, meshAuthoring); } - CreateChild(obj, LightMeshGenerator.Bulb); - CreateChild(obj, LightMeshGenerator.Socket); + meshAuthoring.Add(CreateChild(obj, LightMeshGenerator.Bulb)); + meshAuthoring.Add(CreateChild(obj, LightMeshGenerator.Socket)); if (light.SubComponent == ItemSubComponent.Mesh) { if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { @@ -39,17 +43,16 @@ public static IItemMainAuthoring SetupGameObject(this Light light, GameObject ob } } - //obj.AddComponent(); - return mainAuthoring; + return (mainAuthoring, meshAuthoring); } - public static GameObject CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring + public static T CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring { var subObj = new GameObject(name); subObj.transform.SetParent(obj.transform, false); - subObj.AddComponent(); + var comp = subObj.AddComponent(); //subObj.layer = ChildObjectsLayer; - return subObj; + return comp; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs index 172d3af6d..e4fe58435 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System.Collections.Generic; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.VPT.Table; @@ -23,13 +24,15 @@ namespace VisualPinball.Unity { internal static class PlayfieldExtensions { - public static void SetupGameObject(this Table table, GameObject obj, IItemMainAuthoring parentAuthoring) + public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Table table, GameObject obj, IItemMainAuthoring parentAuthoring) { obj.AddComponent().SetItem(table); obj.AddComponent(); obj.AddComponent(); obj.AddComponent(); obj.name = "Default Playfield"; + + return (null, new IItemMeshAuthoring[0]); } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs index 9306708f6..cf79a6d9f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs @@ -15,38 +15,53 @@ // along with this program. If not, see . using System; +using System.Collections.Generic; +using NLog; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Plunger; +using Logger = NLog.Logger; namespace VisualPinball.Unity { internal static class PlungerExtensions { - public static IItemMainAuthoring SetupGameObject(this Plunger plunger, GameObject obj, IItemMainAuthoring parentAuthoring) + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Plunger plunger, GameObject obj, IItemMainAuthoring parentAuthoring) { + var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(plunger); switch (plunger.SubComponent) { - case ItemSubComponent.None: - CreateMeshComponents(plunger, obj); + case ItemSubComponent.None: { + switch (plunger.Data.Type) { + case PlungerType.PlungerTypeFlat: + meshAuthoring.Add(CreateChild(obj, PlungerMeshGenerator.Flat)); + break; + + case PlungerType.PlungerTypeCustom: + meshAuthoring.Add(CreateChild(obj, PlungerMeshGenerator.Spring)); + meshAuthoring.Add(CreateChild(obj, PlungerMeshGenerator.Rod)); + break; + + case PlungerType.PlungerTypeModern: + meshAuthoring.Add(CreateChild(obj, PlungerMeshGenerator.Rod)); + break; + + } obj.AddComponent(); break; + } case ItemSubComponent.Collider: { - obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyColliderComponent(); - } + Logger.Error("Cannot parent a plunger collider to a different object than a plunger!"); break; } case ItemSubComponent.Mesh: { - CreateMeshComponents(plunger, obj); - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyMeshComponent(); - } + Logger.Error("Cannot parent a plunger mesh to a different object than a plunger!"); break; } @@ -54,35 +69,16 @@ public static IItemMainAuthoring SetupGameObject(this Plunger plunger, GameObjec throw new ArgumentOutOfRangeException(); } obj.AddComponent(); - return mainAuthoring; - } - - private static void CreateMeshComponents(Plunger plunger, GameObject obj) - { - switch (plunger.Data.Type) { - case PlungerType.PlungerTypeFlat: - CreateChild(obj, PlungerMeshGenerator.Flat); - break; - - case PlungerType.PlungerTypeCustom: - CreateChild(obj, PlungerMeshGenerator.Spring); - CreateChild(obj, PlungerMeshGenerator.Rod); - break; - - case PlungerType.PlungerTypeModern: - CreateChild(obj, PlungerMeshGenerator.Rod); - break; - - } + return (mainAuthoring, meshAuthoring); } - public static GameObject CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring + public static T CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring { var subObj = new GameObject(name); subObj.transform.SetParent(obj.transform, false); - subObj.AddComponent(); + var comp = subObj.AddComponent(); //subObj.layer = ChildObjectsLayer; - return subObj; + return comp; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderAuthoring.cs index 440f8e756..1aef16448 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderAuthoring.cs @@ -24,7 +24,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Primitive Collider")] public class PrimitiveColliderAuthoring : ItemColliderAuthoring { - public static readonly Type[] ValidParentTypes = new Type[0]; + public static readonly Type[] ValidParentTypes = { + typeof(RubberAuthoring), + typeof(SurfaceAuthoring) + }; public override IEnumerable ValidParents => ValidParentTypes; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs index 0fd3aa8c2..4789aec94 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs @@ -15,24 +15,28 @@ // along with this program. If not, see . using System; +using System.Collections.Generic; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Primitive; +using Logger = NLog.Logger; namespace VisualPinball.Unity { internal static class PrimitiveExtensions { - public static IItemMainAuthoring SetupGameObject(this Primitive primitive, GameObject obj, IItemMainAuthoring parentAuthoring) + public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Primitive primitive, GameObject obj, IItemMainAuthoring parentAuthoring) { + var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(primitive); switch (primitive.SubComponent) { - case ItemSubComponent.None: - obj.AddMeshComponent(primitive); + case ItemSubComponent.None: { + meshAuthoring.Add(obj.AddComponent()); obj.AddColliderComponent(primitive); break; + } case ItemSubComponent.Collider: { obj.AddColliderComponent(primitive); @@ -43,7 +47,7 @@ public static IItemMainAuthoring SetupGameObject(this Primitive primitive, GameO } case ItemSubComponent.Mesh: { - obj.AddMeshComponent(primitive); + meshAuthoring.Add(obj.AddComponent()); if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { parentMainAuthoring.DestroyMeshComponent(); } @@ -54,13 +58,7 @@ public static IItemMainAuthoring SetupGameObject(this Primitive primitive, GameO throw new ArgumentOutOfRangeException(); } obj.AddComponent(); - return mainAuthoring; - } - - private static void AddMeshComponent(this GameObject obj, Primitive primitive) - { - var comp = obj.AddComponent(); - comp.enabled = primitive.Data.IsVisible; + return (mainAuthoring, meshAuthoring); } private static void AddColliderComponent(this GameObject obj, Primitive primitive) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs index c6a34a8fb..1f15f9771 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveMeshAuthoring.cs @@ -27,6 +27,16 @@ public class PrimitiveMeshAuthoring : ItemMeshAuthoring ValidParents => ValidParentTypes; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampColliderAuthoring.cs index 134107a7f..7fdefaa41 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampColliderAuthoring.cs @@ -24,7 +24,9 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Ramp Collider")] public class RampColliderAuthoring : ItemColliderAuthoring { - public static readonly Type[] ValidParentTypes = new Type[0]; + public static readonly Type[] ValidParentTypes = { + typeof(PrimitiveAuthoring) + }; public override IEnumerable ValidParents => ValidParentTypes; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs index 18ce13217..81a77bccd 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs @@ -15,23 +15,34 @@ // along with this program. If not, see . using System; +using System.Collections.Generic; +using NLog; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Ramp; +using Logger = NLog.Logger; namespace VisualPinball.Unity { internal static class RampExtensions { - public static IItemMainAuthoring SetupGameObject(this Ramp ramp, GameObject obj, IItemMainAuthoring parentAuthoring) + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Ramp ramp, GameObject obj, IItemMainAuthoring parentAuthoring) { + var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(ramp); switch (ramp.SubComponent) { case ItemSubComponent.None: - CreateMeshComponents(ramp, obj); obj.AddColliderComponent(ramp); + if (ramp.IsHabitrail) { + meshAuthoring.Add(CreateChild(obj, RampMeshGenerator.Wires)); + } else { + meshAuthoring.Add(CreateChild(obj, RampMeshGenerator.Floor)); + meshAuthoring.Add(CreateChild(obj, RampMeshGenerator.Wall)); + } break; case ItemSubComponent.Collider: { @@ -43,11 +54,7 @@ public static IItemMainAuthoring SetupGameObject(this Ramp ramp, GameObject obj, } case ItemSubComponent.Mesh: { - // todo - CreateMeshComponents(ramp, obj); - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyMeshComponent(); - } + Logger.Error("Cannot parent a ramp mesh to a different object than a ramp!"); break; } @@ -55,7 +62,7 @@ public static IItemMainAuthoring SetupGameObject(this Ramp ramp, GameObject obj, throw new ArgumentOutOfRangeException(); } obj.AddComponent(); - return mainAuthoring; + return (mainAuthoring, meshAuthoring); } private static void AddColliderComponent(this GameObject obj, Ramp ramp) @@ -65,23 +72,13 @@ private static void AddColliderComponent(this GameObject obj, Ramp ramp) } } - private static void CreateMeshComponents(Ramp ramp, GameObject obj) - { - if (ramp.IsHabitrail) { - CreateChild(obj, RampMeshGenerator.Wires); - } else { - CreateChild(obj, RampMeshGenerator.Floor); - CreateChild(obj, RampMeshGenerator.Wall); - } - } - - public static GameObject CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring + public static T CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring { var subObj = new GameObject(name); subObj.transform.SetParent(obj.transform, false); - subObj.AddComponent(); + var comp = subObj.AddComponent(); //subObj.layer = ChildObjectsLayer; - return subObj; + return comp; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs index 64ce55b82..b2da16c1a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs @@ -15,6 +15,7 @@ // along with this program. If not, see . using System; +using System.Collections.Generic; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.VPT; @@ -24,14 +25,15 @@ namespace VisualPinball.Unity { internal static class RubberExtensions { - public static IItemMainAuthoring SetupGameObject(this Rubber rubber, GameObject obj, IItemMainAuthoring parentAuthoring) + public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Rubber rubber, GameObject obj, IItemMainAuthoring parentAuthoring) { + var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(rubber); switch (rubber.SubComponent) { case ItemSubComponent.None: { obj.AddColliderComponent(rubber); - AddMeshComponent(rubber, obj); + meshAuthoring.Add(obj.AddComponent()); break; } @@ -44,7 +46,7 @@ public static IItemMainAuthoring SetupGameObject(this Rubber rubber, GameObject } case ItemSubComponent.Mesh: { - AddMeshComponent(rubber, obj); + meshAuthoring.Add(obj.AddComponent()); if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { parentMainAuthoring.DestroyMeshComponent(); } @@ -56,13 +58,7 @@ public static IItemMainAuthoring SetupGameObject(this Rubber rubber, GameObject } obj.AddComponent(); - return mainAuthoring; - } - - private static void AddMeshComponent(Rubber rubber, GameObject obj) - { - var meshComponent = obj.AddComponent(); - meshComponent.enabled = rubber.Data.IsVisible; + return (mainAuthoring, meshAuthoring); } private static void AddColliderComponent(this GameObject obj, Rubber rubber) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs index c01b13e62..070d81528 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs @@ -15,40 +15,42 @@ // along with this program. If not, see . using System; +using System.Collections.Generic; +using NLog; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Spinner; +using Logger = NLog.Logger; namespace VisualPinball.Unity { internal static class SpinnerExtensions { - public static IItemMainAuthoring SetupGameObject(this Spinner spinner, GameObject obj, IItemMainAuthoring parentAuthoring) + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Spinner spinner, GameObject obj, IItemMainAuthoring parentAuthoring) { + var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(spinner); switch (spinner.SubComponent) { case ItemSubComponent.None: obj.AddComponent(); - CreateChild(obj, SpinnerMeshGenerator.Bracket); - var wire = CreateChild(obj, SpinnerMeshGenerator.Plate); - wire.AddComponent(); + meshAuthoring.Add(CreateChild(obj, SpinnerMeshGenerator.Bracket)); + + var wireMeshAuth = CreateChild(obj, SpinnerMeshGenerator.Plate); + wireMeshAuth.gameObject.AddComponent(); + meshAuthoring.Add(wireMeshAuth); break; case ItemSubComponent.Collider: { - obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyColliderComponent(); - } + Logger.Error("Cannot parent a spinner collider to a different object than a spinner!"); break; } case ItemSubComponent.Mesh: { - // todo - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyMeshComponent(); - } + Logger.Error("Cannot parent a spinner mesh to a different object than a spinner!"); break; } @@ -56,16 +58,16 @@ public static IItemMainAuthoring SetupGameObject(this Spinner spinner, GameObjec throw new ArgumentOutOfRangeException(); } obj.AddComponent(); - return mainAuthoring; + return (mainAuthoring, meshAuthoring); } - private static GameObject CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring + private static T CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring { var subObj = new GameObject(name); subObj.transform.SetParent(obj.transform, false); - subObj.AddComponent(); + var comp = subObj.AddComponent(); //subObj.layer = ChildObjectsLayer; - return subObj; + return comp; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs index 3e03b80c6..385c2af92 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceColliderAuthoring.cs @@ -24,7 +24,10 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Collision/Surface Collider")] public class SurfaceColliderAuthoring : ItemColliderAuthoring { - public static readonly Type[] ValidParentTypes = new Type[0]; + public static readonly Type[] ValidParentTypes = { + typeof(RubberAuthoring), + typeof(PrimitiveAuthoring) + }; public override IEnumerable ValidParents => ValidParentTypes; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs index c4e8f5d2b..88e7a9e56 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs @@ -15,6 +15,7 @@ // along with this program. If not, see . using System; +using System.Collections.Generic; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.VPT; @@ -24,15 +25,16 @@ namespace VisualPinball.Unity { internal static class SurfaceExtensions { - public static IItemMainAuthoring SetupGameObject(this Surface surface, GameObject obj, IItemMainAuthoring parentAuthoring) + public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Surface surface, GameObject obj, IItemMainAuthoring parentAuthoring) { + var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(surface); switch (surface.SubComponent) { case ItemSubComponent.None: obj.AddColliderComponent(surface); - CreateChild(obj, SurfaceMeshGenerator.Side); - CreateChild(obj, SurfaceMeshGenerator.Top); + meshAuthoring.Add(CreateChild(obj, SurfaceMeshGenerator.Side)); + meshAuthoring.Add(CreateChild(obj, SurfaceMeshGenerator.Top)); break; case ItemSubComponent.Collider: { @@ -44,8 +46,8 @@ public static IItemMainAuthoring SetupGameObject(this Surface surface, GameObjec } case ItemSubComponent.Mesh: { - CreateChild(obj, SurfaceMeshGenerator.Side); - CreateChild(obj, SurfaceMeshGenerator.Top); + meshAuthoring.Add(CreateChild(obj, SurfaceMeshGenerator.Side)); + meshAuthoring.Add(CreateChild(obj, SurfaceMeshGenerator.Top)); if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { parentMainAuthoring.DestroyMeshComponent(); } @@ -56,7 +58,7 @@ public static IItemMainAuthoring SetupGameObject(this Surface surface, GameObjec throw new ArgumentOutOfRangeException(); } obj.AddComponent(); - return mainAuthoring; + return (mainAuthoring, meshAuthoring); } private static void AddColliderComponent(this GameObject obj, Surface surface) @@ -66,13 +68,13 @@ private static void AddColliderComponent(this GameObject obj, Surface surface) } } - private static GameObject CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring + private static T CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring { var subObj = new GameObject(name); subObj.transform.SetParent(obj.transform, false); - subObj.AddComponent(); + var comp = subObj.AddComponent(); //subObj.layer = ChildObjectsLayer; - return subObj; + return comp; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs index e90b7c1c5..869f284b5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs @@ -15,38 +15,38 @@ // along with this program. If not, see . using System; +using System.Collections.Generic; +using NLog; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Trigger; +using Logger = NLog.Logger; namespace VisualPinball.Unity { internal static class TriggerExtensions { - public static IItemMainAuthoring SetupGameObject(this Trigger trigger, GameObject obj, IItemMainAuthoring parentAuthoring) + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Trigger trigger, GameObject obj, IItemMainAuthoring parentAuthoring) { + var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(trigger); switch (trigger.SubComponent) { case ItemSubComponent.None: obj.AddComponent(); - obj.AddComponent(); + meshAuthoring.Add(obj.AddComponent()); break; case ItemSubComponent.Collider: { - obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyColliderComponent(); - } + Logger.Error("Cannot parent a trigger collider to a different object than a trigger!"); break; } case ItemSubComponent.Mesh: { - obj.AddComponent(); - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyMeshComponent(); - } + Logger.Error("Cannot parent a trigger mesh to a different object than a trigger!"); break; } @@ -54,7 +54,7 @@ public static IItemMainAuthoring SetupGameObject(this Trigger trigger, GameObjec throw new ArgumentOutOfRangeException(); } obj.AddComponent(); - return mainAuthoring; + return (mainAuthoring, meshAuthoring); } } } From 89a7265c4365881ff604731f15a136a7250718d5 Mon Sep 17 00:00:00 2001 From: freezy Date: Tue, 27 Oct 2020 00:49:37 +0100 Subject: [PATCH 113/124] import: Refactor object creation. --- .../Toolbox/ToolboxEditor.cs | 5 +- .../Patcher/Common/Defaults.cs | 9 +-- .../Patcher/Patcher.cs | 4 + .../Patcher/Tables/IndianaJones.cs | 5 +- .../Game/Engine/DefaultGamelogicEngine.cs | 1 - .../Import/VpxConverter.cs | 78 +++++++++++++------ .../VPT/Bumper/BumperExtensions.cs | 15 ++-- .../VPT/Flipper/FlipperExtensions.cs | 9 ++- .../VPT/Gate/GateExtensions.cs | 15 ++-- .../VPT/HitTarget/HitTargetExtensions.cs | 15 ++-- .../VPT/IItemMainAuthoring.cs | 2 + .../VPT/Kicker/KickerExtensions.cs | 9 ++- .../VPT/Light/LightExtensions.cs | 9 +-- .../VPT/Playfield/PlayfieldExtensions.cs | 4 +- .../VPT/Plunger/PlungerExtensions.cs | 9 ++- .../VPT/Primitive/PrimitiveAuthoring.cs | 2 - .../VPT/Primitive/PrimitiveExtensions.cs | 21 ++--- .../VPT/Ramp/RampAuthoring.cs | 1 - .../VPT/Ramp/RampExtensions.cs | 17 ++-- .../VPT/Rubber/RubberExtensions.cs | 17 ++-- .../VPT/Spinner/SpinnerExtensions.cs | 7 +- .../VPT/Surface/SurfaceAuthoring.cs | 1 - .../VPT/Surface/SurfaceExtensions.cs | 17 ++-- .../VPT/Trigger/TriggerExtensions.cs | 9 ++- 24 files changed, 156 insertions(+), 125 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs index 893f517e7..3250ee86a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Toolbox/ToolboxEditor.cs @@ -184,9 +184,8 @@ private void CreateItem(Func create, string actionName) whe private GameObject CreateRenderable(IRenderable renderable) { - //var rog = renderable.GetRenderObjects(_table.Table, Origin.Original, false); - var (obj, _, _) = VpxConverter.CreateGameObjects(_tableAuthoring.Table, renderable, GetOrCreateParent(_tableAuthoring, renderable)); - return obj; + var convertedItem = VpxConverter.CreateGameObjects(_tableAuthoring.Table, renderable, GetOrCreateParent(_tableAuthoring, renderable)); + return convertedItem.MainAuthoring.gameObject; } private static GameObject GetOrCreateParent(Component tb, IItem renderable) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Common/Defaults.cs b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Common/Defaults.cs index 7ded02606..320ec1648 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Common/Defaults.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Common/Defaults.cs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -using UnityEngine; using VisualPinball.Engine.VPT.Primitive; namespace VisualPinball.Unity.Patcher @@ -29,16 +28,16 @@ public class Defaults [NameMatch("BallShadow5")] [NameMatch("BallShadow6")] [NameMatch("BallShadow7")] - public void RemoveBallShadow(GameObject gameObject) + public void RemoveBallShadow(Primitive primitive) { - gameObject.GetComponent().enabled = false; + primitive.Data.IsVisible = false; } [NameMatch("FlipperLSh")] [NameMatch("FlipperRSh")] - public void RemoveFlipperShadow(GameObject gameObject) + public void RemoveFlipperShadow(Primitive primitive) { - gameObject.GetComponent().enabled = false; + primitive.Data.IsVisible = false; } [NameMatch("Ruler_mm")] diff --git a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Patcher.cs b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Patcher.cs index e18ab3a4a..a3aa2be70 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Patcher.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Patcher.cs @@ -53,6 +53,10 @@ public Patcher(Table table, string fileName) Logger.Info("Table will be patched using the following patchers: [ {0} ]", string.Join(", ", _patchers.Select(o => o.GetType().Name))); } + /// + /// Pre-patches are match methods that purely contain the item as parameter + /// + /// public void ApplyPrePatches(IRenderable item) { foreach (var patcher in _patchers) { diff --git a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Tables/IndianaJones.cs b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Tables/IndianaJones.cs index e12ec6596..dec805b98 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Tables/IndianaJones.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Patcher/Patcher/Tables/IndianaJones.cs @@ -18,6 +18,7 @@ using UnityEngine; using UnityEngine.Rendering; +using VisualPinball.Engine.VPT.Primitive; namespace VisualPinball.Unity.Patcher { @@ -26,9 +27,9 @@ public class IndianaJones { [NameMatch("LeftFlipperSh", IgnoreCase = false)] [NameMatch("RightFlipperSh")] - public void RemoveFlipperShadow(GameObject gameObject) + public void RemoveFlipperShadow(Primitive primitive) { - gameObject.GetComponent().enabled = false; + primitive.Data.IsVisible = false; } [NameMatch("Primitive21")] diff --git a/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/DefaultGamelogicEngine.cs b/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/DefaultGamelogicEngine.cs index de2803975..9a64353a7 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/DefaultGamelogicEngine.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Game/Engine/DefaultGamelogicEngine.cs @@ -20,7 +20,6 @@ using NLog; using VisualPinball.Engine.Common; using VisualPinball.Engine.Game.Engines; -using Debug = UnityEngine.Debug; namespace VisualPinball.Unity { diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index 1c2990a2f..8b90bf04a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -22,6 +22,7 @@ using System.Collections.Generic; using System.Linq; using NLog; +using NLog.Targets.Wrappers; using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT; @@ -112,9 +113,10 @@ public void Convert(string fileName, Table table, bool applyPatch = true, string private void ConvertGameItems(GameObject tableGameObject) { - var createdMainObjs = new Dictionary(); - var createdMainMbs = new Dictionary(); - var createdMeshMbs = new Dictionary>(); + var convertedItems = new Dictionary(); + // var createdMainObjs = new Dictionary(); + // var createdMainMbs = new Dictionary(); + // var createdMeshMbs = new Dictionary>(); var renderableLookup = new Dictionary(); var renderables = from renderable in _table.Renderables orderby renderable.SubComponent @@ -136,59 +138,52 @@ orderby renderable.SubComponent if (renderable.SubComponent == ItemSubComponent.None) { // create object(s) - var (rootObj, rootMb, meshMbs) = CreateGameObjects(_table, renderable, _parents[renderable.ItemGroupName]); - - createdMainObjs[lookupName] = rootObj; - createdMainMbs[lookupName] = rootMb; - createdMeshMbs[lookupName] = meshMbs; + convertedItems[lookupName] = CreateGameObjects(_table, renderable, _parents[renderable.ItemGroupName]); } else { // if the object's names was parsed to be part of another object, re-link to other object. var parentName = renderable.ComponentName.ToLower(); - if (createdMainObjs.ContainsKey(parentName)) { - var mainObj = createdMainObjs[parentName]; - var mainMb = createdMainMbs[parentName]; + if (convertedItems.ContainsKey(parentName)) { + var parentMb = convertedItems[parentName].MainAuthoring; + var parentObj = parentMb.gameObject; // move and rotate into parent - if (mainMb.IItem is IRenderable parentRenderable) { + if (parentMb.IItem is IRenderable parentRenderable) { renderable.Position.Sub(parentRenderable.Position); renderable.RotationY -= parentRenderable.RotationY; } - var (rootObj, rootMb, meshMbs) = CreateGameObjects(_table, renderable, _parents[renderable.ItemGroupName], mainMb); - - createdMeshMbs[lookupName] = meshMbs; - - rootObj.transform.SetParent(mainObj.transform, false); + convertedItems[lookupName] = CreateGameObjects(_table, renderable, _parents[renderable.ItemGroupName], parentMb); + convertedItems[lookupName].MainAuthoring.gameObject.transform.SetParent(parentObj.transform, false); } else { - throw new InvalidOperationException($"Cannot find component \"{parentName}\" that is supposed to be the parent of \"{renderable.Name}\"."); + Logger.Warn($"Cannot find component \"{parentName}\" that is supposed to be the parent of \"{renderable.Name}\"."); } } } // now we have all renderables imported, patch them. - foreach (var lookupName in createdMeshMbs.Keys) { - foreach (var meshMb in createdMeshMbs[lookupName]) { + foreach (var lookupName in convertedItems.Keys) { + foreach (var meshMb in convertedItems[lookupName].MeshAuthoring) { _tableAuthoring.Patcher.ApplyPatches(renderableLookup[lookupName], meshMb.gameObject, tableGameObject); } } } - public static (GameObject, IItemMainAuthoring, IEnumerable) CreateGameObjects(Table table, IRenderable renderable, GameObject parent, IItemMainAuthoring parentAuthoring = null) + public static ConvertedItem CreateGameObjects(Table table, IRenderable renderable, GameObject parent, IItemMainAuthoring parentAuthoring = null) { var obj = new GameObject(renderable.Name); obj.transform.parent = parent.transform; - var (mainAuthoring, meshAuthoring) = SetupGameObjects(renderable, obj, parentAuthoring); + var importedObject = SetupGameObjects(renderable, obj, parentAuthoring); // apply transformation obj.transform.SetFromMatrix(renderable.TransformationMatrix(table, Origin.Original).ToUnityMatrix()); - return (obj, mainAuthoring, meshAuthoring); + return importedObject; } - private static (IItemMainAuthoring, IEnumerable) SetupGameObjects(IRenderable item, GameObject obj, IItemMainAuthoring parentAuthoring = null) + private static ConvertedItem SetupGameObjects(IRenderable item, GameObject obj, IItemMainAuthoring parentAuthoring = null) { switch (item) { case Bumper bumper: return bumper.SetupGameObject(obj, parentAuthoring); @@ -247,4 +242,39 @@ private void MakeSerializable(GameObject go, Table table) ); } } + + public class ConvertedItem + { + public readonly IItemMainAuthoring MainAuthoring; + public readonly IEnumerable MeshAuthoring; + public readonly IItemColliderAuthoring ColliderAuthoring; + + public ConvertedItem() + { + MainAuthoring = null; + MeshAuthoring = new IItemMeshAuthoring[0]; + ColliderAuthoring = null; + } + + public ConvertedItem(IItemMainAuthoring mainAuthoring) + { + MainAuthoring = mainAuthoring; + MeshAuthoring = new IItemMeshAuthoring[0]; + ColliderAuthoring = null; + } + + public ConvertedItem(IItemMainAuthoring mainAuthoring, IEnumerable meshAuthoring) + { + MainAuthoring = mainAuthoring; + MeshAuthoring = meshAuthoring; + ColliderAuthoring = null; + } + + public ConvertedItem(IItemMainAuthoring mainAuthoring, IEnumerable meshAuthoring, IItemColliderAuthoring colliderAuthoring) + { + MainAuthoring = mainAuthoring; + MeshAuthoring = meshAuthoring; + ColliderAuthoring = colliderAuthoring; + } + } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs index b86bfec52..fc7ba0383 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs @@ -29,14 +29,15 @@ internal static class BumperExtensions { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Bumper bumper, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Bumper bumper, GameObject obj, IItemMainAuthoring parentAuthoring) { - var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(bumper); + var meshAuthoring = new List(); + BumperColliderAuthoring colliderAuthoring = null; switch (bumper.SubComponent) { case ItemSubComponent.None: - obj.AddColliderComponent(bumper); + colliderAuthoring = obj.AddColliderComponent(bumper); meshAuthoring.Add(CreateChild(obj, BumperMeshGenerator.Base)); meshAuthoring.Add(CreateChild(obj, BumperMeshGenerator.Cap)); @@ -65,14 +66,12 @@ public static (IItemMainAuthoring, IEnumerable) SetupGameObj } obj.AddComponent(); - return (mainAuthoring, meshAuthoring); + return new ConvertedItem(mainAuthoring, meshAuthoring, colliderAuthoring); } - private static void AddColliderComponent(this GameObject obj, Bumper bumper) + private static BumperColliderAuthoring AddColliderComponent(this GameObject obj, Bumper bumper) { - if (bumper.Data.IsCollidable) { - obj.AddComponent(); - } + return bumper.Data.IsCollidable ? obj.AddComponent() : null; } private static T CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs index 6c454c823..f8f3c154b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs @@ -29,14 +29,15 @@ internal static class FlipperExtensions { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Flipper flipper, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Flipper flipper, GameObject obj, IItemMainAuthoring parentAuthoring) { - var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(flipper); + var meshAuthoring = new List(); + FlipperColliderAuthoring colliderAuthoring = null; switch (flipper.SubComponent) { case ItemSubComponent.None: - obj.AddComponent(); + colliderAuthoring = obj.AddComponent(); // if invisible in main component, we skip creation entirely, because we think users won't dynamically toggle visibility. if (flipper.Data.IsVisible) { @@ -59,7 +60,7 @@ public static (IItemMainAuthoring, IEnumerable) SetupGameObj throw new ArgumentOutOfRangeException(); } obj.AddComponent(); - return (mainAuthoring, meshAuthoring); + return new ConvertedItem(mainAuthoring, meshAuthoring, colliderAuthoring); } public static T CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs index 9bee0ff44..0e23f3ce3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs @@ -29,15 +29,16 @@ internal static class GateExtensions { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Gate gate, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Gate gate, GameObject obj, IItemMainAuthoring parentAuthoring) { - var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(gate); + var meshAuthoring = new List(); + GateColliderAuthoring colliderAuthoring = null; switch (gate.SubComponent) { case ItemSubComponent.None: // collider - obj.AddColliderComponent(gate); + colliderAuthoring = obj.AddColliderComponent(gate); // bracket mesh meshAuthoring.Add(CreateChild(obj, GateMeshGenerator.Bracket)); @@ -62,14 +63,12 @@ public static (IItemMainAuthoring, IEnumerable) SetupGameObj throw new ArgumentOutOfRangeException(); } obj.AddComponent(); - return (mainAuthoring, meshAuthoring); + return new ConvertedItem(mainAuthoring, meshAuthoring, colliderAuthoring); } - private static void AddColliderComponent(this GameObject obj, Gate gate) + private static GateColliderAuthoring AddColliderComponent(this GameObject obj, Gate gate) { - if (gate.Data.IsCollidable) { - obj.AddComponent(); - } + return gate.Data.IsCollidable ? obj.AddComponent() : null; } private static T CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs index 9a5cd58ee..37137154c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs @@ -29,14 +29,15 @@ internal static class HitTargetExtensions { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this HitTarget hitTarget, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this HitTarget hitTarget, GameObject obj, IItemMainAuthoring parentAuthoring) { - var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(hitTarget); + var meshAuthoring = new List(); + HitTargetColliderAuthoring colliderAuthoring = null; switch (hitTarget.SubComponent) { case ItemSubComponent.None: - obj.AddColliderComponent(hitTarget); + colliderAuthoring = obj.AddColliderComponent(hitTarget); meshAuthoring.Add(obj.AddComponent()); break; @@ -55,14 +56,12 @@ public static (IItemMainAuthoring, IEnumerable) SetupGameObj } obj.AddComponent(); - return (mainAuthoring, meshAuthoring); + return new ConvertedItem(mainAuthoring, meshAuthoring, colliderAuthoring); } - private static void AddColliderComponent(this GameObject obj, HitTarget hitTarget) + private static HitTargetColliderAuthoring AddColliderComponent(this GameObject obj, HitTarget hitTarget) { - if (hitTarget.Data.IsCollidable) { - obj.AddComponent(); - } + return hitTarget.Data.IsCollidable ? obj.AddComponent() : null; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs index 2a792cb52..539060c29 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs @@ -24,6 +24,8 @@ public interface IItemMainAuthoring : IItemAuthoring bool CanBeTransformed { get; } + GameObject gameObject { get; } + /// /// Sets the mesh of all mesh sub components to dirty. /// diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs index 6cacb8b66..364f2febc 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs @@ -29,14 +29,15 @@ internal static class KickerExtensions { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Kicker kicker, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Kicker kicker, GameObject obj, IItemMainAuthoring parentAuthoring) { - var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(kicker); + var meshAuthoring = new List(); + KickerColliderAuthoring colliderAuthoring = null; switch (kicker.SubComponent) { case ItemSubComponent.None: - obj.AddComponent(); + colliderAuthoring = obj.AddComponent(); meshAuthoring.Add(obj.AddComponent()); break; @@ -55,7 +56,7 @@ public static (IItemMainAuthoring, IEnumerable) SetupGameObj } obj.AddComponent(); - return (mainAuthoring, meshAuthoring); + return new ConvertedItem(mainAuthoring, meshAuthoring, colliderAuthoring); } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs index 056d3286d..b6bc524db 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs @@ -24,14 +24,13 @@ namespace VisualPinball.Unity { internal static class LightExtensions { - - public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Light light, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Light light, GameObject obj, IItemMainAuthoring parentAuthoring) { - var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(light); + var meshAuthoring = new List(); if (!light.Data.ShowBulbMesh) { - return (mainAuthoring, meshAuthoring); + return new ConvertedItem(mainAuthoring); } meshAuthoring.Add(CreateChild(obj, LightMeshGenerator.Bulb)); @@ -43,7 +42,7 @@ public static (IItemMainAuthoring, IEnumerable) SetupGameObj } } - return (mainAuthoring, meshAuthoring); + return new ConvertedItem(mainAuthoring, meshAuthoring); } public static T CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs index e4fe58435..3ea93962f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs @@ -24,7 +24,7 @@ namespace VisualPinball.Unity { internal static class PlayfieldExtensions { - public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Table table, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Table table, GameObject obj, IItemMainAuthoring parentAuthoring) { obj.AddComponent().SetItem(table); obj.AddComponent(); @@ -32,7 +32,7 @@ public static (IItemMainAuthoring, IEnumerable) SetupGameObj obj.AddComponent(); obj.name = "Default Playfield"; - return (null, new IItemMeshAuthoring[0]); + return new ConvertedItem(); } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs index cf79a6d9f..3293110a6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs @@ -29,13 +29,15 @@ internal static class PlungerExtensions { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Plunger plunger, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Plunger plunger, GameObject obj, IItemMainAuthoring parentAuthoring) { - var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(plunger); + var meshAuthoring = new List(); + PlungerColliderAuthoring colliderAuthoring = null; switch (plunger.SubComponent) { case ItemSubComponent.None: { + colliderAuthoring = obj.AddComponent(); switch (plunger.Data.Type) { case PlungerType.PlungerTypeFlat: meshAuthoring.Add(CreateChild(obj, PlungerMeshGenerator.Flat)); @@ -51,7 +53,6 @@ public static (IItemMainAuthoring, IEnumerable) SetupGameObj break; } - obj.AddComponent(); break; } @@ -69,7 +70,7 @@ public static (IItemMainAuthoring, IEnumerable) SetupGameObj throw new ArgumentOutOfRangeException(); } obj.AddComponent(); - return (mainAuthoring, meshAuthoring); + return new ConvertedItem(mainAuthoring, meshAuthoring, colliderAuthoring); } public static T CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs index 767f29d39..ef0e7175c 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveAuthoring.cs @@ -25,7 +25,6 @@ using System.Linq; using Unity.Entities; using UnityEngine; -using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT.Primitive; namespace VisualPinball.Unity @@ -33,7 +32,6 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Game Item/Primitive")] public class PrimitiveAuthoring : ItemMainAuthoring, IConvertGameObjectToEntity { - protected override Primitive InstantiateItem(PrimitiveData data) => new Primitive(data); protected override Type MeshAuthoringType { get; } = typeof(ItemMeshAuthoring); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs index 4789aec94..e2cd94596 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs @@ -20,26 +20,26 @@ using UnityEngine; using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Primitive; -using Logger = NLog.Logger; namespace VisualPinball.Unity { internal static class PrimitiveExtensions { - public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Primitive primitive, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Primitive primitive, GameObject obj, IItemMainAuthoring parentAuthoring) { - var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(primitive); + var meshAuthoring = new List(); + PrimitiveColliderAuthoring colliderAuthoring = null; switch (primitive.SubComponent) { case ItemSubComponent.None: { + colliderAuthoring = obj.AddColliderComponent(primitive); meshAuthoring.Add(obj.AddComponent()); - obj.AddColliderComponent(primitive); break; } case ItemSubComponent.Collider: { - obj.AddColliderComponent(primitive); + colliderAuthoring = obj.AddColliderComponent(primitive); if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { parentMainAuthoring.DestroyColliderComponent(); } @@ -58,14 +58,17 @@ public static (IItemMainAuthoring, IEnumerable) SetupGameObj throw new ArgumentOutOfRangeException(); } obj.AddComponent(); - return (mainAuthoring, meshAuthoring); + + return new ConvertedItem(mainAuthoring, meshAuthoring, colliderAuthoring); } - private static void AddColliderComponent(this GameObject obj, Primitive primitive) + private static PrimitiveColliderAuthoring AddColliderComponent(this GameObject obj, Primitive primitive) { - if (!primitive.Data.IsToy && primitive.IsCollidable) { // todo handle dynamic collision - obj.AddComponent(); + // todo handle dynamic collision + if (!primitive.Data.IsToy && primitive.IsCollidable) { + return obj.AddComponent(); } + return null; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs index 306b443e3..f5761f466 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampAuthoring.cs @@ -25,7 +25,6 @@ using System.Linq; using Unity.Entities; using UnityEngine; -using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Ramp; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs index 81a77bccd..969e19bda 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs @@ -29,14 +29,15 @@ internal static class RampExtensions { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Ramp ramp, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Ramp ramp, GameObject obj, IItemMainAuthoring parentAuthoring) { - var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(ramp); + var meshAuthoring = new List(); + RampColliderAuthoring colliderAuthoring = null; switch (ramp.SubComponent) { case ItemSubComponent.None: - obj.AddColliderComponent(ramp); + colliderAuthoring = obj.AddColliderComponent(ramp); if (ramp.IsHabitrail) { meshAuthoring.Add(CreateChild(obj, RampMeshGenerator.Wires)); } else { @@ -46,7 +47,7 @@ public static (IItemMainAuthoring, IEnumerable) SetupGameObj break; case ItemSubComponent.Collider: { - obj.AddColliderComponent(ramp); + colliderAuthoring = obj.AddColliderComponent(ramp); if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { parentMainAuthoring.DestroyColliderComponent(); } @@ -62,14 +63,12 @@ public static (IItemMainAuthoring, IEnumerable) SetupGameObj throw new ArgumentOutOfRangeException(); } obj.AddComponent(); - return (mainAuthoring, meshAuthoring); + return new ConvertedItem(mainAuthoring, meshAuthoring, colliderAuthoring); } - private static void AddColliderComponent(this GameObject obj, Ramp ramp) + private static RampColliderAuthoring AddColliderComponent(this GameObject obj, Ramp ramp) { - if (ramp.Data.IsCollidable) { - obj.AddComponent(); - } + return ramp.Data.IsCollidable ? obj.AddComponent() : null; } public static T CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs index b2da16c1a..7f4918ab6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs @@ -25,20 +25,21 @@ namespace VisualPinball.Unity { internal static class RubberExtensions { - public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Rubber rubber, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Rubber rubber, GameObject obj, IItemMainAuthoring parentAuthoring) { - var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(rubber); + var meshAuthoring = new List(); + RubberColliderAuthoring colliderAuthoring = null; switch (rubber.SubComponent) { case ItemSubComponent.None: { - obj.AddColliderComponent(rubber); + colliderAuthoring = obj.AddColliderComponent(rubber); meshAuthoring.Add(obj.AddComponent()); break; } case ItemSubComponent.Collider: { - obj.AddColliderComponent(rubber); + colliderAuthoring = obj.AddColliderComponent(rubber); if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { parentMainAuthoring.DestroyColliderComponent(); } @@ -58,14 +59,12 @@ public static (IItemMainAuthoring, IEnumerable) SetupGameObj } obj.AddComponent(); - return (mainAuthoring, meshAuthoring); + return new ConvertedItem(mainAuthoring, meshAuthoring, colliderAuthoring); } - private static void AddColliderComponent(this GameObject obj, Rubber rubber) + private static RubberColliderAuthoring AddColliderComponent(this GameObject obj, Rubber rubber) { - if (rubber.Data.IsCollidable) { - obj.AddComponent(); - } + return rubber.Data.IsCollidable ? obj.AddComponent() : null; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs index 070d81528..be8440e1b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs @@ -29,14 +29,15 @@ internal static class SpinnerExtensions { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Spinner spinner, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Spinner spinner, GameObject obj, IItemMainAuthoring parentAuthoring) { var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(spinner); + SpinnerColliderAuthoring colliderAuthoring = null; switch (spinner.SubComponent) { case ItemSubComponent.None: - obj.AddComponent(); + colliderAuthoring = obj.AddComponent(); meshAuthoring.Add(CreateChild(obj, SpinnerMeshGenerator.Bracket)); var wireMeshAuth = CreateChild(obj, SpinnerMeshGenerator.Plate); @@ -58,7 +59,7 @@ public static (IItemMainAuthoring, IEnumerable) SetupGameObj throw new ArgumentOutOfRangeException(); } obj.AddComponent(); - return (mainAuthoring, meshAuthoring); + return new ConvertedItem(mainAuthoring, meshAuthoring, colliderAuthoring); } private static T CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs index d759ded08..b46cd03f9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceAuthoring.cs @@ -25,7 +25,6 @@ using System.Linq; using Unity.Entities; using UnityEngine; -using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; using VisualPinball.Engine.VPT.Surface; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs index 88e7a9e56..25f468d6a 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs @@ -25,20 +25,21 @@ namespace VisualPinball.Unity { internal static class SurfaceExtensions { - public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Surface surface, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Surface surface, GameObject obj, IItemMainAuthoring parentAuthoring) { - var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(surface); + var meshAuthoring = new List(); + SurfaceColliderAuthoring colliderAuthoring = null; switch (surface.SubComponent) { case ItemSubComponent.None: - obj.AddColliderComponent(surface); + colliderAuthoring = obj.AddColliderComponent(surface); meshAuthoring.Add(CreateChild(obj, SurfaceMeshGenerator.Side)); meshAuthoring.Add(CreateChild(obj, SurfaceMeshGenerator.Top)); break; case ItemSubComponent.Collider: { - obj.AddColliderComponent(surface); + colliderAuthoring = obj.AddColliderComponent(surface); if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { parentMainAuthoring.DestroyColliderComponent(); } @@ -58,14 +59,12 @@ public static (IItemMainAuthoring, IEnumerable) SetupGameObj throw new ArgumentOutOfRangeException(); } obj.AddComponent(); - return (mainAuthoring, meshAuthoring); + return new ConvertedItem(mainAuthoring, meshAuthoring, colliderAuthoring); } - private static void AddColliderComponent(this GameObject obj, Surface surface) + private static SurfaceColliderAuthoring AddColliderComponent(this GameObject obj, Surface surface) { - if (surface.Data.IsCollidable) { - obj.AddComponent(); - } + return surface.Data.IsCollidable ? obj.AddComponent() : null; } private static T CreateChild(GameObject obj, string name) where T : MonoBehaviour, IItemMeshAuthoring diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs index 869f284b5..d2ea51632 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs @@ -29,14 +29,15 @@ internal static class TriggerExtensions { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public static (IItemMainAuthoring, IEnumerable) SetupGameObject(this Trigger trigger, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Trigger trigger, GameObject obj, IItemMainAuthoring parentAuthoring) { - var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(trigger); + var meshAuthoring = new List(); + TriggerColliderAuthoring colliderAuthoring = null; switch (trigger.SubComponent) { case ItemSubComponent.None: - obj.AddComponent(); + colliderAuthoring = obj.AddComponent(); meshAuthoring.Add(obj.AddComponent()); break; @@ -54,7 +55,7 @@ public static (IItemMainAuthoring, IEnumerable) SetupGameObj throw new ArgumentOutOfRangeException(); } obj.AddComponent(); - return (mainAuthoring, meshAuthoring); + return new ConvertedItem(mainAuthoring, meshAuthoring, colliderAuthoring); } } } From 33f6590b02c42a3e0752bcf7507b027f512962fe Mon Sep 17 00:00:00 2001 From: freezy Date: Tue, 27 Oct 2020 22:16:50 +0100 Subject: [PATCH 114/124] editor: Don't disable gizmos, only icons on recompilation. --- VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs index 404e496a3..3ee143dc5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Utils/Icons.cs @@ -229,7 +229,7 @@ private Texture2D GetItem(string name, IconSize size, IconColor color) private static void DisableGizmo() where T : MonoBehaviour { var className = typeof(T).Name; - SetGizmoEnabled?.Invoke(null, new object[] { MonoBehaviourClassID, className, 0, false }); + //SetGizmoEnabled?.Invoke(null, new object[] { MonoBehaviourClassID, className, 0, false }); SetIconEnabled?.Invoke(null, new object[] { MonoBehaviourClassID, className, 0 }); } } From 58d1242d1ac608ad73aca4d6c580a69f78a21783 Mon Sep 17 00:00:00 2001 From: freezy Date: Tue, 27 Oct 2020 22:18:00 +0100 Subject: [PATCH 115/124] components: Move component destruction to converter. --- .../Import/VpxConverter.cs | 72 ++++++++++++------- .../VPT/Bumper/BumperExtensions.cs | 2 +- .../VPT/Flipper/FlipperExtensions.cs | 2 +- .../VPT/Gate/GateExtensions.cs | 2 +- .../VPT/HitTarget/HitTargetExtensions.cs | 2 +- .../VPT/Kicker/KickerExtensions.cs | 2 +- .../VPT/Light/LightExtensions.cs | 8 +-- .../VPT/Playfield/PlayfieldExtensions.cs | 2 +- .../VPT/Plunger/PlungerExtensions.cs | 2 +- .../VPT/Primitive/PrimitiveExtensions.cs | 8 +-- .../VPT/Ramp/RampExtensions.cs | 5 +- .../VPT/Rubber/RubberExtensions.cs | 8 +-- .../VPT/Spinner/SpinnerExtensions.cs | 2 +- .../VPT/Surface/SurfaceExtensions.cs | 8 +-- .../VPT/Trigger/TriggerExtensions.cs | 2 +- 15 files changed, 59 insertions(+), 68 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index 8b90bf04a..361a833e6 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -114,9 +114,6 @@ public void Convert(string fileName, Table table, bool applyPatch = true, string private void ConvertGameItems(GameObject tableGameObject) { var convertedItems = new Dictionary(); - // var createdMainObjs = new Dictionary(); - // var createdMainMbs = new Dictionary(); - // var createdMeshMbs = new Dictionary>(); var renderableLookup = new Dictionary(); var renderables = from renderable in _table.Renderables orderby renderable.SubComponent @@ -144,17 +141,26 @@ orderby renderable.SubComponent // if the object's names was parsed to be part of another object, re-link to other object. var parentName = renderable.ComponentName.ToLower(); if (convertedItems.ContainsKey(parentName)) { - var parentMb = convertedItems[parentName].MainAuthoring; - var parentObj = parentMb.gameObject; + var parent = convertedItems[parentName]; // move and rotate into parent - if (parentMb.IItem is IRenderable parentRenderable) { + if (parent.MainAuthoring.IItem is IRenderable parentRenderable) { renderable.Position.Sub(parentRenderable.Position); renderable.RotationY -= parentRenderable.RotationY; } - convertedItems[lookupName] = CreateGameObjects(_table, renderable, _parents[renderable.ItemGroupName], parentMb); - convertedItems[lookupName].MainAuthoring.gameObject.transform.SetParent(parentObj.transform, false); + var convertedItem = CreateGameObjects(_table, renderable, _parents[renderable.ItemGroupName]); + + if (convertedItem.MeshAuthoring.Any()) { + parent.DestroyMeshComponent(); + } + if (convertedItem.ColliderAuthoring != null) { + parent.DestroyColliderComponent(); + } + + convertedItem.MainAuthoring.gameObject.transform.SetParent(parent.MainAuthoring.gameObject.transform, false); + + convertedItems[lookupName] = convertedItem; } else { Logger.Warn($"Cannot find component \"{parentName}\" that is supposed to be the parent of \"{renderable.Name}\"."); @@ -170,12 +176,12 @@ orderby renderable.SubComponent } } - public static ConvertedItem CreateGameObjects(Table table, IRenderable renderable, GameObject parent, IItemMainAuthoring parentAuthoring = null) + public static ConvertedItem CreateGameObjects(Table table, IRenderable renderable, GameObject parent) { var obj = new GameObject(renderable.Name); obj.transform.parent = parent.transform; - var importedObject = SetupGameObjects(renderable, obj, parentAuthoring); + var importedObject = SetupGameObjects(renderable, obj); // apply transformation obj.transform.SetFromMatrix(renderable.TransformationMatrix(table, Origin.Original).ToUnityMatrix()); @@ -183,23 +189,23 @@ public static ConvertedItem CreateGameObjects(Table table, IRenderable renderabl return importedObject; } - private static ConvertedItem SetupGameObjects(IRenderable item, GameObject obj, IItemMainAuthoring parentAuthoring = null) + private static ConvertedItem SetupGameObjects(IRenderable item, GameObject obj) { switch (item) { - case Bumper bumper: return bumper.SetupGameObject(obj, parentAuthoring); - case Flipper flipper: return flipper.SetupGameObject(obj, parentAuthoring); - case Gate gate: return gate.SetupGameObject(obj, parentAuthoring); - case HitTarget hitTarget: return hitTarget.SetupGameObject(obj, parentAuthoring); - case Kicker kicker: return kicker.SetupGameObject(obj, parentAuthoring); - case Engine.VPT.Light.Light lt: return lt.SetupGameObject(obj, parentAuthoring); - case Plunger plunger: return plunger.SetupGameObject(obj, parentAuthoring); - case Primitive primitive: return primitive.SetupGameObject(obj, parentAuthoring); - case Ramp ramp: return ramp.SetupGameObject(obj, parentAuthoring); - case Rubber rubber: return rubber.SetupGameObject(obj, parentAuthoring); - case Spinner spinner: return spinner.SetupGameObject(obj, parentAuthoring); - case Surface surface: return surface.SetupGameObject(obj, parentAuthoring); - case Table table: return table.SetupGameObject(obj, parentAuthoring); - case Trigger trigger: return trigger.SetupGameObject(obj, parentAuthoring); + case Bumper bumper: return bumper.SetupGameObject(obj); + case Flipper flipper: return flipper.SetupGameObject(obj); + case Gate gate: return gate.SetupGameObject(obj); + case HitTarget hitTarget: return hitTarget.SetupGameObject(obj); + case Kicker kicker: return kicker.SetupGameObject(obj); + case Engine.VPT.Light.Light lt: return lt.SetupGameObject(obj); + case Plunger plunger: return plunger.SetupGameObject(obj); + case Primitive primitive: return primitive.SetupGameObject(obj); + case Ramp ramp: return ramp.SetupGameObject(obj); + case Rubber rubber: return rubber.SetupGameObject(obj); + case Spinner spinner: return spinner.SetupGameObject(obj); + case Surface surface: return surface.SetupGameObject(obj); + case Table table: return table.SetupGameObject(obj); + case Trigger trigger: return trigger.SetupGameObject(obj); } throw new InvalidOperationException("Unknown item " + item + " to setup!"); @@ -246,8 +252,8 @@ private void MakeSerializable(GameObject go, Table table) public class ConvertedItem { public readonly IItemMainAuthoring MainAuthoring; - public readonly IEnumerable MeshAuthoring; - public readonly IItemColliderAuthoring ColliderAuthoring; + public IEnumerable MeshAuthoring; + public IItemColliderAuthoring ColliderAuthoring; public ConvertedItem() { @@ -276,5 +282,17 @@ public ConvertedItem(IItemMainAuthoring mainAuthoring, IEnumerable().SetItem(bumper); var meshAuthoring = new List(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs index f8f3c154b..c52bc49bc 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Flipper/FlipperExtensions.cs @@ -29,7 +29,7 @@ internal static class FlipperExtensions { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public static ConvertedItem SetupGameObject(this Flipper flipper, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Flipper flipper, GameObject obj) { var mainAuthoring = obj.AddComponent().SetItem(flipper); var meshAuthoring = new List(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs index 0e23f3ce3..880039631 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Gate/GateExtensions.cs @@ -29,7 +29,7 @@ internal static class GateExtensions { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public static ConvertedItem SetupGameObject(this Gate gate, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Gate gate, GameObject obj) { var mainAuthoring = obj.AddComponent().SetItem(gate); var meshAuthoring = new List(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs index 37137154c..4dad6c7f4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/HitTarget/HitTargetExtensions.cs @@ -29,7 +29,7 @@ internal static class HitTargetExtensions { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public static ConvertedItem SetupGameObject(this HitTarget hitTarget, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this HitTarget hitTarget, GameObject obj) { var mainAuthoring = obj.AddComponent().SetItem(hitTarget); var meshAuthoring = new List(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs index 364f2febc..50f21544b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs @@ -29,7 +29,7 @@ internal static class KickerExtensions { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public static ConvertedItem SetupGameObject(this Kicker kicker, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Kicker kicker, GameObject obj) { var mainAuthoring = obj.AddComponent().SetItem(kicker); var meshAuthoring = new List(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs index b6bc524db..94a1dda37 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs @@ -24,7 +24,7 @@ namespace VisualPinball.Unity { internal static class LightExtensions { - public static ConvertedItem SetupGameObject(this Light light, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Light light, GameObject obj) { var mainAuthoring = obj.AddComponent().SetItem(light); var meshAuthoring = new List(); @@ -36,12 +36,6 @@ public static ConvertedItem SetupGameObject(this Light light, GameObject obj, II meshAuthoring.Add(CreateChild(obj, LightMeshGenerator.Bulb)); meshAuthoring.Add(CreateChild(obj, LightMeshGenerator.Socket)); - if (light.SubComponent == ItemSubComponent.Mesh) { - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyMeshComponent(); - } - } - return new ConvertedItem(mainAuthoring, meshAuthoring); } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs index 3ea93962f..a7962af75 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs @@ -24,7 +24,7 @@ namespace VisualPinball.Unity { internal static class PlayfieldExtensions { - public static ConvertedItem SetupGameObject(this Table table, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Table table, GameObject obj) { obj.AddComponent().SetItem(table); obj.AddComponent(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs index 3293110a6..aa9e1b490 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Plunger/PlungerExtensions.cs @@ -29,7 +29,7 @@ internal static class PlungerExtensions { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public static ConvertedItem SetupGameObject(this Plunger plunger, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Plunger plunger, GameObject obj) { var mainAuthoring = obj.AddComponent().SetItem(plunger); var meshAuthoring = new List(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs index e2cd94596..227ade777 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveExtensions.cs @@ -25,7 +25,7 @@ namespace VisualPinball.Unity { internal static class PrimitiveExtensions { - public static ConvertedItem SetupGameObject(this Primitive primitive, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Primitive primitive, GameObject obj) { var mainAuthoring = obj.AddComponent().SetItem(primitive); var meshAuthoring = new List(); @@ -40,17 +40,11 @@ public static ConvertedItem SetupGameObject(this Primitive primitive, GameObject case ItemSubComponent.Collider: { colliderAuthoring = obj.AddColliderComponent(primitive); - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyColliderComponent(); - } break; } case ItemSubComponent.Mesh: { meshAuthoring.Add(obj.AddComponent()); - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyMeshComponent(); - } break; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs index 969e19bda..a2733ed61 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Ramp/RampExtensions.cs @@ -29,7 +29,7 @@ internal static class RampExtensions { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public static ConvertedItem SetupGameObject(this Ramp ramp, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Ramp ramp, GameObject obj) { var mainAuthoring = obj.AddComponent().SetItem(ramp); var meshAuthoring = new List(); @@ -48,9 +48,6 @@ public static ConvertedItem SetupGameObject(this Ramp ramp, GameObject obj, IIte case ItemSubComponent.Collider: { colliderAuthoring = obj.AddColliderComponent(ramp); - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyColliderComponent(); - } break; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs index 7f4918ab6..8e2a57d49 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberExtensions.cs @@ -25,7 +25,7 @@ namespace VisualPinball.Unity { internal static class RubberExtensions { - public static ConvertedItem SetupGameObject(this Rubber rubber, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Rubber rubber, GameObject obj) { var mainAuthoring = obj.AddComponent().SetItem(rubber); var meshAuthoring = new List(); @@ -40,17 +40,11 @@ public static ConvertedItem SetupGameObject(this Rubber rubber, GameObject obj, case ItemSubComponent.Collider: { colliderAuthoring = obj.AddColliderComponent(rubber); - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyColliderComponent(); - } break; } case ItemSubComponent.Mesh: { meshAuthoring.Add(obj.AddComponent()); - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyMeshComponent(); - } break; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs index be8440e1b..a23f63b35 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Spinner/SpinnerExtensions.cs @@ -29,7 +29,7 @@ internal static class SpinnerExtensions { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public static ConvertedItem SetupGameObject(this Spinner spinner, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Spinner spinner, GameObject obj) { var meshAuthoring = new List(); var mainAuthoring = obj.AddComponent().SetItem(spinner); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs index 25f468d6a..3f2665cb8 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Surface/SurfaceExtensions.cs @@ -25,7 +25,7 @@ namespace VisualPinball.Unity { internal static class SurfaceExtensions { - public static ConvertedItem SetupGameObject(this Surface surface, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Surface surface, GameObject obj) { var mainAuthoring = obj.AddComponent().SetItem(surface); var meshAuthoring = new List(); @@ -40,18 +40,12 @@ public static ConvertedItem SetupGameObject(this Surface surface, GameObject obj case ItemSubComponent.Collider: { colliderAuthoring = obj.AddColliderComponent(surface); - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyColliderComponent(); - } break; } case ItemSubComponent.Mesh: { meshAuthoring.Add(CreateChild(obj, SurfaceMeshGenerator.Side)); meshAuthoring.Add(CreateChild(obj, SurfaceMeshGenerator.Top)); - if (parentAuthoring != null && parentAuthoring is IItemMainAuthoring parentMainAuthoring) { - parentMainAuthoring.DestroyMeshComponent(); - } break; } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs index d2ea51632..30968312f 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trigger/TriggerExtensions.cs @@ -29,7 +29,7 @@ internal static class TriggerExtensions { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public static ConvertedItem SetupGameObject(this Trigger trigger, GameObject obj, IItemMainAuthoring parentAuthoring) + public static ConvertedItem SetupGameObject(this Trigger trigger, GameObject obj) { var mainAuthoring = obj.AddComponent().SetItem(trigger); var meshAuthoring = new List(); From a79b0dac2099b478876d0a3dd3c551be2666fa44 Mon Sep 17 00:00:00 2001 From: freezy Date: Tue, 27 Oct 2020 22:59:36 +0100 Subject: [PATCH 116/124] fix: Various small fixes. --- VisualPinball.Engine/VPT/Rubber/Rubber.cs | 2 +- .../VisualPinball.Unity/VPT/ItemAuthoring.cs | 2 - .../VPT/ItemMainAuthoring.cs | 39 ++++++++++--------- .../VPT/Playfield/PlayfieldAuthoring.cs | 6 +-- .../VPT/Rubber/RubberAuthoring.cs | 2 - 5 files changed, 23 insertions(+), 28 deletions(-) diff --git a/VisualPinball.Engine/VPT/Rubber/Rubber.cs b/VisualPinball.Engine/VPT/Rubber/Rubber.cs index 85aa94ca9..6ae41f93f 100644 --- a/VisualPinball.Engine/VPT/Rubber/Rubber.cs +++ b/VisualPinball.Engine/VPT/Rubber/Rubber.cs @@ -66,7 +66,7 @@ public static Rubber GetDefault(Table.Table table) #region IRenderable - Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => _meshGenerator.GetPostMatrix(table, origin); + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) => Matrix3D.Identity; public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs index 6ac1ac491..6d35288f3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemAuthoring.cs @@ -66,8 +66,6 @@ public abstract class ItemAuthoring : MonoBehaviour /// public ItemData ItemData => Data; - public string ItemType => Item.ItemName; - public bool IsLocked { get => Data.IsLocked; set => Data.IsLocked = value; } private Table _table; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs index f7f50bce5..a6f0ca4b0 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs @@ -26,12 +26,29 @@ public abstract class ItemMainAuthoring : ItemAuthoring true; + /// + /// List of types for parenting. Empty list if only to own parent. + /// public abstract IEnumerable ValidParents { get; } - public virtual void Restore() - { - // todo make abstract - } + /// + /// Authoring type of the child class. + /// + protected abstract Type MeshAuthoringType { get; } + + protected abstract Type ColliderAuthoringType { get; } + + /// + /// Instantiates a new item based on the item data. + /// + /// Item data + /// New item instance + protected abstract TItem InstantiateItem(TData data); + + /// + /// Applies the GameObject data to the item data. typically name and visibility. + /// + public abstract void Restore(); /// /// The serialized data, as written to the .vpx file. @@ -137,20 +154,6 @@ public void DestroyColliderComponent() } } - /// - /// Authoring type of the child class. - /// - protected abstract Type MeshAuthoringType { get; } - - protected abstract Type ColliderAuthoringType { get; } - - /// - /// Instantiates a new item based on the item data. - /// - /// Item data - /// New item instance - protected abstract TItem InstantiateItem(TData data); - protected void Convert(Entity entity, EntityManager dstManager) { Item.Index = entity.Index; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs index 3c754b7a6..8c79a9c4e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs @@ -27,13 +27,9 @@ namespace VisualPinball.Unity public class PlayfieldAuthoring : ItemMainAuthoring, IConvertGameObjectToEntity { - public IRenderable Renderable => Table; - - public IHittable Hittable => Table; - public override bool CanBeTransformed => false; - protected override Table InstantiateItem(TableData data) => throw new InvalidOperationException("Table is not instantiated via authoring component."); + protected override Table InstantiateItem(TableData data) => GetComponentInParent().Table; protected override Type MeshAuthoringType { get; } = null; protected override Type ColliderAuthoringType { get; } = null; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs index 36716bf2c..39309549b 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs @@ -45,8 +45,6 @@ public class RubberAuthoring : ItemMainAuthoring, .Concat(RubberMeshAuthoring.ValidParentTypes) .Distinct(); - public IHittable Hittable => Item; - private void OnDestroy() { if (!Application.isPlaying) { From 33e3e9bd3042c02e2a4d887633731d7a0c00bd34 Mon Sep 17 00:00:00 2001 From: freezy Date: Tue, 27 Oct 2020 23:24:01 +0100 Subject: [PATCH 117/124] components: Don't parent on import if parenting isn't supported. --- .../Import/VpxConverter.cs | 30 ++++++++++++++----- .../VPT/IItemMainAuthoring.cs | 6 ++++ .../VPT/ItemMainAuthoring.cs | 5 ++++ 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index 361a833e6..ac7a14e5d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -151,16 +151,25 @@ orderby renderable.SubComponent var convertedItem = CreateGameObjects(_table, renderable, _parents[renderable.ItemGroupName]); - if (convertedItem.MeshAuthoring.Any()) { - parent.DestroyMeshComponent(); - } - if (convertedItem.ColliderAuthoring != null) { - parent.DestroyColliderComponent(); - } + if (convertedItem.IsValidChild(parent)) { + + if (convertedItem.MeshAuthoring.Any()) { + parent.DestroyMeshComponent(); + } + if (convertedItem.ColliderAuthoring != null) { + parent.DestroyColliderComponent(); + } + convertedItem.MainAuthoring.gameObject.transform.SetParent(parent.MainAuthoring.gameObject.transform, false); + convertedItems[lookupName] = convertedItem; + + } else { - convertedItem.MainAuthoring.gameObject.transform.SetParent(parent.MainAuthoring.gameObject.transform, false); + // invalid parenting, re-convert the item, because it returned only the sub component. + convertedItems[lookupName] = CreateGameObjects(_table, renderable, _parents[renderable.ItemGroupName]); - convertedItems[lookupName] = convertedItem; + // ..and destroy the other one + convertedItem.MainAuthoring.Destroy(); + } } else { Logger.Warn($"Cannot find component \"{parentName}\" that is supposed to be the parent of \"{renderable.Name}\"."); @@ -294,5 +303,10 @@ public void DestroyColliderComponent() MainAuthoring.DestroyColliderComponent(); ColliderAuthoring = null; } + + public bool IsValidChild(ConvertedItem parent) + { + return MainAuthoring.ValidParents.Contains(parent.MainAuthoring.GetType()); + } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs index 539060c29..fd4d4389e 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMainAuthoring.cs @@ -14,6 +14,8 @@ // 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 UnityEngine; namespace VisualPinball.Unity @@ -24,6 +26,8 @@ public interface IItemMainAuthoring : IItemAuthoring bool CanBeTransformed { get; } + IEnumerable ValidParents { get; } + GameObject gameObject { get; } /// @@ -31,6 +35,8 @@ public interface IItemMainAuthoring : IItemAuthoring /// void SetMeshDirty(); void RebuildMeshIfDirty(); + + void Destroy(); void DestroyMeshComponent(); void DestroyColliderComponent(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs index a6f0ca4b0..3ac898b52 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemMainAuthoring.cs @@ -122,6 +122,11 @@ public void RebuildMeshIfDirty() } } + public void Destroy() + { + DestroyImmediate(gameObject); + } + public void DestroyMeshComponent() { foreach (var component in MeshComponents) { From eb95008f3d956fd1314aab4abad8040aab148c4d Mon Sep 17 00:00:00 2001 From: freezy Date: Tue, 27 Oct 2020 23:47:50 +0100 Subject: [PATCH 118/124] components: Properely unparent when parenting isn't supported. --- VisualPinball.Engine/Game/IRenderable.cs | 2 ++ VisualPinball.Engine/VPT/Item.cs | 7 +++++++ .../VisualPinball.Unity/Import/VpxConverter.cs | 10 ++++++++-- .../VisualPinball.Unity/VPT/Bumper/BumperExtensions.cs | 4 ++-- .../VPT/Flipper/FlipperExtensions.cs | 4 ++-- .../VisualPinball.Unity/VPT/Gate/GateExtensions.cs | 4 ++-- .../VPT/HitTarget/HitTargetExtensions.cs | 4 ++-- .../VisualPinball.Unity/VPT/Kicker/KickerExtensions.cs | 4 ++-- .../VPT/Plunger/PlungerExtensions.cs | 4 ++-- .../VisualPinball.Unity/VPT/Ramp/RampExtensions.cs | 2 +- .../VPT/Spinner/SpinnerExtensions.cs | 4 ++-- .../VPT/Trigger/TriggerExtensions.cs | 4 ++-- 12 files changed, 34 insertions(+), 19 deletions(-) diff --git a/VisualPinball.Engine/Game/IRenderable.cs b/VisualPinball.Engine/Game/IRenderable.cs index e65565ffe..ae7819ac9 100644 --- a/VisualPinball.Engine/Game/IRenderable.cs +++ b/VisualPinball.Engine/Game/IRenderable.cs @@ -31,5 +31,7 @@ public interface IRenderable : IItem Vertex3D Position { get; set; } float RotationY { get; set; } + + void DisableSubComponent(); } } diff --git a/VisualPinball.Engine/VPT/Item.cs b/VisualPinball.Engine/VPT/Item.cs index 1d164497d..34de7558e 100644 --- a/VisualPinball.Engine/VPT/Item.cs +++ b/VisualPinball.Engine/VPT/Item.cs @@ -62,6 +62,13 @@ protected Item(TData data) (ComponentName, SubComponent, SubName) = SplitName(); } + public void DisableSubComponent() + { + ComponentName = Name; + SubComponent = ItemSubComponent.None; + SubName = null; + } + private (string, ItemSubComponent, string) SplitName() { var names = Name.Split(new[] {'_'}, 3, StringSplitOptions.None); diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index ac7a14e5d..2c40d4fea 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -150,7 +150,6 @@ orderby renderable.SubComponent } var convertedItem = CreateGameObjects(_table, renderable, _parents[renderable.ItemGroupName]); - if (convertedItem.IsValidChild(parent)) { if (convertedItem.MeshAuthoring.Any()) { @@ -164,11 +163,13 @@ orderby renderable.SubComponent } else { + renderable.DisableSubComponent(); + // invalid parenting, re-convert the item, because it returned only the sub component. convertedItems[lookupName] = CreateGameObjects(_table, renderable, _parents[renderable.ItemGroupName]); // ..and destroy the other one - convertedItem.MainAuthoring.Destroy(); + convertedItem.Destroy(); } } else { @@ -292,6 +293,11 @@ public ConvertedItem(IItemMainAuthoring mainAuthoring, IEnumerable Date: Wed, 28 Oct 2020 00:12:28 +0100 Subject: [PATCH 119/124] component: Fix parented collider position. --- .../VisualPinball.Unity/Import/VpxConverter.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index 2c40d4fea..b75cb2dba 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -143,16 +143,17 @@ orderby renderable.SubComponent if (convertedItems.ContainsKey(parentName)) { var parent = convertedItems[parentName]; + var convertedItem = CreateGameObjects(_table, renderable, _parents[renderable.ItemGroupName]); + if (convertedItem.IsValidChild(parent)) { + + if (convertedItem.MeshAuthoring.Any()) { + // move and rotate into parent if (parent.MainAuthoring.IItem is IRenderable parentRenderable) { renderable.Position.Sub(parentRenderable.Position); renderable.RotationY -= parentRenderable.RotationY; } - var convertedItem = CreateGameObjects(_table, renderable, _parents[renderable.ItemGroupName]); - if (convertedItem.IsValidChild(parent)) { - - if (convertedItem.MeshAuthoring.Any()) { parent.DestroyMeshComponent(); } if (convertedItem.ColliderAuthoring != null) { From 7a622bc7ed2135cdfbecacd3b4f036cb48086e56 Mon Sep 17 00:00:00 2001 From: freezy Date: Wed, 28 Oct 2020 00:13:19 +0100 Subject: [PATCH 120/124] components: Allow primitive colliders to be parented to primitives. --- .../VPT/Primitive/PrimitiveColliderAuthoring.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderAuthoring.cs index 1aef16448..7318862a3 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Primitive/PrimitiveColliderAuthoring.cs @@ -25,6 +25,7 @@ namespace VisualPinball.Unity public class PrimitiveColliderAuthoring : ItemColliderAuthoring { public static readonly Type[] ValidParentTypes = { + typeof(PrimitiveAuthoring), typeof(RubberAuthoring), typeof(SurfaceAuthoring) }; From 0c1d6478a40ffe9bac8a9dbc3e2dff7606e9d697 Mon Sep 17 00:00:00 2001 From: freezy Date: Wed, 28 Oct 2020 00:25:21 +0100 Subject: [PATCH 121/124] components: Check sub components when validating parenting. --- VisualPinball.Engine/VPT/Table/Table.cs | 3 +++ .../VisualPinball.Unity/Import/VpxConverter.cs | 18 +++++++++++++----- .../VPT/IItemColliderAuthoring.cs | 5 +++++ .../VPT/IItemMeshAuthoring.cs | 3 +++ 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/VisualPinball.Engine/VPT/Table/Table.cs b/VisualPinball.Engine/VPT/Table/Table.cs index e96883fe3..81f8735e8 100644 --- a/VisualPinball.Engine/VPT/Table/Table.cs +++ b/VisualPinball.Engine/VPT/Table/Table.cs @@ -440,6 +440,9 @@ public string GetNewName(string prefix) where T : IItem public void Remove(string name) where T : IItem { var dict = GetItemDictionary(); + if (!dict.ContainsKey(name)) { + return; + } var removedStorageIndex = dict[name].StorageIndex; var gameItems = ItemDatas; foreach (var gameItem in gameItems) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index b75cb2dba..280569bcd 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -148,11 +148,11 @@ orderby renderable.SubComponent if (convertedItem.MeshAuthoring.Any()) { - // move and rotate into parent - if (parent.MainAuthoring.IItem is IRenderable parentRenderable) { - renderable.Position.Sub(parentRenderable.Position); - renderable.RotationY -= parentRenderable.RotationY; - } + // move and rotate into parent + if (parent.MainAuthoring.IItem is IRenderable parentRenderable) { + renderable.Position.Sub(parentRenderable.Position); + renderable.RotationY -= parentRenderable.RotationY; + } parent.DestroyMeshComponent(); } @@ -313,6 +313,14 @@ public void DestroyColliderComponent() public bool IsValidChild(ConvertedItem parent) { + if (MeshAuthoring.Any()) { + return MeshAuthoring.First().ValidParents.Contains(parent.MainAuthoring.GetType()); + } + + if (ColliderAuthoring != null) { + return ColliderAuthoring.ValidParents.Contains(parent.MainAuthoring.GetType()); + } + return MainAuthoring.ValidParents.Contains(parent.MainAuthoring.GetType()); } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs index ad7574a9a..c09ace1bf 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemColliderAuthoring.cs @@ -14,10 +14,15 @@ // 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; + namespace VisualPinball.Unity { public interface IItemColliderAuthoring : IItemAuthoring { IItemMainAuthoring MainAuthoring { get; } + + IEnumerable ValidParents { get; } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs index 9ee6533a6..0214a4392 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/IItemMeshAuthoring.cs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; using System.Collections.Generic; using System.Reflection; using UnityEngine; @@ -32,5 +33,7 @@ public interface IItemMeshAuthoring : IItemAuthoring GameObject gameObject { get; } void RebuildMeshes(); + + IEnumerable ValidParents { get; } } } From ce806bbfd6713a769f387a2b1fde44aaf982cf85 Mon Sep 17 00:00:00 2001 From: freezy Date: Wed, 28 Oct 2020 00:26:04 +0100 Subject: [PATCH 122/124] chore: Fix imports. --- VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs | 1 - .../VisualPinball.Unity/VPT/Light/LightExtensions.cs | 1 - .../VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs | 1 - .../VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs | 1 - .../VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs | 1 - 5 files changed, 5 deletions(-) diff --git a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs index 280569bcd..3a9b0a0bf 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Import/VpxConverter.cs @@ -22,7 +22,6 @@ using System.Collections.Generic; using System.Linq; using NLog; -using NLog.Targets.Wrappers; using UnityEngine; using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs index 94a1dda37..4e5889da5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Light/LightExtensions.cs @@ -16,7 +16,6 @@ using System.Collections.Generic; using UnityEngine; -using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Light; using Light = VisualPinball.Engine.VPT.Light.Light; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs index 8c79a9c4e..342fd16e4 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldAuthoring.cs @@ -18,7 +18,6 @@ using System.Collections.Generic; using System.Linq; using Unity.Entities; -using VisualPinball.Engine.Game; using VisualPinball.Engine.VPT.Table; using VisualPinball.Unity.Playfield; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs index a7962af75..c6643a2b8 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Playfield/PlayfieldExtensions.cs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -using System.Collections.Generic; using Unity.Entities; using UnityEngine; using VisualPinball.Engine.VPT.Table; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs index 39309549b..b272f8713 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Rubber/RubberAuthoring.cs @@ -25,7 +25,6 @@ using System.Linq; using Unity.Entities; using UnityEngine; -using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; using VisualPinball.Engine.VPT.Rubber; From acb200ad4d0edef4823020e67b5a7d9e69603718 Mon Sep 17 00:00:00 2001 From: Eli Curtz Date: Tue, 27 Oct 2020 17:23:13 -0700 Subject: [PATCH 123/124] Generic inspector field for references between ItemAuthoring ocmponents. --- VisualPinball.Engine/VPT/Trough/Trough.cs | 2 +- .../Inspectors/ItemInspector.cs | 27 ++++++++++++------- .../Inspectors/TroughInspector.cs | 4 ++- .../VPT/Trough/TroughAuthoring.cs | 5 ++-- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/VisualPinball.Engine/VPT/Trough/Trough.cs b/VisualPinball.Engine/VPT/Trough/Trough.cs index 4ab5bb8e2..a3172cc71 100644 --- a/VisualPinball.Engine/VPT/Trough/Trough.cs +++ b/VisualPinball.Engine/VPT/Trough/Trough.cs @@ -33,7 +33,7 @@ public Trough(BinaryReader reader, string itemName) : this(new TroughData(reader public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) { - return null; + return new RenderObjectGroup(Data.Name, "trough", Math.Matrix3D.Identity, new RenderObject[0]); } } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/ItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/ItemInspector.cs index 523d352c0..51e44aab9 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/ItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/ItemInspector.cs @@ -18,7 +18,9 @@ using System.Linq; using UnityEditor; using UnityEngine; +using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; +using VisualPinball.Engine.VPT; using VisualPinball.Engine.VPT.Surface; namespace VisualPinball.Unity.Editor @@ -26,7 +28,7 @@ namespace VisualPinball.Unity.Editor public abstract class ItemInspector : UnityEditor.Editor { protected TableAuthoring _table; - protected SurfaceAuthoring _surface; + protected MonoBehaviour _item; protected string[] _allMaterials = new string[0]; protected string[] _allTextures = new string[0]; @@ -210,29 +212,36 @@ protected void ItemDataField(string label, ref Engine.Math.Color field, bool dir } } - protected void SurfaceField(string label, ref string field, bool dirtyMesh = true) + protected void ItemReferenceField(string label, ref string field, bool dirtyMesh = true) + where TItemAuthoring : ItemAuthoring + where TData : ItemData where TItem : Item, IRenderable { - if (_surface?.name != field) { - _surface = null; + if (_item?.name != field) { + _item = null; } var mb = target as MonoBehaviour; - if (_surface == null && _table != null) { + if (_item == null && _table != null) { string currentFieldName = field; - if (currentFieldName != null && _table.Table.Has(currentFieldName)) { - _surface = _table.gameObject.GetComponentsInChildren(true) + if (currentFieldName != null && _table.Table.Has(currentFieldName)) { + _item = _table.gameObject.GetComponentsInChildren(true) .FirstOrDefault(s => s.name == currentFieldName); } } EditorGUI.BeginChangeCheck(); - _surface = (SurfaceAuthoring)EditorGUILayout.ObjectField(label, _surface, typeof(SurfaceAuthoring), true); + _item = (TItemAuthoring)EditorGUILayout.ObjectField(label, _item, typeof(TItemAuthoring), true); if (EditorGUI.EndChangeCheck()) { FinishEdit(label, dirtyMesh); - field = _surface != null ? _surface.name : ""; + field = _item != null ? _item.name : ""; } } + protected void SurfaceField(string label, ref string field, bool dirtyMesh = true) + { + ItemReferenceField(label, ref field, dirtyMesh); + } + protected void DropDownField(string label, ref T field, string[] optionStrings, T[] optionValues, bool dirtyMesh = true) where T : IEquatable { if (optionStrings == null || optionValues == null || optionStrings.Length != optionValues.Length) { diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TroughInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TroughInspector.cs index 61fdd8cc6..ded3b4151 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TroughInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TroughInspector.cs @@ -15,6 +15,7 @@ // along with this program. If not, see . using UnityEditor; +using VisualPinball.Engine.VPT.Kicker; namespace VisualPinball.Unity.Editor { @@ -36,7 +37,8 @@ public override void OnInspectorGUI() OnPreInspectorGUI(); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - //ItemDataField("", ref _trough.data.Entrance); + ItemReferenceField("Entry Kicker", ref _trough.data.EntryKicker); + ItemReferenceField("Exit Kicker", ref _trough.data.ExitKicker); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughAuthoring.cs index ea649e115..3f4b1a730 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughAuthoring.cs @@ -33,9 +33,9 @@ namespace VisualPinball.Unity [AddComponentMenu("Visual Pinball/Trough")] public class TroughAuthoring : ItemAuthoring, IConvertGameObjectToEntity { - protected override string[] Children => new[] { "Entrance", "Exit" }; + protected override string[] Children => null; - protected override Trough GetItem() => new Trough(data); + protected override Trough GetItem() => new Trough(data); private void OnDestroy() { @@ -47,6 +47,7 @@ private void OnDestroy() public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { Convert(entity, dstManager); + dstManager.AddComponentData(entity, new TroughStaticData { BallCount = data.BallCount, From 96fa534cc8ba4aeccf14a4f7718a67fa716bea17 Mon Sep 17 00:00:00 2001 From: Eli Curtz Date: Wed, 28 Oct 2020 11:59:56 -0700 Subject: [PATCH 124/124] Post rebase cleanup of Trough classes. --- VisualPinball.Engine/VPT/Trough/Trough.cs | 23 ++++++- .../Inspectors/TroughInspector.cs | 10 +-- .../VPT/ItemInspector.cs | 5 +- .../VisualPinball.Unity/Game/Player.cs | 8 +++ .../VisualPinball.Unity/VPT/ItemApi.cs | 1 + .../VPT/Trough/TroughApi.cs | 69 +++++++++++++------ .../VPT/Trough/TroughAuthoring.cs | 36 +++++----- 7 files changed, 106 insertions(+), 46 deletions(-) diff --git a/VisualPinball.Engine/VPT/Trough/Trough.cs b/VisualPinball.Engine/VPT/Trough/Trough.cs index a3172cc71..e90437187 100644 --- a/VisualPinball.Engine/VPT/Trough/Trough.cs +++ b/VisualPinball.Engine/VPT/Trough/Trough.cs @@ -16,12 +16,17 @@ using System.IO; using VisualPinball.Engine.Game; +using VisualPinball.Engine.Math; namespace VisualPinball.Engine.VPT.Trough { public class Trough : Item, IRenderable { - public override string ItemType => "Trough"; + public override string ItemName { get; } = "Trough"; + public override string ItemGroupName { get; } = "Troughs"; + + public Vertex3D Position { get => Vertex3D.Zero; set { } } + public float RotationY { get => 0f; set { } } public Trough(TroughData data) : base(data) { @@ -29,11 +34,25 @@ public Trough(TroughData data) : base(data) public Trough(BinaryReader reader, string itemName) : this(new TroughData(reader, itemName)) { - } + } + + #region IRenderable + + Matrix3D IRenderable.TransformationMatrix(Table.Table table, Origin origin) + { + return Matrix3D.Identity; + } + + public RenderObject GetRenderObject(Table.Table table, string id = null, Origin origin = Origin.Global, bool asRightHanded = true) + { + return null; + } public RenderObjectGroup GetRenderObjects(Table.Table table, Origin origin = Origin.Global, bool asRightHanded = true) { return new RenderObjectGroup(Data.Name, "trough", Math.Matrix3D.Identity, new RenderObject[0]); } + + #endregion } } diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TroughInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TroughInspector.cs index ded3b4151..6ed6d0188 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TroughInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/Inspectors/TroughInspector.cs @@ -37,15 +37,15 @@ public override void OnInspectorGUI() OnPreInspectorGUI(); if (_foldoutPosition = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutPosition, "Position")) { - ItemReferenceField("Entry Kicker", ref _trough.data.EntryKicker); - ItemReferenceField("Exit Kicker", ref _trough.data.ExitKicker); + ItemReferenceField("Entry Kicker", ref _trough.Data.EntryKicker); + ItemReferenceField("Exit Kicker", ref _trough.Data.ExitKicker); } EditorGUILayout.EndFoldoutHeaderGroup(); if (_foldoutMisc = EditorGUILayout.BeginFoldoutHeaderGroup(_foldoutMisc, "Misc")) { - ItemDataField("Max Balls", ref _trough.data.BallCount, dirtyMesh: false); - ItemDataField("Switch Count", ref _trough.data.SwitchCount, dirtyMesh: false); - ItemDataField("Settle Time", ref _trough.data.SettleTime, dirtyMesh: false); + ItemDataField("Max Balls", ref _trough.Data.BallCount, dirtyMesh: false); + ItemDataField("Switch Count", ref _trough.Data.SwitchCount, dirtyMesh: false); + ItemDataField("Settle Time", ref _trough.Data.SettleTime, dirtyMesh: false); } EditorGUILayout.EndFoldoutHeaderGroup(); diff --git a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs index ab7089ae0..0ad034ced 100644 --- a/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs +++ b/VisualPinball.Unity/VisualPinball.Unity.Editor/VPT/ItemInspector.cs @@ -21,13 +21,14 @@ using VisualPinball.Engine.Game; using VisualPinball.Engine.Math; using VisualPinball.Engine.VPT; +using VisualPinball.Engine.VPT.Surface; namespace VisualPinball.Unity.Editor { public abstract class ItemInspector : UnityEditor.Editor { private TableAuthoring _table; - private SurfaceAuthoring _surface; + private MonoBehaviour _item; private string[] _allMaterials = new string[0]; private string[] _allTextures = new string[0]; @@ -238,7 +239,7 @@ protected void ItemDataField(string label, ref Engine.Math.Color field, bool dir } protected void ItemReferenceField(string label, ref string field, bool dirtyMesh = true) - where TItemAuthoring : ItemAuthoring + where TItemAuthoring : ItemMainAuthoring where TData : ItemData where TItem : Item, IRenderable { if (_item?.name != field) { diff --git a/VisualPinball.Unity/VisualPinball.Unity/Game/Player.cs b/VisualPinball.Unity/VisualPinball.Unity/Game/Player.cs index 749418438..742cf15a5 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/Game/Player.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/Game/Player.cs @@ -37,6 +37,7 @@ using VisualPinball.Engine.VPT.Surface; using VisualPinball.Engine.VPT.Table; using VisualPinball.Engine.VPT.Trigger; +using VisualPinball.Engine.VPT.Trough; using Logger = NLog.Logger; namespace VisualPinball.Unity @@ -44,6 +45,7 @@ namespace VisualPinball.Unity public class Player : MonoBehaviour { public Table Table { get; private set; } + public TableApi TableApi { get { return _tableApi; } } // shortcuts public Matrix4x4 TableToWorld => transform.localToWorldMatrix; @@ -258,6 +260,12 @@ public void RegisterTrigger(Trigger trigger, Entity entity, GameObject go) _switches[trigger.Name] = triggerApi; } + public void RegisterTrough(Trough trough, Entity entity, GameObject go) + { + var troughApi = new TroughApi(trough, entity, this); + _initializables.Add(troughApi); + } + #endregion #region Mapping diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemApi.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemApi.cs index 032aa22e8..41845acfc 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemApi.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/ItemApi.cs @@ -30,6 +30,7 @@ public abstract class ItemApi : IApi where T : Item where TData protected TData Data => Item.Data; protected Table Table => _player.Table; + protected TableApi TableApi => _player.TableApi; protected readonly EntityManager EntityManager = World.DefaultGameObjectInjectionWorld.EntityManager; diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughApi.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughApi.cs index ea02d49af..4ef9cee08 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughApi.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughApi.cs @@ -14,30 +14,57 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -using System; -using Unity.Entities; - -namespace VisualPinball.Unity -{ - public class TroughApi : ItemApi, - IApiInitializable +using System; +using Unity.Entities; +using VisualPinball.Engine.VPT.Trough; + +namespace VisualPinball.Unity +{ + public class TroughApi : ItemApi, + IApiInitializable { - /// - /// Event emitted when the table is started. - /// + private KickerApi _entryKicker; + private KickerApi _exitKicker; + + /// + /// Event emitted when the table is started. + /// public event EventHandler Init; - - internal TroughApi(Engine.VPT.Trough.Trough item, Entity entity, Player player) : base(item, entity, player) - { + + internal TroughApi(Trough item, Entity entity, Player player) : base(item, entity, player) + { } - #region Events + #region Events + + void IApiInitializable.OnInit(BallManager ballManager) + { + _entryKicker = TableApi.Kicker(Data.EntryKicker); + _exitKicker = TableApi.Kicker(Data.ExitKicker); - void IApiInitializable.OnInit(BallManager ballManager) - { - Init?.Invoke(this, EventArgs.Empty); - } + if (_entryKicker != null) + { + _entryKicker.Hit += OnEntryKickerHit; + } + + if (_exitKicker != null) + { + _exitKicker.Hit += OnExitKickerFire; + } + + Init?.Invoke(this, EventArgs.Empty); + } + + void OnEntryKickerHit(object sender, EventArgs args) + { + (sender as KickerApi)?.DestroyBall(); + } + + void OnExitKickerFire(object sender, EventArgs args) + { + (sender as KickerApi)?.CreateBall(); + } - #endregion - } -} + #endregion + } +} diff --git a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughAuthoring.cs b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughAuthoring.cs index 3f4b1a730..bba2c920d 100644 --- a/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughAuthoring.cs +++ b/VisualPinball.Unity/VisualPinball.Unity/VPT/Trough/TroughAuthoring.cs @@ -20,29 +20,24 @@ // ReSharper disable MemberCanBePrivate.Global #endregion +using System; using System.Collections.Generic; using Unity.Entities; using UnityEngine; -using VisualPinball.Engine.Game; -using VisualPinball.Engine.Math; using VisualPinball.Engine.VPT.Trough; namespace VisualPinball.Unity { [ExecuteAlways] [AddComponentMenu("Visual Pinball/Trough")] - public class TroughAuthoring : ItemAuthoring, IConvertGameObjectToEntity + public class TroughAuthoring : ItemMainAuthoring, IConvertGameObjectToEntity { - protected override string[] Children => null; - - protected override Trough GetItem() => new Trough(data); - - private void OnDestroy() - { - if (!Application.isPlaying) { - Table?.Remove(Name); - } - } + protected override Trough InstantiateItem(TroughData data) => new Trough(data); + + protected override Type MeshAuthoringType { get; } = null; + protected override Type ColliderAuthoringType { get; } = null; + + public override IEnumerable ValidParents => new Type[0]; public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { @@ -50,10 +45,19 @@ public void Convert(Entity entity, EntityManager dstManager, GameObjectConversio dstManager.AddComponentData(entity, new TroughStaticData { - BallCount = data.BallCount, - SwitchCount = data.SwitchCount, - SettleTime = data.SettleTime + BallCount = Data.BallCount, + SwitchCount = Data.SwitchCount, + SettleTime = Data.SettleTime }); + + // register + transform.GetComponentInParent().RegisterTrough(Item, entity, gameObject); + } + + public override void Restore() + { + // update the name + Item.Name = name; } //public override ItemDataTransformType EditorPositionType => ItemDataTransformType.TwoD;