protected override void OnScene(SceneView sceneView, ChiselSpiralStairs generator) { var normal = Vector3.up; var topDirection = Vector3.forward; var lowDirection = Vector3.forward; var originalOuterDiameter = generator.OuterDiameter; var originalInnerDiameter = generator.InnerDiameter; var originalStartAngle = generator.StartAngle; var originalStepHeight = generator.StepHeight; var originalRotation = generator.Rotation; var originalHeight = generator.Height; var originalOrigin = generator.Origin; var cylinderTop = new ChiselCircleDefinition(1, originalOrigin.y + originalHeight); var cylinderLow = new ChiselCircleDefinition(1, originalOrigin.y); var originalTopPoint = normal * cylinderTop.height; var originalLowPoint = normal * cylinderLow.height; var originalMidPoint = (originalTopPoint + originalLowPoint) * 0.5f; var outerDiameter = originalOuterDiameter; var innerDiameter = originalInnerDiameter; var topPoint = originalTopPoint; var lowPoint = originalLowPoint; var midPoint = originalMidPoint; var startAngle = originalStartAngle; var rotation = originalRotation; EditorGUI.BeginChangeCheck(); { var startRotateEdgeID = GUIUtility.GetControlID("SpiralStairsStartAngle".GetHashCode(), FocusType.Keyboard); var endRotateEdgeID = GUIUtility.GetControlID("SpiralStairsEndAngle".GetHashCode(), FocusType.Keyboard); // TODO: properly show things as backfaced // TODO: temporarily show inner or outer diameter as disabled when resizing one or the other // TODO: FIXME: why aren't there any arrows? topPoint = UnitySceneExtensions.SceneHandles.DirectionHandle(topPoint, normal, snappingStep: originalStepHeight); topPoint.y = Mathf.Max(lowPoint.y + originalStepHeight, topPoint.y); lowPoint = UnitySceneExtensions.SceneHandles.DirectionHandle(lowPoint, -normal, snappingStep: originalStepHeight); lowPoint.y = Mathf.Min(topPoint.y - originalStepHeight, lowPoint.y); float minOuterDiameter = innerDiameter + ChiselSpiralStairsDefinition.kMinStairsDepth; outerDiameter = Mathf.Max(minOuterDiameter, UnitySceneExtensions.SceneHandles.RadiusHandle(Vector3.up, topPoint, outerDiameter * 0.5f, renderDisc: false) * 2.0f); outerDiameter = Mathf.Max(minOuterDiameter, UnitySceneExtensions.SceneHandles.RadiusHandle(Vector3.up, lowPoint, outerDiameter * 0.5f, renderDisc: false) * 2.0f); float maxInnerDiameter = outerDiameter - ChiselSpiralStairsDefinition.kMinStairsDepth; innerDiameter = Mathf.Min(maxInnerDiameter, UnitySceneExtensions.SceneHandles.RadiusHandle(Vector3.up, midPoint, innerDiameter * 0.5f, renderDisc: false) * 2.0f); startAngle = RotatedEdge2DHandle(startRotateEdgeID, startAngle, lowPoint, outerDiameter * 0.5f, normal, lowDirection, Vector3.Cross(normal, lowDirection)); rotation = RotatedEdge2DHandle(endRotateEdgeID, startAngle + rotation, topPoint, outerDiameter * 0.5f, normal, topDirection, Vector3.Cross(normal, topDirection)) - startAngle; // TODO: somehow put this into a separate renderer cylinderTop.diameterZ = cylinderTop.diameterX = cylinderLow.diameterZ = cylinderLow.diameterX = originalInnerDiameter; BrushMeshFactory.GetConicalFrustumVertices(cylinderLow, cylinderTop, 0, generator.InnerSegments, ref innerVertices); cylinderTop.diameterZ = cylinderTop.diameterX = cylinderLow.diameterZ = cylinderLow.diameterX = originalOuterDiameter; BrushMeshFactory.GetConicalFrustumVertices(cylinderLow, cylinderTop, 0, generator.OuterSegments, ref outerVertices); var originalColor = UnityEditor.Handles.yAxisColor; var color = Color.Lerp(originalColor, UnitySceneExtensions.SceneHandles.staticColor, UnitySceneExtensions.SceneHandles.staticBlend); var outlineColor = Color.black; outlineColor.a = color.a; UnityEditor.Handles.color = outlineColor; { var sides = generator.OuterSegments; for (int i = 0, j = sides - 1; i < sides; j = i, i++) { var t0 = outerVertices[i]; var t1 = outerVertices[j]; var b0 = outerVertices[i + sides]; var b1 = outerVertices[j + sides]; UnityEditor.Handles.DrawAAPolyLine(3.0f, t0, b0); UnityEditor.Handles.DrawAAPolyLine(3.0f, t0, t1); UnityEditor.Handles.DrawAAPolyLine(3.0f, b0, b1); } } { var sides = generator.InnerSegments; for (int i = 0, j = sides - 1; i < sides; j = i, i++) { var t0 = innerVertices[i]; var t1 = innerVertices[j]; var b0 = innerVertices[i + sides]; var b1 = innerVertices[j + sides]; UnityEditor.Handles.DrawAAPolyLine(3.0f, t0, b0); UnityEditor.Handles.DrawAAPolyLine(3.0f, t0, t1); UnityEditor.Handles.DrawAAPolyLine(3.0f, b0, b1); } } UnityEditor.Handles.color = originalColor; { var sides = generator.OuterSegments; for (int i = 0, j = sides - 1; i < sides; j = i, i++) { var t0 = outerVertices[i]; var t1 = outerVertices[j]; var b0 = outerVertices[i + sides]; var b1 = outerVertices[j + sides]; UnityEditor.Handles.DrawAAPolyLine(2.0f, t0, b0); UnityEditor.Handles.DrawAAPolyLine(2.0f, t0, t1); UnityEditor.Handles.DrawAAPolyLine(2.0f, b0, b1); } } { var sides = generator.InnerSegments; for (int i = 0, j = sides - 1; i < sides; j = i, i++) { var t0 = innerVertices[i]; var t1 = innerVertices[j]; var b0 = innerVertices[i + sides]; var b1 = innerVertices[j + sides]; UnityEditor.Handles.DrawAAPolyLine(2.0f, t0, b0); UnityEditor.Handles.DrawAAPolyLine(2.0f, t0, t1); UnityEditor.Handles.DrawAAPolyLine(2.0f, b0, b1); var m0 = (t0 + b0) * 0.5f; var m1 = (t1 + b1) * 0.5f; UnityEditor.Handles.DrawDottedLine(m0, m1, 4.0f); } } } if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(target, "Modified " + generator.NodeTypeName); generator.OuterDiameter = outerDiameter; generator.InnerDiameter = innerDiameter; generator.StartAngle = startAngle; generator.Rotation = rotation; if (topPoint != originalTopPoint) { generator.Height = topPoint.y - lowPoint.y; } if (lowPoint != originalLowPoint) { generator.Height = topPoint.y - lowPoint.y; var newOrigin = originalOrigin; newOrigin.y += lowPoint.y - originalLowPoint.y; generator.Origin = newOrigin; } generator.OnValidate(); } }
public void ShowInstance() { var tempTop = generator.Top; var tempBottom = generator.Bottom; var sides = generator.Sides; var topId = GUIUtility.GetControlID(s_TopHash, FocusType.Passive); var bottomId = GUIUtility.GetControlID(s_BottomHash, FocusType.Passive); var focusControl = UnitySceneExtensions.SceneHandleUtility.focusControl; var color = UnityEditor.Handles.yAxisColor; var isDisabled = UnitySceneExtensions.SceneHandles.disabled; if (!generator.IsEllipsoid) { tempTop.diameterZ = tempTop.diameterX; tempBottom.diameterZ = tempBottom.diameterX; } EditorGUI.BeginChangeCheck(); { switch (generator.Type) { case CylinderShapeType.Cylinder: { if (generator.IsEllipsoid) { UnitySceneExtensions.SceneHandles.Radius2DHandle(topPoint, normal, ref bottomXVector, ref bottomZVector, renderDisc: false); UnitySceneExtensions.SceneHandles.Radius2DHandle(bottomPoint, -normal, ref bottomXVector, ref bottomZVector, renderDisc: false); } else { bottomXVector = UnitySceneExtensions.SceneHandles.Radius2DHandle(topPoint, normal, bottomXVector, renderDisc: false); bottomXVector = UnitySceneExtensions.SceneHandles.Radius2DHandle(bottomPoint, -normal, bottomXVector, renderDisc: false); bottomZVector = bottomXVector; } topXVector = bottomXVector; topZVector = bottomZVector; tempTop.diameterX = tempBottom.diameterX; tempTop.diameterZ = tempBottom.diameterZ; break; } case CylinderShapeType.ConicalFrustum: { if (generator.IsEllipsoid) { UnitySceneExtensions.SceneHandles.Radius2DHandle(topPoint, normal, ref topXVector, ref topZVector, renderDisc: false); UnitySceneExtensions.SceneHandles.Radius2DHandle(bottomPoint, -normal, ref bottomXVector, ref bottomZVector, renderDisc: false); } else { UnitySceneExtensions.SceneHandles.Radius2DHandle(topPoint, normal, ref topXVector, ref topXVector, renderDisc: false); UnitySceneExtensions.SceneHandles.Radius2DHandle(bottomPoint, -normal, ref bottomXVector, ref bottomXVector, renderDisc: false); bottomXVector = UnitySceneExtensions.SceneHandles.Radius2DHandle(bottomPoint, -normal, bottomXVector, renderDisc: false); bottomZVector = bottomXVector; } break; } case CylinderShapeType.Cone: { if (generator.IsEllipsoid) { UnitySceneExtensions.SceneHandles.Radius2DHandle(bottomPoint, -normal, ref bottomXVector, ref bottomZVector, renderDisc: false); } else { bottomXVector = UnitySceneExtensions.SceneHandles.Radius2DHandle(bottomPoint, -normal, bottomXVector, renderDisc: false); bottomZVector = bottomXVector; } topXVector = bottomXVector; topZVector = bottomZVector; tempTop.diameterX = 0; tempTop.diameterZ = 0; break; } } // TODO: add cylinder horizon "side-lines" } if (EditorGUI.EndChangeCheck()) { topZVector.y = 0; topXVector.y = 0; bottomZVector.y = 0; bottomXVector.y = 0; Undo.RecordObject(generator, "Modified " + generator.NodeTypeName); if (!generator.IsEllipsoid) { if (prevBottomXVector != bottomXVector) { bottomZVector = Vector3.Cross(normal, bottomXVector.normalized) * bottomXVector.magnitude; } if (prevTopXVector != topXVector) { topZVector = Vector3.Cross(normal, topXVector.normalized) * topXVector.magnitude; } } if (prevTopXVector != topXVector) { generator.Rotation = Utilities.GeometryMath.SignedAngle(Vector3.right, topXVector.normalized, Vector3.up); } else if (prevBottomXVector != bottomXVector) { generator.Rotation = Utilities.GeometryMath.SignedAngle(Vector3.right, bottomXVector.normalized, Vector3.up); } if (generator.IsEllipsoid) { generator.BottomDiameterX = bottomXVector.magnitude * 2.0f; generator.BottomDiameterZ = bottomZVector.magnitude * 2.0f; generator.TopDiameterX = topXVector.magnitude * 2.0f; generator.TopDiameterZ = topZVector.magnitude * 2.0f; } else { if (prevBottomZVector != bottomZVector) { generator.BottomDiameterX = bottomZVector.magnitude * 2.0f; generator.BottomDiameterZ = bottomZVector.magnitude * 2.0f; } else { generator.BottomDiameterX = bottomXVector.magnitude * 2.0f; generator.BottomDiameterZ = bottomXVector.magnitude * 2.0f; } if (prevTopZVector != topZVector) { generator.TopDiameterX = topZVector.magnitude * 2.0f; generator.TopDiameterZ = topZVector.magnitude * 2.0f; } else { generator.TopDiameterX = topXVector.magnitude * 2.0f; generator.TopDiameterZ = topXVector.magnitude * 2.0f; } } } const float kLineDash = 2.0f; const float kLineThickness = 1.0f; const float kCircleThickness = 1.5f; const float kCapLineThickness = 2.0f; const float kCapLineThicknessSelected = 2.5f; const int kMaxOutlineSides = 32; const int kMinimumSides = 8; var baseColor = UnityEditor.Handles.yAxisColor; BrushMeshFactory.GetConicalFrustumVertices(tempBottom, tempTop, generator.Rotation, sides, ref vertices); if (generator.TopHeight < generator.BottomHeight) { normal = -normal; } var isTopBackfaced = IsSufaceBackFaced(topPoint, normal); var topHasFocus = (focusControl == topId); var topThickness = topHasFocus ? kCapLineThicknessSelected : kCapLineThickness; var isBottomBackfaced = IsSufaceBackFaced(bottomPoint, -normal); var bottomHasFocus = (focusControl == bottomId); var bottomThickness = bottomHasFocus ? kCapLineThicknessSelected : kCapLineThickness; UnityEditor.Handles.color = GetColorForState(baseColor, bottomHasFocus, isBottomBackfaced, isDisabled); ChiselOutlineRenderer.DrawLineLoop(vertices, 0, sides, thickness: bottomThickness); UnityEditor.Handles.color = GetColorForState(baseColor, topHasFocus, isTopBackfaced, isDisabled); ChiselOutlineRenderer.DrawLineLoop(vertices, sides, sides, thickness: topThickness); UnityEditor.Handles.color = GetColorForState(baseColor, false, false, isDisabled); for (int i = 0; i < sides; i++) { ChiselOutlineRenderer.DrawLine(vertices[i], vertices[i + sides], lineMode: LineMode.ZTest, thickness: kLineThickness); } UnityEditor.Handles.color = GetColorForState(baseColor, false, true, isDisabled); for (int i = 0; i < sides; i++) { ChiselOutlineRenderer.DrawLine(vertices[i], vertices[i + sides], lineMode: LineMode.NoZTest, thickness: kLineThickness); } /* * var point0 = camera.WorldToScreenPoint(topPoint); * var direction = camera.ScreenToWorldPoint(point0 - Vector3.right); * var point1 = camera.WorldToScreenPoint(point0 - (direction * tempTop.diameterX)); * var size = Mathf.Max(point1.x - point0.x, point1.y - point0.y); */ // TODO: figure out how to reduce the sides of the circle depending on radius & distance int outlineSides = kMaxOutlineSides; if (sides <= kMinimumSides) { BrushMeshFactory.GetConicalFrustumVertices(tempBottom, tempTop, generator.Rotation, outlineSides, ref dottedVertices); UnityEditor.Handles.color = GetColorForState(baseColor, topHasFocus, false, isDisabled); ChiselOutlineRenderer.DrawLineLoop(dottedVertices, outlineSides, outlineSides, lineMode: LineMode.ZTest, thickness: kCircleThickness, dashSize: kLineDash); UnityEditor.Handles.color = GetColorForState(baseColor, topHasFocus, true, isDisabled); ChiselOutlineRenderer.DrawLineLoop(dottedVertices, outlineSides, outlineSides, lineMode: LineMode.NoZTest, thickness: kCircleThickness, dashSize: kLineDash); UnityEditor.Handles.color = GetColorForState(baseColor, bottomHasFocus, false, isDisabled); ChiselOutlineRenderer.DrawLineLoop(dottedVertices, 0, outlineSides, lineMode: LineMode.ZTest, thickness: kCircleThickness, dashSize: kLineDash); UnityEditor.Handles.color = GetColorForState(baseColor, bottomHasFocus, true, isDisabled); ChiselOutlineRenderer.DrawLineLoop(dottedVertices, 0, outlineSides, lineMode: LineMode.NoZTest, thickness: kCircleThickness, dashSize: kLineDash); } EditorGUI.BeginChangeCheck(); { UnityEditor.Handles.color = GetColorForState(baseColor, bottomHasFocus, isBottomBackfaced, isDisabled); bottomPoint = UnitySceneExtensions.SceneHandles.DirectionHandle(bottomId, bottomPoint, -normal); UnityEditor.Handles.color = GetColorForState(baseColor, topHasFocus, isTopBackfaced, isDisabled); topPoint = UnitySceneExtensions.SceneHandles.DirectionHandle(topId, topPoint, normal); } if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(generator, "Modified " + generator.NodeTypeName); generator.TopHeight = Vector3.Dot(Vector3.up, topPoint); generator.BottomHeight = Vector3.Dot(Vector3.up, bottomPoint); } }