fireblade-ecs/Sources/FirebladeECS/FamilyTraitSet.swift

81 lines
2.3 KiB
Swift

//
// FamilyTraitSet.swift
// FirebladeECS
//
// Created by Christian Treffs on 09.10.17.
//
public struct FamilyTraitSet {
private let requiresAll: ComponentSet
private let excludesAll: ComponentSet
private let needsAtLeastOne: ComponentSet
private let setHash: Int
private let isEmptyAny: Bool
public init(requiresAll: [Component.Type], excludesAll: [Component.Type], needsAtLeastOne: [Component.Type] = []) {
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)")
isEmptyAny = one.isEmpty
setHash = hash(combine: [all, one, none])
self.requiresAll = all
self.needsAtLeastOne = one
self.excludesAll = none
}
// MARK: - match
public func isMatch(components: ComponentSet) -> Bool {
return hasAll(components) && hasNone(components) && hasOne(components)
}
private func hasAll(_ components: ComponentSet) -> Bool {
return requiresAll.isSubset(of: components)
}
private func hasNone(_ components: ComponentSet) -> Bool {
return excludesAll.isDisjoint(with: components)
}
private func hasOne(_ components: ComponentSet) -> Bool {
if needsAtLeastOne.isEmpty {
return true
}
return !needsAtLeastOne.isDisjoint(with: components)
}
// MARK: - valid
static func isValid(requiresAll: ComponentSet, excludesAll: ComponentSet, atLeastOne: ComponentSet) -> Bool {
return validAtLeastOneNonEmpty(requiresAll, atLeastOne) &&
requiresAll.isDisjoint(with: atLeastOne) &&
requiresAll.isDisjoint(with: excludesAll) &&
atLeastOne.isDisjoint(with: excludesAll)
}
static func validAtLeastOneNonEmpty(_ requiresAll: ComponentSet, _ atLeastOne: ComponentSet) -> Bool {
return !requiresAll.isEmpty || !atLeastOne.isEmpty
}
}
// MARK: - Equatable
extension FamilyTraitSet: Equatable {
public static func == (lhs: FamilyTraitSet, rhs: FamilyTraitSet) -> Bool {
return lhs.setHash == rhs.setHash
}
}
// MARK: - Hashable
extension FamilyTraitSet: Hashable {
public var hashValue: Int {
return setHash
}
}