@ work on (G)ZDoom Editing plugin

This commit is contained in:
codeimp 2010-09-10 13:17:38 +00:00
parent f289920dca
commit f2e16e0707
14 changed files with 516 additions and 181 deletions

View file

@ -55,6 +55,8 @@
<Compile Include="VisualModes\BaseVisualThing.cs" />
<Compile Include="VisualModes\IVisualEventReceiver.cs" />
<Compile Include="VisualModes\NullVisualEventReceiver.cs" />
<Compile Include="VisualModes\Sector3DFloor.cs" />
<Compile Include="VisualModes\VisualMiddle3D.cs" />
<Compile Include="VisualModes\WallPolygon.cs" />
<Compile Include="VisualModes\SectorData.cs" />
<Compile Include="VisualModes\SectorLevel.cs" />

View file

@ -73,7 +73,10 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
// Static property to access the BuilderPlug
public static BuilderPlug Me { get { return me; } }
// This is the lowest Doom Builder core revision that is required for this plugin to work
public override int MinimumRevision { get { return 1382; } }
// Settings
public int ShowVisualThings { get { return showvisualthings; } set { showvisualthings = value; } }
public int ChangeHeightBySidedef { get { return changeheightbysidedef; } }

View file

@ -121,9 +121,9 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
polygons.Add(poly);
// Go for all levels to build geometry
for(int i = sd.Levels.Count - 1; i >= 0; i--)
for(int i = sd.LightLevels.Count - 1; i >= 0; i--)
{
SectorLevel l = sd.Levels[i];
SectorLevel l = sd.LightLevels[i];
if((l != sd.Floor) && (l != sd.Ceiling) && (l.type != SectorLevelType.Floor))
{
// Go for all polygons

View file

@ -542,7 +542,7 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
// Camera below floor level?
Vector3D feetposition = General.Map.VisualCamera.Position - new Vector3D(0, 0, cameraflooroffset - 7.0f);
SectorLevel floorlevel = sd.GetFloorBelow(feetposition) ?? sd.Levels[0];
SectorLevel floorlevel = sd.GetFloorBelow(feetposition) ?? sd.LightLevels[0];
float floorheight = floorlevel.plane.GetZ(General.Map.VisualCamera.Position);
if(General.Map.VisualCamera.Position.z < (floorheight + cameraflooroffset + 0.01f))
{
@ -559,7 +559,7 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
if(gravity.z > 3.0f) gravity.z = 3.0f;
// Test if we don't go through a floor
SectorLevel newfloorlevel = sd.GetFloorBelow(feetposition + gravity) ?? sd.Levels[0];
SectorLevel newfloorlevel = sd.GetFloorBelow(feetposition + gravity) ?? sd.LightLevels[0];
if(newfloorlevel != floorlevel)
{
// Stay above floor
@ -577,7 +577,7 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
// Camera above ceiling?
feetposition = General.Map.VisualCamera.Position - new Vector3D(0, 0, cameraflooroffset - 7.0f);
SectorLevel ceillevel = sd.GetCeilingAbove(feetposition) ?? sd.Levels[sd.Levels.Count - 1];
SectorLevel ceillevel = sd.GetCeilingAbove(feetposition) ?? sd.LightLevels[sd.LightLevels.Count - 1];
float ceilheight = ceillevel.plane.GetZ(General.Map.VisualCamera.Position);
if(General.Map.VisualCamera.Position.z > (ceilheight - cameraceilingoffset - 0.01f))
{

View file

@ -146,27 +146,29 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
data = mode.GetSectorData(this.Sector);
if(!data.Built) data.BuildLevels(mode);
// Create levels
foreach(SectorLevel lvl in data.Levels)
// Create floor
floor = floor ?? new VisualFloor(mode, this, data.Floor);
floor.Setup();
base.AddGeometry(floor);
// Create ceiling
ceiling = ceiling ?? new VisualCeiling(mode, this, data.Ceiling);
ceiling.Setup();
base.AddGeometry(ceiling);
// Create 3D floors
foreach(Sector3DFloor ef in data.ExtraFloors)
{
if(lvl.type == SectorLevelType.Floor)
{
// Create a floor
VisualFloor g = new VisualFloor(mode, this, lvl);
g.Setup();
base.AddGeometry(g);
}
else if(lvl.type == SectorLevelType.Ceiling)
{
// Create a ceiling
VisualCeiling g = new VisualCeiling(mode, this, lvl);
g.Setup();
base.AddGeometry(g);
}
// Create a floor
VisualFloor vf = new VisualFloor(mode, this, ef.floor);
vf.Setup();
base.AddGeometry(vf);
// Create a ceiling
VisualCeiling vc = new VisualCeiling(mode, this, ef.ceiling);
vc.Setup();
base.AddGeometry(vc);
}
// NOTE: Because we no longer use the Floor and Ceiling members, these are now null.
// They need to be replaced with a different system that works for all levels in the sector.
// Go for all sidedefs
Dictionary<Sidedef, VisualSidedefParts> oldsides = sides ?? new Dictionary<Sidedef, VisualSidedefParts>(1);
@ -193,9 +195,22 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
VisualMiddleDouble vm = parts.middledouble ?? new VisualMiddleDouble(mode, this, sd);
vm.Setup();
base.AddGeometry(vm);
// Create 3D wall parts
SectorData osd = mode.GetSectorData(sd.Other.Sector);
if(!osd.Built) osd.BuildLevels(mode);
Dictionary<Sector3DFloor, VisualMiddle3D> oldfloors = parts.middle3d ?? new Dictionary<Sector3DFloor, VisualMiddle3D>(2);
Dictionary<Sector3DFloor, VisualMiddle3D> newfloors = new Dictionary<Sector3DFloor, VisualMiddle3D>(2);
foreach(Sector3DFloor ef in osd.ExtraFloors)
{
VisualMiddle3D vm3 = oldfloors.ContainsKey(ef) ? oldfloors[ef] : new VisualMiddle3D(mode, this, sd, ef);
vm3.Setup();
base.AddGeometry(vm3);
newfloors.Add(ef, vm3);
}
// Store
sides.Add(sd, new VisualSidedefParts(vu, vl, vm));
sides.Add(sd, new VisualSidedefParts(vu, vl, vm, newfloors));
}
else
{

View file

@ -0,0 +1,60 @@
#region === Copyright (c) 2010 Pascal van der Heiden ===
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Rendering;
#endregion
namespace CodeImp.DoomBuilder.GZDoomEditing
{
internal class Sector3DFloor
{
// Floor and ceiling planes
public SectorLevel floor;
public SectorLevel ceiling;
// Linedef that is used to create this 3D floor
public Linedef linedef;
// Constructor
public Sector3DFloor(SectorData controlsector, Linedef sourcelinedef)
{
linedef = sourcelinedef;
// For non-vavoom types, we must switch the level types
if((sourcelinedef.Args[1] & 0x03) != 0)
{
floor = new SectorLevel(controlsector.Ceiling);
ceiling = new SectorLevel(controlsector.Floor);
floor.type = SectorLevelType.Floor;
floor.plane = floor.plane.GetInverted();
ceiling.type = SectorLevelType.Ceiling;
ceiling.plane = ceiling.plane.GetInverted();
}
else
{
floor = new SectorLevel(controlsector.Floor);
ceiling = new SectorLevel(controlsector.Ceiling);
}
// A 3D floor's color is always that of the sector it is placed in
floor.color = 0;
// Do not adjust light? (works only for non-vavoom types)
if(((sourcelinedef.Args[2] & 1) != 0) && ((sourcelinedef.Args[1] & 0x03) != 0))
{
floor.brightnessbelow = -1;
floor.colorbelow = PixelColor.FromInt(0);
ceiling.color = 0;
ceiling.brightnessbelow = -1;
ceiling.colorbelow = PixelColor.FromInt(0);
}
}
}
}

View file

@ -27,7 +27,10 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
private bool isbuilding;
// Levels sorted by height
private List<SectorLevel> levels;
private List<SectorLevel> lightlevels;
// 3D floors
private List<Sector3DFloor> extrafloors;
// Original floor and ceiling levels
private SectorLevel floor;
@ -44,7 +47,8 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
public Sector Sector { get { return sector; } }
public bool Built { get { return built; } }
public List<SectorLevel> Levels { get { return levels; } }
public List<SectorLevel> LightLevels { get { return lightlevels; } }
public List<Sector3DFloor> ExtraFloors { get { return extrafloors; } }
public SectorLevel Floor { get { return floor; } }
public SectorLevel Ceiling { get { return ceiling; } }
@ -61,7 +65,8 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
// Initialize
this.sector = s;
this.built = false;
this.levels = new List<SectorLevel>(2);
this.lightlevels = new List<SectorLevel>(2);
this.extrafloors = new List<Sector3DFloor>(1);
this.linedefs = new List<Linedef>(1);
this.things = new List<Thing>(1);
@ -97,8 +102,8 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
ceiling.colorbelow = lightcolor.WithAlpha(255);
// Add ceiling and floor
levels.Add(floor);
levels.Add(ceiling);
lightlevels.Add(floor);
lightlevels.Add(ceiling);
}
#endregion
@ -118,7 +123,7 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
if(isbuilding) return;
isbuilding = true;
levels.Clear();
lightlevels.Clear();
foreach(Linedef l in linedefs)
{
@ -192,32 +197,14 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
{
SectorData sd = mode.GetSectorData(l.Front.Sector);
if(!sd.Built) sd.BuildLevels(mode);
SectorLevel f = new SectorLevel(sd.Floor);
SectorLevel c = new SectorLevel(sd.Ceiling);
// For non-vavoom types, we must switch the level types
if((l.Args[1] & 0x03) != 0)
{
f.type = SectorLevelType.Ceiling;
c.type = SectorLevelType.Floor;
}
// A 3D floor's color is always that of the sector it is placed in
f.color = 0;
// Create 3D floor
Sector3DFloor ef = new Sector3DFloor(sd, l);
extrafloors.Add(ef);
// Do not adjust light? (works only for non-vavoom types)
if(((l.Args[2] & 1) != 0) && ((l.Args[1] & 0x03) != 0))
{
f.brightnessbelow = -1;
f.colorbelow = PixelColor.FromInt(0);
c.color = 0;
c.brightnessbelow = -1;
c.colorbelow = PixelColor.FromInt(0);
}
levels.Add(f);
levels.Add(c);
// Add levels so that they can participate in lighting
lightlevels.Add(ef.floor);
lightlevels.Add(ef.ceiling);
}
}
// ========== Transfer Brightness (see http://zdoom.org/wiki/ExtraFloor_LightOnly) =========
@ -236,7 +223,7 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
//f.brightnessbelow = 0;
//f.colorbelow = PixelColor.FromInt(0);
//levels.Add(f);
levels.Add(c);
lightlevels.Add(c);
}
}
}
@ -300,22 +287,22 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
}
// Sort the levels
levels.Sort();
lightlevels.Sort();
// Floor is always first, ceiling always last
levels.Add(ceiling);
levels.Insert(0, floor);
lightlevels.Add(ceiling);
lightlevels.Insert(0, floor);
// Now that we know the levels in this sector (and in the right order) we
// can determine the lighting in between and on the levels.
// Start from the absolute ceiling and go down to 'cast' the lighting
for(int i = levels.Count - 2; i >= 0; i--)
for(int i = lightlevels.Count - 2; i >= 0; i--)
{
SectorLevel l = levels[i];
SectorLevel pl = levels[i + 1];
SectorLevel l = lightlevels[i];
SectorLevel pl = lightlevels[i + 1];
// Set color when no color is specified, or when a 3D floor is placed above the absolute floor
if((l.color == 0) || ((l == floor) && (levels.Count > 2)))
if((l.color == 0) || ((l == floor) && (lightlevels.Count > 2)))
{
PixelColor floorbrightness = PixelColor.FromInt(mode.CalculateBrightness(pl.brightnessbelow));
PixelColor floorcolor = PixelColor.Modulate(pl.colorbelow, floorbrightness);
@ -340,7 +327,7 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
SectorLevel found = null;
float dist = float.MaxValue;
foreach(SectorLevel l in levels)
foreach(SectorLevel l in lightlevels)
{
float d = l.plane.GetZ(pos) - pos.z;
if((d > 0.0f) && (d < dist))
@ -359,7 +346,7 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
SectorLevel found = null;
float dist = float.MaxValue;
foreach(SectorLevel l in levels)
foreach(SectorLevel l in lightlevels)
{
if(l.type == SectorLevelType.Ceiling)
{
@ -381,7 +368,7 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
SectorLevel found = null;
float dist = float.MaxValue;
foreach(SectorLevel l in levels)
foreach(SectorLevel l in lightlevels)
{
float d = pos.z - l.plane.GetZ(pos);
if((d > 0.0f) && (d < dist))
@ -400,7 +387,7 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
SectorLevel found = null;
float dist = float.MaxValue;
foreach(SectorLevel l in levels)
foreach(SectorLevel l in lightlevels)
{
if(l.type == SectorLevelType.Floor)
{

View file

@ -127,7 +127,7 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
tp.trb.y = tp.tlt.y + ((float)Sidedef.Other.Sector.FloorHeight - ((float)Sidedef.Sector.FloorHeight + floorbias));
// Apply texture offset
if (General.Map.Config.ScaledTextureOffsets && !base.Texture.WorldPanning)
if(General.Map.Config.ScaledTextureOffsets && !base.Texture.WorldPanning)
{
tp.tlt += new Vector2D(Sidedef.OffsetX * base.Texture.Scale.x, Sidedef.OffsetY * base.Texture.Scale.y);
tp.trb += new Vector2D(Sidedef.OffsetX * base.Texture.Scale.x, Sidedef.OffsetY * base.Texture.Scale.y);
@ -179,15 +179,9 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
base.SetVertices(verts);
return true;
}
else
{
return false;
}
}
else
{
return false;
}
return false;
}
#endregion

View file

@ -0,0 +1,217 @@
#region ================== Copyright (c) 2007 Pascal vd Heiden
/*
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#endregion
#region ================== Namespaces
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using System.Drawing;
using System.ComponentModel;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Geometry;
using System.Drawing.Imaging;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Editing;
using CodeImp.DoomBuilder.IO;
using CodeImp.DoomBuilder.Rendering;
using CodeImp.DoomBuilder.VisualModes;
#endregion
namespace CodeImp.DoomBuilder.GZDoomEditing
{
internal sealed class VisualMiddle3D : BaseVisualGeometrySidedef
{
#region ================== Constants
#endregion
#region ================== Variables
private Sector3DFloor extrafloor;
#endregion
#region ================== Properties
#endregion
#region ================== Constructor / Setup
// Constructor
public VisualMiddle3D(BaseVisualMode mode, VisualSector vs, Sidedef s, Sector3DFloor extrafloor) : base(mode, vs, s)
{
this.extrafloor = extrafloor;
// We have no destructor
GC.SuppressFinalize(this);
}
// This builds the geometry. Returns false when no geometry created.
public override bool Setup()
{
Vector2D vl, vr;
Sidedef sourceside = extrafloor.linedef.Front;
// Left and right vertices for this sidedef
if(Sidedef.IsFront)
{
vl = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
vr = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
}
else
{
vl = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
vr = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
}
// Load sector data
SectorData sd = mode.GetSectorData(Sidedef.Sector);
// Texture given?
if((sourceside.MiddleTexture.Length > 0) && (sourceside.MiddleTexture[0] != '-'))
{
// Load texture
base.Texture = General.Map.Data.GetTextureImage(sourceside.LongMiddleTexture);
if(base.Texture == null)
{
base.Texture = General.Map.Data.MissingTexture3D;
setuponloadedtexture = sourceside.LongMiddleTexture;
}
else
{
if(!base.Texture.IsImageLoaded)
setuponloadedtexture = sourceside.LongMiddleTexture;
}
}
else
{
// Use missing texture
base.Texture = General.Map.Data.MissingTexture3D;
setuponloadedtexture = 0;
}
// Get texture scaled size
Vector2D tsz = new Vector2D(base.Texture.ScaledWidth, base.Texture.ScaledHeight);
// Determine texture coordinates plane as they would be in normal circumstances.
// We can then use this plane to find any texture coordinate we need.
// The logic here is the same as in the original VisualMiddleSingle (except that
// the values are stored in a TexturePlane)
// NOTE: I use a small bias for the floor height, because if the difference in
// height is 0 then the TexturePlane doesn't work!
TexturePlane tp = new TexturePlane();
float floorbias = (Sidedef.Other.Sector.FloorHeight == Sidedef.Sector.FloorHeight) ? 1.0f : 0.0f;
if(Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag))
{
// When lower unpegged is set, the lower texture is bound to the bottom
tp.tlt.y = (float)Sidedef.Sector.CeilHeight - (float)sourceside.Sector.FloorHeight;
}
tp.trb.x = tp.tlt.x + Sidedef.Line.Length;
tp.trb.y = tp.tlt.y + ((float)sourceside.Sector.FloorHeight - ((float)Sidedef.Sector.FloorHeight + floorbias));
// Apply texture offset
if(General.Map.Config.ScaledTextureOffsets && !base.Texture.WorldPanning)
{
tp.tlt += new Vector2D(Sidedef.OffsetX * base.Texture.Scale.x, Sidedef.OffsetY * base.Texture.Scale.y);
tp.trb += new Vector2D(Sidedef.OffsetX * base.Texture.Scale.x, Sidedef.OffsetY * base.Texture.Scale.y);
}
else
{
tp.tlt += new Vector2D(Sidedef.OffsetX, Sidedef.OffsetY);
tp.trb += new Vector2D(Sidedef.OffsetX, Sidedef.OffsetY);
}
// Transform pixel coordinates to texture coordinates
tp.tlt /= tsz;
tp.trb /= tsz;
// Left top and right bottom of the geometry that
tp.vlt = new Vector3D(vl.x, vl.y, (float)sourceside.Sector.FloorHeight);
tp.vrb = new Vector3D(vr.x, vr.y, (float)Sidedef.Sector.FloorHeight + floorbias);
// Make the right-top coordinates
tp.trt = new Vector2D(tp.trb.x, tp.tlt.y);
tp.vrt = new Vector3D(tp.vrb.x, tp.vrb.y, tp.vlt.z);
// Get ceiling and floor heights
float fl = sd.Floor.plane.GetZ(vl);
float fr = sd.Floor.plane.GetZ(vr);
float cl = sd.Ceiling.plane.GetZ(vl);
float cr = sd.Ceiling.plane.GetZ(vr);
// Anything to see?
if(((cl - fl) > 0.01f) || ((cr - fr) > 0.01f))
{
// Keep top and bottom planes for intersection testing
top = extrafloor.floor.plane;
bottom = extrafloor.ceiling.plane;
// Create initial polygon, which is just a quad between floor and ceiling
WallPolygon poly = new WallPolygon();
poly.Add(new Vector3D(vl.x, vl.y, fl));
poly.Add(new Vector3D(vl.x, vl.y, cl));
poly.Add(new Vector3D(vr.x, vr.y, cr));
poly.Add(new Vector3D(vr.x, vr.y, fr));
// Determine initial color
PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(sd.Ceiling.brightnessbelow));
PixelColor wallcolor = PixelColor.Modulate(sd.Ceiling.colorbelow, wallbrightness);
poly.color = wallcolor.WithAlpha(255).ToInt();
// Cut off the part above the 3D floor and below the 3D ceiling
CropPoly(ref poly, extrafloor.floor.plane, false);
CropPoly(ref poly, extrafloor.ceiling.plane, false);
// Process the polygon and create vertices
List<WorldVertex> verts = CreatePolygonVertices(poly, tp);
if(verts.Count > 0)
{
base.SetVertices(verts);
return true;
}
}
return false;
}
#endregion
#region ================== Methods
// Return texture name
public override string GetTextureName()
{
return this.Sidedef.MiddleTexture;
}
// This changes the texture
protected override void SetTexture(string texturename)
{
this.Sidedef.SetTextureMid(texturename);
General.Map.Data.UpdateUsedTextures();
this.Setup();
}
#endregion
}
}

View file

@ -47,6 +47,10 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
#region ================== Variables
private bool repeatmidtex;
private Plane topclipplane;
private Plane bottomclipplane;
#endregion
#region ================== Properties
@ -68,25 +72,31 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
// This builds the geometry. Returns false when no geometry created.
public override bool Setup()
{
WorldVertex[] verts;
int brightness = mode.CalculateBrightness(Sidedef.Sector.Brightness);
Vector2D vl, vr;
// Calculate size of this wall part
float geotop = (float)Math.Min(Sidedef.Sector.CeilHeight, Sidedef.Other.Sector.CeilHeight);
float geobottom = (float)Math.Max(Sidedef.Sector.FloorHeight, Sidedef.Other.Sector.FloorHeight);
float geoheight = geotop - geobottom;
if(geoheight > 0.001f)
// Texture given?
if((Sidedef.MiddleTexture.Length > 0) && (Sidedef.MiddleTexture[0] != '-'))
{
// Left and right vertices for this sidedef
if(Sidedef.IsFront)
{
vl = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
vr = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
}
else
{
vl = new Vector2D(Sidedef.Line.End.Position.x, Sidedef.Line.End.Position.y);
vr = new Vector2D(Sidedef.Line.Start.Position.x, Sidedef.Line.Start.Position.y);
}
// Load sector data
SectorData sd = mode.GetSectorData(Sidedef.Sector);
SectorData osd = mode.GetSectorData(Sidedef.Other.Sector);
if(!osd.Built) osd.BuildLevels(mode);
// Texture given?
if((Sidedef.MiddleTexture.Length > 0) && (Sidedef.MiddleTexture[0] != '-'))
{
Vector2D t1 = new Vector2D();
Vector2D t2 = new Vector2D();
float textop, texbottom;
float cliptop = 0.0f;
float clipbottom = 0.0f;
// Load texture
base.Texture = General.Map.Data.GetTextureImage(Sidedef.LongMiddleTexture);
if(base.Texture == null)
@ -99,89 +109,126 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
if(!base.Texture.IsImageLoaded)
setuponloadedtexture = Sidedef.LongMiddleTexture;
}
// Get texture scaled size
Vector2D tsz = new Vector2D(base.Texture.ScaledWidth, base.Texture.ScaledHeight);
// Because the middle texture on a double sided line does not repeat vertically,
// we first determine the visible portion of the texture
}
else
{
// Use missing texture
base.Texture = General.Map.Data.MissingTexture3D;
setuponloadedtexture = 0;
}
// Get texture scaled size
Vector2D tsz = new Vector2D(base.Texture.ScaledWidth, base.Texture.ScaledHeight);
// Determine texture coordinates plane as they would be in normal circumstances.
// We can then use this plane to find any texture coordinate we need.
// The logic here is the same as in the original VisualMiddleSingle (except that
// the values are stored in a TexturePlane)
// NOTE: I use a small bias for the floor height, because if the difference in
// height is 0 then the TexturePlane doesn't work!
TexturePlane tp = new TexturePlane();
float floorbias = (Sidedef.Sector.CeilHeight == Sidedef.Sector.FloorHeight) ? 1.0f : 0.0f;
if(Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag))
{
// When lower unpegged is set, the middle texture is bound to the bottom
tp.tlt.y = tsz.y - (float)(Sidedef.Sector.CeilHeight - Sidedef.Sector.FloorHeight);
}
tp.trb.x = tp.tlt.x + Sidedef.Line.Length;
tp.trb.y = tp.tlt.y + ((float)Sidedef.Sector.CeilHeight - ((float)Sidedef.Sector.FloorHeight + floorbias));
// Apply texture offset
if (General.Map.Config.ScaledTextureOffsets && !base.Texture.WorldPanning)
{
tp.tlt += new Vector2D(Sidedef.OffsetX * base.Texture.Scale.x, Sidedef.OffsetY * base.Texture.Scale.y);
tp.trb += new Vector2D(Sidedef.OffsetX * base.Texture.Scale.x, Sidedef.OffsetY * base.Texture.Scale.y);
}
else
{
tp.tlt += new Vector2D(Sidedef.OffsetX, Sidedef.OffsetY);
tp.trb += new Vector2D(Sidedef.OffsetX, Sidedef.OffsetY);
}
// Transform pixel coordinates to texture coordinates
tp.tlt /= tsz;
tp.trb /= tsz;
// Left top and right bottom of the geometry that
tp.vlt = new Vector3D(vl.x, vl.y, (float)Sidedef.Sector.CeilHeight);
tp.vrb = new Vector3D(vr.x, vr.y, (float)Sidedef.Sector.FloorHeight + floorbias);
// Make the right-top coordinates
tp.trt = new Vector2D(tp.trb.x, tp.tlt.y);
tp.vrt = new Vector3D(tp.vrb.x, tp.vrb.y, tp.vlt.z);
// Keep top and bottom planes for intersection testing
top = sd.Ceiling.plane;
bottom = sd.Floor.plane;
// Create initial polygon, which is just a quad between floor and ceiling
WallPolygon poly = new WallPolygon();
poly.Add(new Vector3D(vl.x, vl.y, sd.Floor.plane.GetZ(vl)));
poly.Add(new Vector3D(vl.x, vl.y, sd.Ceiling.plane.GetZ(vl)));
poly.Add(new Vector3D(vr.x, vr.y, sd.Ceiling.plane.GetZ(vr)));
poly.Add(new Vector3D(vr.x, vr.y, sd.Floor.plane.GetZ(vr)));
// Determine initial color
PixelColor wallbrightness = PixelColor.FromInt(mode.CalculateBrightness(sd.Ceiling.brightnessbelow));
PixelColor wallcolor = PixelColor.Modulate(sd.Ceiling.colorbelow, wallbrightness);
poly.color = wallcolor.WithAlpha(255).ToInt();
// Cut off the part below the other floor and above the other ceiling
CropPoly(ref poly, osd.Ceiling.plane, true);
CropPoly(ref poly, osd.Floor.plane, true);
// Determine if we should repeat the middle texture
repeatmidtex = false;
if(Sidedef.Fields.ContainsKey("wrapmidtex"))
{
if(Sidedef.Fields["wrapmidtex"].Value is bool)
repeatmidtex = (bool)Sidedef.Fields["wrapmidtex"].Value;
}
if(!repeatmidtex)
{
// First determine the visible portion of the texture
float geotop = (float)Math.Min(Sidedef.Sector.CeilHeight, Sidedef.Other.Sector.CeilHeight);
float geobottom = (float)Math.Max(Sidedef.Sector.FloorHeight, Sidedef.Other.Sector.FloorHeight);
float textop, texbottom;
// Determine top portion height
if(Sidedef.Line.IsFlagSet(General.Map.Config.LowerUnpeggedFlag))
textop = geobottom + tsz.y;
else
textop = geotop;
// Apply texture offset
if (General.Map.Config.ScaledTextureOffsets)
{
textop += Sidedef.OffsetY * base.Texture.Scale.y;
}
else
{
textop += Sidedef.OffsetY;
}
// Calculate texture portion bottom
// Calculate bottom portion height
texbottom = textop - tsz.y;
// Clip texture portion by geometry
if(geotop < textop) { cliptop = textop - geotop; textop = geotop; }
if(geobottom > texbottom) { clipbottom = geobottom - texbottom; texbottom = geobottom; }
// Check if anything is still visible
if((textop - texbottom) > 0.001f)
// Create crop planes (we also need these for intersection testing)
topclipplane = new Plane(new Vector3D(0, 0, -1), textop);
bottomclipplane = new Plane(new Vector3D(0, 0, 1), -texbottom);
// Crop polygon by these heights
CropPoly(ref poly, topclipplane, true);
CropPoly(ref poly, bottomclipplane, true);
}
if(poly.Count > 2)
{
// Keep top and bottom planes for intersection testing
top = osd.Ceiling.plane;
bottom = osd.Floor.plane;
// Process the polygon and create vertices
List<WorldVertex> verts = CreatePolygonVertices(poly, tp);
if(verts.Count > 0)
{
// Determine texture coordinatess
t1.y = cliptop;
t2.y = tsz.y - clipbottom;
if (General.Map.Config.ScaledTextureOffsets && !base.Texture.WorldPanning)
{
t1.x = Sidedef.OffsetX * base.Texture.Scale.x;
}
else
{
t1.x = Sidedef.OffsetX;
}
t2.x = t1.x + Sidedef.Line.Length;
// Transform pixel coordinates to texture coordinates
t1 /= tsz;
t2 /= tsz;
// Get world coordinates for geometry
Vector2D v1, v2;
if(Sidedef.IsFront)
{
v1 = Sidedef.Line.Start.Position;
v2 = Sidedef.Line.End.Position;
}
else
{
v1 = Sidedef.Line.End.Position;
v2 = Sidedef.Line.Start.Position;
}
// Make vertices
verts = new WorldVertex[6];
verts[0] = new WorldVertex(v1.x, v1.y, texbottom, brightness, t1.x, t2.y);
verts[1] = new WorldVertex(v1.x, v1.y, textop, brightness, t1.x, t1.y);
verts[2] = new WorldVertex(v2.x, v2.y, textop, brightness, t2.x, t1.y);
verts[3] = verts[0];
verts[4] = verts[2];
verts[5] = new WorldVertex(v2.x, v2.y, texbottom, brightness, t2.x, t2.y);
// Apply vertices
base.SetVertices(verts);
return true;
}
}
}
// No geometry for invisible wall
verts = new WorldVertex[0];
base.SetVertices(verts);
return false;
}
@ -189,6 +236,20 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
#region ================== Methods
// This performs a fast test in object picking
public override bool PickFastReject(Vector3D from, Vector3D to, Vector3D dir)
{
if(!repeatmidtex)
{
// Whe nthe texture is not repeated, leave when outside crop planes
if((pickintersect.z < bottomclipplane.GetZ(pickintersect)) ||
(pickintersect.z > topclipplane.GetZ(pickintersect)))
return false;
}
return base.PickFastReject(from, to, dir);
}
// Return texture name
public override string GetTextureName()
{

View file

@ -180,15 +180,9 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
base.SetVertices(verts);
return true;
}
else
{
return false;
}
}
else
{
return false;
}
return false;
}
#endregion

View file

@ -43,16 +43,18 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
public VisualLower lower;
public VisualMiddleDouble middledouble;
public VisualMiddleSingle middlesingle;
public Dictionary<Sector3DFloor, VisualMiddle3D> middle3d;
// Constructor
public VisualSidedefParts(VisualUpper u, VisualLower l, VisualMiddleDouble m)
public VisualSidedefParts(VisualUpper u, VisualLower l, VisualMiddleDouble m, Dictionary<Sector3DFloor, VisualMiddle3D> e)
{
this.upper = u;
this.lower = l;
this.middledouble = m;
this.middlesingle = null;
this.middle3d = e;
}
// Constructor
public VisualSidedefParts(VisualMiddleSingle m)
{
@ -60,8 +62,9 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
this.lower = null;
this.middledouble = null;
this.middlesingle = m;
this.middle3d = null;
}
// This calls Setup() on all parts
public void SetupAllParts()
{
@ -69,6 +72,11 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
if(middledouble != null) middledouble.Setup();
if(middlesingle != null) middlesingle.Setup();
if(upper != null) upper.Setup();
if(middle3d != null)
{
foreach(VisualMiddle3D m in middle3d.Values)
m.Setup();
}
}
}
}

View file

@ -179,15 +179,9 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
base.SetVertices(verts);
return true;
}
else
{
return false;
}
}
else
{
return false;
}
return false;
}
#endregion

Binary file not shown.