mirror of
https://git.do.srb2.org/STJr/ZoneBuilder.git
synced 2024-11-12 23:54:10 +00:00
Added, Map Analysis mode: added "Check Polyobjects" checker.
Changed, Game configurations: "Polyobject Anchor" things should not trigger "Thing outside the map geometry" error in the Map Analysis mode. Updated ZDoom_DECORATE.cfg (A_SetScale).
This commit is contained in:
parent
41e4b26d79
commit
16e476f02e
7 changed files with 356 additions and 1 deletions
|
@ -1518,6 +1518,7 @@ other
|
||||||
title = "Polyobject Anchor";
|
title = "Polyobject Anchor";
|
||||||
sprite = "internal:anchor";
|
sprite = "internal:anchor";
|
||||||
fixedrotation = true;
|
fixedrotation = true;
|
||||||
|
error = 0; // Can be outside of map geometry
|
||||||
}
|
}
|
||||||
3001
|
3001
|
||||||
{
|
{
|
||||||
|
|
|
@ -1091,6 +1091,7 @@ zdoom
|
||||||
sprite = "internal:anchor";
|
sprite = "internal:anchor";
|
||||||
class = "$PolyAnchor";
|
class = "$PolyAnchor";
|
||||||
fixedrotation = true;
|
fixedrotation = true;
|
||||||
|
error = 0; // Can be outside of map geometry
|
||||||
}
|
}
|
||||||
|
|
||||||
9301
|
9301
|
||||||
|
|
|
@ -238,7 +238,7 @@ keywords
|
||||||
A_SetRipMin = "A_SetRipMin(int min)";
|
A_SetRipMin = "A_SetRipMin(int min)";
|
||||||
A_SetRipMax = "A_SetRipMax(int max)";
|
A_SetRipMax = "A_SetRipMax(int max)";
|
||||||
A_SetRoll = "A_SetRoll(float roll[, int flags = 0[, int pointer = AAPTR_DEFAULT]])";
|
A_SetRoll = "A_SetRoll(float roll[, int flags = 0[, int pointer = AAPTR_DEFAULT]])";
|
||||||
A_SetScale = "A_SetScale(float scaleX[, float scaleY = scaleX[, int pointer = AAPTR_DEFAULT]])";
|
A_SetScale = "A_SetScale(float scaleX[, float scaleY = scaleX[, int pointer = AAPTR_DEFAULT[, bool usezero = false]]])";
|
||||||
A_SetShadow = "A_SetShadow";
|
A_SetShadow = "A_SetShadow";
|
||||||
A_SetShootable = "A_SetShootable";
|
A_SetShootable = "A_SetShootable";
|
||||||
A_SetSolid = "A_SetSolid";
|
A_SetSolid = "A_SetSolid";
|
||||||
|
|
|
@ -347,6 +347,7 @@
|
||||||
<Compile Include="ErrorChecks\CheckMissingTextures.cs" />
|
<Compile Include="ErrorChecks\CheckMissingTextures.cs" />
|
||||||
<Compile Include="ErrorChecks\CheckObsoleteThings.cs" />
|
<Compile Include="ErrorChecks\CheckObsoleteThings.cs" />
|
||||||
<Compile Include="ErrorChecks\CheckOverlappingVertices.cs" />
|
<Compile Include="ErrorChecks\CheckOverlappingVertices.cs" />
|
||||||
|
<Compile Include="ErrorChecks\CheckPolyobjects.cs" />
|
||||||
<Compile Include="ErrorChecks\CheckShortLinedefs.cs" />
|
<Compile Include="ErrorChecks\CheckShortLinedefs.cs" />
|
||||||
<Compile Include="ErrorChecks\CheckStrayVertices.cs" />
|
<Compile Include="ErrorChecks\CheckStrayVertices.cs" />
|
||||||
<Compile Include="ErrorChecks\CheckTextureAlignment.cs" />
|
<Compile Include="ErrorChecks\CheckTextureAlignment.cs" />
|
||||||
|
@ -355,6 +356,8 @@
|
||||||
<Compile Include="ErrorChecks\CheckUnknownThings.cs" />
|
<Compile Include="ErrorChecks\CheckUnknownThings.cs" />
|
||||||
<Compile Include="ErrorChecks\CheckUnusedTextures.cs" />
|
<Compile Include="ErrorChecks\CheckUnusedTextures.cs" />
|
||||||
<Compile Include="ErrorChecks\CheckUnusedThings.cs" />
|
<Compile Include="ErrorChecks\CheckUnusedThings.cs" />
|
||||||
|
<Compile Include="ErrorChecks\ResultInvalidPolyobjectLines.cs" />
|
||||||
|
<Compile Include="ErrorChecks\ResultInvalidPolyobjectThings.cs" />
|
||||||
<Compile Include="ErrorChecks\ResultMapTooBig.cs" />
|
<Compile Include="ErrorChecks\ResultMapTooBig.cs" />
|
||||||
<Compile Include="ErrorChecks\ResultMissingFlat.cs" />
|
<Compile Include="ErrorChecks\ResultMissingFlat.cs" />
|
||||||
<Compile Include="ErrorChecks\ResultNoErrors.cs" />
|
<Compile Include="ErrorChecks\ResultNoErrors.cs" />
|
||||||
|
|
167
Source/Plugins/BuilderModes/ErrorChecks/CheckPolyobjects.cs
Normal file
167
Source/Plugins/BuilderModes/ErrorChecks/CheckPolyobjects.cs
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
#region ================== Namespaces
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using CodeImp.DoomBuilder.Config;
|
||||||
|
using CodeImp.DoomBuilder.Map;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
|
{
|
||||||
|
[ErrorChecker("Check Polyobjects", true, 100)]
|
||||||
|
public class CheckPolyobjects : ErrorChecker
|
||||||
|
{
|
||||||
|
#region ================== Constants
|
||||||
|
|
||||||
|
private const int PROGRESS_STEP = 1000;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ================== Constructor / Destructor
|
||||||
|
|
||||||
|
public CheckPolyobjects()
|
||||||
|
{
|
||||||
|
// Total progress is somewhat done when all linedefs and things are checked
|
||||||
|
SetTotalProgress((General.Map.Map.Linedefs.Count + General.Map.Map.Things.Count) / PROGRESS_STEP);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ================== Methods
|
||||||
|
|
||||||
|
// This runs the check
|
||||||
|
public override void Run()
|
||||||
|
{
|
||||||
|
int progress = 0;
|
||||||
|
int stepprogress = 0;
|
||||||
|
const string Polyobj_StartLine = "Polyobj_StartLine";
|
||||||
|
|
||||||
|
// <Polyobj_Action, <Polyobj_number, Lines using this number>>
|
||||||
|
Dictionary<string, Dictionary<int, List<Linedef>>> polyobjlines = new Dictionary<string, Dictionary<int, List<Linedef>>>();
|
||||||
|
|
||||||
|
// All polyobject-related actions
|
||||||
|
HashSet<string> allactions = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
Polyobj_StartLine, "Polyobj_RotateLeft",
|
||||||
|
"Polyobj_RotateRight", "Polyobj_Move",
|
||||||
|
"Polyobj_MoveTimes8", "Polyobj_DoorSwing",
|
||||||
|
"Polyobj_DoorSlide", "Polyobj_OR_MoveToSpot",
|
||||||
|
"Polyobj_MoveToSpot", "Polyobj_Stop",
|
||||||
|
"Polyobj_MoveTo", "Polyobj_OR_MoveTo",
|
||||||
|
"Polyobj_OR_RotateLeft", "Polyobj_OR_RotateRight",
|
||||||
|
"Polyobj_OR_Move", "Polyobj_OR_MoveTimes8"
|
||||||
|
};
|
||||||
|
|
||||||
|
Dictionary<int, List<Thing>> anchors = new Dictionary<int, List<Thing>>();
|
||||||
|
Dictionary<int, List<Thing>> startspots = new Dictionary<int, List<Thing>>();
|
||||||
|
|
||||||
|
// Collect Linedefs...
|
||||||
|
foreach(Linedef l in General.Map.Map.Linedefs)
|
||||||
|
{
|
||||||
|
if(l.Action > 0 && General.Map.Config.LinedefActions.ContainsKey(l.Action) && allactions.Contains(General.Map.Config.LinedefActions[l.Action].Id))
|
||||||
|
{
|
||||||
|
string id = General.Map.Config.LinedefActions[l.Action].Id;
|
||||||
|
|
||||||
|
if(!polyobjlines.ContainsKey(id))
|
||||||
|
polyobjlines.Add(id, new Dictionary<int, List<Linedef>>());
|
||||||
|
|
||||||
|
// Polyobj number is always the first arg
|
||||||
|
if(!polyobjlines[id].ContainsKey(l.Args[0]))
|
||||||
|
polyobjlines[id].Add(l.Args[0], new List<Linedef>());
|
||||||
|
|
||||||
|
polyobjlines[id][l.Args[0]].Add(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateProgress(ref progress, ref stepprogress);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect Things...
|
||||||
|
foreach(Thing t in General.Map.Map.Things)
|
||||||
|
{
|
||||||
|
ThingTypeInfo info = General.Map.Data.GetThingInfoEx(t.Type);
|
||||||
|
if(info == null) continue;
|
||||||
|
switch(info.ClassName.ToLowerInvariant())
|
||||||
|
{
|
||||||
|
case "$polyanchor":
|
||||||
|
if(!anchors.ContainsKey(t.AngleDoom)) anchors.Add(t.AngleDoom, new List<Thing>());
|
||||||
|
anchors[t.AngleDoom].Add(t);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "$polyspawn":
|
||||||
|
case "$polyspawncrush":
|
||||||
|
case "$polyspawnhurt":
|
||||||
|
if(!startspots.ContainsKey(t.AngleDoom)) startspots.Add(t.AngleDoom, new List<Thing>());
|
||||||
|
startspots[t.AngleDoom].Add(t);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateProgress(ref progress, ref stepprogress);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check Linedefs. These can connect 1 - multiple (except Polyobj_StartLine)
|
||||||
|
// Polyobject number is always arg0.
|
||||||
|
foreach(KeyValuePair<string, Dictionary<int, List<Linedef>>> group in polyobjlines)
|
||||||
|
{
|
||||||
|
foreach(KeyValuePair<int, List<Linedef>> linesbytype in group.Value)
|
||||||
|
{
|
||||||
|
if(!startspots.ContainsKey(linesbytype.Key))
|
||||||
|
SubmitResult(new ResultInvalidPolyobjectLines(linesbytype.Value, "\"" + group.Key + "\" action targets non-existing Polyobject Start Spot (" + linesbytype.Key + ")"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check Linedefs with Polyobj_StartLine action. These must connect 1 - 1.
|
||||||
|
// Polyobject number is arg0, Mirror polyobject number is arg1
|
||||||
|
foreach(KeyValuePair<int, List<Linedef>> linesbytype in polyobjlines[Polyobj_StartLine])
|
||||||
|
{
|
||||||
|
// Should be only one Polyobj_StartLine per Polyobject number
|
||||||
|
if(linesbytype.Value.Count > 1)
|
||||||
|
SubmitResult(new ResultInvalidPolyobjectLines(linesbytype.Value, "Several \"" + Polyobj_StartLine + "\" actions have the same Polyobject Number assigned (" + linesbytype.Key + "). They won't function correctly ingame."));
|
||||||
|
|
||||||
|
// Check if Mirror Polyobject Number exists
|
||||||
|
foreach(Linedef linedef in linesbytype.Value)
|
||||||
|
{
|
||||||
|
if(!startspots.ContainsKey(linedef.Args[1]))
|
||||||
|
SubmitResult(new ResultInvalidPolyobjectLines(new List<Linedef> { linedef }, "\"" + Polyobj_StartLine + "\" action have non-existing Mirror Polyobject Number assigned (" + linedef.Args[1] + "). It won't function correctly ingame."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check Polyobject Anchors. These must connect 1 - 1.
|
||||||
|
foreach(KeyValuePair<int, List<Thing>> group in anchors)
|
||||||
|
{
|
||||||
|
if(!startspots.ContainsKey(group.Key))
|
||||||
|
SubmitResult(new ResultInvalidPolyobjectThings(group.Value, "Polyobject " + (group.Value.Count > 1 ? "Anchors target" : "Anchor targets") + " non-existing Polyobject Start Spot (" + group.Key + ")"));
|
||||||
|
|
||||||
|
if(group.Value.Count > 1)
|
||||||
|
SubmitResult(new ResultInvalidPolyobjectThings(group.Value, "Several Polyobject Anchors target the same Polyobject Start Spot (" + group.Key + "). They won't function correctly ingame."));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check Polyobject Start Spots. These must connect 1 - 1.
|
||||||
|
foreach(KeyValuePair<int, List<Thing>> group in startspots)
|
||||||
|
{
|
||||||
|
if(!anchors.ContainsKey(group.Key))
|
||||||
|
SubmitResult(new ResultInvalidPolyobjectThings(group.Value, "Polyobject Start " + (group.Value.Count > 1 ? "Spots are not targeted" : "Spot " + group.Key + " is not targeted") + " by any Polyobject Anchor"));
|
||||||
|
|
||||||
|
if(group.Value.Count > 1)
|
||||||
|
SubmitResult(new ResultInvalidPolyobjectThings(group.Value, "Several Polyobject Start Spots have the same Polyobject number (" + group.Key + "). They won't function correctly ingame."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateProgress(ref int progress, ref int stepprogress)
|
||||||
|
{
|
||||||
|
// Handle thread interruption
|
||||||
|
try { Thread.Sleep(0); }
|
||||||
|
catch(ThreadInterruptedException) { return; }
|
||||||
|
|
||||||
|
// We are making progress!
|
||||||
|
if((++progress / PROGRESS_STEP) > stepprogress)
|
||||||
|
{
|
||||||
|
stepprogress = (progress / PROGRESS_STEP);
|
||||||
|
AddProgress(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
#region ================== Namespaces
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using CodeImp.DoomBuilder.Map;
|
||||||
|
using CodeImp.DoomBuilder.Rendering;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
|
{
|
||||||
|
public class ResultInvalidPolyobjectLines : ErrorResult
|
||||||
|
{
|
||||||
|
#region ================== Variables
|
||||||
|
|
||||||
|
private readonly List<Linedef> lines;
|
||||||
|
private readonly string linesinfo;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ================== Properties
|
||||||
|
|
||||||
|
public override int Buttons { get { return 0; } }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ================== Constructor / Destructor
|
||||||
|
|
||||||
|
public ResultInvalidPolyobjectLines(List<Linedef> lines, string details)
|
||||||
|
{
|
||||||
|
// Initialize
|
||||||
|
this.lines = lines;
|
||||||
|
this.hidden = true;
|
||||||
|
foreach(Linedef l in lines)
|
||||||
|
{
|
||||||
|
this.viewobjects.Add(l);
|
||||||
|
this.hidden &= l.IgnoredErrorChecks.Contains(this.GetType());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lines.Count == 1)
|
||||||
|
{
|
||||||
|
linesinfo = "Incorrect Polyobject setup for linedef " + lines[0].Index;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
linesinfo = "Incorrect Polyobject setup for linedefs " + lines[0].Index;
|
||||||
|
for(int i = 1; i < lines.Count - 1; i++) linesinfo += ", " + lines[i].Index;
|
||||||
|
linesinfo += " and " + lines[lines.Count - 1].Index;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.description = linesinfo + ": " + details;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ================== Methods
|
||||||
|
|
||||||
|
// This sets if this result is displayed in ErrorCheckForm (mxd)
|
||||||
|
internal override void Hide(bool hide)
|
||||||
|
{
|
||||||
|
hidden = hide;
|
||||||
|
Type t = this.GetType();
|
||||||
|
if(hide)
|
||||||
|
{
|
||||||
|
foreach(Linedef l in lines)
|
||||||
|
l.IgnoredErrorChecks.Add(t);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach(Linedef l in lines)
|
||||||
|
if(l.IgnoredErrorChecks.Contains(t)) l.IgnoredErrorChecks.Remove(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This must return the string that is displayed in the listbox
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return linesinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rendering
|
||||||
|
public override void PlotSelection(IRenderer2D renderer)
|
||||||
|
{
|
||||||
|
foreach(Linedef l in lines)
|
||||||
|
{
|
||||||
|
renderer.PlotLinedef(l, General.Colors.Selection);
|
||||||
|
renderer.PlotVertex(l.Start, ColorCollection.VERTICES);
|
||||||
|
renderer.PlotVertex(l.End, ColorCollection.VERTICES);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
#region ================== Namespaces
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using CodeImp.DoomBuilder.Map;
|
||||||
|
using CodeImp.DoomBuilder.Rendering;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
|
{
|
||||||
|
public class ResultInvalidPolyobjectThings : ErrorResult
|
||||||
|
{
|
||||||
|
#region ================== Variables
|
||||||
|
|
||||||
|
private readonly List<Thing> things;
|
||||||
|
private readonly string thingsinfo;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ================== Properties
|
||||||
|
|
||||||
|
public override int Buttons { get { return 0; } }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ================== Constructor / Destructor
|
||||||
|
|
||||||
|
public ResultInvalidPolyobjectThings(List<Thing> things, string details)
|
||||||
|
{
|
||||||
|
// Initialize
|
||||||
|
this.things = things;
|
||||||
|
this.hidden = true;
|
||||||
|
foreach(Thing t in things)
|
||||||
|
{
|
||||||
|
this.viewobjects.Add(t);
|
||||||
|
this.hidden &= t.IgnoredErrorChecks.Contains(this.GetType());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(things.Count == 1)
|
||||||
|
{
|
||||||
|
thingsinfo = "Incorrect Polyobject setup for thing " + things[0].Index;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
thingsinfo = "Incorrect Polyobject setup for things " + things[0].Index;
|
||||||
|
for(int i = 1; i < things.Count - 1; i++) thingsinfo += ", " + things[i].Index;
|
||||||
|
thingsinfo += " and " + things[things.Count - 1].Index;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.description = thingsinfo + ": " + details;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ================== Methods
|
||||||
|
|
||||||
|
// This sets if this result is displayed in ErrorCheckForm (mxd)
|
||||||
|
internal override void Hide(bool hide)
|
||||||
|
{
|
||||||
|
hidden = hide;
|
||||||
|
Type t = this.GetType();
|
||||||
|
if(hide)
|
||||||
|
{
|
||||||
|
foreach(Thing thing in things) thing.IgnoredErrorChecks.Add(t);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach(Thing thing in things)
|
||||||
|
if(thing.IgnoredErrorChecks.Contains(t)) thing.IgnoredErrorChecks.Remove(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This must return the string that is displayed in the listbox
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return thingsinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rendering
|
||||||
|
public override void RenderOverlaySelection(IRenderer2D renderer)
|
||||||
|
{
|
||||||
|
foreach(Thing thing in things)
|
||||||
|
renderer.RenderThing(thing, General.Colors.Selection, Presentation.THINGS_ALPHA);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue