public void OnChangeTargetHeight(int amount)
        {
            VisualSlope pivothandle = null;
            List <IVisualEventReceiver> selectedsectors = mode.GetSelectedObjects(true, false, false, false, false);
            List <SectorLevel>          levels          = new List <SectorLevel>();

            if (selectedsectors.Count == 0)
            {
                levels.Add(level);
            }
            else
            {
                foreach (BaseVisualGeometrySector bvgs in selectedsectors)
                {
                    levels.Add(bvgs.Level);
                }

                if (!levels.Contains(level))
                {
                    levels.Add(level);
                }
            }

            // Try to find a slope handle the user set to be the pivot handle
            // TODO: doing this every time is kind of stupid. Maybe store the pivot handle in the mode?
            foreach (KeyValuePair <Sector, List <VisualSlope> > kvp in mode.AllSlopeHandles)
            {
                foreach (VisualSidedefSlope handle in kvp.Value)
                {
                    if (handle.Pivot)
                    {
                        pivothandle = handle;
                        break;
                    }
                }
            }

            // User didn't set a pivot handle, try to find the smart pivot handle
            if (pivothandle == null)
            {
                pivothandle = GetSmartPivotHandle(this, mode);
            }

            // Still no pivot handle, cancle
            if (pivothandle == null)
            {
                return;
            }

            pivothandle.SmartPivot = true;

            mode.CreateUndo("Change slope");

            Plane originalplane = level.plane;
            Plane pivotplane    = ((VisualSidedefSlope)pivothandle).Level.plane;

            // Build a new plane. p1 and p2 are the points of the slope handle that is modified, p3 is on the line of the pivot handle
            Vector3D p1 = new Vector3D(sidedef.Line.Start.Position, (float)Math.Round(originalplane.GetZ(sidedef.Line.Start.Position)));
            Vector3D p2 = new Vector3D(sidedef.Line.End.Position, (float)Math.Round(originalplane.GetZ(sidedef.Line.End.Position)));
            Vector3D p3 = new Vector3D(((VisualSidedefSlope)pivothandle).Sidedef.Line.Line.GetCoordinatesAt(0.5f), (float)Math.Round(pivotplane.GetZ(((VisualSidedefSlope)pivothandle).Sidedef.Line.Line.GetCoordinatesAt(0.5f))));

            // Move the points of the handle up/down
            p1 += new Vector3D(0f, 0f, amount);
            p2 += new Vector3D(0f, 0f, amount);

            Plane plane = new Plane(p1, p2, p3, true);

            // Apply slope to surfaces
            foreach (SectorLevel l in levels)
            {
                ApplySlope(l, plane, mode);
            }

            mode.SetActionResult("Changed slope.");
        }
Пример #2
0
        public override void OnChangeTargetHeight(int amount)
        {
            VisualSlope pivothandle = null;
            List <IVisualEventReceiver> selectedsectors = mode.GetSelectedObjects(true, false, false, false, false);
            List <SectorLevel>          levels          = new List <SectorLevel>();

            if (selectedsectors.Count == 0)
            {
                levels.Add(level);
            }
            else
            {
                foreach (BaseVisualGeometrySector bvgs in selectedsectors)
                {
                    levels.Add(bvgs.Level);
                }

                if (!levels.Contains(level))
                {
                    levels.Add(level);
                }
            }

            // Try to find a slope handle the user set to be the pivot handle
            // TODO: doing this every time is kind of stupid. Maybe store the pivot handle in the mode?
            foreach (KeyValuePair <Sector, List <VisualSlope> > kvp in mode.AllSlopeHandles)
            {
                foreach (VisualSlope handle in kvp.Value)
                {
                    if (handle.Pivot)
                    {
                        pivothandle = handle;
                        break;
                    }
                }
            }

            // User didn't set a pivot handle, try to find the smart pivot handle
            if (pivothandle == null)
            {
                pivothandle = GetSmartPivotHandle();
            }

            // Still no pivot handle, cancle
            if (pivothandle == null)
            {
                return;
            }

            mode.CreateUndo("Change slope");

            Plane originalplane = level.plane;

            Vector3D p1, p2, p3;

            if (pivothandle is VisualVertexSlope)
            {
                // Build a new plane. Since we only got 2 points (the pivot point of the pivot handle and the vertex slope vertex) we need
                // to create a third point. That's done by getting the perpendicular of the line between the aforementioned 2 points, then
                // add the perpendicular to the vertex position of the vertex slope vertex
                p3 = pivothandle.GetPivotPoint();
                Vector2D perp = new Line2D(vertex.Position, p3).GetPerpendicular();

                p1 = new Vector3D(vertex.Position, originalplane.GetZ(vertex.Position) + amount);
                p2 = new Vector3D(vertex.Position + perp, originalplane.GetZ(vertex.Position + perp) + amount);
            }
            else             // VisualSidedefSlope
            {
                List <Vector3D> pivotpoints = ((VisualSidedefSlope)pivothandle).GetPivotPoints();
                p1 = new Vector3D(vertex.Position, originalplane.GetZ(vertex.Position) + amount);
                p2 = pivotpoints[0];
                p3 = pivotpoints[1];
            }

            Plane plane = new Plane(p1, p2, p3, true);

            // Apply slope to surfaces
            foreach (SectorLevel l in levels)
            {
                VisualSidedefSlope.ApplySlope(l, plane, mode);
            }

            mode.SetActionResult("Changed slope.");
        }
Пример #3
0
        /// <summary>
        /// Tries to find a slope handle to pivot around. If possible if finds the handle belonging to a line that has the
        /// same angle as the start handle, and is the furthest away. If such a handle does not exist it finds one that's
        /// closest to those specs
        /// </summary>
        /// <returns></returns>
        public override VisualSlope GetSmartPivotHandle()
        {
            List <IVisualEventReceiver> selectedsectors = mode.GetSelectedObjects(true, false, false, false, false);

            // Special handling for triangular sectors
            if (selectedsectors.Count == 0 && BuilderPlug.Me.UseOppositeSmartPivotHandle && sidedef.Sector.Sidedefs.Count == 3)
            {
                foreach (VisualVertexSlope vvs in mode.VertexSlopeHandles[sidedef.Sector])
                {
                    if (vvs.Level == level && !vvs.Vertex.Linedefs.Contains(sidedef.Line))
                    {
                        return(vvs);
                    }
                }
            }

            VisualSlope handle = this;
            List <VisualSidedefSlope> potentialhandles = new List <VisualSidedefSlope>();

            if (selectedsectors.Count == 0)
            {
                // No sectors selected, so find all handles that belong to the same level
                foreach (VisualSidedefSlope checkhandle in mode.SidedefSlopeHandles[sidedef.Sector])
                {
                    if (checkhandle != this && checkhandle.Level == level)
                    {
                        potentialhandles.Add(checkhandle);
                    }
                }
            }
            else
            {
                // Sectors are selected, get all handles from those sectors that have the same level
                HashSet <Sector> sectors = new HashSet <Sector>();

                foreach (BaseVisualGeometrySector bvgs in selectedsectors)
                {
                    sectors.Add(bvgs.Sector.Sector);
                }

                foreach (Sector s in sectors)
                {
                    foreach (VisualSidedefSlope checkhandle in mode.SidedefSlopeHandles[s])
                    {
                        if (checkhandle != this)
                        {
                            foreach (BaseVisualGeometrySector bvgs in selectedsectors)
                            {
                                if (bvgs.Level == checkhandle.Level)
                                {
                                    potentialhandles.Add(checkhandle);
                                }
                            }
                        }
                    }
                }
            }

            // Sort potential handles by their angle difference to the start handle. That means that handles with less angle difference will be at the beginning of the list
            List <VisualSidedefSlope> anglediffsortedhandles = potentialhandles.OrderBy(h => Math.Abs(NormalizedAngleDeg - h.NormalizedAngleDeg)).ToList();

            // Get all potential handles that have to same angle as the one that's closest to the start handle, then sort them by distance, and take the one that's furthest away
            if (anglediffsortedhandles.Count > 0)
            {
                handle = anglediffsortedhandles.Where(h => h.NormalizedAngleDeg == anglediffsortedhandles[0].NormalizedAngleDeg).OrderByDescending(h => Math.Abs(sidedef.Line.Line.GetDistanceToLine(h.sidedef.Line.GetCenterPoint(), false))).First();
            }

            if (handle == this)
            {
                return(null);
            }

            return(handle);
        }
Пример #4
0
        /// <summary>
        /// Finds a slope handle to pivot around. It takes the vertex that's furthest away from the given handle
        /// </summary>
        /// <returns></returns>
        public override VisualSlope GetSmartPivotHandle()
        {
            List <IVisualEventReceiver> selectedsectors = mode.GetSelectedObjects(true, false, false, false, false);

            // Special handling for triangular sectors
            if (selectedsectors.Count == 0 && BuilderPlug.Me.UseOppositeSmartPivotHandle && sector.Sidedefs.Count == 3)
            {
                foreach (VisualSidedefSlope vss in mode.SidedefSlopeHandles[sector])
                {
                    if (vss.Level == level && !(vss.Sidedef.Line.Start == vertex || vss.Sidedef.Line.End == vertex))
                    {
                        return(vss);
                    }
                }
            }

            VisualSlope handle = this;
            List <VisualVertexSlope> potentialhandles = new List <VisualVertexSlope>();

            if (selectedsectors.Count == 0)
            {
                // No sectors selected, so find all handles that belong to the same level
                foreach (VisualVertexSlope checkhandle in mode.VertexSlopeHandles[sector])
                {
                    if (checkhandle != this && checkhandle.Level == level)
                    {
                        potentialhandles.Add(checkhandle);
                    }
                }
            }
            else
            {
                // Sectors are selected, get all handles from those sectors that have the same level
                HashSet <Sector> sectors = new HashSet <Sector>();

                foreach (BaseVisualGeometrySector bvgs in selectedsectors)
                {
                    sectors.Add(bvgs.Sector.Sector);
                }

                foreach (Sector s in sectors)
                {
                    foreach (VisualVertexSlope checkhandle in mode.VertexSlopeHandles[s])
                    {
                        if (checkhandle != this)
                        {
                            foreach (BaseVisualGeometrySector bvgs in selectedsectors)
                            {
                                if (bvgs.Level == checkhandle.Level)
                                {
                                    potentialhandles.Add(checkhandle);
                                }
                            }
                        }
                    }
                }
            }

            handle = potentialhandles.OrderByDescending(h => Vector2D.Distance(h.Vertex.Position, vertex.Position)).First();

            if (handle == this)
            {
                return(null);
            }

            return(handle);
        }