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
parent a4428cf244
commit ee12da96a1
13 changed files with 174 additions and 121 deletions

View file

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

View file

@ -2128,9 +2128,9 @@ zdoom
arg0 arg0
{ {
title = "Target MapSpot Tag"; title = "Target Teleport Dest. Tag";
type = 14; type = 14;
targetclasses = "MapSpot,MapSpotGravity"; targetclasses = "TeleportDest,TeleportDest2,TeleportDest3";
} }
arg1 arg1
{ {
@ -2196,17 +2196,20 @@ zdoom
arg0 arg0
{ {
title = "Thing Tag"; title = "Thing Tag";
tooltip = "The TID of the actor(s) to teleport.\nIf 0, teleports the activator only.";
type = 14; type = 14;
} }
arg1 arg1
{ {
title = "Source Teleport Dest. Tag"; title = "Source Teleport Dest. Tag";
type = 14; type = 14;
targetclasses = "TeleportDest,TeleportDest2,TeleportDest3";
} }
arg2 arg2
{ {
title = "Target Teleport Dest. Tag"; title = "Target Teleport Dest. Tag";
type = 14; type = 14;
targetclasses = "TeleportDest,TeleportDest2,TeleportDest3";
} }
arg3 arg3
{ {
@ -2233,15 +2236,15 @@ zdoom
} }
arg1 arg1
{ {
title = "Source MapSpot Tag"; title = "Source Tag";
tooltip = "The spot relative to which to teleport.";
type = 14; type = 14;
targetclasses = "MapSpot,MapSpotGravity";
} }
arg2 arg2
{ {
title = "Target MapSpot Tag"; title = "Target Teleport Dest. Tag";
type = 14; type = 14;
targetclasses = "MapSpot,MapSpotGravity"; targetclasses = "TeleportDest,TeleportDest2,TeleportDest3";
} }
arg3 arg3
{ {
@ -2252,6 +2255,7 @@ zdoom
arg4 arg4
{ {
title = "Group Thing Tag"; title = "Group Thing Tag";
tooltip = "The TID of the thing(s) to teleport.\nIf 0, teleports all actors in the sector";
type = 14; type = 14;
} }
} }
@ -2262,9 +2266,9 @@ zdoom
arg0 arg0
{ {
title = "Target MapSpot Tag"; title = "Target Teleport Dest. Tag";
type = 14; type = 14;
targetclasses = "MapSpot,MapSpotGravity"; targetclasses = "TeleportDest,TeleportDest2,TeleportDest3";
} }
arg1 arg1
{ {

View file

@ -41,6 +41,7 @@ namespace CodeImp.DoomBuilder
private DebugMessageType filters; private DebugMessageType filters;
private static long starttime = -1; private static long starttime = -1;
private static int counter;
private static DebugConsole me; private static DebugConsole me;
#endregion #endregion
@ -159,6 +160,24 @@ namespace CodeImp.DoomBuilder
starttime = -1; 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() public static void StartProfiler()
{ {
#if PROFILE #if PROFILE

View file

@ -590,7 +590,7 @@ namespace CodeImp.DoomBuilder.Data
palette = null; palette = null;
//mxd. Dispose models //mxd. Dispose models
foreach(KeyValuePair<int, ModelData> i in modeldefentries) i.Value.Dispose(); foreach(ModelData md in modeldefentries.Values) md.Dispose();
// Dispose containers // Dispose containers
foreach(DataReader c in containers) c.Dispose(); foreach(DataReader c in containers) c.Dispose();
@ -2052,7 +2052,7 @@ namespace CodeImp.DoomBuilder.Data
public void ReloadModeldef() public void ReloadModeldef()
{ {
if(modeldefentries != null) if(modeldefentries != null)
foreach(KeyValuePair<int, ModelData> group in modeldefentries) group.Value.Dispose(); foreach(ModelData md in modeldefentries.Values) md.Dispose();
// Bail out when not supported by current game configuration // Bail out when not supported by current game configuration
if(string.IsNullOrEmpty(General.Map.Config.DecorateGames)) return; if(string.IsNullOrEmpty(General.Map.Config.DecorateGames)) return;
@ -2105,15 +2105,13 @@ namespace CodeImp.DoomBuilder.Data
General.MainWindow.DisplayReady(); General.MainWindow.DisplayReady();
} }
//mxd. This parses modeldefs. Should be called after all DECORATE actors are parsed and actorsByClass dictionary created //mxd. This parses modeldefs. Should be called after all DECORATE actors are parsed
private void LoadModeldefs(Dictionary<string, int> actorsbyclass) private void LoadModeldefs(Dictionary<string, int> actorsbyclass)
{ {
//if no actors defined in DECORATE or game config... // Abort if no classnames are defined in DECORATE or game config...
if(actorsbyclass.Count == 0) return; if(actorsbyclass.Count == 0) return;
Dictionary<string, ModelData> modeldefentriesbyname = new Dictionary<string, ModelData>(StringComparer.Ordinal);
ModeldefParser parser = new ModeldefParser(actorsbyclass); ModeldefParser parser = new ModeldefParser(actorsbyclass);
foreach(DataReader dr in containers) foreach(DataReader dr in containers)
{ {
currentreader = dr; currentreader = dr;
@ -2122,30 +2120,21 @@ namespace CodeImp.DoomBuilder.Data
foreach(TextResourceData data in streams) foreach(TextResourceData data in streams)
{ {
// Parse the data // Parse the data
if(parser.Parse(data, true)) parser.Parse(data, true);
{
foreach(KeyValuePair<string, ModelData> g in parser.Entries)
{
if(modeldefentriesbyname.ContainsKey(g.Key))
General.ErrorLogger.Add(ErrorType.Warning, "Model definition for actor \"" + g.Key + "\" is double defined in \"" + Path.Combine(data.Source.Location.GetDisplayName(), data.Filename) + "\"");
modeldefentriesbyname[g.Key] = g.Value;
}
}
// Modeldefs are independable, so parsing fail in one file should not affect the others // Modeldefs are independable, so parsing fail in one file should not affect the others
if(parser.HasError) parser.LogError(); if(parser.HasError) parser.LogError();
} }
} }
//mxd. Add to text resources collection // Add to text resources collection
textresources[parser.ScriptType] = new HashSet<TextResource>(parser.TextResources.Values); textresources[parser.ScriptType] = new HashSet<TextResource>(parser.TextResources.Values);
currentreader = null; currentreader = null;
foreach(KeyValuePair<string, ModelData> e in modeldefentriesbyname) foreach(KeyValuePair<string, ModelData> e in parser.Entries)
{ {
if(actorsbyclass.ContainsKey(e.Key)) if(actorsbyclass.ContainsKey(e.Key))
modeldefentries[actorsbyclass[e.Key]] = modeldefentriesbyname[e.Key]; modeldefentries[actorsbyclass[e.Key]] = parser.Entries[e.Key];
else if(!decorate.ActorsByClass.ContainsKey(e.Key)) else if(!decorate.ActorsByClass.ContainsKey(e.Key))
General.ErrorLogger.Add(ErrorType.Warning, "MODELDEF model \"" + e.Key + "\" doesn't match any Decorate actor class"); General.ErrorLogger.Add(ErrorType.Warning, "MODELDEF model \"" + e.Key + "\" doesn't match any Decorate actor class");
} }
@ -2228,7 +2217,7 @@ namespace CodeImp.DoomBuilder.Data
} }
} }
//mxd. Add to text resources collection // Add to text resources collection
textresources[parser.ScriptType] = new HashSet<TextResource>(parser.TextResources.Values); textresources[parser.ScriptType] = new HashSet<TextResource>(parser.TextResources.Values);
currentreader = null; currentreader = null;

View file

@ -354,9 +354,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
int ofsEnd = br.ReadInt32(); //Relative offset from SURFACE_START to where the Surface object ends. int ofsEnd = br.ReadInt32(); //Relative offset from SURFACE_START to where the Surface object ends.
// Sanity check // Sanity check
if(frame < 0 || frame > numFrames) if(frame < 0 || frame >= numFrames)
{ {
return "invalid frame number! (frame number: " + frame + ", total frames: " + numFrames + ")"; return "frame " + frame + " is outside of model's frame range [0.." + (numFrames - 1) + "]";
} }
// Polygons // Polygons
@ -453,15 +453,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.MD3
int num_frames = br.ReadInt32(); //Total number of frames int num_frames = br.ReadInt32(); //Total number of frames
// Sanity checks // Sanity checks
if(num_frames == 0) if(frame < 0 || frame >= num_frames)
{ {
result.Errors = "model has 0 frames."; result.Errors = "frame " + frame + " is outside of model's frame range [0.." + (num_frames - 1) + "]";
return result;
}
if(num_frames < frame || frame < 0)
{
result.Errors = "invalid target frame! (target frame: " + frame + ", total frames: " + num_frames + ")";
return result; return result;
} }

View file

@ -1833,6 +1833,14 @@ namespace CodeImp.DoomBuilder.Geometry
((sd.LongMiddleTexture == texturelongname) && (sd.MiddleRequired() || sd.LongMiddleTexture != MapSet.EmptyLongName)) ; ((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 //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) public static float GetSidedefOffsetY(Sidedef side, VisualGeometryType part, float offset, float scaleY, bool fromNormalized)
{ {

View file

@ -1603,11 +1603,8 @@ namespace CodeImp.DoomBuilder.Rendering
public void RenderText(TextLabel label) public void RenderText(TextLabel label)
{ {
//mxd. Update the text if needed //mxd. Update the text if needed
RectangleF bbox = label.Update(translatex, translatey, scale, -scale); label.Update(translatex, translatey, scale, -scale);
if(label.SkipRendering) return;
//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;
// Set renderstates for rendering // Set renderstates for rendering
graphics.Device.SetRenderState(RenderState.CullMode, Cull.None); graphics.Device.SetRenderState(RenderState.CullMode, Cull.None);
@ -1637,18 +1634,8 @@ namespace CodeImp.DoomBuilder.Rendering
foreach(TextLabel label in labels) foreach(TextLabel label in labels)
{ {
// Update the text if needed // Update the text if needed
RectangleF bbox = label.Update(translatex, translatey, scale, -scale); label.Update(translatex, translatey, scale, -scale);
if(label.SkipRendering) skipped++;
// 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;
}
} }
if(labels.Count == skipped) return; if(labels.Count == skipped) return;

View file

@ -47,7 +47,6 @@ namespace CodeImp.DoomBuilder.Rendering
// Text settings // Text settings
private string text; private string text;
private RectangleF rect; private RectangleF rect;
private RectangleF absview; //mxd
private bool transformcoords; private bool transformcoords;
private PixelColor color; private PixelColor color;
private PixelColor backcolor; private PixelColor backcolor;
@ -64,6 +63,9 @@ namespace CodeImp.DoomBuilder.Rendering
private float lastscalex; private float lastscalex;
private float lastscaley; private float lastscaley;
//mxd. Rendering
private bool skiprendering;
// Disposing // Disposing
private bool isdisposed; 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 public bool DrawBackground { get { return drawbg; } set { if(drawbg != value) { drawbg = value; textureupdateneeded = true; } } } //mxd
internal Texture Texture { get { return texture; } } //mxd internal Texture Texture { get { return texture; } } //mxd
internal VertexBuffer VertexBuffer { get { return textbuffer; } } internal VertexBuffer VertexBuffer { get { return textbuffer; } }
internal bool SkipRendering; //mxd internal bool SkipRendering { get { return skiprendering; } } //mxd
// Disposing // Disposing
public bool IsDisposed { get { return isdisposed; } } public bool IsDisposed { get { return isdisposed; } }
@ -117,6 +119,10 @@ namespace CodeImp.DoomBuilder.Rendering
// Register as resource // Register as resource
General.Map.Graphics.RegisterResource(this); 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 // We have no destructor
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
@ -143,7 +149,7 @@ namespace CodeImp.DoomBuilder.Rendering
#region ================== Methods #region ================== Methods
// This updates the text if needed // 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 // Check if transformation changed and needs to be updated
if(transformcoords && (translatex != lasttranslatex || translatey != lasttranslatey || if(transformcoords && (translatex != lasttranslatex || translatey != lasttranslatey ||
@ -156,6 +162,36 @@ namespace CodeImp.DoomBuilder.Rendering
updateneeded = true; updateneeded = true;
} }
// Update if needed
if(updateneeded || textureupdateneeded)
{
// Only build when there are any vertices
if(text.Length > 0)
{
// Transform?
RectangleF absview;
if(transformcoords)
{
// Calculate absolute coordinates
Vector2D lt = new Vector2D(rect.Left, rect.Top);
Vector2D rb = new Vector2D(rect.Right, rect.Bottom);
lt = lt.GetTransformed(translatex, translatey, scalex, scaley);
rb = rb.GetTransformed(translatex, translatey, scalex, scaley);
absview = new RectangleF((float)Math.Round(lt.x), (float)Math.Round(lt.y), rb.x - lt.x, rb.y - lt.y);
}
else
{
// Fixed coordinates
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 //mxd. Update texture if needed
if(textureupdateneeded) if(textureupdateneeded)
{ {
@ -180,28 +216,6 @@ namespace CodeImp.DoomBuilder.Rendering
Pool.Managed, General.Map.Graphics.PostFilter, General.Map.Graphics.MipGenerateFilter, 0); Pool.Managed, General.Map.Graphics.PostFilter, General.Map.Graphics.MipGenerateFilter, 0);
} }
// Update if needed
if(updateneeded || textureupdateneeded)
{
// Only build when there are any vertices
if(text.Length > 0)
{
// Transform?
if(transformcoords)
{
// Calculate absolute coordinates
Vector2D lt = new Vector2D(rect.Left, rect.Top);
Vector2D rb = new Vector2D(rect.Right, rect.Bottom);
lt = lt.GetTransformed(translatex, translatey, scalex, scaley);
rb = rb.GetTransformed(translatex, translatey, scalex, scaley);
absview = new RectangleF((float)Math.Round(lt.x), (float)Math.Round(lt.y), rb.x - lt.x, rb.y - lt.y);
}
else
{
// Fixed coordinates
absview = rect;
}
// Align the text horizontally // Align the text horizontally
float beginx = 0; float beginx = 0;
switch(alignx) switch(alignx)
@ -220,14 +234,6 @@ namespace CodeImp.DoomBuilder.Rendering
case TextAlignmentY.Bottom: beginy = absview.Y + absview.Height - textsize.Height; break; 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 //mxd. Lock the buffer
using(DataStream stream = textbuffer.Lock(0, 4 * FlatVertex.Stride, LockFlags.Discard | LockFlags.NoSystemLock)) using(DataStream stream = textbuffer.Lock(0, 4 * FlatVertex.Stride, LockFlags.Discard | LockFlags.NoSystemLock))
{ {
@ -241,16 +247,14 @@ namespace CodeImp.DoomBuilder.Rendering
else else
{ {
// No faces in polygon // No faces in polygon
if(textbuffer != null) textbuffer.Dispose(); //mxd
textsize = new SizeF(); textsize = new SizeF();
skiprendering = true; //mxd
} }
// Text updated // Text updated
updateneeded = false; updateneeded = false;
textureupdateneeded = false; //mxd textureupdateneeded = false; //mxd
} }
return absview; //mxd
} }
//mxd //mxd

View file

@ -606,7 +606,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(requiredsize > group.Key.Labels[i].radius) if(requiredsize > group.Key.Labels[i].radius)
{ {
requiredsize = (General.Interface.MeasureString(group.Value[1], l.Font).Width / 2) / renderer.Scale; 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 else
{ {

View file

@ -197,6 +197,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
List<TextLabel> torender = new List<TextLabel>(orderedselection.Count); List<TextLabel> torender = new List<TextLabel>(orderedselection.Count);
foreach(Sector s in orderedselection) 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 // Render labels
TextLabel[] labelarray = labels[s]; TextLabel[] labelarray = labels[s];
float requiredsize = (labelarray[0].TextSize.Height / 2) / renderer.Scale; float requiredsize = (labelarray[0].TextSize.Height / 2) / renderer.Scale;
@ -238,7 +241,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(requiredsize > group.Key.Labels[i].radius) if(requiredsize > group.Key.Labels[i].radius)
{ {
requiredsize = (General.Interface.MeasureString(group.Value[1], l.Font).Width / 2) / renderer.Scale; 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 else
{ {

View file

@ -277,7 +277,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(requiredsize > group.Key.Labels[i].radius) if(requiredsize > group.Key.Labels[i].radius)
{ {
requiredsize = (General.Interface.MeasureString(group.Value[1], l.Font).Width / 2) / renderer.Scale; 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 else
{ {
@ -541,14 +544,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd. Update helper lines //mxd. Update helper lines
UpdateHelperObjects(); UpdateHelperObjects();
//mxd. Update selection info
UpdateSelectionInfo();
// Update display // Update display
General.Interface.RedrawDisplay(); General.Interface.RedrawDisplay();
} }
} }
} }
//mxd. Update selection info
UpdateSelectionInfo();
} }
editpressed = false; editpressed = false;
@ -964,9 +967,20 @@ namespace CodeImp.DoomBuilder.BuilderModes
Vector2D v = thing.Position; Vector2D v = thing.Position;
TextLabel l = new TextLabel(); TextLabel l = new TextLabel();
l.TransformCoords = true; l.TransformCoords = true;
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.Rectangle = new RectangleF(v.x - thing.Size + 1, v.y + thing.Size - 1, 0f, 0f);
l.AlignX = TextAlignmentX.Left; l.AlignX = TextAlignmentX.Left;
l.AlignY = TextAlignmentY.Top; l.AlignY = TextAlignmentY.Top;
}
l.Color = (thing == highlighted ? General.Colors.Selection : General.Colors.Highlight); l.Color = (thing == highlighted ? General.Colors.Selection : General.Colors.Highlight);
l.Backcolor = General.Colors.Background.WithAlpha(255); l.Backcolor = General.Colors.Background.WithAlpha(255);
l.DrawBackground = true; l.DrawBackground = true;

View file

@ -3732,6 +3732,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
first.controlSide = start.Sidedef; first.controlSide = start.Sidedef;
} }
//mxd
HashSet<long> texturehashes = new HashSet<long> { texture.LongName };
first.forward = true; first.forward = true;
todo.Push(first); todo.Push(first);
@ -3761,11 +3764,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Add sidedefs forward (connected to the right vertex) // Add sidedefs forward (connected to the right vertex)
Vertex v = j.sidedef.IsFront ? j.sidedef.Line.End : j.sidedef.Line.Start; 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) // Add sidedefs backward (connected to the left vertex)
v = j.sidedef.IsFront ? j.sidedef.Line.Start : j.sidedef.Line.End; 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 else
{ {
@ -3787,11 +3790,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Add sidedefs backward (connected to the left vertex) // Add sidedefs backward (connected to the left vertex)
Vertex v = j.sidedef.IsFront ? j.sidedef.Line.Start : j.sidedef.Line.End; 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) // Add sidedefs forward (connected to the right vertex)
v = j.sidedef.IsFront ? j.sidedef.Line.End : j.sidedef.Line.Start; 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);
} }
} }
} }
@ -3821,6 +3824,24 @@ namespace CodeImp.DoomBuilder.BuilderModes
else else
first.controlSide = start.Sidedef; 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 //mxd
List<BaseVisualGeometrySidedef> selectedVisualSides = new List<BaseVisualGeometrySidedef>(); List<BaseVisualGeometrySidedef> selectedVisualSides = new List<BaseVisualGeometrySidedef>();
if(checkSelectedSidedefParts && !singleselection) if(checkSelectedSidedefParts && !singleselection)
@ -3904,9 +3925,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Get the align job to do // Get the align job to do
SidedefAlignJob j = todo.Pop(); SidedefAlignJob j = todo.Pop();
bool matchtop = (!j.sidedef.Marked && (!singleselection || j.sidedef.LongHighTexture == texture.LongName) && j.sidedef.HighRequired()); bool matchtop = (!j.sidedef.Marked && (!singleselection || texturehashes.Contains(j.sidedef.LongHighTexture)) && j.sidedef.HighRequired());
bool matchbottom = (!j.sidedef.Marked && (!singleselection || j.sidedef.LongLowTexture == texture.LongName) && j.sidedef.LowRequired()); bool matchbottom = (!j.sidedef.Marked && (!singleselection || texturehashes.Contains(j.sidedef.LongLowTexture)) && j.sidedef.LowRequired());
bool matchmid = ((!singleselection || j.controlSide.LongMiddleTexture == texture.LongName) && (j.controlSide.MiddleRequired() || j.controlSide.LongMiddleTexture != MapSet.EmptyLongName)); //mxd 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 //mxd. If there's a selection, check if matched part is actually selected
if(checkSelectedSidedefParts && !singleselection) if(checkSelectedSidedefParts && !singleselection)
@ -4037,11 +4058,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Add sidedefs backward (connected to the left vertex) // Add sidedefs backward (connected to the left vertex)
v = j.sidedef.IsFront ? j.sidedef.Line.Start : j.sidedef.Line.End; 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) // Add sidedefs forward (connected to the right vertex)
v = j.sidedef.IsFront ? j.sidedef.Line.End : j.sidedef.Line.Start; 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 else
{ {
@ -4133,17 +4154,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Add sidedefs forward (connected to the right vertex) // Add sidedefs forward (connected to the right vertex)
v = j.sidedef.IsFront ? j.sidedef.Line.End : j.sidedef.Line.Start; 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) // Add sidedefs backward (connected to the left vertex)
v = j.sidedef.IsFront ? j.sidedef.Line.Start : j.sidedef.Line.End; 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 // 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) foreach(Linedef ld in v.Linedefs)
{ {
@ -4156,7 +4177,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
foreach(Sidedef s in controlSides) foreach(Sidedef s in controlSides)
{ {
if(!singleselection || Tools.SidedefTextureMatch(s, texturelongname)) if(!singleselection || Tools.SidedefTextureMatch(s, texturelongnames))
{ {
SidedefAlignJob nj = new SidedefAlignJob(); SidedefAlignJob nj = new SidedefAlignJob();
nj.forward = forward; nj.forward = forward;
@ -4174,7 +4195,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
foreach(Sidedef s in controlSides) foreach(Sidedef s in controlSides)
{ {
if(!singleselection || Tools.SidedefTextureMatch(s, texturelongname)) if(!singleselection || Tools.SidedefTextureMatch(s, texturelongnames))
{ {
SidedefAlignJob nj = new SidedefAlignJob(); SidedefAlignJob nj = new SidedefAlignJob();
nj.forward = forward; nj.forward = forward;

View file

@ -239,6 +239,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(translucent && !othertranslucent && !ef.ClipSidedefs) continue; if(translucent && !othertranslucent && !ef.ClipSidedefs) continue;
if(ef.ClipSidedefs == extrafloor.ClipSidedefs || ef.ClipSidedefs) 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; int num = polygons.Count;
for(int pi = 0; pi < num; pi++) for(int pi = 0; pi < num; pi++)
{ {