Add Entity and Family storage implementations
This commit is contained in:
parent
fb2d011c8d
commit
e16759f9f1
|
|
@ -8,6 +8,9 @@
|
|||
public final class Entity: UniqueEntityIdentifiable {
|
||||
public let uei: UEI
|
||||
|
||||
public var name: String?
|
||||
|
||||
@available(*, deprecated: 0.1, message: "replace this with core/context concept")
|
||||
fileprivate var eventDispatcher: EventDispatcher
|
||||
|
||||
public private(set) var componentMap: [UCT: Component]
|
||||
|
|
|
|||
|
|
@ -10,16 +10,13 @@ public class EntityHub: EventHandler {
|
|||
|
||||
public lazy var eventHub: DefaultEventHub = { return DefaultEventHub() }()
|
||||
|
||||
private(set) var entites: Set<Entity>
|
||||
//private(set) var entites: [UEI:Entity] = [:]
|
||||
private(set) var families: [FamilyTraits:Family]
|
||||
private(set) var entities: EntityStorage
|
||||
private(set) var families: FamilyStorage
|
||||
|
||||
public init() {
|
||||
entites = Set<Entity>()
|
||||
entites.reserveCapacity(512)
|
||||
entities = DefaultEntityStorage()
|
||||
|
||||
families = [FamilyTraits: Family]()
|
||||
families.reserveCapacity(64)
|
||||
families = DefaultFamilyStorage()
|
||||
|
||||
self.delegate = eventHub
|
||||
|
||||
|
|
@ -60,7 +57,7 @@ extension EntityHub {
|
|||
public func createEntity() -> Entity {
|
||||
let newEntity = Entity(uei: UEI.next, dispatcher: eventHub)
|
||||
// ^ dispatches entity creation event here ^
|
||||
let (success, _) = entites.insert(newEntity)
|
||||
let success: Bool = entities.add(newEntity)
|
||||
assert(success == true, "Entity with the exact identifier already exists")
|
||||
|
||||
return newEntity
|
||||
|
|
@ -80,8 +77,8 @@ extension EntityHub {
|
|||
|
||||
let newFamily = Family(traits: traits, eventHub: eventHub)
|
||||
// ^ dispatches family creation event here ^
|
||||
let replaced = families.updateValue(newFamily, forKey: traits)
|
||||
assert(replaced == nil, "Family with the exact traits already exists")
|
||||
let success = families.add(newFamily)
|
||||
assert(success, "Family with the exact traits already exists")
|
||||
|
||||
refreshFamilyCache()
|
||||
|
||||
|
|
@ -89,8 +86,8 @@ extension EntityHub {
|
|||
}
|
||||
|
||||
fileprivate func onFamilyCreated(_ newFamily: Family) {
|
||||
let previousEntities = entites
|
||||
newFamily.update(membership: previousEntities)
|
||||
|
||||
newFamily.update(membership: entities.iterator)
|
||||
}
|
||||
|
||||
fileprivate func refreshFamilyCache() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
//
|
||||
// EntityStorage.swift
|
||||
// FirebladeECS
|
||||
//
|
||||
// Created by Christian Treffs on 10.10.17.
|
||||
//
|
||||
|
||||
public protocol EntityStorage {
|
||||
@discardableResult func add(_ entity: Entity) -> Bool
|
||||
|
||||
var iterator: AnyIterator<Entity> { get }
|
||||
|
||||
func has(_ entity: Entity) -> Bool
|
||||
func has(_ id: UEI) -> Bool
|
||||
func has(_ named: String) -> Bool
|
||||
|
||||
func get(_ id: UEI) -> Entity?
|
||||
subscript(_ id: UEI) -> Entity? { get }
|
||||
|
||||
func get(_ named: String) -> Entity?
|
||||
subscript(_ named: String) -> Entity? { get }
|
||||
|
||||
@discardableResult func remove(_ id: UEI) -> Bool
|
||||
|
||||
func clear()
|
||||
|
||||
}
|
||||
|
||||
class DefaultEntityStorage: EntityStorage {
|
||||
|
||||
fileprivate typealias Index = Set<Entity>.Index
|
||||
fileprivate var entities: Set<Entity> = Set<Entity>()
|
||||
|
||||
var iterator: AnyIterator<Entity> {
|
||||
return AnyIterator(entities.makeIterator())
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func add(_ entity: Entity) -> Bool {
|
||||
let (success, _) = entities.insert(entity)
|
||||
return success
|
||||
}
|
||||
|
||||
func has(_ entity: Entity) -> Bool {
|
||||
return entities.contains(entity)
|
||||
}
|
||||
|
||||
func has(_ id: UEI) -> Bool {
|
||||
return entities.contains { $0.uei == id }
|
||||
}
|
||||
|
||||
func has(_ named: String) -> Bool {
|
||||
return entities.contains { $0.name == named }
|
||||
}
|
||||
|
||||
func get(_ id: UEI) -> Entity? {
|
||||
guard let index = index(id) else { return nil }
|
||||
return entities[index]
|
||||
}
|
||||
|
||||
subscript(id: UEI) -> Entity? { return get(id) }
|
||||
|
||||
func get(_ named: String) -> Entity? {
|
||||
guard let index: Index = index(named) else { return nil }
|
||||
return entities[index]
|
||||
}
|
||||
|
||||
subscript(named: String) -> Entity? { return get(named) }
|
||||
|
||||
@discardableResult
|
||||
func remove(_ id: UEI) -> Bool {
|
||||
guard let index: Index = index(id) else { return false }
|
||||
entities.remove(at: index)
|
||||
return true
|
||||
}
|
||||
|
||||
func clear() {
|
||||
entities.removeAll()
|
||||
}
|
||||
|
||||
// MARK: - internal
|
||||
|
||||
fileprivate func index(_ id: UEI) -> Index? {
|
||||
return entities.index { $0.uei == id }
|
||||
}
|
||||
|
||||
fileprivate func index(_ named: String) -> Index? {
|
||||
return entities.index { $0.name == named }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -54,9 +54,8 @@ public final class Family {
|
|||
// MARK: - update family membership
|
||||
extension Family {
|
||||
|
||||
func update<C: Collection>(membership entites: C) where C.Iterator.Element == Entity {
|
||||
var entityIterator = entites.makeIterator()
|
||||
while let entity: Entity = entityIterator.next() {
|
||||
func update(membership entities: AnyIterator<Entity>) {
|
||||
while let entity: Entity = entities.next() {
|
||||
update(membership: entity)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
//
|
||||
// FamilyStorage.swift
|
||||
// FirebladeECS
|
||||
//
|
||||
// Created by Christian Treffs on 10.10.17.
|
||||
//
|
||||
|
||||
public protocol FamilyStorage {
|
||||
@discardableResult func add(_ family: Family) -> Bool
|
||||
|
||||
var iterator: AnyIterator<(FamilyTraits, Family)> { get }
|
||||
|
||||
func has(_ family: Family) -> Bool
|
||||
func has(_ traits: FamilyTraits) -> Bool
|
||||
|
||||
func get(_ traits: FamilyTraits) -> Family?
|
||||
subscript(_ traits: FamilyTraits) -> Family? { get }
|
||||
|
||||
@discardableResult func remove(_ family: Family) -> Bool
|
||||
@discardableResult func remove(_ traits: FamilyTraits) -> Bool
|
||||
|
||||
func clear()
|
||||
}
|
||||
|
||||
class DefaultFamilyStorage: FamilyStorage {
|
||||
|
||||
fileprivate typealias Index = Dictionary<FamilyTraits, Family>.Index
|
||||
fileprivate var families: [FamilyTraits: Family] = [:]
|
||||
|
||||
var iterator: AnyIterator<(FamilyTraits, Family)> {
|
||||
// see: https://www.raywenderlich.com/139591/building-custom-collection-swift
|
||||
var iter = families.makeIterator()
|
||||
return AnyIterator<(FamilyTraits, Family)> {
|
||||
return iter.next()
|
||||
}
|
||||
}
|
||||
|
||||
func add(_ family: Family) -> Bool {
|
||||
let replaced: Family? = families.updateValue(family, forKey: family.traits)
|
||||
let success: Bool = replaced == nil
|
||||
assert(success)
|
||||
return success
|
||||
}
|
||||
|
||||
func has(_ family: Family) -> Bool {
|
||||
return index(family) != nil
|
||||
}
|
||||
|
||||
func has(_ traits: FamilyTraits) -> Bool {
|
||||
return index(traits) != nil
|
||||
}
|
||||
|
||||
func get(_ traits: FamilyTraits) -> Family? {
|
||||
return families[traits]
|
||||
}
|
||||
|
||||
subscript(_ traits: FamilyTraits) -> Family? {
|
||||
return get(traits)
|
||||
}
|
||||
|
||||
func remove(_ family: Family) -> Bool {
|
||||
guard let index = index(family) else { return false }
|
||||
families.remove(at: index)
|
||||
return true
|
||||
}
|
||||
|
||||
func remove(_ traits: FamilyTraits) -> Bool {
|
||||
guard let index = index(traits) else { return false }
|
||||
families.remove(at: index)
|
||||
return true
|
||||
}
|
||||
|
||||
func clear() {
|
||||
families.removeAll()
|
||||
}
|
||||
|
||||
// MARK: - private
|
||||
private func index(_ traits: FamilyTraits) -> Index? {
|
||||
return families.index(forKey: traits)
|
||||
}
|
||||
|
||||
private func index(_ family: Family) -> Index? {
|
||||
return index(family.traits)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -21,8 +21,8 @@ class EntityHubTests: XCTestCase {
|
|||
let newEntity: Entity = entityHub.createEntity()
|
||||
|
||||
XCTAssert(newEntity.hasComponents == false)
|
||||
//TODO: XCTAssert(entityHub.entites[newEntity.uei] == newEntity)
|
||||
//TODO: XCTAssert(entityHub.entites[newEntity.uei] === newEntity)
|
||||
//TODO: XCTAssert(entityHub.entities[newEntity.uei] == newEntity)
|
||||
//TODO: XCTAssert(entityHub.entities[newEntity.uei] === newEntity)
|
||||
}
|
||||
|
||||
func testCreateEntityAndAddComponent() {
|
||||
|
|
@ -35,8 +35,8 @@ class EntityHubTests: XCTestCase {
|
|||
XCTAssert(newEntity.hasComponents)
|
||||
XCTAssert(newEntity.numComponents == 1)
|
||||
|
||||
//TODO: XCTAssert(entityHub.entites[newEntity.uei] == newEntity)
|
||||
//TODO: XCTAssert(entityHub.entites[newEntity.uei] === newEntity)
|
||||
//TODO: XCTAssert(entityHub.entities[newEntity.uei] == newEntity)
|
||||
//TODO: XCTAssert(entityHub.entities[newEntity.uei] === newEntity)
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ class FamilyTests: XCTestCase {
|
|||
|
||||
let (empty, name) = e1.components(EmptyComponent.self, Name.self)
|
||||
|
||||
print(empty, name)
|
||||
|
||||
e1.components { (empty: EmptyComponent, name: Name) in
|
||||
print(empty, name)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue