diff --git a/Source/Core/Windows/PreferencesForm.Designer.cs b/Source/Core/Windows/PreferencesForm.Designer.cs index 6f6a6a5b..1cefced2 100644 --- a/Source/Core/Windows/PreferencesForm.Designer.cs +++ b/Source/Core/Windows/PreferencesForm.Designer.cs @@ -111,6 +111,9 @@ namespace CodeImp.DoomBuilder.Windows this.fieldofviewlabel = new System.Windows.Forms.Label(); this.label4 = new System.Windows.Forms.Label(); this.tabkeys = new System.Windows.Forms.TabPage(); + this.bClearActionFilter = new System.Windows.Forms.Button(); + this.tbFilterActions = new System.Windows.Forms.TextBox(); + this.label24 = new System.Windows.Forms.Label(); this.listactions = new System.Windows.Forms.ListView(); this.columncontrolaction = new System.Windows.Forms.ColumnHeader(); this.columncontrolkey = new System.Windows.Forms.ColumnHeader(); @@ -1108,6 +1111,9 @@ namespace CodeImp.DoomBuilder.Windows // // tabkeys // + this.tabkeys.Controls.Add(this.bClearActionFilter); + this.tabkeys.Controls.Add(this.tbFilterActions); + this.tabkeys.Controls.Add(this.label24); this.tabkeys.Controls.Add(this.listactions); this.tabkeys.Controls.Add(this.actioncontrolpanel); this.tabkeys.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); @@ -1119,6 +1125,36 @@ namespace CodeImp.DoomBuilder.Windows this.tabkeys.Text = "Controls"; this.tabkeys.UseVisualStyleBackColor = true; // + // bClearActionFilter + // + this.bClearActionFilter.Image = global::CodeImp.DoomBuilder.Properties.Resources.SearchClear; + this.bClearActionFilter.Location = new System.Drawing.Point(227, 10); + this.bClearActionFilter.Name = "bClearActionFilter"; + this.bClearActionFilter.Size = new System.Drawing.Size(26, 25); + this.bClearActionFilter.TabIndex = 12; + this.bClearActionFilter.TabStop = false; + this.bClearActionFilter.UseVisualStyleBackColor = true; + this.bClearActionFilter.Click += new System.EventHandler(this.bClearActionFilter_Click); + // + // tbFilterActions + // + this.tbFilterActions.Location = new System.Drawing.Point(55, 13); + this.tbFilterActions.Name = "tbFilterActions"; + this.tbFilterActions.Size = new System.Drawing.Size(166, 20); + this.tbFilterActions.TabIndex = 11; + this.tbFilterActions.TabStop = false; + this.tbFilterActions.TextChanged += new System.EventHandler(this.tbFilterActions_TextChanged); + // + // label24 + // + this.label24.AutoSize = true; + this.label24.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label24.Location = new System.Drawing.Point(11, 16); + this.label24.Name = "label24"; + this.label24.Size = new System.Drawing.Size(38, 14); + this.label24.TabIndex = 10; + this.label24.Text = "Filter:"; + // // listactions // this.listactions.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) @@ -1130,11 +1166,11 @@ namespace CodeImp.DoomBuilder.Windows this.listactions.FullRowSelect = true; this.listactions.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; this.listactions.HideSelection = false; - this.listactions.Location = new System.Drawing.Point(11, 12); + this.listactions.Location = new System.Drawing.Point(11, 42); this.listactions.Margin = new System.Windows.Forms.Padding(8, 9, 8, 9); this.listactions.MultiSelect = false; this.listactions.Name = "listactions"; - this.listactions.Size = new System.Drawing.Size(352, 462); + this.listactions.Size = new System.Drawing.Size(352, 458); this.listactions.Sorting = System.Windows.Forms.SortOrder.Ascending; this.listactions.TabIndex = 0; this.listactions.TabStop = false; @@ -1147,7 +1183,7 @@ namespace CodeImp.DoomBuilder.Windows // columncontrolaction // this.columncontrolaction.Text = "Action"; - this.columncontrolaction.Width = 179; + this.columncontrolaction.Width = 200; // // columncontrolkey // @@ -1173,7 +1209,7 @@ namespace CodeImp.DoomBuilder.Windows this.actioncontrolpanel.Location = new System.Drawing.Point(377, 12); this.actioncontrolpanel.Margin = new System.Windows.Forms.Padding(6); this.actioncontrolpanel.Name = "actioncontrolpanel"; - this.actioncontrolpanel.Size = new System.Drawing.Size(282, 462); + this.actioncontrolpanel.Size = new System.Drawing.Size(282, 488); this.actioncontrolpanel.TabIndex = 9; this.actioncontrolpanel.TabStop = false; this.actioncontrolpanel.Text = " Action control "; @@ -1185,10 +1221,10 @@ namespace CodeImp.DoomBuilder.Windows this.keyusedlist.FormattingEnabled = true; this.keyusedlist.IntegralHeight = false; this.keyusedlist.ItemHeight = 14; - this.keyusedlist.Location = new System.Drawing.Point(33, 307); + this.keyusedlist.Location = new System.Drawing.Point(23, 307); this.keyusedlist.Name = "keyusedlist"; this.keyusedlist.SelectionMode = System.Windows.Forms.SelectionMode.None; - this.keyusedlist.Size = new System.Drawing.Size(232, 115); + this.keyusedlist.Size = new System.Drawing.Size(233, 115); this.keyusedlist.Sorted = true; this.keyusedlist.TabIndex = 11; this.keyusedlist.Visible = false; @@ -1212,7 +1248,7 @@ namespace CodeImp.DoomBuilder.Windows this.actioncontrol.ImeMode = System.Windows.Forms.ImeMode.Off; this.actioncontrol.Location = new System.Drawing.Point(23, 190); this.actioncontrol.Name = "actioncontrol"; - this.actioncontrol.Size = new System.Drawing.Size(197, 22); + this.actioncontrol.Size = new System.Drawing.Size(233, 22); this.actioncontrol.TabIndex = 8; this.actioncontrol.TabStop = false; this.actioncontrol.SelectedIndexChanged += new System.EventHandler(this.actioncontrol_SelectedIndexChanged); @@ -1230,12 +1266,12 @@ namespace CodeImp.DoomBuilder.Windows // // actioncontrolclear // - this.actioncontrolclear.Location = new System.Drawing.Point(193, 138); + this.actioncontrolclear.Image = global::CodeImp.DoomBuilder.Properties.Resources.SearchClear; + this.actioncontrolclear.Location = new System.Drawing.Point(193, 137); this.actioncontrolclear.Name = "actioncontrolclear"; - this.actioncontrolclear.Size = new System.Drawing.Size(63, 25); + this.actioncontrolclear.Size = new System.Drawing.Size(26, 25); this.actioncontrolclear.TabIndex = 6; this.actioncontrolclear.TabStop = false; - this.actioncontrolclear.Text = "Clear"; this.actioncontrolclear.UseVisualStyleBackColor = true; this.actioncontrolclear.Click += new System.EventHandler(this.actioncontrolclear_Click); // @@ -1760,6 +1796,7 @@ namespace CodeImp.DoomBuilder.Windows ((System.ComponentModel.ISupportInitialize)(this.mousespeed)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.fieldofview)).EndInit(); this.tabkeys.ResumeLayout(false); + this.tabkeys.PerformLayout(); this.actioncontrolpanel.ResumeLayout(false); this.actioncontrolpanel.PerformLayout(); this.tabcolors.ResumeLayout(false); @@ -1901,5 +1938,8 @@ namespace CodeImp.DoomBuilder.Windows private System.Windows.Forms.Label label23; private System.Windows.Forms.Label numSectorsLabel; private Dotnetrix.Controls.TrackBar tbNumSectors; + private System.Windows.Forms.Button bClearActionFilter; + private System.Windows.Forms.TextBox tbFilterActions; + private System.Windows.Forms.Label label24; } } \ No newline at end of file diff --git a/Source/Core/Windows/PreferencesForm.cs b/Source/Core/Windows/PreferencesForm.cs index 2338fdd2..17eaa24e 100644 --- a/Source/Core/Windows/PreferencesForm.cs +++ b/Source/Core/Windows/PreferencesForm.cs @@ -42,6 +42,8 @@ namespace CodeImp.DoomBuilder.Windows private bool allowapplycontrol = false; private bool disregardshift = false; private bool disregardcontrol = false; + private List actionListItems; //mxd + private List actionListItemsGroupIndices; //mxd private bool reloadresources = false; @@ -137,6 +139,8 @@ namespace CodeImp.DoomBuilder.Windows // Fill list of actions actions = General.Actions.GetAllActions(); + actionListItems = new List(); //mxd + actionListItemsGroupIndices = new List(); //mxd foreach(Actions.Action a in actions) { // Create item @@ -145,8 +149,14 @@ namespace CodeImp.DoomBuilder.Windows item.SubItems[1].Tag = a.ShortcutKey; // Put in category, if the category exists - if(General.Actions.Categories.ContainsKey(a.Category)) + if(General.Actions.Categories.ContainsKey(a.Category)) { item.Group = listactions.Groups[a.Category]; + actionListItemsGroupIndices.Add(listactions.Groups.IndexOf(item.Group)); + }else{ //mxd + actionListItemsGroupIndices.Add(-1); + } + + actionListItems.Add(item); //mxd } // Set the colors @@ -245,7 +255,8 @@ namespace CodeImp.DoomBuilder.Windows General.Settings.ScriptFontSize = fontsize; // Apply control keys to actions - foreach(ListViewItem item in listactions.Items) + //foreach(ListViewItem item in listactions.Items) + foreach(ListViewItem item in actionListItems) //mxd General.Actions[item.Name].SetShortcutKey((int)item.SubItems[1].Tag); // Apply the colors @@ -764,6 +775,50 @@ namespace CodeImp.DoomBuilder.Windows allowapplycontrol = true; } + //mxd + private void bClearActionFilter_Click(object sender, EventArgs e) { + tbFilterActions.Clear(); + } + + //mxd + private void tbFilterActions_TextChanged(object sender, EventArgs e) { + listactions.BeginUpdate(); + + //restore everything + if(string.IsNullOrEmpty(tbFilterActions.Text)) { + //restore items + listactions.Items.Clear(); + listactions.Items.AddRange(actionListItems.ToArray()); + + //restore groups + for(int i = 0; i < actionListItems.Count; i++) { + if(actionListItemsGroupIndices[i] != -1) + actionListItems[i].Group = listactions.Groups[actionListItemsGroupIndices[i]]; + } + } else { //apply filtering + string match = tbFilterActions.Text.ToUpperInvariant(); + + for(int i = 0; i < actionListItems.Count; i++) { + if(actionListItems[i].Text.ToUpperInvariant().Contains(match)) { + //ensure visible + if(!listactions.Items.Contains(actionListItems[i])) { + listactions.Items.Add(actionListItems[i]); + + //restore group + if(actionListItemsGroupIndices[i] != -1) + actionListItems[i].Group = listactions.Groups[actionListItemsGroupIndices[i]]; + } + } else if(listactions.Items.Contains(actionListItems[i])) { + //ensure invisible + listactions.Items.Remove(actionListItems[i]); + } + } + } + + listactions.Sort(); + listactions.EndUpdate(); + } + #endregion #region ================== Colors Panel diff --git a/Source/Core/Windows/PreferencesForm.resx b/Source/Core/Windows/PreferencesForm.resx index d68fbbd5..983bf1dc 100644 --- a/Source/Core/Windows/PreferencesForm.resx +++ b/Source/Core/Windows/PreferencesForm.resx @@ -144,4 +144,7 @@ False + + 17, 17 + \ No newline at end of file diff --git a/Source/Plugins/BuilderModes/Resources/Actions.cfg b/Source/Plugins/BuilderModes/Resources/Actions.cfg index 382dfaa8..367dc3af 100644 --- a/Source/Plugins/BuilderModes/Resources/Actions.cfg +++ b/Source/Plugins/BuilderModes/Resources/Actions.cfg @@ -499,10 +499,11 @@ lowersectortonearest { title = "Lower Floor/Ceiling to adjacent sector"; category = "visual"; - description = "Lowers the targeted or selected floors/ceilings to match the height of adjacent sector. Also drops selected things to floor."; + description = "Lowers the targeted or selected floors/ceilings to match the height of adjacent sector. Hold Ctrl to lower to lowest surface in selection. Also drops selected things to floor."; allowkeys = true; allowmouse = true; allowscroll = true; + disregardcontrol = true; default = 34; //PgDn } @@ -511,10 +512,11 @@ raisesectortonearest { title = "Raise Floor/Ceiling to adjacent sector"; category = "visual"; - description = "Raises the targeted or selected floors/ceilings to match the height of adjacent sector. Also aligns selected things to ceiling."; + description = "Raises the targeted or selected floors/ceilings to match the height of adjacent sector. Hold Ctrl to raise to highest surface in selection. Also aligns selected things to ceiling."; allowkeys = true; allowmouse = true; allowscroll = true; + disregardcontrol = true; default = 33; //PgUp } @@ -672,6 +674,18 @@ texturepaste allowscroll = true; } +//mxd +visualautoalign +{ + title = "Auto-align Textures X and Y"; + category = "visual"; + description = "Automatically aligns the neighbouring textures X and Y offsets until another texture is encountered."; + allowkeys = true; + allowmouse = true; + allowscroll = true; + default = 131137; //Ctrl-A +} + visualautoalignx { title = "Auto-align Textures X"; diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs index 07632404..94df503c 100644 --- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs +++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs @@ -1632,7 +1632,7 @@ namespace CodeImp.DoomBuilder.BuilderModes Dictionary ceilings = new Dictionary(); List things = new List(); bool undoGroupCreated = false; - string alignFailDescription = string.Empty; + bool withinSelection = General.Interface.CtrlState; //get selection if(selectedobjects.Count == 0) { @@ -1660,12 +1660,36 @@ namespace CodeImp.DoomBuilder.BuilderModes } } + //check what we have + if(floors.Count + ceilings.Count + things.Count == 0) { + General.Interface.DisplayStatus(StatusType.Warning, "No suitable objects found!"); + PostAction(); + return; + } + + if(withinSelection) { + string s = string.Empty; + + if(floors.Count == 1) s = "floors"; + + if(ceilings.Count == 1) { + if(!string.IsNullOrEmpty(s)) s += " and "; + s += "ceilings"; + } + + if(!string.IsNullOrEmpty(s)){ + General.Interface.DisplayStatus(StatusType.Warning, "Can't do: at least 2 selected " + s + " are required!"); + PostAction(); + return; + } + } + //process floors... int maxSelectedHeight = int.MinValue; int minSelectedCeilingHeight = int.MaxValue; - int targetHeight = int.MaxValue; + int targetFloorHeight = int.MaxValue; - //get maximum floor height from selection + //get maximum floor and minimum ceiling heights from selection foreach(KeyValuePair group in floors) { if(group.Key.FloorHeight > maxSelectedHeight) maxSelectedHeight = group.Key.FloorHeight; @@ -1674,32 +1698,30 @@ namespace CodeImp.DoomBuilder.BuilderModes minSelectedCeilingHeight = group.Key.CeilHeight; } - //get next higher floor from surrounding unselected sectors - foreach(KeyValuePair group in floors) { - foreach(Sidedef side in group.Key.Sidedefs) { - if(side.Other == null || ceilings.ContainsKey(side.Other.Sector) || floors.ContainsKey(side.Other.Sector)) - continue; - if(side.Other.Sector.FloorHeight > maxSelectedHeight && side.Other.Sector.FloorHeight < targetHeight && side.Other.Sector.FloorHeight <= minSelectedCeilingHeight) - targetHeight = side.Other.Sector.FloorHeight; + if(withinSelection) { + //check heights + if(minSelectedCeilingHeight < maxSelectedHeight) { + General.Interface.DisplayStatus(StatusType.Warning, "Can't do: lowest ceiling is lower than highest floor!"); + PostAction(); + return; + } else { + targetFloorHeight = maxSelectedHeight; } - } - - //change floor height - if(targetHeight != int.MaxValue) { - PreAction(UndoGroup.SectorHeightChange); - undoGroupCreated = true; - + } else { + //get next higher floor from surrounding unselected sectors foreach(KeyValuePair group in floors) { - if(targetHeight != group.Key.FloorHeight) - group.Value.OnChangeTargetHeight(targetHeight - group.Key.FloorHeight); + foreach(Sidedef side in group.Key.Sidedefs) { + if(side.Other == null || ceilings.ContainsKey(side.Other.Sector) || floors.ContainsKey(side.Other.Sector)) + continue; + if(side.Other.Sector.FloorHeight > maxSelectedHeight && side.Other.Sector.FloorHeight < targetFloorHeight && side.Other.Sector.FloorHeight <= minSelectedCeilingHeight) + targetFloorHeight = side.Other.Sector.FloorHeight; + } } - } else if(floors.Count > 0) { - alignFailDescription = floors.Count > 1 ? "floors" : "floor"; } //ceilings... maxSelectedHeight = int.MinValue; - targetHeight = int.MaxValue; + int targetCeilingHeight = int.MaxValue; //get highest ceiling height from selection foreach(KeyValuePair group in ceilings) { @@ -1707,32 +1729,63 @@ namespace CodeImp.DoomBuilder.BuilderModes maxSelectedHeight = group.Key.CeilHeight; } - //get next higher ceiling from surrounding unselected sectors - foreach(KeyValuePair group in ceilings) { - foreach(Sidedef side in group.Key.Sidedefs) { - if(side.Other == null || ceilings.ContainsKey(side.Other.Sector) || floors.ContainsKey(side.Other.Sector)) - continue; - if(side.Other.Sector.CeilHeight < targetHeight && side.Other.Sector.CeilHeight > maxSelectedHeight) - targetHeight = side.Other.Sector.CeilHeight; + if(withinSelection) { + //we are raising, so we don't need to check anything + targetCeilingHeight = maxSelectedHeight; + } else { + //get next higher ceiling from surrounding unselected sectors + foreach(KeyValuePair group in ceilings) { + foreach(Sidedef side in group.Key.Sidedefs) { + if(side.Other == null || ceilings.ContainsKey(side.Other.Sector) || floors.ContainsKey(side.Other.Sector)) + continue; + if(side.Other.Sector.CeilHeight < targetCeilingHeight && side.Other.Sector.CeilHeight > maxSelectedHeight) + targetCeilingHeight = side.Other.Sector.CeilHeight; + } } } - //change ceiling height - if(targetHeight != int.MaxValue) { + //CHECK VALUES + string alignFailDescription = string.Empty; + + if(floors.Count > 0 && targetFloorHeight == int.MaxValue) + alignFailDescription = floors.Count > 1 ? "floors" : "floor"; + + if(ceilings.Count > 0 && targetCeilingHeight == int.MaxValue) { + if(!string.IsNullOrEmpty(alignFailDescription)) + alignFailDescription += " and "; + + alignFailDescription += ceilings.Count > 1 ? "ceilings" : "ceiling"; + } + + if(!string.IsNullOrEmpty(alignFailDescription)) { + General.Interface.DisplayStatus(StatusType.Warning, "Unable to align selected " + alignFailDescription + "!"); + PostAction(); + return; + } + + //APPLY VALUES + //change floors heights + if(floors.Count > 0) { + PreAction(UndoGroup.SectorHeightChange); + undoGroupCreated = true; + + foreach(KeyValuePair group in floors) { + if(targetFloorHeight != group.Key.FloorHeight) + group.Value.OnChangeTargetHeight(targetFloorHeight - group.Key.FloorHeight); + } + } + + //change ceilings heights + if(ceilings.Count > 0) { if(!undoGroupCreated) { PreAction(UndoGroup.SectorHeightChange); undoGroupCreated = true; } foreach(KeyValuePair group in ceilings) { - if(targetHeight != group.Key.CeilHeight) - group.Value.OnChangeTargetHeight(targetHeight - group.Key.CeilHeight); + if(targetCeilingHeight != group.Key.CeilHeight) + group.Value.OnChangeTargetHeight(targetCeilingHeight - group.Key.CeilHeight); } - } else if(ceilings.Count > 0) { - if(!string.IsNullOrEmpty(alignFailDescription)) - alignFailDescription += " and "; - - alignFailDescription += ceilings.Count > 1 ? "ceilings" : "ceiling"; } //and things. Just align them to ceiling @@ -1753,9 +1806,6 @@ namespace CodeImp.DoomBuilder.BuilderModes } } - if(!string.IsNullOrEmpty(alignFailDescription)) - General.Interface.DisplayStatus(StatusType.Warning, "Unable to align selected " + alignFailDescription + "!"); - PostAction(); } @@ -1766,7 +1816,7 @@ namespace CodeImp.DoomBuilder.BuilderModes Dictionary ceilings = new Dictionary(); List things = new List(); bool undoGroupCreated = false; - string alignFailDescription = string.Empty; + bool withinSelection = General.Interface.CtrlState; //get selection if(selectedobjects.Count == 0) { @@ -1794,43 +1844,59 @@ namespace CodeImp.DoomBuilder.BuilderModes } } + //check what we have + if(floors.Count + ceilings.Count + things.Count == 0) { + General.Interface.DisplayStatus(StatusType.Warning, "No suitable objects found!"); + PostAction(); + return; + } + + if(withinSelection) { + string s = string.Empty; + + if(floors.Count == 1) s = "floors"; + + if(ceilings.Count == 1) { + if(!string.IsNullOrEmpty(s)) s += " and "; + s += "ceilings"; + } + + if(!string.IsNullOrEmpty(s)) { + General.Interface.DisplayStatus(StatusType.Warning, "Can't do: at least 2 selected " + s + " are required!"); + PostAction(); + return; + } + } + //process floors... int minSelectedHeight = int.MaxValue; - int targetHeight = int.MinValue; + int targetFloorHeight = int.MinValue; //get minimum floor height from selection foreach(KeyValuePair group in floors) { if(group.Key.FloorHeight < minSelectedHeight) minSelectedHeight = group.Key.FloorHeight; } - - //get next floor lower height from surrounding unselected sectors - foreach(KeyValuePair group in floors){ - foreach(Sidedef side in group.Key.Sidedefs) { - if(side.Other == null || ceilings.ContainsKey(side.Other.Sector) || floors.ContainsKey(side.Other.Sector)) - continue; - if(side.Other.Sector.FloorHeight > targetHeight && side.Other.Sector.FloorHeight < minSelectedHeight) - targetHeight = side.Other.Sector.FloorHeight; - } - } - - //change floor height - if(targetHeight != int.MinValue) { - PreAction(UndoGroup.SectorHeightChange); - undoGroupCreated = true; - + + if(withinSelection) { + //we are lowering, so we don't need to check anything + targetFloorHeight = minSelectedHeight; + } else { + //get next floor lower height from surrounding unselected sectors foreach(KeyValuePair group in floors) { - if(targetHeight != group.Key.FloorHeight) - group.Value.OnChangeTargetHeight(targetHeight - group.Key.FloorHeight); + foreach(Sidedef side in group.Key.Sidedefs) { + if(side.Other == null || ceilings.ContainsKey(side.Other.Sector) || floors.ContainsKey(side.Other.Sector)) + continue; + if(side.Other.Sector.FloorHeight > targetFloorHeight && side.Other.Sector.FloorHeight < minSelectedHeight) + targetFloorHeight = side.Other.Sector.FloorHeight; + } } - } else if(floors.Count > 0) { - alignFailDescription = floors.Count > 1 ? "floors" : "floor"; } //ceilings... minSelectedHeight = int.MaxValue; int maxSelectedFloorHeight = int.MinValue; - targetHeight = int.MinValue; + int targetCeilingHeight = int.MinValue; //get minimum ceiling and maximum floor heights from selection foreach(KeyValuePair group in ceilings) { @@ -1841,35 +1907,71 @@ namespace CodeImp.DoomBuilder.BuilderModes maxSelectedFloorHeight = group.Key.FloorHeight; } - //get next lower ceiling height from surrounding unselected sectors - foreach(KeyValuePair group in ceilings) { - foreach(Sidedef side in group.Key.Sidedefs) { - if(side.Other == null || ceilings.ContainsKey(side.Other.Sector) || floors.ContainsKey(side.Other.Sector)) - continue; - if(side.Other.Sector.CeilHeight > targetHeight && side.Other.Sector.CeilHeight < minSelectedHeight && side.Other.Sector.CeilHeight >= maxSelectedFloorHeight) - targetHeight = side.Other.Sector.CeilHeight; + if(withinSelection) { + if(minSelectedHeight < maxSelectedFloorHeight) { + General.Interface.DisplayStatus(StatusType.Warning, "Can't do: lowest ceiling is lower than highest floor!"); + PostAction(); + return; + } else { + targetCeilingHeight = minSelectedHeight; + } + } else { + //get next lower ceiling height from surrounding unselected sectors + foreach(KeyValuePair group in ceilings) { + foreach(Sidedef side in group.Key.Sidedefs) { + if(side.Other == null || ceilings.ContainsKey(side.Other.Sector) || floors.ContainsKey(side.Other.Sector)) + continue; + if(side.Other.Sector.CeilHeight > targetCeilingHeight && side.Other.Sector.CeilHeight < minSelectedHeight && side.Other.Sector.CeilHeight >= maxSelectedFloorHeight) + targetCeilingHeight = side.Other.Sector.CeilHeight; + } } } - //change ceiling height - if(targetHeight != int.MinValue) { - if(!undoGroupCreated) { - PreAction(UndoGroup.SectorHeightChange); - undoGroupCreated = true; - } + //CHECK VALUES: + string alignFailDescription = string.Empty; - foreach(KeyValuePair group in ceilings) { - if(targetHeight != group.Key.CeilHeight) - group.Value.OnChangeTargetHeight(targetHeight - group.Key.CeilHeight); - } - } else if(ceilings.Count > 0) { + if(floors.Count > 0 && targetFloorHeight == int.MinValue) + alignFailDescription = floors.Count > 1 ? "floors" : "floor"; + + if(ceilings.Count > 0 && targetCeilingHeight == int.MinValue) { if(!string.IsNullOrEmpty(alignFailDescription)) alignFailDescription += " and "; alignFailDescription += ceilings.Count > 1 ? "ceilings" : "ceiling"; } - //and things. Just drop them to ground + if(!string.IsNullOrEmpty(alignFailDescription)) { + General.Interface.DisplayStatus(StatusType.Warning, "Unable to align selected " + alignFailDescription + "!"); + PostAction(); + return; + } + + //APPLY VALUES: + //change floor height + if(floors.Count > 0) { + PreAction(UndoGroup.SectorHeightChange); + undoGroupCreated = true; + + foreach(KeyValuePair group in floors) { + if(targetFloorHeight != group.Key.FloorHeight) + group.Value.OnChangeTargetHeight(targetFloorHeight - group.Key.FloorHeight); + } + } + + //change ceiling height + if(ceilings.Count > 0) { + if(!undoGroupCreated) { + PreAction(UndoGroup.SectorHeightChange); + undoGroupCreated = true; + } + + foreach(KeyValuePair group in ceilings) { + if(targetCeilingHeight != group.Key.CeilHeight) + group.Value.OnChangeTargetHeight(targetCeilingHeight - group.Key.CeilHeight); + } + } + + //process things. Just drop them to ground if(General.Map.FormatInterface.HasThingHeight){ foreach(BaseVisualThing vt in things) { if(vt.Thing.Sector == null) continue; @@ -1886,9 +1988,6 @@ namespace CodeImp.DoomBuilder.BuilderModes } } - if(!string.IsNullOrEmpty(alignFailDescription)) - General.Interface.DisplayStatus(StatusType.Warning, "Unable to align selected " + alignFailDescription + "!"); - PostAction(); } @@ -2018,6 +2117,18 @@ namespace CodeImp.DoomBuilder.BuilderModes PostAction(); } + //mxd + [BeginAction("visualautoalign")] + public void TextureAutoAlign() { + PreAction(UndoGroup.None); + renderer.SetCrosshairBusy(true); + General.Interface.RedrawDisplay(); + GetTargetEventReceiver(false).OnTextureAlign(true, true); + UpdateChangedObjects(); + renderer.SetCrosshairBusy(false); + PostAction(); + } + [BeginAction("visualautoalignx")] public void TextureAutoAlignX() {