diff --git a/Sources/FirebladeECS/Entity+Component.swift b/Sources/FirebladeECS/Entity+Component.swift index 5b1e99e..30100eb 100644 --- a/Sources/FirebladeECS/Entity+Component.swift +++ b/Sources/FirebladeECS/Entity+Component.swift @@ -56,18 +56,35 @@ extension Entity { } /// Get the value of a component using the key Path to the property in the component. + /// + /// A `Comp` instance must be assigned to this entity! /// - Parameter componentKeyPath: The `KeyPath` to the property of the given component. @inlinable public func get(valueAt componentKeyPath: KeyPath) -> Value where Comp: Component { self.get(component: Comp.self)![keyPath: componentKeyPath] } + /// Get the value of a component using the key Path to the property in the component. + /// + /// A `Comp` instance must be assigned to this entity! + /// - Parameter componentKeyPath: The `KeyPath` to the property of the given component. + @inlinable + public func get(valueAt componentKeyPath: KeyPath) -> Value? where Comp: Component { + self.get(component: Comp.self)![keyPath: componentKeyPath] + } + /// Get the value of a component using the key Path to the property in the component. @inlinable public subscript(_ componentKeyPath: KeyPath) -> Value where Comp: Component { self.get(valueAt: componentKeyPath) } + /// Get the value of a component using the key Path to the property in the component. + @inlinable + public subscript(_ componentKeyPath: KeyPath) -> Value? where Comp: Component { + self.get(valueAt: componentKeyPath) + } + /// Set the value of a component using the key path to the property in the component. /// /// **Behavior:** @@ -91,6 +108,29 @@ extension Entity { return true } + /// Set the value of a component using the key path to the property in the component. + /// + /// **Behavior:** + /// - If `Comp` is a component type that is currently *not* assigned to this entity, + /// a new instance of `Comp` will be default initialized and `newValue` will be set at the given keyPath. + /// + /// - Parameters: + /// - newValue: The value to set. + /// - componentKeyPath: The `ReferenceWritableKeyPath` to the property of the given component. + /// - Returns: Returns true if an action was performed, false otherwise. + @inlinable + @discardableResult + public func set(value newValue: Value?, for componentKeyPath: ReferenceWritableKeyPath) -> Bool where Comp: Component & DefaultInitializable { + guard has(Comp.self) else { + let newInstance = Comp() + newInstance[keyPath: componentKeyPath] = newValue + return nexus.assign(component: newInstance, entityId: identifier) + } + + get(component: Comp.self)![keyPath: componentKeyPath] = newValue + return true + } + /// Set the value of a component using the key path to the property in the component. /// /// **Behavior:** @@ -101,4 +141,15 @@ extension Entity { get { self.get(valueAt: componentKeyPath) } nonmutating set { self.set(value: newValue, for: componentKeyPath) } } + + /// Set the value of a component using the key path to the property in the component. + /// + /// **Behavior:** + /// - If `Comp` is a component type that is currently *not* assigned to this entity, + /// a new instance of `Comp` will be default initialized and `newValue` will be set at the given keyPath. + @inlinable + public subscript(_ componentKeyPath: ReferenceWritableKeyPath) -> Value? where Comp: Component & DefaultInitializable { + get { self.get(valueAt: componentKeyPath) } + nonmutating set { self.set(value: newValue, for: componentKeyPath) } + } }