Only rebuild effects that have changed

This commit is contained in:
Louis-Antoine 2019-04-02 17:38:48 +02:00 committed by sphere
parent 8ef05744f9
commit 5b4b6acda5
4 changed files with 188 additions and 114 deletions

View file

@ -788,10 +788,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
else s.Fields.Add("rotationceiling", new UniValue(UniversalType.Float, rotation));
}
}
// This rebuilds the sector data
// This requires that the blockmap is up-to-date!
internal void RebuildElementData()
// This rebuilds the sector data
// This requires that the blockmap is up-to-date!
internal void RebuildElementData(bool markedOnly = false)
{
//mxd
Sector[] sectorsWithEffects = null;
@ -819,8 +819,20 @@ namespace CodeImp.DoomBuilder.BuilderModes
Dictionary<int, List<Sector>> sectortags = new Dictionary<int, List<Sector>>();
List<Thing> slopethings = new List<Thing>();
sectordata = new Dictionary<Sector, SectorData>(General.Map.Map.Sectors.Count);
thingdata = new Dictionary<Thing, ThingData>(General.Map.Map.Things.Count);
if (sectordata == null)
sectordata = new Dictionary<Sector, SectorData>(General.Map.Map.Sectors.Count);
foreach (Sector sector in General.Map.Map.Sectors)
{
if (!markedOnly || sector.Marked)
{
RemoveSectorDependencies(sector);
sectordata[sector] = new SectorData(this, sector);
}
}
if (!markedOnly)
thingdata = new Dictionary<Thing, ThingData>(General.Map.Map.Things.Count);
if (bsp.IsDeactivated && !String.IsNullOrEmpty(bsp.ErrorMessage))
MessageBox.Show("Could not load the map's nodes: " + bsp.ErrorMessage + " Defaulting to blockmap.", "Error loading nodes!", MessageBoxButtons.OK, MessageBoxIcon.Error);
@ -867,6 +879,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
sectortags[tag].Add(s);
}
if (markedOnly && !s.Marked)
continue;
if (General.Map.SRB2) s.Fields.Clear(); //Reset fake UDMF properties (since the linedef special that set them might no longer be there)
else
{
@ -929,7 +944,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
if (l.IsRegularSlope)
{
if (!General.Map.FormatInterface.HasLinedefParameters) l.SetSlopeArgs();
if (((l.Args[0] == 1) || (l.Args[1] == 1)) && (l.Front != null))
if (((l.Args[0] == 1) || (l.Args[1] == 1)) && (l.Front != null) && (!markedOnly || l.Front.Sector.Marked || l.Marked))
{
SectorData sd = GetSectorData(l.Front.Sector);
sd.AddEffectLineSlope(l);
@ -941,7 +956,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
l.SetSlopeArgs();
}
}
if (((l.Args[0] == 2) || (l.Args[1] == 2)) && (l.Back != null))
if (((l.Args[0] == 2) || (l.Args[1] == 2)) && (l.Back != null) && (!markedOnly || l.Back.Sector.Marked || l.Marked))
{
SectorData sd = GetSectorData(l.Back.Sector);
sd.AddEffectLineSlope(l);
@ -975,7 +990,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
// Copy slope to front sector
if (l.Front != null)
if (l.Front != null && (!markedOnly || l.Front.Sector.Marked || l.Marked))
{
if ((l.Args[0] > 0 || l.Args[1] > 0) || (l.Back != null && (floorCopyToFront || ceilingCopyToFront)))
{
@ -985,7 +1000,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
// Copy slope to back sector
if (l.Back != null)
if (l.Back != null && (!markedOnly || l.Back.Sector.Marked || l.Marked))
{
if ((l.Args[2] > 0 || l.Args[3] > 0) || (l.Front != null && (floorCopyToBack || ceilingCopyToBack)))
{
@ -1024,9 +1039,15 @@ namespace CodeImp.DoomBuilder.BuilderModes
ApplyFlatAlignment(l, l.Front.Sector, alignfloor, alignceiling, offset, rotation);
else if (sectortags.ContainsKey(sectortag))
{
if (markedOnly && !(s.Marked || l.Marked))
continue;
List<Sector> sectors = sectortags[sectortag];
foreach (Sector s in sectors)
{
if (markedOnly && !(s.Marked || l.Marked))
continue;
ApplyFlatAlignment(l, s, alignfloor, alignceiling, offset, rotation);
}
}
}
@ -1042,12 +1063,18 @@ namespace CodeImp.DoomBuilder.BuilderModes
List<Sector> sectors = (sectortag == 65535) ? General.Map.Map.Sectors.ToList() : sectortags[sectortag];
foreach (Sector s in sectors)
{
if (markedOnly && !(s.Marked || l.Marked))
continue;
s.Fields.BeforeFieldsChange();
if (s.Fields.ContainsKey("lightcolor")) s.Fields["lightcolor"] = new UniValue(UniversalType.Color, color);
else s.Fields.Add("lightcolor", new UniValue(UniversalType.Color, color));
//TODO: Find out why the alpha value is ignored.
/*if (s.Fields.ContainsKey("lightalpha")) s.Fields["lightalpha"] = new UniValue(UniversalType.Integer, alpha);
else s.Fields.Add("lightalpha", new UniValue(UniversalType.Integer, alpha));*/
(GetVisualSector(s) as BaseVisualSector).UpdateSectorGeometry(false);
GetSectorData(l.Front.Sector).AddUpdateSector(s, false);
}
}
}
@ -1097,7 +1124,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
if ((int)t.AngleDoom == l.Tag) slopevertices.Add(t);
}
}
if (slopevertices.Count >= 3)
if (slopevertices.Count >= 3 && (!markedOnly || s.Marked || l.Marked
|| slopevertices[0].Marked || slopevertices[1].Marked || slopevertices[2].Marked))
{
SectorData sd = GetSectorData(s);
sd.AddEffectSRB2ThingVertexSlope(slopevertices, slopefloor, blockmap, bsp);
@ -1120,6 +1148,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
List<Sector> sectors = (sectortag == 65535) ? General.Map.Map.Sectors.ToList() : sectortags[sectortag];
foreach (Sector s in sectors)
{
if (markedOnly && !(s.Marked || l.Marked))
continue;
SectorData sd = GetSectorData(s);
sd.AddEffect3DFloor(l);
}
@ -1138,6 +1169,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
List<Sector> sectors = sectortags[l.Args[0]];
foreach (Sector s in sectors)
{
if (markedOnly && !(s.Marked || l.Marked))
continue;
SectorData sd = GetSectorData(s);
sd.AddEffectBrightnessLevel(l);
}
@ -1151,6 +1185,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
List<Sector> sectors = sectortags[l.Args[0]];
foreach (Sector s in sectors)
{
if (markedOnly && !(s.Marked || l.Marked))
continue;
SectorData sd = GetSectorData(s);
sd.AddEffectTransferFloorBrightness(l);
}
@ -1164,6 +1201,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
List<Sector> sectors = sectortags[l.Args[0]];
foreach (Sector s in sectors)
{
if (markedOnly && !(s.Marked || l.Marked))
continue;
SectorData sd = GetSectorData(s);
sd.AddEffectTransferCeilingBrightness(l);
}
@ -1184,7 +1224,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
case 9511:
case 9510:
t.DetermineSector(blockmap);
if (t.Sector != null)
if (t.Sector != null && (!markedOnly || t.Sector.Marked || t.Marked))
{
SectorData sd = GetSectorData(t.Sector);
sd.AddEffectCopySlope(t);
@ -1195,7 +1235,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
case 9501:
case 9500:
t.DetermineSector(blockmap);
if (t.Sector != null)
if (t.Sector != null && (!markedOnly || t.Sector.Marked || t.Marked))
{
SectorData sd = GetSectorData(t.Sector);
sd.AddEffectThingLineSlope(t);
@ -1206,7 +1246,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
case 9503:
case 9502:
t.DetermineSector(blockmap);
if (t.Sector != null)
if (t.Sector != null && (!markedOnly || t.Sector.Marked || t.Marked))
{
SectorData sd = GetSectorData(t.Sector);
sd.AddEffectThingSlope(t);
@ -1216,7 +1256,44 @@ namespace CodeImp.DoomBuilder.BuilderModes
}
}
}
internal void MarkDependentSectors(MapElement element)
{
Dictionary<Sector, bool> sectorsToUpdate;
if (element is Sector)
sectorsToUpdate = GetSectorData(element as Sector).UpdateAlso;
else if (element is Vertex && vertexdata != null)
sectorsToUpdate = GetVertexData(element as Vertex).UpdateAlso;
else if (element is Thing)
sectorsToUpdate = GetThingData(element as Thing).UpdateAlso;
else
return;
foreach (KeyValuePair<Sector, bool> updateAlso in sectorsToUpdate)
{
if (updateAlso.Key.Marked)
continue;
updateAlso.Key.Marked = true;
MarkDependentSectors(updateAlso.Key);
}
}
internal void RemoveSectorDependencies(Sector sector)
{
foreach (KeyValuePair<MapElement, bool> updatedBy in GetSectorData(sector).updatedBy)
{
MapElement element = updatedBy.Key;
if (element is Sector)
GetSectorData(element as Sector).UpdateAlso.Remove(sector);
else if (element is Vertex)
GetVertexData(element as Vertex).UpdateAlso.Remove(sector);
else if (element is Thing)
GetThingData(element as Thing).UpdateAlso.Remove(sector);
}
}
#endregion
#region ================== Events
@ -1467,102 +1544,104 @@ namespace CodeImp.DoomBuilder.BuilderModes
// and uses the marks to check what needs to be reloaded.
protected override void ResourcesReloadedPartial()
{
bool sectorsmarked = false;
if(General.Map.UndoRedo.GeometryChanged)
foreach (MapElement e in General.Map.Map.RemovedElements)
{
// Let the core do this (it will just dispose the sectors that were changed)
base.ResourcesReloadedPartial();
if (e is Sector)
RemoveSectorDependencies(e as Sector);
MarkDependentSectors(e);
}
else
// Go for all vertices to mark linedefs that need updating
foreach (Vertex v in General.Map.Map.Vertices)
if (v.Marked)
foreach (Linedef ld in v.Linedefs)
ld.Marked = true;
foreach (Linedef l in General.Map.Map.Linedefs)
{
// Neighbour sectors must be updated as well
foreach(Sector s in General.Map.Map.Sectors)
if (l.Marked)
{
if(s.Marked)
{
sectorsmarked = true;
foreach(Sidedef sd in s.Sidedefs)
{
sd.Marked = true;
if(sd.Other != null) sd.Other.Marked = true;
}
}
if (l.Front != null)
l.Front.Marked = true;
if (l.Back != null)
l.Back.Marked = true;
}
// Go for all sidedefs to update
foreach(Sidedef sd in General.Map.Map.Sidedefs)
{
if(sd.Marked && VisualSectorExists(sd.Sector))
{
BaseVisualSector vs = GetVisualSector(sd.Sector) as BaseVisualSector;
VisualSidedefParts parts = vs.GetSidedefParts(sd);
parts.SetupAllParts();
}
}
// Go for all sectors to update
foreach(Sector s in General.Map.Map.Sectors)
{
if(s.Marked)
{
SectorData sd = GetSectorData(s);
sd.Reset();
// UpdateSectorGeometry for associated sectors (sd.UpdateAlso) as well!
foreach(KeyValuePair<Sector, bool> us in sd.UpdateAlso)
{
if(VisualSectorExists(us.Key))
{
BaseVisualSector vs = GetVisualSector(us.Key) as BaseVisualSector;
vs.UpdateSectorGeometry(us.Value);
}
}
// And update for this sector ofcourse
if(VisualSectorExists(s))
{
BaseVisualSector vs = GetVisualSector(s) as BaseVisualSector;
vs.UpdateSectorGeometry(false);
}
}
}
if(!sectorsmarked)
{
// No sectors or geometry changed. So we only have
// to update things when they have changed.
foreach(KeyValuePair<Thing, VisualThing> vt in allthings)
if((vt.Value != null) && vt.Key.Marked) (vt.Value as BaseVisualThing).Rebuild();
}
else
{
// Things depend on the sector they are in and because we can't
// easily determine which ones changed, we dispose all things
foreach(KeyValuePair<Thing, VisualThing> vt in allthings)
if(vt.Value != null) vt.Value.Dispose();
// Apply new lists
allthings = new Dictionary<Thing, VisualThing>(allthings.Count);
}
// Clear visibility collections
visiblesectors.Clear();
visibleblocks.Clear();
visiblegeometry.Clear();
visiblethings.Clear();
// Make new blockmap
if(sectorsmarked || General.Map.UndoRedo.PopulationChanged)
FillBlockMap();
RebuildElementData();
UpdateChangedObjects();
// Visibility culling (this re-creates the needed resources)
DoCulling();
}
// Go for all sidedefs to mark sectors that need updating
foreach (Sidedef sd in General.Map.Map.Sidedefs)
if (sd.Marked)
sd.Sector.Marked = true;
// Mark sectors that depend on updated sectors/linedefs/sidedefs/vertices
// Marking lines, sides and vertices also marks the sectors they are bound to,
// so it will properly mark sectors that don't directly depend on other sectors
foreach (Sector s in General.Map.Map.Sectors)
if (s.Marked)
MarkDependentSectors(s);
// Mark sectors that depend on updated vertices
foreach (Vertex v in General.Map.Map.Vertices)
if (v.Marked)
MarkDependentSectors(v);
// Mark sectors that depend on updated things
foreach (Thing t in General.Map.Map.Things)
if (t.Marked)
MarkDependentSectors(t);
// Neighbour sectors must be updated as well
foreach (Sector s in General.Map.Map.Sectors)
if (s.Marked)
foreach (Sidedef sd in s.Sidedefs)
if (sd.Other != null)
sd.Other.Marked = true;
// Go for all sidedefs to mark sectors that need updating
foreach (Sidedef sd in General.Map.Map.Sidedefs)
if (sd.Marked)
sd.Sector.Marked = true;
// Make new blockmap
FillBlockMap();
RebuildElementData(true);
// Dispose if source was disposed or marked
var newSectors = new Dictionary<Sector,VisualSector>(allsectors.Count);
General.Test("!Rebuild sector list", () => {
foreach (KeyValuePair<Sector, VisualSector> vs in allsectors)
{
if (vs.Value != null)
{
if(vs.Key.IsDisposed || vs.Key.Marked || (vs.Value as BaseVisualSector).Changed)
vs.Value.Dispose();
else
newSectors.Add(vs.Key, vs.Value);
}
}
});
// Things depend on the sector they are in and because we can't
// easily determine which ones changed, we dispose all things
foreach (KeyValuePair<Thing, VisualThing> vt in allthings)
if (vt.Value != null && (vt.Key.IsDisposed || vt.Key.Marked || (vt.Key.Sector != null && vt.Key.Sector.Marked)))
vt.Value.Dispose();
// Apply new lists
allsectors = newSectors;
allthings = new Dictionary<Thing, VisualThing>(allthings.Count);
// Clear visibility collections
visiblesectors.Clear();
visibleblocks.Clear();
visiblegeometry.Clear();
visiblethings.Clear();
// Visibility culling (this re-creates the needed resources)
DoCulling();
// Determine what we're aiming at now
PickTarget();
}
@ -1640,16 +1719,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
base.OnRedoEnd();
//mxd. Effects may've become invalid
if(sectordata != null && sectordata.Count > 0)
RebuildElementData();
//mxd. As well as geometry...
foreach(KeyValuePair<Sector, VisualSector> group in visiblesectors)
{
if(group.Value is BaseVisualSector) (group.Value as BaseVisualSector).Rebuild();
}
RebuildSelectedObjectsList();
}

View file

@ -73,6 +73,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
public SectorLevel Ceiling { get { return ceiling; } }
public BaseVisualMode Mode { get { return mode; } }
public Dictionary<Sector, bool> UpdateAlso { get { return updatesectors; } }
public Dictionary<MapElement, bool> updatedBy { get; set; }
#endregion
@ -91,6 +92,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
this.extrafloors = new List<Effect3DFloor>(1);
this.alleffects = new List<SectorEffect>(1);
this.updatesectors = new Dictionary<Sector, bool>(2);
this.updatedBy = new Dictionary<MapElement, bool>(2);
this.floor = new SectorLevel(sector, SectorLevelType.Floor);
this.floorbase = new SectorLevel(sector, SectorLevelType.Floor); //mxd
this.ceiling = new SectorLevel(sector, SectorLevelType.Ceiling);
@ -203,6 +205,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
public void AddUpdateSector(Sector s, bool includeneighbours)
{
updatesectors[s] = includeneighbours;
mode.GetSectorData(s).updatedBy[sector] = includeneighbours;
}
// This adds a sector level

View file

@ -51,6 +51,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
public void AddUpdateSector(Sector s, bool includeneighbours)
{
updatesectors[s] = includeneighbours;
mode.GetSectorData(s).updatedBy[thing] = includeneighbours;
}
#endregion

View file

@ -47,6 +47,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
public void AddUpdateSector(Sector s, bool includeneighbours)
{
updatesectors[s] = includeneighbours;
mode.GetSectorData(s).updatedBy[vertex] = includeneighbours;
}
#endregion