diff --git a/Build/Configurations/Includes/Eternity_misc.cfg b/Build/Configurations/Includes/Eternity_misc.cfg index b90bfeca..76f47243 100755 --- a/Build/Configurations/Includes/Eternity_misc.cfg +++ b/Build/Configurations/Includes/Eternity_misc.cfg @@ -127,10 +127,44 @@ floorterain, ceilingterrain, floor/ceiling panning/rotation */ portalfloor { type = 0; + //associations + //{ + // 0 + // { + // elements { sector; } + // property = "portalfloor"; + // modify = "abs"; + // nevershoweventlines = true; + // } + // 1 + // { + // elements { sector; } + // property = "portalceiling"; + // modify = "abs"; + // nevershoweventlines = true; + // } + //} } portalceiling { type = 0; + //associations + //{ + // 0 + // { + // elements { sector; } + // property = "portalfloor"; + // modify = "abs"; + // nevershoweventlines = true; + // } + // 1 + // { + // elements { sector; } + // property = "portalceiling"; + // modify = "abs"; + // nevershoweventlines = true; + // } + //} } floorid diff --git a/Source/Core/Config/UniversalFieldInfo.cs b/Source/Core/Config/UniversalFieldInfo.cs index bb12cd8f..88b24a83 100755 --- a/Source/Core/Config/UniversalFieldInfo.cs +++ b/Source/Core/Config/UniversalFieldInfo.cs @@ -26,6 +26,26 @@ using CodeImp.DoomBuilder.Types; namespace CodeImp.DoomBuilder.Config { + public enum UDMFFieldAssociationModifier + { + None, + Absolute + } + + public struct UDMFFieldAssociation + { + public string Property; + public UDMFFieldAssociationModifier Modify; + public bool NeverShowEventLines; + + public UDMFFieldAssociation(string property, UDMFFieldAssociationModifier modify, bool nevershoweventlines) + { + Property = property; + Modify = modify; + NeverShowEventLines = nevershoweventlines; + } + } + public class UniversalFieldInfo : IComparable { #region ================== Constants @@ -39,6 +59,7 @@ namespace CodeImp.DoomBuilder.Config private int type; private object defaultvalue; private EnumList enumlist; + private Dictionary associations; #endregion @@ -48,6 +69,7 @@ namespace CodeImp.DoomBuilder.Config public int Type { get { return type; } } public object Default { get { return defaultvalue; } } public EnumList Enum { get { return enumlist; } } + public Dictionary Associations { get { return associations; } } #endregion @@ -60,6 +82,7 @@ namespace CodeImp.DoomBuilder.Config // Initialize this.name = name.ToLowerInvariant(); + associations = new Dictionary(); // Read type this.type = cfg.ReadSetting(setting + ".type", int.MinValue); @@ -99,7 +122,29 @@ namespace CodeImp.DoomBuilder.Config enumlist = new EnumList(enumsetting as IDictionary); } } - + + // Read associations + IDictionary assocdict = cfg.ReadSetting(setting + ".associations", new Hashtable()); + foreach (DictionaryEntry section in assocdict) + { + string property = cfg.ReadSetting(setting + ".associations." + section.Key + ".property", string.Empty); + string modifystr = cfg.ReadSetting(setting + ".associations." + section.Key + ".modify", string.Empty); + bool nevershoweventlines = cfg.ReadSetting(setting + ".associations." + section.Key + ".nevershoweventlines", false); + UDMFFieldAssociationModifier ufam = UDMFFieldAssociationModifier.None; + + if(!string.IsNullOrWhiteSpace(property)) + { + switch (modifystr) + { + case "abs": + ufam = UDMFFieldAssociationModifier.Absolute; + break; + } + + associations[property] = new UDMFFieldAssociation(property, ufam, nevershoweventlines); + } + } + // We have no destructor GC.SuppressFinalize(this); } diff --git a/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs index d71518b3..ae42fd44 100755 --- a/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs @@ -441,10 +441,10 @@ namespace CodeImp.DoomBuilder.BuilderModes // are or were drawn we need to redraw the entire display. // Previous association highlights something? - bool completeredraw = (highlighted != null) && (highlighted.Tag != 0); + bool completeredraw = (highlighted != null) && (highlighted.Tag != 0 || Association.SectorHasUDMFFieldAssociations(highlighted)); // Set highlight association - if(s != null && s.Tag != 0) + if(s != null && (s.Tag != 0 || Association.SectorHasUDMFFieldAssociations(s))) { highlightasso.Set(s); } @@ -454,7 +454,7 @@ namespace CodeImp.DoomBuilder.BuilderModes } // New association highlights something? - if((s != null) && (s.Tag != 0)) completeredraw = true; + if((s != null) && (s.Tag != 0 || Association.SectorHasUDMFFieldAssociations(s))) completeredraw = true; // Change label color if((highlighted != null) && !highlighted.IsDisposed) diff --git a/Source/Plugins/BuilderModes/General/Association.cs b/Source/Plugins/BuilderModes/General/Association.cs index eb53137a..381995e4 100755 --- a/Source/Plugins/BuilderModes/General/Association.cs +++ b/Source/Plugins/BuilderModes/General/Association.cs @@ -31,6 +31,31 @@ using CodeImp.DoomBuilder.Windows; namespace CodeImp.DoomBuilder.BuilderModes { + public struct UDMFFieldAssociationX + { + public string Property; + public string Modify; + public UniValue Value; + + public UDMFFieldAssociationX(string property, string modify, UniValue value) + { + Property = property; + Modify = modify; + Value = value; + } + + public UniValue GetValue() + { + if(Value.Type == 0) + { + if (Modify == "abs") + return new UniValue(0, Math.Abs((int)Value.Value)); + } + + return new UniValue(0, 0); + } + } + public class Association { private HashSet tags; @@ -264,6 +289,9 @@ namespace CodeImp.DoomBuilder.BuilderModes bool addforward = false; bool addreverse = false; + if (s == element) + continue; + // Check for forward association (from the element to the sector) if (hassectortags && actiontags[(int)UniversalType.SectorTag].Overlaps(s.Tags)) addforward = true; @@ -283,6 +311,35 @@ namespace CodeImp.DoomBuilder.BuilderModes if (addreverse) AddLineToAction(showreverselabel ? GetActionDescription(element) : string.Empty, sectorcenter, center); } + + // Check arbitrary UDMF field associations + foreach (UniversalFieldInfo ufi in General.Map.Config.SectorFields) + { + if (ufi.Associations.Count == 0) + continue; + + UniValue ouv; + + if (element.Fields.TryGetValue(ufi.Name, out ouv)) + { + foreach (KeyValuePair kvp in ufi.Associations) + { + UniValue uv; + if (s.Fields.TryGetValue(kvp.Key, out uv)) + { + if(UniValuesMatch(uv, ouv, kvp.Value.Modify, ufi.Default)) + { + Vector2D sectorcenter = (s.Labels.Count > 0 ? s.Labels[0].position : new Vector2D(s.BBox.X + s.BBox.Width / 2, s.BBox.Y + s.BBox.Height / 2)); + + if(showforwardlabel && kvp.Value.NeverShowEventLines == false) + AddLineToAction(kvp.Key + ": " + uv.Value, center, sectorcenter); + + sectors.Add(s); + } + } + } + } + } } // Process all linedefs in the map @@ -717,6 +774,96 @@ namespace CodeImp.DoomBuilder.BuilderModes return newpositions; } + /// + /// Checks if the type and value of two UniValues match. Takes modifiers into account + /// + /// First UniValue + /// Second UniValue + /// Modifier + /// True if values match + private bool UniValuesMatch(UniValue uv1, UniValue uv2, UDMFFieldAssociationModifier ufam, object def) + { + if (uv1.Type != uv2.Type) + return false; + + switch ((UniversalType)uv1.Type) + { + case UniversalType.AngleRadians: + case UniversalType.AngleDegreesFloat: + case UniversalType.Float: + double d1 = (double)uv1.Value; + double d2 = (double)uv2.Value; + + if(ufam == UDMFFieldAssociationModifier.Absolute) + { + d1 = Math.Abs(d1); + d2 = Math.Abs(d2); + } + + if (d1 == d2) + return true; + + break; + + case UniversalType.AngleDegrees: + case UniversalType.AngleByte: + case UniversalType.Color: + case UniversalType.EnumBits: + case UniversalType.EnumOption: + case UniversalType.Integer: + case UniversalType.LinedefTag: + case UniversalType.LinedefType: + case UniversalType.SectorEffect: + case UniversalType.SectorTag: + case UniversalType.ThingTag: + case UniversalType.ThingType: + int i1 = (int)uv1.Value; + int i2 = (int)uv2.Value; + + if (ufam == UDMFFieldAssociationModifier.Absolute) + { + i1 = Math.Abs(i1); + i2 = Math.Abs(i2); + } + + if (i1 == i2 && i1 != (int)def) + return true; + + break; + + case UniversalType.Boolean: + if ((bool)uv1.Value == (bool)uv2.Value) + return true; + break; + + case UniversalType.Flat: + case UniversalType.String: + case UniversalType.Texture: + case UniversalType.EnumStrings: + case UniversalType.ThingClass: + if ((string)uv1.Value == (string)uv2.Value) + return true; + break; + } + + return false; + } + + /// + /// Checks if the given sector has UDMF fields that have associations + /// + /// Sector to check + /// True if the sector has UDMF fiels associations + public static bool SectorHasUDMFFieldAssociations(Sector sector) + { + foreach (UniversalFieldInfo ufi in General.Map.Config.SectorFields) + { + if (sector.Fields.ContainsKey(ufi.Name)) + return true; + } + + return false; + } /// /// Renders associated things and sectors in the indication color.