Cleanups and lint

This commit is contained in:
Christian Treffs 2018-05-08 17:22:50 +02:00
parent 6061a2addc
commit 11b47da7bb
13 changed files with 154 additions and 165 deletions

View File

@ -2,8 +2,14 @@ included:
- Sources
excluded:
- Tests
identifier_name:
excluded:
- id
line_length: 220
number_separator:
minimum_length: 5
opt_in_rules:
#- file_header
- file_header
- array_init
- attributes
- closure_end_indentation
@ -14,7 +20,6 @@ opt_in_rules:
- explicit_enum_raw_value
- explicit_init
- explicit_top_level_acl
- explicit_type_interface
- extension_access_modifier
- fatal_error_message
- first_where
@ -27,8 +32,6 @@ opt_in_rules:
- multiline_arguments
- multiline_parameters
- nimble_operator
#- no_extension_access_modifier
#- no_grouping_extension
- number_separator
- object_literal
- operator_usage_whitespace
@ -48,20 +51,4 @@ opt_in_rules:
- switch_case_on_newline
- trailing_closure
- unneeded_parentheses_in_closure_argument
- vertical_parameter_alignment_on_call
file_header:
required_pattern: |
\/\/
\/\/ .*?\.swift
\/\/ FirebladeECS
\/\/
\/\/ Created by .*? on \d{1,2}\/\d{1,2}\/\d{2}\.
\/\/ Copyright © \d{4} Christian Treffs\. All rights reserved\.
\/\/
identifier_name:
excluded:
- id
line_length: 220
number_separator:
minimum_length: 5
- vertical_parameter_alignment_on_call

View File

@ -24,15 +24,16 @@ public extension Entity {
}
func get<A, B>(components _: A.Type, _: B.Type) -> (A?, B?) where A: Component, B: Component {
let a: A? = get(component: A.self)
let b: B? = get(component: B.self)
return (a, b)
let compA: A? = get(component: A.self)
let compB: B? = get(component: B.self)
return (compA, compB)
}
// swiftlint:disable:next large_tuple
func get<A, B, C>(components _: A.Type, _: B.Type, _: C.Type) -> (A?, B?, C?) where A: Component, B: Component, C: Component {
let a: A? = get(component: A.self)
let b: B? = get(component: B.self)
let c: C? = get(component: C.self)
return (a, b, c)
let compA: A? = get(component: A.self)
let compB: B? = get(component: B.self)
let compC: C? = get(component: C.self)
return (compA, compB, compC)
}
}

View File

@ -5,6 +5,7 @@
// Created by Christian Treffs on 08.10.17.
//
public protocol ECSEvent {}
public struct EntityCreated: ECSEvent {
let entityId: EntityIdentifier
}

View File

@ -7,57 +7,58 @@
public extension Family {
func iterate(entities apply: @escaping (EntityIdentifier) -> Void) {
for entityId in memberIds {
for entityId: EntityIdentifier in memberIds {
apply(entityId)
}
}
func iterate<A>(components _: A.Type, _ apply: @escaping (EntityIdentifier, A?) -> Void)
where A: Component {
for entityId in memberIds {
let a: A? = nexus?.get(for: entityId)
apply(entityId, a)
for entityId: EntityIdentifier in memberIds {
let compA: A? = nexus?.get(for: entityId)
apply(entityId, compA)
}
}
func iterate<A, B>(components _: A.Type, _: B.Type, _ apply: @escaping (EntityIdentifier, A?, B?) -> Void)
where A: Component, B: Component {
for entityId in memberIds {
let a: A? = nexus?.get(for: entityId)
let b: B? = nexus?.get(for: entityId)
apply(entityId, a, b)
for entityId: EntityIdentifier in memberIds {
let compA: A? = nexus?.get(for: entityId)
let compB: B? = nexus?.get(for: entityId)
apply(entityId, compA, compB)
}
}
func iterate<A, B, C>(components _: A.Type, _: B.Type, _: C.Type, _ apply: @escaping (EntityIdentifier, A?, B?, C?) -> Void)
where A: Component, B: Component, C: Component {
for entityId in memberIds {
let a: A? = nexus?.get(for: entityId)
let b: B? = nexus?.get(for: entityId)
let c: C? = nexus?.get(for: entityId)
apply(entityId, a, b, c)
for entityId: EntityIdentifier in memberIds {
let compA: A? = nexus?.get(for: entityId)
let compB: B? = nexus?.get(for: entityId)
let compC: C? = nexus?.get(for: entityId)
apply(entityId, compA, compB, compC)
}
}
func iterate<A, B, C, D>(components _: A.Type, _: B.Type, _: C.Type, _: D.Type, _ apply: @escaping (EntityIdentifier, A?, B?, C?, D?) -> Void) where A: Component, B: Component, C: Component, D: Component {
for entityId in memberIds {
let a: A? = nexus?.get(for: entityId)
let b: B? = nexus?.get(for: entityId)
let c: C? = nexus?.get(for: entityId)
let d: D? = nexus?.get(for: entityId)
apply(entityId, a, b, c, d)
for entityId: EntityIdentifier in memberIds {
let compA: A? = nexus?.get(for: entityId)
let compB: B? = nexus?.get(for: entityId)
let compC: C? = nexus?.get(for: entityId)
let compD: D? = nexus?.get(for: entityId)
apply(entityId, compA, compB, compC, compD)
}
}
// swiftlint:disable:next function_parameter_count
func iterate<A, B, C, D, E>(components _: A.Type, _: B.Type, _: C.Type, _: D.Type, _: E.Type, _ apply: @escaping (EntityIdentifier, A?, B?, C?, D?, E?) -> Void)
where A: Component, B: Component, C: Component, D: Component, E: Component {
for entityId in memberIds {
let a: A? = nexus?.get(for: entityId)
let b: B? = nexus?.get(for: entityId)
let c: C? = nexus?.get(for: entityId)
let d: D? = nexus?.get(for: entityId)
let e: E? = nexus?.get(for: entityId)
apply(entityId, a, b, c, d, e)
for entityId: EntityIdentifier in memberIds {
let compA: A? = nexus?.get(for: entityId)
let compB: B? = nexus?.get(for: entityId)
let compC: C? = nexus?.get(for: entityId)
let compD: D? = nexus?.get(for: entityId)
let compE: E? = nexus?.get(for: entityId)
apply(entityId, compA, compB, compC, compD, compE)
}
}

View File

@ -1,3 +1,4 @@
//
// Family.swift
// FirebladeECS
//
@ -6,6 +7,7 @@
// MARK: - family
public final class Family {
weak var nexus: Nexus?
// members of this Family must conform to these traits
public let traits: FamilyTraitSet
@ -14,9 +16,10 @@ public final class Family {
// a) define sort order of entities
// b) define read/write access
// c) set size and storage constraints
// d) conform to collection
// TODO: family unions
// a) iterate family A and family B in pairs
// a) iterate family A and family B in pairs - i.e. zip
// b) pair-wise comparison inside families or between families
init(_ nexus: Nexus, traits: FamilyTraitSet) {

View File

@ -15,9 +15,9 @@ public struct FamilyTraitSet {
public init(requiresAll: [Component.Type], excludesAll: [Component.Type], needsAtLeastOne: [Component.Type] = []) {
let all = ComponentSet(requiresAll.map { $0.identifier })
let none = ComponentSet(excludesAll.map { $0.identifier })
let one = ComponentSet(needsAtLeastOne.map { $0.identifier })
let all: ComponentSet = ComponentSet(requiresAll.map { $0.identifier })
let none: ComponentSet = ComponentSet(excludesAll.map { $0.identifier })
let one: ComponentSet = ComponentSet(needsAtLeastOne.map { $0.identifier })
let valid: Bool = FamilyTraitSet.isValid(requiresAll: all, excludesAll: none, atLeastOne: one)
assert(valid, "invalid family trait created - requiresAll: \(all), excludesAll: \(none), atLeastOne: \(one)")

View File

@ -30,8 +30,8 @@ public func hash(combine seed: Int, _ value: Int) -> Int {
#elseif arch(i386) || arch(arm) // 32 bit
let fibA: UInt = 0x9e3779b9 // = 2654435769 aka Fibonacci Hash a value for 2^32; calculate by: 2^32 / (golden ratio)
#endif
var uSeed = UInt(bitPattern: seed)
let uValue = UInt(bitPattern: value)
var uSeed: UInt = UInt(bitPattern: seed)
let uValue: UInt = UInt(bitPattern: value)
uSeed ^= uValue &+ fibA &+ (uSeed << 6) &+ (uSeed >> 2)
return Int(bitPattern: uSeed)
}
@ -66,7 +66,7 @@ extension EntityComponentHash {
static func decompose(_ hash: EntityComponentHash, with entityId: EntityIdentifier) -> ComponentTypeHash {
let entityIdSwapped: UInt = UInt(entityId).byteSwapped
let entityIdSwappedInt = Int(bitPattern: entityIdSwapped)
let entityIdSwappedInt: Int = Int(bitPattern: entityIdSwapped)
return hash ^ entityIdSwappedInt
}

View File

@ -87,8 +87,8 @@ public class ManagedContiguousArray: UniformStorage {
}
func nearest(to index: Index) -> Int {
let delta = Float(index) / Float(ManagedContiguousArray.chunkSize)
let multiplier = Int(delta) + 1
let delta: Float = Float(index) / Float(ManagedContiguousArray.chunkSize)
let multiplier: Int = Int(delta) + 1
return multiplier * ManagedContiguousArray.chunkSize
}
}

View File

@ -7,108 +7,103 @@
extension Nexus {
public var numComponents: Int {
return componentsByType.reduce(0) { return $0 + $1.value.count }
}
public var numComponents: Int {
return componentsByType.reduce(0) { return $0 + $1.value.count }
}
public func has(componentId: ComponentIdentifier, entityIdx: EntityIndex) -> Bool {
guard let uniforms = componentsByType[componentId] else {
return false
}
return uniforms.has(entityIdx)
}
public func has(componentId: ComponentIdentifier, entityIdx: EntityIndex) -> Bool {
guard let uniforms: UniformComponents = componentsByType[componentId] else {
return false
}
return uniforms.has(entityIdx)
}
public func count(components entityId: EntityIdentifier) -> Int {
switch componentIdsByEntity[entityId.index] {
case .some(let componentIds):
return componentIds.count
case .none:
return 0
}
}
public func count(components entityId: EntityIdentifier) -> Int {
return componentIdsByEntity[entityId.index]?.count ?? 0
}
public func assign(component: Component, to entity: Entity) {
let componentId = component.identifier
let entityIdx = entity.identifier.index
let entityId: EntityIdentifier = entity.identifier
public func assign(component: Component, to entity: Entity) {
let componentId: ComponentIdentifier = component.identifier
let entityIdx: EntityIndex = entity.identifier.index
let entityId: EntityIdentifier = entity.identifier
/// test if component is already assigned
guard !has(componentId: componentId, entityIdx: entityIdx) else {
// FIXME: this is still open to debate
// a) we replace the component
// b) we copy the properties
// c) we assert fail
report("ComponentAdd collision: \(entityIdx) already has a component \(component)")
return
}
/// test if component is already assigned
guard !has(componentId: componentId, entityIdx: entityIdx) else {
// FIXME: this is still open to debate
// a) we replace the component
// b) we copy the properties
// c) we assert fail
report("ComponentAdd collision: \(entityIdx) already has a component \(component)")
return
}
// add component instances to uniform component stores
if componentsByType[componentId] == nil {
componentsByType[componentId] = UniformComponents()
}
componentsByType[componentId]?.add(component, at: entityIdx)
// add component instances to uniform component stores
if componentsByType[componentId] == nil {
componentsByType[componentId] = UniformComponents()
}
componentsByType[componentId]?.add(component, at: entityIdx)
// assigns the component id to the entity id
if componentIdsByEntity[entityIdx] == nil {
componentIdsByEntity[entityIdx] = SparseComponentIdentifierSet()
}
componentIdsByEntity[entityIdx]?.add(componentId, at: componentId.hashValue)
// assigns the component id to the entity id
if componentIdsByEntity[entityIdx] == nil {
componentIdsByEntity[entityIdx] = SparseComponentIdentifierSet()
}
componentIdsByEntity[entityIdx]?.add(componentId, at: componentId.hashValue)
update(familyMembership: entityId)
update(familyMembership: entityId)
notify(ComponentAdded(component: componentId, toEntity: entity.identifier))
}
notify(ComponentAdded(component: componentId, toEntity: entity.identifier))
}
public func assign<C>(component: C, to entity: Entity) where C: Component {
assign(component: component, to: entity)
}
public func assign<C>(component: C, to entity: Entity) where C: Component {
assign(component: component, to: entity)
}
public func get(component componentId: ComponentIdentifier, for entityId: EntityIdentifier) -> Component? {
guard let uniformComponents: UniformComponents = componentsByType[componentId] else {
return nil
}
return uniformComponents.get(at: entityId.index) as? Component
}
public func get(component componentId: ComponentIdentifier, for entityId: EntityIdentifier) -> Component? {
guard let uniformComponents: UniformComponents = componentsByType[componentId] else {
return nil
}
return uniformComponents.get(at: entityId.index) as? Component
}
public func get<C>(for entityId: EntityIdentifier) -> C? where C: Component {
let componentId: ComponentIdentifier = C.identifier
return get(componentId: componentId, entityIdx: entityId.index)
}
public func get<C>(for entityId: EntityIdentifier) -> C? where C: Component {
let componentId: ComponentIdentifier = C.identifier
return get(componentId: componentId, entityIdx: entityId.index)
}
private func get<C>(componentId: ComponentIdentifier, entityIdx: EntityIndex) -> C? where C: Component {
guard let uniformComponents: UniformComponents = componentsByType[componentId] else {
return nil
}
return uniformComponents.get(at: entityIdx) as? C
}
private func get<C>(componentId: ComponentIdentifier, entityIdx: EntityIndex) -> C? where C: Component {
guard let uniformComponents: UniformComponents = componentsByType[componentId] else {
return nil
}
return uniformComponents.get(at: entityIdx) as? C
}
public func get(components entityId: EntityIdentifier) -> SparseComponentIdentifierSet? {
return componentIdsByEntity[entityId.index]
}
public func get(components entityId: EntityIdentifier) -> SparseComponentIdentifierSet? {
return componentIdsByEntity[entityId.index]
}
@discardableResult
public func remove(component componentId: ComponentIdentifier, from entityId: EntityIdentifier) -> Bool {
let entityIdx: EntityIndex = entityId.index
//let hash: EntityComponentHash = componentId.hashValue(using: entityIdx)
@discardableResult
public func remove(component componentId: ComponentIdentifier, from entityId: EntityIdentifier) -> Bool {
let entityIdx: EntityIndex = entityId.index
//let hash: EntityComponentHash = componentId.hashValue(using: entityIdx)
// delete component instance
componentsByType[componentId]?.remove(at: entityIdx)
// unasign component from entity
componentIdsByEntity[entityIdx]?.remove(at: componentId.hashValue)
// delete component instance
componentsByType[componentId]?.remove(at: entityIdx)
// unasign component from entity
componentIdsByEntity[entityIdx]?.remove(at: componentId.hashValue)
update(familyMembership: entityId)
update(familyMembership: entityId)
notify(ComponentRemoved(component: componentId, from: entityId))
return true
}
notify(ComponentRemoved(component: componentId, from: entityId))
return true
}
@discardableResult
public func clear(componentes entityId: EntityIdentifier) -> Bool {
guard let allComponents = get(components: entityId) else {
report("clearing components form entity \(entityId) with no components")
return true
}
let removedAll: Bool = allComponents.reduce(true) { $0 && remove(component: $1, from: entityId) }
return removedAll
}
@discardableResult
public func clear(componentes entityId: EntityIdentifier) -> Bool {
guard let allComponents: SparseComponentIdentifierSet = get(components: entityId) else {
report("clearing components form entity \(entityId) with no components")
return true
}
let removedAll: Bool = allComponents.reduce(true) { $0 && remove(component: $1, from: entityId) }
return removedAll
}
}

View File

@ -18,7 +18,7 @@ extension Nexus {
let newEntityIndex: EntityIndex = nextEntityIdx()
let newEntityIdentifier: EntityIdentifier = newEntityIndex.identifier
let newEntity = Entity(nexus: self, id: newEntityIdentifier, name: name)
let newEntity: Entity = Entity(nexus: self, id: newEntityIdentifier, name: name)
entityStorage.add(newEntity, at: newEntityIndex)
notify(EntityCreated(entityId: newEntityIdentifier))
return newEntity

View File

@ -15,7 +15,7 @@ public extension Nexus {
/// - oneComponents: at least one of component types must appear in this family.
/// - Returns: family with given traits.
func family(requiresAll allComponents: [Component.Type], excludesAll noneComponents: [Component.Type], needsAtLeastOne oneComponents: [Component.Type] = []) -> Family {
let traits = FamilyTraitSet(requiresAll: allComponents, excludesAll: noneComponents, needsAtLeastOne: oneComponents)
let traits: FamilyTraitSet = FamilyTraitSet(requiresAll: allComponents, excludesAll: noneComponents, needsAtLeastOne: oneComponents)
return family(with: traits)
}
@ -28,8 +28,8 @@ public extension Nexus {
func canBecomeMember(_ entity: Entity, in family: Family) -> Bool {
let entityIdx: EntityIndex = entity.identifier.index
guard let componentIds = componentIdsByEntity[entityIdx] else {
assert(false, "no component set defined for entity: \(entity)")
guard let componentIds: SparseComponentIdentifierSet = componentIdsByEntity[entityIdx] else {
assertionFailure("no component set defined for entity: \(entity)")
return false
}
let componentSet: ComponentSet = ComponentSet(componentIds)
@ -71,17 +71,18 @@ extension Nexus {
}
func onFamilyDeinit(traitHash: FamilyTraitSetHash) {
guard let members = members(of: traitHash) else {
guard let members: UniformEntityIdentifiers = members(of: traitHash) else {
return
}
for member in members {
for member: EntityIdentifier in members {
remove(from: traitHash, entityId: member, entityIdx: member.index)
}
}
func update(familyMembership entityId: EntityIdentifier) {
// FIXME: iterating all families is costly for many families
for family in familiesByTraitHash.values {
for family: Family in familiesByTraitHash.values {
update(membership: family, for: entityId)
}
}
@ -90,19 +91,19 @@ extension Nexus {
let entityIdx: EntityIndex = entityId.index
let traits: FamilyTraitSet = family.traits
let traitHash: FamilyTraitSetHash = traits.hashValue
guard let componentIds = componentIdsByEntity[entityIdx] else {
guard let componentIds: SparseComponentIdentifierSet = componentIdsByEntity[entityIdx] else {
return
}
let is_Member: Bool = isMember(entityId, in: family)
if !has(entity: entityId) && is_Member {
let isMember: Bool = self.isMember(entityId, in: family)
if !has(entity: entityId) && isMember {
remove(from: traitHash, entityId: entityId, entityIdx: entityIdx)
return
}
let componentsSet: ComponentSet = ComponentSet(componentIds)
let isMatch: Bool = traits.isMatch(components: componentsSet)
switch (isMatch, is_Member) {
switch (isMatch, isMember) {
case (true, false):
add(to: traitHash, entityId: entityId, entityIdx: entityIdx)
notify(FamilyMemberAdded(member: entityId, toFamily: traits))
@ -126,8 +127,8 @@ private extension Nexus {
func create(family traits: FamilyTraitSet) -> Family {
let traitHash: FamilyTraitSetHash = traits.hashValue
let family = Family(self, traits: traits)
let replaced = familiesByTraitHash.updateValue(family, forKey: traitHash)
let family: Family = Family(self, traits: traits)
let replaced: Family? = familiesByTraitHash.updateValue(family, forKey: traitHash)
assert(replaced == nil, "Family with exact trait hash already exists: \(traitHash)")
notify(FamilyCreated(family: traits))
return family

View File

@ -60,8 +60,8 @@ public class Nexus {
deinit {
for e: Entity in entityStorage {
destroy(entity: e)
for entity: Entity in entityStorage {
destroy(entity: entity)
}
entityStorage.clear()

View File

@ -64,7 +64,7 @@ public class SparseSet<Element>: UniformStorage, Sequence {
denseIndices.swapAt(removeIdx, lastIdx)
denseData.swapAt(removeIdx, lastIdx)
sparse[index] = nil
let swappedIndex = denseIndices[removeIdx]
let swappedIndex: Index = denseIndices[removeIdx]
sparse[swappedIndex] = removeIdx
denseIndices.removeLast()
denseData.removeLast()