Merge branch 'develop' into feature/serialization
This commit is contained in:
commit
762e845ae0
|
|
@ -36,7 +36,7 @@ import PackageDescription
|
|||
let package = Package(
|
||||
name: "YourPackageName",
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/fireblade-engine/ecs.git", from: "0.15.3")
|
||||
.package(url: "https://github.com/fireblade-engine/ecs.git", from: "0.15.4")
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
|
|
@ -71,7 +71,7 @@ then create entities by letting the `Nexus` generate them.
|
|||
let newEntity = nexus.createEntity()
|
||||
```
|
||||
|
||||
To define components conform your class to the `Component` protocol
|
||||
To define components, conform your class to the `Component` protocol
|
||||
|
||||
```swift
|
||||
final class Position: Component {
|
||||
|
|
|
|||
|
|
@ -5,19 +5,57 @@
|
|||
// Created by Christian Treffs on 08.10.17.
|
||||
//
|
||||
|
||||
/// **EntityIdentifier**
|
||||
///
|
||||
/// An entity identifier represents the unique identity of an entity.
|
||||
public struct EntityIdentifier {
|
||||
public static let invalid = EntityIdentifier(.max)
|
||||
/// Entity identifier type.
|
||||
///
|
||||
/// Provides 4294967295 unique identifiers.
|
||||
public typealias Identifier = UInt32
|
||||
|
||||
public typealias Idx = Int
|
||||
|
||||
/// provides 4294967295 unique identifiers since it's constrained to UInt32 - invalid.
|
||||
@usableFromInline let id: Idx
|
||||
/// The entity identifier.
|
||||
public let id: Identifier
|
||||
|
||||
@inlinable
|
||||
public init(_ uint32: UInt32) {
|
||||
self.id = Idx(uint32)
|
||||
public init(_ id: Identifier) {
|
||||
self.init(rawValue: id)
|
||||
}
|
||||
}
|
||||
|
||||
extension EntityIdentifier: Equatable { }
|
||||
extension EntityIdentifier: Hashable { }
|
||||
|
||||
extension EntityIdentifier: RawRepresentable {
|
||||
/// The entity identifier represented as a raw value.
|
||||
@inline(__always)
|
||||
public var rawValue: Identifier { id }
|
||||
|
||||
@inlinable
|
||||
public init(rawValue: Identifier) {
|
||||
self.id = rawValue
|
||||
}
|
||||
}
|
||||
|
||||
extension EntityIdentifier: ExpressibleByIntegerLiteral {
|
||||
public init(integerLiteral value: Identifier) {
|
||||
self.init(value)
|
||||
}
|
||||
}
|
||||
|
||||
extension EntityIdentifier {
|
||||
/// Invalid entity identifier
|
||||
///
|
||||
/// Used to represent an invalid entity identifier.
|
||||
public static let invalid = EntityIdentifier(.max)
|
||||
}
|
||||
|
||||
extension EntityIdentifier {
|
||||
/// Provides the entity identifier as an index
|
||||
///
|
||||
/// This is a convenience property for collection indexing and does not represent the raw identifier.
|
||||
///
|
||||
/// Use `id` or `rawValue` instead.
|
||||
@inline(__always)
|
||||
public var index: Int { Int(id) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,12 +32,12 @@ public protocol EntityIdentifierGenerator {
|
|||
public struct DefaultEntityIdGenerator: EntityIdentifierGenerator {
|
||||
@usableFromInline
|
||||
final class Storage {
|
||||
@usableFromInline var stack: [UInt32]
|
||||
@usableFromInline var stack: [EntityIdentifier.Identifier]
|
||||
@usableFromInline var count: Int { stack.count }
|
||||
|
||||
@usableFromInline
|
||||
init(inUse entityIds: [EntityIdentifier]) {
|
||||
stack = entityIds.reversed().map { UInt32($0.id) }
|
||||
stack = entityIds.reversed().map(\.id)
|
||||
}
|
||||
|
||||
@usableFromInline
|
||||
|
|
@ -52,7 +52,7 @@ public struct DefaultEntityIdGenerator: EntityIdentifierGenerator {
|
|||
|
||||
@usableFromInline
|
||||
func markUnused(entityId: EntityIdentifier) {
|
||||
stack.append(UInt32(entityId.id))
|
||||
stack.append(entityId.id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ public struct Family<R> where R: FamilyRequirementsManaging {
|
|||
nexus.onFamilyInit(traits: traits)
|
||||
}
|
||||
|
||||
@inlinable var memberIds: UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Idx> {
|
||||
@inlinable var memberIds: UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Identifier> {
|
||||
nexus.members(withFamilyTraits: traits)
|
||||
}
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ extension Family: LazySequenceProtocol { }
|
|||
// MARK: - components iterator
|
||||
extension Family {
|
||||
public struct ComponentsIterator: IteratorProtocol {
|
||||
@usableFromInline var memberIdsIterator: UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Idx>.ElementIterator
|
||||
@usableFromInline var memberIdsIterator: UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Identifier>.ElementIterator
|
||||
@usableFromInline unowned let nexus: Nexus
|
||||
|
||||
public init(family: Family<R>) {
|
||||
|
|
@ -102,7 +102,7 @@ extension Family {
|
|||
}
|
||||
|
||||
public struct EntityIterator: IteratorProtocol {
|
||||
@usableFromInline var memberIdsIterator: UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Idx>.ElementIterator
|
||||
@usableFromInline var memberIdsIterator: UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Identifier>.ElementIterator
|
||||
@usableFromInline unowned let nexus: Nexus
|
||||
|
||||
public init(family: Family<R>) {
|
||||
|
|
@ -128,7 +128,7 @@ extension Family {
|
|||
}
|
||||
|
||||
public struct EntityComponentIterator: IteratorProtocol {
|
||||
@usableFromInline var memberIdsIterator: UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Idx>.ElementIterator
|
||||
@usableFromInline var memberIdsIterator: UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Identifier>.ElementIterator
|
||||
@usableFromInline unowned let nexus: Nexus
|
||||
|
||||
public init(family: Family<R>) {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ extension Nexus {
|
|||
guard let uniforms = componentsByType[componentId] else {
|
||||
return false
|
||||
}
|
||||
return uniforms.contains(entityId.id)
|
||||
return uniforms.contains(entityId.index)
|
||||
}
|
||||
|
||||
public final func count(components entityId: EntityIdentifier) -> Int {
|
||||
|
|
@ -36,13 +36,13 @@ extension Nexus {
|
|||
guard let uniformComponents = componentsByType[componentId] else {
|
||||
return nil
|
||||
}
|
||||
return uniformComponents.get(at: entityId.id)
|
||||
return uniformComponents.get(at: entityId.index)
|
||||
}
|
||||
|
||||
@inlinable
|
||||
public final func get(unsafeComponent componentId: ComponentIdentifier, for entityId: EntityIdentifier) -> Component {
|
||||
let uniformComponents = componentsByType[componentId].unsafelyUnwrapped
|
||||
return uniformComponents.get(unsafeAt: entityId.id)
|
||||
return uniformComponents.get(unsafeAt: entityId.index)
|
||||
}
|
||||
|
||||
@inlinable
|
||||
|
|
@ -66,7 +66,7 @@ extension Nexus {
|
|||
@discardableResult
|
||||
public final func remove(component componentId: ComponentIdentifier, from entityId: EntityIdentifier) -> Bool {
|
||||
// delete component instance
|
||||
componentsByType[componentId]?.remove(at: entityId.id)
|
||||
componentsByType[componentId]?.remove(at: entityId.index)
|
||||
// un-assign component from entity
|
||||
componentIdsByEntity[entityId]?.remove(componentId)
|
||||
|
||||
|
|
@ -95,6 +95,6 @@ extension Nexus {
|
|||
guard let uniformComponents = componentsByType[componentId] else {
|
||||
return nil
|
||||
}
|
||||
return uniformComponents.get(at: entityId.id) as? C
|
||||
return uniformComponents.get(at: entityId.index) as? C
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ extension Nexus {
|
|||
return traits.isMatch(components: componentIds)
|
||||
}
|
||||
|
||||
public func members(withFamilyTraits traits: FamilyTraitSet) -> UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Idx> {
|
||||
familyMembersByTraits[traits] ?? UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Idx>()
|
||||
public func members(withFamilyTraits traits: FamilyTraitSet) -> UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Identifier> {
|
||||
familyMembersByTraits[traits] ?? UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Identifier>()
|
||||
}
|
||||
|
||||
public func isMember(_ entity: Entity, in family: FamilyTraitSet) -> Bool {
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ extension Nexus {
|
|||
if componentsByType[componentId] == nil {
|
||||
componentsByType[componentId] = ManagedContiguousArray<Component>()
|
||||
}
|
||||
componentsByType[componentId]?.insert(component, at: entityId.id)
|
||||
componentsByType[componentId]?.insert(component, at: entityId.index)
|
||||
}
|
||||
|
||||
func assign(_ componentId: ComponentIdentifier, _ entityId: EntityIdentifier) {
|
||||
|
|
@ -86,7 +86,7 @@ extension Nexus {
|
|||
return
|
||||
}
|
||||
|
||||
familyMembersByTraits[traits] = UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Idx>()
|
||||
familyMembersByTraits[traits] = UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Identifier>()
|
||||
update(familyMembership: traits)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
public final class Nexus {
|
||||
/// Main entity storage.
|
||||
/// Entities are tightly packed by EntityIdentifier.
|
||||
@usableFromInline final var entityStorage: UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Idx>
|
||||
@usableFromInline final var entityStorage: UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Identifier>
|
||||
|
||||
/// - Key: ComponentIdentifier aka component type.
|
||||
/// - Value: Array of component instances of same type (uniform).
|
||||
|
|
@ -22,7 +22,7 @@ public final class Nexus {
|
|||
|
||||
/// - Key: FamilyTraitSet aka component types that make up one distinct family.
|
||||
/// - Value: Tightly packed EntityIdentifiers that represent the association of an entity to the family.
|
||||
@usableFromInline final var familyMembersByTraits: [FamilyTraitSet: UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Idx>]
|
||||
@usableFromInline final var familyMembersByTraits: [FamilyTraitSet: UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Identifier>]
|
||||
|
||||
/// The entity identifier generator responsible for providing unique ids for entities during runtime.
|
||||
///
|
||||
|
|
@ -39,7 +39,7 @@ public final class Nexus {
|
|||
public final weak var delegate: NexusEventDelegate?
|
||||
|
||||
public convenience init() {
|
||||
self.init(entityStorage: UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Idx>(),
|
||||
self.init(entityStorage: UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Identifier>(),
|
||||
componentsByType: [:],
|
||||
componentsByEntity: [:],
|
||||
entityIdGenerator: DefaultEntityIdGenerator(),
|
||||
|
|
@ -47,11 +47,11 @@ public final class Nexus {
|
|||
codingStrategy: DefaultCodingStrategy())
|
||||
}
|
||||
|
||||
internal init(entityStorage: UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Idx>,
|
||||
internal init(entityStorage: UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Identifier>,
|
||||
componentsByType: [ComponentIdentifier: ManagedContiguousArray<Component>],
|
||||
componentsByEntity: [EntityIdentifier: Set<ComponentIdentifier>],
|
||||
entityIdGenerator: EntityIdentifierGenerator,
|
||||
familyMembersByTraits: [FamilyTraitSet: UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Idx>],
|
||||
familyMembersByTraits: [FamilyTraitSet: UnorderedSparseSet<EntityIdentifier, EntityIdentifier.Identifier>],
|
||||
codingStrategy: CodingStrategy) {
|
||||
self.entityStorage = entityStorage
|
||||
self.componentsByType = componentsByType
|
||||
|
|
|
|||
|
|
@ -11,15 +11,15 @@ import XCTest
|
|||
class EntityTests: XCTestCase {
|
||||
func testEntityIdentifierAndIndex() {
|
||||
let min = EntityIdentifier(.min)
|
||||
XCTAssertEqual(min.id, Int(UInt32.min))
|
||||
XCTAssertEqual(min.id, UInt32.min)
|
||||
|
||||
let uRand = UInt32.random(in: UInt32.min...UInt32.max)
|
||||
let rand = EntityIdentifier(uRand)
|
||||
XCTAssertEqual(rand.id, Int(uRand))
|
||||
XCTAssertEqual(rand.id, uRand)
|
||||
|
||||
let max = EntityIdentifier(.max)
|
||||
XCTAssertEqual(max, EntityIdentifier.invalid)
|
||||
XCTAssertEqual(max.id, Int(UInt32.max))
|
||||
XCTAssertEqual(max.id, UInt32.max)
|
||||
}
|
||||
|
||||
func testAllComponentsOfEntity() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue