#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.IO; 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(true); token = ReadToken(); // Try to read the optional decal id if (token == "{") { datastream.Seek(-token.Length - 1, SeekOrigin.Current); } else { if (!string.IsNullOrEmpty(token)) ReadSignedInt(token, ref decalid); } SkipWhitespace(true); DecalInfo di = new DecalInfo(decalname, decalid, type); if (!di.Parse(this)) return false; if(decals.ContainsKey(decalname)) { // TODO: report problem // Overwrite existing decal with new one (who knows if that's the correct way do handle duplicate entries?) decals[decalname] = di; } else 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[di.Index] = di; } return dict; } #endregion } }