From 722c79d894725ddf597d42347b17002fbc535068 Mon Sep 17 00:00:00 2001
From: biwa <6475593+biwa@users.noreply.github.com>
Date: Sun, 11 Oct 2020 22:36:07 +0200
Subject: [PATCH] Added preliminary DECALDEFS support. Parsing works, indexed
decals and decal groups can be selected as the first argument of the Decal
thing. Decals are not displayed in Visual Mode, decals without an index are
not supported
---
Build/Configurations/Includes/ZDoom_misc.cfg | 5 +
.../Configurations/Includes/ZDoom_things.cfg | 2 +
Source/Core/Builder.csproj | 2 +
Source/Core/BuilderMono.csproj | 2 +
Source/Core/Config/ScriptConfiguration.cs | 1 +
Source/Core/Data/DataManager.cs | 62 +++++
Source/Core/ZDoom/DecalDefsParser.cs | 172 ++++++++++++++
Source/Core/ZDoom/DecalInfo.cs | 218 ++++++++++++++++++
8 files changed, 464 insertions(+)
create mode 100644 Source/Core/ZDoom/DecalDefsParser.cs
create mode 100644 Source/Core/ZDoom/DecalInfo.cs
diff --git a/Build/Configurations/Includes/ZDoom_misc.cfg b/Build/Configurations/Includes/ZDoom_misc.cfg
index 796b6758..a711cfa3 100755
--- a/Build/Configurations/Includes/ZDoom_misc.cfg
+++ b/Build/Configurations/Includes/ZDoom_misc.cfg
@@ -925,6 +925,11 @@ enums
0 = "None";
}
+ decals
+ {
+ 0 = "None";
+ }
+
sound_sequences
{
0 = "None";
diff --git a/Build/Configurations/Includes/ZDoom_things.cfg b/Build/Configurations/Includes/ZDoom_things.cfg
index 5fdc58d5..d80a3b20 100755
--- a/Build/Configurations/Includes/ZDoom_things.cfg
+++ b/Build/Configurations/Includes/ZDoom_things.cfg
@@ -1243,6 +1243,8 @@ zdoom
arg0
{
title = "Decal ID";
+ type = 11;
+ enum = "decals";
}
}
diff --git a/Source/Core/Builder.csproj b/Source/Core/Builder.csproj
index fb720b7a..3ff07e61 100644
--- a/Source/Core/Builder.csproj
+++ b/Source/Core/Builder.csproj
@@ -593,6 +593,8 @@
+
+
diff --git a/Source/Core/BuilderMono.csproj b/Source/Core/BuilderMono.csproj
index 1daf50df..faa82e6d 100644
--- a/Source/Core/BuilderMono.csproj
+++ b/Source/Core/BuilderMono.csproj
@@ -589,6 +589,8 @@
+
+
diff --git a/Source/Core/Config/ScriptConfiguration.cs b/Source/Core/Config/ScriptConfiguration.cs
index 76541375..a38b1b77 100755
--- a/Source/Core/Config/ScriptConfiguration.cs
+++ b/Source/Core/Config/ScriptConfiguration.cs
@@ -53,6 +53,7 @@ namespace CodeImp.DoomBuilder.Config
KEYCONF,
FONTDEFS,
ZSCRIPT,
+ DECALDEF,
}
internal class ScriptConfiguration : IComparable
diff --git a/Source/Core/Data/DataManager.cs b/Source/Core/Data/DataManager.cs
index 3a4eb294..b0ed4101 100755
--- a/Source/Core/Data/DataManager.cs
+++ b/Source/Core/Data/DataManager.cs
@@ -437,6 +437,9 @@ namespace CodeImp.DoomBuilder.Data
LoadCvarInfo();
LoadLockDefs();
+ // Load DECALDEF
+ LoadDecalDefs();
+
//mxd. Load Script Editor-only stuff...
LoadExtraTextLumps();
@@ -2818,6 +2821,65 @@ namespace CodeImp.DoomBuilder.Data
}
}
+ ///
+ /// Load DECALDEF decal definitions
+ ///
+ private void LoadDecalDefs()
+ {
+ // Bail out when not supported by current game configuration
+ if (string.IsNullOrEmpty(General.Map.Config.DecorateGames)) return;
+
+ DecalDefsParser parser = new DecalDefsParser();
+
+ foreach(DataReader dr in containers)
+ {
+ currentreader = dr; // Why?
+ IEnumerable streams = dr.GetTextLumpData(ScriptType.DECALDEF, false, false);
+
+ // Parse the data
+ foreach(TextResourceData data in streams)
+ {
+ parser.Parse(data, true);
+
+ // Report errors?
+ if (parser.HasError) parser.LogError();
+ }
+ }
+
+ currentreader = null; // Why?
+
+ if(parser.Decals.Count > 0)
+ {
+ // Update or create the main enums list
+ Dictionary configenums = new Dictionary();
+ if (General.Map.Config.Enums.ContainsKey("decals"))
+ {
+ foreach (EnumItem item in General.Map.Config.Enums["decals"])
+ configenums.Add(item.GetIntValue(), item);
+ }
+ if (configenums.ContainsKey(0)) configenums.Remove(0);
+
+ foreach (KeyValuePair group in parser.GetDecalDefsById())
+ {
+ configenums[group.Key] = new EnumItem(group.Key.ToString(), group.Value.Description);
+ }
+
+ // Store results in "decals" enum
+ EnumList newenums = new EnumList();
+ newenums.AddRange(configenums.Values);
+ newenums.Sort();
+ newenums.Insert(0, new EnumItem("0", "None"));
+ General.Map.Config.Enums["decals"] = newenums;
+
+ // Update all ArgumentInfos...
+ foreach (ThingTypeInfo info in thingtypes.Values)
+ {
+ foreach (ArgumentInfo ai in info.Args)
+ if (ai.Enum.Name == "decals") ai.Enum = newenums;
+ }
+ }
+ }
+
//mxd. This collects ZDoom text lumps, which are not used by the editor anywhere outside the Script Editor
private void LoadExtraTextLumps()
{
diff --git a/Source/Core/ZDoom/DecalDefsParser.cs b/Source/Core/ZDoom/DecalDefsParser.cs
new file mode 100644
index 00000000..83f4accf
--- /dev/null
+++ b/Source/Core/ZDoom/DecalDefsParser.cs
@@ -0,0 +1,172 @@
+#region ================== Copyright (c) 2020 Boris Iwanski
+
+/*
+ * This program is free software: you can redistribute it and/or modify
+ *
+ * it under the terms of the GNU General Public License as published by
+ *
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.If not, see.
+ */
+
+#endregion
+
+#region ================== Namespaces
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CodeImp.DoomBuilder.Config;
+using CodeImp.DoomBuilder.Data;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.ZDoom
+{
+ internal sealed class DecalDefsParser : ZDTextParser
+ {
+ #region ================== Variables
+
+ private Dictionary decals = new Dictionary();
+
+ #endregion
+
+ #region ================== Properties
+
+ internal override ScriptType ScriptType { get { return ScriptType.DECALDEF; } }
+ public Dictionary Decals { get { return decals; } }
+
+ #endregion
+
+ #region ================== Constructors
+
+ ///
+ /// Constructor
+ ///
+ public DecalDefsParser()
+ {
+
+ }
+
+ #endregion
+
+ #region ================== Methods
+
+ ///
+ /// Parses DECALDEF data
+ ///
+ /// The data to parse
+ /// If errors should be cleared
+ /// true if paring worked, otherwise false
+ public override bool Parse(TextResourceData data, bool clearerrors)
+ {
+ if(!AddTextResource(data))
+ {
+ if (clearerrors) ClearError();
+ return true;
+ }
+
+ // Cannot process?
+ if (!base.Parse(data, clearerrors)) return false;
+
+ while(SkipWhitespace(true))
+ {
+ string token = ReadToken().ToLowerInvariant();
+ if (string.IsNullOrEmpty(token)) continue;
+
+ switch(token)
+ {
+ case "decal":
+ case "decalgroup":
+ DecalInfo.DecalType type = token == "decal" ? DecalInfo.DecalType.DECAL : DecalInfo.DecalType.DECALGROUP;
+ string decalname;
+ int decalid = -1;
+
+ SkipWhitespace(false);
+ token = ReadToken();
+ if (!string.IsNullOrEmpty(token))
+ decalname = token;
+ else
+ {
+ ReportError("Expected decal name, got nothing");
+ return false;
+ }
+
+ SkipWhitespace(false);
+
+ // Try to read the optional decal id
+ token = ReadToken();
+ if(!string.IsNullOrEmpty(token))
+ {
+ ReadSignedInt(token, ref decalid);
+ }
+
+ SkipWhitespace(true);
+
+ DecalInfo di = new DecalInfo(decalname, decalid, type);
+
+ if (!di.Parse(this))
+ return false;
+
+ decals.Add(decalname, di);
+
+ break;
+ }
+ }
+
+ return true;
+ }
+
+ ///
+ /// Finishes parsing, getting the DecalInfo of chidren of decal groups
+ ///
+ public void Finish()
+ {
+ foreach(DecalInfo di in decals.Values)
+ {
+ if(di.Type == DecalInfo.DecalType.DECALGROUP && di.Children.Count > 0)
+ {
+ foreach(string childname in di.Children.Keys)
+ {
+ if(decals.ContainsKey(childname))
+ {
+ di.Children[childname] = decals[childname];
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// Gets the parsed DECALDEF data by id
+ ///
+ /// EnumList of parsed decals
+ public Dictionary GetDecalDefsById()
+ {
+ Dictionary dict = new Dictionary();
+
+ foreach (DecalInfo di in decals.Values)
+ {
+ if(di.Index != -1)
+ dict.Add(di.Index, di);
+ }
+
+ return dict;
+ }
+
+ #endregion
+ }
+}
diff --git a/Source/Core/ZDoom/DecalInfo.cs b/Source/Core/ZDoom/DecalInfo.cs
new file mode 100644
index 00000000..df15efeb
--- /dev/null
+++ b/Source/Core/ZDoom/DecalInfo.cs
@@ -0,0 +1,218 @@
+#region ================== Copyright (c) 2020 Boris Iwanski
+
+/*
+ * This program is free software: you can redistribute it and/or modify
+ *
+ * it under the terms of the GNU General Public License as published by
+ *
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.If not, see.
+ */
+
+#endregion
+
+#region ================== Namespaces
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.ZDoom
+{
+ public class DecalInfo
+ {
+ #region ================== Enums
+
+ public enum DecalType
+ {
+ DECAL,
+ DECALGROUP
+ }
+
+ #endregion
+
+ #region ================== Variables
+
+ private string name;
+ private string picturename = string.Empty;
+ private int index;
+ private string description;
+ private DecalType type;
+ private Dictionary childdecals = new Dictionary(); // Children of decal groups
+
+ #endregion
+
+ #region ================== Properties
+
+ public string Name { get { return name; } }
+ public string PictureName { get { return picturename; } }
+ public int Index { get { return index; } }
+ public DecalType Type { get { return type; } }
+ public string Description { get { return description; } }
+ public Dictionary Children { get { return childdecals; } }
+
+ #endregion
+
+ #region ================== Constructor
+
+ public DecalInfo(string name, int index, DecalType type)
+ {
+ this.name = name;
+ this.index = index;
+ this.type = type;
+
+ description = index.ToString() + ": " + name;
+ }
+
+ #endregion
+
+ #region ================== Methods
+
+ internal void SetPictureName(string picturename)
+ {
+ this.picturename = picturename;
+ }
+
+ ///
+ /// Parse a decal or decalgroup definition
+ ///
+ ///
+ ///
+ internal bool Parse(DecalDefsParser parser)
+ {
+ switch(type)
+ {
+ case DecalType.DECAL:
+ return ParseDecal(parser);
+ case DecalType.DECALGROUP:
+ return ParseDecalGroup(parser);
+ }
+
+ return false;
+ }
+
+ ///
+ /// Parses a decal definition
+ ///
+ /// the DecalDefsParser that right before the decal definition block
+ ///
+ private bool ParseDecal(DecalDefsParser parser)
+ {
+ parser.SkipWhitespace(true);
+
+ string token = parser.ReadToken();
+
+ if (token != "{")
+ {
+ parser.ReportError("Expected \"{\", got " + token);
+ return false;
+ }
+
+ while (true)
+ {
+ parser.SkipWhitespace(true);
+
+ token = parser.ReadToken().ToLowerInvariant();
+
+ if (string.IsNullOrEmpty(token))
+ {
+ parser.ReportError("Expected property of }, got nothing");
+ return false;
+ }
+
+ // Decal ends here
+ if (token == "}")
+ {
+ break;
+ }
+
+ switch (token)
+ {
+ case "pic":
+ parser.SkipWhitespace(false);
+ token = parser.ReadToken();
+
+ if (string.IsNullOrEmpty(token))
+ {
+ parser.ReportError("Expected image name, got nothing");
+ return false;
+ }
+
+ picturename = token;
+
+ break;
+ }
+ }
+
+ return true;
+ }
+
+ ///
+ /// Parses a decalgroup defition
+ ///
+ /// The DecalDefsParser that right before the decalgroup definition block
+ ///
+ private bool ParseDecalGroup(DecalDefsParser parser)
+ {
+ parser.SkipWhitespace(true);
+
+ string token = parser.ReadToken();
+
+ if (token != "{")
+ {
+ parser.ReportError("Expected \"{\", got " + token);
+ return false;
+ }
+
+ while (true)
+ {
+ parser.SkipWhitespace(true);
+
+ token = parser.ReadToken().ToLowerInvariant();
+
+ if (string.IsNullOrEmpty(token))
+ {
+ parser.ReportError("Expected property of }, got nothing");
+ return false;
+ }
+
+ // Decal ends here
+ if (token == "}")
+ {
+ break;
+ }
+
+ // Add name of child to the list of children
+ childdecals.Add(token, null);
+
+ // Read the probability wheight. We don't use it, though
+ int weight = 0;
+ parser.SkipWhitespace(false);
+ token = parser.ReadToken();
+ if(string.IsNullOrEmpty(token) || !parser.ReadSignedInt(token, ref weight))
+ {
+ parser.ReportError("Expected probability weight as number, got \"" + token + "\"");
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ #endregion
+ }
+}