public static List <Line3D> GetHelperShapes(ICollection <Thing> things, VisualBlockMap blockmap) { var lines = GetHelperShapes(GetSpecialThings(things, blockmap), blockmap); lines.AddRange(GetThingArgumentShapes(things, blockmap, CIRCLE_SIDES)); return(lines); }
public PathNode(Thing t, VisualBlockMap blockmap) { thing = t; position = t.Position; position.z += GetCorrectHeight(t, blockmap, true); nextnodes = new Dictionary <int, PathNode>(); prevnodes = new Dictionary <int, PathNode>(); }
// This determines which sector the thing is in and links it public void DetermineSector(VisualBlockMap blockmap) { // Find nearest sectors using the blockmap List <Sector> possiblesectors = blockmap.GetBlock(blockmap.GetBlockCoordinates(pos)).Sectors; // Check in which sector we are sector = null; foreach (Sector s in possiblesectors) { if (s.Intersect(pos)) { sector = s; break; } } }
// Required only when called from VisualMode private static float GetCorrectHeight(Thing thing, VisualBlockMap blockmap, bool usethingcenter) { if (blockmap == null) { return(0f); } float height = (usethingcenter ? thing.Height / 2f : 0f); if (thing.Sector == null) { thing.DetermineSector(blockmap); } if (thing.Sector != null) { height += thing.Sector.FloorHeight; } return(height); }
// This determines which sector the thing is in and links it public void DetermineSector(VisualBlockMap blockmap) { //mxd. First check if the sprite is still in the same sector if (sector != null && !sector.IsDisposed && sector.Intersect(pos)) { return; } // Find nearest sectors using the blockmap List <Sector> possiblesectors = blockmap.GetBlock(blockmap.GetBlockCoordinates(pos)).Sectors; // Check in which sector we are sector = null; foreach (Sector s in possiblesectors) { if (s.Intersect(pos)) { sector = s; break; } } }
// This determines which sector the thing is in and links it public void DetermineSector(VisualBlockMap blockmap) { sector = blockmap.GetSectorAt(pos); }
// Create argument value/min/max shapes private static List <Line3D> GetThingArgumentShapes(ICollection <Thing> things, VisualBlockMap blockmap, int numsides) { var lines = new List <Line3D>(); foreach (Thing t in things) { if (t.Action != 0) { continue; } ThingTypeInfo tti = General.Map.Data.GetThingInfoEx(t.Type); if (tti == null) { continue; } Vector3D pos = t.Position; pos.z += GetCorrectHeight(t, blockmap, false); for (int i = 0; i < t.Args.Length; i++) { if (t.Args[i] == 0) { continue; // Avoid visual noise } var a = tti.Args[i]; //TODO: can this be null? switch (a.RenderStyle) { case ArgumentInfo.ArgumentRenderStyle.CIRCLE: lines.AddRange(MakeCircleLines(pos, a.RenderColor, t.Args[i], numsides)); if (a.MinRange > 0) { lines.AddRange(MakeCircleLines(pos, a.MinRangeColor, a.MinRange, numsides)); } if (a.MaxRange > 0) { lines.AddRange(MakeCircleLines(pos, a.MaxRangeColor, a.MaxRange, numsides)); } break; case ArgumentInfo.ArgumentRenderStyle.RECTANGLE: lines.AddRange(MakeRectangleLines(pos, a.RenderColor, t.Args[i])); if (a.MinRange > 0) { lines.AddRange(MakeRectangleLines(pos, a.MinRangeColor, a.MinRange)); } if (a.MaxRange > 0) { lines.AddRange(MakeRectangleLines(pos, a.MaxRangeColor, a.MaxRange)); } break; case ArgumentInfo.ArgumentRenderStyle.NONE: break; default: throw new NotImplementedException("Unknown ArgumentRenderStyle"); } } } return(lines); }
private static List <Line3D> GetHelperShapes(SpecialThings result, VisualBlockMap blockmap) { var lines = new List <Line3D>(); var actormovertargets = new Dictionary <int, List <Thing> >(); // Get ActorMover targets if (result.ActorMovers.Count > 0) { foreach (Thing t in General.Map.Map.Things) { if (t.Tag == 0 || !result.ActorMovers.ContainsKey(t.Tag)) { continue; } if (!actormovertargets.ContainsKey(t.Tag)) { actormovertargets[t.Tag] = new List <Thing>(); } actormovertargets[t.Tag].Add(t); } } Vector3D start, end; // Process patrol points foreach (KeyValuePair <int, List <Thing> > group in result.PatrolPoints) { foreach (Thing t in group.Value) { if (!result.PatrolPoints.ContainsKey(t.Args[0])) { continue; } start = t.Position; start.z += GetCorrectHeight(t, blockmap, true); foreach (Thing tt in result.PatrolPoints[t.Args[0]]) { end = tt.Position; end.z += GetCorrectHeight(tt, blockmap, true); lines.Add(new Line3D(start, end)); } } } // Process things with Thing_SetGoal foreach (Thing t in result.ThingsWithGoal) { if (!result.PatrolPoints.ContainsKey(t.Args[1])) { continue; } start = t.Position; start.z += GetCorrectHeight(t, blockmap, true); foreach (Thing tt in result.PatrolPoints[t.Args[1]]) { end = tt.Position; end.z += GetCorrectHeight(tt, blockmap, true); lines.Add(new Line3D(start, end, General.Colors.Selection)); } } // Process patrol specials foreach (Thing t in result.PatrolSpecials) { if (!result.PatrolPoints.ContainsKey(t.Tag)) { continue; } start = t.Position; start.z += GetCorrectHeight(t, blockmap, true); foreach (Thing tt in result.PatrolPoints[t.Tag]) { end = tt.Position; end.z += GetCorrectHeight(tt, blockmap, true); lines.Add(new Line3D(start, end, General.Colors.Selection)); } } // Process cameras [CAN USE INTERPOLATION] foreach (Thing t in result.Cameras) { int targettag = t.Args[0] + (t.Args[1] << 8); if (targettag == 0 || !result.InterpolationPoints.ContainsKey(targettag)) { continue; //no target / target doesn't exist } bool interpolatepath = ((t.Args[2] & 1) != 1); start = t.Position; start.z += GetCorrectHeight(t, blockmap, true); foreach (PathNode node in result.InterpolationPoints[targettag]) { node.IsCurved = interpolatepath; lines.Add(new Line3D(start, node.Position, General.Colors.Selection)); } } //process actor movers [CAN USE INTERPOLATION] foreach (List <Thing> things in result.ActorMovers.Values) { foreach (Thing t in things) { int targettag = t.Args[0] + (t.Args[1] << 8); // Add interpolation point targets if (targettag != 0 && result.InterpolationPoints.ContainsKey(targettag)) { bool interpolatepath = ((t.Args[2] & 1) != 1); start = t.Position; start.z += GetCorrectHeight(t, blockmap, true); foreach (PathNode node in result.InterpolationPoints[targettag]) { node.IsCurved = interpolatepath; lines.Add(new Line3D(start, node.Position, General.Colors.Selection)); } } // Add thing-to-move targets if (actormovertargets.ContainsKey(t.Args[3])) { start = t.Position; start.z += GetCorrectHeight(t, blockmap, true); foreach (Thing tt in actormovertargets[t.Args[3]]) { end = tt.Position; end.z += GetCorrectHeight(tt, blockmap, true); lines.Add(new Line3D(start, end, General.Colors.Selection)); } } } } // Process path followers [CAN USE INTERPOLATION] foreach (Thing t in result.PathFollowers) { int targettag = t.Args[0] + (t.Args[1] << 8); if (targettag == 0 || !result.InterpolationPoints.ContainsKey(targettag)) { continue; //no target / target doesn't exist } bool interpolatepath = (t.Args[2] & 1) != 1; start = t.Position; start.z += GetCorrectHeight(t, blockmap, true); foreach (PathNode node in result.InterpolationPoints[targettag]) { node.IsCurved = interpolatepath; lines.Add(new Line3D(start, node.Position, General.Colors.Selection)); } } // Process polyobjects foreach (KeyValuePair <int, List <Thing> > group in result.PolyobjectAnchors) { if (!result.PolyobjectStartSpots.ContainsKey(group.Key)) { continue; } foreach (Thing anchor in group.Value) { start = anchor.Position; start.z += GetCorrectHeight(anchor, blockmap, true); foreach (Thing startspot in result.PolyobjectStartSpots[group.Key]) { end = startspot.Position; end.z += GetCorrectHeight(startspot, blockmap, true); lines.Add(new Line3D(start, end, General.Colors.Selection)); } } } // Process interpolation points [CAN BE INTERPOLATED] // 1. Connect PathNodes foreach (KeyValuePair <int, List <PathNode> > group in result.InterpolationPoints) { foreach (PathNode node in group.Value) { int targettag = node.Thing.Args[3] + (node.Thing.Args[4] << 8); if (targettag == 0 || !result.InterpolationPoints.ContainsKey(targettag)) { continue; } foreach (PathNode targetnode in result.InterpolationPoints[targettag]) { // Connect both ways if (!node.NextNodes.ContainsKey(targetnode.Thing.Index)) { node.NextNodes.Add(targetnode.Thing.Index, targetnode); } if (!targetnode.PreviousNodes.ContainsKey(node.Thing.Index)) { targetnode.PreviousNodes.Add(node.Thing.Index, node); } } } } // 2. Propagate IsCurved flag foreach (KeyValuePair <int, List <PathNode> > group in result.InterpolationPoints) { foreach (PathNode node in group.Value) { node.PropagateCurvedFlag(); } } // Process interpolation specials foreach (Thing t in result.InterpolationSpecials) { int targettag = t.Tag; if (targettag == 0 || !result.InterpolationPoints.ContainsKey(targettag)) { continue; //no target / target doesn't exist } start = t.Position; start.z += GetCorrectHeight(t, blockmap, true); foreach (PathNode node in result.InterpolationPoints[targettag]) { //Do not connect specials to the first or last node of a curved path, since those are used as spline control points only if (node.IsCurved && (node.PreviousNodes.Count == 0 || node.NextNodes.Count == 0)) { continue; } lines.Add(new Line3D(start, node.Position, General.Colors.Selection)); } } // 3. Make lines HashSet <int> processedindices = new HashSet <int>(); foreach (KeyValuePair <int, List <PathNode> > group in result.InterpolationPoints) { foreach (PathNode node in group.Value) { // Draw as a curve? if (node.IsCurved && !processedindices.Contains(node.Thing.Index) && node.NextNodes.Count > 0 && node.PreviousNodes.Count > 0) { PathNode prev = General.GetByIndex(node.PreviousNodes, 0).Value; PathNode next = General.GetByIndex(node.NextNodes, 0).Value; if (next.NextNodes.Count > 0) { PathNode nextnext = General.GetByIndex(next.NextNodes, 0).Value; // Generate curve points List <Vector3D> points = new List <Vector3D>(11); for (int i = 0; i < 11; i++) { float u = i * 0.1f; points.Add(new Vector3D( SplineLerp(u, prev.Position.x, node.Position.x, next.Position.x, nextnext.Position.x), SplineLerp(u, prev.Position.y, node.Position.y, next.Position.y, nextnext.Position.y), (blockmap == null ? 0 : SplineLerp(u, prev.Position.z, node.Position.z, next.Position.z, nextnext.Position.z)) )); } // Add line segments for (int i = 1; i < 11; i++) { lines.Add(new Line3D(points[i - 1], points[i], i == 10)); } continue; } } // Draw regular lines bool startnode = (node.IsCurved && node.PreviousNodes.Count == 0); // When using curves, this node won't be used by camera (the last node won't be used as well), so draw them using different color foreach (PathNode targetnode in node.NextNodes.Values) { bool isskipped = (startnode || (targetnode.IsCurved && targetnode.NextNodes.Count == 0)); lines.Add(new Line3D(node.Position, targetnode.Position, (isskipped ? General.Colors.Highlight : General.Colors.InfoLine), !isskipped)); } } } return(lines); }
private static SpecialThings GetSpecialThings(ICollection <Thing> things, VisualBlockMap blockmap) { SpecialThings result = new SpecialThings(); // Process oh so special things foreach (Thing t in things) { ThingTypeInfo info = General.Map.Data.GetThingInfoEx(t.Type); if (info == null) { continue; } switch (info.ClassName.ToLowerInvariant()) { case "patrolpoint": if (t.Tag != 0 || t.Args[0] != 0) { if (!result.PatrolPoints.ContainsKey(t.Tag)) { result.PatrolPoints.Add(t.Tag, new List <Thing>()); } result.PatrolPoints[t.Tag].Add(t); } break; case "patrolspecial": result.PatrolSpecials.Add(t); break; case "$polyanchor": if (!result.PolyobjectAnchors.ContainsKey(t.AngleDoom)) { result.PolyobjectAnchors[t.AngleDoom] = new List <Thing>(); } result.PolyobjectAnchors[t.AngleDoom].Add(t); break; case "$polyspawn": case "$polyspawncrush": case "$polyspawnhurt": if (!result.PolyobjectStartSpots.ContainsKey(t.AngleDoom)) { result.PolyobjectStartSpots[t.AngleDoom] = new List <Thing>(); } result.PolyobjectStartSpots[t.AngleDoom].Add(t); break; } // Process Thing_SetGoal action if (t.Action != 0 && General.Map.Config.LinedefActions.ContainsKey(t.Action) && General.Map.Config.LinedefActions[t.Action].Id.ToLowerInvariant() == "thing_setgoal" && (t.Args[0] == 0 || t.Args[0] == t.Tag) && t.Args[1] != 0) { result.ThingsWithGoal.Add(t); } } // We may need all of these actors... foreach (Thing t in General.Map.ThingsFilter.VisibleThings) { ThingTypeInfo info = General.Map.Data.GetThingInfoEx(t.Type); if (info == null) { continue; } switch (info.ClassName.ToLowerInvariant()) { case "interpolationpoint": if (!result.InterpolationPoints.ContainsKey(t.Tag)) { result.InterpolationPoints.Add(t.Tag, new List <PathNode>()); } result.InterpolationPoints[t.Tag].Add(new PathNode(t, blockmap)); break; case "interpolationspecial": result.InterpolationSpecials.Add(t); break; case "movingcamera": if (t.Args[0] != 0 || t.Args[1] != 0) { result.Cameras.Add(t); } break; case "pathfollower": if (t.Args[0] != 0 || t.Args[1] != 0) { result.PathFollowers.Add(t); } break; case "actormover": if ((t.Args[0] != 0 || t.Args[1] != 0) && t.Args[3] != 0) { if (!result.ActorMovers.ContainsKey(t.Args[3])) { result.ActorMovers.Add(t.Args[3], new List <Thing>()); } result.ActorMovers[t.Args[3]].Add(t); } break; } } return(result); }
private static List <Line3D> GetThingLinks(SpecialThings result, VisualBlockMap blockmap) { var lines = new List <Line3D>(); var actormovertargets = new Dictionary <int, List <Thing> >(); // Get ActorMover targets if (result.ActorMovers.Count > 0) { foreach (Thing t in General.Map.Map.Things) { if (t.Tag == 0 || !result.ActorMovers.ContainsKey(t.Tag)) { continue; } if (!actormovertargets.ContainsKey(t.Tag)) { actormovertargets[t.Tag] = new List <Thing>(); } actormovertargets[t.Tag].Add(t); } } Vector3D start, end; // Process patrol points foreach (KeyValuePair <int, List <Thing> > group in result.PatrolPoints) { foreach (Thing t in group.Value) { if (!result.PatrolPoints.ContainsKey(t.Args[0])) { continue; } start = t.Position; start.z += GetCorrectHeight(t, blockmap, true); foreach (Thing tt in result.PatrolPoints[t.Args[0]]) { end = tt.Position; end.z += GetCorrectHeight(tt, blockmap, true); lines.Add(new Line3D(start, end)); } } } // Process things with Thing_SetGoal foreach (Thing t in result.ThingsWithGoal) { if (!result.PatrolPoints.ContainsKey(t.Args[1])) { continue; } start = t.Position; start.z += GetCorrectHeight(t, blockmap, true); foreach (Thing tt in result.PatrolPoints[t.Args[1]]) { end = tt.Position; end.z += GetCorrectHeight(tt, blockmap, true); lines.Add(new Line3D(start, end, General.Colors.Selection)); } } // Process cameras [CAN USE INTERPOLATION] foreach (Thing t in result.Cameras) { int targettag = t.Args[0] + (t.Args[1] << 8); if (targettag == 0 || !result.InterpolationPoints.ContainsKey(targettag)) { continue; //no target / target doesn't exist } bool interpolatepath = ((t.Args[2] & 1) != 1); start = t.Position; start.z += GetCorrectHeight(t, blockmap, true); foreach (PathNode node in result.InterpolationPoints[targettag]) { node.IsCurved = interpolatepath; lines.Add(new Line3D(start, node.Position, General.Colors.Selection)); } } //process actor movers [CAN USE INTERPOLATION] foreach (List <Thing> things in result.ActorMovers.Values) { foreach (Thing t in things) { int targettag = t.Args[0] + (t.Args[1] << 8); // Add interpolation point targets if (targettag != 0 && result.InterpolationPoints.ContainsKey(targettag)) { bool interpolatepath = ((t.Args[2] & 1) != 1); start = t.Position; start.z += GetCorrectHeight(t, blockmap, true); foreach (PathNode node in result.InterpolationPoints[targettag]) { node.IsCurved = interpolatepath; lines.Add(new Line3D(start, node.Position, General.Colors.Selection)); } } // Add thing-to-move targets if (actormovertargets.ContainsKey(t.Args[3])) { start = t.Position; start.z += GetCorrectHeight(t, blockmap, true); foreach (Thing tt in actormovertargets[t.Args[3]]) { end = tt.Position; end.z += GetCorrectHeight(tt, blockmap, true); lines.Add(new Line3D(start, end, General.Colors.Selection)); } } } } // Process path followers [CAN USE INTERPOLATION] foreach (Thing t in result.PathFollowers) { int targettag = t.Args[0] + (t.Args[1] << 8); if (targettag == 0 || !result.InterpolationPoints.ContainsKey(targettag)) { continue; //no target / target doesn't exist } bool interpolatepath = (t.Args[2] & 1) != 1; start = t.Position; start.z += GetCorrectHeight(t, blockmap, true); foreach (PathNode node in result.InterpolationPoints[targettag]) { node.IsCurved = interpolatepath; lines.Add(new Line3D(start, node.Position, General.Colors.Selection)); } } // Process polyobjects foreach (KeyValuePair <int, List <Thing> > group in result.PolyobjectAnchors) { if (!result.PolyobjectStartSpots.ContainsKey(group.Key)) { continue; } foreach (Thing anchor in group.Value) { start = anchor.Position; start.z += GetCorrectHeight(anchor, blockmap, true); foreach (Thing startspot in result.PolyobjectStartSpots[group.Key]) { end = startspot.Position; end.z += GetCorrectHeight(startspot, blockmap, true); lines.Add(new Line3D(start, end, General.Colors.Selection)); } } } // Process interpolation points [CAN BE INTERPOLATED] // 1. Connect PathNodes foreach (KeyValuePair <int, List <PathNode> > group in result.InterpolationPoints) { foreach (PathNode node in group.Value) { int targettag = node.Thing.Args[3] + (node.Thing.Args[4] << 8); if (targettag == 0 || !result.InterpolationPoints.ContainsKey(targettag)) { continue; } foreach (PathNode targetnode in result.InterpolationPoints[targettag]) { // Connect both ways if (!node.NextNodes.ContainsKey(targetnode.Thing.Index)) { node.NextNodes.Add(targetnode.Thing.Index, targetnode); } if (!targetnode.PreviousNodes.ContainsKey(node.Thing.Index)) { targetnode.PreviousNodes.Add(node.Thing.Index, node); } } } } // 2. Propagate IsCurved flag foreach (KeyValuePair <int, List <PathNode> > group in result.InterpolationPoints) { foreach (PathNode node in group.Value) { node.PropagateCurvedFlag(); } } // 3. Make lines HashSet <int> processedindices = new HashSet <int>(); foreach (KeyValuePair <int, List <PathNode> > group in result.InterpolationPoints) { foreach (PathNode node in group.Value) { // Draw as a curve? if (node.IsCurved && !processedindices.Contains(node.Thing.Index) && node.NextNodes.Count > 0 && node.PreviousNodes.Count > 0) { PathNode prev = General.GetByIndex(node.PreviousNodes, 0).Value; PathNode next = General.GetByIndex(node.NextNodes, 0).Value; if (next.NextNodes.Count > 0) { PathNode nextnext = General.GetByIndex(next.NextNodes, 0).Value; // Generate curve points List <Vector3D> points = new List <Vector3D>(11); for (int i = 0; i < 11; i++) { float u = i * 0.1f; points.Add(new Vector3D( SplineLerp(u, prev.Position.x, node.Position.x, next.Position.x, nextnext.Position.x), SplineLerp(u, prev.Position.y, node.Position.y, next.Position.y, nextnext.Position.y), (blockmap == null ? 0 : SplineLerp(u, prev.Position.z, node.Position.z, next.Position.z, nextnext.Position.z)) )); } // Add line segments for (int i = 1; i < 11; i++) { lines.Add(new Line3D(points[i - 1], points[i], i == 10)); } continue; } } // Draw regular lines bool startnode = (node.IsCurved && node.PreviousNodes.Count == 0); // When using curves, this node won't be used by camera (the last node won't be used as well), so draw them using different color foreach (PathNode targetnode in node.NextNodes.Values) { bool isskipped = (startnode || (targetnode.IsCurved && targetnode.NextNodes.Count == 0)); lines.Add(new Line3D(node.Position, targetnode.Position, (isskipped ? General.Colors.Highlight : General.Colors.InfoLine), !isskipped)); } } } // Process arg helpers const int numsides = 24; foreach (Thing t in General.Map.ThingsFilter.VisibleThings) { if (t.Action != 0) { continue; } ThingTypeInfo tti = General.Map.Data.GetThingInfoEx(t.Type); if (tti == null) { continue; } Vector3D pos = t.Position; pos.z += GetCorrectHeight(t, blockmap, false); for (int i = 0; i < t.Args.Length; i++) { if (t.Args[i] != 0 && tti.Args[i].RenderStyle != ArgumentInfo.ArgumentRenderStyle.NONE) { switch (tti.Args[i].RenderStyle) { case ArgumentInfo.ArgumentRenderStyle.CIRCLE: lines.AddRange(MakeCircleLines(pos, tti.Args[i].RenderColor, t.Args[i], numsides)); break; case ArgumentInfo.ArgumentRenderStyle.RECTANGLE: lines.AddRange(MakeRectangleLines(pos, tti.Args[i].RenderColor, t.Args[i])); break; default: throw new NotImplementedException("Unknown ArgumentRenderStyle"); } } } } return(lines); }
public static List <Line3D> GetThingLinks(IEnumerable <Thing> things, VisualBlockMap blockmap) { return(GetThingLinks(GetSpecialThings(things, blockmap), blockmap)); }