mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2025-01-18 22:41:46 +00:00
Merged remote...
This commit is contained in:
commit
76bfd79bd6
18 changed files with 606 additions and 732 deletions
|
@ -3952,14 +3952,7 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
/// <summary>This returns a sector if given coordinates are inside one.</summary>
|
/// <summary>This returns a sector if given coordinates are inside one.</summary>
|
||||||
public Sector GetSectorByCoordinates(Vector2D pos, VisualBlockMap blockmap)
|
public Sector GetSectorByCoordinates(Vector2D pos, VisualBlockMap blockmap)
|
||||||
{
|
{
|
||||||
// Find nearest sectors using the blockmap
|
return blockmap.GetSectorAt(pos);
|
||||||
List<Sector> possiblesectors = blockmap.GetBlock(blockmap.GetBlockCoordinates(pos)).Sectors;
|
|
||||||
foreach(Sector s in possiblesectors)
|
|
||||||
{
|
|
||||||
if(s.Intersect(pos)) return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//mxd
|
//mxd
|
||||||
|
|
|
@ -23,6 +23,7 @@ using CodeImp.DoomBuilder.Geometry;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using CodeImp.DoomBuilder.Rendering;
|
using CodeImp.DoomBuilder.Rendering;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using CodeImp.DoomBuilder.VisualModes;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -88,6 +89,7 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
private Color4 fogcolor;
|
private Color4 fogcolor;
|
||||||
private SectorFogMode fogmode;
|
private SectorFogMode fogmode;
|
||||||
private int lastProcessed;
|
private int lastProcessed;
|
||||||
|
private VisualSector visualsector;
|
||||||
|
|
||||||
//mxd. Slopes
|
//mxd. Slopes
|
||||||
private Vector3D floorslope;
|
private Vector3D floorslope;
|
||||||
|
@ -144,13 +146,14 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
public Vector3D CeilSlope { get { return ceilslope; } set { BeforePropsChange(); ceilslope = value; updateneeded = true; } }
|
public Vector3D CeilSlope { get { return ceilslope; } set { BeforePropsChange(); ceilslope = value; updateneeded = true; } }
|
||||||
public float CeilSlopeOffset { get { return ceiloffset; } set { BeforePropsChange(); ceiloffset = value; updateneeded = true; } }
|
public float CeilSlopeOffset { get { return ceiloffset; } set { BeforePropsChange(); ceiloffset = value; updateneeded = true; } }
|
||||||
internal int LastProcessed { get { return lastProcessed; } set { lastProcessed = value; } }
|
internal int LastProcessed { get { return lastProcessed; } set { lastProcessed = value; } }
|
||||||
|
public VisualSector VisualSector { get { return visualsector; } set { visualsector = value; } }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ================== Constructor / Disposer
|
#region ================== Constructor / Disposer
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
internal Sector(MapSet map, int listindex, int index)
|
internal Sector(MapSet map, int listindex, int index)
|
||||||
{
|
{
|
||||||
// Initialize
|
// Initialize
|
||||||
this.elementtype = MapElementType.SECTOR; //mxd
|
this.elementtype = MapElementType.SECTOR; //mxd
|
||||||
|
@ -208,6 +211,12 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
sidedefs = null;
|
sidedefs = null;
|
||||||
map = null;
|
map = null;
|
||||||
|
|
||||||
|
if (visualsector != null)
|
||||||
|
{
|
||||||
|
visualsector.Dispose();
|
||||||
|
visualsector = null;
|
||||||
|
}
|
||||||
|
|
||||||
//mxd. Restore isdisposed so base classes can do their disposal job
|
//mxd. Restore isdisposed so base classes can do their disposal job
|
||||||
isdisposed = false;
|
isdisposed = false;
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ using System.Collections.Generic;
|
||||||
using CodeImp.DoomBuilder.IO;
|
using CodeImp.DoomBuilder.IO;
|
||||||
using CodeImp.DoomBuilder.Geometry;
|
using CodeImp.DoomBuilder.Geometry;
|
||||||
using CodeImp.DoomBuilder.Data;
|
using CodeImp.DoomBuilder.Data;
|
||||||
|
using CodeImp.DoomBuilder.VisualModes;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -60,6 +61,7 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
|
|
||||||
// Rendering
|
// Rendering
|
||||||
private int lastProcessed;
|
private int lastProcessed;
|
||||||
|
private List<VisualGeometry> visualgeometry;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -82,6 +84,7 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
public long LongLowTexture { get { return longtexnamelow; } }
|
public long LongLowTexture { get { return longtexnamelow; } }
|
||||||
internal int SerializedIndex { get { return serializedindex; } set { serializedindex = value; } }
|
internal int SerializedIndex { get { return serializedindex; } set { serializedindex = value; } }
|
||||||
internal int LastProcessed { get { return lastProcessed; } set { lastProcessed = value; } }
|
internal int LastProcessed { get { return lastProcessed; } set { lastProcessed = value; } }
|
||||||
|
internal List<VisualGeometry> VisualGeometry { get { return visualgeometry; } set { visualgeometry = value; } }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
|
@ -88,6 +88,7 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
|
|
||||||
// Rendering
|
// Rendering
|
||||||
private int lastProcessed;
|
private int lastProcessed;
|
||||||
|
private VisualThing visualthing;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -120,6 +121,7 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
public bool IsDirectional { get { return directional; } } //mxd
|
public bool IsDirectional { get { return directional; } } //mxd
|
||||||
public bool Highlighted { get { return highlighted; } set { highlighted = value; } } //mxd
|
public bool Highlighted { get { return highlighted; } set { highlighted = value; } } //mxd
|
||||||
internal int LastProcessed { get { return lastProcessed; } set { lastProcessed = value; } }
|
internal int LastProcessed { get { return lastProcessed; } set { lastProcessed = value; } }
|
||||||
|
public VisualThing VisualThing { get { return visualthing; } set { visualthing = value; } }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -161,6 +163,12 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
map = null;
|
map = null;
|
||||||
sector = null;
|
sector = null;
|
||||||
|
|
||||||
|
if (visualthing != null)
|
||||||
|
{
|
||||||
|
visualthing.Dispose();
|
||||||
|
visualthing = null;
|
||||||
|
}
|
||||||
|
|
||||||
// Dispose base
|
// Dispose base
|
||||||
base.Dispose();
|
base.Dispose();
|
||||||
}
|
}
|
||||||
|
@ -269,19 +277,7 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// This determines which sector the thing is in and links it
|
// This determines which sector the thing is in and links it
|
||||||
public void DetermineSector(VisualBlockMap blockmap)
|
public void DetermineSector(VisualBlockMap blockmap)
|
||||||
{
|
{
|
||||||
// Find nearest sectors using the blockmap
|
sector = blockmap.GetSectorAt(pos);
|
||||||
List<Sector> possiblesectors = blockmap.GetBlock(blockmap.GetBlockCoordinates(pos)).Sectors;
|
|
||||||
|
|
||||||
// Check in which sector we are
|
|
||||||
sector = null;
|
|
||||||
foreach(Sector s in possiblesectors)
|
|
||||||
{
|
|
||||||
if(s.Intersect(pos))
|
|
||||||
{
|
|
||||||
sector = s;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This translates the flags into UDMF fields
|
// This translates the flags into UDMF fields
|
||||||
|
|
|
@ -25,33 +25,15 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
{
|
{
|
||||||
public sealed class VisualBlockEntry
|
public sealed class VisualBlockEntry
|
||||||
{
|
{
|
||||||
#region ================== Variables
|
public List<Linedef> Lines { get; set; }
|
||||||
|
public List<Thing> Things { get; set; }
|
||||||
|
public List<Sector> Sectors { get; set; }
|
||||||
|
|
||||||
// Members
|
|
||||||
private List<Linedef> lines;
|
|
||||||
private List<Thing> things;
|
|
||||||
private List<Sector> sectors;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region ================== Properties
|
|
||||||
|
|
||||||
public List<Linedef> Lines { get { return lines; } }
|
|
||||||
public List<Thing> Things { get { return things; } }
|
|
||||||
public List<Sector> Sectors { get { return sectors; } }
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region ================== Constructor
|
|
||||||
|
|
||||||
// Constructor for empty block
|
|
||||||
internal VisualBlockEntry()
|
internal VisualBlockEntry()
|
||||||
{
|
{
|
||||||
lines = new List<Linedef>(2);
|
Lines = new List<Linedef>(2);
|
||||||
things = new List<Thing>(2);
|
Things = new List<Thing>(2);
|
||||||
sectors = new List<Sector>(2);
|
Sectors = new List<Sector>(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,453 +28,296 @@ using System.Linq;
|
||||||
|
|
||||||
namespace CodeImp.DoomBuilder.VisualModes
|
namespace CodeImp.DoomBuilder.VisualModes
|
||||||
{
|
{
|
||||||
public sealed class VisualBlockMap
|
public sealed class VisualBlockMap
|
||||||
{
|
{
|
||||||
#region ================== Constants
|
|
||||||
|
|
||||||
public const int BLOCK_SIZE_SHIFT = 7;
|
|
||||||
public const int BLOCK_SIZE = 1 << BLOCK_SIZE_SHIFT;
|
|
||||||
public const float BLOCK_RADIUS = BLOCK_SIZE * Angle2D.SQRT2;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region ================== Variables
|
|
||||||
|
|
||||||
// Blocks
|
|
||||||
#if DICTIONARY_BLOCKMAP
|
|
||||||
private Dictionary<ulong, VisualBlockEntry> blockmap;
|
|
||||||
#else
|
|
||||||
private VisualBlockEntry[,] blockmap;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// State
|
|
||||||
private bool isdisposed;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region ================== Properties
|
|
||||||
|
|
||||||
public bool IsDisposed { get { return isdisposed; } }
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region ================== Constructor / Disposer
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
internal VisualBlockMap()
|
|
||||||
{
|
|
||||||
#if DICTIONARY_BLOCKMAP
|
|
||||||
// Initialize
|
|
||||||
blockmap = new Dictionary<ulong,VisualBlockEntry>();
|
|
||||||
#else
|
|
||||||
blockmap = new VisualBlockEntry[(1 << 16) / BLOCK_SIZE, (1 << 16) / BLOCK_SIZE]; // 1 megabyte per blockmap
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disposer
|
|
||||||
internal void Dispose()
|
|
||||||
{
|
|
||||||
// Not already disposed?
|
|
||||||
if(!isdisposed)
|
|
||||||
{
|
|
||||||
// Clean up
|
|
||||||
blockmap = null;
|
|
||||||
|
|
||||||
// Done
|
|
||||||
isdisposed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region ================== Methods
|
|
||||||
|
|
||||||
// This returns the block coordinates
|
|
||||||
public Point GetBlockCoordinates(Vector2D v)
|
|
||||||
{
|
|
||||||
return new Point((int)v.x >> BLOCK_SIZE_SHIFT,
|
|
||||||
(int)v.y >> BLOCK_SIZE_SHIFT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This returns the block center in world coordinates
|
|
||||||
public Vector2D GetBlockCenter(Point p)
|
|
||||||
{
|
|
||||||
return new Vector2D((p.X << BLOCK_SIZE_SHIFT) + (BLOCK_SIZE >> 1),
|
|
||||||
(p.Y << BLOCK_SIZE_SHIFT) + (BLOCK_SIZE >> 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
// This returns the key for a block at the given coordinates
|
|
||||||
// TODO: Could we just use the Point struct as key?
|
|
||||||
private static ulong GetBlockKey(Point p)
|
|
||||||
{
|
|
||||||
return unchecked( ((ulong)(uint)p.X << 32) + (uint)p.Y );
|
|
||||||
}
|
|
||||||
|
|
||||||
// This returns the block with the given coordinates
|
|
||||||
// Creates the block if it doesn't exist yet
|
|
||||||
public VisualBlockEntry GetBlock(Point p)
|
|
||||||
{
|
|
||||||
#if DICTIONARY_BLOCKMAP
|
|
||||||
ulong k = GetBlockKey(p);
|
|
||||||
VisualBlockEntry vbe;
|
|
||||||
|
|
||||||
if (blockmap.TryGetValue(k, out vbe))
|
|
||||||
return vbe;
|
|
||||||
else
|
|
||||||
return (blockmap[k] = new VisualBlockEntry());
|
|
||||||
#else
|
|
||||||
int blockX = p.X % blockmap.GetLength(0);
|
|
||||||
int blockY = p.Y % blockmap.GetLength(1);
|
|
||||||
if (blockX < 0) blockX += blockmap.GetLength(0);
|
|
||||||
if (blockY < 0) blockY += blockmap.GetLength(1);
|
|
||||||
if (blockmap[blockX, blockY] == null)
|
|
||||||
blockmap[blockX, blockY] = new VisualBlockEntry();
|
|
||||||
return blockmap[blockX, blockY];
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// This clears the blockmap
|
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
#if DICTIONARY_BLOCKMAP
|
|
||||||
blockmap = new Dictionary<ulong,VisualBlockEntry>();
|
|
||||||
#else
|
|
||||||
blockmap = new VisualBlockEntry[(1 << 16) / BLOCK_SIZE, (1 << 16) / BLOCK_SIZE]; // ok this a little bit expensive..
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// This returns a range of blocks in a square
|
|
||||||
public List<VisualBlockEntry> GetSquareRange(RectangleF rect)
|
|
||||||
{
|
|
||||||
// Calculate block coordinates
|
|
||||||
Point lt = GetBlockCoordinates(new Vector2D(rect.Left, rect.Top));
|
|
||||||
Point rb = GetBlockCoordinates(new Vector2D(rect.Right, rect.Bottom));
|
|
||||||
|
|
||||||
// Go through the range to make a list
|
|
||||||
int entriescount = (rb.X - lt.X) * (rb.Y - lt.Y);
|
|
||||||
List<VisualBlockEntry> entries = new List<VisualBlockEntry>(entriescount);
|
|
||||||
for(int x = lt.X; x <= rb.X; x++)
|
|
||||||
{
|
|
||||||
for(int y = lt.Y; y <= rb.Y; y++)
|
|
||||||
{
|
|
||||||
entries.Add(GetBlock(new Point(x, y)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return list
|
|
||||||
return entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This returns a range of blocks in a frustum
|
|
||||||
public List<VisualBlockEntry> GetFrustumRange(ProjectedFrustum2D frustum)
|
|
||||||
{
|
|
||||||
// Make square range from frustum circle
|
|
||||||
// This will be the range in which we will test blocks
|
|
||||||
Point lb = GetBlockCoordinates(frustum.Center - frustum.Radius);
|
|
||||||
Point rt = GetBlockCoordinates(frustum.Center + frustum.Radius);
|
|
||||||
|
|
||||||
Vector2D maplb = new Vector2D();
|
|
||||||
Vector2D maprt = new Vector2D();
|
|
||||||
|
|
||||||
Vertex firstvertex = General.Map.Map.Vertices.OfType<Vertex>().FirstOrDefault();
|
|
||||||
|
|
||||||
if (firstvertex != null)
|
|
||||||
maplb = maprt = firstvertex.Position;
|
|
||||||
|
|
||||||
// Get maximum dimensions of the map. First vertices...
|
|
||||||
foreach (Vertex v in General.Map.Map.Vertices)
|
|
||||||
{
|
|
||||||
if (v.Position.x < maplb.x) maplb.x = v.Position.x;
|
|
||||||
if (v.Position.y < maplb.y) maplb.y = v.Position.y;
|
|
||||||
if (v.Position.x > maprt.x) maprt.x = v.Position.x;
|
|
||||||
if (v.Position.y > maprt.y) maprt.y = v.Position.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ... then things
|
|
||||||
foreach (Thing t in General.Map.Map.Things)
|
|
||||||
{
|
|
||||||
if (t.Position.x < maplb.x) maplb.x = t.Position.x;
|
|
||||||
if (t.Position.y < maplb.y) maplb.y = t.Position.y;
|
|
||||||
if (t.Position.x > maprt.x) maprt.x = t.Position.x;
|
|
||||||
if (t.Position.y > maprt.y) maprt.y = t.Position.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
Point mlb = GetBlockCoordinates(maplb);
|
|
||||||
Point mrt = GetBlockCoordinates(maprt);
|
|
||||||
|
|
||||||
// Make sure that the checked region does not exceed the dimensions where something is to be displayed
|
|
||||||
if (lb.X < mlb.X) lb.X = mlb.X;
|
|
||||||
if (lb.Y < mlb.Y) lb.Y = mlb.Y;
|
|
||||||
if (rt.X > mrt.X) rt.X = mrt.X;
|
|
||||||
if (rt.Y > mrt.Y) rt.Y = mrt.Y;
|
|
||||||
|
|
||||||
// Constants we need
|
|
||||||
float blockfrustumdistance2 = (frustum.Radius * frustum.Radius) + (BLOCK_RADIUS * BLOCK_RADIUS);
|
|
||||||
|
|
||||||
// Go through the range to make a list
|
|
||||||
int entriescount = (rt.X - lb.X) * (rt.Y - lb.Y);
|
|
||||||
List<VisualBlockEntry> entries = new List<VisualBlockEntry>(entriescount);
|
|
||||||
|
|
||||||
for (int x = lb.X; x <= rt.X; x++)
|
|
||||||
{
|
|
||||||
for(int y = lb.Y; y <= rt.Y; y++)
|
|
||||||
{
|
|
||||||
// First check if the block circle is intersecting the frustum circle
|
|
||||||
Point block = new Point(x, y);
|
|
||||||
Vector2D blockcenter = GetBlockCenter(block);
|
|
||||||
if(Vector2D.DistanceSq(frustum.Center, blockcenter) < blockfrustumdistance2)
|
|
||||||
{
|
|
||||||
// Add the block if the block circle is inside the frustum
|
|
||||||
if (frustum.IntersectCircle(blockcenter, BLOCK_RADIUS)) entries.Add(GetBlock(block));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return list
|
|
||||||
return entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This returns all blocks along the given line
|
// This returns all blocks along the given line
|
||||||
public List<VisualBlockEntry> GetLineBlocks(Vector2D v1, Vector2D v2)
|
public List<VisualBlockEntry> GetLineBlocks(Vector2D v1, Vector2D v2)
|
||||||
{
|
{
|
||||||
// Estimate number of blocks we will go through and create list
|
int x0 = (int)Math.Floor(Math.Min(v1.x, v2.x));
|
||||||
int entriescount = (int)(Vector2D.ManhattanDistance(v1, v2) * 2.0f) / BLOCK_SIZE;
|
int y0 = (int)Math.Floor(Math.Min(v1.y, v2.y));
|
||||||
List<VisualBlockEntry> entries = new List<VisualBlockEntry>(entriescount);
|
int x1 = (int)Math.Floor(Math.Max(v1.x, v2.x)) + 1;
|
||||||
|
int y1 = (int)Math.Floor(Math.Max(v1.y, v2.y)) + 1;
|
||||||
|
|
||||||
// Find start and end block
|
var result = new List<VisualBlockEntry>();
|
||||||
Point pos = GetBlockCoordinates(v1);
|
root.GetBlocks(new Rectangle(x0, y0, x1 - x0, y1 - y0), ref result);
|
||||||
Point end = GetBlockCoordinates(v2);
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Add this block
|
public List<VisualBlockEntry> GetBlocks(RectangleF box)
|
||||||
entries.Add(GetBlock(pos));
|
{
|
||||||
|
var result = new List<VisualBlockEntry>();
|
||||||
|
root.GetBlocks(ToRectangle(box), ref result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Moving outside the block?
|
public List<VisualBlockEntry> GetBlocks(Vector2D pos)
|
||||||
if(pos != end)
|
{
|
||||||
{
|
var result = new List<VisualBlockEntry>();
|
||||||
// Calculate current block edges
|
root.GetBlocks(new Point((int)Math.Floor(pos.x), (int)Math.Floor(pos.y)), ref result);
|
||||||
float cl = pos.X * BLOCK_SIZE;
|
return result;
|
||||||
float cr = (pos.X + 1) * BLOCK_SIZE;
|
}
|
||||||
float ct = pos.Y * BLOCK_SIZE;
|
|
||||||
float cb = (pos.Y + 1) * BLOCK_SIZE;
|
|
||||||
|
|
||||||
// Line directions
|
// This returns a range of blocks in a frustum
|
||||||
int dirx = Math.Sign(v2.x - v1.x);
|
public List<VisualBlockEntry> GetFrustumRange(ProjectedFrustum2D frustum2D)
|
||||||
int diry = Math.Sign(v2.y - v1.y);
|
{
|
||||||
|
var frustum = new Frustum();
|
||||||
|
frustum.planes = new Plane[4]
|
||||||
|
{
|
||||||
|
new Plane(frustum2D.Lines[0]),
|
||||||
|
new Plane(frustum2D.Lines[1]),
|
||||||
|
new Plane(frustum2D.Lines[2]),
|
||||||
|
new Plane(frustum2D.Lines[3])
|
||||||
|
};
|
||||||
|
|
||||||
// Calculate offset and delta movement over x
|
var result = new List<VisualBlockEntry>();
|
||||||
float posx, deltax;
|
root.GetBlocks(frustum, ref result);
|
||||||
if(dirx >= 0)
|
return result;
|
||||||
{
|
}
|
||||||
posx = (cr - v1.x) / (v2.x - v1.x);
|
|
||||||
deltax = BLOCK_SIZE / (v2.x - v1.x);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Calculate offset and delta movement over x
|
|
||||||
posx = (v1.x - cl) / (v1.x - v2.x);
|
|
||||||
deltax = BLOCK_SIZE / (v1.x - v2.x);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate offset and delta movement over y
|
public Sector GetSectorAt(Vector2D pos)
|
||||||
float posy, deltay;
|
{
|
||||||
if(diry >= 0)
|
foreach (VisualBlockEntry e in GetBlocks(pos))
|
||||||
{
|
{
|
||||||
posy = (cb - v1.y) / (v2.y - v1.y);
|
foreach (Sector s in e.Sectors)
|
||||||
deltay = BLOCK_SIZE / (v2.y - v1.y);
|
{
|
||||||
}
|
if (s.Intersect(pos))
|
||||||
else
|
{
|
||||||
{
|
return s;
|
||||||
posy = (v1.y - ct) / (v1.y - v2.y);
|
}
|
||||||
deltay = BLOCK_SIZE / (v1.y - v2.y);
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Continue while not reached the end
|
public void Clear()
|
||||||
while(pos != end)
|
{
|
||||||
{
|
root = new Node(new Rectangle(MapMinX, MapMinY, MapMaxX - MapMinX, MapMaxY - MapMinY));
|
||||||
// Check in which direction to move
|
}
|
||||||
if(posx < posy)
|
|
||||||
{
|
|
||||||
// Move horizontally
|
|
||||||
posx += deltax;
|
|
||||||
if(pos.X != end.X) pos.X += dirx;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Move vertically
|
|
||||||
posy += deltay;
|
|
||||||
if(pos.Y != end.Y) pos.Y += diry;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add lines to this block
|
|
||||||
entries.Add(GetBlock(pos));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return list
|
|
||||||
return entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This puts a thing in the blockmap
|
|
||||||
public void AddThingsSet(ICollection<Thing> things)
|
|
||||||
{
|
|
||||||
foreach(Thing t in things) AddThing(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This puts a thing in the blockmap
|
|
||||||
public void AddThing(Thing t)
|
|
||||||
{
|
|
||||||
//mxd
|
|
||||||
Point p1 = GetBlockCoordinates(new Vector2D(t.Position.x - t.RenderSize, t.Position.y - t.RenderSize));
|
|
||||||
Point p2 = GetBlockCoordinates(new Vector2D(t.Position.x + t.RenderSize, t.Position.y + t.RenderSize));
|
|
||||||
for(int x = p1.X; x <= p2.X; x++)
|
|
||||||
{
|
|
||||||
for(int y = p1.Y; y <= p2.Y; y++)
|
|
||||||
{
|
|
||||||
VisualBlockEntry block = GetBlock(new Point(x, y));
|
|
||||||
block.Things.Add(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This puts a secotr in the blockmap
|
|
||||||
public void AddSectorsSet(ICollection<Sector> sectors)
|
public void AddSectorsSet(ICollection<Sector> sectors)
|
||||||
{
|
{
|
||||||
foreach(Sector s in sectors) AddSector(s);
|
foreach (Sector s in sectors) AddSector(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This puts a sector in the blockmap
|
public void AddLinedefsSet(ICollection<Linedef> lines)
|
||||||
public void AddSector(Sector s)
|
{
|
||||||
|
foreach (Linedef line in lines) AddLinedef(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddThingsSet(ICollection<Thing> things)
|
||||||
|
{
|
||||||
|
foreach (Thing t in things) AddThing(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddSector(Sector sector)
|
||||||
|
{
|
||||||
|
root.GetEntry(ToRectangle(sector.BBox)).Sectors.Add(sector);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddLinedef(Linedef line)
|
||||||
|
{
|
||||||
|
int x0 = (int)Math.Floor(Math.Min(line.Start.Position.x, line.End.Position.x));
|
||||||
|
int y0 = (int)Math.Floor(Math.Min(line.Start.Position.y, line.End.Position.y));
|
||||||
|
int x1 = (int)Math.Floor(Math.Max(line.Start.Position.x, line.End.Position.x)) + 1;
|
||||||
|
int y1 = (int)Math.Floor(Math.Max(line.Start.Position.y, line.End.Position.y)) + 1;
|
||||||
|
root.GetEntry(new Rectangle(x0, y0, x1 - x0, y1 - y0)).Lines.Add(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddThing(Thing thing)
|
||||||
|
{
|
||||||
|
int x0 = (int)Math.Floor(thing.Position.x - thing.Size);
|
||||||
|
int x1 = (int)Math.Floor(thing.Position.x + thing.Size) + 1;
|
||||||
|
int y0 = (int)Math.Floor(thing.Position.y - thing.Size);
|
||||||
|
int y1 = (int)Math.Floor(thing.Position.y + thing.Size) + 1;
|
||||||
|
root.GetEntry(new Rectangle(x0, y0, x1 - x0, y1 - y0)).Things.Add(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Dispose()
|
||||||
{
|
{
|
||||||
Point p1 = GetBlockCoordinates(new Vector2D(s.BBox.Left, s.BBox.Top));
|
Clear();
|
||||||
Point p2 = GetBlockCoordinates(new Vector2D(s.BBox.Right, s.BBox.Bottom));
|
|
||||||
for(int x = p1.X; x <= p2.X; x++)
|
|
||||||
{
|
|
||||||
for(int y = p1.Y; y <= p2.Y; y++)
|
|
||||||
{
|
|
||||||
VisualBlockEntry block = GetBlock(new Point(x, y));
|
|
||||||
block.Sectors.Add(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This puts a whole set of linedefs in the blocks they cross
|
static Rectangle ToRectangle(RectangleF bbox)
|
||||||
public void AddLinedefsSet(ICollection<Linedef> lines)
|
{
|
||||||
{
|
int x0 = (int)Math.Floor(bbox.Left);
|
||||||
foreach(Linedef l in lines) AddLinedef(l);
|
int y0 = (int)Math.Floor(bbox.Top);
|
||||||
}
|
int x1 = (int)Math.Floor(bbox.Right) + 1;
|
||||||
|
int y1 = (int)Math.Floor(bbox.Bottom) + 1;
|
||||||
// This puts a single linedef in all blocks it crosses
|
return new Rectangle(x0, y0, x1 - x0, y1 - y0);
|
||||||
public void AddLinedef(Linedef line)
|
}
|
||||||
{
|
|
||||||
// Get coordinates
|
const int MapMinX = -32768;
|
||||||
Vector2D v1 = line.Start.Position;
|
const int MapMinY = -32768;
|
||||||
Vector2D v2 = line.End.Position;
|
const int MapMaxX = 32768;
|
||||||
|
const int MapMaxY = 32768;
|
||||||
// Find start and end block
|
const int MaxLevels = 8;
|
||||||
Point pos = GetBlockCoordinates(v1);
|
|
||||||
Point end = GetBlockCoordinates(v2);
|
Node root = new Node(new Rectangle(MapMinX, MapMinY, MapMaxX - MapMinX, MapMaxY - MapMinY));
|
||||||
|
|
||||||
// Horizontal straight line?
|
struct Plane
|
||||||
if(pos.Y == end.Y)
|
{
|
||||||
{
|
public Plane(Line2D line)
|
||||||
// Simple loop
|
{
|
||||||
int dirx = Math.Sign(v2.x - v1.x);
|
Vector2D dir = line.v2 - line.v1;
|
||||||
for(int x = pos.X; x != end.X; x += dirx)
|
A = -dir.y;
|
||||||
{
|
B = dir.x;
|
||||||
GetBlock(new Point(x, pos.Y)).Lines.Add(line);
|
D = -(line.v1.x * A + line.v1.y * B);
|
||||||
}
|
}
|
||||||
GetBlock(end).Lines.Add(line);
|
|
||||||
}
|
public float A, B, D;
|
||||||
// Vertical straight line?
|
}
|
||||||
else if(pos.X == end.X)
|
|
||||||
{
|
class Frustum
|
||||||
// Simple loop
|
{
|
||||||
int diry = Math.Sign(v2.y - v1.y);
|
public Plane[] planes;
|
||||||
for(int y = pos.Y; y != end.Y; y += diry)
|
}
|
||||||
{
|
|
||||||
GetBlock(new Point(pos.X, y)).Lines.Add(line);
|
class Node
|
||||||
}
|
{
|
||||||
GetBlock(end).Lines.Add(line);
|
enum Visibility { Inside, Intersecting, Outside };
|
||||||
}
|
|
||||||
else
|
public Node(Rectangle bbox)
|
||||||
{
|
{
|
||||||
// Add lines to this block
|
this.bbox = bbox;
|
||||||
GetBlock(pos).Lines.Add(line);
|
extents = new Vector2D(bbox.Width * 0.5f, bbox.Height * 0.5f);
|
||||||
|
center = new Vector2D(bbox.X + extents.x, bbox.Y + extents.y);
|
||||||
// Moving outside the block?
|
}
|
||||||
if(pos != end)
|
|
||||||
{
|
public void GetBlocks(Frustum frustum, ref List<VisualBlockEntry> list)
|
||||||
// Calculate current block edges
|
{
|
||||||
float cl = pos.X * BLOCK_SIZE;
|
Visibility vis = TestVisibility(frustum);
|
||||||
float cr = (pos.X + 1) * BLOCK_SIZE;
|
if (vis == Visibility.Inside)
|
||||||
float ct = pos.Y * BLOCK_SIZE;
|
{
|
||||||
float cb = (pos.Y + 1) * BLOCK_SIZE;
|
GetAllBlocks(ref list);
|
||||||
|
}
|
||||||
// Line directions
|
else if (vis == Visibility.Intersecting)
|
||||||
int dirx = Math.Sign(v2.x - v1.x);
|
{
|
||||||
int diry = Math.Sign(v2.y - v1.y);
|
if (visualBlock != null)
|
||||||
|
list.Add(visualBlock);
|
||||||
// Calculate offset and delta movement over x
|
|
||||||
float posx, deltax;
|
if (topLeft != null)
|
||||||
if(dirx == 0)
|
{
|
||||||
{
|
topLeft.GetBlocks(frustum, ref list);
|
||||||
posx = float.MaxValue;
|
topRight.GetBlocks(frustum, ref list);
|
||||||
deltax = float.MaxValue;
|
bottomLeft.GetBlocks(frustum, ref list);
|
||||||
}
|
bottomRight.GetBlocks(frustum, ref list);
|
||||||
else if(dirx > 0)
|
}
|
||||||
{
|
}
|
||||||
posx = (cr - v1.x) / (v2.x - v1.x);
|
}
|
||||||
deltax = BLOCK_SIZE / (v2.x - v1.x);
|
|
||||||
}
|
void GetAllBlocks(ref List<VisualBlockEntry> list)
|
||||||
else
|
{
|
||||||
{
|
if (visualBlock != null)
|
||||||
// Calculate offset and delta movement over x
|
list.Add(visualBlock);
|
||||||
posx = (v1.x - cl) / (v1.x - v2.x);
|
|
||||||
deltax = BLOCK_SIZE / (v1.x - v2.x);
|
if (topLeft != null)
|
||||||
}
|
{
|
||||||
|
topLeft.GetAllBlocks(ref list);
|
||||||
// Calculate offset and delta movement over y
|
topRight.GetAllBlocks(ref list);
|
||||||
float posy, deltay;
|
bottomLeft.GetAllBlocks(ref list);
|
||||||
if(diry == 0)
|
bottomRight.GetAllBlocks(ref list);
|
||||||
{
|
}
|
||||||
posy = float.MaxValue;
|
}
|
||||||
deltay = float.MaxValue;
|
|
||||||
}
|
Visibility TestVisibility(Frustum frustum)
|
||||||
else if(diry > 0)
|
{
|
||||||
{
|
Visibility result = Visibility.Inside;
|
||||||
posy = (cb - v1.y) / (v2.y - v1.y);
|
for (int i = 0; i < 4; i++)
|
||||||
deltay = BLOCK_SIZE / (v2.y - v1.y);
|
{
|
||||||
}
|
Visibility vis = TestFrustumLineVisibility(frustum.planes[i]);
|
||||||
else
|
if (vis == Visibility.Outside)
|
||||||
{
|
return Visibility.Outside;
|
||||||
posy = (v1.y - ct) / (v1.y - v2.y);
|
else if (vis == Visibility.Intersecting)
|
||||||
deltay = BLOCK_SIZE / (v1.y - v2.y);
|
result = Visibility.Intersecting;
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
// Continue while not reached the end
|
}
|
||||||
while(pos != end)
|
|
||||||
{
|
Visibility TestFrustumLineVisibility(Plane plane)
|
||||||
// Check in which direction to move
|
{
|
||||||
if(posx < posy)
|
float e = extents.x * Math.Abs(plane.A) + extents.y * Math.Abs(plane.B);
|
||||||
{
|
float s = center.x * plane.A + center.y * plane.B + plane.D;
|
||||||
// Move horizontally
|
if (s - e > 0.0)
|
||||||
posx += deltax;
|
return Visibility.Inside;
|
||||||
if(pos.X != end.X) pos.X += dirx;
|
else if (s + e < 0)
|
||||||
}
|
return Visibility.Outside;
|
||||||
else
|
else
|
||||||
{
|
return Visibility.Intersecting;
|
||||||
// Move vertically
|
}
|
||||||
posy += deltay;
|
|
||||||
if(pos.Y != end.Y) pos.Y += diry;
|
public void GetBlocks(Point pos, ref List<VisualBlockEntry> list)
|
||||||
}
|
{
|
||||||
|
if (visualBlock != null)
|
||||||
// Add lines to this block
|
list.Add(visualBlock);
|
||||||
GetBlock(pos).Lines.Add(line);
|
|
||||||
}
|
if (topLeft != null)
|
||||||
}
|
{
|
||||||
}
|
if (topLeft.bbox.Contains(pos)) topLeft.GetBlocks(pos, ref list);
|
||||||
}
|
if (topRight.bbox.Contains(pos)) topRight.GetBlocks(pos, ref list);
|
||||||
|
if (bottomLeft.bbox.Contains(pos)) bottomLeft.GetBlocks(pos, ref list);
|
||||||
#endregion
|
if (bottomRight.bbox.Contains(pos)) bottomRight.GetBlocks(pos, ref list);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetBlocks(Rectangle box, ref List<VisualBlockEntry> list)
|
||||||
|
{
|
||||||
|
if (visualBlock != null)
|
||||||
|
list.Add(visualBlock);
|
||||||
|
|
||||||
|
if (topLeft != null)
|
||||||
|
{
|
||||||
|
if (topLeft.bbox.IntersectsWith(box)) topLeft.GetBlocks(box, ref list);
|
||||||
|
if (topRight.bbox.IntersectsWith(box)) topRight.GetBlocks(box, ref list);
|
||||||
|
if (bottomLeft.bbox.IntersectsWith(box)) bottomLeft.GetBlocks(box, ref list);
|
||||||
|
if (bottomRight.bbox.IntersectsWith(box)) bottomRight.GetBlocks(box, ref list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public VisualBlockEntry GetEntry(Rectangle box, int level = 0)
|
||||||
|
{
|
||||||
|
if (level == MaxLevels)
|
||||||
|
{
|
||||||
|
if (visualBlock == null)
|
||||||
|
visualBlock = new VisualBlockEntry();
|
||||||
|
return visualBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (topLeft == null)
|
||||||
|
CreateChildren();
|
||||||
|
|
||||||
|
if (topLeft.bbox.Contains(box)) return topLeft.GetEntry(box, level + 1);
|
||||||
|
if (topRight.bbox.Contains(box)) return topRight.GetEntry(box, level + 1);
|
||||||
|
if (bottomLeft.bbox.Contains(box)) return bottomLeft.GetEntry(box, level + 1);
|
||||||
|
if (bottomRight.bbox.Contains(box)) return bottomRight.GetEntry(box, level + 1);
|
||||||
|
|
||||||
|
if (visualBlock == null)
|
||||||
|
visualBlock = new VisualBlockEntry();
|
||||||
|
return visualBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateChildren()
|
||||||
|
{
|
||||||
|
int x0 = bbox.X;
|
||||||
|
int x1 = bbox.X + bbox.Width / 2;
|
||||||
|
int x2 = bbox.X + bbox.Width;
|
||||||
|
int y0 = bbox.Y;
|
||||||
|
int y1 = bbox.Y + bbox.Height / 2;
|
||||||
|
int y2 = bbox.Y + bbox.Height;
|
||||||
|
topLeft = new Node(new Rectangle(x0, y0, x1 - x0, y1 - y0));
|
||||||
|
topRight = new Node(new Rectangle(x1, y0, x2 - x1, y1 - y0));
|
||||||
|
bottomLeft = new Node(new Rectangle(x0, y1, x1 - x0, y2 - y1));
|
||||||
|
bottomRight = new Node(new Rectangle(x1, y1, x2 - x1, y2 - y1));
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle bbox;
|
||||||
|
Vector2D extents;
|
||||||
|
Vector2D center;
|
||||||
|
|
||||||
|
Node topLeft;
|
||||||
|
Node topRight;
|
||||||
|
Node bottomLeft;
|
||||||
|
Node bottomRight;
|
||||||
|
VisualBlockEntry visualBlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ using CodeImp.DoomBuilder.Rendering;
|
||||||
using CodeImp.DoomBuilder.Actions;
|
using CodeImp.DoomBuilder.Actions;
|
||||||
using CodeImp.DoomBuilder.Geometry;
|
using CodeImp.DoomBuilder.Geometry;
|
||||||
using CodeImp.DoomBuilder.Editing;
|
using CodeImp.DoomBuilder.Editing;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -70,8 +71,6 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
|
|
||||||
// Map
|
// Map
|
||||||
protected VisualBlockMap blockmap;
|
protected VisualBlockMap blockmap;
|
||||||
protected Dictionary<Thing, VisualThing> allthings;
|
|
||||||
protected Dictionary<Sector, VisualSector> allsectors;
|
|
||||||
protected List<VisualBlockEntry> visibleblocks;
|
protected List<VisualBlockEntry> visibleblocks;
|
||||||
protected List<VisualThing> visiblethings;
|
protected List<VisualThing> visiblethings;
|
||||||
protected List<VisualSector> visiblesectors;
|
protected List<VisualSector> visiblesectors;
|
||||||
|
@ -101,8 +100,6 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
// Initialize
|
// Initialize
|
||||||
this.renderer = General.Map.Renderer3D;
|
this.renderer = General.Map.Renderer3D;
|
||||||
this.blockmap = new VisualBlockMap();
|
this.blockmap = new VisualBlockMap();
|
||||||
this.allsectors = new Dictionary<Sector, VisualSector>(General.Map.Map.Sectors.Count);
|
|
||||||
this.allthings = new Dictionary<Thing, VisualThing>(General.Map.Map.Things.Count);
|
|
||||||
this.visibleblocks = new List<VisualBlockEntry>();
|
this.visibleblocks = new List<VisualBlockEntry>();
|
||||||
this.visiblesectors = new List<VisualSector>(50);
|
this.visiblesectors = new List<VisualSector>(50);
|
||||||
this.visiblegeometry = new List<VisualGeometry>(200);
|
this.visiblegeometry = new List<VisualGeometry>(200);
|
||||||
|
@ -129,15 +126,20 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
// Not already disposed?
|
// Not already disposed?
|
||||||
if(!isdisposed)
|
if(!isdisposed)
|
||||||
{
|
{
|
||||||
// Clean up
|
// Clean up
|
||||||
foreach(KeyValuePair<Sector, VisualSector> s in allsectors) s.Value.Dispose();
|
foreach (Sector sector in General.Map.Map.Sectors)
|
||||||
|
{
|
||||||
|
if (sector.VisualSector != null)
|
||||||
|
{
|
||||||
|
sector.VisualSector.Dispose();
|
||||||
|
sector.VisualSector = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
blockmap.Dispose();
|
blockmap.Dispose();
|
||||||
visiblesectors = null;
|
visiblesectors = null;
|
||||||
visiblegeometry = null;
|
visiblegeometry = null;
|
||||||
visibleblocks = null;
|
visibleblocks = null;
|
||||||
visiblethings = null;
|
visiblethings = null;
|
||||||
allsectors = null;
|
|
||||||
allthings = null;
|
|
||||||
blockmap = null;
|
blockmap = null;
|
||||||
|
|
||||||
//mxd
|
//mxd
|
||||||
|
@ -216,14 +218,26 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
public override void OnDisengage()
|
public override void OnDisengage()
|
||||||
{
|
{
|
||||||
base.OnDisengage();
|
base.OnDisengage();
|
||||||
|
|
||||||
// Dispose
|
|
||||||
foreach(KeyValuePair<Sector, VisualSector> vs in allsectors)
|
|
||||||
if(vs.Value != null) vs.Value.Dispose();
|
|
||||||
|
|
||||||
// Dispose
|
// Dispose
|
||||||
foreach(KeyValuePair<Thing, VisualThing> vt in allthings)
|
foreach (Sector sector in General.Map.Map.Sectors)
|
||||||
if(vt.Value != null) vt.Value.Dispose();
|
{
|
||||||
|
if (sector.VisualSector != null)
|
||||||
|
{
|
||||||
|
sector.VisualSector.Dispose();
|
||||||
|
sector.VisualSector = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dispose
|
||||||
|
foreach (Thing thing in General.Map.Map.Things)
|
||||||
|
{
|
||||||
|
if (thing.VisualThing != null)
|
||||||
|
{
|
||||||
|
thing.VisualThing.Dispose();
|
||||||
|
thing.VisualThing = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Apply camera position to thing
|
// Apply camera position to thing
|
||||||
General.Map.VisualCamera.ApplyToThing();
|
General.Map.VisualCamera.ApplyToThing();
|
||||||
|
@ -567,67 +581,66 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
// Not filtered out?
|
// Not filtered out?
|
||||||
if(!General.Map.ThingsFilter.IsThingVisible(t)) continue;
|
if(!General.Map.ThingsFilter.IsThingVisible(t)) continue;
|
||||||
|
|
||||||
VisualThing vt;
|
if (t.VisualThing == null)
|
||||||
if(allthings.ContainsKey(t))
|
t.VisualThing = CreateVisualThing(t);
|
||||||
{
|
|
||||||
vt = allthings[t];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Create new visual thing
|
|
||||||
vt = CreateVisualThing(t);
|
|
||||||
allthings[t] = vt;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(vt != null)
|
if(t.VisualThing != null)
|
||||||
{
|
visiblethings.Add(t.VisualThing);
|
||||||
visiblethings.Add(vt);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(processgeometry)
|
if(processgeometry)
|
||||||
{
|
{
|
||||||
// Find camera sector
|
// Find camera sector
|
||||||
Linedef nld = MapSet.NearestLinedef(visiblelines, campos2d);
|
Sector camsector = blockmap.GetSectorAt(campos2d);
|
||||||
if(nld != null)
|
if (camsector != null)
|
||||||
{
|
{
|
||||||
General.Map.VisualCamera.Sector = GetCameraSectorFromLinedef(nld);
|
General.Map.VisualCamera.Sector = camsector;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Exceptional case: no lines found in any nearby blocks!
|
// To do: fix this code. It is retarded. Walking over all visible lines is extremely expensive.
|
||||||
// This could happen in the middle of an extremely large sector and in this case
|
|
||||||
// the above code will not have found any sectors/sidedefs for rendering.
|
Linedef nld = MapSet.NearestLinedef(visiblelines, campos2d);
|
||||||
// Here we handle this special case with brute-force. Let's find the sector
|
if (nld != null)
|
||||||
// the camera is in by searching the entire map and render that sector only.
|
{
|
||||||
nld = General.Map.Map.NearestLinedef(campos2d);
|
General.Map.VisualCamera.Sector = GetCameraSectorFromLinedef(nld);
|
||||||
if(nld != null)
|
}
|
||||||
{
|
else
|
||||||
General.Map.VisualCamera.Sector = GetCameraSectorFromLinedef(nld);
|
{
|
||||||
if(General.Map.VisualCamera.Sector != null)
|
// Exceptional case: no lines found in any nearby blocks!
|
||||||
{
|
// This could happen in the middle of an extremely large sector and in this case
|
||||||
foreach(Sidedef sd in General.Map.VisualCamera.Sector.Sidedefs)
|
// the above code will not have found any sectors/sidedefs for rendering.
|
||||||
{
|
// Here we handle this special case with brute-force. Let's find the sector
|
||||||
float side = sd.Line.SideOfLine(campos2d);
|
// the camera is in by searching the entire map and render that sector only.
|
||||||
if(((side < 0) && sd.IsFront) ||
|
nld = General.Map.Map.NearestLinedef(campos2d);
|
||||||
((side > 0) && !sd.IsFront))
|
if (nld != null)
|
||||||
ProcessSidedefCulling(sd);
|
{
|
||||||
}
|
General.Map.VisualCamera.Sector = GetCameraSectorFromLinedef(nld);
|
||||||
}
|
if (General.Map.VisualCamera.Sector != null)
|
||||||
else
|
{
|
||||||
{
|
foreach (Sidedef sd in General.Map.VisualCamera.Sector.Sidedefs)
|
||||||
// Too far away from the map to see anything
|
{
|
||||||
General.Map.VisualCamera.Sector = null;
|
float side = sd.Line.SideOfLine(campos2d);
|
||||||
}
|
if (((side < 0) && sd.IsFront) ||
|
||||||
}
|
((side > 0) && !sd.IsFront))
|
||||||
else
|
ProcessSidedefCulling(sd);
|
||||||
{
|
}
|
||||||
// Map is empty
|
}
|
||||||
General.Map.VisualCamera.Sector = null;
|
else
|
||||||
}
|
{
|
||||||
}
|
// Too far away from the map to see anything
|
||||||
|
General.Map.VisualCamera.Sector = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Map is empty
|
||||||
|
General.Map.VisualCamera.Sector = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -640,32 +653,20 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
|
|
||||||
sd.LastProcessed = lastProcessed;
|
sd.LastProcessed = lastProcessed;
|
||||||
|
|
||||||
VisualSector vs;
|
if (sd.Sector.VisualSector == null)
|
||||||
|
sd.Sector.VisualSector = CreateVisualSector(sd.Sector);
|
||||||
|
|
||||||
// Find the visualsector and make it if needed
|
if(sd.Sector.VisualSector != null)
|
||||||
if(allsectors.ContainsKey(sd.Sector))
|
|
||||||
{
|
|
||||||
// Take existing visualsector
|
|
||||||
vs = allsectors[sd.Sector];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Make new visualsector
|
|
||||||
vs = CreateVisualSector(sd.Sector);
|
|
||||||
//if(vs != null) allsectors.Add(sd.Sector, vs); //mxd
|
|
||||||
}
|
|
||||||
|
|
||||||
if(vs != null)
|
|
||||||
{
|
{
|
||||||
if (sd.Sector.LastProcessed != lastProcessed)
|
if (sd.Sector.LastProcessed != lastProcessed)
|
||||||
{
|
{
|
||||||
sd.Sector.LastProcessed = lastProcessed;
|
sd.Sector.LastProcessed = lastProcessed;
|
||||||
visiblesectors.Add(vs);
|
visiblesectors.Add(sd.Sector.VisualSector);
|
||||||
visiblegeometry.AddRange(vs.FixedGeometry);
|
visiblegeometry.AddRange(sd.Sector.VisualSector.FixedGeometry);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add sidedef geometry
|
// Add sidedef geometry
|
||||||
visiblegeometry.AddRange(vs.GetSidedefGeometry(sd));
|
visiblegeometry.AddRange(sd.Sector.VisualSector.GetSidedefGeometry(sd));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -705,9 +706,9 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
List<IVisualPickable> pickables = new List<IVisualPickable>(blocks.Count * 10);
|
List<IVisualPickable> pickables = new List<IVisualPickable>(blocks.Count * 10);
|
||||||
|
|
||||||
// Add geometry from the camera sector
|
// Add geometry from the camera sector
|
||||||
if((General.Map.VisualCamera.Sector != null) && allsectors.ContainsKey(General.Map.VisualCamera.Sector))
|
if(General.Map.VisualCamera.Sector != null && General.Map.VisualCamera.Sector.VisualSector != null)
|
||||||
{
|
{
|
||||||
VisualSector vs = allsectors[General.Map.VisualCamera.Sector];
|
VisualSector vs = General.Map.VisualCamera.Sector.VisualSector;
|
||||||
sectors.Add(General.Map.VisualCamera.Sector, vs);
|
sectors.Add(General.Map.VisualCamera.Sector, vs);
|
||||||
foreach(VisualGeometry g in vs.FixedGeometry) pickables.Add(g);
|
foreach(VisualGeometry g in vs.FixedGeometry) pickables.Add(g);
|
||||||
}
|
}
|
||||||
|
@ -740,9 +741,9 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
if(ld.Front != null)
|
if(ld.Front != null)
|
||||||
{
|
{
|
||||||
// Find the visualsector
|
// Find the visualsector
|
||||||
if(allsectors.ContainsKey(ld.Front.Sector))
|
if(ld.Front.Sector.VisualSector != null)
|
||||||
{
|
{
|
||||||
VisualSector vs = allsectors[ld.Front.Sector];
|
VisualSector vs = ld.Front.Sector.VisualSector;
|
||||||
|
|
||||||
// Add sector if not already added
|
// Add sector if not already added
|
||||||
if(!sectors.ContainsKey(ld.Front.Sector))
|
if(!sectors.ContainsKey(ld.Front.Sector))
|
||||||
|
@ -777,9 +778,9 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
if(ld.Back != null)
|
if(ld.Back != null)
|
||||||
{
|
{
|
||||||
// Find the visualsector
|
// Find the visualsector
|
||||||
if(allsectors.ContainsKey(ld.Back.Sector))
|
if(ld.Back.Sector.VisualSector != null)
|
||||||
{
|
{
|
||||||
VisualSector vs = allsectors[ld.Back.Sector];
|
VisualSector vs = ld.Back.Sector.VisualSector;
|
||||||
|
|
||||||
// Add sector if not already added
|
// Add sector if not already added
|
||||||
if(!sectors.ContainsKey(ld.Back.Sector))
|
if(!sectors.ContainsKey(ld.Back.Sector))
|
||||||
|
@ -867,16 +868,26 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void ResourcesReloaded()
|
protected virtual void ResourcesReloaded()
|
||||||
{
|
{
|
||||||
// Dispose
|
// Dispose
|
||||||
foreach(KeyValuePair<Sector, VisualSector> vs in allsectors)
|
foreach (Sector sector in General.Map.Map.Sectors)
|
||||||
if(vs.Value != null) vs.Value.Dispose();
|
{
|
||||||
|
if (sector.VisualSector != null)
|
||||||
foreach(KeyValuePair<Thing, VisualThing> vt in allthings)
|
{
|
||||||
if(vt.Value != null) vt.Value.Dispose();
|
sector.VisualSector.Dispose();
|
||||||
|
sector.VisualSector = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Thing thing in General.Map.Map.Things)
|
||||||
|
{
|
||||||
|
if (thing.VisualThing != null)
|
||||||
|
{
|
||||||
|
thing.VisualThing.Dispose();
|
||||||
|
thing.VisualThing = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Clear collections
|
// Clear collections
|
||||||
allsectors.Clear();
|
|
||||||
allthings.Clear();
|
|
||||||
visiblesectors.Clear();
|
visiblesectors.Clear();
|
||||||
visibleblocks.Clear();
|
visibleblocks.Clear();
|
||||||
visiblegeometry.Clear();
|
visiblegeometry.Clear();
|
||||||
|
@ -897,8 +908,6 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void ResourcesReloadedPartial()
|
protected virtual void ResourcesReloadedPartial()
|
||||||
{
|
{
|
||||||
Dictionary<Sector, VisualSector> newsectors = new Dictionary<Sector,VisualSector>(allsectors.Count);
|
|
||||||
|
|
||||||
// Neighbour sectors must be updated as well
|
// Neighbour sectors must be updated as well
|
||||||
foreach(Sector s in General.Map.Map.Sectors)
|
foreach(Sector s in General.Map.Map.Sectors)
|
||||||
{
|
{
|
||||||
|
@ -933,27 +942,27 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dispose if source was disposed or marked
|
// Dispose if source was marked
|
||||||
foreach(KeyValuePair<Sector, VisualSector> vs in allsectors)
|
foreach(Sector s in General.Map.Map.Sectors)
|
||||||
{
|
{
|
||||||
if(vs.Value != null)
|
if(s.Marked && s.VisualSector != null)
|
||||||
{
|
{
|
||||||
if(vs.Key.IsDisposed || vs.Key.Marked)
|
s.VisualSector.Dispose();
|
||||||
vs.Value.Dispose();
|
s.VisualSector = null;
|
||||||
else
|
|
||||||
newsectors.Add(vs.Key, vs.Value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Things depend on the sector they are in and because we can't
|
// Things depend on the sector they are in and because we can't
|
||||||
// easily determine which ones changed, we dispose all things
|
// easily determine which ones changed, we dispose all things
|
||||||
foreach(KeyValuePair<Thing, VisualThing> vt in allthings)
|
foreach (Thing thing in General.Map.Map.Things)
|
||||||
if(vt.Value != null) vt.Value.Dispose();
|
{
|
||||||
|
if (thing.VisualThing != null)
|
||||||
// Apply new lists
|
{
|
||||||
allsectors = newsectors;
|
thing.VisualThing.Dispose();
|
||||||
allthings = new Dictionary<Thing, VisualThing>(allthings.Count);
|
thing.VisualThing = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Clear visibility collections
|
// Clear visibility collections
|
||||||
visiblesectors.Clear();
|
visiblesectors.Clear();
|
||||||
visibleblocks.Clear();
|
visibleblocks.Clear();
|
||||||
|
@ -982,14 +991,14 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public VisualSector GetVisualSector(Sector s)
|
public VisualSector GetVisualSector(Sector s)
|
||||||
{
|
{
|
||||||
if(!allsectors.ContainsKey(s)) return CreateVisualSector(s); //mxd
|
if(s.VisualSector == null) return CreateVisualSector(s); //mxd
|
||||||
return allsectors[s];
|
return s.VisualSector;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This returns the VisualThing for the given Thing.
|
/// This returns the VisualThing for the given Thing.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public VisualThing GetVisualThing(Thing t) { return allthings[t]; }
|
public VisualThing GetVisualThing(Thing t) { return t.VisualThing; }
|
||||||
|
|
||||||
//mxd
|
//mxd
|
||||||
public List<VisualThing> GetSelectedVisualThings(bool refreshSelection)
|
public List<VisualThing> GetSelectedVisualThings(bool refreshSelection)
|
||||||
|
@ -997,10 +1006,10 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
if(refreshSelection || selectedVisualThings == null)
|
if(refreshSelection || selectedVisualThings == null)
|
||||||
{
|
{
|
||||||
selectedVisualThings = new List<VisualThing>();
|
selectedVisualThings = new List<VisualThing>();
|
||||||
foreach(KeyValuePair<Thing, VisualThing> group in allthings)
|
foreach(Thing t in General.Map.Map.Things)
|
||||||
{
|
{
|
||||||
if(group.Value != null && group.Value.Selected)
|
if(t.VisualThing != null && t.VisualThing.Selected)
|
||||||
selectedVisualThings.Add(group.Value);
|
selectedVisualThings.Add(t.VisualThing);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if nothing is selected - try to get thing from hilighted object
|
//if nothing is selected - try to get thing from hilighted object
|
||||||
|
@ -1028,13 +1037,13 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
if(refreshSelection || selectedVisualSectors == null)
|
if(refreshSelection || selectedVisualSectors == null)
|
||||||
{
|
{
|
||||||
selectedVisualSectors = new List<VisualSector>();
|
selectedVisualSectors = new List<VisualSector>();
|
||||||
foreach(KeyValuePair<Sector, VisualSector> group in allsectors)
|
foreach(Sector s in General.Map.Map.Sectors.Where(x => x.VisualSector != null))
|
||||||
{
|
{
|
||||||
foreach(VisualGeometry vg in group.Value.AllGeometry)
|
foreach(VisualGeometry vg in s.VisualSector.AllGeometry)
|
||||||
{
|
{
|
||||||
if(vg.Selected)
|
if(vg.Selected)
|
||||||
{
|
{
|
||||||
selectedVisualSectors.Add(group.Value);
|
selectedVisualSectors.Add(s.VisualSector);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1056,9 +1065,9 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
public List<VisualGeometry> GetSelectedSurfaces()
|
public List<VisualGeometry> GetSelectedSurfaces()
|
||||||
{
|
{
|
||||||
List<VisualGeometry> selectedSurfaces = new List<VisualGeometry>();
|
List<VisualGeometry> selectedSurfaces = new List<VisualGeometry>();
|
||||||
foreach(KeyValuePair<Sector, VisualSector> group in allsectors)
|
foreach(Sector s in General.Map.Map.Sectors.Where(x => x.VisualSector != null))
|
||||||
{
|
{
|
||||||
foreach(VisualGeometry vg in group.Value.AllGeometry)
|
foreach(VisualGeometry vg in s.VisualSector.AllGeometry)
|
||||||
{
|
{
|
||||||
if(vg.Selected) selectedSurfaces.Add(vg);
|
if(vg.Selected) selectedSurfaces.Add(vg);
|
||||||
}
|
}
|
||||||
|
@ -1092,12 +1101,12 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns True when a VisualSector has been created for the specified Sector.
|
/// Returns True when a VisualSector has been created for the specified Sector.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool VisualSectorExists(Sector s) { return allsectors.ContainsKey(s) && (allsectors[s] != null); }
|
public bool VisualSectorExists(Sector s) { return s.VisualSector != null; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns True when a VisualThing has been created for the specified Thing.
|
/// Returns True when a VisualThing has been created for the specified Thing.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool VisualThingExists(Thing t) { return allthings.ContainsKey(t) && (allthings[t] != null); }
|
public bool VisualThingExists(Thing t) { return t.VisualThing != null; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is called when the blockmap needs to be refilled, because it was invalidated.
|
/// This is called when the blockmap needs to be refilled, because it was invalidated.
|
||||||
|
|
|
@ -36,7 +36,6 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
// Geometry
|
// Geometry
|
||||||
private readonly List<VisualGeometry> fixedgeometry;
|
private readonly List<VisualGeometry> fixedgeometry;
|
||||||
private readonly List<VisualGeometry> allgeometry;
|
private readonly List<VisualGeometry> allgeometry;
|
||||||
private readonly Dictionary<Sidedef, List<VisualGeometry>> sidedefgeometry;
|
|
||||||
private VertexBuffer geobuffer;
|
private VertexBuffer geobuffer;
|
||||||
private bool updategeo;
|
private bool updategeo;
|
||||||
|
|
||||||
|
@ -69,7 +68,6 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
this.sector = s;
|
this.sector = s;
|
||||||
allgeometry = new List<VisualGeometry>();
|
allgeometry = new List<VisualGeometry>();
|
||||||
fixedgeometry = new List<VisualGeometry>();
|
fixedgeometry = new List<VisualGeometry>();
|
||||||
sidedefgeometry = new Dictionary<Sidedef, List<VisualGeometry>>();
|
|
||||||
this.sector.UpdateFogColor(); //mxd
|
this.sector.UpdateFogColor(); //mxd
|
||||||
|
|
||||||
// Register as resource
|
// Register as resource
|
||||||
|
@ -168,9 +166,9 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
allgeometry.Add(geo);
|
allgeometry.Add(geo);
|
||||||
if(geo.Sidedef != null)
|
if(geo.Sidedef != null)
|
||||||
{
|
{
|
||||||
if(!sidedefgeometry.ContainsKey(geo.Sidedef))
|
if(geo.Sidedef.VisualGeometry == null)
|
||||||
sidedefgeometry[geo.Sidedef] = new List<VisualGeometry>(3);
|
geo.Sidedef.VisualGeometry = new List<VisualGeometry>(3);
|
||||||
sidedefgeometry[geo.Sidedef].Add(geo);
|
geo.Sidedef.VisualGeometry.Add(geo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -185,14 +183,13 @@ namespace CodeImp.DoomBuilder.VisualModes
|
||||||
{
|
{
|
||||||
allgeometry.Clear();
|
allgeometry.Clear();
|
||||||
fixedgeometry.Clear();
|
fixedgeometry.Clear();
|
||||||
sidedefgeometry.Clear();
|
|
||||||
updategeo = true;
|
updategeo = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This gets the geometry list for the specified sidedef
|
// This gets the geometry list for the specified sidedef
|
||||||
public List<VisualGeometry> GetSidedefGeometry(Sidedef sd)
|
public List<VisualGeometry> GetSidedefGeometry(Sidedef sd)
|
||||||
{
|
{
|
||||||
if(sidedefgeometry.ContainsKey(sd)) return sidedefgeometry[sd];
|
if(sd.VisualGeometry != null) return sd.VisualGeometry;
|
||||||
return new List<VisualGeometry>();
|
return new List<VisualGeometry>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,9 +25,18 @@
|
||||||
|
|
||||||
GLIndexBuffer::~GLIndexBuffer()
|
GLIndexBuffer::~GLIndexBuffer()
|
||||||
{
|
{
|
||||||
if (Device && mBuffer != 0)
|
Finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLIndexBuffer::Finalize()
|
||||||
|
{
|
||||||
|
if (Device)
|
||||||
{
|
{
|
||||||
glDeleteBuffers(1, &mBuffer);
|
Device->mIndexBuffers.erase(ItBuffer);
|
||||||
|
Device = nullptr;
|
||||||
|
|
||||||
|
if (mBuffer != 0)
|
||||||
|
glDeleteBuffers(1, &mBuffer);
|
||||||
mBuffer = 0;
|
mBuffer = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../Backend.h"
|
#include "../Backend.h"
|
||||||
|
#include <list>
|
||||||
|
|
||||||
class GLRenderDevice;
|
class GLRenderDevice;
|
||||||
|
|
||||||
|
@ -30,9 +31,12 @@ class GLIndexBuffer : public IndexBuffer
|
||||||
public:
|
public:
|
||||||
~GLIndexBuffer();
|
~GLIndexBuffer();
|
||||||
|
|
||||||
|
void Finalize();
|
||||||
|
|
||||||
GLuint GetBuffer();
|
GLuint GetBuffer();
|
||||||
|
|
||||||
GLRenderDevice* Device = nullptr;
|
GLRenderDevice* Device = nullptr;
|
||||||
|
std::list<GLIndexBuffer*>::iterator ItBuffer;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLuint mBuffer = 0;
|
GLuint mBuffer = 0;
|
||||||
|
|
|
@ -83,15 +83,17 @@ GLRenderDevice::~GLRenderDevice()
|
||||||
Context->MakeCurrent();
|
Context->MakeCurrent();
|
||||||
|
|
||||||
ProcessDeleteList();
|
ProcessDeleteList();
|
||||||
|
for (GLTexture* tex : mTextures) mDeleteList.Textures.push_back(tex);
|
||||||
|
for (GLIndexBuffer* buffer : mIndexBuffers) mDeleteList.IndexBuffers.push_back(buffer);
|
||||||
|
for (GLVertexBuffer* buffer : mSharedVertexBuffers[0]->VertexBuffers) mDeleteList.VertexBuffers.push_back(buffer);
|
||||||
|
for (GLVertexBuffer* buffer : mSharedVertexBuffers[1]->VertexBuffers) mDeleteList.VertexBuffers.push_back(buffer);
|
||||||
|
ProcessDeleteList(true);
|
||||||
|
|
||||||
glDeleteBuffers(1, &mStreamVertexBuffer);
|
glDeleteBuffers(1, &mStreamVertexBuffer);
|
||||||
glDeleteVertexArrays(1, &mStreamVAO);
|
glDeleteVertexArrays(1, &mStreamVAO);
|
||||||
|
|
||||||
for (auto& sharedbuf : mSharedVertexBuffers)
|
for (auto& sharedbuf : mSharedVertexBuffers)
|
||||||
{
|
{
|
||||||
for (GLVertexBuffer* buf : sharedbuf->VertexBuffers)
|
|
||||||
buf->Device = nullptr;
|
|
||||||
|
|
||||||
GLuint handle = sharedbuf->GetBuffer();
|
GLuint handle = sharedbuf->GetBuffer();
|
||||||
glDeleteBuffers(1, &handle);
|
glDeleteBuffers(1, &handle);
|
||||||
handle = sharedbuf->GetVAO();
|
handle = sharedbuf->GetVAO();
|
||||||
|
@ -107,6 +109,7 @@ GLRenderDevice::~GLRenderDevice()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mShaderManager->ReleaseResources();
|
mShaderManager->ReleaseResources();
|
||||||
Context->ClearCurrent();
|
Context->ClearCurrent();
|
||||||
}
|
}
|
||||||
|
@ -279,7 +282,7 @@ GLint GLRenderDevice::GetGLMinFilter(TextureFilter filter, TextureFilter mipfilt
|
||||||
if (mipfilter == TextureFilter::Linear)
|
if (mipfilter == TextureFilter::Linear)
|
||||||
{
|
{
|
||||||
if (filter == TextureFilter::Point || filter == TextureFilter::None)
|
if (filter == TextureFilter::Point || filter == TextureFilter::None)
|
||||||
return GL_LINEAR_MIPMAP_NEAREST;
|
return GL_NEAREST_MIPMAP_LINEAR;
|
||||||
else
|
else
|
||||||
return GL_LINEAR_MIPMAP_LINEAR;
|
return GL_LINEAR_MIPMAP_LINEAR;
|
||||||
}
|
}
|
||||||
|
@ -288,7 +291,7 @@ GLint GLRenderDevice::GetGLMinFilter(TextureFilter filter, TextureFilter mipfilt
|
||||||
if (filter == TextureFilter::Point || filter == TextureFilter::None)
|
if (filter == TextureFilter::Point || filter == TextureFilter::None)
|
||||||
return GL_NEAREST_MIPMAP_NEAREST;
|
return GL_NEAREST_MIPMAP_NEAREST;
|
||||||
else
|
else
|
||||||
return GL_NEAREST_MIPMAP_LINEAR;
|
return GL_LINEAR_MIPMAP_NEAREST;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -584,6 +587,11 @@ bool GLRenderDevice::SetIndexBufferData(IndexBuffer* ibuffer, void* data, int64_
|
||||||
{
|
{
|
||||||
CheckContext();
|
CheckContext();
|
||||||
GLIndexBuffer* buffer = static_cast<GLIndexBuffer*>(ibuffer);
|
GLIndexBuffer* buffer = static_cast<GLIndexBuffer*>(ibuffer);
|
||||||
|
if (buffer->Device == nullptr)
|
||||||
|
{
|
||||||
|
buffer->ItBuffer = mIndexBuffers.insert(mIndexBuffers.end(), buffer);
|
||||||
|
buffer->Device = this;
|
||||||
|
}
|
||||||
GLint oldbinding = 0;
|
GLint oldbinding = 0;
|
||||||
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &oldbinding);
|
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &oldbinding);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->GetBuffer());
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->GetBuffer());
|
||||||
|
@ -906,6 +914,8 @@ bool GLRenderDevice::ApplyTextures()
|
||||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_S, wrapMode[(int)mTextureUnit.WrapMode]);
|
glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_S, wrapMode[(int)mTextureUnit.WrapMode]);
|
||||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_T, wrapMode[(int)mTextureUnit.WrapMode]);
|
glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_T, wrapMode[(int)mTextureUnit.WrapMode]);
|
||||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_R, wrapMode[(int)mTextureUnit.WrapMode]);
|
glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_R, wrapMode[(int)mTextureUnit.WrapMode]);
|
||||||
|
if (mSamplerFilterKey.MaxAnisotropy > 0.0f)
|
||||||
|
glSamplerParameterf(samplerHandle, GL_TEXTURE_MAX_ANISOTROPY_EXT, mSamplerFilterKey.MaxAnisotropy);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mTextureUnit.SamplerHandle != samplerHandle)
|
if (mTextureUnit.SamplerHandle != samplerHandle)
|
||||||
|
@ -957,12 +967,23 @@ void GLRenderDevice::DeleteObject(GLTexture* texture)
|
||||||
delete texture;
|
delete texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLRenderDevice::ProcessDeleteList()
|
void GLRenderDevice::ProcessDeleteList(bool finalize)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(GLRenderDevice::GetMutex());
|
std::unique_lock<std::mutex> lock(GLRenderDevice::GetMutex());
|
||||||
for (auto buffer : mDeleteList.IndexBuffers) delete buffer;
|
|
||||||
for (auto buffer : mDeleteList.VertexBuffers) delete buffer;
|
if (!finalize)
|
||||||
for (auto texture : mDeleteList.Textures) delete texture;
|
{
|
||||||
|
for (auto buffer : mDeleteList.IndexBuffers) delete buffer;
|
||||||
|
for (auto buffer : mDeleteList.VertexBuffers) delete buffer;
|
||||||
|
for (auto texture : mDeleteList.Textures) delete texture;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (auto buffer : mDeleteList.IndexBuffers) buffer->Finalize();
|
||||||
|
for (auto buffer : mDeleteList.VertexBuffers) buffer->Finalize();
|
||||||
|
for (auto texture : mDeleteList.Textures) texture->Finalize();
|
||||||
|
}
|
||||||
|
|
||||||
mDeleteList.IndexBuffers.clear();
|
mDeleteList.IndexBuffers.clear();
|
||||||
mDeleteList.VertexBuffers.clear();
|
mDeleteList.VertexBuffers.clear();
|
||||||
mDeleteList.Textures.clear();
|
mDeleteList.Textures.clear();
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "../Backend.h"
|
#include "../Backend.h"
|
||||||
#include "OpenGLContext.h"
|
#include "OpenGLContext.h"
|
||||||
|
#include <list>
|
||||||
|
|
||||||
class GLSharedVertexBuffer;
|
class GLSharedVertexBuffer;
|
||||||
class GLShader;
|
class GLShader;
|
||||||
|
@ -105,7 +106,7 @@ public:
|
||||||
static void DeleteObject(GLIndexBuffer* buffer);
|
static void DeleteObject(GLIndexBuffer* buffer);
|
||||||
static void DeleteObject(GLTexture* texture);
|
static void DeleteObject(GLTexture* texture);
|
||||||
|
|
||||||
void ProcessDeleteList();
|
void ProcessDeleteList(bool finalize = false);
|
||||||
|
|
||||||
std::unique_ptr<IOpenGLContext> Context;
|
std::unique_ptr<IOpenGLContext> Context;
|
||||||
|
|
||||||
|
@ -150,6 +151,9 @@ public:
|
||||||
|
|
||||||
std::unique_ptr<GLSharedVertexBuffer> mSharedVertexBuffers[2];
|
std::unique_ptr<GLSharedVertexBuffer> mSharedVertexBuffers[2];
|
||||||
|
|
||||||
|
std::list<GLTexture*> mTextures;
|
||||||
|
std::list<GLIndexBuffer*> mIndexBuffers;
|
||||||
|
|
||||||
std::unique_ptr<GLShaderManager> mShaderManager;
|
std::unique_ptr<GLShaderManager> mShaderManager;
|
||||||
ShaderName mShaderName = {};
|
ShaderName mShaderName = {};
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,11 @@ GLTexture::GLTexture()
|
||||||
}
|
}
|
||||||
|
|
||||||
GLTexture::~GLTexture()
|
GLTexture::~GLTexture()
|
||||||
|
{
|
||||||
|
Finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLTexture::Finalize()
|
||||||
{
|
{
|
||||||
if (Device)
|
if (Device)
|
||||||
Invalidate();
|
Invalidate();
|
||||||
|
@ -120,6 +125,7 @@ void GLTexture::Invalidate()
|
||||||
mFramebuffer = 0;
|
mFramebuffer = 0;
|
||||||
mTexture = 0;
|
mTexture = 0;
|
||||||
mPBO = 0;
|
mPBO = 0;
|
||||||
|
if (Device) Device->mTextures.erase(ItTexture);
|
||||||
Device = nullptr;
|
Device = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +133,11 @@ GLuint GLTexture::GetTexture(GLRenderDevice* device)
|
||||||
{
|
{
|
||||||
if (mTexture == 0)
|
if (mTexture == 0)
|
||||||
{
|
{
|
||||||
Device = device;
|
if (Device == nullptr)
|
||||||
|
{
|
||||||
|
Device = device;
|
||||||
|
ItTexture = Device->mTextures.insert(Device->mTextures.end(), this);
|
||||||
|
}
|
||||||
|
|
||||||
GLint oldActiveTex = GL_TEXTURE0;
|
GLint oldActiveTex = GL_TEXTURE0;
|
||||||
glGetIntegerv(GL_ACTIVE_TEXTURE, &oldActiveTex);
|
glGetIntegerv(GL_ACTIVE_TEXTURE, &oldActiveTex);
|
||||||
|
@ -174,7 +184,7 @@ GLuint GLTexture::GetFramebuffer(GLRenderDevice* device, bool usedepthbuffer)
|
||||||
{
|
{
|
||||||
if (mFramebuffer == 0)
|
if (mFramebuffer == 0)
|
||||||
{
|
{
|
||||||
GLuint texture = GetTexture(Device);
|
GLuint texture = GetTexture(device);
|
||||||
glGenFramebuffers(1, &mFramebuffer);
|
glGenFramebuffers(1, &mFramebuffer);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
|
||||||
|
@ -187,7 +197,11 @@ GLuint GLTexture::GetFramebuffer(GLRenderDevice* device, bool usedepthbuffer)
|
||||||
{
|
{
|
||||||
if (mDepthRenderbuffer == 0)
|
if (mDepthRenderbuffer == 0)
|
||||||
{
|
{
|
||||||
Device = device;
|
if (Device == nullptr)
|
||||||
|
{
|
||||||
|
Device = device;
|
||||||
|
ItTexture = Device->mTextures.insert(Device->mTextures.end(), this);
|
||||||
|
}
|
||||||
|
|
||||||
glGenRenderbuffers(1, &mDepthRenderbuffer);
|
glGenRenderbuffers(1, &mDepthRenderbuffer);
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, mDepthRenderbuffer);
|
glBindRenderbuffer(GL_RENDERBUFFER, mDepthRenderbuffer);
|
||||||
|
@ -197,7 +211,7 @@ GLuint GLTexture::GetFramebuffer(GLRenderDevice* device, bool usedepthbuffer)
|
||||||
|
|
||||||
if (mFramebuffer == 0)
|
if (mFramebuffer == 0)
|
||||||
{
|
{
|
||||||
GLuint texture = GetTexture(Device);
|
GLuint texture = GetTexture(device);
|
||||||
glGenFramebuffers(1, &mFramebuffer);
|
glGenFramebuffers(1, &mFramebuffer);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
|
||||||
|
@ -214,7 +228,11 @@ GLuint GLTexture::GetPBO(GLRenderDevice* device)
|
||||||
{
|
{
|
||||||
if (mPBO == 0)
|
if (mPBO == 0)
|
||||||
{
|
{
|
||||||
Device = device;
|
if (Device == nullptr)
|
||||||
|
{
|
||||||
|
Device = device;
|
||||||
|
ItTexture = Device->mTextures.insert(Device->mTextures.end(), this);
|
||||||
|
}
|
||||||
|
|
||||||
glGenBuffers(1, &mPBO);
|
glGenBuffers(1, &mPBO);
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../Backend.h"
|
#include "../Backend.h"
|
||||||
|
#include <list>
|
||||||
|
|
||||||
class GLRenderDevice;
|
class GLRenderDevice;
|
||||||
|
|
||||||
|
@ -31,6 +32,8 @@ public:
|
||||||
GLTexture();
|
GLTexture();
|
||||||
~GLTexture();
|
~GLTexture();
|
||||||
|
|
||||||
|
void Finalize();
|
||||||
|
|
||||||
void Set2DImage(int width, int height) override;
|
void Set2DImage(int width, int height) override;
|
||||||
void SetCubeImage(int size) override;
|
void SetCubeImage(int size) override;
|
||||||
|
|
||||||
|
@ -49,6 +52,7 @@ public:
|
||||||
GLuint GetPBO(GLRenderDevice* device);
|
GLuint GetPBO(GLRenderDevice* device);
|
||||||
|
|
||||||
GLRenderDevice* Device = nullptr;
|
GLRenderDevice* Device = nullptr;
|
||||||
|
std::list<GLTexture*>::iterator ItTexture;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int mWidth = 0;
|
int mWidth = 0;
|
||||||
|
|
|
@ -72,6 +72,11 @@ void GLSharedVertexBuffer::SetupWorldVAO()
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
GLVertexBuffer::~GLVertexBuffer()
|
GLVertexBuffer::~GLVertexBuffer()
|
||||||
|
{
|
||||||
|
Finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLVertexBuffer::Finalize()
|
||||||
{
|
{
|
||||||
if (Device)
|
if (Device)
|
||||||
{
|
{
|
||||||
|
|
|
@ -56,6 +56,8 @@ class GLVertexBuffer : public VertexBuffer
|
||||||
public:
|
public:
|
||||||
~GLVertexBuffer();
|
~GLVertexBuffer();
|
||||||
|
|
||||||
|
void Finalize();
|
||||||
|
|
||||||
VertexFormat Format = VertexFormat::Flat;
|
VertexFormat Format = VertexFormat::Flat;
|
||||||
|
|
||||||
GLRenderDevice* Device = nullptr;
|
GLRenderDevice* Device = nullptr;
|
||||||
|
|
|
@ -600,15 +600,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
// Get nearby things
|
// Get nearby things
|
||||||
List<Thing> neighbours = new List<Thing>();
|
List<Thing> neighbours = new List<Thing>();
|
||||||
RectangleF bbox = new RectangleF(thing.Position.x - thing.Size, thing.Position.y - thing.Size, thing.Size * 2, thing.Size * 2);
|
RectangleF bbox = new RectangleF(thing.Position.x - thing.Size, thing.Position.y - thing.Size, thing.Size * 2, thing.Size * 2);
|
||||||
Point p1 = mode.BlockMap.GetBlockCoordinates(new Vector2D(bbox.Left, bbox.Top));
|
foreach (var block in mode.BlockMap.GetBlocks(bbox))
|
||||||
Point p2 = mode.BlockMap.GetBlockCoordinates(new Vector2D(bbox.Right, bbox.Bottom));
|
{
|
||||||
for(int x = p1.X; x <= p2.X; x++)
|
neighbours.AddRange(block.Things);
|
||||||
{
|
}
|
||||||
for(int y = p1.Y; y <= p2.Y; y++)
|
|
||||||
{
|
|
||||||
neighbours.AddRange(mode.BlockMap.GetBlock(new Point(x, y)).Things);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect things intersecting with target thing
|
// Collect things intersecting with target thing
|
||||||
List<Thing> intersectingthings = new List<Thing>();
|
List<Thing> intersectingthings = new List<Thing>();
|
||||||
|
|
|
@ -31,6 +31,8 @@ using CodeImp.DoomBuilder.Config;
|
||||||
using CodeImp.DoomBuilder.GZBuilder.Data;
|
using CodeImp.DoomBuilder.GZBuilder.Data;
|
||||||
using CodeImp.DoomBuilder.Types;
|
using CodeImp.DoomBuilder.Types;
|
||||||
using CodeImp.DoomBuilder.Data;
|
using CodeImp.DoomBuilder.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -289,9 +291,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
General.Interface.DisplayStatus(StatusType.Action, actionresult.displaystatus);
|
General.Interface.DisplayStatus(StatusType.Action, actionresult.displaystatus);
|
||||||
|
|
||||||
// Reset changed flags
|
// Reset changed flags
|
||||||
foreach(KeyValuePair<Sector, VisualSector> vs in allsectors)
|
foreach(Sector s in General.Map.Map.Sectors.Where(x => x.VisualSector != null))
|
||||||
{
|
{
|
||||||
BaseVisualSector bvs = (BaseVisualSector)vs.Value;
|
BaseVisualSector bvs = (BaseVisualSector)s.VisualSector;
|
||||||
foreach(VisualFloor vf in bvs.ExtraFloors) vf.Changed = false;
|
foreach(VisualFloor vf in bvs.ExtraFloors) vf.Changed = false;
|
||||||
foreach(VisualCeiling vc in bvs.ExtraCeilings) vc.Changed = false;
|
foreach(VisualCeiling vc in bvs.ExtraCeilings) vc.Changed = false;
|
||||||
foreach(VisualFloor vf in bvs.ExtraBackFloors) vf.Changed = false; //mxd
|
foreach(VisualFloor vf in bvs.ExtraBackFloors) vf.Changed = false; //mxd
|
||||||
|
@ -348,31 +350,25 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
{
|
{
|
||||||
// Make list of selected objects
|
// Make list of selected objects
|
||||||
selectedobjects = new List<IVisualEventReceiver>();
|
selectedobjects = new List<IVisualEventReceiver>();
|
||||||
foreach(KeyValuePair<Sector, VisualSector> vs in allsectors)
|
foreach(Sector s in General.Map.Map.Sectors.Where(x => x.VisualSector != null))
|
||||||
{
|
{
|
||||||
if(vs.Value != null)
|
BaseVisualSector bvs = (BaseVisualSector)s.VisualSector;
|
||||||
|
if((bvs.Floor != null) && bvs.Floor.Selected) selectedobjects.Add(bvs.Floor);
|
||||||
|
if((bvs.Ceiling != null) && bvs.Ceiling.Selected) selectedobjects.Add(bvs.Ceiling);
|
||||||
|
foreach(Sidedef sd in s.Sidedefs)
|
||||||
{
|
{
|
||||||
BaseVisualSector bvs = (BaseVisualSector)vs.Value;
|
List<VisualGeometry> sidedefgeos = bvs.GetSidedefGeometry(sd);
|
||||||
if((bvs.Floor != null) && bvs.Floor.Selected) selectedobjects.Add(bvs.Floor);
|
foreach(VisualGeometry sdg in sidedefgeos)
|
||||||
if((bvs.Ceiling != null) && bvs.Ceiling.Selected) selectedobjects.Add(bvs.Ceiling);
|
|
||||||
foreach(Sidedef sd in vs.Key.Sidedefs)
|
|
||||||
{
|
{
|
||||||
List<VisualGeometry> sidedefgeos = bvs.GetSidedefGeometry(sd);
|
if(sdg.Selected) selectedobjects.Add((IVisualEventReceiver)sdg);
|
||||||
foreach(VisualGeometry sdg in sidedefgeos)
|
|
||||||
{
|
|
||||||
if(sdg.Selected) selectedobjects.Add((IVisualEventReceiver)sdg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(KeyValuePair<Thing, VisualThing> vt in allthings)
|
foreach(Thing t in General.Map.Map.Things.Where(x => x.VisualThing != null))
|
||||||
{
|
{
|
||||||
if(vt.Value != null)
|
BaseVisualThing bvt = (BaseVisualThing)t.VisualThing;
|
||||||
{
|
if(bvt.Selected) selectedobjects.Add(bvt);
|
||||||
BaseVisualThing bvt = (BaseVisualThing)vt.Value;
|
|
||||||
if(bvt.Selected) selectedobjects.Add(bvt);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//mxd
|
//mxd
|
||||||
|
@ -395,7 +391,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
internal BaseVisualSector CreateBaseVisualSector(Sector s)
|
internal BaseVisualSector CreateBaseVisualSector(Sector s)
|
||||||
{
|
{
|
||||||
BaseVisualSector vs = new BaseVisualSector(this, s);
|
BaseVisualSector vs = new BaseVisualSector(this, s);
|
||||||
allsectors.Add(s, vs);
|
s.VisualSector = vs;
|
||||||
return vs;
|
return vs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,7 +399,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
protected override VisualSector CreateVisualSector(Sector s)
|
protected override VisualSector CreateVisualSector(Sector s)
|
||||||
{
|
{
|
||||||
BaseVisualSector vs = new BaseVisualSector(this, s);
|
BaseVisualSector vs = new BaseVisualSector(this, s);
|
||||||
allsectors.Add(s, vs); //mxd
|
s.VisualSector = vs; //mxd
|
||||||
return vs;
|
return vs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,22 +498,16 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
// This updates the VisualSectors and VisualThings that have their Changed property set
|
// This updates the VisualSectors and VisualThings that have their Changed property set
|
||||||
private void UpdateChangedObjects()
|
private void UpdateChangedObjects()
|
||||||
{
|
{
|
||||||
foreach(KeyValuePair<Sector, VisualSector> vs in allsectors)
|
foreach(Sector s in General.Map.Map.Sectors.Where(x => x.VisualSector != null))
|
||||||
{
|
{
|
||||||
if(vs.Value != null)
|
BaseVisualSector bvs = (BaseVisualSector)s.VisualSector;
|
||||||
{
|
if(bvs.Changed) bvs.Rebuild();
|
||||||
BaseVisualSector bvs = (BaseVisualSector)vs.Value;
|
|
||||||
if(bvs.Changed) bvs.Rebuild();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(KeyValuePair<Thing, VisualThing> vt in allthings)
|
foreach(Thing t in General.Map.Map.Things.Where(x => x.VisualThing != null))
|
||||||
{
|
{
|
||||||
if(vt.Value != null)
|
BaseVisualThing bvt = (BaseVisualThing)t.VisualThing;
|
||||||
{
|
if(bvt.Changed) bvt.Rebuild();
|
||||||
BaseVisualThing bvt = (BaseVisualThing)vt.Value;
|
|
||||||
if(bvt.Changed) bvt.Rebuild();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//mxd
|
//mxd
|
||||||
|
@ -1036,19 +1026,21 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
{
|
{
|
||||||
Vertex v = sd.IsFront ? sd.Line.End : sd.Line.Start;
|
Vertex v = sd.IsFront ? sd.Line.End : sd.Line.Start;
|
||||||
|
|
||||||
// Check if a thing is at this vertex
|
// Check if a thing is at this vertex
|
||||||
VisualBlockEntry b = blockmap.GetBlock(blockmap.GetBlockCoordinates(v.Position));
|
foreach (VisualBlockEntry block in blockmap.GetBlocks(v.Position))
|
||||||
foreach (Thing t in b.Things)
|
{
|
||||||
{
|
foreach (Thing t in block.Things)
|
||||||
if ((Vector2D)t.Position == v.Position)
|
{
|
||||||
{
|
if ((Vector2D)t.Position == v.Position)
|
||||||
switch (t.Type)
|
{
|
||||||
{
|
switch (t.Type)
|
||||||
case 1504: slopefloorthings.Add(t); break;
|
{
|
||||||
case 1505: slopeceilingthings.Add(t); break;
|
case 1504: slopefloorthings.Add(t); break;
|
||||||
}
|
case 1505: slopeceilingthings.Add(t); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Slope any floor vertices?
|
// Slope any floor vertices?
|
||||||
|
@ -1448,31 +1440,27 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
// No sectors or geometry changed. So we only have
|
// No sectors or geometry changed. So we only have
|
||||||
// to update things when they have changed.
|
// to update things when they have changed.
|
||||||
HashSet<Thing> toremove = new HashSet<Thing>(); //mxd
|
HashSet<Thing> toremove = new HashSet<Thing>(); //mxd
|
||||||
foreach(KeyValuePair<Thing, VisualThing> vt in allthings)
|
foreach(Thing t in General.Map.Map.Things.Where(x => x.VisualThing != null && x.Marked))
|
||||||
{
|
{
|
||||||
if((vt.Value != null) && vt.Key.Marked)
|
if(t.IsDisposed) toremove.Add(t); //mxd. Disposed things will cause problems
|
||||||
{
|
else ((BaseVisualThing)t.VisualThing).Rebuild();
|
||||||
if(vt.Key.IsDisposed) toremove.Add(vt.Key); //mxd. Disposed things will cause problems
|
|
||||||
else ((BaseVisualThing)vt.Value).Rebuild();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//mxd. Remove disposed things
|
//mxd. Remove disposed things
|
||||||
foreach(Thing t in toremove)
|
foreach(Thing t in toremove)
|
||||||
{
|
{
|
||||||
if(allthings[t] != null) allthings[t].Dispose();
|
if(t.VisualThing != null) { t.VisualThing.Dispose(); t.VisualThing = null; }
|
||||||
allthings.Remove(t);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Things depend on the sector they are in and because we can't
|
// Things depend on the sector they are in and because we can't
|
||||||
// easily determine which ones changed, we dispose all things
|
// easily determine which ones changed, we dispose all things
|
||||||
foreach(KeyValuePair<Thing, VisualThing> vt in allthings)
|
foreach(Thing t in General.Map.Map.Things.Where(x => x.VisualThing != null))
|
||||||
if(vt.Value != null) vt.Value.Dispose();
|
{
|
||||||
|
t.VisualThing.Dispose();
|
||||||
// Apply new lists
|
t.VisualThing = null;
|
||||||
allthings = new Dictionary<Thing, VisualThing>(allthings.Count);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear visibility collections
|
// Clear visibility collections
|
||||||
|
@ -1584,12 +1572,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
//mxd
|
//mxd
|
||||||
private void Interface_OnSectorEditFormValuesChanged(object sender, EventArgs e)
|
private void Interface_OnSectorEditFormValuesChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if(allsectors == null) return;
|
|
||||||
|
|
||||||
// Reset changed flags
|
// Reset changed flags
|
||||||
foreach(KeyValuePair<Sector, VisualSector> vs in allsectors)
|
foreach(Sector s in General.Map.Map.Sectors.Where(x => x.VisualSector != null))
|
||||||
{
|
{
|
||||||
BaseVisualSector bvs = (BaseVisualSector)vs.Value;
|
BaseVisualSector bvs = (BaseVisualSector)s.VisualSector;
|
||||||
foreach(VisualFloor vf in bvs.ExtraFloors) vf.Changed = false;
|
foreach(VisualFloor vf in bvs.ExtraFloors) vf.Changed = false;
|
||||||
foreach(VisualCeiling vc in bvs.ExtraCeilings) vc.Changed = false;
|
foreach(VisualCeiling vc in bvs.ExtraCeilings) vc.Changed = false;
|
||||||
foreach(VisualFloor vf in bvs.ExtraBackFloors) vf.Changed = false;
|
foreach(VisualFloor vf in bvs.ExtraBackFloors) vf.Changed = false;
|
||||||
|
@ -2072,41 +2058,35 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
});
|
});
|
||||||
|
|
||||||
//
|
//
|
||||||
foreach (KeyValuePair<Sector, VisualSector> vs in allsectors)
|
foreach (Sector s in General.Map.Map.Sectors.Where(x => x.VisualSector != null))
|
||||||
{
|
{
|
||||||
if (vs.Value != null)
|
BaseVisualSector bvs = (BaseVisualSector)s.VisualSector;
|
||||||
|
if (clearsectors)
|
||||||
{
|
{
|
||||||
BaseVisualSector bvs = (BaseVisualSector)vs.Value;
|
if (bvs.Floor != null) bvs.Floor.Selected = false;
|
||||||
if (clearsectors)
|
if (bvs.Ceiling != null) bvs.Ceiling.Selected = false;
|
||||||
{
|
foreach (VisualFloor vf in bvs.ExtraFloors) vf.Selected = false;
|
||||||
if (bvs.Floor != null) bvs.Floor.Selected = false;
|
foreach (VisualCeiling vc in bvs.ExtraCeilings) vc.Selected = false;
|
||||||
if (bvs.Ceiling != null) bvs.Ceiling.Selected = false;
|
foreach (VisualFloor vf in bvs.ExtraBackFloors) vf.Selected = false; //mxd
|
||||||
foreach (VisualFloor vf in bvs.ExtraFloors) vf.Selected = false;
|
foreach (VisualCeiling vc in bvs.ExtraBackCeilings) vc.Selected = false; //mxd
|
||||||
foreach (VisualCeiling vc in bvs.ExtraCeilings) vc.Selected = false;
|
}
|
||||||
foreach (VisualFloor vf in bvs.ExtraBackFloors) vf.Selected = false; //mxd
|
|
||||||
foreach (VisualCeiling vc in bvs.ExtraBackCeilings) vc.Selected = false; //mxd
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clearsidedefs)
|
if (clearsidedefs)
|
||||||
|
{
|
||||||
|
foreach (Sidedef sd in s.Sidedefs)
|
||||||
{
|
{
|
||||||
foreach (Sidedef sd in vs.Key.Sidedefs)
|
//mxd. VisualSidedefParts can contain references to visual geometry, which is not present in VisualSector.sidedefgeometry
|
||||||
{
|
bvs.GetSidedefParts(sd).DeselectAllParts();
|
||||||
//mxd. VisualSidedefParts can contain references to visual geometry, which is not present in VisualSector.sidedefgeometry
|
|
||||||
bvs.GetSidedefParts(sd).DeselectAllParts();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clearthings)
|
if (clearthings)
|
||||||
{
|
{
|
||||||
foreach (KeyValuePair<Thing, VisualThing> vt in allthings)
|
foreach (Thing t in General.Map.Map.Things.Where(x => x.VisualThing != null))
|
||||||
{
|
{
|
||||||
if (vt.Value != null)
|
BaseVisualThing bvt = (BaseVisualThing)t.VisualThing;
|
||||||
{
|
bvt.Selected = false;
|
||||||
BaseVisualThing bvt = (BaseVisualThing)vt.Value;
|
|
||||||
bvt.Selected = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue