diff --git a/Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs b/Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs
index 65f374f0..2fcd0819 100644
--- a/Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs
+++ b/Scripts/Brushes/CompoundBrushes/CurvedStairBrush.cs
@@ -42,6 +42,22 @@ 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 curved wall.
+ [SerializeField]
+ bool curvedWall = false;
+
+ /// Whether the floor is stairs or a smooth slope.
+ [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.
@@ -102,7 +118,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 +143,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 (curvedWall)
+ vertex.z = stepHeight * numSteps;
+ else
+ vertex.z += stepHeight;
vertexPositions.Add(new Vector3(newVertex.x, vertex.z, newVertex.y));
}
@@ -145,7 +163,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 (curvedWall)
+ vertex.z = stepHeight * numSteps;
+ else
+ vertex.z += stepHeight;
vertexPositions.Add(new Vector3(newVertex.x, vertex.z, newVertex.y));
}
@@ -183,6 +204,14 @@ public override void Invalidate (bool polygonsChanged)
index3 = 3;
}
+ // we force NoCSG mode if special NoCSG operators are used.
+ if (curvedWall) { slopedFloor = false; slopedCeiling = false; }
+ if (fillToBottom) { slopedCeiling = false; }
+ if (slopedFloor || slopedCeiling)
+ {
+ this.IsNoCSG = true;
+ }
+
// we calculate the bounds of the output csg.
Bounds csgBounds = new Bounds();
@@ -207,20 +236,34 @@ public override void Invalidate (bool polygonsChanged)
// | Back | Left | Right | Front | Bottom | Top |
// +--------+--------+--------+--------+--------+--------+
+
+
// retrieve the vertices of the top polygon.
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[5]);
// 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 +271,34 @@ 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];
+ }
+ 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.
- 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]);
+
+ // update uv coordinates to prevent distortions using barnaby's genius utilities.
+ GenerateUvCoordinates(polygons[3]);
@@ -246,17 +306,38 @@ 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);
+ }
+ if (slopedFloor)
+ {
+ // 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.
- 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]);
+
+ // update uv coordinates to prevent distortions using barnaby's genius utilities.
+ GenerateUvCoordinates(polygons[1]);
@@ -264,17 +345,38 @@ 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];
+ }
+ if (slopedFloor)
+ {
+ // 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.
- 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]);
+
+ // update uv coordinates to prevent distortions using barnaby's genius utilities.
+ GenerateUvCoordinates(polygons[2]);
@@ -282,16 +384,34 @@ 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);
+ }
+ 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]);
// 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 +419,36 @@ 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);
+ }
+ if (slopedFloor)
+ {
+ // create a smooth floor 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.
- 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]);
+
+ // update uv coordinates to prevent distortions using barnaby's genius utilities.
+ GenerateUvCoordinates(polygons[0]);
+
+
generatedBrushes[i].Invalidate(true);
csgBounds.Encapsulate(generatedBrushes[i].GetBounds());
@@ -320,6 +459,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..8a234335 100644
--- a/Scripts/Brushes/CompoundBrushes/Editor/CurvedStairBrushInspector.cs
+++ b/Scripts/Brushes/CompoundBrushes/Editor/CurvedStairBrushInspector.cs
@@ -18,6 +18,10 @@ public class CurvedStairBrushInspector : CompoundBrushInspector
SerializedProperty numSteps;
SerializedProperty addToFirstStep;
SerializedProperty counterClockwise;
+ SerializedProperty fillToBottom;
+ SerializedProperty curvedWall;
+ SerializedProperty slopedFloor;
+ SerializedProperty slopedCeiling;
protected override void OnEnable()
{
@@ -30,10 +34,16 @@ protected override void OnEnable()
numSteps = serializedObject.FindProperty("numSteps");
addToFirstStep = serializedObject.FindProperty("addToFirstStep");
counterClockwise = serializedObject.FindProperty("counterClockwise");
+ fillToBottom = serializedObject.FindProperty("fillToBottom");
+ curvedWall = serializedObject.FindProperty("curvedWall");
+ slopedFloor = serializedObject.FindProperty("slopedFloor");
+ slopedCeiling = serializedObject.FindProperty("slopedCeiling");
}
public override void OnInspectorGUI()
{
+ bool oldBool;
+
using (new NamedVerticalScope("Curved Stair"))
{
EditorGUI.BeginChangeCheck();
@@ -75,17 +85,62 @@ 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();
+
+ 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 (!curvedWall.boolValue)
+ {
+ using (new NamedVerticalScope("Curved Stair: NoCSG Operators"))
+ {
+ 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();
+ }
}
base.OnInspectorGUI();