diff --git a/Sources/FirebladeECS/EntityHub.swift b/Sources/FirebladeECS/EntityHub.swift index ec354e5..40ce8d5 100644 --- a/Sources/FirebladeECS/EntityHub.swift +++ b/Sources/FirebladeECS/EntityHub.swift @@ -12,33 +12,51 @@ public class EntityHub: EventHandler { private(set) var entites: Set //private(set) var entites: [UEI:Entity] = [:] - private(set) var families: Set + private(set) var families: [FamilyTraits:Family] public init() { entites = Set() entites.reserveCapacity(512) - families = Set() + families = [FamilyTraits: Family]() families.reserveCapacity(64) self.delegate = eventHub subscribe(event: handleEntityCreated) - subscribe(event: handleFamilyCreated) + subscribe(event: handleEntityDestroyed) + subscribe(event: handleComponentAdded) + subscribe(event: handleComponentUpdated) + subscribe(event: handleComponentRemoved) + + subscribe(event: handleFamilyCreated) subscribe(event: handleFamilyMemberAdded) + subscribe(event: handleFamilyMemberUpdated) + subscribe(event: handleFamilyMemberRemoved) + subscribe(event: handleFamilyDestroyed) } + deinit { unsubscribe(event: handleEntityCreated) - unsubscribe(event: handleFamilyCreated) + unsubscribe(event: handleEntityDestroyed) + unsubscribe(event: handleComponentAdded) + unsubscribe(event: handleComponentUpdated) + unsubscribe(event: handleComponentRemoved) + + unsubscribe(event: handleFamilyCreated) + unsubscribe(event: handleFamilyMemberUpdated) unsubscribe(event: handleFamilyMemberAdded) + unsubscribe(event: handleFamilyMemberRemoved) + unsubscribe(event: handleFamilyDestroyed) } } -// MARK: - creators +// MARK: - creator entity extension EntityHub { + public func createEntity() -> Entity { let newEntity = Entity(uei: UEI.next, dispatcher: eventHub) // ^ dispatches entity creation event here ^ @@ -48,13 +66,35 @@ extension EntityHub { return newEntity } - public func createFamily(with traits: FamilyTraits) -> Family { +} + +// MARK: - create/get family +extension EntityHub { + + @discardableResult + public func family(with traits: FamilyTraits) -> (new: Bool, family: Family) { + + if let existingFamily: Family = families[traits] { + return (new: false, family: existingFamily) + } + let newFamily = Family(traits: traits, eventHub: eventHub) // ^ dispatches family creation event here ^ - let (success, _) = families.insert(newFamily) - assert(success == true, "Family with the exact traits already exists") + let replaced = families.updateValue(newFamily, forKey: traits) + assert(replaced == nil, "Family with the exact traits already exists") - return newFamily + refreshFamilyCache() + + return (new: true, family: newFamily) + } + + fileprivate func onFamilyCreated(_ newFamily: Family) { + let previousEntities = entites + newFamily.update(membership: previousEntities) + } + + fileprivate func refreshFamilyCache() { + // TODO: } } @@ -62,8 +102,20 @@ extension EntityHub { // MARK: - event handler extension EntityHub { func handleEntityCreated(_ e: EntityCreated) { print(e) } - func handleFamilyCreated(_ e: FamilyCreated) { print(e) } + func handleEntityDestroyed(_ e: EntityDestroyed) { print(e) } func handleComponentAdded(_ e: ComponentAdded) { print(e) } + func handleComponentUpdated(_ e: ComponentUpdated) { print(e) } + func handleComponentRemoved(_ e: ComponentRemoved) { print(e) } + + func handleFamilyCreated(_ e: FamilyCreated) { + print(e) + let newFamily: Family = e.family + onFamilyCreated(newFamily) + + } func handleFamilyMemberAdded(_ e: FamilyMemberAdded) { print(e) } + func handleFamilyMemberUpdated(_ e: FamilyMemberUpdated) { print(e) } + func handleFamilyMemberRemoved(_ e: FamilyMemberRemoved) { print(e) } + func handleFamilyDestroyed(_ e: FamilyDestroyed) { print(e) } } diff --git a/Sources/FirebladeECS/Events.swift b/Sources/FirebladeECS/Events.swift index a253541..4f2259a 100644 --- a/Sources/FirebladeECS/Events.swift +++ b/Sources/FirebladeECS/Events.swift @@ -6,49 +6,49 @@ // public struct EntityCreated: Event { - let entity: Entity + unowned let entity: Entity } public struct EntityDestroyed: Event { - let entity: Entity + unowned let entity: Entity } public struct ComponentAdded: Event { //let component: Component - let to: Entity + unowned let to: Entity } public struct ComponentUpdated: Event { //let component: Component //let previous: Component - let at: Entity + unowned let at: Entity } public struct ComponentRemoved: Event { //let component: Component - let from: Entity + unowned let from: Entity } struct FamilyMemberAdded: Event { - let member: Entity - let to: Family + unowned let member: Entity + unowned let to: Family } struct FamilyMemberUpdated: Event { - let newMember: Entity - let oldMember: Entity - let `in`: Family + unowned let newMember: Entity + unowned let oldMember: Entity + unowned let `in`: Family } struct FamilyMemberRemoved: Event { - let member: Entity - let from: Family + unowned let member: Entity + unowned let from: Family } struct FamilyCreated: Event { - let family: Family + unowned let family: Family } struct FamilyDestroyed: Event { - let family: Family + unowned let family: Family } diff --git a/Sources/FirebladeECS/Family.swift b/Sources/FirebladeECS/Family.swift index 4b30dc1..2342a18 100644 --- a/Sources/FirebladeECS/Family.swift +++ b/Sources/FirebladeECS/Family.swift @@ -19,6 +19,7 @@ public final class Family { public init(traits: FamilyTraits, eventHub: EventHub & EventDispatcher) { members = Set() + members.reserveCapacity(64) self.traits = traits @@ -53,6 +54,13 @@ public final class Family { // MARK: - update family membership extension Family { + func update(membership entites: C) where C.Iterator.Element == Entity { + var entityIterator = entites.makeIterator() + while let entity: Entity = entityIterator.next() { + update(membership: entity) + } + } + fileprivate func update(membership entity: Entity) { let isMatch: Bool = traits.isMatch(entity) switch isMatch { @@ -143,21 +151,17 @@ extension Family: EventDispatcher { extension Family: EventHandler { fileprivate final func handleComponentAddedToEntity(event: ComponentAdded) { - //let newComponent: Component = event.component - let entity: Entity = event.to + unowned let entity: Entity = event.to update(membership: entity) } fileprivate final func handleComponentUpdatedAtEntity(event: ComponentUpdated) { - //let newComponent: Component = event.component - //let oldComponent: Component = event.previous - let entity: Entity = event.at + unowned let entity: Entity = event.at update(membership: entity) } fileprivate final func handleComponentRemovedFromEntity(event: ComponentRemoved) { - //let removedComponent: Component = event.component - let entity: Entity = event.from + unowned let entity: Entity = event.from update(membership: entity) } diff --git a/Tests/FirebladeECSTests/FamilyTests.swift b/Tests/FirebladeECSTests/FamilyTests.swift index c1a832c..e30ca0f 100644 --- a/Tests/FirebladeECSTests/FamilyTests.swift +++ b/Tests/FirebladeECSTests/FamilyTests.swift @@ -14,14 +14,23 @@ class FamilyTests: XCTestCase { func testFamily() { + let e1 = entityHub.createEntity() + e1 += EmptyComponent() + let e2 = entityHub.createEntity() + e2 += EmptyComponent() + let traits = FamilyTraits(hasAll: [EmptyComponent.uct], hasAny: [], hasNone: []) - let simpleFamily = entityHub.createFamily(with: traits) + let (new, _) = entityHub.family(with: traits) + XCTAssert(new == true) - let e = entityHub.createEntity() - e += EmptyComponent() + let (new2, _) = entityHub.family(with: traits) + XCTAssert(new2 == false) - e.remove(EmptyComponent.self) + let e3 = entityHub.createEntity() + e3 += EmptyComponent() + + e2.remove(EmptyComponent.self) } }