Iteration optimizations
This commit is contained in:
parent
e07ac8e248
commit
f3c64d8dac
|
|
@ -9,11 +9,11 @@
|
|||
public extension Entity {
|
||||
|
||||
public final func get<C>() -> C? where C: Component {
|
||||
return nexus.get(component: C.identifier, for: identifier)
|
||||
return nexus.get(for: identifier)
|
||||
}
|
||||
|
||||
public func get<A>(component compType: A.Type = A.self) -> A? where A: Component {
|
||||
return nexus.get(component: A.identifier, for: identifier)
|
||||
return nexus.get(for: identifier)
|
||||
}
|
||||
|
||||
public func getComponent<A>() -> () -> A? where A: Component {
|
||||
|
|
|
|||
|
|
@ -6,138 +6,81 @@
|
|||
//
|
||||
|
||||
extension Family {
|
||||
public func iterateMembers(_ apply: @escaping (EntityIdentifier, () -> Entity) -> Void) {
|
||||
public func iterateMembers(_ apply: @escaping (EntityIdentifier) -> Void) {
|
||||
memberIds.forEach { (entityId: EntityIdentifier) -> Void in
|
||||
func getEntity() -> Entity {
|
||||
return nexus.get(entity: entityId)
|
||||
}
|
||||
apply(entityId, getEntity)
|
||||
apply(entityId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Family {
|
||||
|
||||
public func iterate<A>(components _: A.Type, _ apply: @escaping (() -> Entity, () -> A?) -> Void)
|
||||
public func iterate<A>(components _: A.Type, _ apply: @escaping (EntityIdentifier, A?) -> Void)
|
||||
where A: Component {
|
||||
iterateMembers { (entityId, getEntityInstance) in
|
||||
func getComponent<Z>() -> Z? where Z: Component {
|
||||
return self.nexus.get(component: Z.identifier, for: entityId) as? Z
|
||||
var iter = memberIds.makeIterator()
|
||||
while let entityId: EntityIdentifier = iter.next() {
|
||||
let a: A? = self.nexus.get(for: entityId)
|
||||
apply(entityId, a)
|
||||
}
|
||||
apply(getEntityInstance, getComponent)
|
||||
}
|
||||
}
|
||||
|
||||
public func iterate<A, B>(components _: A.Type, _: B.Type, _ apply: @escaping (() -> Entity, () -> A?, () -> B?) -> Void)
|
||||
public func iterate<A, B>(components _: A.Type, _: B.Type, _ apply: @escaping (EntityIdentifier, A?, B?) -> Void)
|
||||
where A: Component, B: Component {
|
||||
iterateMembers { (entityId, getEntityInstance) in
|
||||
func getComponent<Z>() -> Z? where Z: Component {
|
||||
return self.nexus.get(component: Z.identifier, for: entityId) as? Z
|
||||
var iter = memberIds.makeIterator()
|
||||
while let entityId: EntityIdentifier = iter.next() {
|
||||
let a: A? = self.nexus.get(for: entityId)
|
||||
let b: B? = self.nexus.get(for: entityId)
|
||||
apply(entityId, a, b)
|
||||
}
|
||||
apply(getEntityInstance, getComponent, getComponent)
|
||||
}
|
||||
}
|
||||
|
||||
public func iterate<A, B, C>(components _: A.Type, _: B.Type, _: C.Type, _ apply: @escaping (() -> Entity, () -> A?, () -> B?, () -> C?) -> Void)
|
||||
public func iterate<A, B, C>(components _: A.Type, _: B.Type, _: C.Type, _ apply: @escaping (EntityIdentifier, A?, B?, C?) -> Void)
|
||||
where A: Component, B: Component, C: Component {
|
||||
iterateMembers { (entityId, getEntityInstance) in
|
||||
func getComponent<Z>() -> Z? where Z: Component {
|
||||
return self.nexus.get(component: Z.identifier, for: entityId) as? Z
|
||||
var iter = memberIds.makeIterator()
|
||||
while let entityId: EntityIdentifier = iter.next() {
|
||||
let a: A? = self.nexus.get(for: entityId)
|
||||
let b: B? = self.nexus.get(for: entityId)
|
||||
let c: C? = self.nexus.get(for: entityId)
|
||||
apply(entityId, a, b, c)
|
||||
}
|
||||
apply(getEntityInstance, getComponent, getComponent, getComponent)
|
||||
}
|
||||
}
|
||||
|
||||
public func iterate<A, B, C, D>(components _: A.Type, _: B.Type, _: C.Type, _: D.Type, _ apply: @escaping (() -> Entity, () -> A?, () -> B?, () -> C?, () -> D?) -> Void)
|
||||
public func iterate<A, B, C, D>(components _: A.Type, _: B.Type, _: C.Type, _: D.Type, _ apply: @escaping (EntityIdentifier, A?, B?, C?, D?) -> Void)
|
||||
where A: Component, B: Component, C: Component, D: Component {
|
||||
iterateMembers { (entityId, getEntityInstance) in
|
||||
func getComponent<Z>() -> Z? where Z: Component {
|
||||
return self.nexus.get(component: Z.identifier, for: entityId) as? Z
|
||||
var iter = memberIds.makeIterator()
|
||||
while let entityId: EntityIdentifier = iter.next() {
|
||||
let a: A? = self.nexus.get(for: entityId)
|
||||
let b: B? = self.nexus.get(for: entityId)
|
||||
let c: C? = self.nexus.get(for: entityId)
|
||||
let d: D? = self.nexus.get(for: entityId)
|
||||
apply(entityId, a, b, c, d)
|
||||
}
|
||||
apply(getEntityInstance, getComponent, getComponent, getComponent, getComponent)
|
||||
}
|
||||
}
|
||||
public func iterate<A, B, C, D, E>(components _: A.Type, _: B.Type, _: C.Type, _: D.Type, _: E.Type, _ apply: @escaping (() -> Entity, () -> A?, () -> B?, () -> C?, () -> D?, () -> E?) -> Void)
|
||||
public func iterate<A, B, C, D, E>(components _: A.Type, _: B.Type, _: C.Type, _: D.Type, _: E.Type, _ apply: @escaping (EntityIdentifier, A?, B?, C?, D?, E?) -> Void)
|
||||
where A: Component, B: Component, C: Component, D: Component, E: Component {
|
||||
iterateMembers { (entityId, getEntityInstance) in
|
||||
func getComponent<Z>() -> Z? where Z: Component {
|
||||
return self.nexus.get(component: Z.identifier, for: entityId) as? Z
|
||||
var iter = memberIds.makeIterator()
|
||||
while let entityId: EntityIdentifier = iter.next() {
|
||||
let a: A? = self.nexus.get(for: entityId)
|
||||
let b: B? = self.nexus.get(for: entityId)
|
||||
let c: C? = self.nexus.get(for: entityId)
|
||||
let d: D? = self.nexus.get(for: entityId)
|
||||
let e: E? = self.nexus.get(for: entityId)
|
||||
apply(entityId, a, b, c, d, e)
|
||||
}
|
||||
apply(getEntityInstance, getComponent, getComponent, getComponent, getComponent, getComponent)
|
||||
}
|
||||
}
|
||||
|
||||
public func iterate<A, B, C, D, E, F>(components _: A.Type, _: B.Type, _: C.Type, _: D.Type, _: E.Type, _: F.Type,
|
||||
_ apply: @escaping (() -> Entity, () -> A?, () -> B?, () -> C?, () -> D?, () -> E?, () -> F?) -> Void)
|
||||
_ apply: @escaping (EntityIdentifier, A?, B?, C?, D?, E?, F?) -> Void)
|
||||
where A: Component, B: Component, C: Component, D: Component, E: Component, F: Component {
|
||||
iterateMembers { (entityId, getEntityInstance) in
|
||||
func getComponent<Z>() -> Z? where Z: Component {
|
||||
return self.nexus.get(component: Z.identifier, for: entityId) as? Z
|
||||
var iter = memberIds.makeIterator()
|
||||
while let entityId: EntityIdentifier = iter.next() {
|
||||
let a: A? = self.nexus.get(for: entityId)
|
||||
let b: B? = self.nexus.get(for: entityId)
|
||||
let c: C? = self.nexus.get(for: entityId)
|
||||
let d: D? = self.nexus.get(for: entityId)
|
||||
let e: E? = self.nexus.get(for: entityId)
|
||||
let f: F? = self.nexus.get(for: entityId)
|
||||
apply(entityId, a, b, c, d, e, f)
|
||||
}
|
||||
apply(getEntityInstance, getComponent, getComponent, getComponent, getComponent, getComponent, getComponent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Family {
|
||||
|
||||
public func iterate<A>(_ apply: @escaping (() -> Entity, () -> A?) -> Void) where A: Component {
|
||||
iterateMembers { (entityId, getEntityInstance) in
|
||||
func getComponent<Z>() -> Z? where Z: Component {
|
||||
return self.nexus.get(component: Z.identifier, for: entityId) as? Z
|
||||
}
|
||||
apply(getEntityInstance, getComponent)
|
||||
}
|
||||
}
|
||||
|
||||
public func iterate<A, B>(_ apply: @escaping (() -> Entity, () -> A?, () -> B?) -> Void)
|
||||
where A: Component, B: Component {
|
||||
iterateMembers { (entityId, getEntityInstance) in
|
||||
func getComponent<Z>() -> Z? where Z: Component {
|
||||
return self.nexus.get(component: Z.identifier, for: entityId) as? Z
|
||||
}
|
||||
apply(getEntityInstance, getComponent, getComponent)
|
||||
}
|
||||
}
|
||||
|
||||
public func iterate<A, B, C>(_ apply: @escaping (() -> Entity, () -> A?, () -> B?, () -> C?) -> Void)
|
||||
where A: Component, B: Component, C: Component {
|
||||
iterateMembers { (entityId, getEntityInstance) in
|
||||
func getComponent<Z>() -> Z? where Z: Component {
|
||||
return self.nexus.get(component: Z.identifier, for: entityId) as? Z
|
||||
}
|
||||
apply(getEntityInstance, getComponent, getComponent, getComponent)
|
||||
}
|
||||
}
|
||||
|
||||
public func iterate<A, B, C, D>(_ apply: @escaping (() -> Entity, () -> A?, () -> B?, () -> C?, () -> D?) -> Void)
|
||||
where A: Component, B: Component, C: Component, D: Component {
|
||||
iterateMembers { (entityId, getEntityInstance) in
|
||||
func getComponent<Z>() -> Z? where Z: Component {
|
||||
return self.nexus.get(component: Z.identifier, for: entityId) as? Z
|
||||
}
|
||||
apply(getEntityInstance, getComponent, getComponent, getComponent, getComponent)
|
||||
}
|
||||
}
|
||||
|
||||
public func iterate<A, B, C, D, E>(_ apply: @escaping (() -> Entity, () -> A?, () -> B?, () -> C?, () -> D?, () -> E?) -> Void)
|
||||
where A: Component, B: Component, C: Component, D: Component, E: Component {
|
||||
iterateMembers { (entityId, getEntityInstance) in
|
||||
func getComponent<Z>() -> Z? where Z: Component {
|
||||
return self.nexus.get(component: Z.identifier, for: entityId) as? Z
|
||||
}
|
||||
apply(getEntityInstance, getComponent, getComponent, getComponent, getComponent, getComponent)
|
||||
}
|
||||
}
|
||||
|
||||
public func iterate<A, B, C, D, E, F>(_ apply: @escaping (() -> Entity, () -> A?, () -> B?, () -> C?, () -> D?, () -> E?, () -> F?) -> Void)
|
||||
where A: Component, B: Component, C: Component, D: Component, E: Component, F: Component {
|
||||
iterateMembers { (entityId, getEntityInstance) in
|
||||
func getComponent<Z>() -> Z? where Z: Component {
|
||||
return self.nexus.get(component: Z.identifier, for: entityId) as? Z
|
||||
}
|
||||
apply(getEntityInstance, getComponent, getComponent, getComponent, getComponent, getComponent, getComponent)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ public final class Family {
|
|||
internal init(_ nexus: Nexus, traits: FamilyTraitSet) {
|
||||
self.nexus = nexus
|
||||
self.traits = traits
|
||||
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
|
@ -39,10 +40,10 @@ extension Family {
|
|||
return nexus.isMember(entityId, in: self)
|
||||
}
|
||||
|
||||
public var members: LazyMapCollection<LazyFilterCollection<LazyMapCollection<EntityIdSet, Entity?>>, Entity> {
|
||||
/*public var members: LazyMapCollection<LazyFilterCollection<LazyMapCollection<EntityIdSet, Entity?>>, Entity> {
|
||||
return nexus.members(of: self)
|
||||
}
|
||||
internal var memberIds: EntityIdSet {
|
||||
}*/
|
||||
internal var memberIds: EntityIds {
|
||||
return nexus.members(of: self)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,13 +33,14 @@ extension Nexus {
|
|||
var newComponentIndex: ComponentIndex = ComponentIndex.invalid
|
||||
if componentsByType[componentId] != nil {
|
||||
newComponentIndex = componentsByType[componentId]!.count // TODO: get next free index
|
||||
componentsByType[componentId]!.insert(component, at: newComponentIndex)
|
||||
componentsByType[componentId]!.append(component) // Amortized O(1)
|
||||
} else {
|
||||
newComponentIndex = 0
|
||||
componentsByType[componentId] = UniformComponents(arrayLiteral: component)
|
||||
}
|
||||
|
||||
// assigns the component id to the entity id
|
||||
// FIXME: expensive
|
||||
if componentIdsByEntity[entityIdx] != nil {
|
||||
let (inserted, _) = componentIdsSetByEntity[entityIdx]!.insert(componentId)
|
||||
assert(inserted)
|
||||
|
|
@ -50,9 +51,7 @@ extension Nexus {
|
|||
componentIdsSetByEntity[entityIdx] = Set<ComponentIdentifier>(minimumCapacity: 2)
|
||||
let (inserted, _) = componentIdsSetByEntity[entityIdx]!.insert(componentId)
|
||||
assert(inserted)
|
||||
componentIdsByEntity[entityIdx] = ComponentIdentifiers()
|
||||
componentIdsByEntity.reserveCapacity(1)
|
||||
componentIdsByEntity[entityIdx]!.insert(componentId, at: 0)
|
||||
componentIdsByEntity[entityIdx] = ComponentIdentifiers(arrayLiteral: componentId)
|
||||
componentIdsByEntityLookup[hash] = 0
|
||||
}
|
||||
|
||||
|
|
@ -72,11 +71,6 @@ extension Nexus {
|
|||
assign(component: component, to: entity)
|
||||
}
|
||||
|
||||
public func get<C>(component componentId: ComponentIdentifier, for entityId: EntityIdentifier) -> C? where C: Component {
|
||||
let hash: EntityComponentHash = componentId.hashValue(using: entityId.index)
|
||||
return get(hash)
|
||||
}
|
||||
|
||||
public func get(component componentId: ComponentIdentifier, for entityId: EntityIdentifier) -> Component? {
|
||||
let hash: EntityComponentHash = componentId.hashValue(using: entityId.index)
|
||||
guard let componentIdx: ComponentIndex = componentIndexByEntityComponentHash[hash] else { return nil }
|
||||
|
|
@ -84,12 +78,16 @@ extension Nexus {
|
|||
return uniformComponents[componentIdx]
|
||||
}
|
||||
|
||||
fileprivate func get<C>(_ hash: EntityComponentHash) -> C? where C: Component {
|
||||
public func get<C>(for entityId: EntityIdentifier) -> C? where C: Component {
|
||||
let componentId: ComponentIdentifier = C.identifier
|
||||
let hash: EntityComponentHash = componentId.hashValue(using: entityId)
|
||||
return get(componentId: componentId, hash: hash)
|
||||
}
|
||||
|
||||
fileprivate func get<C>(componentId: ComponentIdentifier, hash: EntityComponentHash) -> C? where C: Component {
|
||||
guard let componentIdx: ComponentIndex = componentIndexByEntityComponentHash[hash] else { return nil }
|
||||
guard let uniformComponents: UniformComponents = componentsByType[componentId] else { return nil }
|
||||
guard let typedComponent: C = uniformComponents[componentIdx] as? C else { return nil }
|
||||
return typedComponent
|
||||
return uniformComponents[componentIdx] as? C
|
||||
}
|
||||
|
||||
public func get(components entityId: EntityIdentifier) -> ComponentIdentifiers? {
|
||||
|
|
|
|||
|
|
@ -33,14 +33,14 @@ extension Nexus {
|
|||
return family.traits.isMatch(components: componentSet)
|
||||
}
|
||||
|
||||
public func members(of family: Family) -> EntityIdSet {
|
||||
public func members(of family: Family) -> EntityIds {
|
||||
let traitHash: FamilyTraitSetHash = family.traits.hashValue
|
||||
return familyMembersByTraitHash[traitHash] ?? [] // FIXME: fail?
|
||||
}
|
||||
|
||||
public func members(of family: Family) -> LazyMapCollection<LazyFilterCollection<LazyMapCollection<EntityIdSet, Entity?>>, Entity> {
|
||||
/*public func members(of family: Family) -> LazyMapCollection<LazyFilterCollection<LazyMapCollection<EntityIdSet, Entity?>>, Entity> {
|
||||
return members(of: family).lazy.flatMap { self.get(entity: $0) }
|
||||
}
|
||||
}*/
|
||||
|
||||
public func isMember(_ entity: Entity, in family: Family) -> Bool {
|
||||
return isMember(entity.identifier, in: family)
|
||||
|
|
@ -91,14 +91,22 @@ extension Nexus {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: move
|
||||
fileprivate func calculateTrash(traitHash: FamilyTraitSetHash, entityId: EntityIdentifier) -> TraitEntityIdHash {
|
||||
return hash(combine: traitHash, entityId.index)
|
||||
}
|
||||
|
||||
fileprivate func add(to family: Family, entityId: EntityIdentifier) {
|
||||
let traitHash: FamilyTraitSetHash = family.traits.hashValue
|
||||
let trash: TraitEntityIdHash = calculateTrash(traitHash: traitHash, entityId: entityId)
|
||||
|
||||
if familyMembersByTraitHash[traitHash] != nil {
|
||||
let (inserted, _) = familyMembersByTraitHash[traitHash]!.insert(entityId)
|
||||
assert(inserted, "entity with id \(entityId) already in family")
|
||||
let newIndex: Int = familyMembersByTraitHash[traitHash]!.count
|
||||
trashMap[trash] = newIndex
|
||||
familyMembersByTraitHash[traitHash]!.append(entityId)
|
||||
} else {
|
||||
familyMembersByTraitHash[traitHash] = EntityIdSet(minimumCapacity: 2)
|
||||
familyMembersByTraitHash[traitHash]!.insert(entityId)
|
||||
familyMembersByTraitHash[traitHash] = EntityIds(arrayLiteral: entityId)
|
||||
trashMap[trash] = 0
|
||||
}
|
||||
|
||||
notify(FamilyMemberAdded(member: entityId, to: family.traits))
|
||||
|
|
@ -106,8 +114,15 @@ extension Nexus {
|
|||
|
||||
fileprivate func remove(from family: Family, entityId: EntityIdentifier) {
|
||||
let traitHash: FamilyTraitSetHash = family.traits.hashValue
|
||||
let trash: TraitEntityIdHash = calculateTrash(traitHash: traitHash, entityId: entityId)
|
||||
|
||||
guard let removed = familyMembersByTraitHash[traitHash]?.remove(entityId) else {
|
||||
guard let index: EntityIdInFamilyIndex = trashMap[trash] else {
|
||||
assert(false, "removing entity id \(entityId) that is not in family \(family)")
|
||||
report("removing entity id \(entityId) that is not in family \(family)")
|
||||
return
|
||||
}
|
||||
|
||||
guard let removed: EntityIdentifier = familyMembersByTraitHash[traitHash]?.remove(at: index) else {
|
||||
assert(false, "removing entity id \(entityId) that is not in family \(family)")
|
||||
report("removing entity id \(entityId) that is not in family \(family)")
|
||||
return
|
||||
|
|
|
|||
|
|
@ -18,8 +18,12 @@ public typealias UniformComponents = ContiguousArray<Component>
|
|||
public typealias ComponentIdentifiers = ContiguousArray<ComponentIdentifier>
|
||||
public typealias ComponentSet = Set<ComponentIdentifier>
|
||||
public typealias Entities = ContiguousArray<Entity>
|
||||
public typealias EntityIds = ContiguousArray<EntityIdentifier>
|
||||
public typealias EntityIdSet = Set<EntityIdentifier>
|
||||
public typealias FamilyTraitSetHash = Int
|
||||
public typealias TraitEntityIdHash = Int
|
||||
public typealias EntityIdInFamilyIndex = Int
|
||||
public typealias TraitEntityIdHashSet = [TraitEntityIdHash: EntityIdInFamilyIndex]
|
||||
|
||||
public class Nexus {
|
||||
|
||||
|
|
@ -47,7 +51,8 @@ public class Nexus {
|
|||
var freeEntities: ContiguousArray<EntityIdentifier>
|
||||
|
||||
var familiyByTraitHash: [FamilyTraitSetHash: Family]
|
||||
var familyMembersByTraitHash: [FamilyTraitSetHash: EntityIdSet]
|
||||
var trashMap: TraitEntityIdHashSet
|
||||
var familyMembersByTraitHash: [FamilyTraitSetHash: EntityIds]
|
||||
var componentIdsSetByEntity: [EntityIndex: ComponentSet]
|
||||
|
||||
public init() {
|
||||
|
|
@ -60,6 +65,7 @@ public class Nexus {
|
|||
freeEntities = ContiguousArray<EntityIdentifier>()
|
||||
familiyByTraitHash = [:]
|
||||
familyMembersByTraitHash = [:]
|
||||
trashMap = [:]
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,3 +38,25 @@ class Party: Component {
|
|||
self.partying = partying
|
||||
}
|
||||
}
|
||||
|
||||
class ExampleSystem {
|
||||
private let family: Family
|
||||
|
||||
init(nexus: Nexus) {
|
||||
family = nexus.family(requiresAll: [Position.self, Velocity.self], excludesAll: [EmptyComponent.self])
|
||||
}
|
||||
|
||||
func update(deltaT: Double) {
|
||||
family.iterate(components: Position.self, Velocity.self, Name.self) { (_, positionGetter, velocityGetter, nameGetter) in
|
||||
|
||||
let position: Position = positionGetter!
|
||||
let velocity: Velocity = velocityGetter!
|
||||
let name: Name? = nameGetter
|
||||
|
||||
position.x *= 2
|
||||
velocity.a *= 2
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,4 +30,25 @@ class ComponentTests: XCTestCase {
|
|||
XCTAssert(Velocity.identifier != Position.identifier)
|
||||
}
|
||||
|
||||
func testMeasureStaticComponentIdentifier() {
|
||||
let number: Int = 10_000
|
||||
measure {
|
||||
for _ in 0..<number {
|
||||
let id = Position.identifier
|
||||
_ = id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testMeasureComponentIdentifier() {
|
||||
let number: Int = 10_000
|
||||
let pos = Position(x: 1, y: 2)
|
||||
measure {
|
||||
for _ in 0..<number {
|
||||
let id = pos.identifier
|
||||
_ = id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
//
|
||||
|
||||
import XCTest
|
||||
import FirebladeECS
|
||||
@testable import FirebladeECS
|
||||
|
||||
class FamilyTests: XCTestCase {
|
||||
|
||||
|
|
@ -63,56 +63,7 @@ class FamilyTests: XCTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
func testIterateFamilyMembers() {
|
||||
|
||||
let nexus = Nexus()
|
||||
|
||||
nexus.create(entity: "a").assign(Position(x: 1, y: 2), Name(name: "myName"), Velocity(a: 3.14), EmptyComponent())
|
||||
nexus.create(entity: "b").assign(Position(x: 3, y: 4), Velocity(a: 5.23), EmptyComponent())
|
||||
|
||||
let family = nexus.family(requiresAll: [Position.self, Velocity.self], excludesAll: [Party.self], needsAtLeastOne: [Name.self, EmptyComponent.self])
|
||||
|
||||
var index: Int = 0
|
||||
|
||||
family.iterate { (_: () -> Entity, pos: () -> Position!, vel: () -> Velocity!, nm: () -> Name?) in
|
||||
|
||||
let position: Position = pos()!
|
||||
let name: Name? = nm()
|
||||
|
||||
_ = position
|
||||
_ = name
|
||||
|
||||
if index == 0 {
|
||||
let velocity: Velocity = vel()!
|
||||
_ = velocity
|
||||
}
|
||||
// bla
|
||||
index += 1
|
||||
}
|
||||
|
||||
family.iterate(components: Position.self, Velocity.self, Name.self) { (_, pos, vel, nm) in
|
||||
let position: Position = pos()!
|
||||
let velocity: Velocity = vel()!
|
||||
let name: Name? = nm()
|
||||
|
||||
_ = position
|
||||
_ = velocity
|
||||
_ = name
|
||||
}
|
||||
|
||||
family.iterate { (e: () -> Entity, p: () -> Position!, v: () -> Velocity!, n: () -> Name?) in
|
||||
|
||||
print(e(), p().x, n())
|
||||
if index == 0 {
|
||||
print(v())
|
||||
}
|
||||
// bla
|
||||
index += 1
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func testMeasureFamilyIteration() {
|
||||
func testMeasureIterateMembers() {
|
||||
let nexus = Nexus()
|
||||
let number: Int = 10_000
|
||||
|
||||
|
|
@ -126,20 +77,13 @@ class FamilyTests: XCTestCase {
|
|||
XCTAssert(nexus.count == number)
|
||||
|
||||
measure {
|
||||
family.iterate(components: Position.self, Velocity.self, Name.self) { (_, pos, vel, nm) in
|
||||
let position: Position = pos()!
|
||||
let velocity: Velocity = vel()!
|
||||
let name: Name? = nm()
|
||||
|
||||
_ = position
|
||||
_ = velocity
|
||||
_ = name
|
||||
}
|
||||
family.iterateMembers({ (entityId) in
|
||||
_ = entityId
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func testMeasureFamilyIteration2() {
|
||||
func testMeasureFamilyIterationOne() {
|
||||
let nexus = Nexus()
|
||||
let number: Int = 10_000
|
||||
|
||||
|
|
@ -153,12 +97,33 @@ class FamilyTests: XCTestCase {
|
|||
XCTAssert(nexus.count == number)
|
||||
|
||||
measure {
|
||||
family.iterate { (_: () -> Entity, pos: () -> Position!, vel: () -> Velocity!, nm: () -> Name?) in
|
||||
let name: Name? = nm()
|
||||
let velocity: Velocity = vel()!
|
||||
let position: Position = pos()!
|
||||
family.iterate(components: Velocity.self) { (_, vel) in
|
||||
let velocity: Velocity = vel!
|
||||
_ = velocity
|
||||
}
|
||||
}
|
||||
|
||||
_ = position
|
||||
}
|
||||
func testMeasureFamilyIterationThree() {
|
||||
let nexus = Nexus()
|
||||
let number: Int = 10_000
|
||||
|
||||
for i in 0..<number {
|
||||
nexus.create(entity: "\(i)").assign(Position(x: 1+i, y: 2+i), Name(name: "myName\(i)"), Velocity(a: 3.14), EmptyComponent())
|
||||
}
|
||||
|
||||
let family = nexus.family(requiresAll: [Position.self, Velocity.self], excludesAll: [Party.self], needsAtLeastOne: [Name.self, EmptyComponent.self])
|
||||
|
||||
XCTAssert(family.count == number)
|
||||
XCTAssert(nexus.count == number)
|
||||
|
||||
measure {
|
||||
family.iterate(components: Position.self, Velocity.self, Name.self) { (entityId, pos, vel, nm) in
|
||||
let position: Position = pos!
|
||||
let velocity: Velocity = vel!
|
||||
let name: Name? = nm
|
||||
|
||||
position.x += entityId.index
|
||||
_ = velocity
|
||||
_ = name
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue