* A direct tag-to-tag relationship can now be established between two things, which allows event lines to be properly setup between them. This is intended for interpolation and patrol specials which are linked via a shared tag, instead of an argument. A POSITIVE value represents the parent thing, where a NEGATIVE value represents the child thing.

* Added interpolation and patrol point specials to the persistent event line processing
This commit is contained in:
Xabis 2017-02-14 12:33:50 -05:00 committed by spherallic
parent 21e2d93784
commit f8e048b1c1
5 changed files with 121 additions and 11 deletions

View file

@ -85,6 +85,7 @@ namespace CodeImp.DoomBuilder.Config
private string angletext;
private string flagsvaluetext;
private string parametertext;
private int thinglink;
//mxd. GLOOME rendering settings
private Thing.SpriteRenderMode rendermode;
@ -137,7 +138,8 @@ namespace CodeImp.DoomBuilder.Config
public string AngleText { get { return angletext; } }
public string FlagsValueText { get { return flagsvaluetext; } }
public string ParameterText { get { return parametertext; } }
#endregion
public int ThingLink { get { return thinglink; } }
#endregion
#region ================== Constructor / Disposer
@ -180,9 +182,10 @@ namespace CodeImp.DoomBuilder.Config
this.angletext = "Angle";
this.flagsvaluetext = "Flags value";
this.parametertext = "Parameter";
// We have no destructor
GC.SuppressFinalize(this);
this.thinglink = 0;
// We have no destructor
GC.SuppressFinalize(this);
}
// Constructor
@ -227,6 +230,7 @@ namespace CodeImp.DoomBuilder.Config
this.angletext = cfg.ReadSetting("thingtypes." + cat.Name + "." + key + ".angletext", cat.AngleText);
this.flagsvaluetext = cfg.ReadSetting("thingtypes." + cat.Name + "." + key + ".flagsvaluetext", cat.FlagsValueText);
this.parametertext = cfg.ReadSetting("thingtypes." + cat.Name + "." + key + ".parametertext", cat.ParameterText);
this.thinglink = cfg.ReadSetting("thingtypes." + cat.Name + "." + key + ".thinglink", 0);
// Read the args
for (int i = 0; i < Linedef.NUM_ARGS; i++)

View file

@ -12,7 +12,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
private class SpecialThings
{
public readonly Dictionary<int, List<Thing>> PatrolPoints; // PatrolPoint tag, list of PatrolPoints
public readonly List<Thing> PatrolSpecials;
public readonly Dictionary<int, List<PathNode>> InterpolationPoints; // InterpolationPoint tag, list of InterpolationPoints
public readonly List<Thing> InterpolationSpecials;
public readonly List<Thing> ThingsWithGoal;
public readonly List<Thing> Cameras;
public readonly Dictionary<int, List<Thing>> ActorMovers; // ActorMover target tag, list of ActorMovers
@ -23,7 +25,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
public SpecialThings()
{
PatrolPoints = new Dictionary<int, List<Thing>>();
PatrolSpecials = new List<Thing>();
InterpolationPoints = new Dictionary<int, List<PathNode>>();
InterpolationSpecials = new List<Thing>();
ThingsWithGoal = new List<Thing>();
Cameras = new List<Thing>();
ActorMovers = new Dictionary<int, List<Thing>>();
@ -97,6 +101,10 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
}
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);
@ -133,6 +141,10 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
result.InterpolationPoints[t.Tag].Add(new PathNode(t, blockmap, bsp, useblockmap));
break;
case "interpolationspecial":
result.InterpolationSpecials.Add(t);
break;
case "movingcamera":
if(t.Args[0] != 0 || t.Args[1] != 0) result.Cameras.Add(t);
break;
@ -208,6 +220,23 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
}
}
// 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)
{
@ -321,6 +350,24 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
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)

View file

@ -57,6 +57,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Highlighted item
private Thing highlighted;
private readonly Association[] association = new Association[Thing.NUM_ARGS];
private readonly Association directasso = new Association();
private readonly Association highlightasso = new Association();
// Interface
@ -90,6 +91,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
{
//mxd. Associations now requre initializing...
for(int i = 0; i < association.Length; i++) association[i] = new Association();
directasso = new Association();
}
//mxd
@ -253,6 +255,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
renderer.RenderThingSet(General.Map.ThingsFilter.VisibleThings, alpha);
renderer.RenderNiGHTSPath();
for (int i = 0; i < Thing.NUM_ARGS; i++) BuilderPlug.RenderAssociations(renderer, association[i], eventlines);
BuilderPlug.RenderAssociations(renderer, directasso, eventlines);
if((highlighted != null) && !highlighted.IsDisposed)
{
@ -353,8 +356,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd. Update label color?
if(labels.ContainsKey(t)) labels[t].Color = General.Colors.Selection;
//check if this thing directly links to another type of thing
ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(t.Type);
int linktype = 0;
if (ti != null)
linktype = ti.ThingLink;
// New association highlights something?
if(t.Tag != 0) highlightasso.Set(t.Position, t.Tag, UniversalType.ThingTag);
if(t.Tag != 0) highlightasso.Set(t.Position, t.Tag, UniversalType.ThingTag, linktype);
}
else
{
@ -382,6 +391,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
LinedefActionInfo action = General.Map.Config.LinedefActions[t.Action];
for(int i = 0; i < Thing.NUM_ARGS; i++)
association[i].Set(t.Position, t.Args[i], action.Args[i].Type);
//Some things, such as Patrol and Interpolation specials, are associated via a shared tag rather than an argument
ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(t.Type);
if (ti != null && ti.ThingLink < 0)
directasso.Set(t.Position, t.Tag, (int)UniversalType.ThingTag);
}
//mxd. Check if we can use thing arguments
else if(t.Action == 0)
@ -398,7 +412,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
// mxd. Clear associations?
if(clearassociations)
for(int i = 0; i < Thing.NUM_ARGS; i++) association[i].Set(new Vector2D(), 0, 0);
{
for (int i = 0; i < Thing.NUM_ARGS; i++)
association[i].Set(new Vector2D(), 0, 0);
directasso.Set(new Vector2D(), 0, 0);
}
// Set new highlight and redraw display
highlighted = t;

View file

@ -29,10 +29,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
private HashSet<int> tags;
private Vector2D center;
private UniversalType type;
private int directlinktype;
public HashSet<int> Tags { get { return tags; } }
public Vector2D Center { get { return center; } }
public UniversalType Type { get { return type; } }
public int DirectLinkType { get { return directlinktype; } }
//mxd. This sets up the association
public Association()
@ -74,34 +76,51 @@ namespace CodeImp.DoomBuilder.BuilderModes
// This sets up the association
public void Set(Vector2D center, int tag, int type)
{
this.Set(center, tag, type, 0);
}
public void Set(Vector2D center, int tag, int type, int directlinktype)
{
this.tags = new HashSet<int> { tag }; //mxd
this.type = (UniversalType)type;
this.center = center;
this.directlinktype = directlinktype;
}
// This sets up the association
public void Set(Vector2D center, int tag, UniversalType type)
{
this.Set(center, tag, type, 0);
}
public void Set(Vector2D center, int tag, UniversalType type, int directlinktype)
{
this.tags = new HashSet<int> { tag }; //mxd
this.type = type;
this.center = center;
this.directlinktype = directlinktype;
}
//mxd. This also sets up the association
public void Set(Vector2D center, IEnumerable<int> tags, int type)
{
this.tags = new HashSet<int>(tags); //mxd
this.type = (UniversalType)type;
this.center = center;
this.Set(center, tags, (UniversalType)type, 0);
}
//mxd. This also sets up the association
public void Set(Vector2D center, IEnumerable<int> tags, UniversalType type)
{
this.Set(center, tags, type, 0);
}
//mxd. This also sets up the association
public void Set(Vector2D center, IEnumerable<int> tags, UniversalType type, int directlinktype)
{
this.tags = new HashSet<int>(tags); //mxd
this.type = type;
this.center = center;
this.directlinktype = directlinktype;
}
// This compares an association

View file

@ -746,6 +746,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
foreach(Thing t in General.Map.Map.Things)
{
if(!asso.Tags.Contains(t.Tag)) continue;
//Do not draw the association if the user is hovering over a child link
ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(t.Type);
if (ti != null && ti.ThingLink < 0)
continue;
renderer.RenderThing(t, General.Colors.Indication, General.Settings.ActiveThingsAlpha);
if(General.Settings.GZShowEventLines) eventlines.Add(new Line3D(asso.Center, t.Position)); //mxd
}
@ -813,9 +819,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Things
foreach(Thing t in General.Map.Map.Things)
{
// Get the thing type info
ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(t.Type);
// Known action on this thing?
if((t.Action > 0) && General.Map.Config.LinedefActions.ContainsKey(t.Action))
{
//Do not draw the association if this is a child link.
// This prevents a reverse link to a thing via an argument, when it should be a direct tag-to-tag link instead.
if(ti != null && asso.DirectLinkType < 0 && asso.DirectLinkType != -t.Type)
continue;
LinedefActionInfo action = General.Map.Config.LinedefActions[t.Action];
if( ((action.Args[0].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[0]))) ||
((action.Args[1].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[1]))) ||
@ -826,12 +840,20 @@ namespace CodeImp.DoomBuilder.BuilderModes
renderer.RenderThing(t, General.Colors.Indication, General.Settings.ActiveThingsAlpha);
if(General.Settings.GZShowEventLines) eventlines.Add(new Line3D(t.Position, asso.Center)); //mxd
}
//If there is a link setup on this thing, and it matches the association, then draw a direct link to any matching tag
if(ti != null && asso.DirectLinkType == t.Type && asso.Tags.Contains(t.Tag))
{
renderer.RenderThing(t, General.Colors.Indication, General.Settings.ActiveThingsAlpha);
if (General.Settings.GZShowEventLines) eventlines.Add(new Line3D(t.Position, asso.Center));
}
}
//mxd. Thing action on this thing?
else if(t.Action == 0)
{
ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(t.Type);
if(ti != null)
//Draw the association, unless it is a child link.
// This prevents a reverse link to a thing via an argument, when it should be a direct tag-to-tag link instead.
if(ti != null && asso.DirectLinkType >= 0 && Math.Abs(asso.DirectLinkType) != t.Type)
{
if( ((ti.Args[0].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[0]))) ||
((ti.Args[1].Type == (int)asso.Type) && (asso.Tags.Contains(t.Args[1]))) ||