Fix deinit routines

This commit is contained in:
Christian Treffs 2017-11-03 08:47:06 +01:00
parent 78c248ab0a
commit a42918501d
9 changed files with 87 additions and 60 deletions

View File

@ -9,11 +9,11 @@
public extension Entity {
public final func get<C>() -> C? where C: Component {
return delegate.get(for: identifier)
return nexus.get(for: identifier)
}
public func get<A>(component compType: A.Type = A.self) -> A? where A: Component {
return delegate.get(for: identifier)
return nexus.get(for: identifier)
}
public func getComponent<A>() -> () -> A? where A: Component {

View File

@ -10,10 +10,10 @@ public final class Entity: UniqueEntityIdentifiable {
internal(set) public var identifier: EntityIdentifier = EntityIdentifier.invalid
public var name: String?
internal unowned let delegate: Nexus
unowned let nexus: Nexus
internal init(nexus: Nexus, id: EntityIdentifier, name: String? = nil) {
self.delegate = nexus
init(nexus: Nexus, id: EntityIdentifier, name: String? = nil) {
self.nexus = nexus
self.identifier = id
self.name = name
}
@ -34,11 +34,10 @@ extension Entity: Activatable {
extension Entity {
public var isValid: Bool {
return delegate.isValid(entity: self)
return nexus.isValid(entity: self)
}
internal func invalidate() {
assert(delegate.isValid(entity: identifier), "Invalid entity \(self) is being invalidated.")
identifier = EntityIdentifier.invalid
name = nil
}
@ -52,7 +51,7 @@ public func ==(lhs: Entity, rhs: Entity) -> Bool {
// MARK: - number of components
public extension Entity {
public final var numComponents: Int {
return delegate.count(components: identifier)
return nexus.count(components: identifier)
}
}
@ -64,11 +63,11 @@ public extension Entity {
}
public final func has(_ uct: ComponentIdentifier) -> Bool {
return delegate.has(componentId: uct, entityIdx: identifier.index)
return nexus.has(componentId: uct, entityIdx: identifier.index)
}
public final var hasComponents: Bool {
return delegate.count(components: identifier) > 0
return nexus.count(components: identifier) > 0
}
}
@ -86,13 +85,13 @@ public extension Entity {
@discardableResult
public final func assign(_ component: Component) -> Entity {
delegate.assign(component: component, to: self)
nexus.assign(component: component, to: self)
return self
}
@discardableResult
public final func assign<C>(_ component: C) -> Entity where C: Component {
delegate.assign(component: component, to: self)
nexus.assign(component: component, to: self)
return self
}
@ -122,12 +121,12 @@ public extension Entity {
@discardableResult
public final func remove(_ uct: ComponentIdentifier) -> Entity {
delegate.remove(component: uct, from: identifier)
nexus.remove(component: uct, from: identifier)
return self
}
public final func clear() {
delegate.clear(componentes: identifier)
nexus.clear(componentes: identifier)
}
@discardableResult
@ -144,6 +143,6 @@ public extension Entity {
// MARK: - destroy/deinit entity
extension Entity {
public final func destroy() {
delegate.destroy(entity: self)
nexus.destroy(entity: self)
}
}

View File

@ -18,7 +18,7 @@ extension Family {
public func iterate<A>(components _: A.Type, _ apply: @escaping (EntityIdentifier, A?) -> Void)
where A: Component {
for entityId in memberIds {
let a: A? = self.delegate.get(for: entityId)
let a: A? = self.nexus?.get(for: entityId)
apply(entityId, a)
}
}
@ -26,8 +26,8 @@ extension Family {
public func iterate<A, B>(components _: A.Type, _: B.Type, _ apply: @escaping (EntityIdentifier, A?, B?) -> Void)
where A: Component, B: Component {
for entityId in memberIds {
let a: A? = self.delegate.get(for: entityId)
let b: B? = self.delegate.get(for: entityId)
let a: A? = self.nexus?.get(for: entityId)
let b: B? = self.nexus?.get(for: entityId)
apply(entityId, a, b)
}
}
@ -35,9 +35,9 @@ extension Family {
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 {
for entityId in memberIds {
let a: A? = self.delegate.get(for: entityId)
let b: B? = self.delegate.get(for: entityId)
let c: C? = self.delegate.get(for: entityId)
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)
}
}
@ -45,21 +45,21 @@ extension Family {
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 {
for entityId in memberIds {
let a: A? = self.delegate.get(for: entityId)
let b: B? = self.delegate.get(for: entityId)
let c: C? = self.delegate.get(for: entityId)
let d: D? = self.delegate.get(for: entityId)
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)
}
}
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 {
for entityId in memberIds {
let a: A? = self.delegate.get(for: entityId)
let b: B? = self.delegate.get(for: entityId)
let c: C? = self.delegate.get(for: entityId)
let d: D? = self.delegate.get(for: entityId)
let e: E? = self.delegate.get(for: entityId)
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)
}
}
@ -68,12 +68,12 @@ extension Family {
_ apply: @escaping (EntityIdentifier, A?, B?, C?, D?, E?, F?) -> Void)
where A: Component, B: Component, C: Component, D: Component, E: Component, F: Component {
for entityId in memberIds {
let a: A? = self.delegate.get(for: entityId)
let b: B? = self.delegate.get(for: entityId)
let c: C? = self.delegate.get(for: entityId)
let d: D? = self.delegate.get(for: entityId)
let e: E? = self.delegate.get(for: entityId)
let f: F? = self.delegate.get(for: entityId)
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)
}
}

View File

@ -7,42 +7,43 @@
// MARK: - family
public final class Family {
internal unowned var delegate: Nexus
weak var nexus: Nexus?
// members of this Family must conform to these traits
public let traits: FamilyTraitSet
internal init(_ nexus: Nexus, traits: FamilyTraitSet) {
self.delegate = nexus
init(_ nexus: Nexus, traits: FamilyTraitSet) {
self.nexus = nexus
self.traits = traits
defer {
nexus.onFamilyCreated(family: self)
nexus.onFamilyInit(family: self)
}
}
deinit {
delegate.onFamilyRemove(family: self)
let hash: FamilyTraitSetHash = traits.hashValue
nexus?.onFamilyDeinit(traitHash: hash)
}
}
extension Family {
public var count: Int {
return delegate.members(of: self).count
return nexus?.members(of: self).count ?? 0
}
public final func canBecomeMember(_ entity: Entity) -> Bool {
return delegate.canBecomeMember(entity, in: self)
return nexus?.canBecomeMember(entity, in: self) ?? false
}
public final func isMember(_ entity: Entity) -> Bool {
return delegate.isMember(entity, in: self)
return nexus?.isMember(entity, in: self) ?? false
}
public final func isMember(_ entityId: EntityIdentifier) -> Bool {
return delegate.isMember(entityId, in: self)
return nexus?.isMember(entityId, in: self) ?? false
}
internal var memberIds: UniformEntityIdentifiers {
return delegate.members(of: self)
return nexus!.members(of: self)
}
}

View File

@ -30,7 +30,6 @@ public struct FamilyTraitSet {
self.needsAtLeastOne = one
self.excludesAll = none
}
}
// MARK: - match

View File

@ -56,7 +56,7 @@ extension Nexus {
// FIXME: this is costly for many families
let entityId: EntityIdentifier = entity.identifier
for (_, family) in familiyByTraitHash {
for (_, family) in familiesByTraitHash {
update(membership: family, for: entityId)
}
@ -117,7 +117,7 @@ extension Nexus {
}
// FIXME: this is costly for many families
for (_, family) in familiyByTraitHash {
for (_, family) in familiesByTraitHash {
update(membership: family, for: entityId)
}

View File

@ -8,7 +8,7 @@
extension Nexus {
public var entities: [Entity] {
return entityStorage.filter { $0.isValid }
return entityStorage.filter { isValid(entity: $0.identifier) }
}
fileprivate func nextEntityIdx() -> EntityIndex {
@ -78,6 +78,10 @@ extension Nexus {
freeEntities.append(entityId)
for (_, family) in familiesByTraitHash {
update(membership: family, for: entityId)
}
notify(EntityDestroyed(entityId: entityId))
return true
}

View File

@ -41,6 +41,10 @@ extension Nexus {
public func members(of family: Family) -> UniformEntityIdentifiers {
let traitHash: FamilyTraitSetHash = family.traits.hashValue
return members(of: traitHash)
}
public func members(of traitHash: FamilyTraitSetHash) -> UniformEntityIdentifiers {
return familyMembersByTraitHash[traitHash] ?? UniformEntityIdentifiers() // FIXME: fail?
}
@ -56,29 +60,28 @@ extension Nexus {
fileprivate func get(family traits: FamilyTraitSet) -> Family? {
let traitHash: FamilyTraitSetHash = traits.hashValue
return familiyByTraitHash[traitHash]
return familiesByTraitHash[traitHash]
}
fileprivate func create(family traits: FamilyTraitSet) -> Family {
let traitHash: FamilyTraitSetHash = traits.hashValue
let family = Family(self, traits: traits)
let replaced = familiyByTraitHash.updateValue(family, forKey: traitHash)
let replaced = familiesByTraitHash.updateValue(family, forKey: traitHash)
assert(replaced == nil, "Family with exact trait hash already exists: \(traitHash)")
notify(FamilyCreated(family: traits))
return family
}
/// will be called on family init defer
internal func onFamilyCreated(family: Family) {
internal func onFamilyInit(family: Family) {
// FIXME: this is costly for many entities
for entity: Entity in entityStorage {
update(membership: family, for: entity.identifier)
}
}
internal func onFamilyRemove(family: Family) {
let traitHash: FamilyTraitSetHash = family.traits.hashValue
for member in members(of: family) {
internal func onFamilyDeinit(traitHash: FamilyTraitSetHash) {
for member in members(of: traitHash) {
remove(from: traitHash, entityId: member, entityIdx: member.index)
}
}
@ -96,6 +99,10 @@ extension Nexus {
guard let componentIds: ComponentIdentifiers = componentIdsByEntity[entityIdx] else { return }
let is_Member: Bool = isMember(entityId, in: family)
if !isValid(entity: entityId) && is_Member {
remove(from: traitHash, entityId: entityId, entityIdx: entityIdx)
return
}
let componentsSet: ComponentSet = ComponentSet.init(componentIds)
let isMatch: Bool = traits.isMatch(components: componentsSet)

View File

@ -42,7 +42,7 @@ public class Nexus {
/// - Values: entity ids that are currently not used
var freeEntities: ContiguousArray<EntityIdentifier>
var familiyByTraitHash: [FamilyTraitSetHash: Family]
var familiesByTraitHash: [FamilyTraitSetHash: Family]
var familyMembersByTraitHash: [FamilyTraitSetHash: UniformEntityIdentifiers] // SparseSet for EntityIdentifier
public init() {
@ -51,14 +51,31 @@ public class Nexus {
componentIdsByEntity = [:]
componentIdsByEntityLookup = [:]
freeEntities = ContiguousArray<EntityIdentifier>()
familiyByTraitHash = [:]
familiesByTraitHash = [:]
familyMembersByTraitHash = [:]
}
deinit {
// FIXME: clear all things and cleanup
print("nexus deinit")
for e in entities {
destroy(entity: e)
}
entityStorage.removeAll()
freeEntities.removeAll()
assert(entityStorage.isEmpty)
assert(componentsByType.values.reduce(0, { $0 + $1.count }) == 0)
assert(componentIdsByEntity.values.reduce(0, { $0 + $1.count }) == 0)
assert(componentIdsByEntityLookup.isEmpty)
assert(freeEntities.isEmpty)
assert(familiesByTraitHash.values.reduce(0, { $0 + $1.count }) == 0)
assert(familyMembersByTraitHash.values.reduce(0, { $0 + $1.count }) == 0)
componentsByType.removeAll()
componentIdsByEntity.removeAll()
familiesByTraitHash.removeAll()
familyMembersByTraitHash.removeAll()
}
}