mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2025-01-31 04:40:55 +00:00
Visual Mode: added "Lower Floor/Ceiling to adjacent sector" and "Raise Floor/Ceiling to adjacent sector" actions.
UDMF texture offsets are now used when splitting a linedef in UDMF map format. Some changes in auto texture alignment of newly drawn lines.
This commit is contained in:
parent
c6378809d5
commit
4a6897a6ed
4 changed files with 416 additions and 72 deletions
|
@ -1431,50 +1431,15 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
}
|
||||
|
||||
//mxd
|
||||
if(autoAlignTextureOffsets) {
|
||||
if(autoAlignTextureOffsets && !General.Map.UDMF) {
|
||||
//Auto-align new lines
|
||||
if(newlines.Count > 1) {
|
||||
float curLength = 0f;
|
||||
float totalLength = 0f;
|
||||
|
||||
foreach(Linedef l in newlines)
|
||||
totalLength += l.Length;
|
||||
|
||||
bool reversed = newlines[0].End != newlines[1].Start;
|
||||
|
||||
foreach(Linedef l in newlines) {
|
||||
if(l.Front != null) {
|
||||
ImageData texture = null;
|
||||
|
||||
if(l.Front.MiddleRequired() && l.Front.MiddleTexture.Length > 1 && General.Map.Data.GetFlatExists(l.Front.MiddleTexture)) {
|
||||
texture = General.Map.Data.GetFlatImage(l.Front.MiddleTexture);
|
||||
} else if(l.Front.HighRequired() && l.Front.HighTexture.Length > 1 && General.Map.Data.GetFlatExists(l.Front.HighTexture)) {
|
||||
texture = General.Map.Data.GetFlatImage(l.Front.HighTexture);
|
||||
} else if(l.Front.LowRequired() && l.Front.LowTexture.Length > 1 && General.Map.Data.GetFlatExists(l.Front.LowTexture)) {
|
||||
texture = General.Map.Data.GetFlatImage(l.Front.LowTexture);
|
||||
}
|
||||
|
||||
if(texture != null)
|
||||
l.Front.OffsetX = (int)Math.Round((reversed ? totalLength - curLength - l.Length : curLength));// % texture.Width);
|
||||
}
|
||||
|
||||
if(l.Back != null) {
|
||||
ImageData texture = null;
|
||||
|
||||
if(l.Back.MiddleRequired() && l.Back.MiddleTexture.Length > 1 && General.Map.Data.GetFlatExists(l.Back.MiddleTexture)) {
|
||||
texture = General.Map.Data.GetFlatImage(l.Back.MiddleTexture);
|
||||
} else if(l.Back.HighRequired() && l.Back.HighTexture.Length > 1 && General.Map.Data.GetFlatExists(l.Back.HighTexture)) {
|
||||
texture = General.Map.Data.GetFlatImage(l.Back.HighTexture);
|
||||
} else if(l.Back.LowRequired() && l.Back.LowTexture.Length > 1 && General.Map.Data.GetFlatExists(l.Back.LowTexture)) {
|
||||
texture = General.Map.Data.GetFlatImage(l.Back.LowTexture);
|
||||
}
|
||||
|
||||
if(texture != null)
|
||||
l.Back.OffsetX = (int)Math.Round((reversed ? totalLength - curLength - l.Length : curLength));// % texture.Width);
|
||||
}
|
||||
|
||||
curLength += l.Length;
|
||||
}
|
||||
autoAlignTexturesOnSides(newlines, totalLength, (newlines[0].End != newlines[1].Start));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1491,38 +1456,6 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
}
|
||||
}
|
||||
|
||||
foreach(Linedef l in changedLines) {
|
||||
if(l.Front != null) {
|
||||
ImageData texture = null;
|
||||
|
||||
if(l.Front.MiddleRequired() && l.Front.MiddleTexture.Length > 1 && General.Map.Data.GetFlatExists(l.Front.MiddleTexture)) {
|
||||
texture = General.Map.Data.GetFlatImage(l.Front.MiddleTexture);
|
||||
} else if(l.Front.HighRequired() && l.Front.HighTexture.Length > 1 && General.Map.Data.GetFlatExists(l.Front.HighTexture)) {
|
||||
texture = General.Map.Data.GetFlatImage(l.Front.HighTexture);
|
||||
} else if(l.Front.LowRequired() && l.Front.LowTexture.Length > 1 && General.Map.Data.GetFlatExists(l.Front.LowTexture)) {
|
||||
texture = General.Map.Data.GetFlatImage(l.Front.LowTexture);
|
||||
}
|
||||
|
||||
if (texture != null)
|
||||
l.Front.OffsetX %= texture.Width;
|
||||
}
|
||||
|
||||
if(l.Back != null) {
|
||||
ImageData texture = null;
|
||||
|
||||
if(l.Back.MiddleRequired() && l.Back.MiddleTexture.Length > 1 && General.Map.Data.GetFlatExists(l.Back.MiddleTexture)) {
|
||||
texture = General.Map.Data.GetFlatImage(l.Back.MiddleTexture);
|
||||
} else if(l.Back.HighRequired() && l.Back.HighTexture.Length > 1 && General.Map.Data.GetFlatExists(l.Back.HighTexture)) {
|
||||
texture = General.Map.Data.GetFlatImage(l.Back.HighTexture);
|
||||
} else if(l.Back.LowRequired() && l.Back.LowTexture.Length > 1 && General.Map.Data.GetFlatExists(l.Back.LowTexture)) {
|
||||
texture = General.Map.Data.GetFlatImage(l.Back.LowTexture);
|
||||
}
|
||||
|
||||
if (texture != null)
|
||||
l.Back.OffsetX %= texture.Width;
|
||||
}
|
||||
}
|
||||
|
||||
// Mark new geometry only
|
||||
General.Map.Map.ClearMarkedLinedefs(false);
|
||||
General.Map.Map.ClearMarkedVertices(false);
|
||||
|
@ -1533,6 +1466,45 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
return true;
|
||||
}
|
||||
|
||||
//mxd
|
||||
private static void autoAlignTexturesOnSides(List<Linedef> lines, float totalLength, bool reversed) {
|
||||
float curLength = 0f;
|
||||
|
||||
foreach(Linedef l in lines) {
|
||||
if(l.Front != null) {
|
||||
ImageData texture = null;
|
||||
|
||||
if(l.Front.MiddleRequired() && l.Front.MiddleTexture.Length > 1 && General.Map.Data.GetFlatExists(l.Front.MiddleTexture)) {
|
||||
texture = General.Map.Data.GetFlatImage(l.Front.MiddleTexture);
|
||||
} else if(l.Front.HighRequired() && l.Front.HighTexture.Length > 1 && General.Map.Data.GetFlatExists(l.Front.HighTexture)) {
|
||||
texture = General.Map.Data.GetFlatImage(l.Front.HighTexture);
|
||||
} else if(l.Front.LowRequired() && l.Front.LowTexture.Length > 1 && General.Map.Data.GetFlatExists(l.Front.LowTexture)) {
|
||||
texture = General.Map.Data.GetFlatImage(l.Front.LowTexture);
|
||||
}
|
||||
|
||||
if(texture != null)
|
||||
l.Front.OffsetX = (int)Math.Round((reversed ? totalLength - curLength - l.Length : curLength)) % texture.Width;
|
||||
}
|
||||
|
||||
if(l.Back != null) {
|
||||
ImageData texture = null;
|
||||
|
||||
if(l.Back.MiddleRequired() && l.Back.MiddleTexture.Length > 1 && General.Map.Data.GetFlatExists(l.Back.MiddleTexture)) {
|
||||
texture = General.Map.Data.GetFlatImage(l.Back.MiddleTexture);
|
||||
} else if(l.Back.HighRequired() && l.Back.HighTexture.Length > 1 && General.Map.Data.GetFlatExists(l.Back.HighTexture)) {
|
||||
texture = General.Map.Data.GetFlatImage(l.Back.HighTexture);
|
||||
} else if(l.Back.LowRequired() && l.Back.LowTexture.Length > 1 && General.Map.Data.GetFlatExists(l.Back.LowTexture)) {
|
||||
texture = General.Map.Data.GetFlatImage(l.Back.LowTexture);
|
||||
}
|
||||
|
||||
if(texture != null)
|
||||
l.Back.OffsetX = (int)Math.Round((reversed ? totalLength - curLength - l.Length : curLength)) % texture.Width;
|
||||
}
|
||||
|
||||
curLength += l.Length;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Flat Floodfill
|
||||
|
@ -1777,7 +1749,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
|
||||
#endregion
|
||||
|
||||
#region Thing Alignment (mxd)
|
||||
#region ================== Thing Alignment (mxd)
|
||||
|
||||
public static bool TryAlignThingToLine(Thing t, Linedef l) {
|
||||
if(l.Back == null) {
|
||||
|
|
|
@ -27,6 +27,8 @@ using CodeImp.DoomBuilder.Rendering;
|
|||
using SlimDX.Direct3D9;
|
||||
using System.Drawing;
|
||||
using CodeImp.DoomBuilder.IO;
|
||||
using CodeImp.DoomBuilder.Types;
|
||||
using CodeImp.DoomBuilder.Data;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -816,7 +818,8 @@ namespace CodeImp.DoomBuilder.Map
|
|||
nsd.Marked = front.Marked;
|
||||
|
||||
// Make texture offset adjustments
|
||||
nsd.OffsetX += (int)Vector2D.Distance(this.start.Position, this.end.Position);
|
||||
if(nsd.OffsetX != 0 || !General.Map.UDMF) //mxd
|
||||
nsd.OffsetX += (int)Vector2D.Distance(this.start.Position, this.end.Position);
|
||||
}
|
||||
|
||||
// Copy back sidedef if exists
|
||||
|
@ -828,7 +831,18 @@ namespace CodeImp.DoomBuilder.Map
|
|||
nsd.Marked = back.Marked;
|
||||
|
||||
// Make texture offset adjustments
|
||||
back.OffsetX += (int)Vector2D.Distance(nl.start.Position, nl.end.Position);
|
||||
//mxd
|
||||
int distance = (int)Vector2D.Distance(nl.start.Position, nl.end.Position);
|
||||
if(back.OffsetX != 0 || General.Map.UDMF)
|
||||
if(distance != 0) applyTextureOffsetUDMF(back, distance);
|
||||
else
|
||||
back.OffsetX += distance;
|
||||
}
|
||||
|
||||
//mxd. Both sides of line are required, so we do it here...
|
||||
if(nl.Front != null && General.Map.UDMF) {
|
||||
int distance = (int)Vector2D.Distance(this.start.Position, this.end.Position);
|
||||
if(distance != 0) applyTextureOffsetUDMF(nl.Front, distance);
|
||||
}
|
||||
|
||||
// Return result
|
||||
|
@ -1055,6 +1069,73 @@ namespace CodeImp.DoomBuilder.Map
|
|||
colorPresetIndex = -1;
|
||||
}
|
||||
|
||||
//mxd
|
||||
private void applyTextureOffsetUDMF(Sidedef side, int distance) {
|
||||
float scaleTop = side.Fields.GetValue("scalex_top", 1.0f);
|
||||
float scaleMid = side.Fields.GetValue("scalex_mid", 1.0f);
|
||||
float scaleLow = side.Fields.GetValue("scalex_bottom", 1.0f);
|
||||
|
||||
//top
|
||||
if(side.HighTexture.Length > 1 && General.Map.Data.GetFlatExists(side.HighTexture)) {
|
||||
ImageData texture = General.Map.Data.GetFlatImage(side.HighTexture);
|
||||
|
||||
if(side.Fields.ContainsKey("offsetx_top")) {
|
||||
float value = side.Fields.GetValue("offsetx_top", 0f);
|
||||
float offset = (float)(Math.Round((value + distance) * scaleTop) % texture.Width);
|
||||
|
||||
if(offset != 0)
|
||||
side.Fields["offsetx_top"].Value = offset;
|
||||
else
|
||||
side.Fields.Remove("offsetx_top");
|
||||
} else if(side.HighRequired()) {
|
||||
float offset = (float)(Math.Round(distance * scaleTop) % texture.Width);
|
||||
|
||||
if(offset != 0)
|
||||
side.Fields.Add("offsetx_top", new UniValue(UniversalType.Float, offset));
|
||||
}
|
||||
}
|
||||
|
||||
//middle
|
||||
if(side.MiddleTexture.Length > 1 && General.Map.Data.GetFlatExists(side.MiddleTexture)){
|
||||
ImageData texture = General.Map.Data.GetFlatImage(side.MiddleTexture);
|
||||
|
||||
if(side.Fields.ContainsKey("offsetx_mid")) {
|
||||
float value = side.Fields.GetValue("offsetx_mid", 0f);
|
||||
float offset = (float)(Math.Round((value + distance) * scaleMid) % texture.Width);
|
||||
|
||||
if(offset != 0)
|
||||
side.Fields["offsetx_mid"].Value = offset;
|
||||
else
|
||||
side.Fields.Remove("offsetx_mid");
|
||||
} else if(side.MiddleRequired()) {
|
||||
float offset = (float)(Math.Round(distance * scaleMid) % texture.Width);
|
||||
|
||||
if(offset != 0)
|
||||
side.Fields.Add("offsetx_mid", new UniValue(UniversalType.Float, offset));
|
||||
}
|
||||
}
|
||||
|
||||
//bottom
|
||||
if(side.LowTexture.Length > 1 && General.Map.Data.GetFlatExists(side.LowTexture)){
|
||||
ImageData texture = General.Map.Data.GetFlatImage(side.LowTexture);
|
||||
|
||||
if(side.Fields.ContainsKey("offsetx_bottom")) {
|
||||
float value = side.Fields.GetValue("offsetx_bottom", 0f);
|
||||
float offset = (float)(Math.Round((value + distance) * scaleLow) % texture.Width);
|
||||
|
||||
if(offset != 0)
|
||||
side.Fields["offsetx_bottom"].Value = offset;
|
||||
else
|
||||
side.Fields.Remove("offsetx_bottom");
|
||||
} else if(side.LowRequired()) {
|
||||
float offset = (float)(Math.Round(distance * scaleLow) % texture.Width);
|
||||
|
||||
if(offset != 0)
|
||||
side.Fields.Add("offsetx_bottom", new UniValue(UniversalType.Float, offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// String representation
|
||||
public override string ToString()
|
||||
{
|
||||
|
|
|
@ -494,6 +494,30 @@ raisesector1
|
|||
repeat = true;
|
||||
}
|
||||
|
||||
//mxd
|
||||
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.";
|
||||
allowkeys = true;
|
||||
allowmouse = true;
|
||||
allowscroll = true;
|
||||
default = 34; //PgDn
|
||||
}
|
||||
|
||||
//mxd
|
||||
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.";
|
||||
allowkeys = true;
|
||||
allowmouse = true;
|
||||
allowscroll = true;
|
||||
default = 33; //PgUp
|
||||
}
|
||||
|
||||
showvisualthings
|
||||
{
|
||||
title = "Show Things";
|
||||
|
|
|
@ -1624,6 +1624,273 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
PostAction();
|
||||
}
|
||||
|
||||
//mxd
|
||||
[BeginAction("raisesectortonearest")]
|
||||
public void RaiseSectorToNearest() {
|
||||
Dictionary<Sector, VisualFloor> floors = new Dictionary<Sector, VisualFloor>();
|
||||
Dictionary<Sector, VisualCeiling> ceilings = new Dictionary<Sector, VisualCeiling>();
|
||||
List<BaseVisualThing> things = new List<BaseVisualThing>();
|
||||
bool undoGroupCreated = false;
|
||||
string alignFailDescription = string.Empty;
|
||||
|
||||
//get selection
|
||||
if(selectedobjects.Count == 0) {
|
||||
IVisualEventReceiver i = (target.picked as IVisualEventReceiver);
|
||||
if(i is VisualFloor) {
|
||||
VisualFloor vf = i as VisualFloor;
|
||||
floors.Add(vf.Level.sector, vf);
|
||||
} else if(i is VisualCeiling) {
|
||||
VisualCeiling vc = i as VisualCeiling;
|
||||
ceilings.Add(vc.Level.sector, vc);
|
||||
} else if(i is BaseVisualThing) {
|
||||
things.Add(i as BaseVisualThing);
|
||||
}
|
||||
} else {
|
||||
foreach(IVisualEventReceiver i in selectedobjects) {
|
||||
if(i is VisualFloor) {
|
||||
VisualFloor vf = i as VisualFloor;
|
||||
floors.Add(vf.Level.sector, vf);
|
||||
} else if(i is VisualCeiling) {
|
||||
VisualCeiling vc = i as VisualCeiling;
|
||||
ceilings.Add(vc.Level.sector, vc);
|
||||
} else if(i is BaseVisualThing) {
|
||||
things.Add(i as BaseVisualThing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//process floors...
|
||||
int maxSelectedHeight = int.MinValue;
|
||||
int minSelectedCeilingHeight = int.MaxValue;
|
||||
int targetHeight = int.MaxValue;
|
||||
|
||||
//get maximum floor height from selection
|
||||
foreach(KeyValuePair<Sector, VisualFloor> group in floors) {
|
||||
if(group.Key.FloorHeight > maxSelectedHeight)
|
||||
maxSelectedHeight = group.Key.FloorHeight;
|
||||
|
||||
if(group.Key.CeilHeight < minSelectedCeilingHeight)
|
||||
minSelectedCeilingHeight = group.Key.CeilHeight;
|
||||
}
|
||||
|
||||
//get next higher floor from surrounding unselected sectors
|
||||
foreach(KeyValuePair<Sector, VisualFloor> 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;
|
||||
}
|
||||
}
|
||||
|
||||
//change floor height
|
||||
if(targetHeight != int.MaxValue) {
|
||||
PreAction(UndoGroup.SectorHeightChange);
|
||||
undoGroupCreated = true;
|
||||
|
||||
foreach(KeyValuePair<Sector, VisualFloor> group in floors) {
|
||||
if(targetHeight != group.Key.FloorHeight)
|
||||
group.Value.OnChangeTargetHeight(targetHeight - group.Key.FloorHeight);
|
||||
}
|
||||
} else if(floors.Count > 0) {
|
||||
alignFailDescription = floors.Count > 1 ? "floors" : "floor";
|
||||
}
|
||||
|
||||
//ceilings...
|
||||
maxSelectedHeight = int.MinValue;
|
||||
targetHeight = int.MaxValue;
|
||||
|
||||
//get highest ceiling height from selection
|
||||
foreach(KeyValuePair<Sector, VisualCeiling> group in ceilings) {
|
||||
if(group.Key.CeilHeight > maxSelectedHeight)
|
||||
maxSelectedHeight = group.Key.CeilHeight;
|
||||
}
|
||||
|
||||
//get next higher ceiling from surrounding unselected sectors
|
||||
foreach(KeyValuePair<Sector, VisualCeiling> 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;
|
||||
}
|
||||
}
|
||||
|
||||
//change ceiling height
|
||||
if(targetHeight != int.MaxValue) {
|
||||
if(!undoGroupCreated) {
|
||||
PreAction(UndoGroup.SectorHeightChange);
|
||||
undoGroupCreated = true;
|
||||
}
|
||||
|
||||
foreach(KeyValuePair<Sector, VisualCeiling> group in ceilings) {
|
||||
if(targetHeight != group.Key.CeilHeight)
|
||||
group.Value.OnChangeTargetHeight(targetHeight - 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
|
||||
if(General.Map.FormatInterface.HasThingHeight) {
|
||||
foreach(BaseVisualThing vt in things) {
|
||||
if(vt.Thing.Sector == null) continue;
|
||||
ThingTypeInfo ti = General.Map.Data.GetThingInfo(vt.Thing.Type);
|
||||
int zvalue = (int)(vt.Thing.Sector.FloorHeight + vt.Thing.Position.z);
|
||||
|
||||
if(zvalue != vt.Thing.Sector.CeilHeight - ti.Height) {
|
||||
if(!undoGroupCreated) {
|
||||
PreAction(UndoGroup.SectorHeightChange);
|
||||
undoGroupCreated = true;
|
||||
}
|
||||
|
||||
vt.OnChangeTargetHeight((int)(vt.Thing.Sector.CeilHeight - ti.Height) - zvalue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!string.IsNullOrEmpty(alignFailDescription))
|
||||
General.Interface.DisplayStatus(StatusType.Warning, "Unable to align selected " + alignFailDescription + "!");
|
||||
|
||||
PostAction();
|
||||
}
|
||||
|
||||
//mxd
|
||||
[BeginAction("lowersectortonearest")]
|
||||
public void LowerSectorToNearest() {
|
||||
Dictionary<Sector, VisualFloor> floors = new Dictionary<Sector, VisualFloor>();
|
||||
Dictionary<Sector, VisualCeiling> ceilings = new Dictionary<Sector, VisualCeiling>();
|
||||
List<BaseVisualThing> things = new List<BaseVisualThing>();
|
||||
bool undoGroupCreated = false;
|
||||
string alignFailDescription = string.Empty;
|
||||
|
||||
//get selection
|
||||
if(selectedobjects.Count == 0) {
|
||||
IVisualEventReceiver i = (target.picked as IVisualEventReceiver);
|
||||
if(i is VisualFloor) {
|
||||
VisualFloor vf = i as VisualFloor;
|
||||
floors.Add(vf.Level.sector, vf);
|
||||
} else if(i is VisualCeiling) {
|
||||
VisualCeiling vc = i as VisualCeiling;
|
||||
ceilings.Add(vc.Level.sector, vc);
|
||||
} else if(i is BaseVisualThing) {
|
||||
things.Add(i as BaseVisualThing);
|
||||
}
|
||||
}else{
|
||||
foreach(IVisualEventReceiver i in selectedobjects) {
|
||||
if(i is VisualFloor) {
|
||||
VisualFloor vf = i as VisualFloor;
|
||||
floors.Add(vf.Level.sector, vf);
|
||||
} else if(i is VisualCeiling) {
|
||||
VisualCeiling vc = i as VisualCeiling;
|
||||
ceilings.Add(vc.Level.sector, vc);
|
||||
} else if(i is BaseVisualThing) {
|
||||
things.Add(i as BaseVisualThing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//process floors...
|
||||
int minSelectedHeight = int.MaxValue;
|
||||
int targetHeight = int.MinValue;
|
||||
|
||||
//get minimum floor height from selection
|
||||
foreach(KeyValuePair<Sector, VisualFloor> group in floors) {
|
||||
if(group.Key.FloorHeight < minSelectedHeight)
|
||||
minSelectedHeight = group.Key.FloorHeight;
|
||||
}
|
||||
|
||||
//get next floor lower height from surrounding unselected sectors
|
||||
foreach(KeyValuePair<Sector, VisualFloor> 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;
|
||||
|
||||
foreach(KeyValuePair<Sector, VisualFloor> group in floors) {
|
||||
if(targetHeight != group.Key.FloorHeight)
|
||||
group.Value.OnChangeTargetHeight(targetHeight - group.Key.FloorHeight);
|
||||
}
|
||||
} else if(floors.Count > 0) {
|
||||
alignFailDescription = floors.Count > 1 ? "floors" : "floor";
|
||||
}
|
||||
|
||||
//ceilings...
|
||||
minSelectedHeight = int.MaxValue;
|
||||
int maxSelectedFloorHeight = int.MinValue;
|
||||
targetHeight = int.MinValue;
|
||||
|
||||
//get minimum ceiling and maximum floor heights from selection
|
||||
foreach(KeyValuePair<Sector, VisualCeiling> group in ceilings) {
|
||||
if(group.Key.CeilHeight < minSelectedHeight)
|
||||
minSelectedHeight = group.Key.CeilHeight;
|
||||
|
||||
if(group.Key.FloorHeight > maxSelectedFloorHeight)
|
||||
maxSelectedFloorHeight = group.Key.FloorHeight;
|
||||
}
|
||||
|
||||
//get next lower ceiling height from surrounding unselected sectors
|
||||
foreach(KeyValuePair<Sector, VisualCeiling> 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;
|
||||
}
|
||||
}
|
||||
|
||||
//change ceiling height
|
||||
if(targetHeight != int.MinValue) {
|
||||
if(!undoGroupCreated) {
|
||||
PreAction(UndoGroup.SectorHeightChange);
|
||||
undoGroupCreated = true;
|
||||
}
|
||||
|
||||
foreach(KeyValuePair<Sector, VisualCeiling> group in ceilings) {
|
||||
if(targetHeight != group.Key.CeilHeight)
|
||||
group.Value.OnChangeTargetHeight(targetHeight - group.Key.CeilHeight);
|
||||
}
|
||||
} else if(ceilings.Count > 0) {
|
||||
if(!string.IsNullOrEmpty(alignFailDescription))
|
||||
alignFailDescription += " and ";
|
||||
|
||||
alignFailDescription += ceilings.Count > 1 ? "ceilings" : "ceiling";
|
||||
}
|
||||
|
||||
//and things. Just drop them to ground
|
||||
if(General.Map.FormatInterface.HasThingHeight){
|
||||
foreach(BaseVisualThing vt in things) {
|
||||
if(vt.Thing.Sector == null) continue;
|
||||
ThingTypeInfo ti = General.Map.Data.GetThingInfo(vt.Thing.Type);
|
||||
|
||||
if(vt.Thing.Position.z != 0){
|
||||
if(!undoGroupCreated) {
|
||||
PreAction(UndoGroup.SectorHeightChange);
|
||||
undoGroupCreated = true;
|
||||
}
|
||||
|
||||
vt.OnChangeTargetHeight((int)-vt.Thing.Position.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!string.IsNullOrEmpty(alignFailDescription))
|
||||
General.Interface.DisplayStatus(StatusType.Warning, "Unable to align selected " + alignFailDescription + "!");
|
||||
|
||||
PostAction();
|
||||
}
|
||||
|
||||
[BeginAction("showvisualthings")]
|
||||
public void ShowVisualThings()
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue