Compare commits
14 Commits
c40a76cc10
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| b7fe374691 | |||
| c215cab014 | |||
| 21747aa062 | |||
| 227e70219a | |||
| daff25af55 | |||
| 41dbab5ce3 | |||
| 8c3803fcdf | |||
| 6e9aff9468 | |||
| 4a9f3d4476 | |||
| 89daba3278 | |||
| abd47153ad | |||
| 32fdae3248 | |||
| abccecd295 | |||
| 75ebac61d0 |
@@ -1,4 +1,7 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ABuffer_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FSourcesCache_003F3dda17b8c491847aa4bd7c56dd3774cd376d43c76c182d041c160bbf4b812b0_003FBuffer_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AObject_002ECoreCLR_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FSourcesCache_003F41f5f1afc2e9972034b9b24da6b9c16efd59be6d5ae907d0ea203e7865bed2_003FObject_002ECoreCLR_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AObject_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fd614e426e2154c38846b28c27d289de9ca738_003Fcf_003F95fabefb_003FObject_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/Environment/AssemblyExplorer/XmlDocument/@EntryValue"><AssemblyExplorer>
|
||||
<Assembly Path="/Users/averynorris/Programming/Test/Awperative/Awperative/bin/Debug/net8.0/Awperative.dll" />
|
||||
</AssemblyExplorer></s:String></wpf:ResourceDictionary>
|
||||
302
AwperativeKernel/Kernel/Atrributes/DebugAttributes.cs
Normal file
302
AwperativeKernel/Kernel/Atrributes/DebugAttributes.cs
Normal file
@@ -0,0 +1,302 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
|
||||
namespace AwperativeKernel;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Holds a myriad of useful attributes which you are more than welcome to use! These attributes are not meant for reflection, but merely as a means of straightforward debugging.
|
||||
/// Each attribute gives has a method called VerifyOrThrow() which can differ parameter wise. VerifyOrThrow() returns a bool based on if the condition is true or not.
|
||||
/// If it is false it will try to throw an error, and returns false as well.The only time this behavior differs, is if Awperative is set to IgnoreErrors. In that case it will return true no matter what.
|
||||
/// (However it will still debug unless that is disabled too).
|
||||
/// </summary>
|
||||
/// <usage>
|
||||
/// The attributes have been designed to be used in methods like so : if(!Attribute.VerifyOrThrow()) return; This usage allows the attribute to control the flow of output, and halt any unsafe process.
|
||||
/// However, nothing is stopping you from using them any other way, so go wild. Feel free to make more, or use these in your own code!
|
||||
/// </usage>
|
||||
/// <author> Avery Norris </author>
|
||||
public static class DebugAttributes
|
||||
{
|
||||
#region Docker/Entity
|
||||
|
||||
/// <summary> Requires that any Component is owned by the Docker</summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class DockerOwns : Attribute
|
||||
{
|
||||
|
||||
|
||||
/// <summary> 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. </summary>
|
||||
/// <usage> 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.</usage>
|
||||
[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;
|
||||
|
||||
Debug.LogError("Docker does not own the Component!",
|
||||
["ComponentType", "ComponentName", "ComponentHash", "DockerType", "DockerName", "DockerHash"], [
|
||||
__component.GetType().Name,
|
||||
__component.Name,
|
||||
__component.GetHashCode().ToString("N0"),
|
||||
__docker.GetType().Name,
|
||||
__docker switch { Scene scene => scene.Name, Component component => component.Name, _ => "unknown" },
|
||||
__docker.GetHashCode().ToString("N0")
|
||||
]);
|
||||
|
||||
return Debug.IgnoreErrors;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary> Requires that the Docker does not own the given Component</summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class DockerDoesntOwn : Attribute
|
||||
{
|
||||
|
||||
|
||||
/// <inheritdoc cref="DockerOwns.VerifyOrThrow"/>
|
||||
[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;
|
||||
|
||||
Debug.LogError("Docker owns the Component!",
|
||||
["ComponentType", "ComponentName", "ComponentHash", "DockerType", "DockerName", "DockerHash"], [
|
||||
__component.GetType().Name,
|
||||
__component.Name,
|
||||
__component.GetHashCode().ToString("N0"),
|
||||
__docker.GetType().Name,
|
||||
__docker switch { Scene scene => scene.Name, Component component => component.Name, _ => "unknown" },
|
||||
__docker.GetHashCode().ToString("N0")
|
||||
]);
|
||||
|
||||
return Debug.IgnoreErrors;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary> Requires that the Component does not belong to a Docker</summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class OrphanComponent : Attribute
|
||||
{
|
||||
|
||||
|
||||
/// <inheritdoc cref="DockerOwns.VerifyOrThrow"/>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public static bool VerifyOrThrow(Component __component) {
|
||||
if (__component.ComponentDocker == null) return true;
|
||||
|
||||
Debug.LogError("Component is already owned!",
|
||||
["ComponentType", "ComponentName", "ComponentHash", "DockerType", "DockerName", "DockerHash"], [
|
||||
__component.GetType().Name,
|
||||
__component.Name,
|
||||
__component.GetHashCode().ToString("N0"),
|
||||
__component.ComponentDocker.GetType().Name,
|
||||
__component.ComponentDocker switch { Scene scene => scene.Name, Component component => component.Name, _ => "unknown" },
|
||||
__component.ComponentDocker.GetHashCode().ToString("N0")
|
||||
]);
|
||||
|
||||
return Debug.IgnoreErrors;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary> Requires that a given Docker is not the same</summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class DifferentDocker : Attribute
|
||||
{
|
||||
|
||||
|
||||
/// <inheritdoc cref="DockerOwns.VerifyOrThrow"/>
|
||||
[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;
|
||||
|
||||
Debug.LogError("The dockers are the same!", ["DockerType", "DockerName", "DockerHash"], [
|
||||
__docker.GetType().Name,
|
||||
__docker switch { Scene scene => scene.Name, Component component => component.Name, _ => "unknown" },
|
||||
__docker.GetHashCode().ToString("N0")
|
||||
]);
|
||||
|
||||
return Debug.IgnoreErrors;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary> Requires that the Component is not null</summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class ComponentNotNull : Attribute
|
||||
{
|
||||
|
||||
|
||||
/// <inheritdoc cref="DockerOwns.VerifyOrThrow"/>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public static bool VerifyOrThrow(Component __component) {
|
||||
if (__component != null) return true;
|
||||
|
||||
Debug.LogError("Component is null!");
|
||||
|
||||
return Debug.IgnoreErrors;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary> Requires that the Docker is not null</summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class DockerNotNull : Attribute
|
||||
{
|
||||
|
||||
|
||||
/// <inheritdoc cref="DockerOwns.VerifyOrThrow"/>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public static bool VerifyOrThrow(ComponentDocker __componentDocker) {
|
||||
if (__componentDocker != null) return true;
|
||||
|
||||
Debug.LogError("Docker is null!");
|
||||
|
||||
return Debug.IgnoreErrors;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary> Requires that a given Scene is not null</summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class SceneNotNull : Attribute
|
||||
{
|
||||
|
||||
|
||||
/// <inheritdoc cref="DockerOwns.VerifyOrThrow"/>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public static bool VerifyOrThrow(Scene __scene) {
|
||||
if (__scene != null) return true;
|
||||
|
||||
Debug.LogError("Scene is null!");
|
||||
|
||||
return Debug.IgnoreErrors;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Requires that a given Scene is not null</summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class SceneDoesNotExist : Attribute
|
||||
{
|
||||
|
||||
|
||||
/// <inheritdoc cref="DockerOwns.VerifyOrThrow"/>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public static bool VerifyOrThrow(Scene __scene) {
|
||||
if (!Awperative._scenes.Contains(__scene)) return true;
|
||||
|
||||
Debug.LogError("Scene already exists!");
|
||||
|
||||
return Debug.IgnoreErrors;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Null/Collection
|
||||
|
||||
|
||||
|
||||
/// <summary> Requires all elements in an Enumerator are not null</summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class EnumerableNotNull : Attribute
|
||||
{
|
||||
|
||||
|
||||
/// <inheritdoc cref="DockerOwns.VerifyOrThrow"/>
|
||||
public static bool VerifyOrThrow(IEnumerable<object> __enumerator) {
|
||||
if (__enumerator == null) { Debug.LogError("A given enumerator is null!"); return Debug.IgnoreErrors; }
|
||||
|
||||
foreach (object obj in __enumerator) {
|
||||
if (obj == null) {
|
||||
Debug.LogError("A given enumerator has null members!", ["Type"], [__enumerator.GetType().Name]);
|
||||
return Debug.IgnoreErrors;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary> Requires that the enumerator contains a certain element.</summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class EnumerableContains : Attribute
|
||||
{
|
||||
|
||||
|
||||
/// <inheritdoc cref="DockerOwns.VerifyOrThrow"/>
|
||||
public static bool VerifyOrThrow(IEnumerable<object> __enumerator, object __object) {
|
||||
if (__enumerator.Contains(__object)) return true;
|
||||
|
||||
Debug.LogError("A given enumerator does not contains an object!", ["EnumeratorType", "ObjectType", "Value"], [__enumerator.GetType().Name, __object.GetType().Name, __object.ToString()]);
|
||||
|
||||
return Debug.IgnoreErrors;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary> Requires that the enumerator does not contain a certain element.</summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class EnumerableDoesntContain : Attribute
|
||||
{
|
||||
|
||||
|
||||
/// <inheritdoc cref="DockerOwns.VerifyOrThrow"/>
|
||||
public static bool VerifyOrThrow(IEnumerable<object> __enumerator, object __object) {
|
||||
if (!__enumerator.Contains(__object)) return true;
|
||||
|
||||
Debug.LogError("A given enumerator already contains the object object!", ["EnumeratorType", "ObjectType", "Value"], [__enumerator.GetType().Name, __object.GetType().Name, __object.ToString()]);
|
||||
|
||||
return Debug.IgnoreErrors;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary> Requires a given object is not null </summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class NotNull : Attribute
|
||||
{
|
||||
|
||||
|
||||
/// <inheritdoc cref="DockerOwns.VerifyOrThrow"/>
|
||||
public static bool VerifyOrThrow(Object __object) {
|
||||
if (__object != null) return true;
|
||||
|
||||
Debug.LogError("A given object is null!");
|
||||
|
||||
return Debug.IgnoreErrors;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary> Requires that an integer fits a range</summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class ValueFitsRange : Attribute
|
||||
{
|
||||
|
||||
|
||||
/// <inheritdoc cref="DockerOwns.VerifyOrThrow"/>
|
||||
public static bool VerifyOrThrow(int __index, int __min, int __max) {
|
||||
if (__index >= __min && __index <= __max) return true;
|
||||
|
||||
Debug.LogError("Value does not fit range!", ["Index"], [__index.ToString("N0")]);
|
||||
|
||||
return Debug.IgnoreErrors;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
69
AwperativeKernel/Kernel/Atrributes/MarkerAttributes.cs
Normal file
69
AwperativeKernel/Kernel/Atrributes/MarkerAttributes.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
|
||||
|
||||
namespace AwperativeKernel;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Provides many handy cosmetic attributes for methods to specify use cases or provide information.
|
||||
/// </summary>
|
||||
/// <author> Avery Norris </author>
|
||||
public static class MarkerAttributes
|
||||
{
|
||||
|
||||
/// <summary> 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 the exposing public methods already check, and double checks would only slow me down </summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class UnsafeInternal : Attribute { }
|
||||
|
||||
|
||||
|
||||
/// <summary> Shows that the given object is calculated every time it is called! Good to know for performance heavy systems. </summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class CalculatedProperty : Attribute { }
|
||||
|
||||
|
||||
|
||||
/// <summary> Just a way to write how expensive a calculated property or method can be. </summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class Expense(Expense.ExpenseLevel __expense) : Attribute
|
||||
{
|
||||
public enum ExpenseLevel {
|
||||
None,
|
||||
VeryLow,
|
||||
Low,
|
||||
Medium,
|
||||
High,
|
||||
VeryHigh,
|
||||
}
|
||||
|
||||
|
||||
public ExpenseLevel expense = __expense;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary> Just a way to write the time complexity of a calculated property or method. </summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class Complexity(Complexity.TimeComplexity __complexity) : Attribute
|
||||
{
|
||||
public enum TimeComplexity
|
||||
{
|
||||
O1,
|
||||
OLogN,
|
||||
ON,
|
||||
ONLogN,
|
||||
ON2,
|
||||
ON3
|
||||
}
|
||||
|
||||
public TimeComplexity complexity = __complexity;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary> Shows that the given method does not actually belong to the object, but instead just calls a lambda to another method. </summary>
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class MethodPointer : Attribute { }
|
||||
}
|
||||
@@ -1,240 +1,96 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
using Awperative.Kernel.Overhead.Reflection;
|
||||
|
||||
|
||||
namespace AwperativeKernel;
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 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!
|
||||
/// </summary>
|
||||
/// <author> Avery Norris </author>
|
||||
public abstract partial class Component : ComponentDocker
|
||||
{
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Current parent of the Component. Can be either Scene or another Component.
|
||||
/// </summary>
|
||||
public ComponentDocker ComponentDocker { get; internal set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If the component receives time events or not.
|
||||
/// </summary>
|
||||
public bool Enabled = true;
|
||||
|
||||
/// <summary> Current parent of the Component. Can be either a Scene or another Component.</summary>
|
||||
[MarkerAttributes.UnsafeInternal]
|
||||
public ComponentDocker ComponentDocker { get; internal set; } = null;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Component name
|
||||
/// </summary>
|
||||
public string Name;
|
||||
/// <summary> Component's name </summary>
|
||||
[DebugAttributes.NotNull]
|
||||
public string Name {
|
||||
get => _name;
|
||||
set { if (!DebugAttributes.NotNull.VerifyOrThrow(value)) return; _name = value; }
|
||||
} [MarkerAttributes.UnsafeInternal] private string _name;
|
||||
|
||||
|
||||
/// <summary> Represents the state of this Component, The largest bit represents if the Component is enabled or not, while the
|
||||
/// next 7 represent its priority like so : (Enabled -> 0 | Priority -> 0000000) </summary>
|
||||
[MarkerAttributes.UnsafeInternal]
|
||||
private byte OrderProfile;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Order for when Components are called on. Only applies between Components on the same Docker.
|
||||
/// </summary>
|
||||
/// <summary> If the component receives time events or not. </summary>
|
||||
[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));
|
||||
}
|
||||
|
||||
/// <summary> Represents the Component's Update priority; higher priorities get updated first. Can be any integer in the range -64 -> 63. </summary>
|
||||
[MarkerAttributes.CalculatedProperty, MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public int Priority {
|
||||
get => _priority; set => ComponentDocker.UpdatePriority(this, value);
|
||||
} internal int _priority;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// To be called when the Component is created.
|
||||
/// </summary>
|
||||
/// <param name="__parent"> Docker that this spawned in this Component</param>
|
||||
/// <param name="__name"> Name of the component</param>
|
||||
internal void Initiate(ComponentDocker __parent, string __name, string[] __tags) {
|
||||
ComponentDocker = __parent;
|
||||
Name = __name;
|
||||
_tags = [..__tags];
|
||||
Create();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Called when the Game is Closing; does not always happen depending on if it is Force Closed.
|
||||
/// </summary>
|
||||
protected internal virtual void Unload() {}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the Game is Loading.
|
||||
/// </summary>
|
||||
protected internal virtual void Load() {}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Called every frame before Draw, it is recommended to do any Non-Drawing update logic here.
|
||||
/// </summary>
|
||||
protected internal virtual void Update() {}
|
||||
|
||||
/// <summary>
|
||||
/// Called after Update when the screen is being drawn. Please only put Drawing related logic here.
|
||||
/// </summary>
|
||||
protected internal virtual void Draw() {}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Called when the Component is created.
|
||||
/// </summary>
|
||||
protected internal virtual void Create() {}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the Component is destroyed. Not called when the Game is closed.
|
||||
/// </summary>
|
||||
protected internal virtual void Destroy() {}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Scene the Component resides in.
|
||||
/// </summary>
|
||||
public Scene Scene => __QueryScene();
|
||||
protected Scene __QueryScene() {
|
||||
if (ComponentDocker is Scene scene) return scene;
|
||||
if (ComponentDocker is Component Component) return Component.__QueryScene();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Identifiers for Components.
|
||||
/// </summary>
|
||||
public ImmutableArray<string> Tags => [.._tags];
|
||||
internal HashSet<string> _tags = [];
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new tag to the Component
|
||||
/// </summary>
|
||||
/// <param name="__tag"> The tag to add</param>
|
||||
public void AddTag(string __tag) => ComponentDocker.HashTaggedComponent(this, __tag);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Removes a tag from the Component
|
||||
/// </summary>
|
||||
/// <param name="__tag"> The tag to remove</param>
|
||||
public void RemoveTag(string __tag) => ComponentDocker.UnhashTaggedComponent(this, __tag);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// All parent Dockers and the parents of the parents up until the Scene. Will only list parents of parents, not uncle dockers.
|
||||
/// </summary>
|
||||
/// <remarks> Dockers[0] is the parent of this object, and Dockers[^1] is the Scene.</remarks>
|
||||
public ImmutableArray<ComponentDocker> Dockers => __QueryDockers();
|
||||
protected ImmutableArray<ComponentDocker> __QueryDockers() {
|
||||
List<ComponentDocker> returnValue = [];
|
||||
ComponentDocker currentComponentDocker = ComponentDocker;
|
||||
|
||||
while (!(currentComponentDocker is Scene)) {
|
||||
if (currentComponentDocker is Component Component) {
|
||||
returnValue.Add(currentComponentDocker);
|
||||
currentComponentDocker = Component.ComponentDocker;
|
||||
} else {
|
||||
Debug.LogError("Component has a Parent that is not a Scene or Component, Please do not use the Docker class unless you know what you are doing!", ["Component", "Type", "Docker"],
|
||||
[GetHashCode().ToString(), GetType().ToString(), ComponentDocker.GetHashCode().ToString()]);
|
||||
}
|
||||
get => (sbyte)(OrderProfile << 1) >> 1;
|
||||
set {
|
||||
if(!DebugAttributes.ValueFitsRange.VerifyOrThrow(value, -64, 63)) return;
|
||||
OrderProfile = (byte)((OrderProfile & 0x80) | (value & 0x7F));
|
||||
ComponentDocker.UpdatePriority(this, value);
|
||||
}
|
||||
}
|
||||
|
||||
returnValue.Add(currentComponentDocker);
|
||||
|
||||
return [..returnValue];
|
||||
/// <summary> A list of all tags belonging to the component. Use AddTag() to modify it.</summary>
|
||||
public IReadOnlySet<string> Tags => _tags;
|
||||
[MarkerAttributes.UnsafeInternal] internal HashSet<string> _tags = [];
|
||||
|
||||
|
||||
/// <summary> Attempts to send an event to the component, and quietly exits if not.</summary>
|
||||
[MarkerAttributes.UnsafeInternal]
|
||||
internal void TryEvent(int __timeEvent) {
|
||||
EventManager._TypeAssociatedTimeEvents[GetType()][__timeEvent]?.Invoke(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary> Adds a new tag to the component</summary>
|
||||
[MarkerAttributes.CalculatedProperty, MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Low), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public void AddTag([DebugAttributes.NotNull, DebugAttributes.EnumerableDoesntContain] string __tag) {
|
||||
if(!DebugAttributes.NotNull.VerifyOrThrow(__tag)) return;
|
||||
if(!DebugAttributes.EnumerableDoesntContain.VerifyOrThrow(_tags, __tag)) return;
|
||||
|
||||
_tags.Add(__tag);
|
||||
ComponentDocker.HashTaggedComponent(__tag, this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary> Removes a tag from the component.</summary>
|
||||
[MarkerAttributes.CalculatedProperty, MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Low), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public void RemoveTag([DebugAttributes.NotNull,DebugAttributes.EnumerableContains] string __tag) {
|
||||
if (!DebugAttributes.NotNull.VerifyOrThrow(__tag)) return;
|
||||
if(!DebugAttributes.EnumerableContains.VerifyOrThrow(_tags, __tag)) return;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the Parent Component. Will be null if the Component is under a scene.
|
||||
/// </summary>
|
||||
public Component Parent => __QueryParent();
|
||||
protected Component __QueryParent() {
|
||||
if (ComponentDocker is Component Component)
|
||||
return Component;
|
||||
return null;
|
||||
_tags.Remove(__tag);
|
||||
ComponentDocker.UnhashTaggedComponent(__tag, this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// All parent Components and the parents of the parents up until the Scene. Will only list parents of parents, not uncle Components.
|
||||
/// </summary>
|
||||
public ImmutableArray<Component> Parents => __QueryComponents();
|
||||
protected ImmutableArray<Component> __QueryComponents() {
|
||||
List<Component> returnValue = [];
|
||||
ComponentDocker currentComponentDocker = ComponentDocker;
|
||||
|
||||
while (!(currentComponentDocker is Scene))
|
||||
if (currentComponentDocker is Component Component) {
|
||||
returnValue.Add(Component);
|
||||
currentComponentDocker = Component.ComponentDocker;
|
||||
}
|
||||
return [..returnValue];
|
||||
/// <summary> Just gives the Component's name. But makes debugging a little easier :).</summary>
|
||||
public override string ToString() {
|
||||
return this.Name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new Scene
|
||||
/// </summary>
|
||||
/// <param name="__name">Name of the Scene</param>
|
||||
public Scene CreateScene(string __name) => Awperative.CreateScene(__name);
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Finds a scene.
|
||||
/// </summary>
|
||||
/// <param name="__name">Name of the Scene</param>
|
||||
/// <returns></returns>
|
||||
public Scene GetScene(string __name) => Awperative.GetScene(__name);
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Destroys a Scene forever
|
||||
/// </summary>
|
||||
/// <param name="__scene"> Target scene</param>
|
||||
public void RemoveScene(Scene __scene) => Awperative.CloseScene(__scene);
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Destroys a Scene forever
|
||||
/// </summary>
|
||||
/// <param name="__name">Name of the Scene</param>
|
||||
public void RemoveScene(string __name) => Awperative.CloseScene(__name);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
namespace AwperativeKernel;
|
||||
|
||||
|
||||
public abstract partial class Component
|
||||
{
|
||||
/// <summary> Scene the Component resides in. To save ram it's not stored but calculated on the fly. </summary>
|
||||
[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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary> Returns the Parent Component. Will be null if the Component's parent is a Scene. </summary>
|
||||
[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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary> 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 </summary>
|
||||
[MarkerAttributes.CalculatedProperty, MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public IEnumerable<Component> AllParents => __QueryComponents();
|
||||
private IEnumerable<Component> __QueryComponents() {
|
||||
List<Component> returnValue = [];
|
||||
ComponentDocker currentComponentDocker = ComponentDocker;
|
||||
|
||||
while (currentComponentDocker is not AwperativeKernel.Scene) {
|
||||
if (currentComponentDocker is Component Component) {
|
||||
returnValue.Add(Component);
|
||||
currentComponentDocker = Component.ComponentDocker;
|
||||
}
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
40
AwperativeKernel/Kernel/Component/ComponentLambda.cs
Normal file
40
AwperativeKernel/Kernel/Component/ComponentLambda.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
namespace AwperativeKernel;
|
||||
|
||||
|
||||
public abstract partial class Component
|
||||
{
|
||||
/// <inheritdoc cref="Awperative.CreateScene"/>
|
||||
[MarkerAttributes.MethodPointer]
|
||||
public static Scene CreateScene(string __name) => Awperative.CreateScene(__name);
|
||||
|
||||
|
||||
|
||||
/// <inheritdoc cref="Awperative.GetScene"/>
|
||||
[MarkerAttributes.MethodPointer]
|
||||
public static Scene GetScene(string __name) => Awperative.GetScene(__name);
|
||||
|
||||
|
||||
|
||||
/// <inheritdoc cref="Awperative.CloseScene(AwperativeKernel.Scene)"/>
|
||||
[MarkerAttributes.MethodPointer]
|
||||
public void RemoveScene(Scene __scene) => Awperative.CloseScene(__scene);
|
||||
|
||||
|
||||
|
||||
/// <inheritdock cref="Awperative.CloseScene(string)" />
|
||||
[MarkerAttributes.MethodPointer]
|
||||
public void RemoveScene(string __name) => Awperative.CloseScene(__name);
|
||||
|
||||
|
||||
|
||||
/// <inheritdoc cref="ComponentDocker.Move"/>
|
||||
[MarkerAttributes.MethodPointer]
|
||||
public void Move(ComponentDocker __newDocker) => ComponentDocker.Move(this, __newDocker);
|
||||
|
||||
|
||||
|
||||
/// <summary> Makes the Component destroy itself </summary>
|
||||
[MarkerAttributes.MethodPointer]
|
||||
public void Destroy() => ComponentDocker.Destroy(this);
|
||||
|
||||
}
|
||||
62
AwperativeKernel/Kernel/ComponentDocker/ComponentDockEnum.cs
Normal file
62
AwperativeKernel/Kernel/ComponentDocker/ComponentDockEnum.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
namespace AwperativeKernel;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Provides an Enumerator for the Component Docker, Loops through all Components in the Docker all for your convenience :)
|
||||
/// </summary>
|
||||
/// <param name="__components">Reference to the Component Docker's components, (List to Enumerate through)</param>
|
||||
/// <remarks> Enumerates on a snapshot of the list. This allows you to modify the ComponentDocker's collection during the loop. </remarks>
|
||||
/// <author> Avery Norris </author>
|
||||
public class ComponentDockEnum(Component[] __components) : IEnumerator, IEnumerator<Component>, IDisposable
|
||||
{
|
||||
|
||||
|
||||
|
||||
//Current index of the loop
|
||||
private int index = -1;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current Component;
|
||||
/// </summary>
|
||||
public Component Current => __components[index];
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the current Component as a generic object
|
||||
/// </summary>
|
||||
object IEnumerator.Current => Current;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Proceeds to the next index of the loop
|
||||
/// </summary>
|
||||
/// <returns> Returns true or false, depending on whether the Enumeration should continue</returns>
|
||||
bool IEnumerator.MoveNext() { ++index; return index < __components.Length; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Resets the loop back to the very start
|
||||
/// </summary>
|
||||
public void Reset() => index = -1;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Destroys the enumerator
|
||||
/// </summary>
|
||||
public void Dispose() => GC.SuppressFinalize(this);
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,593 +1,143 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
|
||||
namespace AwperativeKernel;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Base class for all Awperative Entities. 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.
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <remarks> Please don't inherit this. I don't know why you would</remarks>
|
||||
/// <author> Avery Norris </author>
|
||||
public abstract class ComponentDocker
|
||||
public abstract partial class ComponentDocker : IEnumerable<Component>, IEquatable<Component>, IEquatable<ComponentDocker>, IEquatable<Scene>
|
||||
{
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// List of all Components belonging to the Docker, Please Use Add, Get, Move and Destroy to modify it.
|
||||
/// </summary>
|
||||
public ImmutableArray<Component> Components => [.._Components];
|
||||
//Blocks external inheritance
|
||||
internal ComponentDocker() {}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Amount of all Components in the Docker
|
||||
/// </summary>
|
||||
public int Count => _Components.Count;
|
||||
/// <summary> Core of the Docker, holds all of the Components, sorted by update priority.</summary>
|
||||
[MarkerAttributes.UnsafeInternal] internal readonly List<Component> _components = [];
|
||||
/// <summary> Holds a list of Components at each of their types. This optimizes Get<Type> to O(1) </summary>
|
||||
[MarkerAttributes.UnsafeInternal] internal readonly Dictionary<Type, HashSet<Component>> _componentTypeDictionary = new();
|
||||
/// <summary> Stores a Component in a list at each of their tags. This optimizes Get(string tag) to O(1)</summary>
|
||||
[MarkerAttributes.UnsafeInternal] internal readonly Dictionary<string, HashSet<Component>> _componentTagDictionary = new();
|
||||
|
||||
|
||||
|
||||
/// <summary> All children belonging to the Component. </summary>
|
||||
public IEnumerable<Component> Children => _components;
|
||||
|
||||
|
||||
/// <summary> All children and children of children until the bottom of the scene. Uses Breadth First Search. </summary>
|
||||
[MarkerAttributes.CalculatedProperty, MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.High), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public IEnumerable<Component> AllChildren => GetAllChildren();
|
||||
public IEnumerable<Component> GetAllChildren() {
|
||||
List<Component> returnValue = [];
|
||||
Queue<Component> 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]);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Core of Docker, contains all of our precious Components. Sorts them by their priorities with highest going first.
|
||||
/// If they are equal it defaults to hash codes to ensure consistent Behavior
|
||||
/// </summary>
|
||||
internal SortedSet<Component> _Components = new(_componentSorter);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Amount of Components attached to the Docker</summary>
|
||||
public int Count => _components.Count;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// How Priority is sorted.
|
||||
/// </summary>
|
||||
private readonly static Comparer<Component> _componentSorter = Comparer<Component>.Create((a, b) => {
|
||||
int result = b.Priority.CompareTo(a.Priority);
|
||||
return (result != 0) ? result : a.GetHashCode().CompareTo(b.GetHashCode());
|
||||
});
|
||||
//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<Component> GetEnumerator() { return new ComponentDockEnum([.._components]); }
|
||||
|
||||
|
||||
|
||||
/// <summary>Compares the Docker to another Scene.</summary>
|
||||
public bool Equals(Scene __other) {
|
||||
if (this is Scene scene)
|
||||
return scene == __other;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>Compares the Docker to another Component.</summary>
|
||||
public bool Equals(Component __other) {
|
||||
if (this is Component component)
|
||||
return component == __other;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>Compares the Docker to another Docker.</summary>
|
||||
public bool Equals(ComponentDocker __other) {
|
||||
return this == __other;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Resorts member of Component list to match the Priority.
|
||||
/// </summary>
|
||||
/// <param name="__component"> Component to modify</param>
|
||||
/// <param name="__priority"> New priority for Component</param>
|
||||
/// <summary> Resorts the component list to order of priority </summary>
|
||||
[MarkerAttributes.UnsafeInternal]
|
||||
internal void UpdatePriority(Component __component, int __priority) {
|
||||
foreach (String tag in __component._tags) {
|
||||
_taggedComponents[tag].Remove(__component);
|
||||
} _Components.Remove(__component);
|
||||
|
||||
__component._priority = __priority;
|
||||
|
||||
foreach (String tag in __component._tags) {
|
||||
_taggedComponents[tag].Add(__component);
|
||||
} _Components.Add(__component);
|
||||
_components.Sort(Awperative._prioritySorter);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Called by Awperative when the game is Closed, sends the event to all children; and they send it to their children.
|
||||
/// </summary>
|
||||
/// <remarks> Will not always trigger if the program is force closed </remarks>
|
||||
internal virtual void ChainUnload() { foreach (Component component in (Component[])[.._Components]) { if(component.Enabled) { component.Unload(); component.ChainUnload(); } } }
|
||||
|
||||
/// <summary>
|
||||
/// Called by Awperative when the game is Opened, sends the event to all children; and they send it to their children.
|
||||
/// </summary>
|
||||
internal virtual void ChainLoad() { foreach (Component component in (Component[])[.._Components]) { if(component.Enabled) { component.Load(); component.ChainLoad(); } } }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Called by Awperative when the game is Updated sends the event to all children; and they send it to their children.
|
||||
/// </summary>
|
||||
internal virtual void ChainUpdate() { foreach (Component component in (Component[])[.._Components]) { if(component.Enabled) { component.Update(); component.ChainUpdate(); } } }
|
||||
|
||||
/// <summary>
|
||||
/// Called by Awperative when the game is Drawn, sends the event to all children; and they send it to their children.
|
||||
/// </summary>
|
||||
/// <remarks> Only use this method for drawing methods</remarks>
|
||||
internal virtual void ChainDraw() { foreach (Component component in (Component[])[.._Components]) { if(component.Enabled) { component.Draw(); component.ChainDraw(); } } }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Called by Awperative when this is Created, sends the event to all children; and they send it to their children.
|
||||
/// </summary>
|
||||
internal virtual void ChainCreate() { foreach (Component component in (Component[])[.._Components]) { if(component.Enabled) { component.Create(); component.ChainCreate(); } } }
|
||||
|
||||
/// <summary>
|
||||
/// Called by Awperative when this Component is destroyed, sends the event to all children; since they will be Destroyed too. And they send it to their children.
|
||||
/// </summary>
|
||||
/// <remarks> Not called when the game is closed</remarks>
|
||||
internal virtual void ChainDestroy() { foreach(Component component in (Component[])[.._Components]) { if(component.Enabled) { component.Destroy(); component.ChainDestroy(); } } }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Add a new Component to the Docker; This is the only way they should be created.
|
||||
/// </summary>
|
||||
/// <param name="__args"> Arguments to construct the Component with</param>
|
||||
/// <typeparam name="__Type"> Type of Component to instantiate</typeparam>
|
||||
/// <returns></returns>
|
||||
public __Type Add<__Type>(object[] __args, string name = "", string[] tags = null) where __Type : Component {
|
||||
|
||||
if(name == "") { name = typeof(__Type).Name; }
|
||||
if (tags == null) tags = [];
|
||||
|
||||
|
||||
|
||||
|
||||
//Component does not have a constructor that matches the given args
|
||||
if (typeof(__Type).GetConstructor(__args.Select(x => x.GetType()).ToArray()) == null) {
|
||||
Debug.LogError("Component cannot be constructed with the given arguments",
|
||||
["Type", "Args"],
|
||||
[typeof(__Type).ToString(), "[" + string.Join(", ", __args.Select(x => x.ToString())) + "]"]); return null;
|
||||
};
|
||||
|
||||
|
||||
Component newComponent;
|
||||
|
||||
|
||||
//Tries to instantiate Component, and sends a fail call if an issue occurs.
|
||||
try { newComponent = (__Type)Activator.CreateInstance(typeof(__Type), __args); }
|
||||
catch {
|
||||
Debug.LogError("Component creation failed!", ["Type", "Args", "Docker"],
|
||||
[typeof(__Type).ToString(), "[" + string.Join(", ", __args.Select(x => x.ToString())) + "]", GetHashCode().ToString()]); return null;
|
||||
}
|
||||
|
||||
|
||||
//If Component is null do not add
|
||||
if(newComponent == null) {
|
||||
Debug.LogError("Activator created Null Component", ["Type", "Args", "Docker"],
|
||||
[typeof(__Type).ToString(), "[" + string.Join(", ", __args.Select(x => x.ToString())) + "]", GetHashCode().ToString()]); return null;
|
||||
}
|
||||
|
||||
|
||||
//Add to docker and initialize the new Component
|
||||
_Components.Add(newComponent);
|
||||
newComponent.Initiate(this, name, tags);
|
||||
|
||||
|
||||
return (__Type) newComponent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new Component to the Docker; This is the only way they should be created.
|
||||
/// </summary>
|
||||
/// <typeparam name="__Type"></typeparam>
|
||||
/// <returns></returns>
|
||||
public __Type Add<__Type>(string name = "", string[] tags = null) where __Type : Component => Add<__Type>([], name: name, tags: tags);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Transfers a child Component to another Docker
|
||||
/// </summary>
|
||||
/// <param name="__component"> Component to move</param>
|
||||
/// <param name="__componentDocker"> Docker to move component to</param>
|
||||
/// <remarks> Components cannot transfer themselves with this Method!</remarks>
|
||||
public void Move(Component __component, ComponentDocker __componentDocker) {
|
||||
|
||||
|
||||
|
||||
//This allows self transfer behavior while preserving Docker's actual job, Before all other statements to prevent Double-Debugging.
|
||||
if (__component == this) { __component.ComponentDocker.Move(__component, __componentDocker); return; }
|
||||
|
||||
|
||||
|
||||
if (__component == null) {
|
||||
Debug.LogError("Component is null!", ["CurrentDocker", "NewDocker"],
|
||||
[GetHashCode().ToString(), __componentDocker.GetHashCode().ToString()]); return; }
|
||||
|
||||
|
||||
|
||||
if (!_Components.Contains(__component)) {
|
||||
Debug.LogError("Docker does not have ownership of Component", ["Component", "Type", "CurrentDocker", "NewDocker"],
|
||||
[__component.GetHashCode().ToString(), __component.GetType().ToString(), GetHashCode().ToString(), __componentDocker.GetHashCode().ToString()]); return; }
|
||||
|
||||
|
||||
|
||||
//Update docker lists
|
||||
__componentDocker._Components.Add(__component);
|
||||
_Components.Remove(__component);
|
||||
|
||||
|
||||
|
||||
//Update components parent
|
||||
__component.ComponentDocker = __componentDocker;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Transfers the first found Component of a specific type to another Docker
|
||||
/// </summary>
|
||||
/// <param name="__componentDocker"> Docker to move component to</param>
|
||||
/// <typeparam name="__Type"> Type of component</typeparam>
|
||||
public void Move<__Type>(ComponentDocker __componentDocker) where __Type : Component => Move(Get<__Type>(), __componentDocker);
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Transfers all Components in a list to another Docker.
|
||||
/// </summary>
|
||||
/// <param name="__Components"> List of Components to transfer</param>
|
||||
/// <param name="__componentDocker"> Docker to move Component to</param>
|
||||
public void MoveAll(IEnumerable<Component> __Components, ComponentDocker __componentDocker) { foreach (Component Component in (Component[])[..__Components]) Move(Component, __componentDocker); }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Transfers all Components of a type to another Docker.
|
||||
/// </summary>
|
||||
/// <param name="__componentDocker"> Target Docker</param>
|
||||
/// <typeparam name="__Type"> Type of Components to transfer</typeparam>
|
||||
public void MoveAll<__Type>(ComponentDocker __componentDocker) where __Type : Component => MoveAll(GetAll<__Type>(), __componentDocker);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// /// <summary>
|
||||
/// Holds Components at Keys of their tags.
|
||||
/// </summary>
|
||||
internal Dictionary<string, SortedSet<Component>> _taggedComponents = [];
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Add component to its proper place in the dictionary and resort values to match priorities.
|
||||
/// </summary>
|
||||
/// <param name="__component"> Component to hash</param>
|
||||
/// <param name="__tag"> Value to try and hash</param>
|
||||
internal void HashTaggedComponent(Component __component, string __tag) {
|
||||
|
||||
if (!__component._tags.Add(__tag)) {
|
||||
Debug.LogError("Component already has tag!", ["Component", "Type", "Tag", "Docker"],
|
||||
[__component.GetHashCode().ToString(), __component.GetType().ToString(), __tag, GetHashCode().ToString()]); return;
|
||||
}
|
||||
|
||||
if (_taggedComponents.TryGetValue(__tag, out SortedSet<Component> components)) {
|
||||
components.Add(__component);
|
||||
|
||||
} else { _taggedComponents.Add(__tag, new SortedSet<Component>(_componentSorter)); _taggedComponents[__tag].Add(__component); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="__component"></param>
|
||||
/// <param name="__tag"></param>
|
||||
internal void UnhashTaggedComponent(Component __component, string __tag) {
|
||||
|
||||
if (!__component._tags.Remove(__tag)) {
|
||||
Debug.LogError("Component already doesn't have that tag!", ["Component", "Type", "Tag", "Docker"],
|
||||
[__component.GetHashCode().ToString(), __component.GetType().ToString(), __tag, GetHashCode().ToString()]); return;
|
||||
}
|
||||
|
||||
|
||||
if (_taggedComponents.TryGetValue(__tag, out SortedSet<Component> components)) {
|
||||
components.Remove(__component);
|
||||
|
||||
if(components.Count == 0)
|
||||
_taggedComponents.Remove(__tag);
|
||||
/// <summary> Sends an event to all Children and tells them to continue it. </summary>
|
||||
/// <param name="__timeEvent"> Integer ID of the event to send. </param>
|
||||
[MarkerAttributes.UnsafeInternal]
|
||||
internal void ChainEvent(int __timeEvent) {
|
||||
for (int i = 0; i < _components.Count; i++) {
|
||||
_components[i].TryEvent(__timeEvent);
|
||||
_components[i].ChainEvent(__timeEvent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary> Add a Component to the Docker. </summary>
|
||||
[MarkerAttributes.UnsafeInternal]
|
||||
private void AddComponentToLists(Component __component) {
|
||||
Type Type = __component.GetType();
|
||||
_components.Add(__component);
|
||||
if (!_componentTypeDictionary.TryAdd(Type, [__component])) _componentTypeDictionary[Type].Add(__component);
|
||||
|
||||
/// <summary>
|
||||
/// Finds the first instance of a component with a given tag
|
||||
/// </summary>
|
||||
/// <param name="__tag"> Tag to search for</param>
|
||||
/// <returns></returns>
|
||||
internal Component Get(string __tag) {
|
||||
if (_taggedComponents.TryGetValue(__tag, out SortedSet<Component> components))
|
||||
return ((Component[])[..components])[0];
|
||||
|
||||
return null;
|
||||
foreach (string tag in __component._tags) HashTaggedComponent(tag, __component);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Finds the first instance of a component with a given tag
|
||||
/// </summary>
|
||||
/// <param name="__tag"> Tag to search for</param>
|
||||
/// <param name="__component">Component that has been found</param>
|
||||
/// <returns></returns>
|
||||
internal bool TryGet(string __tag, out Component __component) { __component = Get(__tag); return __component != null; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Finds all Components with a given tag
|
||||
/// </summary>
|
||||
/// <param name="__tag"></param>
|
||||
/// <returns></returns>
|
||||
internal ImmutableArray<Component> GetAll(string __tag) {
|
||||
if (_taggedComponents.TryGetValue(__tag, out SortedSet<Component> components))
|
||||
return [..components];
|
||||
|
||||
return [];
|
||||
/// <summary> Removes a Component from the Docker. </summary>
|
||||
[MarkerAttributes.UnsafeInternal]
|
||||
private void RemoveComponentFromLists(Component __component) {
|
||||
Type Type = __component.GetType();
|
||||
_components.Remove(__component);
|
||||
|
||||
if(_componentTypeDictionary.TryGetValue(Type, out HashSet<Component> value)) value.Remove(__component);
|
||||
|
||||
foreach (string tag in __component._tags) UnhashTaggedComponent(tag, __component);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Searches for all Components with a given tag
|
||||
/// </summary>
|
||||
/// <param name="__tag"></param>
|
||||
/// <param name="__components"></param>
|
||||
/// <returns></returns>
|
||||
internal bool TryGetAll(string __tag, out ImmutableArray<Component> __components) { __components = GetAll(__tag); return __components.Length > 0; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Finds the first Component that has all the given tags
|
||||
/// </summary>
|
||||
/// <param name="__tags"></param>
|
||||
/// <returns></returns>
|
||||
internal Component Get(List<string> __tags) { ImmutableArray<Component> returnValue = GetAll(__tags); return returnValue.Length > 0 ? returnValue[0] : null; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Finds the first Component that has all the given tags
|
||||
/// </summary>
|
||||
/// <param name="__tags"></param>
|
||||
/// <returns></returns>
|
||||
internal bool TryGet(List<string> __tags, out Component __component) { __component = Get(__tags); return __component != null; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Finds all Components that have all the given tags
|
||||
/// </summary>
|
||||
/// <param name="__tags"></param>
|
||||
/// <returns></returns>
|
||||
internal ImmutableArray<Component> GetAll(List<string> __tags) {
|
||||
|
||||
if (__tags.Count == 0)
|
||||
return [];
|
||||
|
||||
SortedSet<Component> foundComponents = _taggedComponents[__tags[0]];
|
||||
|
||||
for (int i = 1; i < __tags.Count; i++) {
|
||||
foreach (Component component in (Component[])[..foundComponents]) {
|
||||
if (!_taggedComponents[__tags[i]].Contains(component)) foundComponents.Remove(component);
|
||||
}
|
||||
}
|
||||
|
||||
return [..foundComponents];
|
||||
/// <summary> Hashes a component in the tag dictionary </summary>
|
||||
[MarkerAttributes.UnsafeInternal]
|
||||
internal void HashTaggedComponent(string __tag, Component __component) {
|
||||
if (!_componentTagDictionary.TryAdd(__tag, [__component]))
|
||||
_componentTagDictionary[__tag].Add(__component);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get all components with the given tags
|
||||
/// </summary>
|
||||
/// <param name="__tags"></param>
|
||||
/// <param name="__components"></param>
|
||||
/// <returns></returns>
|
||||
internal bool TryGetAll(List<string> __tags, out ImmutableArray<Component> __components) { __components = GetAll(__tags); return __components.Length > 0; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Searches and returns the first Component of a type found on the Docker.
|
||||
/// </summary>
|
||||
/// <typeparam name="__Type"> The Type of Component to search for</typeparam>
|
||||
/// <returns></returns>
|
||||
public __Type Get<__Type>() where __Type : Component {
|
||||
|
||||
|
||||
|
||||
//Iterates through the loop and returns if a match is found
|
||||
foreach (Component component in (Component[])[.._Components])
|
||||
if (component is __Type foundComponent) return foundComponent;
|
||||
|
||||
|
||||
|
||||
//Throws error if there is no Component found
|
||||
Debug.LogError("Docker does not have target Component", ["Type", "Docker"],
|
||||
[typeof(__Type).ToString(), GetHashCode().ToString()]); return null;
|
||||
/// <summary> Removes a component's hash from the tag dictionary </summary>
|
||||
[MarkerAttributes.UnsafeInternal]
|
||||
internal void UnhashTaggedComponent(string __tag, Component __component) {
|
||||
if(!_componentTagDictionary.ContainsKey(__tag)) _componentTagDictionary[__tag].Remove(__component);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="__component"></param>
|
||||
/// <typeparam name="__Type"></typeparam>
|
||||
/// <returns></returns>
|
||||
public bool TryGet<__Type>(out __Type __component) where __Type : Component { __component = Get<__Type>(); return __component != null; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Searches and returns all Components of a type found on the Docker.
|
||||
/// </summary>
|
||||
/// <typeparam name="__Type"> The Type of Components to search for</typeparam>
|
||||
/// <returns></returns>
|
||||
public ImmutableArray<__Type> GetAll<__Type>() where __Type : Component {
|
||||
|
||||
|
||||
|
||||
List<__Type> foundComponents = [];
|
||||
|
||||
|
||||
//Iterates through the loop and returns if a match is found
|
||||
foreach (Component component in (Component[])[.._Components]) {
|
||||
if (component is __Type foundComponent) {
|
||||
foundComponents.Add(foundComponent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Throws error if there is no Component found
|
||||
if (foundComponents.Count == 0) {
|
||||
Debug.LogError("Docker does not have target Component", ["Type", "Docker"],
|
||||
[typeof(__Type).ToString(), GetHashCode().ToString()]);
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
|
||||
return [..foundComponents];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="__components"></param>
|
||||
/// <typeparam name="__Type"></typeparam>
|
||||
/// <returns></returns>
|
||||
public bool TryGetAll<__Type>(out ImmutableArray<__Type> __components) where __Type : Component { __components = GetAll<__Type>(); return __components.Length > 0; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a bool based on if the Docker contains a Component with the given tag or not
|
||||
/// </summary>
|
||||
/// <param name="__tag"></param>
|
||||
/// <returns></returns>
|
||||
public bool Contains(string __tag) => _taggedComponents.ContainsKey(__tag);
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a bool based on if the Docker contains a Component of that type or not
|
||||
/// </summary>
|
||||
/// <typeparam name="__Type">Type of the Component</typeparam>
|
||||
/// <returns></returns>
|
||||
public bool Contains<__Type>() where __Type : Component => _Components.Any(x => x is __Type);
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a bool based on if the current __Component is owned by this Docker
|
||||
/// </summary>
|
||||
/// <param name="__component"></param>
|
||||
/// <returns></returns>
|
||||
public bool Contains(Component __component) => _Components.Contains(__component);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Destroys a Component attached to docker
|
||||
/// </summary>
|
||||
/// <param name="__component"></param>
|
||||
public void Remove(Component __component) {
|
||||
|
||||
//Component is null
|
||||
if (__component == null) {
|
||||
Debug.LogError("Component is null", ["CurrentDocker"],
|
||||
[GetHashCode().ToString()]); return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Docker doesn't have Component
|
||||
if (!_Components.Contains(__component)) {
|
||||
Debug.LogError("Docker does not have ownership of Component", ["Component", "Type", "CurrentDocker"],
|
||||
[__component.GetHashCode().ToString(), __component.GetType().ToString(), GetHashCode().ToString()]); return;
|
||||
}
|
||||
|
||||
__component.Destroy();
|
||||
__component.ChainDestroy();
|
||||
foreach (string tag in __component._tags) UnhashTaggedComponent(__component, tag);
|
||||
__component.ComponentDocker = null;
|
||||
|
||||
_Components.Remove(__component);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Destroys the first found Component of a given type
|
||||
/// </summary>
|
||||
/// <typeparam name="__Type"> Type of Component to destroy</typeparam>
|
||||
public void Remove<__Type>() where __Type : Component => Remove(Get<__Type>());
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Destroys all Components from a given collection.
|
||||
/// </summary>
|
||||
/// <param name="__Components"></param>
|
||||
public void RemoveAll(IEnumerable<Component> __Components) { foreach (Component component in (Component[])[..__Components]) { Remove(component); } }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Destroys all Components of a given type
|
||||
/// </summary>
|
||||
/// <typeparam name="__Type"></typeparam>
|
||||
public void RemoveAll<__Type>() where __Type : Component => RemoveAll(GetAll<__Type>());
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Destroys all Components attached to Docker
|
||||
/// </summary>
|
||||
public void RemoveAll() { foreach (Component component in (Component[])[.._Components]) { Remove(component); } }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
|
||||
namespace AwperativeKernel;
|
||||
|
||||
|
||||
public abstract partial class ComponentDocker
|
||||
{
|
||||
|
||||
|
||||
/// <summary> Tells you whether the docker contains a component with the given tag </summary>
|
||||
[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);
|
||||
|
||||
|
||||
/// <summary> Tells you whether the docker contains a component with the given type</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public bool Contains<__Type>() where __Type : Component => _componentTypeDictionary.ContainsKey(typeof(__Type));
|
||||
|
||||
/// <summary> Tells you whether the docker contains a component with a given type and tag</summary>
|
||||
[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();
|
||||
|
||||
/// <summary> Tells you whether the docker contains a component with all the given tags </summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public bool Contains([DebugAttributes.EnumerableNotNull] IEnumerable<string> __tags) => GetAll(__tags).Any();
|
||||
|
||||
/// <summary> Tells you whether the docker contains a component with all the given tags and the type</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public bool Contains<__Type>([DebugAttributes.EnumerableNotNull] IEnumerable<string> __tags) where __Type : Component => GetAll<__Type>(__tags).Any();
|
||||
|
||||
/// <summary> Tells you whether the docker contains the given component.</summary>
|
||||
[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);
|
||||
|
||||
/// <summary> Tells you whether the docker contains the all the given components.</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public bool ContainsAll([DebugAttributes.EnumerableNotNull] IEnumerable<Component> __components) => __components.All(x => _components.Contains(x));
|
||||
|
||||
|
||||
|
||||
/// <summary> Gets all components of a given type</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public IEnumerable<Component> GetAll() => _components;
|
||||
|
||||
/// <summary> Finds the first component with a given Type</summary>
|
||||
[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<Component> Components) ? (__Type)Components.FirstOrDefault() : null;
|
||||
|
||||
/// <summary> Tries to find the first component with a given tag, and returns false if there is none</summary>
|
||||
[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; }
|
||||
|
||||
|
||||
|
||||
/// <summary> Gets all components of a given type</summary>
|
||||
[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 HashSet<Component> components) ? components.OfType<__Type>().ToList() : [];
|
||||
|
||||
/// <summary> Tries to get all components of a given type and returns false if there are none</summary>
|
||||
[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(); }
|
||||
|
||||
|
||||
|
||||
/// <summary> Finds all components that have all the given tags</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public IEnumerable<Component> GetAll([DebugAttributes.EnumerableNotNull] IEnumerable<string> __tags) {
|
||||
if (!DebugAttributes.EnumerableNotNull.VerifyOrThrow(__tags)) return [];
|
||||
|
||||
HashSet<Component> 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;
|
||||
}
|
||||
|
||||
/// <summary> Tries to find all components that have all the given tags, returns false if there are none</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public bool TryGetAll([DebugAttributes.EnumerableNotNull] IEnumerable<string> __tags, out IEnumerable<Component> __components)
|
||||
{ __components = GetAll(__tags); return __components.Any(); }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary> Finds all Components that have the given type, and all the given tags</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public IEnumerable<__Type> GetAll<__Type>([DebugAttributes.EnumerableNotNull] IEnumerable<string> __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();
|
||||
}
|
||||
|
||||
/// <summary> Tries to find all the components that have the given tags and type, returns false if there are none</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public bool TryGetAll<__Type>([DebugAttributes.EnumerableNotNull] IEnumerable<string> __tags, out IEnumerable<__Type> __components) where __Type : Component
|
||||
{ __components = GetAll<__Type>(__tags); return __components.Any(); }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary> Gets all the components with the given tag</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public IEnumerable<Component> GetAll(string __tag) => GetAll([__tag]);
|
||||
|
||||
/// <summary> Tries to get all the components with the given tag, returns false if there are none</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public bool TryGetAll([DebugAttributes.NotNull] string __tag, out IEnumerable<Component> __components) { __components = GetAll(__tag); return __components.Any(); }
|
||||
|
||||
|
||||
|
||||
/// <summary> Gets all the components that have a certain type, and a certain tag</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public IEnumerable<__Type> GetAll<__Type>([DebugAttributes.NotNull] string __tag) where __Type : Component => GetAll<__Type>([__tag]);
|
||||
|
||||
/// <summary> Tries to get all the components with a certain tag, and a type. Returns false if there are none</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public bool TryGetAll<__Type>([DebugAttributes.NotNull] string __tag, out IEnumerable<__Type> __components) where __Type : Component { __components = GetAll<__Type>(__tag); return __components.Any(); }
|
||||
|
||||
|
||||
|
||||
/// <summary> Gets the first component with all the given tags</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public Component Get([DebugAttributes.EnumerableNotNull] IEnumerable<string> __tags) => GetAll(__tags).FirstOrDefault();
|
||||
|
||||
/// <summary> Tries to get the first component with all the given tags. Returns false if there are none</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public bool TryGet([DebugAttributes.EnumerableNotNull] IEnumerable<string> __tags, out Component __component) { __component = Get(__tags); return __component != null; }
|
||||
|
||||
|
||||
|
||||
/// <summary> Finds the first component with the given tag</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public Component Get([DebugAttributes.NotNull] string __tag) => GetAll([__tag]).FirstOrDefault();
|
||||
|
||||
/// <summary> Tries to find the first component with the given tag, returns false if there is none</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public bool TryGet([DebugAttributes.NotNull] string __tag, out Component __component) { __component = Get(__tag); return __component != null; }
|
||||
|
||||
|
||||
|
||||
/// <summary> Gets the first component with the given type and tag</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public __Type Get<__Type>([DebugAttributes.NotNull] string __tag) where __Type : Component => GetAll<__Type>(__tag).FirstOrDefault();
|
||||
|
||||
/// <summary> Tries to get the first component with the given type and tag, returns false if there is none.</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public bool TryGet<__Type>([DebugAttributes.NotNull] string __tag, out __Type __component) where __Type : Component { __component = Get<__Type>(__tag); return __component != null; }
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
|
||||
namespace AwperativeKernel;
|
||||
|
||||
|
||||
public abstract partial class ComponentDocker
|
||||
{
|
||||
|
||||
|
||||
|
||||
/// <summary> Moves a component belonging to the docker to another docker</summary>
|
||||
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;
|
||||
|
||||
RemoveComponentFromLists(__component);
|
||||
__componentDocker.AddComponentToLists(__component);
|
||||
|
||||
__component.ComponentDocker = __componentDocker;
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Moves all components in a list to another docker</summary>
|
||||
public void MoveAll([DebugAttributes.EnumerableNotNull, DebugAttributes.DockerOwns] IEnumerable<Component> __Components, [DebugAttributes.DockerNotNull, DebugAttributes.DifferentDocker] ComponentDocker __componentDocker) {
|
||||
if(!DebugAttributes.EnumerableNotNull.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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Gets all components of a given type</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public void MoveAll([DebugAttributes.DockerNotNull, DebugAttributes.DifferentDocker] ComponentDocker __componentDocker) => MoveAll(GetAll(), __componentDocker);
|
||||
|
||||
/// <summary> Moves the first component with a given Type</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public void Move<__Type>([DebugAttributes.DockerNotNull, DebugAttributes.DifferentDocker] ComponentDocker __componentDocker) where __Type : Component => Move(Get<__Type>(), __componentDocker);
|
||||
|
||||
|
||||
|
||||
/// <summary> Moves all components of a given type</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Low), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public void MoveAll<__Type>([DebugAttributes.DockerNotNull, DebugAttributes.DifferentDocker] ComponentDocker __componentDocker) where __Type : Component => MoveAll(GetAll<__Type>(), __componentDocker);
|
||||
|
||||
|
||||
|
||||
/// <summary> Moves all components that have all the given tags</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public void MoveAll([DebugAttributes.EnumerableNotNull] IEnumerable<string> __tags, [DebugAttributes.DockerNotNull, DebugAttributes.DifferentDocker] ComponentDocker __componentDocker) => MoveAll(GetAll(__tags), __componentDocker);
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary> Moves all Components that have the given type, and all the given tags</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public void MoveAll<__Type>([DebugAttributes.EnumerableNotNull] IEnumerable<string> __tags, [DebugAttributes.DockerNotNull, DebugAttributes.DifferentDocker] ComponentDocker __componentDocker) where __Type : Component => MoveAll(GetAll<__Type>(__tags), __componentDocker);
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary> Moves all the components with the given tag</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public void MoveAll([DebugAttributes.NotNull] string __tag, [DebugAttributes.DockerNotNull, DebugAttributes.DifferentDocker] ComponentDocker __componentDocker) => MoveAll(GetAll([__tag]), __componentDocker);
|
||||
|
||||
|
||||
|
||||
/// <summary> Moves all the components that have a certain type, and a certain tag</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public void MoveAll<__Type>([DebugAttributes.NotNull] string __tag, [DebugAttributes.DockerNotNull, DebugAttributes.DifferentDocker] ComponentDocker __componentDocker) where __Type : Component => MoveAll(GetAll<__Type>([__tag]), __componentDocker);
|
||||
|
||||
|
||||
|
||||
/// <summary> Moves the first component with the given tag</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public void Move([DebugAttributes.NotNull] string __tag, [DebugAttributes.DockerNotNull, DebugAttributes.DifferentDocker] ComponentDocker __componentDocker) => Move(GetAll([__tag]).FirstOrDefault(), __componentDocker);
|
||||
|
||||
|
||||
|
||||
/// <summary> Moves the moves component with the given type and tag</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.VeryLow), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public void Move<__Type>([DebugAttributes.NotNull] string __tag, [DebugAttributes.DockerNotNull, DebugAttributes.DifferentDocker] ComponentDocker __componentDocker) where __Type : Component => Move(GetAll<__Type>(__tag).FirstOrDefault(), __componentDocker);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
|
||||
namespace AwperativeKernel;
|
||||
|
||||
|
||||
public abstract partial class ComponentDocker
|
||||
{
|
||||
|
||||
|
||||
/// <summary> 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</summary>
|
||||
[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;
|
||||
|
||||
InitiateComponent(__component);
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Creates a new instance of that type of component and attaches it to the docker, and returns a reference to it.</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Low), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public __Type Add<__Type>() where __Type : Component, new() {
|
||||
Component newComponent = new __Type();
|
||||
InitiateComponent(newComponent);
|
||||
return (__Type)newComponent;
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Creates a new instance of that type of component and attaches it to the docker, and returns a reference to it.</summary> [MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public __Type Add<__Type>(string name = null, [DebugAttributes.ValueFitsRange] int priority = 0, Collection<string> 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;
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Initiates a component into the docker. </summary>
|
||||
[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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary> Destroys a component attached to the Docker </summary>
|
||||
/// <param name="__component"></param>
|
||||
public void Destroy([DebugAttributes.ComponentNotNull, DebugAttributes.DockerOwns] Component __component) {
|
||||
if (!DebugAttributes.ComponentNotNull.VerifyOrThrow(__component)) return;
|
||||
if (!DebugAttributes.DockerOwns.VerifyOrThrow(this, __component)) return;
|
||||
|
||||
__component.TryEvent(5);
|
||||
__component.ChainEvent(5);
|
||||
|
||||
RemoveComponentFromLists(__component);
|
||||
__component.ComponentDocker = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary> Destroys all the components in a given list </summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public void DestroyAll() => DestroyAll(GetAll());
|
||||
|
||||
|
||||
|
||||
/// <summary> Destroys all the components in a given list </summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public void DestroyAll([DebugAttributes.EnumerableNotNull, DebugAttributes.DockerOwns] IEnumerable<Component> __Components) { foreach (Component component in __Components.ToArray()) Destroy(component); }
|
||||
|
||||
|
||||
|
||||
/// <summary> Destroys the first component with a given Type</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Low), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public void Destroy<__Type>() where __Type : Component => Destroy(Get<__Type>());
|
||||
|
||||
|
||||
|
||||
/// <summary> Destroys all components of a given type</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public void DestroyAll<__Type>() where __Type : Component => DestroyAll(GetAll<__Type>());
|
||||
|
||||
|
||||
|
||||
/// <summary> Destroys all components that have all the given tags</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public void DestroyAll([DebugAttributes.EnumerableNotNull] IEnumerable<string> __tags) => DestroyAll(GetAll(__tags));
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary> Destroys all Components that have the given type, and all the given tags</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public void DestroyAll<__Type>([DebugAttributes.EnumerableNotNull] IEnumerable<string> __tags) where __Type : Component => DestroyAll(GetAll<__Type>(__tags));
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary> Destroys all the components with the given tag</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public void DestroyAll([DebugAttributes.NotNull] string __tag) => DestroyAll(GetAll([__tag]));
|
||||
|
||||
|
||||
|
||||
/// <summary> Destroys all the components that have a certain type, and a certain tag</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public void DestroyAll<__Type>([DebugAttributes.NotNull] string __tag) where __Type : Component => DestroyAll(GetAll<__Type>([__tag]));
|
||||
|
||||
|
||||
|
||||
/// <summary> Destroys the first component with the given tag</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Low), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public void Destroy([DebugAttributes.NotNull] string __tag) => Destroy(GetAll([__tag]).FirstOrDefault());
|
||||
|
||||
|
||||
|
||||
/// <summary> Destroys the Destroys component with the given type and tag</summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Low), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public void Destroy<__Type>([DebugAttributes.NotNull] string __tag) where __Type : Component => Destroy(GetAll<__Type>(__tag).FirstOrDefault());
|
||||
|
||||
}
|
||||
@@ -1,207 +1,132 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
|
||||
|
||||
namespace AwperativeKernel;
|
||||
|
||||
|
||||
public static class Debug
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// True path of the log file Awperative dumps to.
|
||||
/// </summary>
|
||||
public static string LogFilePath { get; private set; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Target name of the log file
|
||||
/// </summary>
|
||||
public static string LogFileName { get; private set; } = "Log";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If this is running or not
|
||||
/// </summary>
|
||||
private static bool Running = false;
|
||||
|
||||
|
||||
|
||||
//Whether to throw error exceptions
|
||||
public static bool ThrowExceptions { get; set; } = false;
|
||||
//Whether to ignore/pass through errors or not
|
||||
public static bool IgnoreErrors { get; set; } = false;
|
||||
//Whether to debug errors at all
|
||||
public static bool DebugErrors { get; set; } = true;
|
||||
|
||||
|
||||
|
||||
public static SafetyLevel safetyLevel {
|
||||
get => _safetyLevel;
|
||||
set {
|
||||
ThrowExceptions = value is SafetyLevel.Extreme;
|
||||
IgnoreErrors = value is SafetyLevel.Low or SafetyLevel.None;
|
||||
DebugErrors = value is not SafetyLevel.None;
|
||||
_safetyLevel = value;
|
||||
}
|
||||
} private static SafetyLevel _safetyLevel;
|
||||
|
||||
public enum SafetyLevel {
|
||||
Extreme, //Throw exceptions and stop the whole program
|
||||
Normal, //Just debug it to the console, and halt current process
|
||||
Low, //Push through tasks but debug error
|
||||
None, //Ignore most/all errors and do not debug it,
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets up the Awperative debugger and finds the log file.
|
||||
/// </summary>
|
||||
internal static void Initiate() {
|
||||
public static void Start() {
|
||||
if(Running) return;
|
||||
|
||||
Running = true;
|
||||
|
||||
string directoryPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
if(directoryPath == null) throw new Exception("Failed to get directory path!");
|
||||
|
||||
|
||||
LogFilePath = Path.Join(directoryPath, LogFileName + ".awlf");
|
||||
|
||||
|
||||
if(!Directory.GetFiles(directoryPath).Contains(LogFileName + ".awlf")) { File.Create(LogFilePath).Close(); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Writes the current message to the log file.
|
||||
/// </summary>
|
||||
/// <param name="__message"> Message to debug</param>
|
||||
public static void LogAction(string __message) => LogGeneric(__message, "ACT", [], []);
|
||||
|
||||
/// <summary>
|
||||
/// Writes the current message to the log file. With any given call sign.
|
||||
/// </summary>
|
||||
/// <param name="__message"> Message to debug</param>
|
||||
/// <param name="__parameters"> Names of values to debug</param>
|
||||
/// <param name="__values"> Values to debug</param>
|
||||
public static void LogAction(string __message, string[] __parameters, string[] __values) => LogGeneric(__message, "ACT", __parameters, __values);
|
||||
|
||||
/// <summary>
|
||||
/// Writes the current message to the log file if the condition is true.
|
||||
/// </summary>
|
||||
/// <param name="__condition"> Condition to debug </param>
|
||||
/// <param name="__message"> Message to debug</param>
|
||||
public static void AssertAction(bool __condition, string __message) => AssertGeneric(__condition, __message, "ACT", [], []);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Writes the current message to the log file.
|
||||
/// </summary>
|
||||
/// <param name="__message"> Message to debug</param>
|
||||
public static void LogState(string __message) => LogGeneric(__message, "STA", [], []);
|
||||
|
||||
/// <summary>
|
||||
/// Writes the current message to the log file. With any given call sign.
|
||||
/// </summary>
|
||||
/// <param name="__message"> Message to debug</param>
|
||||
/// <param name="__parameters"> Names of values to debug</param>
|
||||
/// <param name="__values"> Values to debug</param>
|
||||
public static void LogState(string __message, string[] __parameters, string[] __values) => LogGeneric(__message, "STA", __parameters, __values);
|
||||
|
||||
/// <summary>
|
||||
/// Writes the current message to the log file if the condition is true.
|
||||
/// </summary>
|
||||
/// <param name="__condition"> Condition to debug </param>
|
||||
/// <param name="__message"> Message to debug</param>
|
||||
public static void AssertState(bool __condition, string __message) => AssertGeneric(__condition, __message, "STA", [], []);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Writes the current message to the log file.
|
||||
/// </summary>
|
||||
/// <param name="__message"> Message to debug</param>
|
||||
public static void LogValue(string __message) => LogGeneric(__message, "VAL", [], []);
|
||||
|
||||
/// <summary>
|
||||
/// Writes the current message to the log file. With any given call sign.
|
||||
/// </summary>
|
||||
/// <param name="__message"> Message to debug</param>
|
||||
/// <param name="__parameters"> Names of values to debug</param>
|
||||
/// <param name="__values"> Values to debug</param>
|
||||
public static void LogValue(string __message, string[] __parameters, string[] __values) => LogGeneric(__message, "VAL", __parameters, __values);
|
||||
|
||||
/// <summary>
|
||||
/// Writes the current message to the log file if the condition is true.
|
||||
/// </summary>
|
||||
/// <param name="__condition"> Condition to debug </param>
|
||||
/// <param name="__message"> Message to debug</param>
|
||||
public static void AssertValue(bool __condition, string __message) => AssertGeneric(__condition, __message, "VAL", [], []);
|
||||
public static void Stop() {
|
||||
Running = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Writes the current message to the log file.
|
||||
/// </summary>
|
||||
/// <param name="__message"> Message to debug</param>
|
||||
public static void LogWarning(string __message) => LogGeneric(__message, "WAR", [], []);
|
||||
|
||||
/// <summary>
|
||||
/// Writes the current message to the log file. With any given call sign.
|
||||
/// </summary>
|
||||
/// <param name="__message"> Message to debug</param>
|
||||
/// <param name="__parameters"> Names of values to debug</param>
|
||||
/// <param name="__values"> Values to debug</param>
|
||||
public static void LogWarning(string __message, string[] __parameters, string[] __values) => LogGeneric(__message, "WAR", __parameters, __values);
|
||||
|
||||
/// <summary>
|
||||
/// Writes the current message to the log file if the condition is true.
|
||||
/// </summary>
|
||||
/// <param name="__condition"> Condition to debug </param>
|
||||
/// <param name="__message"> Message to debug</param>
|
||||
public static void AssertWarning(bool __condition, string __message) => AssertGeneric(__condition, __message, "WAR", [], []);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Writes the current message to the log file.
|
||||
/// </summary>
|
||||
/// <param name="__message"> Message to debug</param>
|
||||
public static void LogError(string __message) => LogGeneric(__message, "ERR", [], []);
|
||||
|
||||
/// <summary>
|
||||
/// Writes the current message to the log file. With any given call sign.
|
||||
/// </summary>
|
||||
/// <param name="__message"> Message to debug</param>
|
||||
/// <param name="__parameters"> Names of values to debug</param>
|
||||
/// <param name="__values"> Values to debug</param>
|
||||
public static void LogError(string __message, string[] __parameters, string[] __values) => LogGeneric(__message, "ERR", __parameters, __values);
|
||||
|
||||
/// <summary>
|
||||
/// Writes the current message to the log file if the condition is true.
|
||||
/// </summary>
|
||||
/// <param name="__condition"> Condition to debug </param>
|
||||
/// <param name="__message"> Message to debug</param>
|
||||
public static void AssertError(bool __condition, string __message) => AssertGeneric(__condition, __message, "ERR", [], []);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Writes the current message to the log file. With any given call sign.
|
||||
/// </summary>
|
||||
/// <param name="__message"> Message to debug</param>
|
||||
/// <param name="__callSign"> Message identifier</param>
|
||||
/// <param name="__parameters"> Names of values to debug</param>
|
||||
/// <param name="__values"> Values to debug</param>
|
||||
public static void LogGeneric(string __message, string __callSign, string[] __parameters, string[] __values) {
|
||||
string output = "\n\n" + __callSign + "- \"" + __message + "\"\n STK-" + new StackTrace();
|
||||
|
||||
for (int i = 0; i < __parameters.Length || i < __values.Length; i++)
|
||||
output += "\n " + __parameters[i] + "- " + __values[i];
|
||||
public static void LogAction(string __message) {
|
||||
LogGeneric(__message, "ACT", [], [], false);
|
||||
}
|
||||
|
||||
File.AppendAllText(LogFilePath, output);
|
||||
public static void LogAction(string __message, IEnumerable<string> __values, IEnumerable<string> __args) {
|
||||
LogGeneric(__message, "ACT", __values, __args, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void LogWarning(string __message) {
|
||||
LogGeneric(__message, "WRN", [], [], false);
|
||||
}
|
||||
|
||||
public static void LogWarning(string __message, IEnumerable<string> __values, IEnumerable<string> __args) {
|
||||
LogGeneric(__message, "WRN", __values, __args, false);;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void LogError(string __message) {
|
||||
LogGeneric(__message, "ERR", [], [], true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static void LogError(string __message, IEnumerable<string> __values, IEnumerable<string> __args) {
|
||||
LogGeneric(__message, "ERR", __values, __args, true);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Writes the current message to the log file if the condition is true. With any given call sign.
|
||||
/// Writes the current message to the log file. With any given call sign.
|
||||
/// </summary>
|
||||
/// <param name="__condition"> Condition to debug </param>
|
||||
/// <param name="__message"> Message to debug</param>
|
||||
/// <param name="__callSign"> Message identifier</param>
|
||||
/// <param name="__parameters"> Names of values to debug</param>
|
||||
/// <param name="__values"> Values to debug</param>
|
||||
public static void AssertGeneric(bool __condition, string __message, string __callSign, string[] __parameters, string[] __values) {
|
||||
if (!__condition) return;
|
||||
|
||||
/// <param name="__exception"> Should this throw an exception instead</param>
|
||||
public static void LogGeneric(string __message, string __callSign, IEnumerable<string> __parameters, IEnumerable<string> __values, bool __exception) {
|
||||
string output = "\n\n" + __callSign + "- \"" + __message + "\"\n STK-" + new StackTrace();
|
||||
|
||||
for (int i = 0; i < __parameters.Length || i < __values.Length; i++)
|
||||
output += "\n " + __parameters[i] + "- " + __values[i];
|
||||
|
||||
for (int i = 0; i < __parameters.Count() || i < __values.Count(); i++)
|
||||
output += "\n " + __parameters.ElementAt(i) + "- " + __values.ElementAt(i);
|
||||
|
||||
if (__exception && ThrowExceptions) throw new Exception(output);
|
||||
|
||||
File.AppendAllText(LogFilePath, output);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
Awperative debugger writes errors to file while staying within runtime.
|
||||
|
||||
Searches for a file with any specifiable name in config. that must end in .awlf
|
||||
|
||||
stands for awperative logging format.
|
||||
@@ -1,11 +0,0 @@
|
||||
using System;
|
||||
|
||||
|
||||
namespace AwperativeKernel;
|
||||
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
||||
public class Show : Attribute
|
||||
{
|
||||
public bool UseInspectorDefaults = true;
|
||||
}
|
||||
@@ -1,106 +1,142 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using Awperative.Kernel.Overhead.Reflection;
|
||||
|
||||
|
||||
namespace AwperativeKernel;
|
||||
|
||||
/// <summary>
|
||||
/// Initiating class of Awperative. Call Start() to start the kernel.
|
||||
/// Main class of Awperative, allows you to Create() scenes and Start() the game
|
||||
/// </summary>
|
||||
/// <author> Avery Norris </author>
|
||||
public static class Awperative
|
||||
{
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Bottom class of Awperative. Contains the MonoGame instance.
|
||||
/// </summary>
|
||||
public static Base Base { get; internal set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// List of all scenes currently loaded in the kernel.
|
||||
/// </summary>
|
||||
public static ImmutableArray<Scene> Scenes => [.._scenes];
|
||||
internal static HashSet<Scene> _scenes { get; private set; } = [];
|
||||
/// <summary> Current Version of Awperative </summary>
|
||||
public static string Version = "1.2C";
|
||||
|
||||
|
||||
|
||||
/// <summary> Bottom class of Awperative. Contains the OpenTK Instance. </summary>
|
||||
[DebugAttributes.NotNull, MarkerAttributes.UnsafeInternal] public static Base Base;
|
||||
|
||||
|
||||
|
||||
/// <summary> List of all scenes currently loaded in the kernel. </summary>
|
||||
[MarkerAttributes.CalculatedProperty]
|
||||
public static IReadOnlySet<Scene> Scenes => _scenes;
|
||||
[MarkerAttributes.UnsafeInternal] internal static HashSet<Scene> _scenes { get; private set; } = [];
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new Scene
|
||||
/// </summary>
|
||||
public static Scene CreateScene(string __name) {
|
||||
if (!ContainsScene(__name)) {
|
||||
Scene newScene = new Scene(__name);
|
||||
_scenes.Add(newScene);
|
||||
return newScene;
|
||||
} else Debug.LogError("Awperative already has a Scene with that name!", ["Scene", "Name"], [GetScene(__name).GetHashCode().ToString(), __name]); return null;
|
||||
|
||||
/// <summary> Displays if Awperative has Started or not </summary>
|
||||
public static bool IsStarted { get; private set; } = false;
|
||||
/// <summary> Displays if the update loop is active</summary>
|
||||
public static bool IsRunning { get; private set; } = false;
|
||||
|
||||
|
||||
|
||||
/// <summary> Creates a new Scene with the given name </summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Low), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public static Scene CreateScene([DebugAttributes.NotNull, DebugAttributes.SceneDoesNotExist] string __name) {
|
||||
if (!DebugAttributes.NotNull.VerifyOrThrow(__name)) return null;
|
||||
if (!DebugAttributes.SceneDoesNotExist.VerifyOrThrow(GetScene(__name))) return null;
|
||||
|
||||
Scene newScene = new (__name);
|
||||
_scenes.Add(newScene);
|
||||
return newScene;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Adds a new scene that you construct. </summary>
|
||||
/// <param name="__scene"></param>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Low), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.O1)]
|
||||
public static void AddScene([DebugAttributes.SceneNotNull, DebugAttributes.SceneDoesNotExist] Scene __scene) {
|
||||
if (!DebugAttributes.SceneNotNull.VerifyOrThrow(__scene)) return;
|
||||
if (!DebugAttributes.SceneDoesNotExist.VerifyOrThrow(__scene)) return;
|
||||
|
||||
_scenes.Add(__scene);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds a Scene from a given name
|
||||
/// </summary>
|
||||
/// <param name="__name"> Name to search for</param>
|
||||
/// <returns></returns>
|
||||
public static Scene GetScene(string __name) => _scenes.FirstOrDefault(scene => scene.Name == __name, null);
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns bool based on whether there a scene with the given name or not.
|
||||
/// </summary>
|
||||
/// <param name="__name"> Name of the Scene</param>
|
||||
/// <returns></returns>
|
||||
|
||||
|
||||
/// <summary> Finds a Scene from a given name </summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public static Scene GetScene([DebugAttributes.NotNull] string __name) => !DebugAttributes.NotNull.VerifyOrThrow(__name) ? null : _scenes.FirstOrDefault(scene => scene.Name == __name, null);
|
||||
|
||||
|
||||
|
||||
/// <summary> Returns bool based on whether there a scene with the given name or not. </summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public static bool ContainsScene(string __name) => _scenes.Any(scene => scene.Name == __name);
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Closes a Scene
|
||||
/// </summary>
|
||||
/// <param name="__scene"> Scene to close</param>
|
||||
public static void CloseScene(Scene __scene) => Scenes.Remove(__scene);
|
||||
/// <summary> Closes a Scene </summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public static void CloseScene(Scene __scene) => _scenes.Remove(__scene);
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Closes a Scene
|
||||
/// </summary>
|
||||
/// <param name="__name"> Name of the scene</param>
|
||||
public static void CloseScene(string __name) => Scenes.Remove(GetScene(__name));
|
||||
|
||||
/// <summary> Closes a Scene </summary>
|
||||
[MarkerAttributes.Expense(MarkerAttributes.Expense.ExpenseLevel.Medium), MarkerAttributes.Complexity(MarkerAttributes.Complexity.TimeComplexity.ON)]
|
||||
public static void CloseScene(string __name) => _scenes.Remove(GetScene(__name));
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets Awperative ready to roll!
|
||||
/// </summary>
|
||||
/// <param name="__hooks"> List of all event hooks you wish to use. </param>
|
||||
/// <remarks> You cannot add new hooks later; so make sure to register all of them in the Start() method.</remarks>
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary> Gets Awperative ready to begin! Compiles Component functions etc. Please call before doing anything Awperative related! </summary>
|
||||
public static void Start() {
|
||||
Debug.Initiate();
|
||||
if (IsStarted) return;
|
||||
IsStarted = true;
|
||||
|
||||
Base = new Base();
|
||||
|
||||
ReflectionManager.ResolveModules(AppDomain.CurrentDomain.GetAssemblies());
|
||||
|
||||
Debug.Start();
|
||||
Debug.LogAction("Successfully Compiled Classes!");
|
||||
}
|
||||
|
||||
internal static Comparer<Component> _prioritySorter = Comparer<Component>.Create((a, b) => {
|
||||
int result = b.Priority.CompareTo(a.Priority);
|
||||
return (result != 0) ? result : a.GetHashCode().CompareTo(b.GetHashCode());
|
||||
});
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Starts Awperative up! This method runs forever.
|
||||
/// </summary>
|
||||
/// <summary> Starts Awperative up! This method runs until the game is closed. </summary>
|
||||
public static void Run() {
|
||||
Base = new Base();
|
||||
if(!IsStarted && IsRunning) return;
|
||||
IsRunning = true;
|
||||
Base.Run();
|
||||
}
|
||||
|
||||
/// <summary> Closes Awperative! </summary>
|
||||
public static void Close() {
|
||||
Base.Close();
|
||||
}
|
||||
|
||||
/// <summary> Performs a mock update. </summary>
|
||||
[MarkerAttributes.UnsafeInternal]
|
||||
public static void TestUpdate() {
|
||||
foreach (Scene scene in Scenes) {
|
||||
scene.ChainEvent(2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary> Performs a mock draw call. </summary>
|
||||
[MarkerAttributes.UnsafeInternal]
|
||||
public static void TestDraw() {
|
||||
foreach (Scene scene in Scenes) {
|
||||
scene.ChainEvent(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
using System.ComponentModel;
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics.OpenGL.Compatibility;
|
||||
using OpenTK.Windowing.Common;
|
||||
using OpenTK.Windowing.Desktop;
|
||||
|
||||
@@ -22,7 +25,15 @@ public sealed class Base() : GameWindow(GameWindowSettings.Default, new NativeWi
|
||||
/// LoadContent() is called when the program starts; right after Initialize(). Override Load() in scripting tools or use hooks to call from this event.
|
||||
/// </summary>
|
||||
/// <remarks> It is recommended to load content during LoadContent()</remarks>
|
||||
protected override void OnLoad() { foreach(Scene scene in Awperative.Scenes.ToList()) if(scene.Enabled) scene.ChainLoad(); }
|
||||
protected override void OnLoad() { foreach(Scene scene in Awperative._scenes) scene.ChainEvent(0); base.OnLoad(); }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// EndRun() is called if the program closes. Override Terminate() in scripting tools or use hooks to call from this event.
|
||||
/// </summary>
|
||||
/// <remarks> This event may not trigger if the program is force closed.</remarks>
|
||||
protected override void OnClosing(CancelEventArgs __args) { foreach(Scene scene in Awperative._scenes) scene.ChainEvent(1); base.OnClosing(__args); }
|
||||
|
||||
|
||||
|
||||
@@ -32,9 +43,7 @@ public sealed class Base() : GameWindow(GameWindowSettings.Default, new NativeWi
|
||||
/// Update() is called every frame; before Draw(). Override Update() in scripting tools to call from this event.
|
||||
/// </summary>
|
||||
/// <remarks> Hooks are unable to receive both Update() and Draw()</remarks>
|
||||
protected override void OnUpdateFrame(FrameEventArgs __args) { foreach(Scene scene in Awperative.Scenes.ToList()) if(scene.Enabled) scene.ChainUpdate(); base.OnUpdateFrame(__args); }
|
||||
|
||||
|
||||
protected override void OnUpdateFrame(FrameEventArgs __args) { foreach(Scene scene in Awperative._scenes) scene.ChainEvent(2); base.OnUpdateFrame(__args); }
|
||||
|
||||
|
||||
|
||||
@@ -42,19 +51,12 @@ public sealed class Base() : GameWindow(GameWindowSettings.Default, new NativeWi
|
||||
/// Draw() is called every frame; after Update(). Override Draw() in scripting tools to call from this event.
|
||||
/// </summary>
|
||||
/// <remarks> Hooks are unable to receive both Update() and Draw()</remarks>
|
||||
protected override void OnRenderFrame(FrameEventArgs __args) { foreach(Scene scene in Awperative.Scenes.ToList()) if(scene.Enabled) scene.ChainDraw(); base.OnRenderFrame(__args); }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// EndRun() is called if the program closes. Override Terminate() in scripting tools or use hooks to call from this event.
|
||||
/// </summary>
|
||||
/// <remarks> This event may not trigger if the program is force closed.</remarks>
|
||||
protected override void OnClosing(CancelEventArgs __args) { foreach (Scene scene in Awperative.Scenes.ToList()) if(scene.Enabled) scene.ChainUnload(); base.OnClosing(__args); }
|
||||
|
||||
protected override void OnRenderFrame(FrameEventArgs __args) { foreach(Scene scene in Awperative._scenes) scene.ChainEvent(3); base.OnRenderFrame(__args); }
|
||||
|
||||
|
||||
|
||||
protected override void OnResize(ResizeEventArgs e) {
|
||||
GL.Viewport(0, 0, e.Width, e.Height);
|
||||
base.OnResize(e);
|
||||
}
|
||||
}
|
||||
48
AwperativeKernel/Kernel/Overhead/Reflection/EventManager.cs
Normal file
48
AwperativeKernel/Kernel/Overhead/Reflection/EventManager.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using AwperativeKernel;
|
||||
|
||||
|
||||
namespace Awperative.Kernel.Overhead.Reflection;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Registers events for component type objects.
|
||||
/// </summary>
|
||||
/// <author> Avery Norris </author>
|
||||
internal static class EventManager
|
||||
{
|
||||
/// <summary> Holds an associated action for each component and a time event. Is built with CompileType() during Start().</summary>
|
||||
[MarkerAttributes.UnsafeInternal]
|
||||
internal static Dictionary<Type, Action<Component>[]> _TypeAssociatedTimeEvents = [];
|
||||
|
||||
|
||||
/// <summary> All types of time based events in Awperative.</summary>
|
||||
internal static readonly ImmutableArray<string> Events = ["Load", "Unload", "Update", "Draw", "Create", "Remove"];
|
||||
|
||||
|
||||
/// <summary> Compiles a single type, and stores its events in the dictionary.</summary>
|
||||
[MarkerAttributes.UnsafeInternal]
|
||||
internal static void CompileType(Type __type) {
|
||||
if (!__type.IsSubclassOf(typeof(Component))) return;
|
||||
|
||||
|
||||
List<Action<Component>> timeEvents = [];
|
||||
|
||||
foreach (MethodInfo eventMethod in Events.Select(__type.GetMethod)) {
|
||||
if (eventMethod == null) { timeEvents.Add(null); continue; }
|
||||
|
||||
ParameterExpression ComponentInstanceParameter = Expression.Parameter(typeof(Component), "__component");
|
||||
UnaryExpression Casting = Expression.Convert(ComponentInstanceParameter, __type);
|
||||
MethodCallExpression Call = Expression.Call(Casting, eventMethod);
|
||||
Expression<Action<Component>> Lambda = Expression.Lambda<Action<Component>>(Call, ComponentInstanceParameter);
|
||||
timeEvents.Add(Lambda.Compile());
|
||||
}
|
||||
|
||||
_TypeAssociatedTimeEvents.Add(__type, timeEvents.ToArray());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using AwperativeKernel;
|
||||
|
||||
|
||||
namespace Awperative.Kernel.Overhead.Reflection;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Manages all Awperative reflection based activities, right now limited to registering events.
|
||||
/// </summary>
|
||||
/// <author> Avery Norris </author>
|
||||
internal static class ReflectionManager
|
||||
{
|
||||
/// <summary> Resolves all the modules from the calling assembly and module manager</summary>
|
||||
[MarkerAttributes.UnsafeInternal]
|
||||
internal static void ResolveModules(Assembly[] __assemblies) {
|
||||
foreach (Assembly assembly in __assemblies) ResolveAssembly(assembly);
|
||||
}
|
||||
|
||||
/// <summary> Resolves all the types in an assembly.</summary>
|
||||
[MarkerAttributes.UnsafeInternal]
|
||||
internal static void ResolveAssembly(Assembly __assembly) {
|
||||
foreach (Type type in __assembly.GetTypes()) {
|
||||
EventManager.CompileType(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,24 @@
|
||||
|
||||
|
||||
namespace AwperativeKernel;
|
||||
|
||||
public sealed partial class Scene : ComponentDocker
|
||||
/// <summary>
|
||||
/// One of the main Awperative entities. Acts like a master folder for components to be stored in.
|
||||
/// </summary>
|
||||
/// <author> Avery Norris </author>
|
||||
public class Scene : ComponentDocker
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Whether the scene is enabled or not.
|
||||
/// </summary>
|
||||
/// <summary> Whether the scene should receive updates or not</summary>
|
||||
public bool Enabled = true;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Unique Name of the Scene
|
||||
/// </summary>
|
||||
/// <summary> Unique identifier of the Scene</summary>
|
||||
public string Name;
|
||||
|
||||
|
||||
|
||||
//Blocks external construction
|
||||
internal Scene() {}
|
||||
|
||||
|
||||
|
||||
@@ -27,4 +27,28 @@ A few modules have been given documentation and the website is currently underwa
|
||||
|
||||
---
|
||||
|
||||
Awperative is officially moved to Open TK!
|
||||
Awperative is officially moved to Open TK!
|
||||
|
||||
# Awperative V1.2B
|
||||
|
||||
### Feb 21 2026
|
||||
|
||||
---
|
||||
|
||||
Beta Reflection And Speed Increasment
|
||||
|
||||
# Awperative V1.2C
|
||||
|
||||
### Feb 28 2026
|
||||
|
||||
---
|
||||
|
||||
Finished Reflection, and Awperative is MUCH faster.
|
||||
|
||||
# Awperative V1.3A
|
||||
|
||||
### March 02 2026
|
||||
|
||||
---
|
||||
|
||||
Awperative is nearly in a ready to deploy state! Aside from documentation and on the side support.
|
||||
@@ -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+31304e9361e9cb2c8a96c5b71df5898a3a6da2a5")]
|
||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+c215cab014ff2debe4e45bf05947022f1fef3a3a")]
|
||||
[assembly: System.Reflection.AssemblyProductAttribute("AwperativeKernel")]
|
||||
[assembly: System.Reflection.AssemblyTitleAttribute("AwperativeKernel")]
|
||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||
|
||||
@@ -1 +1 @@
|
||||
35c328d3af30548ed777d71d5913f389ba8fda839eeb8f7de7916868a456c94c
|
||||
b7d1b14e9a1ac81938a6d0c218c9dab887f6f7a09fb1ffc6cc863c2d552ebcf4
|
||||
|
||||
@@ -1 +1 @@
|
||||
1492481e4eae3b80db2d149ab088600d21214f29161b6bc87c6dbab466600b9b
|
||||
9bb3f60279095695d105894a656dbaad7a0575a2cc3d0cea10961bba7a20f857
|
||||
|
||||
@@ -25,4 +25,11 @@
|
||||
/home/avery/Projects/Awperative/Build/Kernel/net8.0/AwperativeKernel.deps.json
|
||||
/home/avery/Projects/Awperative/Build/Kernel/net8.0/AwperativeKernel.dll
|
||||
/home/avery/Projects/Awperative/Build/Kernel/net8.0/AwperativeKernel.pdb
|
||||
/home/avery/Projects/Awperative/AwperativeKernel/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.sourcelink.json
|
||||
/Users/averynorris/RiderProjects/AwperativeKernel/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.csproj.AssemblyReference.cache
|
||||
/Users/averynorris/RiderProjects/AwperativeKernel/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.GeneratedMSBuildEditorConfig.editorconfig
|
||||
/Users/averynorris/RiderProjects/AwperativeKernel/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.AssemblyInfoInputs.cache
|
||||
/Users/averynorris/RiderProjects/AwperativeKernel/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.AssemblyInfo.cs
|
||||
/Users/averynorris/RiderProjects/AwperativeKernel/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.csproj.CoreCompileInputs.cache
|
||||
/Users/averynorris/RiderProjects/AwperativeKernel/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.dll
|
||||
/Users/averynorris/RiderProjects/AwperativeKernel/AwperativeKernel/obj/Debug/net8.0/refint/AwperativeKernel.dll
|
||||
/Users/averynorris/RiderProjects/AwperativeKernel/AwperativeKernel/obj/Debug/net8.0/AwperativeKernel.pdb
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
||||
17713784696110717
|
||||
17725709888021566
|
||||
@@ -1 +1 @@
|
||||
17713784696110717
|
||||
17725709890112277
|
||||
Reference in New Issue
Block a user