Fixed, Visual mode: horizontal sprite offset was applied incorrectly.

DECORATE: added "$obsolete" special comment. When present, it marks the thing as obsolete. It will be detected by "Check obsolete thing" Map Analysis Mode check and will be marked in the Thing Properties Window and the Thing Info panel.
Map Analysis mode: added "Check obsolete things" check.
Updated documentation ("DECORATE keys" page).
Updated ZDoom_DECORATE.cfg.
This commit is contained in:
MaxED 2015-10-15 15:16:31 +00:00
parent 77d2a15f7f
commit 7febb2434f
12 changed files with 1082 additions and 861 deletions

View file

@ -132,18 +132,18 @@ keywords
A_Jump = "A_Jump(int chance, int offset OR str state, ...)";
A_JumpIf = "A_JumpIf(expression, int offset OR str state)";
A_JumpIfArmorType = "A_JumpIfArmorType(str armortype, str state[, int minimum])";
A_JumpIfCloser = "A_JumpIfCloser(int distance, int offset OR str state)";
A_JumpIfCloser = "A_JumpIfCloser(int distance, int offset OR str state[, bool noz = false])";
A_JumpIfHealthLower = "A_JumpIfHealthLower(int health, int offset OR str state[, int pointer = AAPTR_DEFAULT])";
A_JumpIfHigherOrLower = "A_JumpIfHigherOrLower(str high, str low[, float offsethigh = 0.0[, float offsetlow = 0.0[, bool includeHeight = true[, int pointer = AAPTR_TARGET]]]])";
A_JumpIfInventory = "A_JumpIfInventory(str inventorytype, int amount, int offset OR str state[, int owner = AAPTR_DEFAULT])";
A_JumpIfInTargetInventory = "A_JumpIfInTargetInventory(str item, int count, int offset OR str state[, int forward])";
A_JumpIfInTargetLOS = "A_JumpIfInTargetLOS(int offset OR str state[, float fov = 0.0[, int flags = 0[, float dist_max = 0.0[, float dist_close = 0.0]]]])\nflags: JLOSF flags.";
A_JumpIfMasterCloser = "A_JumpIfMasterCloser(int distance, int offset OR str state)";
A_JumpIfMasterCloser = "A_JumpIfMasterCloser(int distance, int offset OR str state[, bool noz = false])";
A_JumpIfNoAmmo = "A_JumpIfNoAmmo(int offset OR str state)";
A_JumpIfTargetInLOS = "A_JumpIfTargetInLOS(int offset OR str state[, float fov = 0.0[, int flags = 0[, float dist_max = 0.0[, float dist_close = 0.0]]]])\nflags: JLOSF flags.";
A_JumpIfTargetInsideMeleeRange = "A_JumpIfTargetInsideMeleeRange(int offset OR str state)\nJumps the number of frames (offset) forward, or to the specified state\nwhen the target of the calling actor is within melee range of the caller.";
A_JumpIfTargetOutsideMeleeRange = "A_JumpIfTargetOutsideMeleeRange(int offset OR str state)\nJumps the number of frames (offset) forward, or to the specified state\nwhen the target of the calling actor is beyond melee range of the caller.";
A_JumpIfTracerCloser = "A_JumpIfTracerCloser(int distance, int offset OR str state)";
A_JumpIfTracerCloser = "A_JumpIfTracerCloser(int distance, int offset OR str state[, bool noz = false])";
//Status changes
A_ActiveAndUnblock = "A_ActiveAndUnblock";
A_CallSpecial = "A_CallSpecial(int special[, int arg1[, int arg2[, int arg3[, int arg4[, int arg5]]]]])";
@ -177,11 +177,15 @@ keywords
A_SetHealth = "A_SetHealth(int health[, int pointer = AAPTR_DEFAULT])\nhealth: The health value to set for the actor. Valid values are 1 and above.\npointer: The actor to set its health. Default is AAPTR_DEFAULT, which corresponds to the calling actor.";
A_SetInvulnerable = "A_SetInvulnerable";
A_SetMass = "A_SetMass(int mass)";
A_SetPainThreshold = "A_SetPainThreshold(int threshold[, int ptr])";
A_SetPitch = "A_SetPitch(float pitch[, int flags = 0[, int pointer = AAPTR_DEFAULT]])\npitch: The actor's new pitch, in degrees.\nflags: SPF flags.";
A_SetReflective = "A_SetReflective";
A_SetReflectiveInvulnerable = "A_SetReflectiveInvulnerable";
A_SetScale = "A_SetScale(float scaleX[, float scaleY = scaleX[, int pointer = AAPTR_DEFAULT]])";
A_SetRipperLevel = "A_SetRipperLevel(int level)";
A_SetRipMin = "A_SetRipMin(int min)";
A_SetRipMax = "A_SetRipMax(int max)";
A_SetRoll = "A_SetRoll(float pitch[, int flags = 0[, int pointer = AAPTR_DEFAULT]])";
A_SetScale = "A_SetScale(float scaleX[, float scaleY = scaleX[, int pointer = AAPTR_DEFAULT]])";
A_SetShadow = "A_SetShadow";
A_SetShootable = "A_SetShootable";
A_SetSolid = "A_SetSolid";
@ -864,6 +868,7 @@ constants
MBFBOUNCER;
USEBOUNCESTATE;
//Miscellaneous
ICESHATTER;
DROPPED;
ISMONSTER;
CORPSE;

View file

@ -54,7 +54,7 @@ pre
{
background: #f4f4f4;
color: #515151;
width: 600px;
width: 95%;
margin: 10px 0px 10px 20px;
font: 100% Courier New,Courier,sans-serif;
text-align: left;

View file

@ -17,8 +17,8 @@
<div id="contents">
<p> Doom Builder 2 includes a DECORATE parser used to obtain relevant information (such as editor number, Radius, Height, Scale, and so on) from custom actors. Additional information can be conveyed with keys in the form of special comments inserted within an actor's declaration block:<br />
<br />
<strong>//$Angled</strong><br />
<strong>//$NotAngled</strong><br />
<strong>//$Angled</strong> - <span class="red">GZDB only</span>.<br />
<strong>//$NotAngled</strong> - <span class="red">GZDB only</span>.<br />
Specifies whether the direction matters (angled) or not. Things that are not angled are represented without a direction arrow.<br />
<br />
<strong>//$Category &lt;category&gt;</strong><br />
@ -71,8 +71,11 @@
<li>18 - <span style="color:#BDB76B">&#9608;</span> Light Brown (default);</li>
<li>19 - <span style="color:#DAA520">&#9608;</span> Orange;</li>
</ul>
Additionaly, you can use the following special comments in the global block:<br />
<br />
<strong>//$Obsolete &lt;reason&gt;</strong> - <span class="red">GZDB only</span>.<br />
Marks the thing as obsolete. It will be detected by &quot;Check obsolete things&quot; <a href="e_mapanalysis.html">Map Analysis Mode</a> check and will be marked in the <a href="w_thingedit.html">Thing Properties Window</a> and the Thing Info panel.<br />
<br /><br />
<h3>Additionaly, you can use the following special comments in the global block:</h3><br />
<strong>//$GZDB_SKIP</strong> - <span class="red">GZDB only</span>.<br />
DECORATE parser will stop parsing a file after encountering this comment. This can be used to speedup the parsing process by skipping files, which don't contain placeable actor definitions.<br />
<br />
@ -87,6 +90,7 @@ Actor ChexShield : ResistanceRune replaces ResistanceRune 5104
//$Title "Chex Shield"
//$Color 12
//$NotAngled
//$Obsolete "That's a strange powerup. Consider replacing it with something else..."
//$Arg0 "Respawn Delay"
//$Arg0ToolTip "Positive values specify delay in tics.\nNegative - in seconds."

View file

@ -72,6 +72,8 @@ namespace CodeImp.DoomBuilder.Config
private bool xybillboard; //mxd
private SizeF spritescale;
private readonly bool locksprite; //mxd
private bool obsolete; //mxd
private string obsoletemessage; //mxd
//mxd. GLOOME rendering settings
private Thing.SpriteRenderMode rendermode;
@ -104,6 +106,8 @@ namespace CodeImp.DoomBuilder.Config
public ArgumentInfo[] Args { get { return args; } }
public bool IsKnown { get { return isknown; } }
public bool IsNull { get { return (index == 0); } }
public bool IsObsolete { get { return obsolete; } } //mxd
public string ObsoleteMessage { get { return obsoletemessage; } } //mxd
public bool AbsoluteZ { get { return absolutez; } }
public bool XYBillboard { get { return xybillboard; } } //mxd
public SizeF SpriteScale { get { return spritescale; } }
@ -391,7 +395,7 @@ namespace CodeImp.DoomBuilder.Config
// Set the title
if(actor.HasPropertyWithValue("$title"))
title = actor.GetPropertyAllValues("$title");
else if (actor.HasPropertyWithValue("tag"))
else if(actor.HasPropertyWithValue("tag"))
{
string tag = actor.GetPropertyAllValues("tag");
if(!tag.StartsWith("\"$")) title = tag; //mxd. Don't use LANGUAGE keywords.
@ -400,7 +404,7 @@ namespace CodeImp.DoomBuilder.Config
if(string.IsNullOrEmpty(title)) title = actor.ClassName;
//mxd. Color override?
if (actor.HasPropertyWithValue("$color"))
if(actor.HasPropertyWithValue("$color"))
{
int ci = actor.GetPropertyValueInt("$color", 0);
color = (ci == 0 || ci > 19 ? 18 : ci) ;
@ -422,6 +426,14 @@ namespace CodeImp.DoomBuilder.Config
if(actor.HasProperty("$angled")) this.arrow = true;
else if(actor.HasProperty("$notangled")) this.arrow = false;
//mxd. Marked as obsolete?
if(actor.HasPropertyWithValue("$obsolete"))
{
obsoletemessage = ZDTextParser.StripQuotes(actor.GetPropertyValueString("$obsolete", 0));
obsolete = true;
color = 4; //red
}
// Remove doublequotes from title
title = ZDTextParser.StripQuotes(title); //mxd

View file

@ -161,6 +161,7 @@ namespace CodeImp.DoomBuilder.Controls
this.thingimages.Images.SetKeyName(37, "category17.png");
this.thingimages.Images.SetKeyName(38, "category18.png");
this.thingimages.Images.SetKeyName(39, "category19.png");
this.thingimages.Images.SetKeyName(40, "Warning.png");
//
// infopanel
//
@ -286,6 +287,7 @@ namespace CodeImp.DoomBuilder.Controls
this.typelist.SelectedImageIndex = 0;
this.typelist.SelectionBackColor = System.Drawing.SystemColors.Highlight;
this.typelist.SelectionMode = CodeImp.DoomBuilder.GZBuilder.Controls.TreeViewSelectionMode.SingleSelect;
this.typelist.ShowNodeToolTips = true;
this.typelist.Size = new System.Drawing.Size(304, 203);
this.typelist.TabIndex = 22;
this.typelist.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.typelist_MouseDoubleClick);

View file

@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Data;
@ -29,6 +30,12 @@ namespace CodeImp.DoomBuilder.Controls
{
public partial class ThingBrowserControl : UserControl
{
#region ================== Constants
private const int WARNING_ICON_INDEX = 40; //mxd
#endregion
#region ================== Events
public delegate void TypeChangedDeletegate(ThingTypeInfo value);
@ -77,31 +84,64 @@ namespace CodeImp.DoomBuilder.Controls
doupdatetextbox = true;
}
//mxd. This recursively creates thing category tree nodes
private void AddThingCategories(ICollection<ThingCategory> categories, TreeNodeCollection collection)
//mxd. This recursively creates thing category tree nodes. Returns true when a thing in this category is obsolete
private bool AddThingCategories(ICollection<ThingCategory> categories, TreeNodeCollection collection)
{
bool containsobsoletethings = false;
foreach(ThingCategory tc in categories)
{
// Create category
TreeNode cn = collection.Add(tc.Name, tc.Title);
cn.ImageIndex = thingimages.Images.Count / 2; // Offset to folder icons
if((tc.Color >= 0) && (tc.Color < thingimages.Images.Count)) cn.ImageIndex += tc.Color;
cn.SelectedImageIndex = cn.ImageIndex;
// Create subcategories
AddThingCategories(tc.Children, cn.Nodes);
bool isobsolete = AddThingCategories(tc.Children, cn.Nodes);
// Create things
foreach(ThingTypeInfo ti in tc.Things)
{
// Create thing
TreeNode n = cn.Nodes.Add(ti.Title);
n.Tag = ti;
if(ti.IsObsolete)
{
n.Text += " - OBSOLETE";
n.BackColor = Color.MistyRose;
n.ToolTipText = ti.ObsoleteMessage;
// Set warning icon
n.ImageIndex = WARNING_ICON_INDEX;
n.SelectedImageIndex = WARNING_ICON_INDEX;
isobsolete = true;
}
else
{
// Set regular icon
if((ti.Color >= 0) && (ti.Color < thingimages.Images.Count)) n.ImageIndex = ti.Color;
n.SelectedImageIndex = n.ImageIndex;
n.Tag = ti;
}
nodes.Add(n);
}
// Set category icon
containsobsoletethings |= isobsolete;
if(isobsolete)
{
cn.BackColor = Color.MistyRose;
cn.ImageIndex = WARNING_ICON_INDEX;
cn.SelectedImageIndex = WARNING_ICON_INDEX;
}
else
{
cn.ImageIndex = thingimages.Images.Count / 2; // Offset to folder icons
if((tc.Color >= 0) && (tc.Color < thingimages.Images.Count)) cn.ImageIndex += tc.Color;
cn.SelectedImageIndex = cn.ImageIndex;
}
}
return containsobsoletethings;
}
#endregion

File diff suppressed because it is too large Load diff

View file

@ -103,6 +103,7 @@ namespace CodeImp.DoomBuilder.Controls
// Thing info
infopanel.Text = " Thing " + t.Index + " ";
type.Text = t.Type + " - " + ti.Title;
if(ti.IsObsolete) type.Text += " - OBSOLETE"; //mxd
action.Text = actioninfo;
bool displayclassname = !string.IsNullOrEmpty(ti.ClassName) && !ti.ClassName.StartsWith("$"); //mxd
labelclass.Enabled = displayclassname; //mxd

View file

@ -247,6 +247,7 @@
<Compile Include="ErrorChecks\CheckMapSize.cs" />
<Compile Include="ErrorChecks\CheckMissingFlats.cs" />
<Compile Include="ErrorChecks\CheckMissingTextures.cs" />
<Compile Include="ErrorChecks\CheckObsoleteThings.cs" />
<Compile Include="ErrorChecks\CheckOverlappingVertices.cs" />
<Compile Include="ErrorChecks\CheckShortLinedefs.cs" />
<Compile Include="ErrorChecks\CheckStrayVertices.cs" />
@ -259,6 +260,7 @@
<Compile Include="ErrorChecks\ResultMapTooBig.cs" />
<Compile Include="ErrorChecks\ResultMissingFlat.cs" />
<Compile Include="ErrorChecks\ResultNoErrors.cs" />
<Compile Include="ErrorChecks\ResultObsoleteThing.cs" />
<Compile Include="ErrorChecks\ResultSectorInvalid.cs" />
<Compile Include="ErrorChecks\ResultShortLinedef.cs" />
<Compile Include="ErrorChecks\ResultStrayVertex.cs" />

View file

@ -0,0 +1,61 @@
#region ================== Namespaces
using System.Threading;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Map;
#endregion
namespace CodeImp.DoomBuilder.BuilderModes
{
[ErrorChecker("Check obsolete things", true, 50)]
public class CheckObsoleteThings : ErrorChecker
{
#region ================== Constants
private const int PROGRESS_STEP = 10;
#endregion
#region ================== Constructor / Destructor
public CheckObsoleteThings()
{
// Total progress is done when all things are checked
SetTotalProgress(General.Map.Map.Things.Count / PROGRESS_STEP);
}
#endregion
#region ================== Methods
// This runs the check
public override void Run()
{
int progress = 0;
int stepprogress = 0;
// Go for all things
foreach(Thing t in General.Map.Map.Things)
{
ThingTypeInfo info = General.Map.Data.GetThingInfoEx(t.Type);
if(info != null && info.IsObsolete)
{
SubmitResult(new ResultObsoleteThing(t, info.ObsoleteMessage));
}
// 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
}
}

View file

@ -0,0 +1,78 @@
#region ================== Namespaces
using System;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Rendering;
#endregion
namespace CodeImp.DoomBuilder.BuilderModes
{
public class ResultObsoleteThing : ErrorResult
{
#region ================== Variables
private readonly Thing thing;
#endregion
#region ================== Properties
public override int Buttons { get { return 1; } }
public override string Button1Text { get { return "Delete Thing"; } }
#endregion
#region ================== Constructor / Destructor
public ResultObsoleteThing(Thing t, string message)
{
// Initialize
this.thing = t;
this.viewobjects.Add(t);
this.hidden = t.IgnoredErrorChecks.Contains(this.GetType());
if(string.IsNullOrEmpty(message))
this.description = "This thing is marked as obsolete in DECORATE. You should probably replace or delete it.";
else
this.description = "This thing is marked as obsolete in DECORATE: " + message;
}
#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) thing.IgnoredErrorChecks.Add(t);
else 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 "Thing " + thing.Index + " (" + General.Map.Data.GetThingInfo(thing.Type).Title + ") at " + thing.Position.x + ", " + thing.Position.y + " is obsolete.";
}
// Rendering
public override void RenderOverlaySelection(IRenderer2D renderer)
{
renderer.RenderThing(thing, General.Colors.Selection, Presentation.THINGS_ALPHA);
}
// This removes the thing
public override bool Button1Click(bool batchMode)
{
if(!batchMode) General.Map.UndoRedo.CreateUndo("Delete thing");
thing.Dispose();
General.Map.IsChanged = true;
General.Map.ThingsFilter.Update();
return true;
}
#endregion
}
}

View file

@ -293,7 +293,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
float height = sprite.ScaledHeight;
if(sprite is SpriteImage)
{
offsetx = (sprite as SpriteImage).OffsetX - radius;
offsetx = radius - (sprite as SpriteImage).OffsetX;
offsety = (sprite as SpriteImage).OffsetY - height;
}