#region ================== Namespaces using CodeImp.DoomBuilder.Config; using CodeImp.DoomBuilder.GZBuilder.Data; using CodeImp.DoomBuilder.Map; using CodeImp.DoomBuilder.ZDoom; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; #endregion namespace CodeImp.DoomBuilder.GZBuilder { //mxd. should get rid of this class one day... public static class GZGeneral { #region ================== Properties //gzdoom light types public class LightDefNum : Attribute { public int[] DoomEdNums { get; private set; } public LightDefNum(params int[] doomEdNums) { DoomEdNums = doomEdNums; } } public class LightDefClass : Attribute { public string[] Classes { get; private set; } public LightDefClass(params string[] clses) { Classes = clses; } } public class LightDefModifier : Attribute { public LightModifier[] Modifiers { get; private set; } public LightDefModifier(params LightModifier[] mods) { Modifiers = mods; } } public class LightDefRenderStyle : Attribute { public LightRenderStyle RenderStyle { get; private set; } public LightDefRenderStyle(LightRenderStyle rs) { RenderStyle = rs; } } public enum LightDef { [LightDefRenderStyle(LightRenderStyle.NORMAL)] [LightDefNum(9800, 9801, 9802, 9803, 9804)] [LightDefClass("pointlight", "pointlightpulse", "pointlightflicker", "sectorpointlight", "pointlightflickerrandom")] [LightDefModifier(LightModifier.NORMAL, LightModifier.PULSE, LightModifier.FLICKER, LightModifier.SECTOR, LightModifier.FLICKERRANDOM)] POINT_NORMAL, [LightDefRenderStyle(LightRenderStyle.ADDITIVE)] [LightDefNum(9810, 9811, 9812, 9813, 9814)] [LightDefClass("pointlightadditive", "pointlightpulseadditive", "pointlightflickeradditive", "sectorpointlightadditive", "pointlightflickerrandomadditive")] [LightDefModifier(LightModifier.NORMAL, LightModifier.PULSE, LightModifier.FLICKER, LightModifier.SECTOR, LightModifier.FLICKERRANDOM)] POINT_ADDITIVE, [LightDefRenderStyle(LightRenderStyle.SUBTRACTIVE)] [LightDefNum(9820, 9821, 9822, 9823, 9824)] [LightDefClass("pointlightsubtractive", "pointlightpulsesubtractive", "pointlightflickersubtractive", "sectorpointlightsubtractive", "pointlightflickerrandomsubtractive")] [LightDefModifier(LightModifier.NORMAL, LightModifier.PULSE, LightModifier.FLICKER, LightModifier.SECTOR, LightModifier.FLICKERRANDOM)] POINT_SUBTRACTIVE, [LightDefRenderStyle(LightRenderStyle.ATTENUATED)] [LightDefNum(9830, 9831, 9832, 9833, 9834)] [LightDefClass("pointlightattenuated", "pointlightpulseattenuated", "pointlightflickerattenuated", "sectorpointlightattenuated", "pointlightflickerrandomattenuated")] [LightDefModifier(LightModifier.NORMAL, LightModifier.PULSE, LightModifier.FLICKER, LightModifier.SECTOR, LightModifier.FLICKERRANDOM)] POINT_ATTENUATED, [LightDefRenderStyle(LightRenderStyle.NORMAL)] [LightDefNum(9840, 9841, 9842, 9843, 8944)] [LightDefClass("spotlight", "spotlightpulse", "spotlightflicker", "sectorspotlight", "spotlightflickerrandom")] [LightDefModifier(LightModifier.NORMAL, LightModifier.PULSE, LightModifier.FLICKER, LightModifier.SECTOR, LightModifier.FLICKERRANDOM)] SPOT_NORMAL, [LightDefRenderStyle(LightRenderStyle.ADDITIVE)] [LightDefNum(9850, 9851, 9852, 9853, 8954)] [LightDefClass("spotlightadditive", "spotlightpulseadditive", "spotlightflickeradditive", "sectorspotlightadditive", "spotlightflickerrandomadditive")] [LightDefModifier(LightModifier.NORMAL, LightModifier.PULSE, LightModifier.FLICKER, LightModifier.SECTOR, LightModifier.FLICKERRANDOM)] SPOT_ADDITIVE, [LightDefRenderStyle(LightRenderStyle.SUBTRACTIVE)] [LightDefNum(9860, 9861, 9862, 9863, 8964)] [LightDefClass("spotlightsubtractive", "spotlightpulsesubtractive", "spotlightflickersubtractive", "sectorspotlightsubtractive", "spotlightflickerrandomsubtractive")] [LightDefModifier(LightModifier.NORMAL, LightModifier.PULSE, LightModifier.FLICKER, LightModifier.SECTOR, LightModifier.FLICKERRANDOM)] SPOT_SUBTRACTIVE, [LightDefRenderStyle(LightRenderStyle.ATTENUATED)] [LightDefNum(9870, 9871, 9872, 9873, 8974)] [LightDefClass("spotlightattenuated", "spotlightpulseattenuated", "spotlightflickerattenuated", "sectorspotlightattenuated", "spotlightflickerrandomattenuated")] [LightDefModifier(LightModifier.NORMAL, LightModifier.PULSE, LightModifier.FLICKER, LightModifier.SECTOR, LightModifier.FLICKERRANDOM)] SPOT_ATTENUATED, [LightDefRenderStyle(LightRenderStyle.VAVOOM)] [LightDefNum(1502)] [LightDefClass("vavoomlightwhite")] VAVOOM_GENERIC, [LightDefRenderStyle(LightRenderStyle.VAVOOM)] [LightDefNum(1503)] [LightDefClass("vavoomlightcolor")] VAVOOM_COLORED, [LightDefRenderStyle(LightRenderStyle.STATIC)] [LightDefNum(9876)] [LightDefClass("staticpointlight")] [LightDefModifier(LightModifier.NORMAL)] POINT_STATIC, [LightDefRenderStyle(LightRenderStyle.STATIC)] [LightDefNum(9881)] [LightDefClass("staticspotlight")] [LightDefModifier(LightModifier.NORMAL)] SPOT_STATIC, [LightDefRenderStyle(LightRenderStyle.NONE)] [LightDefNum(9890)] [LightDefClass("zdraysun")] [LightDefModifier(LightModifier.NORMAL)] SUN, UNKNOWN } // divide these by 100 to get light color alpha // this, sadly, has to duplicate the enum in GZGeneral because it's shader-specific public enum LightRenderStyle { SUBTRACTIVE = 100, NORMAL = 99, ATTENUATED = 98, VAVOOM = 50, ADDITIVE = 25, STATIC = 98, // Same as attenuated NONE = 0, } public enum LightModifier { NORMAL, PULSE, FLICKER, SECTOR, FLICKERRANDOM } public enum LightType { POINT, SPOT, VAVOOM, SUN } public static LightDefNum GetLightDefNum(LightDef d) { FieldInfo fi = typeof(LightDef).GetField(d.ToString()); LightDefNum[] attrs = (LightDefNum[])fi.GetCustomAttributes(typeof(LightDefNum), false); if (attrs.Length != 0) return attrs[0]; return null; } public static LightDefClass GetLightDefClass(LightDef d) { FieldInfo fi = typeof(LightDef).GetField(d.ToString()); LightDefClass[] attrs = (LightDefClass[])fi.GetCustomAttributes(typeof(LightDefClass), false); if (attrs.Length != 0) return attrs[0]; return null; } public static LightDefModifier GetLightDefModifier(LightDef d) { FieldInfo fi = typeof(LightDef).GetField(d.ToString()); LightDefModifier[] attrs = (LightDefModifier[])fi.GetCustomAttributes(typeof(LightDefModifier), false); if (attrs.Length != 0) return attrs[0]; return null; } public static LightDefRenderStyle GetLightDefRenderStyle(LightDef d) { FieldInfo fi = typeof(LightDef).GetField(d.ToString()); LightDefRenderStyle[] attrs = (LightDefRenderStyle[])fi.GetCustomAttributes(typeof(LightDefRenderStyle), false); if (attrs.Length != 0) return attrs[0]; return null; } public class LightData { public LightDef LightDef { get; private set; } private LightDefNum LightDefNum; private LightDefClass LightDefClass; private LightDefModifier LightDefModifier; private LightDefRenderStyle LightDefRenderStyle; public string LightClass { get; private set; } public int LightNum { get; private set; } public LightModifier LightModifier { get; private set; } public LightRenderStyle LightRenderStyle { get; private set; } public bool LightAnimated { get; private set; } public bool LightInternal { get; private set; } public bool LightVavoom { get; private set; } public LightType LightType { get; private set; } private void UpdateLightType() { switch (LightDef) { default: case LightDef.POINT_NORMAL: case LightDef.POINT_ADDITIVE: case LightDef.POINT_SUBTRACTIVE: case LightDef.POINT_ATTENUATED: case LightDef.POINT_STATIC: LightType = LightType.POINT; break; case LightDef.SPOT_NORMAL: case LightDef.SPOT_ADDITIVE: case LightDef.SPOT_SUBTRACTIVE: case LightDef.SPOT_ATTENUATED: case LightDef.SPOT_STATIC: LightType = LightType.SPOT; break; case LightDef.VAVOOM_GENERIC: case LightDef.VAVOOM_COLORED: LightType = LightType.VAVOOM; break; case LightDef.SUN: LightType = LightType.SUN; break; } } public LightData(LightDef d, int num) { LightDef = d; LightNum = num; LightDefNum = GetLightDefNum(LightDef); LightDefClass = GetLightDefClass(LightDef); LightDefModifier = GetLightDefModifier(LightDef); LightDefRenderStyle = GetLightDefRenderStyle(LightDef); LightClass = LightDefClass.Classes[Array.IndexOf(LightDefNum.DoomEdNums, LightNum)]; if (LightDefModifier != null) LightModifier = LightDefModifier.Modifiers[Array.IndexOf(LightDefNum.DoomEdNums, LightNum)]; else LightModifier = LightModifier.NORMAL; if (LightDefRenderStyle != null) LightRenderStyle = LightDefRenderStyle.RenderStyle; else LightRenderStyle = LightRenderStyle.NONE; LightAnimated = (LightModifier == LightModifier.PULSE || LightModifier == LightModifier.FLICKER || LightModifier == LightModifier.FLICKERRANDOM); LightInternal = true; UpdateLightType(); LightVavoom = (LightType == LightType.VAVOOM); } public LightData(LightDef d, string cls) { LightDef = d; LightClass = cls; LightDefNum = GetLightDefNum(LightDef); LightDefClass = GetLightDefClass(LightDef); LightDefModifier = GetLightDefModifier(LightDef); LightDefRenderStyle = GetLightDefRenderStyle(LightDef); LightNum = LightDefNum.DoomEdNums[Array.IndexOf(LightDefClass.Classes, cls)]; if (LightDefModifier != null) LightModifier = LightDefModifier.Modifiers[Array.IndexOf(LightDefClass.Classes, cls)]; else LightModifier = LightModifier.NORMAL; if (LightDefRenderStyle != null) LightRenderStyle = LightDefRenderStyle.RenderStyle; else LightRenderStyle = LightRenderStyle.NONE; LightAnimated = (LightModifier == LightModifier.PULSE || LightModifier == LightModifier.FLICKER || LightModifier == LightModifier.FLICKERRANDOM); LightInternal = true; LightVavoom = (LightDef == LightDef.VAVOOM_GENERIC || LightDef == LightDef.VAVOOM_COLORED); UpdateLightType(); LightVavoom = (LightType == LightType.VAVOOM); } public LightData(LightModifier mod = LightModifier.NORMAL, LightRenderStyle rs = LightRenderStyle.NONE) { LightDef = LightDef.UNKNOWN; LightClass = null; LightNum = -1; LightModifier = mod; LightRenderStyle = rs; LightAnimated = (LightModifier == LightModifier.PULSE || LightModifier == LightModifier.FLICKER || LightModifier == LightModifier.FLICKERRANDOM); LightInternal = false; LightVavoom = false; LightType = LightType.POINT; // always point in GLDEFS } public void SetRenderStyle(LightRenderStyle rs) { if (LightInternal) return; LightRenderStyle = rs; } } static IEnumerable _gldbn_ldefs; public static LightData GetLightDataByNum(int doomednum) { if (_gldbn_ldefs == null) _gldbn_ldefs = Enum.GetValues(typeof(LightDef)).Cast(); foreach (LightDef ldef in _gldbn_ldefs) { // FieldInfo fi = typeof(LightDef).GetField(ldef.ToString()); LightDefNum[] attrs = (LightDefNum[])fi.GetCustomAttributes(typeof(LightDefNum), false); if (attrs.Length == 0) continue; // LightDefNum attr = attrs[0]; if (Array.IndexOf(attr.DoomEdNums, doomednum) != -1) return new LightData(ldef, doomednum); } return null; } public static LightData GetLightDataByClass(string cls) { cls = cls.ToLowerInvariant(); if (_gldbn_ldefs == null) _gldbn_ldefs = Enum.GetValues(typeof(LightDef)).Cast(); foreach (LightDef ldef in _gldbn_ldefs) { // FieldInfo fi = typeof(LightDef).GetField(ldef.ToString()); LightDefClass[] attrs = (LightDefClass[])fi.GetCustomAttributes(typeof(LightDefClass), false); if (attrs.Length == 0) continue; // LightDefClass attr = attrs[0]; if (Array.IndexOf(attr.Classes, cls) != -1) return new LightData(ldef, cls); } return null; } //asc script action specials private static readonly int[] acsSpecials = { 80, 81, 82, 83, 84, 85, 226 }; public static int[] ACS_SPECIALS { get { return acsSpecials; } } // [ZZ] this is for proper inheritance of lights. // technically this can be found by parsing gzdoom.pk3/mapinfo/common.txt, but I wouldn't do that without a good reason for now. public static LightData GetGZLightTypeByClass(ActorStructure actor) { ActorStructure p = actor; while (p != null) { // found dynamic light type. alter it by actor flags. // +MISSILEMORE makes it additive. // +MISSILEEVENMORE makes it subtractive. // +INCOMBAT makes it attenuated. LightData ld = GetLightDataByClass(p.ClassName); if (ld != null) { if (ld.LightDef != LightDef.VAVOOM_GENERIC && ld.LightDef != LightDef.VAVOOM_COLORED) // not vavoom { int baseType = ld.LightNum % 10; int dispType = ld.LightNum - baseType; if (actor.GetFlagValue("MISSILEMORE", false) || actor.GetFlagValue("DYNAMICLIGHT.ADDITIVE", false)) dispType = 9810; else if (actor.GetFlagValue("MISSILEEVENMORE", false) || actor.GetFlagValue("DYNAMICLIGHT.SUBTRACTIVE", false)) dispType = 9820; else if (actor.GetFlagValue("INCOMBAT", false) || actor.GetFlagValue("DYNAMICLIGHT.ATTENUATE", false)) dispType = 9830; if (!actor.GetFlagValue("DYNAMICLIGHT.SPOT", false) && dispType >= 9840) dispType -= 40; if (actor.GetFlagValue("DYNAMICLIGHT.SPOT", false) && dispType < 9840) dispType += 40; return GetLightDataByNum(dispType + baseType); } else return null; } p = p.BaseClass; } return null; } // this is here so that I can see all dirty patches by listing references to this method. public static void AssertNotNull(object o, string whatisit) { if (o == null) { throw new NullReferenceException(whatisit + " is null"); } } #endregion } }