#region === Copyright (c) 2010 Pascal van der Heiden === using System.Collections.Generic; using CodeImp.DoomBuilder.Geometry; using CodeImp.DoomBuilder.Map; #endregion namespace CodeImp.DoomBuilder.BuilderModes { internal class EffectLineSlope : SectorEffect { // Linedef that is used to create this effect private readonly Linedef l; private Plane storedfloor; //mxd. SectorData recreates floor/ceiling planes before updating effects private Plane storedceiling; //mxd // Constructor public EffectLineSlope(SectorData data, Linedef sourcelinedef) : base(data) { l = sourcelinedef; // New effect added: This sector needs an update! if(data.Mode.VisualSectorExists(data.Sector)) { BaseVisualSector vs = (BaseVisualSector)data.Mode.GetVisualSector(data.Sector); vs.UpdateSectorGeometry(true); } } // This makes sure we are updated with the source linedef information public override void Update() { if(l.Front == null || l.Back == null) return; //mxd // Find the vertex furthest from the line Vertex foundv = null; double founddist = -1.0f; foreach(Sidedef sd in data.Sector.Sidedefs) { Vertex v = sd.IsFront ? sd.Line.Start : sd.Line.End; double d = l.DistanceToSq(v.Position, false); if(d > founddist) { foundv = v; founddist = d; } } if(foundv == null) return; //mxd bool updatesides = false; // Align floor with back of line if((l.Args[0] == 1) && (l.Front.Sector == data.Sector)) { Vector3D v1 = new Vector3D(l.Start.Position.x, l.Start.Position.y, l.Back.Sector.FloorHeight); Vector3D v2 = new Vector3D(l.End.Position.x, l.End.Position.y, l.Back.Sector.FloorHeight); Vector3D v3 = new Vector3D(foundv.Position.x, foundv.Position.y, data.Sector.FloorHeight); data.Floor.plane = (l.SideOfLine(v3) < 0.0f ? new Plane(v1, v2, v3, true) : new Plane(v2, v1, v3, true)); //mxd. Update only when actually changed if(storedfloor != data.Floor.plane) { storedfloor = data.Floor.plane; updatesides = true; } } // Align floor with front of line else if((l.Args[0] == 2) && (l.Back.Sector == data.Sector)) { Vector3D v1 = new Vector3D(l.Start.Position.x, l.Start.Position.y, l.Front.Sector.FloorHeight); Vector3D v2 = new Vector3D(l.End.Position.x, l.End.Position.y, l.Front.Sector.FloorHeight); Vector3D v3 = new Vector3D(foundv.Position.x, foundv.Position.y, data.Sector.FloorHeight); data.Floor.plane = (l.SideOfLine(v3) < 0.0f ? new Plane(v1, v2, v3, true) : new Plane(v2, v1, v3, true)); //mxd. Update only when actually changed if(storedfloor != data.Floor.plane) { storedfloor = data.Floor.plane; updatesides = true; } } // Align ceiling with back of line if((l.Args[1] == 1) && (l.Front.Sector == data.Sector)) { Vector3D v1 = new Vector3D(l.Start.Position.x, l.Start.Position.y, l.Back.Sector.CeilHeight); Vector3D v2 = new Vector3D(l.End.Position.x, l.End.Position.y, l.Back.Sector.CeilHeight); Vector3D v3 = new Vector3D(foundv.Position.x, foundv.Position.y, data.Sector.CeilHeight); data.Ceiling.plane = (l.SideOfLine(v3) > 0.0f ? new Plane(v1, v2, v3, false) : new Plane(v2, v1, v3, false)); //mxd. Update only when actually changed if(storedceiling != data.Ceiling.plane) { storedceiling = data.Ceiling.plane; updatesides = true; } } // Align ceiling with front of line else if((l.Args[1] == 2) && (l.Back.Sector == data.Sector)) { Vector3D v1 = new Vector3D(l.Start.Position.x, l.Start.Position.y, l.Front.Sector.CeilHeight); Vector3D v2 = new Vector3D(l.End.Position.x, l.End.Position.y, l.Front.Sector.CeilHeight); Vector3D v3 = new Vector3D(foundv.Position.x, foundv.Position.y, data.Sector.CeilHeight); data.Ceiling.plane = (l.SideOfLine(v3) > 0.0f ? new Plane(v1, v2, v3, false) : new Plane(v2, v1, v3, false)); //mxd. Update only when actually changed if(storedceiling != data.Ceiling.plane) { storedceiling = data.Ceiling.plane; updatesides = true; } } //mxd. Update outer sidedef geometry if(updatesides) { UpdateSectorSides(data.Sector); // Update sectors with PlaneCopySlope Effect... List toupdate = new List(); foreach(Sector s in data.UpdateAlso.Keys) { SectorData osd = data.Mode.GetSectorDataEx(s); if(osd == null) continue; foreach(SectorEffect e in osd.Effects) { if(e is EffectPlaneCopySlope) { toupdate.Add(osd); break; } } } // Do it in 2 steps, because SectorData.Reset() may change SectorData.UpdateAlso collection... foreach(SectorData sd in toupdate) { // Update PlaneCopySlope Effect... sd.Reset(false); // Update outer sides... UpdateSectorSides(sd.Sector); } // Update all things in the sector foreach(Thing t in General.Map.Map.Things) { if(t.Sector == data.Sector) { if(data.Mode.VisualThingExists(t)) { // Update thing BaseVisualThing vt = (BaseVisualThing)data.Mode.GetVisualThing(t); vt.Changed = true; } } } } } //mxd private void UpdateSectorSides(Sector s) { foreach(Sidedef side in s.Sidedefs) { if(side.Other != null && side.Other.Sector != null && data.Mode.VisualSectorExists(side.Other.Sector)) { BaseVisualSector vs = (BaseVisualSector)data.Mode.GetVisualSector(side.Other.Sector); vs.GetSidedefParts(side.Other).SetupAllParts(); } } } } }