Example #1
0
        private void SetPolygonCollider2D(Shape shape)
        {
            PolygonCollider2D pc2d = shape.GetComponent <PolygonCollider2D>();

            if (shape.settings.shapeType == ShapeType.Polygon)
            {
                if (!pc2d)
                {
                    pc2d = shape.gameObject.AddComponent <PolygonCollider2D>();
                }
                Vector3[] points         = shape.GetPolygonWorldVertices();
                Vector2[] colliderPoints = new Vector2[points.Length];
                for (int i = 0; i < points.Length; i++)
                {
                    colliderPoints[i] = shape.transform.InverseTransformPoint(points[i]);
                }
                Undo.RecordObject(pc2d, "Set PolygonCollider2D Points");
                pc2d.points = colliderPoints;
            }
        }
Example #2
0
        void OnSceneGUI()
        {
            Shape shape = (Shape)target;

            if (!isEditingPolygon || shape.settings.shapeType != ShapeType.Polygon)
            {
                return;
            }
            // all the rest is for polygon editing
            if (Tools.current != Tool.None)
            {
                StopEditingPolygon(false);
                return;
            }
            HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));
            // draw the borders so the user knows where vertices should live
            DrawShapeBorders(shape);
            // get the existing verts
            Vector3[]      oldVerts    = shape.GetPolygonWorldVertices();
            List <Vector3> verts       = new List <Vector3>(oldVerts);
            bool           hasMaxVerts = verts.Count == Shape.MaxPolygonVertices;

            // add the first vert at the end as well so Unity will draw it right etc
            verts.Add(verts[0]);
            // are we in delete mode?  what color should handles be?
            Color pink       = new Color(1, 0, 0.75f);
            bool  deleteMode = false;

            if ((Event.current.control || Event.current.command) && verts.Count > 4)
            {
                Handles.color = Color.red;
                deleteMode    = true;
            }
            else
            {
                Handles.color = pink;
            }
            // draw the shape
            Handles.DrawAAPolyLine(3f, verts.ToArray());
            // drag handle result for getting info from our handles
            CustomHandles.DragHandleResult dhResult;
            // draw handles for each existing vert and check if they've been moved or clicked
            bool changed = false;

            for (int i = verts.Count - 2; i >= 0; i--)
            {
                Vector3 v      = verts[i];
                Vector3 newPos = CustomHandles.DragHandle(v, 0.05f * HandleUtility.GetHandleSize(v),
                                                          Handles.DotCap, pink, out dhResult);
                if (deleteMode && dhResult == CustomHandles.DragHandleResult.LMBPress)
                {
                    // the user clicked on the handle while in delete mode, so delete the vert
                    verts.RemoveAt(i);
                    changed = true;
                }
                else if (!deleteMode && newPos != v)
                {
                    // the handle has been dragged, so move the vert to the new position
                    verts[i] = new Vector2(newPos.x, newPos.y);
                    changed  = true;
                }
            }
            // check if the mouse is hovering over a space where we could add a new vert,
            // and draw it if so
            bool    snapped       = false;
            Vector3 closestPos    = HandleUtility.ClosestPointToPolyLine(verts.ToArray());
            float   distance      = HandleUtility.DistanceToPolyLine(verts.ToArray());
            bool    isCloseToLine = distance < 25;

            if (!changed && isCloseToLine && !hasMaxVerts && !deleteMode)
            {
                // todo - ClosestPointToPolyLine doesn't work very well in 3D...
                foreach (Vector3 v in verts)
                {
                    // if close to an existing vert, we don't want to add a new one
                    if (Vector2.Distance(HandleUtility.WorldToGUIPoint(closestPos),
                                         HandleUtility.WorldToGUIPoint(v)) < 15)
                    {
                        snapped = true;
                        break;
                    }
                }
                if (!snapped)
                {
                    // not too close to an existing vert, so draw a new one.  don't
                    // use an actual handle cause we want to intercept nearby clicks
                    // and not just clicks directly on the handle.
                    Rect  rect = new Rect();
                    float dim  = 0.05f * HandleUtility.GetHandleSize(closestPos);
                    rect.center   = closestPos - new Vector3(dim, dim, 0);
                    rect.size     = new Vector2(dim * 2, dim * 2);
                    Handles.color = Color.white; // remove the weird tint it does
                    Handles.DrawSolidRectangleWithOutline(rect, Color.green, Color.clear);
                    if (Event.current.type == EventType.MouseDown)
                    {
                        // the user has clicked the new vert, so add it for real
                        // figure out which line segment it's on
                        int lineStart = GetClosestLineToPoint(closestPos, verts);
                        verts.Insert(lineStart + 1, closestPos);
                        changed = true;
                    }
                }
            }
            // something has been changed, so apply the new verts back to the shape
            if (changed)
            {
                // make sure to remove the duplicated last vert we added
                Undo.RecordObject(shape, "Edit Shapes2D Polygon Vertices");
                shape.SetPolygonWorldVertices(
                    verts.GetRange(0, verts.Count - 1).ToArray());
                EditorUtility.SetDirty(target);
            }
            else
            {
                HandleUtility.Repaint(); // to draw the new vert placeholder handle
                if (Event.current.type == EventType.MouseDown && !isCloseToLine)
                {
                    StopEditingPolygon(true);
                }
            }
        }