Optimized component lookup
This commit is contained in:
parent
669fb374d7
commit
130a5a8edd
|
|
@ -17,7 +17,7 @@ extension Nexus {
|
|||
}
|
||||
|
||||
public func count(components entityId: EntityIdentifier) -> Int {
|
||||
switch componentIdsByEntityIdx[entityId.index] {
|
||||
switch componentIdsByEntity[entityId.index] {
|
||||
case .some(let componentIds):
|
||||
return componentIds.count
|
||||
case .none:
|
||||
|
|
@ -39,11 +39,15 @@ extension Nexus {
|
|||
componentsByType[componentId] = UniformComponents(arrayLiteral: component)
|
||||
}
|
||||
|
||||
if componentIdsByEntityIdx[entityIdx] != nil {
|
||||
componentIdsByEntityIdx[entityIdx]!.append(componentId)
|
||||
// assigns the component id to the entity id
|
||||
if componentIdsByEntity[entityIdx] != nil {
|
||||
let newIndex = componentIdsByEntity[entityIdx]!.count
|
||||
componentIdsByEntity[entityIdx]!.insert(componentId, at: newIndex)
|
||||
componentIdsByEntityLookup[hash] = newIndex
|
||||
} else {
|
||||
componentIdsByEntityIdx[entityIdx] = ComponentIdentifiers()
|
||||
componentIdsByEntityIdx[entityIdx]!.append(componentId)
|
||||
componentIdsByEntity[entityIdx] = ComponentIdentifiers()
|
||||
componentIdsByEntity[entityIdx]!.insert(componentId, at: 0)
|
||||
componentIdsByEntityLookup[hash] = 0
|
||||
}
|
||||
|
||||
// assign entity / component to index
|
||||
|
|
@ -66,13 +70,14 @@ extension Nexus {
|
|||
}
|
||||
|
||||
public func get(components entityId: EntityIdentifier) -> ComponentIdentifiers? {
|
||||
return componentIdsByEntityIdx[entityId.index]
|
||||
return componentIdsByEntity[entityId.index]
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
public func remove(component componentId: ComponentIdentifier, from entityId: EntityIdentifier) -> Bool {
|
||||
let hash: EntityComponentHash = componentId.hashValue(using: entityId.index)
|
||||
|
||||
// MARK: delete component instance
|
||||
guard let componentIdx: ComponentIndex = componentIndexByEntityComponentHash.removeValue(forKey: hash) else {
|
||||
report("ComponentRemove failure: entity \(entityId) has no component \(componentId)")
|
||||
return false
|
||||
|
|
@ -84,18 +89,28 @@ extension Nexus {
|
|||
return false
|
||||
}
|
||||
|
||||
// FIXME: this is expensive
|
||||
guard let removeIndex: Int = get(components: entityId)?.index(where: { $0 == componentId }) else {
|
||||
// MARK: unassign component
|
||||
guard let removeIndex: ComponentIdsByEntityIndex = componentIdsByEntityLookup.removeValue(forKey: hash) else {
|
||||
assert(false, "ComponentRemove failure: no component found to be removed")
|
||||
report("ComponentRemove failure: no component found to be removed")
|
||||
return false
|
||||
}
|
||||
guard componentIdsByEntityIdx[entityId.index]?.remove(at: removeIndex) != nil else {
|
||||
|
||||
guard componentIdsByEntity[entityId.index]?.remove(at: removeIndex) != nil else {
|
||||
assert(false, "ComponentRemove failure: nothing was removed")
|
||||
report("ComponentRemove failure: nothing was removed")
|
||||
return false
|
||||
}
|
||||
|
||||
// relocate remaining indices pointing in the componentsByEntity map
|
||||
if let remainingComponents = componentIdsByEntity[entityId.index] {
|
||||
// FIXME: may be expensive but is cheap for small entities
|
||||
for (index, compId) in remainingComponents.enumerated() {
|
||||
let cHash: EntityComponentHash = compId.hashValue(using: entityId.index)
|
||||
componentIdsByEntityLookup[cHash] = index
|
||||
}
|
||||
}
|
||||
|
||||
notify(ComponentRemoved(component: componentId, from: entityId))
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,14 @@
|
|||
//
|
||||
// Created by Christian Treffs on 09.10.17.
|
||||
//
|
||||
|
||||
/// entity id ^ component identifier hash
|
||||
public typealias EntityComponentHash = Int
|
||||
public typealias ComponentIndex = Int
|
||||
public extension ComponentIndex {
|
||||
static let invalid: ComponentIndex = Int.min
|
||||
}
|
||||
public typealias ComponentIdsByEntityIndex = Int
|
||||
|
||||
public typealias UniformComponents = ContiguousArray<Component>
|
||||
public typealias ComponentIdentifiers = ContiguousArray<ComponentIdentifier>
|
||||
|
|
@ -28,7 +31,13 @@ public class Nexus {
|
|||
/// - Value: each element is an index pointing to the component instance index in the componentsByType map.
|
||||
var componentIndexByEntityComponentHash: [EntityComponentHash: ComponentIndex]
|
||||
|
||||
var componentIdsByEntityIdx: [EntityIndex: ComponentIdentifiers]
|
||||
/// - Key: entity id as index
|
||||
/// - Value: each element is a component identifier associated with this entity
|
||||
var componentIdsByEntity: [EntityIndex: ComponentIdentifiers]
|
||||
|
||||
/// - Key 'entity id' - 'component type' hash that uniquely links both
|
||||
/// - Value: each element is an index pointing to the component identifier per entity in the componentIdsByEntity map
|
||||
var componentIdsByEntityLookup: [EntityComponentHash: ComponentIdsByEntityIndex]
|
||||
|
||||
var freeEntities: ContiguousArray<EntityIdentifier>
|
||||
|
||||
|
|
@ -36,7 +45,8 @@ public class Nexus {
|
|||
entities = Entities()
|
||||
componentsByType = [:]
|
||||
componentIndexByEntityComponentHash = [:]
|
||||
componentIdsByEntityIdx = [:]
|
||||
componentIdsByEntity = [:]
|
||||
componentIdsByEntityLookup = [:]
|
||||
freeEntities = ContiguousArray<EntityIdentifier>()
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue