Visual mode: rewritten most of the 3d floor clipping and light/color assignment logic. As a result, 3d floors should look much closer to what's seen in GZDoom.

Fixed, Visual mode: glow effect was not updated when changing sector textures using the "Select Texture" action.
Browse Textures/Flats window: when textures list is focused, you can now start typing to change the Filter.
This commit is contained in:
MaxED 2015-11-20 14:31:54 +00:00
parent b7ebde6b7e
commit 098e9724d9
19 changed files with 434 additions and 391 deletions

View file

@ -115,6 +115,7 @@ namespace CodeImp.DoomBuilder.Controls
this.list.DrawItem += new System.Windows.Forms.DrawListViewItemEventHandler(this.list_DrawItem); this.list.DrawItem += new System.Windows.Forms.DrawListViewItemEventHandler(this.list_DrawItem);
this.list.DoubleClick += new System.EventHandler(this.list_DoubleClick); this.list.DoubleClick += new System.EventHandler(this.list_DoubleClick);
this.list.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(this.list_ItemSelectionChanged); this.list.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(this.list_ItemSelectionChanged);
this.list.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.list_KeyPress);
// //
// showsubdirtextures // showsubdirtextures
// //

View file

@ -19,6 +19,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Globalization;
using System.Windows.Forms; using System.Windows.Forms;
using CodeImp.DoomBuilder.Data; using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Windows; using CodeImp.DoomBuilder.Windows;
@ -273,6 +274,25 @@ namespace CodeImp.DoomBuilder.Controls
if(SelectedItemDoubleClicked != null) SelectedItemDoubleClicked(); if(SelectedItemDoubleClicked != null) SelectedItemDoubleClicked();
} }
//mxd. Transfer focus to Filter textbox
private void list_KeyPress(object sender, KeyPressEventArgs e)
{
objectname.Focus();
if(e.KeyChar == '\b') // Any better way to check for Backspace?..
{
if(!string.IsNullOrEmpty(objectname.Text) && objectname.SelectionStart > 0 && objectname.SelectionLength == 0)
{
int s = objectname.SelectionStart - 1;
objectname.Text = objectname.Text.Remove(s, 1);
objectname.SelectionStart = s;
}
}
else
{
objectname.AppendText(e.KeyChar.ToString(CultureInfo.InvariantCulture));
}
}
//mxd //mxd
private void cbMixMode_SelectedIndexChanged(object sender, EventArgs e) private void cbMixMode_SelectedIndexChanged(object sender, EventArgs e)
{ {

View file

@ -147,7 +147,7 @@ float4 ps_main_highlight(PixelData pd) : COLOR
// Blend texture color and vertex color // Blend texture color and vertex color
float4 ncolor = tcolor * pd.color; float4 ncolor = tcolor * pd.color;
return float4(highlightcolor.rgb * highlightcolor.a + (ncolor.rgb - 0.4f * highlightcolor.a), ncolor.a + 0.25f); return float4(highlightcolor.rgb * highlightcolor.a + (ncolor.rgb - 0.4f * highlightcolor.a), max(pd.color.a + 0.25f, 0.5f));
} }
// Full-bright pixel shader with highlight // Full-bright pixel shader with highlight
@ -159,7 +159,7 @@ float4 ps_fullbright_highlight(PixelData pd) : COLOR
// Blend texture color and vertex color // Blend texture color and vertex color
float4 ncolor = tcolor * pd.color; float4 ncolor = tcolor * pd.color;
return float4(highlightcolor.rgb * highlightcolor.a + (tcolor.rgb - 0.4f * highlightcolor.a), ncolor.a + 0.25f); return float4(highlightcolor.rgb * highlightcolor.a + (tcolor.rgb - 0.4f * highlightcolor.a), max(pd.color.a + 0.25f, 0.5f));
} }
//mxd. This adds fog color to current pixel color //mxd. This adds fog color to current pixel color

View file

@ -1899,6 +1899,7 @@ namespace CodeImp.DoomBuilder.Windows
// //
this.statuslabel.Image = global::CodeImp.DoomBuilder.Properties.Resources.Status2; this.statuslabel.Image = global::CodeImp.DoomBuilder.Properties.Resources.Status2;
this.statuslabel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; this.statuslabel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.statuslabel.Margin = new System.Windows.Forms.Padding(2, 3, 0, 2);
this.statuslabel.Name = "statuslabel"; this.statuslabel.Name = "statuslabel";
this.statuslabel.Size = new System.Drawing.Size(340, 18); this.statuslabel.Size = new System.Drawing.Size(340, 18);
this.statuslabel.Spring = true; this.statuslabel.Spring = true;

View file

@ -42,7 +42,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
#region ================== Variables #region ================== Variables
protected BaseVisualMode mode; protected readonly BaseVisualMode mode;
protected long setuponloadedtexture; protected long setuponloadedtexture;
// This is only used to see if this object has already received a change // This is only used to see if this object has already received a change
@ -632,11 +632,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Update the visual sector // Update the visual sector
if(mode.VisualSectorExists(s)) if(mode.VisualSectorExists(s))
{ {
BaseVisualSector vs = (mode.GetVisualSector(s) as BaseVisualSector); BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(s);
if(fillceilings) if(fillceilings) vs.Ceiling.Setup();
vs.Ceiling.Setup(); else vs.Floor.Setup();
else
vs.Floor.Setup();
} }
} }
@ -909,6 +907,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
Sector.Rebuild(); Sector.Rebuild();
} }
//mxd
public virtual void OnChangeTextureRotation(float angle) public virtual void OnChangeTextureRotation(float angle)
{ {
if(!General.Map.UDMF) return; if(!General.Map.UDMF) return;

View file

@ -167,72 +167,70 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
List<WallPolygon> polygons = new List<WallPolygon>(poly); List<WallPolygon> polygons = new List<WallPolygon>(poly);
List<WorldVertex> verts = new List<WorldVertex>(); List<WorldVertex> verts = new List<WorldVertex>();
SectorLevel prevlight = null; //mxd
// Go for all levels to build geometry //mxd. Do complicated light level shenanigans only when there are extrafloors
for(int i = sd.LightLevels.Count - 1; i >= 0; i--) if(sd.LightLevels.Count > 2)
{ {
SectorLevel l = sd.LightLevels[i]; SectorLevel prevlight = null; //mxd
//mxd. Skip current light level when it's between TYPE1 and TYPE1_BOTTOM // Go for all levels to build geometry
if(prevlight != null for(int i = sd.LightLevels.Count - 1; i >= 0; i--)
&& prevlight.type == SectorLevelType.Light && l.type == SectorLevelType.Light
&& (prevlight.lighttype == LightLevelType.TYPE1 && l.lighttype != LightLevelType.TYPE1_BOTTOM))
continue;
if((l != sd.Floor) && (l != sd.Ceiling) && (l.type != SectorLevelType.Floor || l.alpha < 255))
{ {
// Go for all polygons SectorLevel l = sd.LightLevels[i];
int num = polygons.Count;
Plane plane = (l.type == SectorLevelType.Floor ? l.plane.GetInverted() : l.plane); //mxd //mxd. Skip current light level when it's between TYPE1 and TYPE1_BOTTOM
if(prevlight != null
for(int pi = 0; pi < num; pi++) && prevlight.type == SectorLevelType.Light && l.type == SectorLevelType.Light
&& (prevlight.lighttype == LightLevelType.TYPE1 && l.lighttype != LightLevelType.TYPE1_BOTTOM)) continue;
if((l != sd.Floor) && (l != sd.Ceiling) && (l.type != SectorLevelType.Floor || l.splitsides /*(l.alpha < 255)*/))
{ {
// Split by plane // Go for all polygons
WallPolygon p = polygons[pi]; int num = polygons.Count;
WallPolygon np = SplitPoly(ref p, plane, false); Plane plane = (l.type == SectorLevelType.Floor ? l.plane.GetInverted() : l.plane); //mxd
if(np.Count > 0)
for(int pi = 0; pi < num; pi++)
{ {
//mxd. Determine color // Split by plane
int lightlevel; WallPolygon p = polygons[pi];
WallPolygon np = SplitPoly(ref p, plane, false);
if(np.Count > 0)
{
//mxd. Determine color
int lightlevel;
if(l.disablelighting) //sidedef part is not affected by 3d floor brightness // Sidedef part is not affected by 3d floor brightness
{ if(l.disablelighting || !l.extrafloor)
lightlevel = lightabsolute ? lightvalue : l.brightnessbelow + lightvalue; lightlevel = (lightabsolute ? lightvalue : l.brightnessbelow + lightvalue);
} // 3d floor transfers brightness below it ignoring sidedef's brightness
else if(l.restrictlighting || (l.type == SectorLevelType.Floor && l.alpha < 255)) //only happens to a sidedef part inside of a non-opaque 3d floor. else
{ lightlevel = l.brightnessbelow;
lightlevel = l.sector.Brightness;
}
else // "Regular" 3d floor transfers brightness below it ignoring sidedef's brightness.
{
lightlevel = l.brightnessbelow;
}
PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel, Sidedef)); //mxd PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel, Sidedef)); //mxd
np.color = PixelColor.Modulate(l.colorbelow, wallbrightness).WithAlpha(255).ToInt(); np.color = PixelColor.Modulate(l.colorbelow, wallbrightness).WithAlpha(255).ToInt();
if(p.Count == 0) if(p.Count == 0)
{ {
polygons[pi] = np; polygons[pi] = np;
}
else
{
polygons[pi] = p;
polygons.Add(np);
}
} }
else else
{ {
polygons[pi] = p; polygons[pi] = p;
polygons.Add(np);
} }
} }
else
{
polygons[pi] = p;
}
} }
}
//mxd //mxd
if(l.type == SectorLevelType.Light) prevlight = l; if(l.type == SectorLevelType.Light) prevlight = l;
}
} }
// Go for all polygons to make geometry // Go for all polygons to make geometry
foreach(WallPolygon p in polygons) foreach(WallPolygon p in polygons)
{ {
@ -446,6 +444,46 @@ namespace CodeImp.DoomBuilder.BuilderModes
poly = newp; poly = newp;
} }
//mxd. This clips given polys by extrafloors
protected void ClipExtraFloors(List<WallPolygon> polygons, List<Effect3DFloor> extrafloors, bool clipalways)
{
foreach(Effect3DFloor ef in extrafloors)
{
//mxd. Walls should be clipped by 3D floors
if(ef.ClipSidedefs || clipalways)
{
int num = polygons.Count;
for(int pi = 0; pi < num; pi++)
{
// Split by floor plane of 3D floor
WallPolygon p = polygons[pi];
WallPolygon np = SplitPoly(ref p, ef.Ceiling.plane, true);
if(np.Count > 0)
{
// Split part below floor by the ceiling plane of 3D floor
// and keep only the part below the ceiling (front)
SplitPoly(ref np, ef.Floor.plane, true);
if(p.Count == 0)
{
polygons[pi] = np;
}
else
{
polygons[pi] = p;
polygons.Add(np);
}
}
else
{
polygons[pi] = p;
}
}
}
}
}
//mxd //mxd
protected void GetLightValue(out int lightvalue, out bool lightabsolute) protected void GetLightValue(out int lightvalue, out bool lightabsolute)
{ {
@ -754,14 +792,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
else if(this is VisualMiddleDouble) else if(this is VisualMiddleDouble)
{ {
if (Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag)) if(Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag))
{
offsety = (options.Bounds.Y - Sidedef.GetHighHeight() - Sidedef.GetLowHeight()) * scaley - Sidedef.OffsetY; offsety = (options.Bounds.Y - Sidedef.GetHighHeight() - Sidedef.GetLowHeight()) * scaley - Sidedef.OffsetY;
}
else else
{
offsety = options.Bounds.Y * scaley - Sidedef.OffsetY; offsety = options.Bounds.Y * scaley - Sidedef.OffsetY;
}
} }
else else
{ {
@ -878,22 +912,18 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
// Change ceiling // Change ceiling
case 1: case 1:
if(!this.Sector.Ceiling.Changed) if(!this.Sector.Ceiling.Changed) this.Sector.Ceiling.OnChangeTargetHeight(amount);
this.Sector.Ceiling.OnChangeTargetHeight(amount);
break; break;
// Change floor // Change floor
case 2: case 2:
if(!this.Sector.Floor.Changed) if(!this.Sector.Floor.Changed) this.Sector.Floor.OnChangeTargetHeight(amount);
this.Sector.Floor.OnChangeTargetHeight(amount);
break; break;
// Change both // Change both
case 3: case 3:
if(!this.Sector.Floor.Changed) if(!this.Sector.Floor.Changed) this.Sector.Floor.OnChangeTargetHeight(amount);
this.Sector.Floor.OnChangeTargetHeight(amount); if(!this.Sector.Ceiling.Changed) this.Sector.Ceiling.OnChangeTargetHeight(amount);
if(!this.Sector.Ceiling.Changed)
this.Sector.Ceiling.OnChangeTargetHeight(amount);
break; break;
} }
} }
@ -1131,7 +1161,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Update the parts for this sidedef! // Update the parts for this sidedef!
if(mode.VisualSectorExists(sd.Sector)) if(mode.VisualSectorExists(sd.Sector))
{ {
BaseVisualSector vs = (mode.GetVisualSector(sd.Sector) as BaseVisualSector); BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(sd.Sector);
VisualSidedefParts parts = vs.GetSidedefParts(sd); VisualSidedefParts parts = vs.GetSidedefParts(sd);
parts.SetupAllParts(); parts.SetupAllParts();
} }

View file

@ -2771,6 +2771,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
General.Interface.RedrawDisplay(); General.Interface.RedrawDisplay();
GetTargetEventReceiver(false).OnSelectTexture(); GetTargetEventReceiver(false).OnSelectTexture();
UpdateChangedObjects(); UpdateChangedObjects();
RebuildElementData(); //mxd. Extrafloors or Glow effects may've been changed
renderer.SetCrosshairBusy(false); renderer.SetCrosshairBusy(false);
PostAction(); PostAction();
} }

View file

@ -13,7 +13,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
// Linedef that is used to create this effect // Linedef that is used to create this effect
// The sector can be found by linedef.Front.Sector // The sector can be found by linedef.Front.Sector
private Linedef linedef; private readonly Linedef linedef;
// Floor and ceiling planes // Floor and ceiling planes
private SectorLevel floor; private SectorLevel floor;
@ -25,12 +25,18 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Vavoom type? // Vavoom type?
private bool vavoomtype; private bool vavoomtype;
//mxd. Translucent 3d-floor? //mxd. Render backsides?
private bool renderinside; private bool renderinside;
//mxd. Dirty hack to emulate GZDoom behaviour? //mxd. Dirty hack to emulate GZDoom behaviour?
private bool sloped3dfloor; private bool sloped3dfloor;
//mxd. Render using Additive pass?
private bool renderadditive;
//mxd. Sidedef should be clipped by floor/ceiling?
private bool clipsides;
//mxd. Ignore Bottom Height? //mxd. Ignore Bottom Height?
private bool ignorebottomheight; private bool ignorebottomheight;
@ -41,8 +47,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
public Linedef Linedef { get { return linedef; } } public Linedef Linedef { get { return linedef; } }
public bool VavoomType { get { return vavoomtype; } } public bool VavoomType { get { return vavoomtype; } }
public bool RenderInside { get { return renderinside; } } //mxd public bool RenderInside { get { return renderinside; } } //mxd
public bool RenderAdditive { get { return renderadditive; } } //mxd
public bool IgnoreBottomHeight { get { return ignorebottomheight; } } //mxd public bool IgnoreBottomHeight { get { return ignorebottomheight; } } //mxd
public bool Sloped3dFloor { get { return sloped3dfloor; } } //mxd public bool Sloped3dFloor { get { return sloped3dfloor; } } //mxd
public bool ClipSidedefs { get { return clipsides; } } //mxd
//mxd. 3D-Floor Flags //mxd. 3D-Floor Flags
[Flags] [Flags]
@ -107,26 +115,33 @@ namespace CodeImp.DoomBuilder.BuilderModes
// For non-vavoom types, we must switch the level types // For non-vavoom types, we must switch the level types
if(linedef.Args[1] != (int)FloorTypes.VavoomStyle) if(linedef.Args[1] != (int)FloorTypes.VavoomStyle)
{ {
//mxd. check for Swimmable/RenderInside/RenderAdditive flags
renderadditive = (linedef.Args[2] & (int)Flags.RenderAdditive) == (int)Flags.RenderAdditive;
renderinside = ((((linedef.Args[1] & (int)FloorTypes.Swimmable) == (int)FloorTypes.Swimmable) && (linedef.Args[1] & (int)FloorTypes.NonSolid) != (int)FloorTypes.NonSolid))
|| ((linedef.Args[1] & (int)FloorTypes.RenderInside) == (int)FloorTypes.RenderInside);
ignorebottomheight = ((linedef.Args[2] & (int)Flags.IgnoreBottomHeight) == (int)Flags.IgnoreBottomHeight);
vavoomtype = false; vavoomtype = false;
alpha = linedef.Args[3]; alpha = General.Clamp(linedef.Args[3], 0, 255);
sd.Ceiling.CopyProperties(floor); sd.Ceiling.CopyProperties(floor);
sd.Floor.CopyProperties(ceiling); sd.Floor.CopyProperties(ceiling);
floor.type = SectorLevelType.Floor; floor.type = SectorLevelType.Floor;
floor.plane = sd.Ceiling.plane.GetInverted(); floor.plane = sd.Ceiling.plane.GetInverted();
ceiling.type = SectorLevelType.Ceiling; ceiling.type = SectorLevelType.Ceiling;
ceiling.plane = sd.Floor.plane.GetInverted(); ceiling.plane = (ignorebottomheight ? sd.Ceiling.plane : sd.Floor.plane.GetInverted()); //mxd. Use upper plane when "ignorebottomheight" flag is set
//mxd. check for Swimmable/RenderInside setting //mxd
renderinside = ( (((linedef.Args[1] & (int)FloorTypes.Swimmable) == (int)FloorTypes.Swimmable) && (linedef.Args[1] & (int)FloorTypes.NonSolid) != (int)FloorTypes.NonSolid) ) clipsides = (!renderinside && !renderadditive && alpha > 254 && !ignorebottomheight);
|| ((linedef.Args[1] & (int)FloorTypes.RenderInside) == (int)FloorTypes.RenderInside);
ignorebottomheight = ((linedef.Args[2] & (int)Flags.IgnoreBottomHeight) == (int)Flags.IgnoreBottomHeight);
// A 3D floor's color is always that of the sector it is placed in // A 3D floor's color is always that of the sector it is placed in
floor.color = 0; // (unless it's affected by glow) - mxd
if(sd.CeilingGlow == null || !sd.CeilingGlow.Fullbright) floor.color = 0;
} }
else else
{ {
vavoomtype = true; vavoomtype = true;
renderadditive = false; //mxd
clipsides = true; //mxd
floor.type = SectorLevelType.Ceiling; floor.type = SectorLevelType.Ceiling;
floor.plane = sd.Ceiling.plane; floor.plane = sd.Ceiling.plane;
ceiling.type = SectorLevelType.Floor; ceiling.type = SectorLevelType.Floor;
@ -134,33 +149,48 @@ namespace CodeImp.DoomBuilder.BuilderModes
alpha = 255; alpha = 255;
// A 3D floor's color is always that of the sector it is placed in // A 3D floor's color is always that of the sector it is placed in
ceiling.color = 0; // (unless it's affected by glow) - mxd
if(sd.FloorGlow == null || !sd.FloorGlow.Fullbright) ceiling.color = 0;
} }
// Apply alpha // Apply alpha
floor.alpha = alpha; floor.alpha = alpha;
ceiling.alpha = alpha; ceiling.alpha = alpha;
//mxd
floor.extrafloor = true;
ceiling.extrafloor = true;
floor.splitsides = !clipsides;
ceiling.splitsides = (!clipsides && !ignorebottomheight); // if "ignorebottomheight" flag is set, both ceiling and floor will be at the same level and sidedef clipping with floor level will fail resulting in incorrect light props transfer in some cases
//mxd. Check slopes, cause GZDoom can't handle sloped translucent 3d floors... //mxd. Check slopes, cause GZDoom can't handle sloped translucent 3d floors...
sloped3dfloor = (alpha < 255 && sloped3dfloor = ((alpha < 255 || renderadditive) &&
(Angle2D.RadToDeg(ceiling.plane.Normal.GetAngleZ()) != 270 || (Angle2D.RadToDeg(ceiling.plane.Normal.GetAngleZ()) != 270 ||
Angle2D.RadToDeg(floor.plane.Normal.GetAngleZ()) != 90)); Angle2D.RadToDeg(floor.plane.Normal.GetAngleZ()) != 90));
// Do not adjust light? (works only for non-vavoom types) // Do not adjust light? (works only for non-vavoom types)
if(!vavoomtype) if(!vavoomtype)
{ {
bool disablelighting = ((linedef.Args[2] & (int) Flags.DisableLighting) == (int) Flags.DisableLighting); //mxd bool disablelighting = ((linedef.Args[2] & (int)Flags.DisableLighting) == (int)Flags.DisableLighting); //mxd
bool restrictlighting = alpha < 255 && ((linedef.Args[2] & (int) Flags.RestrictLighting) == (int) Flags.RestrictLighting); //mxd bool restrictlighting = (alpha < 255 || renderadditive || renderinside) && ((linedef.Args[2] & (int)Flags.RestrictLighting) == (int)Flags.RestrictLighting); //mxd
if(disablelighting || restrictlighting) if(disablelighting || restrictlighting)
{ {
floor.brightnessbelow = -1;
floor.restrictlighting = restrictlighting; //mxd floor.restrictlighting = restrictlighting; //mxd
floor.disablelighting = disablelighting; //mxd floor.disablelighting = disablelighting; //mxd
floor.colorbelow = PixelColor.FromInt(0);
if(disablelighting) //mxd
{
floor.color = 0;
floor.brightnessbelow = -1;
floor.colorbelow = PixelColor.FromInt(0);
}
ceiling.disablelighting = disablelighting; //mxd
ceiling.restrictlighting = restrictlighting; //mxd
ceiling.color = 0; ceiling.color = 0;
ceiling.brightnessbelow = -1; ceiling.brightnessbelow = -1;
ceiling.disablelighting = true; //mxd
ceiling.colorbelow = PixelColor.FromInt(0); ceiling.colorbelow = PixelColor.FromInt(0);
} }
} }

View file

@ -46,7 +46,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Original floor and ceiling levels // Original floor and ceiling levels
private readonly SectorLevel floor; private readonly SectorLevel floor;
private readonly SectorLevel floorbase; // mxd. Sector floor level, unaffected by glow / light properties transfer
private readonly SectorLevel ceiling; private readonly SectorLevel ceiling;
private readonly SectorLevel ceilingbase; // mxd. Sector ceiling level, unaffected by glow / light properties transfer
// This helps keeping track of changes // This helps keeping track of changes
// otherwise we update ceiling/floor too much // otherwise we update ceiling/floor too much
@ -86,7 +88,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
this.alleffects = new List<SectorEffect>(1); this.alleffects = new List<SectorEffect>(1);
this.updatesectors = new Dictionary<Sector, bool>(2); this.updatesectors = new Dictionary<Sector, bool>(2);
this.floor = new SectorLevel(sector, SectorLevelType.Floor); this.floor = new SectorLevel(sector, SectorLevelType.Floor);
this.floorbase = new SectorLevel(sector, SectorLevelType.Floor); //mxd
this.ceiling = new SectorLevel(sector, SectorLevelType.Ceiling); this.ceiling = new SectorLevel(sector, SectorLevelType.Ceiling);
this.ceilingbase = new SectorLevel(sector, SectorLevelType.Ceiling); //mxd
BasicSetup(); BasicSetup();
@ -271,6 +275,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
ceiling.color = ceilingcolor.WithAlpha(255).ToInt(); ceiling.color = ceilingcolor.WithAlpha(255).ToInt();
ceiling.brightnessbelow = sector.Brightness; ceiling.brightnessbelow = sector.Brightness;
ceiling.colorbelow = lightcolor.WithAlpha(255); ceiling.colorbelow = lightcolor.WithAlpha(255);
//mxd. Store a copy of initial settings
floor.CopyProperties(floorbase);
ceiling.CopyProperties(ceilingbase);
} }
//mxd //mxd
@ -294,73 +302,122 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Update all effects // Update all effects
foreach(SectorEffect e in alleffects) e.Update(); foreach(SectorEffect e in alleffects) e.Update();
// Sort the levels (only if there are more than 2 sector levels - mxd) //mxd. Do complicated light level shenanigans only when there are extrafloors
if (lightlevels.Count > 2) if(lightlevels.Count > 2)
{ {
// Sort the levels
SectorLevelComparer comparer = new SectorLevelComparer(sector); SectorLevelComparer comparer = new SectorLevelComparer(sector);
lightlevels.Sort(0, lightlevels.Count, comparer); //mxd. Was lightlevels.Sort(1, lightlevels.Count - 2, comparer); lightlevels.Sort(0, lightlevels.Count, comparer);
}
//mxd. 3d floors can be above the real ceiling, so let's find it first... // Now that we know the levels in this sector (and in the right order)
int startindex = lightlevels.Count - 2; // we can determine the lighting in between and on the levels.
for(int i = lightlevels.Count - 2; i >= 0; i--) SectorLevel stored = ceilingbase;
{
if(lightlevels[i].type == SectorLevelType.Ceiling && lightlevels[i].sector.Index == sector.Index) //mxd. Special cases...
if(lightlevels[lightlevels.Count - 1].disablelighting)
{ {
startindex = i; lightlevels[lightlevels.Count - 1].colorbelow = stored.colorbelow;
break; lightlevels[lightlevels.Count - 1].brightnessbelow = stored.brightnessbelow;
lightlevels[lightlevels.Count - 1].color = stored.colorbelow.ToInt();
} }
}
// Now that we know the levels in this sector (and in the right order) we //mxd. Cast light properties from top to bottom
// can determine the lighting in between and on the levels. for(int i = lightlevels.Count - 2; i >= 0; i--)
// Start from the absolute ceiling and go down to 'cast' the lighting
SectorLevel stored = ceiling; //mxd
for(int i = startindex; i >= 0; i--)
{
SectorLevel l = lightlevels[i];
SectorLevel pl = lightlevels[i + 1];
if(l.lighttype == LightLevelType.TYPE1) stored = pl; //mxd
//mxd. If the real floor has "lightfloor" value and the 3d floor above it doesn't cast down light, use real floor's brightness
if(General.Map.UDMF && l == floor && lightlevels.Count > 2 && (pl.disablelighting || pl.restrictlighting) && l.sector.Fields.ContainsKey("lightfloor"))
{ {
int light = l.sector.Fields.GetValue("lightfloor", pl.brightnessbelow); SectorLevel l = lightlevels[i];
pl.brightnessbelow = (l.sector.Fields.GetValue("lightfloorabsolute", false) ? light : l.sector.Brightness + light); SectorLevel pl = lightlevels[i + 1];
}
// Set color when no color is specified, or when a 3D floor is placed above the absolute floor
//mxd. Or when lightlevel is above a floor/ceiling level
bool uselightlevellight = ((l.type != SectorLevelType.Light) && pl != null && pl.type == SectorLevelType.Light); //mxd
if((l.color == 0) || ((l == floor) && (lightlevels.Count > 2)) || uselightlevellight)
{
PixelColor floorbrightness = PixelColor.FromInt(mode.CalculateBrightness(pl.brightnessbelow));
PixelColor floorcolor = PixelColor.Modulate(pl.colorbelow, floorbrightness);
l.color = floorcolor.WithAlpha(255).ToInt();
if(uselightlevellight) l.brightnessbelow = pl.brightnessbelow; if(l.lighttype == LightLevelType.TYPE1)
}
//mxd. Bottom TYPE1 border requires special handling...
else if(l.lighttype == LightLevelType.TYPE1_BOTTOM)
{
//Use brightness and color from previous light level when it's between TYPE1 and TYPE1_BOTTOM levels
if(pl.type == SectorLevelType.Light && pl.lighttype != LightLevelType.TYPE1)
{ {
l.brightnessbelow = pl.brightnessbelow; stored = pl;
l.colorbelow = pl.colorbelow;
} }
//Use brightness and color from the light level above TYPE1 level // Use stored light params when "disablelighting" flag is set
else if(stored.type == SectorLevelType.Light) else if(l.disablelighting)
{ {
l.brightnessbelow = stored.brightnessbelow;
l.colorbelow = stored.colorbelow; l.colorbelow = stored.colorbelow;
l.brightnessbelow = stored.brightnessbelow;
l.color = stored.colorbelow.ToInt();
} }
// Otherwise light values from the real ceiling are used else if(l.restrictlighting)
} {
if(!pl.restrictlighting && pl != ceiling) stored = pl;
l.color = stored.color;
if(l.colorbelow.a == 0) l.colorbelow = pl.colorbelow; // This is the bottom side of extrafloor with "restrict lighting" flag. Make it cast stored light props.
if(l.brightnessbelow == -1) l.brightnessbelow = pl.brightnessbelow; if(l.type == SectorLevelType.Ceiling)
{
// Special case: 2 intersecting extrafloors with "restrictlighting" flag...
if(pl.restrictlighting && pl.type == SectorLevelType.Floor && pl.sector.Index != l.sector.Index)
{
// Use light and color settings from previous layer
l.colorbelow = pl.colorbelow;
l.brightnessbelow = pl.brightnessbelow;
l.color = pl.colorbelow.ToInt();
// Also colorize previous layer using next higher level color
if(i + 2 < lightlevels.Count)
pl.color = lightlevels[i + 2].colorbelow.ToInt();
}
else
{
l.colorbelow = stored.colorbelow;
l.brightnessbelow = stored.brightnessbelow;
}
}
}
// Bottom TYPE1 border requires special handling...
else if(l.lighttype == LightLevelType.TYPE1_BOTTOM)
{
// Use brightness and color from previous light level when it's between TYPE1 and TYPE1_BOTTOM levels
if(pl.type == SectorLevelType.Light && pl.lighttype != LightLevelType.TYPE1)
{
l.brightnessbelow = pl.brightnessbelow;
l.colorbelow = pl.colorbelow;
}
// Use brightness and color from the light level above TYPE1 level
else if(stored.type == SectorLevelType.Light)
{
l.brightnessbelow = stored.brightnessbelow;
l.colorbelow = stored.colorbelow;
}
// Otherwise light values from the real ceiling are used
}
else if(l.lighttype == LightLevelType.UNKNOWN)
{
// Use stored light level when previous one has "disablelighting" flag
// or is the lower boundary of an extrafloor with "restrictlighting" flag
SectorLevel src = (pl.disablelighting || (pl.restrictlighting && pl.type == SectorLevelType.Ceiling) ? stored : pl);
if((src == l) || (src == ceiling && l == floor && src.LightPropertiesMatch(ceilingbase)))
{
// Don't change anything when light properties were reset before hitting floor
// (otherwise floor UDMF brightness will be lost)
continue;
}
// Transfer color and brightness if previous level has them
if(src.colorbelow.a > 0 && src.brightnessbelow != -1)
{
// Only surface brightness is retained when a glowing flat is used as extrafloor texture
if(!l.affectedbyglow)
{
PixelColor brightness = PixelColor.FromInt(mode.CalculateBrightness(src.brightnessbelow));
PixelColor color = PixelColor.Modulate(src.colorbelow, brightness);
l.color = color.WithAlpha(255).ToInt();
}
// Transfer brightnessbelow and colorbelow if current level is not extrafloor top
if(!(l.extrafloor && l.type == SectorLevelType.Floor))
{
l.brightnessbelow = src.brightnessbelow;
l.colorbelow = src.colorbelow;
}
}
// Store bottom extrafloor level if it doesn't have "restrictlighting" or "restrictlighting" flags set
if(l.extrafloor && l.type == SectorLevelType.Ceiling && !l.restrictlighting && !l.disablelighting) stored = l;
}
}
} }
//mxd. Apply ceiling glow effect? //mxd. Apply ceiling glow effect?

View file

@ -36,6 +36,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
public bool disablelighting; //mxd public bool disablelighting; //mxd
public bool restrictlighting; //mxd public bool restrictlighting; //mxd
public bool affectedbyglow; //mxd public bool affectedbyglow; //mxd
public bool extrafloor; //mxd
public bool splitsides; //mxd
// Constructor // Constructor
public SectorLevel(Sector s, SectorLevelType type) public SectorLevel(Sector s, SectorLevelType type)
@ -43,6 +45,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
this.type = type; this.type = type;
this.sector = s; this.sector = s;
this.alpha = 255; this.alpha = 255;
this.splitsides = true; //mxd
} }
// Copy constructor // Copy constructor
@ -62,8 +65,46 @@ namespace CodeImp.DoomBuilder.BuilderModes
target.color = this.color; target.color = this.color;
target.brightnessbelow = this.brightnessbelow; target.brightnessbelow = this.brightnessbelow;
target.colorbelow = this.colorbelow; target.colorbelow = this.colorbelow;
target.affectedbyglow = this.affectedbyglow; //mxd
target.disablelighting = this.disablelighting; //mxd target.disablelighting = this.disablelighting; //mxd
target.restrictlighting = this.restrictlighting; //mxd target.restrictlighting = this.restrictlighting; //mxd
target.splitsides = this.splitsides; //mxd
} }
//mxd. Compare light properties
public bool LightPropertiesMatch(SectorLevel other)
{
return (this.type == other.type && this.lighttype == other.lighttype && this.alpha == other.alpha && this.splitsides == other.splitsides
&& this.color == other.color && this.brightnessbelow == other.brightnessbelow && this.colorbelow.ToInt() == other.colorbelow.ToInt()
&& this.disablelighting == other.disablelighting && this.restrictlighting == other.restrictlighting);
}
#if DEBUG
//mxd. Handy when debugging
public override string ToString()
{
switch(type)
{
case SectorLevelType.Ceiling: return (extrafloor ? "ExtraCeiling" : "Ceiling");
case SectorLevelType.Floor: return (extrafloor ? "ExtraFloor" : "Floor");
case SectorLevelType.Glow: return "Glow Level";
case SectorLevelType.Light: return "Light Level (" + GetLightType() + ")";
default: return "Unknown Level Type!!!";
}
}
//mxd. Handy when debugging
private string GetLightType()
{
switch(lighttype)
{
case LightLevelType.TYPE0: return "Type 0";
case LightLevelType.TYPE1: return "Type 1";
case LightLevelType.TYPE1_BOTTOM: return "Type 1 (bottom)";
case LightLevelType.TYPE2: return "Type 2";
default: return "Unknown";
}
}
#endif
} }
} }

View file

@ -27,6 +27,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
float diff = (float)Math.Round(x.plane.GetZ(center) - y.plane.GetZ(center), 3); float diff = (float)Math.Round(x.plane.GetZ(center) - y.plane.GetZ(center), 3);
if(diff == 0) if(diff == 0)
{ {
//mxd. Push extrafloors above extraceilings
if(x.extrafloor && y.extrafloor && x.lighttype == LightLevelType.UNKNOWN && y.lighttype == LightLevelType.UNKNOWN)
{
if(x.type == SectorLevelType.Floor) return (y.type == SectorLevelType.Ceiling ? 1 : 0);
return (y.type == SectorLevelType.Floor ? -1 : 0);
}
bool xislight = (x.type == SectorLevelType.Light || x.type == SectorLevelType.Glow); bool xislight = (x.type == SectorLevelType.Light || x.type == SectorLevelType.Glow);
bool yislight = (y.type == SectorLevelType.Light || y.type == SectorLevelType.Glow); bool yislight = (y.type == SectorLevelType.Light || y.type == SectorLevelType.Glow);

View file

@ -163,7 +163,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
if(extrafloor.Sloped3dFloor) //mxd if(extrafloor.Sloped3dFloor) //mxd
this.RenderPass = RenderPass.Mask; this.RenderPass = RenderPass.Mask;
else if((extrafloor.Linedef.Args[2] & (int)Effect3DFloor.Flags.RenderAdditive) != 0) //mxd else if(extrafloor.RenderAdditive) //mxd
this.RenderPass = RenderPass.Additive; this.RenderPass = RenderPass.Additive;
else if(level.alpha < 255) else if(level.alpha < 255)
this.RenderPass = RenderPass.Alpha; this.RenderPass = RenderPass.Alpha;
@ -187,10 +187,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Return texture coordinates // Return texture coordinates
protected override Point GetTextureOffset() protected override Point GetTextureOffset()
{ {
Point p = new Point(); return new Point { X = (int)Sector.Sector.Fields.GetValue("xpanningceiling", 0.0f),
p.X = (int)Sector.Sector.Fields.GetValue("xpanningceiling", 0.0f); Y = (int)Sector.Sector.Fields.GetValue("ypanningceiling", 0.0f) };
p.Y = (int)Sector.Sector.Fields.GetValue("ypanningceiling", 0.0f);
return p;
} }
// Move texture coordinates // Move texture coordinates
@ -357,19 +355,19 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd. Sector brightness change //mxd. Sector brightness change
public override void OnChangeTargetBrightness(bool up) public override void OnChangeTargetBrightness(bool up)
{ {
if (level != null && level.sector != Sector.Sector) if(level != null && level.sector != Sector.Sector)
{ {
int index = -1; int index = -1;
for (int i = 0; i < Sector.ExtraCeilings.Count; i++) for(int i = 0; i < Sector.ExtraCeilings.Count; i++)
{ {
if (Sector.ExtraCeilings[i] == this) if(Sector.ExtraCeilings[i] == this)
{ {
index = i + 1; index = i + 1;
break; break;
} }
} }
if (index > -1 && index < Sector.ExtraCeilings.Count) if(index > -1 && index < Sector.ExtraCeilings.Count)
((BaseVisualSector)mode.GetVisualSector(Sector.ExtraCeilings[index].level.sector)).Floor.OnChangeTargetBrightness(up); ((BaseVisualSector)mode.GetVisualSector(Sector.ExtraCeilings[index].level.sector)).Floor.OnChangeTargetBrightness(up);
else else
base.OnChangeTargetBrightness(up); base.OnChangeTargetBrightness(up);
@ -377,7 +375,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
else else
{ {
//if a map is not in UDMF format, or this ceiling is part of 3D-floor... //if a map is not in UDMF format, or this ceiling is part of 3D-floor...
if(!General.Map.UDMF || Sector.Sector != level.sector) if(!General.Map.UDMF || (level != null && Sector.Sector != level.sector))
{ {
base.OnChangeTargetBrightness(up); base.OnChangeTargetBrightness(up);
return; return;
@ -594,8 +592,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
slopeSource = side.Line; slopeSource = side.Line;
isFront = true; isFront = true;
break; break;
} }
else if(side.Line.Args[1] == 2 && side.Line.Back != null && side.Line.Back == side)
if(side.Line.Args[1] == 2 && side.Line.Back != null && side.Line.Back == side)
{ {
slopeSource = side.Line; slopeSource = side.Line;
break; break;

View file

@ -165,7 +165,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
if(extrafloor.Sloped3dFloor) //mxd if(extrafloor.Sloped3dFloor) //mxd
this.RenderPass = RenderPass.Mask; this.RenderPass = RenderPass.Mask;
else if((extrafloor.Linedef.Args[2] & (int)Effect3DFloor.Flags.RenderAdditive) != 0) //mxd else if(extrafloor.RenderAdditive) //mxd
this.RenderPass = RenderPass.Additive; this.RenderPass = RenderPass.Additive;
else if(level.alpha < 255) else if(level.alpha < 255)
this.RenderPass = RenderPass.Alpha; this.RenderPass = RenderPass.Alpha;
@ -189,10 +189,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Return texture coordinates // Return texture coordinates
protected override Point GetTextureOffset() protected override Point GetTextureOffset()
{ {
Point p = new Point(); return new Point { X = (int)Sector.Sector.Fields.GetValue("xpanningfloor", 0.0f),
p.X = (int)Sector.Sector.Fields.GetValue("xpanningfloor", 0.0f); Y = (int)Sector.Sector.Fields.GetValue("ypanningfloor", 0.0f) };
p.Y = (int)Sector.Sector.Fields.GetValue("ypanningfloor", 0.0f);
return p;
} }
// Move texture coordinates // Move texture coordinates
@ -359,11 +357,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd. Sector brightness change //mxd. Sector brightness change
public override void OnChangeTargetBrightness(bool up) public override void OnChangeTargetBrightness(bool up)
{ {
if (level != null) if(level != null)
{ {
if (level.sector != Sector.Sector) //this floor is part of 3D-floor if(level.sector != Sector.Sector) //this floor is part of 3D-floor
((BaseVisualSector)mode.GetVisualSector(level.sector)).Floor.OnChangeTargetBrightness(up); ((BaseVisualSector)mode.GetVisualSector(level.sector)).Floor.OnChangeTargetBrightness(up);
else if (Sector.ExtraFloors.Count > 0) //this is actual floor of a sector with extrafloors else if(Sector.ExtraFloors.Count > 0 && !Sector.ExtraFloors[0].ExtraFloor.Floor.restrictlighting) //this is actual floor of a sector with extrafloors
Sector.ExtraFloors[0].OnChangeTargetBrightness(up); Sector.ExtraFloors[0].OnChangeTargetBrightness(up);
else else
base.OnChangeTargetBrightness(up); base.OnChangeTargetBrightness(up);

View file

@ -184,43 +184,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
CropPoly(ref poly, osd.Ceiling.plane, true); CropPoly(ref poly, osd.Ceiling.plane, true);
// Cut out pieces that overlap 3D floors in this sector // Cut out pieces that overlap 3D floors in this sector
List<WallPolygon> polygons = new List<WallPolygon>(1); List<WallPolygon> polygons = new List<WallPolygon> { poly };
polygons.Add(poly); ClipExtraFloors(polygons, sd.ExtraFloors, false); //mxd
foreach(Effect3DFloor ef in sd.ExtraFloors)
{
//mxd. Walls should be clipped by solid 3D floors
if(!ef.RenderInside && ef.Alpha == 255)
{
int num = polygons.Count;
for(int pi = 0; pi < num; pi++)
{
// Split by floor plane of 3D floor
WallPolygon p = polygons[pi];
WallPolygon np = SplitPoly(ref p, ef.Ceiling.plane, true);
if(np.Count > 0)
{
// Split part below floor by the ceiling plane of 3D floor
// and keep only the part below the ceiling (front)
SplitPoly(ref np, ef.Floor.plane, true);
if(p.Count == 0)
{
polygons[pi] = np;
}
else
{
polygons[pi] = p;
polygons.Add(np);
}
}
else
{
polygons[pi] = p;
}
}
}
}
if(polygons.Count > 0) if(polygons.Count > 0)
{ {

View file

@ -228,12 +228,16 @@ namespace CodeImp.DoomBuilder.BuilderModes
CropPoly(ref poly, extrafloor.Ceiling.plane, false); CropPoly(ref poly, extrafloor.Ceiling.plane, false);
// Cut out pieces that overlap 3D floors in this sector // Cut out pieces that overlap 3D floors in this sector
List<WallPolygon> polygons = new List<WallPolygon>(1); List<WallPolygon> polygons = new List<WallPolygon> { poly };
polygons.Add(poly); bool translucent = (extrafloor.RenderAdditive || extrafloor.Alpha < 255);
foreach(Effect3DFloor ef in sd.ExtraFloors) foreach(Effect3DFloor ef in sd.ExtraFloors)
{ {
//mxd. Walls of solid 3D floors shouldn't be clipped by translucent 3D floors //mxd. Our poly should be clipped when our ond other extrafloors are both solid or both translucent,
if(extrafloor.Alpha < 255 || (!extrafloor.RenderInside && !ef.RenderInside && extrafloor.Alpha == 255 && ef.Alpha == 255)) // or when only our extrafloor is translucent.
// Our poly should not be clipped when our extrafloor is translucent and the other one isn't and both have renderinside setting.
bool othertranslucent = (ef.RenderAdditive || ef.Alpha < 255);
if(translucent && !othertranslucent && !ef.ClipSidedefs) continue;
if(ef.ClipSidedefs == extrafloor.ClipSidedefs || ef.ClipSidedefs)
{ {
int num = polygons.Count; int num = polygons.Count;
for(int pi = 0; pi < num; pi++) for(int pi = 0; pi < num; pi++)
@ -267,31 +271,26 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
// Process the polygon and create vertices // Process the polygon and create vertices
if (polygons.Count > 0) if(polygons.Count > 0)
{ {
List<WorldVertex> verts = CreatePolygonVertices(polygons, tp, sd, lightvalue, lightabsolute); List<WorldVertex> verts = CreatePolygonVertices(polygons, tp, sd, lightvalue, lightabsolute);
if (verts.Count > 2) if(verts.Count > 2)
{ {
if(extrafloor.Sloped3dFloor) //mxd if(extrafloor.Sloped3dFloor) this.RenderPass = RenderPass.Mask; //mxd
this.RenderPass = RenderPass.Mask; else if(extrafloor.RenderAdditive) this.RenderPass = RenderPass.Additive; //mxd
else if((extrafloor.Linedef.Args[2] & (int) Effect3DFloor.Flags.RenderAdditive) != 0) //mxd else if(extrafloor.Alpha < 255) this.RenderPass = RenderPass.Alpha;
this.RenderPass = RenderPass.Additive; else this.RenderPass = RenderPass.Mask;
else if(extrafloor.Alpha < 255)
this.RenderPass = RenderPass.Alpha;
else
this.RenderPass = RenderPass.Mask;
if (extrafloor.Alpha < 255) if(extrafloor.Alpha < 255)
{ {
// Apply alpha to vertices // Apply alpha to vertices
byte alpha = (byte) General.Clamp(extrafloor.Alpha, 0, 255); byte alpha = (byte)General.Clamp(extrafloor.Alpha, 0, 255);
if (alpha < 255) if(alpha < 255)
{ {
for (int i = 0; i < verts.Count; i++) for(int i = 0; i < verts.Count; i++)
{ {
WorldVertex v = verts[i]; WorldVertex v = verts[i];
PixelColor c = PixelColor.FromInt(v.c); v.c = PixelColor.FromInt(v.c).WithAlpha(alpha).ToInt();
v.c = c.WithAlpha(alpha).ToInt();
verts[i] = v; verts[i] = v;
} }
} }

View file

@ -12,7 +12,8 @@ using CodeImp.DoomBuilder.Data;
#endregion #endregion
namespace CodeImp.DoomBuilder.BuilderModes { namespace CodeImp.DoomBuilder.BuilderModes
{
//mxd. Used to render translucent 3D floor's inner sides //mxd. Used to render translucent 3D floor's inner sides
internal sealed class VisualMiddleBack : BaseVisualGeometrySidedef internal sealed class VisualMiddleBack : BaseVisualGeometrySidedef
{ {
@ -77,23 +78,23 @@ namespace CodeImp.DoomBuilder.BuilderModes {
//mxd. which texture we must use? //mxd. which texture we must use?
long longtexture = 0; long longtexture = 0;
if ((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.UseUpperTexture) != 0) if((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.UseUpperTexture) != 0)
{ {
if (Sidedef.Other.LongHighTexture != MapSet.EmptyLongName) if(Sidedef.Other.LongHighTexture != MapSet.EmptyLongName)
longtexture = Sidedef.Other.LongHighTexture; longtexture = Sidedef.Other.LongHighTexture;
} }
else if ((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.UseLowerTexture) != 0) else if((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.UseLowerTexture) != 0)
{ {
if(Sidedef.Other.LongLowTexture != MapSet.EmptyLongName) if(Sidedef.Other.LongLowTexture != MapSet.EmptyLongName)
longtexture = Sidedef.Other.LongLowTexture; longtexture = Sidedef.Other.LongLowTexture;
} }
else if ((sourceside.LongMiddleTexture != MapSet.EmptyLongName)) else if((sourceside.LongMiddleTexture != MapSet.EmptyLongName))
{ {
longtexture = sourceside.LongMiddleTexture; longtexture = sourceside.LongMiddleTexture;
} }
// Texture given? // Texture given?
if (longtexture != 0) if(longtexture != 0)
{ {
// Load texture // Load texture
base.Texture = General.Map.Data.GetTextureImage(longtexture); base.Texture = General.Map.Data.GetTextureImage(longtexture);
@ -102,7 +103,7 @@ namespace CodeImp.DoomBuilder.BuilderModes {
base.Texture = General.Map.Data.UnknownTexture3D; base.Texture = General.Map.Data.UnknownTexture3D;
setuponloadedtexture = longtexture; setuponloadedtexture = longtexture;
} }
else if (!base.Texture.IsImageLoaded) else if(!base.Texture.IsImageLoaded)
{ {
setuponloadedtexture = longtexture; setuponloadedtexture = longtexture;
} }
@ -190,53 +191,62 @@ namespace CodeImp.DoomBuilder.BuilderModes {
// Determine initial color // Determine initial color
int lightlevel; int lightlevel;
PixelColor levelcolor; //mxd
if(((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.DisableLighting) != 0)) if(((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.DisableLighting) != 0))
{
lightlevel = lightabsolute ? lightvalue : sd.Ceiling.brightnessbelow + lightvalue; lightlevel = lightabsolute ? lightvalue : sd.Ceiling.brightnessbelow + lightvalue;
levelcolor = sd.Ceiling.colorbelow; //mxd
}
else else
{
lightlevel = lightabsolute ? lightvalue : sourceside.Sector.Brightness + lightvalue; lightlevel = lightabsolute ? lightvalue : sourceside.Sector.Brightness + lightvalue;
levelcolor = extrafloor.Floor.colorbelow; //mxd
}
//mxd. This calculates light with doom-style wall shading //mxd. This calculates light with doom-style wall shading
PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel, Sidedef)); PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(lightlevel, Sidedef));
PixelColor wallcolor = PixelColor.Modulate(sd.Ceiling.colorbelow, wallbrightness); int wallcolor = PixelColor.Modulate(levelcolor, wallbrightness).WithAlpha((byte)extrafloor.Alpha).ToInt();
fogfactor = CalculateFogDensity(lightlevel); fogfactor = CalculateFogDensity(lightlevel);
poly.color = wallcolor.WithAlpha(255).ToInt();
// Cut off the part above the 3D floor and below the 3D ceiling // Cut off the part above the 3D floor and below the 3D ceiling
CropPoly(ref poly, bottom, false); CropPoly(ref poly, bottom, false);
CropPoly(ref poly, top, false); CropPoly(ref poly, top, false);
// Cut out pieces that overlap 3D floors in this sector // Cut out pieces that overlap 3D floors in this sector
List<WallPolygon> polygons = new List<WallPolygon>(1); List<WallPolygon> polygons = new List<WallPolygon> { poly };
polygons.Add(poly);
foreach(Effect3DFloor ef in sd.ExtraFloors) foreach(Effect3DFloor ef in sd.ExtraFloors)
{ {
int num = polygons.Count; //mxd. Our poly should be clipped when our ond other extrafloors are both solid or both translucent,
for(int pi = 0; pi < num; pi++) // or when only our extrafloor is translucent
if(ef.ClipSidedefs == extrafloor.ClipSidedefs || ef.ClipSidedefs)
{ {
// Split by floor plane of 3D floor int num = polygons.Count;
WallPolygon p = polygons[pi]; for(int pi = 0; pi < num; pi++)
WallPolygon np = SplitPoly(ref p, ef.Ceiling.plane, true);
if(np.Count > 0)
{ {
// Split part below floor by the ceiling plane of 3D floor // Split by floor plane of 3D floor
// and keep only the part below the ceiling (front) WallPolygon p = polygons[pi];
SplitPoly(ref np, ef.Floor.plane, true); WallPolygon np = SplitPoly(ref p, ef.Ceiling.plane, true);
if(p.Count == 0) if(np.Count > 0)
{ {
polygons[pi] = np; // Split part below floor by the ceiling plane of 3D floor
} // and keep only the part below the ceiling (front)
else SplitPoly(ref np, ef.Floor.plane, true);
if(p.Count == 0)
{
polygons[pi] = np;
}
else
{
polygons[pi] = p;
polygons.Add(np);
}
}
else
{ {
polygons[pi] = p; polygons[pi] = p;
polygons.Add(np);
} }
}
else
{
polygons[pi] = p;
} }
} }
} }
@ -247,27 +257,17 @@ namespace CodeImp.DoomBuilder.BuilderModes {
List<WorldVertex> verts = CreatePolygonVertices(polygons, tp, sd, lightvalue, lightabsolute); List<WorldVertex> verts = CreatePolygonVertices(polygons, tp, sd, lightvalue, lightabsolute);
if(verts.Count > 2) if(verts.Count > 2)
{ {
if((extrafloor.Linedef.Args[2] & (int) Effect3DFloor.Flags.RenderAdditive) != 0) //mxd if(extrafloor.Sloped3dFloor) this.RenderPass = RenderPass.Mask; //mxd
this.RenderPass = RenderPass.Additive; else if(extrafloor.RenderAdditive) this.RenderPass = RenderPass.Additive; //mxd
else if(extrafloor.Alpha < 255) else if(extrafloor.Alpha < 255) this.RenderPass = RenderPass.Alpha;
this.RenderPass = RenderPass.Alpha; else this.RenderPass = RenderPass.Mask;
else
this.RenderPass = RenderPass.Mask;
if(extrafloor.Alpha < 255) //mxd. Inner sides always have extrafloor color
for(int i = 0; i < verts.Count; i++)
{ {
// Apply alpha to vertices WorldVertex v = verts[i];
byte alpha = (byte) General.Clamp(extrafloor.Alpha, 0, 255); v.c = wallcolor;
if(alpha < 255) verts[i] = v;
{
for(int i = 0; i < verts.Count; i++)
{
WorldVertex v = verts[i];
PixelColor c = PixelColor.FromInt(v.c);
v.c = c.WithAlpha(alpha).ToInt();
verts[i] = v;
}
}
} }
base.SetVertices(verts); base.SetVertices(verts);
@ -288,9 +288,9 @@ namespace CodeImp.DoomBuilder.BuilderModes {
public override string GetTextureName() public override string GetTextureName()
{ {
//mxd //mxd
if ((extrafloor.Linedef.Args[2] & (int)Effect3DFloor.Flags.UseUpperTexture) != 0) if((extrafloor.Linedef.Args[2] & (int)Effect3DFloor.Flags.UseUpperTexture) != 0)
return Sidedef.HighTexture; return Sidedef.HighTexture;
if ((extrafloor.Linedef.Args[2] & (int)Effect3DFloor.Flags.UseLowerTexture) != 0) if((extrafloor.Linedef.Args[2] & (int)Effect3DFloor.Flags.UseLowerTexture) != 0)
return Sidedef.LowTexture; return Sidedef.LowTexture;
return extrafloor.Linedef.Front.MiddleTexture; return extrafloor.Linedef.Front.MiddleTexture;
} }
@ -299,9 +299,9 @@ namespace CodeImp.DoomBuilder.BuilderModes {
protected override void SetTexture(string texturename) protected override void SetTexture(string texturename)
{ {
//mxd //mxd
if ((extrafloor.Linedef.Args[2] & (int)Effect3DFloor.Flags.UseUpperTexture) != 0) if((extrafloor.Linedef.Args[2] & (int)Effect3DFloor.Flags.UseUpperTexture) != 0)
Sidedef.Other.SetTextureHigh(texturename); Sidedef.Other.SetTextureHigh(texturename);
if ((extrafloor.Linedef.Args[2] & (int)Effect3DFloor.Flags.UseLowerTexture) != 0) if((extrafloor.Linedef.Args[2] & (int)Effect3DFloor.Flags.UseLowerTexture) != 0)
Sidedef.Other.SetTextureLow(texturename); Sidedef.Other.SetTextureLow(texturename);
else else
extrafloor.Linedef.Front.SetTextureMid(texturename); extrafloor.Linedef.Front.SetTextureMid(texturename);

View file

@ -147,7 +147,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag)) if(Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag))
tp.tlt.y = tsz.y - (geotop - geobottom); tp.tlt.y = tsz.y - (geotop - geobottom);
if (zoffset > 0) tp.tlt.y -= zoffset; //mxd if(zoffset > 0) tp.tlt.y -= zoffset; //mxd
tp.trb.x = tp.tlt.x + Sidedef.Line.Length; tp.trb.x = tp.tlt.x + Sidedef.Line.Length;
tp.trb.y = tp.tlt.y + (Sidedef.Sector.CeilHeight - (Sidedef.Sector.FloorHeight + floorbias)); tp.trb.y = tp.tlt.y + (Sidedef.Sector.CeilHeight - (Sidedef.Sector.FloorHeight + floorbias));
@ -216,47 +216,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
CropPoly(ref poly, bottomclipplane, true); CropPoly(ref poly, bottomclipplane, true);
} }
// Cut out pieces that overlap 3D floors in this sector //mxd. In(G)ZDoom, middle sidedef parts are not clipped by extrafloors of any type...
List<WallPolygon> polygons = new List<WallPolygon>(1); List<WallPolygon> polygons = new List<WallPolygon> { poly };
polygons.Add(poly); //ClipExtraFloors(polygons, sd.ExtraFloors, true); //mxd
foreach(Effect3DFloor ef in sd.ExtraFloors) //ClipExtraFloors(polygons, osd.ExtraFloors, true); //mxd
{
//mxd. Walls should be clipped by solid 3D floors
if(!ef.RenderInside && ef.Alpha == 255)
{
int num = polygons.Count;
for(int pi = 0; pi < num; pi++)
{
// Split by floor plane of 3D floor
WallPolygon p = polygons[pi];
WallPolygon np = SplitPoly(ref p, ef.Ceiling.plane, true);
if(np.Count > 0) //if(polygons.Count > 0)
{ //{
// Split part below floor by the ceiling plane of 3D floor
// and keep only the part below the ceiling (front)
SplitPoly(ref np, ef.Floor.plane, true);
if(p.Count == 0)
{
polygons[pi] = np;
}
else
{
polygons[pi] = p;
polygons.Add(np);
}
}
else
{
polygons[pi] = p;
}
}
}
}
if(polygons.Count > 0)
{
// Keep top and bottom planes for intersection testing // Keep top and bottom planes for intersection testing
top = osd.Ceiling.plane; top = osd.Ceiling.plane;
bottom = osd.Floor.plane; bottom = osd.Floor.plane;
@ -272,8 +238,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
for(int i = 0; i < verts.Count; i++) for(int i = 0; i < verts.Count; i++)
{ {
WorldVertex v = verts[i]; WorldVertex v = verts[i];
PixelColor c = PixelColor.FromInt(v.c); v.c = PixelColor.FromInt(v.c).WithAlpha(alpha).ToInt();
v.c = c.WithAlpha(alpha).ToInt();
verts[i] = v; verts[i] = v;
} }
} }
@ -281,7 +246,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
base.SetVertices(verts); base.SetVertices(verts);
return true; return true;
} }
} //}
base.SetVertices(null); //mxd base.SetVertices(null); //mxd
return false; return false;

View file

@ -183,49 +183,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
poly.color = wallcolor.WithAlpha(255).ToInt(); poly.color = wallcolor.WithAlpha(255).ToInt();
// Cut out pieces that overlap 3D floors in this sector // Cut out pieces that overlap 3D floors in this sector
List<WallPolygon> polygons = new List<WallPolygon>(1); List<WallPolygon> polygons = new List<WallPolygon> { poly };
polygons.Add(poly); ClipExtraFloors(polygons, sd.ExtraFloors, false); //mxd
foreach(Effect3DFloor ef in sd.ExtraFloors)
{
//mxd. Walls should be clipped by solid 3D floors
if(!ef.RenderInside && ef.Alpha == 255)
{
int num = polygons.Count;
for(int pi = 0; pi < num; pi++)
{
// Split by floor plane of 3D floor
WallPolygon p = polygons[pi];
WallPolygon np = SplitPoly(ref p, ef.Ceiling.plane, true);
if(np.Count > 0) if(polygons.Count > 0)
{
// Split part below floor by the ceiling plane of 3D floor
// and keep only the part below the ceiling (front)
SplitPoly(ref np, ef.Floor.plane, true);
if(p.Count == 0)
{
polygons[pi] = np;
}
else
{
polygons[pi] = p;
polygons.Add(np);
}
}
else
{
polygons[pi] = p;
}
}
}
}
if (polygons.Count > 0)
{ {
// Process the polygon and create vertices // Process the polygon and create vertices
List<WorldVertex> verts = CreatePolygonVertices(polygons, tp, sd, lightvalue, lightabsolute); List<WorldVertex> verts = CreatePolygonVertices(polygons, tp, sd, lightvalue, lightabsolute);
if (verts.Count > 2) if(verts.Count > 2)
{ {
base.SetVertices(verts); base.SetVertices(verts);
return true; return true;

View file

@ -175,43 +175,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
CropPoly(ref poly, osd.Ceiling.plane, false); CropPoly(ref poly, osd.Ceiling.plane, false);
// Cut out pieces that overlap 3D floors in this sector // Cut out pieces that overlap 3D floors in this sector
List<WallPolygon> polygons = new List<WallPolygon>(1); List<WallPolygon> polygons = new List<WallPolygon> { poly };
polygons.Add(poly); ClipExtraFloors(polygons, sd.ExtraFloors, false); //mxd
foreach(Effect3DFloor ef in sd.ExtraFloors)
{
//mxd. Walls should be clipped by solid 3D floors
if(!ef.RenderInside && ef.Alpha == 255)
{
int num = polygons.Count;
for(int pi = 0; pi < num; pi++)
{
// Split by floor plane of 3D floor
WallPolygon p = polygons[pi];
WallPolygon np = SplitPoly(ref p, ef.Ceiling.plane, true);
if(np.Count > 0)
{
// Split part below floor by the ceiling plane of 3D floor
// and keep only the part below the ceiling (front)
SplitPoly(ref np, ef.Floor.plane, true);
if(p.Count == 0)
{
polygons[pi] = np;
}
else
{
polygons[pi] = p;
polygons.Add(np);
}
}
else
{
polygons[pi] = p;
}
}
}
}
if(polygons.Count > 0) if(polygons.Count > 0)
{ {