From 4f80fc678a07f679bdeb30ffb181dce9c5752884 Mon Sep 17 00:00:00 2001 From: Henry de Jongh Date: Thu, 25 Jan 2018 14:17:05 +0100 Subject: [PATCH 1/4] Additional Features for Curved Staircase Compound Brushes: Added "Fill To Bottom" identical to the linear staircases. Added "Build Torus" to easily build walls around curved staircases. Fixed the normals for "Counter Clockwise" mode. Updated the inspector to use more of a SabreCSG theme. Moved some identical copy and pasted code into separate functions. --- .../CompoundBrushes/CurvedStairBrush.cs | 180 +++++++++++++----- .../Editor/CurvedStairBrushInspector.cs | 41 +++- 2 files changed, 162 insertions(+), 59 deletions(-) diff --git a/Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs b/Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs index 65f374f0..242cb829 100644 --- a/Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs +++ b/Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs @@ -42,6 +42,14 @@ public class CurvedStairBrush : CompoundBrush [SerializeField] bool counterClockwise = false; + /// Whether the stairs reach down to the bottom. + [SerializeField] + bool fillToBottom = true; + + /// Whether to generate stairs or a torus shape. + [SerializeField] + bool buildTorus = false; + /// The last known extents of the compound brush to detect user resizing the bounds. private Vector3 m_LastKnownExtents; /// The last known position of the compound brush to prevent movement on resizing the bounds. @@ -102,7 +110,6 @@ public override void Invalidate (bool polygonsChanged) // local variables List vertexPositions = new List(); - Plane plane; Vector3 rotateStep = new Vector3(); Vector3 vertex = new Vector3(), newVertex = new Vector3(); float adjustment; @@ -128,7 +135,10 @@ public override void Invalidate (bool polygonsChanged) newVertex = Quaternion.Euler(rotateStep * x) * vertex; vertexPositions.Add(new Vector3(newVertex.x, vertex.z - adjustment, newVertex.y)); - vertex.z += stepHeight; + if (buildTorus) + vertex.z = stepHeight * numSteps; + else + vertex.z += stepHeight; vertexPositions.Add(new Vector3(newVertex.x, vertex.z, newVertex.y)); } @@ -145,7 +155,10 @@ public override void Invalidate (bool polygonsChanged) newVertex = Quaternion.Euler(rotateStep * x) * vertex; vertexPositions.Add(new Vector3(newVertex.x, vertex.z - adjustment, newVertex.y)); - vertex.z += stepHeight; + if (buildTorus) + vertex.z = stepHeight * numSteps; + else + vertex.z += stepHeight; vertexPositions.Add(new Vector3(newVertex.x, vertex.z, newVertex.y)); } @@ -207,6 +220,8 @@ public override void Invalidate (bool polygonsChanged) // | Back | Left | Right | Front | Bottom | Top | // +--------+--------+--------+--------+--------+--------+ + + // retrieve the vertices of the top polygon. Vertex[] vertices = polygons[5].Vertices; @@ -216,11 +231,11 @@ public override void Invalidate (bool polygonsChanged) vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 1]; vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 2]; + // calculate a normal using a virtual plane. + GenerateNormals(polygons[3]); + // update uv coordinates to prevent distortions using barnaby's genius utilities. - vertices[index0].UV = GeometryHelper.GetUVForPosition(polygons[5], vertexPositions[outerStart + (i * 2) + 2]); - vertices[index1].UV = GeometryHelper.GetUVForPosition(polygons[5], vertexPositions[outerStart + (i * 2) + 1]); - vertices[index2].UV = GeometryHelper.GetUVForPosition(polygons[5], vertexPositions[innerStart + (i * 2) + 1]); - vertices[index3].UV = GeometryHelper.GetUVForPosition(polygons[5], vertexPositions[innerStart + (i * 2) + 2]); + GenerateUvCoordinates(polygons[5]); @@ -228,17 +243,25 @@ public override void Invalidate (bool polygonsChanged) vertices = polygons[3].Vertices; // step front. - vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 1]; - vertices[index1].Position = vertexPositions[bottomOuterStart + i]; - vertices[index2].Position = vertexPositions[bottomInnerStart + i]; - vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 1]; + if (fillToBottom) + { + // fill downwards to the bottom. + vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 1]; + vertices[index1].Position = vertexPositions[bottomOuterStart + i]; + vertices[index2].Position = vertexPositions[bottomInnerStart + i]; + vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 1]; + } + else + { + // fill downwards to the step height. + vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 1]; + vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight, 0.0f); + vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight, 0.0f); + vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 1]; + } // calculate a normal using a virtual plane. - plane = new Plane(vertices[index1].Position, vertices[index2].Position, vertices[index3].Position); - vertices[index0].Normal = plane.normal; - vertices[index1].Normal = plane.normal; - vertices[index2].Normal = plane.normal; - vertices[index3].Normal = plane.normal; + GenerateNormals(polygons[3]); @@ -246,17 +269,25 @@ public override void Invalidate (bool polygonsChanged) vertices = polygons[1].Vertices; // inner curve. - vertices[index0].Position = vertexPositions[bottomInnerStart + i + 1]; - vertices[index1].Position = vertexPositions[innerStart + (i * 2) + 2]; - vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 1]; - vertices[index3].Position = vertexPositions[bottomInnerStart + i]; + if (fillToBottom) + { + // fill downwards to the bottom. + vertices[index0].Position = vertexPositions[bottomInnerStart + i + 1]; + vertices[index1].Position = vertexPositions[innerStart + (i * 2) + 2]; + vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 1]; + vertices[index3].Position = vertexPositions[bottomInnerStart + i]; + } + else + { + // fill downwards to the step height. + vertices[index0].Position = vertexPositions[innerStart + (i * 2) + 2] - new Vector3(0.0f, stepHeight, 0.0f); + vertices[index1].Position = vertexPositions[innerStart + (i * 2) + 2]; + vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 1]; + vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight, 0.0f); + } // calculate a normal using a virtual plane. - plane = new Plane(vertices[index1].Position, vertices[index2].Position, vertices[index3].Position); - vertices[index0].Normal = plane.normal; - vertices[index1].Normal = plane.normal; - vertices[index2].Normal = plane.normal; - vertices[index3].Normal = plane.normal; + GenerateNormals(polygons[1]); @@ -264,17 +295,25 @@ public override void Invalidate (bool polygonsChanged) vertices = polygons[2].Vertices; // outer curve. - vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 2]; - vertices[index1].Position = vertexPositions[bottomOuterStart + i + 1]; - vertices[index2].Position = vertexPositions[bottomOuterStart + i]; - vertices[index3].Position = vertexPositions[outerStart + (i * 2) + 1]; + if (fillToBottom) + { + // fill downwards to the bottom. + vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 2]; + vertices[index1].Position = vertexPositions[bottomOuterStart + i + 1]; + vertices[index2].Position = vertexPositions[bottomOuterStart + i]; + vertices[index3].Position = vertexPositions[outerStart + (i * 2) + 1]; + } + else + { + // fill downwards to the step height. + vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 2]; + vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 2] - new Vector3(0.0f, stepHeight, 0.0f); + vertices[index2].Position = vertexPositions[outerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight, 0.0f); + vertices[index3].Position = vertexPositions[outerStart + (i * 2) + 1]; + } // calculate a normal using a virtual plane. - plane = new Plane(vertices[index1].Position, vertices[index2].Position, vertices[index3].Position); - vertices[index0].Normal = plane.normal; - vertices[index1].Normal = plane.normal; - vertices[index2].Normal = plane.normal; - vertices[index3].Normal = plane.normal; + GenerateNormals(polygons[2]); @@ -282,16 +321,28 @@ public override void Invalidate (bool polygonsChanged) vertices = polygons[4].Vertices; // bottom. - vertices[index0].Position = vertexPositions[bottomOuterStart + i]; - vertices[index1].Position = vertexPositions[bottomOuterStart + i + 1]; - vertices[index2].Position = vertexPositions[bottomInnerStart + i + 1]; - vertices[index3].Position = vertexPositions[bottomInnerStart + i]; + if (fillToBottom) + { + // fill downwards to the bottom. + vertices[index0].Position = vertexPositions[bottomOuterStart + i]; + vertices[index1].Position = vertexPositions[bottomOuterStart + i + 1]; + vertices[index2].Position = vertexPositions[bottomInnerStart + i + 1]; + vertices[index3].Position = vertexPositions[bottomInnerStart + i]; + } + else + { + // fill downwards to the step height. + vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight, 0.0f); + vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 2] - new Vector3(0.0f, stepHeight, 0.0f); + vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 2] - new Vector3(0.0f, stepHeight, 0.0f); + vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight, 0.0f); + } + + // calculate a normal using a virtual plane. + GenerateNormals(polygons[3]); // update uv coordinates to prevent distortions using barnaby's genius utilities. - vertices[index0].UV = GeometryHelper.GetUVForPosition(polygons[4], vertexPositions[bottomOuterStart + i]); - vertices[index1].UV = GeometryHelper.GetUVForPosition(polygons[4], vertexPositions[bottomOuterStart + i + 1]); - vertices[index2].UV = GeometryHelper.GetUVForPosition(polygons[4], vertexPositions[bottomInnerStart + i + 1]); - vertices[index3].UV = GeometryHelper.GetUVForPosition(polygons[4], vertexPositions[bottomInnerStart + i]); + GenerateUvCoordinates(polygons[4]); @@ -299,17 +350,27 @@ public override void Invalidate (bool polygonsChanged) vertices = polygons[0].Vertices; // back panel. - vertices[index0].Position = vertexPositions[bottomOuterStart + i + 1]; - vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 2]; - vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 2]; - vertices[index3].Position = vertexPositions[bottomInnerStart + i + 1]; + if (fillToBottom) + { + // fill downwards to the bottom. + vertices[index0].Position = vertexPositions[bottomOuterStart + i + 1]; + vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 2]; + vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 2]; + vertices[index3].Position = vertexPositions[bottomInnerStart + i + 1]; + } + else + { + // fill downwards to the step height. + vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 2] - new Vector3(0.0f, stepHeight, 0.0f); + vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 2]; + vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 2]; + vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 2] - new Vector3(0.0f, stepHeight, 0.0f); + } // calculate a normal using a virtual plane. - plane = new Plane(vertices[index1].Position, vertices[index2].Position, vertices[index3].Position); - vertices[index0].Normal = plane.normal; - vertices[index1].Normal = plane.normal; - vertices[index2].Normal = plane.normal; - vertices[index3].Normal = plane.normal; + GenerateNormals(polygons[0]); + + generatedBrushes[i].Invalidate(true); csgBounds.Encapsulate(generatedBrushes[i].GetBounds()); @@ -320,6 +381,23 @@ public override void Invalidate (bool polygonsChanged) m_LastKnownExtents = localBounds.extents; m_LastKnownPosition = transform.localPosition; } + + /// + /// Generates the UV coordinates for a automatically. + /// + /// The polygon to be updated. + private void GenerateUvCoordinates(Polygon polygon) + { + foreach (Vertex vertex in polygon.Vertices) + vertex.UV = GeometryHelper.GetUVForPosition(polygon, vertex.Position); + } + + private void GenerateNormals(Polygon polygon) + { + Plane plane = new Plane(polygon.Vertices[1].Position, polygon.Vertices[2].Position, polygon.Vertices[3].Position); + foreach (Vertex vertex in polygon.Vertices) + vertex.Normal = plane.normal; + } } } diff --git a/Scripts/Brushes/CompoundBrushes/Editor/CurvedStairBrushInspector.cs b/Scripts/Brushes/CompoundBrushes/Editor/CurvedStairBrushInspector.cs index dcd30aab..0dc96f58 100644 --- a/Scripts/Brushes/CompoundBrushes/Editor/CurvedStairBrushInspector.cs +++ b/Scripts/Brushes/CompoundBrushes/Editor/CurvedStairBrushInspector.cs @@ -18,6 +18,8 @@ public class CurvedStairBrushInspector : CompoundBrushInspector SerializedProperty numSteps; SerializedProperty addToFirstStep; SerializedProperty counterClockwise; + SerializedProperty fillToBottom; + SerializedProperty buildTorus; protected override void OnEnable() { @@ -30,12 +32,16 @@ protected override void OnEnable() numSteps = serializedObject.FindProperty("numSteps"); addToFirstStep = serializedObject.FindProperty("addToFirstStep"); counterClockwise = serializedObject.FindProperty("counterClockwise"); + fillToBottom = serializedObject.FindProperty("fillToBottom"); + buildTorus = serializedObject.FindProperty("buildTorus"); } public override void OnInspectorGUI() { using (new NamedVerticalScope("Curved Stair")) { + bool oldBool; + EditorGUI.BeginChangeCheck(); { EditorGUILayout.PropertyField(innerRadius); @@ -75,17 +81,36 @@ public override void OnInspectorGUI() if (EditorGUI.EndChangeCheck()) ApplyAndInvalidate(); - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(addToFirstStep); - if (addToFirstStep.floatValue < 0.0f) - addToFirstStep.floatValue = 0.0f; - if (EditorGUI.EndChangeCheck()) + // can only use additional height if fill to bottom is enabled. + if (fillToBottom.boolValue) + { + EditorGUI.BeginChangeCheck(); + EditorGUILayout.PropertyField(addToFirstStep); + if (addToFirstStep.floatValue < 0.0f) + addToFirstStep.floatValue = 0.0f; + if (EditorGUI.EndChangeCheck()) + ApplyAndInvalidate(); + } + + EditorGUILayout.Space(); + + EditorGUILayout.BeginHorizontal(); + + counterClockwise.boolValue = GUILayout.Toggle(oldBool = counterClockwise.boolValue, "Counter Clockwise", EditorStyles.toolbarButton); + if (counterClockwise.boolValue != oldBool) ApplyAndInvalidate(); - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(counterClockwise); - if (EditorGUI.EndChangeCheck()) + fillToBottom.boolValue = GUILayout.Toggle(oldBool = fillToBottom.boolValue, "Fill To Bottom", EditorStyles.toolbarButton); + if (fillToBottom.boolValue != oldBool) ApplyAndInvalidate(); + + buildTorus.boolValue = GUILayout.Toggle(oldBool = buildTorus.boolValue, "Build Torus", EditorStyles.toolbarButton); + if (buildTorus.boolValue != oldBool) + ApplyAndInvalidate(); + + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.Space(); } base.OnInspectorGUI(); From 8b946bf171ae1d4260b19a9bfdeda253ee2bf42c Mon Sep 17 00:00:00 2001 From: Henry de Jongh Date: Fri, 26 Jan 2018 00:33:22 +0100 Subject: [PATCH 2/4] Additional Features for Curved Staircase Compound Brushes: Added sloped floor to build beautiful ramps. Fixed the normals for "Counter Clockwise" mode. Improved the automatic UV mapping. --- .../CompoundBrushes/CurvedStairBrush.cs | 63 +++++++++++++++++-- .../Editor/CurvedStairBrushInspector.cs | 22 ++++++- 2 files changed, 76 insertions(+), 9 deletions(-) diff --git a/Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs b/Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs index 242cb829..933b6bba 100644 --- a/Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs +++ b/Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs @@ -50,6 +50,10 @@ public class CurvedStairBrush : CompoundBrush [SerializeField] bool buildTorus = false; + /// Whether the floor is stairs or a smooth slope. + [SerializeField] + bool slopedFloor = false; + /// The last known extents of the compound brush to detect user resizing the bounds. private Vector3 m_LastKnownExtents; /// The last known position of the compound brush to prevent movement on resizing the bounds. @@ -196,6 +200,13 @@ public override void Invalidate (bool polygonsChanged) index3 = 3; } + // we force NoCSG mode if special NoCSG operators are used. + if (buildTorus) slopedFloor = false; + if (slopedFloor) + { + this.IsNoCSG = true; + } + // we calculate the bounds of the output csg. Bounds csgBounds = new Bounds(); @@ -226,13 +237,25 @@ public override void Invalidate (bool polygonsChanged) Vertex[] vertices = polygons[5].Vertices; // step top. - vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 2]; - vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 1]; - vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 1]; - vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 2]; + if (slopedFloor) + { + // create a smooth slope. + vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 2 + 1]; + vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 1]; + vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 1]; + vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 2 + 1]; + } + else + { + // create blocky stairs. + vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 2]; + vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 1]; + vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 1]; + vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 2]; + } // calculate a normal using a virtual plane. - GenerateNormals(polygons[3]); + GenerateNormals(polygons[5]); // update uv coordinates to prevent distortions using barnaby's genius utilities. GenerateUvCoordinates(polygons[5]); @@ -263,6 +286,9 @@ public override void Invalidate (bool polygonsChanged) // calculate a normal using a virtual plane. GenerateNormals(polygons[3]); + // update uv coordinates to prevent distortions using barnaby's genius utilities. + GenerateUvCoordinates(polygons[3]); + // retrieve the vertices of the left polygon. @@ -285,10 +311,18 @@ public override void Invalidate (bool polygonsChanged) vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 1]; vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight, 0.0f); } + if (slopedFloor) + { + // create a smooth slope. + vertices[index1].Position = vertexPositions[innerStart + (i * 2) + 2 + 1]; + } // calculate a normal using a virtual plane. GenerateNormals(polygons[1]); + // update uv coordinates to prevent distortions using barnaby's genius utilities. + GenerateUvCoordinates(polygons[1]); + // retrieve the vertices of the right polygon. @@ -311,10 +345,18 @@ public override void Invalidate (bool polygonsChanged) vertices[index2].Position = vertexPositions[outerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight, 0.0f); vertices[index3].Position = vertexPositions[outerStart + (i * 2) + 1]; } + if (slopedFloor) + { + // create a smooth slope. + vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 2 + 1]; + } // calculate a normal using a virtual plane. GenerateNormals(polygons[2]); + // update uv coordinates to prevent distortions using barnaby's genius utilities. + GenerateUvCoordinates(polygons[2]); + // retrieve the vertices of the bottom polygon. @@ -339,7 +381,7 @@ public override void Invalidate (bool polygonsChanged) } // calculate a normal using a virtual plane. - GenerateNormals(polygons[3]); + GenerateNormals(polygons[4]); // update uv coordinates to prevent distortions using barnaby's genius utilities. GenerateUvCoordinates(polygons[4]); @@ -366,10 +408,19 @@ public override void Invalidate (bool polygonsChanged) vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 2]; vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 2] - new Vector3(0.0f, stepHeight, 0.0f); } + if (slopedFloor) + { + // create a smooth slope. + vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 2 + 1]; + vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 2 + 1]; + } // calculate a normal using a virtual plane. GenerateNormals(polygons[0]); + // update uv coordinates to prevent distortions using barnaby's genius utilities. + GenerateUvCoordinates(polygons[0]); + generatedBrushes[i].Invalidate(true); diff --git a/Scripts/Brushes/CompoundBrushes/Editor/CurvedStairBrushInspector.cs b/Scripts/Brushes/CompoundBrushes/Editor/CurvedStairBrushInspector.cs index 0dc96f58..0a606b55 100644 --- a/Scripts/Brushes/CompoundBrushes/Editor/CurvedStairBrushInspector.cs +++ b/Scripts/Brushes/CompoundBrushes/Editor/CurvedStairBrushInspector.cs @@ -20,6 +20,7 @@ public class CurvedStairBrushInspector : CompoundBrushInspector SerializedProperty counterClockwise; SerializedProperty fillToBottom; SerializedProperty buildTorus; + SerializedProperty slopedFloor; protected override void OnEnable() { @@ -34,14 +35,15 @@ protected override void OnEnable() counterClockwise = serializedObject.FindProperty("counterClockwise"); fillToBottom = serializedObject.FindProperty("fillToBottom"); buildTorus = serializedObject.FindProperty("buildTorus"); + slopedFloor = serializedObject.FindProperty("slopedFloor"); } public override void OnInspectorGUI() { + bool oldBool; + using (new NamedVerticalScope("Curved Stair")) { - bool oldBool; - EditorGUI.BeginChangeCheck(); { EditorGUILayout.PropertyField(innerRadius); @@ -109,8 +111,22 @@ public override void OnInspectorGUI() ApplyAndInvalidate(); EditorGUILayout.EndHorizontal(); + } - EditorGUILayout.Space(); + // can only use nocsg slopes if build torus is disabled. + if (!buildTorus.boolValue) + { + using (new NamedVerticalScope("Curved Stair: NoCSG Operators")) + { + if (slopedFloor.boolValue) + { + EditorGUILayout.HelpBox("The surface of the slope is non-planar. This means there are triangulated bumpy seams (look closely with your camera). NoCSG will be forced for this compound brush as the CSG engine cannot handle this shape properly.", MessageType.Warning); + } + + slopedFloor.boolValue = GUILayout.Toggle(oldBool = slopedFloor.boolValue, "Sloped Floor", EditorStyles.toolbarButton); + if (slopedFloor.boolValue != oldBool) + ApplyAndInvalidate(); + } } base.OnInspectorGUI(); From 526fe5cf52f7e097061ba2b6b37847c3e8ee2d31 Mon Sep 17 00:00:00 2001 From: Henry de Jongh Date: Fri, 26 Jan 2018 01:09:59 +0100 Subject: [PATCH 3/4] Additional Features for Curved Staircase Compound Brushes: Added sloped ceiling to build beautiful ramps. --- .../CompoundBrushes/CurvedStairBrush.cs | 37 ++++++++++++++++--- .../Editor/CurvedStairBrushInspector.cs | 16 +++++++- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs b/Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs index 933b6bba..5ed4c435 100644 --- a/Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs +++ b/Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs @@ -54,6 +54,10 @@ public class CurvedStairBrush : CompoundBrush [SerializeField] bool slopedFloor = false; + /// Whether the ceiling is stairs or a smooth slope. + [SerializeField] + bool slopedCeiling = false; + /// The last known extents of the compound brush to detect user resizing the bounds. private Vector3 m_LastKnownExtents; /// The last known position of the compound brush to prevent movement on resizing the bounds. @@ -201,8 +205,9 @@ public override void Invalidate (bool polygonsChanged) } // we force NoCSG mode if special NoCSG operators are used. - if (buildTorus) slopedFloor = false; - if (slopedFloor) + if (buildTorus) { slopedFloor = false; slopedCeiling = false; } + if (fillToBottom) { slopedCeiling = false; } + if (slopedFloor || slopedCeiling) { this.IsNoCSG = true; } @@ -282,6 +287,12 @@ public override void Invalidate (bool polygonsChanged) vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight, 0.0f); vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 1]; } + if (slopedCeiling) + { + // create a smooth ceiling slope. + vertices[index1].Position -= new Vector3(0.0f, stepHeight, 0.0f); + vertices[index2].Position -= new Vector3(0.0f, stepHeight, 0.0f); + } // calculate a normal using a virtual plane. GenerateNormals(polygons[3]); @@ -313,9 +324,14 @@ public override void Invalidate (bool polygonsChanged) } if (slopedFloor) { - // create a smooth slope. + // create a smooth floor slope. vertices[index1].Position = vertexPositions[innerStart + (i * 2) + 2 + 1]; } + if (slopedCeiling) + { + // create a smooth ceiling slope. + vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight * 2.0f, 0.0f); + } // calculate a normal using a virtual plane. GenerateNormals(polygons[1]); @@ -347,9 +363,14 @@ public override void Invalidate (bool polygonsChanged) } if (slopedFloor) { - // create a smooth slope. + // create a smooth floor slope. vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 2 + 1]; } + if (slopedCeiling) + { + // create a smooth ceiling slope. + vertices[index2].Position = vertexPositions[outerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight * 2.0f, 0.0f); + } // calculate a normal using a virtual plane. GenerateNormals(polygons[2]); @@ -379,6 +400,12 @@ public override void Invalidate (bool polygonsChanged) vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 2] - new Vector3(0.0f, stepHeight, 0.0f); vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight, 0.0f); } + if (slopedCeiling) + { + // create a smooth ceiling slope. + vertices[index0].Position = vertexPositions[outerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight * 2.0f, 0.0f); + vertices[index3].Position = vertexPositions[innerStart + (i * 2) + 1] - new Vector3(0.0f, stepHeight * 2.0f, 0.0f); + } // calculate a normal using a virtual plane. GenerateNormals(polygons[4]); @@ -410,7 +437,7 @@ public override void Invalidate (bool polygonsChanged) } if (slopedFloor) { - // create a smooth slope. + // create a smooth floor slope. vertices[index1].Position = vertexPositions[outerStart + (i * 2) + 2 + 1]; vertices[index2].Position = vertexPositions[innerStart + (i * 2) + 2 + 1]; } diff --git a/Scripts/Brushes/CompoundBrushes/Editor/CurvedStairBrushInspector.cs b/Scripts/Brushes/CompoundBrushes/Editor/CurvedStairBrushInspector.cs index 0a606b55..cf7a03c9 100644 --- a/Scripts/Brushes/CompoundBrushes/Editor/CurvedStairBrushInspector.cs +++ b/Scripts/Brushes/CompoundBrushes/Editor/CurvedStairBrushInspector.cs @@ -21,6 +21,7 @@ public class CurvedStairBrushInspector : CompoundBrushInspector SerializedProperty fillToBottom; SerializedProperty buildTorus; SerializedProperty slopedFloor; + SerializedProperty slopedCeiling; protected override void OnEnable() { @@ -36,6 +37,7 @@ protected override void OnEnable() fillToBottom = serializedObject.FindProperty("fillToBottom"); buildTorus = serializedObject.FindProperty("buildTorus"); slopedFloor = serializedObject.FindProperty("slopedFloor"); + slopedCeiling = serializedObject.FindProperty("slopedCeiling"); } public override void OnInspectorGUI() @@ -118,14 +120,26 @@ public override void OnInspectorGUI() { using (new NamedVerticalScope("Curved Stair: NoCSG Operators")) { - if (slopedFloor.boolValue) + if (slopedFloor.boolValue || slopedCeiling.boolValue) { EditorGUILayout.HelpBox("The surface of the slope is non-planar. This means there are triangulated bumpy seams (look closely with your camera). NoCSG will be forced for this compound brush as the CSG engine cannot handle this shape properly.", MessageType.Warning); } + EditorGUILayout.BeginHorizontal(); + slopedFloor.boolValue = GUILayout.Toggle(oldBool = slopedFloor.boolValue, "Sloped Floor", EditorStyles.toolbarButton); if (slopedFloor.boolValue != oldBool) ApplyAndInvalidate(); + + // can only use ceiling slopes if it isn't filled to the bottom. + if (!fillToBottom.boolValue) + { + slopedCeiling.boolValue = GUILayout.Toggle(oldBool = slopedCeiling.boolValue, "Sloped Ceiling", EditorStyles.toolbarButton); + if (slopedCeiling.boolValue != oldBool) + ApplyAndInvalidate(); + } + + EditorGUILayout.EndHorizontal(); } } From 6c9e1d60dbab0402cb436efe8858863e158716e4 Mon Sep 17 00:00:00 2001 From: Henry de Jongh Date: Tue, 30 Jan 2018 11:04:46 +0100 Subject: [PATCH 4/4] Renamed "Build Torus" to "Curved Wall" indicating the intended usage more clearly. --- Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs | 10 +++++----- .../Editor/CurvedStairBrushInspector.cs | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs b/Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs index 5ed4c435..2fcd0819 100644 --- a/Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs +++ b/Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs @@ -46,9 +46,9 @@ public class CurvedStairBrush : CompoundBrush [SerializeField] bool fillToBottom = true; - /// Whether to generate stairs or a torus shape. + /// Whether to generate stairs or a curved wall. [SerializeField] - bool buildTorus = false; + bool curvedWall = false; /// Whether the floor is stairs or a smooth slope. [SerializeField] @@ -143,7 +143,7 @@ public override void Invalidate (bool polygonsChanged) newVertex = Quaternion.Euler(rotateStep * x) * vertex; vertexPositions.Add(new Vector3(newVertex.x, vertex.z - adjustment, newVertex.y)); - if (buildTorus) + if (curvedWall) vertex.z = stepHeight * numSteps; else vertex.z += stepHeight; @@ -163,7 +163,7 @@ public override void Invalidate (bool polygonsChanged) newVertex = Quaternion.Euler(rotateStep * x) * vertex; vertexPositions.Add(new Vector3(newVertex.x, vertex.z - adjustment, newVertex.y)); - if (buildTorus) + if (curvedWall) vertex.z = stepHeight * numSteps; else vertex.z += stepHeight; @@ -205,7 +205,7 @@ public override void Invalidate (bool polygonsChanged) } // we force NoCSG mode if special NoCSG operators are used. - if (buildTorus) { slopedFloor = false; slopedCeiling = false; } + if (curvedWall) { slopedFloor = false; slopedCeiling = false; } if (fillToBottom) { slopedCeiling = false; } if (slopedFloor || slopedCeiling) { diff --git a/Scripts/Brushes/CompoundBrushes/Editor/CurvedStairBrushInspector.cs b/Scripts/Brushes/CompoundBrushes/Editor/CurvedStairBrushInspector.cs index cf7a03c9..8a234335 100644 --- a/Scripts/Brushes/CompoundBrushes/Editor/CurvedStairBrushInspector.cs +++ b/Scripts/Brushes/CompoundBrushes/Editor/CurvedStairBrushInspector.cs @@ -19,7 +19,7 @@ public class CurvedStairBrushInspector : CompoundBrushInspector SerializedProperty addToFirstStep; SerializedProperty counterClockwise; SerializedProperty fillToBottom; - SerializedProperty buildTorus; + SerializedProperty curvedWall; SerializedProperty slopedFloor; SerializedProperty slopedCeiling; @@ -35,7 +35,7 @@ protected override void OnEnable() addToFirstStep = serializedObject.FindProperty("addToFirstStep"); counterClockwise = serializedObject.FindProperty("counterClockwise"); fillToBottom = serializedObject.FindProperty("fillToBottom"); - buildTorus = serializedObject.FindProperty("buildTorus"); + curvedWall = serializedObject.FindProperty("curvedWall"); slopedFloor = serializedObject.FindProperty("slopedFloor"); slopedCeiling = serializedObject.FindProperty("slopedCeiling"); } @@ -108,15 +108,15 @@ public override void OnInspectorGUI() if (fillToBottom.boolValue != oldBool) ApplyAndInvalidate(); - buildTorus.boolValue = GUILayout.Toggle(oldBool = buildTorus.boolValue, "Build Torus", EditorStyles.toolbarButton); - if (buildTorus.boolValue != oldBool) + curvedWall.boolValue = GUILayout.Toggle(oldBool = curvedWall.boolValue, "Curved Wall", EditorStyles.toolbarButton); + if (curvedWall.boolValue != oldBool) ApplyAndInvalidate(); EditorGUILayout.EndHorizontal(); } // can only use nocsg slopes if build torus is disabled. - if (!buildTorus.boolValue) + if (!curvedWall.boolValue) { using (new NamedVerticalScope("Curved Stair: NoCSG Operators")) {