Fix deinit routines
This commit is contained in:
parent
78c248ab0a
commit
a42918501d
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ public struct FamilyTraitSet {
|
|||
self.needsAtLeastOne = one
|
||||
self.excludesAll = none
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - match
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue