Example #1
0
        /// <summary>
        /// This returns the height of the upper wall part. Returns 0 when no upper part exists.
        /// </summary>

        /*public int GetHighHeight()
         * {
         *      Sidedef other = this.Other;
         *      if(other != null)
         *      {
         *              int top = this.sector.CeilHeight;
         *              int bottom = other.sector.CeilHeight;
         *              int height = top - bottom;
         *              return (height > 0) ? height : 0;
         *      }
         *      else
         *      {
         *              return 0;
         *      }
         * }*/

        /// <summary>
        /// This returns the height of the middle wall part.
        /// </summary>

        /*public int GetMiddleHeight()
         * {
         *      Sidedef other = this.Other;
         *      if(other != null)
         *      {
         *              int top = Math.Min(this.Sector.CeilHeight, other.Sector.CeilHeight);
         *              int bottom = Math.Max(this.Sector.FloorHeight, other.Sector.FloorHeight);
         *              int height = top - bottom;
         *              return (height > 0) ? height : 0;
         *      }
         *      else
         *      {
         *              int top = this.Sector.CeilHeight;
         *              int bottom = this.Sector.FloorHeight;
         *              int height = top - bottom;
         *              return (height > 0) ? height : 0;
         *      }
         * }*/

        /// <summary>
        /// This returns the height of the lower wall part. Returns 0 when no lower part exists.
        /// </summary>

        /*public int GetLowHeight()
         * {
         *      Sidedef other = this.Other;
         *      if(other != null)
         *      {
         *              int top = other.sector.FloorHeight;
         *              int bottom = this.sector.FloorHeight;
         *              int height = top - bottom;
         *              return (height > 0) ? height : 0;
         *      }
         *      else
         *      {
         *              return 0;
         *      }
         * }*/

        // This copies textures to another sidedef
        // And possibly also the offsets
        public void AddTexturesTo(Sidedef s)
        {
            // s cannot be null
            if (s == null)
            {
                return;
            }

            s.BeforePropsChange();
            bool copyoffsets = false;

            //TODO: investigate "masking wall" / "bottoms of invisible walls swapped" wall flags
            // Texture set?
            if (tileindex > 0)
            {
                s.tileindex = tileindex;
                copyoffsets = true;
            }

            // Masked texture set?
            if (maskedtileindex > 0 && s.Other != null)
            {
                s.maskedtileindex = maskedtileindex;
                copyoffsets       = true;
            }

            // Copy offsets?
            if (copyoffsets)
            {
                s.offsetx = offsetx;
                s.offsety = offsety;
            }

            General.Map.IsChanged = true;
        }
Example #2
0
        // This detaches a sidedef
        internal void DetachSidedefP(LinkedListNode <Sidedef> l)
        {
            // Not disposing?
            if (!isdisposed)
            {
                // Remove sidedef
                updateneeded             = true;
                ceilingplaneupdateneeded = true;
                floorplaneupdateneeded   = true;
                triangulationneeded      = true;
                sidedefs.Remove(l);

                // No more sidedefs left?
                if (sidedefs.Count == 0 && map.AutoRemove)
                {
                    // This sector is now useless, dispose it
                    this.Dispose();
                }
                //mxd. FirstWall was detached?
                else if (l.Value == firstwall)
                {
                    firstwall = (sidedefs.Count > 0 ? sidedefs.First.Value : null);
                }
            }
        }
Example #3
0
 // This detaches a sidedef from the front
 internal void DetachSidedefP(Sidedef s)
 {
     // Sidedef is on the front?
     if (front == s)
     {
         // Remove sidedef reference
         if (front != null)
         {
             front.SetLinedefP(null);
         }
         front        = null;
         updateneeded = true;
     }
     // Sidedef is on the back?
     else if (back == s)
     {
         // Remove sidedef reference
         if (back != null)
         {
             back.SetLinedefP(null);
         }
         back         = null;
         updateneeded = true;
     }
 }
Example #4
0
        // This changes sidedefs (used for joining lines)
        // target:		The linedef on which to remove or create a new sidedef
        // front:		Side on which to remove or create the sidedef (true for front side)
        // newside:		The side from which to copy the properties to the new sidedef.
        //				If this is null, no sidedef will be created (only removed)
        // Returns false when the operation could not be completed.
        private bool JoinChangeSidedefs(Linedef target, bool front, Sidedef newside)
        {
            // Change sidedefs
            if (front)
            {
                if (target.front != null)
                {
                    target.front.Dispose();
                }
            }
            else
            {
                if (target.back != null)
                {
                    target.back.Dispose();
                }
            }

            if (newside != null)
            {
                Sidedef sd = map.CreateSidedef(target, front, newside.Sector);
                if (sd == null)
                {
                    return(false);
                }
                newside.CopyPropertiesTo(sd);
                sd.Marked = newside.Marked;
            }

            return(true);
        }
Example #5
0
        // Disposer
        public override void Dispose()
        {
            // Not already disposed?
            if (!isdisposed)
            {
                // Already set isdisposed so that changes can be prohibited
                isdisposed = true;

                // Dispose sidedefs
                if ((front != null) && map.AutoRemove)
                {
                    front.Dispose();
                }
                else
                {
                    AttachFrontP(null);
                }
                if ((back != null) && map.AutoRemove)
                {
                    back.Dispose();
                }
                else
                {
                    AttachBackP(null);
                }

                if (map == General.Map.Map)
                {
                    General.Map.UndoRedo.RecRemLinedef(this);
                }

                // Remove from main list
                map.RemoveLinedef(listindex);

                // Detach from vertices
                if (startvertexlistitem != null)
                {
                    start.DetachLinedefP(startvertexlistitem);
                }
                startvertexlistitem = null;
                start = null;
                if (endvertexlistitem != null)
                {
                    end.DetachLinedefP(endvertexlistitem);
                }
                endvertexlistitem = null;
                end = null;

                // Clean up
                start = null;
                end   = null;
                front = null;
                back  = null;
                map   = null;

                // Clean up base
                base.Dispose();
            }
        }
Example #6
0
 // Passive version, does not record the change
 internal void AttachBackP(Sidedef s)
 {
     // Attach and recalculate
     back = s;
     if (back != null)
     {
         back.SetLinedefP(this);
     }
     updateneeded = true;
 }
Example #7
0
        // This attaches a sidedef on the back
        internal void AttachBack(Sidedef s)
        {
            if (map == General.Map.Map)
            {
                General.Map.UndoRedo.RecRefLinedefBack(this);
            }

            // Attach and recalculate
            AttachBackP(s);
        }
Example #8
0
 // Passive version, does not record the change
 internal void AttachFrontP(Sidedef s)
 {
     // Attach and recalculate
     front = s;
     if (front != null)
     {
         front.SetLinedefP(this);
     }
     updateneeded = true;
 }
Example #9
0
        // This attaches a sidedef and returns the listitem
        internal LinkedListNode <Sidedef> AttachSidedefP(Sidedef sd)
        {
            //mxd. Set first wall?
            if (firstwall == null)
            {
                firstwall = sd;
            }

            updateneeded             = true;
            triangulationneeded      = true;
            ceilingplaneupdateneeded = true;
            floorplaneupdateneeded   = true;
            return(sidedefs.AddLast(sd));
        }
Example #10
0
        // This splits this line by vertex v
        // Returns the new line resulting from the split, or null when it failed
        public Linedef Split(Vertex v)
        {
            // Copy linedef and change vertices
            Linedef nl = map.CreateLinedef(v, end);

            if (nl == null)
            {
                return(null);
            }
            CopyPropertiesTo(nl);
            SetEndVertex(v);
            nl.Selected = this.Selected;
            nl.marked   = this.marked;

            // Copy front wall if exists
            if (front != null)
            {
                Sidedef nsd = map.CreateSidedef(nl, true, front.Sector);
                if (nsd == null)
                {
                    return(null);
                }
                front.CopyPropertiesTo(nsd);
                nsd.Marked = front.Marked;

                // Make texture offset adjustments
                //TODO: works differently in Build...
                nsd.OffsetX += (int)Vector2D.Distance(this.start.Position, this.end.Position);
            }

            // Copy back wall if exists
            if (back != null)
            {
                Sidedef nsd = map.CreateSidedef(nl, false, back.Sector);
                if (nsd == null)
                {
                    return(null);
                }
                back.CopyPropertiesTo(nsd);
                nsd.Marked = back.Marked;

                // Make texture offset adjustments
                //TODO: works differently in Build...
                back.OffsetX += (int)Vector2D.Distance(nl.start.Position, nl.end.Position);
            }

            // Return result
            General.Map.IsChanged = true;
            return(nl);
        }
Example #11
0
        // Disposer
        public override void Dispose()
        {
            // Not already disposed?
            if (!isdisposed)
            {
                // Already set isdisposed so that changes can be prohibited
                isdisposed = true;

                // Dispose the sidedefs that are attached to this sector
                // because a sidedef cannot exist without reference to its sector.
                if (map.AutoRemove)
                {
                    foreach (Sidedef sd in sidedefs)
                    {
                        sd.Dispose();
                    }
                }
                else
                {
                    foreach (Sidedef sd in sidedefs)
                    {
                        sd.SetSectorP(null);
                    }
                }

                if (map == General.Map.Map)
                {
                    General.Map.UndoRedo.RecRemSector(this);
                }

                // Remove from main list
                map.RemoveSector(listindex);

                // Free surface entry
                General.Map.CRenderer2D.Surfaces.FreeSurfaces(surfaceentries);

                // Clean up
                firstwall = null;
                sidedefs  = null;
                map       = null;

                // Dispose base
                base.Dispose();
            }
        }
Example #12
0
        // This copies all properties to another sidedef
        public void CopyPropertiesTo(Sidedef s)
        {
            s.BeforePropsChange();

            // Copy build properties
            s.flags           = new Dictionary <string, bool>(flags, StringComparer.Ordinal);
            s.offsetx         = offsetx;
            s.offsety         = offsety;
            s.repeatx         = repeatx;
            s.repeaty         = repeaty;
            s.tileindex       = tileindex;
            s.maskedtileindex = maskedtileindex;
            s.shade           = shade;
            s.paletteindex    = paletteindex;

            s.hitag = hitag;
            s.lotag = lotag;
            s.extra = extra;
        }
Example #13
0
        // This flips the sidedefs
        public void FlipSidedefs()
        {
            //mxd. FirstWalls may need updating
            if (front != null && front == front.Sector.FirstWall)
            {
                front.Sector.FirstWall = (back ?? General.GetByIndex(front.Sector.Sidedefs, 0));
            }
            if (back != null && back == back.Sector.FirstWall)
            {
                back.Sector.FirstWall = (front ?? General.GetByIndex(back.Sector.Sidedefs, 0));
            }

            // Flip sidedefs
            Sidedef oldfront = front;
            Sidedef oldback  = back;

            AttachFront(oldback);
            AttachBack(oldfront);

            General.Map.IsChanged = true;
        }
Example #14
0
        // Constructor
        internal Sector(MapSet map, int listindex)
        {
            // Initialize
            this.map                      = map;
            this.listindex                = listindex;
            this.sidedefs                 = new LinkedList <Sidedef>();
            this.updateneeded             = true;
            this.ceilingplaneupdateneeded = true;
            this.floorplaneupdateneeded   = true;
            this.triangulationneeded      = true;
            this.surfaceentries           = new SurfaceEntryCollection();
            this.floorflags               = new Dictionary <string, bool>(StringComparer.Ordinal);
            this.ceilingflags             = new Dictionary <string, bool>(StringComparer.Ordinal);
            this.firstwall                = null;
            this.extra                    = -1;
            this.floorslope               = Angle2D.PIHALF; //mxd
            this.ceilingslope             = Angle2D.PIHALF; //mxd

            if (map == General.Map.Map)
            {
                General.Map.UndoRedo.RecAddSector(this);
            }
        }
Example #15
0
        //mxd. Moved here from Tools. This finds the ideal label position for a sector
        private static LabelPositionInfo FindLabelPosition(Sector s)
        {
            // Do we have a triangulation?
            Triangulation triangles = s.Triangles;

            if (triangles != null)
            {
                // Go for all islands
                foreach (int iv in triangles.IslandVertices)
                {
                    Dictionary <Sidedef, Linedef> sides = new Dictionary <Sidedef, Linedef>(iv >> 1);
                    List <Vector2D> candidatepositions  = new List <Vector2D>(iv >> 1);
                    float           founddistance       = float.MinValue;
                    Vector2D        foundposition       = new Vector2D();
                    float           minx = float.MaxValue;
                    float           miny = float.MaxValue;
                    float           maxx = float.MinValue;
                    float           maxy = float.MinValue;

                    // Make candidate lines that are not along sidedefs
                    // We do this before testing the candidate against the sidedefs so that
                    // we can collect the relevant sidedefs first in the same run
                    for (int t = 0; t < iv; t += 3)
                    {
                        Vector2D v1 = triangles.Vertices[t + 2];
                        Sidedef  sd = triangles.Sidedefs[t + 2];
                        for (int v = 0; v < 3; v++)
                        {
                            Vector2D v2 = triangles.Vertices[t + v];

                            // Not along a sidedef? Then this line is across the sector
                            // and guaranteed to be inside the sector!
                            if (sd == null)
                            {
                                // Make the line
                                candidatepositions.Add(v1 + (v2 - v1) * 0.5f);
                            }
                            else
                            {
                                // This sidedefs is part of this island and must be checked
                                // so add it to the dictionary
                                sides[sd] = sd.Line;
                            }

                            // Make bbox of this island
                            minx = Math.Min(minx, v1.x);
                            miny = Math.Min(miny, v1.y);
                            maxx = Math.Max(maxx, v1.x);
                            maxy = Math.Max(maxy, v1.y);

                            // Next
                            sd = triangles.Sidedefs[t + v];
                            v1 = v2;
                        }
                    }

                    // Any candidate lines found at all?
                    if (candidatepositions.Count > 0)
                    {
                        // Start with the first line
                        foreach (Vector2D candidatepos in candidatepositions)
                        {
                            // Check distance against other lines
                            float smallestdist = int.MaxValue;
                            foreach (KeyValuePair <Sidedef, Linedef> sd in sides)
                            {
                                // Check the distance
                                float distance = sd.Value.DistanceToSq(candidatepos, true);
                                smallestdist = Math.Min(smallestdist, distance);
                            }

                            // Keep this candidate if it is better than previous
                            if (smallestdist > founddistance)
                            {
                                foundposition = candidatepos;
                                founddistance = smallestdist;
                            }
                        }

                        // No cceptable line found, just use the first!
                        return(new LabelPositionInfo(foundposition, (float)Math.Sqrt(founddistance)));
                    }

                    // No candidate lines found.
                    // Check to see if the island is a triangle
                    if (iv == 3)
                    {
                        // Use the center of the triangle
                        // TODO: Use the 'incenter' instead, see http://mathworld.wolfram.com/Incenter.html
                        Vector2D v = (triangles.Vertices[0] + triangles.Vertices[1] + triangles.Vertices[2]) / 3.0f;
                        float    d = Line2D.GetDistanceToLineSq(triangles.Vertices[0], triangles.Vertices[1], v, false);
                        d = Math.Min(d, Line2D.GetDistanceToLineSq(triangles.Vertices[1], triangles.Vertices[2], v, false));
                        d = Math.Min(d, Line2D.GetDistanceToLineSq(triangles.Vertices[2], triangles.Vertices[0], v, false));
                        return(new LabelPositionInfo(v, (float)Math.Sqrt(d)));
                    }
                    else
                    {
                        // Use the center of this island.
                        float d = Math.Min((maxx - minx) * 0.5f, (maxy - miny) * 0.5f);
                        return(new LabelPositionInfo(new Vector2D(minx + (maxx - minx) * 0.5f, miny + (maxy - miny) * 0.5f), d));
                    }
                }
            }
            else
            {
                // No triangulation was made. FAIL!
                General.Fail("No triangulation exists for sector " + s + " Triangulation is required to create label positions for a sector.");
            }

            // Nothing found...
            return(new LabelPositionInfo());
        }
Example #16
0
        // Serialize / deserialize (passive: this doesn't record)
        internal void ReadWrite(IReadWriteStream s)
        {
            if (!s.IsWriting)
            {
                BeforePropsChange();
                updateneeded             = true;
                ceilingplaneupdateneeded = true;
                floorplaneupdateneeded   = true;
            }

            ReadWrite(s, ref floorflags);
            ReadWrite(s, ref ceilingflags);

            if (s.IsWriting)
            {
                int firstwallindex = (firstwall == null ? -1 : firstwall.Index);
                s.rwInt(ref firstwallindex);
            }
            else
            {
                int firstwallindex = -1;
                s.rwInt(ref firstwallindex);

                if (firstwallindex != -1)
                {
                    foreach (var wall in sidedefs)
                    {
                        if (wall.Index == firstwallindex)
                        {
                            firstwall = wall;
                            break;
                        }
                    }

                    if (firstwall == null)
                    {
                        throw new Exception("Failed to restore FirstWall!");
                    }
                }
            }

            s.rwInt(ref ceilingheight);
            s.rwInt(ref floorheight);

            s.rwInt(ref ceilingtileindex);
            s.rwFloat(ref ceilingslope);
            s.rwInt(ref ceilingshade);
            s.rwInt(ref ceilingpaletteindex);
            s.rwInt(ref ceilingoffsetx);
            s.rwInt(ref ceilingoffsety);

            s.rwInt(ref floortileindex);
            s.rwFloat(ref floorslope);
            s.rwInt(ref floorshade);
            s.rwInt(ref floorpaletteindex);
            s.rwInt(ref flooroffsetx);
            s.rwInt(ref flooroffsety);

            s.rwInt(ref visibility);

            s.rwInt(ref hitag);
            s.rwInt(ref lotag);
            s.rwInt(ref extra);
        }