Merge remote-tracking branch 'udb/master'
Before Width: | Height: | Size: 471 B After Width: | Height: | Size: 491 B |
Before Width: | Height: | Size: 729 B After Width: | Height: | Size: 749 B |
Before Width: | Height: | Size: 563 B After Width: | Height: | Size: 583 B |
Before Width: | Height: | Size: 631 B After Width: | Height: | Size: 651 B |
Before Width: | Height: | Size: 327 B After Width: | Height: | Size: 347 B |
Before Width: | Height: | Size: 334 B After Width: | Height: | Size: 354 B |
Before Width: | Height: | Size: 649 B After Width: | Height: | Size: 669 B |
Before Width: | Height: | Size: 682 B After Width: | Height: | Size: 702 B |
Before Width: | Height: | Size: 183 B After Width: | Height: | Size: 203 B |
Before Width: | Height: | Size: 511 B After Width: | Height: | Size: 531 B |
Before Width: | Height: | Size: 567 B After Width: | Height: | Size: 587 B |
Before Width: | Height: | Size: 509 B After Width: | Height: | Size: 529 B |
Before Width: | Height: | Size: 510 B After Width: | Height: | Size: 530 B |
Before Width: | Height: | Size: 722 B After Width: | Height: | Size: 742 B |
Before Width: | Height: | Size: 781 B After Width: | Height: | Size: 801 B |
Before Width: | Height: | Size: 738 B After Width: | Height: | Size: 758 B |
Before Width: | Height: | Size: 751 B After Width: | Height: | Size: 771 B |
Before Width: | Height: | Size: 360 B After Width: | Height: | Size: 380 B |
Before Width: | Height: | Size: 337 B After Width: | Height: | Size: 357 B |
Before Width: | Height: | Size: 344 B After Width: | Height: | Size: 364 B |
Before Width: | Height: | Size: 732 B After Width: | Height: | Size: 752 B |
Before Width: | Height: | Size: 621 B After Width: | Height: | Size: 641 B |
Before Width: | Height: | Size: 873 B After Width: | Height: | Size: 893 B |
Before Width: | Height: | Size: 331 B After Width: | Height: | Size: 351 B |
Before Width: | Height: | Size: 587 B After Width: | Height: | Size: 607 B |
Before Width: | Height: | Size: 432 B After Width: | Height: | Size: 452 B |
Before Width: | Height: | Size: 236 B After Width: | Height: | Size: 256 B |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 308 B After Width: | Height: | Size: 328 B |
|
@ -160,7 +160,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
if (filedata != null)
|
||||
{
|
||||
// Get a reader for the data
|
||||
bitmap = ImageDataFormat.TryLoadImage(filedata, probableformat, General.Map.Data.Palette);
|
||||
bitmap = ImageDataFormat.TryLoadImage(filedata, probableformat, General.Map.Data.Palette, out offsetx, out offsety);
|
||||
|
||||
// Not loaded?
|
||||
if (bitmap == null)
|
||||
|
|
|
@ -112,6 +112,8 @@ namespace CodeImp.DoomBuilder.Data
|
|||
// Store source properteis
|
||||
sourcesize = new Size(overridden.Width, overridden.Height);
|
||||
sourcescale = overridden.Scale;
|
||||
offsetx = overridden.OffsetX;
|
||||
offsety = overridden.OffsetY;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,8 @@ namespace CodeImp.DoomBuilder.Data
|
|||
protected long longname;
|
||||
protected int width;
|
||||
protected int height;
|
||||
protected int offsetx;
|
||||
protected int offsety;
|
||||
protected Vector2D scale;
|
||||
protected bool worldpanning;
|
||||
private bool usecolorcorrection;
|
||||
|
@ -141,6 +143,8 @@ namespace CodeImp.DoomBuilder.Data
|
|||
public int MipMapLevels { get { return mipmaplevels; } set { mipmaplevels = value; } }
|
||||
public virtual int Width { get { return width; } }
|
||||
public virtual int Height { get { return height; } }
|
||||
public int OffsetX { get { return offsetx; } }
|
||||
public int OffsetY { get { return offsety; } }
|
||||
//mxd. Scaled texture size is integer in ZDoom.
|
||||
public virtual float ScaledWidth { get { return (float)Math.Round(width * scale.x); } }
|
||||
public virtual float ScaledHeight { get { return (float)Math.Round(height * scale.y); } }
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace CodeImp.DoomBuilder.Data
|
|||
SetName(resourcename);
|
||||
|
||||
// Temporarily load resource from memory
|
||||
Stream bitmapdata = assembly.GetManifestResourceStream(resourcename);
|
||||
Stream bitmapdata = assembly.GetManifestResourceStream(resourcename);
|
||||
Bitmap bmp = (Bitmap)Image.FromStream(bitmapdata);
|
||||
|
||||
// Get width and height from image
|
||||
|
|
|
@ -35,20 +35,6 @@ namespace CodeImp.DoomBuilder.Data
|
|||
|
||||
public sealed class SpriteImage : ImageData, ISpriteImage
|
||||
{
|
||||
#region ================== Variables
|
||||
|
||||
private int offsetx;
|
||||
private int offsety;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Properties
|
||||
|
||||
public int OffsetX { get { return offsetx; } }
|
||||
public int OffsetY { get { return offsety; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Constructor / Disposer
|
||||
|
||||
// Constructor
|
||||
|
|
|
@ -52,12 +52,14 @@ namespace CodeImp.DoomBuilder.Data
|
|||
#region ================== Constructor / Disposer
|
||||
|
||||
// Constructor
|
||||
public TEXTURESImage(string name, string virtualpath, int width, int height, float scalex, float scaley,
|
||||
public TEXTURESImage(string name, string virtualpath, int width, int height, int offsetx, int offsety, float scalex, float scaley,
|
||||
bool worldpanning, TextureNamespace texturenamespace, bool optional, bool nulltexture)
|
||||
{
|
||||
// Initialize
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.offsetx = offsetx;
|
||||
this.offsety = offsety;
|
||||
this.scale.x = scalex;
|
||||
this.scale.y = scaley;
|
||||
this.worldpanning = worldpanning;
|
||||
|
|
3
Source/Core/Rendering/IRenderer2D.cs
Executable file → Normal file
|
@ -52,7 +52,7 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
// Rendering management methods
|
||||
bool StartPlotter(bool clear);
|
||||
bool StartThings(bool clear);
|
||||
bool StartOverlay(bool clear);
|
||||
bool StartOverlay(bool clear, int layernum = 0);
|
||||
void Finish();
|
||||
void SetPresentation(Presentation present);
|
||||
void Present();
|
||||
|
@ -69,6 +69,7 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
void PlotVerticesSet(ICollection<Vertex> vertices, bool checkMode = true);
|
||||
void RenderThing(Thing t, PixelColor c, float alpha);
|
||||
void RenderThingSet(ICollection<Thing> things, float alpha);
|
||||
void RenderThingSet(ICollection<Thing> things, PixelColor c, float alpha);
|
||||
void RenderSRB2Extras();
|
||||
void RenderRectangle(RectangleF rect, float bordersize, PixelColor c, bool transformrect);
|
||||
void RenderRectangleFilled(RectangleF rect, PixelColor c, bool transformrect);
|
||||
|
|
63
Source/Core/Rendering/Renderer2D.cs
Executable file → Normal file
|
@ -65,7 +65,7 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
private Plotter gridplotter;
|
||||
private Plotter plotter;
|
||||
private Texture thingstex;
|
||||
private Texture overlaytex;
|
||||
private List<Texture> overlaytex;
|
||||
private Texture surfacetex;
|
||||
|
||||
// Rendertarget sizes
|
||||
|
@ -181,11 +181,22 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
public void SetPresentation(Presentation present)
|
||||
{
|
||||
this.present = new Presentation(present);
|
||||
|
||||
// We might have to create additional overlay textures
|
||||
int numoverlaylayers = present.layers.Count(l => l.layer == RendererLayer.Overlay);
|
||||
if(numoverlaylayers > overlaytex.Count)
|
||||
{
|
||||
Texture t = new Texture(windowsize.Width, windowsize.Height, TextureFormat.Rgba8);
|
||||
graphics.ClearTexture(General.Colors.Background.WithAlpha(0).ToColorValue(), t);
|
||||
overlaytex.Add(t);
|
||||
}
|
||||
}
|
||||
|
||||
// This draws the image on screen
|
||||
public void Present()
|
||||
{
|
||||
int currentoverlaylayer = 0;
|
||||
|
||||
General.Plugins.OnPresentDisplayBegin();
|
||||
|
||||
// Start drawing
|
||||
|
@ -281,10 +292,11 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
// OVERLAY
|
||||
case RendererLayer.Overlay:
|
||||
graphics.SetShader(aapass);
|
||||
graphics.SetTexture(overlaytex);
|
||||
graphics.SetTexture(overlaytex[currentoverlaylayer]);
|
||||
graphics.SetSamplerState(TextureAddress.Wrap);
|
||||
SetDisplay2DSettings(1f / overlaytex.Width, 1f / overlaytex.Height, FSAA_FACTOR, layer.alpha, false, true);
|
||||
SetDisplay2DSettings(1f / overlaytex[currentoverlaylayer].Width, 1f / overlaytex[currentoverlaylayer].Height, FSAA_FACTOR, layer.alpha, false, true);
|
||||
graphics.Draw(PrimitiveType.TriangleStrip, 0, 2);
|
||||
currentoverlaylayer++;
|
||||
break;
|
||||
|
||||
// SURFACE
|
||||
|
@ -292,7 +304,7 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
graphics.SetShader(aapass);
|
||||
graphics.SetTexture(surfacetex);
|
||||
graphics.SetSamplerState(TextureAddress.Wrap);
|
||||
SetDisplay2DSettings(1f / overlaytex.Width, 1f / overlaytex.Height, FSAA_FACTOR, layer.alpha, false, true);
|
||||
SetDisplay2DSettings(1f / surfacetex.Width, 1f / surfacetex.Height, FSAA_FACTOR, layer.alpha, false, true);
|
||||
graphics.Draw(PrimitiveType.TriangleStrip, 0, 2);
|
||||
break;
|
||||
}
|
||||
|
@ -338,12 +350,12 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
public void DestroyRendertargets()
|
||||
{
|
||||
// Trash rendertargets
|
||||
if(plotter != null) plotter.Dispose();
|
||||
if(thingstex != null) thingstex.Dispose();
|
||||
if(overlaytex != null) overlaytex.Dispose();
|
||||
if(surfacetex != null) surfacetex.Dispose();
|
||||
if(gridplotter != null) gridplotter.Dispose();
|
||||
if(screenverts != null) screenverts.Dispose();
|
||||
if (plotter != null) plotter.Dispose();
|
||||
if (thingstex != null) thingstex.Dispose();
|
||||
if (overlaytex != null) for(int i=0; i < overlaytex.Count; i++) { overlaytex[i].Dispose(); overlaytex[i] = null; } ;
|
||||
if (surfacetex != null) surfacetex.Dispose();
|
||||
if (gridplotter != null) gridplotter.Dispose();
|
||||
if (screenverts != null) screenverts.Dispose();
|
||||
thingstex = null;
|
||||
gridplotter = null;
|
||||
screenverts = null;
|
||||
|
@ -371,13 +383,23 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
plotter = new Plotter(windowsize.Width, windowsize.Height);
|
||||
gridplotter = new Plotter(windowsize.Width, windowsize.Height);
|
||||
thingstex = new Texture(windowsize.Width, windowsize.Height, TextureFormat.Rgba8);
|
||||
overlaytex = new Texture(windowsize.Width, windowsize.Height, TextureFormat.Rgba8);
|
||||
surfacetex = new Texture(windowsize.Width, windowsize.Height, TextureFormat.Rgba8);
|
||||
|
||||
|
||||
if (present == null)
|
||||
{
|
||||
overlaytex = new List<Texture>() { new Texture(windowsize.Width, windowsize.Height, TextureFormat.Rgba8) };
|
||||
}
|
||||
else
|
||||
{
|
||||
overlaytex = new List<Texture>();
|
||||
for (int i = 0; i < present.layers.Count(l => l.layer == RendererLayer.Overlay); i++)
|
||||
overlaytex.Add(new Texture(windowsize.Width, windowsize.Height, TextureFormat.Rgba8));
|
||||
}
|
||||
|
||||
// Clear rendertargets
|
||||
graphics.ClearTexture(General.Colors.Background.WithAlpha(0).ToColorValue(), thingstex);
|
||||
graphics.ClearTexture(General.Colors.Background.WithAlpha(0).ToColorValue(), overlaytex);
|
||||
|
||||
foreach(Texture t in overlaytex) graphics.ClearTexture(General.Colors.Background.WithAlpha(0).ToColorValue(), t);
|
||||
|
||||
// Create vertex buffers
|
||||
screenverts = new VertexBuffer();
|
||||
thingsvertices = new VertexBuffer();
|
||||
|
@ -733,7 +755,7 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
}
|
||||
|
||||
// This begins a drawing session
|
||||
public bool StartOverlay(bool clear)
|
||||
public bool StartOverlay(bool clear, int layernum = 0)
|
||||
{
|
||||
if(renderlayer != RenderLayers.None)
|
||||
{
|
||||
|
@ -747,10 +769,10 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
renderlayer = RenderLayers.Overlay;
|
||||
|
||||
// Rendertargets available?
|
||||
if(overlaytex != null)
|
||||
if(overlaytex != null && layernum >= 0 && layernum < overlaytex.Count)
|
||||
{
|
||||
// Set the rendertarget to the things texture
|
||||
graphics.StartRendering(clear, General.Colors.Background.WithAlpha(0).ToColorValue(), overlaytex, false);
|
||||
graphics.StartRendering(clear, General.Colors.Background.WithAlpha(0).ToColorValue(), overlaytex[layernum], false);
|
||||
|
||||
// Ready for rendering
|
||||
UpdateTransformations();
|
||||
|
@ -1589,6 +1611,13 @@ namespace CodeImp.DoomBuilder.Rendering
|
|||
RenderArrows(LinksCollector.GetSRB2Lines(), true, false);
|
||||
}
|
||||
|
||||
// This adds a thing in the things buffer for rendering
|
||||
public void RenderThingSet(ICollection<Thing> things, PixelColor c, float alpha)
|
||||
{
|
||||
RenderThingsBatch(things, alpha, false, c);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Surface
|
||||
|
|
|
@ -164,7 +164,6 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
triangles = vertices.Length / 3;
|
||||
|
||||
CalculateNormals(); //mxd
|
||||
PerformAutoSelection(); //mxd
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -285,7 +284,7 @@ namespace CodeImp.DoomBuilder.VisualModes
|
|||
}
|
||||
|
||||
//mxd
|
||||
protected abstract void PerformAutoSelection();
|
||||
public abstract void PerformAutoSelection();
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -249,7 +249,7 @@ namespace CodeImp.DoomBuilder.ZDoom
|
|||
float scaley = ((yscale == 0.0f) ? General.Map.Config.DefaultTextureScale : 1f / yscale);
|
||||
|
||||
// Make texture
|
||||
TEXTURESImage tex = new TEXTURESImage(name, virtualpath, width, height, scalex, scaley, worldpanning, texturenamespace, optional, nulltexture);
|
||||
TEXTURESImage tex = new TEXTURESImage(name, virtualpath, width, height, xoffset, yoffset, scalex, scaley, worldpanning, texturenamespace, optional, nulltexture);
|
||||
|
||||
// Add patches
|
||||
foreach(PatchStructure p in patches) tex.AddPatch(new TexturePatch(p));//mxd
|
||||
|
|
|
@ -87,11 +87,15 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
{
|
||||
public readonly SurfaceTextureInfo Floor;
|
||||
public readonly SurfaceTextureInfo Ceiling;
|
||||
public readonly Vertex FirstVertex;
|
||||
public readonly Vector2D PreviousFirstVertexPosition;
|
||||
|
||||
public SectorTextureInfo(Sector s)
|
||||
{
|
||||
// Get transform properties
|
||||
Floor.Offset = new Vector2D(UniFields.GetFloat(s.Fields, "xpanningfloor", 0.0), UniFields.GetFloat(s.Fields, "ypanningfloor", 0.0));
|
||||
FirstVertex = s.Sidedefs.First<Sidedef>().Line.Start;
|
||||
PreviousFirstVertexPosition = FirstVertex.Position;
|
||||
// Get transform properties
|
||||
Floor.Offset = new Vector2D(UniFields.GetFloat(s.Fields, "xpanningfloor", 0.0), UniFields.GetFloat(s.Fields, "ypanningfloor", 0.0));
|
||||
Ceiling.Offset = new Vector2D(UniFields.GetFloat(s.Fields, "xpanningceiling", 0.0), UniFields.GetFloat(s.Fields, "ypanningceiling", 0.0));
|
||||
Floor.Scale = new Vector2D(UniFields.GetFloat(s.Fields, "xscalefloor", 1.0), -UniFields.GetFloat(s.Fields, "yscalefloor", 1.0));
|
||||
Ceiling.Scale = new Vector2D(UniFields.GetFloat(s.Fields, "xscaleceiling", 1.0), -UniFields.GetFloat(s.Fields, "yscaleceiling", 1.0));
|
||||
|
@ -105,7 +109,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
// Surface name
|
||||
Floor.Part = "floor";
|
||||
Ceiling.Part = "ceiling";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Size GetTextureSize(long hash)
|
||||
{
|
||||
|
@ -879,15 +884,20 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
{
|
||||
foreach(KeyValuePair<Sector, SectorTextureInfo> group in selectedsectors)
|
||||
{
|
||||
group.Key.Fields.BeforeFieldsChange();
|
||||
Sector eachSector = group.Key;
|
||||
SectorTextureInfo eachSectorTexInfo = group.Value;
|
||||
Vector2D newFirstVertexPosition = new Vector2D( Math.Round(eachSectorTexInfo.FirstVertex.Position.x, General.Map.FormatInterface.VertexDecimals),
|
||||
Math.Round(eachSectorTexInfo.FirstVertex.Position.y, General.Map.FormatInterface.VertexDecimals) );
|
||||
|
||||
// Apply transforms
|
||||
UpdateTextureTransform(group.Key.Fields, group.Value.Ceiling /*, transformceiloffsets, rotateceiloffsets, scaleceiloffsets */);
|
||||
UpdateTextureTransform(group.Key.Fields, group.Value.Floor /*, transformflooroffsets, rotateflooroffsets, scaleflooroffsets */);
|
||||
eachSector.Fields.BeforeFieldsChange();
|
||||
|
||||
// Update cache
|
||||
group.Key.UpdateNeeded = true;
|
||||
group.Key.UpdateCache();
|
||||
// Apply transforms
|
||||
UpdateTextureTransform(eachSector.Fields, eachSectorTexInfo.Ceiling, newFirstVertexPosition, eachSectorTexInfo.PreviousFirstVertexPosition);
|
||||
UpdateTextureTransform(eachSector.Fields, eachSectorTexInfo.Floor, newFirstVertexPosition, eachSectorTexInfo.PreviousFirstVertexPosition);
|
||||
|
||||
// Update cache
|
||||
eachSector.UpdateNeeded = true;
|
||||
eachSector.UpdateCache();
|
||||
}
|
||||
|
||||
// Map was changed
|
||||
|
@ -895,18 +905,40 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
}
|
||||
|
||||
//mxd. This updates texture transforms in given UniFields
|
||||
private void UpdateTextureTransform(UniFields fields, SurfaceTextureInfo si /*, bool transformoffsets, bool rotateoffsets, bool scaleoffsets */)
|
||||
private void UpdateTextureTransform(UniFields fields, SurfaceTextureInfo si, Vector2D newReferencePosition, Vector2D previousReferencePosition)
|
||||
{
|
||||
if ((si.Part == "floor" && pinfloortextures) || (si.Part == "ceiling" && pinceilingtextures))
|
||||
{
|
||||
double texrotation = Angle2D.PI2 - rotation;
|
||||
if (si.Scale.x != 0 && si.Scale.y != 0)
|
||||
{
|
||||
double selectionRotationRad = Angle2D.PI2 - rotation;
|
||||
double newSurfaceRotationRad = selectionRotationRad + si.Rotation;
|
||||
|
||||
double trotation = texrotation + si.Rotation;
|
||||
Vector2D o = ((referencepoint - selectionbasecenter).GetRotated(-trotation) + selectionbasecenter + this.offset - this.baseoffset).GetRotated(trotation);
|
||||
Vector2D textureSize = new Vector2D ((double)si.TextureSize.Width / si.Scale.x,
|
||||
(double)si.TextureSize.Height / -si.Scale.y);
|
||||
|
||||
fields["xpanning" + si.Part] = new UniValue(UniversalType.Float, Math.Round(-o.x + si.Offset.x, General.Map.FormatInterface.VertexDecimals));
|
||||
fields["ypanning" + si.Part] = new UniValue(UniversalType.Float, Math.Round(o.y + si.Offset.y, General.Map.FormatInterface.VertexDecimals));
|
||||
fields["rotation" + si.Part] = new UniValue(UniversalType.Float, General.ClampAngle(Math.Round(Angle2D.RadToDeg(trotation), General.Map.FormatInterface.VertexDecimals)));
|
||||
double previousSurfaceRotationRad = Angle2D.PI2 - si.Rotation;
|
||||
|
||||
//Set the new surface texture rotation
|
||||
double newSurfaceRotationDegrees = General.ClampAngle(Math.Round(Angle2D.RadToDeg(newSurfaceRotationRad), General.Map.FormatInterface.VertexDecimals));
|
||||
fields["rotation" + si.Part] = new UniValue(UniversalType.Float, newSurfaceRotationDegrees);
|
||||
|
||||
//Find the offset required to place the texture origin point at the reference vector
|
||||
Vector2D globalOffsetForNewReferencePoint = ConvertToOffsetCoordinates(newReferencePosition);
|
||||
Vector2D surfaceOffsetForNewReferencePoint = GetClampedOffsetVector(globalOffsetForNewReferencePoint.GetRotated(-newSurfaceRotationRad), textureSize);
|
||||
|
||||
//find an "origin point offset" using the previous texture offset, relative to our reference vertex
|
||||
Vector2D rotatedPreviousReferencePosition = GetClampedOffsetVector(previousReferencePosition.GetRotated(-previousSurfaceRotationRad), textureSize);
|
||||
Vector2D previousSurfaceOffset = ConvertToOffsetCoordinates(GetClampedOffsetVector(si.Offset, textureSize));
|
||||
Vector2D localSurfaceAdjustment = rotatedPreviousReferencePosition - previousSurfaceOffset;
|
||||
|
||||
//Adjust our offset by applying using the "origin point offset" to the offset for our reference vertex
|
||||
Vector2D adjustedSurfaceOffset = GetClampedOffsetVector(surfaceOffsetForNewReferencePoint - ConvertToOffsetCoordinates(localSurfaceAdjustment), textureSize);
|
||||
|
||||
//Set the new texture offset
|
||||
fields["xpanning" + si.Part] = new UniValue(UniversalType.Float, adjustedSurfaceOffset.x);
|
||||
fields["ypanning" + si.Part] = new UniValue(UniversalType.Float, adjustedSurfaceOffset.y);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -919,6 +951,25 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
}
|
||||
}
|
||||
|
||||
private Vector2D ConvertToOffsetCoordinates(Vector2D v)
|
||||
{
|
||||
return new Vector2D(-v.x, v.y);
|
||||
}
|
||||
|
||||
private Vector2D GetClampedOffsetVector(Vector2D v, Vector2D textureSize)
|
||||
{
|
||||
Vector2D roundedV = new Vector2D(
|
||||
Math.Round(v.x, General.Map.FormatInterface.VertexDecimals),
|
||||
Math.Round(v.y, General.Map.FormatInterface.VertexDecimals));
|
||||
Vector2D roundedTextureSize = new Vector2D(
|
||||
Math.Round(textureSize.x, General.Map.FormatInterface.VertexDecimals),
|
||||
Math.Round(textureSize.y, General.Map.FormatInterface.VertexDecimals));
|
||||
|
||||
return new Vector2D(roundedV.x % roundedTextureSize.x,
|
||||
roundedV.y % roundedTextureSize.y);
|
||||
|
||||
}
|
||||
|
||||
//mxd. This restores texture transforms for all sectors
|
||||
private void RestoreTextureTransform()
|
||||
{
|
||||
|
@ -1300,8 +1351,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
if (General.Map.UDMF)
|
||||
{
|
||||
foreach (Sector s in General.Map.Map.GetSectorsFromLinedefs(selectedlines))
|
||||
if(!s.Fields.ContainsKey(MapSet.VIRTUAL_SECTOR_FIELD)) // Ignore sectors that have the VIRTUAL_SECTOR_FIELD UDMF field created when cloning the MapSet when copying
|
||||
selectedsectors.Add(s, new SectorTextureInfo(s));
|
||||
{
|
||||
if (!s.Fields.ContainsKey(MapSet.VIRTUAL_SECTOR_FIELD)) // Ignore sectors that have the VIRTUAL_SECTOR_FIELD UDMF field created when cloning the MapSet when copying
|
||||
{
|
||||
selectedsectors.Add(s, new SectorTextureInfo(s));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Array to keep original coordinates
|
||||
|
|
|
@ -101,7 +101,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
public virtual void SelectNeighbours(bool select, bool withSameTexture, bool withSameHeight) { } //mxd
|
||||
|
||||
//mxd
|
||||
override protected void PerformAutoSelection()
|
||||
override public void PerformAutoSelection()
|
||||
{
|
||||
if(!performautoselection) return;
|
||||
if(Triangles > 0)
|
||||
|
|
|
@ -94,7 +94,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
#region ================== Methods
|
||||
|
||||
//mxd
|
||||
override protected void PerformAutoSelection()
|
||||
public override void PerformAutoSelection()
|
||||
{
|
||||
if(!performautoselection) return;
|
||||
if(Triangles > 0)
|
||||
|
|
|
@ -1515,8 +1515,53 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
// (Re)create special effects
|
||||
RebuildElementData();
|
||||
|
||||
//mxd. Update event lines
|
||||
renderer.SetEventLines(LinksCollector.GetHelperShapes(General.Map.ThingsFilter.VisibleThings, blockmap));
|
||||
// Objects are only selected when they are created, so for objects that are selected we have to make sure
|
||||
// that they are created immediately. Otherwise the selection order will not be correct, or the objects
|
||||
// will not be selected at all if they are out of the user's camera range when entering visual mode
|
||||
// See https://github.com/jewalky/UltimateDoomBuilder/issues/938
|
||||
if (useSelectionFromClassicMode)
|
||||
{
|
||||
foreach (Sector s in General.Map.Map.GetSelectedSectors(true))
|
||||
{
|
||||
BaseVisualSector bvs = CreateBaseVisualSector(s);
|
||||
bvs.Ceiling.PerformAutoSelection();
|
||||
bvs.Floor.PerformAutoSelection();
|
||||
}
|
||||
|
||||
// Things are automatically selected on creation
|
||||
foreach (Thing t in General.Map.Map.GetSelectedThings(true))
|
||||
CreateVisualThing(t);
|
||||
|
||||
// For linedefs it's a bit more complicated...
|
||||
foreach (Linedef ld in General.Map.Map.GetSelectedLinedefs(true))
|
||||
{
|
||||
foreach (Sidedef sd in new Sidedef[] { ld.Front, ld.Back })
|
||||
{
|
||||
if (sd != null)
|
||||
{
|
||||
if (!allsectors.ContainsKey(sd.Sector))
|
||||
CreateBaseVisualSector(sd.Sector).Rebuild(); // We have to rebuild the sector so that potential 3D floors get created
|
||||
|
||||
VisualSidedefParts vsp = ((BaseVisualSector)allsectors[sd.Sector]).Sides[sd];
|
||||
vsp.upper?.PerformAutoSelection();
|
||||
vsp.middlesingle?.PerformAutoSelection();
|
||||
vsp.middledouble?.PerformAutoSelection();
|
||||
vsp.lower?.PerformAutoSelection();
|
||||
|
||||
if (vsp.middle3d != null)
|
||||
foreach (VisualMiddle3D vm in vsp.middle3d)
|
||||
vm.PerformAutoSelection();
|
||||
|
||||
if (vsp.middleback != null)
|
||||
foreach (VisualMiddleBack vm in vsp.middleback)
|
||||
vm.PerformAutoSelection();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//mxd. Update event lines
|
||||
renderer.SetEventLines(LinksCollector.GetHelperShapes(General.Map.ThingsFilter.VisibleThings, blockmap));
|
||||
|
||||
// [ZZ] this enables calling of this object from the outside world. Only after properly initialized pls.
|
||||
base.OnEngage();
|
||||
|
|
18
Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs
Executable file → Normal file
|
@ -218,10 +218,16 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
{
|
||||
double thingz = Thing.IsFlipped ? sd.Ceiling.plane.GetZ(Thing.Position) - Thing.Position.z - Thing.Height : Thing.Position.z + sd.Floor.plane.GetZ(Thing.Position);
|
||||
Vector3D thingpos = new Vector3D(Thing.Position.x, Thing.Position.y, thingz);
|
||||
SectorLevel level = sd.GetLevelAboveOrAt(thingpos);
|
||||
|
||||
// If is thing's height is flush to a 3D floor top it's not rendered at the brightness of the 3D floor, so take the level above that.
|
||||
// It's actually a bit more intricate, since GZDoom can render multiple vertical brightness levels for each thing, which UDB can't,
|
||||
// so this is more of a workaround than a real solution
|
||||
// See https://github.com/jewalky/UltimateDoomBuilder/issues/940
|
||||
//SectorLevel level = sd.GetLevelAboveOrAt(thingpos);
|
||||
SectorLevel level = sd.GetLevelAbove(thingpos);
|
||||
|
||||
//mxd. Let's use point on floor plane instead of Thing.Sector.FloorHeight;
|
||||
if(nointeraction && level == null && sd.LightLevels.Count > 0) level = sd.LightLevels[sd.LightLevels.Count - 1];
|
||||
if (nointeraction && level == null && sd.LightLevels.Count > 0) level = sd.LightLevels[sd.LightLevels.Count - 1];
|
||||
|
||||
//mxd. Use the light level of the highest surface when a thing is above highest sector level.
|
||||
if(level != null)
|
||||
|
@ -324,12 +330,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
// Determine sprite size and offset
|
||||
float radius = sprite.ScaledWidth * 0.5f;
|
||||
float height = sprite.ScaledHeight;
|
||||
ISpriteImage spriteimg = sprite as ISpriteImage;
|
||||
if(spriteimg != null)
|
||||
{
|
||||
offsets.x = radius - spriteimg.OffsetX;
|
||||
offsets.y = spriteimg.OffsetY - height;
|
||||
}
|
||||
offsets.x = radius - (sprite.OffsetX == int.MinValue ? 0 : sprite.OffsetX);
|
||||
offsets.y = (sprite.OffsetY == int.MinValue ? 0 : sprite.OffsetY) - height;
|
||||
|
||||
// Scale by thing type/actor scale
|
||||
// We do this after the offset x/y determination above, because that is entirely in sprite pixels space
|
||||
|
|
|
@ -386,11 +386,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
|
||||
string skewtype = Sidedef.Fields.GetValue("skew_bottom_type", "none");
|
||||
|
||||
if ((skewtype == "front" || skewtype == "back") && Texture != null)
|
||||
if ((skewtype == "front_floor" || skewtype == "front_ceiling" || skewtype == "back_floor" || skewtype == "back_ceiling") && Texture != null)
|
||||
{
|
||||
double leftz, rightz;
|
||||
|
||||
if (skewtype == "front")
|
||||
if (skewtype == "front_floor")
|
||||
{
|
||||
if (Sidedef.IsFront)
|
||||
{
|
||||
|
@ -405,7 +405,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
rightz = plane.GetZ(Sidedef.Line.Start.Position);
|
||||
}
|
||||
}
|
||||
else // "back"
|
||||
else if(skewtype == "back_floor")
|
||||
{
|
||||
if (Sidedef.IsFront)
|
||||
{
|
||||
|
@ -419,7 +419,36 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
leftz = plane.GetZ(Sidedef.Line.End.Position);
|
||||
rightz = plane.GetZ(Sidedef.Line.Start.Position);
|
||||
}
|
||||
|
||||
}
|
||||
else if(skewtype == "front_ceiling")
|
||||
{
|
||||
if (Sidedef.IsFront)
|
||||
{
|
||||
Plane plane = Sector.GetSectorData().Ceiling.plane;
|
||||
leftz = plane.GetZ(Sidedef.Line.Start.Position);
|
||||
rightz = plane.GetZ(Sidedef.Line.End.Position);
|
||||
}
|
||||
else
|
||||
{
|
||||
Plane plane = mode.GetSectorData(Sidedef.Other.Sector).Ceiling.plane;
|
||||
leftz = plane.GetZ(Sidedef.Line.End.Position);
|
||||
rightz = plane.GetZ(Sidedef.Line.Start.Position);
|
||||
}
|
||||
}
|
||||
else // Back ceiling
|
||||
{
|
||||
if (Sidedef.IsFront)
|
||||
{
|
||||
Plane plane = mode.GetSectorData(Sidedef.Other.Sector).Ceiling.plane;
|
||||
leftz = plane.GetZ(Sidedef.Line.Start.Position);
|
||||
rightz = plane.GetZ(Sidedef.Line.End.Position);
|
||||
}
|
||||
else
|
||||
{
|
||||
Plane plane = Sector.GetSectorData().Ceiling.plane;
|
||||
leftz = plane.GetZ(Sidedef.Line.End.Position);
|
||||
rightz = plane.GetZ(Sidedef.Line.Start.Position);
|
||||
}
|
||||
}
|
||||
|
||||
skew = new Vector2f(
|
||||
|
|
|
@ -378,11 +378,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
|
||||
string skewtype = Sidedef.Fields.GetValue("skew_top_type", "none");
|
||||
|
||||
if ((skewtype == "front" || skewtype == "back") && Texture != null)
|
||||
if ((skewtype == "front_floor" || skewtype == "front_ceiling" || skewtype == "back_floor" || skewtype == "back_ceiling") && Texture != null)
|
||||
{
|
||||
double leftz, rightz;
|
||||
|
||||
if (skewtype == "front")
|
||||
if (skewtype == "front_ceiling")
|
||||
{
|
||||
if (Sidedef.IsFront)
|
||||
{
|
||||
|
@ -397,7 +397,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
rightz = plane.GetZ(Sidedef.Line.Start.Position);
|
||||
}
|
||||
}
|
||||
else // "back"
|
||||
else if (skewtype == "back_ceiling")
|
||||
{
|
||||
if (Sidedef.IsFront)
|
||||
{
|
||||
|
@ -411,7 +411,36 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
leftz = plane.GetZ(Sidedef.Line.End.Position);
|
||||
rightz = plane.GetZ(Sidedef.Line.Start.Position);
|
||||
}
|
||||
|
||||
}
|
||||
else if(skewtype == "front_floor")
|
||||
{
|
||||
if(Sidedef.IsFront)
|
||||
{
|
||||
Plane plane = Sector.GetSectorData().Floor.plane;
|
||||
leftz = plane.GetZ(Sidedef.Line.Start.Position);
|
||||
rightz = plane.GetZ(Sidedef.Line.End.Position);
|
||||
}
|
||||
else
|
||||
{
|
||||
Plane plane = mode.GetSectorData(Sidedef.Other.Sector).Floor.plane;
|
||||
leftz = plane.GetZ(Sidedef.Line.End.Position);
|
||||
rightz = plane.GetZ(Sidedef.Line.Start.Position);
|
||||
}
|
||||
}
|
||||
else // Back floor
|
||||
{
|
||||
if (Sidedef.IsFront)
|
||||
{
|
||||
Plane plane = mode.GetSectorData(Sidedef.Other.Sector).Floor.plane;
|
||||
leftz = plane.GetZ(Sidedef.Line.Start.Position);
|
||||
rightz = plane.GetZ(Sidedef.Line.End.Position);
|
||||
}
|
||||
else
|
||||
{
|
||||
Plane plane = Sector.GetSectorData().Floor.plane;
|
||||
leftz = plane.GetZ(Sidedef.Line.End.Position);
|
||||
rightz = plane.GetZ(Sidedef.Line.Start.Position);
|
||||
}
|
||||
}
|
||||
|
||||
skew = new Vector2f(
|
||||
|
|
|
@ -41,6 +41,12 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
|
|||
// Make sure the class is public, because only public classes can be seen
|
||||
// by the core.
|
||||
//
|
||||
|
||||
internal class ToastMessages
|
||||
{
|
||||
public static readonly string SOUNDPROPAGATIONMODE = "soundpropagationmode";
|
||||
}
|
||||
|
||||
public class BuilderPlug : Plug
|
||||
{
|
||||
#region ================== Constants
|
||||
|
@ -170,6 +176,9 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
|
|||
|
||||
// Keep a static reference
|
||||
me = this;
|
||||
|
||||
// Register toasts
|
||||
General.ToastManager.RegisterToast(ToastMessages.SOUNDPROPAGATIONMODE, "Sound propagation mode", "Toasts related to sound propagation mode");
|
||||
}
|
||||
|
||||
public override void OnMapOpenBegin()
|
||||
|
|
221
Source/Plugins/SoundPropagationMode/LeakFinder.cs
Normal file
|
@ -0,0 +1,221 @@
|
|||
#region ================== Copyright (c) 2023 Boris Iwanski
|
||||
|
||||
/*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
*
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
*
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
*
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
||||
*
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program.If not, see<http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using CodeImp.DoomBuilder.Geometry;
|
||||
using CodeImp.DoomBuilder.Map;
|
||||
|
||||
namespace CodeImp.DoomBuilder.SoundPropagationMode
|
||||
{
|
||||
internal class LeakFinder
|
||||
{
|
||||
public SoundNode Start { get; }
|
||||
public SoundNode End { get; }
|
||||
public List<SoundNode> Nodes { get; }
|
||||
public HashSet<Sector> Sectors { get; }
|
||||
public bool Finished { get; internal set; }
|
||||
|
||||
private ConcurrentDictionary<Linedef, SoundNode> linedefs2nodes;
|
||||
private int numblockingnodes;
|
||||
|
||||
public LeakFinder(Sector source, Vector2D sourceposition, Sector destination, Vector2D destinationposition, HashSet<Sector> sectors)
|
||||
{
|
||||
if (!sectors.Contains(source) || !sectors.Contains(destination))
|
||||
throw new ArgumentException("Sound propagation domain does not contain both the start and end sectors");
|
||||
|
||||
End = new SoundNode(destinationposition);
|
||||
Start = new SoundNode(sourceposition, End) { G = 0 };
|
||||
Sectors = sectors;
|
||||
|
||||
Finished = false;
|
||||
|
||||
Nodes = new List<SoundNode>() { Start, End };
|
||||
|
||||
linedefs2nodes = new ConcurrentDictionary<Linedef, SoundNode>();
|
||||
|
||||
GenerateNodes(sectors);
|
||||
|
||||
PopulateStartEndNeighbors(source, Start);
|
||||
PopulateStartEndNeighbors(destination, End);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the linedef is valid for passing sound.
|
||||
/// </summary>
|
||||
/// <param name="linedef">The linedef to check</param>
|
||||
/// <returns>true if sound can travel through the linedef, false if not</returns>
|
||||
private bool CheckLinedefValidity(Linedef linedef)
|
||||
{
|
||||
if (linedef.Back == null)
|
||||
return false;
|
||||
|
||||
if (linedef.Front.Sector == linedef.Back.Sector)
|
||||
return false;
|
||||
|
||||
if (SoundPropagationDomain.IsSoundBlockedByHeight(linedef))
|
||||
return false;
|
||||
|
||||
return Sectors.Contains(linedef.Front.Sector) && Sectors.Contains(linedef.Back.Sector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates all nodes for the A* search algorithm.
|
||||
/// </summary>
|
||||
/// <param name="sectors">sectors to generate the nodes from</param>
|
||||
private void GenerateNodes(HashSet<Sector> sectors)
|
||||
{
|
||||
// Create sound nodes for all valid linedefs in all given sectors
|
||||
foreach(Sector s in sectors)
|
||||
{
|
||||
IEnumerable<Sidedef> sidedefs = s.Sidedefs.Where(sd => CheckLinedefValidity(sd.Line));
|
||||
|
||||
foreach(Sidedef sd in sidedefs)
|
||||
{
|
||||
if(!linedefs2nodes.ContainsKey(sd.Line))
|
||||
{
|
||||
linedefs2nodes[sd.Line] = new SoundNode(sd.Line, End);
|
||||
Nodes.Add(linedefs2nodes[sd.Line]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We need the number of blocking nodes for safety checking
|
||||
numblockingnodes = linedefs2nodes.Values.Count(n => n.IsBlocking);
|
||||
|
||||
// Set the neighbors for each node. The amount of interconnections can be very high in complex maps
|
||||
// (for example there are nearly 3.9 million in Sunder map 20), so do it in parallel for speed
|
||||
Parallel.ForEach(linedefs2nodes.Keys, ld =>
|
||||
{
|
||||
foreach (Sidedef sd in ld.Front.Sector.Sidedefs)
|
||||
{
|
||||
if (sd.Line != ld && CheckLinedefValidity(sd.Line))
|
||||
linedefs2nodes[ld].Neighbors.Add(linedefs2nodes[sd.Line]);
|
||||
}
|
||||
|
||||
foreach (Sidedef sd in ld.Back.Sector.Sidedefs)
|
||||
{
|
||||
if (sd.Line != ld && CheckLinedefValidity(sd.Line))
|
||||
linedefs2nodes[ld].Neighbors.Add(linedefs2nodes[sd.Line]);
|
||||
}
|
||||
});
|
||||
|
||||
#if DEBUG
|
||||
int bla = linedefs2nodes.Values.Sum(n => n.Neighbors.Count);
|
||||
Console.WriteLine($"There are {linedefs2nodes.Keys.Count} nodes with {bla} interconnections.");
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates a sound node's neightbors to the linedefs of a sector. This is required for the start and end sound nodes.
|
||||
/// </summary>
|
||||
/// <param name="sector">The sector which linedef's sound nodes are used</param>
|
||||
/// <param name="node">The sound node to add the neighbors to</param>
|
||||
private void PopulateStartEndNeighbors(Sector sector, SoundNode node)
|
||||
{
|
||||
foreach(Sidedef sd in sector.Sidedefs)
|
||||
{
|
||||
if(CheckLinedefValidity(sd.Line) && linedefs2nodes.ContainsKey(sd.Line))
|
||||
{
|
||||
node.Neighbors.Add(linedefs2nodes[sd.Line]);
|
||||
linedefs2nodes[sd.Line].Neighbors.Add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds a sound leak between the start and end sound nodes.
|
||||
/// </summary>
|
||||
/// <returns>true if a leak was found, false if no leak was found</returns>
|
||||
public bool FindLeak()
|
||||
{
|
||||
Finished = false;
|
||||
|
||||
// Basic A* search. The twist is that sound blocking lines: we can only pass through one of them,
|
||||
// and A* doesn't backtrack, so it can fail to find a path even if there is a possible one. If that
|
||||
// happens we set the sound blocking node we traveled through to be ignored, and start again. We repeat
|
||||
// that until a path was found, or all blocking nodes are set to be ignored (which shouldn't happen)
|
||||
while (true)
|
||||
{
|
||||
List<SoundNode> openset = new List<SoundNode>() { Start };
|
||||
|
||||
while (openset.Count > 0)
|
||||
{
|
||||
// Find the node with the lowest F score. Doing it that way seems to be fastest
|
||||
SoundNode current = openset[0];
|
||||
for (int i = 1; i < openset.Count; i++)
|
||||
{
|
||||
if (openset[i].F < current.F)
|
||||
current = openset[i];
|
||||
}
|
||||
|
||||
// We're done if the node with the lowest F score is the end node
|
||||
if (current == End)
|
||||
{
|
||||
Finished = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Remove the current node from the open set
|
||||
openset.Remove(current);
|
||||
|
||||
// Compute new values for the current node's neighbors
|
||||
current.ProcessNeighbors(openset, Start);
|
||||
}
|
||||
|
||||
// If we got here we didn't find a path. So we have to start over
|
||||
|
||||
int currentnumblockingnodes = 0;
|
||||
|
||||
// Reset all nodes
|
||||
foreach(SoundNode sn in Nodes)
|
||||
{
|
||||
// Set the sound nodes that block sound and were visited (the G value was set to something) to be skipped.
|
||||
if(sn.IsBlocking && sn.G != double.MaxValue)
|
||||
{
|
||||
sn.IsSkip = true;
|
||||
currentnumblockingnodes++;
|
||||
}
|
||||
|
||||
// We need to reset the sound node's G and F values
|
||||
sn.Reset();
|
||||
}
|
||||
|
||||
// All blocking sound nodes are being skipped, so no path is possible
|
||||
if (currentnumblockingnodes == numblockingnodes)
|
||||
{
|
||||
Finished = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't forget the reset the start node to its special values
|
||||
Start.G = 0.0;
|
||||
Start.F = Start.H;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -70,6 +70,16 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap SoundPropagationIcon {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("SoundPropagationIcon", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
|
|
|
@ -112,15 +112,18 @@
|
|||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="ColorManagement" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\ColorManagement.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="SoundPropagationIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\SoundPropagationIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="Status0" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\Status0.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
|
|
|
@ -54,3 +54,25 @@ soundpropagationcolorconfiguration
|
|||
allowmouse = true;
|
||||
allowscroll = true;
|
||||
}
|
||||
|
||||
setleakfinderstart
|
||||
{
|
||||
title = "Set leak finder start sector";
|
||||
category = "soundpropagationmode";
|
||||
description = "Sets the starting sector for the sound leak finder";
|
||||
allowkeys = true;
|
||||
allowmouse = true;
|
||||
allowscroll = true;
|
||||
default = 65619; // Shift+S
|
||||
}
|
||||
|
||||
setleakfinderend
|
||||
{
|
||||
title = "Set leak finder end sector";
|
||||
category = "soundpropagationmode";
|
||||
description = "Sets the ending sector for the sound leak finder";
|
||||
allowkeys = true;
|
||||
allowmouse = true;
|
||||
allowscroll = true;
|
||||
default = 65605; // Shift+E
|
||||
}
|
8
Source/Plugins/SoundPropagationMode/Resources/Hints.cfg
Normal file
|
@ -0,0 +1,8 @@
|
|||
class SoundPropagationMode
|
||||
group general
|
||||
"This mode shows between which sectors sound can travel. Highlight a sector to see where the sound can travel freely (default color: green), and which sectors are behind a single sound blocking line (default color: yellow). Sound can not travel to (default) gray colored sectors. If no sector is highlighted each sound propagation zone is shown in a different color"
|
||||
"Hold <k>builder_pan_view</k> and move the mouse to pan the view"
|
||||
"Press <k>builder_classicselect</k> to toggle the sound blocking flag on the highlighted line"
|
||||
"Press <k>soundpropagationmode_setleakfinderstart</k> to set the start sector, and <k>soundpropagationmode_setleakfinderend</k> to set the end sector to find a sound leak between them. Depending on the map size finding the leak can take some time."
|
||||
"Press <k>builder_clearselection</k> to clear the start and end sectors for finding a sound leak"
|
||||
"Press <k>soundpropagationmode_soundpropagationcolorconfiguration</k> or use the button in the tool bar to configure the colors"
|
148
Source/Plugins/SoundPropagationMode/SoundNode.cs
Normal file
|
@ -0,0 +1,148 @@
|
|||
#region ================== Copyright (c) 2023 Boris Iwanski
|
||||
|
||||
/*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
*
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
*
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
*
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
||||
*
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program.If not, see<http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using CodeImp.DoomBuilder.Geometry;
|
||||
using CodeImp.DoomBuilder.Map;
|
||||
using CodeImp.DoomBuilder.Rendering;
|
||||
|
||||
namespace CodeImp.DoomBuilder.SoundPropagationMode
|
||||
{
|
||||
internal class SoundNode
|
||||
{
|
||||
public Vector2D Position { get; set; }
|
||||
public List<SoundNode> Neighbors { get; set; }
|
||||
public SoundNode From { get; set; }
|
||||
public double G { get; set; }
|
||||
public double H { get; }
|
||||
public double F { get; set; } // It's G + H, but computing it on the fly is too expensive
|
||||
public bool IsBlocking { get; }
|
||||
public bool IsSkip { get; set; }
|
||||
|
||||
public SoundNode(Vector2D position)
|
||||
{
|
||||
Position = position;
|
||||
G = double.MaxValue;
|
||||
H = double.MaxValue;
|
||||
IsBlocking = false;
|
||||
IsSkip = false;
|
||||
Neighbors = new List<SoundNode>();
|
||||
}
|
||||
|
||||
public SoundNode(Vector2D position, SoundNode destination): this(position)
|
||||
{
|
||||
H = Vector2D.Distance(Position, destination.Position);
|
||||
}
|
||||
|
||||
public SoundNode(Linedef linedef, SoundNode destination) : this(linedef.Line.GetCoordinatesAt(0.5), destination)
|
||||
{
|
||||
IsBlocking = linedef.IsFlagSet(SoundPropagationMode.BlockSoundFlag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recomputes the values for the sound node's neighbors
|
||||
/// </summary>
|
||||
/// <param name="openset">The open set, the add the neighbor to if necessary</param>
|
||||
/// <param name="start">The start sound node</param>
|
||||
public void ProcessNeighbors(List<SoundNode> openset, SoundNode start)
|
||||
{
|
||||
bool blockinginpath = HasBlockingInPath(start);
|
||||
|
||||
foreach (SoundNode neighbor in Neighbors)
|
||||
{
|
||||
// Skip neighbors that are blocking if there's already a blocking sound node in the path
|
||||
// Also skip neighbors that are set to be skipped
|
||||
if ((neighbor.IsBlocking && blockinginpath) || neighbor.IsSkip)
|
||||
continue;
|
||||
|
||||
double newg = G + Vector2D.Distance(Position, neighbor.Position);
|
||||
|
||||
// Compute new values if the path is better
|
||||
if (newg < neighbor.G)
|
||||
{
|
||||
neighbor.From = this;
|
||||
neighbor.G = newg;
|
||||
neighbor.F = neighbor.G + neighbor.H;
|
||||
|
||||
if (!openset.Contains(neighbor))
|
||||
openset.Add(neighbor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the path from this sound node to the start sound node has a blocking sound node
|
||||
/// </summary>
|
||||
/// <param name="start">The start sound node</param>
|
||||
/// <returns>true if there is a blocking sound node in the path, false if there isn't</returns>
|
||||
private bool HasBlockingInPath(SoundNode start)
|
||||
{
|
||||
SoundNode current = this;
|
||||
while(current != start)
|
||||
{
|
||||
if (current.IsBlocking)
|
||||
return true;
|
||||
current = current.From;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the sound node's G and F values, and the sound node that leads here
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
From = null;
|
||||
G = double.MaxValue;
|
||||
F = double.MaxValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the path from this node to the beginning. Traces the path from this sound node back to the start sound node
|
||||
/// </summary>
|
||||
/// <param name="renderer">The Renderer2D to render with</param>
|
||||
internal void RenderPath(IRenderer2D renderer)
|
||||
{
|
||||
SoundNode current = this;
|
||||
|
||||
// If the current node is null we have reached the beginning
|
||||
while(current != null)
|
||||
{
|
||||
// Do not render the start and end sound nodes
|
||||
if (current != this && current.From != null)
|
||||
{
|
||||
RectangleF rectangle = new RectangleF((float)(current.Position.x - 4 / renderer.Scale), (float)(current.Position.y - 4 / renderer.Scale), 8 / renderer.Scale, 8 / renderer.Scale);
|
||||
renderer.RenderRectangleFilled(rectangle, PixelColor.FromColor(Color.Red), true);
|
||||
}
|
||||
|
||||
if(current.From != null)
|
||||
renderer.RenderLine(current.Position, current.From.Position, 1.0f, PixelColor.FromColor(Color.Red), true);
|
||||
|
||||
// One step back
|
||||
current = current.From;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -118,6 +118,7 @@
|
|||
<Compile Include="Interface\SoundEnvironmentPanel.Designer.cs">
|
||||
<DependentUpon>SoundEnvironmentPanel.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="LeakFinder.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
|
@ -125,6 +126,7 @@
|
|||
</Compile>
|
||||
<Compile Include="SoundEnvironment.cs" />
|
||||
<Compile Include="SoundEnvironmentMode.cs" />
|
||||
<Compile Include="SoundNode.cs" />
|
||||
<Compile Include="SoundPropagationDomain.cs" />
|
||||
<Compile Include="Windows\ColorConfiguration.cs">
|
||||
<SubType>Form</SubType>
|
||||
|
@ -193,6 +195,9 @@
|
|||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\Hints.cfg" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
|
|
@ -108,7 +108,7 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
|
|||
}
|
||||
}
|
||||
|
||||
private static bool IsSoundBlockedByHeight(Linedef ld)
|
||||
public static bool IsSoundBlockedByHeight(Linedef ld)
|
||||
{
|
||||
if(ld.Back == null || ld.Front == null) return false;
|
||||
|
||||
|
|
|
@ -19,12 +19,17 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using CodeImp.DoomBuilder.Map;
|
||||
using CodeImp.DoomBuilder.Rendering;
|
||||
using CodeImp.DoomBuilder.Editing;
|
||||
using CodeImp.DoomBuilder.Actions;
|
||||
using CodeImp.DoomBuilder.Geometry;
|
||||
using CodeImp.DoomBuilder.Windows;
|
||||
using System.Diagnostics;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -53,9 +58,19 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
|
|||
private List<Thing> huntingThings;
|
||||
private List<SoundPropagationDomain> propagationdomains;
|
||||
private Dictionary<Sector, SoundPropagationDomain> sector2domain;
|
||||
private LeakFinder leakfinder;
|
||||
private PixelColor doublesidedcolor;
|
||||
|
||||
// The blockmap makes is used to make finding lines faster
|
||||
BlockMap<BlockEntry> blockmap;
|
||||
private BlockMap<BlockEntry> blockmap;
|
||||
|
||||
private Sector leakstartsector;
|
||||
private Sector leakendsector;
|
||||
private Vector2D leakstartposition;
|
||||
private Vector2D leakendposition;
|
||||
private TextLabel leakstartlabel;
|
||||
private TextLabel leakendlabel;
|
||||
private BackgroundWorker worker;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -161,7 +176,6 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
|
|||
{
|
||||
if(!General.Map.ThingsFilter.VisibleThings.Contains(thing)) continue;
|
||||
if(thing.IsFlagSet(General.Map.UDMF ? "ambush" : "8")) continue;
|
||||
if(thing.Sector == null) thing.DetermineSector();
|
||||
if(thing.Sector != null && noisysectors.ContainsKey(thing.Sector.Index)) huntingThings.Add(thing);
|
||||
}
|
||||
}
|
||||
|
@ -175,6 +189,7 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
|
|||
RectangleF area = MapSet.CreateArea(General.Map.Map.Vertices);
|
||||
blockmap = new BlockMap<BlockEntry>(area);
|
||||
blockmap.AddLinedefsSet(General.Map.Map.Linedefs);
|
||||
blockmap.AddSectorsSet(General.Map.Map.Sectors);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -206,6 +221,8 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
|
|||
sector2domain = new Dictionary<Sector, SoundPropagationDomain>();
|
||||
BuilderPlug.Me.BlockingLinedefs = new List<Linedef>();
|
||||
|
||||
doublesidedcolor = General.Colors.Linedefs.WithAlpha(General.Settings.DoubleSidedAlphaByte);
|
||||
|
||||
UpdateData();
|
||||
|
||||
General.Interface.AddButton(BuilderPlug.Me.MenusForm.ColorConfiguration);
|
||||
|
@ -213,19 +230,42 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
|
|||
CustomPresentation presentation = new CustomPresentation();
|
||||
presentation.AddLayer(new PresentLayer(RendererLayer.Background, BlendingMode.Mask, General.Settings.BackgroundAlpha));
|
||||
presentation.AddLayer(new PresentLayer(RendererLayer.Grid, BlendingMode.Mask));
|
||||
presentation.AddLayer(new PresentLayer(RendererLayer.Overlay, BlendingMode.Alpha, 1.0f, true));
|
||||
presentation.AddLayer(new PresentLayer(RendererLayer.Overlay, BlendingMode.Alpha, 1.0f, true)); // First overlay (0)
|
||||
presentation.AddLayer(new PresentLayer(RendererLayer.Things, BlendingMode.Alpha, 1.0f));
|
||||
presentation.AddLayer(new PresentLayer(RendererLayer.Geometry, BlendingMode.Alpha, 1.0f, true));
|
||||
presentation.AddLayer(new PresentLayer(RendererLayer.Overlay, BlendingMode.Alpha, 1.0f, true)); // Second overlay (1)
|
||||
renderer.SetPresentation(presentation);
|
||||
|
||||
leakstartlabel = new TextLabel
|
||||
{
|
||||
TransformCoords = true,
|
||||
AlignX = TextAlignmentX.Center,
|
||||
AlignY = TextAlignmentY.Middle,
|
||||
Color = General.Colors.Selection,
|
||||
BackColor = General.Colors.Background,
|
||||
Text = "S"
|
||||
};
|
||||
|
||||
leakendlabel = new TextLabel
|
||||
{
|
||||
TransformCoords = true,
|
||||
AlignX = TextAlignmentX.Center,
|
||||
AlignY = TextAlignmentY.Middle,
|
||||
Color = General.Colors.Selection,
|
||||
BackColor = General.Colors.Background,
|
||||
Text = "E"
|
||||
};
|
||||
|
||||
// Create the blockmap
|
||||
CreateBlockmap();
|
||||
|
||||
// To show things that will wake up we need to know the sector they are in
|
||||
Parallel.ForEach(General.Map.Map.Things, t => t.DetermineSector(blockmap));
|
||||
|
||||
// Convert geometry selection to sectors only
|
||||
General.Map.Map.ConvertSelection(SelectionType.Sectors);
|
||||
|
||||
UpdateSoundPropagation();
|
||||
General.Interface.RedrawDisplay();
|
||||
}
|
||||
|
||||
// Mode disengages
|
||||
|
@ -236,14 +276,22 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
|
|||
|
||||
// Hide highlight info
|
||||
General.Interface.HideInfo();
|
||||
|
||||
if (worker != null)
|
||||
{
|
||||
worker.CancelAsync();
|
||||
worker.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// This redraws the display
|
||||
public override void OnRedrawDisplay()
|
||||
{
|
||||
List<SoundPropagationDomain> renderedspds = new List<SoundPropagationDomain>();
|
||||
if(BuilderPlug.Me.DataIsDirty) UpdateData();
|
||||
if (BuilderPlug.Me.DataIsDirty) UpdateData();
|
||||
|
||||
// We don't care for the actualy surfaces, but without this the render targets will not be recreated
|
||||
// when the window is resized
|
||||
renderer.RedrawSurface();
|
||||
|
||||
// Render lines and vertices
|
||||
|
@ -253,50 +301,60 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
|
|||
// Plot lines by hand, so that no coloring (line specials, 3D floors etc.) distracts from
|
||||
// the sound propagation. Also don't draw the line's normal. They are not needed here anyway
|
||||
// and can make it harder to see the sound environment propagation
|
||||
foreach(Linedef ld in General.Map.Map.Linedefs)
|
||||
if (General.Settings.ParallelizedLinedefPlotting)
|
||||
{
|
||||
PixelColor c = (ld.IsFlagSet(General.Map.Config.ImpassableFlag) ?
|
||||
General.Colors.Linedefs : General.Colors.Linedefs.WithAlpha(General.Settings.DoubleSidedAlphaByte));
|
||||
renderer.PlotLine(ld.Start.Position, ld.End.Position, c, BuilderPlug.LINE_LENGTH_SCALER);
|
||||
Parallel.ForEach(General.Map.Map.Linedefs, ld =>
|
||||
{
|
||||
PixelColor c = ld.IsFlagSet(General.Map.Config.ImpassableFlag) ? General.Colors.Linedefs : doublesidedcolor;
|
||||
renderer.PlotLine(ld.Start.Position, ld.End.Position, c, BuilderPlug.LINE_LENGTH_SCALER);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (Linedef ld in General.Map.Map.Linedefs)
|
||||
{
|
||||
PixelColor c = ld.IsFlagSet(General.Map.Config.ImpassableFlag) ? General.Colors.Linedefs : doublesidedcolor;
|
||||
renderer.PlotLine(ld.Start.Position, ld.End.Position, c, BuilderPlug.LINE_LENGTH_SCALER);
|
||||
}
|
||||
}
|
||||
|
||||
// Since there will usually be way less blocking linedefs than total linedefs, it's presumably
|
||||
// faster to draw them on their own instead of checking if each linedef is in BlockingLinedefs
|
||||
foreach(Linedef ld in BuilderPlug.Me.BlockingLinedefs)
|
||||
foreach (Linedef ld in BuilderPlug.Me.BlockingLinedefs)
|
||||
renderer.PlotLine(ld.Start.Position, ld.End.Position, BuilderPlug.Me.BlockSoundColor, BuilderPlug.LINE_LENGTH_SCALER);
|
||||
|
||||
//mxd. Render highlighted line
|
||||
if(highlightedline != null)
|
||||
if (highlightedline != null)
|
||||
renderer.PlotLine(highlightedline.Start.Position, highlightedline.End.Position, General.Colors.Highlight, BuilderPlug.LINE_LENGTH_SCALER);
|
||||
|
||||
renderer.Finish();
|
||||
}
|
||||
|
||||
// Render things
|
||||
if(renderer.StartThings(true))
|
||||
if (renderer.StartThings(true))
|
||||
{
|
||||
renderer.RenderThingSet(General.Map.ThingsFilter.HiddenThings, General.Settings.HiddenThingsAlpha);
|
||||
renderer.RenderThingSet(General.Map.ThingsFilter.VisibleThings, General.Settings.InactiveThingsAlpha);
|
||||
foreach(Thing thing in huntingThings)
|
||||
renderer.RenderThing(thing, General.Colors.Selection, General.Settings.ActiveThingsAlpha);
|
||||
renderer.RenderThingSet(huntingThings, General.Colors.Selection, General.Settings.ActiveThingsAlpha);
|
||||
|
||||
renderer.Finish();
|
||||
}
|
||||
|
||||
if(renderer.StartOverlay(true))
|
||||
// The sound propagation domain overlay
|
||||
if (renderer.StartOverlay(true))
|
||||
{
|
||||
// Render highlighted domain and domains adjacent to it
|
||||
if(highlighted != null && !highlighted.IsDisposed)
|
||||
if (highlighted != null && !highlighted.IsDisposed)
|
||||
{
|
||||
renderer.RenderGeometry(overlayGeometry, null, true); //mxd
|
||||
|
||||
|
||||
SoundPropagationDomain spd = sector2domain[highlighted];
|
||||
renderer.RenderGeometry(spd.Level1Geometry, null, true);
|
||||
|
||||
foreach(Sector s in spd.AdjacentSectors)
|
||||
foreach (Sector s in spd.AdjacentSectors)
|
||||
{
|
||||
SoundPropagationDomain aspd = sector2domain[s];
|
||||
if(!renderedspds.Contains(aspd))
|
||||
if (!renderedspds.Contains(aspd))
|
||||
{
|
||||
renderer.RenderGeometry(aspd.Level2Geometry, null, true);
|
||||
renderedspds.Add(aspd);
|
||||
|
@ -308,13 +366,28 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
|
|||
else
|
||||
{
|
||||
//mxd. Render all domains using domain colors
|
||||
foreach(SoundPropagationDomain spd in propagationdomains)
|
||||
foreach (SoundPropagationDomain spd in propagationdomains)
|
||||
renderer.RenderHighlight(spd.Level1Geometry, spd.Color);
|
||||
}
|
||||
|
||||
renderer.Finish();
|
||||
}
|
||||
|
||||
|
||||
// The sound leak overlay. This is done so that the path and labels are drawn at the very top
|
||||
if (renderer.StartOverlay(true, 1))
|
||||
{
|
||||
if (leakfinder != null && leakfinder.Finished)
|
||||
leakfinder.End.RenderPath(renderer);
|
||||
|
||||
if (leakstartsector != null)
|
||||
renderer.RenderText(leakstartlabel);
|
||||
|
||||
if (leakendsector != null)
|
||||
renderer.RenderText(leakendlabel);
|
||||
|
||||
renderer.Finish();
|
||||
}
|
||||
|
||||
renderer.Present();
|
||||
}
|
||||
|
||||
|
@ -331,9 +404,26 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
|
|||
|
||||
// Update
|
||||
ResetSoundPropagation();
|
||||
|
||||
FindSoundLeak();
|
||||
|
||||
General.Interface.RedrawDisplay();
|
||||
}
|
||||
|
||||
public override bool OnUndoBegin()
|
||||
{
|
||||
base.OnUndoBegin();
|
||||
|
||||
if (worker != null)
|
||||
{
|
||||
worker.CancelAsync();
|
||||
worker.Dispose();
|
||||
worker = null;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//mxd
|
||||
public override void OnUndoEnd()
|
||||
{
|
||||
|
@ -342,11 +432,28 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
|
|||
// Recreate the blockmap
|
||||
CreateBlockmap();
|
||||
|
||||
// To show things that will wake up we need to know the sector they are in
|
||||
Parallel.ForEach(General.Map.Map.Things, t => t.DetermineSector(blockmap));
|
||||
|
||||
// Update
|
||||
ResetSoundPropagation();
|
||||
General.Interface.RedrawDisplay();
|
||||
}
|
||||
|
||||
public override bool OnRedoBegin()
|
||||
{
|
||||
base.OnRedoBegin();
|
||||
|
||||
if (worker != null)
|
||||
{
|
||||
worker.CancelAsync();
|
||||
worker.Dispose();
|
||||
worker = null;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//mxd
|
||||
public override void OnRedoEnd()
|
||||
{
|
||||
|
@ -355,6 +462,9 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
|
|||
// Recreate the blockmap
|
||||
CreateBlockmap();
|
||||
|
||||
// To show things that will wake up we need to know the sector they are in
|
||||
Parallel.ForEach(General.Map.Map.Things, t => t.DetermineSector(blockmap));
|
||||
|
||||
// Update
|
||||
ResetSoundPropagation();
|
||||
General.Interface.RedrawDisplay();
|
||||
|
@ -441,7 +551,7 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
|
|||
General.Interface.ShowSectorInfo(highlighted);
|
||||
else
|
||||
General.Interface.HideInfo();
|
||||
|
||||
|
||||
// Redraw display
|
||||
General.Interface.RedrawDisplay();
|
||||
}
|
||||
|
@ -457,6 +567,79 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
|
|||
Highlight(null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts finding a sound leak. Finding the actual leak is done by a background worker that's started from this method
|
||||
/// </summary>
|
||||
private void FindSoundLeak()
|
||||
{
|
||||
leakfinder = null;
|
||||
|
||||
// Do not show an error if either start or end is not set, since that'll happen when you start out
|
||||
if (leakstartsector == null || leakendsector == null)
|
||||
return;
|
||||
|
||||
if (leakendsector == leakstartsector)
|
||||
{
|
||||
General.ToastManager.ShowToast(ToastMessages.SOUNDPROPAGATIONMODE, ToastType.WARNING, "Sound propagation", "Stard and end position for sound leak are in the same sector");
|
||||
return;
|
||||
}
|
||||
|
||||
HashSet<Sector> sectors = new HashSet<Sector>(sector2domain[leakstartsector].Sectors);
|
||||
|
||||
// Mash all sectors from the leak start sector's domain and the adjacent domains into one hash set
|
||||
foreach (Sector s in sector2domain[leakstartsector].AdjacentSectors)
|
||||
sectors.UnionWith(sector2domain[s].Sectors);
|
||||
|
||||
// If the leak end sector isn't in the list of sectors there's no way sound can travel between the start and end
|
||||
if (!sectors.Contains(leakendsector))
|
||||
{
|
||||
General.ToastManager.ShowToast(ToastMessages.SOUNDPROPAGATIONMODE, ToastType.WARNING, "Sound propagation", "Sound can not travel between the selected start and end positions");
|
||||
return;
|
||||
}
|
||||
|
||||
if (worker != null)
|
||||
{
|
||||
worker.CancelAsync();
|
||||
worker.Dispose();
|
||||
}
|
||||
|
||||
General.Interface.DisplayStatus(StatusType.Busy, "Searching for sound leak...");
|
||||
|
||||
worker = new BackgroundWorker();
|
||||
worker.WorkerSupportsCancellation = true;
|
||||
worker.DoWork += FindSoundLeakStart;
|
||||
worker.RunWorkerCompleted += FindSoundLeakFinished;
|
||||
worker.RunWorkerAsync(sectors);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method for the background worker that finds a sound leak.
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender</param>
|
||||
/// <param name="e">The event arguments</param>
|
||||
private void FindSoundLeakStart(object sender, DoWorkEventArgs e)
|
||||
{
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
|
||||
leakfinder = new LeakFinder(leakstartsector, leakstartposition, leakendsector, leakendposition, (HashSet<Sector>)e.Argument);
|
||||
|
||||
if (leakfinder.FindLeak() == false)
|
||||
General.ToastManager.ShowToast(ToastMessages.SOUNDPROPAGATIONMODE, ToastType.WARNING, "Sound propagation", "Could not find a leak between the selected start and end positions, even though there should be one. This is weird");
|
||||
else
|
||||
General.Interface.DisplayStatus(StatusType.Info, string.Format(@"Searching for sound leak finished. Elapsed time: {0:mm\:ss\.ff}", sw.Elapsed));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Method that's called when finding a sound leak finished.
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender</param>
|
||||
/// <param name="e">The event arguments</param>
|
||||
private void FindSoundLeakFinished(object sender, RunWorkerCompletedEventArgs e)
|
||||
{
|
||||
General.Interface.RedrawDisplay();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Actions
|
||||
|
@ -466,11 +649,48 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
|
|||
{
|
||||
using(ColorConfiguration cc = new ColorConfiguration())
|
||||
{
|
||||
if(cc.ShowDialog((Form)General.Interface) == DialogResult.OK)
|
||||
if (cc.ShowDialog((Form)General.Interface) == DialogResult.OK)
|
||||
General.Interface.RedrawDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
[BeginAction("setleakfinderstart")]
|
||||
public void SetLeakFinderStartSector()
|
||||
{
|
||||
leakstartsector = highlighted;
|
||||
leakstartposition = mousemappos;
|
||||
leakstartlabel.Location = mousemappos;
|
||||
leakfinder = null;
|
||||
|
||||
// Redraw to show the label
|
||||
General.Interface.RedrawDisplay();
|
||||
|
||||
FindSoundLeak();
|
||||
}
|
||||
|
||||
[BeginAction("setleakfinderend")]
|
||||
public void SetLeakFinderEndSector()
|
||||
{
|
||||
leakendsector = highlighted;
|
||||
leakendposition = mousemappos;
|
||||
leakendlabel.Location = mousemappos;
|
||||
leakfinder = null;
|
||||
|
||||
// Redraw to show the label
|
||||
General.Interface.RedrawDisplay();
|
||||
|
||||
FindSoundLeak();
|
||||
}
|
||||
|
||||
[BeginAction("clearselection", BaseAction = true)]
|
||||
public void ClearLeakFinder()
|
||||
{
|
||||
leakendsector = leakstartsector = null;
|
||||
leakfinder = null;
|
||||
|
||||
General.Interface.RedrawDisplay();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,202 +1,207 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{F59B344C-DD50-4DB7-ADDD-56AAD66450AF}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>CodeImp.DoomBuilder.SoundPropagationMode</RootNamespace>
|
||||
<AssemblyName>SoundPropagationMode</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
<OldToolsVersion>3.5</OldToolsVersion>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\..\..\Build\Plugins\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<OutputPath>..\..\..\Build\Plugins\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>false</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug + Profiler|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\..\..\Build\Plugins\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;PROFILE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release + Profiler|x86' ">
|
||||
<OutputPath>..\..\..\Build\Plugins\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<OutputPath>..\..\..\Build\Plugins\</OutputPath>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<DefineConstants>TRACE;DEBUG</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<OutputPath>..\..\..\Build\Plugins\</OutputPath>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Optimize>false</Optimize>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug + Profiler|x64'">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<OutputPath>..\..\..\Build\Plugins\</OutputPath>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<DefineConstants>TRACE;DEBUG;PROFILE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release + Profiler|x64'">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<OutputPath>..\..\..\Build\Plugins\</OutputPath>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BuilderPlug.cs" />
|
||||
<Compile Include="Interface\SoundEnvironmentPanel.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Interface\SoundEnvironmentPanel.Designer.cs">
|
||||
<DependentUpon>SoundEnvironmentPanel.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="SoundEnvironment.cs" />
|
||||
<Compile Include="SoundEnvironmentMode.cs" />
|
||||
<Compile Include="SoundPropagationDomain.cs" />
|
||||
<Compile Include="Windows\ColorConfiguration.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Windows\ColorConfiguration.designer.cs">
|
||||
<DependentUpon>ColorConfiguration.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Windows\MenusForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Windows\MenusForm.designer.cs">
|
||||
<DependentUpon>MenusForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SoundPropagationMode.cs" />
|
||||
<Compile Include="Windows\ReverbsPickerForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Windows\ReverbsPickerForm.Designer.cs">
|
||||
<DependentUpon>ReverbsPickerForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Core\BuilderMono.csproj">
|
||||
<Project>{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}</Project>
|
||||
<Name>Builder</Name>
|
||||
<Private>False</Private>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\Actions.cfg" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Resources\ColorManagement.png" />
|
||||
<EmbeddedResource Include="Windows\ColorConfiguration.resx">
|
||||
<DependentUpon>ColorConfiguration.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Windows\MenusForm.resx">
|
||||
<DependentUpon>MenusForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Resources\SoundPropagationIcon.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Interface\SoundEnvironmentPanel.resx">
|
||||
<DependentUpon>SoundEnvironmentPanel.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Resources\ZDoomSoundEnvironment.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\Warning.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\Status0.png" />
|
||||
<EmbeddedResource Include="Windows\ReverbsPickerForm.resx">
|
||||
<DependentUpon>ReverbsPickerForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{F59B344C-DD50-4DB7-ADDD-56AAD66450AF}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>CodeImp.DoomBuilder.SoundPropagationMode</RootNamespace>
|
||||
<AssemblyName>SoundPropagationMode</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
<OldToolsVersion>3.5</OldToolsVersion>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\..\..\Build\Plugins\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<OutputPath>..\..\..\Build\Plugins\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>false</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug + Profiler|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\..\..\Build\Plugins\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;PROFILE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release + Profiler|x86' ">
|
||||
<OutputPath>..\..\..\Build\Plugins\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<OutputPath>..\..\..\Build\Plugins\</OutputPath>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<DefineConstants>TRACE;DEBUG</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<OutputPath>..\..\..\Build\Plugins\</OutputPath>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Optimize>false</Optimize>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug + Profiler|x64'">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<OutputPath>..\..\..\Build\Plugins\</OutputPath>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<DefineConstants>TRACE;DEBUG;PROFILE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release + Profiler|x64'">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<OutputPath>..\..\..\Build\Plugins\</OutputPath>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Optimize>true</Optimize>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BuilderPlug.cs" />
|
||||
<Compile Include="Interface\SoundEnvironmentPanel.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Interface\SoundEnvironmentPanel.Designer.cs">
|
||||
<DependentUpon>SoundEnvironmentPanel.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="LeakFinder.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="SoundEnvironment.cs" />
|
||||
<Compile Include="SoundEnvironmentMode.cs" />
|
||||
<Compile Include="SoundNode.cs" />
|
||||
<Compile Include="SoundPropagationDomain.cs" />
|
||||
<Compile Include="Windows\ColorConfiguration.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Windows\ColorConfiguration.designer.cs">
|
||||
<DependentUpon>ColorConfiguration.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Windows\MenusForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Windows\MenusForm.designer.cs">
|
||||
<DependentUpon>MenusForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SoundPropagationMode.cs" />
|
||||
<Compile Include="Windows\ReverbsPickerForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Windows\ReverbsPickerForm.Designer.cs">
|
||||
<DependentUpon>ReverbsPickerForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Core\BuilderMono.csproj">
|
||||
<Project>{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}</Project>
|
||||
<Name>Builder</Name>
|
||||
<Private>False</Private>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\Actions.cfg" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Resources\ColorManagement.png" />
|
||||
<EmbeddedResource Include="Windows\ColorConfiguration.resx">
|
||||
<DependentUpon>ColorConfiguration.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Windows\MenusForm.resx">
|
||||
<DependentUpon>MenusForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Resources\SoundPropagationIcon.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Interface\SoundEnvironmentPanel.resx">
|
||||
<DependentUpon>SoundEnvironmentPanel.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Resources\ZDoomSoundEnvironment.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\Warning.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\Status0.png" />
|
||||
<EmbeddedResource Include="Windows\ReverbsPickerForm.resx">
|
||||
<DependentUpon>ReverbsPickerForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\Hints.cfg" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
-->
|
||||
</Project>
|