private TreeNode BuildPlanePortalLines(SectorGroup sectorgroup, string name, List<int> tags) { TreeNode node = new TreeNode(name + " Linedefs", 2, 2); List<Linedef> linedefs = new List<Linedef>(); foreach (Sector s in sectorgroup.Sectors) { foreach (Sidedef sd in s.Sidedefs) { if (!linedefs.Contains(sd.Line) && (sd.Line.Action == 385 || (sd.Line.Action >= 358 && sd.Line.Action <= 361)) && tags.Contains(sd.Line.Tag)) linedefs.Add(sd.Line); } } foreach (Linedef ld in linedefs.OrderBy(o => o.Action)) { NodeInfo info = new NodeInfo(ld); LinedefActionInfo ldai = General.Map.Config.GetLinedefActionInfo(ld.Action); string ldname = string.Format("Ld {0}: {1} - {2}", ld.Index, ldai.Index, ldai.Name); node.Nodes.Add(new TreeNode(ldname, 2, 2) { Tag = info }); } return node; }
private ContextMenuStrip CreateContextMenu(SectorGroup a, SectorGroup b, bool geometrymatches, bool topspecialmatch, bool bottomspecialmatch) { ContextMenuStrip cms = new ContextMenuStrip(); cms.ItemClicked += SelectUnmatchedLinedefs; ToolStripMenuItem option; if (!geometrymatches) { option = new ToolStripMenuItem("Select all unmatched linedefs"); option.Tag = new ContextMenuInfo(a, b, UnmatchingLinedefsType.Bottom | UnmatchingLinedefsType.Top); cms.Items.Add(option); option = new ToolStripMenuItem("Select unmatched linedefs of top"); option.Tag = new ContextMenuInfo(a, b, UnmatchingLinedefsType.Top); cms.Items.Add(option); option = new ToolStripMenuItem("Select unmatched linedefs of bottom"); option.Tag = new ContextMenuInfo(a, b, UnmatchingLinedefsType.Bottom); cms.Items.Add(option); } if (!topspecialmatch || !bottomspecialmatch) { if (!geometrymatches) cms.Items.Add(new ToolStripSeparator()); if (!topspecialmatch) { option = new ToolStripMenuItem("Select unmatched special linedefs of top"); option.Tag = new ContextMenuInfo(a, b, UnmatchingLinedefsType.SpecialsTop); cms.Items.Add(option); } if (!bottomspecialmatch) { option = new ToolStripMenuItem("Select unmatched special linedefs of bottom"); option.Tag = new ContextMenuInfo(a, b, UnmatchingLinedefsType.SpecialsBottom); cms.Items.Add(option); } } return cms; }
private TreeNode BuildPlanePortalSectors(SectorGroup sectorgroup, string name) { NodeInfo info = new NodeInfo(sectorgroup); TreeNode node = new TreeNode(name + " Sectors", 0, 0) { Tag = info }; foreach (Sector s in sectorgroup.Sectors.OrderBy(o => o.Index)) { info = new NodeInfo(s); node.Nodes.Add(new TreeNode(s.ToString(), 0, 0) { Tag = info }); } return node; }
public static List<Linedef> GetUnmatchingLinedefs(SectorGroup a, SectorGroup b, UnmatchingLinedefsType type) { List<Linedef> unmatching = new List<Linedef>(); Vector2D offset = b.BBAnchor - a.BBAnchor; if ((type & UnmatchingLinedefsType.Top) == UnmatchingLinedefsType.Top) { offset = SectorGroup.GetOffset(a, b); foreach (Linedef ld in b.Linedefs) { bool matches = false; foreach (Line2D line in a.Lines) { float d1 = line.GetDistanceToLine(ld.Start.Position - offset, true); float d2 = line.GetDistanceToLine(ld.End.Position - offset, true); if ((d1 >= -float.Epsilon && d1 <= float.Epsilon) && (d2 >= -float.Epsilon && d2 <= float.Epsilon)) { matches = true; break; } } if (!matches) unmatching.Add(ld); } } if ((type & UnmatchingLinedefsType.Bottom) == UnmatchingLinedefsType.Bottom) { offset = SectorGroup.GetOffset(a, b); foreach (Linedef ld in a.Linedefs) { bool matches = false; foreach (Line2D line in b.Lines) { float d1 = line.GetDistanceToLine(ld.Start.Position + offset, true); float d2 = line.GetDistanceToLine(ld.End.Position + offset, true); if ((d1 >= -float.Epsilon && d1 <= float.Epsilon) && (d2 >= -float.Epsilon && d2 <= float.Epsilon)) { matches = true; break; } } if (!matches) unmatching.Add(ld); } } if ((type & UnmatchingLinedefsType.SpecialsTop) == UnmatchingLinedefsType.SpecialsTop) { SectorGroup.TopSpecialsMatch(a, b, out unmatching); } if ((type & UnmatchingLinedefsType.SpecialsBottom) == UnmatchingLinedefsType.SpecialsBottom) { SectorGroup.BottomSpecialsMatch(a, b, out unmatching); } return unmatching; }
public static Vector2D GetOffset(SectorGroup a, SectorGroup b) { Linedef ld1 = null; Linedef ld2 = null; Vector2D offset = new Vector2D(0, 0); ld1 = a.SpecialLinedefs.FirstOrDefault(o => o.Action == 360); ld2 = b.SpecialLinedefs.FirstOrDefault(o => o.Action == 358); if (ld1 == null || ld2 == null) { ld1 = b.SpecialLinedefs.FirstOrDefault(o => o.Action == 360); ld2 = a.SpecialLinedefs.FirstOrDefault(o => o.Action == 358); } if (ld1 == null || ld2 == null) throw new Exception("Line specials are missing"); if (ld1.Angle == ld2.Angle) return new Vector2D(ld2.Start.Position - ld1.Start.Position); else return new Vector2D(ld2.Start.Position - ld1.End.Position); }
public static bool BottomSpecialsMatch(SectorGroup a, SectorGroup b, out List<Linedef> unmatchedlinedefs) { Linedef ld1 = a.Linedefs.FirstOrDefault(o => o.Action == 360); Linedef ld2 = b.Linedefs.FirstOrDefault(o => o.Action == 358); unmatchedlinedefs = new List<Linedef>(); if (ld1 == null || ld2 == null) return false; if (ld1.Length != ld2.Length) { unmatchedlinedefs.AddRange(new Linedef[] { ld1, ld2 }); return false; } float difference = Angle2D.Difference(ld1.Angle, ld2.Angle); if (difference != 0f && difference != Angle2D.PI) { unmatchedlinedefs.AddRange(new Linedef[] { ld1, ld2 }); return false; } return true; }
public static List<Linedef> GetUnmatchingLinedefs(SectorGroup a, SectorGroup b) { return GetUnmatchingLinedefs(a, b, UnmatchingLinedefsType.Bottom | UnmatchingLinedefsType.Top); }
public static bool GeometryMatches(SectorGroup a, SectorGroup b) { Vector2D offset = b.BBAnchor - a.BBAnchor; foreach (Line2D l in a.Lines) { if (b.Lines.Count(ol => ol.v1 == l.v1+offset && ol.v2 == l.v2+offset) == 0) return false; } return true; }
public static bool BottomSpecialsMatch(SectorGroup a, SectorGroup b) { List<Linedef> temp; return BottomSpecialsMatch(a, b, out temp); }
public NodeInfo(SectorGroup sg) { type = NodeInfoType.SECTOR_GROUP; sectorgroup = sg; }
// Finds a sector group by action and tag private SectorGroup GetCorrespondingSectorGroup(int action, SectorGroup source, Dictionary<Linedef, SectorGroup> sectorgroups, List<SectorGroup> checkedsectorgroups) { int tag = -1; foreach (Sector s in source.Sectors) foreach (Sidedef sd in s.Sidedefs) if (sd.Line.Action == action) tag = sd.Line.Tag; if (tag == -1) return null; foreach (KeyValuePair<Linedef, SectorGroup> entry in sectorgroups) if (!checkedsectorgroups.Contains(entry.Value)) foreach (Sector s in entry.Value.Sectors) if (s.Tag == tag) return entry.Value; return null; }
public List<List<SectorGroup>> GetPlanePortals() { Dictionary<int, List<Sector>> taglookup = new Dictionary<int, List<Sector>>(); Dictionary<Linedef, SectorGroup> sectorgroups = new Dictionary<Linedef, SectorGroup>(); List<Linedef> applytofrontlines = new List<Linedef>(); List<List<SectorGroup>> portalgroups = new List<List<SectorGroup>>(); List<SectorGroup> checkedsectorgroups = new List<SectorGroup>(); // Create a lookup dictionary, so we only have to crawl through all sectors once foreach (Sector s in General.Map.Map.Sectors) { if (!taglookup.ContainsKey(s.Tag)) taglookup.Add(s.Tag, new List<Sector>()); taglookup[s.Tag].Add(s); } // Go through all linedefs foreach (Linedef ld in General.Map.Map.Linedefs) { if (ld.Action == 358 || ld.Action == 359) // Actions: Apply linked portal to like-tagged ceilings/floors { SectorGroup sg = new SectorGroup(); sg.Type = ld.Action == 358 ? SectorGroupType.Ceiling : SectorGroupType.Floor; if (taglookup.ContainsKey(ld.Tag)) foreach (Sector s in taglookup[ld.Tag]) sg.Sectors.Add(s); sectorgroups.Add(ld, sg); } else if (ld.Action == 385) // Action: Apply portal to front sector { // the sector group this line references might not exist yet, so we have // to store the line and check it later applytofrontlines.Add(ld); } } // Check lines again, that apply a portal to the front sector foreach (Linedef ld in applytofrontlines) { // Find the sector group his front sector of the line belongs to foreach (KeyValuePair<Linedef, SectorGroup> entry in sectorgroups) { // Found the sector group, so add the front sector to it if (entry.Key.Tag == ld.Tag) { entry.Value.Sectors.Add(ld.Front.Sector); break; } } } // Update the sector groups, but set the type to what the map author intended, // not what it really is foreach (KeyValuePair<Linedef, SectorGroup> entry in sectorgroups) { entry.Value.Update(); entry.Value.Type = entry.Key.Action == 358 ? SectorGroupType.Ceiling : SectorGroupType.Floor; } // Form portal groups from two sector groups. Each portal group has a top and a bottom sector group foreach (KeyValuePair<Linedef, SectorGroup> entry in sectorgroups) { if (checkedsectorgroups.Contains(entry.Value)) continue; if (entry.Key.Action == 358) // Actions: Apply linked portal to like-tagged ceilings; this is a top sector group { List<SectorGroup> portalgroup = new List<SectorGroup>() { entry.Value, GetCorrespondingSectorGroup(359, entry.Value, sectorgroups, checkedsectorgroups) }; checkedsectorgroups.Add(portalgroup[0]); checkedsectorgroups.Add(portalgroup[1]); portalgroups.Add(portalgroup); } else if (entry.Key.Action == 359) // Actions: Apply linked portal to like-tagged floors; this is a bottom sector group { List<SectorGroup> portalgroup = new List<SectorGroup>() { GetCorrespondingSectorGroup(358, entry.Value, sectorgroups, checkedsectorgroups), entry.Value }; checkedsectorgroups.Add(portalgroup[0]); checkedsectorgroups.Add(portalgroup[1]); portalgroups.Add(portalgroup); } } return portalgroups; }
private bool GetLinedefPair(SectorGroup sga, SectorGroup sgb, out Linedef la, out Linedef lb) { Vector2D offset = sgb.BBAnchor - sga.BBAnchor; List<Sidedef> sidedefs = new List<Sidedef>(); la = lb = null; foreach (Sector s in sga.Sectors) { foreach (Sidedef sd in s.Sidedefs.Where(sdx => sdx.Line.Action == 0 && sdx.Line.Tag == 0).OrderByDescending(sdx => sdx.Line.Length)) if (!sidedefs.Contains(sd)) sidedefs.Add(sd); } // Get all sidedefs of sector a without action and tag, ordered by their length foreach (Sidedef sda in sidedefs) { foreach (Sector s in sgb.Sectors) { try { // Sidedef sdb = s.Sidedefs.Where(sd => (sd.Line.Start.Position == sda.Line.Start.Position + offset && sd.Line.End.Position == sda.Line.End.Position + offset) || (sd.Line.Start.Position == sda.Line.End.Position + offset && sd.Line.End.Position == sda.Line.Start.Position + offset)).First(); var x = s.Sidedefs.Where(sd => (sd.Line.Start.Position == sda.Line.Start.Position + offset && sd.Line.End.Position == sda.Line.End.Position + offset) || (sd.Line.Start.Position == sda.Line.End.Position + offset && sd.Line.End.Position == sda.Line.Start.Position + offset)); Sidedef sdb = x.First(); if (sdb.Line.Action == 0 && sdb.Line.Tag == 0) { la = sda.Line; lb = sdb.Line; return true; } } catch (Exception e) { } } } return false; }
// Creates groups of sectors that are connected to each other private List<SectorGroup> CreateSectorGroups(List<Sector> sectors) { List<SectorGroup> groups = new List<SectorGroup>(); while (sectors.Count > 0) { SectorGroup sg = new SectorGroup(); List<Sector> sectorstocheck = new List<Sector>(); sectorstocheck.Add(sectors[0]); sectors.Remove(sectorstocheck[0]); while (sectorstocheck.Count > 0) { foreach (Sidedef sd in sectorstocheck[0].Sidedefs) { if (sectors.Contains(sd.Sector) && !sg.Sectors.Contains(sd.Sector)) sectorstocheck.Add(sd.Sector); if (sd.Other != null && sectors.Contains(sd.Other.Sector) && !sg.Sectors.Contains(sd.Other.Sector)) sectorstocheck.Add(sd.Other.Sector); } if (!sg.Sectors.Contains(sectorstocheck[0])) sg.Sectors.Add(sectorstocheck[0]); sectors.Remove(sectorstocheck[0]); sectorstocheck.RemoveAt(0); } sg.Update(); groups.Add(sg); } return groups.OrderBy(g => g.Sectors[0].FloorHeight).ToList(); }