Compare commits
58 Commits
bc1c76d746
...
developmen
Author | SHA1 | Date | |
---|---|---|---|
4bec7bce6e | |||
8d31372c24 | |||
a2e704916e | |||
c7d170fad9 | |||
9ccf7b754d | |||
e3d4899112 | |||
566c16d09c | |||
ae9d4f02ef | |||
e77772cbc2 | |||
4c542df401 | |||
28ca343b43 | |||
651b0614c4 | |||
f47488c6f1 | |||
6d159330a1 | |||
8e314f3269 | |||
f5a7077570 | |||
746d29fb7a | |||
cf68f6ca6f | |||
a4b83679b1 | |||
a31b39fd1d | |||
0205354202 | |||
949dfeb3d9 | |||
620ef911fa | |||
efed24de20 | |||
3912706d27 | |||
d78c42a653 | |||
b04e0f81cd | |||
65dcb0c564 | |||
3d183b21cd | |||
1644a751bb | |||
6631cae7b0 | |||
3452194941 | |||
11612ff0db | |||
63bc94c7a6 | |||
e00319d7ff | |||
11719440dc | |||
f246d68aa7 | |||
6e87c67096 | |||
b8217f2106 | |||
9824980cbf | |||
93a79cd075 | |||
f6e52abcc1 | |||
03232f72e8 | |||
37aca44e45 | |||
9f4d95a57b | |||
65eac57fce | |||
08311acc9a | |||
f8fbae6130 | |||
df06e8d134 | |||
ad365dc722 | |||
200e8ae7da | |||
65cfaf1b4a | |||
83b155fc5e | |||
7db56e7f3e | |||
42064875a0 | |||
41245c0c1c | |||
0e5cc8f898 | |||
c8bb991865 |
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -1,3 +1,3 @@
|
|||||||
[submodule "Engine.Serializers/YamlDotNet"]
|
[submodule "Engine.Integration/YamlDotNet"]
|
||||||
path = Engine.Serializers/YamlDotNet
|
path = Engine.Integration/YamlDotNet
|
||||||
url = git@github.com:Syntriax/YamlDotNet.git
|
url = git@github.com:Syntriax/YamlDotNet.git
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates the class implementing it has Assignable fields that are necessary for the engine to work properly.
|
/// Indicates the class implementing it has Assignable fields that are necessary for the engine to work properly.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IBehaviourController"/> field.
|
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IBehaviourController"/> field.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IEntity"/> field.
|
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IEntity"/> field.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IStateEnable"/> field.
|
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IStateEnable"/> field.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IUniverse"/> field.
|
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IUniverse"/> field.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IUniverseObject"/> field.
|
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IUniverseObject"/> field.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an entity which can be active or not.
|
/// Represents an entity which can be active or not.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a behaviour that any object in the engine that might use to interact with itself or other objects.
|
/// Represents a behaviour that any object in the engine that might use to interact with itself or other objects.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public interface IBehaviour2D : IBehaviour
|
public interface IBehaviour2D : IBehaviour
|
||||||
{
|
{
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a collector for the class type of <typeparamref name="T"/>.
|
/// Represents a collector for the class type of <typeparamref name="T"/>.
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a controller for managing <see cref="IBehaviour"/>s. Connected to an <see cref="IUniverseObject"/>.
|
/// Represents a controller for managing <see cref="IBehaviour"/>s. Connected to an <see cref="IUniverseObject"/>.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a 2D camera in the engine.
|
/// Represents a 2D camera in the engine.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public interface ICoroutineYield
|
public interface ICoroutineYield
|
||||||
{
|
{
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a basic entity in the engine.
|
/// Represents a basic entity in the engine.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an entity that can be initialized and finalized. This information is useful for objects we know that are not in use and can be either recycled or dropped for garbage collection.
|
/// Represents an entity that can be initialized and finalized. This information is useful for objects we know that are not in use and can be either recycled or dropped for garbage collection.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an entity with a name.
|
/// Represents an entity with a name.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an entity with an enable state that can be toggled.
|
/// Represents an entity with an enable state that can be toggled.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents the transformation properties of an object such as position, scale, and rotation in 2D space.
|
/// Represents the transformation properties of an object such as position, scale, and rotation in 2D space.
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a universe responsible for managing <see cref="IUniverseObject"/>s.
|
/// Represents a universe responsible for managing <see cref="IUniverseObject"/>s.
|
||||||
@@ -37,11 +37,21 @@ public interface IUniverse : IEntity, IEnumerable<IUniverseObject>
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Event<IUniverse> OnPostDraw { get; }
|
Event<IUniverse> OnPostDraw { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event triggered when a <see cref="IUniverseObject"/> is about to be registered to the <see cref="IUniverse"/>.
|
||||||
|
/// </summary>
|
||||||
|
Event<IUniverse, UniverseObjectRegisteredArguments> OnPreUniverseObjectRegistered { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event triggered when a <see cref="IUniverseObject"/> is registered to the <see cref="IUniverse"/>.
|
/// Event triggered when a <see cref="IUniverseObject"/> is registered to the <see cref="IUniverse"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Event<IUniverse, UniverseObjectRegisteredArguments> OnUniverseObjectRegistered { get; }
|
Event<IUniverse, UniverseObjectRegisteredArguments> OnUniverseObjectRegistered { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event triggered when a <see cref="IUniverseObject"/> is about to be unregistered from the <see cref="IUniverse"/>.
|
||||||
|
/// </summary>
|
||||||
|
Event<IUniverse, UniverseObjectUnRegisteredArguments> OnPreUniverseObjectUnRegistered { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event triggered when a <see cref="IUniverseObject"/> is unregistered from the <see cref="IUniverse"/>.
|
/// Event triggered when a <see cref="IUniverseObject"/> is unregistered from the <see cref="IUniverse"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an <see cref="IEntity"/> that can enter and exit a universe within the <see cref="IUniverse"/> system.
|
/// Represents an <see cref="IEntity"/> that can enter and exit a universe within the <see cref="IUniverse"/> system.
|
||||||
/// This interface allows for tracking the object's presence in the universe and provides events
|
/// This interface allows for tracking the object's presence in the universe and provides events
|
||||||
/// for notifying when the see enters or exits the universe.
|
/// for notifying when the see enters or exits the universe.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IUniverseObject : IEntity, IActive, INameable, IHasBehaviourController, IEnumerable<IUniverseObject>
|
public interface IUniverseObject : IEntity, IActive, INameable, IHasBehaviourController
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event triggered when the <see cref="IUniverseObject"/> enters the universe.
|
/// Event triggered when the <see cref="IUniverseObject"/> enters the universe.
|
||||||
@@ -47,7 +47,7 @@ public interface IUniverseObject : IEntity, IActive, INameable, IHasBehaviourCon
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The parent <see cref="IUniverseObject"/> of the <see cref="IUniverseObject"/>.
|
/// The parent <see cref="IUniverseObject"/> of the <see cref="IUniverseObject"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IUniverseObject? Parent { get; }
|
IUniverseObject? Parent { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="IUniverseObject"/>s that have this <see cref="IUniverseObject"/> as their <see cref="Parent"/>.
|
/// The <see cref="IUniverseObject"/>s that have this <see cref="IUniverseObject"/> as their <see cref="Parent"/>.
|
||||||
@@ -75,12 +75,6 @@ public interface IUniverseObject : IEntity, IActive, INameable, IHasBehaviourCon
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
internal bool ExitUniverse();
|
internal bool ExitUniverse();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the parent <see cref="IUniverseObject"/> of this <see cref="IUniverseObject"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="universeObject">The parent <see cref="IUniverseObject"/> to set.</param>
|
|
||||||
void SetParent(IUniverseObject? universeObject);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a child <see cref="IUniverseObject"/> to this <see cref="IUniverseObject"/>.
|
/// Adds a child <see cref="IUniverseObject"/> to this <see cref="IUniverseObject"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -1,67 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
|
||||||
|
|
||||||
public class ActiveBehaviourCollectorSorted<T> : ActiveBehaviourCollector<T> where T : class, IBehaviour
|
|
||||||
{
|
|
||||||
private readonly Event<IBehaviour, IBehaviour.PriorityChangedArguments>.EventHandler delegateOnPriorityChanged = null!;
|
|
||||||
|
|
||||||
private IComparer<T>? _sortBy = null;
|
|
||||||
public IComparer<T>? SortBy
|
|
||||||
{
|
|
||||||
get => _sortBy;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_sortBy = value;
|
|
||||||
|
|
||||||
if (value is not null)
|
|
||||||
activeBehaviours.Sort(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void AddBehaviour(T behaviour)
|
|
||||||
{
|
|
||||||
if (SortBy is null)
|
|
||||||
{
|
|
||||||
activeBehaviours.Add(behaviour);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int insertionIndex = activeBehaviours.BinarySearch(behaviour, SortBy);
|
|
||||||
|
|
||||||
if (insertionIndex < 0)
|
|
||||||
insertionIndex = ~insertionIndex;
|
|
||||||
|
|
||||||
activeBehaviours.Insert(insertionIndex, behaviour);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnBehaviourAdd(IBehaviour behaviour)
|
|
||||||
{
|
|
||||||
behaviour.OnPriorityChanged.AddListener(delegateOnPriorityChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnBehaviourRemove(IBehaviour behaviour)
|
|
||||||
{
|
|
||||||
behaviour.OnPriorityChanged.RemoveListener(delegateOnPriorityChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPriorityChanged(IBehaviour sender, IBehaviour.PriorityChangedArguments args)
|
|
||||||
{
|
|
||||||
T behaviour = (T)sender;
|
|
||||||
activeBehaviours.Remove(behaviour);
|
|
||||||
AddBehaviour(behaviour);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActiveBehaviourCollectorSorted()
|
|
||||||
{
|
|
||||||
delegateOnPriorityChanged = OnPriorityChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActiveBehaviourCollectorSorted(IUniverse universe, Comparison<T> sortBy) : base(universe)
|
|
||||||
{
|
|
||||||
delegateOnPriorityChanged = OnPriorityChanged;
|
|
||||||
|
|
||||||
SortBy = Comparer<T>.Create(sortBy);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public abstract class BaseEntity : IEntity
|
public abstract class BaseEntity : IEntity
|
||||||
{
|
{
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public abstract class Behaviour : BehaviourBase
|
public abstract class Behaviour : BehaviourBase
|
||||||
{
|
{
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public abstract class Behaviour2D : Behaviour, IBehaviour2D
|
public abstract class Behaviour2D : Behaviour, IBehaviour2D
|
||||||
{
|
{
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
[System.Diagnostics.DebuggerDisplay("{GetType().Name, nq}, Priority: {Priority}, Initialized: {Initialized}")]
|
[System.Diagnostics.DebuggerDisplay("{GetType().Name, nq}, Priority: {Priority}, Initialized: {Initialized}")]
|
||||||
public abstract class BehaviourBase : BaseEntity, IBehaviour
|
public abstract class BehaviourBase : BaseEntity, IBehaviour
|
||||||
@@ -44,6 +44,7 @@ public abstract class BehaviourBase : BaseEntity, IBehaviour
|
|||||||
_behaviourController = behaviourController;
|
_behaviourController = behaviourController;
|
||||||
OnAssign(behaviourController);
|
OnAssign(behaviourController);
|
||||||
behaviourController.OnUniverseObjectAssigned.AddListener(delegateOnUniverseObjectAssigned);
|
behaviourController.OnUniverseObjectAssigned.AddListener(delegateOnUniverseObjectAssigned);
|
||||||
|
behaviourController.StateEnable.OnEnabledChanged.AddListener(delegateOnStateEnabledChanged);
|
||||||
if (behaviourController.UniverseObject is not null)
|
if (behaviourController.UniverseObject is not null)
|
||||||
OnUniverseObjectAssigned(behaviourController);
|
OnUniverseObjectAssigned(behaviourController);
|
||||||
OnBehaviourControllerAssigned?.Invoke(this);
|
OnBehaviourControllerAssigned?.Invoke(this);
|
||||||
@@ -68,6 +69,7 @@ public abstract class BehaviourBase : BaseEntity, IBehaviour
|
|||||||
BehaviourController.UniverseObject.OnActiveChanged.RemoveListener(delegateOnUniverseObjectActiveChanged);
|
BehaviourController.UniverseObject.OnActiveChanged.RemoveListener(delegateOnUniverseObjectActiveChanged);
|
||||||
StateEnable.OnEnabledChanged.RemoveListener(delegateOnStateEnabledChanged);
|
StateEnable.OnEnabledChanged.RemoveListener(delegateOnStateEnabledChanged);
|
||||||
BehaviourController.OnUniverseObjectAssigned.RemoveListener(delegateOnUniverseObjectAssigned);
|
BehaviourController.OnUniverseObjectAssigned.RemoveListener(delegateOnUniverseObjectAssigned);
|
||||||
|
BehaviourController.StateEnable.OnEnabledChanged.RemoveListener(delegateOnStateEnabledChanged);
|
||||||
base.UnassignInternal();
|
base.UnassignInternal();
|
||||||
_behaviourController = null!;
|
_behaviourController = null!;
|
||||||
}
|
}
|
||||||
@@ -76,6 +78,8 @@ public abstract class BehaviourBase : BaseEntity, IBehaviour
|
|||||||
{
|
{
|
||||||
Debug.Assert.AssertBehaviourControllerAssigned(this);
|
Debug.Assert.AssertBehaviourControllerAssigned(this);
|
||||||
Debug.Assert.AssertStateEnableAssigned(this);
|
Debug.Assert.AssertStateEnableAssigned(this);
|
||||||
|
|
||||||
|
UpdateActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStateEnabledChanged(IStateEnable sender, IStateEnable.EnabledChangedArguments args) => UpdateActive();
|
private void OnStateEnabledChanged(IStateEnable sender, IStateEnable.EnabledChangedArguments args) => UpdateActive();
|
||||||
@@ -84,7 +88,7 @@ public abstract class BehaviourBase : BaseEntity, IBehaviour
|
|||||||
private void UpdateActive()
|
private void UpdateActive()
|
||||||
{
|
{
|
||||||
bool previousActive = IsActive;
|
bool previousActive = IsActive;
|
||||||
_isActive = StateEnable.Enabled && _behaviourController.UniverseObject.IsActive;
|
_isActive = StateEnable.Enabled && _behaviourController.StateEnable.Enabled && _behaviourController.UniverseObject.IsActive;
|
||||||
|
|
||||||
if (previousActive != IsActive)
|
if (previousActive != IsActive)
|
||||||
OnActiveChanged?.Invoke(this, new(previousActive));
|
OnActiveChanged?.Invoke(this, new(previousActive));
|
||||||
|
@@ -1,67 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
|
||||||
|
|
||||||
public class BehaviourCollectorSorted<T> : BehaviourCollector<T> where T : class
|
|
||||||
{
|
|
||||||
private readonly Event<IBehaviour, IBehaviour.PriorityChangedArguments>.EventHandler delegateOnPriorityChanged = null!;
|
|
||||||
|
|
||||||
private IComparer<T>? _sortBy = null;
|
|
||||||
public IComparer<T>? SortBy
|
|
||||||
{
|
|
||||||
get => _sortBy;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_sortBy = value;
|
|
||||||
|
|
||||||
if (value is not null)
|
|
||||||
behaviours.Sort(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void AddBehaviour(T behaviour)
|
|
||||||
{
|
|
||||||
if (SortBy is null)
|
|
||||||
{
|
|
||||||
behaviours.Add(behaviour);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int insertionIndex = behaviours.BinarySearch(behaviour, SortBy);
|
|
||||||
|
|
||||||
if (insertionIndex < 0)
|
|
||||||
insertionIndex = ~insertionIndex;
|
|
||||||
|
|
||||||
behaviours.Insert(insertionIndex, behaviour);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnBehaviourAdd(IBehaviour behaviour)
|
|
||||||
{
|
|
||||||
behaviour.OnPriorityChanged.AddListener(delegateOnPriorityChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnBehaviourRemove(IBehaviour behaviour)
|
|
||||||
{
|
|
||||||
behaviour.OnPriorityChanged.RemoveListener(delegateOnPriorityChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPriorityChanged(IBehaviour sender, IBehaviour.PriorityChangedArguments args)
|
|
||||||
{
|
|
||||||
T behaviour = (T)sender;
|
|
||||||
behaviours.Remove(behaviour);
|
|
||||||
AddBehaviour(behaviour);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BehaviourCollectorSorted()
|
|
||||||
{
|
|
||||||
delegateOnPriorityChanged = OnPriorityChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BehaviourCollectorSorted(IUniverse universe, Comparison<T> sortBy) : base(universe)
|
|
||||||
{
|
|
||||||
delegateOnPriorityChanged = OnPriorityChanged;
|
|
||||||
|
|
||||||
SortBy = Comparer<T>.Create(sortBy);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
[System.Diagnostics.DebuggerDisplay("Behaviour Count: {behaviours.Count}")]
|
[System.Diagnostics.DebuggerDisplay("Behaviour Count: {behaviours.Count}")]
|
||||||
public class BehaviourController : BaseEntity, IBehaviourController
|
public class BehaviourController : BaseEntity, IBehaviourController
|
||||||
@@ -10,7 +10,7 @@ public class BehaviourController : BaseEntity, IBehaviourController
|
|||||||
public Event<IBehaviourController, IBehaviourController.BehaviourRemovedArguments> OnBehaviourRemoved { get; } = new();
|
public Event<IBehaviourController, IBehaviourController.BehaviourRemovedArguments> OnBehaviourRemoved { get; } = new();
|
||||||
public Event<IHasUniverseObject> OnUniverseObjectAssigned { get; } = new();
|
public Event<IHasUniverseObject> OnUniverseObjectAssigned { get; } = new();
|
||||||
|
|
||||||
private readonly List<IBehaviour> behaviours = new(Constants.BEHAVIOURS_SIZE_INITIAL);
|
private readonly FastList<IBehaviour> behaviours = new(Constants.BEHAVIOURS_SIZE_INITIAL);
|
||||||
|
|
||||||
private IUniverseObject _universeObject = null!;
|
private IUniverseObject _universeObject = null!;
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ public class BehaviourController : BaseEntity, IBehaviourController
|
|||||||
|
|
||||||
public void RemoveBehaviour<T>(bool removeAll = false) where T : class, IBehaviour
|
public void RemoveBehaviour<T>(bool removeAll = false) where T : class, IBehaviour
|
||||||
{
|
{
|
||||||
for (int i = behaviours.Count; i >= 0; i--)
|
for (int i = behaviours.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
if (behaviours[i] is not T behaviour)
|
if (behaviours[i] is not T behaviour)
|
||||||
continue;
|
continue;
|
||||||
|
16
Engine.Core/Collectors/ActiveBehaviourCollector.cs
Normal file
16
Engine.Core/Collectors/ActiveBehaviourCollector.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Engine.Core;
|
||||||
|
|
||||||
|
public class ActiveBehaviourCollector<T> : ActiveBehaviourCollectorBase<T> where T : class, IBehaviour
|
||||||
|
{
|
||||||
|
protected readonly FastList<T> activeBehaviours = new(32);
|
||||||
|
public override T this[Index index] => activeBehaviours[index];
|
||||||
|
public override int Count => activeBehaviours.Count;
|
||||||
|
|
||||||
|
public ActiveBehaviourCollector() { }
|
||||||
|
public ActiveBehaviourCollector(IUniverse universe) : base(universe) { }
|
||||||
|
|
||||||
|
protected override void AddBehaviour(T behaviour) => activeBehaviours.Add(behaviour);
|
||||||
|
protected override bool RemoveBehaviour(T tBehaviour) => activeBehaviours.Remove(tBehaviour);
|
||||||
|
}
|
@@ -1,14 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : class, IBehaviour
|
public abstract class ActiveBehaviourCollectorBase<T> : IBehaviourCollector<T> where T : class, IBehaviour
|
||||||
{
|
{
|
||||||
public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourCollectedArguments> OnCollected { get; } = new();
|
protected readonly Dictionary<IActive, T> monitoringActiveToBehaviour = new(32);
|
||||||
public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourRemovedArguments> OnRemoved { get; } = new();
|
protected readonly FastList<T> monitoringBehaviours = new(32);
|
||||||
public Event<IHasUniverse> OnUniverseAssigned { get; } = new();
|
|
||||||
public Event<IAssignable>? OnUnassigned { get; } = new();
|
|
||||||
|
|
||||||
private readonly Event<IBehaviourController, IBehaviourController.BehaviourAddedArguments>.EventHandler delegateOnBehaviourAdded = null!;
|
private readonly Event<IBehaviourController, IBehaviourController.BehaviourAddedArguments>.EventHandler delegateOnBehaviourAdded = null!;
|
||||||
private readonly Event<IBehaviourController, IBehaviourController.BehaviourRemovedArguments>.EventHandler delegateOnBehaviourRemoved = null!;
|
private readonly Event<IBehaviourController, IBehaviourController.BehaviourRemovedArguments>.EventHandler delegateOnBehaviourRemoved = null!;
|
||||||
@@ -16,80 +14,16 @@ public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : clas
|
|||||||
private readonly Event<IUniverse, IUniverse.UniverseObjectRegisteredArguments>.EventHandler delegateOnUniverseObjectRegistered = null!;
|
private readonly Event<IUniverse, IUniverse.UniverseObjectRegisteredArguments>.EventHandler delegateOnUniverseObjectRegistered = null!;
|
||||||
private readonly Event<IUniverse, IUniverse.UniverseObjectUnRegisteredArguments>.EventHandler delegateOnUniverseObjectUnregistered = null!;
|
private readonly Event<IUniverse, IUniverse.UniverseObjectUnRegisteredArguments>.EventHandler delegateOnUniverseObjectUnregistered = null!;
|
||||||
|
|
||||||
private readonly List<T> monitoringBehaviours = new(32);
|
public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourCollectedArguments> OnCollected { get; } = new();
|
||||||
protected readonly List<T> activeBehaviours = new(32);
|
public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourRemovedArguments> OnRemoved { get; } = new();
|
||||||
protected readonly Dictionary<IActive, T> monitoringActiveToBehaviour = new(32);
|
public Event<IHasUniverse> OnUniverseAssigned { get; } = new();
|
||||||
|
public Event<IAssignable>? OnUnassigned { get; } = new();
|
||||||
|
|
||||||
|
public abstract int Count { get; }
|
||||||
|
|
||||||
|
public abstract T this[Index index] { get; }
|
||||||
public IUniverse Universe { get; private set; } = null!;
|
public IUniverse Universe { get; private set; } = null!;
|
||||||
|
|
||||||
private void OnUniverseObjectRegistered(IUniverse manager, IUniverse.UniverseObjectRegisteredArguments args)
|
|
||||||
{
|
|
||||||
IUniverseObject universeObject = args.UniverseObjectRegistered;
|
|
||||||
|
|
||||||
universeObject.BehaviourController.OnBehaviourAdded.AddListener(delegateOnBehaviourAdded);
|
|
||||||
universeObject.BehaviourController.OnBehaviourRemoved.AddListener(delegateOnBehaviourRemoved);
|
|
||||||
|
|
||||||
for (int i = 0; i < universeObject.BehaviourController.Count; i++)
|
|
||||||
OnBehaviourAdded(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnUniverseObjectUnregistered(IUniverse manager, IUniverse.UniverseObjectUnRegisteredArguments args)
|
|
||||||
{
|
|
||||||
IUniverseObject universeObject = args.UniverseObjectUnregistered;
|
|
||||||
|
|
||||||
universeObject.BehaviourController.OnBehaviourAdded.RemoveListener(delegateOnBehaviourAdded);
|
|
||||||
universeObject.BehaviourController.OnBehaviourRemoved.RemoveListener(delegateOnBehaviourRemoved);
|
|
||||||
|
|
||||||
for (int i = 0; i < universeObject.BehaviourController.Count; i++)
|
|
||||||
OnBehaviourRemoved(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnBehaviourAdd(IBehaviour behaviour) { }
|
|
||||||
private void OnBehaviourAdded(IBehaviourController controller, IBehaviourController.BehaviourAddedArguments args)
|
|
||||||
{
|
|
||||||
if (args.BehaviourAdded is not T tBehaviour)
|
|
||||||
return;
|
|
||||||
|
|
||||||
monitoringBehaviours.Add(tBehaviour);
|
|
||||||
monitoringActiveToBehaviour.Add(tBehaviour, tBehaviour);
|
|
||||||
tBehaviour.OnActiveChanged.AddListener(delegateOnBehaviourStateChanged);
|
|
||||||
OnBehaviourStateChanged(tBehaviour, new(!tBehaviour.IsActive));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void AddBehaviour(T behaviour) => activeBehaviours.Add(behaviour);
|
|
||||||
private void OnBehaviourStateChanged(IActive sender, IActive.ActiveChangedArguments args)
|
|
||||||
{
|
|
||||||
T behaviour = monitoringActiveToBehaviour[sender];
|
|
||||||
if (sender.IsActive)
|
|
||||||
{
|
|
||||||
AddBehaviour(behaviour);
|
|
||||||
OnBehaviourAdd(behaviour);
|
|
||||||
OnCollected?.Invoke(this, new(behaviour));
|
|
||||||
}
|
|
||||||
else if (activeBehaviours.Remove(behaviour))
|
|
||||||
{
|
|
||||||
OnBehaviourRemove(behaviour);
|
|
||||||
OnRemoved?.Invoke(this, new(behaviour));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnBehaviourRemove(IBehaviour behaviour) { }
|
|
||||||
private void OnBehaviourRemoved(IBehaviourController controller, IBehaviourController.BehaviourRemovedArguments args)
|
|
||||||
{
|
|
||||||
if (args.BehaviourRemoved is not T tBehaviour)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!monitoringBehaviours.Remove(tBehaviour) || !monitoringActiveToBehaviour.Remove(tBehaviour))
|
|
||||||
return;
|
|
||||||
|
|
||||||
tBehaviour.OnActiveChanged.RemoveListener(delegateOnBehaviourStateChanged);
|
|
||||||
if (activeBehaviours.Remove(tBehaviour))
|
|
||||||
{
|
|
||||||
OnBehaviourRemove(tBehaviour);
|
|
||||||
OnRemoved?.Invoke(this, new(tBehaviour));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Assign(IUniverse universe)
|
public bool Assign(IUniverse universe)
|
||||||
{
|
{
|
||||||
if (Universe is not null)
|
if (Universe is not null)
|
||||||
@@ -123,10 +57,75 @@ public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : clas
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Count => activeBehaviours.Count;
|
protected abstract void AddBehaviour(T behaviour);
|
||||||
public T this[Index index] => activeBehaviours[index];
|
protected virtual void OnBehaviourAdd(IBehaviour behaviour) { }
|
||||||
|
private void OnBehaviourAdded(IBehaviourController controller, IBehaviourController.BehaviourAddedArguments args)
|
||||||
|
{
|
||||||
|
if (args.BehaviourAdded is not T tBehaviour)
|
||||||
|
return;
|
||||||
|
|
||||||
public ActiveBehaviourCollector()
|
monitoringBehaviours.Add(tBehaviour);
|
||||||
|
monitoringActiveToBehaviour.Add(tBehaviour, tBehaviour);
|
||||||
|
tBehaviour.OnActiveChanged.AddListener(delegateOnBehaviourStateChanged);
|
||||||
|
OnBehaviourStateChanged(tBehaviour, new(!tBehaviour.IsActive));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract bool RemoveBehaviour(T behaviour);
|
||||||
|
protected virtual void OnBehaviourRemove(IBehaviour behaviour) { }
|
||||||
|
private void OnBehaviourRemoved(IBehaviourController controller, IBehaviourController.BehaviourRemovedArguments args)
|
||||||
|
{
|
||||||
|
if (args.BehaviourRemoved is not T tBehaviour)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!monitoringBehaviours.Remove(tBehaviour) || !monitoringActiveToBehaviour.Remove(tBehaviour))
|
||||||
|
return;
|
||||||
|
|
||||||
|
tBehaviour.OnActiveChanged.RemoveListener(delegateOnBehaviourStateChanged);
|
||||||
|
if (!RemoveBehaviour(tBehaviour))
|
||||||
|
return;
|
||||||
|
|
||||||
|
OnBehaviourRemove(tBehaviour);
|
||||||
|
OnRemoved?.Invoke(this, new(tBehaviour));
|
||||||
|
}
|
||||||
|
private void OnBehaviourStateChanged(IActive sender, IActive.ActiveChangedArguments args)
|
||||||
|
{
|
||||||
|
T behaviour = monitoringActiveToBehaviour[sender];
|
||||||
|
if (sender.IsActive)
|
||||||
|
{
|
||||||
|
AddBehaviour(behaviour);
|
||||||
|
OnBehaviourAdd(behaviour);
|
||||||
|
OnCollected?.Invoke(this, new(behaviour));
|
||||||
|
}
|
||||||
|
else if (RemoveBehaviour(behaviour))
|
||||||
|
{
|
||||||
|
OnBehaviourRemove(behaviour);
|
||||||
|
OnRemoved?.Invoke(this, new(behaviour));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUniverseObjectRegistered(IUniverse manager, IUniverse.UniverseObjectRegisteredArguments args)
|
||||||
|
{
|
||||||
|
IUniverseObject universeObject = args.UniverseObjectRegistered;
|
||||||
|
|
||||||
|
universeObject.BehaviourController.OnBehaviourAdded.AddListener(delegateOnBehaviourAdded);
|
||||||
|
universeObject.BehaviourController.OnBehaviourRemoved.AddListener(delegateOnBehaviourRemoved);
|
||||||
|
|
||||||
|
for (int i = 0; i < universeObject.BehaviourController.Count; i++)
|
||||||
|
OnBehaviourAdded(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUniverseObjectUnregistered(IUniverse manager, IUniverse.UniverseObjectUnRegisteredArguments args)
|
||||||
|
{
|
||||||
|
IUniverseObject universeObject = args.UniverseObjectUnregistered;
|
||||||
|
|
||||||
|
universeObject.BehaviourController.OnBehaviourAdded.RemoveListener(delegateOnBehaviourAdded);
|
||||||
|
universeObject.BehaviourController.OnBehaviourRemoved.RemoveListener(delegateOnBehaviourRemoved);
|
||||||
|
|
||||||
|
for (int i = 0; i < universeObject.BehaviourController.Count; i++)
|
||||||
|
OnBehaviourRemoved(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActiveBehaviourCollectorBase()
|
||||||
{
|
{
|
||||||
delegateOnBehaviourAdded = OnBehaviourAdded;
|
delegateOnBehaviourAdded = OnBehaviourAdded;
|
||||||
delegateOnBehaviourRemoved = OnBehaviourRemoved;
|
delegateOnBehaviourRemoved = OnBehaviourRemoved;
|
||||||
@@ -135,7 +134,7 @@ public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : clas
|
|||||||
delegateOnUniverseObjectUnregistered = OnUniverseObjectUnregistered;
|
delegateOnUniverseObjectUnregistered = OnUniverseObjectUnregistered;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActiveBehaviourCollector(IUniverse universe)
|
public ActiveBehaviourCollectorBase(IUniverse universe)
|
||||||
{
|
{
|
||||||
delegateOnBehaviourAdded = OnBehaviourAdded;
|
delegateOnBehaviourAdded = OnBehaviourAdded;
|
||||||
delegateOnBehaviourRemoved = OnBehaviourRemoved;
|
delegateOnBehaviourRemoved = OnBehaviourRemoved;
|
104
Engine.Core/Collectors/ActiveBehaviourCollectorOrdered.cs
Normal file
104
Engine.Core/Collectors/ActiveBehaviourCollectorOrdered.cs
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Engine.Core;
|
||||||
|
|
||||||
|
public class ActiveBehaviourCollectorOrdered<TIndex, TItem> : ActiveBehaviourCollector<TItem> where TItem : class, IBehaviour where TIndex : IComparable
|
||||||
|
{
|
||||||
|
private readonly Event<IBehaviour, IBehaviour.PriorityChangedArguments>.EventHandler delegateOnPriorityChanged = null!;
|
||||||
|
|
||||||
|
private readonly SortedDictionary<TIndex, FastList<TItem>> behaviours = null!;
|
||||||
|
|
||||||
|
private readonly Func<TItem, TIndex> getIndexFunc = null!;
|
||||||
|
private readonly IComparer<TIndex> sortBy = null!;
|
||||||
|
|
||||||
|
private int count = 0;
|
||||||
|
public override int Count => count;
|
||||||
|
|
||||||
|
public override TItem this[Index index]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int actualIndex = index.IsFromEnd
|
||||||
|
? count - index.Value
|
||||||
|
: index.Value;
|
||||||
|
|
||||||
|
if (actualIndex < 0 || actualIndex >= count)
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
|
||||||
|
int leftIndex = actualIndex;
|
||||||
|
foreach ((TIndex i, FastList<TItem> list) in behaviours)
|
||||||
|
{
|
||||||
|
if (leftIndex < list.Count)
|
||||||
|
return list[leftIndex];
|
||||||
|
leftIndex -= list.Count;
|
||||||
|
}
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool RemoveBehaviour(TItem tBehaviour)
|
||||||
|
{
|
||||||
|
TIndex index = getIndexFunc(tBehaviour);
|
||||||
|
if (!behaviours.TryGetValue(index, out FastList<TItem>? list))
|
||||||
|
throw new Exceptions.NotFoundException($"Index of '{index}' is not found in the collector");
|
||||||
|
|
||||||
|
if (!list.Remove(tBehaviour))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
count--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void AddBehaviour(TItem behaviour)
|
||||||
|
{
|
||||||
|
TIndex key = getIndexFunc(behaviour);
|
||||||
|
if (!behaviours.TryGetValue(key, out FastList<TItem>? list))
|
||||||
|
behaviours[key] = list = [];
|
||||||
|
|
||||||
|
count++;
|
||||||
|
list.Add(behaviour);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnBehaviourAdd(IBehaviour behaviour) => behaviour.OnPriorityChanged.AddListener(delegateOnPriorityChanged);
|
||||||
|
protected override void OnBehaviourRemove(IBehaviour behaviour) => behaviour.OnPriorityChanged.RemoveListener(delegateOnPriorityChanged);
|
||||||
|
|
||||||
|
private void OnPriorityChanged(IBehaviour sender, IBehaviour.PriorityChangedArguments args)
|
||||||
|
{
|
||||||
|
TItem behaviour = (TItem)sender;
|
||||||
|
RemoveBehaviour(behaviour);
|
||||||
|
AddBehaviour(behaviour);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActiveBehaviourCollectorOrdered(Func<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy)
|
||||||
|
{
|
||||||
|
delegateOnPriorityChanged = OnPriorityChanged;
|
||||||
|
this.getIndexFunc = getIndexFunc;
|
||||||
|
this.sortBy = Comparer<TIndex>.Create(sortBy);
|
||||||
|
behaviours = new(this.sortBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActiveBehaviourCollectorOrdered(IUniverse universe, Func<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy) : base(universe)
|
||||||
|
{
|
||||||
|
delegateOnPriorityChanged = OnPriorityChanged;
|
||||||
|
this.getIndexFunc = getIndexFunc;
|
||||||
|
this.sortBy = Comparer<TIndex>.Create(sortBy);
|
||||||
|
behaviours = new(this.sortBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActiveBehaviourCollectorOrdered(Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy)
|
||||||
|
{
|
||||||
|
this.getIndexFunc = getIndexFunc;
|
||||||
|
delegateOnPriorityChanged = OnPriorityChanged;
|
||||||
|
this.sortBy = sortBy;
|
||||||
|
behaviours = new(sortBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActiveBehaviourCollectorOrdered(IUniverse universe, Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy) : base(universe)
|
||||||
|
{
|
||||||
|
delegateOnPriorityChanged = OnPriorityChanged;
|
||||||
|
this.getIndexFunc = getIndexFunc;
|
||||||
|
this.sortBy = sortBy;
|
||||||
|
behaviours = new(sortBy);
|
||||||
|
}
|
||||||
|
}
|
17
Engine.Core/Collectors/BehaviourCollector.cs
Normal file
17
Engine.Core/Collectors/BehaviourCollector.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Engine.Core;
|
||||||
|
|
||||||
|
public class BehaviourCollector<T> : BehaviourCollectorBase<T> where T : class
|
||||||
|
{
|
||||||
|
protected readonly FastList<T> behaviours = new(32);
|
||||||
|
|
||||||
|
public override T this[Index index] => behaviours[index];
|
||||||
|
public override int Count => behaviours.Count;
|
||||||
|
|
||||||
|
protected override void AddBehaviour(T behaviour) => behaviours.Add(behaviour);
|
||||||
|
protected override bool RemoveBehaviour(T tBehaviour) => behaviours.Remove(tBehaviour);
|
||||||
|
|
||||||
|
public BehaviourCollector() { }
|
||||||
|
public BehaviourCollector(IUniverse universe) : base(universe) { }
|
||||||
|
}
|
@@ -1,24 +1,87 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
|
public abstract class BehaviourCollectorBase<T> : IBehaviourCollector<T> where T : class
|
||||||
{
|
{
|
||||||
public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourCollectedArguments> OnCollected { get; } = new();
|
|
||||||
public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourRemovedArguments> OnRemoved { get; } = new();
|
|
||||||
public Event<IHasUniverse> OnUniverseAssigned { get; } = new();
|
|
||||||
public Event<IAssignable>? OnUnassigned { get; } = new();
|
|
||||||
|
|
||||||
private readonly Event<IBehaviourController, IBehaviourController.BehaviourAddedArguments>.EventHandler delegateOnBehaviourAdded = null!;
|
private readonly Event<IBehaviourController, IBehaviourController.BehaviourAddedArguments>.EventHandler delegateOnBehaviourAdded = null!;
|
||||||
private readonly Event<IBehaviourController, IBehaviourController.BehaviourRemovedArguments>.EventHandler delegateOnBehaviourRemoved = null!;
|
private readonly Event<IBehaviourController, IBehaviourController.BehaviourRemovedArguments>.EventHandler delegateOnBehaviourRemoved = null!;
|
||||||
private readonly Event<IUniverse, IUniverse.UniverseObjectRegisteredArguments>.EventHandler delegateOnUniverseObjectRegistered = null!;
|
private readonly Event<IUniverse, IUniverse.UniverseObjectRegisteredArguments>.EventHandler delegateOnUniverseObjectRegistered = null!;
|
||||||
private readonly Event<IUniverse, IUniverse.UniverseObjectUnRegisteredArguments>.EventHandler delegateOnUniverseObjectUnregistered = null!;
|
private readonly Event<IUniverse, IUniverse.UniverseObjectUnRegisteredArguments>.EventHandler delegateOnUniverseObjectUnregistered = null!;
|
||||||
|
|
||||||
protected readonly List<T> behaviours = new(32);
|
public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourCollectedArguments> OnCollected { get; } = new();
|
||||||
|
public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourRemovedArguments> OnRemoved { get; } = new();
|
||||||
|
public Event<IHasUniverse> OnUniverseAssigned { get; } = new();
|
||||||
|
public Event<IAssignable>? OnUnassigned { get; } = new();
|
||||||
|
|
||||||
public IUniverse Universe { get; private set; } = null!;
|
public IUniverse Universe { get; private set; } = null!;
|
||||||
|
|
||||||
|
public abstract int Count { get; }
|
||||||
|
|
||||||
|
public abstract T this[Index index] { get; }
|
||||||
|
|
||||||
|
public bool Assign(IUniverse universe)
|
||||||
|
{
|
||||||
|
if (Universe is not null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (IUniverseObject universeObject in universe.UniverseObjects)
|
||||||
|
OnUniverseObjectRegistered(universe, new(universeObject));
|
||||||
|
|
||||||
|
universe.OnUniverseObjectRegistered.AddListener(delegateOnUniverseObjectRegistered);
|
||||||
|
universe.OnPreUniverseObjectUnRegistered.AddListener(delegateOnUniverseObjectUnregistered);
|
||||||
|
|
||||||
|
Universe = universe;
|
||||||
|
OnAssign(universe);
|
||||||
|
OnUniverseAssigned?.Invoke(this);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Unassign()
|
||||||
|
{
|
||||||
|
if (Universe is null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (IUniverseObject universeObject in Universe.UniverseObjects)
|
||||||
|
OnUniverseObjectUnregistered(Universe, new(universeObject));
|
||||||
|
|
||||||
|
Universe.OnUniverseObjectRegistered.RemoveListener(delegateOnUniverseObjectRegistered);
|
||||||
|
Universe.OnPreUniverseObjectUnRegistered.RemoveListener(delegateOnUniverseObjectUnregistered);
|
||||||
|
|
||||||
|
Universe = null!;
|
||||||
|
OnUnassigned?.Invoke(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnAssign(IUniverse universe) { }
|
||||||
|
|
||||||
|
protected abstract void AddBehaviour(T behaviour);
|
||||||
|
protected virtual void OnBehaviourAdd(IBehaviour behaviour) { }
|
||||||
|
private void OnBehaviourAdded(IBehaviourController controller, IBehaviourController.BehaviourAddedArguments args)
|
||||||
|
{
|
||||||
|
if (args.BehaviourAdded is not T tBehaviour)
|
||||||
|
return;
|
||||||
|
|
||||||
|
AddBehaviour(tBehaviour);
|
||||||
|
OnBehaviourAdd(args.BehaviourAdded);
|
||||||
|
OnCollected?.Invoke(this, new(tBehaviour));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract bool RemoveBehaviour(T tBehaviour);
|
||||||
|
protected virtual void OnBehaviourRemove(IBehaviour behaviour) { }
|
||||||
|
private void OnBehaviourRemoved(IBehaviourController controller, IBehaviourController.BehaviourRemovedArguments args)
|
||||||
|
{
|
||||||
|
if (args.BehaviourRemoved is not T tBehaviour)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!RemoveBehaviour(tBehaviour))
|
||||||
|
return;
|
||||||
|
|
||||||
|
OnBehaviourRemove(args.BehaviourRemoved);
|
||||||
|
OnRemoved?.Invoke(this, new(tBehaviour));
|
||||||
|
}
|
||||||
|
|
||||||
private void OnUniverseObjectRegistered(IUniverse manager, IUniverse.UniverseObjectRegisteredArguments args)
|
private void OnUniverseObjectRegistered(IUniverse manager, IUniverse.UniverseObjectRegisteredArguments args)
|
||||||
{
|
{
|
||||||
IUniverseObject universeObject = args.UniverseObjectRegistered;
|
IUniverseObject universeObject = args.UniverseObjectRegistered;
|
||||||
@@ -41,70 +104,7 @@ public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
|
|||||||
OnBehaviourRemoved(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
|
OnBehaviourRemoved(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void AddBehaviour(T behaviour) => behaviours.Add(behaviour);
|
public BehaviourCollectorBase()
|
||||||
protected virtual void OnBehaviourAdd(IBehaviour behaviour) { }
|
|
||||||
private void OnBehaviourAdded(IBehaviourController controller, IBehaviourController.BehaviourAddedArguments args)
|
|
||||||
{
|
|
||||||
if (args.BehaviourAdded is not T tBehaviour)
|
|
||||||
return;
|
|
||||||
|
|
||||||
AddBehaviour(tBehaviour);
|
|
||||||
OnBehaviourAdd(args.BehaviourAdded);
|
|
||||||
OnCollected?.Invoke(this, new(tBehaviour));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnBehaviourRemove(IBehaviour behaviour) { }
|
|
||||||
private void OnBehaviourRemoved(IBehaviourController controller, IBehaviourController.BehaviourRemovedArguments args)
|
|
||||||
{
|
|
||||||
if (args.BehaviourRemoved is not T tBehaviour)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!behaviours.Remove(tBehaviour))
|
|
||||||
return;
|
|
||||||
|
|
||||||
OnBehaviourRemove(args.BehaviourRemoved);
|
|
||||||
OnRemoved?.Invoke(this, new(tBehaviour));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnAssign(IUniverse universe) { }
|
|
||||||
public bool Assign(IUniverse universe)
|
|
||||||
{
|
|
||||||
if (Universe is not null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
foreach (IUniverseObject universeObject in universe.UniverseObjects)
|
|
||||||
OnUniverseObjectRegistered(universe, new(universeObject));
|
|
||||||
|
|
||||||
universe.OnUniverseObjectRegistered.AddListener(delegateOnUniverseObjectRegistered);
|
|
||||||
universe.OnUniverseObjectUnRegistered.AddListener(delegateOnUniverseObjectUnregistered);
|
|
||||||
|
|
||||||
Universe = universe;
|
|
||||||
OnAssign(universe);
|
|
||||||
OnUniverseAssigned?.Invoke(this);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Unassign()
|
|
||||||
{
|
|
||||||
if (Universe is null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
foreach (IUniverseObject universeObject in Universe.UniverseObjects)
|
|
||||||
OnUniverseObjectUnregistered(Universe, new(universeObject));
|
|
||||||
|
|
||||||
Universe.OnUniverseObjectRegistered.RemoveListener(delegateOnUniverseObjectRegistered);
|
|
||||||
Universe.OnUniverseObjectUnRegistered.RemoveListener(delegateOnUniverseObjectUnregistered);
|
|
||||||
|
|
||||||
Universe = null!;
|
|
||||||
OnUnassigned?.Invoke(this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Count => behaviours.Count;
|
|
||||||
public T this[Index index] => behaviours[index];
|
|
||||||
|
|
||||||
public BehaviourCollector()
|
|
||||||
{
|
{
|
||||||
delegateOnBehaviourAdded = OnBehaviourAdded;
|
delegateOnBehaviourAdded = OnBehaviourAdded;
|
||||||
delegateOnBehaviourRemoved = OnBehaviourRemoved;
|
delegateOnBehaviourRemoved = OnBehaviourRemoved;
|
||||||
@@ -112,7 +112,7 @@ public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
|
|||||||
delegateOnUniverseObjectUnregistered = OnUniverseObjectUnregistered;
|
delegateOnUniverseObjectUnregistered = OnUniverseObjectUnregistered;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BehaviourCollector(IUniverse universe)
|
public BehaviourCollectorBase(IUniverse universe)
|
||||||
{
|
{
|
||||||
delegateOnBehaviourAdded = OnBehaviourAdded;
|
delegateOnBehaviourAdded = OnBehaviourAdded;
|
||||||
delegateOnBehaviourRemoved = OnBehaviourRemoved;
|
delegateOnBehaviourRemoved = OnBehaviourRemoved;
|
104
Engine.Core/Collectors/BehaviourCollectorOrdered.cs
Normal file
104
Engine.Core/Collectors/BehaviourCollectorOrdered.cs
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Engine.Core;
|
||||||
|
|
||||||
|
public class BehaviourCollectorOrdered<TIndex, TItem> : BehaviourCollectorBase<TItem> where TItem : class where TIndex : IComparable
|
||||||
|
{
|
||||||
|
private readonly Event<IBehaviour, IBehaviour.PriorityChangedArguments>.EventHandler delegateOnPriorityChanged = null!;
|
||||||
|
|
||||||
|
private readonly SortedDictionary<TIndex, FastList<TItem>> behaviours = null!;
|
||||||
|
|
||||||
|
private readonly Func<TItem, TIndex> getIndexFunc = null!;
|
||||||
|
private readonly IComparer<TIndex> sortBy = null!;
|
||||||
|
|
||||||
|
private int count = 0;
|
||||||
|
public override int Count => count;
|
||||||
|
|
||||||
|
public override TItem this[Index index]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int actualIndex = index.IsFromEnd
|
||||||
|
? count - index.Value
|
||||||
|
: index.Value;
|
||||||
|
|
||||||
|
if (actualIndex < 0 || actualIndex >= count)
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
|
||||||
|
int leftIndex = actualIndex;
|
||||||
|
foreach ((TIndex i, FastList<TItem> list) in behaviours)
|
||||||
|
{
|
||||||
|
if (leftIndex < list.Count)
|
||||||
|
return list[leftIndex];
|
||||||
|
leftIndex -= list.Count;
|
||||||
|
}
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool RemoveBehaviour(TItem tBehaviour)
|
||||||
|
{
|
||||||
|
TIndex index = getIndexFunc(tBehaviour);
|
||||||
|
if (!behaviours.TryGetValue(index, out FastList<TItem>? list))
|
||||||
|
throw new Exceptions.NotFoundException($"Index of '{index}' is not found in the collector");
|
||||||
|
|
||||||
|
if (!list.Remove(tBehaviour))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
count--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void AddBehaviour(TItem behaviour)
|
||||||
|
{
|
||||||
|
TIndex key = getIndexFunc(behaviour);
|
||||||
|
if (!behaviours.TryGetValue(key, out FastList<TItem>? list))
|
||||||
|
behaviours[key] = list = [];
|
||||||
|
|
||||||
|
count++;
|
||||||
|
list.Add(behaviour);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnBehaviourAdd(IBehaviour behaviour) => behaviour.OnPriorityChanged.AddListener(delegateOnPriorityChanged);
|
||||||
|
protected override void OnBehaviourRemove(IBehaviour behaviour) => behaviour.OnPriorityChanged.RemoveListener(delegateOnPriorityChanged);
|
||||||
|
|
||||||
|
private void OnPriorityChanged(IBehaviour sender, IBehaviour.PriorityChangedArguments args)
|
||||||
|
{
|
||||||
|
TItem behaviour = (TItem)sender;
|
||||||
|
RemoveBehaviour(behaviour);
|
||||||
|
AddBehaviour(behaviour);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BehaviourCollectorOrdered(Func<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy)
|
||||||
|
{
|
||||||
|
delegateOnPriorityChanged = OnPriorityChanged;
|
||||||
|
this.getIndexFunc = getIndexFunc;
|
||||||
|
this.sortBy = Comparer<TIndex>.Create(sortBy);
|
||||||
|
behaviours = new(this.sortBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BehaviourCollectorOrdered(IUniverse universe, Func<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy) : base(universe)
|
||||||
|
{
|
||||||
|
delegateOnPriorityChanged = OnPriorityChanged;
|
||||||
|
this.getIndexFunc = getIndexFunc;
|
||||||
|
this.sortBy = Comparer<TIndex>.Create(sortBy);
|
||||||
|
behaviours = new(this.sortBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BehaviourCollectorOrdered(Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy)
|
||||||
|
{
|
||||||
|
this.getIndexFunc = getIndexFunc;
|
||||||
|
delegateOnPriorityChanged = OnPriorityChanged;
|
||||||
|
this.sortBy = sortBy;
|
||||||
|
behaviours = new(sortBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BehaviourCollectorOrdered(IUniverse universe, Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy) : base(universe)
|
||||||
|
{
|
||||||
|
delegateOnPriorityChanged = OnPriorityChanged;
|
||||||
|
this.getIndexFunc = getIndexFunc;
|
||||||
|
this.sortBy = sortBy;
|
||||||
|
behaviours = new(sortBy);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public class CoroutineManager : Behaviour, IUpdate
|
public class CoroutineManager : Behaviour, IUpdate
|
||||||
{
|
{
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public class CoroutineYield(Func<bool> condition) : ICoroutineYield
|
public class CoroutineYield(Func<bool> condition) : ICoroutineYield
|
||||||
{
|
{
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Debug;
|
namespace Engine.Core.Debug;
|
||||||
|
|
||||||
public static class Assert
|
public static class Assert
|
||||||
{
|
{
|
||||||
@@ -10,21 +10,21 @@ public static class Assert
|
|||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void AssertBehaviourControllerAssigned(IHasBehaviourController assignable)
|
public static void AssertBehaviourControllerAssigned(IHasBehaviourController assignable)
|
||||||
=> System.Diagnostics.Debug.Assert(assignable.BehaviourController is not null, $"{assignable.GetType().Name} must be initialized");
|
=> System.Diagnostics.Debug.Assert(assignable.BehaviourController is not null, $"{assignable.GetType().Name} must be assigned an {nameof(IBehaviourController)}");
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void AssertEntityAssigned(IHasEntity assignable)
|
public static void AssertEntityAssigned(IHasEntity assignable)
|
||||||
=> System.Diagnostics.Debug.Assert(assignable.Entity is not null, $"{assignable.GetType().Name} must be initialized");
|
=> System.Diagnostics.Debug.Assert(assignable.Entity is not null, $"{assignable.GetType().Name} must be assigned an {nameof(IEntity)}");
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void AssertUniverseAssigned(IHasUniverse assignable)
|
public static void AssertUniverseAssigned(IHasUniverse assignable)
|
||||||
=> System.Diagnostics.Debug.Assert(assignable.Universe is not null, $"{assignable.GetType().Name} must be initialized");
|
=> System.Diagnostics.Debug.Assert(assignable.Universe is not null, $"{assignable.GetType().Name} must be assigned an {nameof(IUniverse)}");
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void AssertUniverseObjectAssigned(IHasUniverseObject assignable)
|
public static void AssertUniverseObjectAssigned(IHasUniverseObject assignable)
|
||||||
=> System.Diagnostics.Debug.Assert(assignable.UniverseObject is not null, $"{assignable.GetType().Name} must be initialized");
|
=> System.Diagnostics.Debug.Assert(assignable.UniverseObject is not null, $"{assignable.GetType().Name} must be assigned an {nameof(IUniverseObject)}");
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void AssertStateEnableAssigned(IHasStateEnable assignable)
|
public static void AssertStateEnableAssigned(IHasStateEnable assignable)
|
||||||
=> System.Diagnostics.Debug.Assert(assignable.StateEnable is not null, $"{assignable.GetType().Name} must be initialized");
|
=> System.Diagnostics.Debug.Assert(assignable.StateEnable is not null, $"{assignable.GetType().Name} must be assigned an {nameof(IStateEnable)}");
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Debug;
|
namespace Engine.Core.Debug;
|
||||||
|
|
||||||
public class ConsoleLogger : LoggerBase
|
public class ConsoleLogger : LoggerBase
|
||||||
{
|
{
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Debug;
|
namespace Engine.Core.Debug;
|
||||||
|
|
||||||
public class FileLogger : LoggerBase
|
public class FileLogger : LoggerBase
|
||||||
{
|
{
|
||||||
@@ -14,6 +14,9 @@ public class FileLogger : LoggerBase
|
|||||||
|
|
||||||
public FileLogger(string filePath)
|
public FileLogger(string filePath)
|
||||||
{
|
{
|
||||||
|
if (!filePath.EndsWith(".log"))
|
||||||
|
filePath += ".log";
|
||||||
|
|
||||||
FilePath = filePath;
|
FilePath = filePath;
|
||||||
|
|
||||||
bool isRelativePath = Path.GetFullPath(filePath).CompareTo(filePath) != 0;
|
bool isRelativePath = Path.GetFullPath(filePath).CompareTo(filePath) != 0;
|
||||||
|
@@ -1,13 +1,16 @@
|
|||||||
namespace Syntriax.Engine.Core.Debug;
|
namespace Engine.Core.Debug;
|
||||||
|
|
||||||
public interface ILogger
|
public interface ILogger
|
||||||
{
|
{
|
||||||
|
static ILogger Shared { get; set; } = new ConsoleLogger();
|
||||||
|
|
||||||
Level FilterLevel { get; set; }
|
Level FilterLevel { get; set; }
|
||||||
|
|
||||||
void Log(string message, Level level = Level.Info, bool force = false);
|
void Log(string message, Level level = Level.Info, bool force = false);
|
||||||
|
|
||||||
enum Level
|
enum Level
|
||||||
{
|
{
|
||||||
|
Trace,
|
||||||
Info,
|
Info,
|
||||||
Warning,
|
Warning,
|
||||||
Error,
|
Error,
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Debug;
|
namespace Engine.Core.Debug;
|
||||||
|
|
||||||
public abstract class LoggerBase : ILogger
|
public abstract class LoggerBase : ILogger
|
||||||
{
|
{
|
||||||
public ILogger.Level FilterLevel { get; set; } = ILogger.Level.Info;
|
public ILogger.Level FilterLevel { get; set; } = ILogger.Level.Trace;
|
||||||
|
|
||||||
public void Log(string message, ILogger.Level level = ILogger.Level.Info, bool force = false)
|
public void Log(string message, ILogger.Level level = ILogger.Level.Info, bool force = false)
|
||||||
{
|
{
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
namespace Syntriax.Engine.Core.Debug;
|
namespace Engine.Core.Debug;
|
||||||
|
|
||||||
public class LoggerContainer : Behaviour, ILogger
|
public class LoggerContainer : Behaviour, ILogger
|
||||||
{
|
{
|
||||||
public ILogger Logger { get; set; } = new ConsoleLogger();
|
public ILogger Logger { get; set; } = ILogger.Shared;
|
||||||
|
|
||||||
public ILogger.Level FilterLevel { get => Logger.FilterLevel; set => Logger.FilterLevel = value; }
|
public ILogger.Level FilterLevel { get => Logger.FilterLevel; set => Logger.FilterLevel = value; }
|
||||||
public void Log(string message, ILogger.Level level = ILogger.Level.Info, bool force = false) => Logger.Log(message, level, force);
|
public void Log(string message, ILogger.Level level = ILogger.Level.Info, bool force = false) => Logger.Log(message, level, force);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Debug;
|
namespace Engine.Core.Debug;
|
||||||
|
|
||||||
public static class LoggerExtensions
|
public static class LoggerExtensions
|
||||||
{
|
{
|
||||||
@@ -16,13 +16,21 @@ public static class LoggerExtensions
|
|||||||
public static void LogError<T>(this ILogger logger, T caller, string message, bool force = false)
|
public static void LogError<T>(this ILogger logger, T caller, string message, bool force = false)
|
||||||
{
|
{
|
||||||
Log(logger, caller, message, ILogger.Level.Error, force);
|
Log(logger, caller, message, ILogger.Level.Error, force);
|
||||||
Log(logger, caller, $"{nameof(StackTrace)}:{Environment.NewLine}{new StackTrace()}");
|
LogTrace(logger, caller, new StackTrace(), force);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void LogException<T>(this ILogger logger, T caller, Exception exception, bool force = false)
|
public static void LogException<T>(this ILogger logger, T caller, Exception exception, bool force = false)
|
||||||
{
|
{
|
||||||
|
Log(logger, caller, $"Exception of type {exception.GetType().Name} occured", ILogger.Level.Error, force);
|
||||||
Log(logger, caller, $"Message: {exception.Message}", ILogger.Level.Error, force);
|
Log(logger, caller, $"Message: {exception.Message}", ILogger.Level.Error, force);
|
||||||
Log(logger, caller, $"InnerException: {exception.InnerException}", ILogger.Level.Error, force);
|
Log(logger, caller, $"InnerException: {exception.InnerException}", ILogger.Level.Error, force);
|
||||||
Log(logger, caller, $"{nameof(StackTrace)}:{Environment.NewLine}{exception.StackTrace}");
|
|
||||||
|
// Not using LogTrace because exception.StackTrace is a type of string
|
||||||
|
Log(logger, caller, $"{nameof(StackTrace)}:{Environment.NewLine}{exception.StackTrace}", ILogger.Level.Trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LogTrace<T>(this ILogger logger, T caller, StackTrace? stackTrace = null, bool force = false)
|
||||||
|
{
|
||||||
|
Log(logger, caller, $"{nameof(StackTrace)}:{Environment.NewLine}{stackTrace ?? new()}", ILogger.Level.Trace, force);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core.Debug;
|
namespace Engine.Core.Debug;
|
||||||
|
|
||||||
public class LoggerWrapper(ILogger firstLogger, ILogger secondLogger) : ILogger
|
public class LoggerWrapper(ILogger firstLogger, ILogger secondLogger) : ILogger
|
||||||
{
|
{
|
||||||
|
6
Engine.Core/Debug/LoggerWrapperExtensions.cs
Normal file
6
Engine.Core/Debug/LoggerWrapperExtensions.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Engine.Core.Debug;
|
||||||
|
|
||||||
|
public static class LoggerWrapperExtensions
|
||||||
|
{
|
||||||
|
public static ILogger WrapWith(this ILogger thisLogger, ILogger logger) => new LoggerWrapper(thisLogger, logger);
|
||||||
|
}
|
71
Engine.Core/Debug/RotatingFileLogger.cs
Normal file
71
Engine.Core/Debug/RotatingFileLogger.cs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Engine.Core.Debug;
|
||||||
|
|
||||||
|
public class RotatingFileLogger : ILogger
|
||||||
|
{
|
||||||
|
public readonly FileLogger FileLogger = null!;
|
||||||
|
public readonly string Directory = string.Empty;
|
||||||
|
public readonly int RotateLength = 3;
|
||||||
|
|
||||||
|
public RotatingFileLogger(string directory, string namePrefix, string nameSuffix = "", int rotateLength = 3)
|
||||||
|
{
|
||||||
|
RotateLength = rotateLength;
|
||||||
|
|
||||||
|
string fileName = Path.Combine(directory, namePrefix);
|
||||||
|
if (!string.IsNullOrWhiteSpace(nameSuffix))
|
||||||
|
fileName += $"_{nameSuffix}";
|
||||||
|
|
||||||
|
bool isRelativePath = Path.GetFullPath(fileName).CompareTo(fileName) != 0;
|
||||||
|
|
||||||
|
if (isRelativePath)
|
||||||
|
fileName = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName));
|
||||||
|
|
||||||
|
if (File.Exists($"{fileName}.log"))
|
||||||
|
RenameExistingLogs(fileName, RotateLength);
|
||||||
|
|
||||||
|
FileLogger = new(fileName);
|
||||||
|
|
||||||
|
Directory = Path.GetDirectoryName(fileName) ?? throw new("Unexpected error on getting directory of logger path");
|
||||||
|
RotateLastLogs(Directory, namePrefix, RotateLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RenameExistingLogs(string filePath, int rotateLength)
|
||||||
|
{
|
||||||
|
for (int i = rotateLength - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
string source = i == 0
|
||||||
|
? $"{filePath}.log"
|
||||||
|
: $"{filePath}_{i}.log";
|
||||||
|
|
||||||
|
string dest = $"{filePath}_{i + 1}.log";
|
||||||
|
|
||||||
|
if (!File.Exists(source))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (File.Exists(dest))
|
||||||
|
File.Delete(dest);
|
||||||
|
|
||||||
|
File.Move(source, dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RotateLastLogs(string directory, string prefix, int rotateLength)
|
||||||
|
{
|
||||||
|
IOrderedEnumerable<string> logs = System.IO.Directory.GetFiles(directory, $"{prefix}*.log")
|
||||||
|
.OrderBy(File.GetCreationTime);
|
||||||
|
|
||||||
|
foreach (string file in logs.Skip(rotateLength))
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ILogger.Shared.Log($"Removing log file located at \"{file}\" during rotation.");
|
||||||
|
File.Delete(file);
|
||||||
|
}
|
||||||
|
catch (Exception e) { ILogger.Shared.LogException($"Failed to rotate log file at \"{file}\"", e); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ILogger.Level FilterLevel { get => FileLogger.FilterLevel; set => FileLogger.FilterLevel = value; }
|
||||||
|
public void Log(string message, ILogger.Level level = ILogger.Level.Info, bool force = false) => FileLogger.Log(message, level, force);
|
||||||
|
}
|
@@ -4,7 +4,8 @@
|
|||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<ImplicitUsings>false</ImplicitUsings>
|
<ImplicitUsings>false</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<RootNamespace>Syntriax.Engine.Core</RootNamespace>
|
<RootNamespace>Engine.Core</RootNamespace>
|
||||||
|
<AssemblyName>Engine.Core</AssemblyName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Exceptions;
|
namespace Engine.Core.Exceptions;
|
||||||
|
|
||||||
public class AssignFailedException(string? message) : Exception(message)
|
public class AssignFailedException(string? message) : Exception(message)
|
||||||
{
|
{
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
namespace Syntriax.Engine.Core.Exceptions;
|
namespace Engine.Core.Exceptions;
|
||||||
|
|
||||||
public class BehaviourNotFoundException(string? message) : NotFoundException(message);
|
public class BehaviourNotFoundException(string? message) : NotFoundException(message);
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Exceptions;
|
namespace Engine.Core.Exceptions;
|
||||||
|
|
||||||
public class NotAssignedException(string? message) : Exception(message)
|
public class NotAssignedException(string? message) : Exception(message)
|
||||||
{
|
{
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Exceptions;
|
namespace Engine.Core.Exceptions;
|
||||||
|
|
||||||
public class NotFoundException(string? message) : Exception(message)
|
public class NotFoundException(string? message) : Exception(message)
|
||||||
{
|
{
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
namespace Syntriax.Engine.Core.Exceptions;
|
namespace Engine.Core.Exceptions;
|
||||||
|
|
||||||
public class UniverseObjectNotFoundException(string? message) : NotFoundException(message);
|
public class UniverseObjectNotFoundException(string? message) : NotFoundException(message);
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
using Syntriax.Engine.Core.Exceptions;
|
using Engine.Core.Exceptions;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public static class BehaviourControllerExtensions
|
public static class BehaviourControllerExtensions
|
||||||
{
|
{
|
||||||
@@ -27,7 +27,7 @@ public static class BehaviourControllerExtensions
|
|||||||
/// <param name="behaviourController">The <see cref="IBehaviourController"/> to start searching from.</param>
|
/// <param name="behaviourController">The <see cref="IBehaviourController"/> to start searching from.</param>
|
||||||
/// <returns>The <see cref="IBehaviour"/> of the specified type if found; otherwise, throws <see cref="BehaviourNotFoundException"/>.</returns>
|
/// <returns>The <see cref="IBehaviour"/> of the specified type if found; otherwise, throws <see cref="BehaviourNotFoundException"/>.</returns>
|
||||||
public static T GetRequiredBehaviour<T>(this IBehaviourController behaviourController) where T : class
|
public static T GetRequiredBehaviour<T>(this IBehaviourController behaviourController) where T : class
|
||||||
=> behaviourController.GetBehaviour<T>() ?? throw new BehaviourNotFoundException($"{behaviourController.UniverseObject.Name}'s {nameof(IBehaviourController)} does not contain any {typeof(T).FullName}");
|
=> behaviourController.GetBehaviour<T>() ?? throw new BehaviourNotFoundException($"{behaviourController.UniverseObject?.Name ?? "NULL"}'s {nameof(IBehaviourController)} does not contain any {typeof(T).FullName}");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets an existing <see cref="IBehaviour"/> of the specified type, or adds and returns a new one if it doesn't exist.
|
/// Gets an existing <see cref="IBehaviour"/> of the specified type, or adds and returns a new one if it doesn't exist.
|
||||||
@@ -93,7 +93,7 @@ public static class BehaviourControllerExtensions
|
|||||||
/// <param name="behaviourController">The <see cref="IBehaviourController"/> to start searching from.</param>
|
/// <param name="behaviourController">The <see cref="IBehaviourController"/> to start searching from.</param>
|
||||||
/// <returns>The <see cref="IBehaviour"/> of the specified type if found; otherwise, throws <see cref="BehaviourNotFoundException"/>.</returns>
|
/// <returns>The <see cref="IBehaviour"/> of the specified type if found; otherwise, throws <see cref="BehaviourNotFoundException"/>.</returns>
|
||||||
public static T GetRequiredBehaviourInParent<T>(this IBehaviourController behaviourController) where T : class
|
public static T GetRequiredBehaviourInParent<T>(this IBehaviourController behaviourController) where T : class
|
||||||
=> behaviourController.GetBehaviourInParent<T>() ?? throw new BehaviourNotFoundException($"{behaviourController.UniverseObject.Name}'s {nameof(IBehaviourController)} does not contain any {typeof(T).FullName} on any parent");
|
=> behaviourController.GetBehaviourInParent<T>() ?? throw new BehaviourNotFoundException($"{behaviourController.UniverseObject?.Name ?? "NULL"}'s {nameof(IBehaviourController)} does not contain any {typeof(T).FullName} on any parent");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all <see cref="IBehaviour"/>s of the specified type in it's <see cref="IUniverseObject"/>'s parents recursively and stores them in the provided list.
|
/// Gets all <see cref="IBehaviour"/>s of the specified type in it's <see cref="IUniverseObject"/>'s parents recursively and stores them in the provided list.
|
||||||
@@ -140,7 +140,7 @@ public static class BehaviourControllerExtensions
|
|||||||
if (behaviourController.GetBehaviour<T>() is T localBehaviour)
|
if (behaviourController.GetBehaviour<T>() is T localBehaviour)
|
||||||
return localBehaviour;
|
return localBehaviour;
|
||||||
|
|
||||||
foreach (IUniverseObject child in behaviourController.UniverseObject)
|
foreach (IUniverseObject child in behaviourController.UniverseObject.Children)
|
||||||
if (GetBehaviourInChildren<T>(child.BehaviourController) is T behaviour)
|
if (GetBehaviourInChildren<T>(child.BehaviourController) is T behaviour)
|
||||||
return behaviour;
|
return behaviour;
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ public static class BehaviourControllerExtensions
|
|||||||
/// <param name="behaviourController">The <see cref="IBehaviourController"/> to start searching from.</param>
|
/// <param name="behaviourController">The <see cref="IBehaviourController"/> to start searching from.</param>
|
||||||
/// <returns>The <see cref="IBehaviour"/> of the specified type if found; otherwise, throws <see cref="BehaviourNotFoundException"/>.</returns>
|
/// <returns>The <see cref="IBehaviour"/> of the specified type if found; otherwise, throws <see cref="BehaviourNotFoundException"/>.</returns>
|
||||||
public static T GetRequiredBehaviourInChildren<T>(this IBehaviourController behaviourController) where T : class
|
public static T GetRequiredBehaviourInChildren<T>(this IBehaviourController behaviourController) where T : class
|
||||||
=> behaviourController.GetBehaviourInChildren<T>() ?? throw new BehaviourNotFoundException($"{behaviourController.UniverseObject.Name}'s {nameof(IBehaviourController)} does not contain any {typeof(T).FullName} on any children ");
|
=> behaviourController.GetBehaviourInChildren<T>() ?? throw new BehaviourNotFoundException($"{behaviourController.UniverseObject?.Name ?? "NULL"}'s {nameof(IBehaviourController)} does not contain any {typeof(T).FullName} on any children ");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all <see cref="IBehaviour"/>s of the specified type in it's <see cref="IUniverseObject"/>'s children recursively and stores them in the provided list.
|
/// Gets all <see cref="IBehaviour"/>s of the specified type in it's <see cref="IUniverseObject"/>'s children recursively and stores them in the provided list.
|
||||||
@@ -176,7 +176,7 @@ public static class BehaviourControllerExtensions
|
|||||||
foreach (T behaviour in cache)
|
foreach (T behaviour in cache)
|
||||||
behaviours.Add(behaviour);
|
behaviours.Add(behaviour);
|
||||||
|
|
||||||
foreach (IUniverseObject child in universeObject)
|
foreach (IUniverseObject child in universeObject.Children)
|
||||||
TraverseChildrenForBehaviour(child, behaviours, cache);
|
TraverseChildrenForBehaviour(child, behaviours, cache);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public static class EnumExtensions
|
public static class EnumExtensions
|
||||||
{
|
{
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public static class FloatExtensions
|
public static class FloatExtensions
|
||||||
{
|
{
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public static class TransformExtensions
|
public static class TransformExtensions
|
||||||
{
|
{
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using Syntriax.Engine.Core.Exceptions;
|
using Engine.Core.Exceptions;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public static class UniverseExtensions
|
public static class UniverseExtensions
|
||||||
{
|
{
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
using Syntriax.Engine.Core.Exceptions;
|
using Engine.Core.Exceptions;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public static class UniverseObjectExtensions
|
public static class UniverseObjectExtensions
|
||||||
{
|
{
|
||||||
@@ -12,7 +12,7 @@ public static class UniverseObjectExtensions
|
|||||||
if (!string.IsNullOrWhiteSpace(name))
|
if (!string.IsNullOrWhiteSpace(name))
|
||||||
universeObject.Name = name;
|
universeObject.Name = name;
|
||||||
if (parent is not null)
|
if (parent is not null)
|
||||||
universeObject.SetParent(parent);
|
universeObject.Parent = parent;
|
||||||
return universeObject;
|
return universeObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ public static class UniverseObjectExtensions
|
|||||||
/// <returns>The <see cref="IUniverseObject"/> of the specified type if found; otherwise, null.</returns>
|
/// <returns>The <see cref="IUniverseObject"/> of the specified type if found; otherwise, null.</returns>
|
||||||
public static T? GetUniverseObjectInParent<T>(this IUniverseObject universeObject) where T : class
|
public static T? GetUniverseObjectInParent<T>(this IUniverseObject universeObject) where T : class
|
||||||
{
|
{
|
||||||
if (universeObject.GetUniverseObject<T>() is T localUniverseObject)
|
if (universeObject.Children.GetUniverseObject<T>() is T localUniverseObject)
|
||||||
return localUniverseObject;
|
return localUniverseObject;
|
||||||
|
|
||||||
IUniverseObject? parent = universeObject;
|
IUniverseObject? parent = universeObject;
|
||||||
@@ -129,10 +129,10 @@ public static class UniverseObjectExtensions
|
|||||||
/// <returns>The <see cref="IUniverseObject"/> of the specified type if found; otherwise, null.</returns>
|
/// <returns>The <see cref="IUniverseObject"/> of the specified type if found; otherwise, null.</returns>
|
||||||
public static T? GetUniverseObjectInChildren<T>(this IUniverseObject universeObject) where T : class
|
public static T? GetUniverseObjectInChildren<T>(this IUniverseObject universeObject) where T : class
|
||||||
{
|
{
|
||||||
if (universeObject.GetUniverseObject<T>() is T localUniverseObject)
|
if (universeObject.Children.GetUniverseObject<T>() is T localUniverseObject)
|
||||||
return localUniverseObject;
|
return localUniverseObject;
|
||||||
|
|
||||||
foreach (IUniverseObject child in universeObject)
|
foreach (IUniverseObject child in universeObject.Children)
|
||||||
if (GetUniverseObjectInChildren<T>(child) is T behaviour)
|
if (GetUniverseObjectInChildren<T>(child) is T behaviour)
|
||||||
return behaviour;
|
return behaviour;
|
||||||
|
|
||||||
@@ -246,7 +246,7 @@ public static class UniverseObjectExtensions
|
|||||||
|
|
||||||
foreach (IUniverseObject universeObject in universeObjects)
|
foreach (IUniverseObject universeObject in universeObjects)
|
||||||
{
|
{
|
||||||
universeObject.Find(cache);
|
universeObject.Children.Find(cache);
|
||||||
foreach (T behaviour in cache)
|
foreach (T behaviour in cache)
|
||||||
instances.Add(behaviour);
|
instances.Add(behaviour);
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core.Factory.Abstract;
|
namespace Engine.Core.Factory.Abstract;
|
||||||
|
|
||||||
public interface IFactory<TInterface> where TInterface : class
|
public interface IFactory<TInterface> where TInterface : class
|
||||||
{
|
{
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
using Syntriax.Engine.Core.Exceptions;
|
using Engine.Core.Exceptions;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Factory;
|
namespace Engine.Core.Factory;
|
||||||
|
|
||||||
public class BehaviourControllerFactory
|
public class BehaviourControllerFactory
|
||||||
{
|
{
|
||||||
public static IBehaviourController Instantiate(IUniverseObject universeObject)
|
public static IBehaviourController Instantiate(IUniverseObject universeObject, IStateEnable? stateEnable = null)
|
||||||
=> Instantiate<BehaviourController>(universeObject);
|
=> Instantiate<BehaviourController>(universeObject, stateEnable);
|
||||||
|
|
||||||
public static T Instantiate<T>(IUniverseObject universeObject, params object?[]? args)
|
public static T Instantiate<T>(IUniverseObject universeObject, IStateEnable? stateEnable = null, params object?[]? args)
|
||||||
where T : class, IBehaviourController
|
where T : class, IBehaviourController
|
||||||
{
|
{
|
||||||
T behaviourController = TypeFactory.Get<T>(args);
|
T behaviourController = TypeFactory.Get<T>(args);
|
||||||
@@ -18,6 +18,17 @@ public class BehaviourControllerFactory
|
|||||||
if (!behaviourController.Assign(universeObject))
|
if (!behaviourController.Assign(universeObject))
|
||||||
throw AssignFailedException.From(behaviourController, universeObject);
|
throw AssignFailedException.From(behaviourController, universeObject);
|
||||||
|
|
||||||
|
if (stateEnable is not null)
|
||||||
|
{
|
||||||
|
if (!stateEnable.Assign(behaviourController))
|
||||||
|
throw AssignFailedException.From(stateEnable, behaviourController);
|
||||||
|
|
||||||
|
if (!behaviourController.Assign(stateEnable))
|
||||||
|
throw AssignFailedException.From(behaviourController, stateEnable);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
StateEnableFactory.Instantiate(behaviourController);
|
||||||
|
|
||||||
return behaviourController;
|
return behaviourController;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using Syntriax.Engine.Core.Exceptions;
|
using Engine.Core.Exceptions;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Factory;
|
namespace Engine.Core.Factory;
|
||||||
|
|
||||||
public class BehaviourFactory
|
public class BehaviourFactory
|
||||||
{
|
{
|
||||||
@@ -12,12 +12,15 @@ public class BehaviourFactory
|
|||||||
{
|
{
|
||||||
T behaviour = TypeFactory.Get<T>(args);
|
T behaviour = TypeFactory.Get<T>(args);
|
||||||
|
|
||||||
stateEnable ??= TypeFactory.Get<StateEnable>();
|
if (stateEnable is not null)
|
||||||
|
{
|
||||||
if (!stateEnable.Assign(behaviour))
|
if (!stateEnable.Assign(behaviour))
|
||||||
throw AssignFailedException.From(stateEnable, behaviour);
|
throw AssignFailedException.From(stateEnable, behaviour);
|
||||||
|
|
||||||
if (!behaviour.Assign(stateEnable))
|
if (!behaviour.Assign(stateEnable))
|
||||||
throw AssignFailedException.From(behaviour, stateEnable);
|
throw AssignFailedException.From(behaviour, stateEnable);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
StateEnableFactory.Instantiate(behaviour);
|
||||||
|
|
||||||
return behaviour;
|
return behaviour;
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using Syntriax.Engine.Core.Factory.Abstract;
|
using Engine.Core.Factory.Abstract;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Factory;
|
namespace Engine.Core.Factory;
|
||||||
|
|
||||||
public abstract class FactoryBase<TInterface> : IFactory<TInterface>
|
public abstract class FactoryBase<TInterface> : IFactory<TInterface>
|
||||||
where TInterface : class
|
where TInterface : class
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using Syntriax.Engine.Core.Exceptions;
|
using Engine.Core.Exceptions;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Factory;
|
namespace Engine.Core.Factory;
|
||||||
|
|
||||||
public class StateEnableFactory
|
public class StateEnableFactory
|
||||||
{
|
{
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core.Factory;
|
namespace Engine.Core.Factory;
|
||||||
|
|
||||||
public class TransformFactory
|
public class TransformFactory
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@ using System.Collections.Concurrent;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Factory;
|
namespace Engine.Core.Factory;
|
||||||
|
|
||||||
public static class TypeFactory
|
public static class TypeFactory
|
||||||
{
|
{
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using Syntriax.Engine.Core.Exceptions;
|
using Engine.Core.Exceptions;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Factory;
|
namespace Engine.Core.Factory;
|
||||||
|
|
||||||
public class UniverseObjectFactory
|
public class UniverseObjectFactory
|
||||||
{
|
{
|
||||||
@@ -18,18 +18,25 @@ public class UniverseObjectFactory
|
|||||||
{
|
{
|
||||||
T universeObject = TypeFactory.Get<T>(args);
|
T universeObject = TypeFactory.Get<T>(args);
|
||||||
|
|
||||||
behaviourController ??= TypeFactory.Get<BehaviourController>();
|
if (behaviourController is not null)
|
||||||
stateEnable ??= TypeFactory.Get<StateEnable>();
|
{
|
||||||
|
|
||||||
if (!behaviourController.Assign(universeObject))
|
if (!behaviourController.Assign(universeObject))
|
||||||
throw AssignFailedException.From(behaviourController, universeObject);
|
throw AssignFailedException.From(behaviourController, universeObject);
|
||||||
if (!stateEnable.Assign(universeObject))
|
|
||||||
throw AssignFailedException.From(stateEnable, universeObject);
|
|
||||||
|
|
||||||
if (!universeObject.Assign(behaviourController))
|
if (!universeObject.Assign(behaviourController))
|
||||||
throw AssignFailedException.From(universeObject, behaviourController);
|
throw AssignFailedException.From(universeObject, behaviourController);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
BehaviourControllerFactory.Instantiate(universeObject);
|
||||||
|
|
||||||
|
if (stateEnable is not null)
|
||||||
|
{
|
||||||
|
if (!stateEnable.Assign(universeObject))
|
||||||
|
throw AssignFailedException.From(stateEnable, universeObject);
|
||||||
if (!universeObject.Assign(stateEnable))
|
if (!universeObject.Assign(stateEnable))
|
||||||
throw AssignFailedException.From(universeObject, stateEnable);
|
throw AssignFailedException.From(universeObject, stateEnable);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
StateEnableFactory.Instantiate(universeObject);
|
||||||
|
|
||||||
return universeObject;
|
return universeObject;
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
using Engine.Core.Debug;
|
||||||
|
|
||||||
|
namespace Engine.Core;
|
||||||
|
|
||||||
|
// TODO!: every reverse loop has a chance to have more than 1 unsubscription,
|
||||||
|
// for (int i = listeners.Count - 1; i >= 0; i--)
|
||||||
|
// can be replaced with
|
||||||
|
// for (int i = listeners.Count - 1; i >= 0; i = Math.Min(i - 1, listeners.Count - 1))
|
||||||
|
// but this would causes possible double calls on already called callbacks, find a better method.
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a simple event with no parameters.
|
/// Represents a simple event with no parameters.
|
||||||
@@ -48,6 +56,9 @@ public class Event
|
|||||||
// We use Ascending order because draw calls are running from last to first
|
// We use Ascending order because draw calls are running from last to first
|
||||||
private static readonly Comparer<ListenerData> SortByAscendingPriority = Comparer<ListenerData>.Create((x, y) => x.Priority.CompareTo(y.Priority));
|
private static readonly Comparer<ListenerData> SortByAscendingPriority = Comparer<ListenerData>.Create((x, y) => x.Priority.CompareTo(y.Priority));
|
||||||
|
|
||||||
|
private ILogger _logger = ILogger.Shared;
|
||||||
|
public ILogger Logger { get => _logger; set => _logger = value ?? ILogger.Shared; }
|
||||||
|
|
||||||
private readonly List<ListenerData> listeners = null!;
|
private readonly List<ListenerData> listeners = null!;
|
||||||
private readonly List<ListenerData> onceListeners = null!;
|
private readonly List<ListenerData> onceListeners = null!;
|
||||||
|
|
||||||
@@ -126,7 +137,7 @@ public class Event
|
|||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
string methodCallRepresentation = $"{listeners[i].Callback.Method.DeclaringType?.FullName}.{listeners[i].Callback.Method.Name}()";
|
string methodCallRepresentation = $"{listeners[i].Callback.Method.DeclaringType?.FullName}.{listeners[i].Callback.Method.Name}()";
|
||||||
Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
|
EventHelpers.LogInvocationException(listeners[i].Callback.Target ?? this, Logger, exception, methodCallRepresentation);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = onceListeners.Count - 1; i >= 0; i--)
|
for (int i = onceListeners.Count - 1; i >= 0; i--)
|
||||||
@@ -135,7 +146,7 @@ public class Event
|
|||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
string methodCallRepresentation = $"{onceListeners[i].Callback.Method.DeclaringType?.FullName}.{onceListeners[i].Callback.Method.Name}()";
|
string methodCallRepresentation = $"{onceListeners[i].Callback.Method.DeclaringType?.FullName}.{onceListeners[i].Callback.Method.Name}()";
|
||||||
Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
|
EventHelpers.LogInvocationException(onceListeners[i].Callback.Target ?? this, Logger, exception, methodCallRepresentation);
|
||||||
}
|
}
|
||||||
onceListeners.RemoveAt(i);
|
onceListeners.RemoveAt(i);
|
||||||
}
|
}
|
||||||
@@ -199,11 +210,14 @@ public class Event
|
|||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TSender">Sender type</typeparam>
|
/// <typeparam name="TSender">Sender type</typeparam>
|
||||||
public class Event<TSender>
|
public class Event<TSender> where TSender : class
|
||||||
{
|
{
|
||||||
// We use Ascending order because draw calls are running from last to first
|
// We use Ascending order because draw calls are running from last to first
|
||||||
private static readonly Comparer<ListenerData> SortByAscendingPriority = Comparer<ListenerData>.Create((x, y) => x.Priority.CompareTo(y.Priority));
|
private static readonly Comparer<ListenerData> SortByAscendingPriority = Comparer<ListenerData>.Create((x, y) => x.Priority.CompareTo(y.Priority));
|
||||||
|
|
||||||
|
private ILogger _logger = ILogger.Shared;
|
||||||
|
public ILogger Logger { get => _logger; set => _logger = value ?? ILogger.Shared; }
|
||||||
|
|
||||||
private readonly List<ListenerData> listeners = null!;
|
private readonly List<ListenerData> listeners = null!;
|
||||||
private readonly List<ListenerData> onceListeners = null!;
|
private readonly List<ListenerData> onceListeners = null!;
|
||||||
|
|
||||||
@@ -283,7 +297,7 @@ public class Event<TSender>
|
|||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
string methodCallRepresentation = $"{listeners[i].Callback.Method.DeclaringType?.FullName}.{listeners[i].Callback.Method.Name}({sender})";
|
string methodCallRepresentation = $"{listeners[i].Callback.Method.DeclaringType?.FullName}.{listeners[i].Callback.Method.Name}({sender})";
|
||||||
Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
|
EventHelpers.LogInvocationException(listeners[i].Callback.Target ?? sender, Logger, exception, methodCallRepresentation);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = onceListeners.Count - 1; i >= 0; i--)
|
for (int i = onceListeners.Count - 1; i >= 0; i--)
|
||||||
@@ -292,7 +306,7 @@ public class Event<TSender>
|
|||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
string methodCallRepresentation = $"{onceListeners[i].Callback.Method.DeclaringType?.FullName}.{onceListeners[i].Callback.Method.Name}({sender})";
|
string methodCallRepresentation = $"{onceListeners[i].Callback.Method.DeclaringType?.FullName}.{onceListeners[i].Callback.Method.Name}({sender})";
|
||||||
Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
|
EventHelpers.LogInvocationException(onceListeners[i].Callback.Target ?? sender, Logger, exception, methodCallRepresentation);
|
||||||
}
|
}
|
||||||
onceListeners.RemoveAt(i);
|
onceListeners.RemoveAt(i);
|
||||||
}
|
}
|
||||||
@@ -363,11 +377,14 @@ public class Event<TSender>
|
|||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TSender">Sender type</typeparam>
|
/// <typeparam name="TSender">Sender type</typeparam>
|
||||||
public class Event<TSender, TArguments>
|
public class Event<TSender, TArguments> where TSender : class
|
||||||
{
|
{
|
||||||
// We use Ascending order because draw calls are running from last to first
|
// We use Ascending order because draw calls are running from last to first
|
||||||
private static readonly Comparer<ListenerData> SortByAscendingPriority = Comparer<ListenerData>.Create((x, y) => x.Priority.CompareTo(y.Priority));
|
private static readonly Comparer<ListenerData> SortByAscendingPriority = Comparer<ListenerData>.Create((x, y) => x.Priority.CompareTo(y.Priority));
|
||||||
|
|
||||||
|
private ILogger _logger = ILogger.Shared;
|
||||||
|
public ILogger Logger { get => _logger; set => _logger = value ?? ILogger.Shared; }
|
||||||
|
|
||||||
private readonly List<ListenerData> listeners = null!;
|
private readonly List<ListenerData> listeners = null!;
|
||||||
private readonly List<ListenerData> onceListeners = null!;
|
private readonly List<ListenerData> onceListeners = null!;
|
||||||
|
|
||||||
@@ -447,8 +464,8 @@ public class Event<TSender, TArguments>
|
|||||||
try { listeners[i].Callback.Invoke(sender, args); }
|
try { listeners[i].Callback.Invoke(sender, args); }
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
string methodCallRepresentation = $"{listeners[i].Callback.Method.DeclaringType?.FullName}.{listeners[i].Callback.Method.Name}({string.Join(", ", sender, args)})";
|
string methodCallRepresentation = $"{listeners[i].Callback.Method.DeclaringType?.FullName}.{listeners[i].Callback.Method.Name}({sender}, {args})";
|
||||||
Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
|
EventHelpers.LogInvocationException(listeners[i].Callback.Target ?? sender, Logger, exception, methodCallRepresentation);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = onceListeners.Count - 1; i >= 0; i--)
|
for (int i = onceListeners.Count - 1; i >= 0; i--)
|
||||||
@@ -456,8 +473,8 @@ public class Event<TSender, TArguments>
|
|||||||
try { onceListeners[i].Callback.Invoke(sender, args); }
|
try { onceListeners[i].Callback.Invoke(sender, args); }
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
string methodCallRepresentation = $"{onceListeners[i].Callback.Method.DeclaringType?.FullName}.{onceListeners[i].Callback.Method.Name}({string.Join(", ", sender, args)})";
|
string methodCallRepresentation = $"{onceListeners[i].Callback.Method.DeclaringType?.FullName}.{onceListeners[i].Callback.Method.Name}({sender}, {args})";
|
||||||
Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
|
EventHelpers.LogInvocationException(onceListeners[i].Callback.Target ?? sender, Logger, exception, methodCallRepresentation);
|
||||||
}
|
}
|
||||||
onceListeners.RemoveAt(i);
|
onceListeners.RemoveAt(i);
|
||||||
}
|
}
|
||||||
@@ -478,3 +495,12 @@ public class Event<TSender, TArguments>
|
|||||||
public delegate void EventHandler(TSender sender, TArguments args);
|
public delegate void EventHandler(TSender sender, TArguments args);
|
||||||
private record struct ListenerData(EventHandler Callback, int Priority);
|
private record struct ListenerData(EventHandler Callback, int Priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static class EventHelpers
|
||||||
|
{
|
||||||
|
public static void LogInvocationException(object sender, ILogger logger, Exception exception, string methodCallRepresentation)
|
||||||
|
{
|
||||||
|
logger.LogException(sender, exception);
|
||||||
|
logger.LogError(sender, $"Unexpected exception on invocation of method {methodCallRepresentation}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
102
Engine.Core/Helpers/FastList.cs
Normal file
102
Engine.Core/Helpers/FastList.cs
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Engine.Core;
|
||||||
|
|
||||||
|
public class FastList<T> : IList<T>, IReadOnlyList<T>, IEnumerable<T> where T : notnull
|
||||||
|
{
|
||||||
|
private readonly List<T> items = [];
|
||||||
|
private readonly Dictionary<T, int> indexMap = [];
|
||||||
|
|
||||||
|
public bool IsReadOnly { get; set; } = false;
|
||||||
|
public int Count => items.Count;
|
||||||
|
public T this[int index]
|
||||||
|
{
|
||||||
|
get => items[index];
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (IsReadOnly)
|
||||||
|
throw new System.Data.ReadOnlyException();
|
||||||
|
|
||||||
|
items[index] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(T item)
|
||||||
|
{
|
||||||
|
if (IsReadOnly)
|
||||||
|
throw new System.Data.ReadOnlyException();
|
||||||
|
|
||||||
|
indexMap[item] = items.Count;
|
||||||
|
items.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAt(int i) => Remove(items[i], i);
|
||||||
|
public bool Remove(T item)
|
||||||
|
{
|
||||||
|
if (IsReadOnly)
|
||||||
|
throw new System.Data.ReadOnlyException();
|
||||||
|
|
||||||
|
if (!indexMap.TryGetValue(item, out int index))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Remove(item, index);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Remove(T item, int index)
|
||||||
|
{
|
||||||
|
int lastIndex = items.Count - 1;
|
||||||
|
T lastItem = items[lastIndex];
|
||||||
|
|
||||||
|
items[index] = lastItem;
|
||||||
|
indexMap[lastItem] = index;
|
||||||
|
|
||||||
|
items.RemoveAt(lastIndex);
|
||||||
|
indexMap.Remove(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Insert(int index, T item)
|
||||||
|
{
|
||||||
|
if (IsReadOnly)
|
||||||
|
throw new System.Data.ReadOnlyException();
|
||||||
|
|
||||||
|
items.Insert(index, item);
|
||||||
|
|
||||||
|
for (int i = index; i < items.Count; i++)
|
||||||
|
indexMap[items[i]] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
if (IsReadOnly)
|
||||||
|
throw new System.Data.ReadOnlyException();
|
||||||
|
|
||||||
|
items.Clear();
|
||||||
|
indexMap.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(T item) => indexMap.ContainsKey(item);
|
||||||
|
public int IndexOf(T item) => items.IndexOf(item);
|
||||||
|
public int BinarySearch(T item, IComparer<T>? comparer = null) => items.BinarySearch(item, comparer);
|
||||||
|
|
||||||
|
public void Sort(IComparer<T> comparer)
|
||||||
|
{
|
||||||
|
if (IsReadOnly)
|
||||||
|
throw new System.Data.ReadOnlyException();
|
||||||
|
|
||||||
|
items.Sort(comparer);
|
||||||
|
|
||||||
|
for (int i = 0; i < items.Count; i++)
|
||||||
|
indexMap[items[i]] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CopyTo(T[] array, int arrayIndex) => items.CopyTo(array, arrayIndex);
|
||||||
|
|
||||||
|
public IEnumerator<T> GetEnumerator() => items.GetEnumerator();
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
|
||||||
|
public FastList() { }
|
||||||
|
public FastList(int count) { items.Capacity = count; }
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public interface IPool<T>
|
public interface IPool<T>
|
||||||
{
|
{
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public class ListPool<T> : IPool<List<T>>
|
public class ListPool<T> : IPool<List<T>>
|
||||||
{
|
{
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public class Pool<T> : IPool<T>
|
public class Pool<T> : IPool<T>
|
||||||
{
|
{
|
||||||
@@ -10,22 +10,25 @@ public class Pool<T> : IPool<T>
|
|||||||
|
|
||||||
private readonly Func<T> generator = null!;
|
private readonly Func<T> generator = null!;
|
||||||
private readonly Queue<T> queue = new();
|
private readonly Queue<T> queue = new();
|
||||||
|
private readonly HashSet<T> queuedHashes = [];
|
||||||
|
|
||||||
public T Get()
|
public T Get()
|
||||||
{
|
{
|
||||||
if (!queue.TryDequeue(out T? result))
|
if (!queue.TryDequeue(out T? result))
|
||||||
result = generator();
|
result = generator();
|
||||||
|
|
||||||
|
queuedHashes.Remove(result);
|
||||||
OnRemoved?.Invoke(this, result);
|
OnRemoved?.Invoke(this, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Return(T item)
|
public void Return(T item)
|
||||||
{
|
{
|
||||||
if (queue.Contains(item))
|
if (queuedHashes.Contains(item))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
queue.Enqueue(item);
|
queue.Enqueue(item);
|
||||||
|
queuedHashes.Add(item);
|
||||||
OnReturned?.Invoke(this, item);
|
OnReturned?.Invoke(this, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public interface IProgressionTracker : IReadOnlyProgressionTracker
|
public interface IProgressionTracker : IReadOnlyProgressionTracker
|
||||||
{
|
{
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public interface IReadOnlyProgressionTracker
|
public interface IReadOnlyProgressionTracker
|
||||||
{
|
{
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public class ProgressionTracker : IProgressionTracker
|
public class ProgressionTracker : IProgressionTracker
|
||||||
{
|
{
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public record struct ProgressiveTask<T>(IReadOnlyProgressionTracker ProgressionTracker, Task<T> Task)
|
public record struct ProgressiveTask<T>(IReadOnlyProgressionTracker ProgressionTracker, Task<T> Task)
|
||||||
{
|
{
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public static class Math
|
public static class Math
|
||||||
{
|
{
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public static class MathExtensions
|
public static class MathExtensions
|
||||||
{
|
{
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core
|
namespace Engine.Core
|
||||||
{
|
{
|
||||||
// This is pretty much so the assembly gets loaded automatically because
|
// This is pretty much so the assembly gets loaded automatically because
|
||||||
// the builds include the assembly but sometimes doesn't link load it at startup.
|
// the builds include the assembly but sometimes doesn't link load it at startup.
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an Axis-Aligned Bounding Box (AABB) in 2D space.
|
/// Represents an Axis-Aligned Bounding Box (AABB) in 2D space.
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a 2D circle.
|
/// Represents a 2D circle.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an HSV color.
|
/// Represents an HSV color.
|
||||||
@@ -27,49 +27,19 @@ public readonly struct ColorHSV(float hue, float saturation, float value)
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly float Value = value.Clamp(0f, 1f);
|
public readonly float Value = value.Clamp(0f, 1f);
|
||||||
|
|
||||||
public static ColorHSV operator -(ColorHSV color) => new(color.Hue.OneMinus().Clamp(0f, 1f), color.Saturation.OneMinus().Clamp(0f, 1f), color.Value.OneMinus().Clamp(0f, 1f));
|
public static ColorHSV operator -(ColorHSV color) => new(color.Hue.OneMinus(), color.Saturation.OneMinus(), color.Value.OneMinus());
|
||||||
public static ColorHSV operator +(ColorHSV left, ColorHSV right) => new((left.Hue + right.Hue).Clamp(0f, 1f), (left.Saturation + right.Saturation).Clamp(0f, 1f), (left.Value + right.Value).Clamp(0f, 1f));
|
public static ColorHSV operator +(ColorHSV left, ColorHSV right) => new(left.Hue + right.Hue, left.Saturation + right.Saturation, left.Value + right.Value);
|
||||||
public static ColorHSV operator -(ColorHSV left, ColorHSV right) => new((left.Hue - right.Hue).Clamp(0f, 1f), (left.Saturation - right.Saturation).Clamp(0f, 1f), (left.Value - right.Value).Clamp(0f, 1f));
|
public static ColorHSV operator -(ColorHSV left, ColorHSV right) => new(left.Hue - right.Hue, left.Saturation - right.Saturation, left.Value - right.Value);
|
||||||
public static ColorHSV operator *(ColorHSV left, ColorHSV right) => new((left.Hue * right.Hue).Clamp(0f, 1f), (left.Saturation * right.Saturation).Clamp(0f, 1f), (left.Value * right.Value).Clamp(0f, 1f));
|
public static ColorHSV operator *(ColorHSV left, ColorHSV right) => new(left.Hue * right.Hue, left.Saturation * right.Saturation, left.Value * right.Value);
|
||||||
public static ColorHSV operator *(ColorHSV color, float value) => new((color.Hue * value).Clamp(0f, 1f), (color.Saturation * value).Clamp(0f, 1f), (color.Value * value).Clamp(0f, 1f));
|
public static ColorHSV operator *(ColorHSV color, float value) => new(color.Hue * value, color.Saturation * value, color.Value * value);
|
||||||
public static ColorHSV operator *(float value, ColorHSV color) => new((color.Hue * value).Clamp(0f, 1f), (color.Saturation * value).Clamp(0f, 1f), (color.Value * value).Clamp(0f, 1f));
|
public static ColorHSV operator *(float value, ColorHSV color) => new(color.Hue * value, color.Saturation * value, color.Value * value);
|
||||||
public static ColorHSV operator /(ColorHSV color, float value) => new((color.Hue / value).Clamp(0f, 1f), (color.Saturation / value).Clamp(0f, 1f), (color.Value / value).Clamp(0f, 1f));
|
public static ColorHSV operator /(ColorHSV color, float value) => new(color.Hue / value, color.Saturation / value, color.Value / value);
|
||||||
public static bool operator ==(ColorHSV left, ColorHSV right) => left.Hue == right.Hue && left.Saturation == right.Saturation && left.Value == right.Value;
|
public static bool operator ==(ColorHSV left, ColorHSV right) => left.Hue == right.Hue && left.Saturation == right.Saturation && left.Value == right.Value;
|
||||||
public static bool operator !=(ColorHSV left, ColorHSV right) => left.Hue != right.Hue || left.Saturation != right.Saturation || left.Value != right.Value;
|
public static bool operator !=(ColorHSV left, ColorHSV right) => left.Hue != right.Hue || left.Saturation != right.Saturation || left.Value != right.Value;
|
||||||
|
|
||||||
public static implicit operator ColorHSV(ColorRGBA rgba) => (ColorRGB)rgba;
|
public static implicit operator ColorHSV(ColorHSVA hsva) => new(hsva.Hue, hsva.Saturation, hsva.Value);
|
||||||
public static implicit operator ColorHSV(ColorRGB rgb)
|
public static implicit operator ColorHSV(ColorRGBA rgba) => (ColorHSVA)rgba;
|
||||||
{
|
public static implicit operator ColorHSV(ColorRGB rgb) => (ColorHSVA)rgb;
|
||||||
float hue;
|
|
||||||
float saturation;
|
|
||||||
float value;
|
|
||||||
|
|
||||||
float rd = rgb.R / 255f;
|
|
||||||
float gd = rgb.G / 255f;
|
|
||||||
float bd = rgb.B / 255f;
|
|
||||||
|
|
||||||
float max = Math.Max(rd, Math.Max(gd, bd));
|
|
||||||
float min = Math.Min(rd, Math.Min(gd, bd));
|
|
||||||
float delta = max - min;
|
|
||||||
|
|
||||||
if (delta.ApproximatelyEquals(0))
|
|
||||||
hue = 0f;
|
|
||||||
else if (max.ApproximatelyEquals(rd))
|
|
||||||
hue = 60f * ((gd - bd) / delta % 6f);
|
|
||||||
else if (max.ApproximatelyEquals(gd))
|
|
||||||
hue = 60f * (((bd - rd) / delta) + 2f);
|
|
||||||
else
|
|
||||||
hue = 60f * (((rd - gd) / delta) + 4f);
|
|
||||||
|
|
||||||
if (hue < 0f)
|
|
||||||
hue += 360f;
|
|
||||||
|
|
||||||
hue /= 360f;
|
|
||||||
saturation = max.ApproximatelyEquals(0f) ? 0f : delta / max;
|
|
||||||
value = max;
|
|
||||||
|
|
||||||
return new(hue, saturation, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Inverts the given <see cref="ColorHSV"/>.
|
/// Inverts the given <see cref="ColorHSV"/>.
|
||||||
@@ -110,14 +80,6 @@ public readonly struct ColorHSV(float hue, float saturation, float value)
|
|||||||
/// <returns>The result of dividing the <see cref="ColorHSV"/> by the scalar value.</returns>
|
/// <returns>The result of dividing the <see cref="ColorHSV"/> by the scalar value.</returns>
|
||||||
public static ColorHSV Divide(ColorHSV color, float value) => color / value;
|
public static ColorHSV Divide(ColorHSV color, float value) => color / value;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates the <see cref="ColorHSV"/> from one point to another.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="from">The starting point.</param>
|
|
||||||
/// <param name="to">The ending point.</param>
|
|
||||||
/// <returns>The <see cref="ColorHSV"/> from the starting point to the ending point.</returns>
|
|
||||||
public static ColorHSV FromTo(ColorHSV from, ColorHSV to) => to - from;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs linear interpolation between two <see cref="ColorHSV"/>s.
|
/// Performs linear interpolation between two <see cref="ColorHSV"/>s.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -125,7 +87,14 @@ public readonly struct ColorHSV(float hue, float saturation, float value)
|
|||||||
/// <param name="to">The ending <see cref="ColorHSV"/> (t = 1).</param>
|
/// <param name="to">The ending <see cref="ColorHSV"/> (t = 1).</param>
|
||||||
/// <param name="t">The interpolation parameter.</param>
|
/// <param name="t">The interpolation parameter.</param>
|
||||||
/// <returns>The interpolated <see cref="ColorHSV"/>.</returns>
|
/// <returns>The interpolated <see cref="ColorHSV"/>.</returns>
|
||||||
public static ColorHSV Lerp(ColorHSV from, ColorHSV to, float t) => from + FromTo(from, to) * t;
|
public static ColorHSV Lerp(ColorHSV from, ColorHSV to, float t)
|
||||||
|
{
|
||||||
|
float hueDiff = to.Hue - from.Hue;
|
||||||
|
float saturationDiff = to.Saturation - from.Saturation;
|
||||||
|
float valueDiff = to.Value - from.Value;
|
||||||
|
|
||||||
|
return from + new ColorHSV(hueDiff * t, saturationDiff * t, valueDiff * t);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if two <see cref="ColorHSV"/>s are approximately equal within a specified epsilon range.
|
/// Checks if two <see cref="ColorHSV"/>s are approximately equal within a specified epsilon range.
|
||||||
@@ -174,9 +143,6 @@ public static class ColorHSVExtensions
|
|||||||
/// <inheritdoc cref="ColorHSV.Divide(ColorHSV, ColorHSV)" />
|
/// <inheritdoc cref="ColorHSV.Divide(ColorHSV, ColorHSV)" />
|
||||||
public static ColorHSV Divide(this ColorHSV color, float value) => ColorHSV.Divide(color, value);
|
public static ColorHSV Divide(this ColorHSV color, float value) => ColorHSV.Divide(color, value);
|
||||||
|
|
||||||
/// <inheritdoc cref="ColorHSV.FromTo(ColorHSV, ColorHSV)" />
|
|
||||||
public static ColorHSV FromTo(this ColorHSV from, ColorHSV to) => ColorHSV.FromTo(from, to);
|
|
||||||
|
|
||||||
/// <inheritdoc cref="ColorHSV.Lerp(ColorHSV, ColorHSV, float)" />
|
/// <inheritdoc cref="ColorHSV.Lerp(ColorHSV, ColorHSV, float)" />
|
||||||
public static ColorHSV Lerp(this ColorHSV from, ColorHSV to, float t) => ColorHSV.Lerp(from, to, t);
|
public static ColorHSV Lerp(this ColorHSV from, ColorHSV to, float t) => ColorHSV.Lerp(from, to, t);
|
||||||
|
|
||||||
|
189
Engine.Core/Primitives/ColorHSVA.cs
Normal file
189
Engine.Core/Primitives/ColorHSVA.cs
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
namespace Engine.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an HSV color.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hue">Hue of the <see cref="ColorHSVA"/>.</param>
|
||||||
|
/// <param name="saturation">Saturation of the <see cref="ColorHSVA"/>.</param>
|
||||||
|
/// <param name="value">Value of the <see cref="ColorHSVA"/>.</param>
|
||||||
|
/// <param name="alpha">Alpha of the <see cref="ColorHSVA"/>.</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// Initializes a new instance of the <see cref="ColorHSVA"/> struct with the specified values.
|
||||||
|
/// </remarks>
|
||||||
|
[System.Diagnostics.DebuggerDisplay("{ToString(),nq}")]
|
||||||
|
public readonly struct ColorHSVA(float hue, float saturation, float value, float alpha = 1)
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The Hue value of the <see cref="ColorHSVA"/>.
|
||||||
|
/// </summary>
|
||||||
|
public readonly float Hue = hue.Clamp(0f, 1f);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Saturation value of the <see cref="ColorHSVA"/>.
|
||||||
|
/// </summary>
|
||||||
|
public readonly float Saturation = saturation.Clamp(0f, 1f);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Value value of the <see cref="ColorHSVA"/>.
|
||||||
|
/// </summary>
|
||||||
|
public readonly float Value = value.Clamp(0f, 1f);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Alpha value of the <see cref="ColorHSVA"/>.
|
||||||
|
/// </summary>
|
||||||
|
public readonly float Alpha = alpha;
|
||||||
|
|
||||||
|
public static ColorHSVA operator -(ColorHSVA color) => new(color.Hue.OneMinus(), color.Saturation.OneMinus(), color.Value.OneMinus(), color.Alpha);
|
||||||
|
public static ColorHSVA operator +(ColorHSVA left, ColorHSVA right) => new(left.Hue + right.Hue, left.Saturation + right.Saturation, left.Value + right.Value, left.Alpha + right.Alpha);
|
||||||
|
public static ColorHSVA operator -(ColorHSVA left, ColorHSVA right) => new(left.Hue - right.Hue, left.Saturation - right.Saturation, left.Value - right.Value, left.Alpha - right.Alpha);
|
||||||
|
public static ColorHSVA operator *(ColorHSVA left, ColorHSVA right) => new(left.Hue * right.Hue, left.Saturation * right.Saturation, left.Value * right.Value, left.Alpha * right.Alpha);
|
||||||
|
public static ColorHSVA operator *(ColorHSVA color, float value) => new(color.Hue * value, color.Saturation * value, color.Value * value, color.Alpha * value);
|
||||||
|
public static ColorHSVA operator *(float value, ColorHSVA color) => new(color.Hue * value, color.Saturation * value, color.Value * value, color.Alpha * value);
|
||||||
|
public static ColorHSVA operator /(ColorHSVA color, float value) => new(color.Hue / value, color.Saturation / value, color.Value / value, color.Alpha / value);
|
||||||
|
public static bool operator ==(ColorHSVA left, ColorHSVA right) => left.Hue == right.Hue && left.Saturation == right.Saturation && left.Value == right.Value;
|
||||||
|
public static bool operator !=(ColorHSVA left, ColorHSVA right) => left.Hue != right.Hue || left.Saturation != right.Saturation || left.Value != right.Value;
|
||||||
|
|
||||||
|
public static implicit operator ColorHSVA(ColorHSV hsv) => new(hsv.Hue, hsv.Saturation, hsv.Value, 1f);
|
||||||
|
public static implicit operator ColorHSVA(ColorRGB rgb) => (ColorRGBA)rgb;
|
||||||
|
public static implicit operator ColorHSVA(ColorRGBA rgba)
|
||||||
|
{
|
||||||
|
float hue;
|
||||||
|
float saturation;
|
||||||
|
float value;
|
||||||
|
|
||||||
|
float rd = rgba.R / 255f;
|
||||||
|
float gd = rgba.G / 255f;
|
||||||
|
float bd = rgba.B / 255f;
|
||||||
|
|
||||||
|
float max = Math.Max(rd, Math.Max(gd, bd));
|
||||||
|
float min = Math.Min(rd, Math.Min(gd, bd));
|
||||||
|
float delta = max - min;
|
||||||
|
|
||||||
|
if (delta.ApproximatelyEquals(0))
|
||||||
|
hue = 0f;
|
||||||
|
else if (max.ApproximatelyEquals(rd))
|
||||||
|
hue = 60f * ((gd - bd) / delta % 6f);
|
||||||
|
else if (max.ApproximatelyEquals(gd))
|
||||||
|
hue = 60f * (((bd - rd) / delta) + 2f);
|
||||||
|
else
|
||||||
|
hue = 60f * (((rd - gd) / delta) + 4f);
|
||||||
|
|
||||||
|
if (hue < 0f)
|
||||||
|
hue += 360f;
|
||||||
|
|
||||||
|
hue /= 360f;
|
||||||
|
saturation = max.ApproximatelyEquals(0f) ? 0f : delta / max;
|
||||||
|
value = max;
|
||||||
|
|
||||||
|
return new(hue, saturation, value, rgba.A / 255f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inverts the given <see cref="ColorHSVA"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="color">The <see cref="ColorHSVA"/>.</param>
|
||||||
|
/// <returns>The inverted <see cref="ColorHSVA"/>.</returns>
|
||||||
|
public static ColorHSVA Invert(ColorHSVA color) => -color;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds two <see cref="ColorHSVA"/>s.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="left">The first <see cref="ColorHSVA"/>.</param>
|
||||||
|
/// <param name="right">The second <see cref="ColorHSVA"/>.</param>
|
||||||
|
/// <returns>The sum of the two <see cref="ColorHSVA"/>s.</returns>
|
||||||
|
public static ColorHSVA Add(ColorHSVA left, ColorHSVA right) => left + right;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Subtracts one <see cref="ColorHSVA"/> from another.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="left">The <see cref="ColorHSVA"/> to subtract from.</param>
|
||||||
|
/// <param name="right">The <see cref="ColorHSVA"/> to subtract.</param>
|
||||||
|
/// <returns>The result of subtracting the second <see cref="ColorHSVA"/> from the first.</returns>
|
||||||
|
public static ColorHSVA Subtract(ColorHSVA left, ColorHSVA right) => left - right;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Multiplies a <see cref="ColorHSVA"/> by a scalar value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="color">The <see cref="ColorHSVA"/>.</param>
|
||||||
|
/// <param name="value">The scalar value.</param>
|
||||||
|
/// <returns>The result of multiplying the <see cref="ColorHSVA"/> by the scalar value.</returns>
|
||||||
|
public static ColorHSVA Multiply(ColorHSVA color, float value) => color * value;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Divides a <see cref="ColorHSVA"/> by a scalar value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="color">The <see cref="ColorHSVA"/>.</param>
|
||||||
|
/// <param name="value">The scalar value.</param>
|
||||||
|
/// <returns>The result of dividing the <see cref="ColorHSVA"/> by the scalar value.</returns>
|
||||||
|
public static ColorHSVA Divide(ColorHSVA color, float value) => color / value;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs linear interpolation between two <see cref="ColorHSVA"/>s.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="from">The starting <see cref="ColorHSVA"/> (t = 0).</param>
|
||||||
|
/// <param name="to">The ending <see cref="ColorHSVA"/> (t = 1).</param>
|
||||||
|
/// <param name="t">The interpolation parameter.</param>
|
||||||
|
/// <returns>The interpolated <see cref="ColorHSVA"/>.</returns>
|
||||||
|
public static ColorHSVA Lerp(ColorHSVA from, ColorHSVA to, float t)
|
||||||
|
{
|
||||||
|
float hueDiff = to.Hue - from.Hue;
|
||||||
|
float saturationDiff = to.Saturation - from.Saturation;
|
||||||
|
float valueDiff = to.Value - from.Value;
|
||||||
|
float alphaDiff = to.Alpha - from.Alpha;
|
||||||
|
|
||||||
|
return from + new ColorHSVA(hueDiff * t, saturationDiff * t, valueDiff * t, alphaDiff * t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if two <see cref="ColorHSVA"/>s are approximately equal within a specified epsilon range.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="left">The first <see cref="ColorHSVA"/>.</param>
|
||||||
|
/// <param name="right">The second <see cref="ColorHSVA"/>.</param>
|
||||||
|
/// <param name="epsilon">The epsilon range.</param>
|
||||||
|
/// <returns><see cref="true"/> if the <see cref="ColorHSVA"/>s are approximately equal; otherwise, <see cref="false"/>.</returns>
|
||||||
|
public static bool ApproximatelyEquals(ColorHSVA left, ColorHSVA right, float epsilon = float.Epsilon)
|
||||||
|
=> left.Hue.ApproximatelyEquals(right.Hue, epsilon) && left.Saturation.ApproximatelyEquals(right.Saturation, epsilon) && left.Value.ApproximatelyEquals(right.Value, epsilon);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the specified object is equal to the current <see cref="ColorHSVA"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">The object to compare with the current <see cref="ColorHSVA"/>.</param>
|
||||||
|
/// <returns><see cref="true"/> if the specified object is equal to the current <see cref="ColorHSVA"/>; otherwise, <see cref="false"/>.</returns>
|
||||||
|
public override bool Equals(object? obj) => obj is ColorHSVA colorHSVA && this == colorHSVA;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a hash code for the <see cref="ColorHSVA"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A hash code for the <see cref="ColorHSVA"/>.</returns>
|
||||||
|
public override int GetHashCode() => System.HashCode.Combine(Hue, Saturation, Value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the <see cref="ColorHSVA"/> to its string representation.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string representation of the <see cref="ColorHSVA"/>.</returns>
|
||||||
|
public override string ToString() => $"{nameof(ColorHSVA)}({Hue}, {Saturation}, {Value})";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides extension methods for <see cref="ColorHSVA"/> type.
|
||||||
|
/// </summary>
|
||||||
|
public static class ColorHSVAExtensions
|
||||||
|
{
|
||||||
|
/// <inheritdoc cref="ColorHSVA.Add(ColorHSVA, ColorHSVA)" />
|
||||||
|
public static ColorHSVA Add(this ColorHSVA color, ColorHSVA value) => ColorHSVA.Add(color, value);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="ColorHSVA.Subtract(ColorHSVA, ColorHSVA)" />
|
||||||
|
public static ColorHSVA Subtract(this ColorHSVA color, ColorHSVA value) => ColorHSVA.Subtract(color, value);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="ColorHSVA.Multiply(ColorHSVA, ColorHSVA)" />
|
||||||
|
public static ColorHSVA Multiply(this ColorHSVA color, float value) => ColorHSVA.Multiply(color, value);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="ColorHSVA.Divide(ColorHSVA, ColorHSVA)" />
|
||||||
|
public static ColorHSVA Divide(this ColorHSVA color, float value) => ColorHSVA.Divide(color, value);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="ColorHSVA.Lerp(ColorHSVA, ColorHSVA, float)" />
|
||||||
|
public static ColorHSVA Lerp(this ColorHSVA from, ColorHSVA to, float t) => ColorHSVA.Lerp(from, to, t);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="ColorHSVA.ApproximatelyEquals(ColorHSVA, ColorHSVA, float) " />
|
||||||
|
public static bool ApproximatelyEquals(this ColorHSVA left, ColorHSVA right, float epsilon = float.Epsilon) => ColorHSVA.ApproximatelyEquals(left, right, epsilon);
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an RGB color.
|
/// Represents an RGB color.
|
||||||
@@ -38,30 +38,8 @@ public readonly struct ColorRGB(byte r, byte g, byte b)
|
|||||||
public static bool operator !=(ColorRGB left, ColorRGB right) => left.R != right.R || left.G != right.G || left.B != right.B;
|
public static bool operator !=(ColorRGB left, ColorRGB right) => left.R != right.R || left.G != right.G || left.B != right.B;
|
||||||
|
|
||||||
public static implicit operator ColorRGB(ColorRGBA rgba) => new(rgba.R, rgba.G, rgba.B);
|
public static implicit operator ColorRGB(ColorRGBA rgba) => new(rgba.R, rgba.G, rgba.B);
|
||||||
public static implicit operator ColorRGB(ColorHSV hsv)
|
public static implicit operator ColorRGB(ColorHSVA hsva) => (ColorRGBA)hsva;
|
||||||
{
|
public static implicit operator ColorRGB(ColorHSV hsv) => (ColorRGBA)hsv;
|
||||||
float hue = hsv.Hue * 360f;
|
|
||||||
float chroma = hsv.Value * hsv.Saturation;
|
|
||||||
float x = chroma * (1f - Math.Abs(hue / 60f % 2f - 1f));
|
|
||||||
float m = hsv.Value - chroma;
|
|
||||||
|
|
||||||
float r1 = 0f;
|
|
||||||
float g1 = 0f;
|
|
||||||
float b1 = 0f;
|
|
||||||
|
|
||||||
if (hue < 60) { r1 = chroma; g1 = x; b1 = 0; }
|
|
||||||
else if (hue < 120) { r1 = x; g1 = chroma; b1 = 0; }
|
|
||||||
else if (hue < 180) { r1 = 0; g1 = chroma; b1 = x; }
|
|
||||||
else if (hue < 240) { r1 = 0; g1 = x; b1 = chroma; }
|
|
||||||
else if (hue < 300) { r1 = x; g1 = 0; b1 = chroma; }
|
|
||||||
else if (hue <= 360) { r1 = chroma; g1 = 0; b1 = x; }
|
|
||||||
|
|
||||||
byte r = (byte)Math.RoundToInt((r1 + m) * 255);
|
|
||||||
byte g = (byte)Math.RoundToInt((g1 + m) * 255);
|
|
||||||
byte b = (byte)Math.RoundToInt((b1 + m) * 255);
|
|
||||||
|
|
||||||
return new(r, g, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Inverts the given <see cref="ColorRGB"/>.
|
/// Inverts the given <see cref="ColorRGB"/>.
|
||||||
@@ -102,14 +80,6 @@ public readonly struct ColorRGB(byte r, byte g, byte b)
|
|||||||
/// <returns>The result of dividing the <see cref="ColorRGB"/> by the scalar value.</returns>
|
/// <returns>The result of dividing the <see cref="ColorRGB"/> by the scalar value.</returns>
|
||||||
public static ColorRGB Divide(ColorRGB color, float value) => color / value;
|
public static ColorRGB Divide(ColorRGB color, float value) => color / value;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates the <see cref="ColorRGB"/> from one point to another.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="from">The starting point.</param>
|
|
||||||
/// <param name="to">The ending point.</param>
|
|
||||||
/// <returns>The <see cref="ColorRGB"/> from the starting point to the ending point.</returns>
|
|
||||||
public static ColorRGB FromTo(ColorRGB from, ColorRGB to) => to - from;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs linear interpolation between two <see cref="ColorRGB"/>s.
|
/// Performs linear interpolation between two <see cref="ColorRGB"/>s.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -117,7 +87,14 @@ public readonly struct ColorRGB(byte r, byte g, byte b)
|
|||||||
/// <param name="to">The ending <see cref="ColorRGB"/> (t = 1).</param>
|
/// <param name="to">The ending <see cref="ColorRGB"/> (t = 1).</param>
|
||||||
/// <param name="t">The interpolation parameter.</param>
|
/// <param name="t">The interpolation parameter.</param>
|
||||||
/// <returns>The interpolated <see cref="ColorRGB"/>.</returns>
|
/// <returns>The interpolated <see cref="ColorRGB"/>.</returns>
|
||||||
public static ColorRGB Lerp(ColorRGB from, ColorRGB to, float t) => from + FromTo(from, to) * t;
|
public static ColorRGB Lerp(ColorRGB from, ColorRGB to, float t)
|
||||||
|
{
|
||||||
|
int redDiff = to.R - from.R;
|
||||||
|
int greenDiff = to.G - from.G;
|
||||||
|
int blueDiff = to.B - from.B;
|
||||||
|
|
||||||
|
return from + new ColorRGB((byte)(redDiff * t), (byte)(greenDiff * t), (byte)(blueDiff * t));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether the specified object is equal to the current <see cref="ColorRGB"/>.
|
/// Determines whether the specified object is equal to the current <see cref="ColorRGB"/>.
|
||||||
@@ -156,9 +133,6 @@ public static class ColorRGBExtensions
|
|||||||
/// <inheritdoc cref="ColorRGB.Divide(ColorRGB, ColorRGB)" />
|
/// <inheritdoc cref="ColorRGB.Divide(ColorRGB, ColorRGB)" />
|
||||||
public static ColorRGB Divide(this ColorRGB color, float value) => ColorRGB.Divide(color, value);
|
public static ColorRGB Divide(this ColorRGB color, float value) => ColorRGB.Divide(color, value);
|
||||||
|
|
||||||
/// <inheritdoc cref="ColorRGB.FromTo(ColorRGB, ColorRGB)" />
|
|
||||||
public static ColorRGB FromTo(this ColorRGB from, ColorRGB to) => ColorRGB.FromTo(from, to);
|
|
||||||
|
|
||||||
/// <inheritdoc cref="ColorRGB.Lerp(ColorRGB, ColorRGB, float)" />
|
/// <inheritdoc cref="ColorRGB.Lerp(ColorRGB, ColorRGB, float)" />
|
||||||
public static ColorRGB Lerp(this ColorRGB from, ColorRGB to, float t) => ColorRGB.Lerp(from, to, t);
|
public static ColorRGB Lerp(this ColorRGB from, ColorRGB to, float t) => ColorRGB.Lerp(from, to, t);
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an RGBA color.
|
/// Represents an RGBA color.
|
||||||
@@ -44,7 +44,31 @@ public readonly struct ColorRGBA(byte r, byte g, byte b, byte a = 255)
|
|||||||
public static bool operator !=(ColorRGBA left, ColorRGBA right) => left.R != right.R || left.G != right.G || left.B != right.B || left.A != right.A;
|
public static bool operator !=(ColorRGBA left, ColorRGBA right) => left.R != right.R || left.G != right.G || left.B != right.B || left.A != right.A;
|
||||||
|
|
||||||
public static implicit operator ColorRGBA(ColorRGB rgb) => new(rgb.R, rgb.G, rgb.B, 255);
|
public static implicit operator ColorRGBA(ColorRGB rgb) => new(rgb.R, rgb.G, rgb.B, 255);
|
||||||
public static implicit operator ColorRGBA(ColorHSV hsv) => (ColorRGB)hsv;
|
public static implicit operator ColorRGBA(ColorHSV hsv) => (ColorHSVA)hsv;
|
||||||
|
public static implicit operator ColorRGBA(ColorHSVA hsva)
|
||||||
|
{
|
||||||
|
float hue = hsva.Hue * 360f;
|
||||||
|
float chroma = hsva.Value * hsva.Saturation;
|
||||||
|
float x = chroma * (1f - Math.Abs(hue / 60f % 2f - 1f));
|
||||||
|
float m = hsva.Value - chroma;
|
||||||
|
|
||||||
|
float r1 = 0f;
|
||||||
|
float g1 = 0f;
|
||||||
|
float b1 = 0f;
|
||||||
|
|
||||||
|
if (hue < 60) { r1 = chroma; g1 = x; b1 = 0; }
|
||||||
|
else if (hue < 120) { r1 = x; g1 = chroma; b1 = 0; }
|
||||||
|
else if (hue < 180) { r1 = 0; g1 = chroma; b1 = x; }
|
||||||
|
else if (hue < 240) { r1 = 0; g1 = x; b1 = chroma; }
|
||||||
|
else if (hue < 300) { r1 = x; g1 = 0; b1 = chroma; }
|
||||||
|
else if (hue <= 360) { r1 = chroma; g1 = 0; b1 = x; }
|
||||||
|
|
||||||
|
byte r = (byte)Math.RoundToInt((r1 + m) * 255);
|
||||||
|
byte g = (byte)Math.RoundToInt((g1 + m) * 255);
|
||||||
|
byte b = (byte)Math.RoundToInt((b1 + m) * 255);
|
||||||
|
|
||||||
|
return new(r, g, b, (byte)(hsva.Alpha * 255));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Inverts the given <see cref="ColorRGBA"/>.
|
/// Inverts the given <see cref="ColorRGBA"/>.
|
||||||
@@ -85,14 +109,6 @@ public readonly struct ColorRGBA(byte r, byte g, byte b, byte a = 255)
|
|||||||
/// <returns>The result of dividing the <see cref="ColorRGBA"/> by the scalar value.</returns>
|
/// <returns>The result of dividing the <see cref="ColorRGBA"/> by the scalar value.</returns>
|
||||||
public static ColorRGBA Divide(ColorRGBA color, float value) => color / value;
|
public static ColorRGBA Divide(ColorRGBA color, float value) => color / value;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates the <see cref="ColorRGBA"/> from one point to another.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="from">The starting point.</param>
|
|
||||||
/// <param name="to">The ending point.</param>
|
|
||||||
/// <returns>The <see cref="ColorRGBA"/> from the starting point to the ending point.</returns>
|
|
||||||
public static ColorRGBA FromTo(ColorRGBA from, ColorRGBA to) => to - from;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs linear interpolation between two <see cref="ColorRGBA"/>s.
|
/// Performs linear interpolation between two <see cref="ColorRGBA"/>s.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -100,7 +116,15 @@ public readonly struct ColorRGBA(byte r, byte g, byte b, byte a = 255)
|
|||||||
/// <param name="to">The ending <see cref="ColorRGBA"/> (t = 1).</param>
|
/// <param name="to">The ending <see cref="ColorRGBA"/> (t = 1).</param>
|
||||||
/// <param name="t">The interpolation parameter.</param>
|
/// <param name="t">The interpolation parameter.</param>
|
||||||
/// <returns>The interpolated <see cref="ColorRGBA"/>.</returns>
|
/// <returns>The interpolated <see cref="ColorRGBA"/>.</returns>
|
||||||
public static ColorRGBA Lerp(ColorRGBA from, ColorRGBA to, float t) => from + FromTo(from, to) * t;
|
public static ColorRGBA Lerp(ColorRGBA from, ColorRGBA to, float t)
|
||||||
|
{
|
||||||
|
int redDiff = to.R - from.R;
|
||||||
|
int greenDiff = to.G - from.G;
|
||||||
|
int blueDiff = to.B - from.B;
|
||||||
|
int alphaDiff = to.A - from.A;
|
||||||
|
|
||||||
|
return from + new ColorRGBA((byte)(redDiff * t), (byte)(greenDiff * t), (byte)(blueDiff * t), (byte)(alphaDiff * t));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether the specified object is equal to the current <see cref="ColorRGBA"/>.
|
/// Determines whether the specified object is equal to the current <see cref="ColorRGBA"/>.
|
||||||
@@ -139,9 +163,6 @@ public static class ColorRGBAExtensions
|
|||||||
/// <inheritdoc cref="ColorRGBA.Divide(ColorRGBA, ColorRGBA)" />
|
/// <inheritdoc cref="ColorRGBA.Divide(ColorRGBA, ColorRGBA)" />
|
||||||
public static ColorRGBA Divide(this ColorRGBA color, float value) => ColorRGBA.Divide(color, value);
|
public static ColorRGBA Divide(this ColorRGBA color, float value) => ColorRGBA.Divide(color, value);
|
||||||
|
|
||||||
/// <inheritdoc cref="ColorRGBA.FromTo(ColorRGBA, ColorRGBA)" />
|
|
||||||
public static ColorRGBA FromTo(this ColorRGBA from, ColorRGBA to) => ColorRGBA.FromTo(from, to);
|
|
||||||
|
|
||||||
/// <inheritdoc cref="ColorRGBA.Lerp(ColorRGBA, ColorRGBA, float)" />
|
/// <inheritdoc cref="ColorRGBA.Lerp(ColorRGBA, ColorRGBA, float)" />
|
||||||
public static ColorRGBA Lerp(this ColorRGBA from, ColorRGBA to, float t) => ColorRGBA.Lerp(from, to, t);
|
public static ColorRGBA Lerp(this ColorRGBA from, ColorRGBA to, float t) => ColorRGBA.Lerp(from, to, t);
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a 2D line segment defined by two endpoints.
|
/// Represents a 2D line segment defined by two endpoints.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a <see cref="Line2DEquation"/> in the form y = mx + b.
|
/// Represents a <see cref="Line2DEquation"/> in the form y = mx + b.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a range of values along a single axis.
|
/// Represents a range of values along a single axis.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a 3D space rotation.
|
/// Represents a 3D space rotation.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an infinite ray in 2D space.
|
/// Represents an infinite ray in 2D space.
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a shape defined by a collection of vertices.
|
/// Represents a shape defined by a collection of vertices.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
[System.Diagnostics.DebuggerDisplay("A: {A.ToString(), nq}, B: {B.ToString(), nq}, B: {C.ToString(), nq}")]
|
[System.Diagnostics.DebuggerDisplay("A: {A.ToString(), nq}, B: {B.ToString(), nq}, B: {C.ToString(), nq}")]
|
||||||
public readonly struct Triangle(Vector2D A, Vector2D B, Vector2D C)
|
public readonly struct Triangle(Vector2D A, Vector2D B, Vector2D C)
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a two-dimensional vector.
|
/// Represents a two-dimensional vector.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a three-dimensional vector.
|
/// Represents a three-dimensional vector.
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Serialization;
|
namespace Engine.Core.Serialization;
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Class)]
|
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Class)]
|
||||||
public class IgnoreSerializationAttribute : Attribute;
|
public class IgnoreSerializationAttribute : Attribute;
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Serialization;
|
namespace Engine.Core.Serialization;
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
|
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
|
||||||
public class SerializeAllAttribute : Attribute;
|
public class SerializeAllAttribute : Attribute;
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Serialization;
|
namespace Engine.Core.Serialization;
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
||||||
public class SerializeAttribute : Attribute;
|
public class SerializeAttribute : Attribute;
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
namespace Syntriax.Engine.Core.Serialization;
|
namespace Engine.Core.Serialization;
|
||||||
|
|
||||||
public record class EntityReference(string? Id = null);
|
public record class EntityReference(string? Id = null);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Serialization;
|
namespace Engine.Core.Serialization;
|
||||||
|
|
||||||
public class EntityRegistry
|
public class EntityRegistry
|
||||||
{
|
{
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Serialization;
|
namespace Engine.Core.Serialization;
|
||||||
|
|
||||||
public interface ISerializer
|
public interface ISerializer
|
||||||
{
|
{
|
||||||
|
@@ -2,9 +2,9 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
using Syntriax.Engine.Core.Factory;
|
using Engine.Core.Factory;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Serialization;
|
namespace Engine.Core.Serialization;
|
||||||
|
|
||||||
public class SerializedClass
|
public class SerializedClass
|
||||||
{
|
{
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user