TilemapTilesetCollection.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. namespace MonoGame.Extended.Tilemaps
  5. {
  6. /// <summary>
  7. /// A collection of tilesets used by a tilemap.
  8. /// </summary>
  9. public class TilemapTilesetCollection : IReadOnlyList<TilemapTileset>
  10. {
  11. private readonly List<TilemapTileset> _tilesets = new();
  12. /// <summary>
  13. /// Gets the tileset at the specified index.
  14. /// </summary>
  15. /// <param name="index">The zero-based index of the tileset to get.</param>
  16. /// <returns>The tileset at the specified index.</returns>
  17. public TilemapTileset this[int index]
  18. {
  19. get
  20. {
  21. return _tilesets[index];
  22. }
  23. }
  24. /// <summary>
  25. /// Gets the number of tilesets in the collection.
  26. /// </summary>
  27. public int Count
  28. {
  29. get
  30. {
  31. return _tilesets.Count;
  32. }
  33. }
  34. /// <summary>
  35. /// Adds a tileset to the collection.
  36. /// </summary>
  37. /// <param name="tileset">The tileset to add.</param>
  38. /// <remarks>
  39. /// This method is not thread-safe. If multiple threads are accessing the collection,
  40. /// external synchronization is required.
  41. /// </remarks>
  42. public void Add(TilemapTileset tileset)
  43. {
  44. if (tileset == null)
  45. throw new ArgumentNullException(nameof(tileset));
  46. _tilesets.Add(tileset);
  47. }
  48. /// <summary>
  49. /// Removes a tileset from the collection.
  50. /// </summary>
  51. /// <param name="tileset">The tileset to remove.</param>
  52. /// <returns><see langword="true"/> if the tileset was removed; otherwise, <see langword="false"/>.</returns>
  53. /// <remarks>
  54. /// This is an O(n) operation. This method is not thread-safe.
  55. /// </remarks>
  56. public bool Remove(TilemapTileset tileset)
  57. {
  58. return _tilesets.Remove(tileset);
  59. }
  60. /// <summary>
  61. /// Removes all tilesets from the collection.
  62. /// </summary>
  63. /// <remarks>
  64. /// <strong>Warning:</strong> This operation cannot be undone and will remove all tileset references.
  65. /// This method is not thread-safe.
  66. /// </remarks>
  67. public void Clear()
  68. {
  69. _tilesets.Clear();
  70. }
  71. /// <summary>
  72. /// Gets the tileset that contains the specified global tile ID.
  73. /// </summary>
  74. /// <param name="globalTileId">The global tile ID.</param>
  75. /// <returns>The tileset containing the tile, or <see langword="null"/> if not found.</returns>
  76. public TilemapTileset GetTilesetForGid(int globalTileId)
  77. {
  78. // Tilesets are ordered by FirstGlobalId
  79. // Find the tileset where: globalTileId >= FirstGlobalId
  80. // and globalTileId < next tileset's FirstGlobalId
  81. TilemapTileset result = null;
  82. for (int i = 0; i < _tilesets.Count; i++)
  83. {
  84. var tileset = _tilesets[i];
  85. // Check if this tile ID belongs to this tileset
  86. if (globalTileId >= tileset.FirstGlobalId)
  87. {
  88. // Check if this GID is within the tileset's range
  89. int localId = globalTileId - tileset.FirstGlobalId;
  90. if(localId < tileset.TileCount)
  91. {
  92. result = tileset;
  93. break;
  94. }
  95. }
  96. }
  97. return result;
  98. }
  99. /// <summary>
  100. /// Gets the local tile ID within a tileset from a global tile ID.
  101. /// </summary>
  102. /// <param name="globalTileId">The global tile ID.</param>
  103. /// <param name="tileset">When this method returns, contains the tileset that owns the tile.</param>
  104. /// <returns>The local tile ID within the tileset.</returns>
  105. /// <exception cref="InvalidOperationException">No tileset contains the specified global tile ID.</exception>
  106. public int GetLocalId(int globalTileId, out TilemapTileset tileset)
  107. {
  108. var foundTileset = GetTilesetForGid(globalTileId);
  109. if (foundTileset == null)
  110. {
  111. throw new InvalidOperationException($"No tileset found for global tile ID {globalTileId}.");
  112. }
  113. tileset = foundTileset;
  114. return globalTileId - foundTileset.FirstGlobalId;
  115. }
  116. public IEnumerator<TilemapTileset> GetEnumerator()
  117. {
  118. return _tilesets.GetEnumerator();
  119. }
  120. IEnumerator IEnumerable.GetEnumerator()
  121. {
  122. return GetEnumerator();
  123. }
  124. }
  125. }