Exemplo n.º 1
0
        public List <LuaVector2D> GetGridIntersections()
        {
            if (linedef.IsDisposed)
            {
                throw new ScriptRuntimeException("Linedef has been disposed, can't GetGridIntersections.");
            }

            List <Vector2D> intersections = linedef.GetGridIntersections();
            int             count         = intersections.Count;

            List <LuaVector2D> output = new List <LuaVector2D>(count);

            for (int i = 0; i < count; i++)
            {
                output.Add(new LuaVector2D(intersections[i]));
            }

            return(output);
        }
        // This moves the selected geometry relatively
        // Returns true when geometry has actually moved
        private bool MoveGeometryRelative(Vector2D offset, bool snapgrid, bool snapnearest)
        {
            Vector2D oldpos = dragitem.Position;
            Vector2D anchorpos = dragitemposition + offset;
            Vector2D tl, br;

            // don't move if the offset contains invalid data
            if (!offset.IsFinite())
            {
                return(false);
            }

            // Find the outmost vertices
            tl = br = oldpositions[0];
            for (int i = 0; i < oldpositions.Count; i++)
            {
                if (oldpositions[i].x < tl.x)
                {
                    tl.x = (int)oldpositions[i].x;
                }
                if (oldpositions[i].x > br.x)
                {
                    br.x = (int)oldpositions[i].x;
                }
                if (oldpositions[i].y > tl.y)
                {
                    tl.y = (int)oldpositions[i].y;
                }
                if (oldpositions[i].y < br.y)
                {
                    br.y = (int)oldpositions[i].y;
                }
            }

            // Snap to nearest?
            if (snapnearest)
            {
                // Find nearest unselected vertex within range
                Vertex nv = MapSet.NearestVertexSquareRange(unselectedverts, anchorpos, BuilderPlug.Me.StitchRange / renderer.Scale);
                if (nv != null)
                {
                    // Move the dragged item
                    dragitem.Move(nv.Position);

                    // Adjust the offset
                    offset = nv.Position - dragitemposition;

                    // Do not snap to grid!
                    snapgrid = false;
                }
                else
                {
                    // Find the nearest unselected line within range
                    Linedef nl = MapSet.NearestLinedefRange(snaptolines, anchorpos, BuilderPlug.Me.StitchRange / renderer.Scale);
                    if (nl != null)
                    {
                        // Snap to grid?
                        if (snaptogrid)
                        {
                            // Get grid intersection coordinates
                            List <Vector2D> coords = nl.GetGridIntersections();

                            // Find nearest grid intersection
                            float    found_distance = float.MaxValue;
                            Vector2D found_coord    = new Vector2D();
                            foreach (Vector2D v in coords)
                            {
                                Vector2D delta = anchorpos - v;
                                if (delta.GetLengthSq() < found_distance)
                                {
                                    found_distance = delta.GetLengthSq();
                                    found_coord    = v;
                                }
                            }

                            // Move the dragged item
                            dragitem.Move(found_coord);

                            // Align to line here
                            offset = found_coord - dragitemposition;

                            // Do not snap to grid anymore
                            snapgrid = false;
                        }
                        else
                        {
                            // Move the dragged item
                            dragitem.Move(nl.NearestOnLine(anchorpos));

                            // Align to line here
                            offset = nl.NearestOnLine(anchorpos) - dragitemposition;
                        }
                    }
                }
            }

            // Snap to grid?
            if (snapgrid)
            {
                // Move the dragged item
                dragitem.Move(anchorpos);

                // Snap item to grid
                dragitem.SnapToGrid();

                // Adjust the offset
                offset += dragitem.Position - anchorpos;
            }

            // Make sure the offset is inside the map boundaries
            if (offset.x + tl.x < General.Map.FormatInterface.LeftBoundary)
            {
                offset.x = General.Map.FormatInterface.LeftBoundary - tl.x;
            }
            if (offset.x + br.x > General.Map.FormatInterface.RightBoundary)
            {
                offset.x = General.Map.FormatInterface.RightBoundary - br.x;
            }
            if (offset.y + tl.y > General.Map.FormatInterface.TopBoundary)
            {
                offset.y = General.Map.FormatInterface.TopBoundary - tl.y;
            }
            if (offset.y + br.y < General.Map.FormatInterface.BottomBoundary)
            {
                offset.y = General.Map.FormatInterface.BottomBoundary - br.y;
            }

            // Drag item moved?
            if (!snapgrid || (dragitem.Position != oldpos))
            {
                int i = 0;

                // Move selected geometry
                foreach (Vertex v in selectedverts)
                {
                    // Move vertex from old position relative to the
                    // mouse position change since drag start
                    v.Move(oldpositions[i] + offset);

                    // Next
                    i++;
                }

                // Update labels
                int index = 0;
                foreach (Linedef l in unstablelines)
                {
                    labels[index++].Move(l.Start.Position, l.End.Position);
                }

                // Moved
                return(true);
            }
            else
            {
                // No changes
                return(false);
            }
        }
Exemplo n.º 3
0
        public static void InsertVertex(Vector2D mousemappos, float rendererscale)
        {
            bool snaptogrid    = General.Interface.ShiftState ^ General.Interface.SnapToGrid;
            bool snaptonearest = General.Interface.CtrlState ^ General.Interface.AutoMerge;

            // Mouse in window?
            if (General.Interface.MouseInDisplay)
            {
                Vector2D insertpos;
                Linedef  l = null;

                // Create undo
                General.Map.UndoRedo.CreateUndo("Insert vertex");

                // Snap to geometry?
                l = General.Map.Map.NearestLinedefRange(mousemappos, BuilderPlug.Me.SplitLinedefsRange / rendererscale);
                if (snaptonearest && (l != null))
                {
                    // Snip to grid also?
                    if (snaptogrid)
                    {
                        // Find all points where the grid intersects the line
                        List <Vector2D> points = l.GetGridIntersections();
                        insertpos = mousemappos;
                        float distance = float.MaxValue;
                        foreach (Vector2D p in points)
                        {
                            float pdist = Vector2D.DistanceSq(p, mousemappos);
                            if (pdist < distance)
                            {
                                insertpos = p;
                                distance  = pdist;
                            }
                        }
                    }
                    else
                    {
                        // Just use the nearest point on line
                        insertpos = l.NearestOnLine(mousemappos);
                    }
                }
                // Snap to grid?
                else if (snaptogrid)
                {
                    // Snap to grid
                    insertpos = General.Map.Grid.SnappedToGrid(mousemappos);
                }
                else
                {
                    // Just insert here, don't snap to anything
                    insertpos = mousemappos;
                }

                // Make the vertex
                Vertex v = General.Map.Map.CreateVertex(insertpos);
                if (v == null)
                {
                    General.Map.UndoRedo.WithdrawUndo();
                    return;
                }

                // Snap to map format accuracy
                v.SnapToAccuracy();

                // Split the line with this vertex
                if (snaptonearest && (l != null))
                {
                    General.Interface.DisplayStatus(StatusType.Action, "Split a linedef.");
                    Linedef sld = l.Split(v);
                    if (sld == null)
                    {
                        General.Map.UndoRedo.WithdrawUndo();
                        return;
                    }
                    BuilderPlug.Me.AdjustSplitCoordinates(l, sld);
                }
                else
                {
                    General.Interface.DisplayStatus(StatusType.Action, "Inserted a vertex.");
                }

                // Update
                General.Map.Map.Update();

                // Redraw screen
                General.Interface.RedrawDisplay();
            }
        }
Exemplo n.º 4
0
        // Start editing
        protected override void OnEditBegin()
        {
            bool snaptogrid    = General.Interface.ShiftState ^ General.Interface.SnapToGrid;
            bool snaptonearest = General.Interface.CtrlState ^ General.Interface.AutoMerge;

            // Vertex highlighted?
            if ((highlighted != null) && !highlighted.IsDisposed)
            {
                // Edit pressed in this mode
                editpressed = true;

                // Highlighted item not selected?
                if (!highlighted.Selected && (BuilderPlug.Me.AutoClearSelection || (General.Map.Map.SelectedVerticessCount == 0)))
                {
                    // Make this the only selection
                    General.Map.Map.ClearSelectedVertices();
                    highlighted.Selected = true;
                    General.Interface.RedrawDisplay();
                }

                // Update display
                if (renderer.StartPlotter(false))
                {
                    // Redraw highlight to show selection
                    renderer.PlotVertex(highlighted, renderer.DetermineVertexColor(highlighted));
                    renderer.Finish();
                    renderer.Present();
                }
            }
            else
            {
                // Find the nearest linedef within highlight range
                Linedef l = General.Map.Map.NearestLinedefRange(mousemappos, BuilderPlug.Me.SplitLinedefsRange / renderer.Scale);
                if (l != null)
                {
                    // Create undo
                    General.Map.UndoRedo.CreateUndo("Split linedef");

                    Vector2D insertpos;

                    // Snip to grid also?
                    if (snaptogrid)
                    {
                        // Find all points where the grid intersects the line
                        List <Vector2D> points = l.GetGridIntersections();
                        insertpos = mousemappos;
                        float distance = float.MaxValue;
                        foreach (Vector2D p in points)
                        {
                            float pdist = Vector2D.DistanceSq(p, mousemappos);
                            if (pdist < distance)
                            {
                                insertpos = p;
                                distance  = pdist;
                            }
                        }
                    }
                    else
                    {
                        // Just use the nearest point on line
                        insertpos = l.NearestOnLine(mousemappos);
                    }

                    // Make the vertex
                    Vertex v = General.Map.Map.CreateVertex(insertpos);
                    if (v == null)
                    {
                        General.Map.UndoRedo.WithdrawUndo();
                        return;
                    }

                    // Snap to map format accuracy
                    v.SnapToAccuracy();

                    // Split the line with this vertex
                    Linedef sld = l.Split(v);
                    if (sld == null)
                    {
                        General.Map.UndoRedo.WithdrawUndo();
                        return;
                    }
                    BuilderPlug.Me.AdjustSplitCoordinates(l, sld);

                    // Update
                    General.Map.Map.Update();

                    // Highlight it
                    Highlight(v);

                    // Redraw display
                    General.Interface.RedrawDisplay();
                }
                else
                {
                    // Start drawing mode
                    DrawGeometryMode drawmode = new DrawGeometryMode();
                    DrawnVertex      v        = DrawGeometryMode.GetCurrentPosition(mousemappos, snaptonearest, snaptogrid, renderer, new List <DrawnVertex>());

                    if (drawmode.DrawPointAt(v))
                    {
                        General.Editing.ChangeMode(drawmode);
                    }
                    else
                    {
                        General.Interface.DisplayStatus(StatusType.Warning, "Failed to draw point: outside of map boundaries.");
                    }
                }
            }

            base.OnEditBegin();
        }
Exemplo n.º 5
0
        // This returns the aligned and snapped draw position
        public static DrawnVertex GetCurrentPosition(Vector2D mousemappos, bool snaptonearest, bool snaptogrid, IRenderer2D renderer, List <DrawnVertex> points)
        {
            DrawnVertex p      = new DrawnVertex();
            Vector2D    vm     = mousemappos;
            float       vrange = BuilderPlug.Me.StitchRange / renderer.Scale;

            // Snap to nearest?
            if (snaptonearest)
            {
                // Go for all drawn points
                foreach (DrawnVertex v in points)
                {
                    if (Vector2D.DistanceSq(mousemappos, v.pos) < (vrange * vrange))
                    {
                        p.pos        = v.pos;
                        p.stitch     = true;
                        p.stitchline = true;
                        return(p);
                    }
                }

                // Try the nearest vertex
                Vertex nv = General.Map.Map.NearestVertexSquareRange(mousemappos, vrange);
                if (nv != null)
                {
                    p.pos        = nv.Position;
                    p.stitch     = true;
                    p.stitchline = true;
                    return(p);
                }

                // Try the nearest linedef
                Linedef nl = General.Map.Map.NearestLinedefRange(mousemappos, BuilderPlug.Me.StitchRange / renderer.Scale);
                if (nl != null)
                {
                    // Snap to grid?
                    if (snaptogrid)
                    {
                        // Get grid intersection coordinates
                        List <Vector2D> coords = nl.GetGridIntersections();

                        // Find nearest grid intersection
                        bool     found          = false;
                        float    found_distance = float.MaxValue;
                        Vector2D found_coord    = new Vector2D();
                        foreach (Vector2D v in coords)
                        {
                            Vector2D delta = mousemappos - v;
                            if (delta.GetLengthSq() < found_distance)
                            {
                                found_distance = delta.GetLengthSq();
                                found_coord    = v;
                                found          = true;
                            }
                        }

                        if (found)
                        {
                            // Align to the closest grid intersection
                            p.pos        = found_coord;
                            p.stitch     = true;
                            p.stitchline = true;
                            return(p);
                        }
                    }
                    else
                    {
                        // Aligned to line
                        p.pos        = nl.NearestOnLine(mousemappos);
                        p.stitch     = true;
                        p.stitchline = true;
                        return(p);
                    }
                }
            }
            else
            {
                // Always snap to the first drawn vertex so that the user can finish a complete sector without stitching
                if (points.Count > 0)
                {
                    if (Vector2D.DistanceSq(mousemappos, points[0].pos) < (vrange * vrange))
                    {
                        p.pos        = points[0].pos;
                        p.stitch     = true;
                        p.stitchline = false;
                        return(p);
                    }
                }
            }

            // if the mouse cursor is outside the map bondaries check if the line between the last set point and the
            // mouse cursor intersect any of the boundary lines. If it does, set the position to this intersection
            if (points.Count > 0 &&
                (mousemappos.x < General.Map.Config.LeftBoundary || mousemappos.x > General.Map.Config.RightBoundary ||
                 mousemappos.y > General.Map.Config.TopBoundary || mousemappos.y < General.Map.Config.BottomBoundary))
            {
                Line2D        dline             = new Line2D(mousemappos, points[points.Count - 1].pos);
                bool          foundintersection = false;
                float         u      = 0.0f;
                List <Line2D> blines = new List <Line2D>();

                // lines for left, top, right and bottom bondaries
                blines.Add(new Line2D(General.Map.Config.LeftBoundary, General.Map.Config.BottomBoundary, General.Map.Config.LeftBoundary, General.Map.Config.TopBoundary));
                blines.Add(new Line2D(General.Map.Config.LeftBoundary, General.Map.Config.TopBoundary, General.Map.Config.RightBoundary, General.Map.Config.TopBoundary));
                blines.Add(new Line2D(General.Map.Config.RightBoundary, General.Map.Config.TopBoundary, General.Map.Config.RightBoundary, General.Map.Config.BottomBoundary));
                blines.Add(new Line2D(General.Map.Config.RightBoundary, General.Map.Config.BottomBoundary, General.Map.Config.LeftBoundary, General.Map.Config.BottomBoundary));

                // check for intersections with boundaries
                for (int i = 0; i < blines.Count; i++)
                {
                    if (!foundintersection)
                    {
                        // only check for intersection if the last set point is not on the
                        // line we are checking against
                        if (blines[i].GetSideOfLine(points[points.Count - 1].pos) != 0.0f)
                        {
                            foundintersection = blines[i].GetIntersection(dline, out u);
                        }
                    }
                }

                // if there was no intersection set the position to the last set point
                if (!foundintersection)
                {
                    vm = points[points.Count - 1].pos;
                }
                else
                {
                    vm = dline.GetCoordinatesAt(u);
                }
            }


            // Snap to grid?
            if (snaptogrid)
            {
                // Aligned to grid
                p.pos = General.Map.Grid.SnappedToGrid(vm);

                // special handling
                if (p.pos.x > General.Map.Config.RightBoundary)
                {
                    p.pos.x = General.Map.Config.RightBoundary;
                }
                if (p.pos.y < General.Map.Config.BottomBoundary)
                {
                    p.pos.y = General.Map.Config.BottomBoundary;
                }
                p.stitch     = snaptonearest;
                p.stitchline = snaptonearest;
                return(p);
            }
            else
            {
                // Normal position
                p.pos        = vm;
                p.stitch     = snaptonearest;
                p.stitchline = snaptonearest;
                return(p);
            }
        }
Exemplo n.º 6
0
        // Mouse moves
        public override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (panning)
            {
                return;                     //mxd. Skip all this jazz while panning
            }
            //mxd
            if (selectpressed && !editpressed && !selecting)
            {
                // Check if moved enough pixels for multiselect
                Vector2D delta = mousedownpos - mousepos;
                if ((Math.Abs(delta.x) > MULTISELECT_START_MOVE_PIXELS) ||
                    (Math.Abs(delta.y) > MULTISELECT_START_MOVE_PIXELS))
                {
                    // Start multiselecting
                    StartMultiSelection();
                }
            }
            else if (paintselectpressed && !editpressed && !selecting)             //mxd. Drag-select
            {
                // Find the nearest thing within highlight range
                Vertex v = General.Map.Map.NearestVertexSquareRange(mousemappos, BuilderPlug.Me.HighlightRange / renderer.Scale);

                if (v != null)
                {
                    if (v != highlighted)
                    {
                        //toggle selected state
                        if (General.Interface.ShiftState ^ BuilderPlug.Me.AdditiveSelect)
                        {
                            v.Selected = true;
                        }
                        else if (General.Interface.CtrlState)
                        {
                            v.Selected = false;
                        }
                        else
                        {
                            v.Selected = !v.Selected;
                        }
                        highlighted = v;

                        UpdateSelectionInfo();                         //mxd

                        // Update entire display
                        General.Interface.RedrawDisplay();
                    }
                }
                else if (highlighted != null)
                {
                    highlighted = null;
                    Highlight(null);

                    // Update entire display
                    General.Interface.RedrawDisplay();
                }
            }
            else if (e.Button == MouseButtons.None)            // Not holding any buttons?
            {
                //mxd. Render insert vertex preview
                Linedef l = General.Map.Map.NearestLinedefRange(mousemappos, BuilderPlug.Me.SplitLinedefsRange / renderer.Scale);

                if (l != null)
                {
                    // Snip to grid?
                    if (General.Interface.ShiftState ^ General.Interface.SnapToGrid)
                    {
                        // Find all points where the grid intersects the line
                        List <Vector2D> points = l.GetGridIntersections();
                        if (points.Count == 0)
                        {
                            insertpreview = l.NearestOnLine(mousemappos);
                        }
                        else
                        {
                            insertpreview = mousemappos;
                            float distance = float.MaxValue;
                            foreach (Vector2D p in points)
                            {
                                float pdist = Vector2D.DistanceSq(p, mousemappos);
                                if (pdist < distance)
                                {
                                    insertpreview = p;
                                    distance      = pdist;
                                }
                            }
                        }
                    }
                    else
                    {
                        // Just use the nearest point on line
                        insertpreview = l.NearestOnLine(mousemappos);
                    }

                    //render preview
                    if (renderer.StartOverlay(true))
                    {
                        float dist  = Math.Min(Vector2D.Distance(mousemappos, insertpreview), BuilderPlug.Me.SplitLinedefsRange);
                        byte  alpha = (byte)(255 - (dist / BuilderPlug.Me.SplitLinedefsRange) * 128);
                        float vsize = (renderer.VertexSize + 1.0f) / renderer.Scale;
                        renderer.RenderRectangleFilled(new RectangleF(insertpreview.x - vsize, insertpreview.y - vsize, vsize * 2.0f, vsize * 2.0f), General.Colors.InfoLine.WithAlpha(alpha), true);
                        renderer.Finish();
                        renderer.Present();
                    }
                }
                else if (insertpreview.IsFinite())
                {
                    insertpreview.x = float.NaN;

                    //undraw preveiw
                    if (renderer.StartOverlay(true))
                    {
                        renderer.Finish();
                        renderer.Present();
                    }
                }

                // Find the nearest vertex within highlight range
                Vertex v = General.Map.Map.NearestVertexSquareRange(mousemappos, BuilderPlug.Me.HighlightRange / renderer.Scale);

                // Highlight if not the same
                if (v != highlighted)
                {
                    Highlight(v);
                }
            }
        }
        // This returns the aligned and snapped draw position
        public static DrawnVertex GetCurrentPosition(Vector2D mousemappos, bool snaptonearest, bool snaptogrid, bool snaptocardinal, bool usefourcardinaldirections, IRenderer2D renderer, List <DrawnVertex> points)
        {
            DrawnVertex p = new DrawnVertex();

            p.stitch       = true;                                 //mxd. Setting these to false seems to be a good way to create invalid geometry...
            p.stitchline   = true;                                 //mxd
            snaptocardinal = (snaptocardinal && points.Count > 0); //mxd. Don't snap to cardinal when there are no points

            //mxd. If snap to cardinal directions is enabled and we have points, modify mouse position
            Vector2D vm, gridoffset;

            if (snaptocardinal)
            {
                Vector2D offset = mousemappos - points[points.Count - 1].pos;

                float angle;
                if (usefourcardinaldirections)
                {
                    angle = Angle2D.DegToRad((General.ClampAngle((int)Angle2D.RadToDeg(offset.GetAngle()))) / 90 * 90 + 45);
                }
                else
                {
                    angle = Angle2D.DegToRad((General.ClampAngle((int)Angle2D.RadToDeg(offset.GetAngle()) + 22)) / 45 * 45);
                }

                offset = new Vector2D(0, -offset.GetLength()).GetRotated(angle);
                vm     = points[points.Count - 1].pos + offset;

                //mxd. We need to be snapped relative to initial position
                Vector2D prev = points[points.Count - 1].pos;
                gridoffset = prev - General.Map.Grid.SnappedToGrid(prev);
            }
            else
            {
                vm         = mousemappos;
                gridoffset = new Vector2D();
            }

            float vrange = BuilderPlug.Me.StitchRange / renderer.Scale;

            // Snap to nearest?
            if (snaptonearest)
            {
                // Go for all drawn points
                foreach (DrawnVertex v in points)
                {
                    if (Vector2D.DistanceSq(vm, v.pos) < (vrange * vrange))
                    {
                        p.pos = v.pos;
                        return(p);
                    }
                }

                // Try the nearest vertex
                Vertex nv = General.Map.Map.NearestVertexSquareRange(vm, vrange);
                if (nv != null)
                {
                    //mxd. Line angle must stay the same
                    if (snaptocardinal)
                    {
                        Line2D ourline = new Line2D(points[points.Count - 1].pos, vm);
                        if (Math.Round(ourline.GetSideOfLine(nv.Position), 1) == 0)
                        {
                            p.pos = nv.Position;
                            return(p);
                        }
                    }
                    else
                    {
                        p.pos = nv.Position;
                        return(p);
                    }
                }

                // Try the nearest linedef. mxd. We'll need much bigger stitch distance when snapping to cardinal directions
                Linedef nl = General.Map.Map.NearestLinedefRange(vm, BuilderPlug.Me.StitchRange / renderer.Scale);
                if (nl != null)
                {
                    //mxd. Line angle must stay the same
                    if (snaptocardinal)
                    {
                        Line2D   ourline      = new Line2D(points[points.Count - 1].pos, vm);
                        Line2D   nearestline  = new Line2D(nl.Start.Position, nl.End.Position);
                        Vector2D intersection = Line2D.GetIntersectionPoint(nearestline, ourline, false);
                        if (!float.IsNaN(intersection.x))
                        {
                            // Intersection is on nearestline?
                            float u = Line2D.GetNearestOnLine(nearestline.v1, nearestline.v2, intersection);

                            if (u < 0f || u > 1f)
                            {
                            }
                            else
                            {
                                p.pos = new Vector2D((float)Math.Round(intersection.x, General.Map.FormatInterface.VertexDecimals),
                                                     (float)Math.Round(intersection.y, General.Map.FormatInterface.VertexDecimals));
                                return(p);
                            }
                        }
                    }
                    // Snap to grid?
                    else if (snaptogrid)
                    {
                        // Get grid intersection coordinates
                        List <Vector2D> coords = nl.GetGridIntersections(General.Map.Grid.GridRotate,
                                                                         General.Map.Grid.GridOriginX, General.Map.Grid.GridOriginY);

                        // Find nearest grid intersection
                        bool     found          = false;
                        float    found_distance = float.MaxValue;
                        Vector2D found_coord    = new Vector2D();
                        foreach (Vector2D v in coords)
                        {
                            Vector2D delta = vm - v;
                            if (delta.GetLengthSq() < found_distance)
                            {
                                found_distance = delta.GetLengthSq();
                                found_coord    = v;
                                found          = true;
                            }
                        }

                        if (found)
                        {
                            // Align to the closest grid intersection
                            p.pos = found_coord;
                            return(p);
                        }
                    }
                    else
                    {
                        // Aligned to line
                        p.pos = nl.NearestOnLine(vm);
                        return(p);
                    }
                }
            }
            else
            {
                // Always snap to the first drawn vertex so that the user can finish a complete sector without stitching
                if (points.Count > 0)
                {
                    if (Vector2D.DistanceSq(vm, points[0].pos) < (vrange * vrange))
                    {
                        p.pos = points[0].pos;
                        return(p);
                    }
                }
            }

            // if the mouse cursor is outside the map bondaries check if the line between the last set point and the
            // mouse cursor intersect any of the boundary lines. If it does, set the position to this intersection
            if (points.Count > 0 &&
                (mousemappos.x < General.Map.Config.LeftBoundary || mousemappos.x > General.Map.Config.RightBoundary ||
                 mousemappos.y > General.Map.Config.TopBoundary || mousemappos.y < General.Map.Config.BottomBoundary))
            {
                Line2D        dline             = new Line2D(mousemappos, points[points.Count - 1].pos);
                bool          foundintersection = false;
                float         u      = 0.0f;
                List <Line2D> blines = new List <Line2D>();

                // lines for left, top, right and bottom boundaries
                blines.Add(new Line2D(General.Map.Config.LeftBoundary, General.Map.Config.BottomBoundary, General.Map.Config.LeftBoundary, General.Map.Config.TopBoundary));
                blines.Add(new Line2D(General.Map.Config.LeftBoundary, General.Map.Config.TopBoundary, General.Map.Config.RightBoundary, General.Map.Config.TopBoundary));
                blines.Add(new Line2D(General.Map.Config.RightBoundary, General.Map.Config.TopBoundary, General.Map.Config.RightBoundary, General.Map.Config.BottomBoundary));
                blines.Add(new Line2D(General.Map.Config.RightBoundary, General.Map.Config.BottomBoundary, General.Map.Config.LeftBoundary, General.Map.Config.BottomBoundary));

                // check for intersections with boundaries
                for (int i = 0; i < blines.Count; i++)
                {
                    if (!foundintersection)
                    {
                        // only check for intersection if the last set point is not on the
                        // line we are checking against
                        if (blines[i].GetSideOfLine(points[points.Count - 1].pos) != 0.0f)
                        {
                            foundintersection = blines[i].GetIntersection(dline, out u);
                        }
                    }
                }

                // if there was no intersection set the position to the last set point
                if (!foundintersection)
                {
                    vm = points[points.Count - 1].pos;
                }
                else
                {
                    vm = dline.GetCoordinatesAt(u);
                }
            }

            // Snap to grid?
            if (snaptogrid)
            {
                // Aligned to grid
                p.pos = General.Map.Grid.SnappedToGrid(vm - gridoffset) + gridoffset;

                // special handling
                if (p.pos.x > General.Map.Config.RightBoundary)
                {
                    p.pos.x = General.Map.Config.RightBoundary;
                }
                if (p.pos.y < General.Map.Config.BottomBoundary)
                {
                    p.pos.y = General.Map.Config.BottomBoundary;
                }

                return(p);
            }
            else
            {
                // Normal position
                p.pos.x = (float)Math.Round(vm.x);                 //mxd
                p.pos.y = (float)Math.Round(vm.y);                 //mxd

                return(p);
            }
        }
Exemplo n.º 8
0
        // This updates the selection
        private void Update()
        {
            // Not in any modifying mode?
            if (mode == ModifyMode.None)
            {
                Vector2D prevdragoffset = alignoffset;
                alignoffset     = new Vector2D(float.MinValue, float.MinValue);
                showalignoffset = false;

                // Check what grip the mouse is over
                // and change cursor accordingly
                Grip mousegrip = CheckMouseGrip();
                switch (mousegrip)
                {
                case Grip.Main:
                    int   closestcorner = -1;
                    float cornerdist    = float.MaxValue;
                    for (int i = 0; i < 4; i++)
                    {
                        Vector2D delta = corners[i] - mousemappos;
                        float    d     = delta.GetLengthSq();
                        if (d < cornerdist)
                        {
                            closestcorner = i;
                            cornerdist    = d;
                        }
                    }
                    switch (closestcorner)
                    {
                    // TODO:
                    case 0: alignoffset = new Vector2D(0f, 0f); break;

                    case 1: alignoffset = new Vector2D(texture.ScaledWidth, 0f); break;

                    case 2: alignoffset = new Vector2D(texture.ScaledWidth, -texture.ScaledHeight); break;

                    case 3: alignoffset = new Vector2D(0f, -texture.ScaledHeight); break;
                    }
                    showalignoffset = true;
                    General.Interface.SetCursor(Cursors.Hand);
                    break;

                case Grip.RotateLB:
                case Grip.RotateRT:
                    alignoffset     = new Vector2D(0f, 0f);
                    showalignoffset = true;
                    General.Interface.SetCursor(Cursors.Cross);
                    break;

                case Grip.SizeH:
                case Grip.SizeV:
                    alignoffset     = new Vector2D(0f, 0f);
                    showalignoffset = true;
                    // Pick the best matching cursor depending on rotation and side
                    float resizeangle = -(rotation + sectorinfo[0].rotation);
                    if (mousegrip == Grip.SizeH)
                    {
                        resizeangle += Angle2D.PIHALF;
                    }
                    resizeangle = Angle2D.Normalized(resizeangle);
                    if (resizeangle > Angle2D.PI)
                    {
                        resizeangle -= Angle2D.PI;
                    }
                    resizeangle = Math.Abs(resizeangle + Angle2D.PI / 8.000001f);
                    int cursorindex = (int)Math.Floor((resizeangle / Angle2D.PI) * 4.0f) % 4;
                    General.Interface.SetCursor(RESIZE_CURSORS[cursorindex]);
                    break;

                default:
                    General.Interface.SetCursor(Cursors.Default);
                    break;
                }

                if (prevdragoffset != alignoffset)
                {
                    General.Interface.RedrawDisplay();
                }
            }
            else
            {
                Vector2D snappedmappos = mousemappos;
                bool     dosnaptogrid  = snaptogrid;

                // Options
                snaptogrid    = General.Interface.ShiftState ^ General.Interface.SnapToGrid;
                snaptonearest = General.Interface.CtrlState ^ General.Interface.AutoMerge;

                // Change to crosshair cursor so we can clearly see around the mouse cursor
                General.Interface.SetCursor(Cursors.Cross);

                // Check what modifying mode we are in
                switch (mode)
                {
                case ModifyMode.Dragging:

                    offset = -mousemappos - dragoffset;
                    Vector2D transformedpos = TexToWorld(alignoffset);

                    // Snap to nearest vertex?
                    if (snaptonearest)
                    {
                        float vrange = BuilderPlug.Me.StitchRange / renderer.Scale;

                        // Try the nearest vertex
                        Vertex nv = MapSet.NearestVertexSquareRange(General.Map.Map.Vertices, transformedpos, vrange);
                        if (nv != null)
                        {
                            // Change offset to snap to target
                            offset      -= nv.Position - transformedpos;
                            dosnaptogrid = false;
                        }
                        else
                        {
                            // Find the nearest line within range
                            Linedef nl = MapSet.NearestLinedefRange(General.Map.Map.Linedefs, transformedpos, vrange);
                            if (nl != null)
                            {
                                // Snap to grid?
                                if (dosnaptogrid)
                                {
                                    // Get grid intersection coordinates
                                    List <Vector2D> coords = nl.GetGridIntersections();

                                    // Find nearest grid intersection
                                    float    found_distance = float.MaxValue;
                                    Vector2D found_pos      = new Vector2D(float.NaN, float.NaN);
                                    foreach (Vector2D v in coords)
                                    {
                                        Vector2D dist = transformedpos - v;
                                        if (dist.GetLengthSq() < found_distance)
                                        {
                                            // Found a better match
                                            found_distance = dist.GetLengthSq();
                                            found_pos      = v;

                                            // Do not snap to grid anymore
                                            dosnaptogrid = false;
                                        }
                                    }

                                    // Found something?
                                    if (!float.IsNaN(found_pos.x))
                                    {
                                        // Change offset to snap to target
                                        offset -= found_pos - transformedpos;
                                    }
                                }
                                else
                                {
                                    // Change offset to snap onto the line
                                    offset -= nl.NearestOnLine(transformedpos) - transformedpos;
                                }
                            }
                        }
                    }

                    // Snap to grid?
                    if (dosnaptogrid)
                    {
                        // Change offset to align to grid
                        offset -= General.Map.Grid.SnappedToGrid(transformedpos) - transformedpos;
                    }

                    break;

                case ModifyMode.Resizing:

                    // Snap to nearest vertex?
                    if (snaptonearest)
                    {
                        float vrange = BuilderPlug.Me.StitchRange / renderer.Scale;

                        // Try the nearest vertex
                        Vertex nv = MapSet.NearestVertexSquareRange(General.Map.Map.Vertices, snappedmappos, vrange);
                        if (nv != null)
                        {
                            snappedmappos = nv.Position;
                            dosnaptogrid  = false;
                        }
                    }

                    // Snap to grid?
                    if (dosnaptogrid)
                    {
                        // Aligned to grid
                        snappedmappos = General.Map.Grid.SnappedToGrid(snappedmappos);
                    }

                    float newscale = 1f / resizeaxis.GetNearestOnLine(snappedmappos);
                    if (float.IsInfinity(newscale) || float.IsNaN(newscale))
                    {
                        newscale = 99999f;
                    }
                    scale = (newscale * resizefilter) + scale * (1.0f - resizefilter);
                    if (float.IsInfinity(scale.x) || float.IsNaN(scale.x))
                    {
                        scale.x = 99999f;
                    }
                    if (float.IsInfinity(scale.y) || float.IsNaN(scale.y))
                    {
                        scale.y = 99999f;
                    }

                    // Show the extension line so that the user knows what it is aligning to
                    UpdateRectangleComponents();
                    Line2D edgeline;
                    if (resizefilter.x > resizefilter.y)
                    {
                        edgeline = new Line2D(corners[1], corners[2]);
                    }
                    else
                    {
                        edgeline = new Line2D(corners[3], corners[2]);
                    }
                    float nearestonedge = edgeline.GetNearestOnLine(snappedmappos);
                    if (nearestonedge > 0.5f)
                    {
                        extensionline = new Line2D(edgeline.v1, snappedmappos);
                    }
                    else
                    {
                        extensionline = new Line2D(edgeline.v2, snappedmappos);
                    }

                    break;

                case ModifyMode.Rotating:

                    // Snap to nearest vertex?
                    extensionline = new Line2D();
                    if (snaptonearest)
                    {
                        float vrange = BuilderPlug.Me.StitchRange / renderer.Scale;

                        // Try the nearest vertex
                        Vertex nv = MapSet.NearestVertexSquareRange(General.Map.Map.Vertices, snappedmappos, vrange);
                        if (nv != null)
                        {
                            snappedmappos = nv.Position;
                            dosnaptogrid  = false;

                            // Show the extension line so that the user knows what it is aligning to
                            extensionline = new Line2D(corners[0], snappedmappos);
                        }
                    }

                    Vector2D delta      = snappedmappos - rotationcenter;
                    float    deltaangle = -delta.GetAngle();

                    // Snap to grid?
                    if (dosnaptogrid)
                    {
                        // We make 8 vectors that the rotation can snap to
                        float founddistance = float.MaxValue;
                        float foundrotation = rotation;
                        for (int i = 0; i < 8; i++)
                        {
                            // Make the vectors
                            float    angle   = (float)i * Angle2D.PI * 0.25f;
                            Vector2D gridvec = Vector2D.FromAngle(angle);
                            Vector3D rotvec  = Vector2D.FromAngle(deltaangle + rotationoffset);

                            // Check distance
                            float dist = 2.0f - Vector2D.DotProduct(gridvec, rotvec);
                            if (dist < founddistance)
                            {
                                foundrotation = angle;
                                founddistance = dist;
                            }
                        }

                        // Keep rotation
                        rotation = foundrotation - sectorinfo[0].rotation;
                    }
                    else
                    {
                        rotation = deltaangle + rotationoffset - sectorinfo[0].rotation;
                    }
                    break;
                }

                UpdateSectors();
                General.Interface.RedrawDisplay();
            }
        }
Exemplo n.º 9
0
        //retrieves the current mouse position on the grid, snapped as necessary
        private Vector2D SnapToNearest(Vector2D vm)
        {
            float vrange     = 20f / renderer.Scale;
            bool  snaptogrid = General.Interface.ShiftState ^ General.Interface.SnapToGrid; //allow temporary disable of snap by holding shift

            if (General.Interface.AutoMerge)                                                //only snap to geometry if the option is enabled
            {
                // Try the nearest slope vertex
                SlopeVertex nh = NearestSlopeVertexSquareRange(vm, vrange);
                if (nh != null)
                {
                    return(nh.Pos);
                }

                // Try the nearest map vertex
                Vertex nv = General.Map.Map.NearestVertexSquareRange(vm, vrange);
                if (nv != null)
                {
                    return(nv.Position);
                }

                // Try the nearest linedef
                Linedef nl = General.Map.Map.NearestLinedefRange(vm, vrange);
                if (nl != null)
                {
                    // Snap to grid?
                    if (snaptogrid)
                    {
                        // Get grid intersection coordinates
                        List <Vector2D> coords = nl.GetGridIntersections();

                        // Find nearest grid intersection
                        bool     found          = false;
                        float    found_distance = float.MaxValue;
                        Vector2D found_coord    = new Vector2D();
                        foreach (Vector2D v in coords)
                        {
                            Vector2D delta = vm - v;
                            if (delta.GetLengthSq() < found_distance)
                            {
                                found_distance = delta.GetLengthSq();
                                found_coord    = v;
                                found          = true;
                            }
                        }

                        if (found)
                        {
                            return(found_coord);
                        }
                    }
                    else
                    {
                        return(nl.NearestOnLine(vm));
                    }
                }
            }

            //Just get the current mouse location instead
            if (snaptogrid)
            {
                return(General.Map.Grid.SnappedToGrid(vm));
            }
            return(vm);
        }
Exemplo n.º 10
0
        // from CodeImp's DrawGeometryMode
        public static Vector2D GetCurrentPosition(Vector2D mousemappos, bool snaptonearest, bool snaptogrid, IRenderer2D renderer)
        {
            Vector2D output = new Vector2D();
            Vector2D vm     = mousemappos;
            float    vrange = BuilderPlug.Me.StitchRange / renderer.Scale;

            // Snap to nearest?
            if (snaptonearest)
            {
                // Try the nearest vertex
                Vertex nv = General.Map.Map.NearestVertexSquareRange(mousemappos, vrange);
                if (nv != null)
                {
                    output = nv.Position;
                    return(output);
                }

                // Try the nearest linedef
                Linedef nl = General.Map.Map.NearestLinedefRange(mousemappos, BuilderPlug.Me.StitchRange / renderer.Scale);
                if (nl != null)
                {
                    // Snap to grid?
                    if (snaptogrid)
                    {
                        // Get grid intersection coordinates
                        List <Vector2D> coords = nl.GetGridIntersections();

                        // Find nearest grid intersection
                        bool     found          = false;
                        float    found_distance = float.MaxValue;
                        Vector2D found_coord    = new Vector2D();
                        foreach (Vector2D v in coords)
                        {
                            Vector2D delta = mousemappos - v;
                            if (delta.GetLengthSq() < found_distance)
                            {
                                found_distance = delta.GetLengthSq();
                                found_coord    = v;
                                found          = true;
                            }
                        }

                        if (found)
                        {
                            // Align to the closest grid intersection
                            output = found_coord;
                            return(output);
                        }
                    }
                    else
                    {
                        // Aligned to line
                        output = nl.NearestOnLine(mousemappos);
                        return(output);
                    }
                }
            }


            // Snap to grid?
            if (snaptogrid)
            {
                // Aligned to grid
                output = General.Map.Grid.SnappedToGrid(vm);

                // special handling
                if (output.x > General.Map.Config.RightBoundary)
                {
                    output.x = General.Map.Config.RightBoundary;
                }
                if (output.y < General.Map.Config.BottomBoundary)
                {
                    output.y = General.Map.Config.BottomBoundary;
                }
                return(output);
            }
            else
            {
                // Normal position
                output = vm;
                return(output);
            }
        }
Exemplo n.º 11
0
        private void InsertVertex()
        {
            bool snaptogrid    = General.Interface.ShiftState ^ General.Interface.SnapToGrid;
            bool snaptonearest = General.Interface.CtrlState ^ General.Interface.AutoMerge;

            // Mouse in window?
            if (General.Interface.MouseInDisplay)
            {
                Vector2D insertpos;

                // Create undo
                General.Map.UndoRedo.CreateUndo("Insert vertex");

                // Snap to geometry?
                Linedef l = MapSet.NearestLinedefRange(blockmap, mousemappos, BuilderPlug.Me.SplitLinedefsRange / renderer.Scale);
                if (snaptonearest && (l != null))
                {
                    // Snip to grid also?
                    if (snaptogrid)
                    {
                        // Find all points where the grid intersects the line
                        List <Vector2D> points = l.GetGridIntersections(General.Map.Grid.GridRotate, General.Map.Grid.GridOriginX, General.Map.Grid.GridOriginY);
                        if (points.Count == 0)
                        {
                            //mxd. Just use the nearest point on line
                            insertpos = l.NearestOnLine(mousemappos);
                        }
                        else
                        {
                            insertpos = mousemappos;
                            double distance = double.MaxValue;
                            foreach (Vector2D p in points)
                            {
                                double pdist = Vector2D.DistanceSq(p, mousemappos);
                                if (pdist < distance)
                                {
                                    insertpos = p;
                                    distance  = pdist;
                                }
                            }
                        }
                    }
                    else
                    {
                        // Just use the nearest point on line
                        insertpos = l.NearestOnLine(mousemappos);
                    }
                }
                // Snap to grid?
                else if (snaptogrid)
                {
                    // Snap to grid
                    insertpos = General.Map.Grid.SnappedToGrid(mousemappos);
                }
                else
                {
                    // Just insert here, don't snap to anything
                    insertpos = mousemappos;
                }

                // Make the vertex
                Vertex v = General.Map.Map.CreateVertex(insertpos);
                if (v == null)
                {
                    General.Map.UndoRedo.WithdrawUndo();
                    return;
                }

                // Snap to map format accuracy
                v.SnapToAccuracy();

                // Split the line with this vertex
                if (snaptonearest)
                {
                    //mxd. Check if snapped vertex is still on top of a linedef
                    l = MapSet.NearestLinedefRange(blockmap, v.Position, BuilderPlug.Me.SplitLinedefsRange / renderer.Scale);

                    if (l != null)
                    {
                        //mxd
                        if (v.Position == l.Start.Position || v.Position == l.End.Position)
                        {
                            General.Interface.DisplayStatus(StatusType.Info, "There's already a vertex here.");
                            General.Map.UndoRedo.WithdrawUndo();
                            return;
                        }

                        General.Interface.DisplayStatus(StatusType.Action, "Split a linedef.");
                        Linedef sld = l.Split(v);
                        if (sld == null)
                        {
                            General.Map.UndoRedo.WithdrawUndo();
                            return;
                        }
                        //BuilderPlug.Me.AdjustSplitCoordinates(l, sld);
                    }
                }
                else
                {
                    General.Interface.DisplayStatus(StatusType.Action, "Inserted a vertex.");
                }

                // Create the blockmap
                CreateBlockmap();

                // Update
                General.Map.Map.Update();

                // Redraw screen
                General.Interface.RedrawDisplay();
            }
        }
Exemplo n.º 12
0
        // This moves the selected geometry relatively
        // Returns true when geometry has actually moved
        private bool MoveGeometryRelative(Vector2D offset, bool snapgrid, bool snapgridincrement, bool snapnearest, bool snapcardinal)
        {
            //mxd. If snap to cardinal directions is enabled, modify the offset
            if (snapcardinal)
            {
                double angle = Angle2D.DegToRad((General.ClampAngle((int)Angle2D.RadToDeg(offset.GetAngle()) + 44)) / 90 * 90);
                offset            = new Vector2D(0, -offset.GetLength()).GetRotated(angle);
                snapgridincrement = true;                 // We don't want to move the geometry away from the cardinal directions
            }

            Vector2D oldpos = dragitem.Position;
            Vector2D anchorpos = dragitemposition + offset;
            Vector2D tl, br;

            // don't move if the offset contains invalid data
            if (!offset.IsFinite())
            {
                return(false);
            }

            // Find the outmost vertices
            tl = br = oldpositions[0];
            for (int i = 0; i < oldpositions.Count; i++)
            {
                if (oldpositions[i].x < tl.x)
                {
                    tl.x = (int)oldpositions[i].x;
                }
                if (oldpositions[i].x > br.x)
                {
                    br.x = (int)oldpositions[i].x;
                }
                if (oldpositions[i].y > tl.y)
                {
                    tl.y = (int)oldpositions[i].y;
                }
                if (oldpositions[i].y < br.y)
                {
                    br.y = (int)oldpositions[i].y;
                }
            }

            // Snap to nearest?
            if (snapnearest)
            {
                // Find nearest unselected vertex within range
                Vertex nv = MapSet.NearestVertexSquareRange(unselectedverts, anchorpos, BuilderPlug.Me.StitchRange / renderer.Scale);
                if (nv != null)
                {
                    // Move the dragged item
                    dragitem.Move(nv.Position);

                    // Adjust the offset
                    offset = nv.Position - dragitemposition;

                    // Do not snap to grid!
                    snapgrid            = false;
                    snaptogridincrement = false;                     //mxd
                }
                else
                {
                    // Find the nearest unselected line within range
                    Linedef nl = MapSet.NearestLinedefRange(snaptolines, anchorpos, BuilderPlug.Me.StitchRange / renderer.Scale);
                    if (nl != null)
                    {
                        // Snap to grid?
                        if (snapgrid || snapgridincrement)
                        {
                            // Get grid intersection coordinates
                            List <Vector2D> coords = nl.GetGridIntersections(snapgridincrement ? dragstartoffset : new Vector2D(),
                                                                             General.Map.Grid.GridRotate, General.Map.Grid.GridOriginX, General.Map.Grid.GridOriginY);

                            // mxd. Do the rest only if we actually have some coordinates
                            if (coords.Count > 0)
                            {
                                // Find nearest grid intersection
                                double   found_distance = double.MaxValue;
                                Vector2D found_coord    = new Vector2D();

                                foreach (Vector2D v in coords)
                                {
                                    Vector2D delta = anchorpos - v;
                                    if (delta.GetLengthSq() < found_distance)
                                    {
                                        found_distance = delta.GetLengthSq();
                                        found_coord    = v;
                                    }
                                }

                                // Move the dragged item
                                dragitem.Move(found_coord);

                                // Align to line here
                                offset = found_coord - dragitemposition;

                                // Do not snap to grid anymore
                                snapgrid          = false;
                                snapgridincrement = false;                                 //mxd
                            }
                        }
                        else
                        {
                            // Move the dragged item
                            dragitem.Move(nl.NearestOnLine(anchorpos));

                            // Align to line here
                            offset = nl.NearestOnLine(anchorpos) - dragitemposition;
                        }
                    }
                }
            }

            // Snap to grid or grid increment?
            if (snapgrid || snapgridincrement)
            {
                // Move the dragged item
                dragitem.Move(anchorpos);

                // Snap item to grid increment
                if (snapgridincrement)                //mxd
                {
                    dragitem.Move(General.Map.Grid.SnappedToGrid(dragitem.Position) - dragstartoffset);
                }
                else                 // Or to the grid itself
                {
                    dragitem.SnapToGrid();
                }

                // Adjust the offset
                offset += dragitem.Position - anchorpos;
            }

            // Make sure the offset is inside the map boundaries
            if (offset.x + tl.x < General.Map.Config.LeftBoundary)
            {
                offset.x = General.Map.Config.LeftBoundary - tl.x;
            }
            if (offset.x + br.x > General.Map.Config.RightBoundary)
            {
                offset.x = General.Map.Config.RightBoundary - br.x;
            }
            if (offset.y + tl.y > General.Map.Config.TopBoundary)
            {
                offset.y = General.Map.Config.TopBoundary - tl.y;
            }
            if (offset.y + br.y < General.Map.Config.BottomBoundary)
            {
                offset.y = General.Map.Config.BottomBoundary - br.y;
            }

            // Drag item moved?
            if ((!snapgrid && !snapgridincrement) || (dragitem.Position != oldpos))
            {
                int i = 0;

                // Move selected geometry
                foreach (Vertex v in selectedverts)
                {
                    // Move vertex from old position relative to the mouse position change since drag start
                    v.Move(oldpositions[i++] + offset);
                }

                //mxd. Move selected things
                i = 0;
                foreach (Thing t in thingstodrag)
                {
                    t.Move(oldthingpositions[i++] + offset);
                }

                // Update labels
                int index = 0;
                foreach (Linedef l in unstablelines)
                {
                    labels[index++].Move(l.Start.Position, l.End.Position);
                }

                // Moved
                return(true);
            }

            // No changes
            return(false);
        }
Exemplo n.º 13
0
        // FIXME provide a version with snaptogrid based on shift key but no snaptonearest
        public static LuaVector2D GetMouseMapPosition(bool snaptogrid, bool snaptonearest)
        {
            Vector2D mousemappos = ScriptContext.context.mousemappos;

            // Snap to nearest?
            if (snaptonearest)
            {
                float vrange = BuilderPlug.Me.StitchRange / ScriptContext.context.rendererscale;

                // Try the nearest vertex
                Vertex nv = General.Map.Map.NearestVertexSquareRange(mousemappos, vrange);
                if (nv != null)
                {
                    return(new LuaVector2D(nv.Position));
                }

                // Try the nearest linedef
                Linedef nl = General.Map.Map.NearestLinedefRange(mousemappos, vrange);
                if (nl != null)
                {
                    // Snap to grid?
                    if (snaptogrid)
                    {
                        // Get grid intersection coordinates
                        List <Vector2D> coords = nl.GetGridIntersections();

                        // Find nearest grid intersection
                        bool     found          = false;
                        float    found_distance = float.MaxValue;
                        Vector2D found_coord    = new Vector2D();
                        foreach (Vector2D v in coords)
                        {
                            Vector2D delta = mousemappos - v;
                            if (delta.GetLengthSq() < found_distance)
                            {
                                found_distance = delta.GetLengthSq();
                                found_coord    = v;
                                found          = true;
                            }
                        }

                        if (found)
                        {
                            // Align to the closest grid intersection
                            return(new LuaVector2D(found_coord));
                        }
                    }
                    else
                    {
                        return(new LuaVector2D(nl.NearestOnLine(mousemappos)));
                    }
                }
            }

            if (snaptogrid)
            {
                return(new LuaVector2D(General.Map.Grid.SnappedToGrid(mousemappos)));
            }
            else
            {
                return(new LuaVector2D(new Vector2D(
                                           (float)Math.Round(mousemappos.x, General.Map.FormatInterface.VertexDecimals),
                                           (float)Math.Round(mousemappos.y, General.Map.FormatInterface.VertexDecimals)
                                           )));
            }
        }