Пример #1
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();
            }
        }
        // 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);
            }
        }
Пример #3
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);
        }