Finish basic scene graph implementation
This commit is contained in:
parent
8958d96687
commit
71a319fe27
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue