Stencil WIP

This commit is contained in:
Christian Treffs 2020-08-04 15:37:31 +02:00
parent f08c3f8ba9
commit c53952615a
No known key found for this signature in database
GPG Key ID: 49A4B4B460BE3ED4
8 changed files with 108 additions and 396 deletions

View File

@ -62,4 +62,4 @@ setupEnvironment:
brew install sourcery
generateCode:
sourcery
sourcery --verbose

View File

@ -8,7 +8,8 @@ let package = Package(
targets: ["FirebladeECS"])
],
targets: [
.target(name: "FirebladeECS"),
.target(name: "FirebladeECS",
exclude: ["Stencils"]),
.testTarget(name: "FirebladeECSTests",
dependencies: ["FirebladeECS"]),
.testTarget(name: "FirebladeECSPerformanceTests",

View File

@ -1,60 +0,0 @@
//
// Family1.swift
//
//
// Created by Christian Treffs on 21.08.19.
//
public typealias Family1<A: Component> = Family<Requires1<A>>
public struct Requires1<A>: FamilyRequirementsManaging where A: Component {
public let componentTypes: [Component.Type]
public init(_ components: A.Type) {
componentTypes = [A.self]
}
public static func components(nexus: Nexus, entityId: EntityIdentifier) -> A {
let compA: A = nexus.get(unsafeComponentFor: entityId)
return (compA)
}
public static func entityAndComponents(nexus: Nexus, entityId: EntityIdentifier) -> (Entity, A) {
let entity: Entity = nexus.get(unsafeEntity: entityId)
let compA: A = nexus.get(unsafeComponentFor: entityId)
return (entity, compA)
}
public static func relativesDescending(nexus: Nexus, parentId: EntityIdentifier, childId: EntityIdentifier) -> (parent: A, child: A) {
let parentCompA: A = nexus.get(unsafeComponentFor: parentId)
let childCompA: A = nexus.get(unsafeComponentFor: childId)
return (parent: parentCompA, child: childCompA)
}
public static func createMember(nexus: Nexus, components: A) -> Entity {
nexus.createEntity(with: components)
}
}
extension Requires1: FamilyDecoding where A: Decodable {
public static func decode(componentsIn container: KeyedDecodingContainer<DynamicCodingKey>, using strategy: CodingStrategy) throws -> A {
try container.decode(A.self, forKey: strategy.codingKey(for: A.self))
}
}
extension Requires1: FamilyEncoding where A: Encodable {
public static func encode(components: Components, into container: inout KeyedEncodingContainer<DynamicCodingKey>, using strategy: CodingStrategy) throws {
try container.encode(components, forKey: strategy.codingKey(for: A.self))
}
}
extension Nexus {
public func family<A>(
requires componentA: A.Type,
excludesAll excludedComponents: Component.Type...
) -> Family1<A> where A: Component {
Family1<A>(nexus: self,
requiresAll: componentA,
excludesAll: excludedComponents)
}
}

View File

@ -1,72 +0,0 @@
//
// Family2.swift
//
//
// Created by Christian Treffs on 21.08.19.
//
// swiftlint:disable large_tuple
public typealias Family2<A: Component, B: Component> = Family<Requires2<A, B>>
public struct Requires2<A, B>: FamilyRequirementsManaging where A: Component, B: Component {
public let componentTypes: [Component.Type]
public init(_ components: (A.Type, B.Type)) {
componentTypes = [ A.self, B.self]
}
public static func components(nexus: Nexus, entityId: EntityIdentifier) -> (A, B) {
let compA: A = nexus.get(unsafeComponentFor: entityId)
let compB: B = nexus.get(unsafeComponentFor: entityId)
return (compA, compB)
}
public static func entityAndComponents(nexus: Nexus, entityId: EntityIdentifier) -> (Entity, A, B) {
let entity: Entity = nexus.get(unsafeEntity: entityId)
let compA: A = nexus.get(unsafeComponentFor: entityId)
let compB: B = nexus.get(unsafeComponentFor: entityId)
return (entity, compA, compB)
}
public static func relativesDescending(nexus: Nexus, parentId: EntityIdentifier, childId: EntityIdentifier) -> (parent: (A, B), child: (A, B)) {
let pcA: A = nexus.get(unsafeComponentFor: parentId)
let pcB: B = nexus.get(unsafeComponentFor: parentId)
let ccA: A = nexus.get(unsafeComponentFor: childId)
let ccB: B = nexus.get(unsafeComponentFor: childId)
return (parent: (pcA, pcB), child: (ccA, ccB))
}
public static func createMember(nexus: Nexus, components: (A, B)) -> Entity {
nexus.createEntity(with: components.0, components.1)
}
}
extension Requires2: FamilyEncoding where A: Encodable, B: Encodable {
public static func encode(components: (A, B), into container: inout KeyedEncodingContainer<DynamicCodingKey>, using strategy: CodingStrategy) throws {
try container.encode(components.0, forKey: strategy.codingKey(for: A.self))
try container.encode(components.1, forKey: strategy.codingKey(for: B.self))
}
}
extension Requires2: FamilyDecoding where A: Decodable, B: Decodable {
public static func decode(componentsIn container: KeyedDecodingContainer<DynamicCodingKey>, using strategy: CodingStrategy) throws -> (A, B) {
let compA = try container.decode(A.self, forKey: strategy.codingKey(for: A.self))
let compB = try container.decode(B.self, forKey: strategy.codingKey(for: B.self))
return Components(compA, compB)
}
}
extension Nexus {
public func family<A, B>(
requiresAll componentA: A.Type,
_ componentB: B.Type,
excludesAll excludedComponents: Component.Type...
) -> Family2<A, B> where A: Component, B: Component {
Family2<A, B>(
nexus: self,
requiresAll: (componentA, componentB),
excludesAll: excludedComponents
)
}
}

View File

@ -1,79 +0,0 @@
//
// Family3.swift
//
//
// Created by Christian Treffs on 21.08.19.
//
// swiftlint:disable large_tuple
public typealias Family3<A: Component, B: Component, C: Component> = Family<Requires3<A, B, C>>
public struct Requires3<A, B, C>: FamilyRequirementsManaging where A: Component, B: Component, C: Component {
public let componentTypes: [Component.Type]
public init(_ types: (A.Type, B.Type, C.Type)) {
componentTypes = [A.self, B.self, C.self]
}
public static func components(nexus: Nexus, entityId: EntityIdentifier) -> (A, B, C) {
let compA: A = nexus.get(unsafeComponentFor: entityId)
let compB: B = nexus.get(unsafeComponentFor: entityId)
let compC: C = nexus.get(unsafeComponentFor: entityId)
return (compA, compB, compC)
}
public static func entityAndComponents(nexus: Nexus, entityId: EntityIdentifier) -> (Entity, A, B, C) {
let entity: Entity = nexus.get(unsafeEntity: entityId)
let compA: A = nexus.get(unsafeComponentFor: entityId)
let compB: B = nexus.get(unsafeComponentFor: entityId)
let compC: C = nexus.get(unsafeComponentFor: entityId)
return (entity, compA, compB, compC)
}
public static func relativesDescending(nexus: Nexus, parentId: EntityIdentifier, childId: EntityIdentifier) ->
(parent: (A, B, C), child: (A, B, C)) {
let pcA: A = nexus.get(unsafeComponentFor: parentId)
let pcB: B = nexus.get(unsafeComponentFor: parentId)
let pcC: C = nexus.get(unsafeComponentFor: parentId)
let ccA: A = nexus.get(unsafeComponentFor: childId)
let ccB: B = nexus.get(unsafeComponentFor: childId)
let ccC: C = nexus.get(unsafeComponentFor: childId)
return (parent: (pcA, pcB, pcC), child: (ccA, ccB, ccC))
}
public static func createMember(nexus: Nexus, components: (A, B, C)) -> Entity {
nexus.createEntity(with: components.0, components.1, components.2)
}
}
extension Requires3: FamilyEncoding where A: Encodable, B: Encodable, C: Encodable {
public static func encode(components: (A, B, C), into container: inout KeyedEncodingContainer<DynamicCodingKey>, using strategy: CodingStrategy) throws {
try container.encode(components.0, forKey: strategy.codingKey(for: A.self))
try container.encode(components.1, forKey: strategy.codingKey(for: B.self))
try container.encode(components.2, forKey: strategy.codingKey(for: C.self))
}
}
extension Requires3: FamilyDecoding where A: Decodable, B: Decodable, C: Decodable {
public static func decode(componentsIn container: KeyedDecodingContainer<DynamicCodingKey>, using strategy: CodingStrategy) throws -> (A, B, C) {
let compA = try container.decode(A.self, forKey: strategy.codingKey(for: A.self))
let compB = try container.decode(B.self, forKey: strategy.codingKey(for: B.self))
let compC = try container.decode(C.self, forKey: strategy.codingKey(for: C.self))
return Components(compA, compB, compC)
}
}
extension Nexus {
public func family<A, B, C>(
requiresAll componentA: A.Type,
_ componentB: B.Type,
_ componentC: C.Type,
excludesAll excludedComponents: Component.Type...
) -> Family3<A, B, C> where A: Component, B: Component, C: Component {
Family3(
nexus: self,
requiresAll: (componentA, componentB, componentC),
excludesAll: excludedComponents
)
}
}

View File

@ -1,87 +0,0 @@
//
// Family4.swift
//
//
// Created by Christian Treffs on 21.08.19.
//
// swiftlint:disable large_tuple
public typealias Family4<A: Component, B: Component, C: Component, D: Component> = Family<Requires4<A, B, C, D>>
public struct Requires4<A, B, C, D>: FamilyRequirementsManaging where A: Component, B: Component, C: Component, D: Component {
public let componentTypes: [Component.Type]
public init(_ types: (A.Type, B.Type, C.Type, D.Type)) {
componentTypes = [A.self, B.self, C.self, D.self]
}
public static func components(nexus: Nexus, entityId: EntityIdentifier) -> (A, B, C, D) {
let compA: A = nexus.get(unsafeComponentFor: entityId)
let compB: B = nexus.get(unsafeComponentFor: entityId)
let compC: C = nexus.get(unsafeComponentFor: entityId)
let compD: D = nexus.get(unsafeComponentFor: entityId)
return (compA, compB, compC, compD)
}
public static func entityAndComponents(nexus: Nexus, entityId: EntityIdentifier) -> (Entity, A, B, C, D) {
let entity: Entity = nexus.get(unsafeEntity: entityId)
let compA: A = nexus.get(unsafeComponentFor: entityId)
let compB: B = nexus.get(unsafeComponentFor: entityId)
let compC: C = nexus.get(unsafeComponentFor: entityId)
let compD: D = nexus.get(unsafeComponentFor: entityId)
return (entity, compA, compB, compC, compD)
}
public static func relativesDescending(nexus: Nexus, parentId: EntityIdentifier, childId: EntityIdentifier) ->
(parent: (A, B, C, D), child: (A, B, C, D)) {
let pcA: A = nexus.get(unsafeComponentFor: parentId)
let pcB: B = nexus.get(unsafeComponentFor: parentId)
let pcC: C = nexus.get(unsafeComponentFor: parentId)
let pcD: D = nexus.get(unsafeComponentFor: parentId)
let ccA: A = nexus.get(unsafeComponentFor: childId)
let ccB: B = nexus.get(unsafeComponentFor: childId)
let ccC: C = nexus.get(unsafeComponentFor: childId)
let ccD: D = nexus.get(unsafeComponentFor: childId)
return (parent: (pcA, pcB, pcC, pcD), child: (ccA, ccB, ccC, ccD))
}
public static func createMember(nexus: Nexus, components: (A, B, C, D)) -> Entity {
nexus.createEntity(with: components.0, components.1, components.2, components.3)
}
}
extension Requires4: FamilyEncoding where A: Encodable, B: Encodable, C: Encodable, D: Encodable {
public static func encode(components: (A, B, C, D), into container: inout KeyedEncodingContainer<DynamicCodingKey>, using strategy: CodingStrategy) throws {
try container.encode(components.0, forKey: strategy.codingKey(for: A.self))
try container.encode(components.1, forKey: strategy.codingKey(for: B.self))
try container.encode(components.2, forKey: strategy.codingKey(for: C.self))
try container.encode(components.3, forKey: strategy.codingKey(for: D.self))
}
}
extension Requires4: FamilyDecoding where A: Decodable, B: Decodable, C: Decodable, D: Decodable {
public static func decode(componentsIn container: KeyedDecodingContainer<DynamicCodingKey>, using strategy: CodingStrategy) throws -> (A, B, C, D) {
let compA = try container.decode(A.self, forKey: strategy.codingKey(for: A.self))
let compB = try container.decode(B.self, forKey: strategy.codingKey(for: B.self))
let compC = try container.decode(C.self, forKey: strategy.codingKey(for: C.self))
let compD = try container.decode(D.self, forKey: strategy.codingKey(for: D.self))
return Components(compA, compB, compC, compD)
}
}
extension Nexus {
public func family<A, B, C, D>(
requiresAll componentA: A.Type,
_ componentB: B.Type,
_ componentC: C.Type,
_ componentD: D.Type,
excludesAll excludedComponents: Component.Type...
) -> Family4<A, B, C, D> where A: Component, B: Component, C: Component, D: Component {
Family4(
nexus: self,
requiresAll: (componentA, componentB, componentC, componentD),
excludesAll: excludedComponents
)
}
}

View File

@ -1,96 +0,0 @@
//
// Family5.swift
//
//
// Created by Christian Treffs on 21.08.19.
//
// swiftlint:disable large_tuple
public typealias Family5<A: Component, B: Component, C: Component, D: Component, E: Component> = Family<Requires5<A, B, C, D, E>>
public struct Requires5<A, B, C, D, E>: FamilyRequirementsManaging where A: Component, B: Component, C: Component, D: Component, E: Component {
public let componentTypes: [Component.Type]
public init(_ types: (A.Type, B.Type, C.Type, D.Type, E.Type)) {
componentTypes = [A.self, B.self, C.self, D.self, E.self]
}
public static func components(nexus: Nexus, entityId: EntityIdentifier) -> (A, B, C, D, E) {
let compA: A = nexus.get(unsafeComponentFor: entityId)
let compB: B = nexus.get(unsafeComponentFor: entityId)
let compC: C = nexus.get(unsafeComponentFor: entityId)
let compD: D = nexus.get(unsafeComponentFor: entityId)
let compE: E = nexus.get(unsafeComponentFor: entityId)
return (compA, compB, compC, compD, compE)
}
public static func entityAndComponents(nexus: Nexus, entityId: EntityIdentifier) -> (Entity, A, B, C, D, E) {
let entity = nexus.get(unsafeEntity: entityId)
let compA: A = nexus.get(unsafeComponentFor: entityId)
let compB: B = nexus.get(unsafeComponentFor: entityId)
let compC: C = nexus.get(unsafeComponentFor: entityId)
let compD: D = nexus.get(unsafeComponentFor: entityId)
let compE: E = nexus.get(unsafeComponentFor: entityId)
return (entity, compA, compB, compC, compD, compE)
}
public static func relativesDescending(nexus: Nexus, parentId: EntityIdentifier, childId: EntityIdentifier) ->
(parent: (A, B, C, D, E), child: (A, B, C, D, E)) {
let pcA: A = nexus.get(unsafeComponentFor: parentId)
let pcB: B = nexus.get(unsafeComponentFor: parentId)
let pcC: C = nexus.get(unsafeComponentFor: parentId)
let pcD: D = nexus.get(unsafeComponentFor: parentId)
let pcE: E = nexus.get(unsafeComponentFor: parentId)
let ccA: A = nexus.get(unsafeComponentFor: childId)
let ccB: B = nexus.get(unsafeComponentFor: childId)
let ccC: C = nexus.get(unsafeComponentFor: childId)
let ccD: D = nexus.get(unsafeComponentFor: childId)
let ccE: E = nexus.get(unsafeComponentFor: childId)
return (parent: (pcA, pcB, pcC, pcD, pcE),
child: (ccA, ccB, ccC, ccD, ccE))
}
public static func createMember(nexus: Nexus, components: (A, B, C, D, E)) -> Entity {
nexus.createEntity(with: components.0, components.1, components.2, components.3, components.4)
}
}
extension Requires5: FamilyEncoding where A: Encodable, B: Encodable, C: Encodable, D: Encodable, E: Encodable {
public static func encode(components: (A, B, C, D, E), into container: inout KeyedEncodingContainer<DynamicCodingKey>, using strategy: CodingStrategy) throws {
try container.encode(components.0, forKey: strategy.codingKey(for: A.self))
try container.encode(components.1, forKey: strategy.codingKey(for: B.self))
try container.encode(components.2, forKey: strategy.codingKey(for: C.self))
try container.encode(components.3, forKey: strategy.codingKey(for: D.self))
try container.encode(components.4, forKey: strategy.codingKey(for: E.self))
}
}
extension Requires5: FamilyDecoding where A: Decodable, B: Decodable, C: Decodable, D: Decodable, E: Decodable {
public static func decode(componentsIn container: KeyedDecodingContainer<DynamicCodingKey>, using strategy: CodingStrategy) throws -> (A, B, C, D, E) {
let compA = try container.decode(A.self, forKey: strategy.codingKey(for: A.self))
let compB = try container.decode(B.self, forKey: strategy.codingKey(for: B.self))
let compC = try container.decode(C.self, forKey: strategy.codingKey(for: C.self))
let compD = try container.decode(D.self, forKey: strategy.codingKey(for: D.self))
let compE = try container.decode(E.self, forKey: strategy.codingKey(for: E.self))
return Components(compA, compB, compC, compD, compE)
}
}
extension Nexus {
// swiftlint:disable function_parameter_count
public func family<A, B, C, D, E>(
requiresAll componentA: A.Type,
_ componentB: B.Type,
_ componentC: C.Type,
_ componentD: D.Type,
_ componentE: E.Type,
excludesAll excludedComponents: Component.Type...
) -> Family5<A, B, C, D, E> where A: Component, B: Component, C: Component, D: Component, E: Component {
Family5(
nexus: self,
requiresAll: (componentA, componentB, componentC, componentD, componentE),
excludesAll: excludedComponents
)
}
}

View File

@ -1,3 +1,108 @@
// swiftlint:disable large_tuple
// swiftlint:disable line_length
// swiftlint:disable variable_name
{% 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 }}) {
fatalError()
}
}
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 {
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 %}