Sectors, Linedefs, Things modes: optimized text label rendering.

Fixed, Things mode: in some cases selection labels were not updated after editing a thing.
Fixed, Things mode: selection labels were positioned incorrectly on things with FixedSize setting.
Fixed, Sectors mode: fixed a crash when selecting self-referencing sector when selection labels were enabled.
Fixed, Visual mode: in some cases Auto-align texture actions were not working when "use long texture names" Map Options setting was enabled.
Fixed, MD2/MD3 loader: available animation frames upper bound check was performed incorrectly, which would cause a crash in some very special cases.
Fixed, Game configurations: most Hexen/ZDoom teleport actions use TeleportDests as teleport targets, not MapSpots.
This commit is contained in:
MaxED 2016-04-05 22:24:36 +00:00 committed by spherallic
parent 4c7aae544b
commit 187653bfa9
11 changed files with 160 additions and 90 deletions

View file

@ -3642,9 +3642,9 @@ teleport
arg0
{
title = "Target MapSpot Tag";
title = "Target Teleport Dest. Tag";
type = 14;
targetclasses = "MapSpot,MapSpotGravity";
targetclasses = "TeleportDest,TeleportDest2,TeleportDest3";
}
arg1
@ -3661,9 +3661,9 @@ teleport
arg0
{
title = "Target MapSpot Tag";
title = "Target Teleport Dest. Tag";
type = 14;
targetclasses = "MapSpot,MapSpotGravity";
targetclasses = "TeleportDest,TeleportDest2,TeleportDest3";
}
arg1

View file

@ -6473,9 +6473,9 @@ zdoom
arg0
{
title = "Target MapSpot Tag";
title = "Target Teleport Dest. Tag";
type = 14;
targetclasses = "MapSpot,MapSpotGravity";
targetclasses = "TeleportDest,TeleportDest2,TeleportDest3";
}
arg1
{
@ -6541,17 +6541,20 @@ zdoom
arg0
{
title = "Thing Tag";
tooltip = "The TID of the actor(s) to teleport.\nIf 0, teleports the activator only.";
type = 14;
}
arg1
{
title = "Source Teleport Dest. Tag";
type = 14;
targetclasses = "TeleportDest,TeleportDest2,TeleportDest3";
}
arg2
{
title = "Target Teleport Dest. Tag";
type = 14;
targetclasses = "TeleportDest,TeleportDest2,TeleportDest3";
}
arg3
{
@ -6578,15 +6581,15 @@ zdoom
}
arg1
{
title = "Source MapSpot Tag";
title = "Source Tag";
tooltip = "The spot relative to which to teleport.";
type = 14;
targetclasses = "MapSpot,MapSpotGravity";
}
arg2
{
title = "Target MapSpot Tag";
title = "Target Teleport Dest. Tag";
type = 14;
targetclasses = "MapSpot,MapSpotGravity";
targetclasses = "TeleportDest,TeleportDest2,TeleportDest3";
}
arg3
{
@ -6597,6 +6600,7 @@ zdoom
arg4
{
title = "Group Thing Tag";
tooltip = "The TID of the thing(s) to teleport.\nIf 0, teleports all actors in the sector";
type = 14;
}
}
@ -6607,9 +6611,9 @@ zdoom
arg0
{
title = "Target MapSpot Tag";
title = "Target Teleport Dest. Tag";
type = 14;
targetclasses = "MapSpot,MapSpotGravity";
targetclasses = "TeleportDest,TeleportDest2,TeleportDest3";
}
arg1
{

View file

@ -41,6 +41,7 @@ namespace CodeImp.DoomBuilder
private DebugMessageType filters;
private static long starttime = -1;
private static int counter;
private static DebugConsole me;
#endregion
@ -159,6 +160,24 @@ namespace CodeImp.DoomBuilder
starttime = -1;
}
public static void IncrementCounter() { IncrementCounter(1); }
public static void IncrementCounter(int incrementby)
{
counter += incrementby;
}
public static void ResetCounter(string message)
{
if(message.Contains("%"))
message = message.Replace("%", counter.ToString());
else
message = message.TrimEnd() + ": " + counter;
WriteLine(DebugMessageType.SPECIAL, message);
counter = 0;
}
public static void StartProfiler()
{
#if PROFILE

View file

@ -1846,6 +1846,14 @@ namespace CodeImp.DoomBuilder.Geometry
((sd.LongMiddleTexture == texturelongname) && (sd.MiddleRequired() || sd.LongMiddleTexture != MapSet.EmptyLongName)) ;
}
//mxd. This checks if any of the sidedef texture match the given textures
public static bool SidedefTextureMatch(Sidedef sd, HashSet<long> texturelongnames)
{
return (texturelongnames.Contains(sd.LongHighTexture) && sd.HighRequired()) ||
(texturelongnames.Contains(sd.LongLowTexture) && sd.LowRequired()) ||
(texturelongnames.Contains(sd.LongMiddleTexture) && (sd.MiddleRequired() || sd.LongMiddleTexture != MapSet.EmptyLongName));
}
//mxd. This converts offsetY from/to "normalized" offset for given wall part
public static float GetSidedefOffsetY(Sidedef side, VisualGeometryType part, float offset, float scaleY, bool fromNormalized)
{

View file

@ -1725,11 +1725,8 @@ namespace CodeImp.DoomBuilder.Rendering
public void RenderText(TextLabel label)
{
//mxd. Update the text if needed
RectangleF bbox = label.Update(translatex, translatey, scale, -scale);
//mxd. Have graphics / on screen?
if(label.VertexBuffer == null || (bbox.Right < 0.1f) || (bbox.Left > windowsize.Width) || (bbox.Bottom < 0.1f) || (bbox.Top > windowsize.Height))
return;
label.Update(translatex, translatey, scale, -scale);
if(label.SkipRendering) return;
// Set renderstates for rendering
graphics.Device.SetRenderState(RenderState.CullMode, Cull.None);
@ -1759,18 +1756,8 @@ namespace CodeImp.DoomBuilder.Rendering
foreach(TextLabel label in labels)
{
// Update the text if needed
RectangleF bbox = label.Update(translatex, translatey, scale, -scale);
// Have graphics / on screen?
if(label.VertexBuffer == null || (bbox.Right < 0.1f) || (bbox.Left > windowsize.Width) || (bbox.Bottom < 0.1f) || (bbox.Top > windowsize.Height))
{
label.SkipRendering = true;
skipped++;
}
else
{
label.SkipRendering = false;
}
label.Update(translatex, translatey, scale, -scale);
if(label.SkipRendering) skipped++;
}
if(labels.Count == skipped) return;

View file

@ -47,7 +47,6 @@ namespace CodeImp.DoomBuilder.Rendering
// Text settings
private string text;
private RectangleF rect;
private RectangleF absview; //mxd
private bool transformcoords;
private PixelColor color;
private PixelColor backcolor;
@ -63,6 +62,9 @@ namespace CodeImp.DoomBuilder.Rendering
private float lasttranslatey;
private float lastscalex;
private float lastscaley;
//mxd. Rendering
private bool skiprendering;
// Disposing
private bool isdisposed;
@ -90,7 +92,7 @@ namespace CodeImp.DoomBuilder.Rendering
public bool DrawBackground { get { return drawbg; } set { if(drawbg != value) { drawbg = value; textureupdateneeded = true; } } } //mxd
internal Texture Texture { get { return texture; } } //mxd
internal VertexBuffer VertexBuffer { get { return textbuffer; } }
internal bool SkipRendering; //mxd
internal bool SkipRendering { get { return skiprendering; } } //mxd
// Disposing
public bool IsDisposed { get { return isdisposed; } }
@ -116,6 +118,10 @@ namespace CodeImp.DoomBuilder.Rendering
// Register as resource
General.Map.Graphics.RegisterResource(this);
//mxd. Create the buffer
this.textbuffer = new VertexBuffer(General.Map.Graphics.Device, 4 * FlatVertex.Stride,
Usage.Dynamic | Usage.WriteOnly, VertexFormat.None, Pool.Default);
// We have no destructor
GC.SuppressFinalize(this);
@ -143,7 +149,7 @@ namespace CodeImp.DoomBuilder.Rendering
#region ================== Methods
// This updates the text if needed
internal RectangleF Update(float translatex, float translatey, float scalex, float scaley)
internal void Update(float translatex, float translatey, float scalex, float scaley)
{
// Check if transformation changed and needs to be updated
if(transformcoords && (translatex != lasttranslatex || translatey != lasttranslatey ||
@ -156,30 +162,6 @@ namespace CodeImp.DoomBuilder.Rendering
updateneeded = true;
}
//mxd. Update texture if needed
if(textureupdateneeded)
{
// Get rid of old texture
if(texture != null)
{
texture.Dispose();
texture = null;
}
// Create label image
Bitmap img = CreateLabelImage(text, font, color, backcolor, drawbg);
textsize = img.Size;
// Create texture
MemoryStream memstream = new MemoryStream((img.Size.Width * img.Size.Height * 4) + 4096);
img.Save(memstream, ImageFormat.Bmp);
memstream.Seek(0, SeekOrigin.Begin);
texture = Texture.FromStream(General.Map.Graphics.Device, memstream, (int)memstream.Length,
img.Size.Width, img.Size.Height, 1, Usage.None, Format.Unknown,
Pool.Managed, General.Map.Graphics.PostFilter, General.Map.Graphics.MipGenerateFilter, 0);
}
// Update if needed
if(updateneeded || textureupdateneeded)
{
@ -187,6 +169,7 @@ namespace CodeImp.DoomBuilder.Rendering
if(text.Length > 0)
{
// Transform?
RectangleF absview;
if(transformcoords)
{
// Calculate absolute coordinates
@ -202,6 +185,37 @@ namespace CodeImp.DoomBuilder.Rendering
absview = rect;
}
//mxd. Skip when not on screen...
RectangleF abssize = absview;
abssize.Inflate(textsize.Width / 2, textsize.Height / 2);
Size windowsize = General.Map.Graphics.RenderTarget.ClientSize;
skiprendering = (abssize.Right < 0.1f) || (abssize.Left > windowsize.Width) || (abssize.Bottom < 0.1f) || (abssize.Top > windowsize.Height);
if(skiprendering) return;
//mxd. Update texture if needed
if(textureupdateneeded)
{
// Get rid of old texture
if(texture != null)
{
texture.Dispose();
texture = null;
}
// Create label image
Bitmap img = CreateLabelImage(text, font, color, backcolor, drawbg);
textsize = img.Size;
// Create texture
MemoryStream memstream = new MemoryStream((img.Size.Width * img.Size.Height * 4) + 4096);
img.Save(memstream, ImageFormat.Bmp);
memstream.Seek(0, SeekOrigin.Begin);
texture = Texture.FromStream(General.Map.Graphics.Device, memstream, (int)memstream.Length,
img.Size.Width, img.Size.Height, 1, Usage.None, Format.Unknown,
Pool.Managed, General.Map.Graphics.PostFilter, General.Map.Graphics.MipGenerateFilter, 0);
}
// Align the text horizontally
float beginx = 0;
switch(alignx)
@ -220,14 +234,6 @@ namespace CodeImp.DoomBuilder.Rendering
case TextAlignmentY.Bottom: beginy = absview.Y + absview.Height - textsize.Height; break;
}
// Do we have to make a new buffer?
if(textbuffer == null)
{
// Create the buffer
textbuffer = new VertexBuffer(General.Map.Graphics.Device, 4 * FlatVertex.Stride,
Usage.Dynamic | Usage.WriteOnly, VertexFormat.None, Pool.Default);
}
//mxd. Lock the buffer
using(DataStream stream = textbuffer.Lock(0, 4 * FlatVertex.Stride, LockFlags.Discard | LockFlags.NoSystemLock))
{
@ -241,16 +247,14 @@ namespace CodeImp.DoomBuilder.Rendering
else
{
// No faces in polygon
if(textbuffer != null) textbuffer.Dispose(); //mxd
textsize = new SizeF();
skiprendering = true; //mxd
}
// Text updated
updateneeded = false;
textureupdateneeded = false; //mxd
}
return absview; //mxd
}
//mxd

View file

@ -706,7 +706,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(requiredsize > group.Key.Labels[i].radius)
{
requiredsize = (General.Interface.MeasureString(group.Value[1], l.Font).Width / 2) / renderer.Scale;
l.Text = (requiredsize > group.Key.Labels[i].radius ? "+" : group.Value[1]);
if(requiredsize > group.Key.Labels[i].radius)
l.Text = (requiredsize > group.Key.Labels[i].radius * 4 ? string.Empty : "+");
else
l.Text = group.Value[1];
}
else
{

View file

@ -197,6 +197,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
List<TextLabel> torender = new List<TextLabel>(orderedselection.Count);
foreach(Sector s in orderedselection)
{
//mxd. Self-referencing (and probably some other) sectors don't have labels...
if(labels[s].Length == 0) continue;
// Render labels
TextLabel[] labelarray = labels[s];
float requiredsize = (labelarray[0].TextSize.Height / 2) / renderer.Scale;
@ -238,7 +241,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(requiredsize > group.Key.Labels[i].radius)
{
requiredsize = (General.Interface.MeasureString(group.Value[1], l.Font).Width / 2) / renderer.Scale;
l.Text = (requiredsize > group.Key.Labels[i].radius ? "+" : group.Value[1]);
if(requiredsize > group.Key.Labels[i].radius)
l.Text = (requiredsize > group.Key.Labels[i].radius * 4 ? string.Empty : "+");
else
l.Text = group.Value[1];
}
else
{

View file

@ -295,7 +295,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(requiredsize > group.Key.Labels[i].radius)
{
requiredsize = (General.Interface.MeasureString(group.Value[1], l.Font).Width / 2) / renderer.Scale;
l.Text = (requiredsize > group.Key.Labels[i].radius ? "+" : group.Value[1]);
if(requiredsize > group.Key.Labels[i].radius)
l.Text = (requiredsize > group.Key.Labels[i].radius * 4 ? string.Empty : "+");
else
l.Text = group.Value[1];
}
else
{
@ -559,14 +562,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd. Update helper lines
UpdateHelperObjects();
//mxd. Update selection info
UpdateSelectionInfo();
// Update display
General.Interface.RedrawDisplay();
}
}
}
//mxd. Update selection info
UpdateSelectionInfo();
}
editpressed = false;
@ -982,9 +985,20 @@ namespace CodeImp.DoomBuilder.BuilderModes
Vector2D v = thing.Position;
TextLabel l = new TextLabel();
l.TransformCoords = true;
l.Rectangle = new RectangleF(v.x - thing.Size + 1, v.y + thing.Size - 1, 0f, 0f);
l.AlignX = TextAlignmentX.Left;
l.AlignY = TextAlignmentY.Top;
if(thing.FixedSize)
{
l.Rectangle = new RectangleF(v.x, v.y, 0f, 0f);
l.AlignX = TextAlignmentX.Center;
l.AlignY = TextAlignmentY.Middle;
}
else
{
l.Rectangle = new RectangleF(v.x - thing.Size + 1, v.y + thing.Size - 1, 0f, 0f);
l.AlignX = TextAlignmentX.Left;
l.AlignY = TextAlignmentY.Top;
}
l.Color = (thing == highlighted ? General.Colors.Selection : General.Colors.Highlight);
l.Backcolor = General.Colors.Background.WithAlpha(255);
l.DrawBackground = true;

View file

@ -4488,6 +4488,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
first.controlSide = start.Sidedef;
}
//mxd
HashSet<long> texturehashes = new HashSet<long> { texture.LongName };
first.forward = true;
todo.Push(first);
@ -4535,11 +4538,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Add sidedefs forward (connected to the right vertex)
Vertex v = j.sidedef.IsFront ? j.sidedef.Line.End : j.sidedef.Line.Start;
AddSidedefsForAlignment(todo, v, true, forwardoffset, 1.0f, texture.LongName, false);
AddSidedefsForAlignment(todo, v, true, forwardoffset, 1.0f, texturehashes, false);
// Add sidedefs backward (connected to the left vertex)
v = j.sidedef.IsFront ? j.sidedef.Line.Start : j.sidedef.Line.End;
AddSidedefsForAlignment(todo, v, false, backwardoffset, 1.0f, texture.LongName, false);
AddSidedefsForAlignment(todo, v, false, backwardoffset, 1.0f, texturehashes, false);
}
else
{
@ -4575,11 +4578,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Add sidedefs backward (connected to the left vertex)
Vertex v = j.sidedef.IsFront ? j.sidedef.Line.Start : j.sidedef.Line.End;
AddSidedefsForAlignment(todo, v, false, backwardoffset, 1.0f, texture.LongName, false);
AddSidedefsForAlignment(todo, v, false, backwardoffset, 1.0f, texturehashes, false);
// Add sidedefs forward (connected to the right vertex)
v = j.sidedef.IsFront ? j.sidedef.Line.End : j.sidedef.Line.Start;
AddSidedefsForAlignment(todo, v, true, forwardoffset, 1.0f, texture.LongName, false);
AddSidedefsForAlignment(todo, v, true, forwardoffset, 1.0f, texturehashes, false);
}
}
}
@ -4609,6 +4612,24 @@ namespace CodeImp.DoomBuilder.BuilderModes
else
first.controlSide = start.Sidedef;
//mxd. We potentially need to deal with 2 textures (because of long and short texture names)...
HashSet<long> texturehashes = new HashSet<long> { texture.LongName };
switch(start.GeometryType)
{
case VisualGeometryType.WALL_LOWER:
texturehashes.Add(first.controlSide.LongLowTexture);
break;
case VisualGeometryType.WALL_MIDDLE:
case VisualGeometryType.WALL_MIDDLE_3D:
texturehashes.Add(first.controlSide.LongMiddleTexture);
break;
case VisualGeometryType.WALL_UPPER:
texturehashes.Add(first.controlSide.LongHighTexture);
break;
}
//mxd
List<BaseVisualGeometrySidedef> selectedVisualSides = new List<BaseVisualGeometrySidedef>();
if(checkSelectedSidedefParts && !singleselection)
@ -4692,9 +4713,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Get the align job to do
SidedefAlignJob j = todo.Pop();
bool matchtop = (!j.sidedef.Marked && (!singleselection || j.sidedef.LongHighTexture == texture.LongName) && j.sidedef.HighRequired());
bool matchbottom = (!j.sidedef.Marked && (!singleselection || j.sidedef.LongLowTexture == texture.LongName) && j.sidedef.LowRequired());
bool matchmid = ((!singleselection || j.controlSide.LongMiddleTexture == texture.LongName) && (j.controlSide.MiddleRequired() || j.controlSide.LongMiddleTexture != MapSet.EmptyLongName)); //mxd
bool matchtop = (!j.sidedef.Marked && (!singleselection || texturehashes.Contains(j.sidedef.LongHighTexture)) && j.sidedef.HighRequired());
bool matchbottom = (!j.sidedef.Marked && (!singleselection || texturehashes.Contains(j.sidedef.LongLowTexture)) && j.sidedef.LowRequired());
bool matchmid = ((!singleselection || texturehashes.Contains(j.controlSide.LongMiddleTexture)) && (j.controlSide.MiddleRequired() || j.controlSide.LongMiddleTexture != MapSet.EmptyLongName)); //mxd
//mxd. If there's a selection, check if matched part is actually selected
if(checkSelectedSidedefParts && !singleselection)
@ -4825,11 +4846,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Add sidedefs backward (connected to the left vertex)
v = j.sidedef.IsFront ? j.sidedef.Line.Start : j.sidedef.Line.End;
AddSidedefsForAlignment(todo, v, false, backwardoffset, j.scaleY, texture.LongName, true);
AddSidedefsForAlignment(todo, v, false, backwardoffset, j.scaleY, texturehashes, true);
// Add sidedefs forward (connected to the right vertex)
v = j.sidedef.IsFront ? j.sidedef.Line.End : j.sidedef.Line.Start;
AddSidedefsForAlignment(todo, v, true, forwardoffset, j.scaleY, texture.LongName, true);
AddSidedefsForAlignment(todo, v, true, forwardoffset, j.scaleY, texturehashes, true);
}
else
{
@ -4921,17 +4942,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Add sidedefs forward (connected to the right vertex)
v = j.sidedef.IsFront ? j.sidedef.Line.End : j.sidedef.Line.Start;
AddSidedefsForAlignment(todo, v, true, forwardoffset, j.scaleY, texture.LongName, true);
AddSidedefsForAlignment(todo, v, true, forwardoffset, j.scaleY, texturehashes, true);
// Add sidedefs backward (connected to the left vertex)
v = j.sidedef.IsFront ? j.sidedef.Line.Start : j.sidedef.Line.End;
AddSidedefsForAlignment(todo, v, false, backwardoffset, j.scaleY, texture.LongName, true);
AddSidedefsForAlignment(todo, v, false, backwardoffset, j.scaleY, texturehashes, true);
}
}
}
// This adds the matching, unmarked sidedefs from a vertex for texture alignment
private void AddSidedefsForAlignment(Stack<SidedefAlignJob> stack, Vertex v, bool forward, float offsetx, float scaleY, long texturelongname, bool udmf)
private void AddSidedefsForAlignment(Stack<SidedefAlignJob> stack, Vertex v, bool forward, float offsetx, float scaleY, HashSet<long> texturelongnames, bool udmf)
{
foreach(Linedef ld in v.Linedefs)
{
@ -4949,7 +4970,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
foreach(Sidedef s in controlSides)
{
if(!singleselection || Tools.SidedefTextureMatch(s, texturelongname))
if(!singleselection || Tools.SidedefTextureMatch(s, texturelongnames))
{
SidedefAlignJob nj = new SidedefAlignJob();
nj.forward = forward;
@ -4967,7 +4988,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
foreach(Sidedef s in controlSides)
{
if(!singleselection || Tools.SidedefTextureMatch(s, texturelongname))
if(!singleselection || Tools.SidedefTextureMatch(s, texturelongnames))
{
SidedefAlignJob nj = new SidedefAlignJob();
nj.forward = forward;

View file

@ -270,6 +270,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(translucent && !othertranslucent && !ef.ClipSidedefs) continue;
if(ef.ClipSidedefs == extrafloor.ClipSidedefs || ef.ClipSidedefs)
{
//TODO: find out why ef can be not updated at this point
//TODO: [this crashed on me once when performing auto-align on myriad of textures on BoA C1M0]
if(ef.Floor == null || ef.Ceiling == null) ef.Update();
int num = polygons.Count;
for(int pi = 0; pi < num; pi++)
{