Cosmetic, actions: renamed "Lower Floor/Ceiling by 8 mp" to "Lower Floor/Ceiling/Thing by 8 mp", "Raise Floor/Ceiling by 8 mp" to "Raise Floor/Ceiling/Thing by 8 mp", "Lower Floor/Ceiling by 1 mp" to "Lower Floor/Ceiling/Thing by 1 mp", "Raise Floor/Ceiling by 1 mp" to "Raise Floor/Ceiling/Thing by 1 mp", "Lower Floor/Ceiling to adjacent sector" to "Lower Floor/Ceiling/Thing to adjacent Sector/Thing", "Raise Floor/Ceiling to adjacent sector" to "Raise Floor/Ceiling/Thing to adjacent Sector/Thing".

Updated, Visual mode, "Raise Floor/Ceiling/Thing to adjacent Sector/Thing" / "Lower Floor/Ceiling/Thing to adjacent Sector/Thing" actions: sectors across targeted sectors are now taken into account when determining target height.
Updated, Visual mode, "Raise Floor/Ceiling/Thing to adjacent Sector/Thing" / "Lower Floor/Ceiling/Thing to adjacent Sector/Thing" actions: the actions can now stack things on top of other things when their bounding boxes intersect. 
Internal: cosmetic changes to shader update logic.
Internal: thing bounding box is now used when adding a thing to VisualBlockMap.
This commit is contained in:
MaxED 2015-12-10 14:34:34 +00:00
parent 44b5c60b0d
commit 2ea51d237b
9 changed files with 404 additions and 173 deletions

View file

@ -29,16 +29,16 @@ namespace CodeImp.DoomBuilder.Rendering
#region ================== Variables #region ================== Variables
// Property handlers // Property handlers
private EffectHandle texture1; private readonly EffectHandle texture1;
private EffectHandle rendersettings; private readonly EffectHandle rendersettings;
private EffectHandle transformsettings; private readonly EffectHandle transformsettings;
private EffectHandle filtersettings; private readonly EffectHandle filtersettings;
#endregion #endregion
#region ================== Properties #region ================== Properties
public Texture Texture1 { set { if(manager.Enabled) effect.SetTexture(texture1, value); } } public Texture Texture1 { set { if(manager.Enabled) effect.SetTexture(texture1, value); settingschanged = true; } }
#endregion #endregion
@ -60,7 +60,7 @@ namespace CodeImp.DoomBuilder.Rendering
} }
// Initialize world vertex declaration // Initialize world vertex declaration
VertexElement[] elements = new VertexElement[] VertexElement[] elements = new[]
{ {
new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0), new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0),
new VertexElement(0, 12, DeclarationType.Color, DeclarationMethod.Default, DeclarationUsage.Color, 0), new VertexElement(0, 12, DeclarationType.Color, DeclarationMethod.Default, DeclarationUsage.Color, 0),
@ -106,6 +106,7 @@ namespace CodeImp.DoomBuilder.Rendering
effect.SetValue(transformsettings, world * view); effect.SetValue(transformsettings, world * view);
TextureFilter filter = (bilinear ? TextureFilter.Linear : TextureFilter.Point); TextureFilter filter = (bilinear ? TextureFilter.Linear : TextureFilter.Point);
effect.SetValue(filtersettings, (int)filter); effect.SetValue(filtersettings, (int)filter);
settingschanged = true; //mxd
} }
} }

View file

@ -164,6 +164,7 @@ namespace CodeImp.DoomBuilder.Rendering
if(highlightimage != null) highlightimage.Dispose(); if(highlightimage != null) highlightimage.Dispose();
selectionimage = null; selectionimage = null;
highlightimage = null; highlightimage = null;
vertexHandle.Dispose(); //mxd
// Done // Done
base.Dispose(); base.Dispose();
@ -748,7 +749,6 @@ namespace CodeImp.DoomBuilder.Rendering
curtexture.CreateTexture(); curtexture.CreateTexture();
// Apply texture // Apply texture
if(!graphics.Shaders.Enabled) graphics.Device.SetTexture(0, curtexture.Texture);
graphics.Shaders.World3D.Texture1 = curtexture.Texture; graphics.Shaders.World3D.Texture1 = curtexture.Texture;
//mxd. Sort geometry by sector index //mxd. Sort geometry by sector index
@ -1248,14 +1248,12 @@ namespace CodeImp.DoomBuilder.Rendering
//mxd //mxd
private Matrix CreateThingPositionMatrix(VisualThing t) private Matrix CreateThingPositionMatrix(VisualThing t)
{ {
Matrix result;
//mxd. Create the matrix for positioning //mxd. Create the matrix for positioning
if(t.Info.RenderMode == Thing.SpriteRenderMode.NORMAL) // Apply billboarding? if(t.Info.RenderMode == Thing.SpriteRenderMode.NORMAL) // Apply billboarding?
{ {
if(t.Info.XYBillboard) if(t.Info.XYBillboard)
{ {
result = Matrix.Translation(0f, 0f, -t.LocalCenterZ) return Matrix.Translation(0f, 0f, -t.LocalCenterZ)
* Matrix.RotationX(Angle2D.PI - General.Map.VisualCamera.AngleZ) * Matrix.RotationX(Angle2D.PI - General.Map.VisualCamera.AngleZ)
* Matrix.Translation(0f, 0f, t.LocalCenterZ) * Matrix.Translation(0f, 0f, t.LocalCenterZ)
* billboard * billboard
@ -1264,18 +1262,16 @@ namespace CodeImp.DoomBuilder.Rendering
} }
else else
{ {
result = billboard return billboard
* Matrix.Scaling(t.Thing.ScaleX, t.Thing.ScaleX, t.Thing.ScaleY) * Matrix.Scaling(t.Thing.ScaleX, t.Thing.ScaleX, t.Thing.ScaleY)
* t.Position; * t.Position;
} }
} }
else else
{ {
result = Matrix.Scaling(t.Thing.ScaleX, t.Thing.ScaleX, t.Thing.ScaleY) return Matrix.Scaling(t.Thing.ScaleX, t.Thing.ScaleX, t.Thing.ScaleY)
* t.Position; * t.Position;
} }
return result;
} }
//mxd. Dynamic lights pass! //mxd. Dynamic lights pass!
@ -1328,12 +1324,12 @@ namespace CodeImp.DoomBuilder.Rendering
{ {
graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.Add); graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.Add);
for (i = 0; i < count; i++) for(i = 0; i < count; i++)
{ {
if (BoundingBoxesIntersect(g.BoundingBox, lights[i].BoundingBox)) if(BoundingBoxesIntersect(g.BoundingBox, lights[i].BoundingBox))
{ {
lpr = new Vector4(lights[i].Center, lights[i].LightRadius); lpr = new Vector4(lights[i].Center, lights[i].LightRadius);
if (lpr.W == 0) continue; if(lpr.W == 0) continue;
graphics.Shaders.World3D.LightColor = lights[i].LightColor; graphics.Shaders.World3D.LightColor = lights[i].LightColor;
graphics.Shaders.World3D.LightPositionAndRadius = lpr; graphics.Shaders.World3D.LightPositionAndRadius = lpr;
graphics.Shaders.World3D.ApplySettings(); graphics.Shaders.World3D.ApplySettings();
@ -1348,12 +1344,12 @@ namespace CodeImp.DoomBuilder.Rendering
count += lightOffsets[1]; count += lightOffsets[1];
graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.Add); graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.Add);
for (i = lightOffsets[0]; i < count; i++) for(i = lightOffsets[0]; i < count; i++)
{ {
if (BoundingBoxesIntersect(g.BoundingBox, lights[i].BoundingBox)) if(BoundingBoxesIntersect(g.BoundingBox, lights[i].BoundingBox))
{ {
lpr = new Vector4(lights[i].Center, lights[i].LightRadius); lpr = new Vector4(lights[i].Center, lights[i].LightRadius);
if (lpr.W == 0) continue; if(lpr.W == 0) continue;
graphics.Shaders.World3D.LightColor = lights[i].LightColor; graphics.Shaders.World3D.LightColor = lights[i].LightColor;
graphics.Shaders.World3D.LightPositionAndRadius = lpr; graphics.Shaders.World3D.LightPositionAndRadius = lpr;
graphics.Shaders.World3D.ApplySettings(); graphics.Shaders.World3D.ApplySettings();
@ -1368,12 +1364,12 @@ namespace CodeImp.DoomBuilder.Rendering
count += lightOffsets[2]; count += lightOffsets[2];
graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.ReverseSubtract); graphics.Device.SetRenderState(RenderState.BlendOperation, BlendOperation.ReverseSubtract);
for (i = lightOffsets[0] + lightOffsets[1]; i < count; i++) for(i = lightOffsets[0] + lightOffsets[1]; i < count; i++)
{ {
if (BoundingBoxesIntersect(g.BoundingBox, lights[i].BoundingBox)) if(BoundingBoxesIntersect(g.BoundingBox, lights[i].BoundingBox))
{ {
lpr = new Vector4(lights[i].Center, lights[i].LightRadius); lpr = new Vector4(lights[i].Center, lights[i].LightRadius);
if (lpr.W == 0) continue; if(lpr.W == 0) continue;
Color4 lc = lights[i].LightColor; Color4 lc = lights[i].LightColor;
graphics.Shaders.World3D.LightColor = new Color4(lc.Alpha, (lc.Green + lc.Blue) / 2, (lc.Red + lc.Blue) / 2, (lc.Green + lc.Red) / 2); graphics.Shaders.World3D.LightColor = new Color4(lc.Alpha, (lc.Green + lc.Blue) / 2, (lc.Red + lc.Blue) / 2, (lc.Green + lc.Red) / 2);
graphics.Shaders.World3D.LightPositionAndRadius = lpr; graphics.Shaders.World3D.LightPositionAndRadius = lpr;

View file

@ -29,20 +29,31 @@ namespace CodeImp.DoomBuilder.Rendering
#region ================== Variables #region ================== Variables
// Property handlers // Property handlers
private EffectHandle texture1; private readonly EffectHandle texture1;
private EffectHandle rendersettings; private readonly EffectHandle rendersettings;
private EffectHandle transformsettings; private readonly EffectHandle transformsettings;
private readonly EffectHandle fillcolor; //mxd
//mxd
private EffectHandle fillColorHandle;
#endregion #endregion
#region ================== Properties #region ================== Properties
public Texture Texture1 { set { if(manager.Enabled) effect.SetTexture(texture1, value); } } public Texture Texture1 { set { if(manager.Enabled) effect.SetTexture(texture1, value); settingschanged = true; } }
//mxd //mxd
public Color4 FillColor { set { if (manager.Enabled) effect.SetValue<Color4>(fillColorHandle, value); } } private Color4 fc;
public Color4 FillColor
{
set
{
if(manager.Enabled && fc != value)
{
effect.SetValue(fillcolor, value);
fc = value;
settingschanged = true;
}
}
}
#endregion #endregion
@ -60,12 +71,11 @@ namespace CodeImp.DoomBuilder.Rendering
texture1 = effect.GetParameter(null, "texture1"); texture1 = effect.GetParameter(null, "texture1");
rendersettings = effect.GetParameter(null, "rendersettings"); rendersettings = effect.GetParameter(null, "rendersettings");
transformsettings = effect.GetParameter(null, "transformsettings"); transformsettings = effect.GetParameter(null, "transformsettings");
//mxd fillcolor = effect.GetParameter(null, "fillColor"); //mxd
fillColorHandle = effect.GetParameter(null, "fillColor");
} }
// Initialize world vertex declaration // Initialize world vertex declaration
VertexElement[] elements = new VertexElement[] VertexElement[] elements = new[]
{ {
new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0), new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0),
new VertexElement(0, 12, DeclarationType.Color, DeclarationMethod.Default, DeclarationUsage.Color, 0), new VertexElement(0, 12, DeclarationType.Color, DeclarationMethod.Default, DeclarationUsage.Color, 0),
@ -88,8 +98,7 @@ namespace CodeImp.DoomBuilder.Rendering
if(texture1 != null) texture1.Dispose(); if(texture1 != null) texture1.Dispose();
if(rendersettings != null) rendersettings.Dispose(); if(rendersettings != null) rendersettings.Dispose();
if(transformsettings != null) transformsettings.Dispose(); if(transformsettings != null) transformsettings.Dispose();
//mxd if(fillcolor != null) fillcolor.Dispose(); //mxd
if (fillColorHandle != null) fillColorHandle.Dispose();
// Done // Done
base.Dispose(); base.Dispose();
@ -110,6 +119,7 @@ namespace CodeImp.DoomBuilder.Rendering
Matrix world = manager.D3DDevice.Device.GetTransform(TransformState.World); Matrix world = manager.D3DDevice.Device.GetTransform(TransformState.World);
Matrix view = manager.D3DDevice.Device.GetTransform(TransformState.View); Matrix view = manager.D3DDevice.Device.GetTransform(TransformState.View);
effect.SetValue(transformsettings, world * view); effect.SetValue(transformsettings, world * view);
settingschanged = true; //mxd
} }
} }

View file

@ -53,7 +53,20 @@ namespace CodeImp.DoomBuilder.Rendering
#region ================== Properties #region ================== Properties
public Matrix WorldViewProj { set { if(manager.Enabled) effect.SetValue(worldviewproj, value); settingschanged = true; } } private Matrix wwp;
public Matrix WorldViewProj
{
set
{
if(manager.Enabled && wwp != value)
{
effect.SetValue(worldviewproj, value);
wwp = value;
settingschanged = true;
}
}
}
public Texture Texture1 { set { if(manager.Enabled) effect.SetTexture(texture1, value); settingschanged = true; } } public Texture Texture1 { set { if(manager.Enabled) effect.SetTexture(texture1, value); settingschanged = true; } }
//mxd //mxd
@ -264,6 +277,8 @@ namespace CodeImp.DoomBuilder.Rendering
effect.SetValue(mipfiltersettings, (int)TextureFilter.Linear); effect.SetValue(mipfiltersettings, (int)TextureFilter.Linear);
effect.SetValue(maxanisotropysetting, 1.0f); effect.SetValue(maxanisotropysetting, 1.0f);
} }
settingschanged = true; //mxd
} }
} }

View file

@ -33,7 +33,7 @@ struct LitPixelData
float4 highlightcolor; float4 highlightcolor;
// Matrix for final transformation // Matrix for final transformation
float4x4 worldviewproj; const float4x4 worldviewproj;
//mxd //mxd
float4x4 world; float4x4 world;
@ -44,16 +44,16 @@ float4 lightPosAndRadius;
float4 lightColor; //also used as fog color float4 lightColor; //also used as fog color
//fog //fog
float4 cameraPos; //w is set to fade factor (distance, at wich fog color completely overrides pixel color) const float4 cameraPos; //w is set to fade factor (distance, at wich fog color completely overrides pixel color)
// Texture input // Texture input
texture texture1; const texture texture1;
// Filter settings // Filter settings
dword minfiltersettings; const dword minfiltersettings;
dword magfiltersettings; const dword magfiltersettings;
dword mipfiltersettings; const dword mipfiltersettings;
float maxanisotropysetting; const float maxanisotropysetting;
// Texture sampler settings // Texture sampler settings
sampler2D texturesamp = sampler_state sampler2D texturesamp = sampler_state

View file

@ -268,9 +268,17 @@ namespace CodeImp.DoomBuilder.VisualModes
// This puts a thing in the blockmap // This puts a thing in the blockmap
public void AddThing(Thing t) public void AddThing(Thing t)
{ {
Point p = GetBlockCoordinates(t.Position); //mxd
VisualBlockEntry block = GetBlock(p); Point p1 = GetBlockCoordinates(new Vector2D(t.Position.x - t.Size, t.Position.y - t.Size));
block.Things.Add(t); Point p2 = GetBlockCoordinates(new Vector2D(t.Position.x + t.Size, t.Position.y + t.Size));
for(int x = p1.X; x <= p2.X; x++)
{
for(int y = p1.Y; y <= p2.Y; y++)
{
VisualBlockEntry block = GetBlock(new Point(x, y));
block.Things.Add(t);
}
}
} }
// This puts a secotr in the blockmap // This puts a secotr in the blockmap

View file

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Geometry; using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Map; using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.VisualModes; using CodeImp.DoomBuilder.VisualModes;
@ -366,13 +367,21 @@ namespace CodeImp.DoomBuilder.BuilderModes
#region ================== Things #region ================== Things
internal static float GetHigherThingZ(SectorData sd, Vector3D pos, float thingheight, bool absolute, bool hangs) internal static float GetHigherThingZ(BaseVisualMode mode, SectorData sd, VisualThing thing)
{ {
Vector3D pos = thing.Thing.Position;
float thingheight = thing.Thing.Height;
bool absolute = thing.Info.AbsoluteZ;
bool hangs = thing.Info.Hangs;
if(absolute && hangs) if(absolute && hangs)
{ {
General.Interface.DisplayStatus(StatusType.Warning, "Sorry, can't have both 'absolute' and 'hangs' flags..."); General.Interface.DisplayStatus(StatusType.Warning, "Sorry, can't have both 'absolute' and 'hangs' flags...");
return pos.z; return pos.z;
} }
// Get things, which bounding boxes intersect with target thing
IEnumerable<Thing> intersectingthings = GetIntersectingThings(mode, thing.Thing);
float fz = (absolute ? 0 : sd.Floor.plane.GetZ(pos)); float fz = (absolute ? 0 : sd.Floor.plane.GetZ(pos));
float cz = sd.Ceiling.plane.GetZ(pos); float cz = sd.Ceiling.plane.GetZ(pos);
@ -381,41 +390,95 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
// Transform to floor-aligned position // Transform to floor-aligned position
Vector3D floorpos = new Vector3D(pos, (cz - fz) - pos.z - thingheight); Vector3D floorpos = new Vector3D(pos, (cz - fz) - pos.z - thingheight);
float highertingz = GetNextHigherThingZ(mode, intersectingthings, floorpos.z, thingheight);
// Unlike sd.ExtraFloors, these are sorted by height float higherfloorz = float.MinValue;
foreach (SectorLevel level in sd.LightLevels)
// Do it only when there are extrafloors
if(sd.LightLevels.Count > 2)
{ {
if(level.type == SectorLevelType.Light) continue; // Skip lights // Unlike sd.ExtraFloors, these are sorted by height
float z = level.plane.GetZ(floorpos) - fz; foreach(SectorLevel level in sd.LightLevels)
if(level.type == SectorLevelType.Ceiling) z -= thingheight; {
if(z > floorpos.z) return cz - fz - z - thingheight; // Transform back to ceiling-aligned position if(level.type == SectorLevelType.Light || level.type == SectorLevelType.Glow) continue; // Skip lights and glows
float z = level.plane.GetZ(floorpos) - fz;
if(level.type == SectorLevelType.Ceiling) z -= thingheight;
if(z > floorpos.z)
{
higherfloorz = z;
break;
}
}
}
if(higherfloorz != float.MinValue && highertingz != float.MaxValue)
{
// Transform back to ceiling-aligned position
return cz - fz - Math.Max(Math.Min(higherfloorz, highertingz), 0) - thingheight;
}
if(higherfloorz != float.MinValue)
{
// Transform back to ceiling-aligned position
return Math.Max(cz - fz - higherfloorz - thingheight, 0);
}
if(highertingz != float.MaxValue)
{
// Transform back to ceiling-aligned position
return Math.Max(cz - fz - highertingz - thingheight, 0);
} }
return 0; // Align to real ceiling return 0; // Align to real ceiling
} }
else else
{ {
// Unlike sd.ExtraFloors, these are sorted by height float highertingz = GetNextHigherThingZ(mode, intersectingthings, (absolute ? pos.z - fz : pos.z), thingheight);
foreach(SectorLevel level in sd.LightLevels) float higherfloorz = float.MinValue;
// Do it only when there are extrafloors
if(sd.LightLevels.Count > 2)
{ {
if(level.type == SectorLevelType.Light) continue; // Skip lights // Unlike sd.ExtraFloors, these are sorted by height
float z = level.plane.GetZ(pos) - fz; foreach(SectorLevel level in sd.LightLevels)
if(level.type == SectorLevelType.Ceiling) z -= thingheight; {
if(z > pos.z) return z; if(level.type == SectorLevelType.Light || level.type == SectorLevelType.Glow) continue; // Skip lights and glows
float z = level.plane.GetZ(pos) - fz;
if(level.type == SectorLevelType.Ceiling) z -= thingheight;
if(z > pos.z)
{
higherfloorz = z;
break;
}
}
} }
return cz - fz - thingheight; // Align to real ceiling float floorz = sd.Floor.plane.GetZ(pos);
float ceilpos = cz - floorz - thingheight; // Ceiling-aligned relative target thing z
if(higherfloorz != float.MinValue && highertingz != float.MaxValue) ceilpos = Math.Min(ceilpos, Math.Min(higherfloorz, highertingz));
if(higherfloorz != float.MinValue) ceilpos = Math.Min(ceilpos, higherfloorz);
if(highertingz != float.MaxValue) ceilpos = Math.Min(ceilpos, highertingz);
return (absolute ? ceilpos + floorz : ceilpos); // Convert to absolute position if necessary
} }
} }
internal static float GetLowerThingZ(SectorData sd, Vector3D pos, float thingheight, bool absolute, bool hangs) internal static float GetLowerThingZ(BaseVisualMode mode, SectorData sd, VisualThing thing)
{ {
Vector3D pos = thing.Thing.Position;
float thingheight = thing.Thing.Height;
bool absolute = thing.Info.AbsoluteZ;
bool hangs = thing.Info.Hangs;
if(absolute && hangs) if(absolute && hangs)
{ {
General.Interface.DisplayStatus(StatusType.Warning, "Sorry, can't have both 'absolute' and 'hangs' flags..."); General.Interface.DisplayStatus(StatusType.Warning, "Sorry, can't have both 'absolute' and 'hangs' flags...");
return pos.z; return pos.z;
} }
// Get things, which bounding boxes intersect with target thing
IEnumerable<Thing> intersectingthings = GetIntersectingThings(mode, thing.Thing);
float fz = (absolute ? 0 : sd.Floor.plane.GetZ(pos)); float fz = (absolute ? 0 : sd.Floor.plane.GetZ(pos));
float cz = sd.Ceiling.plane.GetZ(pos); float cz = sd.Ceiling.plane.GetZ(pos);
@ -423,35 +486,200 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
// Transform to floor-aligned position // Transform to floor-aligned position
Vector3D floorpos = new Vector3D(pos, (cz - fz) - pos.z - thingheight); Vector3D floorpos = new Vector3D(pos, (cz - fz) - pos.z - thingheight);
float lowertingz = GetNextLowerThingZ(mode, intersectingthings, floorpos.z, thingheight);
float lowerfloorz = float.MaxValue;
// Unlike sd.ExtraFloors, these are sorted by height // Do it only when there are extrafloors
for(int i = sd.LightLevels.Count - 1; i > -1; i--) if(sd.LightLevels.Count > 2)
{ {
SectorLevel level = sd.LightLevels[i]; // Unlike sd.ExtraFloors, these are sorted by height
if(level.type == SectorLevelType.Light) continue; // Skip lights for(int i = sd.LightLevels.Count - 1; i > -1; i--)
float z = level.plane.GetZ(floorpos) - fz; {
if(level.type == SectorLevelType.Ceiling) z -= thingheight; SectorLevel level = sd.LightLevels[i];
if(z < floorpos.z) return cz - fz - z - thingheight; // Transform back to ceiling-aligned position if(level.type == SectorLevelType.Light || level.type == SectorLevelType.Glow) continue; // Skip lights and glows
float z = level.plane.GetZ(floorpos) - fz;
if(level.type == SectorLevelType.Ceiling) z -= thingheight;
if(z < floorpos.z)
{
lowerfloorz = z;
break;
}
}
} }
return cz - fz - thingheight; // Align to real floor float floorz = cz - fz; // Floor height when counted from ceiling
if(lowerfloorz != float.MaxValue && lowertingz != float.MinValue)
{
// Transform back to ceiling-aligned position
return cz - fz - Math.Min(Math.Max(lowerfloorz, lowertingz), floorz) - thingheight;
}
if(lowerfloorz != float.MaxValue)
{
// Transform back to ceiling-aligned position
return cz - fz - Math.Min(lowerfloorz, floorz) - thingheight;
}
if(lowertingz != float.MinValue)
{
// Transform back to ceiling-aligned position
return cz - fz - Math.Min(lowertingz, floorz) - thingheight;
}
return floorz - thingheight; // Align to real floor
} }
else else
{ {
// Unlike sd.ExtraFloors, these are sorted by height float lowertingz = GetNextLowerThingZ(mode, intersectingthings, (absolute ? pos.z - fz : pos.z), thingheight);
for(int i = sd.LightLevels.Count - 1; i > -1; i--) float lowerfloorz = float.MaxValue;
// Do it only when there are extrafloors
if(sd.LightLevels.Count > 2)
{ {
SectorLevel level = sd.LightLevels[i]; // Unlike sd.ExtraFloors, these are sorted by height
if(level.type == SectorLevelType.Light) continue; // Skip lights for(int i = sd.LightLevels.Count - 1; i > -1; i--)
float z = level.plane.GetZ(pos) - fz; {
if(level.type == SectorLevelType.Ceiling) z -= thingheight; SectorLevel level = sd.LightLevels[i];
if(z < pos.z) return z; if(level.type == SectorLevelType.Light || level.type == SectorLevelType.Glow) continue; // Skip lights and glows
float z = level.plane.GetZ(pos) - fz;
if(level.type == SectorLevelType.Ceiling) z -= thingheight;
if(z < pos.z)
{
lowerfloorz = z;
break;
}
}
} }
return (absolute ? sd.Floor.plane.GetZ(pos) : 0); // Align to real floor float floorz = sd.Floor.plane.GetZ(pos); // Floor-aligned relative target thing z
float floorpos = 0;
if(lowerfloorz != float.MaxValue && lowertingz != float.MinValue) floorpos = Math.Max(Math.Max(lowerfloorz, lowertingz), floorz);
if(lowerfloorz != float.MaxValue) floorpos = Math.Max(lowerfloorz, floorz);
if(lowertingz != float.MinValue) floorpos = Math.Max(lowertingz, floorz);
return (absolute ? floorpos + floorz : floorpos); // Convert to absolute position if necessary
} }
} }
//mxd. Gets thing z next higher to target thing z
private static float GetNextHigherThingZ(BaseVisualMode mode, IEnumerable<Thing> things, float thingz, float thingheight)
{
float higherthingz = float.MaxValue;
foreach(Thing t in things)
{
float neighbourz = GetAlignedThingZ(mode, t, thingheight);
if(neighbourz > thingz && neighbourz < higherthingz) higherthingz = neighbourz;
}
return higherthingz;
}
//mxd. Gets thing z next lower to target thing z
private static float GetNextLowerThingZ(BaseVisualMode mode, IEnumerable<Thing> things, float thingz, float thingheight)
{
float lowerthingz = float.MinValue;
foreach(Thing t in things)
{
float neighbourz = GetAlignedThingZ(mode, t, thingheight);
if(neighbourz < thingz && neighbourz > lowerthingz) lowerthingz = neighbourz;
}
return lowerthingz;
}
private static float GetAlignedThingZ(BaseVisualMode mode, Thing t, float targtthingheight)
{
ThingTypeInfo info = General.Map.Data.GetThingInfoEx(t.Type);
if(info != null)
{
if(info.AbsoluteZ && info.Hangs) return t.Position.z; // Not sure what to do here...
if(info.AbsoluteZ)
{
// Transform to floor-aligned position
SectorData nsd = mode.GetSectorData(t.Sector);
return t.Position.z - nsd.Floor.plane.GetZ(t.Position) + t.Height;
}
if(info.Hangs)
{
// Transform to floor-aligned position. Align top of target thing to the bottom of the hanging thing
SectorData nsd = mode.GetSectorData(t.Sector);
return (nsd.Ceiling.plane.GetZ(t.Position) - nsd.Floor.plane.GetZ(t.Position)) - t.Position.z - t.Height - targtthingheight;
}
}
return t.Position.z + t.Height;
}
private static IEnumerable<Thing> GetIntersectingThings(VisualMode mode, Thing thing)
{
// Get nearby things
List<Thing> neighbours = new List<Thing>();
RectangleF bbox = new RectangleF(thing.Position.x - thing.Size, thing.Position.y - thing.Size, thing.Size * 2, thing.Size * 2);
Point p1 = mode.BlockMap.GetBlockCoordinates(new Vector2D(bbox.Left, bbox.Top));
Point p2 = mode.BlockMap.GetBlockCoordinates(new Vector2D(bbox.Right, bbox.Bottom));
for(int x = p1.X; x <= p2.X; x++)
{
for(int y = p1.Y; y <= p2.Y; y++)
{
neighbours.AddRange(mode.BlockMap.GetBlock(new Point(x, y)).Things);
}
}
// Collect things intersecting with target thing
List<Thing> intersectingthings = new List<Thing>();
foreach(Thing t in neighbours)
{
if(t != thing && t.Sector != null && bbox.IntersectsWith(new RectangleF(t.Position.x - t.Size, t.Position.y - t.Size, t.Size * 2, t.Size * 2)))
intersectingthings.Add(t);
}
return intersectingthings;
}
#endregion
#region ================== Sectors
// This gets sectors which surround given sectors
internal static IEnumerable<Sector> GetSectorsAround(IEnumerable<Sector> selected)
{
HashSet<int> processedsectors = new HashSet<int>();
HashSet<Vertex> verts = new HashSet<Vertex>();
List<Sector> result = new List<Sector>();
foreach(Sector s in selected)
{
processedsectors.Add(s.Index);
foreach(Sidedef side in s.Sidedefs)
{
if(!verts.Contains(side.Line.Start)) verts.Add(side.Line.Start);
if(!verts.Contains(side.Line.End)) verts.Add(side.Line.End);
}
}
foreach(Vertex v in verts)
{
foreach(Linedef l in v.Linedefs)
{
if(l.Front != null && l.Front.Sector != null && !processedsectors.Contains(l.Front.Sector.Index))
{
result.Add(l.Front.Sector);
processedsectors.Add(l.Front.Sector.Index);
}
if(l.Back != null && l.Back.Sector != null && !processedsectors.Contains(l.Back.Sector.Index))
{
result.Add(l.Back.Sector);
processedsectors.Add(l.Back.Sector.Index);
}
}
}
return result;
}
#endregion #endregion
} }
} }

View file

@ -569,7 +569,7 @@ errorcheckmode
lowersector8 lowersector8
{ {
title = "Lower Floor/Ceiling by 8 mp"; title = "Lower Floor/Ceiling/Thing by 8 mp";
category = "visual"; category = "visual";
description = "Lowers the targeted or selected floors/ceilings by 8 mp. This also lowers selected or targeted things."; description = "Lowers the targeted or selected floors/ceilings by 8 mp. This also lowers selected or targeted things.";
allowkeys = true; allowkeys = true;
@ -580,7 +580,7 @@ lowersector8
raisesector8 raisesector8
{ {
title = "Raise Floor/Ceiling by 8 mp"; title = "Raise Floor/Ceiling/Thing by 8 mp";
category = "visual"; category = "visual";
description = "Raises the targeted or selected floors/ceilings by 8 mp. This also raises selected or targeted things."; description = "Raises the targeted or selected floors/ceilings by 8 mp. This also raises selected or targeted things.";
allowkeys = true; allowkeys = true;
@ -591,7 +591,7 @@ raisesector8
lowersector1 lowersector1
{ {
title = "Lower Floor/Ceiling by 1 mp"; title = "Lower Floor/Ceiling/Thing by 1 mp";
category = "visual"; category = "visual";
description = "Lowers the targeted or selected floors/ceilings by 1 mp. This also lowers selected or targeted things."; description = "Lowers the targeted or selected floors/ceilings by 1 mp. This also lowers selected or targeted things.";
allowkeys = true; allowkeys = true;
@ -602,7 +602,7 @@ lowersector1
raisesector1 raisesector1
{ {
title = "Raise Floor/Ceiling by 1 mp"; title = "Raise Floor/Ceiling/Thing by 1 mp";
category = "visual"; category = "visual";
description = "Raises the targeted or selected floors/ceilings by 1 mp. This also raises selected or targeted things."; description = "Raises the targeted or selected floors/ceilings by 1 mp. This also raises selected or targeted things.";
allowkeys = true; allowkeys = true;
@ -614,9 +614,9 @@ raisesector1
//mxd //mxd
lowersectortonearest lowersectortonearest
{ {
title = "Lower Floor/Ceiling to adjacent sector"; title = "Lower Floor/Ceiling/Thing to adjacent Sector/Thing";
category = "visual"; category = "visual";
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 targeted or selected things to the nearest floor or ceiling."; 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 targeted or selected things to the nearest floor or ceiling or on top of another thing.";
allowkeys = true; allowkeys = true;
allowmouse = true; allowmouse = true;
allowscroll = true; allowscroll = true;
@ -627,9 +627,9 @@ lowersectortonearest
//mxd //mxd
raisesectortonearest raisesectortonearest
{ {
title = "Raise Floor/Ceiling to adjacent sector"; title = "Raise Floor/Ceiling/Thing to adjacent Sector/Thing";
category = "visual"; category = "visual";
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 raises targeted or selected things to the nearest ceiling or floor."; 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 raises targeted or selected things to the nearest ceiling or floor or puts them on top of another thing.";
allowkeys = true; allowkeys = true;
allowmouse = true; allowmouse = true;
allowscroll = true; allowscroll = true;

View file

@ -18,6 +18,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
using CodeImp.DoomBuilder.BuilderModes.Interface; using CodeImp.DoomBuilder.BuilderModes.Interface;
using CodeImp.DoomBuilder.Windows; using CodeImp.DoomBuilder.Windows;
@ -824,7 +825,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Find all sector who's tag is not 0 and hash them so that we can find them quicly // Find all sector who's tag is not 0 and hash them so that we can find them quicly
foreach(Sector s in General.Map.Map.Sectors) foreach(Sector s in General.Map.Map.Sectors)
{ {
s.UpdateFogColor(); //mxd. Also update fog color
foreach(int tag in s.Tags) foreach(int tag in s.Tags)
{ {
if(tag == 0) continue; if(tag == 0) continue;
@ -1066,6 +1066,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
cameraflooroffset = General.Map.Config.ReadSetting("cameraflooroffset", cameraflooroffset); cameraflooroffset = General.Map.Config.ReadSetting("cameraflooroffset", cameraflooroffset);
cameraceilingoffset = General.Map.Config.ReadSetting("cameraceilingoffset", cameraceilingoffset); cameraceilingoffset = General.Map.Config.ReadSetting("cameraceilingoffset", cameraceilingoffset);
//mxd. Update fog color (otherwise FogBoundaries won't be setup correctly)
foreach(Sector s in General.Map.Map.Sectors) s.UpdateFogColor();
// (Re)create special effects // (Re)create special effects
RebuildElementData(); RebuildElementData();
@ -2034,8 +2037,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
List<BaseVisualThing> things = new List<BaseVisualThing>(); List<BaseVisualThing> things = new List<BaseVisualThing>();
bool withinSelection = General.Interface.CtrlState; bool withinSelection = General.Interface.CtrlState;
//get selection // Get selection
if(selectedobjects.Count == 0) if(selectedobjects.Count == 0)
{ {
IVisualEventReceiver i = (target.picked as IVisualEventReceiver); IVisualEventReceiver i = (target.picked as IVisualEventReceiver);
if(i is VisualFloor) if(i is VisualFloor)
@ -2074,7 +2077,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
} }
//check what we have // Check what we have
if(floors.Count + ceilings.Count == 0 && (things.Count == 0 || !General.Map.FormatInterface.HasThingHeight)) if(floors.Count + ceilings.Count == 0 && (things.Count == 0 || !General.Map.FormatInterface.HasThingHeight))
{ {
General.Interface.DisplayStatus(StatusType.Warning, "No suitable objects found!"); General.Interface.DisplayStatus(StatusType.Warning, "No suitable objects found!");
@ -2100,57 +2103,48 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
} }
//process floors... // Process floors...
int maxSelectedHeight = int.MinValue; int maxSelectedHeight = int.MinValue;
int minSelectedCeilingHeight = int.MaxValue; int minSelectedCeilingHeight = int.MaxValue;
int targetCeilingHeight = int.MaxValue; int targetCeilingHeight = int.MaxValue;
//get highest ceiling height from selection // Get highest ceiling height from selection
foreach(KeyValuePair<Sector, VisualCeiling> group in ceilings) foreach(KeyValuePair<Sector, VisualCeiling> group in ceilings)
{ {
if(group.Key.CeilHeight > maxSelectedHeight) if(group.Key.CeilHeight > maxSelectedHeight) maxSelectedHeight = group.Key.CeilHeight;
maxSelectedHeight = group.Key.CeilHeight;
} }
if(withinSelection) if(withinSelection)
{ {
//we are raising, so we don't need to check anything // We are raising, so we don't need to check anything
targetCeilingHeight = maxSelectedHeight; targetCeilingHeight = maxSelectedHeight;
} }
else else
{ {
//get next higher floor or ceiling from surrounding unselected sectors // Get next higher floor or ceiling from surrounding unselected sectors
foreach(KeyValuePair<Sector, VisualCeiling> group in ceilings) foreach(Sector s in BuilderModesTools.GetSectorsAround(ceilings.Keys))
{ {
foreach(Sidedef side in group.Key.Sidedefs) if(s.FloorHeight < targetCeilingHeight && s.FloorHeight > maxSelectedHeight)
{ targetCeilingHeight = s.FloorHeight;
if(side.Other == null || ceilings.ContainsKey(side.Other.Sector) || floors.ContainsKey(side.Other.Sector)) else if(s.CeilHeight < targetCeilingHeight && s.CeilHeight > maxSelectedHeight)
continue; targetCeilingHeight = s.CeilHeight;
if(side.Other.Sector.FloorHeight < targetCeilingHeight && side.Other.Sector.FloorHeight > maxSelectedHeight)
targetCeilingHeight = side.Other.Sector.FloorHeight;
else if(side.Other.Sector.CeilHeight < targetCeilingHeight && side.Other.Sector.CeilHeight > maxSelectedHeight)
targetCeilingHeight = side.Other.Sector.CeilHeight;
}
} }
} }
//ceilings... // Ceilings...
maxSelectedHeight = int.MinValue; maxSelectedHeight = int.MinValue;
int targetFloorHeight = int.MaxValue; int targetFloorHeight = int.MaxValue;
//get maximum floor and minimum ceiling heights from selection // Get maximum floor and minimum ceiling heights from selection
foreach(KeyValuePair<Sector, VisualFloor> group in floors) foreach(KeyValuePair<Sector, VisualFloor> group in floors)
{ {
if(group.Key.FloorHeight > maxSelectedHeight) if(group.Key.FloorHeight > maxSelectedHeight) maxSelectedHeight = group.Key.FloorHeight;
maxSelectedHeight = group.Key.FloorHeight; if(group.Key.CeilHeight < minSelectedCeilingHeight) minSelectedCeilingHeight = group.Key.CeilHeight;
if(group.Key.CeilHeight < minSelectedCeilingHeight)
minSelectedCeilingHeight = group.Key.CeilHeight;
} }
if(withinSelection) if(withinSelection)
{ {
//check heights // Check heights
if(minSelectedCeilingHeight < maxSelectedHeight) if(minSelectedCeilingHeight < maxSelectedHeight)
{ {
General.Interface.DisplayStatus(StatusType.Warning, "Can't do: lowest ceiling is lower than highest floor!"); General.Interface.DisplayStatus(StatusType.Warning, "Can't do: lowest ceiling is lower than highest floor!");
@ -2160,27 +2154,22 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
else else
{ {
//get next higher floor or ceiling from surrounding unselected sectors // Get next higher floor or ceiling from surrounding unselected sectors
foreach(KeyValuePair<Sector, VisualFloor> group in floors) foreach(Sector s in BuilderModesTools.GetSectorsAround(floors.Keys))
{ {
foreach(Sidedef side in group.Key.Sidedefs) if(s.FloorHeight > maxSelectedHeight && s.FloorHeight < targetFloorHeight && s.FloorHeight <= minSelectedCeilingHeight)
{ targetFloorHeight = s.FloorHeight;
if(side.Other == null || ceilings.ContainsKey(side.Other.Sector) || floors.ContainsKey(side.Other.Sector)) else if(s.CeilHeight > maxSelectedHeight && s.CeilHeight < targetFloorHeight && s.CeilHeight <= minSelectedCeilingHeight)
continue; targetFloorHeight = s.CeilHeight;
if(side.Other.Sector.FloorHeight > maxSelectedHeight && side.Other.Sector.FloorHeight < targetFloorHeight && side.Other.Sector.FloorHeight <= minSelectedCeilingHeight)
targetFloorHeight = side.Other.Sector.FloorHeight;
else if(side.Other.Sector.CeilHeight > maxSelectedHeight && side.Other.Sector.CeilHeight < targetFloorHeight && side.Other.Sector.CeilHeight <= side.Sector.CeilHeight)
targetFloorHeight = side.Other.Sector.CeilHeight;
}
} }
} }
//CHECK VALUES //CHECK VALUES
string alignFailDescription = string.Empty; string alignFailDescription = string.Empty;
if (floors.Count > 0 && targetFloorHeight == int.MaxValue) if(floors.Count > 0 && targetFloorHeight == int.MaxValue)
{ {
//raise to lowest ceiling? // Raise to lowest ceiling?
if(!withinSelection && minSelectedCeilingHeight > maxSelectedHeight) if(!withinSelection && minSelectedCeilingHeight > maxSelectedHeight)
{ {
targetFloorHeight = minSelectedCeilingHeight; targetFloorHeight = minSelectedCeilingHeight;
@ -2193,9 +2182,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(ceilings.Count > 0 && targetCeilingHeight == int.MaxValue) if(ceilings.Count > 0 && targetCeilingHeight == int.MaxValue)
{ {
if(!string.IsNullOrEmpty(alignFailDescription)) if(!string.IsNullOrEmpty(alignFailDescription)) alignFailDescription += " and ";
alignFailDescription += " and ";
alignFailDescription += ceilings.Count > 1 ? "ceilings" : "ceiling"; alignFailDescription += ceilings.Count > 1 ? "ceilings" : "ceiling";
} }
@ -2208,7 +2195,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
//APPLY VALUES //APPLY VALUES
PreAction(UndoGroup.SectorHeightChange); PreAction(UndoGroup.SectorHeightChange);
//change floors heights // Change floors heights
if(floors.Count > 0) if(floors.Count > 0)
{ {
foreach(KeyValuePair<Sector, VisualFloor> group in floors) foreach(KeyValuePair<Sector, VisualFloor> group in floors)
@ -2218,7 +2205,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
} }
//change ceilings heights // Change ceilings heights
if(ceilings.Count > 0) if(ceilings.Count > 0)
{ {
foreach(KeyValuePair<Sector, VisualCeiling> group in ceilings) foreach(KeyValuePair<Sector, VisualCeiling> group in ceilings)
@ -2235,7 +2222,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
if(vt.Thing.Sector == null) continue; if(vt.Thing.Sector == null) continue;
SectorData sd = GetSectorData(vt.Thing.Sector); SectorData sd = GetSectorData(vt.Thing.Sector);
vt.OnMove(new Vector3D(vt.Thing.Position, BuilderModesTools.GetHigherThingZ(sd, vt.Thing.Position, vt.Thing.Height, vt.Info.AbsoluteZ, vt.Info.Hangs))); vt.OnMove(new Vector3D(vt.Thing.Position, BuilderModesTools.GetHigherThingZ(this, sd, vt)));
} }
} }
@ -2291,7 +2278,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
} }
//check what we have // Check what we have
if(floors.Count + ceilings.Count == 0 && (things.Count == 0 || !General.Map.FormatInterface.HasThingHeight)) if(floors.Count + ceilings.Count == 0 && (things.Count == 0 || !General.Map.FormatInterface.HasThingHeight))
{ {
General.Interface.DisplayStatus(StatusType.Warning, "No suitable objects found!"); General.Interface.DisplayStatus(StatusType.Warning, "No suitable objects found!");
@ -2317,52 +2304,43 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
} }
//process floors... // Process floors...
int minSelectedHeight = int.MaxValue; int minSelectedHeight = int.MaxValue;
int targetFloorHeight = int.MinValue; int targetFloorHeight = int.MinValue;
//get minimum floor height from selection // Get minimum floor height from selection
foreach(KeyValuePair<Sector, VisualFloor> group in floors) foreach(KeyValuePair<Sector, VisualFloor> group in floors)
{ {
if(group.Key.FloorHeight < minSelectedHeight) if(group.Key.FloorHeight < minSelectedHeight) minSelectedHeight = group.Key.FloorHeight;
minSelectedHeight = group.Key.FloorHeight;
} }
if(withinSelection) if(withinSelection)
{ {
//we are lowering, so we don't need to check anything // We are lowering, so we don't need to check anything
targetFloorHeight = minSelectedHeight; targetFloorHeight = minSelectedHeight;
} }
else else
{ {
//get next lower ceiling or floor from surrounding unselected sectors // Get next lower ceiling or floor from surrounding unselected sectors
foreach(KeyValuePair<Sector, VisualFloor> group in floors) foreach(Sector s in BuilderModesTools.GetSectorsAround(floors.Keys))
{ {
foreach(Sidedef side in group.Key.Sidedefs) if(s.CeilHeight > targetFloorHeight && s.CeilHeight < minSelectedHeight)
{ targetFloorHeight = s.CeilHeight;
if(side.Other == null || ceilings.ContainsKey(side.Other.Sector) || floors.ContainsKey(side.Other.Sector)) else if(s.FloorHeight > targetFloorHeight && s.FloorHeight < minSelectedHeight)
continue; targetFloorHeight = s.FloorHeight;
if(side.Other.Sector.CeilHeight > targetFloorHeight && side.Other.Sector.CeilHeight < minSelectedHeight)
targetFloorHeight = side.Other.Sector.CeilHeight;
else if(side.Other.Sector.FloorHeight > targetFloorHeight && side.Other.Sector.FloorHeight < minSelectedHeight)
targetFloorHeight = side.Other.Sector.FloorHeight;
}
} }
} }
//ceilings... // Ceilings...
minSelectedHeight = int.MaxValue; minSelectedHeight = int.MaxValue;
int maxSelectedFloorHeight = int.MinValue; int maxSelectedFloorHeight = int.MinValue;
int targetCeilingHeight = int.MinValue; int targetCeilingHeight = int.MinValue;
//get minimum ceiling and maximum floor heights from selection // Get minimum ceiling and maximum floor heights from selection
foreach(KeyValuePair<Sector, VisualCeiling> group in ceilings) foreach(KeyValuePair<Sector, VisualCeiling> group in ceilings)
{ {
if(group.Key.CeilHeight < minSelectedHeight) if(group.Key.CeilHeight < minSelectedHeight) minSelectedHeight = group.Key.CeilHeight;
minSelectedHeight = group.Key.CeilHeight; if(group.Key.FloorHeight > maxSelectedFloorHeight) maxSelectedFloorHeight = group.Key.FloorHeight;
if(group.Key.FloorHeight > maxSelectedFloorHeight)
maxSelectedFloorHeight = group.Key.FloorHeight;
} }
if(withinSelection) if(withinSelection)
@ -2376,18 +2354,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
else else
{ {
//get next lower ceiling or floor from surrounding unselected sectors // Get next lower ceiling or floor from surrounding unselected sectors
foreach(KeyValuePair<Sector, VisualCeiling> group in ceilings) foreach(Sector s in BuilderModesTools.GetSectorsAround(ceilings.Keys))
{ {
foreach(Sidedef side in group.Key.Sidedefs) if(s.CeilHeight > targetCeilingHeight && s.CeilHeight < minSelectedHeight && s.CeilHeight >= maxSelectedFloorHeight)
{ targetCeilingHeight = s.CeilHeight;
if(side.Other == null || ceilings.ContainsKey(side.Other.Sector) || floors.ContainsKey(side.Other.Sector)) else if(s.FloorHeight > targetCeilingHeight && s.FloorHeight < minSelectedHeight && s.FloorHeight >= maxSelectedFloorHeight)
continue; targetCeilingHeight = s.FloorHeight;
if(side.Other.Sector.CeilHeight > targetCeilingHeight && side.Other.Sector.CeilHeight < minSelectedHeight && side.Other.Sector.CeilHeight >= maxSelectedFloorHeight)
targetCeilingHeight = side.Other.Sector.CeilHeight;
else if(side.Other.Sector.FloorHeight > targetCeilingHeight && side.Other.Sector.FloorHeight < minSelectedHeight && side.Other.Sector.FloorHeight >= side.Sector.FloorHeight)
targetCeilingHeight = side.Other.Sector.FloorHeight;
}
} }
} }
@ -2399,7 +2372,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(ceilings.Count > 0 && targetCeilingHeight == int.MinValue) if(ceilings.Count > 0 && targetCeilingHeight == int.MinValue)
{ {
//drop to highest floor? // Drop to highest floor?
if(!withinSelection && maxSelectedFloorHeight < minSelectedHeight) if(!withinSelection && maxSelectedFloorHeight < minSelectedHeight)
{ {
targetCeilingHeight = maxSelectedFloorHeight; targetCeilingHeight = maxSelectedFloorHeight;
@ -2420,7 +2393,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
//APPLY VALUES: //APPLY VALUES:
PreAction(UndoGroup.SectorHeightChange); PreAction(UndoGroup.SectorHeightChange);
//change floor height // Change floor height
if(floors.Count > 0) if(floors.Count > 0)
{ {
foreach(KeyValuePair<Sector, VisualFloor> group in floors) foreach(KeyValuePair<Sector, VisualFloor> group in floors)
@ -2430,7 +2403,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
} }
//change ceiling height // Change ceiling height
if(ceilings.Count > 0) if(ceilings.Count > 0)
{ {
foreach(KeyValuePair<Sector, VisualCeiling> group in ceilings) foreach(KeyValuePair<Sector, VisualCeiling> group in ceilings)
@ -2447,7 +2420,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
if(vt.Thing.Sector == null) continue; if(vt.Thing.Sector == null) continue;
SectorData sd = GetSectorData(vt.Thing.Sector); SectorData sd = GetSectorData(vt.Thing.Sector);
vt.OnMove(new Vector3D(vt.Thing.Position, BuilderModesTools.GetLowerThingZ(sd, vt.Thing.Position, vt.Thing.Height, vt.Info.AbsoluteZ, vt.Info.Hangs))); vt.OnMove(new Vector3D(vt.Thing.Position, BuilderModesTools.GetLowerThingZ(this, sd, vt)));
} }
} }