public static MemberInfo[] FindWritablePropertiesWithCustomAttribute(this Type contract, Type customAttributeType) { FasterList <MemberInfo> propertyList = new FasterList <MemberInfo>(8); do { var propertyInfos = contract.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.DeclaredOnly | System.Reflection.BindingFlags.Instance); for (int i = 0; i < propertyInfos.Length; i++) { PropertyInfo propertyInfo = propertyInfos[i]; if (propertyInfo.CanWrite && propertyInfo.ContainsCustomAttribute(customAttributeType, false) == true) { propertyList.Add(propertyInfo); } } contract = contract.GetBaseType(); } while (contract != null); if (propertyList.Count > 0) { return(propertyList.ToArray()); } return(null); }
static SerializableEntityDescriptor() { IEntityBuilder[] defaultEntities = EntityDescriptorTemplate <TType> .descriptor.entitiesToBuild; var hashNameAttribute = _type.GetCustomAttribute <HashNameAttribute>(); if (hashNameAttribute == null) { throw new Exception("HashName attribute not found on the serializable type ".FastConcat(_type.FullName)); } _hash = DesignatedHash.Hash(Encoding.ASCII.GetBytes(hashNameAttribute._name)); var(index, dynamicIndex) = SetupSpecialEntityStruct(defaultEntities, out _entitiesToBuild); if (index == -1) { index = _entitiesToBuild.Length - 1; } // Stores the hash of this EntityDescriptor _entitiesToBuild[index] = new EntityBuilder <SerializableEntityStruct> ( new SerializableEntityStruct { descriptorHash = _hash } ); // If the current serializable is an ExtendibleDescriptor, I have to update it. if (dynamicIndex != -1) { _entitiesToBuild[dynamicIndex] = new EntityBuilder <EntityStructInfoView> ( new EntityStructInfoView { entitiesToBuild = _entitiesToBuild } ); } ///// var entitiesToSerialize = new FasterList <ISerializableEntityBuilder>(); _entitiesToSerializeMap = new FasterDictionary <RefWrapper <Type>, ISerializableEntityBuilder>(); foreach (IEntityBuilder e in defaultEntities) { if (e is ISerializableEntityBuilder serializableEntityBuilder) { var entityType = serializableEntityBuilder.GetEntityType(); _entitiesToSerializeMap[new RefWrapper <Type>(entityType)] = serializableEntityBuilder; entitiesToSerialize.Add(serializableEntityBuilder); } } _entitiesToSerialize = entitiesToSerialize.ToArray(); }
private static ProcessedVoxelObjectNotation[] groupBlocksBestEffort(ProcessedVoxelObjectNotation[] blocksToOptimise, int id) { // a really complicated algorithm to determine if two similar blocks are touching (before they're placed) // the general concept: // two blocks are touching when they have a common face (equal to 4 corners on the cube, where the 4 corners aren't completely opposite each other) // between the two blocks, the 8 corners that aren't in common are the corners for the merged block // // to merge the 2 blocks, switch out the 4 common corners of one block with the nearest non-common corners from the other block // i.e. swap the common face on block A with the face opposite the common face of block B // to prevent a nonsensical face (rotated compared to other faces), the corners of the face should be swapped out with the corresponding corner which shares an edge // // note: e.g. if common face on block A is its top, the common face of block B is not necessarily the bottom face because blocks can be rotated differently // this means it's not safe to assume that block A's common face (top) can be swapped with block B's non-common opposite face (top) to get the merged block // // note2: this does not work with blocks which aren't cubes (i.e. any block where rotation matters) try { #if DEBUG Stopwatch timer = Stopwatch.StartNew(); #endif FasterList <ProcessedVoxelObjectNotation> optVONs = new FasterList <ProcessedVoxelObjectNotation>(blocksToOptimise); int item = 0; while (item < optVONs.count - 1) { #if DEBUG Logging.MetaLog($"({id}) Now grouping item {item}/{optVONs.count} ({100f * item/(float)optVONs.count}%)"); #endif bool isItemUpdated = false; ProcessedVoxelObjectNotation itemVON = optVONs[item]; if (isOptimisableBlock(itemVON.block)) { float3[] itemCorners = calculateCorners(itemVON); int seeker = item + 1; // despite this, assume that seeker goes thru the entire list (not just blocks after item) while (seeker < optVONs.count) { if (seeker == item) { seeker++; } else { ProcessedVoxelObjectNotation seekerVON = optVONs[seeker]; //Logging.MetaLog($"Comparing {itemVON} and {seekerVON}"); float3[] seekerCorners = calculateCorners(seekerVON); int[][] mapping = findMatchingCorners(itemCorners, seekerCorners); if (mapping.Length != 0 && itemVON.block == seekerVON.block && itemVON.color.Color == seekerVON.color.Color && itemVON.color.Darkness == seekerVON.color.Darkness && isOptimisableBlock(seekerVON.block)) // match found { // switch out corners based on mapping //Logging.MetaLog($"Corners {float3ArrToString(itemCorners)}\nand {float3ArrToString(seekerCorners)}"); //Logging.MetaLog($"Mappings (len:{mapping[0].Length}) {mapping[0][0]} -> {mapping[1][0]}\n{mapping[0][1]} -> {mapping[1][1]}\n{mapping[0][2]} -> {mapping[1][2]}\n{mapping[0][3]} -> {mapping[1][3]}\n"); for (byte i = 0; i < 4; i++) { itemCorners[mapping[0][i]] = seekerCorners[mapping[1][i]]; } // remove 2nd block, since it's now part of the 1st block //Logging.MetaLog($"Removing {seekerVON}"); optVONs.RemoveAt(seeker); if (seeker < item) { item--; // note: this will never become less than 0 } isItemUpdated = true; // regenerate info //Logging.MetaLog($"Final corners {float3ArrToString(itemCorners)}"); updateVonFromCorners(itemCorners, ref itemVON); itemCorners = calculateCorners(itemVON); //Logging.MetaLog($"Merged block is {itemVON}"); } else { seeker++; } } } if (isItemUpdated) { optVONs[item] = itemVON; //Logging.MetaLog($"Optimised block is now {itemVON}"); } item++; } else { item++; } } #if DEBUG timer.Stop(); Logging.MetaLog($"({id}) Completed best effort grouping of range in {timer.ElapsedMilliseconds}ms"); #endif return(optVONs.ToArray()); } catch (Exception e) { Logging.MetaLog($"({id}) Exception occured...\n{e.ToString()}"); } return(blocksToOptimise); }