Compare commits
39 Commits
main
...
developmen
Author | SHA1 | Date | |
---|---|---|---|
5c1c025fe3 | |||
1d292a104e | |||
70c884acfe | |||
a9f5974568 | |||
dae72b11c5 | |||
58eb373c79 | |||
00f7b1aaab | |||
9e4c74ed1d | |||
2e2306c5bb | |||
86b8cd9b55 | |||
bfbcfdce4f | |||
80202d4a07 | |||
2be99d2142 | |||
4081693d32 | |||
193d23c877 | |||
c135035d5b | |||
fabc485689 | |||
48710b0a7f | |||
bf34e52dc8 | |||
e3845a2f5c | |||
26a80452bc | |||
2535a1d6ec | |||
3a385900fb | |||
b94bbc8ed7 | |||
3f7a646bf0 | |||
f119a23d2b | |||
61488aa0e5 | |||
66b46e3d36 | |||
1ee07b41f8 | |||
6f425776cc | |||
98c9dde98a | |||
04d325f38b | |||
901585d4bb | |||
33a452a62e | |||
906edf096e | |||
d1129c95df | |||
40f483974d | |||
4b856420f9 | |||
7f93d95f6b |
@ -1,26 +0,0 @@
|
|||||||
namespace Syntriax.Engine.Core.Abstract;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="ITransform2D"/> field.
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasGameManager : IAssignable
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Event triggered when the <see cref="IGameManager"/> value has has been assigned a new value.
|
|
||||||
/// </summary>
|
|
||||||
event GameManagerAssignedEventHandler? OnGameManagerAssigned;
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IGameManager" />
|
|
||||||
IGameManager GameManager { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Assign a value to the <see cref="IGameManager"/> field of this object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="gameManager">New <see cref="IGameManager"/> to assign.</param>
|
|
||||||
/// <returns>
|
|
||||||
/// <see cref="true"/>, if the value given assigned successfully assigned, <see cref="false"/> if not.
|
|
||||||
/// </returns>
|
|
||||||
bool Assign(IGameManager gameManager);
|
|
||||||
|
|
||||||
delegate void GameManagerAssignedEventHandler(IHasGameManager sender);
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
namespace Syntriax.Engine.Core.Abstract;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IHierarchyObject"/> field.
|
|
||||||
/// </summary>
|
|
||||||
public interface IHasHierarchyObject : IAssignable
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Event triggered when the <see cref="IHierarchyObject"/> value has has been assigned a new value.
|
|
||||||
/// </summary>
|
|
||||||
event HierarchyObjectAssignedEventHandler? OnHierarchyObjectAssigned;
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IHierarchyObject" />
|
|
||||||
IHierarchyObject HierarchyObject { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Assign a value to the <see cref="IHierarchyObject"/> field of this object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hierarchyObject">New <see cref="IHierarchyObject"/> to assign.</param>
|
|
||||||
/// <returns>
|
|
||||||
/// <see cref="true"/>, if the value given assigned successfully assigned, <see cref="false"/> if not.
|
|
||||||
/// </returns>
|
|
||||||
bool Assign(IHierarchyObject hierarchyObject);
|
|
||||||
|
|
||||||
delegate void HierarchyObjectAssignedEventHandler(IHasHierarchyObject sender);
|
|
||||||
}
|
|
26
Engine.Core/Abstract/Assignable/IHasUniverse.cs
Normal file
26
Engine.Core/Abstract/Assignable/IHasUniverse.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
namespace Syntriax.Engine.Core.Abstract;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IUniverse"/> field.
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasUniverse : IAssignable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Event triggered when the <see cref="IUniverse"/> value has has been assigned a new value.
|
||||||
|
/// </summary>
|
||||||
|
event UniverseAssignedEventHandler? OnUniverseAssigned;
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IUniverse" />
|
||||||
|
IUniverse Universe { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Assign a value to the <see cref="IUniverse"/> field of this object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="universe">New <see cref="IUniverse"/> to assign.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// <see cref="true"/>, if the value given assigned successfully assigned, <see cref="false"/> if not.
|
||||||
|
/// </returns>
|
||||||
|
bool Assign(IUniverse universe);
|
||||||
|
|
||||||
|
delegate void UniverseAssignedEventHandler(IHasUniverse sender);
|
||||||
|
}
|
26
Engine.Core/Abstract/Assignable/IHasUniverseObject.cs
Normal file
26
Engine.Core/Abstract/Assignable/IHasUniverseObject.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
namespace Syntriax.Engine.Core.Abstract;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IUniverseObject"/> field.
|
||||||
|
/// </summary>
|
||||||
|
public interface IHasUniverseObject : IAssignable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Event triggered when the <see cref="IUniverseObject"/> value has has been assigned a new value.
|
||||||
|
/// </summary>
|
||||||
|
event UniverseObjectAssignedEventHandler? OnUniverseObjectAssigned;
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IUniverseObject" />
|
||||||
|
IUniverseObject UniverseObject { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Assign a value to the <see cref="IUniverseObject"/> field of this object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="universeObject">New <see cref="IUniverseObject"/> to assign.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// <see cref="true"/>, if the value given assigned successfully assigned, <see cref="false"/> if not.
|
||||||
|
/// </returns>
|
||||||
|
bool Assign(IUniverseObject universeObject);
|
||||||
|
|
||||||
|
delegate void UniverseObjectAssignedEventHandler(IHasUniverseObject sender);
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
namespace Syntriax.Engine.Core.Abstract;
|
namespace Syntriax.Engine.Core.Abstract;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a behaviour that any object in the game 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.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IBehaviour : IEntity, IActive, IHasBehaviourController, IHasStateEnable
|
public interface IBehaviour : IEntity, IActive, IHasBehaviourController, IHasStateEnable
|
||||||
{
|
{
|
||||||
|
@ -4,10 +4,10 @@ namespace Syntriax.Engine.Core.Abstract;
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a collector for the class type of <typeparamref name="T"/>.
|
/// Represents a collector for the class type of <typeparamref name="T"/>.
|
||||||
/// Provides mechanisms for tracking additions and removals, and notifies subscribers when such events occur on the assigned <see cref="IGameManager"/>.
|
/// Provides mechanisms for tracking additions and removals, and notifies subscribers when such events occur on the assigned <see cref="IUniverse"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The type of objects tracked by the collector.</typeparam>
|
/// <typeparam name="T">The type of objects tracked by the collector.</typeparam>
|
||||||
public interface IBehaviourCollector<T> : IHasGameManager, IEnumerable<T> where T : class
|
public interface IBehaviourCollector<T> : IHasUniverse, IEnumerable<T> where T : class
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event triggered when an object of type <typeparamref name="T"/> is added to the collector.
|
/// Event triggered when an object of type <typeparamref name="T"/> is added to the collector.
|
||||||
|
@ -3,9 +3,9 @@ using System.Collections.Generic;
|
|||||||
namespace Syntriax.Engine.Core.Abstract;
|
namespace Syntriax.Engine.Core.Abstract;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a controller for managing <see cref="IBehaviour"/>s and notify them accordingly about the engine's updates. Connected to an <see cref="IHierarchyObject"/>.
|
/// Represents a controller for managing <see cref="IBehaviour"/>s and notify them accordingly about the engine's updates. Connected to an <see cref="IUniverseObject"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IBehaviourController : IInitializable, IHasHierarchyObject, IEnumerable<IBehaviour>
|
public interface IBehaviourController : IInitializable, IHasUniverseObject, IEnumerable<IBehaviour>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event triggered before the update of <see cref="IBehaviour"/>s.
|
/// Event triggered before the update of <see cref="IBehaviour"/>s.
|
||||||
@ -60,7 +60,7 @@ public interface IBehaviourController : IInitializable, IHasHierarchyObject, IEn
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The type of <see cref="IBehaviour"/>s to get.</typeparam>
|
/// <typeparam name="T">The type of <see cref="IBehaviour"/>s to get.</typeparam>
|
||||||
/// <returns>A list of <see cref="IBehaviour"/>s of the specified type.</returns>
|
/// <returns>A list of <see cref="IBehaviour"/>s of the specified type.</returns>
|
||||||
IList<T> GetBehaviours<T>();
|
IReadOnlyList<T> GetBehaviours<T>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all <see cref="IBehaviour"/>s of the specified type and stores them in the provided list.
|
/// Gets all <see cref="IBehaviour"/>s of the specified type and stores them in the provided list.
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Abstract;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a game world responsible for managing <see cref="IHierarchyObject"/>s.
|
|
||||||
/// </summary>
|
|
||||||
public interface IGameManager : IEntity, IEnumerable<IHierarchyObject>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Event triggered when <see cref="Update(double)"/> is called on the <see cref="IGameManager"/>.
|
|
||||||
/// </summary>
|
|
||||||
event UpdateEventHandler? OnUpdate;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event triggered when <see cref="PreDraw"/> is called on the <see cref="IGameManager"/>.
|
|
||||||
/// </summary>
|
|
||||||
event PreDawEventHandler? OnPreDraw;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event triggered when a <see cref="IHierarchyObject"/> is registered to the <see cref="IGameManager"/>.
|
|
||||||
/// </summary>
|
|
||||||
event HierarchyObjectRegisteredEventHandler? OnHierarchyObjectRegistered;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event triggered when a <see cref="IHierarchyObject"/> is unregistered from the <see cref="IGameManager"/>.
|
|
||||||
/// </summary>
|
|
||||||
event HierarchyObjectUnRegisteredEventHandler? OnHierarchyObjectUnRegistered;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Contains time data related to this <see cref="IGameManager"/>.
|
|
||||||
/// </summary>
|
|
||||||
EngineTime Time { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a read-only list of <see cref="IHierarchyObject"/>s managed by the <see cref="IGameManager"/>.
|
|
||||||
/// </summary>
|
|
||||||
IReadOnlyList<IHierarchyObject> HierarchyObjects { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Registers an <see cref="IHierarchyObject"/> to the <see cref="IGameManager"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hierarchyObject">The <see cref="IHierarchyObject"/> to register.</param>
|
|
||||||
void Register(IHierarchyObject hierarchyObject);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Instantiates a <see cref="IHierarchyObject"/> of type T with the given arguments and registers it to the <see cref="IGameManager"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">The type of <see cref="IHierarchyObject"/> to instantiate.</typeparam>
|
|
||||||
/// <param name="args">Constructor parameters for the given type of <see cref="IHierarchyObject"/>.</param>
|
|
||||||
/// <returns>The instantiated <see cref="IHierarchyObject"/>.</returns>
|
|
||||||
T InstantiateHierarchyObject<T>(params object?[]? args) where T : class, IHierarchyObject;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes an <see cref="IHierarchyObject"/> from the <see cref="IGameManager"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hierarchyObject">The <see cref="IHierarchyObject"/> to remove.</param>
|
|
||||||
void Remove(IHierarchyObject hierarchyObject);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Updates the <see cref="IGameManager"/> with the given delta time.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="engineTime">Delta time.</param>
|
|
||||||
void Update(EngineTime engineTime);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Performs operations that should be done before the draw calls.
|
|
||||||
/// </summary>
|
|
||||||
void PreDraw();
|
|
||||||
|
|
||||||
delegate void UpdateEventHandler(IGameManager sender, EngineTime engineTime);
|
|
||||||
delegate void PreDawEventHandler(IGameManager sender);
|
|
||||||
|
|
||||||
delegate void HierarchyObjectRegisteredEventHandler(IGameManager sender, IHierarchyObject hierarchyObjectRegistered);
|
|
||||||
delegate void HierarchyObjectUnRegisteredEventHandler(IGameManager sender, IHierarchyObject hierarchyObjectUnregistered);
|
|
||||||
}
|
|
@ -1,131 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Abstract;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents an <see cref="IEntity"/> that can enter and exit a hierarchy within the <see cref="IGameManager"/> system.
|
|
||||||
/// This interface allows for tracking the object's presence in the hierarchy and provides events
|
|
||||||
/// for notifying when the see enters or exits the hierarchy.
|
|
||||||
/// </summary>
|
|
||||||
public interface IHierarchyObject : IEntity, IActive, INameable, IHasBehaviourController, IEnumerable<IHierarchyObject>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Event triggered when the <see cref="IHierarchyObject"/> enters the hierarchy.
|
|
||||||
/// </summary>
|
|
||||||
event EnteredHierarchyEventHandler? OnEnteredHierarchy;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event triggered when the <see cref="IHierarchyObject"/> exits the hierarchy.
|
|
||||||
/// </summary>
|
|
||||||
event ExitedHierarchyEventHandler? OnExitedHierarchy;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event triggered when the <see cref="Parent"/> of the <see cref="IHierarchyObject"/> changes. The second parameter is the old <see cref="IHierarchyObject"/>.
|
|
||||||
/// </summary>
|
|
||||||
event ParentChangedEventHandler? OnParentChanged;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event triggered when a new <see cref="IHierarchyObject"/> is added to the <see cref="Children"/>.
|
|
||||||
/// </summary>
|
|
||||||
event ChildrenAddedEventHandler? OnChildrenAdded;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event triggered when an <see cref="IHierarchyObject"/> is removed from the <see cref="Children"/>.
|
|
||||||
/// </summary>
|
|
||||||
event ChildrenRemovedEventHandler? OnChildrenRemoved;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the <see cref="IGameManager"/> this <see cref="IHierarchyObject"/> is connected to, if any.
|
|
||||||
/// </summary>
|
|
||||||
IGameManager GameManager { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates whether the <see cref="IHierarchyObject"/> is currently in the hierarchy.
|
|
||||||
/// </summary>
|
|
||||||
bool IsInHierarchy { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The parent <see cref="IHierarchyObject"/> of the <see cref="IHierarchyObject"/>.
|
|
||||||
/// </summary>
|
|
||||||
IHierarchyObject? Parent { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The <see cref="IHierarchyObject"/>s that have this <see cref="IHierarchyObject"/> as their <see cref="Parent"/>.
|
|
||||||
/// </summary>
|
|
||||||
IReadOnlyList<IHierarchyObject> Children { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Internal method to handle entering the hierarchy.
|
|
||||||
/// This should be called by the system to properly manage hierarchy states.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="gameManager">The <see cref="IGameManager"/> that is managing this hierarchy.</param>
|
|
||||||
/// <returns>
|
|
||||||
/// <see cref="true"/> if the <see cref="IHierarchyObject"/> successfully entered the hierarchy;
|
|
||||||
/// <see cref="false"/> if it failed to do so.
|
|
||||||
/// </returns>
|
|
||||||
internal bool EnterHierarchy(IGameManager gameManager);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Internal method to handle exiting the hierarchy.
|
|
||||||
/// This should be called by the system to properly manage hierarchy states.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>
|
|
||||||
/// <see cref="true"/> if the <see cref="IHierarchyObject"/> successfully exited the hierarchy;
|
|
||||||
/// <see cref="false"/> if it failed to do so.
|
|
||||||
/// </returns>
|
|
||||||
internal bool ExitHierarchy();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the parent <see cref="IHierarchyObject"/> of this <see cref="IHierarchyObject"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hierarchyObject">The parent <see cref="IHierarchyObject"/> to set.</param>
|
|
||||||
void SetParent(IHierarchyObject? hierarchyObject);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a child <see cref="IHierarchyObject"/> to this <see cref="IHierarchyObject"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hierarchyObject">The child <see cref="IHierarchyObject"/> to add.</param>
|
|
||||||
void AddChild(IHierarchyObject hierarchyObject);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes a child <see cref="IHierarchyObject"/> from this <see cref="IHierarchyObject"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hierarchyObject">The child <see cref="IHierarchyObject"/> to remove.</param>
|
|
||||||
void RemoveChild(IHierarchyObject hierarchyObject);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// EventHandler delegate for the event triggered when the <see cref="IHierarchyObject"/> enters the hierarchy of a <see cref="IGameManager">.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender">The <see cref="IHierarchyObject"/> that entered the hierarchy.</param>
|
|
||||||
/// <param name="gameManager">The <see cref="IGameManager"/> that the <see cref="IHierarchyObject"/> has entered it's hierarchy.</param>
|
|
||||||
delegate void EnteredHierarchyEventHandler(IHierarchyObject sender, IGameManager gameManager);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// EventHandler delegate for the event triggered when the <see cref="IHierarchyObject"/> exits the hierarchy of a <see cref="IGameManager">.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender">The <see cref="IHierarchyObject"/> that exited the hierarchy.</param>
|
|
||||||
/// <param name="gameManager">The <see cref="IGameManager"/> that the <see cref="IHierarchyObject"/> has exited it's hierarchy.</param>
|
|
||||||
delegate void ExitedHierarchyEventHandler(IHierarchyObject sender, IGameManager gameManager);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Delegate for the event triggered when the <see cref="IHierarchyObject"/>'s parent changes.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender">The <see cref="IHierarchyObject"/> that the parent has changed.</param>
|
|
||||||
/// <param name="previousParent">The previous <see cref="IHierarchyObject"/> the sender was a child of.</param>
|
|
||||||
/// <param name="newParent">The new and current <see cref="IHierarchyObject"/> the sender is a child of.</param>
|
|
||||||
delegate void ParentChangedEventHandler(IHierarchyObject sender, IHierarchyObject? previousParent, IHierarchyObject? newParent);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Delegate for the event triggered when a new <see cref="IHierarchyObject"/> added as a child.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender">The parent <see cref="IHierarchyObject"/> this event is being called from.</param>
|
|
||||||
/// <param name="childrenAdded">The <see cref="IHierarchyObject"/> that got removed as a children of the sender <see cref="IHierarchyObject"/>.</param>
|
|
||||||
delegate void ChildrenAddedEventHandler(IHierarchyObject sender, IHierarchyObject childrenAdded);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Delegate for the event triggered when a new <see cref="IHierarchyObject"/> removed from being a child.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender">The parent <see cref="IHierarchyObject"/> this event is being called from.</param>
|
|
||||||
/// <param name="childrenAdded">The <see cref="IHierarchyObject"/> that got removed as a children of the sender <see cref="IHierarchyObject"/>.</param>
|
|
||||||
delegate void ChildrenRemovedEventHandler(IHierarchyObject sender, IHierarchyObject childrenRemoved);
|
|
||||||
}
|
|
91
Engine.Core/Abstract/IUniverse.cs
Normal file
91
Engine.Core/Abstract/IUniverse.cs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.Core.Abstract;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a universe responsible for managing <see cref="IUniverseObject"/>s.
|
||||||
|
/// </summary>
|
||||||
|
public interface IUniverse : IEntity, IEnumerable<IUniverseObject>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Event triggered when <see cref="Update(UniverseTime)"/> is about to be called called on the <see cref="IUniverse"/>.
|
||||||
|
/// </summary>
|
||||||
|
event UpdateEventHandler? OnPreUpdate;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event triggered when <see cref="Update(UniverseTime)"/> is called on the <see cref="IUniverse"/>.
|
||||||
|
/// </summary>
|
||||||
|
event UpdateEventHandler? OnUpdate;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event triggered when <see cref="PreDraw"/> is called on the <see cref="IUniverse"/>.
|
||||||
|
/// </summary>
|
||||||
|
event PreDrawEventHandler? OnPreDraw;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event triggered when a <see cref="IUniverseObject"/> is registered to the <see cref="IUniverse"/>.
|
||||||
|
/// </summary>
|
||||||
|
event UniverseObjectRegisteredEventHandler? OnUniverseObjectRegistered;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event triggered when a <see cref="IUniverseObject"/> is unregistered from the <see cref="IUniverse"/>.
|
||||||
|
/// </summary>
|
||||||
|
event UniverseObjectUnRegisteredEventHandler? OnUniverseObjectUnRegistered;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Current time scale the <see cref="IUniverse"/> operates on.
|
||||||
|
/// </summary>
|
||||||
|
float TimeScale { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains time data related to this <see cref="IUniverse"/>.
|
||||||
|
/// </summary>
|
||||||
|
UniverseTime Time { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains unscaled time data related to this <see cref="IUniverse"/>.
|
||||||
|
/// </summary>
|
||||||
|
UniverseTime UnscaledTime { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a read-only list of <see cref="IUniverseObject"/>s managed by the <see cref="IUniverse"/>.
|
||||||
|
/// </summary>
|
||||||
|
IReadOnlyList<IUniverseObject> UniverseObjects { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers an <see cref="IUniverseObject"/> to the <see cref="IUniverse"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="universeObject">The <see cref="IUniverseObject"/> to register.</param>
|
||||||
|
void Register(IUniverseObject universeObject);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Instantiates a <see cref="IUniverseObject"/> of type T with the given arguments and registers it to the <see cref="IUniverse"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type of <see cref="IUniverseObject"/> to instantiate.</typeparam>
|
||||||
|
/// <param name="args">Constructor parameters for the given type of <see cref="IUniverseObject"/>.</param>
|
||||||
|
/// <returns>The instantiated <see cref="IUniverseObject"/>.</returns>
|
||||||
|
T InstantiateUniverseObject<T>(params object?[]? args) where T : class, IUniverseObject;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes an <see cref="IUniverseObject"/> from the <see cref="IUniverse"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="universeObject">The <see cref="IUniverseObject"/> to remove.</param>
|
||||||
|
void Remove(IUniverseObject universeObject);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the <see cref="IUniverse"/> with the given delta time.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="universeTime">Delta time.</param>
|
||||||
|
void Update(UniverseTime universeTime);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs operations that should be done before the draw calls.
|
||||||
|
/// </summary>
|
||||||
|
void PreDraw();
|
||||||
|
|
||||||
|
delegate void UpdateEventHandler(IUniverse sender, UniverseTime engineTime);
|
||||||
|
delegate void PreDrawEventHandler(IUniverse sender);
|
||||||
|
|
||||||
|
delegate void UniverseObjectRegisteredEventHandler(IUniverse sender, IUniverseObject universeObjectRegistered);
|
||||||
|
delegate void UniverseObjectUnRegisteredEventHandler(IUniverse sender, IUniverseObject universeObjectUnregistered);
|
||||||
|
}
|
131
Engine.Core/Abstract/IUniverseObject.cs
Normal file
131
Engine.Core/Abstract/IUniverseObject.cs
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.Core.Abstract;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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
|
||||||
|
/// for notifying when the see enters or exits the universe.
|
||||||
|
/// </summary>
|
||||||
|
public interface IUniverseObject : IEntity, IActive, INameable, IHasBehaviourController, IEnumerable<IUniverseObject>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Event triggered when the <see cref="IUniverseObject"/> enters the universe.
|
||||||
|
/// </summary>
|
||||||
|
event EnteredUniverseEventHandler? OnEnteredUniverse;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event triggered when the <see cref="IUniverseObject"/> exits the universe.
|
||||||
|
/// </summary>
|
||||||
|
event ExitedUniverseEventHandler? OnExitedUniverse;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event triggered when the <see cref="Parent"/> of the <see cref="IUniverseObject"/> changes. The second parameter is the old <see cref="IUniverseObject"/>.
|
||||||
|
/// </summary>
|
||||||
|
event ParentChangedEventHandler? OnParentChanged;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event triggered when a new <see cref="IUniverseObject"/> is added to the <see cref="Children"/>.
|
||||||
|
/// </summary>
|
||||||
|
event ChildrenAddedEventHandler? OnChildrenAdded;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event triggered when an <see cref="IUniverseObject"/> is removed from the <see cref="Children"/>.
|
||||||
|
/// </summary>
|
||||||
|
event ChildrenRemovedEventHandler? OnChildrenRemoved;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="IUniverse"/> this <see cref="IUniverseObject"/> is connected to, if any.
|
||||||
|
/// </summary>
|
||||||
|
IUniverse Universe { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the <see cref="IUniverseObject"/> is currently in the universe.
|
||||||
|
/// </summary>
|
||||||
|
bool IsInUniverse { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The parent <see cref="IUniverseObject"/> of the <see cref="IUniverseObject"/>.
|
||||||
|
/// </summary>
|
||||||
|
IUniverseObject? Parent { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="IUniverseObject"/>s that have this <see cref="IUniverseObject"/> as their <see cref="Parent"/>.
|
||||||
|
/// </summary>
|
||||||
|
IReadOnlyList<IUniverseObject> Children { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Internal method to handle entering the universe.
|
||||||
|
/// This should be called by the system to properly manage universe states.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="universe">The <see cref="IUniverse"/> that is managing this universe.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// <see cref="true"/> if the <see cref="IUniverseObject"/> successfully entered the universe;
|
||||||
|
/// <see cref="false"/> if it failed to do so.
|
||||||
|
/// </returns>
|
||||||
|
internal bool EnterUniverse(IUniverse universe);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Internal method to handle exiting the universe.
|
||||||
|
/// This should be called by the system to properly manage universe states.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// <see cref="true"/> if the <see cref="IUniverseObject"/> successfully exited the universe;
|
||||||
|
/// <see cref="false"/> if it failed to do so.
|
||||||
|
/// </returns>
|
||||||
|
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>
|
||||||
|
/// Adds a child <see cref="IUniverseObject"/> to this <see cref="IUniverseObject"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="universeObject">The child <see cref="IUniverseObject"/> to add.</param>
|
||||||
|
void AddChild(IUniverseObject universeObject);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes a child <see cref="IUniverseObject"/> from this <see cref="IUniverseObject"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="universeObject">The child <see cref="IUniverseObject"/> to remove.</param>
|
||||||
|
void RemoveChild(IUniverseObject universeObject);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// EventHandler delegate for the event triggered when the <see cref="IUniverseObject"/> enters the universe of a <see cref="IUniverse">.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The <see cref="IUniverseObject"/> that entered the universe.</param>
|
||||||
|
/// <param name="universe">The <see cref="IUniverse"/> that the <see cref="IUniverseObject"/> has entered it's universe.</param>
|
||||||
|
delegate void EnteredUniverseEventHandler(IUniverseObject sender, IUniverse universe);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// EventHandler delegate for the event triggered when the <see cref="IUniverseObject"/> exits the universe of a <see cref="IUniverse">.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The <see cref="IUniverseObject"/> that exited the universe.</param>
|
||||||
|
/// <param name="universe">The <see cref="IUniverse"/> that the <see cref="IUniverseObject"/> has exited it's universe.</param>
|
||||||
|
delegate void ExitedUniverseEventHandler(IUniverseObject sender, IUniverse universe);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate for the event triggered when the <see cref="IUniverseObject"/>'s parent changes.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The <see cref="IUniverseObject"/> that the parent has changed.</param>
|
||||||
|
/// <param name="previousParent">The previous <see cref="IUniverseObject"/> the sender was a child of.</param>
|
||||||
|
/// <param name="newParent">The new and current <see cref="IUniverseObject"/> the sender is a child of.</param>
|
||||||
|
delegate void ParentChangedEventHandler(IUniverseObject sender, IUniverseObject? previousParent, IUniverseObject? newParent);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate for the event triggered when a new <see cref="IUniverseObject"/> added as a child.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The parent <see cref="IUniverseObject"/> this event is being called from.</param>
|
||||||
|
/// <param name="childrenAdded">The <see cref="IUniverseObject"/> that got removed as a children of the sender <see cref="IUniverseObject"/>.</param>
|
||||||
|
delegate void ChildrenAddedEventHandler(IUniverseObject sender, IUniverseObject childrenAdded);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delegate for the event triggered when a new <see cref="IUniverseObject"/> removed from being a child.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The parent <see cref="IUniverseObject"/> this event is being called from.</param>
|
||||||
|
/// <param name="childrenAdded">The <see cref="IUniverseObject"/> that got removed as a children of the sender <see cref="IUniverseObject"/>.</param>
|
||||||
|
delegate void ChildrenRemovedEventHandler(IUniverseObject sender, IUniverseObject childrenRemoved);
|
||||||
|
}
|
@ -9,7 +9,7 @@ namespace Syntriax.Engine.Core;
|
|||||||
public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : class, IBehaviour
|
public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : class, IBehaviour
|
||||||
{
|
{
|
||||||
public event IAssignable.UnassignEventHandler? OnUnassigned = null;
|
public event IAssignable.UnassignEventHandler? OnUnassigned = null;
|
||||||
public event IHasGameManager.GameManagerAssignedEventHandler? OnGameManagerAssigned = null;
|
public event IHasUniverse.UniverseAssignedEventHandler? OnUniverseAssigned = null;
|
||||||
|
|
||||||
public event IBehaviourCollector<T>.CollectedEventHandler? OnCollected = null;
|
public event IBehaviourCollector<T>.CollectedEventHandler? OnCollected = null;
|
||||||
public event IBehaviourCollector<T>.RemovedEventHandler? OnRemoved = null;
|
public event IBehaviourCollector<T>.RemovedEventHandler? OnRemoved = null;
|
||||||
@ -19,29 +19,29 @@ public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : clas
|
|||||||
protected readonly Dictionary<IActive, T> monitoringActiveToBehaviour = new(32);
|
protected readonly Dictionary<IActive, T> monitoringActiveToBehaviour = new(32);
|
||||||
|
|
||||||
public IReadOnlyList<T> Behaviours => activeBehaviours;
|
public IReadOnlyList<T> Behaviours => activeBehaviours;
|
||||||
public IGameManager GameManager { get; private set; } = null!;
|
public IUniverse Universe { get; private set; } = null!;
|
||||||
|
|
||||||
public T this[Index index] => activeBehaviours[index];
|
public T this[Index index] => activeBehaviours[index];
|
||||||
|
|
||||||
public ActiveBehaviourCollector() { }
|
public ActiveBehaviourCollector() { }
|
||||||
public ActiveBehaviourCollector(IGameManager gameManager) => Assign(gameManager);
|
public ActiveBehaviourCollector(IUniverse universe) => Assign(universe);
|
||||||
|
|
||||||
private void OnHierarchyObjectRegistered(IGameManager manager, IHierarchyObject hierarchyObject)
|
private void OnUniverseObjectRegistered(IUniverse manager, IUniverseObject universeObject)
|
||||||
{
|
{
|
||||||
hierarchyObject.BehaviourController.OnBehaviourAdded += OnBehaviourAdded;
|
universeObject.BehaviourController.OnBehaviourAdded += OnBehaviourAdded;
|
||||||
hierarchyObject.BehaviourController.OnBehaviourRemoved += OnBehaviourRemoved;
|
universeObject.BehaviourController.OnBehaviourRemoved += OnBehaviourRemoved;
|
||||||
|
|
||||||
foreach (IBehaviour item in hierarchyObject.BehaviourController)
|
foreach (IBehaviour item in universeObject.BehaviourController)
|
||||||
OnBehaviourAdded(hierarchyObject.BehaviourController, item);
|
OnBehaviourAdded(universeObject.BehaviourController, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnHierarchyObjectUnregistered(IGameManager manager, IHierarchyObject hierarchyObject)
|
private void OnUniverseObjectUnregistered(IUniverse manager, IUniverseObject universeObject)
|
||||||
{
|
{
|
||||||
hierarchyObject.BehaviourController.OnBehaviourAdded -= OnBehaviourAdded;
|
universeObject.BehaviourController.OnBehaviourAdded -= OnBehaviourAdded;
|
||||||
hierarchyObject.BehaviourController.OnBehaviourRemoved -= OnBehaviourRemoved;
|
universeObject.BehaviourController.OnBehaviourRemoved -= OnBehaviourRemoved;
|
||||||
|
|
||||||
foreach (IBehaviour item in hierarchyObject.BehaviourController)
|
foreach (IBehaviour item in universeObject.BehaviourController)
|
||||||
OnBehaviourRemoved(hierarchyObject.BehaviourController, item);
|
OnBehaviourRemoved(universeObject.BehaviourController, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnBehaviourAdd(IBehaviour behaviour) { }
|
protected virtual void OnBehaviourAdd(IBehaviour behaviour) { }
|
||||||
@ -63,12 +63,12 @@ public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : clas
|
|||||||
{
|
{
|
||||||
activeBehaviours.Add(behaviour);
|
activeBehaviours.Add(behaviour);
|
||||||
OnBehaviourAdd(behaviour);
|
OnBehaviourAdd(behaviour);
|
||||||
OnCollected?.Invoke(this, behaviour);
|
OnCollected?.InvokeSafe(this, behaviour);
|
||||||
}
|
}
|
||||||
else if (activeBehaviours.Remove(behaviour))
|
else if (activeBehaviours.Remove(behaviour))
|
||||||
{
|
{
|
||||||
OnBehaviourRemove(behaviour);
|
OnBehaviourRemove(behaviour);
|
||||||
OnRemoved?.Invoke(this, behaviour);
|
OnRemoved?.InvokeSafe(this, behaviour);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,40 +85,40 @@ public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : clas
|
|||||||
if (activeBehaviours.Remove(tBehaviour))
|
if (activeBehaviours.Remove(tBehaviour))
|
||||||
{
|
{
|
||||||
OnBehaviourRemove(tBehaviour);
|
OnBehaviourRemove(tBehaviour);
|
||||||
OnRemoved?.Invoke(this, tBehaviour);
|
OnRemoved?.InvokeSafe(this, tBehaviour);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Assign(IGameManager gameManager)
|
public bool Assign(IUniverse universe)
|
||||||
{
|
{
|
||||||
if (GameManager is not null)
|
if (Universe is not null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
foreach (IHierarchyObject hierarchyObject in gameManager.HierarchyObjects)
|
foreach (IUniverseObject universeObject in universe.UniverseObjects)
|
||||||
OnHierarchyObjectRegistered(gameManager, hierarchyObject);
|
OnUniverseObjectRegistered(universe, universeObject);
|
||||||
|
|
||||||
gameManager.OnHierarchyObjectRegistered += OnHierarchyObjectRegistered;
|
universe.OnUniverseObjectRegistered += OnUniverseObjectRegistered;
|
||||||
gameManager.OnHierarchyObjectUnRegistered += OnHierarchyObjectUnregistered;
|
universe.OnUniverseObjectUnRegistered += OnUniverseObjectUnregistered;
|
||||||
|
|
||||||
GameManager = gameManager;
|
Universe = universe;
|
||||||
OnGameManagerAssigned?.Invoke(this);
|
OnUniverseAssigned?.InvokeSafe(this);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Unassign()
|
public bool Unassign()
|
||||||
{
|
{
|
||||||
if (GameManager is null)
|
if (Universe is null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
foreach (IHierarchyObject hierarchyObject in GameManager.HierarchyObjects)
|
foreach (IUniverseObject universeObject in Universe.UniverseObjects)
|
||||||
OnHierarchyObjectUnregistered(GameManager, hierarchyObject);
|
OnUniverseObjectUnregistered(Universe, universeObject);
|
||||||
|
|
||||||
GameManager.OnHierarchyObjectRegistered -= OnHierarchyObjectRegistered;
|
Universe.OnUniverseObjectRegistered -= OnUniverseObjectRegistered;
|
||||||
GameManager.OnHierarchyObjectUnRegistered -= OnHierarchyObjectUnregistered;
|
Universe.OnUniverseObjectUnRegistered -= OnUniverseObjectUnregistered;
|
||||||
|
|
||||||
GameManager = null!;
|
Universe = null!;
|
||||||
OnUnassigned?.Invoke(this);
|
OnUnassigned?.InvokeSafe(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,18 @@ namespace Syntriax.Engine.Core;
|
|||||||
|
|
||||||
public class ActiveBehaviourCollectorSorted<T> : ActiveBehaviourCollector<T> where T : class, IBehaviour
|
public class ActiveBehaviourCollectorSorted<T> : ActiveBehaviourCollector<T> where T : class, IBehaviour
|
||||||
{
|
{
|
||||||
public Comparison<T>? SortBy { get; set; } = null;
|
private Comparison<T>? _sortBy = null;
|
||||||
|
public Comparison<T>? SortBy
|
||||||
|
{
|
||||||
|
get => _sortBy;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_sortBy = value;
|
||||||
|
|
||||||
|
if (value is not null)
|
||||||
|
activeBehaviours.Sort(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnBehaviourAdd(IBehaviour behaviour)
|
protected override void OnBehaviourAdd(IBehaviour behaviour)
|
||||||
{
|
{
|
||||||
@ -15,5 +26,5 @@ public class ActiveBehaviourCollectorSorted<T> : ActiveBehaviourCollector<T> whe
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ActiveBehaviourCollectorSorted() { }
|
public ActiveBehaviourCollectorSorted() { }
|
||||||
public ActiveBehaviourCollectorSorted(IGameManager gameManager) : base(gameManager) { }
|
public ActiveBehaviourCollectorSorted(IUniverse universe, Comparison<T> sortBy) : base(universe) => SortBy = sortBy;
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ public abstract class BaseEntity : IEntity
|
|||||||
string previousId = _id;
|
string previousId = _id;
|
||||||
|
|
||||||
_id = value;
|
_id = value;
|
||||||
OnIdChanged?.Invoke(this, previousId);
|
OnIdChanged?.InvokeSafe(this, previousId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,9 +47,9 @@ public abstract class BaseEntity : IEntity
|
|||||||
|
|
||||||
_initialized = value;
|
_initialized = value;
|
||||||
if (value)
|
if (value)
|
||||||
OnInitialized?.Invoke(this);
|
OnInitialized?.InvokeSafe(this);
|
||||||
else
|
else
|
||||||
OnFinalized?.Invoke(this);
|
OnFinalized?.InvokeSafe(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ public abstract class BaseEntity : IEntity
|
|||||||
_stateEnable = stateEnable;
|
_stateEnable = stateEnable;
|
||||||
_stateEnable.Assign(this);
|
_stateEnable.Assign(this);
|
||||||
OnAssign(stateEnable);
|
OnAssign(stateEnable);
|
||||||
OnStateEnableAssigned?.Invoke(this);
|
OnStateEnableAssigned?.InvokeSafe(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ public abstract class BaseEntity : IEntity
|
|||||||
|
|
||||||
_stateEnable = null!;
|
_stateEnable = null!;
|
||||||
_stateEnable.Unassign();
|
_stateEnable.Unassign();
|
||||||
OnUnassigned?.Invoke(this);
|
OnUnassigned?.InvokeSafe(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@ public abstract class Behaviour : BehaviourBase
|
|||||||
{
|
{
|
||||||
private bool isInitializedThisFrame = false;
|
private bool isInitializedThisFrame = false;
|
||||||
|
|
||||||
protected IGameManager GameManager => BehaviourController.HierarchyObject.GameManager;
|
protected IUniverse Universe => BehaviourController.UniverseObject.Universe;
|
||||||
protected IHierarchyObject HierarchyObject => BehaviourController.HierarchyObject;
|
protected IUniverseObject UniverseObject => BehaviourController.UniverseObject;
|
||||||
|
|
||||||
public Behaviour()
|
public Behaviour()
|
||||||
{
|
{
|
||||||
@ -27,13 +27,13 @@ public abstract class Behaviour : BehaviourBase
|
|||||||
BehaviourController.OnPreUpdate += PreUpdate;
|
BehaviourController.OnPreUpdate += PreUpdate;
|
||||||
BehaviourController.OnPreDraw += PreDraw;
|
BehaviourController.OnPreDraw += PreDraw;
|
||||||
BehaviourController.OnUpdate += Update;
|
BehaviourController.OnUpdate += Update;
|
||||||
BehaviourController.HierarchyObject.OnEnteredHierarchy += EnteredHierarchy;
|
BehaviourController.UniverseObject.OnEnteredUniverse += EnteredUniverse;
|
||||||
BehaviourController.HierarchyObject.OnExitedHierarchy += ExitedHierarchy;
|
BehaviourController.UniverseObject.OnExitedUniverse += ExitedUniverse;
|
||||||
|
|
||||||
OnInitialize();
|
OnInitialize();
|
||||||
|
|
||||||
if (HierarchyObject.IsInHierarchy)
|
if (UniverseObject.IsInUniverse)
|
||||||
EnteredHierarchy(HierarchyObject, GameManager);
|
EnteredUniverse(UniverseObject, Universe);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnFinalize() { }
|
protected virtual void OnFinalize() { }
|
||||||
@ -42,19 +42,21 @@ public abstract class Behaviour : BehaviourBase
|
|||||||
BehaviourController.OnPreUpdate -= PreUpdate;
|
BehaviourController.OnPreUpdate -= PreUpdate;
|
||||||
BehaviourController.OnPreDraw -= PreDraw;
|
BehaviourController.OnPreDraw -= PreDraw;
|
||||||
BehaviourController.OnUpdate -= Update;
|
BehaviourController.OnUpdate -= Update;
|
||||||
BehaviourController.HierarchyObject.OnEnteredHierarchy -= EnteredHierarchy;
|
BehaviourController.UniverseObject.OnEnteredUniverse -= EnteredUniverse;
|
||||||
BehaviourController.HierarchyObject.OnExitedHierarchy -= ExitedHierarchy;
|
BehaviourController.UniverseObject.OnExitedUniverse -= ExitedUniverse;
|
||||||
|
|
||||||
OnFinalize();
|
OnFinalize();
|
||||||
|
|
||||||
if (HierarchyObject.IsInHierarchy)
|
if (UniverseObject.IsInUniverse)
|
||||||
ExitedHierarchy(HierarchyObject, GameManager);
|
ExitedUniverse(UniverseObject, Universe);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnPreUpdatePreActiveCheck() { }
|
protected virtual void OnPreUpdatePreActiveCheck() { }
|
||||||
protected virtual void OnPreUpdate() { }
|
protected virtual void OnPreUpdate() { }
|
||||||
protected virtual void PreUpdate(IBehaviourController _)
|
protected virtual void PreUpdate(IBehaviourController _)
|
||||||
{
|
{
|
||||||
|
Debug.AssertHelpers.AssertInitialized(this);
|
||||||
|
|
||||||
OnPreUpdatePreActiveCheck();
|
OnPreUpdatePreActiveCheck();
|
||||||
|
|
||||||
if (!IsActive)
|
if (!IsActive)
|
||||||
@ -77,6 +79,8 @@ public abstract class Behaviour : BehaviourBase
|
|||||||
protected virtual void OnUpdate() { }
|
protected virtual void OnUpdate() { }
|
||||||
protected virtual void Update(IBehaviourController _)
|
protected virtual void Update(IBehaviourController _)
|
||||||
{
|
{
|
||||||
|
Debug.AssertHelpers.AssertInitialized(this);
|
||||||
|
|
||||||
OnUpdatePreActiveCheck();
|
OnUpdatePreActiveCheck();
|
||||||
|
|
||||||
if (!IsActive)
|
if (!IsActive)
|
||||||
@ -89,6 +93,8 @@ public abstract class Behaviour : BehaviourBase
|
|||||||
protected virtual void OnPreDraw() { }
|
protected virtual void OnPreDraw() { }
|
||||||
protected virtual void PreDraw(IBehaviourController _)
|
protected virtual void PreDraw(IBehaviourController _)
|
||||||
{
|
{
|
||||||
|
Debug.AssertHelpers.AssertInitialized(this);
|
||||||
|
|
||||||
OnPreDrawPreActiveCheck();
|
OnPreDrawPreActiveCheck();
|
||||||
|
|
||||||
if (!StateEnable.Enabled)
|
if (!StateEnable.Enabled)
|
||||||
@ -97,9 +103,9 @@ public abstract class Behaviour : BehaviourBase
|
|||||||
OnPreDraw();
|
OnPreDraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnEnteredHierarchy(IGameManager gameManager) { }
|
protected virtual void OnEnteredUniverse(IUniverse universe) { }
|
||||||
protected virtual void EnteredHierarchy(IHierarchyObject sender, IGameManager gameManager) => OnEnteredHierarchy(gameManager);
|
protected virtual void EnteredUniverse(IUniverseObject sender, IUniverse universe) => OnEnteredUniverse(universe);
|
||||||
|
|
||||||
protected virtual void OnExitedHierarchy(IGameManager gameManager) { }
|
protected virtual void OnExitedUniverse(IUniverse universe) { }
|
||||||
protected virtual void ExitedHierarchy(IHierarchyObject sender, IGameManager gameManager) => OnExitedHierarchy(gameManager);
|
protected virtual void ExitedUniverse(IUniverseObject sender, IUniverse universe) => OnExitedUniverse(universe);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ public abstract class Behaviour2D : Behaviour, IBehaviour2D
|
|||||||
|
|
||||||
protected sealed override void OnInitialize(IInitializable _)
|
protected sealed override void OnInitialize(IInitializable _)
|
||||||
{
|
{
|
||||||
Transform = BehaviourController.GetBehaviourInChildren<ITransform2D>() ?? throw new($"{HierarchyObject.Name} does not contain any {nameof(ITransform2D)}");
|
Transform = BehaviourController.GetRequiredBehaviour<ITransform2D>();
|
||||||
base.OnInitialize(_);
|
base.OnInitialize(_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,6 +23,6 @@ public abstract class Behaviour2D : Behaviour, IBehaviour2D
|
|||||||
protected sealed override void FirstActiveFrame() => base.FirstActiveFrame();
|
protected sealed override void FirstActiveFrame() => base.FirstActiveFrame();
|
||||||
protected sealed override void Update(IBehaviourController behaviourController) => base.Update(behaviourController);
|
protected sealed override void Update(IBehaviourController behaviourController) => base.Update(behaviourController);
|
||||||
protected sealed override void PreDraw(IBehaviourController behaviourController) => base.PreDraw(behaviourController);
|
protected sealed override void PreDraw(IBehaviourController behaviourController) => base.PreDraw(behaviourController);
|
||||||
protected sealed override void EnteredHierarchy(IHierarchyObject sender, IGameManager gameManager) => base.EnteredHierarchy(sender, gameManager);
|
protected sealed override void EnteredUniverse(IUniverseObject sender, IUniverse universe) => base.EnteredUniverse(sender, universe);
|
||||||
protected sealed override void ExitedHierarchy(IHierarchyObject sender, IGameManager gameManager) => base.ExitedHierarchy(sender, gameManager);
|
protected sealed override void ExitedUniverse(IUniverseObject sender, IUniverse universe) => base.ExitedUniverse(sender, universe);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using Syntriax.Engine.Core.Abstract;
|
using Syntriax.Engine.Core.Abstract;
|
||||||
using Syntriax.Engine.Core.Exceptions;
|
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Syntriax.Engine.Core;
|
||||||
|
|
||||||
@ -24,7 +23,7 @@ public abstract class BehaviourBase : BaseEntity, IBehaviour
|
|||||||
|
|
||||||
int previousPriority = _priority;
|
int previousPriority = _priority;
|
||||||
_priority = value;
|
_priority = value;
|
||||||
OnPriorityChanged?.Invoke(this, previousPriority);
|
OnPriorityChanged?.InvokeSafe(this, previousPriority);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,16 +38,16 @@ public abstract class BehaviourBase : BaseEntity, IBehaviour
|
|||||||
|
|
||||||
_behaviourController = behaviourController;
|
_behaviourController = behaviourController;
|
||||||
OnAssign(behaviourController);
|
OnAssign(behaviourController);
|
||||||
behaviourController.OnHierarchyObjectAssigned += OnHierarchyObjectAssigned;
|
behaviourController.OnUniverseObjectAssigned += OnUniverseObjectAssigned;
|
||||||
if (behaviourController.HierarchyObject is not null)
|
if (behaviourController.UniverseObject is not null)
|
||||||
OnHierarchyObjectAssigned(behaviourController);
|
OnUniverseObjectAssigned(behaviourController);
|
||||||
OnBehaviourControllerAssigned?.Invoke(this);
|
OnBehaviourControllerAssigned?.InvokeSafe(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnHierarchyObjectAssigned(IHasHierarchyObject sender)
|
private void OnUniverseObjectAssigned(IHasUniverseObject sender)
|
||||||
{
|
{
|
||||||
sender.HierarchyObject.OnActiveChanged += OnHierarchyObjectActiveChanged;
|
sender.UniverseObject.OnActiveChanged += OnUniverseObjectActiveChanged;
|
||||||
UpdateActive();
|
UpdateActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,27 +61,26 @@ public abstract class BehaviourBase : BaseEntity, IBehaviour
|
|||||||
protected override void UnassignInternal()
|
protected override void UnassignInternal()
|
||||||
{
|
{
|
||||||
StateEnable.OnEnabledChanged -= OnStateEnabledChanged;
|
StateEnable.OnEnabledChanged -= OnStateEnabledChanged;
|
||||||
BehaviourController.OnHierarchyObjectAssigned -= OnHierarchyObjectAssigned;
|
BehaviourController.OnUniverseObjectAssigned -= OnUniverseObjectAssigned;
|
||||||
base.UnassignInternal();
|
base.UnassignInternal();
|
||||||
_behaviourController = null!;
|
_behaviourController = null!;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void InitializeInternal()
|
protected override void InitializeInternal()
|
||||||
{
|
{
|
||||||
base.InitializeInternal();
|
Debug.AssertHelpers.AssertBehaviourControllerAssigned(this);
|
||||||
NotAssignedException.Check(this, _behaviourController);
|
Debug.AssertHelpers.AssertStateEnableAssigned(this);
|
||||||
NotAssignedException.Check(this, StateEnable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStateEnabledChanged(IStateEnable sender, bool previousState) => UpdateActive();
|
private void OnStateEnabledChanged(IStateEnable sender, bool previousState) => UpdateActive();
|
||||||
private void OnHierarchyObjectActiveChanged(IActive sender, bool previousState) => UpdateActive();
|
private void OnUniverseObjectActiveChanged(IActive sender, bool previousState) => UpdateActive();
|
||||||
|
|
||||||
private void UpdateActive()
|
private void UpdateActive()
|
||||||
{
|
{
|
||||||
bool previousActive = IsActive;
|
bool previousActive = IsActive;
|
||||||
_isActive = StateEnable.Enabled && _behaviourController.HierarchyObject.IsActive;
|
_isActive = StateEnable.Enabled && _behaviourController.UniverseObject.IsActive;
|
||||||
|
|
||||||
if (previousActive != IsActive)
|
if (previousActive != IsActive)
|
||||||
OnActiveChanged?.Invoke(this, previousActive);
|
OnActiveChanged?.InvokeSafe(this, previousActive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ namespace Syntriax.Engine.Core;
|
|||||||
public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
|
public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
|
||||||
{
|
{
|
||||||
public event IAssignable.UnassignEventHandler? OnUnassigned = null;
|
public event IAssignable.UnassignEventHandler? OnUnassigned = null;
|
||||||
public event IHasGameManager.GameManagerAssignedEventHandler? OnGameManagerAssigned = null;
|
public event IHasUniverse.UniverseAssignedEventHandler? OnUniverseAssigned = null;
|
||||||
|
|
||||||
public event IBehaviourCollector<T>.CollectedEventHandler? OnCollected = null;
|
public event IBehaviourCollector<T>.CollectedEventHandler? OnCollected = null;
|
||||||
public event IBehaviourCollector<T>.RemovedEventHandler? OnRemoved = null;
|
public event IBehaviourCollector<T>.RemovedEventHandler? OnRemoved = null;
|
||||||
@ -17,29 +17,29 @@ public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
|
|||||||
protected readonly List<T> behaviours = new(32);
|
protected readonly List<T> behaviours = new(32);
|
||||||
|
|
||||||
public IReadOnlyList<T> Behaviours => behaviours;
|
public IReadOnlyList<T> Behaviours => behaviours;
|
||||||
public IGameManager GameManager { get; private set; } = null!;
|
public IUniverse Universe { get; private set; } = null!;
|
||||||
|
|
||||||
public T this[Index index] => behaviours[index];
|
public T this[Index index] => behaviours[index];
|
||||||
|
|
||||||
public BehaviourCollector() { }
|
public BehaviourCollector() { }
|
||||||
public BehaviourCollector(IGameManager gameManager) => Assign(gameManager);
|
public BehaviourCollector(IUniverse universe) => Assign(universe);
|
||||||
|
|
||||||
private void OnHierarchyObjectRegistered(IGameManager manager, IHierarchyObject hierarchyObject)
|
private void OnUniverseObjectRegistered(IUniverse manager, IUniverseObject universeObject)
|
||||||
{
|
{
|
||||||
hierarchyObject.BehaviourController.OnBehaviourAdded += OnBehaviourAdded;
|
universeObject.BehaviourController.OnBehaviourAdded += OnBehaviourAdded;
|
||||||
hierarchyObject.BehaviourController.OnBehaviourRemoved += OnBehaviourRemoved;
|
universeObject.BehaviourController.OnBehaviourRemoved += OnBehaviourRemoved;
|
||||||
|
|
||||||
foreach (IBehaviour item in hierarchyObject.BehaviourController)
|
foreach (IBehaviour item in universeObject.BehaviourController)
|
||||||
OnBehaviourAdded(hierarchyObject.BehaviourController, item);
|
OnBehaviourAdded(universeObject.BehaviourController, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnHierarchyObjectUnregistered(IGameManager manager, IHierarchyObject hierarchyObject)
|
private void OnUniverseObjectUnregistered(IUniverse manager, IUniverseObject universeObject)
|
||||||
{
|
{
|
||||||
hierarchyObject.BehaviourController.OnBehaviourAdded -= OnBehaviourAdded;
|
universeObject.BehaviourController.OnBehaviourAdded -= OnBehaviourAdded;
|
||||||
hierarchyObject.BehaviourController.OnBehaviourRemoved -= OnBehaviourRemoved;
|
universeObject.BehaviourController.OnBehaviourRemoved -= OnBehaviourRemoved;
|
||||||
|
|
||||||
foreach (IBehaviour item in hierarchyObject.BehaviourController)
|
foreach (IBehaviour item in universeObject.BehaviourController)
|
||||||
OnBehaviourRemoved(hierarchyObject.BehaviourController, item);
|
OnBehaviourRemoved(universeObject.BehaviourController, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnBehaviourAdd(IBehaviour behaviour) { }
|
protected virtual void OnBehaviourAdd(IBehaviour behaviour) { }
|
||||||
@ -50,7 +50,7 @@ public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
|
|||||||
|
|
||||||
behaviours.Add(tBehaviour);
|
behaviours.Add(tBehaviour);
|
||||||
OnBehaviourAdd(behaviour);
|
OnBehaviourAdd(behaviour);
|
||||||
OnCollected?.Invoke(this, tBehaviour);
|
OnCollected?.InvokeSafe(this, tBehaviour);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnBehaviourRemove(IBehaviour behaviour) { }
|
protected virtual void OnBehaviourRemove(IBehaviour behaviour) { }
|
||||||
@ -63,41 +63,41 @@ public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
OnBehaviourRemove(behaviour);
|
OnBehaviourRemove(behaviour);
|
||||||
OnRemoved?.Invoke(this, tBehaviour);
|
OnRemoved?.InvokeSafe(this, tBehaviour);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnAssign(IGameManager gameManager) { }
|
protected virtual void OnAssign(IUniverse universe) { }
|
||||||
public bool Assign(IGameManager gameManager)
|
public bool Assign(IUniverse universe)
|
||||||
{
|
{
|
||||||
if (GameManager is not null)
|
if (Universe is not null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
foreach (IHierarchyObject hierarchyObject in gameManager.HierarchyObjects)
|
foreach (IUniverseObject universeObject in universe.UniverseObjects)
|
||||||
OnHierarchyObjectRegistered(gameManager, hierarchyObject);
|
OnUniverseObjectRegistered(universe, universeObject);
|
||||||
|
|
||||||
gameManager.OnHierarchyObjectRegistered += OnHierarchyObjectRegistered;
|
universe.OnUniverseObjectRegistered += OnUniverseObjectRegistered;
|
||||||
gameManager.OnHierarchyObjectUnRegistered += OnHierarchyObjectUnregistered;
|
universe.OnUniverseObjectUnRegistered += OnUniverseObjectUnregistered;
|
||||||
|
|
||||||
GameManager = gameManager;
|
Universe = universe;
|
||||||
OnAssign(gameManager);
|
OnAssign(universe);
|
||||||
OnGameManagerAssigned?.Invoke(this);
|
OnUniverseAssigned?.InvokeSafe(this);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Unassign()
|
public bool Unassign()
|
||||||
{
|
{
|
||||||
if (GameManager is null)
|
if (Universe is null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
foreach (IHierarchyObject hierarchyObject in GameManager.HierarchyObjects)
|
foreach (IUniverseObject universeObject in Universe.UniverseObjects)
|
||||||
OnHierarchyObjectUnregistered(GameManager, hierarchyObject);
|
OnUniverseObjectUnregistered(Universe, universeObject);
|
||||||
|
|
||||||
GameManager.OnHierarchyObjectRegistered -= OnHierarchyObjectRegistered;
|
Universe.OnUniverseObjectRegistered -= OnUniverseObjectRegistered;
|
||||||
GameManager.OnHierarchyObjectUnRegistered -= OnHierarchyObjectUnregistered;
|
Universe.OnUniverseObjectUnRegistered -= OnUniverseObjectUnregistered;
|
||||||
|
|
||||||
GameManager = null!;
|
Universe = null!;
|
||||||
OnUnassigned?.Invoke(this);
|
OnUnassigned?.InvokeSafe(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,18 @@ namespace Syntriax.Engine.Core;
|
|||||||
|
|
||||||
public class BehaviourCollectorSorted<T> : BehaviourCollector<T> where T : class
|
public class BehaviourCollectorSorted<T> : BehaviourCollector<T> where T : class
|
||||||
{
|
{
|
||||||
public Comparison<T>? SortBy { get; set; } = null;
|
private Comparison<T>? _sortBy = null;
|
||||||
|
public Comparison<T>? SortBy
|
||||||
|
{
|
||||||
|
get => _sortBy;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_sortBy = value;
|
||||||
|
|
||||||
|
if (value is not null)
|
||||||
|
behaviours.Sort(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnBehaviourAdd(IBehaviour behaviour)
|
protected override void OnBehaviourAdd(IBehaviour behaviour)
|
||||||
{
|
{
|
||||||
@ -15,5 +26,5 @@ public class BehaviourCollectorSorted<T> : BehaviourCollector<T> where T : class
|
|||||||
}
|
}
|
||||||
|
|
||||||
public BehaviourCollectorSorted() { }
|
public BehaviourCollectorSorted() { }
|
||||||
public BehaviourCollectorSorted(IGameManager gameManager) : base(gameManager) { }
|
public BehaviourCollectorSorted(IUniverse universe, Comparison<T> sortBy) : base(universe) => SortBy = sortBy;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
using Syntriax.Engine.Core.Abstract;
|
using Syntriax.Engine.Core.Abstract;
|
||||||
using Syntriax.Engine.Core.Exceptions;
|
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Syntriax.Engine.Core;
|
||||||
|
|
||||||
@ -17,7 +16,7 @@ public class BehaviourController : IBehaviourController
|
|||||||
|
|
||||||
public event IBehaviourController.BehaviourAddedEventHandler? OnBehaviourAdded = null;
|
public event IBehaviourController.BehaviourAddedEventHandler? OnBehaviourAdded = null;
|
||||||
public event IBehaviourController.BehaviourRemovedEventHandler? OnBehaviourRemoved = null;
|
public event IBehaviourController.BehaviourRemovedEventHandler? OnBehaviourRemoved = null;
|
||||||
public event IHasHierarchyObject.HierarchyObjectAssignedEventHandler? OnHierarchyObjectAssigned = null;
|
public event IHasUniverseObject.UniverseObjectAssignedEventHandler? OnUniverseObjectAssigned = null;
|
||||||
|
|
||||||
public event IInitializable.InitializedEventHandler? OnInitialized = null;
|
public event IInitializable.InitializedEventHandler? OnInitialized = null;
|
||||||
public event IInitializable.FinalizedEventHandler? OnFinalized = null;
|
public event IInitializable.FinalizedEventHandler? OnFinalized = null;
|
||||||
@ -26,10 +25,10 @@ public class BehaviourController : IBehaviourController
|
|||||||
|
|
||||||
private readonly IList<IBehaviour> behaviours = new List<IBehaviour>(Constants.BEHAVIOURS_SIZE_INITIAL);
|
private readonly IList<IBehaviour> behaviours = new List<IBehaviour>(Constants.BEHAVIOURS_SIZE_INITIAL);
|
||||||
|
|
||||||
private IHierarchyObject _hierarchyObject = null!;
|
private IUniverseObject _universeObject = null!;
|
||||||
private bool _initialized = false;
|
private bool _initialized = false;
|
||||||
|
|
||||||
public IHierarchyObject HierarchyObject => _hierarchyObject;
|
public IUniverseObject UniverseObject => _universeObject;
|
||||||
|
|
||||||
public bool IsInitialized
|
public bool IsInitialized
|
||||||
{
|
{
|
||||||
@ -41,9 +40,9 @@ public class BehaviourController : IBehaviourController
|
|||||||
|
|
||||||
_initialized = value;
|
_initialized = value;
|
||||||
if (value)
|
if (value)
|
||||||
OnInitialized?.Invoke(this);
|
OnInitialized?.InvokeSafe(this);
|
||||||
else
|
else
|
||||||
OnFinalized?.Invoke(this);
|
OnFinalized?.InvokeSafe(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,12 +55,12 @@ public class BehaviourController : IBehaviourController
|
|||||||
|
|
||||||
behaviour.Initialize();
|
behaviour.Initialize();
|
||||||
behaviour.OnPriorityChanged += OnPriorityChange;
|
behaviour.OnPriorityChanged += OnPriorityChange;
|
||||||
OnBehaviourAdded?.Invoke(this, behaviour);
|
OnBehaviourAdded?.InvokeSafe(this, behaviour);
|
||||||
return behaviour;
|
return behaviour;
|
||||||
}
|
}
|
||||||
|
|
||||||
public T AddBehaviour<T>(params object?[]? args) where T : class, IBehaviour
|
public T AddBehaviour<T>(params object?[]? args) where T : class, IBehaviour
|
||||||
=> AddBehaviour(Factory.BehaviourFactory.Instantiate<T>(_hierarchyObject, args));
|
=> AddBehaviour(Factory.BehaviourFactory.Instantiate<T>(_universeObject, args));
|
||||||
|
|
||||||
public T? GetBehaviour<T>()
|
public T? GetBehaviour<T>()
|
||||||
{
|
{
|
||||||
@ -72,7 +71,7 @@ public class BehaviourController : IBehaviourController
|
|||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IList<T> GetBehaviours<T>()
|
public IReadOnlyList<T> GetBehaviours<T>()
|
||||||
{
|
{
|
||||||
List<T>? behaviours = null;
|
List<T>? behaviours = null;
|
||||||
foreach (IBehaviour behaviourItem in this.behaviours)
|
foreach (IBehaviour behaviourItem in this.behaviours)
|
||||||
@ -116,23 +115,23 @@ public class BehaviourController : IBehaviourController
|
|||||||
public void RemoveBehaviour<T>(T behaviour) where T : class, IBehaviour
|
public void RemoveBehaviour<T>(T behaviour) where T : class, IBehaviour
|
||||||
{
|
{
|
||||||
if (!behaviours.Contains(behaviour))
|
if (!behaviours.Contains(behaviour))
|
||||||
throw new Exception($"{behaviour.GetType().Name} does not exist in {HierarchyObject.Name}'s {nameof(IBehaviourController)}.");
|
throw new Exception($"{behaviour.GetType().Name} does not exist in {UniverseObject.Name}'s {nameof(IBehaviourController)}.");
|
||||||
|
|
||||||
behaviour.OnPriorityChanged -= OnPriorityChange;
|
behaviour.OnPriorityChanged -= OnPriorityChange;
|
||||||
behaviour.Finalize();
|
behaviour.Finalize();
|
||||||
behaviours.Remove(behaviour);
|
behaviours.Remove(behaviour);
|
||||||
OnBehaviourRemoved?.Invoke(this, behaviour);
|
OnBehaviourRemoved?.InvokeSafe(this, behaviour);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnAssign(IHierarchyObject hierarchyObject) { }
|
protected virtual void OnAssign(IUniverseObject universeObject) { }
|
||||||
public bool Assign(IHierarchyObject hierarchyObject)
|
public bool Assign(IUniverseObject universeObject)
|
||||||
{
|
{
|
||||||
if (HierarchyObject is not null && HierarchyObject.IsInitialized)
|
if (UniverseObject is not null && UniverseObject.IsInitialized)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
_hierarchyObject = hierarchyObject;
|
_universeObject = universeObject;
|
||||||
OnAssign(hierarchyObject);
|
OnAssign(universeObject);
|
||||||
OnHierarchyObjectAssigned?.Invoke(this);
|
OnUniverseObjectAssigned?.InvokeSafe(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +140,7 @@ public class BehaviourController : IBehaviourController
|
|||||||
if (IsInitialized)
|
if (IsInitialized)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
NotAssignedException.Check(this, _hierarchyObject);
|
Debug.AssertHelpers.AssertUniverseObjectAssigned(this);
|
||||||
|
|
||||||
foreach (IBehaviour behaviour in behaviours)
|
foreach (IBehaviour behaviour in behaviours)
|
||||||
behaviour.Initialize();
|
behaviour.Initialize();
|
||||||
@ -167,30 +166,30 @@ public class BehaviourController : IBehaviourController
|
|||||||
if (IsInitialized)
|
if (IsInitialized)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
_hierarchyObject = null!;
|
_universeObject = null!;
|
||||||
OnUnassigned?.Invoke(this);
|
OnUnassigned?.InvokeSafe(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
if (!HierarchyObject.StateEnable.Enabled)
|
if (!UniverseObject.StateEnable.Enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
OnPreUpdate?.Invoke(this);
|
OnPreUpdate?.InvokeSafe(this);
|
||||||
OnUpdate?.Invoke(this);
|
OnUpdate?.InvokeSafe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdatePreDraw()
|
public void UpdatePreDraw()
|
||||||
{
|
{
|
||||||
if (!HierarchyObject.StateEnable.Enabled)
|
if (!UniverseObject.StateEnable.Enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
OnPreDraw?.Invoke(this);
|
OnPreDraw?.InvokeSafe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BehaviourController() { }
|
public BehaviourController() { }
|
||||||
public BehaviourController(IHierarchyObject hierarchyObject) => Assign(hierarchyObject);
|
public BehaviourController(IUniverseObject universeObject) => Assign(universeObject);
|
||||||
|
|
||||||
private void InsertBehaviourByPriority<T>(T behaviour) where T : class, IBehaviour
|
private void InsertBehaviourByPriority<T>(T behaviour) where T : class, IBehaviour
|
||||||
{
|
{
|
||||||
|
@ -5,7 +5,7 @@ using Syntriax.Engine.Core.Abstract;
|
|||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Syntriax.Engine.Core;
|
||||||
|
|
||||||
public class CoroutineManager : HierarchyObject
|
public class CoroutineManager : UniverseObject
|
||||||
{
|
{
|
||||||
private readonly List<IEnumerator> enumerators = [];
|
private readonly List<IEnumerator> enumerators = [];
|
||||||
|
|
||||||
@ -20,17 +20,17 @@ public class CoroutineManager : HierarchyObject
|
|||||||
enumerators.Remove(enumerator);
|
enumerators.Remove(enumerator);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnEnteringHierarchy(IGameManager gameManager)
|
protected override void OnEnteringUniverse(IUniverse universe)
|
||||||
{
|
{
|
||||||
gameManager.OnUpdate += OnUpdate;
|
universe.OnUpdate += OnUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnExitingHierarchy(IGameManager gameManager)
|
protected override void OnExitingUniverse(IUniverse universe)
|
||||||
{
|
{
|
||||||
gameManager.OnUpdate -= OnUpdate;
|
universe.OnUpdate -= OnUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnUpdate(IGameManager sender, EngineTime time)
|
private void OnUpdate(IUniverse sender, UniverseTime time)
|
||||||
{
|
{
|
||||||
for (int i = enumerators.Count - 1; i >= 0; i--)
|
for (int i = enumerators.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
|
@ -7,11 +7,11 @@ skinparam nodesep 100
|
|||||||
title Core Engine Relations
|
title Core Engine Relations
|
||||||
|
|
||||||
interface Engine.Core.Abstract.IEntity extends Engine.Core.Abstract.IInitializable {}
|
interface Engine.Core.Abstract.IEntity extends Engine.Core.Abstract.IInitializable {}
|
||||||
interface Engine.Core.Abstract.IHierarchyObject extends Engine.Core.Abstract.IEntity, Engine.Core.Abstract.INameable {}
|
interface Engine.Core.Abstract.IUniverseObject extends Engine.Core.Abstract.IEntity, Engine.Core.Abstract.INameable {}
|
||||||
|
|
||||||
interface Engine.Core.Abstract.INameable {}
|
interface Engine.Core.Abstract.INameable {}
|
||||||
|
|
||||||
Engine.Core.Abstract.IHierarchyObject --> Engine.Core.Abstract.IBehaviourController: has
|
Engine.Core.Abstract.IUniverseObject --> Engine.Core.Abstract.IBehaviourController: has
|
||||||
Engine.Core.Abstract.IBehaviourController "1" --> "0..*" Engine.Core.Abstract.IBehaviour: has
|
Engine.Core.Abstract.IBehaviourController "1" --> "0..*" Engine.Core.Abstract.IBehaviour: has
|
||||||
|
|
||||||
interface Engine.Core.Abstract.IBehaviourController {}
|
interface Engine.Core.Abstract.IBehaviourController {}
|
||||||
@ -19,18 +19,18 @@ interface Engine.Core.Abstract.IBehaviour {}
|
|||||||
interface Engine.Core.Abstract.IBehaviour2D extends Engine.Core.Abstract.IBehaviour {}
|
interface Engine.Core.Abstract.IBehaviour2D extends Engine.Core.Abstract.IBehaviour {}
|
||||||
interface Engine.Core.Abstract.IBehaviour3D extends Engine.Core.Abstract.IBehaviour {}
|
interface Engine.Core.Abstract.IBehaviour3D extends Engine.Core.Abstract.IBehaviour {}
|
||||||
|
|
||||||
interface Engine.Core.Abstract.IGameManager {}
|
interface Engine.Core.Abstract.IUniverse {}
|
||||||
Engine.Core.Abstract.IGameManager "1" -r-> "0..*" Engine.Core.Abstract.IHierarchyObject: has
|
Engine.Core.Abstract.IUniverse "1" -r-> "0..*" Engine.Core.Abstract.IUniverseObject: has
|
||||||
|
|
||||||
' together {
|
' together {
|
||||||
' interface Engine.Core.Abstract.IAssignable {}
|
' interface Engine.Core.Abstract.IAssignable {}
|
||||||
' interface Engine.Core.Abstract.IHasStateEnable extends Engine.Core.Abstract.IAssignable {}
|
' interface Engine.Core.Abstract.IHasStateEnable extends Engine.Core.Abstract.IAssignable {}
|
||||||
' interface Engine.Core.Abstract.IHasGameManager extends Engine.Core.Abstract.IAssignable {}
|
' interface Engine.Core.Abstract.IHasUniverse extends Engine.Core.Abstract.IAssignable {}
|
||||||
' interface Engine.Core.Abstract.IHasHierarchyObject extends Engine.Core.Abstract.IAssignable {}
|
' interface Engine.Core.Abstract.IHasUniverseObject extends Engine.Core.Abstract.IAssignable {}
|
||||||
' interface Engine.Core.Abstract.IHasBehaviourController extends Engine.Core.Abstract.IAssignable {}
|
' interface Engine.Core.Abstract.IHasBehaviourController extends Engine.Core.Abstract.IAssignable {}
|
||||||
' ' Engine.Core.Abstract.IHasStateEnable --> Engine.Core.Abstract.IStateEnable: has
|
' ' Engine.Core.Abstract.IHasStateEnable --> Engine.Core.Abstract.IStateEnable: has
|
||||||
' ' Engine.Core.Abstract.IHasGameManager --> Engine.Core.Abstract.IGameManager: has
|
' ' Engine.Core.Abstract.IHasUniverse --> Engine.Core.Abstract.IUniverse: has
|
||||||
' ' Engine.Core.Abstract.IHasHierarchyObject --> Engine.Core.Abstract.IHierarchyObject: has
|
' ' Engine.Core.Abstract.IHasUniverseObject --> Engine.Core.Abstract.IUniverseObject: has
|
||||||
' ' Engine.Core.Abstract.IHasBehaviourController --> Engine.Core.Abstract.IBehaviourController: has
|
' ' Engine.Core.Abstract.IHasBehaviourController --> Engine.Core.Abstract.IBehaviourController: has
|
||||||
' }
|
' }
|
||||||
|
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Exceptions;
|
|
||||||
|
|
||||||
public class AssignException : Exception
|
|
||||||
{
|
|
||||||
public AssignException() : base("Assign operation has failed.") { }
|
|
||||||
public AssignException(string? message) : base(message) { }
|
|
||||||
|
|
||||||
public static AssignException From<T, T2>(T to, T2? value)
|
|
||||||
=> new($"Assign operation has failed on T: {to?.GetType().FullName ?? "\"null\""}, value: {value?.GetType().ToString() ?? "\"null\""}");
|
|
||||||
}
|
|
9
Engine.Core/Exceptions/AssignFailedException.cs
Normal file
9
Engine.Core/Exceptions/AssignFailedException.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.Core.Exceptions;
|
||||||
|
|
||||||
|
public class AssignFailedException(string? message) : Exception(message)
|
||||||
|
{
|
||||||
|
public static AssignFailedException From<T, T2>(T to, T2? value)
|
||||||
|
=> new($"Assign operation has failed on T: {to?.GetType().FullName ?? "\"null\""}, value: {value?.GetType().ToString() ?? "\"null\""}");
|
||||||
|
}
|
9
Engine.Core/Exceptions/BehaviourNotFoundException.cs
Normal file
9
Engine.Core/Exceptions/BehaviourNotFoundException.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.Core.Exceptions;
|
||||||
|
|
||||||
|
public class BehaviourNotFoundException(string? message) : Exception(message)
|
||||||
|
{
|
||||||
|
public static NotAssignedException FromType<TBehaviour>()
|
||||||
|
=> new($"{typeof(TBehaviour).FullName} was not found");
|
||||||
|
}
|
@ -1,21 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using Syntriax.Engine.Core.Abstract;
|
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Exceptions;
|
namespace Syntriax.Engine.Core.Exceptions;
|
||||||
|
|
||||||
public class NotAssignedException : Exception
|
public class NotAssignedException(string? message) : Exception(message)
|
||||||
{
|
{
|
||||||
public NotAssignedException() : base("The object has not been assigned.") { }
|
|
||||||
public NotAssignedException(string? message) : base(message) { }
|
|
||||||
|
|
||||||
public static NotAssignedException From<T1, T2>(T1 to, T2? value)
|
public static NotAssignedException From<T1, T2>(T1 to, T2? value)
|
||||||
=> new($"{value?.GetType().FullName ?? "\"null\""} has not been assigned to {to?.GetType().FullName ?? "\"null\""}");
|
=> new($"{value?.GetType().FullName ?? "\"null\""} has not been assigned to {to?.GetType().FullName ?? "\"null\""}");
|
||||||
|
|
||||||
public static void Check<T1, T2>(T1 to, T2? value)
|
|
||||||
{
|
|
||||||
if (value is not null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
throw From(to, value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.Core.Exceptions;
|
||||||
|
|
||||||
|
public class UniverseObjectNotFoundException(string? message) : Exception(message)
|
||||||
|
{
|
||||||
|
public static NotAssignedException FromType<TUniverseObject>()
|
||||||
|
=> new($"{typeof(TUniverseObject).FullName} was not found");
|
||||||
|
}
|
@ -1,9 +0,0 @@
|
|||||||
namespace Syntriax.Engine.Core.Abstract;
|
|
||||||
|
|
||||||
public static class TransformExtensions
|
|
||||||
{
|
|
||||||
public static Vector2D TransformVector2D(this ITransform2D transform, Vector2D vector)
|
|
||||||
=> vector.Scale(transform.Scale)
|
|
||||||
.Rotate(transform.Rotation * Math.DegreeToRadian)
|
|
||||||
.Add(transform.Position);
|
|
||||||
}
|
|
@ -1,6 +1,7 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
using Syntriax.Engine.Core.Abstract;
|
using Syntriax.Engine.Core.Abstract;
|
||||||
|
using Syntriax.Engine.Core.Exceptions;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Syntriax.Engine.Core;
|
||||||
|
|
||||||
@ -19,6 +20,15 @@ public static class BehaviourControllerExtensions
|
|||||||
return behaviour is not null;
|
return behaviour is not null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a <see cref="IBehaviour"/> of the specified type in the provided <see cref="IBehaviourController"/>. Throws an error if not found.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type of <see cref="IBehaviour"/> to get.</typeparam>
|
||||||
|
/// <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>
|
||||||
|
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}");
|
||||||
|
|
||||||
/// <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.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -30,12 +40,12 @@ public static class BehaviourControllerExtensions
|
|||||||
=> behaviourController.GetBehaviour<T>() ?? behaviourController.AddBehaviour<T>(args);
|
=> behaviourController.GetBehaviour<T>() ?? behaviourController.AddBehaviour<T>(args);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tries to get a <see cref="IBehaviour"/> of the specified type in the parent hierarchy.
|
/// Tries to get a <see cref="IBehaviour"/> of the specified type in it's <see cref="IUniverseObject"/>'s parents recursively.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The type of <see cref="IBehaviour"/> to get.</typeparam>
|
/// <typeparam name="T">The type of <see cref="IBehaviour"/> to get.</typeparam>
|
||||||
/// <param name="behaviourController">The <see cref="IBehaviourController"/> to start searching from.</param>
|
/// <param name="behaviourController">The <see cref="IBehaviourController"/> to start searching from.</param>
|
||||||
/// <param name="behaviour">When this method returns, contains the <see cref="IBehaviour"/> of the specified type, if found; otherwise, null.</param>
|
/// <param name="behaviour">When this method returns, contains the <see cref="IBehaviour"/> of the specified type, if found; otherwise, null.</param>
|
||||||
/// <returns><see cref="true"/> if a <see cref="IBehaviour"/> of the specified type was found in the parent hierarchy; otherwise, <see cref="false"/>.</returns>
|
/// <returns><see cref="true"/> if a <see cref="IBehaviour"/> of the specified type was found in the parent universe; otherwise, <see cref="false"/>.</returns>
|
||||||
public static bool TryGetBehaviourInParent<T>(this IBehaviourController behaviourController, [NotNullWhen(returnValue: true)] out T? behaviour) where T : class
|
public static bool TryGetBehaviourInParent<T>(this IBehaviourController behaviourController, [NotNullWhen(returnValue: true)] out T? behaviour) where T : class
|
||||||
{
|
{
|
||||||
behaviour = GetBehaviourInParent<T>(behaviourController);
|
behaviour = GetBehaviourInParent<T>(behaviourController);
|
||||||
@ -43,7 +53,7 @@ public static class BehaviourControllerExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a <see cref="IBehaviour"/> of the specified type in the parent hierarchy.
|
/// Gets a <see cref="IBehaviour"/> of the specified type in it's <see cref="IUniverseObject"/>'s parents recursively.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The type of <see cref="IBehaviour"/> to get.</typeparam>
|
/// <typeparam name="T">The type of <see cref="IBehaviour"/> to get.</typeparam>
|
||||||
/// <param name="behaviourController">The <see cref="IBehaviourController"/> to start searching from.</param>
|
/// <param name="behaviourController">The <see cref="IBehaviourController"/> to start searching from.</param>
|
||||||
@ -54,22 +64,31 @@ public static class BehaviourControllerExtensions
|
|||||||
|
|
||||||
while (controller is not null)
|
while (controller is not null)
|
||||||
{
|
{
|
||||||
if (behaviourController.GetBehaviour<T>() is T behaviour)
|
if (controller.GetBehaviour<T>() is T behaviour)
|
||||||
return behaviour;
|
return behaviour;
|
||||||
|
|
||||||
controller = controller.HierarchyObject.Parent?.BehaviourController;
|
controller = controller.UniverseObject.Parent?.BehaviourController;
|
||||||
}
|
}
|
||||||
|
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tries to get a <see cref="IBehaviour"/> of the specified type in the child hierarchy.
|
/// Gets a <see cref="IBehaviour"/> of the specified type in it's <see cref="IUniverseObject"/>'s parents recursively. Throws an error if not found.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type of <see cref="IBehaviour"/> to get.</typeparam>
|
||||||
|
/// <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>
|
||||||
|
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");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to get a <see cref="IBehaviour"/> of the specified type in it's <see cref="IUniverseObject"/>'s children recursively.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The type of <see cref="IBehaviour"/> to get.</typeparam>
|
/// <typeparam name="T">The type of <see cref="IBehaviour"/> to get.</typeparam>
|
||||||
/// <param name="behaviourController">The <see cref="IBehaviourController"/> to start searching from.</param>
|
/// <param name="behaviourController">The <see cref="IBehaviourController"/> to start searching from.</param>
|
||||||
/// <param name="behaviour">When this method returns, contains the <see cref="IBehaviour"/> of the specified type, if found; otherwise, null.</param>
|
/// <param name="behaviour">When this method returns, contains the <see cref="IBehaviour"/> of the specified type, if found; otherwise, null.</param>
|
||||||
/// <returns><see cref="true"/> if a <see cref="IBehaviour"/> of the specified type was found in the child hierarchy; otherwise, <see cref="false"/>.</returns>
|
/// <returns><see cref="true"/> if a <see cref="IBehaviour"/> of the specified type was found in the child universe; otherwise, <see cref="false"/>.</returns>
|
||||||
public static bool TryGetBehaviourInChildren<T>(this IBehaviourController behaviourController, [NotNullWhen(returnValue: true)] out T? behaviour) where T : class
|
public static bool TryGetBehaviourInChildren<T>(this IBehaviourController behaviourController, [NotNullWhen(returnValue: true)] out T? behaviour) where T : class
|
||||||
{
|
{
|
||||||
behaviour = GetBehaviourInChildren<T>(behaviourController);
|
behaviour = GetBehaviourInChildren<T>(behaviourController);
|
||||||
@ -77,7 +96,7 @@ public static class BehaviourControllerExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a <see cref="IBehaviour"/> of the specified type in the child hierarchy.
|
/// Gets a <see cref="IBehaviour"/> of the specified type in it's <see cref="IUniverseObject"/>'s children recursively.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The type of <see cref="IBehaviour"/> to get.</typeparam>
|
/// <typeparam name="T">The type of <see cref="IBehaviour"/> to get.</typeparam>
|
||||||
/// <param name="behaviourController">The <see cref="IBehaviourController"/> to start searching from.</param>
|
/// <param name="behaviourController">The <see cref="IBehaviourController"/> to start searching from.</param>
|
||||||
@ -87,10 +106,19 @@ public static class BehaviourControllerExtensions
|
|||||||
if (behaviourController.GetBehaviour<T>() is T localBehaviour)
|
if (behaviourController.GetBehaviour<T>() is T localBehaviour)
|
||||||
return localBehaviour;
|
return localBehaviour;
|
||||||
|
|
||||||
foreach (IHierarchyObject child in behaviourController.HierarchyObject)
|
foreach (IUniverseObject child in behaviourController.UniverseObject)
|
||||||
if (GetBehaviourInChildren<T>(child.BehaviourController) is T behaviour)
|
if (GetBehaviourInChildren<T>(child.BehaviourController) is T behaviour)
|
||||||
return behaviour;
|
return behaviour;
|
||||||
|
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a <see cref="IBehaviour"/> of the specified type in the children recursively. Throws an error if not found.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type of <see cref="IBehaviour"/> to get.</typeparam>
|
||||||
|
/// <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>
|
||||||
|
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 ");
|
||||||
}
|
}
|
||||||
|
@ -7,29 +7,29 @@ namespace Syntriax.Engine.Core;
|
|||||||
|
|
||||||
public static class BehaviourExtensions
|
public static class BehaviourExtensions
|
||||||
{
|
{
|
||||||
public static T? FindBehaviour<T>(this IEnumerable<IHierarchyObject> hierarchyObjects) where T : class
|
public static T? FindBehaviour<T>(this IEnumerable<IUniverseObject> universeObjects) where T : class
|
||||||
{
|
{
|
||||||
foreach (IHierarchyObject hierarchyObject in hierarchyObjects)
|
foreach (IUniverseObject universeObject in universeObjects)
|
||||||
if (hierarchyObject.BehaviourController.GetBehaviour<T>() is T behaviour)
|
if (universeObject.BehaviourController.GetBehaviour<T>() is T behaviour)
|
||||||
return behaviour;
|
return behaviour;
|
||||||
|
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool TryFindBehaviour<T>(this IEnumerable<IHierarchyObject> hierarchyObjects, [NotNullWhen(returnValue: true)] out T? behaviour) where T : class
|
public static bool TryFindBehaviour<T>(this IEnumerable<IUniverseObject> universeObjects, [NotNullWhen(returnValue: true)] out T? behaviour) where T : class
|
||||||
{
|
{
|
||||||
behaviour = FindBehaviour<T>(hierarchyObjects);
|
behaviour = FindBehaviour<T>(universeObjects);
|
||||||
return behaviour is not null;
|
return behaviour is not null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void FindBehaviours<T>(this IEnumerable<IHierarchyObject> hierarchyObjects, List<T> behaviours) where T : class
|
public static void FindBehaviours<T>(this IEnumerable<IUniverseObject> universeObjects, List<T> behaviours) where T : class
|
||||||
{
|
{
|
||||||
behaviours.Clear();
|
behaviours.Clear();
|
||||||
List<T> cache = [];
|
List<T> cache = [];
|
||||||
|
|
||||||
foreach (IHierarchyObject hierarchyObject in hierarchyObjects)
|
foreach (IUniverseObject universeObject in universeObjects)
|
||||||
{
|
{
|
||||||
hierarchyObject.BehaviourController.GetBehaviours(cache);
|
universeObject.BehaviourController.GetBehaviours(cache);
|
||||||
behaviours.AddRange(cache);
|
behaviours.AddRange(cache);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
using Syntriax.Engine.Core.Abstract;
|
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
|
||||||
|
|
||||||
public static class GameManagerExtensions
|
|
||||||
{
|
|
||||||
public static IHierarchyObject InstantiateHierarchyObject(this IGameManager gameManager, params object?[]? args)
|
|
||||||
=> gameManager.InstantiateHierarchyObject<HierarchyObject>(args);
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
|
|
||||||
using Syntriax.Engine.Core.Abstract;
|
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
|
||||||
|
|
||||||
public static class HierarchyObjectExtensions
|
|
||||||
{
|
|
||||||
public static IHierarchyObject SetHierarchyObject(this IHierarchyObject hierarchyObject, string name)
|
|
||||||
{
|
|
||||||
hierarchyObject.Name = name;
|
|
||||||
return hierarchyObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static T? FindHierarchyObject<T>(this IEnumerable<IHierarchyObject> hierarchyObjects) where T : class
|
|
||||||
{
|
|
||||||
foreach (IHierarchyObject hierarchyObject in hierarchyObjects)
|
|
||||||
if (hierarchyObject is T @object)
|
|
||||||
return @object;
|
|
||||||
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryFindHierarchyObject<T>(this IEnumerable<IHierarchyObject> hierarchyObjects, [NotNullWhen(returnValue: true)] out T? behaviour) where T : class
|
|
||||||
{
|
|
||||||
behaviour = FindHierarchyObject<T>(hierarchyObjects);
|
|
||||||
return behaviour is not null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void FindHierarchyObjects<T>(this IEnumerable<IHierarchyObject> hierarchyObjects, List<T> behaviours) where T : class
|
|
||||||
{
|
|
||||||
behaviours.Clear();
|
|
||||||
foreach (IHierarchyObject hierarchyObject in hierarchyObjects)
|
|
||||||
if (hierarchyObject is T @object)
|
|
||||||
behaviours.Add(@object);
|
|
||||||
}
|
|
||||||
}
|
|
16
Engine.Core/Extensions/UniverseExtensions.cs
Normal file
16
Engine.Core/Extensions/UniverseExtensions.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using Syntriax.Engine.Core.Abstract;
|
||||||
|
using Syntriax.Engine.Core.Exceptions;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.Core;
|
||||||
|
|
||||||
|
public static class UniverseExtensions
|
||||||
|
{
|
||||||
|
public static IUniverseObject InstantiateUniverseObject(this IUniverse universe, params object?[]? args)
|
||||||
|
=> universe.InstantiateUniverseObject<UniverseObject>(args);
|
||||||
|
|
||||||
|
public static T GetRequiredUniverseObject<T>(this IUniverse universe) where T : class
|
||||||
|
=> universe.GetUniverseObject<T>() ?? throw new UniverseObjectNotFoundException($"{universe.GetType().FullName}({universe.Id}) does not contain any {nameof(IUniverseObject)} object of type {typeof(T).FullName}");
|
||||||
|
|
||||||
|
public static T FindRequiredBehaviour<T>(this IUniverse universe) where T : class
|
||||||
|
=> universe.FindBehaviour<T>() ?? throw new BehaviourNotFoundException($"{universe.GetType().FullName}({universe.Id}) does not contain any {nameof(IUniverseObject)} with {nameof(IBehaviour)} of type {typeof(T).FullName}");
|
||||||
|
}
|
41
Engine.Core/Extensions/UniverseObjectExtensions.cs
Normal file
41
Engine.Core/Extensions/UniverseObjectExtensions.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
using Syntriax.Engine.Core.Abstract;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.Core;
|
||||||
|
|
||||||
|
public static class UniverseObjectExtensions
|
||||||
|
{
|
||||||
|
public static T SetUniverseObject<T>(this T universeObject, string? name = "", IUniverseObject? parent = null) where T : IUniverseObject
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(name))
|
||||||
|
universeObject.Name = name;
|
||||||
|
if (parent is not null)
|
||||||
|
universeObject.SetParent(parent);
|
||||||
|
return universeObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T? GetUniverseObject<T>(this IEnumerable<IUniverseObject> universeObjects) where T : class
|
||||||
|
{
|
||||||
|
foreach (IUniverseObject universeObject in universeObjects)
|
||||||
|
if (universeObject is T @object)
|
||||||
|
return @object;
|
||||||
|
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryGetUniverseObject<T>(this IEnumerable<IUniverseObject> universeObjects, [NotNullWhen(returnValue: true)] out T? behaviour) where T : class
|
||||||
|
{
|
||||||
|
behaviour = GetUniverseObject<T>(universeObjects);
|
||||||
|
return behaviour is not null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void GetUniverseObjects<T>(this IEnumerable<IUniverseObject> universeObjects, List<T> behaviours) where T : class
|
||||||
|
{
|
||||||
|
behaviours.Clear();
|
||||||
|
foreach (IUniverseObject universeObject in universeObjects)
|
||||||
|
if (universeObject is T @object)
|
||||||
|
behaviours.Add(@object);
|
||||||
|
}
|
||||||
|
}
|
@ -5,19 +5,19 @@ namespace Syntriax.Engine.Core.Factory;
|
|||||||
|
|
||||||
public class BehaviourControllerFactory
|
public class BehaviourControllerFactory
|
||||||
{
|
{
|
||||||
public static IBehaviourController Instantiate(IHierarchyObject hierarchyObject)
|
public static IBehaviourController Instantiate(IUniverseObject universeObject)
|
||||||
=> Instantiate<BehaviourController>(hierarchyObject);
|
=> Instantiate<BehaviourController>(universeObject);
|
||||||
|
|
||||||
public static T Instantiate<T>(IHierarchyObject hierarchyObject, params object?[]? args)
|
public static T Instantiate<T>(IUniverseObject universeObject, params object?[]? args)
|
||||||
where T : class, IBehaviourController
|
where T : class, IBehaviourController
|
||||||
{
|
{
|
||||||
T behaviourController = TypeFactory.Get<T>(args);
|
T behaviourController = TypeFactory.Get<T>(args);
|
||||||
|
|
||||||
if (!hierarchyObject.Assign(behaviourController))
|
if (!universeObject.Assign(behaviourController))
|
||||||
throw AssignException.From(hierarchyObject, behaviourController);
|
throw AssignFailedException.From(universeObject, behaviourController);
|
||||||
|
|
||||||
if (!behaviourController.Assign(hierarchyObject))
|
if (!behaviourController.Assign(universeObject))
|
||||||
throw AssignException.From(behaviourController, hierarchyObject);
|
throw AssignFailedException.From(behaviourController, universeObject);
|
||||||
|
|
||||||
return behaviourController;
|
return behaviourController;
|
||||||
}
|
}
|
||||||
|
@ -5,22 +5,22 @@ namespace Syntriax.Engine.Core.Factory;
|
|||||||
|
|
||||||
public class BehaviourFactory
|
public class BehaviourFactory
|
||||||
{
|
{
|
||||||
public static T Instantiate<T>(IHierarchyObject hierarchyObject, params object?[]? args) where T : class, IBehaviour
|
public static T Instantiate<T>(IUniverseObject universeObject, params object?[]? args) where T : class, IBehaviour
|
||||||
=> Instantiate<T>(hierarchyObject, stateEnable: null, args);
|
=> Instantiate<T>(universeObject, stateEnable: null, args);
|
||||||
|
|
||||||
public static T Instantiate<T>(IHierarchyObject hierarchyObject, IStateEnable? stateEnable, params object?[]? args)
|
public static T Instantiate<T>(IUniverseObject universeObject, IStateEnable? stateEnable, params object?[]? args)
|
||||||
where T : class, IBehaviour
|
where T : class, IBehaviour
|
||||||
{
|
{
|
||||||
T behaviour = TypeFactory.Get<T>(args);
|
T behaviour = TypeFactory.Get<T>(args);
|
||||||
|
|
||||||
stateEnable ??= TypeFactory.Get<StateEnable>();
|
stateEnable ??= TypeFactory.Get<StateEnable>();
|
||||||
if (!stateEnable.Assign(behaviour))
|
if (!stateEnable.Assign(behaviour))
|
||||||
throw AssignException.From(stateEnable, behaviour);
|
throw AssignFailedException.From(stateEnable, behaviour);
|
||||||
|
|
||||||
if (!behaviour.Assign(stateEnable))
|
if (!behaviour.Assign(stateEnable))
|
||||||
throw AssignException.From(behaviour, stateEnable);
|
throw AssignFailedException.From(behaviour, stateEnable);
|
||||||
if (!behaviour.Assign(hierarchyObject.BehaviourController))
|
if (!behaviour.Assign(universeObject.BehaviourController))
|
||||||
throw AssignException.From(behaviour, hierarchyObject.BehaviourController);
|
throw AssignFailedException.From(behaviour, universeObject.BehaviourController);
|
||||||
|
|
||||||
return behaviour;
|
return behaviour;
|
||||||
}
|
}
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
using Syntriax.Engine.Core.Abstract;
|
|
||||||
using Syntriax.Engine.Core.Exceptions;
|
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core.Factory;
|
|
||||||
|
|
||||||
public class HierarchyObjectFactory
|
|
||||||
{
|
|
||||||
public static T Instantiate<T>(params object?[]? args) where T : class, IHierarchyObject
|
|
||||||
=> Instantiate<T>(behaviourController: null, stateEnable: null, args);
|
|
||||||
|
|
||||||
public static T Instantiate<T>(
|
|
||||||
IBehaviourController? behaviourController = null,
|
|
||||||
IStateEnable? stateEnable = null,
|
|
||||||
params object?[]? args
|
|
||||||
)
|
|
||||||
where T : class, IHierarchyObject
|
|
||||||
{
|
|
||||||
T hierarchyObject = TypeFactory.Get<T>(args);
|
|
||||||
|
|
||||||
behaviourController ??= TypeFactory.Get<BehaviourController>();
|
|
||||||
stateEnable ??= TypeFactory.Get<StateEnable>();
|
|
||||||
|
|
||||||
if (!behaviourController.Assign(hierarchyObject))
|
|
||||||
throw AssignException.From(behaviourController, hierarchyObject);
|
|
||||||
if (!stateEnable.Assign(hierarchyObject))
|
|
||||||
throw AssignException.From(stateEnable, hierarchyObject);
|
|
||||||
|
|
||||||
if (!hierarchyObject.Assign(behaviourController))
|
|
||||||
throw AssignException.From(hierarchyObject, behaviourController);
|
|
||||||
if (!hierarchyObject.Assign(stateEnable))
|
|
||||||
throw AssignException.From(hierarchyObject, stateEnable);
|
|
||||||
|
|
||||||
return hierarchyObject;
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,10 +12,10 @@ public class StateEnableFactory
|
|||||||
T stateEnable = TypeFactory.Get<T>(args);
|
T stateEnable = TypeFactory.Get<T>(args);
|
||||||
|
|
||||||
if (!entity.Assign(stateEnable))
|
if (!entity.Assign(stateEnable))
|
||||||
throw AssignException.From(entity, stateEnable);
|
throw AssignFailedException.From(entity, stateEnable);
|
||||||
|
|
||||||
if (!stateEnable.Assign(entity))
|
if (!stateEnable.Assign(entity))
|
||||||
throw AssignException.From(stateEnable, entity);
|
throw AssignFailedException.From(stateEnable, entity);
|
||||||
|
|
||||||
return stateEnable;
|
return stateEnable;
|
||||||
}
|
}
|
||||||
|
37
Engine.Core/Factory/UniverseObjectFactory.cs
Normal file
37
Engine.Core/Factory/UniverseObjectFactory.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using Syntriax.Engine.Core.Abstract;
|
||||||
|
using Syntriax.Engine.Core.Exceptions;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.Core.Factory;
|
||||||
|
|
||||||
|
public class UniverseObjectFactory
|
||||||
|
{
|
||||||
|
public static IUniverseObject Instantiate() => Instantiate<UniverseObject>();
|
||||||
|
public static T Instantiate<T>(params object?[]? args) where T : class, IUniverseObject
|
||||||
|
=> Instantiate<T>(behaviourController: null, stateEnable: null, args);
|
||||||
|
|
||||||
|
public static IUniverseObject Instantiate(IBehaviourController? behaviourController = null, IStateEnable? stateEnable = null) => Instantiate<UniverseObject>(behaviourController, stateEnable);
|
||||||
|
public static T Instantiate<T>(
|
||||||
|
IBehaviourController? behaviourController = null,
|
||||||
|
IStateEnable? stateEnable = null,
|
||||||
|
params object?[]? args
|
||||||
|
)
|
||||||
|
where T : class, IUniverseObject
|
||||||
|
{
|
||||||
|
T universeObject = TypeFactory.Get<T>(args);
|
||||||
|
|
||||||
|
behaviourController ??= TypeFactory.Get<BehaviourController>();
|
||||||
|
stateEnable ??= TypeFactory.Get<StateEnable>();
|
||||||
|
|
||||||
|
if (!behaviourController.Assign(universeObject))
|
||||||
|
throw AssignFailedException.From(behaviourController, universeObject);
|
||||||
|
if (!stateEnable.Assign(universeObject))
|
||||||
|
throw AssignFailedException.From(stateEnable, universeObject);
|
||||||
|
|
||||||
|
if (!universeObject.Assign(behaviourController))
|
||||||
|
throw AssignFailedException.From(universeObject, behaviourController);
|
||||||
|
if (!universeObject.Assign(stateEnable))
|
||||||
|
throw AssignFailedException.From(universeObject, stateEnable);
|
||||||
|
|
||||||
|
return universeObject;
|
||||||
|
}
|
||||||
|
}
|
@ -1,139 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
using Syntriax.Engine.Core.Abstract;
|
|
||||||
using Syntriax.Engine.Core.Exceptions;
|
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
|
||||||
|
|
||||||
[System.Diagnostics.DebuggerDisplay("HierarchyObject Count: {_hierarchyObjects.Count}")]
|
|
||||||
public class GameManager : BaseEntity, IGameManager
|
|
||||||
{
|
|
||||||
public event IGameManager.UpdateEventHandler? OnUpdate = null;
|
|
||||||
public event IGameManager.PreDawEventHandler? OnPreDraw = null;
|
|
||||||
|
|
||||||
public event IGameManager.HierarchyObjectRegisteredEventHandler? OnHierarchyObjectRegistered = null;
|
|
||||||
public event IGameManager.HierarchyObjectUnRegisteredEventHandler? OnHierarchyObjectUnRegistered = null;
|
|
||||||
|
|
||||||
private readonly List<IHierarchyObject> _hierarchyObjects = new(Constants.GAME_OBJECTS_SIZE_INITIAL);
|
|
||||||
|
|
||||||
public IReadOnlyList<IHierarchyObject> HierarchyObjects => _hierarchyObjects;
|
|
||||||
|
|
||||||
public override IStateEnable StateEnable
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (base.StateEnable is null)
|
|
||||||
{
|
|
||||||
Assign(Factory.StateEnableFactory.Instantiate(this));
|
|
||||||
if (base.StateEnable is null)
|
|
||||||
throw NotAssignedException.From(this, base.StateEnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.StateEnable;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public EngineTime Time { get; private set; } = new();
|
|
||||||
|
|
||||||
public void Register(IHierarchyObject hierarchyObject)
|
|
||||||
{
|
|
||||||
if (_hierarchyObjects.Contains(hierarchyObject))
|
|
||||||
throw new Exception($"{nameof(IHierarchyObject)} named {hierarchyObject.Name} is already registered to the {nameof(GameManager)}.");
|
|
||||||
|
|
||||||
hierarchyObject.OnFinalized += OnHierarchyObjectFinalize;
|
|
||||||
hierarchyObject.OnExitedHierarchy += OnHierarchyObjectExitedHierarchy;
|
|
||||||
|
|
||||||
if (!hierarchyObject.Initialize())
|
|
||||||
throw new Exception($"{hierarchyObject.Name} can't be initialized");
|
|
||||||
|
|
||||||
foreach (IHierarchyObject child in hierarchyObject.Children)
|
|
||||||
Register(child);
|
|
||||||
|
|
||||||
_hierarchyObjects.Add(hierarchyObject);
|
|
||||||
|
|
||||||
if (!hierarchyObject.EnterHierarchy(this))
|
|
||||||
throw new Exception($"{hierarchyObject.Name} can't enter the hierarchy");
|
|
||||||
|
|
||||||
OnHierarchyObjectRegistered?.Invoke(this, hierarchyObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T InstantiateHierarchyObject<T>(params object?[]? args) where T : class, IHierarchyObject
|
|
||||||
{
|
|
||||||
T hierarchyObject = Factory.HierarchyObjectFactory.Instantiate<T>(args);
|
|
||||||
Register(hierarchyObject);
|
|
||||||
return hierarchyObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Remove(IHierarchyObject hierarchyObject)
|
|
||||||
{
|
|
||||||
if (!_hierarchyObjects.Contains(hierarchyObject))
|
|
||||||
throw new Exception($"{nameof(IHierarchyObject)} named {hierarchyObject.Name} is not registered to the {nameof(GameManager)}.");
|
|
||||||
|
|
||||||
hierarchyObject.OnFinalized -= OnHierarchyObjectFinalize;
|
|
||||||
hierarchyObject.OnExitedHierarchy -= OnHierarchyObjectExitedHierarchy;
|
|
||||||
|
|
||||||
foreach (IHierarchyObject child in hierarchyObject.Children)
|
|
||||||
Remove(child);
|
|
||||||
|
|
||||||
_hierarchyObjects.Remove(hierarchyObject);
|
|
||||||
|
|
||||||
if (!hierarchyObject.ExitHierarchy())
|
|
||||||
throw new Exception($"{hierarchyObject.Name} can't exit the hierarchy");
|
|
||||||
|
|
||||||
if (!hierarchyObject.Finalize())
|
|
||||||
throw new Exception($"{hierarchyObject.Name} can't be finalized");
|
|
||||||
|
|
||||||
OnHierarchyObjectUnRegistered?.Invoke(this, hierarchyObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void InitializeInternal()
|
|
||||||
{
|
|
||||||
base.InitializeInternal();
|
|
||||||
NotAssignedException.Check(this, StateEnable);
|
|
||||||
|
|
||||||
foreach (IHierarchyObject hierarchyObject in HierarchyObjects)
|
|
||||||
hierarchyObject.Initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void FinalizeInternal()
|
|
||||||
{
|
|
||||||
base.FinalizeInternal();
|
|
||||||
for (int i = HierarchyObjects.Count; i >= 0; i--)
|
|
||||||
HierarchyObjects[i].Finalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Update(EngineTime engineTime)
|
|
||||||
{
|
|
||||||
Time = engineTime;
|
|
||||||
|
|
||||||
for (int i = 0; i < HierarchyObjects.Count; i++)
|
|
||||||
HierarchyObjects[i].BehaviourController.Update();
|
|
||||||
|
|
||||||
OnUpdate?.Invoke(this, engineTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PreDraw()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < HierarchyObjects.Count; i++)
|
|
||||||
HierarchyObjects[i].BehaviourController.UpdatePreDraw();
|
|
||||||
|
|
||||||
OnPreDraw?.Invoke(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnHierarchyObjectFinalize(IInitializable initializable)
|
|
||||||
{
|
|
||||||
if (initializable is IHierarchyObject hierarchyObject)
|
|
||||||
Remove(hierarchyObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnHierarchyObjectExitedHierarchy(IHierarchyObject sender, IGameManager gameManager)
|
|
||||||
{
|
|
||||||
if (sender is IHierarchyObject hierarchyObject)
|
|
||||||
Remove(hierarchyObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerator<IHierarchyObject> GetEnumerator() => _hierarchyObjects.GetEnumerator();
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() => _hierarchyObjects.GetEnumerator();
|
|
||||||
}
|
|
32
Engine.Core/Helpers/AssertHelpers.cs
Normal file
32
Engine.Core/Helpers/AssertHelpers.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
using Syntriax.Engine.Core.Abstract;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.Core.Debug;
|
||||||
|
|
||||||
|
public class AssertHelpers
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void AssertInitialized(IInitializable initializable)
|
||||||
|
=> System.Diagnostics.Debug.Assert(initializable.IsInitialized, $"{initializable.GetType().Name} must be initialized");
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void AssertBehaviourControllerAssigned(IHasBehaviourController assignable)
|
||||||
|
=> System.Diagnostics.Debug.Assert(assignable.BehaviourController is not null, $"{assignable.GetType().Name} must be initialized");
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void AssertEntityAssigned(IHasEntity assignable)
|
||||||
|
=> System.Diagnostics.Debug.Assert(assignable.Entity is not null, $"{assignable.GetType().Name} must be initialized");
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void AssertUniverseAssigned(IHasUniverse assignable)
|
||||||
|
=> System.Diagnostics.Debug.Assert(assignable.Universe is not null, $"{assignable.GetType().Name} must be initialized");
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void AssertUniverseObjectAssigned(IHasUniverseObject assignable)
|
||||||
|
=> System.Diagnostics.Debug.Assert(assignable.UniverseObject is not null, $"{assignable.GetType().Name} must be initialized");
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void AssertStateEnableAssigned(IHasStateEnable assignable)
|
||||||
|
=> System.Diagnostics.Debug.Assert(assignable.StateEnable is not null, $"{assignable.GetType().Name} must be initialized");
|
||||||
|
}
|
17
Engine.Core/Helpers/DelegateHelpers.cs
Normal file
17
Engine.Core/Helpers/DelegateHelpers.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.Core;
|
||||||
|
|
||||||
|
public static class DelegateHelpers
|
||||||
|
{
|
||||||
|
public static void InvokeSafe(this Delegate @delegate, params object?[] args)
|
||||||
|
{
|
||||||
|
foreach (Delegate invocation in @delegate.GetInvocationList())
|
||||||
|
try { invocation.DynamicInvoke(args); }
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
string methodCallRepresentation = $"{invocation.Method.DeclaringType?.FullName}.{invocation.Method.Name}({string.Join(", ", args)})";
|
||||||
|
Console.WriteLine($"Unexpected exception on invocation of method {methodCallRepresentation}:{Environment.NewLine}{exception.InnerException}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
using Syntriax.Engine.Core.Abstract;
|
using Syntriax.Engine.Core.Abstract;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Syntriax.Engine.Core;
|
||||||
@ -66,8 +67,8 @@ public readonly struct Circle(Vector2D center, float radius)
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Transforms the <see cref="Circle"/> by the specified <see cref="ITransform2D"/>.
|
/// Transforms the <see cref="Circle"/> by the specified <see cref="ITransform2D"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static Circle TransformCircle(ITransform2D transform, Circle circle)
|
public static Circle Transform(ITransform2D transform, Circle circle)
|
||||||
=> new(transform.TransformVector2D(circle.Center), circle.Radius * (transform.Scale.Magnitude / Vector2D.One.Magnitude));
|
=> new(transform.Transform(circle.Center), circle.Radius * (transform.Scale.Magnitude / Vector2D.One.Magnitude));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if two <see cref="Circle"/>s are approximately equal.
|
/// Checks if two <see cref="Circle"/>s are approximately equal.
|
||||||
@ -97,8 +98,11 @@ public static class CircleExtensions
|
|||||||
/// <inheritdoc cref="Circle.Project(Circle, Vector2D)" />
|
/// <inheritdoc cref="Circle.Project(Circle, Vector2D)" />
|
||||||
public static Projection1D ToProjection(this Circle circle, Vector2D projectionVector) => Circle.Project(circle, projectionVector);
|
public static Projection1D ToProjection(this Circle circle, Vector2D projectionVector) => Circle.Project(circle, projectionVector);
|
||||||
|
|
||||||
/// <inheritdoc cref="Circle.TransformCircle(ITransform2D, Circle)" />
|
/// <inheritdoc cref="Circle.Transform(ITransform2D, Circle)" />
|
||||||
public static Circle TransformCircle(this ITransform2D transform, Circle circle) => Circle.TransformCircle(transform, circle);
|
public static Circle Transform(this ITransform2D transform, Circle circle) => Circle.Transform(transform, circle);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Circle.Transform(ITransform2D, Circle)" />
|
||||||
|
public static Circle Transform(this Circle circle, ITransform2D transform) => Circle.Transform(transform, circle);
|
||||||
|
|
||||||
/// <inheritdoc cref="Circle.ApproximatelyEquals(Circle, Circle, float)" />
|
/// <inheritdoc cref="Circle.ApproximatelyEquals(Circle, Circle, float)" />
|
||||||
public static bool ApproximatelyEquals(this Circle left, Circle right, float epsilon = float.Epsilon) => Circle.ApproximatelyEquals(left, right, epsilon);
|
public static bool ApproximatelyEquals(this Circle left, Circle right, float epsilon = float.Epsilon) => Circle.ApproximatelyEquals(left, right, epsilon);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using Syntriax.Engine.Core.Abstract;
|
using Syntriax.Engine.Core.Abstract;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Syntriax.Engine.Core;
|
||||||
@ -9,20 +10,20 @@ namespace Syntriax.Engine.Core;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="vertices">The vertices of the shape.</param>
|
/// <param name="vertices">The vertices of the shape.</param>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Initializes a new instance of the <see cref="Shape2D"/> struct with the specified vertices.
|
/// Initializes a new instance of a <see cref="Shape2D"/> struct with the specified vertices.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[System.Diagnostics.DebuggerDisplay("Vertices Count: {Vertices.Count}")]
|
[System.Diagnostics.DebuggerDisplay("Vertices Count: {Vertices.Count}")]
|
||||||
public readonly struct Shape2D(List<Vector2D> vertices) : IEnumerable<Vector2D>
|
public readonly struct Shape2D(List<Vector2D> vertices) : IEnumerable<Vector2D>
|
||||||
{
|
{
|
||||||
public static readonly Shape2D Triangle = CreateNgon(3, Vector2D.Up);
|
public static readonly Shape2D Triangle = CreateNgon(3, Vector2D.Up);
|
||||||
public static readonly Shape2D Box = CreateNgon(4, Vector2D.One);
|
public static readonly Shape2D Square = CreateNgon(4, Vector2D.One);
|
||||||
public static readonly Shape2D Pentagon = CreateNgon(5, Vector2D.Up);
|
public static readonly Shape2D Pentagon = CreateNgon(5, Vector2D.Up);
|
||||||
public static readonly Shape2D Hexagon = CreateNgon(6, Vector2D.Right);
|
public static readonly Shape2D Hexagon = CreateNgon(6, Vector2D.Right);
|
||||||
|
|
||||||
private readonly List<Vector2D> _verticesList = vertices;
|
private readonly List<Vector2D> _verticesList = vertices;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the vertices of the shape.
|
/// Gets the vertices of the <see cref="Shape2D"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IReadOnlyList<Vector2D> Vertices => _verticesList;
|
public IReadOnlyList<Vector2D> Vertices => _verticesList;
|
||||||
|
|
||||||
@ -34,10 +35,10 @@ public readonly struct Shape2D(List<Vector2D> vertices) : IEnumerable<Vector2D>
|
|||||||
public Vector2D this[System.Index index] => Vertices[index];
|
public Vector2D this[System.Index index] => Vertices[index];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a copy of the current shape.
|
/// Returns a copy of the current <see cref="Shape2D"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="shape">The shape to copy.</param>
|
/// <param name="shape">The <see cref="Shape2D"/> to copy.</param>
|
||||||
/// <returns>A copy of the input shape.</returns>
|
/// <returns>A copy of the input <see cref="Shape2D"/>.</returns>
|
||||||
public static Shape2D CreateCopy(Shape2D shape) => new(new List<Vector2D>(shape.Vertices));
|
public static Shape2D CreateCopy(Shape2D shape) => new(new List<Vector2D>(shape.Vertices));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -69,10 +70,10 @@ public readonly struct Shape2D(List<Vector2D> vertices) : IEnumerable<Vector2D>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the super triangle that encloses the given shape.
|
/// Gets the super triangle that encloses the given <see cref="Shape2D"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="shape">The shape to enclose.</param>
|
/// <param name="shape">The <see cref="Shape2D"/> to enclose.</param>
|
||||||
/// <returns>The super triangle that encloses the given shape.</returns>
|
/// <returns>The super triangle that encloses the given <see cref="Shape2D"/>.</returns>
|
||||||
public static Triangle GetSuperTriangle(Shape2D shape)
|
public static Triangle GetSuperTriangle(Shape2D shape)
|
||||||
{
|
{
|
||||||
float minX = float.MaxValue, minY = float.MaxValue;
|
float minX = float.MaxValue, minY = float.MaxValue;
|
||||||
@ -100,10 +101,35 @@ public readonly struct Shape2D(List<Vector2D> vertices) : IEnumerable<Vector2D>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the lines that form the edges of the shape.
|
/// Triangulates the given convex <see cref="Shape2D"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="shape">The shape to get lines from.</param>
|
/// <param name="shape">The <see cref="Shape2D"/> to triangulate.</param>
|
||||||
/// <param name="lines">The list to populate with lines.</param>
|
/// <param name="triangles">The list to populate with triangles.</param>
|
||||||
|
public static void TriangulateConvex(Shape2D shape, IList<Triangle> triangles)
|
||||||
|
{
|
||||||
|
triangles.Clear();
|
||||||
|
|
||||||
|
for (int i = 2; i < shape.Vertices.Count; i++)
|
||||||
|
triangles.Add(new Triangle(shape[0], shape[i - 1], shape[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Triangulates the given convex <see cref="Shape2D"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="shape">The <see cref="Shape2D"/> to triangulate.</param>
|
||||||
|
/// <returns>A list of <see cref="Triangle"/>s that makes up the given convex <see cref="Shape2D"/>.</returns>
|
||||||
|
public static List<Triangle> TriangulateConvex(Shape2D shape)
|
||||||
|
{
|
||||||
|
List<Triangle> triangles = new(shape.Vertices.Count - 2);
|
||||||
|
TriangulateConvex(shape, triangles);
|
||||||
|
return triangles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="Line2D"/>s that form the edges of the <see cref="Shape2D"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="shape">The <see cref="Shape2D"/> to get <see cref="Line2D"/>s from.</param>
|
||||||
|
/// <param name="lines">The list to populate with <see cref="Line2D"/>.</sparam>
|
||||||
public static void GetLines(Shape2D shape, IList<Line2D> lines)
|
public static void GetLines(Shape2D shape, IList<Line2D> lines)
|
||||||
{
|
{
|
||||||
lines.Clear();
|
lines.Clear();
|
||||||
@ -113,10 +139,10 @@ public readonly struct Shape2D(List<Vector2D> vertices) : IEnumerable<Vector2D>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a list of lines that form the edges of the shape.
|
/// Gets a list of <see cref="Line2D"/>s that form the edges of the <see cref="Shape2D"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="shape">The shape to get lines from.</param>
|
/// <param name="shape">The shape to get <see cref="Line2D"/>s from.</param>
|
||||||
/// <returns>A list of lines that form the edges of the shape.</returns>
|
/// <returns>A list of <see cref="Line2D"/>s that form the edges of the <see cref="Shape2D"/>.</returns>
|
||||||
public static List<Line2D> GetLines(Shape2D shape)
|
public static List<Line2D> GetLines(Shape2D shape)
|
||||||
{
|
{
|
||||||
List<Line2D> lines = new(shape.Vertices.Count - 1);
|
List<Line2D> lines = new(shape.Vertices.Count - 1);
|
||||||
@ -125,7 +151,7 @@ public readonly struct Shape2D(List<Vector2D> vertices) : IEnumerable<Vector2D>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Projects the shape onto a vector.
|
/// Projects the <see cref="Shape2D"/> onto a 1D plane.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="shape">The shape to project.</param>
|
/// <param name="shape">The shape to project.</param>
|
||||||
/// <param name="projectionVector">The vector to project onto.</param>
|
/// <param name="projectionVector">The vector to project onto.</param>
|
||||||
@ -140,11 +166,11 @@ public readonly struct Shape2D(List<Vector2D> vertices) : IEnumerable<Vector2D>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Projects the shape onto a vector.
|
/// Projects the <see cref="Shape2D"/> onto a vector.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="shape">The shape to project.</param>
|
/// <param name="shape">The <see cref="Shape2D"/> to project.</param>
|
||||||
/// <param name="projectionVector">The vector to project onto.</param>
|
/// <param name="projectionVector">The vector to project onto.</param>
|
||||||
/// <returns>The projection of the shape onto the vector.</returns>
|
/// <returns>The projection of the <see cref="Shape2D"/> onto the vector.</returns>
|
||||||
public static Projection1D Project(Shape2D shape, Vector2D projectionVector)
|
public static Projection1D Project(Shape2D shape, Vector2D projectionVector)
|
||||||
{
|
{
|
||||||
float min = float.MaxValue;
|
float min = float.MaxValue;
|
||||||
@ -161,44 +187,44 @@ public readonly struct Shape2D(List<Vector2D> vertices) : IEnumerable<Vector2D>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Transforms the shape using the specified transform.
|
/// Transforms the <see cref="Shape2D"/> using the specified <see cref="ITransform2D"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="shape">The shape to transform.</param>
|
/// <param name="shape">The <see cref="Shape2D"/> to transform.</param>
|
||||||
/// <param name="transform">The transform to apply.</param>
|
/// <param name="transform">The <see cref="ITransform2D"/> to apply.</param>
|
||||||
/// <returns>The transformed shape.</returns>
|
/// <returns>The transformed <see cref="Shape2D"/>.</returns>
|
||||||
public static Shape2D TransformShape(Shape2D shape, ITransform2D transform)
|
public static Shape2D Transform(Shape2D shape, ITransform2D transform)
|
||||||
{
|
{
|
||||||
List<Vector2D> vertices = new(shape.Vertices.Count);
|
List<Vector2D> vertices = new(shape.Vertices.Count);
|
||||||
|
|
||||||
int count = shape.Vertices.Count;
|
int count = shape.Vertices.Count;
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
vertices.Add(transform.TransformVector2D(shape[i]));
|
vertices.Add(transform.Transform(shape[i]));
|
||||||
|
|
||||||
return new Shape2D(vertices);
|
return new Shape2D(vertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Transforms the shape using the specified transform.
|
/// Transforms the <see cref="Shape2D"/> using the specified <see cref="ITransform2D"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="from">The shape to transform.</param>
|
/// <param name="from">The <see cref="Shape2D"/> to transform.</param>
|
||||||
/// <param name="transform">The transform to apply.</param>
|
/// <param name="transform">The <see cref="ITransform2D"/> to apply.</param>
|
||||||
/// <param name="to">The transformed shape.</param>
|
/// <param name="to">The transformed <see cref="Shape2D"/>.</param>
|
||||||
public static void TransformShape(Shape2D from, ITransform2D transform, ref Shape2D to)
|
public static void Transform(Shape2D from, ITransform2D transform, ref Shape2D to)
|
||||||
{
|
{
|
||||||
to._verticesList.Clear();
|
to._verticesList.Clear();
|
||||||
|
|
||||||
int count = from._verticesList.Count;
|
int count = from._verticesList.Count;
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
to._verticesList.Add(transform.TransformVector2D(from[i]));
|
to._verticesList.Add(transform.Transform(from[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether two shapes are approximately equal.
|
/// Determines whether two <see cref="Shape2D"/>s are approximately equal.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="left">The first shape to compare.</param>
|
/// <param name="left">The first <see cref="Shape2D"/> to compare.</param>
|
||||||
/// <param name="right">The second shape to compare.</param>
|
/// <param name="right">The second <see cref="Shape2D"/> to compare.</param>
|
||||||
/// <param name="epsilon">The epsilon range.</param>
|
/// <param name="epsilon">The epsilon range.</param>
|
||||||
/// <returns><c>true</c> if the shapes are approximately equal; otherwise, <c>false</c>.</returns>
|
/// <returns><c>true</c> if the <see cref="Shape2D"/>s are approximately equal; otherwise, <c>false</c>.</returns>
|
||||||
public static bool ApproximatelyEquals(Shape2D left, Shape2D right, float epsilon = float.Epsilon)
|
public static bool ApproximatelyEquals(Shape2D left, Shape2D right, float epsilon = float.Epsilon)
|
||||||
{
|
{
|
||||||
if (left.Vertices.Count != right.Vertices.Count)
|
if (left.Vertices.Count != right.Vertices.Count)
|
||||||
@ -229,6 +255,12 @@ public static class Shape2DExtensions
|
|||||||
/// <inheritdoc cref="Shape2D.GetSuperTriangle(Shape2D)" />
|
/// <inheritdoc cref="Shape2D.GetSuperTriangle(Shape2D)" />
|
||||||
public static Triangle ToSuperTriangle(this Shape2D shape) => Shape2D.GetSuperTriangle(shape);
|
public static Triangle ToSuperTriangle(this Shape2D shape) => Shape2D.GetSuperTriangle(shape);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Shape2D.TriangulateConvex(Shape2D, IList{Triangle})" />
|
||||||
|
public static void ToTrianglesConvex(this Shape2D shape, IList<Triangle> lines) => Shape2D.TriangulateConvex(shape, lines);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Shape2D.TriangulateConvex(Shape2D)" />
|
||||||
|
public static List<Triangle> ToTrianglesConvex(this Shape2D shape) => Shape2D.TriangulateConvex(shape);
|
||||||
|
|
||||||
/// <inheritdoc cref="Shape2D.GetLines(Shape2D, IList{Line2D})" />
|
/// <inheritdoc cref="Shape2D.GetLines(Shape2D, IList{Line2D})" />
|
||||||
public static void ToLines(this Shape2D shape, IList<Line2D> lines) => Shape2D.GetLines(shape, lines);
|
public static void ToLines(this Shape2D shape, IList<Line2D> lines) => Shape2D.GetLines(shape, lines);
|
||||||
|
|
||||||
@ -241,11 +273,17 @@ public static class Shape2DExtensions
|
|||||||
/// <inheritdoc cref="Shape2D.Project(Shape2D, Vector2D)" />
|
/// <inheritdoc cref="Shape2D.Project(Shape2D, Vector2D)" />
|
||||||
public static Projection1D ToProjection(this Shape2D shape, Vector2D projectionVector) => Shape2D.Project(shape, projectionVector);
|
public static Projection1D ToProjection(this Shape2D shape, Vector2D projectionVector) => Shape2D.Project(shape, projectionVector);
|
||||||
|
|
||||||
/// <inheritdoc cref="Shape2D.TransformShape(Shape2D, ITransform2D)" />
|
/// <inheritdoc cref="Shape2D.Transform(Shape2D, ITransform2D)" />
|
||||||
public static Shape2D TransformShape(this ITransform2D transform, Shape2D shape) => Shape2D.TransformShape(shape, transform);
|
public static Shape2D Transform(this ITransform2D transform, Shape2D shape) => Shape2D.Transform(shape, transform);
|
||||||
|
|
||||||
/// <inheritdoc cref="Shape2D.TransformShape(Shape2D, ITransform2D, Shape2D)" />
|
/// <inheritdoc cref="Shape2D.Transform(Shape2D, ITransform2D, Shape2D)" />
|
||||||
public static void TransformShape(this ITransform2D transform, Shape2D from, ref Shape2D to) => Shape2D.TransformShape(from, transform, ref to);
|
public static void Transform(this ITransform2D transform, Shape2D from, ref Shape2D to) => Shape2D.Transform(from, transform, ref to);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Shape2D.Transform(Shape2D, ITransform2D)" />
|
||||||
|
public static Shape2D Transform(this Shape2D shape, ITransform2D transform) => Shape2D.Transform(shape, transform);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Shape2D.Transform(Shape2D, ITransform2D, ref Shape2D)" />
|
||||||
|
public static void Transform(this Shape2D from, ITransform2D transform, ref Shape2D to) => Shape2D.Transform(from, transform, ref to);
|
||||||
|
|
||||||
/// <inheritdoc cref="Shape2D.ApproximatelyEquals(Shape2D, Shape2D, float)" />
|
/// <inheritdoc cref="Shape2D.ApproximatelyEquals(Shape2D, Shape2D, float)" />
|
||||||
public static bool ApproximatelyEquals(this Shape2D left, Shape2D right, float epsilon = float.Epsilon) => Shape2D.ApproximatelyEquals(left, right, epsilon);
|
public static bool ApproximatelyEquals(this Shape2D left, Shape2D right, float epsilon = float.Epsilon) => Shape2D.ApproximatelyEquals(left, right, epsilon);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Syntriax.Engine.Core.Abstract;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Syntriax.Engine.Core;
|
||||||
|
|
||||||
@ -278,6 +279,17 @@ public readonly struct Vector2D(float x, float y)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Transforms the <see cref="Vector2D"/> using the specified <see cref="ITransform2D"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vector">The <see cref="Vector2D"/> to transform.</param>
|
||||||
|
/// <param name="transform">The <see cref="ITransform2D"/> to apply.</param>
|
||||||
|
/// <returns>The transformed <see cref="Vector2D"/>.</returns>
|
||||||
|
public static Vector2D Transform(Vector2D vector, ITransform2D transform)
|
||||||
|
=> vector.Scale(transform.Scale)
|
||||||
|
.Rotate(transform.Rotation * Math.DegreeToRadian)
|
||||||
|
.Add(transform.Position);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if two <see cref="Vector2D"/>s are approximately equal within a specified epsilon range.
|
/// Checks if two <see cref="Vector2D"/>s are approximately equal within a specified epsilon range.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -379,6 +391,12 @@ public static class Vector2DExtensions
|
|||||||
/// <inheritdoc cref="Vector2D.Dot(Vector2D, Vector2D)" />
|
/// <inheritdoc cref="Vector2D.Dot(Vector2D, Vector2D)" />
|
||||||
public static float Dot(this Vector2D left, Vector2D right) => Vector2D.Dot(left, right);
|
public static float Dot(this Vector2D left, Vector2D right) => Vector2D.Dot(left, right);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Vector2D.Transform(Vector2D, ITransform2D)" />
|
||||||
|
public static Vector2D Transform(this Vector2D vector, ITransform2D transform) => Vector2D.Transform(vector, transform);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Vector2D.Transform(Vector2D, ITransform2D)" />
|
||||||
|
public static Vector2D Transform(this ITransform2D transform, Vector2D vector) => Vector2D.Transform(vector, transform);
|
||||||
|
|
||||||
/// <inheritdoc cref="Vector2D.ApproximatelyEquals(Vector2D, Vector2D, float) " />
|
/// <inheritdoc cref="Vector2D.ApproximatelyEquals(Vector2D, Vector2D, float) " />
|
||||||
public static bool ApproximatelyEquals(this Vector2D left, Vector2D right, float epsilon = float.Epsilon) => Vector2D.ApproximatelyEquals(left, right, epsilon);
|
public static bool ApproximatelyEquals(this Vector2D left, Vector2D right, float epsilon = float.Epsilon) => Vector2D.ApproximatelyEquals(left, right, epsilon);
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ public class StateEnable : IStateEnable
|
|||||||
|
|
||||||
bool previousState = _enabled;
|
bool previousState = _enabled;
|
||||||
_enabled = value;
|
_enabled = value;
|
||||||
OnEnabledChanged?.Invoke(this, previousState);
|
OnEnabledChanged?.InvokeSafe(this, previousState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ public class StateEnable : IStateEnable
|
|||||||
|
|
||||||
_entity = entity;
|
_entity = entity;
|
||||||
OnAssign(entity);
|
OnAssign(entity);
|
||||||
OnEntityAssigned?.Invoke(this);
|
OnEntityAssigned?.InvokeSafe(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ public class StateEnable : IStateEnable
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
_entity = null!;
|
_entity = null!;
|
||||||
OnUnassigned?.Invoke(this);
|
OnUnassigned?.InvokeSafe(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,5 @@ namespace Syntriax.Engine.Core;
|
|||||||
internal static class Constants
|
internal static class Constants
|
||||||
{
|
{
|
||||||
internal static int BEHAVIOURS_SIZE_INITIAL = 16;
|
internal static int BEHAVIOURS_SIZE_INITIAL = 16;
|
||||||
internal static int GAME_OBJECTS_SIZE_INITIAL = 256;
|
internal static int UNIVERSE_OBJECTS_SIZE_INITIAL = 256;
|
||||||
internal static int DRAWABLE_OBJECTS_SIZE_INITIAL = 256;
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ using Syntriax.Engine.Core.Abstract;
|
|||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Syntriax.Engine.Core;
|
||||||
|
|
||||||
[System.Diagnostics.DebuggerDisplay("Name: {HierarchyObject.Name, nq} Position: {Position.ToString(), nq}, Scale: {Scale.ToString(), nq}, Rotation: {Rotation}")]
|
[System.Diagnostics.DebuggerDisplay("Name: {UniverseObject.Name, nq} Position: {Position.ToString(), nq}, Scale: {Scale.ToString(), nq}, Rotation: {Rotation}")]
|
||||||
public class Transform2D : Behaviour, ITransform2D
|
public class Transform2D : Behaviour, ITransform2D
|
||||||
{
|
{
|
||||||
public event ITransform2D.PositionChangedEventHandler? OnPositionChanged = null;
|
public event ITransform2D.PositionChangedEventHandler? OnPositionChanged = null;
|
||||||
@ -31,7 +31,7 @@ public class Transform2D : Behaviour, ITransform2D
|
|||||||
_position = value;
|
_position = value;
|
||||||
|
|
||||||
UpdateLocalPosition();
|
UpdateLocalPosition();
|
||||||
OnPositionChanged?.Invoke(this, _position);
|
OnPositionChanged?.InvokeSafe(this, _position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ public class Transform2D : Behaviour, ITransform2D
|
|||||||
_scale = value;
|
_scale = value;
|
||||||
|
|
||||||
UpdateLocalScale();
|
UpdateLocalScale();
|
||||||
OnScaleChanged?.Invoke(this, previousScale);
|
OnScaleChanged?.InvokeSafe(this, previousScale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ public class Transform2D : Behaviour, ITransform2D
|
|||||||
_rotation = value;
|
_rotation = value;
|
||||||
|
|
||||||
UpdateLocalRotation();
|
UpdateLocalRotation();
|
||||||
OnRotationChanged?.Invoke(this, previousRotation);
|
OnRotationChanged?.InvokeSafe(this, previousRotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ public class Transform2D : Behaviour, ITransform2D
|
|||||||
_localPosition = value;
|
_localPosition = value;
|
||||||
|
|
||||||
UpdatePosition();
|
UpdatePosition();
|
||||||
OnPositionChanged?.Invoke(this, previousPosition);
|
OnPositionChanged?.InvokeSafe(this, previousPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,10 +92,13 @@ public class Transform2D : Behaviour, ITransform2D
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
Vector2D previousScale = _scale;
|
Vector2D previousScale = _scale;
|
||||||
|
Vector2D previousPosition = _position;
|
||||||
_localScale = value;
|
_localScale = value;
|
||||||
|
|
||||||
UpdateScale();
|
UpdateScale();
|
||||||
OnScaleChanged?.Invoke(this, previousScale);
|
UpdatePosition();
|
||||||
|
OnScaleChanged?.InvokeSafe(this, previousScale);
|
||||||
|
OnPositionChanged?.InvokeSafe(this, previousPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +114,7 @@ public class Transform2D : Behaviour, ITransform2D
|
|||||||
_localRotation = value;
|
_localRotation = value;
|
||||||
|
|
||||||
UpdateRotation();
|
UpdateRotation();
|
||||||
OnRotationChanged?.Invoke(this, previousRotation);
|
OnRotationChanged?.InvokeSafe(this, previousRotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,13 +123,9 @@ public class Transform2D : Behaviour, ITransform2D
|
|||||||
if (parentTransform is null)
|
if (parentTransform is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float previousRotation = Rotation;
|
|
||||||
|
|
||||||
UpdatePosition();
|
UpdatePosition();
|
||||||
UpdateRotation();
|
|
||||||
|
|
||||||
OnPositionChanged?.Invoke(this, previousPosition);
|
OnPositionChanged?.InvokeSafe(this, previousPosition);
|
||||||
OnRotationChanged?.Invoke(this, previousRotation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecalculateScale(ITransform2D _, Vector2D previousScale)
|
private void RecalculateScale(ITransform2D _, Vector2D previousScale)
|
||||||
@ -134,9 +133,13 @@ public class Transform2D : Behaviour, ITransform2D
|
|||||||
if (parentTransform is null)
|
if (parentTransform is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UpdateScale();
|
Vector2D previousPosition = _position;
|
||||||
|
|
||||||
OnScaleChanged?.Invoke(this, previousScale);
|
UpdateScale();
|
||||||
|
UpdatePosition();
|
||||||
|
|
||||||
|
OnScaleChanged?.InvokeSafe(this, previousScale);
|
||||||
|
OnPositionChanged?.InvokeSafe(this, previousPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecalculateRotation(ITransform2D _, float previousRotation)
|
private void RecalculateRotation(ITransform2D _, float previousRotation)
|
||||||
@ -146,11 +149,11 @@ public class Transform2D : Behaviour, ITransform2D
|
|||||||
|
|
||||||
Vector2D previousPosition = Position;
|
Vector2D previousPosition = Position;
|
||||||
|
|
||||||
UpdatePosition();
|
|
||||||
UpdateRotation();
|
UpdateRotation();
|
||||||
|
UpdatePosition();
|
||||||
|
|
||||||
OnPositionChanged?.Invoke(this, previousPosition);
|
OnRotationChanged?.InvokeSafe(this, previousRotation);
|
||||||
OnRotationChanged?.Invoke(this, previousRotation);
|
OnPositionChanged?.InvokeSafe(this, previousPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateLocalPosition()
|
private void UpdateLocalPosition()
|
||||||
@ -203,53 +206,62 @@ public class Transform2D : Behaviour, ITransform2D
|
|||||||
|
|
||||||
protected override void InitializeInternal()
|
protected override void InitializeInternal()
|
||||||
{
|
{
|
||||||
UpdateParent(BehaviourController.HierarchyObject.Parent);
|
UpdateReferences(UniverseObject.Parent);
|
||||||
BehaviourController.HierarchyObject.OnParentChanged += OnParentChanged;
|
UniverseObject.OnParentChanged += OnParentChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void FinalizeInternal()
|
protected override void FinalizeInternal()
|
||||||
{
|
{
|
||||||
BehaviourController.HierarchyObject.OnParentChanged -= OnParentChanged;
|
UniverseObject.OnParentChanged -= OnParentChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateParent(IHierarchyObject? parent)
|
private void UpdateReferences(IUniverseObject? parent)
|
||||||
{
|
{
|
||||||
ITransform2D? previousParent = parentTransform;
|
ITransform2D? previousParent = parentTransform;
|
||||||
if (previousParent is not null)
|
if (previousParent is not null)
|
||||||
{
|
{
|
||||||
previousParent.BehaviourController.HierarchyObject.RemoveChild(HierarchyObject);
|
|
||||||
previousParent.OnPositionChanged -= RecalculatePosition;
|
previousParent.OnPositionChanged -= RecalculatePosition;
|
||||||
previousParent.OnScaleChanged -= RecalculateScale;
|
previousParent.OnScaleChanged -= RecalculateScale;
|
||||||
previousParent.OnRotationChanged -= RecalculateRotation;
|
previousParent.OnRotationChanged -= RecalculateRotation;
|
||||||
previousParent.BehaviourController.HierarchyObject.OnParentChanged -= OnParentChanged;
|
previousParent.BehaviourController.UniverseObject.OnParentChanged -= OnParentChanged;
|
||||||
|
previousParent.BehaviourController.OnBehaviourAdded -= LookForTransform2D;
|
||||||
}
|
}
|
||||||
|
|
||||||
parentTransform = parent?.BehaviourController.GetBehaviour<ITransform2D>();
|
parentTransform = parent?.BehaviourController.GetBehaviour<ITransform2D>();
|
||||||
|
|
||||||
if (parentTransform is not null)
|
if (parentTransform is not null)
|
||||||
{
|
{
|
||||||
parentTransform.BehaviourController.HierarchyObject.AddChild(HierarchyObject);
|
|
||||||
parentTransform.OnPositionChanged += RecalculatePosition;
|
parentTransform.OnPositionChanged += RecalculatePosition;
|
||||||
parentTransform.OnScaleChanged += RecalculateScale;
|
parentTransform.OnScaleChanged += RecalculateScale;
|
||||||
parentTransform.OnRotationChanged += RecalculateRotation;
|
parentTransform.OnRotationChanged += RecalculateRotation;
|
||||||
parentTransform.BehaviourController.HierarchyObject.OnParentChanged += OnParentChanged;
|
parentTransform.BehaviourController.UniverseObject.OnParentChanged += OnParentChanged;
|
||||||
|
|
||||||
UpdatePosition();
|
UpdatePosition();
|
||||||
UpdateScale();
|
UpdateScale();
|
||||||
UpdateRotation();
|
UpdateRotation();
|
||||||
}
|
}
|
||||||
|
else if (UniverseObject.Parent is not null)
|
||||||
|
UniverseObject.Parent.BehaviourController.OnBehaviourAdded += LookForTransform2D;
|
||||||
|
|
||||||
UpdateLocalPosition();
|
UpdateLocalPosition();
|
||||||
UpdateLocalScale();
|
UpdateLocalScale();
|
||||||
UpdateLocalRotation();
|
UpdateLocalRotation();
|
||||||
|
|
||||||
OnPositionChanged?.Invoke(this, Position);
|
OnPositionChanged?.InvokeSafe(this, Position);
|
||||||
OnScaleChanged?.Invoke(this, Scale);
|
OnScaleChanged?.InvokeSafe(this, Scale);
|
||||||
OnRotationChanged?.Invoke(this, Rotation);
|
OnRotationChanged?.InvokeSafe(this, Rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnParentChanged(IHierarchyObject sender, IHierarchyObject? previousParent, IHierarchyObject? newParent)
|
private void LookForTransform2D(IBehaviourController sender, IBehaviour behaviourAdded)
|
||||||
{
|
{
|
||||||
UpdateParent(newParent);
|
if (behaviourAdded is not ITransform2D transform2D)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UpdateReferences(UniverseObject.Parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnParentChanged(IUniverseObject sender, IUniverseObject? previousParent, IUniverseObject? newParent)
|
||||||
|
{
|
||||||
|
UpdateReferences(newParent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
141
Engine.Core/Universe.cs
Normal file
141
Engine.Core/Universe.cs
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using Syntriax.Engine.Core.Abstract;
|
||||||
|
|
||||||
|
namespace Syntriax.Engine.Core;
|
||||||
|
|
||||||
|
[System.Diagnostics.DebuggerDisplay("UniverseObject Count: {_universeObjects.Count}")]
|
||||||
|
public class Universe : BaseEntity, IUniverse
|
||||||
|
{
|
||||||
|
public event IUniverse.UpdateEventHandler? OnPreUpdate = null;
|
||||||
|
public event IUniverse.UpdateEventHandler? OnUpdate = null;
|
||||||
|
public event IUniverse.PreDrawEventHandler? OnPreDraw = null;
|
||||||
|
|
||||||
|
public event IUniverse.UniverseObjectRegisteredEventHandler? OnUniverseObjectRegistered = null;
|
||||||
|
public event IUniverse.UniverseObjectUnRegisteredEventHandler? OnUniverseObjectUnRegistered = null;
|
||||||
|
|
||||||
|
private readonly List<IUniverseObject> _universeObjects = new(Constants.UNIVERSE_OBJECTS_SIZE_INITIAL);
|
||||||
|
private float _timeScale = 1f;
|
||||||
|
|
||||||
|
public IReadOnlyList<IUniverseObject> UniverseObjects => _universeObjects;
|
||||||
|
|
||||||
|
public UniverseTime Time { get; private set; } = new();
|
||||||
|
public UniverseTime UnscaledTime { get; private set; } = new();
|
||||||
|
public float TimeScale
|
||||||
|
{
|
||||||
|
get => _timeScale;
|
||||||
|
set => _timeScale = value.Max(0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Register(IUniverseObject universeObject)
|
||||||
|
{
|
||||||
|
if (_universeObjects.Contains(universeObject))
|
||||||
|
throw new Exception($"{nameof(IUniverseObject)} named {universeObject.Name} is already registered to the {nameof(Universe)}.");
|
||||||
|
|
||||||
|
universeObject.OnFinalized += OnUniverseObjectFinalize;
|
||||||
|
universeObject.OnExitedUniverse += OnUniverseObjectExitedUniverse;
|
||||||
|
|
||||||
|
if (!universeObject.Initialize())
|
||||||
|
throw new Exception($"{universeObject.Name} can't be initialized");
|
||||||
|
|
||||||
|
for (int i = 0; i < universeObject.Children.Count; i++)
|
||||||
|
Register(universeObject.Children[i]);
|
||||||
|
|
||||||
|
_universeObjects.Add(universeObject);
|
||||||
|
|
||||||
|
if (!universeObject.EnterUniverse(this))
|
||||||
|
throw new Exception($"{universeObject.Name} can't enter the universe");
|
||||||
|
|
||||||
|
OnUniverseObjectRegistered?.InvokeSafe(this, universeObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T InstantiateUniverseObject<T>(params object?[]? args) where T : class, IUniverseObject
|
||||||
|
{
|
||||||
|
T universeObject = Factory.UniverseObjectFactory.Instantiate<T>(args);
|
||||||
|
Register(universeObject);
|
||||||
|
return universeObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove(IUniverseObject universeObject)
|
||||||
|
{
|
||||||
|
universeObject.SetParent(null);
|
||||||
|
RemoveIncursive(universeObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveIncursive(IUniverseObject universeObject)
|
||||||
|
{
|
||||||
|
if (!_universeObjects.Contains(universeObject))
|
||||||
|
throw new Exception($"{nameof(IUniverseObject)} named {universeObject.Name} is not registered to the {nameof(Universe)}.");
|
||||||
|
|
||||||
|
universeObject.OnFinalized -= OnUniverseObjectFinalize;
|
||||||
|
universeObject.OnExitedUniverse -= OnUniverseObjectExitedUniverse;
|
||||||
|
|
||||||
|
for (int i = universeObject.Children.Count - 1; i >= 0; i--)
|
||||||
|
Remove(universeObject.Children[i]);
|
||||||
|
|
||||||
|
_universeObjects.Remove(universeObject);
|
||||||
|
|
||||||
|
if (!universeObject.ExitUniverse())
|
||||||
|
throw new Exception($"{universeObject.Name} can't exit the universe");
|
||||||
|
|
||||||
|
if (!universeObject.Finalize())
|
||||||
|
throw new Exception($"{universeObject.Name} can't be finalized");
|
||||||
|
|
||||||
|
OnUniverseObjectUnRegistered?.InvokeSafe(this, universeObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void InitializeInternal()
|
||||||
|
{
|
||||||
|
foreach (IUniverseObject universeObject in UniverseObjects)
|
||||||
|
universeObject.Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void FinalizeInternal()
|
||||||
|
{
|
||||||
|
base.FinalizeInternal();
|
||||||
|
for (int i = UniverseObjects.Count; i >= 0; i--)
|
||||||
|
UniverseObjects[i].Finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(UniverseTime engineTime)
|
||||||
|
{
|
||||||
|
Debug.AssertHelpers.AssertInitialized(this);
|
||||||
|
|
||||||
|
UnscaledTime = engineTime;
|
||||||
|
Time = new(TimeSpan.FromTicks((long)(Time.TimeSinceStart.Ticks + engineTime.DeltaSpan.Ticks * TimeScale)), TimeSpan.FromTicks((long)(engineTime.DeltaSpan.Ticks * TimeScale)));
|
||||||
|
|
||||||
|
OnPreUpdate?.InvokeSafe(this, Time);
|
||||||
|
|
||||||
|
for (int i = 0; i < UniverseObjects.Count; i++)
|
||||||
|
UniverseObjects[i].BehaviourController.Update();
|
||||||
|
|
||||||
|
OnUpdate?.InvokeSafe(this, Time);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PreDraw()
|
||||||
|
{
|
||||||
|
Debug.AssertHelpers.AssertInitialized(this);
|
||||||
|
|
||||||
|
for (int i = 0; i < UniverseObjects.Count; i++)
|
||||||
|
UniverseObjects[i].BehaviourController.UpdatePreDraw();
|
||||||
|
|
||||||
|
OnPreDraw?.InvokeSafe(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUniverseObjectFinalize(IInitializable initializable)
|
||||||
|
{
|
||||||
|
if (initializable is IUniverseObject universeObject)
|
||||||
|
Remove(universeObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUniverseObjectExitedUniverse(IUniverseObject sender, IUniverse universe)
|
||||||
|
{
|
||||||
|
if (sender is IUniverseObject universeObject)
|
||||||
|
Remove(universeObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<IUniverseObject> GetEnumerator() => _universeObjects.GetEnumerator();
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() => _universeObjects.GetEnumerator();
|
||||||
|
}
|
@ -6,28 +6,28 @@ using Syntriax.Engine.Core.Abstract;
|
|||||||
namespace Syntriax.Engine.Core;
|
namespace Syntriax.Engine.Core;
|
||||||
|
|
||||||
[System.Diagnostics.DebuggerDisplay("Name: {Name}, Initialized: {Initialized}")]
|
[System.Diagnostics.DebuggerDisplay("Name: {Name}, Initialized: {Initialized}")]
|
||||||
public class HierarchyObject : BaseEntity, IHierarchyObject
|
public class UniverseObject : BaseEntity, IUniverseObject
|
||||||
{
|
{
|
||||||
public event IHierarchyObject.EnteredHierarchyEventHandler? OnEnteredHierarchy = null;
|
public event IUniverseObject.EnteredUniverseEventHandler? OnEnteredUniverse = null;
|
||||||
public event IHierarchyObject.ExitedHierarchyEventHandler? OnExitedHierarchy = null;
|
public event IUniverseObject.ExitedUniverseEventHandler? OnExitedUniverse = null;
|
||||||
public event IHierarchyObject.ParentChangedEventHandler? OnParentChanged = null;
|
public event IUniverseObject.ParentChangedEventHandler? OnParentChanged = null;
|
||||||
public event IHierarchyObject.ChildrenAddedEventHandler? OnChildrenAdded = null;
|
public event IUniverseObject.ChildrenAddedEventHandler? OnChildrenAdded = null;
|
||||||
public event IHierarchyObject.ChildrenRemovedEventHandler? OnChildrenRemoved = null;
|
public event IUniverseObject.ChildrenRemovedEventHandler? OnChildrenRemoved = null;
|
||||||
public event IHasBehaviourController.BehaviourControllerAssignedEventHandler? OnBehaviourControllerAssigned = null;
|
public event IHasBehaviourController.BehaviourControllerAssignedEventHandler? OnBehaviourControllerAssigned = null;
|
||||||
public event INameable.NameChangedEventHandler? OnNameChanged = null;
|
public event INameable.NameChangedEventHandler? OnNameChanged = null;
|
||||||
public event IActive.ActiveChangedEventHandler? OnActiveChanged = null;
|
public event IActive.ActiveChangedEventHandler? OnActiveChanged = null;
|
||||||
|
|
||||||
private string _name = nameof(HierarchyObject);
|
private string _name = nameof(UniverseObject);
|
||||||
private IGameManager _gameManager = null!;
|
private IUniverse _universe = null!;
|
||||||
private IBehaviourController _behaviourController = null!;
|
private IBehaviourController _behaviourController = null!;
|
||||||
private bool _isActive = false;
|
private bool _isActive = false;
|
||||||
private readonly List<IHierarchyObject> _children = [];
|
private readonly List<IUniverseObject> _children = [];
|
||||||
|
|
||||||
public IHierarchyObject? Parent { get; private set; } = null;
|
public IUniverseObject? Parent { get; private set; } = null;
|
||||||
public IReadOnlyList<IHierarchyObject> Children => _children;
|
public IReadOnlyList<IUniverseObject> Children => _children;
|
||||||
public IBehaviourController BehaviourController => _behaviourController;
|
public IBehaviourController BehaviourController => _behaviourController;
|
||||||
public IGameManager GameManager => _gameManager;
|
public IUniverse Universe => _universe;
|
||||||
public bool IsInHierarchy => _gameManager is not null;
|
public bool IsInUniverse => _universe is not null;
|
||||||
public bool IsActive => _isActive;
|
public bool IsActive => _isActive;
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
@ -39,41 +39,44 @@ public class HierarchyObject : BaseEntity, IHierarchyObject
|
|||||||
|
|
||||||
string previousName = _name;
|
string previousName = _name;
|
||||||
_name = value;
|
_name = value;
|
||||||
OnNameChanged?.Invoke(this, previousName);
|
OnNameChanged?.InvokeSafe(this, previousName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnEnteringHierarchy(IGameManager gameManager) { }
|
protected virtual void OnEnteringUniverse(IUniverse universe) { }
|
||||||
bool IHierarchyObject.EnterHierarchy(IGameManager gameManager)
|
bool IUniverseObject.EnterUniverse(IUniverse universe)
|
||||||
{
|
{
|
||||||
if (IsInHierarchy)
|
if (IsInUniverse)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
_gameManager = gameManager;
|
_universe = universe;
|
||||||
UpdateActive();
|
UpdateActive();
|
||||||
OnEnteringHierarchy(gameManager);
|
OnEnteringUniverse(universe);
|
||||||
OnEnteredHierarchy?.Invoke(this, gameManager);
|
OnEnteredUniverse?.InvokeSafe(this, universe);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnExitingHierarchy(IGameManager gameManager) { }
|
protected virtual void OnExitingUniverse(IUniverse universe) { }
|
||||||
bool IHierarchyObject.ExitHierarchy()
|
bool IUniverseObject.ExitUniverse()
|
||||||
{
|
{
|
||||||
if (!IsInHierarchy || _gameManager is not IGameManager gameManager)
|
if (!IsInUniverse || _universe is not IUniverse universe)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
_gameManager = null!;
|
OnExitingUniverse(universe);
|
||||||
OnExitingHierarchy(gameManager);
|
_universe = null!;
|
||||||
OnExitedHierarchy?.Invoke(this, gameManager);
|
OnExitedUniverse?.InvokeSafe(this, universe);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetParent(IHierarchyObject? parent)
|
public void SetParent(IUniverseObject? parent)
|
||||||
{
|
{
|
||||||
if (parent == this || Parent == parent)
|
if (parent == this)
|
||||||
|
throw new Exceptions.AssignFailedException($"{Name} can not parent itself");
|
||||||
|
|
||||||
|
if (Parent == parent)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
IHierarchyObject? previousParent = Parent;
|
IUniverseObject? previousParent = Parent;
|
||||||
if (previousParent is not null)
|
if (previousParent is not null)
|
||||||
{
|
{
|
||||||
previousParent.RemoveChild(this);
|
previousParent.RemoveChild(this);
|
||||||
@ -84,31 +87,34 @@ public class HierarchyObject : BaseEntity, IHierarchyObject
|
|||||||
|
|
||||||
if (parent is not null)
|
if (parent is not null)
|
||||||
{
|
{
|
||||||
|
if (parent.IsInUniverse && !IsInUniverse)
|
||||||
|
parent.Universe.Register(this);
|
||||||
|
|
||||||
parent.AddChild(this);
|
parent.AddChild(this);
|
||||||
parent.OnActiveChanged += OnParentActiveChanged;
|
parent.OnActiveChanged += OnParentActiveChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateActive();
|
UpdateActive();
|
||||||
OnParentChanged?.Invoke(this, previousParent, parent);
|
OnParentChanged?.InvokeSafe(this, previousParent, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddChild(IHierarchyObject parent)
|
public void AddChild(IUniverseObject parent)
|
||||||
{
|
{
|
||||||
if (_children.Contains(parent))
|
if (_children.Contains(parent))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_children.Add(parent);
|
_children.Add(parent);
|
||||||
parent.SetParent(this);
|
parent.SetParent(this);
|
||||||
OnChildrenAdded?.Invoke(this, parent);
|
OnChildrenAdded?.InvokeSafe(this, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveChild(IHierarchyObject parent)
|
public void RemoveChild(IUniverseObject child)
|
||||||
{
|
{
|
||||||
if (!_children.Remove(parent))
|
if (!_children.Remove(child))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
parent.SetParent(null);
|
child.SetParent(null);
|
||||||
OnChildrenRemoved?.Invoke(this, parent);
|
OnChildrenRemoved?.InvokeSafe(this, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnAssign(IBehaviourController behaviourController) { }
|
protected virtual void OnAssign(IBehaviourController behaviourController) { }
|
||||||
@ -119,7 +125,7 @@ public class HierarchyObject : BaseEntity, IHierarchyObject
|
|||||||
|
|
||||||
_behaviourController = behaviourController;
|
_behaviourController = behaviourController;
|
||||||
OnAssign(behaviourController);
|
OnAssign(behaviourController);
|
||||||
OnBehaviourControllerAssigned?.Invoke(this);
|
OnBehaviourControllerAssigned?.InvokeSafe(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +145,7 @@ public class HierarchyObject : BaseEntity, IHierarchyObject
|
|||||||
_isActive = StateEnable.Enabled && (Parent?.IsActive ?? true);
|
_isActive = StateEnable.Enabled && (Parent?.IsActive ?? true);
|
||||||
|
|
||||||
if (previousActive != IsActive)
|
if (previousActive != IsActive)
|
||||||
OnActiveChanged?.Invoke(this, previousActive);
|
OnActiveChanged?.InvokeSafe(this, previousActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UnassignInternal()
|
protected override void UnassignInternal()
|
||||||
@ -154,6 +160,11 @@ public class HierarchyObject : BaseEntity, IHierarchyObject
|
|||||||
_behaviourController ??= Factory.BehaviourControllerFactory.Instantiate(this);
|
_behaviourController ??= Factory.BehaviourControllerFactory.Instantiate(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerator<IHierarchyObject> GetEnumerator() => _children.GetEnumerator();
|
public UniverseObject()
|
||||||
|
{
|
||||||
|
_name = GetType().Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<IUniverseObject> GetEnumerator() => _children.GetEnumerator();
|
||||||
IEnumerator IEnumerable.GetEnumerator() => _children.GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => _children.GetEnumerator();
|
||||||
}
|
}
|
@ -2,7 +2,7 @@ using System;
|
|||||||
|
|
||||||
namespace Syntriax.Engine.Core;
|
namespace Syntriax.Engine.Core;
|
||||||
|
|
||||||
public readonly struct EngineTime(TimeSpan TimeSinceStart, TimeSpan TimeDelta)
|
public readonly struct UniverseTime(TimeSpan TimeSinceStart, TimeSpan TimeDelta)
|
||||||
{
|
{
|
||||||
public readonly TimeSpan TimeSinceStart = TimeSinceStart;
|
public readonly TimeSpan TimeSinceStart = TimeSinceStart;
|
||||||
public readonly TimeSpan DeltaSpan = TimeDelta;
|
public readonly TimeSpan DeltaSpan = TimeDelta;
|
@ -10,7 +10,7 @@ public abstract class Collider2DBehaviourBase : Behaviour2D, ICollider2D
|
|||||||
public event ICollider2D.CollisionResolvedEventHandler? OnCollisionResolved = null;
|
public event ICollider2D.CollisionResolvedEventHandler? OnCollisionResolved = null;
|
||||||
public event ICollider2D.TriggeredEventHandler? OnTriggered = null;
|
public event ICollider2D.TriggeredEventHandler? OnTriggered = null;
|
||||||
|
|
||||||
protected bool NeedsRecalculation { get; private set; } = true;
|
protected bool NeedsRecalculation { get; set; } = true;
|
||||||
protected IRigidBody2D? _rigidBody2D = null;
|
protected IRigidBody2D? _rigidBody2D = null;
|
||||||
|
|
||||||
public IRigidBody2D? RigidBody2D => _rigidBody2D;
|
public IRigidBody2D? RigidBody2D => _rigidBody2D;
|
||||||
@ -37,10 +37,10 @@ public abstract class Collider2DBehaviourBase : Behaviour2D, ICollider2D
|
|||||||
Transform.OnPositionChanged += SetNeedsRecalculationFromPosition;
|
Transform.OnPositionChanged += SetNeedsRecalculationFromPosition;
|
||||||
Transform.OnRotationChanged += SetNeedsRecalculationFromRotation;
|
Transform.OnRotationChanged += SetNeedsRecalculationFromRotation;
|
||||||
Transform.OnScaleChanged += SetNeedsRecalculationFromScale;
|
Transform.OnScaleChanged += SetNeedsRecalculationFromScale;
|
||||||
HierarchyObject.OnParentChanged += UpdateRigidBody2D;
|
UniverseObject.OnParentChanged += UpdateRigidBody2D;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateRigidBody2D(IHierarchyObject sender, IHierarchyObject? previousParent, IHierarchyObject? newParent)
|
private void UpdateRigidBody2D(IUniverseObject sender, IUniverseObject? previousParent, IUniverseObject? newParent)
|
||||||
{
|
{
|
||||||
BehaviourController.TryGetBehaviourInParent(out _rigidBody2D);
|
BehaviourController.TryGetBehaviourInParent(out _rigidBody2D);
|
||||||
}
|
}
|
||||||
@ -71,7 +71,7 @@ public abstract class Collider2DBehaviourBase : Behaviour2D, ICollider2D
|
|||||||
Transform.OnRotationChanged -= SetNeedsRecalculationFromRotation;
|
Transform.OnRotationChanged -= SetNeedsRecalculationFromRotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Detect(CollisionDetectionInformation collisionDetectionInformation) => OnCollisionDetected?.Invoke(this, collisionDetectionInformation);
|
public void Detect(CollisionDetectionInformation collisionDetectionInformation) => OnCollisionDetected?.InvokeSafe(this, collisionDetectionInformation);
|
||||||
public void Resolve(CollisionDetectionInformation collisionDetectionInformation) => OnCollisionResolved?.Invoke(this, collisionDetectionInformation);
|
public void Resolve(CollisionDetectionInformation collisionDetectionInformation) => OnCollisionResolved?.InvokeSafe(this, collisionDetectionInformation);
|
||||||
public void Trigger(ICollider2D initiator) => OnTriggered?.Invoke(this, initiator);
|
public void Trigger(ICollider2D initiator) => OnTriggered?.InvokeSafe(this, initiator);
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,20 @@ namespace Syntriax.Engine.Physics2D;
|
|||||||
|
|
||||||
public class Collider2DCircleBehaviour : Collider2DBehaviourBase, ICircleCollider2D
|
public class Collider2DCircleBehaviour : Collider2DBehaviourBase, ICircleCollider2D
|
||||||
{
|
{
|
||||||
public Circle CircleWorld { get; protected set; } = Circle.UnitCircle;
|
private Circle _circleLocal = Circle.UnitCircle;
|
||||||
public Circle CircleLocal { get; set; } = Circle.UnitCircle;
|
|
||||||
|
|
||||||
public override void CalculateCollider() => CircleWorld = Transform.TransformCircle(CircleLocal);
|
public Circle CircleWorld { get; protected set; } = Circle.UnitCircle;
|
||||||
|
public Circle CircleLocal
|
||||||
|
{
|
||||||
|
get => _circleLocal;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_circleLocal = value;
|
||||||
|
NeedsRecalculation = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void CalculateCollider() => CircleWorld = Transform.Transform(_circleLocal);
|
||||||
|
|
||||||
public Collider2DCircleBehaviour() { }
|
public Collider2DCircleBehaviour() { }
|
||||||
public Collider2DCircleBehaviour(Circle circle) => CircleLocal = circle;
|
public Collider2DCircleBehaviour(Circle circle) => CircleLocal = circle;
|
||||||
|
@ -6,12 +6,24 @@ namespace Syntriax.Engine.Physics2D;
|
|||||||
public class Collider2DShapeBehaviour : Collider2DBehaviourBase, IShapeCollider2D
|
public class Collider2DShapeBehaviour : Collider2DBehaviourBase, IShapeCollider2D
|
||||||
{
|
{
|
||||||
public Shape2D ShapeWorld { get => _shapeWorld; protected set => _shapeWorld = value; }
|
public Shape2D ShapeWorld { get => _shapeWorld; protected set => _shapeWorld = value; }
|
||||||
public Shape2D ShapeLocal { get; set; } = Shape2D.Box;
|
public Shape2D ShapeLocal
|
||||||
|
{
|
||||||
|
get => _shapeLocal;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_shapeLocal = value;
|
||||||
|
NeedsRecalculation = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Shape2D _shapeWorld = Shape2D.Box.CreateCopy();
|
private Shape2D _shapeWorld = Shape2D.Square.CreateCopy();
|
||||||
|
private Shape2D _shapeLocal = Shape2D.Square;
|
||||||
|
|
||||||
public override void CalculateCollider() => Transform.TransformShape(ShapeLocal, ref _shapeWorld);
|
public override void CalculateCollider() => Transform.Transform(ShapeLocal, ref _shapeWorld);
|
||||||
|
|
||||||
public Collider2DShapeBehaviour() { }
|
public Collider2DShapeBehaviour() { }
|
||||||
public Collider2DShapeBehaviour(Shape2D shape) => ShapeLocal = shape;
|
public Collider2DShapeBehaviour(Shape2D shape)
|
||||||
|
{
|
||||||
|
ShapeLocal = shape;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ using Syntriax.Engine.Physics2D.Abstract;
|
|||||||
|
|
||||||
namespace Syntriax.Engine.Physics2D;
|
namespace Syntriax.Engine.Physics2D;
|
||||||
|
|
||||||
public class PhysicsCoroutineManager : HierarchyObject
|
public class PhysicsCoroutineManager : UniverseObject
|
||||||
{
|
{
|
||||||
private readonly List<IEnumerator> enumerators = [];
|
private readonly List<IEnumerator> enumerators = [];
|
||||||
private IPhysicsEngine2D? physicsEngine = null;
|
private IPhysicsEngine2D? physicsEngine = null;
|
||||||
@ -23,13 +23,13 @@ public class PhysicsCoroutineManager : HierarchyObject
|
|||||||
enumerators.Remove(enumerator);
|
enumerators.Remove(enumerator);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnEnteringHierarchy(IGameManager gameManager)
|
protected override void OnEnteringUniverse(IUniverse universe)
|
||||||
{
|
{
|
||||||
physicsEngine = gameManager.FindHierarchyObject<IPhysicsEngine2D>();
|
physicsEngine = universe.GetUniverseObject<IPhysicsEngine2D>();
|
||||||
if (physicsEngine is IPhysicsEngine2D foundPhysicsEngine)
|
if (physicsEngine is IPhysicsEngine2D foundPhysicsEngine)
|
||||||
foundPhysicsEngine.OnPhysicsStep += OnPhysicsStep;
|
foundPhysicsEngine.OnPhysicsStep += OnPhysicsStep;
|
||||||
else
|
else
|
||||||
gameManager.OnUpdate += OnUpdate;
|
universe.OnUpdate += OnUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPhysicsStep(IPhysicsEngine2D sender, float stepDeltaTime)
|
private void OnPhysicsStep(IPhysicsEngine2D sender, float stepDeltaTime)
|
||||||
@ -44,23 +44,23 @@ public class PhysicsCoroutineManager : HierarchyObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnExitingHierarchy(IGameManager gameManager)
|
protected override void OnExitingUniverse(IUniverse universe)
|
||||||
{
|
{
|
||||||
if (physicsEngine is IPhysicsEngine2D existingPhysicsEngine)
|
if (physicsEngine is IPhysicsEngine2D existingPhysicsEngine)
|
||||||
existingPhysicsEngine.OnPhysicsStep -= OnPhysicsStep;
|
existingPhysicsEngine.OnPhysicsStep -= OnPhysicsStep;
|
||||||
gameManager.OnUpdate -= OnUpdate;
|
universe.OnUpdate -= OnUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnUpdate(IGameManager sender, EngineTime engineTime)
|
private void OnUpdate(IUniverse sender, UniverseTime engineTime)
|
||||||
{
|
{
|
||||||
if (GameManager is not IGameManager gameManager)
|
if (Universe is not IUniverse universe)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
physicsEngine = gameManager.FindHierarchyObject<IPhysicsEngine2D>();
|
physicsEngine = universe.GetUniverseObject<IPhysicsEngine2D>();
|
||||||
if (physicsEngine is IPhysicsEngine2D foundPhysicsEngine)
|
if (physicsEngine is IPhysicsEngine2D foundPhysicsEngine)
|
||||||
{
|
{
|
||||||
foundPhysicsEngine.OnPhysicsStep += OnPhysicsStep;
|
foundPhysicsEngine.OnPhysicsStep += OnPhysicsStep;
|
||||||
gameManager.OnUpdate -= OnUpdate;
|
universe.OnUpdate -= OnUpdate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,43 +1,27 @@
|
|||||||
using System.Collections.Generic;
|
using Syntriax.Engine.Core;
|
||||||
|
|
||||||
using Syntriax.Engine.Core.Abstract;
|
using Syntriax.Engine.Core.Abstract;
|
||||||
using Syntriax.Engine.Physics2D.Abstract;
|
using Syntriax.Engine.Physics2D.Abstract;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Physics2D;
|
namespace Syntriax.Engine.Physics2D;
|
||||||
|
|
||||||
public class PhysicsEngine2D : IPhysicsEngine2D
|
public class PhysicsEngine2D : UniverseObject, IPhysicsEngine2D
|
||||||
{
|
{
|
||||||
public event IPhysicsEngine2D.PhysicsIterationEventHandler? OnPhysicsIteration = null;
|
public event IPhysicsEngine2D.PhysicsIterationEventHandler? OnPhysicsIteration = null;
|
||||||
public event IPhysicsEngine2D.PhysicsStepEventHandler? OnPhysicsStep = null;
|
public event IPhysicsEngine2D.PhysicsStepEventHandler? OnPhysicsStep = null;
|
||||||
|
|
||||||
private readonly List<IRigidBody2D> rigidBodies = new(32);
|
private float physicsTicker = 0f;
|
||||||
private readonly List<ICollider2D> colliders = new(64);
|
private int _iterationPerStep = 1;
|
||||||
|
private float _iterationPeriod = 1f / 60f;
|
||||||
|
|
||||||
private int _iterationCount = 1;
|
protected readonly ICollisionDetector2D collisionDetector = null!;
|
||||||
|
protected readonly ICollisionResolver2D collisionResolver = null!;
|
||||||
|
|
||||||
private readonly ICollisionDetector2D collisionDetector = null!;
|
protected BehaviourCollector<IRigidBody2D> rigidBodyCollector = new();
|
||||||
private readonly ICollisionResolver2D collisionResolver = null!;
|
protected BehaviourCollector<ICollider2D> colliderCollector = new();
|
||||||
|
protected BehaviourCollector<IPhysicsUpdate> physicsUpdateCollector = new();
|
||||||
|
|
||||||
public int IterationPerStep { get => _iterationCount; set => _iterationCount = value < 1 ? 1 : value; }
|
public int IterationPerStep { get => _iterationPerStep; set => _iterationPerStep = value < 1 ? 1 : value; }
|
||||||
|
public float IterationPeriod { get => _iterationPeriod; set => _iterationPeriod = value.Max(0.0001f); }
|
||||||
public void AddRigidBody(IRigidBody2D rigidBody)
|
|
||||||
{
|
|
||||||
if (rigidBodies.Contains(rigidBody))
|
|
||||||
return;
|
|
||||||
|
|
||||||
rigidBodies.Add(rigidBody);
|
|
||||||
|
|
||||||
foreach (ICollider2D collider2D in rigidBody.BehaviourController.GetBehaviours<ICollider2D>())
|
|
||||||
colliders.Add(collider2D);
|
|
||||||
|
|
||||||
rigidBody.BehaviourController.OnBehaviourAdded += OnBehaviourAdded;
|
|
||||||
rigidBody.BehaviourController.OnBehaviourRemoved += OnBehaviourRemoved;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveRigidBody(IRigidBody2D rigidBody)
|
|
||||||
{
|
|
||||||
rigidBodies.Remove(rigidBody);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Step(float deltaTime)
|
public void Step(float deltaTime)
|
||||||
{
|
{
|
||||||
@ -46,23 +30,23 @@ public class PhysicsEngine2D : IPhysicsEngine2D
|
|||||||
for (int iterationIndex = 0; iterationIndex < IterationPerStep; iterationIndex++)
|
for (int iterationIndex = 0; iterationIndex < IterationPerStep; iterationIndex++)
|
||||||
{
|
{
|
||||||
// Can Parallel
|
// Can Parallel
|
||||||
for (int i = 0; i < rigidBodies.Count; i++)
|
foreach (IRigidBody2D rigidBody in rigidBodyCollector)
|
||||||
StepRigidBody(rigidBodies[i], intervalDeltaTime);
|
StepRigidBody(rigidBody, intervalDeltaTime);
|
||||||
|
|
||||||
// Can Parallel
|
// Can Parallel
|
||||||
foreach (ICollider2D collider in colliders)
|
foreach (ICollider2D collider in colliderCollector)
|
||||||
collider.Recalculate();
|
collider.Recalculate();
|
||||||
|
|
||||||
// Can Parallel
|
// Can Parallel
|
||||||
for (int x = 0; x < colliders.Count; x++)
|
for (int x = 0; x < colliderCollector.Behaviours.Count; x++)
|
||||||
{
|
{
|
||||||
ICollider2D? colliderX = colliders[x];
|
ICollider2D? colliderX = colliderCollector.Behaviours[x];
|
||||||
if (!colliderX.IsActive)
|
if (!colliderX.IsActive)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (int y = x + 1; y < colliders.Count; y++)
|
for (int y = x + 1; y < colliderCollector.Behaviours.Count; y++)
|
||||||
{
|
{
|
||||||
ICollider2D? colliderY = colliders[y];
|
ICollider2D? colliderY = colliderCollector.Behaviours[y];
|
||||||
|
|
||||||
if (!colliderY.IsActive)
|
if (!colliderY.IsActive)
|
||||||
return;
|
return;
|
||||||
@ -87,7 +71,7 @@ public class PhysicsEngine2D : IPhysicsEngine2D
|
|||||||
}
|
}
|
||||||
else if (colliderY.IsTrigger)
|
else if (colliderY.IsTrigger)
|
||||||
{
|
{
|
||||||
colliderY.Trigger(colliderY);
|
colliderY.Trigger(colliderX);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,9 +90,14 @@ public class PhysicsEngine2D : IPhysicsEngine2D
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OnPhysicsIteration?.Invoke(this, intervalDeltaTime);
|
|
||||||
|
OnPhysicsIteration?.InvokeSafe(this, intervalDeltaTime);
|
||||||
}
|
}
|
||||||
OnPhysicsStep?.Invoke(this, deltaTime);
|
|
||||||
|
foreach (IPhysicsUpdate physicsUpdate in physicsUpdateCollector)
|
||||||
|
physicsUpdate.PhysicsUpdate(deltaTime);
|
||||||
|
|
||||||
|
OnPhysicsStep?.InvokeSafe(this, deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void StepRigidBody(IRigidBody2D rigidBody, float intervalDeltaTime)
|
private static void StepRigidBody(IRigidBody2D rigidBody, float intervalDeltaTime)
|
||||||
@ -120,20 +109,33 @@ public class PhysicsEngine2D : IPhysicsEngine2D
|
|||||||
rigidBody.Transform.Rotation += rigidBody.AngularVelocity * intervalDeltaTime;
|
rigidBody.Transform.Rotation += rigidBody.AngularVelocity * intervalDeltaTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnBehaviourAdded(IBehaviourController controller, IBehaviour behaviour)
|
protected override void OnEnteringUniverse(IUniverse universe)
|
||||||
{
|
{
|
||||||
if (behaviour is not ICollider2D collider2D)
|
physicsUpdateCollector.Assign(universe);
|
||||||
return;
|
colliderCollector.Assign(universe);
|
||||||
|
rigidBodyCollector.Assign(universe);
|
||||||
|
|
||||||
colliders.Add(collider2D);
|
universe.OnPreUpdate += OnEnginePreUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnBehaviourRemoved(IBehaviourController controller, IBehaviour behaviour)
|
protected override void OnExitingUniverse(IUniverse universe)
|
||||||
{
|
{
|
||||||
if (behaviour is not ICollider2D collider2D)
|
physicsUpdateCollector.Unassign();
|
||||||
return;
|
colliderCollector.Unassign();
|
||||||
|
rigidBodyCollector.Unassign();
|
||||||
|
|
||||||
colliders.Remove(collider2D);
|
universe.OnPreUpdate -= OnEnginePreUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEnginePreUpdate(IUniverse sender, UniverseTime engineTime)
|
||||||
|
{
|
||||||
|
physicsTicker += engineTime.DeltaTime;
|
||||||
|
|
||||||
|
while (physicsTicker >= IterationPeriod)
|
||||||
|
{
|
||||||
|
physicsTicker -= IterationPeriod;
|
||||||
|
Step(IterationPeriod);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public PhysicsEngine2D()
|
public PhysicsEngine2D()
|
||||||
|
@ -1,24 +1,44 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using Syntriax.Engine.Core;
|
using Syntriax.Engine.Core;
|
||||||
using Syntriax.Engine.Core.Abstract;
|
using Syntriax.Engine.Core.Abstract;
|
||||||
using Syntriax.Engine.Physics2D.Abstract;
|
using Syntriax.Engine.Physics2D.Abstract;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Physics2D;
|
namespace Syntriax.Engine.Physics2D;
|
||||||
|
|
||||||
public class PhysicsEngine2DCollector : HierarchyObject, IPhysicsEngine2D
|
public class PhysicsEngine2DStandalone : IPhysicsEngine2D
|
||||||
{
|
{
|
||||||
public event IPhysicsEngine2D.PhysicsIterationEventHandler? OnPhysicsIteration = null;
|
public event IPhysicsEngine2D.PhysicsIterationEventHandler? OnPhysicsIteration = null;
|
||||||
public event IPhysicsEngine2D.PhysicsStepEventHandler? OnPhysicsStep = null;
|
public event IPhysicsEngine2D.PhysicsStepEventHandler? OnPhysicsStep = null;
|
||||||
|
|
||||||
private int _iterationPerStep = 1;
|
private readonly List<IRigidBody2D> rigidBodies = new(32);
|
||||||
|
private readonly List<ICollider2D> colliders = new(64);
|
||||||
|
|
||||||
protected readonly ICollisionDetector2D collisionDetector = null!;
|
private int _iterationCount = 1;
|
||||||
protected readonly ICollisionResolver2D collisionResolver = null!;
|
|
||||||
|
|
||||||
protected BehaviourCollector<IRigidBody2D> rigidBodyCollector = new();
|
private readonly ICollisionDetector2D collisionDetector = null!;
|
||||||
protected BehaviourCollector<ICollider2D> colliderCollector = new();
|
private readonly ICollisionResolver2D collisionResolver = null!;
|
||||||
protected BehaviourCollector<IPhysicsUpdate> physicsUpdateCollector = new();
|
|
||||||
|
|
||||||
public int IterationPerStep { get => _iterationPerStep; set => _iterationPerStep = value < 1 ? 1 : value; }
|
public int IterationPerStep { get => _iterationCount; set => _iterationCount = value < 1 ? 1 : value; }
|
||||||
|
|
||||||
|
public void AddRigidBody(IRigidBody2D rigidBody)
|
||||||
|
{
|
||||||
|
if (rigidBodies.Contains(rigidBody))
|
||||||
|
return;
|
||||||
|
|
||||||
|
rigidBodies.Add(rigidBody);
|
||||||
|
|
||||||
|
foreach (ICollider2D collider2D in rigidBody.BehaviourController.GetBehaviours<ICollider2D>())
|
||||||
|
colliders.Add(collider2D);
|
||||||
|
|
||||||
|
rigidBody.BehaviourController.OnBehaviourAdded += OnBehaviourAdded;
|
||||||
|
rigidBody.BehaviourController.OnBehaviourRemoved += OnBehaviourRemoved;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveRigidBody(IRigidBody2D rigidBody)
|
||||||
|
{
|
||||||
|
rigidBodies.Remove(rigidBody);
|
||||||
|
}
|
||||||
|
|
||||||
public void Step(float deltaTime)
|
public void Step(float deltaTime)
|
||||||
{
|
{
|
||||||
@ -27,23 +47,23 @@ public class PhysicsEngine2DCollector : HierarchyObject, IPhysicsEngine2D
|
|||||||
for (int iterationIndex = 0; iterationIndex < IterationPerStep; iterationIndex++)
|
for (int iterationIndex = 0; iterationIndex < IterationPerStep; iterationIndex++)
|
||||||
{
|
{
|
||||||
// Can Parallel
|
// Can Parallel
|
||||||
foreach (IRigidBody2D rigidBody in rigidBodyCollector)
|
for (int i = 0; i < rigidBodies.Count; i++)
|
||||||
StepRigidBody(rigidBody, intervalDeltaTime);
|
StepRigidBody(rigidBodies[i], intervalDeltaTime);
|
||||||
|
|
||||||
// Can Parallel
|
// Can Parallel
|
||||||
foreach (ICollider2D collider in colliderCollector)
|
foreach (ICollider2D collider in colliders)
|
||||||
collider.Recalculate();
|
collider.Recalculate();
|
||||||
|
|
||||||
// Can Parallel
|
// Can Parallel
|
||||||
for (int x = 0; x < colliderCollector.Behaviours.Count; x++)
|
for (int x = 0; x < colliders.Count; x++)
|
||||||
{
|
{
|
||||||
ICollider2D? colliderX = colliderCollector.Behaviours[x];
|
ICollider2D? colliderX = colliders[x];
|
||||||
if (!colliderX.IsActive)
|
if (!colliderX.IsActive)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (int y = x + 1; y < colliderCollector.Behaviours.Count; y++)
|
for (int y = x + 1; y < colliders.Count; y++)
|
||||||
{
|
{
|
||||||
ICollider2D? colliderY = colliderCollector.Behaviours[y];
|
ICollider2D? colliderY = colliders[y];
|
||||||
|
|
||||||
if (!colliderY.IsActive)
|
if (!colliderY.IsActive)
|
||||||
return;
|
return;
|
||||||
@ -68,7 +88,7 @@ public class PhysicsEngine2DCollector : HierarchyObject, IPhysicsEngine2D
|
|||||||
}
|
}
|
||||||
else if (colliderY.IsTrigger)
|
else if (colliderY.IsTrigger)
|
||||||
{
|
{
|
||||||
colliderY.Trigger(colliderY);
|
colliderY.Trigger(colliderX);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,14 +107,9 @@ public class PhysicsEngine2DCollector : HierarchyObject, IPhysicsEngine2D
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
OnPhysicsIteration?.InvokeSafe(this, intervalDeltaTime);
|
||||||
OnPhysicsIteration?.Invoke(this, intervalDeltaTime);
|
|
||||||
}
|
}
|
||||||
|
OnPhysicsStep?.InvokeSafe(this, deltaTime);
|
||||||
foreach (IPhysicsUpdate physicsUpdate in physicsUpdateCollector)
|
|
||||||
physicsUpdate.PhysicsUpdate(deltaTime);
|
|
||||||
|
|
||||||
OnPhysicsStep?.Invoke(this, deltaTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void StepRigidBody(IRigidBody2D rigidBody, float intervalDeltaTime)
|
private static void StepRigidBody(IRigidBody2D rigidBody, float intervalDeltaTime)
|
||||||
@ -105,27 +120,30 @@ public class PhysicsEngine2DCollector : HierarchyObject, IPhysicsEngine2D
|
|||||||
rigidBody.Transform.Position += rigidBody.Velocity * intervalDeltaTime;
|
rigidBody.Transform.Position += rigidBody.Velocity * intervalDeltaTime;
|
||||||
rigidBody.Transform.Rotation += rigidBody.AngularVelocity * intervalDeltaTime;
|
rigidBody.Transform.Rotation += rigidBody.AngularVelocity * intervalDeltaTime;
|
||||||
}
|
}
|
||||||
protected override void OnEnteringHierarchy(IGameManager gameManager)
|
|
||||||
|
private void OnBehaviourAdded(IBehaviourController controller, IBehaviour behaviour)
|
||||||
{
|
{
|
||||||
physicsUpdateCollector.Assign(gameManager);
|
if (behaviour is not ICollider2D collider2D)
|
||||||
colliderCollector.Assign(gameManager);
|
return;
|
||||||
rigidBodyCollector.Assign(gameManager);
|
|
||||||
|
colliders.Add(collider2D);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnExitingHierarchy(IGameManager gameManager)
|
private void OnBehaviourRemoved(IBehaviourController controller, IBehaviour behaviour)
|
||||||
{
|
{
|
||||||
physicsUpdateCollector.Unassign();
|
if (behaviour is not ICollider2D collider2D)
|
||||||
colliderCollector.Unassign();
|
return;
|
||||||
rigidBodyCollector.Unassign();
|
|
||||||
|
colliders.Remove(collider2D);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PhysicsEngine2DCollector()
|
public PhysicsEngine2DStandalone()
|
||||||
{
|
{
|
||||||
collisionDetector = new CollisionDetector2D();
|
collisionDetector = new CollisionDetector2D();
|
||||||
collisionResolver = new CollisionResolver2D();
|
collisionResolver = new CollisionResolver2D();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PhysicsEngine2DCollector(ICollisionDetector2D collisionDetector, ICollisionResolver2D collisionResolver)
|
public PhysicsEngine2DStandalone(ICollisionDetector2D collisionDetector, ICollisionResolver2D collisionResolver)
|
||||||
{
|
{
|
||||||
this.collisionDetector = collisionDetector;
|
this.collisionDetector = collisionDetector;
|
||||||
this.collisionResolver = collisionResolver;
|
this.collisionResolver = collisionResolver;
|
@ -1,3 +1,5 @@
|
|||||||
|
using Syntriax.Engine.Core;
|
||||||
|
|
||||||
namespace Syntriax.Engine.StateMachine;
|
namespace Syntriax.Engine.StateMachine;
|
||||||
|
|
||||||
public class State : IState
|
public class State : IState
|
||||||
@ -35,12 +37,12 @@ public class State : IState
|
|||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
if (GetNextState() is IState transitionState)
|
if (GetNextState() is IState transitionState)
|
||||||
OnStateTransitionReady?.Invoke(this, transitionState);
|
OnStateTransitionReady?.InvokeSafe(this, transitionState);
|
||||||
OnStateUpdate?.Invoke(this);
|
OnStateUpdate?.InvokeSafe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TransitionTo(IState from) => OnStateTransitionedTo?.Invoke(this, from);
|
public void TransitionTo(IState from) => OnStateTransitionedTo?.InvokeSafe(this, from);
|
||||||
public void TransitionFrom(IState to) => OnStateTransitionedFrom?.Invoke(this, to);
|
public void TransitionFrom(IState to) => OnStateTransitionedFrom?.InvokeSafe(this, to);
|
||||||
|
|
||||||
public IState? GetNextState()
|
public IState? GetNextState()
|
||||||
{
|
{
|
||||||
|
@ -16,21 +16,21 @@ public abstract class StateBehaviourBase : Behaviour, IState
|
|||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
OnUpdateState();
|
OnUpdateState();
|
||||||
OnStateUpdate?.Invoke(this);
|
OnStateUpdate?.InvokeSafe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnTransitionedToState(IState from) { }
|
protected virtual void OnTransitionedToState(IState from) { }
|
||||||
public void TransitionTo(IState from)
|
public void TransitionTo(IState from)
|
||||||
{
|
{
|
||||||
OnTransitionedToState(from);
|
OnTransitionedToState(from);
|
||||||
OnStateTransitionedTo?.Invoke(this, from);
|
OnStateTransitionedTo?.InvokeSafe(this, from);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnTransitionedFromState(IState to) { }
|
protected virtual void OnTransitionedFromState(IState to) { }
|
||||||
public void TransitionFrom(IState to)
|
public void TransitionFrom(IState to)
|
||||||
{
|
{
|
||||||
OnTransitionedFromState(to);
|
OnTransitionedFromState(to);
|
||||||
OnStateTransitionedFrom?.Invoke(this, to);
|
OnStateTransitionedFrom?.InvokeSafe(this, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract IState? GetNextState();
|
public abstract IState? GetNextState();
|
||||||
|
@ -21,7 +21,7 @@ public class StateMachine : Behaviour
|
|||||||
_state = value;
|
_state = value;
|
||||||
previousState.TransitionFrom(value);
|
previousState.TransitionFrom(value);
|
||||||
value.TransitionTo(_state);
|
value.TransitionTo(_state);
|
||||||
OnStateChanged?.Invoke(this, previousState, value);
|
OnStateChanged?.InvokeSafe(this, previousState, value);
|
||||||
|
|
||||||
value.OnStateTransitionReady += OnStateTransitionReady;
|
value.OnStateTransitionReady += OnStateTransitionReady;
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,9 @@ namespace Syntriax.Engine.Systems.Time;
|
|||||||
|
|
||||||
public interface IStopwatch : IReadOnlyStopwatch
|
public interface IStopwatch : IReadOnlyStopwatch
|
||||||
{
|
{
|
||||||
void StopwatchStart();
|
void Start();
|
||||||
void StopwatchStop();
|
void Stop();
|
||||||
|
|
||||||
void StopwatchPause();
|
void Pause();
|
||||||
void StopwatchResume();
|
void Resume();
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ public interface ITicker : IStopwatch
|
|||||||
event TickerTickEventHandler? OnTick;
|
event TickerTickEventHandler? OnTick;
|
||||||
|
|
||||||
int TickCounter { get; }
|
int TickCounter { get; }
|
||||||
double TickPeriod { get; set; }
|
double Period { get; set; }
|
||||||
|
|
||||||
delegate void TickerTickEventHandler(ITicker sender);
|
delegate void TickerTickEventHandler(ITicker sender);
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,9 @@ namespace Syntriax.Engine.Systems.Time;
|
|||||||
|
|
||||||
public interface ITimer : IReadOnlyTimer
|
public interface ITimer : IReadOnlyTimer
|
||||||
{
|
{
|
||||||
void TimerStart(double time);
|
void Start(double time);
|
||||||
void TimerStop();
|
void Stop();
|
||||||
|
|
||||||
void TimerPause();
|
void Pause();
|
||||||
void TimerResume();
|
void Resume();
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ public class StopwatchBehaviour : Behaviour, IStopwatch
|
|||||||
private bool shouldBeTicking = false;
|
private bool shouldBeTicking = false;
|
||||||
private bool hasStartedTickingBefore = false;
|
private bool hasStartedTickingBefore = false;
|
||||||
|
|
||||||
public virtual void StopwatchStart()
|
public virtual void Start()
|
||||||
{
|
{
|
||||||
Time = 0f;
|
Time = 0f;
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ public class StopwatchBehaviour : Behaviour, IStopwatch
|
|||||||
StartStopwatch();
|
StartStopwatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void StopwatchStop()
|
public virtual void Stop()
|
||||||
{
|
{
|
||||||
if (!shouldBeTicking)
|
if (!shouldBeTicking)
|
||||||
return;
|
return;
|
||||||
@ -36,7 +36,7 @@ public class StopwatchBehaviour : Behaviour, IStopwatch
|
|||||||
shouldBeTicking = false;
|
shouldBeTicking = false;
|
||||||
|
|
||||||
State = TimerState.Stopped;
|
State = TimerState.Stopped;
|
||||||
OnStopped?.Invoke(this);
|
OnStopped?.InvokeSafe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnUpdate()
|
protected override void OnUpdate()
|
||||||
@ -44,41 +44,41 @@ public class StopwatchBehaviour : Behaviour, IStopwatch
|
|||||||
if (State is not TimerState.Ticking)
|
if (State is not TimerState.Ticking)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
double delta = GameManager.Time.DeltaSpan.TotalSeconds;
|
double delta = Universe.Time.DeltaSpan.TotalSeconds;
|
||||||
|
|
||||||
Time += delta;
|
Time += delta;
|
||||||
OnDelta?.Invoke(this, delta);
|
OnDelta?.InvokeSafe(this, delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnEnteredHierarchy(IGameManager gameManager)
|
protected override void OnEnteredUniverse(IUniverse universe)
|
||||||
{
|
{
|
||||||
if (!shouldBeTicking || State is TimerState.Ticking)
|
if (!shouldBeTicking || State is TimerState.Ticking)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (hasStartedTickingBefore)
|
if (hasStartedTickingBefore)
|
||||||
StopwatchResume();
|
Resume();
|
||||||
else
|
else
|
||||||
StartStopwatch();
|
StartStopwatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnExitedHierarchy(IGameManager gameManager)
|
protected override void OnExitedUniverse(IUniverse universe)
|
||||||
{
|
{
|
||||||
if (!shouldBeTicking || State is not TimerState.Ticking)
|
if (!shouldBeTicking || State is not TimerState.Ticking)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
StopwatchPause();
|
Pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void StopwatchPause()
|
public virtual void Pause()
|
||||||
{
|
{
|
||||||
State = TimerState.Paused;
|
State = TimerState.Paused;
|
||||||
OnPaused?.Invoke(this);
|
OnPaused?.InvokeSafe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void StopwatchResume()
|
public virtual void Resume()
|
||||||
{
|
{
|
||||||
State = TimerState.Ticking;
|
State = TimerState.Ticking;
|
||||||
OnResumed?.Invoke(this);
|
OnResumed?.InvokeSafe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StartStopwatch()
|
private void StartStopwatch()
|
||||||
@ -86,7 +86,7 @@ public class StopwatchBehaviour : Behaviour, IStopwatch
|
|||||||
hasStartedTickingBefore = true;
|
hasStartedTickingBefore = true;
|
||||||
|
|
||||||
State = TimerState.Ticking;
|
State = TimerState.Ticking;
|
||||||
OnStarted?.Invoke(this);
|
OnStarted?.InvokeSafe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnFinalize()
|
protected override void OnFinalize()
|
||||||
|
@ -1,31 +1,33 @@
|
|||||||
|
using Syntriax.Engine.Core;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Systems.Time;
|
namespace Syntriax.Engine.Systems.Time;
|
||||||
|
|
||||||
public class TickerBehaviour : StopwatchBehaviour, ITicker
|
public class TickerBehaviour : StopwatchBehaviour, ITicker
|
||||||
{
|
{
|
||||||
public event ITicker.TickerTickEventHandler? OnTick = null;
|
public event ITicker.TickerTickEventHandler? OnTick = null;
|
||||||
|
|
||||||
public double TickPeriod { get; set; } = 1f;
|
public double Period { get; set; } = 1f;
|
||||||
public int TickCounter { get; private set; } = 0;
|
public int TickCounter { get; private set; } = 0;
|
||||||
|
|
||||||
private double nextTick = 0f;
|
private double nextTick = 0f;
|
||||||
|
|
||||||
public override void StopwatchStart()
|
public override void Start()
|
||||||
{
|
{
|
||||||
TickCounter = 0;
|
TickCounter = 0;
|
||||||
base.StopwatchStart();
|
base.Start();
|
||||||
nextTick = Time + TickPeriod;
|
nextTick = Time + Period;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnUpdate()
|
protected override void OnUpdate()
|
||||||
{
|
{
|
||||||
base.OnUpdate();
|
base.OnUpdate();
|
||||||
|
|
||||||
if (Time < nextTick)
|
while (Time > nextTick)
|
||||||
return;
|
{
|
||||||
|
nextTick += Period;
|
||||||
nextTick += TickPeriod;
|
TickCounter++;
|
||||||
TickCounter++;
|
OnTick?.InvokeSafe(this);
|
||||||
OnTick?.Invoke(this);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnFinalize()
|
protected override void OnFinalize()
|
||||||
|
@ -31,7 +31,7 @@ public class TimerBehaviour : Behaviour, ITimer
|
|||||||
private bool shouldBeTicking = false;
|
private bool shouldBeTicking = false;
|
||||||
private bool hasStartedTickingBefore = false;
|
private bool hasStartedTickingBefore = false;
|
||||||
|
|
||||||
public virtual void TimerStart(double time)
|
public virtual void Start(double time)
|
||||||
{
|
{
|
||||||
StartTime = time;
|
StartTime = time;
|
||||||
Remaining = time;
|
Remaining = time;
|
||||||
@ -43,7 +43,7 @@ public class TimerBehaviour : Behaviour, ITimer
|
|||||||
StartTimer();
|
StartTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void TimerStop()
|
public virtual void Stop()
|
||||||
{
|
{
|
||||||
if (!shouldBeTicking)
|
if (!shouldBeTicking)
|
||||||
return;
|
return;
|
||||||
@ -51,7 +51,7 @@ public class TimerBehaviour : Behaviour, ITimer
|
|||||||
shouldBeTicking = false;
|
shouldBeTicking = false;
|
||||||
|
|
||||||
State = TimerState.Stopped;
|
State = TimerState.Stopped;
|
||||||
OnStopped?.Invoke(this);
|
OnStopped?.InvokeSafe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnUpdate()
|
protected override void OnUpdate()
|
||||||
@ -59,44 +59,44 @@ public class TimerBehaviour : Behaviour, ITimer
|
|||||||
if (State is not TimerState.Ticking)
|
if (State is not TimerState.Ticking)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
double delta = GameManager.Time.DeltaSpan.TotalSeconds;
|
double delta = Universe.Time.DeltaSpan.TotalSeconds;
|
||||||
|
|
||||||
Remaining -= delta;
|
Remaining -= delta;
|
||||||
OnDelta?.Invoke(this, delta);
|
OnDelta?.InvokeSafe(this, delta);
|
||||||
|
|
||||||
if (Remaining <= .0f)
|
if (Remaining <= .0f)
|
||||||
TimerStop();
|
Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnEnteredHierarchy(IGameManager gameManager)
|
protected override void OnEnteredUniverse(IUniverse universe)
|
||||||
{
|
{
|
||||||
if (!shouldBeTicking || State is TimerState.Ticking)
|
if (!shouldBeTicking || State is TimerState.Ticking)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (hasStartedTickingBefore)
|
if (hasStartedTickingBefore)
|
||||||
TimerResume();
|
Resume();
|
||||||
else
|
else
|
||||||
StartTimer();
|
StartTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnExitedHierarchy(IGameManager gameManager)
|
protected override void OnExitedUniverse(IUniverse universe)
|
||||||
{
|
{
|
||||||
if (!shouldBeTicking || State is not TimerState.Ticking)
|
if (!shouldBeTicking || State is not TimerState.Ticking)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TimerPause();
|
Pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void TimerPause()
|
public virtual void Pause()
|
||||||
{
|
{
|
||||||
State = TimerState.Paused;
|
State = TimerState.Paused;
|
||||||
OnPaused?.Invoke(this);
|
OnPaused?.InvokeSafe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void TimerResume()
|
public virtual void Resume()
|
||||||
{
|
{
|
||||||
State = TimerState.Ticking;
|
State = TimerState.Ticking;
|
||||||
OnResumed?.Invoke(this);
|
OnResumed?.InvokeSafe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StartTimer()
|
private void StartTimer()
|
||||||
@ -104,7 +104,7 @@ public class TimerBehaviour : Behaviour, ITimer
|
|||||||
hasStartedTickingBefore = true;
|
hasStartedTickingBefore = true;
|
||||||
|
|
||||||
State = TimerState.Ticking;
|
State = TimerState.Ticking;
|
||||||
OnStarted?.Invoke(this);
|
OnStarted?.InvokeSafe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnFinalize()
|
protected override void OnFinalize()
|
||||||
|
@ -7,66 +7,66 @@ internal static class EaseConstants
|
|||||||
internal const float c1 = 1.70158f;
|
internal const float c1 = 1.70158f;
|
||||||
internal const float c2 = c1 * 1.525f;
|
internal const float c2 = c1 * 1.525f;
|
||||||
internal const float c3 = c1 + 1f;
|
internal const float c3 = c1 + 1f;
|
||||||
internal const float c4 = 2f * Core.Math.PI / 3;
|
internal const float c4 = 2f * Core.Math.PI / 3f;
|
||||||
internal const float c5 = 2f * Core.Math.PI / 4.5f;
|
internal const float c5 = 2f * Core.Math.PI / 4.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly struct EaseLinear : IEasing { public readonly float Evaluate(float value) => value; }
|
public readonly struct EaseLinear : IEasing { public readonly float Evaluate(float x) => x; }
|
||||||
|
|
||||||
public readonly struct EaseInQuad : IEasing { public readonly float Evaluate(float value) => value * value; }
|
public readonly struct EaseInQuad : IEasing { public readonly float Evaluate(float x) => x * x; }
|
||||||
public readonly struct EaseOutQuad : IEasing { public readonly float Evaluate(float value) => 1f - (1f - value) * (1f - value); }
|
public readonly struct EaseOutQuad : IEasing { public readonly float Evaluate(float x) => 1f - (1f - x) * (1f - x); }
|
||||||
public readonly struct EaseInOutQuad : IEasing { public readonly float Evaluate(float value) => value < 0.5f ? 2f * value * value : 1f - Core.Math.Pow(-2f * value + 2f, 2f) * .5f; }
|
public readonly struct EaseInOutQuad : IEasing { public readonly float Evaluate(float x) => x < .5f ? 2f * x * x : 1f - Core.Math.Pow(-2f * x + 2f, 2f) * .5f; }
|
||||||
|
|
||||||
public readonly struct EaseInCubic : IEasing { public readonly float Evaluate(float value) => value * value * value; }
|
public readonly struct EaseInCubic : IEasing { public readonly float Evaluate(float x) => x * x * x; }
|
||||||
public readonly struct EaseOutCubic : IEasing { public readonly float Evaluate(float value) => 1f - Core.Math.Pow(1f - value, 3); }
|
public readonly struct EaseOutCubic : IEasing { public readonly float Evaluate(float x) => 1f - Core.Math.Pow(1f - x, 3f); }
|
||||||
public readonly struct EaseInOutCubic : IEasing { public readonly float Evaluate(float value) => value < 0.5f ? 4f * value * value * value : 1f - Core.Math.Pow(-2f * value + 2f, 3) * .5f; }
|
public readonly struct EaseInOutCubic : IEasing { public readonly float Evaluate(float x) => x < .5f ? 4f * x * x * x : 1f - Core.Math.Pow(-2f * x + 2f, 3f) * .5f; }
|
||||||
|
|
||||||
public readonly struct EaseInQuart : IEasing { public readonly float Evaluate(float value) => value * value * value * value; }
|
public readonly struct EaseInQuart : IEasing { public readonly float Evaluate(float x) => x * x * x * x; }
|
||||||
public readonly struct EaseOutQuart : IEasing { public readonly float Evaluate(float value) => 1f - Core.Math.Pow(1f - value, 4f); }
|
public readonly struct EaseOutQuart : IEasing { public readonly float Evaluate(float x) => 1f - Core.Math.Pow(1f - x, 4f); }
|
||||||
public readonly struct EaseInOutQuart : IEasing { public readonly float Evaluate(float value) => value < 0.5f ? 8 * value * value * value * value : 1f - Core.Math.Pow(-2f * value + 2f, 4f) * .5f; }
|
public readonly struct EaseInOutQuart : IEasing { public readonly float Evaluate(float x) => x < .5f ? 8f * x * x * x * x : 1f - Core.Math.Pow(-2f * x + 2f, 4f) * .5f; }
|
||||||
|
|
||||||
public readonly struct EaseInQuint : IEasing { public readonly float Evaluate(float value) => value * value * value * value * value; }
|
public readonly struct EaseInQuint : IEasing { public readonly float Evaluate(float x) => x * x * x * x * x; }
|
||||||
public readonly struct EaseOutQuint : IEasing { public readonly float Evaluate(float value) => 1f - Core.Math.Pow(1f - value, 5); }
|
public readonly struct EaseOutQuint : IEasing { public readonly float Evaluate(float x) => 1f - Core.Math.Pow(1f - x, 5f); }
|
||||||
public readonly struct EaseInOutQuint : IEasing { public readonly float Evaluate(float value) => value < 0.5f ? 16 * value * value * value * value * value : 1f - Core.Math.Pow(-2f * value + 2f, 5) * .5f; }
|
public readonly struct EaseInOutQuint : IEasing { public readonly float Evaluate(float x) => x < .5f ? 16f * x * x * x * x * x : 1f - Core.Math.Pow(-2f * x + 2f, 5f) * .5f; }
|
||||||
|
|
||||||
public readonly struct EaseInSine : IEasing { public readonly float Evaluate(float value) => 1f - Core.Math.Cos(value * Core.Math.PI * .5f); }
|
public readonly struct EaseInSine : IEasing { public readonly float Evaluate(float x) => 1f - Core.Math.Cos(x * Core.Math.PI * .5f); }
|
||||||
public readonly struct EaseOutSine : IEasing { public readonly float Evaluate(float value) => Core.Math.Sin(value * Core.Math.PI * .5f); }
|
public readonly struct EaseOutSine : IEasing { public readonly float Evaluate(float x) => Core.Math.Sin(x * Core.Math.PI * .5f); }
|
||||||
public readonly struct EaseInOutSine : IEasing { public readonly float Evaluate(float value) => -(Core.Math.Cos(Core.Math.PI * value) - 1f) * .5f; }
|
public readonly struct EaseInOutSine : IEasing { public readonly float Evaluate(float x) => -(Core.Math.Cos(Core.Math.PI * x) - 1f) * .5f; }
|
||||||
|
|
||||||
public readonly struct EaseInExpo : IEasing { public readonly float Evaluate(float value) => value == 0 ? 0 : Core.Math.Pow(2f, 10f * value - 10f); }
|
public readonly struct EaseInExpo : IEasing { public readonly float Evaluate(float x) => x == 0f ? 0f : Core.Math.Pow(2f, 10f * x - 10f); }
|
||||||
public readonly struct EaseOutExpo : IEasing { public readonly float Evaluate(float value) => value == 1f ? 1f : 1f - Core.Math.Pow(2f, -10f * value); }
|
public readonly struct EaseOutExpo : IEasing { public readonly float Evaluate(float x) => x == 1f ? 1f : 1f - Core.Math.Pow(2f, -10f * x); }
|
||||||
public readonly struct EaseInOutExpo : IEasing { public readonly float Evaluate(float value) => value == 0 ? 0 : value == 1f ? 1f : value < 0.5f ? Core.Math.Pow(2f, 20 * value - 10f) * .5f : (2f - Core.Math.Pow(2f, -20 * value + 10f)) * .5f; }
|
public readonly struct EaseInOutExpo : IEasing { public readonly float Evaluate(float x) => x == 0f ? 0f : x == 1f ? 1f : x < .5f ? Core.Math.Pow(2f, 20f * x - 10f) * .5f : (2f - Core.Math.Pow(2f, -20f * x + 10f)) * .5f; }
|
||||||
|
|
||||||
public readonly struct EaseInCirc : IEasing { public readonly float Evaluate(float value) => 1f - Core.Math.Sqrt(1f - Core.Math.Pow(value, 2f)); }
|
public readonly struct EaseInCirc : IEasing { public readonly float Evaluate(float x) => 1f - Core.Math.Sqrt(1f - Core.Math.Pow(x, 2f)); }
|
||||||
public readonly struct EaseOutCirc : IEasing { public readonly float Evaluate(float value) => Core.Math.Sqrt(1f - Core.Math.Pow(value - 1f, 2f)); }
|
public readonly struct EaseOutCirc : IEasing { public readonly float Evaluate(float x) => Core.Math.Sqrt(1f - Core.Math.Pow(x - 1f, 2f)); }
|
||||||
public readonly struct EaseInOutCirc : IEasing { public readonly float Evaluate(float value) => value < 0.5f ? (1f - Core.Math.Sqrt(1f - Core.Math.Pow(2f * value, 2f))) * .5f : (Core.Math.Sqrt(1f - Core.Math.Pow(-2f * value + 2f, 2f)) + 1f) * .5f; }
|
public readonly struct EaseInOutCirc : IEasing { public readonly float Evaluate(float x) => x < .5f ? (1f - Core.Math.Sqrt(1f - Core.Math.Pow(2f * x, 2f))) * .5f : (Core.Math.Sqrt(1f - Core.Math.Pow(-2f * x + 2f, 2f)) + 1f) * .5f; }
|
||||||
|
|
||||||
public readonly struct EaseInBack : IEasing { public readonly float Evaluate(float value) => EaseConstants.c3 * value * value * value - EaseConstants.c1 * value * value; }
|
public readonly struct EaseInBack : IEasing { public readonly float Evaluate(float x) => EaseConstants.c3 * x * x * x - EaseConstants.c1 * x * x; }
|
||||||
public readonly struct EaseOutBack : IEasing { public readonly float Evaluate(float value) => 1f + EaseConstants.c3 * Core.Math.Pow(value - 1f, 3) + EaseConstants.c1 * Core.Math.Pow(value - 1f, 2f); }
|
public readonly struct EaseOutBack : IEasing { public readonly float Evaluate(float x) => 1f + EaseConstants.c3 * Core.Math.Pow(x - 1f, 3f) + EaseConstants.c1 * Core.Math.Pow(x - 1f, 2f); }
|
||||||
public readonly struct EaseInOutBack : IEasing { public readonly float Evaluate(float value) => value < 0.5f ? Core.Math.Pow(2f * value, 2f) * ((EaseConstants.c2 + 1f) * 2f * value - EaseConstants.c2) * .5f : (Core.Math.Pow(2f * value - 2f, 2f) * ((EaseConstants.c2 + 1f) * (value * 2f - 2f) + EaseConstants.c2) + 2f) * .5f; }
|
public readonly struct EaseInOutBack : IEasing { public readonly float Evaluate(float x) => x < .5f ? Core.Math.Pow(2f * x, 2f) * ((EaseConstants.c2 + 1f) * 2f * x - EaseConstants.c2) * .5f : (Core.Math.Pow(2f * x - 2f, 2f) * ((EaseConstants.c2 + 1f) * (x * 2f - 2f) + EaseConstants.c2) + 2f) * .5f; }
|
||||||
|
|
||||||
public readonly struct EaseInElastic : IEasing { public readonly float Evaluate(float value) => value == 0 ? 0 : value == 1f ? 1f : -Core.Math.Pow(2f, 10f * value - 10f) * Core.Math.Sin((value * 10f - 10.75f) * EaseConstants.c4); }
|
public readonly struct EaseInElastic : IEasing { public readonly float Evaluate(float x) => x == 0 ? 0 : x == 1f ? 1f : -Core.Math.Pow(2f, 10f * x - 10f) * Core.Math.Sin((x * 10f - 10.75f) * EaseConstants.c4); }
|
||||||
public readonly struct EaseOutElastic : IEasing { public readonly float Evaluate(float value) => value == 0 ? 0 : value == 1f ? 1f : Core.Math.Pow(2f, -10f * value) * Core.Math.Sin((value * 10f - 0.75f) * EaseConstants.c4) + 1f; }
|
public readonly struct EaseOutElastic : IEasing { public readonly float Evaluate(float x) => x == 0 ? 0 : x == 1f ? 1f : Core.Math.Pow(2f, -10f * x) * Core.Math.Sin((x * 10f - .75f) * EaseConstants.c4) + 1f; }
|
||||||
public readonly struct EaseInOutElastic : IEasing { public readonly float Evaluate(float value) => value == 0 ? 0 : value == 1f ? 1f : value < 0.5f ? -(Core.Math.Pow(2f, 20 * value - 10f) * Core.Math.Sin((20 * value - 11.125f) * EaseConstants.c5)) * .5f : Core.Math.Pow(2f, -20 * value + 10f) * Core.Math.Sin((20 * value - 11.125f) * EaseConstants.c5) * .5f + 1f; }
|
public readonly struct EaseInOutElastic : IEasing { public readonly float Evaluate(float x) => x == 0 ? 0 : x == 1f ? 1f : x < .5f ? -(Core.Math.Pow(2f, 20f * x - 10f) * Core.Math.Sin((20f * x - 11.125f) * EaseConstants.c5)) * .5f : Core.Math.Pow(2f, -20f * x + 10f) * Core.Math.Sin((20f * x - 11.125f) * EaseConstants.c5) * .5f + 1f; }
|
||||||
|
|
||||||
public readonly struct EaseInBounce : IEasing { public readonly float Evaluate(float value) => 1f - new EaseOutBounce().Evaluate(1f - value); }
|
public readonly struct EaseInBounce : IEasing { public readonly float Evaluate(float x) => 1f - new EaseOutBounce().Evaluate(1f - x); }
|
||||||
public readonly struct EaseOutBounce : IEasing
|
public readonly struct EaseOutBounce : IEasing
|
||||||
{
|
{
|
||||||
public readonly float Evaluate(float value)
|
public readonly float Evaluate(float x)
|
||||||
{
|
{
|
||||||
const float n1 = 7.5625f;
|
const float n1 = 7.5625f;
|
||||||
const float d1 = 2.75f;
|
const float d1 = 2.75f;
|
||||||
|
|
||||||
if (value < 1 / d1)
|
if (x < 1f / d1)
|
||||||
return n1 * value * value;
|
return n1 * x * x;
|
||||||
|
|
||||||
if (value < 2 / d1)
|
if (x < 2f / d1)
|
||||||
return n1 * (value -= 1.5f / d1) * value + 0.75f;
|
return n1 * (x -= 1.5f / d1) * x + .75f;
|
||||||
|
|
||||||
if (value < 2.5 / d1)
|
if (x < 2.5f / d1)
|
||||||
return n1 * (value -= 2.25f / d1) * value + 0.9375f;
|
return n1 * (x -= 2.25f / d1) * x + .9375f;
|
||||||
|
|
||||||
return n1 * (value -= 2.625f / d1) * value + 0.984375f;
|
return n1 * (x -= 2.625f / d1) * x + .984375f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public readonly struct EaseInOutBounce : IEasing { public readonly float Evaluate(float value) => value < 0.5f ? (1f - new EaseOutBounce().Evaluate(1f - 2f * value)) * .5f : (1f + new EaseOutBounce().Evaluate(2f * value - 1f)) * .5f; }
|
public readonly struct EaseInOutBounce : IEasing { public readonly float Evaluate(float x) => x < .5f ? (1f - new EaseOutBounce().Evaluate(1f - 2f * x)) * .5f : (1f + new EaseOutBounce().Evaluate(2f * x - 1f)) * .5f; }
|
||||||
|
@ -2,6 +2,6 @@ namespace Syntriax.Engine.Systems.Tween;
|
|||||||
|
|
||||||
public interface IEasing
|
public interface IEasing
|
||||||
{
|
{
|
||||||
float Evaluate(float value);
|
float Evaluate(float x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,14 +26,14 @@ internal class Tween : ITween
|
|||||||
_state = value;
|
_state = value;
|
||||||
switch (value)
|
switch (value)
|
||||||
{
|
{
|
||||||
case TweenState.Completed: OnCompleted?.Invoke(this); OnEnded?.Invoke(this); break;
|
case TweenState.Completed: OnCompleted?.InvokeSafe(this); OnEnded?.InvokeSafe(this); break;
|
||||||
case TweenState.Cancelled: OnCancelled?.Invoke(this); OnEnded?.Invoke(this); break;
|
case TweenState.Cancelled: OnCancelled?.InvokeSafe(this); OnEnded?.InvokeSafe(this); break;
|
||||||
case TweenState.Paused: OnPaused?.Invoke(this); break;
|
case TweenState.Paused: OnPaused?.InvokeSafe(this); break;
|
||||||
case TweenState.Playing:
|
case TweenState.Playing:
|
||||||
if (previousState == TweenState.Idle)
|
if (previousState == TweenState.Idle)
|
||||||
OnStarted?.Invoke(this);
|
OnStarted?.InvokeSafe(this);
|
||||||
else
|
else
|
||||||
OnResumed?.Invoke(this);
|
OnResumed?.InvokeSafe(this);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,9 +58,9 @@ internal class Tween : ITween
|
|||||||
|
|
||||||
_counter = value.Min(Duration).Max(0f);
|
_counter = value.Min(Duration).Max(0f);
|
||||||
Progress = Counter / Duration;
|
Progress = Counter / Duration;
|
||||||
OnUpdated?.Invoke(this);
|
OnUpdated?.InvokeSafe(this);
|
||||||
|
|
||||||
OnDeltaUpdated?.Invoke(this, Easing.Evaluate(Progress) - Easing.Evaluate(previousProgress));
|
OnDeltaUpdated?.InvokeSafe(this, Easing.Evaluate(Progress) - Easing.Evaluate(previousProgress));
|
||||||
|
|
||||||
if (_counter >= Duration)
|
if (_counter >= Duration)
|
||||||
State = TweenState.Completed;
|
State = TweenState.Completed;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
using Syntriax.Engine.Core;
|
||||||
|
|
||||||
namespace Syntriax.Engine.Systems.Tween;
|
namespace Syntriax.Engine.Systems.Tween;
|
||||||
|
|
||||||
public static class TweenExtensions
|
public static class TweenExtensions
|
||||||
@ -42,49 +44,49 @@ public static class TweenExtensions
|
|||||||
public static ITween OnStart(this ITween tween, Action callback)
|
public static ITween OnStart(this ITween tween, Action callback)
|
||||||
{
|
{
|
||||||
Tween tweenConcrete = (Tween)tween;
|
Tween tweenConcrete = (Tween)tween;
|
||||||
tweenConcrete.OnStarted += _ => callback.Invoke();
|
tweenConcrete.OnStarted += _ => callback.InvokeSafe();
|
||||||
return tween;
|
return tween;
|
||||||
}
|
}
|
||||||
public static ITween OnPause(this ITween tween, Action callback)
|
public static ITween OnPause(this ITween tween, Action callback)
|
||||||
{
|
{
|
||||||
Tween tweenConcrete = (Tween)tween;
|
Tween tweenConcrete = (Tween)tween;
|
||||||
tweenConcrete.OnPaused += _ => callback.Invoke();
|
tweenConcrete.OnPaused += _ => callback.InvokeSafe();
|
||||||
return tween;
|
return tween;
|
||||||
}
|
}
|
||||||
public static ITween OnResume(this ITween tween, Action callback)
|
public static ITween OnResume(this ITween tween, Action callback)
|
||||||
{
|
{
|
||||||
Tween tweenConcrete = (Tween)tween;
|
Tween tweenConcrete = (Tween)tween;
|
||||||
tweenConcrete.OnResumed += _ => callback.Invoke();
|
tweenConcrete.OnResumed += _ => callback.InvokeSafe();
|
||||||
return tween;
|
return tween;
|
||||||
}
|
}
|
||||||
public static ITween OnCancel(this ITween tween, Action callback)
|
public static ITween OnCancel(this ITween tween, Action callback)
|
||||||
{
|
{
|
||||||
Tween tweenConcrete = (Tween)tween;
|
Tween tweenConcrete = (Tween)tween;
|
||||||
tweenConcrete.OnCancelled += _ => callback.Invoke();
|
tweenConcrete.OnCancelled += _ => callback.InvokeSafe();
|
||||||
return tween;
|
return tween;
|
||||||
}
|
}
|
||||||
public static ITween OnComplete(this ITween tween, Action callback)
|
public static ITween OnComplete(this ITween tween, Action callback)
|
||||||
{
|
{
|
||||||
Tween tweenConcrete = (Tween)tween;
|
Tween tweenConcrete = (Tween)tween;
|
||||||
tweenConcrete.OnCompleted += _ => callback.Invoke();
|
tweenConcrete.OnCompleted += _ => callback.InvokeSafe();
|
||||||
return tween;
|
return tween;
|
||||||
}
|
}
|
||||||
public static ITween OnEnd(this ITween tween, Action callback)
|
public static ITween OnEnd(this ITween tween, Action callback)
|
||||||
{
|
{
|
||||||
Tween tweenConcrete = (Tween)tween;
|
Tween tweenConcrete = (Tween)tween;
|
||||||
tweenConcrete.OnEnded += _ => callback.Invoke();
|
tweenConcrete.OnEnded += _ => callback.InvokeSafe();
|
||||||
return tween;
|
return tween;
|
||||||
}
|
}
|
||||||
public static ITween OnUpdate(this ITween tween, Action callback)
|
public static ITween OnUpdate(this ITween tween, Action callback)
|
||||||
{
|
{
|
||||||
Tween tweenConcrete = (Tween)tween;
|
Tween tweenConcrete = (Tween)tween;
|
||||||
tweenConcrete.OnUpdated += _ => callback.Invoke();
|
tweenConcrete.OnUpdated += _ => callback.InvokeSafe();
|
||||||
return tween;
|
return tween;
|
||||||
}
|
}
|
||||||
public static ITween OnDeltaUpdate(this ITween tween, Action<float> callback)
|
public static ITween OnDeltaUpdate(this ITween tween, Action<float> callback)
|
||||||
{
|
{
|
||||||
Tween tweenConcrete = (Tween)tween;
|
Tween tweenConcrete = (Tween)tween;
|
||||||
tweenConcrete.OnDeltaUpdated += (_, delta) => callback.Invoke(delta);
|
tweenConcrete.OnDeltaUpdated += (_, delta) => callback.InvokeSafe(delta);
|
||||||
return tween;
|
return tween;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ using Syntriax.Engine.Core.Abstract;
|
|||||||
|
|
||||||
namespace Syntriax.Engine.Systems.Tween;
|
namespace Syntriax.Engine.Systems.Tween;
|
||||||
|
|
||||||
public class TweenManager : HierarchyObject
|
public class TweenManager : UniverseObject
|
||||||
{
|
{
|
||||||
private CoroutineManager coroutineManager = null!;
|
private CoroutineManager coroutineManager = null!;
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ public class TweenManager : HierarchyObject
|
|||||||
public ITween StartTween(float duration, TweenSetCallback? setCallback = null)
|
public ITween StartTween(float duration, TweenSetCallback? setCallback = null)
|
||||||
{
|
{
|
||||||
Tween tween = new(duration);
|
Tween tween = new(duration);
|
||||||
tween.OnUpdated += tween => setCallback?.Invoke(tween.Value);
|
tween.OnUpdated += tween => setCallback?.InvokeSafe(tween.Value);
|
||||||
runningCoroutines.Add(tween, coroutineManager.StartCoroutine(RunTween(tween)));
|
runningCoroutines.Add(tween, coroutineManager.StartCoroutine(RunTween(tween)));
|
||||||
return tween;
|
return tween;
|
||||||
}
|
}
|
||||||
@ -35,7 +35,7 @@ public class TweenManager : HierarchyObject
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
tween.Counter += GameManager.Time.DeltaTime;
|
tween.Counter += Universe.Time.DeltaTime;
|
||||||
yield return null;
|
yield return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,12 +52,12 @@ public class TweenManager : HierarchyObject
|
|||||||
runningCoroutines.Remove(tween);
|
runningCoroutines.Remove(tween);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnEnteringHierarchy(IGameManager gameManager)
|
protected override void OnEnteringUniverse(IUniverse universe)
|
||||||
{
|
{
|
||||||
coroutineManager = gameManager.FindHierarchyObject<CoroutineManager>() ?? throw new($"No {nameof(CoroutineManager)} was found in the game manager");
|
coroutineManager = universe.GetRequiredUniverseObject<CoroutineManager>();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnExitingHierarchy(IGameManager gameManager)
|
protected override void OnExitingUniverse(IUniverse universe)
|
||||||
{
|
{
|
||||||
coroutineManager = null!;
|
coroutineManager = null!;
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
# Work In Progress
|
# Work In Progress
|
||||||
|
|
||||||
This engine is still in development but the implemented features include:
|
This engine is still in development so there **WILL** be breaking changes, but the implemented features include:
|
||||||
|
|
||||||
- Modular Systems
|
- Modular Systems
|
||||||
- Behaviour System
|
- Behaviour System
|
||||||
- 2D Physics Engine(**Not Fully Completed, but usable**)
|
- 2D Physics Engine(**Not Fully Completed, but usable**)
|
||||||
- Rigid Body Simulations
|
- Rigid Body Simulations
|
||||||
- Collision Detection (Convex Shape & Circle)
|
- Collision Detection (Convex Shape & Circle)
|
||||||
- Collision Resolution (**Not Fully Completed**)
|
- Collision Resolution (**Not Fully Completed**)
|
||||||
- Vector2D, AABB, Circle, Line, LineEquation, Projection & Shape Data Types
|
- Vector2D, AABB, Circle, Line, LineEquation, Projection & Shape Data Types
|
||||||
- General Math
|
- General Math
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user