diff --git a/packages/tiled/lib/src/tiled_map.dart b/packages/tiled/lib/src/tiled_map.dart index 8b7bb5b..270f425 100644 --- a/packages/tiled/lib/src/tiled_map.dart +++ b/packages/tiled/lib/src/tiled_map.dart @@ -91,6 +91,9 @@ class TiledMap { List editorSettings; CustomProperties properties; + // Cache the object by ID when accessed. + Map? _cachedObjects; + // only for hexagonal maps: int? hexSideLength; StaggerAxis? staggerAxis; @@ -279,6 +282,27 @@ class TiledMap { throw ArgumentError('Layer $name not found'); } + /// Finds the [TiledObject] in this map with the unique [id]. + /// Objects have map wide unique IDs which are never reused. + /// https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#object + /// + /// This reads through a cached map of all the objects so it does not + /// need to loop through all the object layers each time. + /// + /// Returns null if not found. + TiledObject? objectById(int id) { + if (_cachedObjects == null) { + _cachedObjects = {}; + layers.whereType().forEach((objectGroup) { + for (final object in objectGroup.objects) { + _cachedObjects![object.id] = object; + } + }); + } + + return _cachedObjects?[id]; + } + Tileset tilesetByName(String name) { return tilesets.firstWhere( (element) => element.name == name, diff --git a/packages/tiled/test/map_test.dart b/packages/tiled/test/map_test.dart index 9b1acd3..7f91085 100644 --- a/packages/tiled/test/map_test.dart +++ b/packages/tiled/test/map_test.dart @@ -380,4 +380,55 @@ void main() { expect(map.tilesetByName('Humans'), equals(tileset)); }); }); + + group('Map.objectById', () { + late TiledMap map; + setUp(() { + map = TiledMap( + width: 2, + height: 2, + tileWidth: 8, + tileHeight: 8, + layers: [ + TileLayer( + name: 'tile layer 1', + width: 2, + height: 2, + data: [1, 0, 2, 0], + ), + ObjectGroup( + name: 'object layer 1', + objects: [ + TiledObject(id: 1, name: 'object one'), + TiledObject(id: 5, name: 'object five'), + ], + ), + ], + tilesets: [ + Tileset( + name: 'TileSet_1', + image: const TiledImage(source: 'tileset_1.png'), + firstGid: 1, + columns: 1, + tileCount: 2, + tiles: [ + Tile(localId: 0), + Tile(localId: 1), + ], + ), + ], + ); + }); + + test('gets images only in use on each TileLayer', () { + final object1 = map.objectById(1); + expect(object1?.name, equals('object one')); + + final object5 = map.objectById(5); + expect(object5?.name, equals('object five')); + + final object3 = map.objectById(3); + expect(object3, equals(null)); + }); + }); }