diff --git a/Sources/FirebladeECS/Entity.swift b/Sources/FirebladeECS/Entity.swift index d5a290e..4a43f05 100644 --- a/Sources/FirebladeECS/Entity.swift +++ b/Sources/FirebladeECS/Entity.swift @@ -133,6 +133,7 @@ extension Entity { } } } +extension Entity.ComponentsIterator: Sequence { } extension Entity: Equatable { public static func == (lhs: Entity, rhs: Entity) -> Bool { diff --git a/Sources/FirebladeECS/Nexus+Entity.swift b/Sources/FirebladeECS/Nexus+Entity.swift index 772da3e..76d1bd1 100644 --- a/Sources/FirebladeECS/Nexus+Entity.swift +++ b/Sources/FirebladeECS/Nexus+Entity.swift @@ -33,6 +33,13 @@ extension Nexus { componentIdsByEntity.keys.count } + /// Creates an iterator over all entities in the nexus. + /// + /// Entity order is not guaranteed to stay the same over iterations. + public func makeEntitiesIterator() -> EntitiesIterator { + EntitiesIterator(nexus: self) + } + public func exists(entity entityId: EntityIdentifier) -> Bool { componentIdsByEntity.keys.contains(entityId) } @@ -67,3 +74,26 @@ extension Nexus { return true } } + +// MARK: - entities iterator +extension Nexus { + public struct EntitiesIterator: IteratorProtocol { + private var iterator: AnyIterator + + @usableFromInline + init(nexus: Nexus) { + var iter = nexus.componentIdsByEntity.keys.makeIterator() + iterator = AnyIterator { + guard let entityId = iter.next() else { + return nil + } + return Entity(nexus: nexus, id: entityId) + } + } + + public func next() -> Entity? { + iterator.next() + } + } +} +extension Nexus.EntitiesIterator: Sequence { } diff --git a/Tests/FirebladeECSTests/NexusTests.swift b/Tests/FirebladeECSTests/NexusTests.swift index 714db97..3468e40 100644 --- a/Tests/FirebladeECSTests/NexusTests.swift +++ b/Tests/FirebladeECSTests/NexusTests.swift @@ -155,4 +155,15 @@ class NexusTests: XCTestCase { XCTAssert(pB.x != pA.x) XCTAssert(pB.y != pA.y) } + + func testEntityIteration() { + nexus.createEntities(count: 1000) { ctx in Position(x: ctx.index, y: ctx.index) } + + let entityArray = [Entity](nexus.makeEntitiesIterator()).lazy + + XCTAssertEqual(entityArray.count, 1000) + + XCTAssertTrue(entityArray.contains(where: { $0.identifier.index == 0 })) + XCTAssertTrue(entityArray.contains(where: { $0.identifier.index == 999 })) + } } diff --git a/Tests/FirebladeECSTests/XCTestManifests.swift b/Tests/FirebladeECSTests/XCTestManifests.swift index c9b2465..97a839f 100644 --- a/Tests/FirebladeECSTests/XCTestManifests.swift +++ b/Tests/FirebladeECSTests/XCTestManifests.swift @@ -342,7 +342,8 @@ extension NexusTests { ("testComponentRetrieval", testComponentRetrieval), ("testComponentUniqueness", testComponentUniqueness), ("testEntityCreate", testEntityCreate), - ("testEntityDestroy", testEntityDestroy) + ("testEntityDestroy", testEntityDestroy), + ("testEntityIteration", testEntityIteration) ] }