Added: nested thing categories can now be defined in DECORATE using "//$Category" special comment. Syntax is the same as in SLADE 3.

Added: thing categories defined in Game Configurations can now be nested.
Changed, Thing Edit window: thing categories now use different icons.
Fixed: Thing Edit and Vertex edit windows had incorrect help links.
Fixed: Sound Propagation and Sound Environment modes had incorrect help links.
Documentation: updated "DECORATE keys" and "Things Settings" pages.
This commit is contained in:
MaxED 2015-06-01 21:46:28 +00:00
parent efd9ba09a7
commit 5a7b599a46
15 changed files with 1134 additions and 512 deletions

View file

@ -1,7 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Game Configuration - Things Settings</title>
<title>DECORATE keys</title>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<link rel="stylesheet" type="text/css" href="default.css" media="screen" title="Default" />
</head>
@ -23,6 +23,7 @@
<br />
<strong>//$Category &lt;category&gt;</strong><br />
Specifies in which category (Monsters, Weapons, etc.) it should be sorted. By default, a custom actor not identified in a configuration file will be put in the Decorate category.<br />
GZDoom Builder supports hierarchical subgroups, using the backslash separator. For example, <strong>//$Category "Decorations/Tech"</strong> will put the actor within the "Tech" subgroup of the "Decorations" group.<br />
<br />
<strong>//$Sprite &lt;sprite&gt;</strong><br />
Specifies which sprite to use to represent the actor in the editor. By default, a custom actor not identified in a configuration file will use the first suitable sprite it finds in the actor definition, trying first the states in the sequence Idle, See, Inactive, Spawn, and if all these fail, the first defined state. This key is therefore especially useful for stateless actor definitions. Keep in mind that this sprite name must match an image in the wad (i.e., if the sprite in your wad is named JUNKA0D0, you need to put JUNKA0D0, JUNKA0 won't work).<br />
@ -47,28 +48,28 @@
Allows to specify an enum for this argument. This can be either a name of an enum defined in the Game Configuration, or an explicit enum definition. This property can only be used in conjunction with &quot;<strong>//$ArgN</strong>&quot; property.<br />
<br />
<strong>//$Color &lt;color index&gt;</strong> - <span class="red">GZDB only</span>.<br />
Allows to override category color for this actor. Possible values:
Allows to override category color for this actor. Possible values are:
<ul>
<li>0 - Dark Gray;</li>
<li>1 - Blue;</li>
<li>2 - Green;</li>
<li>3 - Cyan;</li>
<li>4 - Red;</li>
<li>5 - Magenta;</li>
<li>6 - Brown;</li>
<li>7 - Gray;</li>
<li>8 - Light Gray;</li>
<li>9 - Light Blue;</li>
<li>10 - Light Green;</li>
<li>11 - Light Cyan;</li>
<li>12 - Light Red;</li>
<li>13 - Light Magenta;</li>
<li>14 - Yellow;</li>
<li>15 - White;</li>
<li>16 - Pink;</li>
<li>17 - Light Orange;</li>
<li>18 - Light Brown (default);</li>
<li>19 - Orange;</li>
<li>&nbsp;&nbsp;0 - <span style="color:#696969">&#9608;</span> Dark Gray;</li>
<li>&nbsp;&nbsp;1 - <span style="color:#4169E1">&#9608;</span> Blue;</li>
<li>&nbsp;&nbsp;2 - <span style="color:#228B22">&#9608;</span> Green;</li>
<li>&nbsp;&nbsp;3 - <span style="color:#20B2AA">&#9608;</span> Cyan;</li>
<li>&nbsp;&nbsp;4 - <span style="color:#B22222">&#9608;</span> Red;</li>
<li>&nbsp;&nbsp;5 - <span style="color:#9400D3">&#9608;</span> Magenta;</li>
<li>&nbsp;&nbsp;6 - <span style="color:#B8860B">&#9608;</span> Brown;</li>
<li>&nbsp;&nbsp;7 - <span style="color:#C0C0C0">&#9608;</span> Gray;</li>
<li>&nbsp;&nbsp;8 - <span style="color:#808080">&#9608;</span> Light Gray;</li>
<li>&nbsp;&nbsp;9 - <span style="color:#00BFFF">&#9608;</span> Light Blue;</li>
<li>10 - <span style="color:#32CD32">&#9608;</span> Light Green;</li>
<li>11 - <span style="color:#AFEEEE">&#9608;</span> Light Cyan;</li>
<li>12 - <span style="color:#FF6347">&#9608;</span> Light Red;</li>
<li>13 - <span style="color:#EE82EE">&#9608;</span> Light Magenta;</li>
<li>14 - <span style="color:#FFFF00">&#9608;</span> Yellow;</li>
<li>15 - <span style="color:#F5F5F5">&#9608;</span> White;</li>
<li>16 - <span style="color:#FFB6C1">&#9608;</span> Pink;</li>
<li>17 - <span style="color:#FF8C00">&#9608;</span> Light Orange;</li>
<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 />
@ -81,7 +82,7 @@
<pre>
Actor ChexShield : ResistanceRune replaces ResistanceRune 5104
{
//$Category powerups
//$Category &quot;Pickups/Chex Powerups&quot;
//$Sprite ARMXA0
//$Title "Chex Shield"
//$Color 12

View file

@ -66,6 +66,7 @@ thingrenderstyles
<br />
<span class="big">Thing Category definitions:</span><br />
These settings can be used inside of thing category definitions.<br />
<span class="blue">Info:</span> thing categories can be nested in GZDB.<br />
<br />
<b class="fat">sorted</b> (integer) [0 .. 1]<br />
When set to 1, items in this category will be sorted by title.<br />

View file

@ -475,26 +475,32 @@ namespace CodeImp.DoomBuilder.Config
if(de.Value is IDictionary)
{
// Make a category
thingcat = new ThingCategory(cfg, de.Key.ToString(), enums);
thingcat = new ThingCategory(cfg, null, de.Key.ToString(), enums);
// Add all things in category to the big list
foreach(ThingTypeInfo t in thingcat.Things)
{
if(!things.ContainsKey(t.Index))
{
things.Add(t.Index, t);
}
else
{
General.ErrorLogger.Add(ErrorType.Warning, "Thing number " + t.Index + " is defined more than once (as '" + things[t.Index].Title + "' and '" + t.Title + "') in game configuration '" + this.Name + "'");
}
}
AddThingsFromCategory(thingcat); //mxd
// Add category to list
thingcategories.Add(thingcat);
}
}
}
//mxd. This recursively adds all things from a ThingCategory and it's children
private void AddThingsFromCategory(ThingCategory thingcat)
{
// Add all things in category to the big list
foreach(ThingTypeInfo t in thingcat.Things)
{
if(!things.ContainsKey(t.Index))
things.Add(t.Index, t);
else
General.ErrorLogger.Add(ErrorType.Warning, "Thing number " + t.Index + " is defined more than once (as '" + things[t.Index].Title + "' and '" + t.Title + "') in game configuration '" + this.Name + "'");
}
// Recursively add things from child categories
foreach(ThingCategory c in thingcat.Children) AddThingsFromCategory(c);
}
// Linedef flags
private void LoadLinedefFlags()

View file

@ -41,6 +41,7 @@ namespace CodeImp.DoomBuilder.Config
private readonly string name;
private readonly string title;
private readonly bool sorted;
private List<ThingCategory> children; //mxd
// Thing properties for inheritance
private readonly string sprite;
@ -67,6 +68,7 @@ namespace CodeImp.DoomBuilder.Config
public string Title { get { return title; } }
public string Sprite { get { return sprite; } }
public bool Sorted { get { return sorted; } }
public List<ThingCategory> Children { get { return children; } } //mxd
public int Color { get { return color; } }
public int Arrow { get { return arrow; } }
public float Radius { get { return radius; } }
@ -92,6 +94,7 @@ namespace CodeImp.DoomBuilder.Config
this.name = name;
this.title = title;
this.things = new List<ThingTypeInfo>();
this.children = new List<ThingCategory>();
// Set default properties
this.sprite = "";
@ -113,36 +116,57 @@ namespace CodeImp.DoomBuilder.Config
}
// Constructor
internal ThingCategory(Configuration cfg, string name, IDictionary<string, EnumList> enums)
internal ThingCategory(Configuration cfg, ThingCategory parent, string name, IDictionary<string, EnumList> enums)
{
IDictionary dic;
int index;
// Initialize
this.name = name;
this.things = new List<ThingTypeInfo>();
this.children = new List<ThingCategory>();
// Read properties
this.title = cfg.ReadSetting("thingtypes." + name + ".title", "<category>");
this.sprite = cfg.ReadSetting("thingtypes." + name + ".sprite", "");
this.sorted = (cfg.ReadSetting("thingtypes." + name + ".sort", 0) != 0);
this.color = cfg.ReadSetting("thingtypes." + name + ".color", 0);
this.arrow = cfg.ReadSetting("thingtypes." + name + ".arrow", 0);
this.radius = cfg.ReadSetting("thingtypes." + name + ".width", 10);
this.height = cfg.ReadSetting("thingtypes." + name + ".height", 20);
this.hangs = cfg.ReadSetting("thingtypes." + name + ".hangs", 0);
this.blocking = cfg.ReadSetting("thingtypes." + name + ".blocking", 0);
this.errorcheck = cfg.ReadSetting("thingtypes." + name + ".error", 1);
this.fixedsize = cfg.ReadSetting("thingtypes." + name + ".fixedsize", false);
this.fixedrotation = cfg.ReadSetting("thingtypes." + name + ".fixedrotation", false); //mxd
this.absolutez = cfg.ReadSetting("thingtypes." + name + ".absolutez", false);
this.spritescale = cfg.ReadSetting("thingtypes." + name + ".spritescale", 1.0f);
if(parent != null) //mxd
{
this.sprite = cfg.ReadSetting("thingtypes." + name + ".sprite", parent.sprite);
this.sorted = (cfg.ReadSetting("thingtypes." + name + ".sort", (parent.sorted ? 1 : 0)) != 0);
this.color = cfg.ReadSetting("thingtypes." + name + ".color", parent.color);
this.arrow = cfg.ReadSetting("thingtypes." + name + ".arrow", parent.arrow);
this.radius = cfg.ReadSetting("thingtypes." + name + ".width", parent.radius);
this.height = cfg.ReadSetting("thingtypes." + name + ".height", parent.height);
this.hangs = cfg.ReadSetting("thingtypes." + name + ".hangs", parent.hangs);
this.blocking = cfg.ReadSetting("thingtypes." + name + ".blocking", parent.blocking);
this.errorcheck = cfg.ReadSetting("thingtypes." + name + ".error", parent.errorcheck);
this.fixedsize = cfg.ReadSetting("thingtypes." + name + ".fixedsize", parent.fixedsize);
this.fixedrotation = cfg.ReadSetting("thingtypes." + name + ".fixedrotation", parent.fixedrotation); //mxd
this.absolutez = cfg.ReadSetting("thingtypes." + name + ".absolutez", parent.absolutez);
this.spritescale = cfg.ReadSetting("thingtypes." + name + ".spritescale", parent.spritescale);
}
else
{
this.sprite = cfg.ReadSetting("thingtypes." + name + ".sprite", "");
this.sorted = (cfg.ReadSetting("thingtypes." + name + ".sort", 0) != 0);
this.color = cfg.ReadSetting("thingtypes." + name + ".color", 0);
this.arrow = cfg.ReadSetting("thingtypes." + name + ".arrow", 0);
this.radius = cfg.ReadSetting("thingtypes." + name + ".width", 10);
this.height = cfg.ReadSetting("thingtypes." + name + ".height", 20);
this.hangs = cfg.ReadSetting("thingtypes." + name + ".hangs", 0);
this.blocking = cfg.ReadSetting("thingtypes." + name + ".blocking", 0);
this.errorcheck = cfg.ReadSetting("thingtypes." + name + ".error", 1);
this.fixedsize = cfg.ReadSetting("thingtypes." + name + ".fixedsize", false);
this.fixedrotation = cfg.ReadSetting("thingtypes." + name + ".fixedrotation", false); //mxd
this.absolutez = cfg.ReadSetting("thingtypes." + name + ".absolutez", false);
this.spritescale = cfg.ReadSetting("thingtypes." + name + ".spritescale", 1.0f);
}
// Safety
if(this.radius < 4f) this.radius = 8f;
// Go for all items in category
dic = cfg.ReadSetting("thingtypes." + name, new Hashtable());
IDictionary dic = cfg.ReadSetting("thingtypes." + name, new Hashtable());
Dictionary<string, ThingCategory> cats = new Dictionary<string, ThingCategory>(StringComparer.Ordinal); //mxd
foreach(DictionaryEntry de in dic)
{
// Check if the item key is numeric
@ -161,8 +185,22 @@ namespace CodeImp.DoomBuilder.Config
things.Add(new ThingTypeInfo(this, index, de.Value.ToString()));
}
}
//mxd. This should be a child category
else if(de.Value is IDictionary)
{
ThingCategory child = new ThingCategory(cfg, this, name + "." + de.Key, enums);
if(child.things.Count > 0)
{
if(cats.ContainsKey(child.title.ToLowerInvariant()))
General.ErrorLogger.Add(ErrorType.Warning, "Thing Category '" + child.title + "' is double-defined in " + this.title);
cats[child.title.ToLowerInvariant()] = child;
}
}
}
//mxd. Add to main collection
foreach (ThingCategory tc in cats.Values) children.Add(tc);
// We have no destructor
GC.SuppressFinalize(this);
}
@ -176,6 +214,9 @@ namespace CodeImp.DoomBuilder.Config
// Clean up
things = null;
//mxd. Dispose children (oh so cruel!!11)
foreach (ThingCategory tc in children) tc.Dispose();
// Done
isdisposed = true;
}
@ -189,6 +230,9 @@ namespace CodeImp.DoomBuilder.Config
internal void SortIfNeeded()
{
if(sorted) things.Sort();
//mxd. Sort children as well
foreach (ThingCategory tc in children) tc.SortIfNeeded();
}
// This adds a thing to the category

View file

@ -381,7 +381,7 @@ namespace CodeImp.DoomBuilder.Config
sprite = DataManager.INTERNAL_PREFIX + "unknownthing";
if(this.sprite.Length <= 8)
if(this.sprite.Length < 9)
this.spritelongname = Lump.MakeLongName(this.sprite);
else
this.spritelongname = long.MaxValue;

View file

@ -39,16 +39,16 @@ namespace CodeImp.DoomBuilder.Controls
this.positionlabel = new System.Windows.Forms.Label();
this.thingimages = new System.Windows.Forms.ImageList(this.components);
this.infopanel = new System.Windows.Forms.Panel();
this.spritepanel = new System.Windows.Forms.Panel();
this.spritetex = new CodeImp.DoomBuilder.Controls.ConfigurablePictureBox();
this.classname = new System.Windows.Forms.LinkLabel();
this.labelclassname = new System.Windows.Forms.Label();
this.spritepanel = new System.Windows.Forms.Panel();
this.typeid = new CodeImp.DoomBuilder.Controls.NumericTextbox();
this.label1 = new System.Windows.Forms.Label();
this.tbFilter = new System.Windows.Forms.TextBox();
this.bClear = new System.Windows.Forms.Button();
this.updatetimer = new System.Windows.Forms.Timer(this.components);
this.typelist = new CodeImp.DoomBuilder.GZBuilder.Controls.MultiSelectTreeview();
this.spritetex = new CodeImp.DoomBuilder.Controls.ConfigurablePictureBox();
this.typeid = new CodeImp.DoomBuilder.Controls.NumericTextbox();
this.infopanel.SuspendLayout();
this.spritepanel.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.spritetex)).BeginInit();
@ -141,6 +141,26 @@ namespace CodeImp.DoomBuilder.Controls
this.thingimages.Images.SetKeyName(17, "thing17.png");
this.thingimages.Images.SetKeyName(18, "thing18.png");
this.thingimages.Images.SetKeyName(19, "thing19.png");
this.thingimages.Images.SetKeyName(20, "category00.png");
this.thingimages.Images.SetKeyName(21, "category01.png");
this.thingimages.Images.SetKeyName(22, "category02.png");
this.thingimages.Images.SetKeyName(23, "category03.png");
this.thingimages.Images.SetKeyName(24, "category04.png");
this.thingimages.Images.SetKeyName(25, "category05.png");
this.thingimages.Images.SetKeyName(26, "category06.png");
this.thingimages.Images.SetKeyName(27, "category07.png");
this.thingimages.Images.SetKeyName(28, "category08.png");
this.thingimages.Images.SetKeyName(29, "category09.png");
this.thingimages.Images.SetKeyName(30, "category10.png");
this.thingimages.Images.SetKeyName(31, "category11.png");
this.thingimages.Images.SetKeyName(32, "category12.png");
this.thingimages.Images.SetKeyName(33, "category13.png");
this.thingimages.Images.SetKeyName(34, "category14.png");
this.thingimages.Images.SetKeyName(35, "category15.png");
this.thingimages.Images.SetKeyName(36, "category16.png");
this.thingimages.Images.SetKeyName(37, "category17.png");
this.thingimages.Images.SetKeyName(38, "category18.png");
this.thingimages.Images.SetKeyName(39, "category19.png");
//
// infopanel
//
@ -160,6 +180,33 @@ namespace CodeImp.DoomBuilder.Controls
this.infopanel.Size = new System.Drawing.Size(304, 87);
this.infopanel.TabIndex = 18;
//
// spritepanel
//
this.spritepanel.BackColor = System.Drawing.SystemColors.AppWorkspace;
this.spritepanel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.spritepanel.Controls.Add(this.spritetex);
this.spritepanel.Location = new System.Drawing.Point(235, 2);
this.spritepanel.Margin = new System.Windows.Forms.Padding(3, 3, 0, 3);
this.spritepanel.Name = "spritepanel";
this.spritepanel.Size = new System.Drawing.Size(68, 68);
this.spritepanel.TabIndex = 23;
//
// spritetex
//
this.spritetex.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.Default;
this.spritetex.Dock = System.Windows.Forms.DockStyle.Fill;
this.spritetex.Highlighted = false;
this.spritetex.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
this.spritetex.Location = new System.Drawing.Point(0, 0);
this.spritetex.Name = "spritetex";
this.spritetex.PageUnit = System.Drawing.GraphicsUnit.Pixel;
this.spritetex.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None;
this.spritetex.Size = new System.Drawing.Size(64, 64);
this.spritetex.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.spritetex.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default;
this.spritetex.TabIndex = 0;
this.spritetex.TabStop = false;
//
// classname
//
this.classname.ActiveLinkColor = System.Drawing.SystemColors.Highlight;
@ -183,16 +230,18 @@ namespace CodeImp.DoomBuilder.Controls
this.labelclassname.Text = "Class:";
this.labelclassname.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
//
// spritepanel
// typeid
//
this.spritepanel.BackColor = System.Drawing.SystemColors.AppWorkspace;
this.spritepanel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.spritepanel.Controls.Add(this.spritetex);
this.spritepanel.Location = new System.Drawing.Point(235, 2);
this.spritepanel.Margin = new System.Windows.Forms.Padding(3, 3, 0, 3);
this.spritepanel.Name = "spritepanel";
this.spritepanel.Size = new System.Drawing.Size(68, 68);
this.spritepanel.TabIndex = 23;
this.typeid.AllowDecimal = false;
this.typeid.AllowNegative = false;
this.typeid.AllowRelative = false;
this.typeid.ForeColor = System.Drawing.SystemColors.WindowText;
this.typeid.ImeMode = System.Windows.Forms.ImeMode.Off;
this.typeid.Location = new System.Drawing.Point(60, 2);
this.typeid.Name = "typeid";
this.typeid.Size = new System.Drawing.Size(68, 20);
this.typeid.TabIndex = 1;
this.typeid.TextChanged += new System.EventHandler(this.typeid_TextChanged);
//
// label1
//
@ -245,34 +294,6 @@ namespace CodeImp.DoomBuilder.Controls
this.typelist.MouseEnter += new System.EventHandler(this.typelist_MouseEnter);
this.typelist.SelectionsChanged += new System.EventHandler(this.typelist_SelectionsChanged);
//
// spritetex
//
this.spritetex.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.Default;
this.spritetex.Dock = System.Windows.Forms.DockStyle.Fill;
this.spritetex.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
this.spritetex.Location = new System.Drawing.Point(0, 0);
this.spritetex.Name = "spritetex";
this.spritetex.PageUnit = System.Drawing.GraphicsUnit.Pixel;
this.spritetex.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None;
this.spritetex.Size = new System.Drawing.Size(64, 64);
this.spritetex.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.spritetex.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default;
this.spritetex.TabIndex = 0;
this.spritetex.TabStop = false;
//
// typeid
//
this.typeid.AllowDecimal = false;
this.typeid.AllowNegative = false;
this.typeid.AllowRelative = false;
this.typeid.ForeColor = System.Drawing.SystemColors.WindowText;
this.typeid.ImeMode = System.Windows.Forms.ImeMode.Off;
this.typeid.Location = new System.Drawing.Point(60, 2);
this.typeid.Name = "typeid";
this.typeid.Size = new System.Drawing.Size(68, 20);
this.typeid.TabIndex = 1;
this.typeid.TextChanged += new System.EventHandler(this.typeid_TextChanged);
//
// ThingBrowserControl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);

View file

@ -72,13 +72,27 @@ namespace CodeImp.DoomBuilder.Controls
typelist.Nodes.Clear();
nodes = new List<TreeNode>();
validnodes = new List<TreeNode>(); //mxd
foreach(ThingCategory tc in General.Map.Data.ThingCategories)
AddThingCategories(General.Map.Data.ThingCategories, typelist.Nodes); //mxd
doupdatenode = true;
doupdatetextbox = true;
}
//mxd. This recursively creates thing category tree nodes
private void AddThingCategories(ICollection<ThingCategory> categories, TreeNodeCollection collection)
{
foreach(ThingCategory tc in categories)
{
// Create category
TreeNode cn = typelist.Nodes.Add(tc.Name, tc.Title);
if((tc.Color >= 0) && (tc.Color < thingimages.Images.Count)) cn.ImageIndex = tc.Color;
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;
foreach(ThingTypeInfo ti in tc.Things)
// Create subcategories
AddThingCategories(tc.Children, cn.Nodes);
// Create things
foreach(ThingTypeInfo ti in tc.Things)
{
// Create thing
TreeNode n = cn.Nodes.Add(ti.Title);
@ -88,9 +102,6 @@ namespace CodeImp.DoomBuilder.Controls
nodes.Add(n);
}
}
doupdatenode = true;
doupdatetextbox = true;
}
#endregion
@ -299,7 +310,7 @@ namespace CodeImp.DoomBuilder.Controls
if((n.Tag as ThingTypeInfo).Index == typeindex)
{
// Select this
if(typelist.Nodes.Contains(n.Parent)) //mxd. Tree node may've been removed during filtering
if(n.TreeView != null) //mxd. Tree node may've been removed during filtering
{
n.Parent.Expand();
typelist.SelectedNodes.Add(n);

File diff suppressed because it is too large Load diff

View file

@ -1341,6 +1341,7 @@ namespace CodeImp.DoomBuilder.Data
private int LoadDecorateThings(Dictionary<int, string> spawnnumsoverride, Dictionary<int, string> doomednumsoverride)
{
int counter = 0;
char[] catsplitter = new[] {Path.AltDirectorySeparatorChar}; //mxd
// Create new parser
decorate = new DecorateParser();
@ -1382,8 +1383,12 @@ namespace CodeImp.DoomBuilder.Data
// Check if we want to add this actor
if(actor.DoomEdNum > 0)
{
string catname = actor.GetPropertyAllValues("$category").ToLowerInvariant();
if(string.IsNullOrEmpty(catname.Trim())) catname = "decorate";
string catname = actor.GetPropertyAllValues("$category");
string[] catnames; //mxd
if(string.IsNullOrEmpty(catname.Trim()))
catnames = new[] { "decorate" };
else
catnames = catname.Split(catsplitter, StringSplitOptions.RemoveEmptyEntries); //mxd
// Check if we can find this thing in our existing collection
if(thingtypes.ContainsKey(actor.DoomEdNum))
@ -1394,7 +1399,7 @@ namespace CodeImp.DoomBuilder.Data
else
{
// Find the category to put the actor in
ThingCategory cat = GetThingCategory(actor, catname);
ThingCategory cat = GetThingCategory(null, thingcategories, catnames); //mxd
// Add new thing
ThingTypeInfo t = new ThingTypeInfo(cat, actor);
@ -1450,9 +1455,14 @@ namespace CodeImp.DoomBuilder.Data
if(actor != null)
{
// Find the category to put the actor in
string catname = actor.GetPropertyAllValues("$category").ToLowerInvariant();
if(string.IsNullOrEmpty(catname.Trim())) catname = "decorate";
ThingCategory cat = GetThingCategory(actor, catname);
string catname = actor.GetPropertyAllValues("$category");
string[] catnames; //mxd
if(string.IsNullOrEmpty(catname.Trim()))
catnames = new[] { "decorate" };
else
catnames = catname.Split(catsplitter, StringSplitOptions.RemoveEmptyEntries); //mxd
ThingCategory cat = GetThingCategory(null, thingcategories, catnames); //mxd
// Add a new ThingTypeInfo, replacing already existing one if necessary
ThingTypeInfo info = new ThingTypeInfo(cat, actor, group.Key);
@ -1551,31 +1561,44 @@ namespace CodeImp.DoomBuilder.Data
}
//mxd
private ThingCategory GetThingCategory(ActorStructure actor, string catname)
private static ThingCategory GetThingCategory(ThingCategory parent, List<ThingCategory> categories, string[] catnames)
{
// Find the category to put the actor in
// First search by Title, then search by Name
ThingCategory cat = null;
foreach(ThingCategory c in thingcategories)
string catname = catnames[0].ToLowerInvariant().Trim();
if(string.IsNullOrEmpty(catname)) catname = "decorate";
if(parent != null) catname = parent.Name + "." + catname;
// First search by Title...
foreach(ThingCategory c in categories)
{
if(c.Title.ToLowerInvariant() == catname) cat = c;
}
//... then - by Name
if(cat == null)
{
foreach(ThingCategory c in thingcategories)
foreach(ThingCategory c in categories)
{
if(c.Name.ToLowerInvariant() == catname) cat = c;
}
}
// Make the category if needed
if(cat == null)
if(cat == null)
{
string catfullname = actor.GetPropertyAllValues("$category");
if(string.IsNullOrEmpty(catfullname.Trim())) catfullname = "Decorate";
cat = new ThingCategory(catname, catfullname);
thingcategories.Add(cat);
string cattitle = catnames[0].Trim();
if(string.IsNullOrEmpty(cattitle)) cattitle = "Decorate";
cat = new ThingCategory(catname, cattitle);
categories.Add(cat); // ^.^
}
// Still have subcategories?
if(catnames.Length > 1)
{
string[] remainingnames = new string[catnames.Length - 1];
Array.Copy(catnames, 1, remainingnames, 0, remainingnames.Length);
return GetThingCategory(cat, cat.Children, remainingnames);
}
return cat;

View file

@ -589,7 +589,7 @@ namespace CodeImp.DoomBuilder.Windows
// Help
private void ThingEditForm_HelpRequested(object sender, HelpEventArgs hlpevent)
{
General.ShowHelp("w_thingeditor.html");
General.ShowHelp("w_thingedit.html");
hlpevent.Handled = true;
}

View file

@ -751,7 +751,7 @@ namespace CodeImp.DoomBuilder.Windows
// Help
private void ThingEditForm_HelpRequested(object sender, HelpEventArgs hlpevent)
{
General.ShowHelp("w_thingeditor.html");
General.ShowHelp("w_thingedit.html");
hlpevent.Handled = true;
}

View file

@ -31,6 +31,27 @@ namespace CodeImp.DoomBuilder.Windows
{
internal partial class ThingsFiltersForm : DelayedForm
{
#region ================== Structs
private class ThingCategoryData //mxd
{
public ThingCategory Category;
public string FullName;
public ThingCategoryData(ThingCategory category, string fullname)
{
Category = category;
FullName = fullname;
}
public override string ToString()
{
return FullName;
}
}
#endregion
#region ================== Variables
private bool settingup;
@ -55,7 +76,9 @@ namespace CodeImp.DoomBuilder.Windows
// Fill the categories combobox
filtercategory.Items.Add("(any category)");
filtercategory.Items.AddRange(General.Map.Data.ThingCategories.ToArray());
//mxd. Add ThingCategories with subcategories
AddThingFilterCategories(General.Map.Data.ThingCategories, string.Empty);
// Fill actions list
filteraction.GeneralizedCategories = General.Map.Config.GenActionCategories;
@ -108,6 +131,17 @@ namespace CodeImp.DoomBuilder.Windows
settingup = false;
}
//mxd. This recursively adds ThingCategories
private void AddThingFilterCategories(List<ThingCategory> list, string fullname)
{
foreach (ThingCategory cat in list)
{
string catname = (string.IsNullOrEmpty(fullname) ? cat.Title : fullname + " / " + cat.Title);
filtercategory.Items.Add(new ThingCategoryData(cat, catname));
AddThingFilterCategories(cat.Children, catname);
}
}
#endregion
#region ================== Management
@ -185,8 +219,8 @@ namespace CodeImp.DoomBuilder.Windows
// Properties
foreach(object c in filtercategory.Items)
{
ThingCategory tc = (c as ThingCategory);
if((tc != null) && (tc.Name == f.CategoryName)) filtercategory.SelectedItem = tc;
ThingCategoryData tc = (c as ThingCategoryData); //mxd
if((tc != null) && (tc.Category.Name == f.CategoryName)) filtercategory.SelectedItem = tc;
}
if(filtercategory.SelectedIndex == -1) filtercategory.SelectedIndex = 0;
@ -242,7 +276,8 @@ namespace CodeImp.DoomBuilder.Windows
}
// Custom fields
if (General.Map.FormatInterface.HasCustomFields) { //mxd
if(General.Map.FormatInterface.HasCustomFields) //mxd
{
fieldslist.ClearFields();
fieldslist.Setup("thing");
fieldslist.SetValues(f.ThingCustomFields, true);
@ -277,16 +312,16 @@ namespace CodeImp.DoomBuilder.Windows
private void filtercategory_SelectedIndexChanged(object sender, EventArgs e)
{
// Anything selected?
if(listfilters.SelectedItems.Count > 0)
if(!settingup && listfilters.SelectedItems.Count > 0)
{
// Get selected filter
ThingsFilter f = listfilters.SelectedItems[0].Tag as ThingsFilter;
// Category selected
if((filtercategory.SelectedIndex > -1) && (filtercategory.SelectedItem is ThingCategory))
if((filtercategory.SelectedIndex > -1) && (filtercategory.SelectedItem is ThingCategoryData))
{
// Set new category name
f.CategoryName = (filtercategory.SelectedItem as ThingCategory).Name;
f.CategoryName = (filtercategory.SelectedItem as ThingCategoryData).Category.Name; //mxd
}
else
{

View file

@ -396,7 +396,7 @@ namespace CodeImp.DoomBuilder.Windows
// Help requested
private void VertexEditForm_HelpRequested(object sender, HelpEventArgs hlpevent)
{
General.ShowHelp("w_vertexeditor.html");
General.ShowHelp("w_vertexedit.html");
hlpevent.Handled = true;
}

View file

@ -142,7 +142,7 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
public override void OnHelp()
{
General.ShowHelp("e_sectors.html");
General.ShowHelp("gzdb/features/classic_modes/mode_soundenvironment.html");
}
// Cancel mode

View file

@ -177,7 +177,7 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
public override void OnHelp()
{
General.ShowHelp("e_sectors.html");
General.ShowHelp("gzdb/features/classic_modes/mode_soundpropagation.html");
}
// Cancel mode