mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-11-27 22:22:32 +00:00
7ab0a86a92
Changed, Sound Propagation mode: all sound zones are now shown when no sector is highlighted. Changed, Sound Environments mode: the mode is now available only in UDMF map format. Changed, Color Picker plugin: the plugin functionality is no longer available in Doom map format. Restored the ability to create superimposed lines by dragging them with "Snap to Geometry" mode disabled. Fixed, Sound Propagation mode: fixed a crash when a single-sided linedef had "Block Sound" flag. Fixed, Find & Replace mode: in some cases "Find Sector/Sidedef/Linedef/Thing flags" search modes failed to find map elements with required flags. Fixed, Edit Selection mode: in some cases incorrect geometry was created after applying multipart sector edit when "Replace with Dragged Geometry" mode was enabled. Fixed a crash caused by eventual GDI font objects overflow.
126 lines
3.9 KiB
C#
126 lines
3.9 KiB
C#
#region ================== Namespaces
|
|
|
|
using System.Collections.Generic;
|
|
using CodeImp.DoomBuilder.Map;
|
|
using CodeImp.DoomBuilder.Rendering;
|
|
|
|
#endregion
|
|
|
|
namespace CodeImp.DoomBuilder.SoundPropagationMode
|
|
{
|
|
public class SoundPropagationDomain
|
|
{
|
|
#region ================== Variables
|
|
|
|
private HashSet<Sector> sectors;
|
|
private HashSet<Sector> adjacentsectors;
|
|
private FlatVertex[] level1geometry;
|
|
private FlatVertex[] level2geometry;
|
|
|
|
#endregion
|
|
|
|
#region ================== Properties
|
|
|
|
public HashSet<Sector> Sectors { get { return sectors; } }
|
|
public HashSet<Sector> AdjacentSectors { get { return adjacentsectors; } }
|
|
public FlatVertex[] Level1Geometry { get { return level1geometry; } }
|
|
public FlatVertex[] Level2Geometry { get { return level2geometry; } }
|
|
public int Color { get; set; } //mxd
|
|
|
|
#endregion
|
|
|
|
#region ================== Constructor
|
|
|
|
public SoundPropagationDomain(Sector sector)
|
|
{
|
|
sectors = new HashSet<Sector>();
|
|
adjacentsectors = new HashSet<Sector>();
|
|
|
|
CreateSoundPropagationDomain(sector);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Methods
|
|
|
|
private void CreateSoundPropagationDomain(Sector sourcesector)
|
|
{
|
|
List<Sector> sectorstocheck = new List<Sector> { sourcesector };
|
|
HashSet<Linedef> blockinglines = new HashSet<Linedef>(); //mxd
|
|
|
|
while(sectorstocheck.Count > 0)
|
|
{
|
|
// Make sure to first check all sectors that are not behind a sound blocking line
|
|
Sector sector = sectorstocheck[0];
|
|
|
|
foreach(Sidedef sd in sector.Sidedefs)
|
|
{
|
|
bool blocksound = sd.Line.IsFlagSet(SoundPropagationMode.BlockSoundFlag);
|
|
if(blocksound && sd.Other != null) blockinglines.Add(sd.Line);
|
|
|
|
// If the line is one sided, the sound can travel nowhere, so try the next one
|
|
if(sd.Other == null || blocksound) continue;
|
|
|
|
// Get the sector on the other side of the line we're checking right now
|
|
Sector oppositesector = sd.Other.Sector;
|
|
|
|
bool blockheight = IsSoundBlockedByHeight(sd.Line);
|
|
|
|
// Try next line if sound will not pass through the current one. The last check makes
|
|
// sure that the next line is tried if the current line is blocking sound, and the current
|
|
// sector is already behind a sound blocking line
|
|
if(oppositesector == null || blockheight) continue;
|
|
|
|
// If the opposite sector was not regarded at all yet...
|
|
if(!sectors.Contains(oppositesector) && !sectorstocheck.Contains(oppositesector))
|
|
{
|
|
sectorstocheck.Add(oppositesector);
|
|
}
|
|
}
|
|
|
|
sectorstocheck.Remove(sector);
|
|
sectors.Add(sector);
|
|
}
|
|
|
|
foreach(Linedef ld in blockinglines)
|
|
{
|
|
// Lines that don't have a back side, or where the sound is blocked due to
|
|
// the sector heights on each side can be skipped
|
|
if(IsSoundBlockedByHeight(ld)) continue;
|
|
if(!sectors.Contains(ld.Front.Sector)) adjacentsectors.Add(ld.Front.Sector);
|
|
if(!sectors.Contains(ld.Back.Sector)) adjacentsectors.Add(ld.Back.Sector);
|
|
}
|
|
|
|
List<FlatVertex> vertices = new List<FlatVertex>();
|
|
|
|
foreach(Sector s in sectors)
|
|
{
|
|
vertices.AddRange(s.FlatVertices);
|
|
}
|
|
|
|
level1geometry = vertices.ToArray();
|
|
level2geometry = vertices.ToArray();
|
|
|
|
for(int i = 0; i < level1geometry.Length; i++)
|
|
{
|
|
level1geometry[i].c = BuilderPlug.Me.Level1Color.WithAlpha(128).ToInt();
|
|
level2geometry[i].c = BuilderPlug.Me.Level2Color.WithAlpha(128).ToInt();
|
|
}
|
|
}
|
|
|
|
private static bool IsSoundBlockedByHeight(Linedef ld)
|
|
{
|
|
if(ld.Back == null || ld.Front == null) return false;
|
|
|
|
Sector s1 = ld.Front.Sector;
|
|
Sector s2 = ld.Back.Sector;
|
|
|
|
// Check if the sound will be blocked because of sector floor and ceiling heights
|
|
// (like closed doors, raised lifts etc.)
|
|
return (s1.CeilHeight <= s2.FloorHeight || s1.FloorHeight >= s2.CeilHeight ||
|
|
s2.CeilHeight <= s2.FloorHeight || s1.CeilHeight <= s1.FloorHeight);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|