diff --git a/Sources/FirebladeECS/Components1.swift b/Sources/FirebladeECS/Components1.swift index 5b9e33d..8084f6a 100644 --- a/Sources/FirebladeECS/Components1.swift +++ b/Sources/FirebladeECS/Components1.swift @@ -14,10 +14,16 @@ public struct Components1: ComponentsProviding where A: Component { componentTypes = [A.self] } - public static func getComponents(nexus: Nexus, entityId: EntityIdentifier) -> (A) { + public static func components(nexus: Nexus, entityId: EntityIdentifier) -> (A) { let compA: A = nexus.get(unsafeComponentFor: entityId) return (compA) } + + public static func entityAndComponents(nexus: Nexus, entityId: EntityIdentifier) -> (Entity, A) { + let entity: Entity = nexus.get(unsafeEntity: entityId) + let compA: A = nexus.get(unsafeComponentFor: entityId) + return (entity, compA) + } } extension Nexus { diff --git a/Sources/FirebladeECS/Components2.swift b/Sources/FirebladeECS/Components2.swift index daf866b..b86aea0 100644 --- a/Sources/FirebladeECS/Components2.swift +++ b/Sources/FirebladeECS/Components2.swift @@ -13,11 +13,18 @@ public struct Components2: ComponentsProviding where A: Component, B: Comp public init(_ components: (A.Type, B.Type)) { componentTypes = [ A.self, B.self] } - public static func getComponents(nexus: Nexus, entityId: EntityIdentifier) -> (A, B) { + public static func components(nexus: Nexus, entityId: EntityIdentifier) -> (A, B) { let compA: A = nexus.get(unsafeComponentFor: entityId) let compB: B = nexus.get(unsafeComponentFor: entityId) return (compA, compB) } + + public static func entityAndComponents(nexus: Nexus, entityId: EntityIdentifier) -> (Entity, A, B) { + let entity: Entity = nexus.get(unsafeEntity: entityId) + let compA: A = nexus.get(unsafeComponentFor: entityId) + let compB: B = nexus.get(unsafeComponentFor: entityId) + return (entity, compA, compB) + } } extension Nexus { diff --git a/Sources/FirebladeECS/Components3.swift b/Sources/FirebladeECS/Components3.swift index d5b25ba..d0b4450 100644 --- a/Sources/FirebladeECS/Components3.swift +++ b/Sources/FirebladeECS/Components3.swift @@ -13,12 +13,20 @@ public struct Components3: ComponentsProviding where A: Component, B: C componentTypes = [A.self, B.self, C.self] } - public static func getComponents(nexus: Nexus, entityId: EntityIdentifier) -> (A, B, C) { + public static func components(nexus: Nexus, entityId: EntityIdentifier) -> (A, B, C) { let compA: A = nexus.get(unsafeComponentFor: entityId) let compB: B = nexus.get(unsafeComponentFor: entityId) let compC: C = nexus.get(unsafeComponentFor: entityId) return (compA, compB, compC) } + + public static func entityAndComponents(nexus: Nexus, entityId: EntityIdentifier) -> (Entity, A, B, C) { + let entity: Entity = nexus.get(unsafeEntity: entityId) + let compA: A = nexus.get(unsafeComponentFor: entityId) + let compB: B = nexus.get(unsafeComponentFor: entityId) + let compC: C = nexus.get(unsafeComponentFor: entityId) + return (entity, compA, compB, compC) + } } extension Nexus { diff --git a/Sources/FirebladeECS/Components4.swift b/Sources/FirebladeECS/Components4.swift index d981a13..6294f11 100644 --- a/Sources/FirebladeECS/Components4.swift +++ b/Sources/FirebladeECS/Components4.swift @@ -13,13 +13,22 @@ public struct Components4: ComponentsProviding where A: Component, B componentTypes = [A.self, B.self, C.self, D.self] } - public static func getComponents(nexus: Nexus, entityId: EntityIdentifier) -> (A, B, C, D) { + public static func components(nexus: Nexus, entityId: EntityIdentifier) -> (A, B, C, D) { let compA: A = nexus.get(unsafeComponentFor: entityId) let compB: B = nexus.get(unsafeComponentFor: entityId) let compC: C = nexus.get(unsafeComponentFor: entityId) let compD: D = nexus.get(unsafeComponentFor: entityId) return (compA, compB, compC, compD) } + + public static func entityAndComponents(nexus: Nexus, entityId: EntityIdentifier) -> (Entity, A, B, C, D) { + let entity: Entity = nexus.get(unsafeEntity: entityId) + let compA: A = nexus.get(unsafeComponentFor: entityId) + let compB: B = nexus.get(unsafeComponentFor: entityId) + let compC: C = nexus.get(unsafeComponentFor: entityId) + let compD: D = nexus.get(unsafeComponentFor: entityId) + return (entity, compA, compB, compC, compD) + } } extension Nexus { diff --git a/Sources/FirebladeECS/Components5.swift b/Sources/FirebladeECS/Components5.swift index 27966f7..6b5954b 100644 --- a/Sources/FirebladeECS/Components5.swift +++ b/Sources/FirebladeECS/Components5.swift @@ -13,7 +13,7 @@ public struct Components5: ComponentsProviding where A: Component componentTypes = [A.self, B.self, C.self, D.self, E.self] } - public static func getComponents(nexus: Nexus, entityId: EntityIdentifier) -> (A, B, C, D, E) { + public static func components(nexus: Nexus, entityId: EntityIdentifier) -> (A, B, C, D, E) { let compA: A = nexus.get(unsafeComponentFor: entityId) let compB: B = nexus.get(unsafeComponentFor: entityId) let compC: C = nexus.get(unsafeComponentFor: entityId) @@ -21,6 +21,16 @@ public struct Components5: ComponentsProviding where A: Component let compE: E = nexus.get(unsafeComponentFor: entityId) return (compA, compB, compC, compD, compE) } + + public static func entityAndComponents(nexus: Nexus, entityId: EntityIdentifier) -> (Entity, A, B, C, D, E) { + let entity = nexus.get(unsafeEntity: entityId) + let compA: A = nexus.get(unsafeComponentFor: entityId) + let compB: B = nexus.get(unsafeComponentFor: entityId) + let compC: C = nexus.get(unsafeComponentFor: entityId) + let compD: D = nexus.get(unsafeComponentFor: entityId) + let compE: E = nexus.get(unsafeComponentFor: entityId) + return (entity, compA, compB, compC, compD, compE) + } } extension Nexus { diff --git a/Sources/FirebladeECS/ComponentsProviding.swift b/Sources/FirebladeECS/ComponentsProviding.swift index 10f4494..8483b22 100644 --- a/Sources/FirebladeECS/ComponentsProviding.swift +++ b/Sources/FirebladeECS/ComponentsProviding.swift @@ -8,7 +8,9 @@ public protocol ComponentsProviding { associatedtype Components associatedtype ComponentTypes + associatedtype EntityAndComponents init(_ types: ComponentTypes) var componentTypes: [Component.Type] { get } - static func getComponents(nexus: Nexus, entityId: EntityIdentifier) -> Components + static func components(nexus: Nexus, entityId: EntityIdentifier) -> Components + static func entityAndComponents(nexus: Nexus, entityId: EntityIdentifier) -> EntityAndComponents } diff --git a/Sources/FirebladeECS/Family.swift b/Sources/FirebladeECS/Family.swift index 45cba8d..47b2ba1 100644 --- a/Sources/FirebladeECS/Family.swift +++ b/Sources/FirebladeECS/Family.swift @@ -12,14 +12,16 @@ public struct Family where R: ComponentsProviding { public init(nexus: Nexus, requiresAll: @autoclosure () -> (R.ComponentTypes), excludesAll: [Component.Type]) { let required = R(requiresAll()) self.nexus = nexus - traits = FamilyTraitSet(requiresAll: required.componentTypes, excludesAll: excludesAll) + let traits = FamilyTraitSet(requiresAll: required.componentTypes, excludesAll: excludesAll) + self.traits = traits + nexus.onFamilyInit(traits: traits) } @inlinable public var memberIds: UnorderedSparseSet { return nexus.members(withFamilyTraits: traits) } - @inlinable public var count: Int { + @inlinable public var count: Int { return memberIds.count } @@ -27,10 +29,6 @@ public struct Family where R: ComponentsProviding { return memberIds.isEmpty } - @inlinable public var entities: FamilyEntities { - return FamilyEntities(nexus, memberIds) - } - @inlinable public func canBecomeMember(_ entity: Entity) -> Bool { return nexus.canBecomeMember(entity, in: traits) @@ -42,8 +40,17 @@ public struct Family where R: ComponentsProviding { } } +extension Family: Sequence { + __consuming public func makeIterator() -> ComponentsIterator { + return ComponentsIterator(family: self) + } +} + +extension Family: LazySequenceProtocol { } + +// MARK: - components iterator extension Family { - public struct FamilyIterator: IteratorProtocol { + public struct ComponentsIterator: IteratorProtocol { @usableFromInline var memberIdsIterator: UnorderedSparseSetIterator @usableFromInline unowned let nexus: Nexus @@ -57,13 +64,64 @@ extension Family { return nil } - return R.getComponents(nexus: nexus, entityId: entityId) + return R.components(nexus: nexus, entityId: entityId) } } } -extension Family: Sequence { - __consuming public func makeIterator() -> FamilyIterator { - return FamilyIterator(family: self) +extension Family.ComponentsIterator: LazySequenceProtocol { } + +// MARK: - entity iterator +extension Family { + @inlinable public var entities: EntityIterator { + return EntityIterator(family: self) + } + + public struct EntityIterator: IteratorProtocol { + @usableFromInline var memberIdsIterator: UnorderedSparseSetIterator + @usableFromInline unowned let nexus: Nexus + + public init(family: Family) { + self.nexus = family.nexus + memberIdsIterator = family.memberIds.makeIterator() + } + + public mutating func next() -> Entity? { + guard let entityId = memberIdsIterator.next() else { + return nil + } + return nexus.get(unsafeEntity: entityId) + } } } + +extension Family.EntityIterator: LazySequenceProtocol { } + +// MARK: - entity component iterator +extension Family { + @inlinable public var entityAndComponents: EntityComponentIterator { + return EntityComponentIterator(family: self) + } + + public struct EntityComponentIterator: IteratorProtocol { + @usableFromInline var memberIdsIterator: UnorderedSparseSetIterator + @usableFromInline unowned let nexus: Nexus + + public init(family: Family) { + self.nexus = family.nexus + memberIdsIterator = family.memberIds.makeIterator() + } + + public mutating func next() -> R.EntityAndComponents? { + guard let entityId = memberIdsIterator.next() else { + return nil + } + return R.entityAndComponents(nexus: nexus, entityId: entityId) + } + } +} + +extension Family.EntityComponentIterator: LazySequenceProtocol { } + +// MARK: - Equatable +extension Family: Equatable { } diff --git a/Sources/FirebladeECS/FamilyEntities.swift b/Sources/FirebladeECS/FamilyEntities.swift deleted file mode 100644 index 025bfd5..0000000 --- a/Sources/FirebladeECS/FamilyEntities.swift +++ /dev/null @@ -1,30 +0,0 @@ -// -// FamilyEntities.swift -// -// -// Created by Christian Treffs on 21.08.19. -// - -public struct FamilyEntities { - public let nexus: Nexus - public var memberIdsIterator: UnorderedSparseSetIterator - - public init(_ nexus: Nexus, _ memberIds: UnorderedSparseSet) { - self.nexus = nexus - memberIdsIterator = memberIds.makeIterator() - } -} - -extension FamilyEntities: IteratorProtocol { - public mutating func next() -> Entity? { - guard let entityId = memberIdsIterator.next() else { - return nil - } - - return nexus.get(entity: entityId) - } -} - -extension FamilyEntities: LazySequenceProtocol { } - -// TODO: extension FamilyEntities: Equatable { } diff --git a/Tests/FirebladeECSTests/FamilyTests.swift b/Tests/FirebladeECSTests/FamilyTests.swift index 7e6506b..acdb36f 100644 --- a/Tests/FirebladeECSTests/FamilyTests.swift +++ b/Tests/FirebladeECSTests/FamilyTests.swift @@ -5,7 +5,7 @@ // Created by Christian Treffs on 09.10.17. // -import FirebladeECS +@testable import FirebladeECS import XCTest class FamilyTests: XCTestCase {