Finish basic scene graph implementation

This commit is contained in:
Christian Treffs 2019-10-01 07:06:00 +02:00
parent 8958d96687
commit 71a319fe27
1 changed files with 35 additions and 8 deletions

View File

@ -134,25 +134,52 @@ extension Family.EntityComponentIterator: LazySequenceProtocol { }
// MARK: - relatives iterator
extension Family {
@inlinable public var descendRelatives: RelativesIterator {
return RelativesIterator(family: self)
@inlinable
public func descendRelatives(from root: Entity) -> RelativesIterator {
return RelativesIterator(family: self, root: root)
}
public struct RelativesIterator: IteratorProtocol {
@usableFromInline var memberIdsIterator: UnorderedSparseSetIterator<EntityIdentifier>
@usableFromInline unowned let nexus: Nexus
@usableFromInline let familyTraits: FamilyTraitSet
public init(family: Family<R>) {
@usableFromInline var relatives: [(EntityIdentifier, EntityIdentifier)]
public init(family: Family<R>, root: Entity) {
self.nexus = family.nexus
memberIdsIterator = family.memberIds.makeIterator()
self.familyTraits = family.traits
// FIXME: this is not the most efficient way to aggregate all parent child tuples
// Problems:
// - allocates new memory
// - needs to be build on every iteration
// - relies on isMember check
self.relatives = []
self.relatives.reserveCapacity(family.memberIds.count)
aggregateRelativesBreathFirst(root.identifier)
relatives.reverse()
}
mutating func aggregateRelativesBreathFirst(_ parent: EntityIdentifier) {
guard let children = nexus.parentChildrenMap[parent] else {
return
}
children
.compactMap { child in
guard nexus.isMember(child, in: familyTraits) else {
return nil
}
relatives.append((parent, child))
return child
}
.forEach { aggregateRelativesBreathFirst($0) }
}
public mutating func next() -> R.RelativesDescending? {
guard let parentId = memberIdsIterator.next() else {
guard let (parentId, childId) = relatives.popLast() else {
return nil
}
return nil
return R.relativesDescending(nexus: nexus, parentId: parentId, childId: childId)
}
}
}