First attempt at rendering polyobject previews.

This commit is contained in:
spherallic 2022-03-05 13:12:25 +01:00
parent 953312482d
commit 2f55a6897a
2 changed files with 388 additions and 244 deletions

View File

@ -68,6 +68,8 @@ namespace CodeImp.DoomBuilder.Rendering
void PlotVerticesSet(ICollection<Vertex> vertices);
void RenderThing(Thing t, PixelColor c, float alpha);
void RenderThingSet(ICollection<Thing> things, float alpha);
void RenderWaypoints();
void RenderPolyobjects();
void RenderNiGHTSPath();
void RenderRectangle(RectangleF rect, float bordersize, PixelColor c, bool transformrect);
void RenderRectangleFilled(RectangleF rect, PixelColor c, bool transformrect);

View File

@ -58,12 +58,12 @@ namespace CodeImp.DoomBuilder.Rendering
private const int FONT_HEIGHT = 0;
internal const int NUM_VIEW_MODES = 4;
#endregion
#endregion
#region ================== Variables
#region ================== Variables
// Rendertargets
private Texture backtex;
// Rendertargets
private Texture backtex;
private Texture plottertex;
private Texture thingstex;
private Texture overlaytex;
@ -124,6 +124,21 @@ namespace CodeImp.DoomBuilder.Rendering
// Presentation
private Presentation present;
// SRB2 stuff
private List<Thing> axes;
private List<Thing> axistransferlines;
private List<Thing> waypoints;
private List<Thing> polyanchors;
private List<Thing> polyspawns;
private List<Linedef> firstlines;
private Vector2D[] starts;
private Vector2D[] ends;
private TextLabel waypointlabel;
private TextLabel spawnlabel;
private TextLabel anchorlabel;
#endregion
#region ================== Properties
@ -156,6 +171,39 @@ namespace CodeImp.DoomBuilder.Rendering
// Create rendertargets
CreateRendertargets();
anchorlabel = new TextLabel(3) // create sequence ID label
{
Text = "0",
AlignX = TextAlignmentX.Center,
AlignY = TextAlignmentY.Middle,
Color = General.Colors.GetNiGHTSColor(8),
Backcolor = General.Colors.Background,
Scale = 16f,
TransformCoords = true
};
spawnlabel = new TextLabel(3) // create sequence ID label
{
Text = "0",
AlignX = TextAlignmentX.Center,
AlignY = TextAlignmentY.Middle,
Color = General.Colors.GetNiGHTSColor(7),
Backcolor = General.Colors.Background,
Scale = 16f,
TransformCoords = true
};
waypointlabel = new TextLabel(3) // create sequence ID label
{
Text = "0",
AlignX = TextAlignmentX.Center,
AlignY = TextAlignmentY.Middle,
Color = General.Colors.WaypointColor,
Backcolor = General.Colors.Background,
Scale = 16f,
TransformCoords = true
};
// We have no destructor
GC.SuppressFinalize(this);
}
@ -164,7 +212,7 @@ namespace CodeImp.DoomBuilder.Rendering
public override void Dispose()
{
// Not already disposed?
if(!isdisposed)
if (!isdisposed)
{
// Destroy rendertargets
DestroyRendertargets();
@ -194,7 +242,7 @@ namespace CodeImp.DoomBuilder.Rendering
General.Plugins.OnPresentDisplayBegin();
// Start drawing
if(graphics.StartRendering(true, General.Colors.Background.ToColorValue(), graphics.BackBuffer, graphics.DepthBuffer))
if (graphics.StartRendering(true, General.Colors.Background.ToColorValue(), graphics.BackBuffer, graphics.DepthBuffer))
{
// Renderstates that count for this whole sequence
graphics.Device.SetRenderState(RenderState.CullMode, Cull.None);
@ -205,12 +253,12 @@ namespace CodeImp.DoomBuilder.Rendering
graphics.Shaders.Display2D.Begin();
// Go for all layers
foreach(PresentLayer layer in present.layers)
foreach (PresentLayer layer in present.layers)
{
int aapass;
// Set blending mode
switch(layer.blending)
switch (layer.blending)
{
case BlendingMode.None:
graphics.Device.SetRenderState(RenderState.AlphaBlendEnable, false);
@ -242,14 +290,14 @@ namespace CodeImp.DoomBuilder.Rendering
}
// Check which pass to use
if(layer.antialiasing && General.Settings.QualityDisplay) aapass = 0; else aapass = 1;
if (layer.antialiasing && General.Settings.QualityDisplay) aapass = 0; else aapass = 1;
// Render layer
switch(layer.layer)
switch (layer.layer)
{
// BACKGROUND
case RendererLayer.Background:
if((backimageverts == null) || (General.Map.Grid.Background.Texture == null)) break;
if ((backimageverts == null) || (General.Map.Grid.Background.Texture == null)) break;
graphics.Device.SetTexture(0, General.Map.Grid.Background.Texture);
graphics.Shaders.Display2D.Texture1 = General.Map.Grid.Background.Texture;
graphics.Shaders.Display2D.SetSettings(1f / windowsize.Width, 1f / windowsize.Height, FSAA_FACTOR, layer.alpha, false);
@ -359,12 +407,12 @@ namespace CodeImp.DoomBuilder.Rendering
public void DestroyRendertargets()
{
// Trash rendertargets
if(plottertex != null) plottertex.Dispose();
if(thingstex != null) thingstex.Dispose();
if(overlaytex != null) overlaytex.Dispose();
if(surfacetex != null) surfacetex.Dispose();
if(backtex != null) backtex.Dispose();
if(screenverts != null) screenverts.Dispose();
if (plottertex != null) plottertex.Dispose();
if (thingstex != null) thingstex.Dispose();
if (overlaytex != null) overlaytex.Dispose();
if (surfacetex != null) surfacetex.Dispose();
if (backtex != null) backtex.Dispose();
if (screenverts != null) screenverts.Dispose();
plottertex = null;
thingstex = null;
backtex = null;
@ -373,13 +421,13 @@ namespace CodeImp.DoomBuilder.Rendering
surfacetex = null;
// Trash things batch buffer
if(thingsvertices != null) thingsvertices.Dispose();
if (thingsvertices != null) thingsvertices.Dispose();
thingsvertices = null;
lastgridscale = -1f;
lastgridsize = 0;
// Trash font
if(font != null) font.Dispose();
if (font != null) font.Dispose();
font = null;
}
@ -513,8 +561,8 @@ namespace CodeImp.DoomBuilder.Rendering
minlinenormallength = linenormalsize * 2f; //mxd
vertexsize = (int)(1.7f * General.Settings.GZVertexScale2D * scale + 0.5f); //mxd. added GZVertexScale2D
if(vertexsize < 0) vertexsize = 0;
if(vertexsize > 4) vertexsize = 4;
if (vertexsize < 0) vertexsize = 0;
if (vertexsize > 4) vertexsize = 4;
Matrix scaling = Matrix.Scaling((1f / windowsize.Width) * 2f, (1f / windowsize.Height) * -2f, 1f);
Matrix translate = Matrix.Translation(-(float)windowsize.Width * 0.5f, -(float)windowsize.Height * 0.5f, 0f);
@ -529,7 +577,7 @@ namespace CodeImp.DoomBuilder.Rendering
// This sets the world matrix for transformation
private void SetWorldTransformation(bool transform)
{
if(transform)
if (transform)
{
Matrix translate = Matrix.Translation(translatex, translatey, 0f);
Matrix scaling = Matrix.Scaling(scale, -scale, 1f);
@ -565,14 +613,14 @@ namespace CodeImp.DoomBuilder.Rendering
public PixelColor DetermineThingColor(Thing t)
{
// Determine color
if(t.Selected) return General.Colors.Selection;
if (t.Selected) return General.Colors.Selection;
//mxd. If thing is light, set it's color to light color:
if(Array.IndexOf(GZBuilder.GZGeneral.GZ_LIGHTS, t.SRB2Type) != -1)
if (Array.IndexOf(GZBuilder.GZGeneral.GZ_LIGHTS, t.SRB2Type) != -1)
{
if(t.SRB2Type == 1502) //vavoom light
if (t.SRB2Type == 1502) //vavoom light
return new PixelColor(255, 255, 255, 255);
if(t.SRB2Type == 1503) //vavoom colored light
if (t.SRB2Type == 1503) //vavoom colored light
return new PixelColor(255, (byte)t.Args[1], (byte)t.Args[2], (byte)t.Args[3]);
return new PixelColor(255, (byte)t.Args[0], (byte)t.Args[1], (byte)t.Args[2]);
}
@ -584,25 +632,25 @@ namespace CodeImp.DoomBuilder.Rendering
public int DetermineVertexColor(Vertex v)
{
// Determine color
if(v.Selected) return ColorCollection.SELECTION;
if (v.Selected) return ColorCollection.SELECTION;
return ColorCollection.VERTICES;
}
// This returns the color for a linedef
public PixelColor DetermineLinedefColor(Linedef l)
{
if(l.Selected) return General.Colors.Selection;
if (l.Selected) return General.Colors.Selection;
//mxd. Impassable lines
if(l.ImpassableFlag)
if (l.ImpassableFlag)
{
if(l.ColorPresetIndex != -1)
if (l.ColorPresetIndex != -1)
return General.Map.ConfigSettings.LinedefColorPresets[l.ColorPresetIndex].Color;
return General.Colors.Linedefs;
}
//mxd. Passable lines
if(l.ColorPresetIndex != -1)
if (l.ColorPresetIndex != -1)
return General.Map.ConfigSettings.LinedefColorPresets[l.ColorPresetIndex].Color.WithAlpha(General.Settings.DoubleSidedAlphaByte);
return General.Colors.Linedefs.WithAlpha(General.Settings.DoubleSidedAlphaByte);
}
@ -613,26 +661,26 @@ namespace CodeImp.DoomBuilder.Rendering
HashSet<int> tags = new HashSet<int>();
//find lines with 3d floor action and collect sector tags
foreach(Linedef l in General.Map.Map.Linedefs)
foreach (Linedef l in General.Map.Map.Linedefs)
{
//MascaraSnake: 3D floor handling
if(l.Is3DFloor)
{
if (!General.Map.FormatInterface.HasLinedefParameters) l.Set3DFloorArgs();
int sectortag = (General.Map.UDMF || (l.Args[1] & 8) != 0) ? l.Args[0] : l.Args[0] + (l.Args[4] << 8);
if(sectortag != 0 && !tags.Contains(sectortag)) tags.Add(sectortag);
//MascaraSnake: 3D floor handling
if (l.Is3DFloor)
{
if (!General.Map.FormatInterface.HasLinedefParameters) l.Set3DFloorArgs();
int sectortag = (General.Map.UDMF || (l.Args[1] & 8) != 0) ? l.Args[0] : l.Args[0] + (l.Args[4] << 8);
if (sectortag != 0 && !tags.Contains(sectortag)) tags.Add(sectortag);
}
}
//find lines, which are related to sectors with 3d floors, and collect their valuable indices
foreach(Linedef l in General.Map.Map.Linedefs)
foreach (Linedef l in General.Map.Map.Linedefs)
{
if(l.Front != null && l.Front.Sector != null && l.Front.Sector.Tag != 0 && tags.Overlaps(l.Front.Sector.Tags))
if (l.Front != null && l.Front.Sector != null && l.Front.Sector.Tag != 0 && tags.Overlaps(l.Front.Sector.Tags))
{
l.ExtraFloorFlag = true;
continue;
}
if(l.Back != null && l.Back.Sector != null && l.Back.Sector.Tag != 0 && tags.Overlaps(l.Back.Sector.Tags))
if (l.Back != null && l.Back.Sector != null && l.Back.Sector.Tag != 0 && tags.Overlaps(l.Back.Sector.Tags))
{
l.ExtraFloorFlag = true;
continue;
@ -649,7 +697,7 @@ namespace CodeImp.DoomBuilder.Rendering
// This begins a drawing session
public unsafe bool StartPlotter(bool clear)
{
if(renderlayer != RenderLayers.None)
if (renderlayer != RenderLayers.None)
{
#if DEBUG
throw new InvalidOperationException("Renderer starting called before finished previous layer. Call Finish() first!");
@ -659,10 +707,10 @@ namespace CodeImp.DoomBuilder.Rendering
}
renderlayer = RenderLayers.Plotter;
try { graphics.Device.SetRenderState(RenderState.FogEnable, false); } catch(Exception) { }
try { graphics.Device.SetRenderState(RenderState.FogEnable, false); } catch (Exception) { }
// Rendertargets available?
if(plottertex != null)
if (plottertex != null)
{
// Lock structures rendertarget memory
plotlocked = plottertex.LockRectangle(0, LockFlags.NoSystemLock);
@ -671,7 +719,7 @@ namespace CodeImp.DoomBuilder.Rendering
plotter = new Plotter((PixelColor*)plotlocked.Data.DataPointer.ToPointer(), plotlocked.Pitch / sizeof(PixelColor), structsize.Height, structsize.Width, structsize.Height);
// Redraw grid when structures image was cleared
if(clear)
if (clear)
{
plotter.Clear();
RenderBackgroundGrid();
@ -691,7 +739,7 @@ namespace CodeImp.DoomBuilder.Rendering
// This begins a drawing session
public bool StartThings(bool clear)
{
if(renderlayer != RenderLayers.None)
if (renderlayer != RenderLayers.None)
{
#if DEBUG
throw new InvalidOperationException("Renderer starting called before finished previous layer. Call Finish() first!");
@ -701,14 +749,14 @@ namespace CodeImp.DoomBuilder.Rendering
}
renderlayer = RenderLayers.Things;
try { graphics.Device.SetRenderState(RenderState.FogEnable, false); } catch(Exception) { }
try { graphics.Device.SetRenderState(RenderState.FogEnable, false); } catch (Exception) { }
// Rendertargets available?
if(thingstex != null)
if (thingstex != null)
{
// Set the rendertarget to the things texture
targetsurface = thingstex.GetSurfaceLevel(0);
if(graphics.StartRendering(clear, General.Colors.Background.WithAlpha(0).ToColorValue(), targetsurface, null))
if (graphics.StartRendering(clear, General.Colors.Background.WithAlpha(0).ToColorValue(), targetsurface, null))
{
// Ready for rendering
UpdateTransformations();
@ -728,7 +776,7 @@ namespace CodeImp.DoomBuilder.Rendering
// This begins a drawing session
public bool StartOverlay(bool clear)
{
if(renderlayer != RenderLayers.None)
if (renderlayer != RenderLayers.None)
{
#if DEBUG
throw new InvalidOperationException("Renderer starting called before finished previous layer. Call Finish() first!");
@ -738,14 +786,14 @@ namespace CodeImp.DoomBuilder.Rendering
}
renderlayer = RenderLayers.Overlay;
try { graphics.Device.SetRenderState(RenderState.FogEnable, false); } catch(Exception) { }
try { graphics.Device.SetRenderState(RenderState.FogEnable, false); } catch (Exception) { }
// Rendertargets available?
if(overlaytex != null)
if (overlaytex != null)
{
// Set the rendertarget to the things texture
targetsurface = overlaytex.GetSurfaceLevel(0);
if(graphics.StartRendering(clear, General.Colors.Background.WithAlpha(0).ToColorValue(), targetsurface, null))
if (graphics.StartRendering(clear, General.Colors.Background.WithAlpha(0).ToColorValue(), targetsurface, null))
{
// Ready for rendering
UpdateTransformations();
@ -766,15 +814,15 @@ namespace CodeImp.DoomBuilder.Rendering
public void Finish()
{
// Clean up plotter
if(renderlayer == RenderLayers.Plotter)
if (renderlayer == RenderLayers.Plotter)
{
if(plottertex != null) plottertex.UnlockRectangle(0);
if(plotlocked.Data != null) plotlocked.Data.Dispose();
if (plottertex != null) plottertex.UnlockRectangle(0);
if (plotlocked.Data != null) plotlocked.Data.Dispose();
plotter = null;
}
// Clean up things / overlay
if((renderlayer == RenderLayers.Things) || (renderlayer == RenderLayers.Overlay) || (renderlayer == RenderLayers.Surface))
if ((renderlayer == RenderLayers.Things) || (renderlayer == RenderLayers.Overlay) || (renderlayer == RenderLayers.Surface))
{
// Stop rendering
graphics.FinishRendering();
@ -785,8 +833,8 @@ namespace CodeImp.DoomBuilder.Rendering
graphics.Device.DepthStencilSurface = graphics.DepthBuffer;
graphics.Device.SetRenderTarget(0, graphics.BackBuffer);
}
catch(Exception) { }
if(targetsurface != null) targetsurface.Dispose();
catch (Exception) { }
if (targetsurface != null) targetsurface.Dispose();
targetsurface = null;
}
@ -802,7 +850,7 @@ namespace CodeImp.DoomBuilder.Rendering
private void SetupBackground()
{
// Only if a background image is set
if((General.Map.Grid.Background != null) && !(General.Map.Grid.Background is UnknownImage))
if ((General.Map.Grid.Background != null) && !(General.Map.Grid.Background is UnknownImage))
{
Vector2D backoffset = new Vector2D(General.Map.Grid.BackgroundX, General.Map.Grid.BackgroundY);
Vector2D backimagesize = new Vector2D(General.Map.Grid.Background.ScaledWidth, General.Map.Grid.Background.ScaledHeight);
@ -844,7 +892,7 @@ namespace CodeImp.DoomBuilder.Rendering
private unsafe void RenderBackgroundGrid()
{
// Do we need to redraw grid?
if((lastgridsize != General.Map.Grid.GridSize) || (lastgridscale != scale) ||
if ((lastgridsize != General.Map.Grid.GridSize) || (lastgridscale != scale) ||
(lastgridx != offsetx) || (lastgridy != offsety))
{
// Lock background rendertarget memory
@ -854,13 +902,13 @@ namespace CodeImp.DoomBuilder.Rendering
Plotter gridplotter = new Plotter((PixelColor*)lockedrect.Data.DataPointer.ToPointer(), lockedrect.Pitch / sizeof(PixelColor), backsize.Height, backsize.Width, backsize.Height);
gridplotter.Clear();
if(General.Settings.RenderGrid) //mxd
if (General.Settings.RenderGrid) //mxd
{
// Render normal grid
RenderGrid(General.Map.Grid.GridSize, General.Colors.Grid, gridplotter);
// Render 64 grid
if(General.Map.Grid.GridSize <= 64) RenderGrid(64f, General.Colors.Grid64, gridplotter);
if (General.Map.Grid.GridSize <= 64) RenderGrid(64f, General.Colors.Grid64, gridplotter);
}
else
{
@ -879,31 +927,31 @@ namespace CodeImp.DoomBuilder.Rendering
int cx = (int)center.x;
int cy = (int)center.y;
PixelColor c = General.Colors.Highlight;
int top, bottom, left, right;
if (General.Settings.DrawFullCrosshair)
{
Vector2D plusCenter = new Vector2D(General.Map.Config.RightBoundary, General.Map.Config.TopBoundary).GetTransformed(translatex, translatey, scale, -scale);
Vector2D minusCenter = new Vector2D(General.Map.Config.LeftBoundary, General.Map.Config.BottomBoundary).GetTransformed(translatex, translatey, scale, -scale);
top = (int)plusCenter.y;
bottom = (int)minusCenter.y;
left = (int)minusCenter.x;
right = (int)plusCenter.x;
}
else
{
top = cy + MAP_CENTER_SIZE;
bottom = cy - MAP_CENTER_SIZE;
left = cx - MAP_CENTER_SIZE;
right = cx + MAP_CENTER_SIZE;
}
if (General.Settings.DrawCrosshair)
{
gridplotter.DrawLineSolid(cx, top, cx, bottom, ref c);
gridplotter.DrawLineSolid(left, cy, right, cy, ref c);
}
int top, bottom, left, right;
if (General.Settings.DrawFullCrosshair)
{
Vector2D plusCenter = new Vector2D(General.Map.Config.RightBoundary, General.Map.Config.TopBoundary).GetTransformed(translatex, translatey, scale, -scale);
Vector2D minusCenter = new Vector2D(General.Map.Config.LeftBoundary, General.Map.Config.BottomBoundary).GetTransformed(translatex, translatey, scale, -scale);
top = (int)plusCenter.y;
bottom = (int)minusCenter.y;
left = (int)minusCenter.x;
right = (int)plusCenter.x;
}
else
{
top = cy + MAP_CENTER_SIZE;
bottom = cy - MAP_CENTER_SIZE;
left = cx - MAP_CENTER_SIZE;
right = cx + MAP_CENTER_SIZE;
}
if (General.Settings.DrawCrosshair)
{
gridplotter.DrawLineSolid(cx, top, cx, bottom, ref c);
gridplotter.DrawLineSolid(left, cy, right, cy, ref c);
}
// Done
backtex.UnlockRectangle(0);
// Done
backtex.UnlockRectangle(0);
lockedrect.Data.Dispose();
lastgridscale = scale;
lastgridsize = General.Map.Grid.GridSize;
@ -918,8 +966,8 @@ namespace CodeImp.DoomBuilder.Rendering
Vector2D pos = new Vector2D();
//mxd. Increase rendered grid size if needed
if(!General.Settings.DynamicGridSize && size * scale <= 6f)
do { size *= 2; } while(size * scale <= 6f);
if (!General.Settings.DynamicGridSize && size * scale <= 6f)
do { size *= 2; } while (size * scale <= 6f);
float sizeinv = 1f / size;
// Determine map coordinates for view window
@ -938,10 +986,10 @@ namespace CodeImp.DoomBuilder.Rendering
float ystart = rbpos.y > General.Map.Config.BottomBoundary ? rbpos.y : General.Map.Config.BottomBoundary;
float yend = ltpos.y < General.Map.Config.TopBoundary ? ltpos.y : General.Map.Config.TopBoundary;
for(float y = ystart; y < yend + size; y += size)
for (float y = ystart; y < yend + size; y += size)
{
if(y > General.Map.Config.TopBoundary) y = General.Map.Config.TopBoundary;
else if(y < General.Map.Config.BottomBoundary) y = General.Map.Config.BottomBoundary;
if (y > General.Map.Config.TopBoundary) y = General.Map.Config.TopBoundary;
else if (y < General.Map.Config.BottomBoundary) y = General.Map.Config.BottomBoundary;
float from = tlb.x < 0 ? 0 : tlb.x;
float to = rbb.x > windowsize.Width ? windowsize.Width : rbb.x;
@ -957,10 +1005,10 @@ namespace CodeImp.DoomBuilder.Rendering
float xstart = ltpos.x > General.Map.Config.LeftBoundary ? ltpos.x : General.Map.Config.LeftBoundary;
float xend = rbpos.x < General.Map.Config.RightBoundary ? rbpos.x : General.Map.Config.RightBoundary;
for(float x = xstart; x < xend + size; x += size)
for (float x = xstart; x < xend + size; x += size)
{
if(x > General.Map.Config.RightBoundary) x = General.Map.Config.RightBoundary;
else if(x < General.Map.Config.LeftBoundary) x = General.Map.Config.LeftBoundary;
if (x > General.Map.Config.RightBoundary) x = General.Map.Config.RightBoundary;
else if (x < General.Map.Config.LeftBoundary) x = General.Map.Config.LeftBoundary;
float from = tlb.y < 0 ? 0 : tlb.y;
float to = rbb.y > windowsize.Height ? windowsize.Height : rbb.y;
@ -987,8 +1035,8 @@ namespace CodeImp.DoomBuilder.Rendering
// Returns false when not on the screen
private bool CreateThingBoxVerts(Thing t, ref FlatVertex[] verts, Dictionary<Thing, Vector2D> thingsByPosition, int offset, PixelColor c)
{
float thingsize = General.Settings.DrawThingsFixedSize ? General.Settings.DefaultThingSize : t.Size;
if(thingsize * scale < MINIMUM_THING_RADIUS) return false; //mxd. Don't render tiny little things
float thingsize = General.Settings.DrawThingsFixedSize ? General.Settings.DefaultThingSize : t.Size;
if (thingsize * scale < MINIMUM_THING_RADIUS) return false; //mxd. Don't render tiny little things
// Determine size
float circlesize = (t.FixedSize && (scale > 1.0f) ? thingsize /* * THING_CIRCLE_SIZE*/ : thingsize * scale /* * THING_CIRCLE_SIZE*/);
@ -997,7 +1045,7 @@ namespace CodeImp.DoomBuilder.Rendering
Vector2D screenpos = ((Vector2D)t.Position).GetTransformed(translatex, translatey, scale, -scale);
// Check if the thing is actually on screen
if(((screenpos.x + circlesize) <= 0.0f) || ((screenpos.x - circlesize) >= windowsize.Width) ||
if (((screenpos.x + circlesize) <= 0.0f) || ((screenpos.x - circlesize) >= windowsize.Width) ||
((screenpos.y + circlesize) <= 0.0f) || ((screenpos.y - circlesize) >= windowsize.Height))
return false;
@ -1043,9 +1091,9 @@ namespace CodeImp.DoomBuilder.Rendering
//mxd
private void CreateThingArrowVerts(Thing t, ref FlatVertex[] verts, Vector2D screenpos, int offset)
{
// Determine size
float thingsize = General.Settings.DrawThingsFixedSize ? General.Settings.DefaultThingSize : t.Size;
float arrowsize = (t.FixedSize && (scale > 1.0f) ? thingsize : thingsize * scale) * THING_ARROW_SIZE; //mxd
// Determine size
float thingsize = General.Settings.DrawThingsFixedSize ? General.Settings.DefaultThingSize : t.Size;
float arrowsize = (t.FixedSize && (scale > 1.0f) ? thingsize : thingsize * scale) * THING_ARROW_SIZE; //mxd
// Setup rotated rect for arrow
float sinarrowsize = (float)Math.Sin(t.Angle + Angle2D.PI * 0.25f) * arrowsize;
@ -1117,7 +1165,7 @@ namespace CodeImp.DoomBuilder.Rendering
private void RenderThingsBatch(ICollection<Thing> things, float alpha, bool fixedcolor, PixelColor c)
{
// Anything to render?
if(things.Count > 0)
if (things.Count > 0)
{
DataStream stream;
@ -1157,33 +1205,33 @@ namespace CodeImp.DoomBuilder.Rendering
// Go for all things
int buffercount = 0;
int totalcount = 0;
foreach(Thing t in things)
foreach (Thing t in things)
{
//mxd. Highlighted thing should be rendered separately
if(!fixedcolor && t.Highlighted) continue;
if (!fixedcolor && t.Highlighted) continue;
//collect models
if(t.IsModel)
if (t.IsModel)
{
if(!modelsByType.ContainsKey(t.SRB2Type)) modelsByType.Add(t.SRB2Type, new List<Thing>());
if (!modelsByType.ContainsKey(t.SRB2Type)) modelsByType.Add(t.SRB2Type, new List<Thing>());
modelsByType[t.SRB2Type].Add(t);
}
// Create vertices
PixelColor tc = fixedcolor ? c : DetermineThingColor(t);
if(CreateThingBoxVerts(t, ref verts, thingsByPosition, buffercount * 6, tc))
if (CreateThingBoxVerts(t, ref verts, thingsByPosition, buffercount * 6, tc))
{
buffercount++;
//mxd
if(!thingsByType.ContainsKey(t.SRB2Type)) thingsByType.Add(t.SRB2Type, new List<Thing>());
if (!thingsByType.ContainsKey(t.SRB2Type)) thingsByType.Add(t.SRB2Type, new List<Thing>());
thingsByType[t.SRB2Type].Add(t);
}
totalcount++;
// Buffer filled?
if(buffercount == locksize)
if (buffercount == locksize)
{
// Write to buffer
stream = thingsvertices.Lock(0, locksize * 6 * FlatVertex.Stride, LockFlags.Discard);
@ -1202,12 +1250,12 @@ namespace CodeImp.DoomBuilder.Rendering
// Write to buffer
stream = thingsvertices.Lock(0, locksize * 6 * FlatVertex.Stride, LockFlags.Discard);
if(buffercount > 0) stream.WriteRange(verts, 0, buffercount * 6);
if (buffercount > 0) stream.WriteRange(verts, 0, buffercount * 6);
thingsvertices.Unlock();
stream.Dispose();
// Draw what's still remaining
if(buffercount > 0)
if (buffercount > 0)
graphics.Device.DrawPrimitives(PrimitiveType.TriangleList, 0, buffercount * 2);
// Done
@ -1217,22 +1265,22 @@ namespace CodeImp.DoomBuilder.Rendering
int selectionColor = General.Colors.Selection.ToInt();
graphics.Shaders.Things2D.BeginPass(1);
foreach(KeyValuePair<int, List<Thing>> group in thingsByType)
foreach (KeyValuePair<int, List<Thing>> group in thingsByType)
{
// Find thing information
ThingTypeInfo info = General.Map.Data.GetThingInfo(group.Key);
// Find sprite texture
if(info.Sprite.Length == 0) continue;
if (info.Sprite.Length == 0) continue;
ImageData sprite = General.Map.Data.GetSpriteImage(info.Sprite);
if(sprite == null) continue;
if(!sprite.IsImageLoaded)
if (sprite == null) continue;
if (!sprite.IsImageLoaded)
{
sprite.SetUsedInMap(true);
continue;
}
if(sprite.Texture == null) sprite.CreateTexture();
if (sprite.Texture == null) sprite.CreateTexture();
graphics.Device.SetTexture(0, sprite.Texture);
graphics.Shaders.Things2D.Texture1 = sprite.Texture;
@ -1248,13 +1296,13 @@ namespace CodeImp.DoomBuilder.Rendering
float spriteWidth, spriteHeight;
float spriteScale = (group.Value[0].FixedSize && (scale > 1.0f)) ? 1.0f : scale;
float radius = General.Settings.DrawThingsFixedSize ? General.Settings.DefaultThingSize : info.Radius;
if(sprite.Width > sprite.Height)
float radius = General.Settings.DrawThingsFixedSize ? General.Settings.DefaultThingSize : info.Radius;
if (sprite.Width > sprite.Height)
{
spriteWidth = radius * spriteScale - THING_SPRITE_SHRINK * spriteScale;
spriteHeight = spriteWidth * ((float)sprite.Height / sprite.Width);
}
else if(sprite.Width < sprite.Height)
else if (sprite.Width < sprite.Height)
{
spriteHeight = radius * spriteScale - THING_SPRITE_SHRINK * spriteScale;
spriteWidth = spriteHeight * ((float)sprite.Width / sprite.Height);
@ -1265,19 +1313,19 @@ namespace CodeImp.DoomBuilder.Rendering
spriteHeight = spriteWidth;
}
foreach(Thing t in group.Value)
foreach (Thing t in group.Value)
{
if(t.IsModel && (General.Settings.GZDrawModelsMode == ModelRenderMode.ALL || (General.Settings.GZDrawModelsMode == ModelRenderMode.SELECTION && t.Selected) || (General.Settings.GZDrawModelsMode == ModelRenderMode.ACTIVE_THINGS_FILTER && alpha == 1.0f))) continue;
float thingsize = General.Settings.DrawThingsFixedSize ? General.Settings.DefaultThingSize : t.Size;
float scaler = thingsize / radius;
if(Math.Max(spriteWidth, spriteHeight) * scaler < MINIMUM_SPRITE_RADIUS) continue; //don't render tiny little sprites
if (t.IsModel && (General.Settings.GZDrawModelsMode == ModelRenderMode.ALL || (General.Settings.GZDrawModelsMode == ModelRenderMode.SELECTION && t.Selected) || (General.Settings.GZDrawModelsMode == ModelRenderMode.ACTIVE_THINGS_FILTER && alpha == 1.0f))) continue;
float thingsize = General.Settings.DrawThingsFixedSize ? General.Settings.DefaultThingSize : t.Size;
float scaler = thingsize / radius;
if (Math.Max(spriteWidth, spriteHeight) * scaler < MINIMUM_SPRITE_RADIUS) continue; //don't render tiny little sprites
CreateThingSpriteVerts(thingsByPosition[t], spriteWidth * scaler, spriteHeight * scaler, ref verts, buffercount * 6, t.Selected ? selectionColor : 0xFFFFFF);
buffercount++;
totalcount++;
// Buffer filled?
if(buffercount == locksize)
if (buffercount == locksize)
{
// Write to buffer
stream = thingsvertices.Lock(0, locksize * 6 * FlatVertex.Stride, LockFlags.Discard);
@ -1297,12 +1345,12 @@ namespace CodeImp.DoomBuilder.Rendering
// Write to buffer
stream = thingsvertices.Lock(0, locksize * 6 * FlatVertex.Stride, LockFlags.Discard);
if(buffercount > 0) stream.WriteRange(verts, 0, buffercount * 6);
if (buffercount > 0) stream.WriteRange(verts, 0, buffercount * 6);
thingsvertices.Unlock();
stream.Dispose();
// Draw what's still remaining
if(buffercount > 0)
if (buffercount > 0)
graphics.Device.DrawPrimitives(PrimitiveType.TriangleList, 0, buffercount * 2);
}
@ -1322,16 +1370,16 @@ namespace CodeImp.DoomBuilder.Rendering
buffercount = 0;
totalcount = 0;
foreach(KeyValuePair<Thing, Vector2D> group in thingsByPosition)
foreach (KeyValuePair<Thing, Vector2D> group in thingsByPosition)
{
if(!group.Key.IsDirectional) continue;
if (!group.Key.IsDirectional) continue;
CreateThingArrowVerts(group.Key, ref verts, group.Value, buffercount * 6);
buffercount++;
totalcount++;
// Buffer filled?
if(buffercount == locksize)
if (buffercount == locksize)
{
// Write to buffer
stream = thingsvertices.Lock(0, locksize * 6 * FlatVertex.Stride, LockFlags.Discard);
@ -1350,19 +1398,19 @@ namespace CodeImp.DoomBuilder.Rendering
// Write to buffer
stream = thingsvertices.Lock(0, locksize * 6 * FlatVertex.Stride, LockFlags.Discard);
if(buffercount > 0) stream.WriteRange(verts, 0, buffercount * 6);
if (buffercount > 0) stream.WriteRange(verts, 0, buffercount * 6);
thingsvertices.Unlock();
stream.Dispose();
// Draw what's still remaining
if(buffercount > 0)
if (buffercount > 0)
graphics.Device.DrawPrimitives(PrimitiveType.TriangleList, 0, buffercount * 2);
//Done with this pass
graphics.Shaders.Things2D.EndPass();
//mxd. Render models
if(General.Settings.GZDrawModelsMode != ModelRenderMode.NONE)
if (General.Settings.GZDrawModelsMode != ModelRenderMode.NONE)
{
// Set renderstates for rendering
graphics.Device.SetRenderState(RenderState.AlphaBlendEnable, false);
@ -1379,17 +1427,17 @@ namespace CodeImp.DoomBuilder.Rendering
Matrix viewscale = Matrix.Scaling(scale, -scale, 0.0f);
foreach(KeyValuePair<int, List<Thing>> group in modelsByType)
foreach (KeyValuePair<int, List<Thing>> group in modelsByType)
{
ModelData mde = General.Map.Data.ModeldefEntries[@group.Key];
foreach(Thing t in group.Value)
foreach (Thing t in group.Value)
{
if((General.Settings.GZDrawModelsMode == ModelRenderMode.SELECTION && !t.Selected) || (General.Settings.GZDrawModelsMode == ModelRenderMode.ACTIVE_THINGS_FILTER && alpha < 1.0f)) continue;
if ((General.Settings.GZDrawModelsMode == ModelRenderMode.SELECTION && !t.Selected) || (General.Settings.GZDrawModelsMode == ModelRenderMode.ACTIVE_THINGS_FILTER && alpha < 1.0f)) continue;
Vector2D screenpos = ((Vector2D)t.Position).GetTransformed(translatex, translatey, scale, -scale);
float modelScale = scale * t.ActorScale.Width * t.ScaleX;
//should we render this model?
if(((screenpos.x + mde.Model.Radius * modelScale) <= 0.0f) || ((screenpos.x - mde.Model.Radius * modelScale) >= windowsize.Width) ||
if (((screenpos.x + mde.Model.Radius * modelScale) <= 0.0f) || ((screenpos.x - mde.Model.Radius * modelScale) >= windowsize.Width) ||
((screenpos.y + mde.Model.Radius * modelScale) <= 0.0f) || ((screenpos.y - mde.Model.Radius * modelScale) >= windowsize.Height))
continue;
@ -1408,7 +1456,7 @@ namespace CodeImp.DoomBuilder.Rendering
graphics.Shaders.Things2D.ApplySettings();
// Draw
foreach(Mesh mesh in mde.Model.Meshes) mesh.DrawSubset(0);
foreach (Mesh mesh in mde.Model.Meshes) mesh.DrawSubset(0);
}
}
@ -1433,51 +1481,24 @@ namespace CodeImp.DoomBuilder.Rendering
public void RenderThingSet(ICollection<Thing> things, float alpha)
{
RenderThingsBatch(things, alpha, false, new PixelColor());
}
}
public void RenderNiGHTSPath()
{
if (!General.Settings.RenderNiGHTSPath) return;
ICollection<Thing> things = General.Map.Map.Things;
List<Thing> axes = new List<Thing>();
List<Thing> axistransferlines = new List<Thing>();
List<Thing> waypoints = new List<Thing>();
foreach (Thing t in things)
{
int type = t.SRB2Type;
if (type == General.Map.FormatInterface.AxisType) axes.Add(t);
if (type == General.Map.FormatInterface.AxisTransferLineType) axistransferlines.Add(t);
if (type == General.Map.FormatInterface.WaypointType) waypoints.Add(t);
}
//Sort waypoints by angle
waypoints.Sort((x,y) => (x.AngleDoom.CompareTo(y.AngleDoom)));
//Sort by axis number and mare number.
axistransferlines.Sort((x, y) => (x.GetFlagsValue() | (x.Parameter)<<16).CompareTo((y.GetFlagsValue() | (y.Parameter) << 16)));
//Render (zoom tube) waypoint sequences.
//Render (zoom tube) waypoint sequences.
public void RenderWaypoints()
{
int i = 0;
int size = waypoints.Count;
int seqStart = 0;
TextLabel[] sequencelabels = new TextLabel[256];
while (i < size)
{
int iNext = i + 1;
if (waypoints[i].AngleDoom % 256 == 0) // start of a new sequence?
{
seqStart = i;
sequencelabels[waypoints[i].AngleDoom / 256] = new TextLabel(3) // create sequence ID label
{
Text = (waypoints[i].AngleDoom / 256).ToString(),
AlignX = TextAlignmentX.Center,
AlignY = TextAlignmentY.Middle,
Color = General.Colors.WaypointColor,
Backcolor = General.Colors.Background,
Scale = 16f,
TransformCoords = true,
Rectangle = new RectangleF(waypoints[i].Position.x, waypoints[i].Position.y, 0.0f, 0.0f)
};
waypointlabel.Text = (waypoints[i].AngleDoom / 256).ToString();
waypointlabel.Left = waypoints[i].Position.x;
waypointlabel.Top = waypoints[i].Position.y;
RenderText(waypointlabel);
}
if (iNext < size && waypoints[iNext].AngleDoom == waypoints[i].AngleDoom + 1)
{
@ -1502,13 +1523,134 @@ namespace CodeImp.DoomBuilder.Rendering
}
i = iNext;
}
}
for (i = 0; i < 256; i++)
if (sequencelabels[i] != null) RenderText(sequencelabels[i]);
public void RenderPolyobjects()
{
starts = new Vector2D[4096];
ends = new Vector2D[4096];
int i = 0, j = 0, k = 0, v = 0;
while (i < polyanchors.Count && j < polyspawns.Count && k < firstlines.Count)
{
while (j + 1 < polyspawns.Count && polyanchors[i].AngleDoom > polyspawns[j].AngleDoom)
{
// Mark invalid spawnpoints
spawnlabel.Text = polyspawns[j].AngleDoom.ToString();
spawnlabel.Left = polyspawns[j].Position.x;
spawnlabel.Top = polyspawns[j].Position.y;
spawnlabel.Color = PixelColor.FromColor(Color.Red);
RenderText(spawnlabel);
j++;
}
while (k+1 < firstlines.Count && polyanchors[i].AngleDoom > firstlines[k].Tag) k++;
Sector s = null;
if (polyanchors[i].AngleDoom == firstlines[k].Tag)
s = firstlines[k].Back.Sector;
if (polyanchors[i].AngleDoom == polyspawns[j].AngleDoom && s != null)
{
while (j+1 < polyspawns.Count && polyspawns[j].AngleDoom == polyspawns[j + 1].AngleDoom)
{
spawnlabel.Text = polyspawns[j].AngleDoom.ToString();
spawnlabel.Left = polyspawns[j].Position.x;
spawnlabel.Top = polyspawns[j].Position.y;
spawnlabel.Color = PixelColor.FromColor(Color.Red);
RenderText(spawnlabel);
j++;
}
float xdiff = polyanchors[i].Position.x - polyspawns[j].Position.x;
float ydiff = polyanchors[i].Position.y - polyspawns[j].Position.y;
foreach (Sidedef side in s.Sidedefs)
{
Vector2D start = side.Line.Start.Position;
Vector2D end = side.Line.End.Position;
start.x -= xdiff;
start.y -= ydiff;
end.x -= xdiff;
end.y -= ydiff;
starts[v] = start;
ends[v] = end;
v++;
}
anchorlabel.Color = General.Colors.GetNiGHTSColor(8);
spawnlabel.Color = General.Colors.GetNiGHTSColor(7);
spawnlabel.Text = polyspawns[j].AngleDoom.ToString();
spawnlabel.Left = polyspawns[j].Position.x;
spawnlabel.Top = polyspawns[j].Position.y;
RenderText(spawnlabel);
}
else
{
// Mark invalid points
anchorlabel.Color = PixelColor.FromColor(Color.Red);
}
anchorlabel.Text = polyanchors[i].AngleDoom.ToString();
anchorlabel.Left = polyanchors[i].Position.x;
anchorlabel.Top = polyanchors[i].Position.y;
RenderText(anchorlabel);
i++;
}
RenderLines(starts, ends, 1.0f, General.Colors.GetNiGHTSColor(7), true);
}
public void RenderNiGHTSPath()
{
if (!General.Settings.RenderNiGHTSPath)
{
return;
}
axes = new List<Thing>();
axistransferlines = new List<Thing>();
waypoints = new List<Thing>();
polyanchors = new List<Thing>();
polyspawns = new List<Thing>();
firstlines = new List<Linedef>();
foreach (Thing t in General.Map.Map.Things)
{
int type = t.SRB2Type;
if (type == General.Map.FormatInterface.AxisType) axes.Add(t);
if (type == General.Map.FormatInterface.AxisTransferLineType) axistransferlines.Add(t);
if (type == General.Map.FormatInterface.WaypointType) waypoints.Add(t);
if (type == 760) polyanchors.Add(t);
if (type == 761 || type == 762) polyspawns.Add(t);
}
foreach (Linedef l in General.Map.Map.Linedefs)
{
if (l.Action == 20) firstlines.Add(l);
}
//Sort waypoints by angle
waypoints.Sort((x,y) => (x.AngleDoom.CompareTo(y.AngleDoom)));
// Sort polyobject stuff by "angle"/tag
polyanchors.Sort((x, y) => (x.AngleDoom.CompareTo(y.AngleDoom)));
polyspawns.Sort((x, y) => (x.AngleDoom.CompareTo(y.AngleDoom)));
firstlines.Sort((x, y) => (x.Tag.CompareTo(y.Tag)));
//Sort by axis number and mare number.
axistransferlines.Sort((x, y) => (x.GetFlagsValue() | (x.Parameter)<<16).CompareTo((y.GetFlagsValue() | (y.Parameter) << 16)));
//Render zoom tubes and polyobjects
RenderWaypoints();
RenderPolyobjects();
//Render axis transfer lines.
i = 0;
size = axistransferlines.Count;
int i = 0;
int size = axistransferlines.Count;
while (i < size - 1)
{
int iNext = i;