Exemplo n.º 1
0
        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();
            }
        }
Exemplo n.º 2
0
            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);
                }
            }