From eacbc8ff370a592c2361fef9a355637981b304ac Mon Sep 17 00:00:00 2001 From: Will Date: Sat, 24 Oct 2015 23:46:42 -0600 Subject: [PATCH] Add custom attributes for Index and Count members of some lumps to indicate which lump they refer to. These can be used with BSP.GetReferencedObjects to get all objects of one lump referred to by an object from another. --- LibBSP/src/Attributes/CountAttribute.cs | 24 +++++++ LibBSP/src/Attributes/IndexAttribute.cs | 24 +++++++ .../Extensions/CustomAttributeExtensions.cs | 16 +++++ LibBSP/src/Structs/BSP/BSP.cs | 62 +++++++++++++++++++ LibBSP/src/Structs/BSP/Brush.cs | 4 +- LibBSP/src/Structs/BSP/Face.cs | 12 ++-- LibBSP/src/Structs/BSP/Leaf.cs | 8 +-- .../Structs/BSP/Lumps/SourceDispVertices.cs | 2 +- LibBSP/src/Structs/BSP/Model.cs | 12 ++-- 9 files changed, 145 insertions(+), 19 deletions(-) create mode 100644 LibBSP/src/Attributes/CountAttribute.cs create mode 100644 LibBSP/src/Attributes/IndexAttribute.cs create mode 100644 LibBSP/src/Extensions/CustomAttributeExtensions.cs diff --git a/LibBSP/src/Attributes/CountAttribute.cs b/LibBSP/src/Attributes/CountAttribute.cs new file mode 100644 index 0000000..97669e3 --- /dev/null +++ b/LibBSP/src/Attributes/CountAttribute.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; + +namespace LibBSP { + /// + /// Custom Attribute class to mark a member of a struct as an count for another lump. The + /// member this Attribute is applied to should always be paired with a member with an Index + /// Attribute applied to it. The two attributes can the be used to grab a range of objects + /// from the specified lump through the BSP.GetReferencedObjects<T> method. + /// + public class CountAttribute : Attribute { + + public string lumpName; + + /// + /// Constructs a new instance of an CountAttribute object. The member this Attribute + /// is applied to will be used as a count of objects in the lump referenced by . + /// + /// The lump the member is an count for. Corresponds to the public properties in the BSP class. + public CountAttribute(string lumpName) { + this.lumpName = lumpName; + } + } +} diff --git a/LibBSP/src/Attributes/IndexAttribute.cs b/LibBSP/src/Attributes/IndexAttribute.cs new file mode 100644 index 0000000..3631401 --- /dev/null +++ b/LibBSP/src/Attributes/IndexAttribute.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; + +namespace LibBSP { + /// + /// Custom Attribute class to mark a member of a struct as an index into another lump. The + /// member this Attribute is applied to should always be paired with a member with a Count + /// Attribute applied to it. The two attributes can the be used to grab a range of objects + /// from the specified lump through the BSP.GetReferencedObjects<T> method. + /// + public class IndexAttribute : Attribute { + + public string lumpName; + + /// + /// Constructs a new instance of an IndexAttribute object. The member this Attribute + /// is applied to will be used as an index into the lump referenced by . + /// + /// The lump the member is an index into. Corresponds to the public properties in the BSP class. + public IndexAttribute(string lumpName) { + this.lumpName = lumpName; + } + } +} diff --git a/LibBSP/src/Extensions/CustomAttributeExtensions.cs b/LibBSP/src/Extensions/CustomAttributeExtensions.cs new file mode 100644 index 0000000..7fef756 --- /dev/null +++ b/LibBSP/src/Extensions/CustomAttributeExtensions.cs @@ -0,0 +1,16 @@ +#if (UNITY_2_6 || UNITY_2_6_1 || UNITY_3_0 || UNITY_3_0_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5) + +using System; +using System.Reflection; + +namespace LibBSP { + public static class CustomAttributeExtensions { + + public static T GetCustomAttribute(this MemberInfo element) where T : Attribute { + return Attribute.GetCustomAttribute(element, typeof(T)) as T; + } + + } +} + +#endif diff --git a/LibBSP/src/Structs/BSP/BSP.cs b/LibBSP/src/Structs/BSP/BSP.cs index b226b3e..a9f07be 100644 --- a/LibBSP/src/Structs/BSP/BSP.cs +++ b/LibBSP/src/Structs/BSP/BSP.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Collections.Generic; +using System.Reflection; #if UNITY using UnityEngine; #endif @@ -435,5 +436,66 @@ namespace LibBSP { reader = new BSPReader(file); this.filePath = file.FullName; } + + /// + /// Gets all objects of type referenced through passed object + /// contained in the lump stored in this BSP class. This is done by + /// reflecting the Type of and looping through its public properties to find + /// a member with an IndexAttribute attribute and a member with CountAttribute attribute + /// both corresponding to . The index and count are obtained and used to construct + /// a new List<> object containing the corresponding objects. + /// + /// The type of object stored in the lump . + /// The object which contains and index and count corresponding to . + /// The name of the property in this BSP object to get a List of objects from. + /// The List<> of objects in the lump from the index and length specified in . + /// The BSP class contains no property corresponding to . + /// The object referenced by is missing one or both members with IndexAttribute or CountAttribute attributes corresponding to . + public List GetReferencedObjects(object o, string lumpName) + { + // First, find the property in this class corresponding to lumpName, and grab its "get" method + PropertyInfo targetLump = typeof(BSP).GetProperty(lumpName, BindingFlags.Public | BindingFlags.Instance); + if (targetLump == null) { + throw new ArgumentException("The lump " + lumpName + " does not exist in the BSP class"); + } + + // Next, find the properties in the passed object corresponding to lumpName, through the Index and Length custom attributes + Type objectType = o.GetType(); + PropertyInfo[] objectProperties = objectType.GetProperties(BindingFlags.Public | BindingFlags.Instance); + PropertyInfo indexProperty = null; + PropertyInfo countProperty = null; + foreach (PropertyInfo info in objectProperties) { + IndexAttribute indexAttribute = info.GetCustomAttribute(); + if (indexAttribute != null) { + if (indexAttribute.lumpName == lumpName) { + indexProperty = info; + if (indexProperty != null && countProperty != null) { + break; + } + } + } + CountAttribute lengthAttribute = info.GetCustomAttribute(); + if (lengthAttribute != null) { + if (lengthAttribute.lumpName == lumpName) { + countProperty = info; + if (indexProperty != null && countProperty != null) { + break; + } + } + } + } + if (indexProperty == null || countProperty == null) { + throw new ArgumentException("An object of type " + objectType.Name + " does not implement both an Index and Count for lump " + lumpName); + } + + // Get the index and length from the object + int index = (int)indexProperty.GetGetMethod().Invoke(o, null); + int count = (int)countProperty.GetGetMethod().Invoke(o, null); + + // Get the lump from this class + List theLump = targetLump.GetGetMethod().Invoke(this, null) as List; + + return theLump.GetRange(index, count); + } } } diff --git a/LibBSP/src/Structs/BSP/Brush.cs b/LibBSP/src/Structs/BSP/Brush.cs index 40d33a5..5af44dc 100644 --- a/LibBSP/src/Structs/BSP/Brush.cs +++ b/LibBSP/src/Structs/BSP/Brush.cs @@ -7,8 +7,8 @@ namespace LibBSP { /// public struct Brush { - public int firstSide { get; private set; } - public int numSides { get; private set; } + [Index("brushSides")] public int firstSide { get; private set; } + [Count("brushSides")] public int numSides { get; private set; } public int texture { get; private set; } public int contents { get; private set; } diff --git a/LibBSP/src/Structs/BSP/Face.cs b/LibBSP/src/Structs/BSP/Face.cs index 72016cc..a37d84a 100644 --- a/LibBSP/src/Structs/BSP/Face.cs +++ b/LibBSP/src/Structs/BSP/Face.cs @@ -26,18 +26,18 @@ namespace LibBSP { public int plane { get; private set; } public int side { get; private set; } - public int firstEdge { get; private set; } - public int numEdges { get; private set; } + [Index("edges")] public int firstEdge { get; private set; } + [Count("edges")] public int numEdges { get; private set; } public int texture { get; private set; } - public int firstVertex { get; private set; } - public int numVertices { get; private set; } + [Index("vertices")] public int firstVertex { get; private set; } + [Count("vertices")] public int numVertices { get; private set; } public int material { get; private set; } public int textureScale { get; private set; } public int displacement { get; private set; } public int original { get; private set; } public int flags { get; private set; } - public int firstIndex { get; private set; } - public int numIndices { get; private set; } + [Index("indices")] public int firstIndex { get; private set; } + [Count("indices")] public int numIndices { get; private set; } public int unknown { get; private set; } public int lightStyles { get; private set; } public int lightMaps { get; private set; } diff --git a/LibBSP/src/Structs/BSP/Leaf.cs b/LibBSP/src/Structs/BSP/Leaf.cs index d49a241..98d8504 100644 --- a/LibBSP/src/Structs/BSP/Leaf.cs +++ b/LibBSP/src/Structs/BSP/Leaf.cs @@ -8,10 +8,10 @@ namespace LibBSP { public struct Leaf { public int contents { get; private set; } - public int firstMarkBrush { get; private set; } - public int numMarkBrushes { get; private set; } - public int firstMarkFace { get; private set; } - public int numMarkFaces { get; private set; } + [Index("markBrushes")] public int firstMarkBrush { get; private set; } + [Count("markBrushes")] public int numMarkBrushes { get; private set; } + [Index("markSurfaces")] public int firstMarkFace { get; private set; } + [Count("markSurfaces")] public int numMarkFaces { get; private set; } public int pvs { get; private set; } /// diff --git a/LibBSP/src/Structs/BSP/Lumps/SourceDispVertices.cs b/LibBSP/src/Structs/BSP/Lumps/SourceDispVertices.cs index 90cd467..f136e4a 100644 --- a/LibBSP/src/Structs/BSP/Lumps/SourceDispVertices.cs +++ b/LibBSP/src/Structs/BSP/Lumps/SourceDispVertices.cs @@ -31,7 +31,7 @@ namespace LibBSP { /// The first vertex to get /// The power of the displacement /// Array of SourceDispVertex objects containing all the vertices in this displacement - public virtual SourceDispVertex[] GetVertsInDisp(int first, int power) { + public virtual SourceDispVertex[] GetVerticesInDisplacement(int first, int power) { int numVerts = 0; switch (power) { case 2: { diff --git a/LibBSP/src/Structs/BSP/Model.cs b/LibBSP/src/Structs/BSP/Model.cs index c57687f..26a6f10 100644 --- a/LibBSP/src/Structs/BSP/Model.cs +++ b/LibBSP/src/Structs/BSP/Model.cs @@ -17,12 +17,12 @@ namespace LibBSP { public struct Model { public int headNode { get; private set; } // Quake, Half-life, Quake 2, SiN - public int firstLeaf { get; private set; } // 007 nightfire - public int numLeaves { get; private set; } - public int firstBrush { get; private set; } // Quake 3 and derivatives - public int numBrushes { get; private set; } - public int firstFace { get; private set; } // Quake/GoldSrc - public int numFaces { get; private set; } + [Index("leaves")] public int firstLeaf { get; private set; } // 007 nightfire + [Count("leaves")] public int numLeaves { get; private set; } + [Index("brushes")] public int firstBrush { get; private set; } // Quake 3 and derivatives + [Count("brushes")] public int numBrushes { get; private set; } + [Index("faces")] public int firstFace { get; private set; } // Quake/GoldSrc + [Count("faces")] public int numFaces { get; private set; } /// /// Creates a new Model object from a byte array.