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.