2010-09-02 20:42:38 +00:00
|
|
|
#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 SectorData
|
|
|
|
{
|
|
|
|
#region ================== Variables
|
2010-09-03 15:12:07 +00:00
|
|
|
|
2010-09-02 20:42:38 +00:00
|
|
|
// Sector for which this data is
|
|
|
|
private Sector sector;
|
2010-09-03 15:12:07 +00:00
|
|
|
|
2010-09-03 06:03:28 +00:00
|
|
|
// Levels have been built?
|
|
|
|
private bool built;
|
2010-09-02 20:42:38 +00:00
|
|
|
|
2010-09-03 15:12:07 +00:00
|
|
|
// This is to prevent recursion when sectors need each other to build
|
|
|
|
private bool isbuilding;
|
|
|
|
|
|
|
|
// Levels sorted by height
|
2010-09-02 20:42:38 +00:00
|
|
|
private List<SectorLevel> levels;
|
2010-09-03 15:12:07 +00:00
|
|
|
|
|
|
|
// Original floor and ceiling levels
|
|
|
|
private SectorLevel floor;
|
|
|
|
private SectorLevel ceiling;
|
|
|
|
|
2010-09-03 06:03:28 +00:00
|
|
|
// Linedefs and Things of interest when building the levels
|
|
|
|
// See RebuildSectorData() in BaseVisualMode.cs for the logic which selects interesting elements
|
|
|
|
private List<Linedef> linedefs;
|
|
|
|
private List<Thing> things;
|
2010-09-03 15:12:07 +00:00
|
|
|
|
2010-09-02 20:42:38 +00:00
|
|
|
#endregion
|
2010-09-03 15:12:07 +00:00
|
|
|
|
2010-09-02 20:42:38 +00:00
|
|
|
#region ================== Properties
|
2010-09-03 15:12:07 +00:00
|
|
|
|
2010-09-02 20:42:38 +00:00
|
|
|
public Sector Sector { get { return sector; } }
|
2010-09-03 06:03:28 +00:00
|
|
|
public bool Built { get { return built; } }
|
2010-09-02 20:42:38 +00:00
|
|
|
public List<SectorLevel> Levels { get { return levels; } }
|
2010-09-03 15:12:07 +00:00
|
|
|
public SectorLevel Floor { get { return floor; } }
|
|
|
|
public SectorLevel Ceiling { get { return ceiling; } }
|
|
|
|
|
2010-09-02 20:42:38 +00:00
|
|
|
#endregion
|
2010-09-03 15:12:07 +00:00
|
|
|
|
2010-09-02 20:42:38 +00:00
|
|
|
#region ================== Constructor / Destructor
|
2010-09-03 15:12:07 +00:00
|
|
|
|
2010-09-02 20:42:38 +00:00
|
|
|
// Constructor
|
2010-09-03 15:12:07 +00:00
|
|
|
public SectorData(BaseVisualMode mode, Sector s)
|
2010-09-02 20:42:38 +00:00
|
|
|
{
|
2010-09-03 15:12:07 +00:00
|
|
|
int color = -1, flight = s.Brightness, clight = s.Brightness;
|
|
|
|
bool fabs = true, cabs = true;
|
|
|
|
|
2010-09-02 20:42:38 +00:00
|
|
|
// Initialize
|
|
|
|
this.sector = s;
|
2010-09-03 06:03:28 +00:00
|
|
|
this.built = false;
|
2010-09-02 20:42:38 +00:00
|
|
|
this.levels = new List<SectorLevel>(2);
|
2010-09-03 06:03:28 +00:00
|
|
|
this.linedefs = new List<Linedef>(1);
|
|
|
|
this.things = new List<Thing>(1);
|
2010-09-03 15:12:07 +00:00
|
|
|
|
|
|
|
// Create floor and ceiling planes
|
|
|
|
floor = new SectorLevel(s, SectorLevelType.Floor);
|
|
|
|
ceiling = new SectorLevel(s, SectorLevelType.Ceiling);
|
|
|
|
floor.plane = new Plane(new Vector3D(0, 0, 1), sector.FloorHeight);
|
2010-09-04 11:19:37 +00:00
|
|
|
ceiling.plane = new Plane(new Vector3D(0, 0, 1), sector.CeilHeight);
|
2010-09-03 15:12:07 +00:00
|
|
|
|
|
|
|
// Determine colors
|
|
|
|
try
|
|
|
|
{
|
|
|
|
// Fetch ZDoom fields
|
|
|
|
color = sector.Fields.ContainsKey("lightcolor") ? (int)sector.Fields["lightcolor"].Value : -1;
|
|
|
|
flight = sector.Fields.ContainsKey("lightfloor") ? (int)sector.Fields["lightfloor"].Value : 0;
|
|
|
|
fabs = sector.Fields.ContainsKey("lightfloorabsolute") ? (bool)sector.Fields["lightfloorabsolute"].Value : false;
|
|
|
|
clight = sector.Fields.ContainsKey("lightceiling") ? (int)sector.Fields["lightceiling"].Value : 0;
|
|
|
|
cabs = sector.Fields.ContainsKey("lightceilingabsolute") ? (bool)sector.Fields["lightceilingabsolute"].Value : false;
|
|
|
|
}
|
|
|
|
catch(Exception) { }
|
|
|
|
PixelColor lightcolor = PixelColor.FromInt(color);
|
|
|
|
if(!fabs) flight = sector.Brightness + flight;
|
|
|
|
if(!cabs) clight = sector.Brightness + clight;
|
|
|
|
PixelColor floorbrightness = PixelColor.FromInt(mode.CalculateBrightness(flight));
|
|
|
|
PixelColor ceilingbrightness = PixelColor.FromInt(mode.CalculateBrightness(clight));
|
|
|
|
PixelColor floorcolor = PixelColor.Modulate(lightcolor, floorbrightness);
|
|
|
|
PixelColor ceilingcolor = PixelColor.Modulate(lightcolor, ceilingbrightness);
|
|
|
|
floor.color = floorcolor.WithAlpha(255).ToInt();
|
|
|
|
ceiling.color = ceilingcolor.WithAlpha(255).ToInt();
|
|
|
|
ceiling.brightnessbelow = sector.Brightness;
|
|
|
|
ceiling.colorbelow = lightcolor;
|
|
|
|
|
|
|
|
// Add ceiling and floor
|
|
|
|
levels.Add(floor);
|
|
|
|
levels.Add(ceiling);
|
2010-09-03 06:03:28 +00:00
|
|
|
}
|
2010-09-03 15:12:07 +00:00
|
|
|
|
2010-09-03 06:03:28 +00:00
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region ================== Public Methods
|
2010-09-03 15:12:07 +00:00
|
|
|
|
2010-09-03 06:03:28 +00:00
|
|
|
// This adds a linedef that of interest to this sector, because it modifies the sector
|
|
|
|
public void AddLinedef(Linedef l) { linedefs.Add(l); }
|
2010-09-03 15:12:07 +00:00
|
|
|
|
2010-09-03 06:03:28 +00:00
|
|
|
// This adds a thing that of interest to this sector, because it modifies the sector
|
|
|
|
public void AddThing(Thing t) { things.Add(t); }
|
2010-09-03 15:12:07 +00:00
|
|
|
|
|
|
|
// This creates additional levels from things and linedefs
|
2010-09-03 06:03:28 +00:00
|
|
|
public void BuildLevels(BaseVisualMode mode)
|
|
|
|
{
|
2010-09-03 15:12:07 +00:00
|
|
|
// Begin
|
|
|
|
if(isbuilding) return;
|
|
|
|
isbuilding = true;
|
2010-09-04 11:19:37 +00:00
|
|
|
|
2010-09-03 15:12:07 +00:00
|
|
|
foreach(Linedef l in linedefs)
|
|
|
|
{
|
2010-09-04 14:51:35 +00:00
|
|
|
// ========== Plane Align (see http://zdoom.org/wiki/Plane_Align) ==========
|
2010-09-03 15:12:07 +00:00
|
|
|
if(l.Action == 181)
|
|
|
|
{
|
|
|
|
// Find the vertex furthest from the line
|
|
|
|
Vertex foundv = null;
|
|
|
|
float founddist = -1.0f;
|
|
|
|
foreach(Sidedef sd in sector.Sidedefs)
|
|
|
|
{
|
|
|
|
Vertex v = sd.IsFront ? sd.Line.Start : sd.Line.End;
|
|
|
|
float d = l.DistanceToSq(v.Position, false);
|
|
|
|
if(d > founddist)
|
|
|
|
{
|
|
|
|
foundv = v;
|
|
|
|
founddist = d;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Align floor with back of line
|
|
|
|
if((l.Args[0] == 1) && (l.Front.Sector == sector) && (l.Back != null))
|
|
|
|
{
|
2010-09-04 11:19:37 +00:00
|
|
|
Vector3D v1 = new Vector3D(l.End.Position.x, l.End.Position.y, l.Back.Sector.FloorHeight);
|
2010-09-03 15:12:07 +00:00
|
|
|
Vector3D v2 = new Vector3D(l.Start.Position.x, l.Start.Position.y, l.Back.Sector.FloorHeight);
|
2010-09-04 11:19:37 +00:00
|
|
|
Vector3D v3 = new Vector3D(foundv.Position.x, foundv.Position.y, sector.FloorHeight);
|
|
|
|
if(l.SideOfLine(v3) < 0.0f)
|
|
|
|
floor.plane = new Plane(v1, v2, v3, true);
|
|
|
|
else
|
|
|
|
floor.plane = new Plane(v2, v1, v3, true);
|
2010-09-03 15:12:07 +00:00
|
|
|
}
|
|
|
|
// Align floor with front of line
|
|
|
|
else if((l.Args[0] == 2) && (l.Back.Sector == sector) && (l.Front != null))
|
|
|
|
{
|
2010-09-04 11:19:37 +00:00
|
|
|
Vector3D v1 = new Vector3D(l.End.Position.x, l.End.Position.y, l.Front.Sector.FloorHeight);
|
2010-09-03 15:12:07 +00:00
|
|
|
Vector3D v2 = new Vector3D(l.Start.Position.x, l.Start.Position.y, l.Front.Sector.FloorHeight);
|
2010-09-04 11:19:37 +00:00
|
|
|
Vector3D v3 = new Vector3D(foundv.Position.x, foundv.Position.y, sector.FloorHeight);
|
|
|
|
if(l.SideOfLine(v3) < 0.0f)
|
|
|
|
floor.plane = new Plane(v1, v2, v3, true);
|
|
|
|
else
|
|
|
|
floor.plane = new Plane(v2, v1, v3, true);
|
2010-09-03 15:12:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Align ceiling with back of line
|
|
|
|
if((l.Args[1] == 1) && (l.Front.Sector == sector) && (l.Back != null))
|
|
|
|
{
|
2010-09-04 11:19:37 +00:00
|
|
|
Vector3D v1 = new Vector3D(l.End.Position.x, l.End.Position.y, l.Back.Sector.CeilHeight);
|
2010-09-03 15:12:07 +00:00
|
|
|
Vector3D v2 = new Vector3D(l.Start.Position.x, l.Start.Position.y, l.Back.Sector.CeilHeight);
|
2010-09-04 11:19:37 +00:00
|
|
|
Vector3D v3 = new Vector3D(foundv.Position.x, foundv.Position.y, sector.CeilHeight);
|
|
|
|
if(l.SideOfLine(v3) > 0.0f)
|
|
|
|
ceiling.plane = new Plane(v1, v2, v3, false);
|
|
|
|
else
|
|
|
|
ceiling.plane = new Plane(v2, v1, v3, false);
|
2010-09-03 15:12:07 +00:00
|
|
|
}
|
|
|
|
// Align ceiling with front of line
|
|
|
|
else if((l.Args[1] == 2) && (l.Back.Sector == sector) && (l.Front != null))
|
|
|
|
{
|
2010-09-04 11:19:37 +00:00
|
|
|
Vector3D v1 = new Vector3D(l.End.Position.x, l.End.Position.y, l.Front.Sector.CeilHeight);
|
2010-09-03 15:12:07 +00:00
|
|
|
Vector3D v2 = new Vector3D(l.Start.Position.x, l.Start.Position.y, l.Front.Sector.CeilHeight);
|
2010-09-04 11:19:37 +00:00
|
|
|
Vector3D v3 = new Vector3D(foundv.Position.x, foundv.Position.y, sector.CeilHeight);
|
|
|
|
if(l.SideOfLine(v3) > 0.0f)
|
|
|
|
ceiling.plane = new Plane(v1, v2, v3, false);
|
|
|
|
else
|
|
|
|
ceiling.plane = new Plane(v2, v1, v3, false);
|
2010-09-03 15:12:07 +00:00
|
|
|
}
|
|
|
|
}
|
2010-09-04 14:51:35 +00:00
|
|
|
// ========== Sector 3D floor (see http://zdoom.org/wiki/Sector_Set3dFloor) ==========
|
|
|
|
else if(l.Action == 160)
|
|
|
|
{
|
|
|
|
if(l.Front != null)
|
|
|
|
{
|
|
|
|
SectorData sd = mode.GetSectorData(l.Front.Sector);
|
|
|
|
if(!sd.Built) sd.BuildLevels(mode);
|
|
|
|
|
|
|
|
// Add floor and ceiling of control sector
|
|
|
|
levels.Add(sd.Floor);
|
|
|
|
levels.Add(sd.Ceiling);
|
|
|
|
}
|
|
|
|
}
|
2010-09-03 15:12:07 +00:00
|
|
|
}
|
2010-09-03 06:03:28 +00:00
|
|
|
|
2010-09-03 15:12:07 +00:00
|
|
|
foreach(Thing t in things)
|
2010-09-02 20:42:38 +00:00
|
|
|
{
|
2010-09-04 14:51:35 +00:00
|
|
|
// ========== Copy floor slope ==========
|
2010-09-03 15:12:07 +00:00
|
|
|
if(t.Type == 9510)
|
|
|
|
{
|
|
|
|
// Find tagged sector
|
|
|
|
Sector ts = null;
|
|
|
|
foreach(Sector s in General.Map.Map.Sectors)
|
|
|
|
{
|
|
|
|
if(s.Tag == t.Args[0])
|
|
|
|
{
|
|
|
|
ts = s;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ts != null)
|
|
|
|
{
|
|
|
|
SectorData tsd = mode.GetSectorData(ts);
|
|
|
|
if(!tsd.Built) tsd.BuildLevels(mode);
|
|
|
|
floor.plane = tsd.floor.plane;
|
|
|
|
}
|
|
|
|
}
|
2010-09-02 20:42:38 +00:00
|
|
|
}
|
2010-09-03 15:12:07 +00:00
|
|
|
|
|
|
|
// Sort the levels
|
|
|
|
levels.Sort();
|
|
|
|
|
2010-09-03 06:03:28 +00:00
|
|
|
// Done
|
|
|
|
built = true;
|
2010-09-03 15:12:07 +00:00
|
|
|
isbuilding = false;
|
2010-09-03 06:03:28 +00:00
|
|
|
}
|
2010-09-03 15:12:07 +00:00
|
|
|
|
2010-09-02 20:42:38 +00:00
|
|
|
#endregion
|
|
|
|
}
|
|
|
|
}
|