diff --git a/Source/Core/Controls/ImageBrowserControl.Designer.cs b/Source/Core/Controls/ImageBrowserControl.Designer.cs index 104d1054..80d3291e 100644 --- a/Source/Core/Controls/ImageBrowserControl.Designer.cs +++ b/Source/Core/Controls/ImageBrowserControl.Designer.cs @@ -30,19 +30,39 @@ namespace CodeImp.DoomBuilder.Controls private void InitializeComponent() { this.components = new System.ComponentModel.Container(); + this.labelMixMode = new System.Windows.Forms.Label(); + this.label = new System.Windows.Forms.Label(); this.splitter = new System.Windows.Forms.SplitContainer(); - this.list = new CodeImp.DoomBuilder.Controls.OptimizedListView(); + this.cbMixMode = new System.Windows.Forms.ComboBox(); this.texturesize = new System.Windows.Forms.Label(); this.texturesizelabel = new System.Windows.Forms.Label(); this.objectname = new System.Windows.Forms.TextBox(); - this.label = new System.Windows.Forms.Label(); this.refreshtimer = new System.Windows.Forms.Timer(this.components); this.texturesizetimer = new System.Windows.Forms.Timer(this.components); + this.list = new CodeImp.DoomBuilder.Controls.OptimizedListView(); this.splitter.Panel1.SuspendLayout(); this.splitter.Panel2.SuspendLayout(); this.splitter.SuspendLayout(); this.SuspendLayout(); // + // labelMixMode + // + this.labelMixMode.AutoSize = true; + this.labelMixMode.Location = new System.Drawing.Point(3, 11); + this.labelMixMode.Name = "labelMixMode"; + this.labelMixMode.Size = new System.Drawing.Size(39, 14); + this.labelMixMode.TabIndex = 3; + this.labelMixMode.Text = "Show:"; + // + // label + // + this.label.AutoSize = true; + this.label.Location = new System.Drawing.Point(156, 11); + this.label.Name = "label"; + this.label.Size = new System.Drawing.Size(33, 14); + this.label.TabIndex = 0; + this.label.Text = "Filter:"; + // // splitter // this.splitter.Dock = System.Windows.Forms.DockStyle.Fill; @@ -58,6 +78,8 @@ namespace CodeImp.DoomBuilder.Controls // // splitter.Panel2 // + this.splitter.Panel2.Controls.Add(this.cbMixMode); + this.splitter.Panel2.Controls.Add(this.labelMixMode); this.splitter.Panel2.Controls.Add(this.texturesize); this.splitter.Panel2.Controls.Add(this.texturesizelabel); this.splitter.Panel2.Controls.Add(this.objectname); @@ -67,29 +89,25 @@ namespace CodeImp.DoomBuilder.Controls this.splitter.TabIndex = 0; this.splitter.TabStop = false; // - // list + // cbMixMode // - this.list.Dock = System.Windows.Forms.DockStyle.Fill; - this.list.HideSelection = false; - this.list.Location = new System.Drawing.Point(0, 0); - this.list.MultiSelect = false; - this.list.Name = "list"; - this.list.OwnerDraw = true; - this.list.ShowItemToolTips = true; - this.list.Size = new System.Drawing.Size(518, 312); - this.list.TabIndex = 1; - this.list.TabStop = false; - this.list.TileSize = new System.Drawing.Size(90, 90); - this.list.UseCompatibleStateImageBehavior = false; - this.list.View = System.Windows.Forms.View.Tile; - this.list.DrawItem += new System.Windows.Forms.DrawListViewItemEventHandler(this.list_DrawItem); - this.list.DoubleClick += new System.EventHandler(this.list_DoubleClick); - this.list.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(this.list_ItemSelectionChanged); - this.list.KeyDown += new System.Windows.Forms.KeyEventHandler(this.list_KeyDown); + this.cbMixMode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cbMixMode.FormattingEnabled = true; + this.cbMixMode.Items.AddRange(new object[] { + "All", + "Textures", + "Flats"}); + this.cbMixMode.Location = new System.Drawing.Point(48, 7); + this.cbMixMode.Margin = new System.Windows.Forms.Padding(3, 3, 6, 3); + this.cbMixMode.Name = "cbMixMode"; + this.cbMixMode.Size = new System.Drawing.Size(90, 22); + this.cbMixMode.TabIndex = 4; + this.cbMixMode.TabStop = false; + this.cbMixMode.SelectedIndexChanged += new System.EventHandler(this.cbMixMode_SelectedIndexChanged); // // texturesize // - this.texturesize.Location = new System.Drawing.Point(368, 13); + this.texturesize.Location = new System.Drawing.Point(368, 11); this.texturesize.Name = "texturesize"; this.texturesize.Size = new System.Drawing.Size(271, 14); this.texturesize.TabIndex = 2; @@ -99,7 +117,7 @@ namespace CodeImp.DoomBuilder.Controls // texturesizelabel // this.texturesizelabel.AutoSize = true; - this.texturesizelabel.Location = new System.Drawing.Point(331, 13); + this.texturesizelabel.Location = new System.Drawing.Point(331, 11); this.texturesizelabel.Name = "texturesizelabel"; this.texturesizelabel.Size = new System.Drawing.Size(31, 14); this.texturesizelabel.TabIndex = 1; @@ -109,7 +127,8 @@ namespace CodeImp.DoomBuilder.Controls // objectname // this.objectname.CharacterCasing = System.Windows.Forms.CharacterCasing.Upper; - this.objectname.Location = new System.Drawing.Point(145, 10); + this.objectname.Location = new System.Drawing.Point(192, 8); + this.objectname.Margin = new System.Windows.Forms.Padding(3, 3, 6, 3); this.objectname.Name = "objectname"; this.objectname.Size = new System.Drawing.Size(122, 20); this.objectname.TabIndex = 0; @@ -117,15 +136,6 @@ namespace CodeImp.DoomBuilder.Controls this.objectname.TextChanged += new System.EventHandler(this.objectname_TextChanged); this.objectname.KeyDown += new System.Windows.Forms.KeyEventHandler(this.objectname_KeyDown); // - // label - // - this.label.AutoSize = true; - this.label.Location = new System.Drawing.Point(1, 13); - this.label.Name = "label"; - this.label.Size = new System.Drawing.Size(138, 14); - this.label.TabIndex = 0; - this.label.Text = "Select or type object name:"; - // // refreshtimer // this.refreshtimer.Interval = 500; @@ -136,6 +146,25 @@ namespace CodeImp.DoomBuilder.Controls this.texturesizetimer.Interval = 3; this.texturesizetimer.Tick += new System.EventHandler(this.texturesizetimer_Tick); // + // list + // + this.list.Dock = System.Windows.Forms.DockStyle.Fill; + this.list.HideSelection = false; + this.list.Location = new System.Drawing.Point(0, 0); + this.list.MultiSelect = false; + this.list.Name = "list"; + this.list.OwnerDraw = true; + this.list.Size = new System.Drawing.Size(518, 312); + this.list.TabIndex = 1; + this.list.TabStop = false; + this.list.TileSize = new System.Drawing.Size(90, 90); + this.list.UseCompatibleStateImageBehavior = false; + this.list.View = System.Windows.Forms.View.Tile; + this.list.DrawItem += new System.Windows.Forms.DrawListViewItemEventHandler(this.list_DrawItem); + this.list.DoubleClick += new System.EventHandler(this.list_DoubleClick); + this.list.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(this.list_ItemSelectionChanged); + this.list.KeyDown += new System.Windows.Forms.KeyEventHandler(this.list_KeyDown); + // // ImageBrowserControl // this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); @@ -159,10 +188,12 @@ namespace CodeImp.DoomBuilder.Controls private OptimizedListView list; private System.Windows.Forms.Timer refreshtimer; private System.Windows.Forms.TextBox objectname; - private System.Windows.Forms.Label label; private System.Windows.Forms.Label texturesize; private System.Windows.Forms.Label texturesizelabel; private System.Windows.Forms.Timer texturesizetimer; + private System.Windows.Forms.ComboBox cbMixMode; + private System.Windows.Forms.Label label; + private System.Windows.Forms.Label labelMixMode; } } diff --git a/Source/Core/Controls/ImageBrowserControl.cs b/Source/Core/Controls/ImageBrowserControl.cs index 6ee20bdc..246c34d3 100644 --- a/Source/Core/Controls/ImageBrowserControl.cs +++ b/Source/Core/Controls/ImageBrowserControl.cs @@ -66,6 +66,9 @@ namespace CodeImp.DoomBuilder.Controls // Items visible in the list private List visibleitems; + + //mxd + private static int mixMode; #endregion @@ -73,7 +76,7 @@ namespace CodeImp.DoomBuilder.Controls public bool PreventSelection { get { return preventselection; } set { preventselection = value; } } public bool HideInputBox { get { return splitter.Panel2Collapsed; } set { splitter.Panel2Collapsed = value; } } - public string LabelText { get { return label.Text; } set { label.Text = value; objectname.Left = label.Right + label.Margin.Right + objectname.Margin.Left; } } + //public string LabelText { get { return label.Text; } set { label.Text = value; objectname.Left = label.Right + label.Margin.Right + objectname.Margin.Left; } } //mxd public ListViewItem SelectedItem { get { if(list.SelectedItems.Count > 0) return list.SelectedItems[0]; else return null; } } #endregion @@ -86,9 +89,19 @@ namespace CodeImp.DoomBuilder.Controls // Initialize InitializeComponent(); items = new List(); - - // Move textbox with label - objectname.Left = label.Right + label.Margin.Right + objectname.Margin.Left; + + //mxd + if(General.Map.Config.MixTexturesFlats) { + cbMixMode.SelectedIndex = mixMode; + } else { + labelMixMode.Visible = false; + cbMixMode.Visible = false; + label.Left = labelMixMode.Left; + objectname.Left = label.Right + label.Margin.Right + objectname.Margin.Left; + texturesizelabel.Left = objectname.Right + objectname.Margin.Right; + texturesize.Left = texturesizelabel.Right + texturesizelabel.Margin.Right; + mixMode = 0; + } } // This applies the application settings @@ -236,6 +249,12 @@ namespace CodeImp.DoomBuilder.Controls texturesize.Visible = false; texturesizelabel.Visible = false; } + + //mxd + private void cbMixMode_SelectedIndexChanged(object sender, EventArgs e) { + mixMode = cbMixMode.SelectedIndex; + RefillList(false); + } #endregion @@ -498,6 +517,12 @@ namespace CodeImp.DoomBuilder.Controls // This validates an item private bool ValidateItem(ImageBrowserItem i) { + //mxd. mixMode: 0 = All, 1 = Textures, 2 = Flats + if(!splitter.Panel2Collapsed) { + if(mixMode == 1 && i.icon.IsFlat) return false; + if(mixMode == 2 && !i.icon.IsFlat) return false; + } + return i.Text.Contains(objectname.Text); } diff --git a/Source/Core/Controls/ImageBrowserControl.resx b/Source/Core/Controls/ImageBrowserControl.resx index cc4ec46b..3ff430ae 100644 --- a/Source/Core/Controls/ImageBrowserControl.resx +++ b/Source/Core/Controls/ImageBrowserControl.resx @@ -123,18 +123,6 @@ True - - True - - - True - - - True - - - True - 103, 17 diff --git a/Source/Core/Data/DataManager.cs b/Source/Core/Data/DataManager.cs index 2a3a00f1..f2fc99c3 100644 --- a/Source/Core/Data/DataManager.cs +++ b/Source/Core/Data/DataManager.cs @@ -964,6 +964,7 @@ namespace CodeImp.DoomBuilder.Data // Add to preview manager previews.AddImage(img); + img.IsFlat = true; //mxd } } } diff --git a/Source/Core/Data/ImageData.cs b/Source/Core/Data/ImageData.cs index 745ae797..4bffb09c 100644 --- a/Source/Core/Data/ImageData.cs +++ b/Source/Core/Data/ImageData.cs @@ -55,6 +55,7 @@ namespace CodeImp.DoomBuilder.Data protected bool worldpanning; protected bool usecolorcorrection; protected string fullName; //mxd. name with path; + protected bool isFlat; //mxd. if false, it's a texture // Loading private volatile ImageLoadState previewstate; @@ -84,8 +85,8 @@ namespace CodeImp.DoomBuilder.Data public string Name { get { return name; } } public long LongName { get { return longname; } } - //mxd - public string FullName { get { return fullName; } } + public string FullName { get { return fullName; } } //mxd + public bool IsFlat { get { return isFlat; } internal set { isFlat = value; } } //mxd public bool UseColorCorrection { get { return usecolorcorrection; } set { usecolorcorrection = value; } } public Texture Texture { get { lock(this) { return texture; } } } public bool IsPreviewLoaded { get { return (previewstate == ImageLoadState.Ready); } } diff --git a/Source/Core/General/General.cs b/Source/Core/General/General.cs index 8e381b90..1d8049b2 100644 --- a/Source/Core/General/General.cs +++ b/Source/Core/General/General.cs @@ -1286,6 +1286,7 @@ namespace CodeImp.DoomBuilder savefile.CheckPathExists = true; savefile.OverwritePrompt = true; savefile.ValidateNames = true; + savefile.FileName = map.FileTitle; //mxd if(savefile.ShowDialog(mainwindow) == DialogResult.OK) { // Check if we're saving to the same file as the original. diff --git a/Source/Core/Map/Linedef.cs b/Source/Core/Map/Linedef.cs index 3a71d2df..b95eb5d7 100644 --- a/Source/Core/Map/Linedef.cs +++ b/Source/Core/Map/Linedef.cs @@ -148,14 +148,6 @@ namespace CodeImp.DoomBuilder.Map // Already set isdisposed so that changes can be prohibited isdisposed = true; - //mxd. If there are sectors on both sides, join them - if(front != null && front.Sector != null && back != null && back.Sector != null && front.Sector.Index != back.Sector.Index) { - if(front.Sector.BBox.Width * front.Sector.BBox.Height > back.Sector.BBox.Width * back.Sector.BBox.Height) - back.Sector.Join(front.Sector); - else - front.Sector.Join(back.Sector); - } - // Dispose sidedefs if((front != null) && map.AutoRemove) front.Dispose(); else AttachFrontP(null); if((back != null) && map.AutoRemove) back.Dispose(); else AttachBackP(null); diff --git a/Source/Core/Windows/TextureBrowserForm.Designer.cs b/Source/Core/Windows/TextureBrowserForm.Designer.cs index ce578944..11f005d0 100644 --- a/Source/Core/Windows/TextureBrowserForm.Designer.cs +++ b/Source/Core/Windows/TextureBrowserForm.Designer.cs @@ -96,7 +96,6 @@ namespace CodeImp.DoomBuilder.Windows | System.Windows.Forms.AnchorStyles.Right))); this.browser.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.browser.HideInputBox = false; - this.browser.LabelText = "Select or enter a texture name:"; this.browser.Location = new System.Drawing.Point(218, 9); this.browser.Name = "browser"; this.browser.PreventSelection = false; diff --git a/Source/Core/Windows/TextureBrowserForm.resx b/Source/Core/Windows/TextureBrowserForm.resx index 5325b0f2..96958820 100644 --- a/Source/Core/Windows/TextureBrowserForm.resx +++ b/Source/Core/Windows/TextureBrowserForm.resx @@ -131,7 +131,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAc - DwAAAk1TRnQBSQFMAgEBBwEAAXQBAAF0AQABEAEAARYBAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + DwAAAk1TRnQBSQFMAgEBBwEAAYQBAAGEAQABEAEAARYBAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAASwDAAEBAQABCAYAAQsYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA diff --git a/Source/Core/Windows/TextureSetForm.Designer.cs b/Source/Core/Windows/TextureSetForm.Designer.cs index 34db9e03..8cdb1c00 100644 --- a/Source/Core/Windows/TextureSetForm.Designer.cs +++ b/Source/Core/Windows/TextureSetForm.Designer.cs @@ -239,7 +239,6 @@ namespace CodeImp.DoomBuilder.Windows | System.Windows.Forms.AnchorStyles.Right))); this.matcheslist.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.matcheslist.HideInputBox = true; - this.matcheslist.LabelText = "Select or type object name:"; this.matcheslist.Location = new System.Drawing.Point(18, 55); this.matcheslist.Name = "matcheslist"; this.matcheslist.PreventSelection = true; diff --git a/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs index 7c466c92..a6f96c85 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs @@ -776,7 +776,17 @@ namespace CodeImp.DoomBuilder.BuilderModes } // Dispose selected linedefs - foreach(Linedef ld in selected) ld.Dispose(); + foreach(Linedef ld in selected) { + //mxd. If there are different sectors on both sides, join them + if(ld.Front != null && ld.Front.Sector != null && ld.Back != null && ld.Back.Sector != null && ld.Front.Sector.Index != ld.Back.Sector.Index) { + if(ld.Front.Sector.BBox.Width * ld.Front.Sector.BBox.Height > ld.Back.Sector.BBox.Width * ld.Back.Sector.BBox.Height) + ld.Back.Sector.Join(ld.Front.Sector); + else + ld.Front.Sector.Join(ld.Back.Sector); + } + + ld.Dispose(); + } //mxd Tools.MergeInvalidSectors(toMerge); diff --git a/Source/Plugins/BuilderModes/ClassicModes/VerticesMode.cs b/Source/Plugins/BuilderModes/ClassicModes/VerticesMode.cs index e4f06679..64040711 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/VerticesMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/VerticesMode.cs @@ -731,10 +731,11 @@ namespace CodeImp.DoomBuilder.BuilderModes [BeginAction("deleteitem", BaseAction = true)] public void DeleteItem() { - deleteItem(true); //mxd + deleteItem(true, new List()); //mxd } - private void deleteItem(bool createUndo) + //mxd. MMMMMMONSTROUS solution! + private void deleteItem(bool createUndo, List redrawnLines) { // Make list of selected vertices ICollection selected = General.Map.Map.GetSelectedVertices(true); @@ -797,98 +798,146 @@ namespace CodeImp.DoomBuilder.BuilderModes if(!v.IsDisposed) { // If the vertex only has 2 linedefs attached, then merge the linedefs - if(v.Linedefs.Count == 2) - { + if(v.Linedefs.Count == 2) { Linedef ld1 = General.GetByIndex(v.Linedefs, 0); Linedef ld2 = General.GetByIndex(v.Linedefs, 1); - //mxd. We don't want to do this if it will result in sector with 2 sidedefs - if(ld1.Front.Sector.Sidedefs.Count > 3 || ld1.Back.Sector.Sidedefs.Count > 3 || - ld2.Front.Sector.Sidedefs.Count > 3 ||ld2.Back.Sector.Sidedefs.Count > 3) { + if(!ld1.IsDisposed && !ld2.IsDisposed) { + //mxd. We don't want to do this if it will result in sector with 2 sidedefs + if((ld1.Front != null && ld1.Front.Sector != null && ld1.Front.Sector.Sidedefs.Count > 3) || + (ld1.Back != null && ld1.Back.Sector != null && ld1.Back.Sector.Sidedefs.Count > 3) || + (ld2.Front != null && ld2.Front.Sector != null && ld2.Front.Sector.Sidedefs.Count > 3) || + (ld2.Back != null && ld2.Back.Sector != null && ld2.Back.Sector.Sidedefs.Count > 3)) { - Vertex v1 = (ld1.Start == v) ? ld1.End : ld1.Start; - Vertex v2 = (ld2.Start == v) ? ld2.End : ld2.Start; + Vertex v1 = (ld1.Start == v) ? ld1.End : ld1.Start; + Vertex v2 = (ld2.Start == v) ? ld2.End : ld2.Start; - //mxd. Check if removing a vertex will collapse a sector with 3 "outer" sides - bool skip = false; - - if(ld1.Front != null) { - foreach(Sidedef side in ld1.Front.Sector.Sidedefs) { - if(!possiblyInvalidSectors.Contains(ld1.Front.Sector) && (side.Line.Start == v1 && side.Line.End == v2) || side.Line.Start == v2 && side.Line.End == v1) { - possiblyInvalidSectors.Add(ld1.Front.Sector); - skip = true; - } - } - } - - if(ld2.Front != null) { - foreach(Sidedef side in ld2.Front.Sector.Sidedefs) { - if(!possiblyInvalidSectors.Contains(ld2.Front.Sector) && (side.Line.Start == v1 && side.Line.End == v2) || side.Line.Start == v2 && side.Line.End == v1) { - possiblyInvalidSectors.Add(ld2.Front.Sector); - skip = true; - } - } - } - - if(ld1.Back != null) { - foreach(Sidedef side in ld1.Back.Sector.Sidedefs) { - if(!possiblyInvalidSectors.Contains(ld1.Back.Sector) && (side.Line.Start == v1 && side.Line.End == v2) || side.Line.Start == v2 && side.Line.End == v1) { - possiblyInvalidSectors.Add(ld1.Back.Sector); - skip = true; - } - } - } - - if(ld2.Back != null) { - foreach(Sidedef side in ld2.Back.Sector.Sidedefs) { - if(!possiblyInvalidSectors.Contains(ld2.Back.Sector) && (side.Line.Start == v1 && side.Line.End == v2) || side.Line.Start == v2 && side.Line.End == v1) { - possiblyInvalidSectors.Add(ld2.Back.Sector); - skip = true; - } - } - } - - //mxd - if(!skip) { - DrawnVertex dv1 = new DrawnVertex(); - DrawnVertex dv2 = new DrawnVertex(); - dv1.stitchline = true; - dv2.stitchline = true; - dv1.stitch = true; - dv2.stitch = true; - - if(ld1.Start == v) { - dv1.pos = v2.Position; - dv2.pos = v1.Position; - } else { - dv1.pos = v1.Position; - dv2.pos = v2.Position; - } - - Tools.DrawLines(new List() { dv1, dv2 }); - - General.Map.IsChanged = true; - General.Map.Map.Update(); - - //if both of the lines are single sided, remove newly created sector - if((ld1.Front == null || ld1.Back == null) && (ld2.Front == null || ld2.Back == null)) { - List newLines = General.Map.Map.GetMarkedLinedefs(true); - - int index = ld1.Front != null ? ld1.Front.Sector.Index : ld1.Back.Sector.Index; - General.Map.Map.GetSectorByIndex(index).Dispose(); - - foreach(Linedef l in newLines) { - if(l.Front != null && l.Front.Sector != null && !affectedSectors.Contains(l.Front.Sector)) - affectedSectors.Add(l.Front.Sector); - if(l.Back != null && l.Back.Sector != null && !affectedSectors.Contains(l.Back.Sector)) - affectedSectors.Add(l.Back.Sector); - } - } else { - ld1.Dispose(); + //if both linedefs are on the same line + if(ld1.AngleDeg == ld2.AngleDeg || ld1.AngleDeg == ld2.AngleDeg - 180) { + if(ld1.Start == v) ld1.SetStartVertex(v2); else ld1.SetEndVertex(v2); ld2.Dispose(); + } else { + //mxd. Check if removing a vertex will collapse a sector with 3 "outer" sides + bool skip = false; + + if(ld1.Front != null) { + foreach(Sidedef side in ld1.Front.Sector.Sidedefs) { + if(!possiblyInvalidSectors.Contains(ld1.Front.Sector) && (side.Line.Start == v1 && side.Line.End == v2) || side.Line.Start == v2 && side.Line.End == v1) { + possiblyInvalidSectors.Add(ld1.Front.Sector); + skip = true; + } + } + } + + if(ld2.Front != null) { + foreach(Sidedef side in ld2.Front.Sector.Sidedefs) { + if(!possiblyInvalidSectors.Contains(ld2.Front.Sector) && (side.Line.Start == v1 && side.Line.End == v2) || side.Line.Start == v2 && side.Line.End == v1) { + possiblyInvalidSectors.Add(ld2.Front.Sector); + skip = true; + } + } + } + + if(ld1.Back != null) { + foreach(Sidedef side in ld1.Back.Sector.Sidedefs) { + if(!possiblyInvalidSectors.Contains(ld1.Back.Sector) && (side.Line.Start == v1 && side.Line.End == v2) || side.Line.Start == v2 && side.Line.End == v1) { + possiblyInvalidSectors.Add(ld1.Back.Sector); + skip = true; + } + } + } + + if(ld2.Back != null) { + foreach(Sidedef side in ld2.Back.Sector.Sidedefs) { + if(!possiblyInvalidSectors.Contains(ld2.Back.Sector) && (side.Line.Start == v1 && side.Line.End == v2) || side.Line.Start == v2 && side.Line.End == v1) { + possiblyInvalidSectors.Add(ld2.Back.Sector); + skip = true; + } + } + } + + //mxd + if(!skip) { + DrawnVertex dv1 = new DrawnVertex(); + DrawnVertex dv2 = new DrawnVertex(); + dv1.stitchline = true; + dv2.stitchline = true; + dv1.stitch = true; + dv2.stitch = true; + + if(ld1.Start == v) { + dv1.pos = v2.Position; + dv2.pos = v1.Position; + } else { + dv1.pos = v1.Position; + dv2.pos = v2.Position; + } + + Tools.DrawLines(new List() { dv1, dv2 }); + List newLines = General.Map.Map.GetMarkedLinedefs(true); + if(newLines.Count > 0) redrawnLines.AddRange(newLines); + + General.Map.IsChanged = true; + General.Map.Map.Update(); + + //if both of the lines are single sided, remove newly created sector + if((!ld1.IsDisposed && !ld2.IsDisposed) && (ld1.Front == null || ld1.Back == null) && (ld2.Front == null || ld2.Back == null)) { + int index = ld1.Front != null ? ld1.Front.Sector.Index : ld1.Back.Sector.Index; + General.Map.Map.GetSectorByIndex(index).Dispose(); + + foreach(Linedef l in newLines) { + if(l.Front != null && l.Front.Sector != null && !affectedSectors.Contains(l.Front.Sector)) + affectedSectors.Add(l.Front.Sector); + if(l.Back != null && l.Back.Sector != null && !affectedSectors.Contains(l.Back.Sector)) + affectedSectors.Add(l.Back.Sector); + } + } else { + tryJoinSectors(ld1); + tryJoinSectors(ld2); + ld1.Dispose(); + ld2.Dispose(); + } + } } } } + } else { //mxd. More than 2 lines share this vertex + Linedef[] lines = new Linedef[v.Linedefs.Count]; + v.Linedefs.CopyTo(lines, 0); + + List parallel = new List(); + + foreach(Linedef ld1 in lines) { + foreach(Linedef ld2 in lines) { + if(ld1.Index == ld2.Index) continue; + + if(ld1.AngleDeg == ld2.AngleDeg || ld1.AngleDeg == General.ClampAngle(ld2.AngleDeg - 180)) { + if(!parallel.Contains(ld1)) + parallel.Add(ld1); + if(!parallel.Contains(ld2)) + parallel.Add(ld2); + } + } + } + + if(parallel.Count == 2) { //if there are 2 parallel lines, join them and remove the rest. + for(int i = 0; i < lines.Length; i++) { + if(parallel.Contains(lines[i])) continue; + Linedef ld = lines[i]; + tryJoinSectors(ld); + ld.Dispose(); + } + + Vertex v2 = (parallel[1].Start == v) ? parallel[1].End : parallel[1].Start; + if(parallel[0].Start == v) parallel[0].SetStartVertex(v2); else parallel[0].SetEndVertex(v2); + parallel[1].Dispose(); + } else { //just trash them + for(int i = 0; i < lines.Length; i++) { + Linedef ld = lines[i]; + tryJoinSectors(ld); + ld.Dispose(); + } + } } // Trash vertex @@ -925,8 +974,15 @@ namespace CodeImp.DoomBuilder.BuilderModes //mxd. Because... well... some new vertices might have been created during vertex removal process... if(General.Map.Map.GetSelectedVertices(true).Count > 0) { - deleteItem(false); + deleteItem(false, redrawnLines); return; + } else if(redrawnLines.Count > 0) { + //try to merge redrawn lines + mergeLines(redrawnLines); + + // Update cache values + General.Map.IsChanged = true; + General.Map.Map.Update(); } // Invoke a new mousemove so that the highlighted item updates @@ -937,6 +993,63 @@ namespace CodeImp.DoomBuilder.BuilderModes General.Interface.RedrawDisplay(); } } + + //mxd. If there are different sectors on both sides of given linedef, join them + private void tryJoinSectors(Linedef ld) { + if(ld.IsDisposed) return; + + if(ld.Front != null && ld.Front.Sector != null && ld.Back != null && ld.Back.Sector != null && ld.Front.Sector.Index != ld.Back.Sector.Index) { + if(ld.Front.Sector.BBox.Width * ld.Front.Sector.BBox.Height > ld.Back.Sector.BBox.Width * ld.Back.Sector.BBox.Height) + ld.Back.Sector.Join(ld.Front.Sector); + else + ld.Front.Sector.Join(ld.Back.Sector); + } + } + + private void mergeLines(List lines) { + if(lines.Count < 2) return; + + for(int i = 0; i < lines.Count; i++) { + if(lines[i].IsDisposed) lines.RemoveAt(i); + } + + for(int i = 0; i < lines.Count; i++) { + for(int c = 0; c < lines.Count; c++) { + if(i == c) continue; + + //lines have the same angle? + if(lines[i].AngleDeg == lines[c].AngleDeg || lines[i].AngleDeg == General.ClampAngle(lines[c].AngleDeg - 180)) { + Vertex mid = null; + + //lines share a vertex? + if(lines[i].End == lines[c].Start || lines[i].End == lines[c].End) { + mid = lines[i].End; + } else if(lines[i].Start == lines[c].Start || lines[i].Start == lines[c].End) { + mid = lines[i].Start; + } + + if(mid == null || mid.Linedefs.Count > 2) continue; + + Vertex end = (lines[c].Start == mid) ? lines[c].End : lines[c].Start; + + //merge lines + if(lines[i].Start == mid) + lines[i].SetStartVertex(end); + else + lines[i].SetEndVertex(end); + lines[c].Dispose(); + + //trash vertex + mid.Dispose(); + lines.RemoveAt(c); + + //restart + mergeLines(lines); + return; + } + } + } + } #endregion }