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,6 +386,16 @@ keywords
A_SPosAttackUseAtkSound = "A_SPosAttackUseAtkSound";
//Mathematical functions
abs = "abs(x)\nReturns the absolute value of 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.";
log10 = "log10(x)\nReturns the common (base-10) logarithm of x.";
ceil = "ceil(x)\nRounds the number upward to the next closest integer.";
floor = "floor(x)\nRounds the number downward to the next closest integer.";
sqrt = "sqrt(x)\nReturns the square root of x.";
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.";
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.";
@ -395,15 +405,8 @@ keywords
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.";
log = "log(x)\nReturns the natural logarithm of x - the opposite of exp.";
log10 = "log10(x)\nReturns the common (base-10) logarithm of x.";
ceil = "ceil(x)\nRounds the number upward to the next closest integer.";
floor = "floor(x)\nRounds the number downward to the next closest integer.";
sqrt = "sqrt(x)\nReturns the square root of x.";
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.";
clamp = "clamp(src, min, max)\nReturns src within the range of min and max inclusively. All parameters can be ints or floats.";
atan2 = "atan2(y, x)\nTrigonometry function, Returns an angle in degrees.";
VectorAngle = "VectorAngle(x, y)\nTrigonometry function.";
//Randum number functions
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.";

View file

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

View file

@ -132,7 +132,7 @@ namespace CodeImp.DoomBuilder.ZDoom
{
case "int":
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 + "\"");
return false;
@ -146,7 +146,7 @@ namespace CodeImp.DoomBuilder.ZDoom
case "float":
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 + "\"");
return false;

View file

@ -388,10 +388,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
TextLabel[] larr = new TextLabel[s.Labels.Count];
for(int i = 0; i < s.Labels.Count; i++)
{
Vector2D v = s.Labels[i].position;
TextLabel l = new TextLabel();
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.AlignY = TextAlignmentY.Middle;
l.Color = General.Colors.InfoLine;

View file

@ -153,10 +153,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
TextLabel[] labelarray = new TextLabel[s.Labels.Count];
for(int i = 0; i < s.Labels.Count; i++)
{
Vector2D v = s.Labels[i].position;
labelarray[i] = new TextLabel();
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].AlignY = TextAlignmentY.Middle;
labelarray[i].Color = c;

View file

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

View file

@ -32,7 +32,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
bool endvisible = viewport.Contains(end.x, end.y);
// Get visile area
RectangleF labelrect;
if(!startvisible || !endvisible)
{
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);
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
{
Vector2D delta = end - start;
labelrect = new RectangleF(start.x + delta.x * 0.5f, start.y + delta.y * 0.5f, 0f, 0f);
}
// Apply changes
label.Rectangle = labelrect;
label.Location = new Vector2D(start.x + delta.x * 0.5f, start.y + delta.y * 0.5f);
}
}
}
}

View file

@ -204,7 +204,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Apply changes
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

View file

@ -231,44 +231,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
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
public virtual bool IsSelected()
{
@ -449,18 +411,29 @@ namespace CodeImp.DoomBuilder.BuilderModes
mode.CreateUndo(undodescription);
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);
Sector.Sector.UpdateNeeded = true;
level.sector.Fields.Remove(key);
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
@ -576,7 +549,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(mode.VisualSectorExists(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.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"
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))
{
BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(level.sector);
@ -766,7 +725,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
mode.CreateUndo("Change flat \"" + texture + "\"");
SetTexture(texture);
OnTextureChanged(); //mxd
// Update
if(mode.VisualSectorExists(level.sector))
{
BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(level.sector);
vs.UpdateSectorGeometry(false);
}
}
// Copy texture
@ -837,8 +802,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
else
{
//mxd. Need this to apply changes to 3d-floor even if control sector doesn't exist
//as BaseVisualSector
//mxd. Need this to apply changes to 3d-floor even if control sector doesn't exist as BaseVisualSector
vs = mode.CreateBaseVisualSector(level.sector);
}

View file

@ -66,7 +66,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
private bool performautoselection; //mxd
// Undo/redo
private int undoticket;
protected int undoticket;
#endregion
@ -532,26 +532,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
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
public void SelectNeighbours(bool select, bool matchtexture, bool matchheight)
{
@ -594,7 +574,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd
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)
{
VisualSidedefParts parts = s.GetSidedefParts(side);
@ -778,7 +758,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Update
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.");
SetTexture("-");
// Update
Sector.UpdateSectorGeometry(true);
//mxd. Update linked effects
SectorData sd = mode.GetSectorDataEx(Sector.Sector);
if(sd != null) sd.Reset(true);
}
// Processing
@ -871,12 +852,29 @@ namespace CodeImp.DoomBuilder.BuilderModes
ResetTextureScale();
// And brightness
if(Sidedef.Fields.ContainsKey("light")) Sidedef.Fields.Remove("light");
if(Sidedef.Fields.ContainsKey("lightabsolute")) Sidedef.Fields.Remove("lightabsolute");
bool setupallparts = false;
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
VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef);
parts.SetupAllParts();
if(setupallparts)
{
// Update all sidedef geometry
VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef);
parts.SetupAllParts();
}
else
{
// Update this part only
this.Setup();
}
}
// Toggle upper-unpegged
@ -1034,7 +1032,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Update the parts for this sidedef!
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);
parts.SetupAllParts();
}
@ -1112,7 +1110,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
mode.CreateUndo("Change texture " + texture);
SetTexture(texture);
OnTextureChanged();//mxd
//mxd. Update linked effects
SectorData sd = mode.GetSectorDataEx(Sector.Sector);
if(sd != null) sd.Reset(true);
}
// Paste texture
@ -1123,7 +1124,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
mode.CreateUndo("Paste texture \"" + BuilderPlug.Me.CopiedTexture + "\"");
mode.SetActionResult("Pasted texture \"" + 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,17 +1139,25 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
SetTextureOffsetX(BuilderPlug.Me.CopiedOffsets.X);
SetTextureOffsetY(BuilderPlug.Me.CopiedOffsets.Y);
// Update sidedef part geometry
this.Setup();
}
else
{
Sidedef.OffsetX = BuilderPlug.Me.CopiedOffsets.X;
Sidedef.OffsetY = BuilderPlug.Me.CopiedOffsets.Y;
// Update sidedef geometry
VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef);
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 + ".");
// Update sidedef geometry
VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef);
parts.SetupAllParts();
}
// Copy texture
@ -1262,9 +1274,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
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;
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);
General.Interface.OnEditFormValuesChanged -= Interface_OnEditFormValuesChanged;
@ -1393,18 +1409,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(newlight == light) return;
//create undo
// Create undo
mode.CreateUndo("Change wall brightness", UndoGroup.SurfaceBrightnessChange, Sector.Sector.FixedIndex);
Sidedef.Fields.BeforeFieldsChange();
//apply changes
// Apply changes
UniFields.SetInteger(Sidedef.Fields, "light", newlight, (absolute ? int.MinValue : 0));
Tools.UpdateLightFogFlag(Sidedef);
mode.SetActionResult("Changed wall brightness to " + newlight + ".");
Sector.Sector.UpdateCache();
//rebuild sector
Sector.UpdateSectorGeometry(false);
// Update this part only
this.Setup();
}
else if(!Sector.Changed)
{
@ -1431,7 +1446,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(mode.VisualThingExists(t))
{
// Update thing
BaseVisualThing vt = (mode.GetVisualThing(t) as BaseVisualThing);
BaseVisualThing vt = (BaseVisualThing)mode.GetVisualThing(t);
vt.Changed = true;
}
}
@ -1452,6 +1467,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
MoveTextureOffset(new Point(-horizontal, -vertical));
Point p = GetTextureOffset();
mode.SetActionResult("Changed texture offsets to " + p.X + ", " + p.Y + ".");
// Update this part only
this.Setup();
}
else
{
@ -1462,11 +1480,15 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(geometrytype != VisualGeometryType.WALL_MIDDLE && Texture != null) Sidedef.OffsetY %= Texture.Height;
mode.SetActionResult("Changed texture offsets to " + Sidedef.OffsetX + ", " + Sidedef.OffsetY + ".");
// Update all sidedef geometry
VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef);
parts.SetupAllParts();
}
// Update sidedef geometry
VisualSidedefParts parts = Sector.GetSidedefParts(Sidedef);
parts.SetupAllParts();
//mxd. Update linked effects
SectorData sd = mode.GetSectorDataEx(Sector.Sector);
if(sd != null) sd.Reset(true);
}
//mxd
@ -1488,7 +1510,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
break;
case VisualGeometryType.WALL_MIDDLE:
case VisualGeometryType.WALL_MIDDLE_3D:
keyX = "scalex_mid";
keyY = "scaley_mid";
break;
@ -1523,8 +1544,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
UniFields.SetFloat(Sidedef.Fields, keyY, scaleY, 1.0f);
}
//update geometry
// Update geometry
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) + ").");
}

View file

@ -282,7 +282,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Reset changed flags
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(VisualCeiling vc in bvs.ExtraCeilings) vc.Changed = false;
foreach(VisualFloor vf in bvs.ExtraBackFloors) vf.Changed = false; //mxd
@ -343,7 +343,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
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.Ceiling != null) && bvs.Ceiling.Selected) selectedobjects.Add(bvs.Ceiling);
foreach(Sidedef sd in vs.Key.Sidedefs)
@ -351,7 +351,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
List<VisualGeometry> sidedefgeos = bvs.GetSidedefGeometry(sd);
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)
{
BaseVisualThing bvt = vt.Value as BaseVisualThing;
BaseVisualThing bvt = (BaseVisualThing)vt.Value;
if(bvt.Selected) selectedobjects.Add(bvt);
}
}
@ -502,7 +502,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if(vs.Value != null)
{
BaseVisualSector bvs = vs.Value as BaseVisualSector;
BaseVisualSector bvs = (BaseVisualSector)vs.Value;
if(bvs.Changed) bvs.Rebuild();
}
}
@ -511,7 +511,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if(vt.Value != null)
{
BaseVisualThing bvt = vt.Value as BaseVisualThing;
BaseVisualThing bvt = (BaseVisualThing)vt.Value;
if(bvt.Changed) bvt.Rebuild();
}
}
@ -543,7 +543,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
Vector3D[] translatedcoords = TranslateCoordinates(coords, direction, absoluteposition);
for(int i = 0; i < visualthings.Count; i++)
{
BaseVisualThing t = visualthings[i] as BaseVisualThing;
BaseVisualThing t = (BaseVisualThing)visualthings[i];
t.OnMove(translatedcoords[i]);
}
@ -735,7 +735,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(!vertices.ContainsKey(v))
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
@ -785,7 +785,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// The visual sector associated is now outdated
if(VisualSectorExists(sectorsWithEffects[i]))
{
BaseVisualSector vs = GetVisualSector(sectorsWithEffects[i]) as BaseVisualSector;
BaseVisualSector vs = (BaseVisualSector)GetVisualSector(sectorsWithEffects[i]);
vs.UpdateSectorGeometry(true);
}
}
@ -853,13 +853,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
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)
@ -1077,7 +1070,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
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))
{
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
|| 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))
{
selectedlineindices.Add(vg.Sidedef.Line.Index);
@ -1096,7 +1089,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
else if(obj is VisualVertex)
{
VisualVertex v = obj as VisualVertex;
VisualVertex v = (VisualVertex)obj;
if(!selectedvertexindices.Contains(v.Vertex.Index))
{
selectedvertexindices.Add(v.Vertex.Index);
@ -1293,7 +1286,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if(sd.Marked && VisualSectorExists(sd.Sector))
{
BaseVisualSector vs = GetVisualSector(sd.Sector) as BaseVisualSector;
BaseVisualSector vs = (BaseVisualSector)GetVisualSector(sd.Sector);
VisualSidedefParts parts = vs.GetSidedefParts(sd);
parts.SetupAllParts();
}
@ -1304,23 +1297,26 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if(s.Marked)
{
SectorData sd = GetSectorData(s);
sd.Reset(false); //mxd (changed Reset implementation)
// UpdateSectorGeometry for associated sectors (sd.UpdateAlso) as well!
foreach(KeyValuePair<Sector, bool> us in sd.UpdateAlso)
SectorData sd = GetSectorDataEx(s);
if(sd != null)
{
if(VisualSectorExists(us.Key))
sd.Reset(false); //mxd (changed Reset implementation)
// UpdateSectorGeometry for associated sectors (sd.UpdateAlso) as well!
foreach(KeyValuePair<Sector, bool> us in sd.UpdateAlso)
{
BaseVisualSector vs = GetVisualSector(us.Key) as BaseVisualSector;
vs.UpdateSectorGeometry(us.Value);
if(VisualSectorExists(us.Key))
{
BaseVisualSector vs = (BaseVisualSector)GetVisualSector(us.Key);
vs.UpdateSectorGeometry(us.Value);
}
}
}
// And update for this sector ofcourse
if(VisualSectorExists(s))
{
BaseVisualSector vs = GetVisualSector(s) as BaseVisualSector;
BaseVisualSector vs = (BaseVisualSector)GetVisualSector(s);
vs.UpdateSectorGeometry(false);
}
}
@ -1336,7 +1332,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if((vt.Value != null) && vt.Key.Marked)
{
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();
//mxd. Effects may've become invalid
if(General.Settings.GZDoomRenderingEffects && sectordata != null && sectordata.Count > 0)
RebuildElementData();
if(sectordata != null && sectordata.Count > 0) RebuildElementData();
//mxd. As well as geometry...
foreach(KeyValuePair<Sector, VisualSector> group in visiblesectors)
{
BaseVisualSector vs = group.Value as BaseVisualSector;
BaseVisualSector vs = (BaseVisualSector)group.Value;
if(vs != null) vs.Rebuild();
}
@ -1445,13 +1440,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
base.OnRedoEnd();
//mxd. Effects may've become invalid
if(sectordata != null && sectordata.Count > 0)
RebuildElementData();
if(sectordata != null && sectordata.Count > 0) RebuildElementData();
//mxd. As well as geometry...
foreach(KeyValuePair<Sector, VisualSector> group in visiblesectors)
{
BaseVisualSector vs = group.Value as BaseVisualSector;
BaseVisualSector vs = (BaseVisualSector)group.Value;
if(vs != null) vs.Rebuild();
}
@ -1466,7 +1460,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Reset changed flags
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(VisualCeiling vc in bvs.ExtraCeilings) vc.Changed = false;
foreach(VisualFloor vf in bvs.ExtraBackFloors) vf.Changed = false;
@ -1494,7 +1488,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if(VisualSectorExists(s.Key))
{
BaseVisualSector vs = GetVisualSector(s.Key) as BaseVisualSector;
BaseVisualSector vs = (BaseVisualSector)GetVisualSector(s.Key);
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
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)
{
if(!(i is BaseVisualGeometrySidedef)) continue;
BaseVisualGeometrySidedef vs = i as BaseVisualGeometrySidedef; //mxd
if(!donesides.ContainsKey(vs))
BaseVisualGeometrySidedef vs = (BaseVisualGeometrySidedef)i; //mxd
if(!donesides.Contains(vs))
{
//mxd. added scaling by texture scale
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);
donesides.Add(vs, false);
donesides.Add(vs);
}
}
}
else
{
Dictionary<Sidedef, bool> donesides = new Dictionary<Sidedef, bool>(selectedobjects.Count);
HashSet<Sidedef> donesides = new HashSet<Sidedef>();
foreach(IVisualEventReceiver i in objs)
{
if(!(i is BaseVisualGeometrySidedef)) continue;
BaseVisualGeometrySidedef vs = i as BaseVisualGeometrySidedef; //mxd
if(!donesides.ContainsKey(vs.Sidedef))
BaseVisualGeometrySidedef vs = (BaseVisualGeometrySidedef)i; //mxd
if(!donesides.Contains(vs.Sidedef))
{
//mxd. added scaling by texture scale
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);
donesides.Add(vs.Sidedef, false);
donesides.Add(vs.Sidedef);
}
}
}
@ -1572,17 +1564,15 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Apply flat offsets
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);
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))
{
i.OnChangeTextureOffset(dx, dy, false);
donesectors.Add((i as BaseVisualGeometrySector).Sector.Sector, 0);
}
bvs.OnChangeTextureOffset(dx, dy, false);
donesectors.Add(bvs.Sector.Sector);
}
}
}
@ -1657,7 +1647,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd
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>();
foreach(IVisualEventReceiver i in objs)
@ -1665,9 +1655,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
BaseVisualGeometrySidedef sidedef = i as BaseVisualGeometrySidedef;
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);
}
}
@ -1683,15 +1673,15 @@ namespace CodeImp.DoomBuilder.BuilderModes
// This returns all selected sectors, no doubles
public List<Sector> GetSelectedSectors()
{
Dictionary<Sector, int> added = new Dictionary<Sector, int>();
HashSet<Sector> added = new HashSet<Sector>();
List<Sector> sectors = new List<Sector>();
foreach(IVisualEventReceiver i in selectedobjects)
{
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);
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))
{
Sector s = ((BaseVisualGeometrySector)target.picked).Level.sector;
if(!added.ContainsKey(s)) sectors.Add(s);
if(!added.Contains(s)) sectors.Add(s);
}
return sectors;
@ -1708,7 +1698,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// This returns all selected linedefs, no doubles
public List<Linedef> GetSelectedLinedefs()
{
Dictionary<Linedef, int> added = new Dictionary<Linedef, int>();
HashSet<Linedef> added = new HashSet<Linedef>();
List<Linedef> linedefs = new List<Linedef>();
foreach(IVisualEventReceiver i in selectedobjects)
{
@ -1716,10 +1706,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(sidedef != null)
{
Linedef l = sidedef.GetControlLinedef(); //mxd
if(!added.ContainsKey(l))
if(!added.Contains(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))
{
Linedef l = ((BaseVisualGeometrySidedef)target.picked).GetControlLinedef(); //mxd
if(!added.ContainsKey(l)) linedefs.Add(l);
if(!added.Contains(l)) linedefs.Add(l);
}
return linedefs;
@ -1737,15 +1727,15 @@ namespace CodeImp.DoomBuilder.BuilderModes
// This returns all selected sidedefs, no doubles
public List<Sidedef> GetSelectedSidedefs()
{
Dictionary<Sidedef, int> added = new Dictionary<Sidedef, int>();
HashSet<Sidedef> added = new HashSet<Sidedef>();
List<Sidedef> sidedefs = new List<Sidedef>();
foreach(IVisualEventReceiver i in selectedobjects)
{
BaseVisualGeometrySidedef sidedef = i as BaseVisualGeometrySidedef;
if(sidedef != null && !added.ContainsKey(sidedef.Sidedef))
if(sidedef != null && !added.Contains(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))
{
Sidedef sd = ((BaseVisualGeometrySidedef)target.picked).Sidedef;
if(!added.ContainsKey(sd)) sidedefs.Add(sd);
if(!added.Contains(sd)) sidedefs.Add(sd);
}
return sidedefs;
@ -1762,15 +1752,15 @@ namespace CodeImp.DoomBuilder.BuilderModes
// This returns all selected things, no doubles
public List<Thing> GetSelectedThings()
{
Dictionary<Thing, int> added = new Dictionary<Thing, int>();
HashSet<Thing> added = new HashSet<Thing>();
List<Thing> things = new List<Thing>();
foreach(IVisualEventReceiver i in selectedobjects)
{
BaseVisualThing thing = i as BaseVisualThing;
if(thing != null && !added.ContainsKey(thing.Thing))
if(thing != null && !added.Contains(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))
{
Thing t = ((BaseVisualThing)target.picked).Thing;
if(!added.ContainsKey(t)) things.Add(t);
if(!added.Contains(t)) things.Add(t);
}
return things;
@ -1787,20 +1777,16 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd. This returns all selected vertices, no doubles
public List<Vertex> GetSelectedVertices()
{
Dictionary<Vertex, int> added = new Dictionary<Vertex, int>();
HashSet<Vertex> added = new HashSet<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;
if(!added.ContainsKey(v))
{
verts.Add(v);
added.Add(v, 0);
}
verts.Add(vertex.Vertex);
added.Add(vertex.Vertex);
}
}
@ -1808,7 +1794,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if((selectedobjects.Count == 0) && (target.picked is BaseVisualVertex))
{
Vertex v = ((BaseVisualVertex)target.picked).Vertex;
if(!added.ContainsKey(v)) verts.Add(v);
if(!added.Contains(v)) verts.Add(v);
}
return verts;
@ -1821,7 +1807,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if(singleselection || target.picked.Selected || targetonly)
{
return target.picked as IVisualEventReceiver;
return (IVisualEventReceiver)target.picked;
}
if(selectedobjects.Count > 0)
@ -1829,7 +1815,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
return selectedobjects[0];
}
return target.picked as IVisualEventReceiver;
return (IVisualEventReceiver)target.picked;
}
return new NullVisualEventReceiver();
@ -1907,7 +1893,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if(vt.Value != null)
{
BaseVisualThing bvt = vt.Value as BaseVisualThing;
BaseVisualThing bvt = (BaseVisualThing)vt.Value;
bvt.Selected = false;
}
}
@ -2023,20 +2009,19 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Get selection
if(selectedobjects.Count == 0)
{
IVisualEventReceiver i = (target.picked as IVisualEventReceiver);
if(i is VisualFloor)
if(target.picked is VisualFloor)
{
VisualFloor vf = i as VisualFloor;
VisualFloor vf = (VisualFloor)target.picked;
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);
}
else if(i is BaseVisualThing)
else if(target.picked is BaseVisualThing)
{
things.Add(i as BaseVisualThing);
things.Add((BaseVisualThing)target.picked);
}
}
else
@ -2045,17 +2030,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if(i is VisualFloor)
{
VisualFloor vf = i as VisualFloor;
VisualFloor vf = (VisualFloor)i;
floors.Add(vf.Level.sector, vf);
}
else if(i is VisualCeiling)
{
VisualCeiling vc = i as VisualCeiling;
VisualCeiling vc = (VisualCeiling)i;
ceilings.Add(vc.Level.sector, vc);
}
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>();
bool withinSelection = General.Interface.CtrlState;
//get selection
// Get selection
if(selectedobjects.Count == 0)
{
IVisualEventReceiver i = (target.picked as IVisualEventReceiver);
if(i is VisualFloor)
if(target.picked is VisualFloor)
{
VisualFloor vf = i as VisualFloor;
VisualFloor vf = (VisualFloor)target.picked;
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);
}
else if(i is BaseVisualThing)
else if(target.picked is BaseVisualThing)
{
things.Add(i as BaseVisualThing);
things.Add((BaseVisualThing)target.picked);
}
}
else
@ -2246,17 +2230,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if(i is VisualFloor)
{
VisualFloor vf = i as VisualFloor;
VisualFloor vf = (VisualFloor)i;
floors.Add(vf.Level.sector, vf);
}
else if(i is VisualCeiling)
{
VisualCeiling vc = i as VisualCeiling;
VisualCeiling vc = (VisualCeiling)i;
ceilings.Add(vc.Level.sector, vc);
}
else if(i is BaseVisualThing)
{
things.Add(i as BaseVisualThing);
things.Add((BaseVisualThing)i);
}
}
}
@ -2427,7 +2411,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
return;
}
IVisualEventReceiver highlighted = (target.picked as IVisualEventReceiver);
IVisualEventReceiver highlighted = (IVisualEventReceiver)target.picked;
if(highlighted is BaseVisualThing)
{
@ -2439,7 +2423,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
int targetbrightness;
if(highlighted is VisualFloor)
{
VisualFloor v = highlighted as VisualFloor;
VisualFloor v = (VisualFloor)highlighted;
targetbrightness = v.Level.sector.Fields.GetValue("lightfloor", 0);
if(!v.Level.sector.Fields.GetValue("lightfloorabsolute", false))
{
@ -2448,7 +2432,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
else if(highlighted is VisualCeiling)
{
VisualCeiling v = highlighted as VisualCeiling;
VisualCeiling v = (VisualCeiling)highlighted;
targetbrightness = v.Level.sector.Fields.GetValue("lightceiling", 0);
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)
{
BaseVisualGeometrySidedef v = highlighted as BaseVisualGeometrySidedef;
BaseVisualGeometrySidedef v = (BaseVisualGeometrySidedef)highlighted;
targetbrightness = v.Sidedef.Fields.GetValue("light", 0);
if(!v.Sidedef.Fields.GetValue("lightabsolute", false))
{
@ -2466,7 +2450,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
else if(highlighted is VisualMiddle3D)
{
VisualMiddle3D v = highlighted as VisualMiddle3D;
VisualMiddle3D v = (VisualMiddle3D)highlighted;
Sidedef sd = v.GetControlLinedef().Front;
if(sd == null)
{
@ -2497,7 +2481,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(obj is VisualFloor)
{
VisualFloor v = obj as VisualFloor;
VisualFloor v = (VisualFloor)obj;
v.Level.sector.Fields.BeforeFieldsChange();
v.Sector.Changed = true;
@ -2514,7 +2498,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
else if(obj is VisualCeiling)
{
VisualCeiling v = obj as VisualCeiling;
VisualCeiling v = (VisualCeiling)obj;
v.Level.sector.Fields.BeforeFieldsChange();
v.Sector.Changed = 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)
{
BaseVisualGeometrySidedef v = obj as BaseVisualGeometrySidedef;
BaseVisualGeometrySidedef v = (BaseVisualGeometrySidedef)obj;
v.Sidedef.Fields.BeforeFieldsChange();
v.Sector.Changed = true;
@ -2727,7 +2711,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
renderer.SetCrosshairBusy(true);
General.Interface.RedrawDisplay();
GetTargetEventReceiver(false).OnSelectTexture();
RebuildElementData(); //mxd. Extrafloors or Glow effects may've been changed
renderer.SetCrosshairBusy(false);
PostAction();
}
@ -2851,7 +2834,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
//align
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)
if(!side.Texture.IsImageLoaded) side.Texture.LoadImage();
@ -2867,7 +2850,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Update the parts for this sidedef!
if(VisualSectorExists(sd.Sector))
{
BaseVisualSector vs = (GetVisualSector(sd.Sector) as BaseVisualSector);
BaseVisualSector vs = (BaseVisualSector)GetVisualSector(sd.Sector);
VisualSidedefParts parts = vs.GetSidedefParts(sd);
parts.SetupAllParts();
}
@ -2884,9 +2867,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Get selection
List<IVisualEventReceiver> objs = GetSelectedObjects(false, true, false, false);
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)
@ -3016,7 +3000,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
added = new HashSet<int>();
foreach(IVisualEventReceiver receiver in obj)
{
VisualGeometry vg = receiver as VisualGeometry;
VisualGeometry vg = (VisualGeometry)receiver;
if(vg != null && !added.Contains(vg.Sector.GetHashCode()))
{
selection.Add(receiver);
@ -3035,7 +3019,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
added = new HashSet<int>();
foreach(IVisualEventReceiver receiver in obj)
{
VisualGeometry vg = receiver as VisualGeometry;
VisualGeometry vg = (VisualGeometry)receiver;
if(vg != null && !added.Contains(vg.Sidedef.Line.GetHashCode()))
{
selection.Add(receiver);
@ -3054,7 +3038,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
added = new HashSet<int>();
foreach(IVisualEventReceiver receiver in obj)
{
VisualThing vt = receiver as VisualThing;
VisualThing vt = (VisualThing)receiver;
if(vt != null && !added.Contains(vt.Thing.GetHashCode()))
{
selection.Add(receiver);
@ -3073,7 +3057,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
added = new HashSet<int>();
foreach(IVisualEventReceiver receiver in obj)
{
VisualVertex vv = receiver as VisualVertex;
VisualVertex vv = (VisualVertex)receiver;
if(vv != null && !added.Contains(vv.Vertex.GetHashCode()))
{
selection.Add(receiver);
@ -3157,7 +3141,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
copybuffer.Clear();
foreach(IVisualEventReceiver i in objs)
{
VisualThing vt = i as VisualThing;
VisualThing vt = (VisualThing)i;
if(vt != null) copybuffer.Add(new ThingCopyData(vt.Thing));
}
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);
foreach(IVisualEventReceiver i in objs)
{
BaseVisualThing thing = i as BaseVisualThing;
BaseVisualThing thing = (BaseVisualThing)i;
thing.Thing.Fields.BeforeFieldsChange();
thing.Thing.Dispose();
thing.Dispose();
@ -3267,17 +3251,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
if(obj is BaseVisualThing)
{
BaseVisualThing t = obj as BaseVisualThing;
BaseVisualThing t = (BaseVisualThing)obj;
t.SetAngle(General.ClampAngle(t.Thing.AngleDoom + increment));
}
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));
}
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));
}
}
@ -3309,9 +3293,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
foreach(IVisualEventReceiver obj in selection)
{
if(!(obj is BaseVisualThing)) continue;
BaseVisualThing t = obj as BaseVisualThing;
t.SetPitch(General.ClampAngle(t.Thing.Pitch + increment));
BaseVisualThing t = (BaseVisualThing)obj;
if(t != null) t.SetPitch(General.ClampAngle(t.Thing.Pitch + increment));
}
PostAction();
@ -3341,9 +3324,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
foreach(IVisualEventReceiver obj in selection)
{
if(!(obj is BaseVisualThing)) continue;
BaseVisualThing t = obj as BaseVisualThing;
t.SetRoll(General.ClampAngle(t.Thing.Roll + increment));
BaseVisualThing t = (BaseVisualThing)obj;
if(t != null) t.SetRoll(General.ClampAngle(t.Thing.Roll + increment));
}
PostAction();
@ -3418,7 +3400,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
//apply changes to Visual Things
for(int i = 0; i < visualThings.Count; i++)
{
BaseVisualThing t = visualThings[i] as BaseVisualThing;
BaseVisualThing t = (BaseVisualThing)visualThings[i];
t.Changed = true;
// Update what must be updated
@ -3667,7 +3649,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
//add to update list
if(update) toUpdate.Add(vg.Sector as BaseVisualSector);
if(update) toUpdate.Add((BaseVisualSector)vg.Sector);
}
//update changed geometry
@ -3846,13 +3828,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
List<BaseVisualGeometrySidedef> selectedVisualSides = new List<BaseVisualGeometrySidedef>();
if(checkSelectedSidedefParts && !singleselection)
{
foreach(IVisualEventReceiver i in selectedobjects)
foreach(IVisualEventReceiver i in selectedobjects)
{
if(i is BaseVisualGeometrySidedef)
{
BaseVisualGeometrySidedef sd = i as BaseVisualGeometrySidedef;
if(!selectedVisualSides.Contains(sd)) selectedVisualSides.Add(sd);
}
BaseVisualGeometrySidedef side = (BaseVisualGeometrySidedef)i;
if(side != null && !selectedVisualSides.Contains(side)) selectedVisualSides.Add(side);
}
}
@ -4221,11 +4200,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd
private List<Sidedef> GetControlSides(Sidedef side, bool udmf)
{
if(side.Other == null) return new List<Sidedef>() { side };
if(side.Other.Sector.Tag == 0) 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 };
SectorData data = GetSectorData(side.Other.Sector);
if(data.ExtraFloors.Count == 0) return new List<Sidedef>() { side };
SectorData data = GetSectorDataEx(side.Other.Sector);
if(data == null || data.ExtraFloors.Count == 0) return new List<Sidedef> { side };
List<Sidedef> sides = new List<Sidedef>();
foreach(Effect3DFloor ef in data.ExtraFloors)

View file

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

View file

@ -707,7 +707,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
foreach(Thing t in things)
{
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;

View file

@ -1,45 +1,35 @@
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Rendering;
using CodeImp.DoomBuilder.Rendering;
namespace CodeImp.DoomBuilder.BuilderModes
{
internal class EffectGlowingFlat : SectorEffect
internal class EffectGlowingFlat
{
private readonly Sector sector;
private readonly SectorData data;
// Level planes
private SectorLevel ceillevel;
private SectorLevel floorlevel;
// Constructor
public EffectGlowingFlat(SectorData data, Sector sourcesector) : base(data)
public EffectGlowingFlat(SectorData sourcedata)
{
sector = sourcesector;
// 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);
}
data = sourcedata;
}
public override void Update()
public void Update()
{
// Create ceiling glow effect?
if(General.Map.Data.GlowingFlats.ContainsKey(sector.LongCeilTexture))
if(General.Map.Data.GlowingFlats.ContainsKey(data.Sector.LongCeilTexture))
{
// Create ceiling level?
if(ceillevel == null)
{
ceillevel = new SectorLevel(data.Ceiling);
ceillevel.type = SectorLevelType.Glow;
ceillevel.disablelighting = true;
ceillevel = new SectorLevel(data.Ceiling) { type = SectorLevelType.Glow, disablelighting = true };
data.AddSectorLevel(ceillevel);
}
// 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.color = 0; // so we need to reset all shading and coloring
ceillevel.plane = data.Ceiling.plane;
@ -52,19 +42,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
// Create floor glow effect?
if(General.Map.Data.GlowingFlats.ContainsKey(sector.LongFloorTexture))
if(General.Map.Data.GlowingFlats.ContainsKey(data.Sector.LongFloorTexture))
{
// Create floor level?
if(floorlevel == null)
{
floorlevel = new SectorLevel(data.Floor);
floorlevel.type = SectorLevelType.Glow;
floorlevel.disablelighting = true;
floorlevel = new SectorLevel(data.Floor) { type = SectorLevelType.Glow, disablelighting = true };
data.AddSectorLevel(floorlevel);
}
// 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.Offset += data.FloorGlow.Height;

View file

@ -43,6 +43,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
founddist = d;
}
}
if(foundv == null) return; //mxd
// Align floor with back of line
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);
else
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
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);
else
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
@ -81,8 +79,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
data.Ceiling.plane = new Plane(v1, v2, v3, false);
else
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
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);
else
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
private readonly List<SectorEffect> alleffects;
private readonly List<Effect3DFloor> extrafloors;
private readonly EffectGlowingFlat glowingflateffect; //mxd
internal GlowingFlatData CeilingGlow; //mxd
internal GlowingFlatData FloorGlow; //mxd
@ -91,12 +92,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
this.floorbase = new SectorLevel(sector, SectorLevelType.Floor); //mxd
this.ceiling = new SectorLevel(sector, SectorLevelType.Ceiling);
this.ceilingbase = new SectorLevel(sector, SectorLevelType.Ceiling); //mxd
BasicSetup();
this.glowingflateffect = new EffectGlowingFlat(this); //mxd
// Add ceiling and floor
lightlevels.Add(floor);
lightlevels.Add(ceiling);
BasicSetup();
}
#endregion
@ -187,13 +189,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
EffectUDMFVertexOffset e = new EffectUDMFVertexOffset(this);
alleffects.Add(e);
}
//mxd.
public void AddEffectGlowingFlat(Sector sourcesector)
{
EffectGlowingFlat e = new EffectGlowingFlat(this, sourcesector);
alleffects.Add(e);
}
// This adds a sector for updating
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...
ceilingbase.brightnessbelow = sector.Brightness;
ceilingbase.color = PixelColor.FromInt(mode.CalculateBrightness(sector.Brightness)).WithAlpha(255).ToInt();
//mxd
glowingflateffect.Update();
}
//mxd

View file

@ -93,9 +93,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
base.Texture = General.Map.Data.UnknownTexture3D;
setuponloadedtexture = s.LongCeilTexture;
}
else
else if(!base.Texture.IsImageLoaded)
{
if(!base.Texture.IsImageLoaded) setuponloadedtexture = s.LongCeilTexture;
setuponloadedtexture = s.LongCeilTexture;
}
}
else
@ -113,20 +113,35 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Determine brightness
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;
if(extrafloor != null && !extrafloor.VavoomType && !level.disablelighting)
{
targetbrightness = 0;
SectorData sd = mode.GetSectorData(this.Sector.Sector);
for(int i = 0; i < sd.LightLevels.Count - 1; i++)
//mxd. Top extrafloor level should calculate fogdensity from the brightness of the level above it
if(!innerside)
{
if(sd.LightLevels[i] == level)
targetbrightness = 0;
SectorData sd = mode.GetSectorData(this.Sector.Sector);
for(int i = 0; i < sd.LightLevels.Count - 1; i++)
{
targetbrightness = sd.LightLevels[i + 1].brightnessbelow;
break;
if(sd.LightLevels[i] == level)
{
targetbrightness = sd.LightLevels[i + 1].brightnessbelow;
break;
}
}
}
//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;
}
}
}
}
@ -271,8 +286,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
UniFields.SetFloat(s.Fields, "yscaleceiling", scaleY, 1.0f);
}
//update geometry
OnTextureChanged();
// Update
if(mode.VisualSectorExists(level.sector))
{
BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(level.sector);
vs.UpdateSectorGeometry(false);
}
s.UpdateNeeded = true;
s.UpdateCache();
@ -308,8 +327,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
SetTexture(BuilderPlug.Me.CopiedFlat);
//mxd. 3D floors may need updating...
OnTextureChanged();
// Update
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
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
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();
}
@ -553,7 +564,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
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;
// When current ceiling is part of a 3d floor, it looks like a floor, so we need to select adjacent floors

View file

@ -93,10 +93,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
base.Texture = General.Map.Data.UnknownTexture3D;
setuponloadedtexture = s.LongFloorTexture;
}
else
else if(!base.Texture.IsImageLoaded)
{
if(!base.Texture.IsImageLoaded)
setuponloadedtexture = s.LongFloorTexture;
setuponloadedtexture = s.LongFloorTexture;
}
}
else
@ -259,8 +258,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
UniFields.SetFloat(s.Fields, "yscalefloor", scaleY, 1.0f);
}
//update geometry
OnTextureChanged();
// Update geometry
if(mode.VisualSectorExists(level.sector))
{
BaseVisualSector vs = (BaseVisualSector)mode.GetVisualSector(level.sector);
vs.UpdateSectorGeometry(false);
}
s.UpdateNeeded = true;
s.UpdateCache();
@ -296,8 +299,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
SetTexture(BuilderPlug.Me.CopiedFlat);
//mxd. 3D floors may need updating...
OnTextureChanged();
// Update
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
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
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();
}
@ -513,7 +508,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
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;
// 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.Collections.Generic;
using System.Drawing;
using System.Globalization;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Rendering;
@ -30,7 +31,7 @@ using CodeImp.DoomBuilder.Data;
namespace CodeImp.DoomBuilder.BuilderModes
{
internal sealed class VisualMiddle3D : BaseVisualGeometrySidedef
internal class VisualMiddle3D : BaseVisualGeometrySidedef
{
#region ================== Constants
@ -38,7 +39,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
#region ================== Variables
private Effect3DFloor extrafloor;
protected Effect3DFloor extrafloor;
#endregion
@ -99,36 +100,35 @@ namespace CodeImp.DoomBuilder.BuilderModes
SectorData sd = mode.GetSectorData(Sidedef.Sector);
//mxd. which texture we must use?
long textureLong = 0;
long texturelong = 0;
if((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.UseUpperTexture) != 0)
{
if(Sidedef.LongHighTexture != MapSet.EmptyLongName)
textureLong = Sidedef.LongHighTexture;
texturelong = Sidedef.LongHighTexture;
}
else if((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.UseLowerTexture) != 0)
{
if(Sidedef.LongLowTexture != MapSet.EmptyLongName)
textureLong = Sidedef.LongLowTexture;
texturelong = Sidedef.LongLowTexture;
}
else if(sourceside.LongMiddleTexture != MapSet.EmptyLongName)
{
textureLong = sourceside.LongMiddleTexture;
texturelong = sourceside.LongMiddleTexture;
}
// Texture given?
if(textureLong != 0)
if(texturelong != 0)
{
// Load texture
base.Texture = General.Map.Data.GetTextureImage(textureLong);
base.Texture = General.Map.Data.GetTextureImage(texturelong);
if(base.Texture == null || base.Texture is UnknownImage)
{
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
@ -379,14 +379,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
extrafloor.Linedef.Front.SetTextureMid(texturename);
General.Map.Data.UpdateUsedTextures();
this.Sector.Rebuild();
//mxd. Other sector also may require updating
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
//mxd. Update model sector
mode.GetVisualSector(extrafloor.Linedef.Front.Sector).UpdateSectorGeometry(false);
}
@ -407,8 +401,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
Sidedef.Fields.BeforeFieldsChange();
float oldx = Sidedef.Fields.GetValue("offsetx_mid", 0.0f);
float oldy = Sidedef.Fields.GetValue("offsety_mid", 0.0f);
Sidedef.Fields["offsetx_mid"] = new UniValue(UniversalType.Float, oldx + xy.X);
Sidedef.Fields["offsety_mid"] = new UniValue(UniversalType.Float, oldy + xy.Y);
float scalex = extrafloor.Linedef.Front.Fields.GetValue("scalex_mid", 1.0f); //mxd
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()
@ -430,7 +426,78 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(!General.Map.UDMF) return;
if(string.IsNullOrEmpty(extrafloor.Linedef.Front.MiddleTexture) || extrafloor.Linedef.Front.MiddleTexture == "-" || !Texture.IsImageLoaded) return;
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
mode.GetVisualSector(extrafloor.Linedef.Front.Sector).UpdateSectorGeometry(false);

View file

@ -1,12 +1,9 @@
#region ================== Namespaces
using System;
using System.Collections.Generic;
using System.Drawing;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Rendering;
using CodeImp.DoomBuilder.Types;
using CodeImp.DoomBuilder.VisualModes;
using CodeImp.DoomBuilder.Data;
@ -15,31 +12,16 @@ using CodeImp.DoomBuilder.Data;
namespace CodeImp.DoomBuilder.BuilderModes
{
//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
// Constructor
public VisualMiddleBack(BaseVisualMode mode, VisualSector vs, Sidedef s)
: base(mode, vs, s)
{
//mxd
geometrytype = VisualGeometryType.WALL_MIDDLE;
partname = "mid";
// We have no destructor
GC.SuppressFinalize(this);
}
public VisualMiddleBack(BaseVisualMode mode, VisualSector vs, Sidedef s) : base(mode, vs, s) { }
// This builds the geometry. Returns false when no geometry created.
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;
this.extrafloor = extrafloor;
@ -77,35 +59,35 @@ namespace CodeImp.DoomBuilder.BuilderModes
SectorData sd = mode.GetSectorData(Sidedef.Other.Sector);
//mxd. which texture we must use?
long longtexture = 0;
long texturelong = 0;
if((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.UseUpperTexture) != 0)
{
if(Sidedef.Other.LongHighTexture != MapSet.EmptyLongName)
longtexture = Sidedef.Other.LongHighTexture;
if(Sidedef.LongHighTexture != MapSet.EmptyLongName)
texturelong = Sidedef.LongHighTexture;
}
else if((sourceside.Line.Args[2] & (int)Effect3DFloor.Flags.UseLowerTexture) != 0)
{
if(Sidedef.Other.LongLowTexture != MapSet.EmptyLongName)
longtexture = Sidedef.Other.LongLowTexture;
if(Sidedef.LongLowTexture != MapSet.EmptyLongName)
texturelong = Sidedef.LongLowTexture;
}
else if((sourceside.LongMiddleTexture != MapSet.EmptyLongName))
else if(sourceside.LongMiddleTexture != MapSet.EmptyLongName)
{
longtexture = sourceside.LongMiddleTexture;
texturelong = sourceside.LongMiddleTexture;
}
// Texture given?
if(longtexture != 0)
if(texturelong != 0)
{
// Load texture
base.Texture = General.Map.Data.GetTextureImage(longtexture);
if(base.Texture == null || base.Texture is UnknownImage)
base.Texture = General.Map.Data.GetTextureImage(texturelong);
if(base.Texture == null || base.Texture is UnknownImage)
{
base.Texture = General.Map.Data.UnknownTexture3D;
setuponloadedtexture = longtexture;
setuponloadedtexture = texturelong;
}
else if(!base.Texture.IsImageLoaded)
{
setuponloadedtexture = longtexture;
setuponloadedtexture = texturelong;
}
}
else
@ -179,8 +161,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(((cl - fl) > 0.01f) || ((cr - fr) > 0.01f))
{
// Keep top and bottom planes for intersection testing
bottom = extrafloor.Ceiling.plane;
top = extrafloor.Floor.plane;
bottom = extrafloor.Ceiling.plane;
// Create initial polygon, which is just a quad between floor and ceiling
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, fr));
// Determine initial color
// Determine initial color. Inside parts are shaded using control sector's brightness
int lightlevel;
PixelColor levelcolor; //mxd
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
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;
for(int pi = 0; pi < num; pi++)
{
@ -281,113 +266,5 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
#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;
FitTexture(options);
Setup();
// Update linked effects
SectorData sd = mode.GetSectorDataEx(Sector.Sector);
if(sd != null) sd.Reset(true);
}
#endregion