155 lines
4.7 KiB
Swift
155 lines
4.7 KiB
Swift
//
|
|
// Entity.swift
|
|
// FirebladeECS
|
|
//
|
|
// Created by Christian Treffs on 08.10.17.
|
|
//
|
|
|
|
/// **Entity**
|
|
///
|
|
/// An entity is a general purpose object.
|
|
/// It only consists of a unique id (EntityIdentifier).
|
|
/// Components can be assigned to an entity to give it behavior or functionality.
|
|
/// An entity creates the relationship between all it's assigned components.
|
|
public struct Entity {
|
|
@usableFromInline unowned let nexus: Nexus
|
|
|
|
/// The unique entity identifier.
|
|
public private(set) var identifier: EntityIdentifier
|
|
|
|
internal init(nexus: Nexus, id: EntityIdentifier) {
|
|
self.nexus = nexus
|
|
self.identifier = id
|
|
}
|
|
|
|
/// Returns the number of components for this entity.
|
|
public var numComponents: Int {
|
|
nexus.count(components: identifier)
|
|
}
|
|
|
|
/// Checks if a component with given type is assigned to this entity.
|
|
/// - Parameter type: the component type.
|
|
public func has<C>(_ type: C.Type) -> Bool where C: Component {
|
|
has(type.identifier)
|
|
}
|
|
|
|
/// Checks if a component with a given component identifier is assigned to this entity.
|
|
/// - Parameter compId: the component identifier.
|
|
public func has(_ compId: ComponentIdentifier) -> Bool {
|
|
nexus.has(componentId: compId, entityId: identifier)
|
|
}
|
|
|
|
/// Checks if this entity has any components.
|
|
public var hasComponents: Bool {
|
|
nexus.count(components: identifier) > 0
|
|
}
|
|
|
|
/// Add one or more components to this entity.
|
|
/// - Parameter components: one or more components.
|
|
@discardableResult
|
|
public func assign(_ components: Component...) -> Entity {
|
|
for component: Component in components {
|
|
assign(component)
|
|
}
|
|
return self
|
|
}
|
|
|
|
/// Add a component to this entity.
|
|
/// - Parameter component: a component.
|
|
@discardableResult
|
|
public func assign(_ component: Component) -> Entity {
|
|
nexus.assign(component: component, to: self)
|
|
return self
|
|
}
|
|
|
|
/// Add a typed component to this entity.
|
|
/// - Parameter component: the typed component.
|
|
@discardableResult
|
|
public func assign<C>(_ component: C) -> Entity where C: Component {
|
|
nexus.assign(component: component, to: self)
|
|
return self
|
|
}
|
|
|
|
/// Remove a component from this entity.
|
|
/// - Parameter component: the component.
|
|
@discardableResult
|
|
public func remove<C>(_ component: C) -> Entity where C: Component {
|
|
remove(component.identifier)
|
|
}
|
|
|
|
/// Remove a component by type from this entity.
|
|
/// - Parameter compType: the component type.
|
|
@discardableResult
|
|
public func remove<C>(_ compType: C.Type) -> Entity where C: Component {
|
|
remove(compType.identifier)
|
|
}
|
|
|
|
/// Remove a component by id from this entity.
|
|
/// - Parameter compId: the component id.
|
|
@discardableResult
|
|
public func remove(_ compId: ComponentIdentifier) -> Entity {
|
|
nexus.remove(component: compId, from: identifier)
|
|
return self
|
|
}
|
|
|
|
/// Remove all components from this entity.
|
|
public func removeAll() {
|
|
nexus.removeAll(components: identifier)
|
|
}
|
|
|
|
/// Destroy this entity.
|
|
public func destroy() {
|
|
nexus.destroy(entity: self)
|
|
}
|
|
|
|
/// Returns an iterator over all components of this entity.
|
|
@inlinable
|
|
public func makeComponentsIterator() -> ComponentsIterator {
|
|
ComponentsIterator(nexus: nexus, entityIdentifier: identifier)
|
|
}
|
|
|
|
/// Returns a sequence of all componenents of this entity.
|
|
@inlinable
|
|
public func allComponents() -> AnySequence<Component> {
|
|
AnySequence { self.makeComponentsIterator() }
|
|
}
|
|
}
|
|
|
|
extension Entity {
|
|
public struct ComponentsIterator: IteratorProtocol {
|
|
private var iterator: AnyIterator<Component>
|
|
|
|
@usableFromInline
|
|
init(nexus: Nexus, entityIdentifier: EntityIdentifier) {
|
|
if let comps = nexus.get(components: entityIdentifier) {
|
|
iterator = AnyIterator<Component>(comps.compactMap { nexus.get(component: $0, for: entityIdentifier) }.makeIterator())
|
|
} else {
|
|
iterator = AnyIterator { nil }
|
|
}
|
|
}
|
|
|
|
public mutating func next() -> Component? {
|
|
iterator.next()
|
|
}
|
|
}
|
|
}
|
|
extension Entity.ComponentsIterator: Sequence { }
|
|
|
|
extension Entity: Equatable {
|
|
public static func == (lhs: Entity, rhs: Entity) -> Bool {
|
|
lhs.nexus === rhs.nexus && lhs.identifier == rhs.identifier
|
|
}
|
|
}
|
|
|
|
extension Entity: CustomStringConvertible {
|
|
public var description: String {
|
|
"<Entity id:\(identifier.id)>"
|
|
}
|
|
}
|
|
|
|
extension Entity: CustomDebugStringConvertible {
|
|
public var debugDescription: String {
|
|
"<Entity id:\(identifier.id) numComponents:\(numComponents)>"
|
|
}
|
|
}
|