135 lines
6.7 KiB
Plaintext
135 lines
6.7 KiB
Plaintext
// swiftlint:disable file_length
|
|
// swiftlint:disable function_parameter_count
|
|
// swiftlint:disable large_tuple
|
|
// swiftlint:disable multiline_parameters
|
|
{% for idx in 1...5 %}
|
|
{% map 1...idx into components using index %}Comp{{ index }}{% endmap %}
|
|
{% set CompParams %}{{components|join: ", "}}{% endset %}
|
|
{% map components into compWhere using comp %}{{ comp }}: Component{% endmap %}
|
|
{% set CompsWhere %}{{compWhere|join: ", "}}{% endset %}
|
|
{% map components into compEncodable using comp %}{{ comp }}: Encodable{% endmap %}
|
|
{% set CompsWhereEncodable %}{{compEncodable|join: ", "}}{% endset %}
|
|
{% map components into compsDecodable using comp %}{{ comp }}: Decodable{% endmap %}
|
|
{% set CompsWhereDecodable %}{{compsDecodable|join: ", "}}{% endset %}
|
|
{% map components into compTypes using comp %}{{ comp }}.Type{% endmap %}
|
|
{% set CompsTypes %}{{compTypes|join: ", "}}{% endset %}
|
|
{% map components into compSelf using comp %}{{ comp }}.self{% endmap %}
|
|
{% set CompsSelf %}{{compSelf|join: ", "}}{% endset %}
|
|
{% map components into compsLowercased using comp %}{{ comp|lowercase }}{% endmap %}
|
|
{% set CompsLowercased %}{{compsLowercased|join: ", "}}{% endset %}
|
|
{% map components into compsTuple using comp %}components.{{ maploop.counter }}{% endmap %}
|
|
{% set CompsTuple %}{{compsTuple|join: ", "}}{% endset %}
|
|
{% map components into compsParams using comp %}{% if not maploop.first %}_ {% endif %}{{ comp|lowercase }}: {{ comp }}.Type{% endmap %}
|
|
{% set CompsParams %}{{compsParams|join: ", "}}{% endset %}
|
|
|
|
// MARK: - Family {{ idx }}
|
|
|
|
public typealias Family{{ idx }}<{{ CompParams }}> = Family<Requires{{ idx }}<{{ CompParams }}>> where {{ CompsWhere }}
|
|
|
|
public struct Requires{{ idx }}<{{ CompParams }}>: FamilyRequirementsManaging where {{ CompsWhere }} {
|
|
public let componentTypes: [Component.Type]
|
|
|
|
public init(_ components: ({{ CompsTypes }})) {
|
|
componentTypes = [{{ CompsSelf}}]
|
|
}
|
|
|
|
public static func components(nexus: Nexus, entityId: EntityIdentifier) -> ({{ CompParams }}) {
|
|
{% for comp in components %}
|
|
let {{ comp|lowercase }}: {{ comp }} = nexus.get(unsafeComponentFor: entityId)
|
|
{% endfor %}
|
|
return ({{ CompsLowercased }})
|
|
}
|
|
|
|
public static func entityAndComponents(nexus: Nexus, entityId: EntityIdentifier) -> (Entity, {{ CompParams }}) {
|
|
let entity: Entity = nexus.get(unsafeEntity: entityId)
|
|
{% for comp in components %}
|
|
let {{ comp|lowercase }}: {{ comp }} = nexus.get(unsafeComponentFor: entityId)
|
|
{% endfor %}
|
|
return (entity, {{ CompsLowercased }})
|
|
}
|
|
|
|
public static func createMember(nexus: Nexus, components: ({{ CompParams }})) -> Entity {
|
|
{% if compEncodable.count == 1 %}nexus.createEntity(with: components){% else %}nexus.createEntity(with: {{ CompsTuple }}){% endif %}
|
|
}
|
|
|
|
public static func relativesDescending(nexus: Nexus, parentId: EntityIdentifier, childId: EntityIdentifier) -> (parent: ({{ CompParams }}), child: ({{ CompParams }})) {
|
|
{% for comp in components %}
|
|
let parent{{ comp|lowercase }}: {{ comp }} = nexus.get(unsafeComponentFor: parentId)
|
|
{% endfor %}
|
|
{% for comp in components %}
|
|
let child{{ comp|lowercase }}: {{ comp }} = nexus.get(unsafeComponentFor: childId)
|
|
{% endfor %}
|
|
{% map compsLowercased into compsParent using comp %}parent{{ comp }}{% endmap %}
|
|
{% map compsLowercased into compsChild using comp %}child{{ comp }}{% endmap %}
|
|
{% set CompsParentChild %}parent: ({{compsParent|join: ", "}}), child: ({{compsChild|join: ", "}}){% endset %}
|
|
return ({{ CompsParentChild }})
|
|
}
|
|
}
|
|
|
|
extension Requires{{ idx }}: FamilyEncoding where {{ CompsWhereEncodable }} {
|
|
public static func encode(components: ({{ CompParams }}), into container: inout KeyedEncodingContainer<DynamicCodingKey>, using strategy: CodingStrategy) throws {
|
|
{% if compEncodable.count == 1 %}
|
|
try container.encode(components, forKey: strategy.codingKey(for: {{ CompsSelf }}))
|
|
{% else %}
|
|
{% for comp in compSelf %}
|
|
try container.encode(components.{{ forloop.counter0 }}, forKey: strategy.codingKey(for: {{ comp }}))
|
|
{% endfor %}
|
|
{% endif %}
|
|
}
|
|
}
|
|
|
|
extension Requires{{ idx }}: FamilyDecoding where {{ CompsWhereDecodable }} {
|
|
public static func decode(componentsIn container: KeyedDecodingContainer<DynamicCodingKey>, using strategy: CodingStrategy) throws -> ({{ CompParams }}) {
|
|
{% for comp in components %}
|
|
let {{ comp|lowercase }} = try container.decode({{ comp }}.self, forKey: strategy.codingKey(for: {{ comp }}.self))
|
|
{% endfor %}
|
|
{% if compEncodable.count == 1 %}
|
|
return {{ CompsLowercased }}
|
|
{% else %}
|
|
return Components({{ CompsLowercased }})
|
|
{% endif %}
|
|
}
|
|
}
|
|
|
|
extension Nexus {
|
|
/// Create a family of entities (aka members) having {{ components.count }} required components.
|
|
///
|
|
/// A family is a collection of entities with uniform component types per entity.
|
|
/// Entities that are be part of this family will have at least the {{ components.count }} required components,
|
|
/// but may have more components assigned.
|
|
///
|
|
/// A family is just a view on (component) data, creating them is cheap.
|
|
/// Use them to iterate efficiently over entities with the same components assigned.
|
|
/// Families with the same requirements provide a view on the same collection of entities (aka members).
|
|
/// A family conforms to the `LazySequenceProtocol` and therefore can be accessed like any other (lazy) sequence.
|
|
///
|
|
/// **General usage**
|
|
/// ```swift
|
|
/// let family = nexus.family({% if components.count == 1 %}requires{% else %}requiresAll{%endif%}: {{ CompsSelf }})
|
|
/// // iterate each entity's components
|
|
/// family.forEach { ({{ CompsLowercased }}) in
|
|
/// ...
|
|
/// }
|
|
/// ```
|
|
/// **Caveats**
|
|
/// - Component types must be unique per family
|
|
/// - Component type order is arbitrary
|
|
///
|
|
/// - Parameters:
|
|
{% for comp in compsLowercased %}
|
|
/// - {{ comp }}: Component type {{ forloop.counter }} required by members of this family.
|
|
{% endfor %}
|
|
/// - excludedComponents: All component types that must not be assigned to an entity in this family.
|
|
/// - Returns: The family of entities having {{ components.count }} required components each.
|
|
public func family<{{ CompParams }}>(
|
|
{% if components.count == 1 %}requires{% else %}requiresAll{%endif%} {{ CompsParams }},
|
|
excludesAll excludedComponents: Component.Type...
|
|
) -> Family{{ idx }}<{{ CompParams }}> where {{ CompsWhere }} {
|
|
Family{{ idx }}<{{ CompParams }}>(
|
|
nexus: self,
|
|
requiresAll: ({{ CompsLowercased }}),
|
|
excludesAll: excludedComponents
|
|
)
|
|
}
|
|
}
|
|
{% endfor %} |