diff --git a/AwperativeKernel/Kernel/Atrributes/DebugAttributes.cs b/AwperativeKernel/Kernel/Atrributes/DebugAttributes.cs index 3e16cfc..fbdaeb6 100644 --- a/AwperativeKernel/Kernel/Atrributes/DebugAttributes.cs +++ b/AwperativeKernel/Kernel/Atrributes/DebugAttributes.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; namespace AwperativeKernel; @@ -30,6 +29,7 @@ public static class DebugAttributes /// Returns true or false based on the given condition from the attribute, unless Debug.IgnoreErrors is true, in which it will always return true, but still try to throw errors. /// It is required to use VerifyOrThrow() to validate important conditions for methods within the kernel. You may also feel free to use this outside in any modules or games. /// It is easiest to use VerifyOrThrow like : (In your method) if(!Attribute.VerifyOrThrow()) return; That way the attribute can exit the code if the condition is false. + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] public static bool VerifyOrThrow(ComponentDocker __docker, Component __component) { if (__docker.Contains(__component)) return true; @@ -56,6 +56,7 @@ public static class DebugAttributes /// + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] public static bool VerifyOrThrow(ComponentDocker __docker, Component __component) { if (!__docker.Contains(__component)) return true; @@ -82,6 +83,7 @@ public static class DebugAttributes /// + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] public static bool VerifyOrThrow(Component __component) { if (__component.ComponentDocker == null) return true; @@ -108,6 +110,7 @@ public static class DebugAttributes /// + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] public static bool VerifyOrThrow(ComponentDocker __docker, ComponentDocker __other) { if (!__docker.Equals(__other)) return true; @@ -130,6 +133,7 @@ public static class DebugAttributes /// + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] public static bool VerifyOrThrow(Component __component) { if (__component != null) return true; @@ -148,6 +152,7 @@ public static class DebugAttributes /// + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] public static bool VerifyOrThrow(ComponentDocker __componentDocker) { if (__componentDocker != null) return true; @@ -166,6 +171,7 @@ public static class DebugAttributes /// + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] public static bool VerifyOrThrow(Scene __scene) { if (__scene != null) return true; diff --git a/AwperativeKernel/Kernel/Atrributes/MarkerAttributes.cs b/AwperativeKernel/Kernel/Atrributes/MarkerAttributes.cs index 2161b04..190529a 100644 --- a/AwperativeKernel/Kernel/Atrributes/MarkerAttributes.cs +++ b/AwperativeKernel/Kernel/Atrributes/MarkerAttributes.cs @@ -4,30 +4,66 @@ using System; namespace AwperativeKernel; +/// +/// Provides many handy cosmetic attributes for methods to specify use cases or provide information. +/// +/// Avery Norris public static class MarkerAttributes { - /// - /// Shows that the given object is unsafe (ex. it doesn't check for null values and such, or it doesn't have guardrails based on cases). + /// Shows that the given object is unsafe (ex. it doesn't check for null values and such, or it doesn't have guardrails based on cases). /// This is just for internal/private methods to remind myself how to call it :) The reasoning is case by case, but most of the time, - /// it is because all of the exposing public methods already check, and double checks would only slow me down - /// + /// it is because all the exposing public methods already check, and double checks would only slow me down [AttributeUsage(AttributeTargets.All)] public class UnsafeInternal : Attribute { } - /// - /// Shows that the given object (meant for external use) is calculated every time it is called! Good to know for performance heavy systems. - /// + /// Shows that the given object is calculated every time it is called! Good to know for performance heavy systems. [AttributeUsage(AttributeTargets.All)] - public class CalculatedProperty() : Attribute { } + public class CalculatedProperty : Attribute { } - /// - /// Just a way to write how expensive a calculated property can be. - /// + /// Just a way to write how expensive a calculated property or method can be. [AttributeUsage(AttributeTargets.All)] - public class CalculatedPropertyExpense(string Expense) : Attribute { } + public class Expense(Expense.ExpenseLevel __expense) : Attribute + { + public enum ExpenseLevel { + None, + VeryLow, + Low, + Medium, + High, + VeryHigh, + } + + + public ExpenseLevel expense = __expense; + } + + + + /// Just a way to write the time complexity of a calculated property or method. + [AttributeUsage(AttributeTargets.All)] + public class Complexity(Complexity.TimeComplexity __complexity) : Attribute + { + public enum TimeComplexity + { + O1, + OLogN, + ON, + ONLogN, + ON2, + ON3 + } + + public TimeComplexity complexity = __complexity; + } + + + + /// Shows that the given method does not actually belong to the object, but instead just calls a lambda to another method. + [AttributeUsage(AttributeTargets.All)] + public class MethodPointer : Attribute { } } \ No newline at end of file diff --git a/AwperativeKernel/Kernel/Component/Component.cs b/AwperativeKernel/Kernel/Component/Component.cs index 2dfb875..521e398 100644 --- a/AwperativeKernel/Kernel/Component/Component.cs +++ b/AwperativeKernel/Kernel/Component/Component.cs @@ -1,32 +1,26 @@ -using System; using System.Collections.Generic; -using System.Collections.Immutable; -using System.Collections.ObjectModel; -using System.Diagnostics; -using System.Linq; -using System.Reflection; -using Microsoft.VisualBasic; namespace AwperativeKernel; - - +/// +/// The backing class for components in Awperative; provides access to a few important methods, and inheriting this is required to receive time based events. +/// When Start() is called, Awperative reflectively analyzes all classes that inherits component, and checks for given events. See the wiki for more information! +/// +/// Avery Norris public abstract partial class Component : ComponentDocker { - /// Current parent of the Component. Can be either Scene or another Component. + /// Current parent of the Component. Can be either a Scene or another Component. [MarkerAttributes.UnsafeInternal] - public ComponentDocker ComponentDocker { get; set; } = null; + public ComponentDocker ComponentDocker { get; internal set; } = null; - - /// - /// Component name - /// - [NotNull] + + /// Component's name + [DebugAttributes.NotNull] public string Name { get => _name; set { if (!DebugAttributes.NotNull.VerifyOrThrow(value)) return; _name = value; } @@ -34,19 +28,19 @@ public abstract partial class Component : ComponentDocker /// Represents the state of this Component, The largest bit represents if the Component is enabled or not, while the - /// next 7 represent its priority + /// next 7 represent its priority like so : (Enabled -> 0 | Priority -> 0000000) [MarkerAttributes.UnsafeInternal] private byte OrderProfile; /// If the component receives time events or not. - [MarkerAttributes.CalculatedProperty, MarkerAttributes.CalculatedPropertyExpense("Very Low")] + [MarkerAttributes.CalculatedProperty, MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] public bool Enabled { get => (OrderProfile & 128) > 0; set => OrderProfile = (byte)((OrderProfile & 127) | (value ? 128 : 0)); } - /// Represents the Component's Update priority, can be set to any value ranging from -64 to 63; otherwise an error will throw! - [MarkerAttributes.CalculatedProperty, MarkerAttributes.CalculatedPropertyExpense("Very Low")] + /// Represents the Component's Update priority; higher priorities get updated first. Can be any integer in the range -64 -> 63. + [MarkerAttributes.CalculatedProperty, MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] public int Priority { get => (sbyte)(OrderProfile << 1) >> 1; set { @@ -55,62 +49,46 @@ public abstract partial class Component : ComponentDocker ComponentDocker.UpdatePriority(this, value); } } - - - - - /// - /// Attempts to send an Event to the Component, terminates if the Component does not have the given Event - /// - /// Type of Event + + /// A list of all tags belonging to the component. Use AddTag() to modify it. + public IReadOnlySet Tags => _tags; + [MarkerAttributes.UnsafeInternal] internal HashSet _tags = []; + + + /// Attempts to send an event to the component, and quietly exits if not. [MarkerAttributes.UnsafeInternal] internal void TryEvent(int __timeEvent) { Awperative._TypeAssociatedTimeEvents[GetType()][__timeEvent]?.Invoke(this); } - - - /// - /// Identifiers for Components. - /// - public IReadOnlyList Tags => [.._tags]; - [MarkerAttributes.UnsafeInternal] internal HashSet _tags = []; - - - - /// - /// Adds a new tag to the Component - /// - /// The tag to add - public void AddTag([DebugAttributes.NotNull, DebugAttributes.CollectionDoesntContain] string __tag) - { + /// Adds a new tag to the component + [MarkerAttributes.CalculatedProperty, MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Low), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public void AddTag([DebugAttributes.NotNull, DebugAttributes.CollectionDoesntContain] string __tag) { if(!DebugAttributes.NotNull.VerifyOrThrow(__tag)) return; if(!DebugAttributes.CollectionDoesntContain.VerifyOrThrow(__tag, _tags)) return; - + _tags.Add(__tag); - ComponentDocker.AddTagToComponent(__tag, this); + ComponentDocker.HashTaggedComponent(__tag, this); } - /// - /// Adds a new tag to the Component - /// - /// The tag to add - public void RemoveTag([DebugAttributes.NotNull,DebugAttributes.CollectionContains] string __tag) - { + /// Removes a tag from the component. + [MarkerAttributes.CalculatedProperty, MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Low), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public void RemoveTag([DebugAttributes.NotNull,DebugAttributes.CollectionContains] string __tag) { if (!DebugAttributes.NotNull.VerifyOrThrow(__tag)) return; if(!DebugAttributes.CollectionContains.VerifyOrThrow(__tag, _tags)) return; - + _tags.Remove(__tag); - ComponentDocker.RemoveTagFromComponent(__tag, this); + ComponentDocker.UnhashTaggedComponent(__tag, this); } + /// Just gives the Component's name. But makes debugging a little easier :). public override string ToString() { return this.Name; } diff --git a/AwperativeKernel/Kernel/Component/ComponentCalculatedProperties.cs b/AwperativeKernel/Kernel/Component/ComponentCalculatedProperties.cs new file mode 100644 index 0000000..e714fe1 --- /dev/null +++ b/AwperativeKernel/Kernel/Component/ComponentCalculatedProperties.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; + + +namespace AwperativeKernel; + + +public abstract partial class Component +{ + /// Scene the Component resides in. To save ram it's not stored but calculated on the fly. + [MarkerAttributes.CalculatedProperty, MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public Scene Scene => __QueryScene(); + private Scene __QueryScene() { + if (ComponentDocker is Scene scene) return scene; + if (ComponentDocker is Component Component) return Component.__QueryScene(); + + return null; + } + + + + /// Returns the Parent Component. Will be null if the Component's parent is a Scene. + [MarkerAttributes.CalculatedProperty, MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public Component Parent => __QueryParent(); + private Component __QueryParent() { + if (ComponentDocker is Component Component) + return Component; + return null; + } + + + + /// All parent Components and the parents of the parents up until the Scene. Will only list parents of parents, not uncle Components. And will not list the Scene + [MarkerAttributes.CalculatedProperty, MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public IEnumerable AllParents => __QueryComponents(); + private IEnumerable __QueryComponents() { + List returnValue = []; + ComponentDocker currentComponentDocker = ComponentDocker; + + while (currentComponentDocker is not AwperativeKernel.Scene) { + if (currentComponentDocker is Component Component) { + returnValue.Add(Component); + currentComponentDocker = Component.ComponentDocker; + } + } + + return returnValue; + } + + +} \ No newline at end of file diff --git a/AwperativeKernel/Kernel/Component/ComponentCalculatedProperty.cs b/AwperativeKernel/Kernel/Component/ComponentCalculatedProperty.cs deleted file mode 100644 index 6f379c1..0000000 --- a/AwperativeKernel/Kernel/Component/ComponentCalculatedProperty.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System.Collections.Generic; - -namespace AwperativeKernel; - -public abstract partial class Component -{ - /// - /// Scene the Component resides in. - /// - [CalculatedProperty, CalculatedPropertyExpense("Medium: O(Parents)")] - public Scene Scene => __QueryScene(); - private Scene __QueryScene() { - if (ComponentDocker is Scene scene) return scene; - if (ComponentDocker is Component Component) return Component.__QueryScene(); - - return null; - } - - - - /// - /// Returns the Parent Component. Will be null if the Component is at the base of a scene. - /// - [CalculatedProperty, CalculatedPropertyExpense("Very Low O(1)")] - public Component Parent => __QueryParent(); - private Component __QueryParent() { - if (ComponentDocker is Component Component) - return Component; - return null; - } - - - - /// - /// All parent Components and the parents of the parents up until the Scene. Will only list parents of parents, not uncle Components. - /// - [CalculatedProperty, CalculatedPropertyExpense("Medium O(Parents)")] - public IReadOnlyList AllParents => __QueryComponents(); - private IReadOnlyList __QueryComponents() { - List returnValue = []; - ComponentDocker currentComponentDocker = ComponentDocker; - - while (!(currentComponentDocker is Scene)) - if (currentComponentDocker is Component Component) { - returnValue.Add(Component); - currentComponentDocker = Component.ComponentDocker; - } - return [..returnValue]; - } - - -} \ No newline at end of file diff --git a/AwperativeKernel/Kernel/Component/ComponentLambda.cs b/AwperativeKernel/Kernel/Component/ComponentLambda.cs index 8dc598e..d012169 100644 --- a/AwperativeKernel/Kernel/Component/ComponentLambda.cs +++ b/AwperativeKernel/Kernel/Component/ComponentLambda.cs @@ -1,33 +1,40 @@ namespace AwperativeKernel; + public abstract partial class Component { /// + [MarkerAttributes.MethodPointer] public static Scene CreateScene(string __name) => Awperative.CreateScene(__name); /// + [MarkerAttributes.MethodPointer] public static Scene GetScene(string __name) => Awperative.GetScene(__name); /// + [MarkerAttributes.MethodPointer] public void RemoveScene(Scene __scene) => Awperative.CloseScene(__scene); /// + [MarkerAttributes.MethodPointer] public void RemoveScene(string __name) => Awperative.CloseScene(__name); /// + [MarkerAttributes.MethodPointer] public void Move(ComponentDocker __newDocker) => ComponentDocker.Move(this, __newDocker); /// Makes the Component destroy itself + [MarkerAttributes.MethodPointer] public void Destroy() => ComponentDocker.Destroy(this); } \ No newline at end of file diff --git a/AwperativeKernel/Kernel/ComponentDocker/ComponentDocker.cs b/AwperativeKernel/Kernel/ComponentDocker/ComponentDocker.cs new file mode 100644 index 0000000..654f547 --- /dev/null +++ b/AwperativeKernel/Kernel/ComponentDocker/ComponentDocker.cs @@ -0,0 +1,143 @@ +using System; +using System.Collections; +using System.Collections.Generic; + + +namespace AwperativeKernel; + + +/// +/// Base class for all Awperative objects. Responsible for Managing hierarchy between Components and Scenes, has Extensive Component Manipulation Available. +/// Also transfers Time and Carries most of the responsibilities akin to the Component. NOT FOR INHERITING, please use docker by inheriting component. +/// +/// Avery Norris +public abstract partial class ComponentDocker : IEnumerable, IEquatable, IEquatable, IEquatable +{ + + //Blocks external inheritance + internal ComponentDocker() {} + + + + /// Core of the Docker, holds all of the Components, sorted by update priority. + [MarkerAttributes.UnsafeInternal] internal readonly List _components = []; + /// Holds a list of Components at each of their types. This optimizes Get<Type> to O(1) + [MarkerAttributes.UnsafeInternal] internal readonly Dictionary> _componentTypeDictionary = new(); + /// Stores a Component in a list at each of their tags. This optimizes Get(string tag) to O(1) + [MarkerAttributes.UnsafeInternal] internal readonly Dictionary> _componentTagDictionary = new(); + + + + /// All children belonging to the Component. + public IEnumerable Children => _components; + + + /// All children and children of children until the bottom of the scene. Uses Breadth First Search. + [MarkerAttributes.CalculatedProperty, MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.High), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public IEnumerable AllChildren => GetAllChildren(); + public IEnumerable GetAllChildren() { + List returnValue = []; + Queue queue = new(_components); + while (queue.Count > 0) { + Component current = queue.Dequeue(); + returnValue.Add(current); + + for (int i = 0; i < current.Count; i++) queue.Enqueue(current[i]); + } + + return returnValue; + } + + + /// Amount of Components attached to the Docker + public int Count => _components.Count; + + + + //Indexers to make for loops easier. + public Component this[[DebugAttributes.ValueFitsRange] int __index] { + get => !DebugAttributes.ValueFitsRange.VerifyOrThrow(__index, 0, _components.Count) ? null : _components[__index]; + set { if (!DebugAttributes.ValueFitsRange.VerifyOrThrow(__index, 0, _components.Count)) return; _components[__index] = value; } + } + + + + //Enumerators that allow convenient foreach loops. + IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } + public IEnumerator GetEnumerator() { return new ComponentDockEnum([.._components]); } + + + + /// Compares the Docker to another Scene. + public bool Equals(Scene __other) { + if (this is Scene scene) + return scene == __other; + return false; + } + + /// Compares the Docker to another Component. + public bool Equals(Component __other) { + if (this is Component component) + return component == __other; + return false; + } + + /// Compares the Docker to another Docker. + public bool Equals(ComponentDocker __other) { + return this == __other; + } + + + + + + /// Resorts the component list to order of priority + [MarkerAttributes.UnsafeInternal] + internal void UpdatePriority(Component __component, int __priority) { + _components.Sort(Awperative._prioritySorter); + } + + /// Sends an event to all Children and tells them to continue it. + /// Integer ID of the event to send. + [MarkerAttributes.UnsafeInternal] + internal void ChainEvent(int __timeEvent) { + for (int i = 0; i < _components.Count; i++) { + _components[i].TryEvent(__timeEvent); + _components[i].ChainEvent(__timeEvent); + } + } + + /// Add a Component to the Docker. + [MarkerAttributes.UnsafeInternal] + private void AddComponentToLists(Component __component) { + Type Type = __component.GetType(); + _components.Add(__component); + if (!_componentTypeDictionary.TryAdd(Type, [__component])) _componentTypeDictionary[Type].Add(__component); + + foreach (string tag in __component._tags) HashTaggedComponent(tag, __component); + } + + /// Removes a Component from the Docker. + [MarkerAttributes.UnsafeInternal] + private void RemoveComponentFromLists(Component __component) { + Type Type = __component.GetType(); + _components.Remove(__component); + + if(_componentTypeDictionary.TryGetValue(Type, out HashSet value)) value.Remove(__component); + + foreach (string tag in __component._tags) UnhashTaggedComponent(tag, __component); + } + + /// Hashes a component in the tag dictionary + [MarkerAttributes.UnsafeInternal] + internal void HashTaggedComponent(string __tag, Component __component) { + if (!_componentTagDictionary.TryAdd(__tag, [__component])) + _componentTagDictionary[__tag].Add(__component); + } + + /// Removes a component's hash from the tag dictionary + [MarkerAttributes.UnsafeInternal] + internal void UnhashTaggedComponent(string __tag, Component __component) { + if(!_componentTagDictionary.ContainsKey(__tag)) _componentTagDictionary[__tag].Remove(__component); + } +} \ No newline at end of file diff --git a/AwperativeKernel/Kernel/ComponentDocker/ComponentDockerExposure.cs b/AwperativeKernel/Kernel/ComponentDocker/ComponentDockerExposure.cs new file mode 100644 index 0000000..5783494 --- /dev/null +++ b/AwperativeKernel/Kernel/ComponentDocker/ComponentDockerExposure.cs @@ -0,0 +1,164 @@ +using System.Collections.Generic; +using System.Linq; + + +namespace AwperativeKernel; + + +public abstract partial class ComponentDocker +{ + + + /// Tells you whether the docker contains a component with the given tag + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public bool Contains([DebugAttributes.NotNull] string __tag) => DebugAttributes.NotNull.VerifyOrThrow(__tag) && _componentTagDictionary.ContainsKey(__tag); + + + /// Tells you whether the docker contains a component with the given type + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public bool Contains<__Type>() where __Type : Component => _componentTypeDictionary.ContainsKey(typeof(__Type)); + + /// Tells you whether the docker contains a component with a given type and tag + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public bool Contains<__Type>([DebugAttributes.NotNull] string __tag) where __Type : Component => DebugAttributes.NotNull.VerifyOrThrow(__tag) && GetAll<__Type>(__tag).Any(); + + /// Tells you whether the docker contains a component with all the given tags + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public bool Contains(IEnumerable __tags) => GetAll(__tags).Any(); + + /// Tells you whether the docker contains a component with all the given tags and the type + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public bool Contains<__Type>(IEnumerable __tags) where __Type : Component => GetAll<__Type>(__tags).Any(); + + /// Tells you whether the docker contains the given component. + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public bool Contains([DebugAttributes.ComponentNotNull] Component __component) => DebugAttributes.NotNull.VerifyOrThrow(__component) && _componentTypeDictionary.TryGetValue(__component.GetType(), out var components) && components.Contains(__component); + + + + + + /// Finds the first component with a given Type + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public __Type Get<__Type>() where __Type : Component => _componentTypeDictionary.TryGetValue(typeof(__Type), out HashSet Components) ? (__Type)Components.FirstOrDefault() : null; + + /// Tries to find the first component with a given tag, and returns false if there is none + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public bool TryGet<__Type>(out __Type __component) where __Type : Component { __component = Get<__Type>(); return __component != null; } + + + + /// Gets all components of a given type + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public IEnumerable<__Type> GetAll<__Type>() where __Type : Component => _componentTypeDictionary.TryGetValue(typeof(__Type), out var components) ? components.OfType<__Type>().ToList() : []; + + /// Tries to get all components of a given type and returns false if there are none + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public bool TryGetAll<__Type>(out IEnumerable<__Type> __components) where __Type : Component { __components = GetAll<__Type>(); return __components.Any(); } + + + + /// Finds all components that have all the given tags + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public IEnumerable GetAll(IEnumerable __tags) { + + HashSet components; + + if (_componentTagDictionary.TryGetValue(__tags.First(), out var firstComponents)) components = firstComponents; else return []; + + foreach(var tag in __tags) + if (_componentTagDictionary.TryGetValue(tag, out var taggedComponents)) + components.RemoveWhere(x => !taggedComponents.Contains(x)); + + return components; + } + + /// Tries to find all components that have all the given tags, returns false if there are none + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public bool TryGetAll(IEnumerable __tags, out IEnumerable __components) + { __components = GetAll(__tags); return __components.Any(); } + + + + + + /// Finds all Components that have the given type, and all the given tags + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public IEnumerable<__Type> GetAll<__Type>(IEnumerable __tags) where __Type : Component { + + if (!__tags.Any()) + return []; + + HashSet<__Type> components = []; + + if (_componentTagDictionary.TryGetValue(__tags.First(), out var firstComponents)) + foreach (var component in firstComponents) if (component is __Type typedComponent) components.Add(typedComponent); + + foreach(string tag in __tags) + if (_componentTagDictionary.TryGetValue(tag, out var taggedComponents)) + components.RemoveWhere(x => !taggedComponents.Contains(x as Component)); + + return components.ToList(); + } + + /// Tries to find all the components that have the given tags and type, returns false if there are none + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public bool TryGetAll<__Type>(IEnumerable __tags, out IEnumerable<__Type> __components) where __Type : Component { + __components = GetAll<__Type>(__tags); return __components.Any(); + } + + + + + + /// Gets all the components with the given tag + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public IEnumerable GetAll(string __tag) => GetAll([__tag]); + + /// Tries to get all the components with the given tag, returns false if there are none + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public bool TryGetAll(string __tag, out IEnumerable __components) { __components = GetAll(__tag); return __components.Any(); } + + + + /// Gets all the components that have a certain type, and a certain tag + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public IEnumerable<__Type> GetAll<__Type>(string __tag) where __Type : Component => GetAll<__Type>([__tag]); + + /// Tries to get all the components with a certain tag, and a type. Returns false if there are none + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public bool TryGetAll<__Type>(string __tag, out IEnumerable<__Type> __components) where __Type : Component { __components = GetAll<__Type>(__tag); return __components.Any(); } + + + + /// Gets the first component with all the given tags + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public Component Get(IEnumerable __tags) => GetAll(__tags).FirstOrDefault(); + + /// Tries to get the first component with all the given tags. Returns false if there are none + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public bool TryGet(IEnumerable __tags, out Component __component) { __component = Get(__tags); return __component != null; } + + + + /// Finds the first component with the given tag + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public Component Get(string __tag) => GetAll([__tag]).FirstOrDefault(); + + /// Tries to find the first component with the given tag, returns false if there is none + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public bool TryGet(string __tag, out Component __component) { __component = Get(__tag); return __component != null; } + + + + /// Gets the first component with the given type and tag + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public __Type Get<__Type>(string __tag) where __Type : Component => GetAll<__Type>(__tag).FirstOrDefault(); + + /// Tries to get the first component with the given type and tag, returns false if there is none. + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public bool TryGet<__Type>(string __tag, out __Type __component) where __Type : Component { __component = Get<__Type>(__tag); return __component != null; } + + + +} \ No newline at end of file diff --git a/AwperativeKernel/Kernel/ComponentDocker/ComponentDockerMovement.cs b/AwperativeKernel/Kernel/ComponentDocker/ComponentDockerMovement.cs new file mode 100644 index 0000000..f94c3e1 --- /dev/null +++ b/AwperativeKernel/Kernel/ComponentDocker/ComponentDockerMovement.cs @@ -0,0 +1,96 @@ +using System.Collections.Generic; +using System.Linq; + + +namespace AwperativeKernel; + + +public abstract partial class ComponentDocker +{ + + + + /// Moves a component belonging to the docker to another docker + public void Move([DebugAttributes.ComponentNotNull,DebugAttributes.DockerOwns] Component __component, [DebugAttributes.DockerNotNull,DebugAttributes.DifferentDocker] ComponentDocker __componentDocker) { + if(!DebugAttributes.ComponentNotNull.VerifyOrThrow(__component)) return; + if(!DebugAttributes.DockerOwns.VerifyOrThrow(this, __component)) return; + if(!DebugAttributes.DockerNotNull.VerifyOrThrow(__componentDocker)) return; + if(!DebugAttributes.DifferentDocker.VerifyOrThrow(this, __componentDocker)) return; + + if (!Contains(__component)) { + Debug.LogError("Docker does not have ownership over Component!", ["ComponentType"], [__component.GetType().Name]); return; + } + + if (__componentDocker == this) { + Debug.LogError("Docker already has Component!", ["ComponentType"], [__component.GetType().Name]); return; + } + + RemoveComponentFromLists(__component); + __componentDocker.AddComponentToLists(__component); + + __component.ComponentDocker = __componentDocker; + } + + + /// Moves all components in a list to another docker + public void MoveAll([DebugAttributes.EnumeratorNotNull, DebugAttributes.DockerOwns] IEnumerable __Components, [DebugAttributes.DockerNotNull, DebugAttributes.DifferentDocker] ComponentDocker __componentDocker) { + if(!DebugAttributes.EnumeratorNotNull.VerifyOrThrow(__Components)) return; + if(!DebugAttributes.DockerNotNull.VerifyOrThrow(__componentDocker)) return; + if(!DebugAttributes.DifferentDocker.VerifyOrThrow(this, __componentDocker)) return; + + foreach (Component Component in __Components) { + if(!DebugAttributes.DockerOwns.VerifyOrThrow(__componentDocker, Component)) return; + Move(Component, __componentDocker); + } + } + + /// Moves the first component with a given Type + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public void Move<__Type>(ComponentDocker __componentDocker) where __Type : Component => Move(Get<__Type>(), __componentDocker); + + + + /// Moves all components of a given type + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Low), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public void MoveAll<__Type>(ComponentDocker __componentDocker) where __Type : Component => MoveAll(GetAll<__Type>(), __componentDocker); + + + + /// Moves all components that have all the given tags + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public void MoveAll(IEnumerable __tags, ComponentDocker __componentDocker) => MoveAll(GetAll(__tags), __componentDocker); + + + + + /// Moves all Components that have the given type, and all the given tags + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public void MoveAll<__Type>(IEnumerable __tags, ComponentDocker __componentDocker) where __Type : Component => MoveAll(GetAll<__Type>(__tags), __componentDocker); + + + + + /// Moves all the components with the given tag + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public void MoveAll(string __tag, ComponentDocker __componentDocker) => MoveAll(GetAll([__tag]), __componentDocker); + + + + /// Moves all the components that have a certain type, and a certain tag + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public void MoveAll<__Type>(string __tag, ComponentDocker __componentDocker) where __Type : Component => MoveAll(GetAll<__Type>([__tag]), __componentDocker); + + + + /// Moves the first component with the given tag + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public void Move(string __tag, ComponentDocker __componentDocker) => Move(GetAll([__tag]).FirstOrDefault(), __componentDocker); + + + + /// Moves the moves component with the given type and tag + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public void Move<__Type>(string __tag, ComponentDocker __componentDocker) where __Type : Component => Move(GetAll<__Type>(__tag).FirstOrDefault(), __componentDocker); + + +} \ No newline at end of file diff --git a/AwperativeKernel/Kernel/ComponentDocker/ComponentDockerMutation.cs b/AwperativeKernel/Kernel/ComponentDocker/ComponentDockerMutation.cs new file mode 100644 index 0000000..2524b8e --- /dev/null +++ b/AwperativeKernel/Kernel/ComponentDocker/ComponentDockerMutation.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Linq; + + +namespace AwperativeKernel; + + +public abstract partial class ComponentDocker +{ + + + /// Attaches a preexisting component to the docker, this is not transferring the component, the method will throw an error if the component is already attached to a docker + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public void Add([DebugAttributes.ComponentNotNull,DebugAttributes.OrphanComponent] Component __component) { + if(!DebugAttributes.ComponentNotNull.VerifyOrThrow(__component)) return; + if(!DebugAttributes.OrphanComponent.VerifyOrThrow(__component)) return; + + //Component has already been added to another docker + if (__component.ComponentDocker != null) { Debug.LogError("You cannot use add if the Component already belongs to a Docker, use Component.Transfer();"); return; } + + InitiateComponent(__component); + } + + + /// Creates a new instance of that type of component and attaches it to the docker, and returns a reference to it. + public __Type Add<__Type>() where __Type : Component, new() { Component newComponent = new __Type(); InitiateComponent(newComponent); return (__Type)newComponent; } + + + /// Creates a new instance of that type of component and attaches it to the docker, and returns a reference to it. + public __Type Add<__Type>(string name = null, [DebugAttributes.ValueFitsRange] int priority = 0, Collection tags = null) where __Type : Component, new() { + Component newComponent = new __Type(); + newComponent.Name = name ??= typeof(__Type).Name; + newComponent._tags = [..tags ??= []]; + newComponent.Priority = priority; + + InitiateComponent(newComponent); return (__Type)newComponent; + } + + + /// Initiates a component into the docker. + [MarkerAttributes.UnsafeInternal] + private void InitiateComponent(Component __component) { + //add to Component Docker's lists + AddComponentToLists(__component); + + __component.ComponentDocker = this; + //create event + __component.TryEvent(4); __component.ChainEvent(4); + } + + + + + + /// Destroys a component attached to the Docker + /// + public void Destroy([DebugAttributes.ComponentNotNull,DebugAttributes.DockerOwns] Component __component) { + Stopwatch timer = Stopwatch.StartNew(); + if(!DebugAttributes.ComponentNotNull.VerifyOrThrow(__component)) return; + if(!DebugAttributes.DockerOwns.VerifyOrThrow(this, __component)) return; + + __component.TryEvent(5); + __component.ChainEvent(5); + + RemoveComponentFromLists(__component); + __component.ComponentDocker = null; + } + + + + /// Destroys all the components in a given list + public void DestroyAll([DebugAttributes.ComponentNotNull, DebugAttributes.DockerOwns] IEnumerable __Components) { foreach(Component component in __Components) Destroy(component); } + + + + /// Destroys the first component with a given Type + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public void Destroy<__Type>() where __Type : Component => Destroy(Get<__Type>()); + + + + /// Destroys all components of a given type + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Low), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public void DestroyAll<__Type>() where __Type : Component => DestroyAll(GetAll<__Type>()); + + + + /// Destroys all components that have all the given tags + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public void DestroyAll(IEnumerable __tags) => DestroyAll(GetAll(__tags)); + + + + + /// Destroys all Components that have the given type, and all the given tags + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public void DestroyAll<__Type>(IEnumerable __tags) where __Type : Component => DestroyAll(GetAll<__Type>(__tags)); + + + + + /// Destroys all the components with the given tag + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public void DestroyAll(string __tag) => DestroyAll(GetAll([__tag])); + + + + /// Destroys all the components that have a certain type, and a certain tag + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public void DestroyAll<__Type>(string __tag) where __Type : Component => DestroyAll(GetAll<__Type>([__tag])); + + + + /// Destroys the first component with the given tag + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)] + public void Destroy(string __tag) => Destroy(GetAll([__tag]).FirstOrDefault()); + + + + /// Destroys the Destroys component with the given type and tag + [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)] + public void Destroy<__Type>(string __tag) where __Type : Component => Destroy(GetAll<__Type>(__tag).FirstOrDefault()); + +} \ No newline at end of file diff --git a/AwperativeKernel/Kernel/ComponentDocker/Core/ComponentDocker.cs b/AwperativeKernel/Kernel/ComponentDocker/Core/ComponentDocker.cs deleted file mode 100644 index 4709020..0000000 --- a/AwperativeKernel/Kernel/ComponentDocker/Core/ComponentDocker.cs +++ /dev/null @@ -1,168 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Diagnostics; -using System.Linq; -using System.Reflection; - -namespace AwperativeKernel; - -/// -/// Base class for all Awperative objects. Responsible for Managing hierarchy between Components and Scenes, has Extensive Component Manipulation Available. -/// Also transfers Time and Carries most of the responsibilities akin to the Component. -/// -/// Please don't inherit this. I don't know why you would -/// Avery Norris -public abstract partial class ComponentDocker : IEnumerable, IEnumerable, IEquatable, IEquatable, IEquatable -{ - - //Blocks external inheritance - internal ComponentDocker() {} - - - - /// Core of the Docker, holds all of the Components, sorted by update priority. - [UnsafeInternal] internal readonly List _components = []; - /// Holds a list of Components at each of their types. This optimizes Get<Type> to O(1) - [UnsafeInternal] internal readonly Dictionary> _componentTypeDictionary = new(); - /// Stores a Component in a list at each of their tags. This optimizes Get(string tag) to O(1) - [UnsafeInternal] internal readonly Dictionary> _componentTagDictionary = new(); - - - - //Indexers to allow juicy speedy: for loops - public Component this[[ValueFitsRange] int __index] { - get => !ValueFitsRange.VerifyOrThrow(__index, 0, _components.Count) ? null : _components[__index]; - set { if (!ValueFitsRange.VerifyOrThrow(__index, 0, _components.Count)) return; _components[__index] = value; } - } - - //Allows uint indexing, which makes me mad because nobody ever does those. To convert it over we just mask the largest bit, and cast to integer. That way - //no sign flipping buisness happens. - public Component this[uint __index] => this[(int) (__index & 0x7FFFFFFF)]; - - - //Enumerators for convenient foreach loops - IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } - public IEnumerator GetEnumerator() { return new ComponentDockEnum([.._components]); } - - - /// Amount of Components attached to the Docker - public int Count => _components.Count; - - - - /// Compares the Docker to another Scene. - public bool Equals(Scene __other) { - if (this is Scene scene) - return scene == __other; - return false; - } - - /// Compares the Docker to another Component. - public bool Equals(Component __other) { - if (this is Component component) - return component == __other; - return false; - } - - /// Compares the Docker to another Docker. - public bool Equals(ComponentDocker __other) { - return this == __other; - } - - - - - - /// - /// Resorts member of Component list to match the Priority. - /// - /// Component to modify - /// New priority for Component - [UnsafeInternal] - internal void UpdatePriority(Component __component, int __priority) { - _components.Sort(Awperative._prioritySorter); - } - - /// - /// Sends an event to all Children and tells them to continue it. - /// - /// Type of event to send - [UnsafeInternal] - internal void ChainEvent(int __timeEvent) { - for (int i = 0; i < _components.Count; i++) { - _components[i].TryEvent(__timeEvent); - _components[i].ChainEvent(__timeEvent); - } - } - - /// - /// Add a Component into the lists and dictionaries. - /// - /// - [UnsafeInternal] - private void AddComponentToLists(Component __component) { - var Type = __component.GetType(); - _components.Add(__component); - if (!_componentTypeDictionary.TryAdd(Type, [__component])) _componentTypeDictionary[Type].Add(__component); - - foreach (var tag in __component._tags) AddTagToComponent(tag, __component); - } - - /// - /// Removes a Component from the lists and dictionaries. - /// - /// - [UnsafeInternal] - private void RemoveComponentFromLists(Component __component) { - var Type = __component.GetType(); - _components.Remove(__component); - - if(_componentTypeDictionary.TryGetValue(Type, out var value)) value.Remove(__component); - - foreach (var tag in __component._tags) RemoveTagFromComponent(tag, __component); - } - - /// - /// Hashes a Component in the tag dictionary - /// - /// Tag to add - /// Component to add it to - [UnsafeInternal] - internal void AddTagToComponent(string __tag, Component __component) { - if (!_componentTagDictionary.TryAdd(__tag, [__component])) - _componentTagDictionary[__tag].Add(__component); - } - - /// - /// Unhashes a Component from the tag dictionary - /// - /// Tag to remove - /// Component to remove it from - [UnsafeInternal] - internal void RemoveTagFromComponent(string __tag, Component __component) { - if(!_componentTagDictionary.ContainsKey(__tag)) _componentTagDictionary[__tag].Remove(__component); - } - - - - /// - /// All children belonging to the Component. - /// - [CalculatedProperty, CalculatedPropertyExpense("Very Low")] - public IReadOnlyList Children => _components; - - - - /// - /// All children and their children until the bottom of the scene. Uses Breadth First Search. - /// - [CalculatedProperty, CalculatedPropertyExpense("Medium O(Children)")] - public IReadOnlyList AllChildren => GetAllChildren(); - public IReadOnlyList GetAllChildren() { - List targets = [.._components]; - for (int i = 0; i < targets.Count; i++) targets.InsertRange(i + 1, targets[i]._components); - return [..targets]; - } -} \ No newline at end of file diff --git a/AwperativeKernel/Kernel/ComponentDocker/Core/ComponentDockerExposure.cs b/AwperativeKernel/Kernel/ComponentDocker/Core/ComponentDockerExposure.cs deleted file mode 100644 index e5404d1..0000000 --- a/AwperativeKernel/Kernel/ComponentDocker/Core/ComponentDockerExposure.cs +++ /dev/null @@ -1,366 +0,0 @@ - - -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Collections.ObjectModel; -using System.Linq; -using System.Runtime.CompilerServices; - - -namespace AwperativeKernel; - - -public abstract partial class ComponentDocker -{ - - - /// - /// Returns a bool based on if the Docker contains a Component with the given tag or not - /// - /// - /// - public bool Contains([NotNull] string __tag) - => NotNull.VerifyOrThrow(__tag) && _componentTagDictionary.ContainsKey(__tag); - - - /// - /// Returns a bool for if the Docker contains a Component of that type or not - /// - /// Type of the Component - public bool Contains<__Type>() where __Type : Component - => _componentTypeDictionary.ContainsKey(typeof(__Type)); - - - - /// - /// Returns a bool based on if the current __Component is owned by this Docker - /// - /// - /// - public bool Contains([ComponentNotNull] Component __component) - => NotNull.VerifyOrThrow(__component) && _componentTypeDictionary.TryGetValue(__component.GetType(), out var components) && components.Contains(__component); - - /// - /// Finds all Components that have all the given tags - /// - /// - /// - public bool Contains<__Type>([NotNull] string __tag) - => NotNull.VerifyOrThrow(__tag) && GetAll<__Type>(__tag).Any(); - - /// - /// Finds all Components that have all the given tags - /// - /// - /// - public bool Contains(IList __tags) { - return GetAll(__tags).Any(); - } - - /// - /// Finds all Components that have all the given tags - /// - /// - /// - public bool Contains(IEnumerable __tags) { - return GetAll(__tags).Any(); - } - - /// - /// Finds all Components that have all the given tags - /// - /// - /// - public bool Contains<__Type>(IList __tags) { - return GetAll<__Type>(__tags).Any(); - } - - /// - /// Finds all Components that have all the given tags - /// - /// - /// - public bool Contains<__Type>(IEnumerable __tags) { - return GetAll<__Type>(__tags).Any(); - } - - - - - - /// - /// Searches and returns the first Component of a type found on the Docker. - /// - /// The Type of Component to search for - /// - public __Type Get<__Type>() where __Type : Component { - return _componentTypeDictionary.TryGetValue(typeof(__Type), out var Components) ? (__Type)Components.FirstOrDefault() : null; - } - - /// - /// - /// - /// - /// - /// - public bool TryGet<__Type>(out __Type __component) where __Type : Component { - __component = Get<__Type>(); return __component != null; - } - - - - /// - /// Searches and returns all Components of a type found on the Docker. - /// - /// The Type of Components to search for - /// - public IReadOnlyList<__Type> GetAll<__Type>() where __Type : Component { - return _componentTypeDictionary.TryGetValue(typeof(__Type), out var components) ? components.OfType<__Type>().ToList() : []; - } - - /// - /// - /// - /// - /// - /// - public bool TryGetAll<__Type>(out IReadOnlyList<__Type> __components) where __Type : Component { - __components = GetAll<__Type>(); return __components.Any(); - } - - - - - - /// - /// Finds all Components that have all the given tags - /// - /// - /// - public IReadOnlyList GetAll(IList __tags) { - - if (__tags.Count == 0) - return []; - - HashSet components; - - if (_componentTagDictionary.TryGetValue(__tags[0], out var firstComponents)) components = firstComponents; else return []; - - for (var i = 1; i < __tags.Count; i++) - if (_componentTagDictionary.TryGetValue(__tags[i], out var taggedComponents)) - foreach (var component in components) if (!taggedComponents.Contains(component)) components.Remove(component);else return []; - - return components.ToList(); - } - - /// - /// Finds all Components that have all the given tags - /// - /// - /// - public bool TryGetAll(IList __tags, out IReadOnlyList __components) { - __components = GetAll(__tags); return __components.Any(); - } - - - - /// - /// Finds all Components that have all the given tags, slower than GetAll() using IList. If you are being high performance, use that. - /// - /// - /// - public IReadOnlyList GetAll(IEnumerable __tags) { - - if (!__tags.Any()) - return []; - - HashSet components; - - if (_componentTagDictionary.TryGetValue(__tags.First(), out var firstComponents)) components = firstComponents; else return []; - - foreach(var tag in __tags) - if (_componentTagDictionary.TryGetValue(tag, out var taggedComponents)) - foreach (var component in components) if (!taggedComponents.Contains(component)) components.Remove(component);else return []; - - return components.ToList(); - } - - /// - /// Finds all Components that have all the given tags - /// - /// - /// - public bool TryGetAll(IEnumerable __tags, out IReadOnlyList __components) { - __components = GetAll(__tags); return __components.Any(); - } - - - - - - /// - /// Finds all Components that have all the given tags - /// - /// - /// - public IReadOnlyList<__Type> GetAll<__Type>(IList __tags) { - - if (!__tags.Any()) - return []; - - HashSet<__Type> components = []; - - if (_componentTagDictionary.TryGetValue(__tags[0], out var firstComponents)) - foreach (var component in firstComponents) if (component is __Type typedComponent) components.Add(typedComponent); - - for (var i = 1; i < __tags.Count; i++) - if (_componentTagDictionary.TryGetValue(__tags[i], out var taggedComponents)) - foreach (var component in components) if (!taggedComponents.Contains(component as Component)) components.Remove(component);else return []; - - return components.ToList(); - } - - /// - /// Finds all Components that have all the given tags - /// - /// - /// - public bool TryGetAll<__Type>(IList __tags, out IReadOnlyList<__Type> __components) { - __components = GetAll<__Type>(__tags); return __components.Any(); - } - - - - - - /// - /// Finds all Components that have all the given tags - /// - /// - /// - public IReadOnlyList<__Type> GetAll<__Type>(IEnumerable __tags) { - - if (!__tags.Any()) - return []; - - HashSet<__Type> components = []; - - if (_componentTagDictionary.TryGetValue(__tags.First(), out var firstComponents)) - foreach (var component in firstComponents) if (component is __Type typedComponent) components.Add(typedComponent); - - foreach(string tag in __tags) - if (_componentTagDictionary.TryGetValue(tag, out var taggedComponents)) - foreach (var component in components) if (!taggedComponents.Contains(component as Component)) components.Remove(component);else return []; - - return components.ToList(); - } - - /// - /// Finds all Components that have all the given tags - /// - /// - /// - public bool TryGetAll<__Type>(IEnumerable __tags, out IReadOnlyList<__Type> __components) { - __components = GetAll<__Type>(__tags); return __components.Any(); - } - - - - /// - /// Finds all Components that have all the given tags - /// - /// - /// - public IReadOnlyList GetAll(string __tag) { - return GetAll([__tag]); - } - - /// - /// Finds all Components that have all the given tags - /// - /// - /// - public bool TryGetAll(string __tag, out IReadOnlyList __components) { - __components = GetAll(__tag); return __components.Any(); - } - - - - /// - /// Finds all Components that have all the given tags - /// - /// - /// - public IReadOnlyList<__Type> GetAll<__Type>(string __tag) { - return GetAll<__Type>([__tag]); - } - - /// - /// Finds all Components that have all the given tags - /// - /// - /// - public bool TryGetAll<__Type>(string __tag, out IReadOnlyList<__Type> __components) { - __components = GetAll<__Type>(__tag); return __components.Any(); - } - - - - public Component Get(IList __tags) { - return GetAll(__tags).FirstOrDefault(); - } - - public bool TryGet(IList __tags, out Component __component) { - __component = Get(__tags); return __component != null; - } - - - - public Component Get(IEnumerable __tags) { - return GetAll(__tags).FirstOrDefault(); - } - - public bool TryGet(IEnumerable __tags, out Component __component) { - __component = Get(__tags); return __component != null; - } - - - - public __Type Get<__Type>(IList __tags) { - return GetAll<__Type>(__tags).FirstOrDefault(); - } - - public bool TryGet<__Type>(IList __tags, out __Type __component) { - __component = Get<__Type>(__tags); return __component != null; - } - - - - public Component Get(string __tag) { - return GetAll([__tag]).FirstOrDefault(); - } - - public bool TryGet(string __tag, out Component __component) { - __component = Get(__tag); return __component != null; - } - - - - public __Type Get<__Type>(string __tag) { - return Get<__Type>([__tag]); - } - - public bool TryGet<__Type>(string __tag, out __Type __component) { - __component = Get<__Type>([__tag]); return __component != null; - } - - - - - - - - - -} \ No newline at end of file diff --git a/AwperativeKernel/Kernel/ComponentDocker/Core/ComponentDockerManagement.cs b/AwperativeKernel/Kernel/ComponentDocker/Core/ComponentDockerManagement.cs deleted file mode 100644 index 0357b89..0000000 --- a/AwperativeKernel/Kernel/ComponentDocker/Core/ComponentDockerManagement.cs +++ /dev/null @@ -1,191 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; - - -namespace AwperativeKernel; - - -public abstract partial class ComponentDocker -{ - - - - /// - /// Adds a previously instantiated Component to the Docker - /// - /// The Component to add - /// This is NOT meant to transfer a Component from one docker to another (Please use Move() for that). - /// And If you are just instantiating an Empty Component, also consider instead using Add<Type>(); - /// Avery Norris - #nullable enable - public void Add([ComponentNotNull,OrphanComponent] Component __component) { - if(!ComponentNotNull.VerifyOrThrow(__component)) return; - if(!OrphanComponent.VerifyOrThrow(__component)) return; - - //Component has already been added to another docker - if (__component.ComponentDocker != null) { Debug.LogError("You cannot use add if the Component already belongs to a Docker, use Component.Transfer();"); return; } - - InitiateComponent(__component); - } - - - - /// - /// Add a new Component to the Docker; and returns a reference to it! - /// - /// Type of Component to instantiate - /// Component cannot have a Constructor - /// Avery Norris - public __Type Add<__Type>() where __Type : Component, new() { Component newComponent = new __Type(); InitiateComponent(newComponent); return (__Type)newComponent; } - - - - /// - /// Add a new Component to the Docker; and returns a reference to it! - /// - /// Type of Component to instantiate - /// Component cannot have a Constructor - /// Avery Norris - public __Type Add<__Type>(string name = null, [ValueFitsRange] int priority = 0, Collection tags = null) where __Type : Component, new() { - Component newComponent = new __Type(); - newComponent.Name = name ??= typeof(__Type).Name; - newComponent._tags = [..tags ??= []]; - newComponent.Priority = priority; - - InitiateComponent(newComponent); return (__Type)newComponent; - } - - - - - - /// - /// Sets important Component variables; and tries to send the Create() event. - /// - /// - /// - private void InitiateComponent(Component __component) { - //add to Component Docker's lists - AddComponentToLists(__component); - - __component.ComponentDocker = this; - //create event - __component.TryEvent(4); __component.ChainEvent(4); - } - - - - - - /// - /// Transfers a Component to another Docker - /// - /// Component to move - /// Docker to move component to - /// Components cannot transfer themselves with this Method! - public void Move([ComponentNotNull,DockerOwns] Component __component, [DockerNotNull,DifferentDocker] ComponentDocker __componentDocker) { - if(!ComponentNotNull.VerifyOrThrow(__component)) return; - if(!DockerOwns.VerifyOrThrow(this, __component)) return; - if(!DockerNotNull.VerifyOrThrow(__componentDocker)) return; - if(!DifferentDocker.VerifyOrThrow(this, __componentDocker)) return; - - if (!Contains(__component)) { - Debug.LogError("Docker does not have ownership over Component!", ["ComponentType"], [__component.GetType().Name]); return; - } - - if (__componentDocker == this) { - Debug.LogError("Docker already has Component!", ["ComponentType"], [__component.GetType().Name]); return; - } - - var type = __component.GetType(); - - //Modify collections on both Dockers - RemoveComponentFromLists(__component); - __componentDocker.AddComponentToLists(__component); - - __component.ComponentDocker = __componentDocker; - } - - - - /// - /// Transfers the first found Component of a specific type to another Docker - /// - /// Docker to move the Component to - /// Type of component - public void Move<__Type>([DockerNotNull,DifferentDocker] ComponentDocker __componentDocker) where __Type : Component => Move(Get<__Type>(), __componentDocker); - - - - /// - /// Transfers all Components in a collection to another Docker. - /// - /// The Components that need to be transferred - /// Docker to move Component to - public void MoveAll([ComponentNotNull,DockerOwns] IEnumerable __Components, [DockerNotNull,DifferentDocker] ComponentDocker __componentDocker) { foreach (Component Component in (Component[])[..__Components]) Move(Component, __componentDocker); } - - - - /// - /// Transfers all Components of a type to another Docker. - /// - /// Target Docker - /// Type of Components to transfer - public void MoveAll<__Type>([DockerNotNull, DifferentDocker] ComponentDocker __componentDocker) where __Type : Component => MoveAll(GetAll<__Type>(), __componentDocker); - - - - - public TimeSpan total; - /// - /// Destroys a Component attached to the Docker - /// - /// - public void Destroy([ComponentNotNull,DockerOwns] Component __component) { - Stopwatch timer = Stopwatch.StartNew(); - if(!ComponentNotNull.VerifyOrThrow(__component)) return; - if(!DockerOwns.VerifyOrThrow(this, __component)) return; - - __component.TryEvent(5); - __component.ChainEvent(5); - - RemoveComponentFromLists(__component); - __component.ComponentDocker = null; - timer.Stop(); - total += timer.Elapsed; - } - - - - /// - /// Destroys the first found Component of a given type - /// - /// Type of Component to destroy - public void Destroy<__Type>() where __Type : Component => DestroyAll(GetAll<__Type>()); - - - - /// - /// Destroys all Components from a given collection. - /// - /// - public void DestroyAll([ComponentNotNull, DockerOwns] IReadOnlyList __Components) { for (var i = 0; i < __Components.Count; i++) Destroy(__Components[i]); } - - - - /// - /// Destroys all Components of a given type - /// - /// - public void DestroyAll<__Type>() where __Type : Component => DestroyAll(GetAll<__Type>()); - - - - /// - /// Destroys all Components attached to Docker - /// - public void DestroyAll() { for(var i = 0; i < _components.Count; i++) Destroy(_components[i]); } -} \ No newline at end of file diff --git a/AwperativeKernel/Kernel/Overhead/Awperative/Awperative.cs b/AwperativeKernel/Kernel/Overhead/Awperative/Awperative.cs index 5d49957..69d53a1 100644 --- a/AwperativeKernel/Kernel/Overhead/Awperative/Awperative.cs +++ b/AwperativeKernel/Kernel/Overhead/Awperative/Awperative.cs @@ -27,16 +27,16 @@ public static partial class Awperative /// /// Bottom class of Awperative. Contains the OpenTK Instance. /// - [NotNull, UnsafeInternal] private static Base Base; + [DebugAttributes.NotNull, MarkerAttributes.UnsafeInternal] private static Base Base; /// /// List of all scenes currently loaded in the kernel. /// - [CalculatedProperty, CalculatedPropertyExpense("Very Low")] - public static IReadOnlyList Scenes => [.._scenes]; - [UnsafeInternal] internal static HashSet _scenes { get; private set; } = []; + [MarkerAttributes.CalculatedProperty] + public static IEnumerable Scenes => [.._scenes]; + [MarkerAttributes.UnsafeInternal] internal static HashSet _scenes { get; private set; } = []; @@ -68,7 +68,7 @@ public static partial class Awperative public static void AddScene(Scene __scene) { if (!ContainsScene(__scene.Name)) { _scenes.Add(__scene); - } else Debug.LogError("Awperative already has a Scene with that name!", ["Scene", "Name"], [GetScene(__scene.Name).GetHashCode().ToString(), __scene.Name]); return null; + } else Debug.LogError("Awperative already has a Scene with that name!", ["Scene", "Name"], [GetScene(__scene.Name).GetHashCode().ToString(), __scene.Name]); return; } diff --git a/AwperativeKernel/Kernel/RequiredModules/IDebugger.cs b/AwperativeKernel/Kernel/RequiredModules/IDebugger.cs index ceb6f31..78669c6 100644 --- a/AwperativeKernel/Kernel/RequiredModules/IDebugger.cs +++ b/AwperativeKernel/Kernel/RequiredModules/IDebugger.cs @@ -17,13 +17,13 @@ public interface IDebugger public void Stop(); public void LogAction(string __message); - public void LogAction(string __message, IReadOnlyList __values, IReadOnlyList __args); + public void LogAction(string __message, IEnumerable __values, IEnumerable __args); public void LogWarning(string __message); - public void LogWarning(string __message, IReadOnlyList __values, IReadOnlyList __args); + public void LogWarning(string __message, IEnumerable __values, IEnumerable __args); public void LogError(string __message); - public void LogError(string __message, IReadOnlyList __values, IReadOnlyList __args); + public void LogError(string __message, IEnumerable __values, IEnumerable __args); diff --git a/AwperativeKernel/Kernel/RequiredModules/IModuleManager.cs b/AwperativeKernel/Kernel/RequiredModules/IModuleManager.cs index b80d675..b4683f7 100644 --- a/AwperativeKernel/Kernel/RequiredModules/IModuleManager.cs +++ b/AwperativeKernel/Kernel/RequiredModules/IModuleManager.cs @@ -7,5 +7,5 @@ namespace AwperativeKernel; public interface IModuleManager { - public IReadOnlyList GetDependencies(); + public IEnumerable GetDependencies(); } \ No newline at end of file diff --git a/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.AssemblyInfo.cs b/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.AssemblyInfo.cs index 26a1202..ff95b26 100644 --- a/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.AssemblyInfo.cs +++ b/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("AwperativeKernel")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+8c3803fcdf9411da13e462596847a88f1080bb39")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+41dbab5ce36d1e19917d80ba23482cbbd5b04533")] [assembly: System.Reflection.AssemblyProductAttribute("AwperativeKernel")] [assembly: System.Reflection.AssemblyTitleAttribute("AwperativeKernel")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.AssemblyInfoInputs.cache b/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.AssemblyInfoInputs.cache index 49ebfc5..e5ec2db 100644 --- a/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.AssemblyInfoInputs.cache +++ b/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.AssemblyInfoInputs.cache @@ -1 +1 @@ -1401ec548e06fa205cbd38d50de2d7971689c7694c0af3dc509c2945921d606a +b1a9e115a38433219f1f2e46313d2b5f0dd905c9ce83715b972f620249d7097d diff --git a/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.csproj.CoreCompileInputs.cache b/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.csproj.CoreCompileInputs.cache index be3a4c0..d4a5a71 100644 --- a/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.csproj.CoreCompileInputs.cache +++ b/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -22dd22d60e6c8fbd5110065c2450e37bceb89fe776160bf2e51e6a6a8825b2b1 +5635b864dfc1ecaa0f2c52b65d178dd300857fd622e8afa48acfcadbd77f72d1 diff --git a/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.dll b/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.dll index 73c7ee2..84430ca 100644 Binary files a/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.dll and b/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.dll differ diff --git a/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.pdb b/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.pdb index 347b73b..5104910 100644 Binary files a/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.pdb and b/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.pdb differ diff --git a/AwperativeKernel/obj/Debug/net8.0/ref/AwperativeKernel.dll b/AwperativeKernel/obj/Debug/net8.0/ref/AwperativeKernel.dll index 1831c88..8609238 100644 Binary files a/AwperativeKernel/obj/Debug/net8.0/ref/AwperativeKernel.dll and b/AwperativeKernel/obj/Debug/net8.0/ref/AwperativeKernel.dll differ diff --git a/AwperativeKernel/obj/Debug/net8.0/refint/AwperativeKernel.dll b/AwperativeKernel/obj/Debug/net8.0/refint/AwperativeKernel.dll index 1831c88..8609238 100644 Binary files a/AwperativeKernel/obj/Debug/net8.0/refint/AwperativeKernel.dll and b/AwperativeKernel/obj/Debug/net8.0/refint/AwperativeKernel.dll differ diff --git a/AwperativeKernel/obj/rider.project.model.nuget.info b/AwperativeKernel/obj/rider.project.model.nuget.info index a14e091..88febf5 100644 --- a/AwperativeKernel/obj/rider.project.model.nuget.info +++ b/AwperativeKernel/obj/rider.project.model.nuget.info @@ -1 +1 @@ -17722975223225869 \ No newline at end of file +17722975227348769 \ No newline at end of file