Added, Visual mode: "Increase/Decrease Scale", "Reset Texture Offsets" and "Reset Local Texture Offsets" actions now work when used on 3d floor sides.

Fixed: CVARINFO parser was unable to parse negative int/float values.
Fixed: in some cases TextLabel text size was checked before it was calculated. 
Internal, Visual mode: reduced the number of unnecessary geometry updates when changing map geometry.
Updated ZDoom_DECORATE.cfg (atan2 and VectorAngle).
This commit is contained in:
MaxED 2016-04-19 20:40:42 +00:00
parent 38105c4b98
commit 3eb05509af
21 changed files with 523 additions and 629 deletions

View file

@ -386,15 +386,6 @@ keywords
A_SPosAttackUseAtkSound = "A_SPosAttackUseAtkSound"; A_SPosAttackUseAtkSound = "A_SPosAttackUseAtkSound";
//Mathematical functions //Mathematical functions
abs = "abs(x)\nReturns the absolute value of x."; abs = "abs(x)\nReturns the absolute value of x.";
sin = "sin(x)\nTrigonometry function, x must be in degrees.";
cos = "cos(x)\nTrigonometry function, x must be in degrees.";
tan = "tan(x)\nTrigonometry function, x must be in degrees.";
asin = "asin(x)\nTrigonometry function, returns an angle in degrees.";
acos = "acos(x)\nTrigonometry function, returns an angle in degrees.";
atan = "atan(x)\nTrigonometry function, returns an angle in degrees.";
sinh = "sinh(x)\nTrigonometry function, x must be in radians.";
cosh = "cosh(x)\nTrigonometry function, x must be in radians.";
tanh = "tanh(x)\nTrigonometry function, x must be in radians.";
exp = "exp(x)\nReturns the base-e exponential function of x, which is e raised to the power x."; exp = "exp(x)\nReturns the base-e exponential function of x, which is e raised to the power x.";
log = "log(x)\nReturns the natural logarithm of x - the opposite of exp."; log = "log(x)\nReturns the natural logarithm of x - the opposite of exp.";
log10 = "log10(x)\nReturns the common (base-10) logarithm of x."; log10 = "log10(x)\nReturns the common (base-10) logarithm of x.";
@ -404,6 +395,18 @@ keywords
min = "min(x1, ...)\nGets the smallest value of all values listed.\nCan take any amount of numbers, and can solve both ints and floats."; min = "min(x1, ...)\nGets the smallest value of all values listed.\nCan take any amount of numbers, and can solve both ints and floats.";
max = "max(x1, ...)\nGets the largest value of all values listed.\nCan take any amount of numbers, and can solve both ints and floats."; max = "max(x1, ...)\nGets the largest value of all values listed.\nCan take any amount of numbers, and can solve both ints and floats.";
clamp = "clamp(src, min, max)\nReturns src within the range of min and max inclusively. All parameters can be ints or floats."; clamp = "clamp(src, min, max)\nReturns src within the range of min and max inclusively. All parameters can be ints or floats.";
//Trigonometry functions
sin = "sin(x)\nTrigonometry function, x must be in degrees.";
cos = "cos(x)\nTrigonometry function, x must be in degrees.";
tan = "tan(x)\nTrigonometry function, x must be in degrees.";
asin = "asin(x)\nTrigonometry function, returns an angle in degrees.";
acos = "acos(x)\nTrigonometry function, returns an angle in degrees.";
atan = "atan(x)\nTrigonometry function, returns an angle in degrees.";
sinh = "sinh(x)\nTrigonometry function, x must be in radians.";
cosh = "cosh(x)\nTrigonometry function, x must be in radians.";
tanh = "tanh(x)\nTrigonometry function, x must be in radians.";
atan2 = "atan2(y, x)\nTrigonometry function, Returns an angle in degrees.";
VectorAngle = "VectorAngle(x, y)\nTrigonometry function.";
//Randum number functions //Randum number functions
random = "int random[identifier](min, max)\nReturns a random integer value between min and max."; random = "int random[identifier](min, max)\nReturns a random integer value between min and max.";
random2 = "int random2[identifier](mask)\nReturns a random integer value between -mask and +mask."; random2 = "int random2[identifier](mask)\nReturns a random integer value between -mask and +mask.";

View file

@ -46,15 +46,20 @@ namespace CodeImp.DoomBuilder.Rendering
// Text settings // Text settings
private string text; private string text;
private RectangleF rect; private Vector2D location; //mxd
private bool transformcoords; private bool transformcoords;
private PixelColor color; private PixelColor color;
private PixelColor backcolor; private PixelColor backcolor;
private TextAlignmentX alignx; private TextAlignmentX alignx;
private TextAlignmentY aligny; private TextAlignmentY aligny;
private bool drawbg; //mxd
//mxd. Label image settings...
private SizeF textsize; private SizeF textsize;
private Size texturesize; private Size texturesize;
private bool drawbg; //mxd private RectangleF textrect;
private RectangleF bgrect;
private PointF textorigin;
// This keeps track if changes were made // This keeps track if changes were made
private bool updateneeded; private bool updateneeded;
@ -75,15 +80,9 @@ namespace CodeImp.DoomBuilder.Rendering
#region ================== Properties #region ================== Properties
// Properties // Properties
public RectangleF Rectangle { get { return rect; } set { rect = value; updateneeded = true; } } public Vector2D Location { get { return location; } set { location = value; updateneeded = true; } } //mxd
public float Left { get { return rect.X; } set { rect.X = value; updateneeded = true; } } public string Text { get { return text; } set { if(text != value) { text = value; textsize = Size.Empty; textureupdateneeded = true; } } }
public float Top { get { return rect.Y; } set { rect.Y = value; updateneeded = true; } } public Font Font { get { return font; } set { font = value; textsize = Size.Empty; textureupdateneeded = true; } } //mxd
public float Width { get { return rect.Width; } set { rect.Width = value; updateneeded = true; } }
public float Height { get { return rect.Height; } set { rect.Height = value; updateneeded = true; } }
public float Right { get { return rect.Right; } set { rect.Width = value - rect.X + 1f; updateneeded = true; } }
public float Bottom { get { return rect.Bottom; } set { rect.Height = value - rect.Y + 1f; updateneeded = true; } }
public string Text { get { return text; } set { if(text != value) { text = value; textureupdateneeded = true; } } }
public Font Font { get { return font; } set { font = value; textureupdateneeded = true; } } //mxd
public bool TransformCoords { get { return transformcoords; } set { transformcoords = value; updateneeded = true; } } public bool TransformCoords { get { return transformcoords; } set { transformcoords = value; updateneeded = true; } }
public SizeF TextSize { get { if(textureupdateneeded) Update(General.Map.Renderer2D.TranslateX, General.Map.Renderer2D.TranslateY, General.Map.Renderer2D.Scale, -General.Map.Renderer2D.Scale); return textsize; } } public SizeF TextSize { get { if(textureupdateneeded) Update(General.Map.Renderer2D.TranslateX, General.Map.Renderer2D.TranslateY, General.Map.Renderer2D.Scale, -General.Map.Renderer2D.Scale); return textsize; } }
public TextAlignmentX AlignX { get { return alignx; } set { alignx = value; updateneeded = true; } } public TextAlignmentX AlignX { get { return alignx; } set { alignx = value; updateneeded = true; } }
@ -108,12 +107,13 @@ namespace CodeImp.DoomBuilder.Rendering
// Initialize // Initialize
this.text = ""; this.text = "";
this.font = General.Settings.TextLabelFont; //mxd this.font = General.Settings.TextLabelFont; //mxd
this.rect = new RectangleF(0f, 0f, 1f, 1f); this.location = new Vector2D(); //mxd
this.color = new PixelColor(255, 255, 255, 255); this.color = new PixelColor(255, 255, 255, 255);
this.backcolor = new PixelColor(128, 0, 0, 0); this.backcolor = new PixelColor(128, 0, 0, 0);
this.alignx = TextAlignmentX.Center; this.alignx = TextAlignmentX.Center;
this.aligny = TextAlignmentY.Top; this.aligny = TextAlignmentY.Top;
this.textsize = new SizeF(); this.textsize = SizeF.Empty; //mxd
this.texturesize = Size.Empty; //mxd
this.updateneeded = true; this.updateneeded = true;
this.textureupdateneeded = true; //mxd this.textureupdateneeded = true; //mxd
@ -166,25 +166,59 @@ namespace CodeImp.DoomBuilder.Rendering
if(text.Length > 0) if(text.Length > 0)
{ {
// Transform? // Transform?
RectangleF absview; Vector2D abspos = (transformcoords ? location.GetTransformed(translatex, translatey, scalex, scaley) : location);
if(transformcoords)
// Update text and texture sizes
if(textsize.IsEmpty || texturesize.IsEmpty)
{ {
// Calculate absolute coordinates textorigin = new PointF(4, 3);
Vector2D lt = new Vector2D(rect.Left, rect.Top); textrect = new RectangleF(textorigin, General.Interface.MeasureString(text, font));
Vector2D rb = new Vector2D(rect.Right, rect.Bottom); textrect.Width = (float)Math.Round(textrect.Width);
lt = lt.GetTransformed(translatex, translatey, scalex, scaley); textrect.Height = (float)Math.Round(textrect.Height);
rb = rb.GetTransformed(translatex, translatey, scalex, scaley); bgrect = new RectangleF(0, 0, textrect.Width + textorigin.X * 2, textrect.Height + textorigin.Y * 2);
absview = new RectangleF((float)Math.Round(lt.x), (float)Math.Round(lt.y), rb.x - lt.x, rb.y - lt.y);
// Store calculated text size...
textsize = new SizeF(textrect.Width + textorigin.X * 2, textrect.Height + textorigin.Y * 2);
// Make PO2 image, for speed and giggles...
texturesize = new Size(General.NextPowerOf2((int)textsize.Width), General.NextPowerOf2((int)textsize.Height));
switch(alignx)
{
case TextAlignmentX.Center: bgrect.X = (texturesize.Width - bgrect.Width) / 2; break;
case TextAlignmentX.Right: bgrect.X = texturesize.Width - bgrect.Width; break;
} }
else
switch(aligny)
{ {
// Fixed coordinates case TextAlignmentY.Middle: bgrect.Y = (texturesize.Height - bgrect.Height) / 2; break;
absview = rect; case TextAlignmentY.Bottom: bgrect.Y = texturesize.Height - bgrect.Height; break;
}
textrect.X += bgrect.X;
textrect.Y += bgrect.Y;
}
// Align the text horizontally
float beginx = 0;
switch(alignx)
{
case TextAlignmentX.Left: beginx = abspos.x; break;
case TextAlignmentX.Center: beginx = abspos.x - texturesize.Width * 0.5f; break;
case TextAlignmentX.Right: beginx = abspos.x - texturesize.Width; break;
}
// Align the text vertically
float beginy = 0;
switch(aligny)
{
case TextAlignmentY.Top: beginy = abspos.y; break;
case TextAlignmentY.Middle: beginy = abspos.y - texturesize.Height * 0.5f; break;
case TextAlignmentY.Bottom: beginy = abspos.y - texturesize.Height; break;
} }
//mxd. Skip when not on screen... //mxd. Skip when not on screen...
RectangleF abssize = absview; RectangleF abssize = new RectangleF(beginx, beginy, texturesize.Width, texturesize.Height);
abssize.Inflate(textsize.Width / 2, textsize.Height / 2);
Size windowsize = General.Map.Graphics.RenderTarget.ClientSize; Size windowsize = General.Map.Graphics.RenderTarget.ClientSize;
skiprendering = (abssize.Right < 0.1f) || (abssize.Left > windowsize.Width) || (abssize.Bottom < 0.1f) || (abssize.Top > windowsize.Height); skiprendering = (abssize.Right < 0.1f) || (abssize.Left > windowsize.Width) || (abssize.Bottom < 0.1f) || (abssize.Top > windowsize.Height);
if(skiprendering) return; if(skiprendering) return;
@ -200,8 +234,8 @@ namespace CodeImp.DoomBuilder.Rendering
} }
// Create label image // Create label image
Bitmap img = CreateLabelImage(text, font, alignx, aligny, color, backcolor, drawbg, out textsize); Bitmap img = CreateLabelImage(text, font, color, backcolor, drawbg, textrect, bgrect, texturesize, textorigin);
texturesize = img.Size; //texturesize = img.Size;
// Create texture // Create texture
MemoryStream memstream = new MemoryStream((img.Size.Width * img.Size.Height * 4) + 4096); MemoryStream memstream = new MemoryStream((img.Size.Width * img.Size.Height * 4) + 4096);
@ -213,24 +247,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);
} }
// Align the text horizontally
float beginx = 0;
switch(alignx)
{
case TextAlignmentX.Left: beginx = absview.X; break;
case TextAlignmentX.Center: beginx = absview.X + (absview.Width - texturesize.Width) * 0.5f; break;
case TextAlignmentX.Right: beginx = absview.X + absview.Width - texturesize.Width; break;
}
// Align the text vertically
float beginy = 0;
switch(aligny)
{
case TextAlignmentY.Top: beginy = absview.Y; break;
case TextAlignmentY.Middle: beginy = absview.Y + (absview.Height - texturesize.Height) * 0.5f; break;
case TextAlignmentY.Bottom: beginy = absview.Y + absview.Height - texturesize.Height; break;
}
//mxd. Create the buffer //mxd. Create the buffer
if(textbuffer == null || textbuffer.Disposed) if(textbuffer == null || textbuffer.Disposed)
{ {
@ -251,7 +267,8 @@ namespace CodeImp.DoomBuilder.Rendering
else else
{ {
// No faces in polygon // No faces in polygon
textsize = new SizeF(); textsize = SizeF.Empty; //mxd
texturesize = Size.Empty; //mxd
skiprendering = true; //mxd skiprendering = true; //mxd
} }
@ -262,36 +279,9 @@ namespace CodeImp.DoomBuilder.Rendering
} }
//mxd //mxd
private static Bitmap CreateLabelImage(string text, Font font, TextAlignmentX alignx, TextAlignmentY aligny, PixelColor color, PixelColor backcolor, bool drawbg, out SizeF textsize) private static Bitmap CreateLabelImage(string text, Font font, PixelColor color, PixelColor backcolor, bool drawbg, RectangleF textrect, RectangleF bgrect, Size texturesize, PointF textorigin)
{ {
PointF textorigin = new PointF(4, 3); Bitmap result = new Bitmap(texturesize.Width, texturesize.Height);
RectangleF textrect = new RectangleF(textorigin, General.Interface.MeasureString(text, font));
textrect.Width = (float)Math.Round(textrect.Width);
textrect.Height = (float)Math.Round(textrect.Height);
RectangleF bgrect = new RectangleF(0, 0, textrect.Width + textorigin.X * 2, textrect.Height + textorigin.Y * 2);
// Store calculated text size...
textsize = new SizeF(bgrect.Width, bgrect.Height);
// Make PO2 image, for speed and giggles...
RectangleF po2rect = new RectangleF(0, 0, General.NextPowerOf2((int)bgrect.Width), General.NextPowerOf2((int)bgrect.Height));
switch(alignx)
{
case TextAlignmentX.Center: bgrect.X = (po2rect.Width - bgrect.Width) / 2; break;
case TextAlignmentX.Right: bgrect.X = po2rect.Width - bgrect.Width; break;
}
switch(aligny)
{
case TextAlignmentY.Middle: bgrect.Y = (po2rect.Height - bgrect.Height) / 2; break;
case TextAlignmentY.Bottom: bgrect.Y = po2rect.Height - bgrect.Height; break;
}
textrect.X += bgrect.X;
textrect.Y += bgrect.Y;
Bitmap result = new Bitmap((int)po2rect.Width, (int)po2rect.Height);
using(Graphics g = Graphics.FromImage(result)) using(Graphics g = Graphics.FromImage(result))
{ {
g.SmoothingMode = SmoothingMode.HighQuality; g.SmoothingMode = SmoothingMode.HighQuality;

View file

@ -132,7 +132,7 @@ namespace CodeImp.DoomBuilder.ZDoom
{ {
case "int": case "int":
int iv = 0; int iv = 0;
if(!string.IsNullOrEmpty(value) && !int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out iv)) if(!string.IsNullOrEmpty(value) && !ReadSignedInt(value, ref iv))
{ {
ReportError("Cvar \"" + name + "\" has invalid integer value: \"" + value + "\""); ReportError("Cvar \"" + name + "\" has invalid integer value: \"" + value + "\"");
return false; return false;
@ -146,7 +146,7 @@ namespace CodeImp.DoomBuilder.ZDoom
case "float": case "float":
float fv = 0f; float fv = 0f;
if(!string.IsNullOrEmpty(value) && !float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out fv)) if(!string.IsNullOrEmpty(value) && !ReadSignedFloat(value, ref fv))
{ {
ReportError("Cvar \"" + name + "\" has invalid decimal value: \"" + value + "\""); ReportError("Cvar \"" + name + "\" has invalid decimal value: \"" + value + "\"");
return false; return false;

View file

@ -388,10 +388,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
TextLabel[] larr = new TextLabel[s.Labels.Count]; TextLabel[] larr = new TextLabel[s.Labels.Count];
for(int i = 0; i < s.Labels.Count; i++) for(int i = 0; i < s.Labels.Count; i++)
{ {
Vector2D v = s.Labels[i].position;
TextLabel l = new TextLabel(); TextLabel l = new TextLabel();
l.TransformCoords = true; l.TransformCoords = true;
l.Rectangle = new RectangleF(v.x, v.y, 0.0f, 0.0f); l.Location = s.Labels[i].position;
l.AlignX = TextAlignmentX.Center; l.AlignX = TextAlignmentX.Center;
l.AlignY = TextAlignmentY.Middle; l.AlignY = TextAlignmentY.Middle;
l.Color = General.Colors.InfoLine; l.Color = General.Colors.InfoLine;

View file

@ -153,10 +153,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
TextLabel[] labelarray = new TextLabel[s.Labels.Count]; TextLabel[] labelarray = new TextLabel[s.Labels.Count];
for(int i = 0; i < s.Labels.Count; i++) for(int i = 0; i < s.Labels.Count; i++)
{ {
Vector2D v = s.Labels[i].position;
labelarray[i] = new TextLabel(); labelarray[i] = new TextLabel();
labelarray[i].TransformCoords = true; labelarray[i].TransformCoords = true;
labelarray[i].Rectangle = new RectangleF(v.x, v.y, 0.0f, 0.0f); labelarray[i].Location = s.Labels[i].position;
labelarray[i].AlignX = TextAlignmentX.Center; labelarray[i].AlignX = TextAlignmentX.Center;
labelarray[i].AlignY = TextAlignmentY.Middle; labelarray[i].AlignY = TextAlignmentY.Middle;
labelarray[i].Color = c; labelarray[i].Color = c;

View file

@ -929,10 +929,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
TextLabel[] larr = new TextLabel[s.Labels.Count]; TextLabel[] larr = new TextLabel[s.Labels.Count];
for(int i = 0; i < s.Labels.Count; i++) for(int i = 0; i < s.Labels.Count; i++)
{ {
Vector2D v = s.Labels[i].position;
TextLabel l = new TextLabel(); TextLabel l = new TextLabel();
l.TransformCoords = true; l.TransformCoords = true;
l.Rectangle = new RectangleF(v.x, v.y, 0.0f, 0.0f); l.Location = s.Labels[i].position;
l.AlignX = TextAlignmentX.Center; l.AlignX = TextAlignmentX.Center;
l.AlignY = TextAlignmentY.Middle; l.AlignY = TextAlignmentY.Middle;
l.Color = General.Colors.InfoLine; l.Color = General.Colors.InfoLine;
@ -964,19 +963,18 @@ namespace CodeImp.DoomBuilder.BuilderModes
labels = new Dictionary<Thing, TextLabel>(orderedselection.Count); labels = new Dictionary<Thing, TextLabel>(orderedselection.Count);
foreach(Thing thing in orderedselection) foreach(Thing thing in orderedselection)
{ {
Vector2D v = thing.Position;
TextLabel l = new TextLabel(); TextLabel l = new TextLabel();
l.TransformCoords = true; l.TransformCoords = true;
if(thing.FixedSize) if(thing.FixedSize)
{ {
l.Rectangle = new RectangleF(v.x, v.y, 0f, 0f); l.Location = thing.Position;
l.AlignX = TextAlignmentX.Center; l.AlignX = TextAlignmentX.Center;
l.AlignY = TextAlignmentY.Middle; l.AlignY = TextAlignmentY.Middle;
} }
else else
{ {
l.Rectangle = new RectangleF(v.x - thing.Size + 1, v.y + thing.Size - 1, 0f, 0f); l.Location = new Vector2D(thing.Position.x - thing.Size + 1, thing.Position.y + thing.Size - 1);
l.AlignX = TextAlignmentX.Left; l.AlignX = TextAlignmentX.Left;
l.AlignY = TextAlignmentY.Top; l.AlignY = TextAlignmentY.Top;
} }

View file

@ -32,7 +32,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
bool endvisible = viewport.Contains(end.x, end.y); bool endvisible = viewport.Contains(end.x, end.y);
// Get visile area // Get visile area
RectangleF labelrect;
if(!startvisible || !endvisible) if(!startvisible || !endvisible)
{ {
float minx = Math.Min(start.x, end.x); float minx = Math.Min(start.x, end.x);
@ -42,16 +41,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
RectangleF labelarea = new RectangleF(minx, miny, maxx - minx, maxy - miny); RectangleF labelarea = new RectangleF(minx, miny, maxx - minx, maxy - miny);
labelarea.Intersect(viewport); labelarea.Intersect(viewport);
labelrect = new RectangleF(labelarea.X + labelarea.Width * 0.5f, labelarea.Y + labelarea.Height * 0.5f, 0f, 0f); label.Location = new Vector2D(labelarea.X + labelarea.Width * 0.5f, labelarea.Y + labelarea.Height * 0.5f);
} }
else else
{ {
Vector2D delta = end - start; Vector2D delta = end - start;
labelrect = new RectangleF(start.x + delta.x * 0.5f, start.y + delta.y * 0.5f, 0f, 0f);
}
// Apply changes label.Location = new Vector2D(start.x + delta.x * 0.5f, start.y + delta.y * 0.5f);
label.Rectangle = labelrect; }
} }
} }
} }

View file

@ -204,7 +204,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Apply changes // Apply changes
Vector2D delta = end - start; Vector2D delta = end - start;
label.Rectangle = new RectangleF(start.x + delta.x * 0.5f, start.y + delta.y * 0.5f, 0f, 0f); label.Location = new Vector2D(start.x + delta.x * 0.5f, start.y + delta.y * 0.5f);
} }
#endregion #endregion

View file

@ -231,44 +231,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
return level.sector; return level.sector;
} }
//mxd
protected void OnTextureChanged()
{
// Effects may need updating...
mode.RebuildElementData();
// As well as sky render flag...
UpdateSkyRenderFlag();
if(level.sector == this.Sector.Sector)
{
this.Setup();
// 3D floors may need updating...
foreach(Sidedef s in level.sector.Sidedefs)
{
if(s.Line.Action == 160 && s.Line.Front != null)
{
int sectortag = ((General.Map.UDMF || (s.Line.Args[1] & 8) != 0) ? s.Line.Args[0] : s.Line.Args[0] + (s.Line.Args[4] << 8));
foreach(Sector sector in General.Map.Map.Sectors)
{
if(sector.Tags.Contains(sectortag))
{
BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(sector);
vs.UpdateSectorGeometry(false);
}
}
}
}
}
// As well as this sector's geometry
else if(mode.VisualSectorExists(level.sector))
{
BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(level.sector);
vs.UpdateSectorGeometry(false);
}
}
//mxd //mxd
public virtual bool IsSelected() public virtual bool IsSelected()
{ {
@ -449,18 +411,29 @@ namespace CodeImp.DoomBuilder.BuilderModes
mode.CreateUndo(undodescription); mode.CreateUndo(undodescription);
mode.SetActionResult(resultdescription); mode.SetActionResult(resultdescription);
Sector.Sector.Fields.BeforeFieldsChange(); level.sector.Fields.BeforeFieldsChange();
foreach(string key in keys) foreach(string key in keys)
{ {
if(Sector.Sector.Fields.ContainsKey(key)) if(level.sector.Fields.ContainsKey(key))
{ {
Sector.Sector.Fields.Remove(key); level.sector.Fields.Remove(key);
Sector.Sector.UpdateNeeded = true; level.sector.UpdateNeeded = true;
} }
} }
if(Sector.Sector.UpdateNeeded) Sector.UpdateSectorGeometry(false); if(level.sector.UpdateNeeded)
{
if(level.sector != Sector.Sector && mode.VisualSectorExists(level.sector))
{
BaseVisualSector vs = (BaseVisualSector) mode.GetVisualSector(level.sector);
vs.UpdateSectorGeometry(false);
}
else
{
Sector.UpdateSectorGeometry(false);
}
}
} }
#endregion #endregion
@ -576,7 +549,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(mode.VisualSectorExists(level.sector)) if(mode.VisualSectorExists(level.sector))
{ {
BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(level.sector); BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(level.sector);
vs.UpdateSectorGeometry(true); vs.UpdateSectorGeometry(false);
} }
} }
@ -720,23 +693,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
mode.CreateUndo("Paste sector properties"); mode.CreateUndo("Paste sector properties");
mode.SetActionResult("Pasted sector properties."); mode.SetActionResult("Pasted sector properties.");
//mxd. Glow effect may require SectorData update
bool oldfloortextureglows = (SectorProperties.CopySettings.FloorTexture && General.Map.Data.GlowingFlats.ContainsKey(level.sector.LongFloorTexture));
bool oldceiltextureglows = (SectorProperties.CopySettings.CeilingTexture && General.Map.Data.GlowingFlats.ContainsKey(level.sector.LongCeilTexture));
//mxd. Added "usecopysettings" //mxd. Added "usecopysettings"
BuilderPlug.Me.CopiedSectorProps.Apply(level.sector, usecopysettings); BuilderPlug.Me.CopiedSectorProps.Apply(level.sector, usecopysettings);
//mxd. Glow effect may require SectorData update
if(oldfloortextureglows || oldceiltextureglows
|| (SectorProperties.CopySettings.FloorTexture && General.Map.Data.GlowingFlats.ContainsKey(level.sector.LongFloorTexture))
|| (SectorProperties.CopySettings.CeilingTexture && General.Map.Data.GlowingFlats.ContainsKey(level.sector.LongCeilTexture)))
{
mode.RebuildElementData();
SectorData sd = mode.GetSectorData(level.sector);
sd.UpdateForced();
}
if(mode.VisualSectorExists(level.sector)) if(mode.VisualSectorExists(level.sector))
{ {
BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(level.sector); BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(level.sector);
@ -766,7 +725,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
mode.CreateUndo("Change flat \"" + texture + "\""); mode.CreateUndo("Change flat \"" + texture + "\"");
SetTexture(texture); SetTexture(texture);
OnTextureChanged(); //mxd
// Update
if(mode.VisualSectorExists(level.sector))
{
BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(level.sector);
vs.UpdateSectorGeometry(false);
}
} }
// Copy texture // Copy texture
@ -837,8 +802,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
else else
{ {
//mxd. Need this to apply changes to 3d-floor even if control sector doesn't exist //mxd. Need this to apply changes to 3d-floor even if control sector doesn't exist as BaseVisualSector
//as BaseVisualSector
vs = mode.CreateBaseVisualSector(level.sector); vs = mode.CreateBaseVisualSector(level.sector);
} }

View file

@ -66,7 +66,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
private bool performautoselection; //mxd private bool performautoselection; //mxd
// Undo/redo // Undo/redo
private int undoticket; protected int undoticket;
#endregion #endregion
@ -532,26 +532,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
return result; return result;
} }
//mxd
private void OnTextureChanged()
{
//check for 3d floors
if(Sidedef.Line.Action == 160)
{
int sectortag = ((General.Map.UDMF || (Sidedef.Line.Args[1] & 8) != 0) ? Sidedef.Line.Args[0] : Sidedef.Line.Args[0] + (Sidedef.Line.Args[4] << 8));
if(sectortag == 0) return;
foreach(Sector sector in General.Map.Map.Sectors)
{
if(sector.Tags.Contains(sectortag))
{
BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(sector);
vs.UpdateSectorGeometry(true);
}
}
}
}
//mxd //mxd
public void SelectNeighbours(bool select, bool matchtexture, bool matchheight) public void SelectNeighbours(bool select, bool matchtexture, bool matchheight)
{ {
@ -594,7 +574,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd //mxd
private void SelectNeighbourSideParts(Sidedef side, Rectangle sourcerect, bool select, bool matchtexture, bool matchheight) private void SelectNeighbourSideParts(Sidedef side, Rectangle sourcerect, bool select, bool matchtexture, bool matchheight)
{ {
BaseVisualSector s = mode.GetVisualSector(side.Sector) as BaseVisualSector; BaseVisualSector s = (BaseVisualSector)mode.GetVisualSector(side.Sector);
if(s != null) if(s != null)
{ {
VisualSidedefParts parts = s.GetSidedefParts(side); VisualSidedefParts parts = s.GetSidedefParts(side);
@ -778,7 +758,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Update // Update
VisualSector othersector = mode.GetVisualSector(Sidedef.Other.Sector); VisualSector othersector = mode.GetVisualSector(Sidedef.Other.Sector);
if(othersector is BaseVisualSector) (othersector as BaseVisualSector).Changed = true; if(othersector is BaseVisualSector) ((BaseVisualSector)othersector).Changed = true;
} }
} }
} }
@ -791,8 +771,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
mode.SetActionResult("Deleted a texture."); mode.SetActionResult("Deleted a texture.");
SetTexture("-"); SetTexture("-");
// Update //mxd. Update linked effects
Sector.UpdateSectorGeometry(true); SectorData sd = mode.GetSectorDataEx(Sector.Sector);
if(sd != null) sd.Reset(true);
} }
// Processing // Processing
@ -871,13 +852,30 @@ namespace CodeImp.DoomBuilder.BuilderModes
ResetTextureScale(); ResetTextureScale();
// And brightness // And brightness
if(Sidedef.Fields.ContainsKey("light")) Sidedef.Fields.Remove("light"); bool setupallparts = false;
if(Sidedef.Fields.ContainsKey("lightabsolute")) Sidedef.Fields.Remove("lightabsolute"); if(Sidedef.Fields.ContainsKey("light"))
{
Sidedef.Fields.Remove("light");
setupallparts = true;
}
if(Sidedef.Fields.ContainsKey("lightabsolute"))
{
Sidedef.Fields.Remove("lightabsolute");
setupallparts = true;
}
// Update sidedef geometry if(setupallparts)
{
// Update all sidedef geometry
VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef); VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef);
parts.SetupAllParts(); parts.SetupAllParts();
} }
else
{
// Update this part only
this.Setup();
}
}
// Toggle upper-unpegged // Toggle upper-unpegged
public virtual void OnToggleUpperUnpegged() public virtual void OnToggleUpperUnpegged()
@ -1034,7 +1032,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Update the parts for this sidedef! // Update the parts for this sidedef!
if(mode.VisualSectorExists(sd.Sector)) if(mode.VisualSectorExists(sd.Sector))
{ {
BaseVisualSector vs = (mode.GetVisualSector(sd.Sector) as BaseVisualSector); BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(sd.Sector);
VisualSidedefParts parts = vs.GetSidedefParts(sd); VisualSidedefParts parts = vs.GetSidedefParts(sd);
parts.SetupAllParts(); parts.SetupAllParts();
} }
@ -1112,7 +1110,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
mode.CreateUndo("Change texture " + texture); mode.CreateUndo("Change texture " + texture);
SetTexture(texture); SetTexture(texture);
OnTextureChanged();//mxd
//mxd. Update linked effects
SectorData sd = mode.GetSectorDataEx(Sector.Sector);
if(sd != null) sd.Reset(true);
} }
// Paste texture // Paste texture
@ -1123,7 +1124,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
mode.CreateUndo("Paste texture \"" + BuilderPlug.Me.CopiedTexture + "\""); mode.CreateUndo("Paste texture \"" + BuilderPlug.Me.CopiedTexture + "\"");
mode.SetActionResult("Pasted texture \"" + BuilderPlug.Me.CopiedTexture + "\"."); mode.SetActionResult("Pasted texture \"" + BuilderPlug.Me.CopiedTexture + "\".");
SetTexture(BuilderPlug.Me.CopiedTexture); SetTexture(BuilderPlug.Me.CopiedTexture);
OnTextureChanged(); //mxd
//mxd. Update linked effects
SectorData sd = mode.GetSectorDataEx(Sector.Sector);
if(sd != null) sd.Reset(true);
} }
} }
@ -1135,19 +1139,27 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
SetTextureOffsetX(BuilderPlug.Me.CopiedOffsets.X); SetTextureOffsetX(BuilderPlug.Me.CopiedOffsets.X);
SetTextureOffsetY(BuilderPlug.Me.CopiedOffsets.Y); SetTextureOffsetY(BuilderPlug.Me.CopiedOffsets.Y);
// Update sidedef part geometry
this.Setup();
} }
else else
{ {
Sidedef.OffsetX = BuilderPlug.Me.CopiedOffsets.X; Sidedef.OffsetX = BuilderPlug.Me.CopiedOffsets.X;
Sidedef.OffsetY = BuilderPlug.Me.CopiedOffsets.Y; Sidedef.OffsetY = BuilderPlug.Me.CopiedOffsets.Y;
}
mode.SetActionResult("Pasted texture offsets " + BuilderPlug.Me.CopiedOffsets.X + ", " + BuilderPlug.Me.CopiedOffsets.Y + ".");
// Update sidedef geometry // Update sidedef geometry
VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef); VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef);
parts.SetupAllParts(); parts.SetupAllParts();
} }
//mxd. Update linked effects
SectorData sd = mode.GetSectorDataEx(Sector.Sector);
if(sd != null) sd.Reset(true);
mode.SetActionResult("Pasted texture offsets " + BuilderPlug.Me.CopiedOffsets.X + ", " + BuilderPlug.Me.CopiedOffsets.Y + ".");
}
// Copy texture // Copy texture
public virtual void OnCopyTexture() public virtual void OnCopyTexture()
{ {
@ -1262,9 +1274,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
updatelist.Add((BaseVisualSector)mode.GetVisualSector(l.Back.Sector)); updatelist.Add((BaseVisualSector)mode.GetVisualSector(l.Back.Sector));
} }
//mxd. Always select front side for extrafloors
Linedef sourceline = GetControlLinedef();
Sidedef target = (sourceline != Sidedef.Line && sourceline.Front != null ? sourceline.Front : Sidedef);
General.Interface.OnEditFormValuesChanged += Interface_OnEditFormValuesChanged; General.Interface.OnEditFormValuesChanged += Interface_OnEditFormValuesChanged;
mode.StartRealtimeInterfaceUpdate(SelectionType.Linedefs); mode.StartRealtimeInterfaceUpdate(SelectionType.Linedefs);
DialogResult result = General.Interface.ShowEditLinedefs(linedefs, Sidedef.IsFront, !Sidedef.IsFront); DialogResult result = General.Interface.ShowEditLinedefs(linedefs, target.IsFront, !target.IsFront);
mode.StopRealtimeInterfaceUpdate(SelectionType.Linedefs); mode.StopRealtimeInterfaceUpdate(SelectionType.Linedefs);
General.Interface.OnEditFormValuesChanged -= Interface_OnEditFormValuesChanged; General.Interface.OnEditFormValuesChanged -= Interface_OnEditFormValuesChanged;
@ -1393,18 +1409,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(newlight == light) return; if(newlight == light) return;
//create undo // Create undo
mode.CreateUndo("Change wall brightness", UndoGroup.SurfaceBrightnessChange, Sector.Sector.FixedIndex); mode.CreateUndo("Change wall brightness", UndoGroup.SurfaceBrightnessChange, Sector.Sector.FixedIndex);
Sidedef.Fields.BeforeFieldsChange(); Sidedef.Fields.BeforeFieldsChange();
//apply changes // Apply changes
UniFields.SetInteger(Sidedef.Fields, "light", newlight, (absolute ? int.MinValue : 0)); UniFields.SetInteger(Sidedef.Fields, "light", newlight, (absolute ? int.MinValue : 0));
Tools.UpdateLightFogFlag(Sidedef); Tools.UpdateLightFogFlag(Sidedef);
mode.SetActionResult("Changed wall brightness to " + newlight + "."); mode.SetActionResult("Changed wall brightness to " + newlight + ".");
Sector.Sector.UpdateCache();
//rebuild sector // Update this part only
Sector.UpdateSectorGeometry(false); this.Setup();
} }
else if(!Sector.Changed) else if(!Sector.Changed)
{ {
@ -1431,7 +1446,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(mode.VisualThingExists(t)) if(mode.VisualThingExists(t))
{ {
// Update thing // Update thing
BaseVisualThing vt = (mode.GetVisualThing(t) as BaseVisualThing); BaseVisualThing vt = (BaseVisualThing)mode.GetVisualThing(t);
vt.Changed = true; vt.Changed = true;
} }
} }
@ -1452,6 +1467,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
MoveTextureOffset(new Point(-horizontal, -vertical)); MoveTextureOffset(new Point(-horizontal, -vertical));
Point p = GetTextureOffset(); Point p = GetTextureOffset();
mode.SetActionResult("Changed texture offsets to " + p.X + ", " + p.Y + "."); mode.SetActionResult("Changed texture offsets to " + p.X + ", " + p.Y + ".");
// Update this part only
this.Setup();
} }
else else
{ {
@ -1462,13 +1480,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(geometrytype != VisualGeometryType.WALL_MIDDLE && Texture != null) Sidedef.OffsetY %= Texture.Height; if(geometrytype != VisualGeometryType.WALL_MIDDLE && Texture != null) Sidedef.OffsetY %= Texture.Height;
mode.SetActionResult("Changed texture offsets to " + Sidedef.OffsetX + ", " + Sidedef.OffsetY + "."); mode.SetActionResult("Changed texture offsets to " + Sidedef.OffsetX + ", " + Sidedef.OffsetY + ".");
}
// Update sidedef geometry // Update all sidedef geometry
VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef); VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef);
parts.SetupAllParts(); parts.SetupAllParts();
} }
//mxd. Update linked effects
SectorData sd = mode.GetSectorDataEx(Sector.Sector);
if(sd != null) sd.Reset(true);
}
//mxd //mxd
public virtual void OnChangeScale(int incrementX, int incrementY) public virtual void OnChangeScale(int incrementX, int incrementY)
{ {
@ -1488,7 +1510,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
break; break;
case VisualGeometryType.WALL_MIDDLE: case VisualGeometryType.WALL_MIDDLE:
case VisualGeometryType.WALL_MIDDLE_3D:
keyX = "scalex_mid"; keyX = "scalex_mid";
keyY = "scaley_mid"; keyY = "scaley_mid";
break; break;
@ -1523,8 +1544,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
UniFields.SetFloat(Sidedef.Fields, keyY, scaleY, 1.0f); UniFields.SetFloat(Sidedef.Fields, keyY, scaleY, 1.0f);
} }
//update geometry // Update geometry
Setup(); Setup();
//mxd. Update linked effects
SectorData sd = mode.GetSectorDataEx(Sector.Sector);
if(sd != null) sd.Reset(true);
mode.SetActionResult("Wall scale changed to " + scaleX.ToString("F03", CultureInfo.InvariantCulture) + ", " + scaleY.ToString("F03", CultureInfo.InvariantCulture) + " (" + (int)Math.Round(Texture.Width / scaleX) + " x " + (int)Math.Round(Texture.Height / scaleY) + ")."); mode.SetActionResult("Wall scale changed to " + scaleX.ToString("F03", CultureInfo.InvariantCulture) + ", " + scaleY.ToString("F03", CultureInfo.InvariantCulture) + " (" + (int)Math.Round(Texture.Width / scaleX) + " x " + (int)Math.Round(Texture.Height / scaleY) + ").");
} }

View file

@ -282,7 +282,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Reset changed flags // Reset changed flags
foreach(KeyValuePair<Sector, VisualSector> vs in allsectors) foreach(KeyValuePair<Sector, VisualSector> vs in allsectors)
{ {
BaseVisualSector bvs = (vs.Value as BaseVisualSector); BaseVisualSector bvs = (BaseVisualSector)vs.Value;
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
@ -343,7 +343,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
if(vs.Value != null) if(vs.Value != null)
{ {
BaseVisualSector bvs = vs.Value as BaseVisualSector; BaseVisualSector bvs = (BaseVisualSector)vs.Value;
if((bvs.Floor != null) && bvs.Floor.Selected) selectedobjects.Add(bvs.Floor); if((bvs.Floor != null) && bvs.Floor.Selected) selectedobjects.Add(bvs.Floor);
if((bvs.Ceiling != null) && bvs.Ceiling.Selected) selectedobjects.Add(bvs.Ceiling); if((bvs.Ceiling != null) && bvs.Ceiling.Selected) selectedobjects.Add(bvs.Ceiling);
foreach(Sidedef sd in vs.Key.Sidedefs) foreach(Sidedef sd in vs.Key.Sidedefs)
@ -351,7 +351,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
List<VisualGeometry> sidedefgeos = bvs.GetSidedefGeometry(sd); List<VisualGeometry> sidedefgeos = bvs.GetSidedefGeometry(sd);
foreach(VisualGeometry sdg in sidedefgeos) foreach(VisualGeometry sdg in sidedefgeos)
{ {
if(sdg.Selected) selectedobjects.Add((sdg as IVisualEventReceiver)); if(sdg.Selected) selectedobjects.Add((IVisualEventReceiver)sdg);
} }
} }
} }
@ -361,7 +361,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
if(vt.Value != null) if(vt.Value != null)
{ {
BaseVisualThing bvt = vt.Value as BaseVisualThing; BaseVisualThing bvt = (BaseVisualThing)vt.Value;
if(bvt.Selected) selectedobjects.Add(bvt); if(bvt.Selected) selectedobjects.Add(bvt);
} }
} }
@ -502,7 +502,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
if(vs.Value != null) if(vs.Value != null)
{ {
BaseVisualSector bvs = vs.Value as BaseVisualSector; BaseVisualSector bvs = (BaseVisualSector)vs.Value;
if(bvs.Changed) bvs.Rebuild(); if(bvs.Changed) bvs.Rebuild();
} }
} }
@ -511,7 +511,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
if(vt.Value != null) if(vt.Value != null)
{ {
BaseVisualThing bvt = vt.Value as BaseVisualThing; BaseVisualThing bvt = (BaseVisualThing)vt.Value;
if(bvt.Changed) bvt.Rebuild(); if(bvt.Changed) bvt.Rebuild();
} }
} }
@ -543,7 +543,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
Vector3D[] translatedcoords = TranslateCoordinates(coords, direction, absoluteposition); Vector3D[] translatedcoords = TranslateCoordinates(coords, direction, absoluteposition);
for(int i = 0; i < visualthings.Count; i++) for(int i = 0; i < visualthings.Count; i++)
{ {
BaseVisualThing t = visualthings[i] as BaseVisualThing; BaseVisualThing t = (BaseVisualThing)visualthings[i];
t.OnMove(translatedcoords[i]); t.OnMove(translatedcoords[i]);
} }
@ -735,7 +735,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(!vertices.ContainsKey(v)) if(!vertices.ContainsKey(v))
vertices.Add(v, new VisualVertexPair(new BaseVisualVertex(this, v, false), new BaseVisualVertex(this, v, true))); vertices.Add(v, new VisualVertexPair(new BaseVisualVertex(this, v, false), new BaseVisualVertex(this, v, true)));
return (floor ? vertices[v].FloorVertex as BaseVisualVertex : vertices[v].CeilingVertex as BaseVisualVertex); return (floor ? (BaseVisualVertex)vertices[v].FloorVertex : (BaseVisualVertex)vertices[v].CeilingVertex);
} }
//mxd //mxd
@ -785,7 +785,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// The visual sector associated is now outdated // The visual sector associated is now outdated
if(VisualSectorExists(sectorsWithEffects[i])) if(VisualSectorExists(sectorsWithEffects[i]))
{ {
BaseVisualSector vs = GetVisualSector(sectorsWithEffects[i]) as BaseVisualSector; BaseVisualSector vs = (BaseVisualSector)GetVisualSector(sectorsWithEffects[i]);
vs.UpdateSectorGeometry(true); vs.UpdateSectorGeometry(true);
} }
} }
@ -853,13 +853,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
sd.AddEffectThingVertexSlope(slopeceilingthings, false); sd.AddEffectThingVertexSlope(slopeceilingthings, false);
} }
} }
// ========== mxd. Glowing flats ==========
if(General.Map.Data.GlowingFlats.ContainsKey(s.LongFloorTexture) || General.Map.Data.GlowingFlats.ContainsKey(s.LongCeilTexture))
{
SectorData sd = GetSectorData(s);
sd.AddEffectGlowingFlat(s);
}
} }
// Find interesting linedefs (such as line slopes) // Find interesting linedefs (such as line slopes)
@ -1077,7 +1070,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
else if(obj is VisualFloor || obj is VisualCeiling) else if(obj is VisualFloor || obj is VisualCeiling)
{ {
VisualGeometry vg = obj as VisualGeometry; VisualGeometry vg = (VisualGeometry)obj;
if(vg.Sector != null && vg.Sector.Sector != null && !selectedsectorindices.Contains(vg.Sector.Sector.Index)) if(vg.Sector != null && vg.Sector.Sector != null && !selectedsectorindices.Contains(vg.Sector.Sector.Index))
{ {
selectedsectorindices.Add(vg.Sector.Sector.Index); selectedsectorindices.Add(vg.Sector.Sector.Index);
@ -1087,7 +1080,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
else if(obj is VisualLower || obj is VisualUpper || obj is VisualMiddleDouble else if(obj is VisualLower || obj is VisualUpper || obj is VisualMiddleDouble
|| obj is VisualMiddleSingle || obj is VisualMiddle3D) || obj is VisualMiddleSingle || obj is VisualMiddle3D)
{ {
VisualGeometry vg = obj as VisualGeometry; VisualGeometry vg = (VisualGeometry)obj;
if(vg.Sidedef != null && !selectedlineindices.Contains(vg.Sidedef.Line.Index)) if(vg.Sidedef != null && !selectedlineindices.Contains(vg.Sidedef.Line.Index))
{ {
selectedlineindices.Add(vg.Sidedef.Line.Index); selectedlineindices.Add(vg.Sidedef.Line.Index);
@ -1096,7 +1089,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
else if(obj is VisualVertex) else if(obj is VisualVertex)
{ {
VisualVertex v = obj as VisualVertex; VisualVertex v = (VisualVertex)obj;
if(!selectedvertexindices.Contains(v.Vertex.Index)) if(!selectedvertexindices.Contains(v.Vertex.Index))
{ {
selectedvertexindices.Add(v.Vertex.Index); selectedvertexindices.Add(v.Vertex.Index);
@ -1293,7 +1286,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
if(sd.Marked && VisualSectorExists(sd.Sector)) if(sd.Marked && VisualSectorExists(sd.Sector))
{ {
BaseVisualSector vs = GetVisualSector(sd.Sector) as BaseVisualSector; BaseVisualSector vs = (BaseVisualSector)GetVisualSector(sd.Sector);
VisualSidedefParts parts = vs.GetSidedefParts(sd); VisualSidedefParts parts = vs.GetSidedefParts(sd);
parts.SetupAllParts(); parts.SetupAllParts();
} }
@ -1304,7 +1297,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
if(s.Marked) if(s.Marked)
{ {
SectorData sd = GetSectorData(s); SectorData sd = GetSectorDataEx(s);
if(sd != null)
{
sd.Reset(false); //mxd (changed Reset implementation) sd.Reset(false); //mxd (changed Reset implementation)
// UpdateSectorGeometry for associated sectors (sd.UpdateAlso) as well! // UpdateSectorGeometry for associated sectors (sd.UpdateAlso) as well!
@ -1312,15 +1307,16 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
if(VisualSectorExists(us.Key)) if(VisualSectorExists(us.Key))
{ {
BaseVisualSector vs = GetVisualSector(us.Key) as BaseVisualSector; BaseVisualSector vs = (BaseVisualSector)GetVisualSector(us.Key);
vs.UpdateSectorGeometry(us.Value); vs.UpdateSectorGeometry(us.Value);
} }
} }
}
// And update for this sector ofcourse // And update for this sector ofcourse
if(VisualSectorExists(s)) if(VisualSectorExists(s))
{ {
BaseVisualSector vs = GetVisualSector(s) as BaseVisualSector; BaseVisualSector vs = (BaseVisualSector)GetVisualSector(s);
vs.UpdateSectorGeometry(false); vs.UpdateSectorGeometry(false);
} }
} }
@ -1336,7 +1332,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if((vt.Value != null) && vt.Key.Marked) if((vt.Value != null) && vt.Key.Marked)
{ {
if(vt.Key.IsDisposed) toremove.Add(vt.Key); //mxd. Disposed things will cause problems if(vt.Key.IsDisposed) toremove.Add(vt.Key); //mxd. Disposed things will cause problems
else (vt.Value as BaseVisualThing).Rebuild(); else ((BaseVisualThing)vt.Value).Rebuild();
} }
} }
@ -1423,13 +1419,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
base.OnUndoEnd(); base.OnUndoEnd();
//mxd. Effects may've become invalid //mxd. Effects may've become invalid
if(General.Settings.GZDoomRenderingEffects && sectordata != null && sectordata.Count > 0) if(sectordata != null && sectordata.Count > 0) RebuildElementData();
RebuildElementData();
//mxd. As well as geometry... //mxd. As well as geometry...
foreach(KeyValuePair<Sector, VisualSector> group in visiblesectors) foreach(KeyValuePair<Sector, VisualSector> group in visiblesectors)
{ {
BaseVisualSector vs = group.Value as BaseVisualSector; BaseVisualSector vs = (BaseVisualSector)group.Value;
if(vs != null) vs.Rebuild(); if(vs != null) vs.Rebuild();
} }
@ -1445,13 +1440,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
base.OnRedoEnd(); base.OnRedoEnd();
//mxd. Effects may've become invalid //mxd. Effects may've become invalid
if(sectordata != null && sectordata.Count > 0) if(sectordata != null && sectordata.Count > 0) RebuildElementData();
RebuildElementData();
//mxd. As well as geometry... //mxd. As well as geometry...
foreach(KeyValuePair<Sector, VisualSector> group in visiblesectors) foreach(KeyValuePair<Sector, VisualSector> group in visiblesectors)
{ {
BaseVisualSector vs = group.Value as BaseVisualSector; BaseVisualSector vs = (BaseVisualSector)group.Value;
if(vs != null) vs.Rebuild(); if(vs != null) vs.Rebuild();
} }
@ -1466,7 +1460,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Reset changed flags // Reset changed flags
foreach(KeyValuePair<Sector, VisualSector> vs in allsectors) foreach(KeyValuePair<Sector, VisualSector> vs in allsectors)
{ {
BaseVisualSector bvs = (vs.Value as BaseVisualSector); BaseVisualSector bvs = (BaseVisualSector)vs.Value;
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;
@ -1494,7 +1488,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
if(VisualSectorExists(s.Key)) if(VisualSectorExists(s.Key))
{ {
BaseVisualSector vs = GetVisualSector(s.Key) as BaseVisualSector; BaseVisualSector vs = (BaseVisualSector)GetVisualSector(s.Key);
vs.UpdateSectorGeometry(s.Value); vs.UpdateSectorGeometry(s.Value);
} }
} }
@ -1535,35 +1529,33 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd. Because Upper/Middle/Lower textures offsets should be threated separately in UDMF //mxd. Because Upper/Middle/Lower textures offsets should be threated separately in UDMF
if(General.Map.UDMF) if(General.Map.UDMF)
{ {
Dictionary<BaseVisualGeometrySidedef, bool> donesides = new Dictionary<BaseVisualGeometrySidedef, bool>(selectedobjects.Count); HashSet<BaseVisualGeometrySidedef> donesides = new HashSet<BaseVisualGeometrySidedef>();
foreach(IVisualEventReceiver i in objs) foreach(IVisualEventReceiver i in objs)
{ {
if(!(i is BaseVisualGeometrySidedef)) continue; BaseVisualGeometrySidedef vs = (BaseVisualGeometrySidedef)i; //mxd
BaseVisualGeometrySidedef vs = i as BaseVisualGeometrySidedef; //mxd if(!donesides.Contains(vs))
if(!donesides.ContainsKey(vs))
{ {
//mxd. added scaling by texture scale //mxd. added scaling by texture scale
if(vs.Texture.UsedInMap) //mxd. Otherwise it's MissingTexture3D and we probably don't want to drag that if(vs.Texture.UsedInMap) //mxd. Otherwise it's MissingTexture3D and we probably don't want to drag that
vs.OnChangeTextureOffset((int)(dx / vs.Texture.Scale.x), (int)(dy / vs.Texture.Scale.y), false); vs.OnChangeTextureOffset((int)(dx / vs.Texture.Scale.x), (int)(dy / vs.Texture.Scale.y), false);
donesides.Add(vs, false); donesides.Add(vs);
} }
} }
} }
else else
{ {
Dictionary<Sidedef, bool> donesides = new Dictionary<Sidedef, bool>(selectedobjects.Count); HashSet<Sidedef> donesides = new HashSet<Sidedef>();
foreach(IVisualEventReceiver i in objs) foreach(IVisualEventReceiver i in objs)
{ {
if(!(i is BaseVisualGeometrySidedef)) continue; BaseVisualGeometrySidedef vs = (BaseVisualGeometrySidedef)i; //mxd
BaseVisualGeometrySidedef vs = i as BaseVisualGeometrySidedef; //mxd if(!donesides.Contains(vs.Sidedef))
if(!donesides.ContainsKey(vs.Sidedef))
{ {
//mxd. added scaling by texture scale //mxd. added scaling by texture scale
if(vs.Texture.UsedInMap) //mxd. Otherwise it's MissingTexture3D and we probably don't want to drag that if(vs.Texture.UsedInMap) //mxd. Otherwise it's MissingTexture3D and we probably don't want to drag that
vs.OnChangeTextureOffset((int)(dx / vs.Texture.Scale.x), (int)(dy / vs.Texture.Scale.y), false); vs.OnChangeTextureOffset((int)(dx / vs.Texture.Scale.x), (int)(dy / vs.Texture.Scale.y), false);
donesides.Add(vs.Sidedef, false); donesides.Add(vs.Sidedef);
} }
} }
} }
@ -1572,17 +1564,15 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Apply flat offsets // Apply flat offsets
public void ApplyFlatOffsetChange(int dx, int dy) public void ApplyFlatOffsetChange(int dx, int dy)
{ {
Dictionary<Sector, int> donesectors = new Dictionary<Sector, int>(selectedobjects.Count); HashSet<Sector> donesectors = new HashSet<Sector>();
List<IVisualEventReceiver> objs = GetSelectedObjects(true, false, false, false); List<IVisualEventReceiver> objs = GetSelectedObjects(true, false, false, false);
foreach(IVisualEventReceiver i in objs) foreach(IVisualEventReceiver i in objs)
{ {
if(i is BaseVisualGeometrySector) BaseVisualGeometrySector bvs = (BaseVisualGeometrySector)i;
if(bvs != null && !donesectors.Contains(bvs.Sector.Sector))
{ {
if(!donesectors.ContainsKey((i as BaseVisualGeometrySector).Sector.Sector)) bvs.OnChangeTextureOffset(dx, dy, false);
{ donesectors.Add(bvs.Sector.Sector);
i.OnChangeTextureOffset(dx, dy, false);
donesectors.Add((i as BaseVisualGeometrySector).Sector.Sector, 0);
}
} }
} }
} }
@ -1657,7 +1647,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd //mxd
internal List<IVisualEventReceiver> RemoveDuplicateSidedefs(List<IVisualEventReceiver> objs) internal List<IVisualEventReceiver> RemoveDuplicateSidedefs(List<IVisualEventReceiver> objs)
{ {
Dictionary<Sidedef, bool> processed = new Dictionary<Sidedef, bool>(); HashSet<Sidedef> processed = new HashSet<Sidedef>();
List<IVisualEventReceiver> result = new List<IVisualEventReceiver>(); List<IVisualEventReceiver> result = new List<IVisualEventReceiver>();
foreach(IVisualEventReceiver i in objs) foreach(IVisualEventReceiver i in objs)
@ -1665,9 +1655,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
BaseVisualGeometrySidedef sidedef = i as BaseVisualGeometrySidedef; BaseVisualGeometrySidedef sidedef = i as BaseVisualGeometrySidedef;
if(sidedef != null) if(sidedef != null)
{ {
if (!processed.ContainsKey(sidedef.Sidedef)) if(!processed.Contains(sidedef.Sidedef))
{ {
processed.Add(sidedef.Sidedef, false); processed.Add(sidedef.Sidedef);
result.Add(i); result.Add(i);
} }
} }
@ -1683,15 +1673,15 @@ namespace CodeImp.DoomBuilder.BuilderModes
// This returns all selected sectors, no doubles // This returns all selected sectors, no doubles
public List<Sector> GetSelectedSectors() public List<Sector> GetSelectedSectors()
{ {
Dictionary<Sector, int> added = new Dictionary<Sector, int>(); HashSet<Sector> added = new HashSet<Sector>();
List<Sector> sectors = new List<Sector>(); List<Sector> sectors = new List<Sector>();
foreach(IVisualEventReceiver i in selectedobjects) foreach(IVisualEventReceiver i in selectedobjects)
{ {
BaseVisualGeometrySector sector = i as BaseVisualGeometrySector; BaseVisualGeometrySector sector = i as BaseVisualGeometrySector;
if(sector != null && !added.ContainsKey(sector.Level.sector)) if(sector != null && !added.Contains(sector.Level.sector))
{ {
sectors.Add(sector.Level.sector); sectors.Add(sector.Level.sector);
added.Add(sector.Level.sector, 0); added.Add(sector.Level.sector);
} }
} }
@ -1699,7 +1689,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if((selectedobjects.Count == 0) && (target.picked is BaseVisualGeometrySector)) if((selectedobjects.Count == 0) && (target.picked is BaseVisualGeometrySector))
{ {
Sector s = ((BaseVisualGeometrySector)target.picked).Level.sector; Sector s = ((BaseVisualGeometrySector)target.picked).Level.sector;
if(!added.ContainsKey(s)) sectors.Add(s); if(!added.Contains(s)) sectors.Add(s);
} }
return sectors; return sectors;
@ -1708,7 +1698,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// This returns all selected linedefs, no doubles // This returns all selected linedefs, no doubles
public List<Linedef> GetSelectedLinedefs() public List<Linedef> GetSelectedLinedefs()
{ {
Dictionary<Linedef, int> added = new Dictionary<Linedef, int>(); HashSet<Linedef> added = new HashSet<Linedef>();
List<Linedef> linedefs = new List<Linedef>(); List<Linedef> linedefs = new List<Linedef>();
foreach(IVisualEventReceiver i in selectedobjects) foreach(IVisualEventReceiver i in selectedobjects)
{ {
@ -1716,10 +1706,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(sidedef != null) if(sidedef != null)
{ {
Linedef l = sidedef.GetControlLinedef(); //mxd Linedef l = sidedef.GetControlLinedef(); //mxd
if(!added.ContainsKey(l)) if(!added.Contains(l))
{ {
linedefs.Add(l); linedefs.Add(l);
added.Add(l, 0); added.Add(l);
} }
} }
} }
@ -1728,7 +1718,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if((selectedobjects.Count == 0) && (target.picked is BaseVisualGeometrySidedef)) if((selectedobjects.Count == 0) && (target.picked is BaseVisualGeometrySidedef))
{ {
Linedef l = ((BaseVisualGeometrySidedef)target.picked).GetControlLinedef(); //mxd Linedef l = ((BaseVisualGeometrySidedef)target.picked).GetControlLinedef(); //mxd
if(!added.ContainsKey(l)) linedefs.Add(l); if(!added.Contains(l)) linedefs.Add(l);
} }
return linedefs; return linedefs;
@ -1737,15 +1727,15 @@ namespace CodeImp.DoomBuilder.BuilderModes
// This returns all selected sidedefs, no doubles // This returns all selected sidedefs, no doubles
public List<Sidedef> GetSelectedSidedefs() public List<Sidedef> GetSelectedSidedefs()
{ {
Dictionary<Sidedef, int> added = new Dictionary<Sidedef, int>(); HashSet<Sidedef> added = new HashSet<Sidedef>();
List<Sidedef> sidedefs = new List<Sidedef>(); List<Sidedef> sidedefs = new List<Sidedef>();
foreach(IVisualEventReceiver i in selectedobjects) foreach(IVisualEventReceiver i in selectedobjects)
{ {
BaseVisualGeometrySidedef sidedef = i as BaseVisualGeometrySidedef; BaseVisualGeometrySidedef sidedef = i as BaseVisualGeometrySidedef;
if(sidedef != null && !added.ContainsKey(sidedef.Sidedef)) if(sidedef != null && !added.Contains(sidedef.Sidedef))
{ {
sidedefs.Add(sidedef.Sidedef); sidedefs.Add(sidedef.Sidedef);
added.Add(sidedef.Sidedef, 0); added.Add(sidedef.Sidedef);
} }
} }
@ -1753,7 +1743,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if((selectedobjects.Count == 0) && (target.picked is BaseVisualGeometrySidedef)) if((selectedobjects.Count == 0) && (target.picked is BaseVisualGeometrySidedef))
{ {
Sidedef sd = ((BaseVisualGeometrySidedef)target.picked).Sidedef; Sidedef sd = ((BaseVisualGeometrySidedef)target.picked).Sidedef;
if(!added.ContainsKey(sd)) sidedefs.Add(sd); if(!added.Contains(sd)) sidedefs.Add(sd);
} }
return sidedefs; return sidedefs;
@ -1762,15 +1752,15 @@ namespace CodeImp.DoomBuilder.BuilderModes
// This returns all selected things, no doubles // This returns all selected things, no doubles
public List<Thing> GetSelectedThings() public List<Thing> GetSelectedThings()
{ {
Dictionary<Thing, int> added = new Dictionary<Thing, int>(); HashSet<Thing> added = new HashSet<Thing>();
List<Thing> things = new List<Thing>(); List<Thing> things = new List<Thing>();
foreach(IVisualEventReceiver i in selectedobjects) foreach(IVisualEventReceiver i in selectedobjects)
{ {
BaseVisualThing thing = i as BaseVisualThing; BaseVisualThing thing = i as BaseVisualThing;
if(thing != null && !added.ContainsKey(thing.Thing)) if(thing != null && !added.Contains(thing.Thing))
{ {
things.Add(thing.Thing); things.Add(thing.Thing);
added.Add(thing.Thing, 0); added.Add(thing.Thing);
} }
} }
@ -1778,7 +1768,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if((selectedobjects.Count == 0) && (target.picked is BaseVisualThing)) if((selectedobjects.Count == 0) && (target.picked is BaseVisualThing))
{ {
Thing t = ((BaseVisualThing)target.picked).Thing; Thing t = ((BaseVisualThing)target.picked).Thing;
if(!added.ContainsKey(t)) things.Add(t); if(!added.Contains(t)) things.Add(t);
} }
return things; return things;
@ -1787,20 +1777,16 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd. This returns all selected vertices, no doubles //mxd. This returns all selected vertices, no doubles
public List<Vertex> GetSelectedVertices() public List<Vertex> GetSelectedVertices()
{ {
Dictionary<Vertex, int> added = new Dictionary<Vertex, int>(); HashSet<Vertex> added = new HashSet<Vertex>();
List<Vertex> verts = new List<Vertex>(); List<Vertex> verts = new List<Vertex>();
foreach(IVisualEventReceiver i in selectedobjects) foreach(IVisualEventReceiver i in selectedobjects)
{ {
if(i is BaseVisualVertex) BaseVisualVertex vertex = i as BaseVisualVertex;
if(vertex != null && !added.Contains(vertex.Vertex))
{ {
Vertex v = (i as BaseVisualVertex).Vertex; verts.Add(vertex.Vertex);
added.Add(vertex.Vertex);
if(!added.ContainsKey(v))
{
verts.Add(v);
added.Add(v, 0);
}
} }
} }
@ -1808,7 +1794,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if((selectedobjects.Count == 0) && (target.picked is BaseVisualVertex)) if((selectedobjects.Count == 0) && (target.picked is BaseVisualVertex))
{ {
Vertex v = ((BaseVisualVertex)target.picked).Vertex; Vertex v = ((BaseVisualVertex)target.picked).Vertex;
if(!added.ContainsKey(v)) verts.Add(v); if(!added.Contains(v)) verts.Add(v);
} }
return verts; return verts;
@ -1821,7 +1807,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
if(singleselection || target.picked.Selected || targetonly) if(singleselection || target.picked.Selected || targetonly)
{ {
return target.picked as IVisualEventReceiver; return (IVisualEventReceiver)target.picked;
} }
if(selectedobjects.Count > 0) if(selectedobjects.Count > 0)
@ -1829,7 +1815,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
return selectedobjects[0]; return selectedobjects[0];
} }
return target.picked as IVisualEventReceiver; return (IVisualEventReceiver)target.picked;
} }
return new NullVisualEventReceiver(); return new NullVisualEventReceiver();
@ -1907,7 +1893,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
if(vt.Value != null) if(vt.Value != null)
{ {
BaseVisualThing bvt = vt.Value as BaseVisualThing; BaseVisualThing bvt = (BaseVisualThing)vt.Value;
bvt.Selected = false; bvt.Selected = false;
} }
} }
@ -2023,20 +2009,19 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Get selection // Get selection
if(selectedobjects.Count == 0) if(selectedobjects.Count == 0)
{ {
IVisualEventReceiver i = (target.picked as IVisualEventReceiver); if(target.picked is VisualFloor)
if(i is VisualFloor)
{ {
VisualFloor vf = i as VisualFloor; VisualFloor vf = (VisualFloor)target.picked;
floors.Add(vf.Level.sector, vf); floors.Add(vf.Level.sector, vf);
} }
else if(i is VisualCeiling) else if(target.picked is VisualCeiling)
{ {
VisualCeiling vc = i as VisualCeiling; VisualCeiling vc = (VisualCeiling)target.picked;
ceilings.Add(vc.Level.sector, vc); ceilings.Add(vc.Level.sector, vc);
} }
else if(i is BaseVisualThing) else if(target.picked is BaseVisualThing)
{ {
things.Add(i as BaseVisualThing); things.Add((BaseVisualThing)target.picked);
} }
} }
else else
@ -2045,17 +2030,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
if(i is VisualFloor) if(i is VisualFloor)
{ {
VisualFloor vf = i as VisualFloor; VisualFloor vf = (VisualFloor)i;
floors.Add(vf.Level.sector, vf); floors.Add(vf.Level.sector, vf);
} }
else if(i is VisualCeiling) else if(i is VisualCeiling)
{ {
VisualCeiling vc = i as VisualCeiling; VisualCeiling vc = (VisualCeiling)i;
ceilings.Add(vc.Level.sector, vc); ceilings.Add(vc.Level.sector, vc);
} }
else if(i is BaseVisualThing) else if(i is BaseVisualThing)
{ {
things.Add(i as BaseVisualThing); things.Add((BaseVisualThing)i);
} }
} }
} }
@ -2221,23 +2206,22 @@ namespace CodeImp.DoomBuilder.BuilderModes
List<BaseVisualThing> things = new List<BaseVisualThing>(); List<BaseVisualThing> things = new List<BaseVisualThing>();
bool withinSelection = General.Interface.CtrlState; bool withinSelection = General.Interface.CtrlState;
//get selection // Get selection
if(selectedobjects.Count == 0) if(selectedobjects.Count == 0)
{ {
IVisualEventReceiver i = (target.picked as IVisualEventReceiver); if(target.picked is VisualFloor)
if(i is VisualFloor)
{ {
VisualFloor vf = i as VisualFloor; VisualFloor vf = (VisualFloor)target.picked;
floors.Add(vf.Level.sector, vf); floors.Add(vf.Level.sector, vf);
} }
else if(i is VisualCeiling) else if(target.picked is VisualCeiling)
{ {
VisualCeiling vc = i as VisualCeiling; VisualCeiling vc = (VisualCeiling)target.picked;
ceilings.Add(vc.Level.sector, vc); ceilings.Add(vc.Level.sector, vc);
} }
else if(i is BaseVisualThing) else if(target.picked is BaseVisualThing)
{ {
things.Add(i as BaseVisualThing); things.Add((BaseVisualThing)target.picked);
} }
} }
else else
@ -2246,17 +2230,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
if(i is VisualFloor) if(i is VisualFloor)
{ {
VisualFloor vf = i as VisualFloor; VisualFloor vf = (VisualFloor)i;
floors.Add(vf.Level.sector, vf); floors.Add(vf.Level.sector, vf);
} }
else if(i is VisualCeiling) else if(i is VisualCeiling)
{ {
VisualCeiling vc = i as VisualCeiling; VisualCeiling vc = (VisualCeiling)i;
ceilings.Add(vc.Level.sector, vc); ceilings.Add(vc.Level.sector, vc);
} }
else if(i is BaseVisualThing) else if(i is BaseVisualThing)
{ {
things.Add(i as BaseVisualThing); things.Add((BaseVisualThing)i);
} }
} }
} }
@ -2427,7 +2411,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
return; return;
} }
IVisualEventReceiver highlighted = (target.picked as IVisualEventReceiver); IVisualEventReceiver highlighted = (IVisualEventReceiver)target.picked;
if(highlighted is BaseVisualThing) if(highlighted is BaseVisualThing)
{ {
@ -2439,7 +2423,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
int targetbrightness; int targetbrightness;
if(highlighted is VisualFloor) if(highlighted is VisualFloor)
{ {
VisualFloor v = highlighted as VisualFloor; VisualFloor v = (VisualFloor)highlighted;
targetbrightness = v.Level.sector.Fields.GetValue("lightfloor", 0); targetbrightness = v.Level.sector.Fields.GetValue("lightfloor", 0);
if(!v.Level.sector.Fields.GetValue("lightfloorabsolute", false)) if(!v.Level.sector.Fields.GetValue("lightfloorabsolute", false))
{ {
@ -2448,7 +2432,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
else if(highlighted is VisualCeiling) else if(highlighted is VisualCeiling)
{ {
VisualCeiling v = highlighted as VisualCeiling; VisualCeiling v = (VisualCeiling)highlighted;
targetbrightness = v.Level.sector.Fields.GetValue("lightceiling", 0); targetbrightness = v.Level.sector.Fields.GetValue("lightceiling", 0);
if(!v.Level.sector.Fields.GetValue("lightceilingabsolute", false)) if(!v.Level.sector.Fields.GetValue("lightceilingabsolute", false))
{ {
@ -2457,7 +2441,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
else if(highlighted is VisualUpper || highlighted is VisualMiddleSingle || highlighted is VisualMiddleDouble || highlighted is VisualLower) else if(highlighted is VisualUpper || highlighted is VisualMiddleSingle || highlighted is VisualMiddleDouble || highlighted is VisualLower)
{ {
BaseVisualGeometrySidedef v = highlighted as BaseVisualGeometrySidedef; BaseVisualGeometrySidedef v = (BaseVisualGeometrySidedef)highlighted;
targetbrightness = v.Sidedef.Fields.GetValue("light", 0); targetbrightness = v.Sidedef.Fields.GetValue("light", 0);
if(!v.Sidedef.Fields.GetValue("lightabsolute", false)) if(!v.Sidedef.Fields.GetValue("lightabsolute", false))
{ {
@ -2466,7 +2450,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
else if(highlighted is VisualMiddle3D) else if(highlighted is VisualMiddle3D)
{ {
VisualMiddle3D v = highlighted as VisualMiddle3D; VisualMiddle3D v = (VisualMiddle3D)highlighted;
Sidedef sd = v.GetControlLinedef().Front; Sidedef sd = v.GetControlLinedef().Front;
if(sd == null) if(sd == null)
{ {
@ -2497,7 +2481,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(obj is VisualFloor) if(obj is VisualFloor)
{ {
VisualFloor v = obj as VisualFloor; VisualFloor v = (VisualFloor)obj;
v.Level.sector.Fields.BeforeFieldsChange(); v.Level.sector.Fields.BeforeFieldsChange();
v.Sector.Changed = true; v.Sector.Changed = true;
@ -2514,7 +2498,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
else if(obj is VisualCeiling) else if(obj is VisualCeiling)
{ {
VisualCeiling v = obj as VisualCeiling; VisualCeiling v = (VisualCeiling)obj;
v.Level.sector.Fields.BeforeFieldsChange(); v.Level.sector.Fields.BeforeFieldsChange();
v.Sector.Changed = true; v.Sector.Changed = true;
v.Sector.Sector.UpdateNeeded = true; v.Sector.Sector.UpdateNeeded = true;
@ -2532,7 +2516,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
else if(obj is VisualUpper || obj is VisualMiddleSingle || obj is VisualMiddleDouble || obj is VisualLower) else if(obj is VisualUpper || obj is VisualMiddleSingle || obj is VisualMiddleDouble || obj is VisualLower)
{ {
BaseVisualGeometrySidedef v = obj as BaseVisualGeometrySidedef; BaseVisualGeometrySidedef v = (BaseVisualGeometrySidedef)obj;
v.Sidedef.Fields.BeforeFieldsChange(); v.Sidedef.Fields.BeforeFieldsChange();
v.Sector.Changed = true; v.Sector.Changed = true;
@ -2727,7 +2711,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
renderer.SetCrosshairBusy(true); renderer.SetCrosshairBusy(true);
General.Interface.RedrawDisplay(); General.Interface.RedrawDisplay();
GetTargetEventReceiver(false).OnSelectTexture(); GetTargetEventReceiver(false).OnSelectTexture();
RebuildElementData(); //mxd. Extrafloors or Glow effects may've been changed
renderer.SetCrosshairBusy(false); renderer.SetCrosshairBusy(false);
PostAction(); PostAction();
} }
@ -2851,7 +2834,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
//align //align
foreach(IVisualEventReceiver i in objs) foreach(IVisualEventReceiver i in objs)
{ {
BaseVisualGeometrySidedef side = i as BaseVisualGeometrySidedef; BaseVisualGeometrySidedef side = (BaseVisualGeometrySidedef)i;
// Make sure the texture is loaded (we need the texture size) // Make sure the texture is loaded (we need the texture size)
if(!side.Texture.IsImageLoaded) side.Texture.LoadImage(); if(!side.Texture.IsImageLoaded) side.Texture.LoadImage();
@ -2867,7 +2850,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Update the parts for this sidedef! // Update the parts for this sidedef!
if(VisualSectorExists(sd.Sector)) if(VisualSectorExists(sd.Sector))
{ {
BaseVisualSector vs = (GetVisualSector(sd.Sector) as BaseVisualSector); BaseVisualSector vs = (BaseVisualSector)GetVisualSector(sd.Sector);
VisualSidedefParts parts = vs.GetSidedefParts(sd); VisualSidedefParts parts = vs.GetSidedefParts(sd);
parts.SetupAllParts(); parts.SetupAllParts();
} }
@ -2884,9 +2867,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Get selection // Get selection
List<IVisualEventReceiver> objs = GetSelectedObjects(false, true, false, false); List<IVisualEventReceiver> objs = GetSelectedObjects(false, true, false, false);
List<BaseVisualGeometrySidedef> sides = new List<BaseVisualGeometrySidedef>(); List<BaseVisualGeometrySidedef> sides = new List<BaseVisualGeometrySidedef>();
foreach(IVisualEventReceiver side in objs) foreach(IVisualEventReceiver i in objs)
{ {
if(side is BaseVisualGeometrySidedef) sides.Add(side as BaseVisualGeometrySidedef); BaseVisualGeometrySidedef side = (BaseVisualGeometrySidedef)i;
if(side != null) sides.Add(side);
} }
if(sides.Count == 0) if(sides.Count == 0)
@ -3016,7 +3000,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
added = new HashSet<int>(); added = new HashSet<int>();
foreach(IVisualEventReceiver receiver in obj) foreach(IVisualEventReceiver receiver in obj)
{ {
VisualGeometry vg = receiver as VisualGeometry; VisualGeometry vg = (VisualGeometry)receiver;
if(vg != null && !added.Contains(vg.Sector.GetHashCode())) if(vg != null && !added.Contains(vg.Sector.GetHashCode()))
{ {
selection.Add(receiver); selection.Add(receiver);
@ -3035,7 +3019,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
added = new HashSet<int>(); added = new HashSet<int>();
foreach(IVisualEventReceiver receiver in obj) foreach(IVisualEventReceiver receiver in obj)
{ {
VisualGeometry vg = receiver as VisualGeometry; VisualGeometry vg = (VisualGeometry)receiver;
if(vg != null && !added.Contains(vg.Sidedef.Line.GetHashCode())) if(vg != null && !added.Contains(vg.Sidedef.Line.GetHashCode()))
{ {
selection.Add(receiver); selection.Add(receiver);
@ -3054,7 +3038,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
added = new HashSet<int>(); added = new HashSet<int>();
foreach(IVisualEventReceiver receiver in obj) foreach(IVisualEventReceiver receiver in obj)
{ {
VisualThing vt = receiver as VisualThing; VisualThing vt = (VisualThing)receiver;
if(vt != null && !added.Contains(vt.Thing.GetHashCode())) if(vt != null && !added.Contains(vt.Thing.GetHashCode()))
{ {
selection.Add(receiver); selection.Add(receiver);
@ -3073,7 +3057,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
added = new HashSet<int>(); added = new HashSet<int>();
foreach(IVisualEventReceiver receiver in obj) foreach(IVisualEventReceiver receiver in obj)
{ {
VisualVertex vv = receiver as VisualVertex; VisualVertex vv = (VisualVertex)receiver;
if(vv != null && !added.Contains(vv.Vertex.GetHashCode())) if(vv != null && !added.Contains(vv.Vertex.GetHashCode()))
{ {
selection.Add(receiver); selection.Add(receiver);
@ -3157,7 +3141,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
copybuffer.Clear(); copybuffer.Clear();
foreach(IVisualEventReceiver i in objs) foreach(IVisualEventReceiver i in objs)
{ {
VisualThing vt = i as VisualThing; VisualThing vt = (VisualThing)i;
if(vt != null) copybuffer.Add(new ThingCopyData(vt.Thing)); if(vt != null) copybuffer.Add(new ThingCopyData(vt.Thing));
} }
General.Interface.DisplayStatus(StatusType.Info, "Copied " + copybuffer.Count + " Things"); General.Interface.DisplayStatus(StatusType.Info, "Copied " + copybuffer.Count + " Things");
@ -3177,7 +3161,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
List<IVisualEventReceiver> objs = GetSelectedObjects(false, false, true, false); List<IVisualEventReceiver> objs = GetSelectedObjects(false, false, true, false);
foreach(IVisualEventReceiver i in objs) foreach(IVisualEventReceiver i in objs)
{ {
BaseVisualThing thing = i as BaseVisualThing; BaseVisualThing thing = (BaseVisualThing)i;
thing.Thing.Fields.BeforeFieldsChange(); thing.Thing.Fields.BeforeFieldsChange();
thing.Thing.Dispose(); thing.Thing.Dispose();
thing.Dispose(); thing.Dispose();
@ -3267,17 +3251,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
if(obj is BaseVisualThing) if(obj is BaseVisualThing)
{ {
BaseVisualThing t = obj as BaseVisualThing; BaseVisualThing t = (BaseVisualThing)obj;
t.SetAngle(General.ClampAngle(t.Thing.AngleDoom + increment)); t.SetAngle(General.ClampAngle(t.Thing.AngleDoom + increment));
} }
else if(obj is VisualFloor) else if(obj is VisualFloor)
{ {
VisualFloor vf = obj as VisualFloor; VisualFloor vf = (VisualFloor)obj;
vf.OnChangeTextureRotation(General.ClampAngle(vf.GetControlSector().Fields.GetValue("rotationfloor", 0.0f) + increment)); vf.OnChangeTextureRotation(General.ClampAngle(vf.GetControlSector().Fields.GetValue("rotationfloor", 0.0f) + increment));
} }
else if(obj is VisualCeiling) else if(obj is VisualCeiling)
{ {
VisualCeiling vc = obj as VisualCeiling; VisualCeiling vc = (VisualCeiling)obj;
vc.OnChangeTextureRotation(General.ClampAngle(vc.GetControlSector().Fields.GetValue("rotationceiling", 0.0f) + increment)); vc.OnChangeTextureRotation(General.ClampAngle(vc.GetControlSector().Fields.GetValue("rotationceiling", 0.0f) + increment));
} }
} }
@ -3309,9 +3293,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
foreach(IVisualEventReceiver obj in selection) foreach(IVisualEventReceiver obj in selection)
{ {
if(!(obj is BaseVisualThing)) continue; BaseVisualThing t = (BaseVisualThing)obj;
BaseVisualThing t = obj as BaseVisualThing; if(t != null) t.SetPitch(General.ClampAngle(t.Thing.Pitch + increment));
t.SetPitch(General.ClampAngle(t.Thing.Pitch + increment));
} }
PostAction(); PostAction();
@ -3341,9 +3324,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
foreach(IVisualEventReceiver obj in selection) foreach(IVisualEventReceiver obj in selection)
{ {
if(!(obj is BaseVisualThing)) continue; BaseVisualThing t = (BaseVisualThing)obj;
BaseVisualThing t = obj as BaseVisualThing; if(t != null) t.SetRoll(General.ClampAngle(t.Thing.Roll + increment));
t.SetRoll(General.ClampAngle(t.Thing.Roll + increment));
} }
PostAction(); PostAction();
@ -3418,7 +3400,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
//apply changes to Visual Things //apply changes to Visual Things
for(int i = 0; i < visualThings.Count; i++) for(int i = 0; i < visualThings.Count; i++)
{ {
BaseVisualThing t = visualThings[i] as BaseVisualThing; BaseVisualThing t = (BaseVisualThing)visualThings[i];
t.Changed = true; t.Changed = true;
// Update what must be updated // Update what must be updated
@ -3667,7 +3649,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
//add to update list //add to update list
if(update) toUpdate.Add(vg.Sector as BaseVisualSector); if(update) toUpdate.Add((BaseVisualSector)vg.Sector);
} }
//update changed geometry //update changed geometry
@ -3848,11 +3830,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
foreach(IVisualEventReceiver i in selectedobjects) foreach(IVisualEventReceiver i in selectedobjects)
{ {
if(i is BaseVisualGeometrySidedef) BaseVisualGeometrySidedef side = (BaseVisualGeometrySidedef)i;
{ if(side != null && !selectedVisualSides.Contains(side)) selectedVisualSides.Add(side);
BaseVisualGeometrySidedef sd = i as BaseVisualGeometrySidedef;
if(!selectedVisualSides.Contains(sd)) selectedVisualSides.Add(sd);
}
} }
} }
@ -4221,11 +4200,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd //mxd
private List<Sidedef> GetControlSides(Sidedef side, bool udmf) private List<Sidedef> GetControlSides(Sidedef side, bool udmf)
{ {
if(side.Other == null) return new List<Sidedef>() { side }; if(side.Other == null) return new List<Sidedef> { side };
if(side.Other.Sector.Tag == 0) return new List<Sidedef>() { side }; if(side.Other.Sector.Tag == 0) return new List<Sidedef> { side };
SectorData data = GetSectorData(side.Other.Sector); SectorData data = GetSectorDataEx(side.Other.Sector);
if(data.ExtraFloors.Count == 0) return new List<Sidedef>() { side }; if(data == null || data.ExtraFloors.Count == 0) return new List<Sidedef> { side };
List<Sidedef> sides = new List<Sidedef>(); List<Sidedef> sides = new List<Sidedef>();
foreach(Effect3DFloor ef in data.ExtraFloors) foreach(Effect3DFloor ef in data.ExtraFloors)

View file

@ -124,16 +124,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
SectorData data = mode.GetSectorDataEx(this.Sector); //mxd SectorData data = mode.GetSectorDataEx(this.Sector); //mxd
if(data != null) //mxd if(data != null) //mxd
{ {
data.Reset(includeneighbours); data.Reset(false);
// Update sectors that rely on this sector // Update sectors that rely on this sector
foreach(KeyValuePair<Sector, bool> s in data.UpdateAlso) foreach(KeyValuePair<Sector, bool> s in data.UpdateAlso)
{ {
if(mode.VisualSectorExists(s.Key)) SectorData other = mode.GetSectorDataEx(s.Key);
{ if(other != null) other.Reset(s.Value);
BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(s.Key);
vs.Changed = true;
}
} }
} }
@ -145,7 +142,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(mode.VisualThingExists(t)) if(mode.VisualThingExists(t))
{ {
// Update thing // Update thing
BaseVisualThing vt = (mode.GetVisualThing(t) as BaseVisualThing); BaseVisualThing vt = (BaseVisualThing)mode.GetVisualThing(t);
vt.Changed = true; vt.Changed = true;
} }
} }
@ -160,8 +157,16 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
if(mode.VisualSectorExists(sd.Other.Sector)) if(mode.VisualSectorExists(sd.Other.Sector))
{ {
BaseVisualSector bvs = (BaseVisualSector)mode.GetVisualSector(sd.Other.Sector); SectorData other = mode.GetSectorDataEx(sd.Other.Sector);
bvs.Changed = true; if(other != null)
{
other.Reset(false);
}
else
{
BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(sd.Other.Sector);
vs.Changed = true;
}
} }
} }
} }
@ -189,7 +194,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(mode.VisualThingExists(t)) if(mode.VisualThingExists(t))
{ {
// Update thing // Update thing
BaseVisualThing vt = (mode.GetVisualThing(t) as BaseVisualThing); BaseVisualThing vt = (BaseVisualThing)mode.GetVisualThing(t);
vt.Rebuild(); vt.Rebuild();
} }
} }

View file

@ -707,7 +707,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
foreach(Thing t in things) foreach(Thing t in things)
{ {
VisualThing vt = mode.GetVisualThing(t); VisualThing vt = mode.GetVisualThing(t);
if(vt != null) updateList.Add(vt as BaseVisualThing); if(vt != null) updateList.Add((BaseVisualThing)vt);
} }
General.Interface.OnEditFormValuesChanged += Interface_OnEditFormValuesChanged; General.Interface.OnEditFormValuesChanged += Interface_OnEditFormValuesChanged;

View file

@ -1,45 +1,35 @@
using CodeImp.DoomBuilder.Map; using CodeImp.DoomBuilder.Rendering;
using CodeImp.DoomBuilder.Rendering;
namespace CodeImp.DoomBuilder.BuilderModes namespace CodeImp.DoomBuilder.BuilderModes
{ {
internal class EffectGlowingFlat : SectorEffect internal class EffectGlowingFlat
{ {
private readonly Sector sector; private readonly SectorData data;
// Level planes // Level planes
private SectorLevel ceillevel; private SectorLevel ceillevel;
private SectorLevel floorlevel; private SectorLevel floorlevel;
// Constructor // Constructor
public EffectGlowingFlat(SectorData data, Sector sourcesector) : base(data) public EffectGlowingFlat(SectorData sourcedata)
{ {
sector = sourcesector; data = sourcedata;
// New effect added: This sector needs an update!
if(data.Mode.VisualSectorExists(data.Sector))
{
BaseVisualSector vs = (BaseVisualSector)data.Mode.GetVisualSector(data.Sector);
vs.UpdateSectorGeometry(false);
}
} }
public override void Update() public void Update()
{ {
// Create ceiling glow effect? // Create ceiling glow effect?
if(General.Map.Data.GlowingFlats.ContainsKey(sector.LongCeilTexture)) if(General.Map.Data.GlowingFlats.ContainsKey(data.Sector.LongCeilTexture))
{ {
// Create ceiling level? // Create ceiling level?
if(ceillevel == null) if(ceillevel == null)
{ {
ceillevel = new SectorLevel(data.Ceiling); ceillevel = new SectorLevel(data.Ceiling) { type = SectorLevelType.Glow, disablelighting = true };
ceillevel.type = SectorLevelType.Glow;
ceillevel.disablelighting = true;
data.AddSectorLevel(ceillevel); data.AddSectorLevel(ceillevel);
} }
// Update ceiling level // Update ceiling level
data.CeilingGlow = General.Map.Data.GlowingFlats[sector.LongCeilTexture]; data.CeilingGlow = General.Map.Data.GlowingFlats[data.Sector.LongCeilTexture];
ceillevel.brightnessbelow = -1; // We need this plane for clipping only, ceillevel.brightnessbelow = -1; // We need this plane for clipping only,
ceillevel.color = 0; // so we need to reset all shading and coloring ceillevel.color = 0; // so we need to reset all shading and coloring
ceillevel.plane = data.Ceiling.plane; ceillevel.plane = data.Ceiling.plane;
@ -52,19 +42,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
// Create floor glow effect? // Create floor glow effect?
if(General.Map.Data.GlowingFlats.ContainsKey(sector.LongFloorTexture)) if(General.Map.Data.GlowingFlats.ContainsKey(data.Sector.LongFloorTexture))
{ {
// Create floor level? // Create floor level?
if(floorlevel == null) if(floorlevel == null)
{ {
floorlevel = new SectorLevel(data.Floor); floorlevel = new SectorLevel(data.Floor) { type = SectorLevelType.Glow, disablelighting = true };
floorlevel.type = SectorLevelType.Glow;
floorlevel.disablelighting = true;
data.AddSectorLevel(floorlevel); data.AddSectorLevel(floorlevel);
} }
// Update floor level // Update floor level
data.FloorGlow = General.Map.Data.GlowingFlats[sector.LongFloorTexture]; data.FloorGlow = General.Map.Data.GlowingFlats[data.Sector.LongFloorTexture];
floorlevel.plane = data.Floor.plane.GetInverted(); floorlevel.plane = data.Floor.plane.GetInverted();
floorlevel.plane.Offset += data.FloorGlow.Height; floorlevel.plane.Offset += data.FloorGlow.Height;

View file

@ -44,6 +44,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
} }
if(foundv == null) return; //mxd
// Align floor with back of line // Align floor with back of line
if((l.Args[0] == 1) && (l.Front.Sector == data.Sector)) if((l.Args[0] == 1) && (l.Front.Sector == data.Sector))
{ {
@ -54,8 +56,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
data.Floor.plane = new Plane(v1, v2, v3, true); data.Floor.plane = new Plane(v1, v2, v3, true);
else else
data.Floor.plane = new Plane(v2, v1, v3, true); data.Floor.plane = new Plane(v2, v1, v3, true);
SectorData sd = data.Mode.GetSectorData(l.Back.Sector);
sd.AddUpdateSector(data.Sector, true);
} }
// Align floor with front of line // Align floor with front of line
else if((l.Args[0] == 2) && (l.Back.Sector == data.Sector)) else if((l.Args[0] == 2) && (l.Back.Sector == data.Sector))
@ -67,8 +67,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
data.Floor.plane = new Plane(v1, v2, v3, true); data.Floor.plane = new Plane(v1, v2, v3, true);
else else
data.Floor.plane = new Plane(v2, v1, v3, true); data.Floor.plane = new Plane(v2, v1, v3, true);
SectorData sd = data.Mode.GetSectorData(l.Front.Sector);
sd.AddUpdateSector(data.Sector, true);
} }
// Align ceiling with back of line // Align ceiling with back of line
@ -81,8 +79,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
data.Ceiling.plane = new Plane(v1, v2, v3, false); data.Ceiling.plane = new Plane(v1, v2, v3, false);
else else
data.Ceiling.plane = new Plane(v2, v1, v3, false); data.Ceiling.plane = new Plane(v2, v1, v3, false);
SectorData sd = data.Mode.GetSectorData(l.Back.Sector);
sd.AddUpdateSector(data.Sector, true);
} }
// Align ceiling with front of line // Align ceiling with front of line
else if((l.Args[1] == 2) && (l.Back.Sector == data.Sector)) else if((l.Args[1] == 2) && (l.Back.Sector == data.Sector))
@ -94,8 +90,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
data.Ceiling.plane = new Plane(v1, v2, v3, false); data.Ceiling.plane = new Plane(v1, v2, v3, false);
else else
data.Ceiling.plane = new Plane(v2, v1, v3, false); data.Ceiling.plane = new Plane(v2, v1, v3, false);
SectorData sd = data.Mode.GetSectorData(l.Front.Sector);
sd.AddUpdateSector(data.Sector, true);
} }
} }
} }

View file

@ -33,6 +33,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Effects // Effects
private readonly List<SectorEffect> alleffects; private readonly List<SectorEffect> alleffects;
private readonly List<Effect3DFloor> extrafloors; private readonly List<Effect3DFloor> extrafloors;
private readonly EffectGlowingFlat glowingflateffect; //mxd
internal GlowingFlatData CeilingGlow; //mxd internal GlowingFlatData CeilingGlow; //mxd
internal GlowingFlatData FloorGlow; //mxd internal GlowingFlatData FloorGlow; //mxd
@ -91,12 +92,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
this.floorbase = new SectorLevel(sector, SectorLevelType.Floor); //mxd this.floorbase = new SectorLevel(sector, SectorLevelType.Floor); //mxd
this.ceiling = new SectorLevel(sector, SectorLevelType.Ceiling); this.ceiling = new SectorLevel(sector, SectorLevelType.Ceiling);
this.ceilingbase = new SectorLevel(sector, SectorLevelType.Ceiling); //mxd this.ceilingbase = new SectorLevel(sector, SectorLevelType.Ceiling); //mxd
this.glowingflateffect = new EffectGlowingFlat(this); //mxd
BasicSetup();
// Add ceiling and floor // Add ceiling and floor
lightlevels.Add(floor); lightlevels.Add(floor);
lightlevels.Add(ceiling); lightlevels.Add(ceiling);
BasicSetup();
} }
#endregion #endregion
@ -188,13 +190,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
alleffects.Add(e); alleffects.Add(e);
} }
//mxd.
public void AddEffectGlowingFlat(Sector sourcesector)
{
EffectGlowingFlat e = new EffectGlowingFlat(this, sourcesector);
alleffects.Add(e);
}
// This adds a sector for updating // This adds a sector for updating
public void AddUpdateSector(Sector s, bool includeneighbours) public void AddUpdateSector(Sector s, bool includeneighbours)
{ {
@ -319,6 +314,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd. We need sector brightness here, unaffected by custom ceiling brightness... //mxd. We need sector brightness here, unaffected by custom ceiling brightness...
ceilingbase.brightnessbelow = sector.Brightness; ceilingbase.brightnessbelow = sector.Brightness;
ceilingbase.color = PixelColor.FromInt(mode.CalculateBrightness(sector.Brightness)).WithAlpha(255).ToInt(); ceilingbase.color = PixelColor.FromInt(mode.CalculateBrightness(sector.Brightness)).WithAlpha(255).ToInt();
//mxd
glowingflateffect.Update();
} }
//mxd //mxd

View file

@ -93,9 +93,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
base.Texture = General.Map.Data.UnknownTexture3D; base.Texture = General.Map.Data.UnknownTexture3D;
setuponloadedtexture = s.LongCeilTexture; setuponloadedtexture = s.LongCeilTexture;
} }
else else if(!base.Texture.IsImageLoaded)
{ {
if(!base.Texture.IsImageLoaded) setuponloadedtexture = s.LongCeilTexture; setuponloadedtexture = s.LongCeilTexture;
} }
} }
else else
@ -113,11 +113,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Determine brightness // Determine brightness
int color = PixelColor.FromInt(level.color).WithAlpha((byte)General.Clamp(level.alpha, 0, 255)).ToInt(); int color = PixelColor.FromInt(level.color).WithAlpha((byte)General.Clamp(level.alpha, 0, 255)).ToInt();
//mxd. Top extrafloor level should calculate fogdensity
//from the brightness of the level above it
int targetbrightness; int targetbrightness;
if(extrafloor != null && !extrafloor.VavoomType && !level.disablelighting) if(extrafloor != null && !extrafloor.VavoomType && !level.disablelighting)
{
//mxd. Top extrafloor level should calculate fogdensity from the brightness of the level above it
if(!innerside)
{ {
targetbrightness = 0; targetbrightness = 0;
SectorData sd = mode.GetSectorData(this.Sector.Sector); SectorData sd = mode.GetSectorData(this.Sector.Sector);
@ -130,6 +130,21 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
} }
} }
//mxd. Inner extrafloor ceilings must be colored using control sector's color and brightness
else
{
targetbrightness = level.brightnessbelow;
SectorData sd = mode.GetSectorData(this.Sector.Sector);
for(int i = 0; i < sd.LightLevels.Count; i++)
{
if(sd.LightLevels[i] == level)
{
if(i > 0) color = sd.LightLevels[i - 1].color;
break;
}
}
}
}
else else
{ {
targetbrightness = level.brightnessbelow; targetbrightness = level.brightnessbelow;
@ -271,8 +286,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
UniFields.SetFloat(s.Fields, "yscaleceiling", scaleY, 1.0f); UniFields.SetFloat(s.Fields, "yscaleceiling", scaleY, 1.0f);
} }
//update geometry // Update
OnTextureChanged(); if(mode.VisualSectorExists(level.sector))
{
BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(level.sector);
vs.UpdateSectorGeometry(false);
}
s.UpdateNeeded = true; s.UpdateNeeded = true;
s.UpdateCache(); s.UpdateCache();
@ -308,8 +327,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
SetTexture(BuilderPlug.Me.CopiedFlat); SetTexture(BuilderPlug.Me.CopiedFlat);
//mxd. 3D floors may need updating... // Update
OnTextureChanged(); if(mode.VisualSectorExists(level.sector))
{
BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(level.sector);
vs.UpdateSectorGeometry(false);
}
} }
} }
@ -512,20 +535,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
// This changes the texture // This changes the texture
protected override void SetTexture(string texturename) protected override void SetTexture(string texturename)
{ {
//mxd. Glow effect may require SectorData and geometry update
bool prevtextureglows = General.Map.Data.GlowingFlats.ContainsKey(Sector.Sector.LongCeilTexture);
// Set new texture // Set new texture
level.sector.SetCeilTexture(texturename); level.sector.SetCeilTexture(texturename);
//mxd. Glow effect may require SectorData and geometry update
if(prevtextureglows
&& !General.Map.Data.GlowingFlats.ContainsKey(Sector.Sector.LongCeilTexture)
&& mode.VisualSectorExists(level.sector))
{
((BaseVisualSector)mode.GetVisualSector(level.sector)).Changed = true;
}
General.Map.Data.UpdateUsedTextures(); General.Map.Data.UpdateUsedTextures();
} }
@ -553,7 +564,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
if(side.Other != null && side.Other.Sector != Sector.Sector && !neighbours.Contains(side.Other.Sector)) if(side.Other != null && side.Other.Sector != Sector.Sector && !neighbours.Contains(side.Other.Sector))
{ {
BaseVisualSector vs = mode.GetVisualSector(side.Other.Sector) as BaseVisualSector; BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(side.Other.Sector);
if(vs == null) continue; if(vs == null) continue;
// When current ceiling is part of a 3d floor, it looks like a floor, so we need to select adjacent floors // When current ceiling is part of a 3d floor, it looks like a floor, so we need to select adjacent floors

View file

@ -93,9 +93,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
base.Texture = General.Map.Data.UnknownTexture3D; base.Texture = General.Map.Data.UnknownTexture3D;
setuponloadedtexture = s.LongFloorTexture; setuponloadedtexture = s.LongFloorTexture;
} }
else else if(!base.Texture.IsImageLoaded)
{ {
if(!base.Texture.IsImageLoaded)
setuponloadedtexture = s.LongFloorTexture; setuponloadedtexture = s.LongFloorTexture;
} }
} }
@ -259,8 +258,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
UniFields.SetFloat(s.Fields, "yscalefloor", scaleY, 1.0f); UniFields.SetFloat(s.Fields, "yscalefloor", scaleY, 1.0f);
} }
//update geometry // Update geometry
OnTextureChanged(); if(mode.VisualSectorExists(level.sector))
{
BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(level.sector);
vs.UpdateSectorGeometry(false);
}
s.UpdateNeeded = true; s.UpdateNeeded = true;
s.UpdateCache(); s.UpdateCache();
@ -296,8 +299,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
SetTexture(BuilderPlug.Me.CopiedFlat); SetTexture(BuilderPlug.Me.CopiedFlat);
//mxd. 3D floors may need updating... // Update
OnTextureChanged(); if(mode.VisualSectorExists(level.sector))
{
BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(level.sector);
vs.UpdateSectorGeometry(false);
}
} }
} }
@ -472,20 +479,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
// This changes the texture // This changes the texture
protected override void SetTexture(string texturename) protected override void SetTexture(string texturename)
{ {
//mxd. Glow effect may require SectorData and geometry update
bool prevtextureglows = General.Map.Data.GlowingFlats.ContainsKey(Sector.Sector.LongFloorTexture);
// Set new texture // Set new texture
level.sector.SetFloorTexture(texturename); level.sector.SetFloorTexture(texturename);
//mxd. Glow effect may require SectorData and geometry update
if(prevtextureglows
&& !General.Map.Data.GlowingFlats.ContainsKey(Sector.Sector.LongFloorTexture)
&& mode.VisualSectorExists(level.sector))
{
((BaseVisualSector)mode.GetVisualSector(level.sector)).Changed = true;
}
General.Map.Data.UpdateUsedTextures(); General.Map.Data.UpdateUsedTextures();
} }
@ -513,7 +508,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{ {
if(side.Other != null && side.Other.Sector != Sector.Sector && !neighbours.Contains(side.Other.Sector)) if(side.Other != null && side.Other.Sector != Sector.Sector && !neighbours.Contains(side.Other.Sector))
{ {
BaseVisualSector vs = mode.GetVisualSector(side.Other.Sector) as BaseVisualSector; BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(side.Other.Sector);
if(vs == null) continue; if(vs == null) continue;
// When current floor is part of a 3d floor, it looks like a ceiling, so we need to select adjacent ceilings // When current floor is part of a 3d floor, it looks like a ceiling, so we need to select adjacent ceilings

View file

@ -19,6 +19,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Globalization;
using CodeImp.DoomBuilder.Map; using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Geometry; using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Rendering; using CodeImp.DoomBuilder.Rendering;
@ -30,7 +31,7 @@ using CodeImp.DoomBuilder.Data;
namespace CodeImp.DoomBuilder.BuilderModes namespace CodeImp.DoomBuilder.BuilderModes
{ {
internal sealed class VisualMiddle3D : BaseVisualGeometrySidedef internal class VisualMiddle3D : BaseVisualGeometrySidedef
{ {
#region ================== Constants #region ================== Constants
@ -38,7 +39,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
#region ================== Variables #region ================== Variables
private Effect3DFloor extrafloor; protected Effect3DFloor extrafloor;
#endregion #endregion
@ -99,36 +100,35 @@ namespace CodeImp.DoomBuilder.BuilderModes
SectorData sd = mode.GetSectorData(Sidedef.Sector); SectorData sd = mode.GetSectorData(Sidedef.Sector);
//mxd. which texture we must use? //mxd. which texture we must use?
long textureLong = 0; long texturelong = 0;
if((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.UseUpperTexture) != 0) if((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.UseUpperTexture) != 0)
{ {
if(Sidedef.LongHighTexture != MapSet.EmptyLongName) if(Sidedef.LongHighTexture != MapSet.EmptyLongName)
textureLong = Sidedef.LongHighTexture; texturelong = Sidedef.LongHighTexture;
} }
else if((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.UseLowerTexture) != 0) else if((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.UseLowerTexture) != 0)
{ {
if(Sidedef.LongLowTexture != MapSet.EmptyLongName) if(Sidedef.LongLowTexture != MapSet.EmptyLongName)
textureLong = Sidedef.LongLowTexture; texturelong = Sidedef.LongLowTexture;
} }
else if(sourceside.LongMiddleTexture != MapSet.EmptyLongName) else if(sourceside.LongMiddleTexture != MapSet.EmptyLongName)
{ {
textureLong = sourceside.LongMiddleTexture; texturelong = sourceside.LongMiddleTexture;
} }
// Texture given? // Texture given?
if(textureLong != 0) if(texturelong != 0)
{ {
// Load texture // Load texture
base.Texture = General.Map.Data.GetTextureImage(textureLong); base.Texture = General.Map.Data.GetTextureImage(texturelong);
if(base.Texture == null || base.Texture is UnknownImage) if(base.Texture == null || base.Texture is UnknownImage)
{ {
base.Texture = General.Map.Data.UnknownTexture3D; base.Texture = General.Map.Data.UnknownTexture3D;
setuponloadedtexture = textureLong; setuponloadedtexture = texturelong;
} }
else else if(!base.Texture.IsImageLoaded)
{ {
if(!base.Texture.IsImageLoaded) setuponloadedtexture = texturelong;
setuponloadedtexture = textureLong;
} }
} }
else else
@ -379,14 +379,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
extrafloor.Linedef.Front.SetTextureMid(texturename); extrafloor.Linedef.Front.SetTextureMid(texturename);
General.Map.Data.UpdateUsedTextures(); General.Map.Data.UpdateUsedTextures();
this.Sector.Rebuild();
//mxd. Other sector also may require updating //mxd. Update model sector
SectorData sd = mode.GetSectorData(Sidedef.Other.Sector);
if(sd.ExtraFloors.Count > 0)
((BaseVisualSector)mode.GetVisualSector(Sidedef.Other.Sector)).Rebuild();
//mxd. As well as model sector
mode.GetVisualSector(extrafloor.Linedef.Front.Sector).UpdateSectorGeometry(false); mode.GetVisualSector(extrafloor.Linedef.Front.Sector).UpdateSectorGeometry(false);
} }
@ -407,8 +401,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
Sidedef.Fields.BeforeFieldsChange(); Sidedef.Fields.BeforeFieldsChange();
float oldx = Sidedef.Fields.GetValue("offsetx_mid", 0.0f); float oldx = Sidedef.Fields.GetValue("offsetx_mid", 0.0f);
float oldy = Sidedef.Fields.GetValue("offsety_mid", 0.0f); float oldy = Sidedef.Fields.GetValue("offsety_mid", 0.0f);
Sidedef.Fields["offsetx_mid"] = new UniValue(UniversalType.Float, oldx + xy.X); float scalex = extrafloor.Linedef.Front.Fields.GetValue("scalex_mid", 1.0f); //mxd
Sidedef.Fields["offsety_mid"] = new UniValue(UniversalType.Float, oldy + xy.Y); float scaley = extrafloor.Linedef.Front.Fields.GetValue("scaley_mid", 1.0f); //mxd
Sidedef.Fields["offsetx_mid"] = new UniValue(UniversalType.Float, GetRoundedTextureOffset(oldx, xy.X, scalex, Texture.Width)); //mxd
Sidedef.Fields["offsety_mid"] = new UniValue(UniversalType.Float, GetRoundedTextureOffset(oldy, xy.Y, scaley, Texture.Height)); //mxd
} }
protected override Point GetTextureOffset() protected override Point GetTextureOffset()
@ -430,7 +426,78 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(!General.Map.UDMF) return; if(!General.Map.UDMF) return;
if(string.IsNullOrEmpty(extrafloor.Linedef.Front.MiddleTexture) || extrafloor.Linedef.Front.MiddleTexture == "-" || !Texture.IsImageLoaded) return; if(string.IsNullOrEmpty(extrafloor.Linedef.Front.MiddleTexture) || extrafloor.Linedef.Front.MiddleTexture == "-" || !Texture.IsImageLoaded) return;
FitTexture(options); FitTexture(options);
Setup();
// Update the model sector to update all 3d floors
mode.GetVisualSector(extrafloor.Linedef.Front.Sector).UpdateSectorGeometry(false);
}
//mxd. Only control sidedef scale is used by GZDoom
public override void OnChangeScale(int incrementX, int incrementY)
{
if(!General.Map.UDMF || !Texture.IsImageLoaded) return;
if((General.Map.UndoRedo.NextUndo == null) || (General.Map.UndoRedo.NextUndo.TicketID != undoticket))
undoticket = mode.CreateUndo("Change wall scale");
Sidedef target = extrafloor.Linedef.Front;
if(target == null) return;
float scaleX = target.Fields.GetValue("scalex_mid", 1.0f);
float scaleY = target.Fields.GetValue("scaley_mid", 1.0f);
target.Fields.BeforeFieldsChange();
if(incrementX != 0)
{
float pix = (int)Math.Round(Texture.Width * scaleX) - incrementX;
float newscaleX = (float)Math.Round(pix / Texture.Width, 3);
scaleX = (newscaleX == 0 ? scaleX * -1 : newscaleX);
UniFields.SetFloat(target.Fields, "scalex_mid", scaleX, 1.0f);
}
if(incrementY != 0)
{
float pix = (int)Math.Round(Texture.Height * scaleY) - incrementY;
float newscaleY = (float)Math.Round(pix / Texture.Height, 3);
scaleY = (newscaleY == 0 ? scaleY * -1 : newscaleY);
UniFields.SetFloat(target.Fields, "scaley_mid", scaleY, 1.0f);
}
// Update the model sector to update all 3d floors
mode.GetVisualSector(extrafloor.Linedef.Front.Sector).UpdateSectorGeometry(false);
// Display result
mode.SetActionResult("Wall scale changed to " + scaleX.ToString("F03", CultureInfo.InvariantCulture) + ", " + scaleY.ToString("F03", CultureInfo.InvariantCulture) + " (" + (int)Math.Round(Texture.Width / scaleX) + " x " + (int)Math.Round(Texture.Height / scaleY) + ").");
}
//mxd
protected override void ResetTextureScale()
{
Sidedef target = extrafloor.Linedef.Front;
target.Fields.BeforeFieldsChange();
if(target.Fields.ContainsKey("scalex_mid")) target.Fields.Remove("scalex_mid");
if(target.Fields.ContainsKey("scaley_mid")) target.Fields.Remove("scaley_mid");
}
//mxd
public override void OnResetTextureOffset()
{
base.OnResetTextureOffset();
// Update the model sector to update all 3d floors
mode.GetVisualSector(extrafloor.Linedef.Front.Sector).UpdateSectorGeometry(false);
}
//mxd
public override void OnResetLocalTextureOffset()
{
if(!General.Map.UDMF)
{
OnResetTextureOffset();
return;
}
base.OnResetLocalTextureOffset();
// Update the model sector to update all 3d floors // Update the model sector to update all 3d floors
mode.GetVisualSector(extrafloor.Linedef.Front.Sector).UpdateSectorGeometry(false); mode.GetVisualSector(extrafloor.Linedef.Front.Sector).UpdateSectorGeometry(false);

View file

@ -1,12 +1,9 @@
#region ================== Namespaces #region ================== Namespaces
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing;
using CodeImp.DoomBuilder.Map; using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Geometry; using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Rendering; using CodeImp.DoomBuilder.Rendering;
using CodeImp.DoomBuilder.Types;
using CodeImp.DoomBuilder.VisualModes; using CodeImp.DoomBuilder.VisualModes;
using CodeImp.DoomBuilder.Data; using CodeImp.DoomBuilder.Data;
@ -15,31 +12,16 @@ using CodeImp.DoomBuilder.Data;
namespace CodeImp.DoomBuilder.BuilderModes namespace CodeImp.DoomBuilder.BuilderModes
{ {
//mxd. Used to render translucent 3D floor's inner sides //mxd. Used to render translucent 3D floor's inner sides
internal sealed class VisualMiddleBack : BaseVisualGeometrySidedef internal sealed class VisualMiddleBack : VisualMiddle3D
{ {
#region ================== Variables
private Effect3DFloor extrafloor;
#endregion
#region ================== Constructor / Setup #region ================== Constructor / Setup
// Constructor // Constructor
public VisualMiddleBack(BaseVisualMode mode, VisualSector vs, Sidedef s) public VisualMiddleBack(BaseVisualMode mode, VisualSector vs, Sidedef s) : base(mode, vs, s) { }
: base(mode, vs, s)
{
//mxd
geometrytype = VisualGeometryType.WALL_MIDDLE;
partname = "mid";
// We have no destructor
GC.SuppressFinalize(this);
}
// This builds the geometry. Returns false when no geometry created. // This builds the geometry. Returns false when no geometry created.
public override bool Setup() { return this.Setup(this.extrafloor); } public override bool Setup() { return this.Setup(this.extrafloor); }
public bool Setup(Effect3DFloor extrafloor) public new bool Setup(Effect3DFloor extrafloor)
{ {
Sidedef sourceside = extrafloor.Linedef.Front; Sidedef sourceside = extrafloor.Linedef.Front;
this.extrafloor = extrafloor; this.extrafloor = extrafloor;
@ -77,35 +59,35 @@ namespace CodeImp.DoomBuilder.BuilderModes
SectorData sd = mode.GetSectorData(Sidedef.Other.Sector); SectorData sd = mode.GetSectorData(Sidedef.Other.Sector);
//mxd. which texture we must use? //mxd. which texture we must use?
long longtexture = 0; long texturelong = 0;
if((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.UseUpperTexture) != 0) if((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.UseUpperTexture) != 0)
{ {
if(Sidedef.Other.LongHighTexture != MapSet.EmptyLongName) if(Sidedef.LongHighTexture != MapSet.EmptyLongName)
longtexture = Sidedef.Other.LongHighTexture; texturelong = Sidedef.LongHighTexture;
} }
else if((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.UseLowerTexture) != 0) else if((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.UseLowerTexture) != 0)
{ {
if(Sidedef.Other.LongLowTexture != MapSet.EmptyLongName) if(Sidedef.LongLowTexture != MapSet.EmptyLongName)
longtexture = Sidedef.Other.LongLowTexture; texturelong = Sidedef.LongLowTexture;
} }
else if((sourceside.LongMiddleTexture != MapSet.EmptyLongName)) else if(sourceside.LongMiddleTexture != MapSet.EmptyLongName)
{ {
longtexture = sourceside.LongMiddleTexture; texturelong = sourceside.LongMiddleTexture;
} }
// Texture given? // Texture given?
if(longtexture != 0) if(texturelong != 0)
{ {
// Load texture // Load texture
base.Texture = General.Map.Data.GetTextureImage(longtexture); base.Texture = General.Map.Data.GetTextureImage(texturelong);
if(base.Texture == null || base.Texture is UnknownImage) if(base.Texture == null || base.Texture is UnknownImage)
{ {
base.Texture = General.Map.Data.UnknownTexture3D; base.Texture = General.Map.Data.UnknownTexture3D;
setuponloadedtexture = longtexture; setuponloadedtexture = texturelong;
} }
else if(!base.Texture.IsImageLoaded) else if(!base.Texture.IsImageLoaded)
{ {
setuponloadedtexture = longtexture; setuponloadedtexture = texturelong;
} }
} }
else else
@ -179,8 +161,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(((cl - fl) > 0.01f) || ((cr - fr) > 0.01f)) if(((cl - fl) > 0.01f) || ((cr - fr) > 0.01f))
{ {
// Keep top and bottom planes for intersection testing // Keep top and bottom planes for intersection testing
bottom = extrafloor.Ceiling.plane;
top = extrafloor.Floor.plane; top = extrafloor.Floor.plane;
bottom = extrafloor.Ceiling.plane;
// Create initial polygon, which is just a quad between floor and ceiling // Create initial polygon, which is just a quad between floor and ceiling
WallPolygon poly = new WallPolygon(); WallPolygon poly = new WallPolygon();
@ -189,7 +171,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
poly.Add(new Vector3D(vr.x, vr.y, cr)); poly.Add(new Vector3D(vr.x, vr.y, cr));
poly.Add(new Vector3D(vr.x, vr.y, fr)); poly.Add(new Vector3D(vr.x, vr.y, fr));
// Determine initial color // Determine initial color. Inside parts are shaded using control sector's brightness
int lightlevel; int lightlevel;
PixelColor levelcolor; //mxd PixelColor levelcolor; //mxd
if(((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.DisableLighting) != 0)) if(((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.DisableLighting) != 0))
@ -220,6 +202,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
// or when only our extrafloor is translucent // or when only our extrafloor is translucent
if(ef.ClipSidedefs == extrafloor.ClipSidedefs || ef.ClipSidedefs) if(ef.ClipSidedefs == extrafloor.ClipSidedefs || ef.ClipSidedefs)
{ {
//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++)
{ {
@ -281,113 +266,5 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
#endregion #endregion
#region ================== Methods
// Alpha based picking
public override bool PickAccurate(Vector3D from, Vector3D to, Vector3D dir, ref float u_ray)
{
if(!Texture.IsImageLoaded || (!Texture.IsTranslucent && !Texture.IsMasked)) return base.PickAccurate(from, to, dir, ref u_ray);
float u;
Sidedef sourceside = extrafloor.Linedef.Front;
new Line2D(from, to).GetIntersection(Sidedef.Line.Line, out u);
if(Sidedef != Sidedef.Line.Front) u = 1.0f - u;
// Some textures (e.g. HiResImage) may lie about their size, so use bitmap size instead
Bitmap image = Texture.GetBitmap();
// Determine texture scale...
Vector2D imgscale = new Vector2D((float)Texture.Width / image.Width, (float)Texture.Height / image.Height);
Vector2D texscale = (Texture is HiResImage) ? imgscale * Texture.Scale : Texture.Scale;
// Get correct offset to texture space...
float texoffsetx = Sidedef.OffsetX + sourceside.OffsetX + UniFields.GetFloat(Sidedef.Fields, "offsetx_mid") + UniFields.GetFloat(sourceside.Fields, "offsetx_mid");
int ox = (int)Math.Floor((u * Sidedef.Line.Length * UniFields.GetFloat(sourceside.Fields, "scalex_mid", 1.0f) / texscale.x + (texoffsetx / imgscale.x)) % image.Width);
float texoffsety = Sidedef.OffsetY + sourceside.OffsetY + UniFields.GetFloat(Sidedef.Fields, "offsety_mid") + UniFields.GetFloat(sourceside.Fields, "offsety_mid");
int oy = (int)Math.Ceiling(((pickintersect.z - sourceside.Sector.CeilHeight) * UniFields.GetFloat(sourceside.Fields, "scaley_mid", 1.0f) / texscale.y - (texoffsety / imgscale.y)) % image.Height);
// Make sure offsets are inside of texture dimensions...
if(ox < 0) ox += image.Width;
if(oy < 0) oy += image.Height;
// Check pixel alpha
Point pixelpos = new Point(General.Clamp(ox, 0, image.Width - 1), General.Clamp(image.Height - oy, 0, image.Height - 1));
return (image.GetPixel(pixelpos.X, pixelpos.Y).A > 0 && base.PickAccurate(@from, to, dir, ref u_ray));
}
// Return texture name
public override string GetTextureName()
{
//mxd
if((extrafloor.Linedef.Args[2] & (int)Effect3DFloor.Flags.UseUpperTexture) != 0)
return Sidedef.HighTexture;
if((extrafloor.Linedef.Args[2] & (int)Effect3DFloor.Flags.UseLowerTexture) != 0)
return Sidedef.LowTexture;
return extrafloor.Linedef.Front.MiddleTexture;
}
// This changes the texture
protected override void SetTexture(string texturename)
{
//mxd
if((extrafloor.Linedef.Args[2] & (int)Effect3DFloor.Flags.UseUpperTexture) != 0)
Sidedef.Other.SetTextureHigh(texturename);
if((extrafloor.Linedef.Args[2] & (int)Effect3DFloor.Flags.UseLowerTexture) != 0)
Sidedef.Other.SetTextureLow(texturename);
else
extrafloor.Linedef.Front.SetTextureMid(texturename);
General.Map.Data.UpdateUsedTextures();
this.Sector.Rebuild();
//mxd. Other sector also may require updating
((BaseVisualSector)mode.GetVisualSector(Sidedef.Other.Sector)).Rebuild();
//mxd. As well as model sector
mode.GetVisualSector(extrafloor.Linedef.Front.Sector).UpdateSectorGeometry(false);
}
protected override void SetTextureOffsetX(int x)
{
Sidedef.Fields.BeforeFieldsChange();
Sidedef.Fields["offsetx_mid"] = new UniValue(UniversalType.Float, (float)x);
}
protected override void SetTextureOffsetY(int y)
{
Sidedef.Fields.BeforeFieldsChange();
Sidedef.Fields["offsety_mid"] = new UniValue(UniversalType.Float, (float)y);
}
protected override void MoveTextureOffset(Point xy)
{
Sidedef.Fields.BeforeFieldsChange();
float oldx = Sidedef.Fields.GetValue("offsetx_mid", 0.0f);
float oldy = Sidedef.Fields.GetValue("offsety_mid", 0.0f);
float scalex = Sidedef.Fields.GetValue("scalex_mid", 1.0f);
float scaley = Sidedef.Fields.GetValue("scaley_mid", 1.0f);
Sidedef.Fields["offsetx_mid"] = new UniValue(UniversalType.Float, GetRoundedTextureOffset(oldx, xy.X, scalex, Texture != null ? Texture.Width : -1)); //mxd
//mxd. Don't clamp offsetY of clipped mid textures
bool dontClamp = (Texture == null || Sidedef.IsFlagSet("clipmidtex") || Sidedef.Line.IsFlagSet("clipmidtex"));
Sidedef.Fields["offsety_mid"] = new UniValue(UniversalType.Float, GetRoundedTextureOffset(oldy, xy.Y, scaley, dontClamp ? -1 : Texture.Height));
}
protected override Point GetTextureOffset()
{
float oldx = Sidedef.Fields.GetValue("offsetx_mid", 0.0f);
float oldy = Sidedef.Fields.GetValue("offsety_mid", 0.0f);
return new Point((int)oldx, (int)oldy);
}
//mxd
public override Linedef GetControlLinedef()
{
return extrafloor.Linedef;
}
#endregion
} }
} }

View file

@ -274,6 +274,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(string.IsNullOrEmpty(Sidedef.MiddleTexture) || Sidedef.MiddleTexture == "-" || !Texture.IsImageLoaded) return; if(string.IsNullOrEmpty(Sidedef.MiddleTexture) || Sidedef.MiddleTexture == "-" || !Texture.IsImageLoaded) return;
FitTexture(options); FitTexture(options);
Setup(); Setup();
// Update linked effects
SectorData sd = mode.GetSectorDataEx(Sector.Sector);
if(sd != null) sd.Reset(true);
} }
#endregion #endregion