Development Merge 2025.04.01 #1

Merged
Syntriax merged 32 commits from development into main 2025-04-01 19:20:18 +03:00
58 changed files with 937 additions and 1187 deletions
Showing only changes of commit 4ec1a32db2 - Show all commits

View File

@ -1,26 +0,0 @@
namespace Syntriax.Engine.Core.Abstract;
/// <summary>
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IGameObject"/> field.
/// </summary>
public interface IAssignableGameObject : IAssignable
{
/// <summary>
/// Event triggered when the <see cref="IGameObject"/> value has has been assigned a new value.
/// </summary>
event OnGameObjectAssignedEventHandler? OnGameObjectAssigned;
/// <inheritdoc cref="IGameObject" />
IGameObject GameObject { get; }
/// <summary>
/// Assign a value to the <see cref="IGameObject"/> field of this object.
/// </summary>
/// <param name="gameObject">New <see cref="IGameObject"/> to assign.</param>
/// <returns>
/// <see cref="true"/>, if the value given assigned successfully assigned, <see cref="false"/> if not.
/// </returns>
bool Assign(IGameObject gameObject);
delegate void OnGameObjectAssignedEventHandler(IAssignableGameObject sender);
}

View File

@ -1,26 +0,0 @@
namespace Syntriax.Engine.Core.Abstract;
/// <summary>
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="ITransform"/> field.
/// </summary>
public interface IAssignableTransform : IAssignable
{
/// <summary>
/// Event triggered when the <see cref="ITransform"/> value has has been assigned a new value.
/// </summary>
event OnTransformAssignedEventHandler? OnTransformAssigned;
/// <inheritdoc cref="ITransform" />
ITransform Transform { get; }
/// <summary>
/// Assign a value to the <see cref="ITransform"/> field of this object.
/// </summary>
/// <param name="transform">New <see cref="ITransform"/> to assign.</param>
/// <returns>
/// <see cref="true"/>, if the value given assigned successfully assigned, <see cref="false"/> if not.
/// </returns>
bool Assign(ITransform transform);
delegate void OnTransformAssignedEventHandler(IAssignableTransform sender);
}

View File

@ -3,7 +3,7 @@ namespace Syntriax.Engine.Core.Abstract;
/// <summary>
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IBehaviourController"/> field.
/// </summary>
public interface IAssignableBehaviourController : IAssignable
public interface IHasBehaviourController : IAssignable
{
/// <summary>
/// Event triggered when the <see cref="IBehaviourController"/> value has has been assigned a new value.
@ -22,5 +22,5 @@ public interface IAssignableBehaviourController : IAssignable
/// </returns>
bool Assign(IBehaviourController behaviourController);
delegate void OnBehaviourControllerAssignedEventHandler(IAssignableBehaviourController sender);
delegate void OnBehaviourControllerAssignedEventHandler(IHasBehaviourController sender);
}

View File

@ -3,7 +3,7 @@ namespace Syntriax.Engine.Core.Abstract;
/// <summary>
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IEntity"/> field.
/// </summary>
public interface IAssignableEntity : IAssignable
public interface IHasEntity : IAssignable
{
/// <summary>
/// Event triggered when the <see cref="IEntity"/> value has has been assigned a new value.
@ -22,5 +22,5 @@ public interface IAssignableEntity : IAssignable
/// </returns>
bool Assign(IEntity entity);
delegate void OnEntityAssignedEventHandler(IAssignableEntity sender);
delegate void OnEntityAssignedEventHandler(IHasEntity sender);
}

View File

@ -1,9 +1,9 @@
namespace Syntriax.Engine.Core.Abstract;
/// <summary>
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="ITransform"/> field.
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="ITransform2D"/> field.
/// </summary>
public interface IAssignableGameManager : IAssignable
public interface IHasGameManager : IAssignable
{
/// <summary>
/// Event triggered when the <see cref="IGameManager"/> value has has been assigned a new value.
@ -22,5 +22,5 @@ public interface IAssignableGameManager : IAssignable
/// </returns>
bool Assign(IGameManager gameManager);
delegate void OnGameManagerAssignedEventHandler(IAssignableGameManager sender);
delegate void OnGameManagerAssignedEventHandler(IHasGameManager sender);
}

View File

@ -0,0 +1,26 @@
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 OnHierarchyObjectAssignedEventHandler? 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 OnHierarchyObjectAssignedEventHandler(IHasHierarchyObject sender);
}

View File

@ -3,7 +3,7 @@ namespace Syntriax.Engine.Core.Abstract;
/// <summary>
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IStateEnable"/> field.
/// </summary>
public interface IAssignableStateEnable : IAssignable
public interface IHasStateEnable : IAssignable
{
/// <summary>
/// Event triggered when the <see cref="IStateEnable"/> value has has been assigned a new value.
@ -22,5 +22,5 @@ public interface IAssignableStateEnable : IAssignable
/// </returns>
bool Assign(IStateEnable stateEnable);
delegate void OnStateEnableAssignedEventHandler(IAssignableStateEnable sender);
delegate void OnStateEnableAssignedEventHandler(IHasStateEnable sender);
}

View File

@ -1,64 +0,0 @@
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, INameable
{
/// <summary>
/// Event triggered when the <see cref="IEntity"/> enters the hierarchy.
/// </summary>
event OnEnteredHierarchyEventHandler? OnEnteredHierarchy;
/// <summary>
/// Event triggered when the <see cref="IEntity"/> exits the hierarchy.
/// </summary>
event OnExitedHierarchyEventHandler? OnExitedHierarchy;
/// <summary>
/// Gets the <see cref="IGameManager"/> associated with this <see cref="IEntity"/> , if any.
/// </summary>
IGameManager GameManager { get; }
/// <summary>
/// Indicates whether the <see cref="IEntity"/> is currently in the hierarchy.
/// </summary>
bool IsInHierarchy { 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 game manager that is managing this hierarchy.</param>
/// <returns>
/// <see cref="true"/> if the <see cref="IEntity"/> 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="IEntity"/> successfully exited the hierarchy;
/// <see cref="false"/> if it failed to do so.
/// </returns>
internal bool ExitHierarchy();
/// <summary>
/// EventHandler delegate for the event triggered when the <see cref="IEntity"/> enters the hierarchy of a <see cref="IGameManager">.
/// </summary>
/// <param name="sender">The <see cref="IEntity"/> that entered the hierarchy.</param>
/// <param name="gameManager">The <see cref="IGameManager"/> that the <see cref="IEntity"/> has entered it's hierarchy.</param>
delegate void OnEnteredHierarchyEventHandler(IHierarchyObject sender, IGameManager gameManager);
/// <summary>
/// EventHandler delegate for the event triggered when the <see cref="IEntity"/> exits the hierarchy of a <see cref="IGameManager">.
/// </summary>
/// <param name="sender">The <see cref="IEntity"/> that exited the hierarchy.</param>
/// <param name="gameManager">The <see cref="IGameManager"/> that the <see cref="IEntity"/> has exited it's hierarchy.</param>
delegate void OnExitedHierarchyEventHandler(IHierarchyObject sender, IGameManager gameManager);
}

View File

@ -1,17 +1,15 @@
using System;
using Syntriax.Engine.Core.Exceptions;
namespace Syntriax.Engine.Core.Abstract;
public abstract class BaseEntity : IEntity
{
public event IEntity.OnIdChangedEventHandler? OnIdChanged = null;
public event IInitialize.OnInitializedEventHandler? OnInitialized = null;
public event IInitialize.OnFinalizedEventHandler? OnFinalized = null;
public event IInitializable.OnInitializedEventHandler? OnInitialized = null;
public event IInitializable.OnFinalizedEventHandler? OnFinalized = null;
public event IAssignableStateEnable.OnStateEnableAssignedEventHandler? OnStateEnableAssigned = null;
public event IHasStateEnable.OnStateEnableAssignedEventHandler? OnStateEnableAssigned = null;
public event IAssignable.OnUnassignedEventHandler? OnUnassigned = null;
private IStateEnable _stateEnable = null!;
@ -28,6 +26,9 @@ public abstract class BaseEntity : IEntity
get => _id;
set
{
if (IsInitialized)
throw new($"Can't change {nameof(Id)} of {_id} because it's initialized");
if (value == _id)
return;
@ -85,7 +86,7 @@ public abstract class BaseEntity : IEntity
if (IsInitialized)
return false;
NotAssignedException.Check(this, _stateEnable);
_stateEnable ??= new Factory.StateEnableFactory().Instantiate(this);
InitializeInternal();

View File

@ -3,7 +3,7 @@ namespace Syntriax.Engine.Core.Abstract;
/// <summary>
/// Represents a behaviour that any object in the game might use to interact with itself or other objects.
/// </summary>
public interface IBehaviour : IEntity, IAssignableBehaviourController, IAssignableStateEnable
public interface IBehaviour : IEntity, IHasBehaviourController, IHasStateEnable
{
/// <summary>
/// Event triggered when the priority of the <see cref="IBehaviour"/> changes.

View File

@ -0,0 +1,6 @@
namespace Syntriax.Engine.Core.Abstract;
public interface IBehaviour2D : IBehaviour
{
ITransform2D Transform { get; }
}

View File

@ -7,7 +7,7 @@ namespace Syntriax.Engine.Core.Abstract;
/// Provides mechanisms for tracking additions and removals, and notifies subscribers when such events occur on the assigned <see cref="IGameManager"/>.
/// </summary>
/// <typeparam name="T">The type of objects tracked by the collector.</typeparam>
public interface IBehaviourCollector<T> : IAssignableGameManager, IEnumerable<T> where T : class
public interface IBehaviourCollector<T> : IHasGameManager, IEnumerable<T> where T : class
{
/// <summary>
/// Event triggered when an object of type <typeparamref name="T"/> is added to the collector.

View File

@ -3,9 +3,9 @@ using System.Collections.Generic;
namespace Syntriax.Engine.Core.Abstract;
/// <summary>
/// Represents a controller for managing <see cref="IBehaviour"/>s and notify them accordingly about the engine's updates. Connected to an <see cref="IGameObject"/>.
/// Represents a controller for managing <see cref="IBehaviour"/>s and notify them accordingly about the engine's updates. Connected to an <see cref="IHierarchyObject"/>.
/// </summary>
public interface IBehaviourController : IInitialize, IAssignableGameObject, IEnumerable<IBehaviour>
public interface IBehaviourController : IInitializable, IHasHierarchyObject, IEnumerable<IBehaviour>
{
/// <summary>
/// Event triggered before the update of <see cref="IBehaviour"/>s.

View File

@ -3,7 +3,7 @@ namespace Syntriax.Engine.Core.Abstract;
/// <summary>
/// Represents a 2D camera in the engine.
/// </summary>
public interface ICamera2D : IBehaviour, IAssignableTransform
public interface ICamera2D : IBehaviour2D
{
/// <summary>
/// The zoom level of the camera.

View File

@ -3,7 +3,7 @@ namespace Syntriax.Engine.Core.Abstract;
/// <summary>
/// Represents a basic entity in the engine.
/// </summary>
public interface IEntity : IInitialize, IAssignableStateEnable
public interface IEntity : IInitializable, IHasStateEnable
{
/// <summary>
/// Event triggered when the <see cref="Id"/> of the <see cref="IEntity"/> changes.

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
namespace Syntriax.Engine.Core.Abstract;
/// <summary>
/// Represents a game world responsible for managing <see cref="IGameObject"/>s.
/// Represents a game world responsible for managing <see cref="IHierarchyObject"/>s.
/// </summary>
public interface IGameManager : IEntity
{
@ -17,16 +17,6 @@ public interface IGameManager : IEntity
/// </summary>
event OnPreDawEventHandler? OnPreDraw;
/// <summary>
/// Event triggered when a <see cref="IGameObject"/> is registered to the <see cref="IGameManager"/>.
/// </summary>
event OnGameObjectRegisteredEventHandler? OnGameObjectRegistered;
/// <summary>
/// Event triggered when a <see cref="IGameObject"/> is unregistered from the <see cref="IGameManager"/>.
/// </summary>
event OnGameObjectUnRegisteredEventHandler? OnGameObjectUnRegistered;
/// <summary>
/// Event triggered when a <see cref="IHierarchyObject"/> is registered to the <see cref="IGameManager"/>.
/// </summary>
@ -37,11 +27,6 @@ public interface IGameManager : IEntity
/// </summary>
event OnHierarchyObjectUnRegisteredEventHandler? OnHierarchyObjectUnRegistered;
/// <summary>
/// Gets a read-only list of <see cref="IGameObject"/>s managed by the <see cref="IGameManager"/>.
/// </summary>
IReadOnlyList<IGameObject> GameObjects { get; }
/// <summary>
/// Gets a read-only list of <see cref="IHierarchyObject"/>s managed by the <see cref="IGameManager"/>.
/// </summary>
@ -54,12 +39,12 @@ public interface IGameManager : IEntity
void Register(IHierarchyObject hierarchyObject);
/// <summary>
/// Instantiates a <see cref="IGameObject"/> of type T with the given arguments and registers it to the <see cref="IGameManager"/>.
/// 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="IGameObject"/> to instantiate.</typeparam>
/// <param name="args">Constructor parameters for the given type of <see cref="IGameObject"/>.</param>
/// <returns>The instantiated <see cref="IGameObject"/>.</returns>
T InstantiateGameObject<T>(params object?[]? args) where T : class, IGameObject;
/// <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"/>.
@ -81,8 +66,6 @@ public interface IGameManager : IEntity
delegate void OnUpdateEventHandler(IGameManager sender, EngineTime time);
delegate void OnPreDawEventHandler(IGameManager sender);
delegate void OnGameObjectRegisteredEventHandler(IGameManager sender, IGameObject gameObjectRegistered);
delegate void OnGameObjectUnRegisteredEventHandler(IGameManager sender, IGameObject gameObjectUnregistered);
delegate void OnHierarchyObjectRegisteredEventHandler(IGameManager sender, IHierarchyObject hierarchyObjectRegistered);
delegate void OnHierarchyObjectUnRegisteredEventHandler(IGameManager sender, IHierarchyObject hierarchyObjectUnregistered);
}

View File

@ -1,19 +0,0 @@
namespace Syntriax.Engine.Core.Abstract;
/// <summary>
/// Represents a game object with various properties and functionalities.
/// </summary>
public interface IGameObject : IEntity, IHierarchyObject, IAssignableTransform, IAssignableBehaviourController, INameable, IInitialize
{
/// <summary>
/// Event triggered when the <see cref="Update"/> method is called.
/// </summary>
event OnUpdatedEventHandler? OnUpdated;
/// <summary>
/// Updates the game object.
/// </summary>
void Update();
delegate void OnUpdatedEventHandler(IGameObject sender);
}

View 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 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, INameable, IHasBehaviourController, IEnumerable<IHierarchyObject>
{
/// <summary>
/// Event triggered when the <see cref="IHierarchyObject"/> enters the hierarchy.
/// </summary>
event OnEnteredHierarchyEventHandler? OnEnteredHierarchy;
/// <summary>
/// Event triggered when the <see cref="IHierarchyObject"/> exits the hierarchy.
/// </summary>
event OnExitedHierarchyEventHandler? 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 OnParentChangedEventHandler? OnParentChanged;
/// <summary>
/// Event triggered when a new <see cref="IHierarchyObject"/> is added to the <see cref="Children"/>.
/// </summary>
event OnChildrenAddedEventHandler? OnChildrenAdded;
/// <summary>
/// Event triggered when an <see cref="IHierarchyObject"/> is removed from the <see cref="Children"/>.
/// </summary>
event OnChildrenRemovedEventHandler? 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 OnEnteredHierarchyEventHandler(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 OnExitedHierarchyEventHandler(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 OnParentChangedEventHandler(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 OnChildrenAddedEventHandler(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 OnChildrenRemovedEventHandler(IHierarchyObject sender, IHierarchyObject childrenRemoved);
}

View File

@ -3,7 +3,7 @@ namespace Syntriax.Engine.Core.Abstract;
/// <summary>
/// Represents an entity that can be initialized and finalized. This information is useful for objects we know that are not in use and can be either recycled or dropped for garbage collection.
/// </summary>
public interface IInitialize
public interface IInitializable
{
/// <summary>
/// Event triggered when the <see cref="Initialize"/> method is called successfully.
@ -11,7 +11,7 @@ public interface IInitialize
event OnInitializedEventHandler? OnInitialized;
/// <summary>
/// Event triggered when the <see cref="Finalize"/> method is called successfully.
/// Event triggered when the <see cref="IInitializable"/> method is called successfully.
/// </summary>
event OnFinalizedEventHandler? OnFinalized;
@ -32,6 +32,6 @@ public interface IInitialize
/// <returns><see cref="true"/> if finalization is successful, otherwise <see cref="false"/>.</returns>
bool Finalize();
delegate void OnInitializedEventHandler(IInitialize sender);
delegate void OnFinalizedEventHandler(IInitialize sender);
delegate void OnInitializedEventHandler(IInitializable sender);
delegate void OnFinalizedEventHandler(IInitializable sender);
}

View File

@ -3,7 +3,7 @@ namespace Syntriax.Engine.Core.Abstract;
/// <summary>
/// Represents an entity with an enable state that can be toggled.
/// </summary>
public interface IStateEnable : IAssignableEntity
public interface IStateEnable : IHasEntity
{
/// <summary>
/// Event triggered when the <see cref="Enabled"/> state of the <see cref="IStateEnable"/> changes.

View File

@ -1,140 +0,0 @@
using System.Collections.Generic;
namespace Syntriax.Engine.Core.Abstract;
/// <summary>
/// Represents the transformation properties of an object such as position, scale, and rotation.
/// </summary>
public interface ITransform : IAssignableGameObject, IEnumerable<ITransform>
{
/// <summary>
/// Event triggered when the <see cref="Position"/> of the <see cref="ITransform"/> changes.
/// </summary>
event OnPositionChangedEventHandler? OnPositionChanged;
/// <summary>
/// Event triggered when the <see cref="Scale"/> of the <see cref="ITransform"/> changes.
/// </summary>
event OnScaleChangedEventHandler? OnScaleChanged;
/// <summary>
/// Event triggered when the <see cref="Rotation"/> of the <see cref="ITransform"/> changes.
/// </summary>
event OnRotationChangedEventHandler? OnRotationChanged;
/// <summary>
/// Event triggered when the <see cref="Parent"/> of the <see cref="ITransform"/> changes. The second parameter is the old <see cref="ITransform"/>.
/// </summary>
event OnParentChangedEventHandler? OnParentChanged;
/// <summary>
/// Event triggered when a new <see cref="ITransform"/> is added to the <see cref="Children"/>.
/// </summary>
event OnChildrenAddedEventHandler? OnChildrenAdded;
/// <summary>
/// Event triggered when an <see cref="ITransform"/> is removed from the <see cref="Children"/>.
/// </summary>
event OnChildrenRemovedEventHandler? OnChildrenRemoved;
/// <summary>
/// The world position of the <see cref="ITransform"/> in 2D space.
/// </summary>
Vector2D Position { get; set; }
/// <summary>
/// The world scale of the <see cref="ITransform"/>.
/// </summary>
Vector2D Scale { get; set; }
/// <summary>
/// The world rotation of the <see cref="ITransform"/> in degrees.
/// </summary>
float Rotation { get; set; }
/// <summary>
/// The local position of the <see cref="ITransform"/> in 2D space.
/// </summary>
Vector2D LocalPosition { get; set; }
/// <summary>
/// The local scale of the <see cref="ITransform"/>.
/// </summary>
Vector2D LocalScale { get; set; }
/// <summary>
/// The local rotation of the <see cref="ITransform"/> in degrees.
/// </summary>
float LocalRotation { get; set; }
/// <summary>
/// The parent <see cref="ITransform"/> of the <see cref="ITransform"/>.
/// </summary>
ITransform? Parent { get; }
/// <summary>
/// The <see cref="ITransform"/>s that have this <see cref="ITransform"/> as their <see cref="Parent"/>.
/// </summary>
IReadOnlyList<ITransform> Children { get; }
/// <summary>
/// Sets the parent <see cref="ITransform"/> of this <see cref="ITransform"/>.
/// </summary>
/// <param name="transform">The parent <see cref="ITransform"/> to set.</param>
void SetParent(ITransform? transform);
/// <summary>
/// Adds a child <see cref="ITransform"/> to this <see cref="ITransform"/>.
/// </summary>
/// <param name="transform">The child <see cref="ITransform"/> to add.</param>
void AddChild(ITransform transform);
/// <summary>
/// Removes a child <see cref="ITransform"/> from this <see cref="ITransform"/>.
/// </summary>
/// <param name="transform">The child <see cref="ITransform"/> to remove.</param>
void RemoveChild(ITransform transform);
/// <summary>
/// Delegate for the event triggered when the <see cref="ITransform"/>'s rotation changes.
/// </summary>
/// <param name="sender">The <see cref="ITransform"/> that the parent has changed.</param>
/// <param name="previousPosition">The previous <see cref="Position"/> of the <see cref="ITransform"/>.</param>
delegate void OnPositionChangedEventHandler(ITransform sender, Vector2D previousPosition);
/// <summary>
/// Delegate for the event triggered when the <see cref="ITransform"/>'s rotation changes.
/// </summary>
/// <param name="sender">The <see cref="ITransform"/> that the parent has changed.</param>
/// <param name="previousScale">The previous <see cref="Scale"/> of the <see cref="ITransform"/>.</param>
delegate void OnScaleChangedEventHandler(ITransform sender, Vector2D previousScale);
/// <summary>
/// Delegate for the event triggered when the <see cref="ITransform"/>'s rotation changes.
/// </summary>
/// <param name="sender">The <see cref="ITransform"/> that the parent has changed.</param>
/// <param name="previousRotation">The previous <see cref="Rotation"/> of the <see cref="ITransform"/>.</param>
delegate void OnRotationChangedEventHandler(ITransform sender, float previousRotation);
/// <summary>
/// Delegate for the event triggered when the <see cref="ITransform"/>'s parent changes.
/// </summary>
/// <param name="sender">The <see cref="ITransform"/> that the parent has changed.</param>
/// <param name="previousParent">The previous <see cref="ITransform"/> the sender was a child of.</param>
/// <param name="newParent">The new and current <see cref="ITransform"/> the sender is a child of.</param>
delegate void OnParentChangedEventHandler(ITransform sender, ITransform? previousParent, ITransform? newParent);
/// <summary>
/// Delegate for the event triggered when a new <see cref="ITransform"/> added as a child.
/// </summary>
/// <param name="sender">The parent <see cref="ITransform"/> this event is being called from.</param>
/// <param name="childrenAdded">The <see cref="ITransform"/> that got removed as a children of the sender <see cref="ITransform"/>.</param>
delegate void OnChildrenAddedEventHandler(ITransform sender, ITransform childrenAdded);
/// <summary>
/// Delegate for the event triggered when a new <see cref="ITransform"/> removed from being a child.
/// </summary>
/// <param name="sender">The parent <see cref="ITransform"/> this event is being called from.</param>
/// <param name="childrenAdded">The <see cref="ITransform"/> that got removed as a children of the sender <see cref="ITransform"/>.</param>
delegate void OnChildrenRemovedEventHandler(ITransform sender, ITransform childrenRemoved);
}

View File

@ -0,0 +1,73 @@
namespace Syntriax.Engine.Core.Abstract;
/// <summary>
/// Represents the transformation properties of an object such as position, scale, and rotation in 2D space.
/// </summary>
public interface ITransform2D : IBehaviour
{
/// <summary>
/// Event triggered when the <see cref="Position"/> of the <see cref="ITransform2D"/> changes.
/// </summary>
event OnPositionChangedEventHandler? OnPositionChanged;
/// <summary>
/// Event triggered when the <see cref="Scale"/> of the <see cref="ITransform2D"/> changes.
/// </summary>
event OnScaleChangedEventHandler? OnScaleChanged;
/// <summary>
/// Event triggered when the <see cref="Rotation"/> of the <see cref="ITransform"/> changes.
/// </summary>
event OnRotationChangedEventHandler? OnRotationChanged;
/// <summary>
/// The world position of the <see cref="ITransform2D"/> in 2D space.
/// </summary>
Vector2D Position { get; set; }
/// <summary>
/// The world scale of the <see cref="ITransform2D"/>.
/// </summary>
Vector2D Scale { get; set; }
/// <summary>
/// The world rotation of the <see cref="ITransform2D"/> in degrees.
/// </summary>
float Rotation { get; set; }
/// <summary>
/// The local position of the <see cref="ITransform2D"/> in 2D space.
/// </summary>
Vector2D LocalPosition { get; set; }
/// <summary>
/// The local scale of the <see cref="ITransform2D"/>.
/// </summary>
Vector2D LocalScale { get; set; }
/// <summary>
/// The local rotation of the <see cref="ITransform2D"/> in degrees.
/// </summary>
float LocalRotation { get; set; }
/// <summary>
/// Delegate for the event triggered when the <see cref="ITransform2D"/>'s rotation changes.
/// </summary>
/// <param name="sender">The <see cref="ITransform2D"/> that the parent has changed.</param>
/// <param name="previousPosition">The previous <see cref="Position"/> of the <see cref="ITransform2D"/>.</param>
delegate void OnPositionChangedEventHandler(ITransform2D sender, Vector2D previousPosition);
/// <summary>
/// Delegate for the event triggered when the <see cref="ITransform2D"/>'s rotation changes.
/// </summary>
/// <param name="sender">The <see cref="ITransform2D"/> that the parent has changed.</param>
/// <param name="previousScale">The previous <see cref="Scale"/> of the <see cref="ITransform2D"/>.</param>
delegate void OnScaleChangedEventHandler(ITransform2D sender, Vector2D previousScale);
/// <summary>
/// Delegate for the event triggered when the <see cref="ITransform2D"/>'s rotation changes.
/// </summary>
/// <param name="sender">The <see cref="ITransform2D"/> that the parent has changed.</param>
/// <param name="previousRotation">The previous <see cref="Rotation"/> of the <see cref="ITransform2D"/>.</param>
delegate void OnRotationChangedEventHandler(ITransform2D sender, float previousRotation);
}

View File

@ -6,9 +6,8 @@ public abstract class Behaviour : BehaviourBase
{
private bool isInitializedThisFrame = false;
protected IGameManager GameManager => BehaviourController.GameObject.GameManager;
protected IGameObject GameObject => BehaviourController.GameObject;
protected ITransform Transform => BehaviourController.GameObject.Transform;
protected IGameManager GameManager => BehaviourController.HierarchyObject.GameManager;
protected IHierarchyObject HierarchyObject => BehaviourController.HierarchyObject;
public Behaviour()
{
@ -18,43 +17,43 @@ public abstract class Behaviour : BehaviourBase
}
protected virtual void OnUnassign() { }
private void OnUnassign(IAssignable assignable) => OnUnassign();
protected virtual void OnUnassign(IAssignable assignable) => OnUnassign();
protected virtual void OnInitialize() { }
private void OnInitialize(IInitialize _)
protected virtual void OnInitialize(IInitializable _)
{
isInitializedThisFrame = true;
BehaviourController.OnPreUpdate += PreUpdate;
BehaviourController.OnPreDraw += PreDraw;
BehaviourController.OnUpdate += Update;
BehaviourController.GameObject.OnEnteredHierarchy += EnteredHierarchy;
BehaviourController.GameObject.OnExitedHierarchy += ExitedHierarchy;
BehaviourController.HierarchyObject.OnEnteredHierarchy += EnteredHierarchy;
BehaviourController.HierarchyObject.OnExitedHierarchy += ExitedHierarchy;
OnInitialize();
if (GameObject.IsInHierarchy)
EnteredHierarchy(GameObject, GameManager);
if (HierarchyObject.IsInHierarchy)
EnteredHierarchy(HierarchyObject, GameManager);
}
protected virtual void OnFinalize() { }
private void OnFinalize(IInitialize _)
protected virtual void OnFinalize(IInitializable _)
{
BehaviourController.OnPreUpdate -= PreUpdate;
BehaviourController.OnPreDraw -= PreDraw;
BehaviourController.OnUpdate -= Update;
BehaviourController.GameObject.OnEnteredHierarchy -= EnteredHierarchy;
BehaviourController.GameObject.OnExitedHierarchy -= ExitedHierarchy;
BehaviourController.HierarchyObject.OnEnteredHierarchy -= EnteredHierarchy;
BehaviourController.HierarchyObject.OnExitedHierarchy -= ExitedHierarchy;
OnFinalize();
if (GameObject.IsInHierarchy)
ExitedHierarchy(GameObject, GameManager);
if (HierarchyObject.IsInHierarchy)
ExitedHierarchy(HierarchyObject, GameManager);
}
protected virtual void OnPreUpdatePreActiveCheck() { }
protected virtual void OnPreUpdate() { }
private void PreUpdate(IBehaviourController _)
protected virtual void PreUpdate(IBehaviourController _)
{
OnPreUpdatePreActiveCheck();
@ -68,7 +67,7 @@ public abstract class Behaviour : BehaviourBase
}
protected virtual void OnFirstActiveFrame() { }
private void FirstActiveFrame()
protected virtual void FirstActiveFrame()
{
OnFirstActiveFrame();
isInitializedThisFrame = false;
@ -76,7 +75,7 @@ public abstract class Behaviour : BehaviourBase
protected virtual void OnUpdatePreActiveCheck() { }
protected virtual void OnUpdate() { }
private void Update(IBehaviourController _)
protected virtual void Update(IBehaviourController _)
{
OnUpdatePreActiveCheck();
@ -88,7 +87,7 @@ public abstract class Behaviour : BehaviourBase
protected virtual void OnPreDrawPreActiveCheck() { }
protected virtual void OnPreDraw() { }
private void PreDraw(IBehaviourController _)
protected virtual void PreDraw(IBehaviourController _)
{
OnPreDrawPreActiveCheck();
@ -99,8 +98,8 @@ public abstract class Behaviour : BehaviourBase
}
protected virtual void OnEnteredHierarchy(IGameManager gameManager) { }
private void EnteredHierarchy(IHierarchyObject sender, IGameManager gameManager) => OnEnteredHierarchy(gameManager);
protected virtual void EnteredHierarchy(IHierarchyObject sender, IGameManager gameManager) => OnEnteredHierarchy(gameManager);
protected virtual void OnExitedHierarchy(IGameManager gameManager) { }
private void ExitedHierarchy(IHierarchyObject sender, IGameManager gameManager) => OnExitedHierarchy(gameManager);
protected virtual void ExitedHierarchy(IHierarchyObject sender, IGameManager gameManager) => OnExitedHierarchy(gameManager);
}

View File

@ -0,0 +1,28 @@
using Syntriax.Engine.Core.Abstract;
namespace Syntriax.Engine.Core;
public abstract class Behaviour2D : Behaviour, IBehaviour2D
{
public ITransform2D Transform { get; private set; } = null!;
protected sealed override void OnInitialize(IInitializable _)
{
Transform = BehaviourController.GetBehaviourInChildren<ITransform2D>() ?? throw new($"{HierarchyObject.Name} does not contain any {nameof(ITransform2D)}");
base.OnInitialize(_);
}
protected sealed override void OnFinalize(IInitializable _)
{
Transform = null!;
base.OnFinalize(_);
}
protected sealed override void OnUnassign(IAssignable assignable) => base.OnUnassign(assignable);
protected sealed override void PreUpdate(IBehaviourController behaviourController) => base.PreUpdate(behaviourController);
protected sealed override void FirstActiveFrame() => base.FirstActiveFrame();
protected sealed override void Update(IBehaviourController behaviourController) => base.Update(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 ExitedHierarchy(IHierarchyObject sender, IGameManager gameManager) => base.ExitedHierarchy(sender, gameManager);
}

View File

@ -6,7 +6,7 @@ namespace Syntriax.Engine.Core;
[System.Diagnostics.DebuggerDisplay("{GetType().Name, nq}, Priority: {Priority}, Initialized: {Initialized}")]
public abstract class BehaviourBase : BaseEntity, IBehaviour
{
public event IAssignableBehaviourController.OnBehaviourControllerAssignedEventHandler? OnBehaviourControllerAssigned = null;
public event IHasBehaviourController.OnBehaviourControllerAssignedEventHandler? OnBehaviourControllerAssigned = null;
public event IBehaviour.OnPriorityChangedEventHandler? OnPriorityChanged = null;
@ -16,7 +16,7 @@ public abstract class BehaviourBase : BaseEntity, IBehaviour
public IBehaviourController BehaviourController => _behaviourController;
public override bool IsActive => base.IsActive && BehaviourController.GameObject.StateEnable.Enabled;
public override bool IsActive => base.IsActive && BehaviourController.HierarchyObject.StateEnable.Enabled;
public int Priority
{

View File

@ -9,7 +9,7 @@ namespace Syntriax.Engine.Core;
public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
{
public event IAssignable.OnUnassignedEventHandler? OnUnassigned = null;
public event IAssignableGameManager.OnGameManagerAssignedEventHandler? OnGameManagerAssigned = null;
public event IHasGameManager.OnGameManagerAssignedEventHandler? OnGameManagerAssigned = null;
public event IBehaviourCollector<T>.OnCollectedEventHandler? OnCollected = null;
public event IBehaviourCollector<T>.OnRemovedEventHandler? OnRemoved = null;
@ -24,22 +24,22 @@ public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
public BehaviourCollector() { }
public BehaviourCollector(IGameManager gameManager) => Assign(gameManager);
private void OnGameObjectRegistered(IGameManager manager, IGameObject gameObject)
private void OnHierarchyObjectRegistered(IGameManager manager, IHierarchyObject hierarchyObject)
{
gameObject.BehaviourController.OnBehaviourAdded += OnBehaviourAdded;
gameObject.BehaviourController.OnBehaviourRemoved += OnBehaviourRemoved;
hierarchyObject.BehaviourController.OnBehaviourAdded += OnBehaviourAdded;
hierarchyObject.BehaviourController.OnBehaviourRemoved += OnBehaviourRemoved;
foreach (IBehaviour item in gameObject.BehaviourController)
OnBehaviourAdded(gameObject.BehaviourController, item);
foreach (IBehaviour item in hierarchyObject.BehaviourController)
OnBehaviourAdded(hierarchyObject.BehaviourController, item);
}
private void OnGameObjectUnregistered(IGameManager manager, IGameObject gameObject)
private void OnHierarchyObjectUnregistered(IGameManager manager, IHierarchyObject hierarchyObject)
{
gameObject.BehaviourController.OnBehaviourAdded -= OnBehaviourAdded;
gameObject.BehaviourController.OnBehaviourRemoved -= OnBehaviourRemoved;
hierarchyObject.BehaviourController.OnBehaviourAdded -= OnBehaviourAdded;
hierarchyObject.BehaviourController.OnBehaviourRemoved -= OnBehaviourRemoved;
foreach (IBehaviour item in gameObject.BehaviourController)
OnBehaviourRemoved(gameObject.BehaviourController, item);
foreach (IBehaviour item in hierarchyObject.BehaviourController)
OnBehaviourRemoved(hierarchyObject.BehaviourController, item);
}
protected virtual void OnBehaviourAdd(IBehaviour behaviour) { }
@ -71,11 +71,11 @@ public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
if (GameManager is not null)
return false;
foreach (IGameObject gameObject in gameManager.GameObjects)
OnGameObjectRegistered(gameManager, gameObject);
foreach (IHierarchyObject hierarchyObject in gameManager.HierarchyObjects)
OnHierarchyObjectRegistered(gameManager, hierarchyObject);
gameManager.OnGameObjectRegistered += OnGameObjectRegistered;
gameManager.OnGameObjectUnRegistered += OnGameObjectUnregistered;
gameManager.OnHierarchyObjectRegistered += OnHierarchyObjectRegistered;
gameManager.OnHierarchyObjectUnRegistered += OnHierarchyObjectUnregistered;
GameManager = gameManager;
OnGameManagerAssigned?.Invoke(this);
@ -88,11 +88,11 @@ public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
if (GameManager is null)
return false;
foreach (IGameObject gameObject in GameManager.GameObjects)
OnGameObjectUnregistered(GameManager, gameObject);
foreach (IHierarchyObject hierarchyObject in GameManager.HierarchyObjects)
OnHierarchyObjectUnregistered(GameManager, hierarchyObject);
GameManager.OnGameObjectRegistered -= OnGameObjectRegistered;
GameManager.OnGameObjectUnRegistered -= OnGameObjectUnregistered;
GameManager.OnHierarchyObjectRegistered -= OnHierarchyObjectRegistered;
GameManager.OnHierarchyObjectUnRegistered -= OnHierarchyObjectUnregistered;
GameManager = null!;
OnUnassigned?.Invoke(this);

View File

@ -17,19 +17,19 @@ public class BehaviourController : IBehaviourController
public event IBehaviourController.OnBehaviourAddedEventHandler? OnBehaviourAdded = null;
public event IBehaviourController.OnBehaviourRemovedEventHandler? OnBehaviourRemoved = null;
public event IAssignableGameObject.OnGameObjectAssignedEventHandler? OnGameObjectAssigned = null;
public event IHasHierarchyObject.OnHierarchyObjectAssignedEventHandler? OnHierarchyObjectAssigned = null;
public event IInitialize.OnInitializedEventHandler? OnInitialized = null;
public event IInitialize.OnFinalizedEventHandler? OnFinalized = null;
public event IInitializable.OnInitializedEventHandler? OnInitialized = null;
public event IInitializable.OnFinalizedEventHandler? OnFinalized = null;
public event IAssignable.OnUnassignedEventHandler? OnUnassigned = null;
private readonly IList<IBehaviour> behaviours = new List<IBehaviour>(Constants.BEHAVIOURS_SIZE_INITIAL);
private IGameObject _gameObject = null!;
private IHierarchyObject _hierarchyObject = null!;
private bool _initialized = false;
public IGameObject GameObject => _gameObject;
public IHierarchyObject HierarchyObject => _hierarchyObject;
public bool IsInitialized
{
@ -52,7 +52,7 @@ public class BehaviourController : IBehaviourController
InsertBehaviourByPriority(behaviour);
behaviour.Assign(this);
behaviour.Assign(GameObject.StateEnable);
behaviour.Assign(HierarchyObject.StateEnable);
behaviour.Initialize();
behaviour.OnPriorityChanged += OnPriorityChange;
@ -61,7 +61,7 @@ public class BehaviourController : IBehaviourController
}
public T AddBehaviour<T>(params object?[]? args) where T : class, IBehaviour
=> AddBehaviour(new Factory.BehaviourFactory().Instantiate<T>(_gameObject, args));
=> AddBehaviour(new Factory.BehaviourFactory().Instantiate<T>(_hierarchyObject, args));
public T? GetBehaviour<T>()
{
@ -116,7 +116,7 @@ public class BehaviourController : IBehaviourController
public void RemoveBehaviour<T>(T behaviour) where T : class, IBehaviour
{
if (!behaviours.Contains(behaviour))
throw new Exception($"{behaviour.GetType().Name} does not exist in {GameObject.Name}'s {nameof(IBehaviourController)}.");
throw new Exception($"{behaviour.GetType().Name} does not exist in {HierarchyObject.Name}'s {nameof(IBehaviourController)}.");
behaviour.OnPriorityChanged -= OnPriorityChange;
behaviour.Finalize();
@ -124,13 +124,13 @@ public class BehaviourController : IBehaviourController
OnBehaviourRemoved?.Invoke(this, behaviour);
}
public bool Assign(IGameObject gameObject)
public bool Assign(IHierarchyObject hierarchyObject)
{
if (GameObject is not null && GameObject.IsInitialized)
if (HierarchyObject is not null && HierarchyObject.IsInitialized)
return false;
_gameObject = gameObject;
OnGameObjectAssigned?.Invoke(this);
_hierarchyObject = hierarchyObject;
OnHierarchyObjectAssigned?.Invoke(this);
return true;
}
@ -139,7 +139,7 @@ public class BehaviourController : IBehaviourController
if (IsInitialized)
return false;
NotAssignedException.Check(this, _gameObject);
NotAssignedException.Check(this, _hierarchyObject);
foreach (IBehaviour behaviour in behaviours)
behaviour.Initialize();
@ -165,14 +165,14 @@ public class BehaviourController : IBehaviourController
if (IsInitialized)
return false;
_gameObject = null!;
_hierarchyObject = null!;
OnUnassigned?.Invoke(this);
return true;
}
public void Update()
{
if (!GameObject.StateEnable.Enabled)
if (!HierarchyObject.StateEnable.Enabled)
return;
OnPreUpdate?.Invoke(this);
@ -181,14 +181,14 @@ public class BehaviourController : IBehaviourController
public void UpdatePreDraw()
{
if (!GameObject.StateEnable.Enabled)
if (!HierarchyObject.StateEnable.Enabled)
return;
OnPreDraw?.Invoke(this);
}
public BehaviourController() { }
public BehaviourController(IGameObject gameObject) => Assign(gameObject);
public BehaviourController(IHierarchyObject hierarchyObject) => Assign(hierarchyObject);
private void InsertBehaviourByPriority<T>(T behaviour) where T : class, IBehaviour
{

View File

@ -5,7 +5,7 @@ using Syntriax.Engine.Core.Abstract;
namespace Syntriax.Engine.Core;
public class CoroutineManager : HierarchyObjectBase
public class CoroutineManager : HierarchyObject
{
private readonly List<IEnumerator> enumerators = [];

View File

@ -0,0 +1,46 @@
@startuml "Core Engine Relations"
top to bottom direction
skinparam linetype ortho
skinparam nodesep 100
title Core Engine Relations
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.INameable {}
Engine.Core.Abstract.IHierarchyObject --> Engine.Core.Abstract.IBehaviourController: has
Engine.Core.Abstract.IBehaviourController "1" --> "0..*" Engine.Core.Abstract.IBehaviour: has
interface Engine.Core.Abstract.IBehaviourController {}
interface 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.IGameManager {}
Engine.Core.Abstract.IGameManager "1" -r-> "0..*" Engine.Core.Abstract.IHierarchyObject: has
' together {
' interface 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.IHasHierarchyObject 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.IHasGameManager --> Engine.Core.Abstract.IGameManager: has
' ' Engine.Core.Abstract.IHasHierarchyObject --> Engine.Core.Abstract.IHierarchyObject: has
' ' Engine.Core.Abstract.IHasBehaviourController --> Engine.Core.Abstract.IBehaviourController: has
' }
together {
interface Engine.Core.Abstract.ITransform2D {}
interface Engine.Core.Abstract.ICamera2D {}
interface Engine.Core.Abstract.ICoroutineYield {}
interface Engine.Core.Abstract.IStateEnable {}
interface Engine.Core.Abstract.IInitializable {}
interface Engine.Core.Abstract.IBehaviourCollector {}
}
@enduml

View File

@ -8,10 +8,10 @@ public class NotAssignedException : Exception
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) where T1 : IAssignable
public static NotAssignedException From<T1, T2>(T1 to, T2? value)
=> new($"{value?.GetType().FullName ?? "\"null\""} has not been assigned to {to?.GetType().FullName ?? "\"null\""}");
public static void Check<T1, T2>(T1 to, T2? value) where T1 : IAssignable
public static void Check<T1, T2>(T1 to, T2? value)
{
if (value is not null)
return;

View File

@ -2,7 +2,7 @@ namespace Syntriax.Engine.Core.Abstract;
public static class TransformExtensions
{
public static Vector2D TransformVector2D(this ITransform transform, Vector2D vector)
public static Vector2D TransformVector2D(this ITransform2D transform, Vector2D vector)
=> vector.Scale(transform.Scale)
.Rotate(transform.Rotation * Math.DegreeToRadian)
.Add(transform.Position);

View File

@ -57,7 +57,7 @@ public static class BehaviourControllerExtensions
if (behaviourController.GetBehaviour<T>() is T behaviour)
return behaviour;
controller = controller.GameObject.Transform.Parent?.GameObject.BehaviourController;
controller = controller.HierarchyObject.Parent?.BehaviourController;
}
return default;
@ -87,8 +87,8 @@ public static class BehaviourControllerExtensions
if (behaviourController.GetBehaviour<T>() is T localBehaviour)
return localBehaviour;
foreach (ITransform transform in behaviourController.GameObject.Transform)
if (GetBehaviourInChildren<T>(transform.GameObject.BehaviourController) is T behaviour)
foreach (IHierarchyObject child in behaviourController.HierarchyObject)
if (GetBehaviourInChildren<T>(child.BehaviourController) is T behaviour)
return behaviour;
return default;

View File

@ -7,29 +7,29 @@ namespace Syntriax.Engine.Core;
public static class BehaviourExtensions
{
public static T? FindBehaviour<T>(this IEnumerable<IGameObject> gameObjects) where T : class
public static T? FindBehaviour<T>(this IEnumerable<IHierarchyObject> hierarchyObjects) where T : class
{
foreach (IGameObject gameObject in gameObjects)
if (gameObject.BehaviourController.GetBehaviour<T>() is T behaviour)
foreach (IHierarchyObject hierarchyObject in hierarchyObjects)
if (hierarchyObject.BehaviourController.GetBehaviour<T>() is T behaviour)
return behaviour;
return default;
}
public static bool TryFindBehaviour<T>(this IEnumerable<IGameObject> gameObjects, [NotNullWhen(returnValue: true)] out T? behaviour) where T : class
public static bool TryFindBehaviour<T>(this IEnumerable<IHierarchyObject> hierarchyObjects, [NotNullWhen(returnValue: true)] out T? behaviour) where T : class
{
behaviour = FindBehaviour<T>(gameObjects);
behaviour = FindBehaviour<T>(hierarchyObjects);
return behaviour is not null;
}
public static void FindBehaviours<T>(this IEnumerable<IGameObject> gameObjects, List<T> behaviours) where T : class
public static void FindBehaviours<T>(this IEnumerable<IHierarchyObject> hierarchyObjects, List<T> behaviours) where T : class
{
behaviours.Clear();
List<T> cache = [];
foreach (IGameObject gameObject in gameObjects)
foreach (IHierarchyObject hierarchyObject in hierarchyObjects)
{
gameObject.BehaviourController.GetBehaviours(cache);
hierarchyObject.BehaviourController.GetBehaviours(cache);
behaviours.AddRange(cache);
}
}

View File

@ -4,6 +4,6 @@ namespace Syntriax.Engine.Core;
public static class GameManagerExtensions
{
public static IGameObject InstantiateGameObject(this IGameManager gameManager, params object?[]? args)
=> gameManager.InstantiateGameObject<GameObject>(args);
public static IHierarchyObject InstantiateHierarchyObject(this IGameManager gameManager, params object?[]? args)
=> gameManager.InstantiateHierarchyObject<HierarchyObject>(args);
}

View File

@ -1,12 +0,0 @@
using Syntriax.Engine.Core.Abstract;
namespace Syntriax.Engine.Core;
public static class GameObjectExtensions
{
public static IGameObject SetGameObject(this IGameObject gameObject, string name)
{
gameObject.Name = name;
return gameObject;
}
}

View File

@ -7,6 +7,12 @@ 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? FindObject<T>(this IEnumerable<IHierarchyObject> hierarchyObjects) where T : class
{
foreach (IHierarchyObject hierarchyObject in hierarchyObjects)

View File

@ -4,7 +4,7 @@ namespace Syntriax.Engine.Core;
public static class TransformExtensions
{
public static ITransform SetTransform(this ITransform transform,
public static ITransform2D SetTransform(this ITransform2D transform,
Vector2D? position = null, float? rotation = null, Vector2D? scale = null,
Vector2D? localPosition = null, float? localRotation = null, Vector2D? localScale = null)
{

View File

@ -5,16 +5,16 @@ namespace Syntriax.Engine.Core.Factory;
public class BehaviourControllerFactory
{
public IBehaviourController Instantiate(IGameObject gameObject)
=> Instantiate<BehaviourController>(gameObject);
public IBehaviourController Instantiate(IHierarchyObject hierarchyObject)
=> Instantiate<BehaviourController>(hierarchyObject);
public T Instantiate<T>(IGameObject gameObject, params object?[]? args)
public T Instantiate<T>(IHierarchyObject hierarchyObject, params object?[]? args)
where T : class, IBehaviourController
{
T behaviourController = TypeFactory.Get<T>(args);
if (!behaviourController.Assign(gameObject))
throw AssignException.From(behaviourController, gameObject);
if (!behaviourController.Assign(hierarchyObject))
throw AssignException.From(behaviourController, hierarchyObject);
return behaviourController;
}

View File

@ -5,10 +5,10 @@ namespace Syntriax.Engine.Core.Factory;
public class BehaviourFactory
{
public T Instantiate<T>(IGameObject gameObject, params object?[]? args) where T : class, IBehaviour
=> Instantiate<T>(gameObject, stateEnable: null, args);
public T Instantiate<T>(IHierarchyObject hierarchyObject, params object?[]? args) where T : class, IBehaviour
=> Instantiate<T>(hierarchyObject, stateEnable: null, args);
public T Instantiate<T>(IGameObject gameObject, IStateEnable? stateEnable, params object?[]? args)
public T Instantiate<T>(IHierarchyObject hierarchyObject, IStateEnable? stateEnable, params object?[]? args)
where T : class, IBehaviour
{
T behaviour = TypeFactory.Get<T>(args);
@ -17,8 +17,8 @@ public class BehaviourFactory
if (!stateEnable.Assign(behaviour))
throw AssignException.From(stateEnable, behaviour);
if (!behaviour.Assign(gameObject.BehaviourController))
throw AssignException.From(behaviour, gameObject.BehaviourController);
if (!behaviour.Assign(hierarchyObject.BehaviourController))
throw AssignException.From(behaviour, hierarchyObject.BehaviourController);
if (!behaviour.Assign(stateEnable))
throw AssignException.From(behaviour, stateEnable);

View File

@ -1,42 +0,0 @@
using Syntriax.Engine.Core.Abstract;
using Syntriax.Engine.Core.Exceptions;
namespace Syntriax.Engine.Core.Factory;
public class GameObjectFactory
{
public T Instantiate<T>(params object?[]? args) where T : class, IGameObject
=> Instantiate<T>(transform: null, behaviourController: null, stateEnable: null, args);
public T Instantiate<T>(
ITransform? transform = null,
IBehaviourController? behaviourController = null,
IStateEnable? stateEnable = null,
params object?[]? args
)
where T : class, IGameObject
{
T gameObject = TypeFactory.Get<T>(args);
transform ??= TypeFactory.Get<Transform>();
behaviourController ??= TypeFactory.Get<BehaviourController>();
stateEnable ??= TypeFactory.Get<StateEnable>();
if (!transform.Assign(gameObject))
throw AssignException.From(transform, gameObject);
if (!behaviourController.Assign(gameObject))
throw AssignException.From(behaviourController, gameObject);
if (!stateEnable.Assign(gameObject))
throw AssignException.From(stateEnable, gameObject);
if (!gameObject.Assign(transform))
throw AssignException.From(gameObject, transform);
if (!gameObject.Assign(behaviourController))
throw AssignException.From(gameObject, behaviourController);
if (!gameObject.Assign(stateEnable))
throw AssignException.From(gameObject, stateEnable);
return gameObject;
}
}

View File

@ -0,0 +1,35 @@
using Syntriax.Engine.Core.Abstract;
using Syntriax.Engine.Core.Exceptions;
namespace Syntriax.Engine.Core.Factory;
public class HierarchyObjectFactory
{
public T Instantiate<T>(params object?[]? args) where T : class, IHierarchyObject
=> Instantiate<T>(behaviourController: null, stateEnable: null, args);
public 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;
}
}

View File

@ -4,7 +4,7 @@ namespace Syntriax.Engine.Core.Factory;
public class TransformFactory
{
public ITransform Instantiate() => TypeFactory.Get<Transform>();
public T Instantiate<T>(params object?[]? args) where T : class, ITransform
public ITransform2D Instantiate() => TypeFactory.Get<Transform2D>();
public T Instantiate<T>(params object?[]? args) where T : class, ITransform2D
=> TypeFactory.Get<T>(args);
}

View File

@ -7,33 +7,28 @@ using Syntriax.Engine.Core.Factory;
namespace Syntriax.Engine.Core;
[System.Diagnostics.DebuggerDisplay("GameObject Count: {_gameObjects.Count}")]
[System.Diagnostics.DebuggerDisplay("HierarchyObject Count: {_hierarchyObjects.Count}")]
public class GameManager : BaseEntity, IGameManager
{
public event IGameManager.OnUpdateEventHandler? OnUpdate = null;
public event IGameManager.OnPreDawEventHandler? OnPreDraw = null;
public event IGameManager.OnGameObjectRegisteredEventHandler? OnGameObjectRegistered = null;
public event IGameManager.OnGameObjectUnRegisteredEventHandler? OnGameObjectUnRegistered = null;
public event IGameManager.OnHierarchyObjectRegisteredEventHandler? OnHierarchyObjectRegistered = null;
public event IGameManager.OnHierarchyObjectUnRegisteredEventHandler? OnHierarchyObjectUnRegistered = null;
private readonly List<IGameObject> _gameObjects = new(Constants.GAME_OBJECTS_SIZE_INITIAL);
private readonly List<IHierarchyObject> _hierarchyObjects = new(Constants.GAME_OBJECTS_SIZE_INITIAL);
private GameObjectFactory _gameObjectFactory = null!;
private HierarchyObjectFactory _hierarchyObjectFactory = null!;
private GameObjectFactory GameObjectFactory
private HierarchyObjectFactory HierarchyObjectFactory
{
get
{
if (_gameObjectFactory is null)
_gameObjectFactory = new GameObjectFactory();
return _gameObjectFactory;
_hierarchyObjectFactory ??= new HierarchyObjectFactory();
return _hierarchyObjectFactory;
}
}
public IReadOnlyList<IGameObject> GameObjects => _gameObjects;
public IReadOnlyList<IHierarchyObject> HierarchyObjects => _hierarchyObjects;
public override IStateEnable StateEnable
@ -56,25 +51,28 @@ public class GameManager : BaseEntity, IGameManager
if (_hierarchyObjects.Contains(hierarchyObject))
throw new Exception($"{nameof(IHierarchyObject)} named {hierarchyObject.Name} is already registered to the {nameof(GameManager)}.");
if (hierarchyObject is IGameObject gameObject)
Register(gameObject);
else
{
if (!hierarchyObject.Initialize())
throw new Exception($"{nameof(hierarchyObject)} can't be initialized");
hierarchyObject.OnFinalized += OnHierarchyObjectFinalize;
hierarchyObject.OnExitedHierarchy += OnHierarchyObjectExitedHierarchy;
_hierarchyObjects.Add(hierarchyObject);
hierarchyObject.EnterHierarchy(this);
if (!hierarchyObject.Initialize())
throw new Exception($"{hierarchyObject.Name} can't be initialized");
OnHierarchyObjectRegistered?.Invoke(this, hierarchyObject);
}
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 InstantiateGameObject<T>(params object?[]? args) where T : class, IGameObject
public T InstantiateHierarchyObject<T>(params object?[]? args) where T : class, IHierarchyObject
{
T gameObject = GameObjectFactory.Instantiate<T>(args);
Register(gameObject);
return gameObject;
T hierarchyObject = HierarchyObjectFactory.Instantiate<T>(args);
Register(hierarchyObject);
return hierarchyObject;
}
public void Remove(IHierarchyObject hierarchyObject)
@ -82,18 +80,21 @@ public class GameManager : BaseEntity, IGameManager
if (!_hierarchyObjects.Contains(hierarchyObject))
throw new Exception($"{nameof(IHierarchyObject)} named {hierarchyObject.Name} is not registered to the {nameof(GameManager)}.");
if (hierarchyObject is IGameObject gameObject)
Unregister(gameObject);
else
{
_hierarchyObjects.Remove(hierarchyObject);
hierarchyObject.ExitHierarchy();
hierarchyObject.OnFinalized -= OnHierarchyObjectFinalize;
hierarchyObject.OnExitedHierarchy -= OnHierarchyObjectExitedHierarchy;
if (!hierarchyObject.Finalize())
throw new Exception($"{nameof(hierarchyObject)} can't be finalized");
foreach (IHierarchyObject child in hierarchyObject.Children)
Remove(child);
OnHierarchyObjectUnRegistered?.Invoke(this, hierarchyObject);
}
_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()
@ -101,93 +102,45 @@ public class GameManager : BaseEntity, IGameManager
base.InitializeInternal();
NotAssignedException.Check(this, StateEnable);
foreach (IGameObject gameObject in GameObjects)
gameObject.Initialize();
foreach (IHierarchyObject hierarchyObject in HierarchyObjects)
hierarchyObject.Initialize();
}
protected override void FinalizeInternal()
{
base.FinalizeInternal();
for (int i = GameObjects.Count; i >= 0; i--)
GameObjects[i].Finalize();
for (int i = HierarchyObjects.Count; i >= 0; i--)
HierarchyObjects[i].Finalize();
}
public void Update(EngineTime time)
{
Time.SetTime(time);
for (int i = 0; i < GameObjects.Count; i++)
GameObjects[i].BehaviourController.Update();
for (int i = 0; i < HierarchyObjects.Count; i++)
HierarchyObjects[i].BehaviourController.Update();
OnUpdate?.Invoke(this, time);
}
public void PreDraw()
{
for (int i = 0; i < GameObjects.Count; i++)
GameObjects[i].BehaviourController.UpdatePreDraw();
for (int i = 0; i < HierarchyObjects.Count; i++)
HierarchyObjects[i].BehaviourController.UpdatePreDraw();
OnPreDraw?.Invoke(this);
}
/////////////////////////////////////////////////////////////////
private void Register(IGameObject gameObject)
private void OnHierarchyObjectFinalize(IInitializable initializable)
{
if (_gameObjects.Contains(gameObject))
throw new Exception($"{nameof(IGameObject)} named {gameObject.Name} is already registered to the {nameof(GameManager)}.");
gameObject.OnFinalized += OnGameObjectFinalize;
gameObject.OnExitedHierarchy += OnGameObjectExitedHierarchy;
if (!gameObject.Initialize())
throw new Exception($"{nameof(gameObject)} can't be initialized");
foreach (ITransform child in gameObject.Transform.Children)
Register(child.GameObject);
_gameObjects.Add(gameObject);
_hierarchyObjects.Add(gameObject);
if (!gameObject.EnterHierarchy(this))
throw new Exception($"{nameof(gameObject)} can't enter the hierarchy");
OnHierarchyObjectRegistered?.Invoke(this, gameObject);
OnGameObjectRegistered?.Invoke(this, gameObject);
if (initializable is IHierarchyObject hierarchyObject)
Remove(hierarchyObject);
}
private void Unregister(IGameObject gameObject)
private void OnHierarchyObjectExitedHierarchy(IHierarchyObject sender, IGameManager gameManager)
{
if (!_gameObjects.Contains(gameObject))
throw new Exception($"{nameof(IGameObject)} named {gameObject.Name} is not registered to the {nameof(GameManager)}.");
gameObject.OnFinalized -= OnGameObjectFinalize;
gameObject.OnExitedHierarchy -= OnGameObjectExitedHierarchy;
foreach (ITransform child in gameObject.Transform.Children)
Unregister(child.GameObject);
_gameObjects.Remove(gameObject);
_hierarchyObjects.Remove(gameObject);
if (!gameObject.ExitHierarchy())
throw new Exception($"{nameof(gameObject)} can't exit the hierarchy");
if (!gameObject.Finalize())
throw new Exception($"{nameof(gameObject)} can't be finalized");
OnHierarchyObjectUnRegistered?.Invoke(this, gameObject);
OnGameObjectUnRegistered?.Invoke(this, gameObject);
}
private void OnGameObjectFinalize(IInitialize initialize)
{
if (initialize is IGameObject gameObject)
Unregister(gameObject);
}
private void OnGameObjectExitedHierarchy(IHierarchyObject sender, IGameManager gameManager)
{
if (sender is IGameObject gameObject)
Unregister(gameObject);
if (sender is IHierarchyObject hierarchyObject)
Remove(hierarchyObject);
}
}

View File

@ -1,151 +0,0 @@
using Syntriax.Engine.Core.Abstract;
using Syntriax.Engine.Core.Exceptions;
namespace Syntriax.Engine.Core;
[System.Diagnostics.DebuggerDisplay("Name: {Name}, Initialized: {Initialized}")]
public class GameObject : BaseEntity, IGameObject
{
public event IHierarchyObject.OnEnteredHierarchyEventHandler? OnEnteredHierarchy = null;
public event IHierarchyObject.OnExitedHierarchyEventHandler? OnExitedHierarchy = null;
public event IAssignableTransform.OnTransformAssignedEventHandler? OnTransformAssigned = null;
public event IAssignableBehaviourController.OnBehaviourControllerAssignedEventHandler? OnBehaviourControllerAssigned = null;
public event INameable.OnNameChangedEventHandler? OnNameChanged = null;
public event IGameObject.OnUpdatedEventHandler? OnUpdated = null;
private ITransform _transform = null!;
private IBehaviourController _behaviourController = null!;
private IGameManager _gameManager = null!;
private string _name = nameof(GameObject);
public ITransform Transform => _transform;
public IBehaviourController BehaviourController => _behaviourController;
public IGameManager GameManager => _gameManager;
public bool IsInHierarchy => GameManager is not null;
public string Name
{
get => _name;
set
{
if (value == _name) return;
string previousName = _name;
_name = value;
OnNameChanged?.Invoke(this, previousName);
}
}
protected override void InitializeInternal()
{
base.InitializeInternal();
NotAssignedException.Check(this, _transform);
NotAssignedException.Check(this, _behaviourController);
if (!_behaviourController.Initialize())
throw new System.Exception($"Failed to Initialize {BehaviourController.GetType().Name} on {Transform.GameObject.Name}");
}
public void Update()
{
if (!StateEnable.Enabled)
return;
OnUpdated?.Invoke(this);
}
protected override void FinalizeInternal()
{
base.FinalizeInternal();
if (!_behaviourController.Finalize())
throw new System.Exception($"Failed to Finalize {BehaviourController.GetType().Name} on {Transform.GameObject.Name}");
}
public bool Assign(ITransform transform)
{
if (IsInitialized)
return false;
_transform = transform;
OnTransformAssigned?.Invoke(this);
transform.OnParentChanged += OnParentChangedInternal;
OnParentChangedInternal(transform, null, transform.Parent);
return true;
}
public bool Assign(IBehaviourController behaviourController)
{
if (IsInitialized)
return false;
_behaviourController = behaviourController;
OnBehaviourControllerAssigned?.Invoke(this);
return true;
}
protected override void UnassignInternal()
{
base.UnassignInternal();
_transform.OnParentChanged -= OnParentChangedInternal;
OnParentChangedInternal(_transform, _transform.Parent, null);
_transform = null!;
_behaviourController = null!;
_gameManager = null!;
}
public GameObject() { OnBehaviourControllerAssigned += ConnectBehaviourController; }
private void ConnectBehaviourController(IAssignableBehaviourController controller)
{
controller.BehaviourController.OnBehaviourAdded += OnBehaviourAdded;
controller.BehaviourController.OnBehaviourRemoved += OnBehaviourRemoved;
}
private void OnBehaviourRemoved(IBehaviourController _, IBehaviour behaviour) { if (IsInitialized) behaviour.Finalize(); }
private void OnBehaviourAdded(IBehaviourController _, IBehaviour behaviour) { if (!IsInitialized) behaviour.Initialize(); }
private void OnParentChangedInternal(ITransform sender, ITransform? previousParent, ITransform? newParent)
{
if (previousParent is not null)
{
previousParent.OnParentChanged -= OnParentChangedInternal;
previousParent.GameObject.OnEnteredHierarchy -= EnterHierarchyInternal;
previousParent.GameObject.OnExitedHierarchy -= ExitHierarchyInternal;
}
if (newParent is not null)
{
newParent.OnParentChanged += OnParentChangedInternal;
newParent.GameObject.OnEnteredHierarchy += EnterHierarchyInternal;
newParent.GameObject.OnExitedHierarchy += ExitHierarchyInternal;
}
}
private void EnterHierarchyInternal(IHierarchyObject sender, IGameManager gameManager) => ((IHierarchyObject)this).EnterHierarchy(gameManager);
private void ExitHierarchyInternal(IHierarchyObject sender, IGameManager gameManager) => ((IHierarchyObject)this).ExitHierarchy();
bool IHierarchyObject.EnterHierarchy(IGameManager gameManager)
{
if (IsInHierarchy)
return false;
_gameManager = gameManager;
OnEnteredHierarchy?.Invoke(this, gameManager);
return true;
}
bool IHierarchyObject.ExitHierarchy()
{
if (!IsInHierarchy || _gameManager is not IGameManager gameManager)
return false;
_gameManager = null!;
OnExitedHierarchy?.Invoke(this, gameManager);
return true;
}
}

View File

@ -0,0 +1,136 @@
using System.Collections;
using System.Collections.Generic;
using Syntriax.Engine.Core.Abstract;
namespace Syntriax.Engine.Core;
[System.Diagnostics.DebuggerDisplay("Name: {Name}, Initialized: {Initialized}")]
public class HierarchyObject : BaseEntity, IHierarchyObject
{
public event IHierarchyObject.OnEnteredHierarchyEventHandler? OnEnteredHierarchy = null;
public event IHierarchyObject.OnExitedHierarchyEventHandler? OnExitedHierarchy = null;
public event IHierarchyObject.OnParentChangedEventHandler? OnParentChanged = null;
public event IHierarchyObject.OnChildrenAddedEventHandler? OnChildrenAdded = null;
public event IHierarchyObject.OnChildrenRemovedEventHandler? OnChildrenRemoved = null;
public event IHasBehaviourController.OnBehaviourControllerAssignedEventHandler? OnBehaviourControllerAssigned = null;
public event INameable.OnNameChangedEventHandler? OnNameChanged = null;
private string _name = nameof(HierarchyObject);
private IGameManager _gameManager = null!;
private IBehaviourController _behaviourController = null!;
private readonly List<IHierarchyObject> _children = [];
public IHierarchyObject? Parent { get; private set; } = null;
public IReadOnlyList<IHierarchyObject> Children => _children;
public IGameManager GameManager => _gameManager;
public bool IsInHierarchy => _gameManager is not null;
public string Name
{
get => _name;
set
{
if (value == _name) return;
string previousName = _name;
_name = value;
OnNameChanged?.Invoke(this, previousName);
}
}
public IBehaviourController BehaviourController => _behaviourController;
protected virtual void OnEnteringHierarchy(IGameManager gameManager) { }
bool IHierarchyObject.EnterHierarchy(IGameManager gameManager)
{
if (IsInHierarchy)
return false;
_gameManager = gameManager;
OnEnteringHierarchy(gameManager);
OnEnteredHierarchy?.Invoke(this, gameManager);
return true;
}
protected virtual void OnExitingHierarchy(IGameManager gameManager) { }
bool IHierarchyObject.ExitHierarchy()
{
if (!IsInHierarchy || _gameManager is not IGameManager gameManager)
return false;
_gameManager = null!;
OnExitingHierarchy(gameManager);
OnExitedHierarchy?.Invoke(this, gameManager);
return true;
}
public void SetParent(IHierarchyObject? parent)
{
if (parent == this || Parent == parent)
return;
IHierarchyObject? previousParent = Parent;
if (previousParent is not null)
{
previousParent.RemoveChild(this);
previousParent.OnParentChanged -= NotifyChildrenOnParentChange;
}
Parent = parent;
if (parent is not null)
{
parent.AddChild(this);
parent.OnParentChanged += NotifyChildrenOnParentChange;
}
OnParentChanged?.Invoke(this, previousParent, parent);
}
public void AddChild(IHierarchyObject parent)
{
if (_children.Contains(parent))
return;
_children.Add(parent);
parent.SetParent(this);
OnChildrenAdded?.Invoke(this, parent);
}
public void RemoveChild(IHierarchyObject parent)
{
if (!_children.Remove(parent))
return;
parent.SetParent(null);
OnChildrenRemoved?.Invoke(this, parent);
}
private void NotifyChildrenOnParentChange(IHierarchyObject sender, IHierarchyObject? previousParent, IHierarchyObject? newParent)
{
// TODO No idea how logical this is to propagate this to the children the way I'm doing right now.
// I was originally gonna just call `child.OnParentChanged?.Invoke(child, child.parentTransform);` but seems an unnecessary call too?
foreach (IHierarchyObject child in Children) // TODO CHECK ERRORS
child.SetParent(this);
}
public bool Assign(IBehaviourController behaviourController)
{
if (IsInitialized)
return false;
_behaviourController = behaviourController;
OnBehaviourControllerAssigned?.Invoke(this);
return true;
}
protected override void InitializeInternal()
{
base.InitializeInternal();
_behaviourController ??= new Factory.BehaviourControllerFactory().Instantiate(this);
}
public IEnumerator<IHierarchyObject> GetEnumerator() => _children.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => _children.GetEnumerator();
}

View File

@ -1,142 +0,0 @@
using Syntriax.Engine.Core.Abstract;
namespace Syntriax.Engine.Core;
public abstract class HierarchyObjectBase : IHierarchyObject
{
public event IHierarchyObject.OnEnteredHierarchyEventHandler? OnEnteredHierarchy = null;
public event IHierarchyObject.OnExitedHierarchyEventHandler? OnExitedHierarchy = null;
public event IEntity.OnIdChangedEventHandler? OnIdChanged = null;
public event IInitialize.OnInitializedEventHandler? OnInitialized = null;
public event IInitialize.OnFinalizedEventHandler? OnFinalized = null;
public event IAssignableStateEnable.OnStateEnableAssignedEventHandler? OnStateEnableAssigned = null;
public event IAssignable.OnUnassignedEventHandler? OnUnassigned = null;
public event INameable.OnNameChangedEventHandler? OnNameChanged = null;
private string _id = string.Empty;
private string _name = nameof(HierarchyObjectBase);
private bool _initialized = false;
private IStateEnable _stateEnable = null!;
private IGameManager _gameManager = null!;
public IGameManager GameManager => _gameManager;
public bool IsInHierarchy => _gameManager is not null;
public bool IsInitialized
{
get => _initialized;
private set
{
if (value == _initialized)
return;
_initialized = value;
if (value)
OnInitialized?.Invoke(this);
else
OnFinalized?.Invoke(this);
}
}
public virtual IStateEnable StateEnable => _stateEnable;
public string Name
{
get => _name;
set
{
if (value == _name) return;
string previousName = _name;
_name = value;
OnNameChanged?.Invoke(this, previousName);
}
}
public string Id
{
get => _id;
set
{
if (value == _id)
return;
string previousId = _id;
_id = value;
OnIdChanged?.Invoke(this, previousId);
}
}
public bool Assign(IStateEnable stateEnable)
{
if (IsInitialized)
return false;
_stateEnable = stateEnable;
_stateEnable.Assign(this);
OnStateEnableAssigned?.Invoke(this);
return true;
}
protected virtual void UnassignInternal() { }
public bool Unassign()
{
if (IsInitialized)
return false;
UnassignInternal();
OnUnassigned?.Invoke(this);
return true;
}
protected virtual void InitializeInternal() { }
public bool Initialize()
{
if (IsInitialized)
return false;
InitializeInternal();
IsInitialized = true;
return true;
}
protected virtual void FinalizeInternal() { }
public bool Finalize()
{
if (!IsInitialized)
return false;
FinalizeInternal();
IsInitialized = false;
return true;
}
protected virtual void OnEnteringHierarchy(IGameManager gameManager) { }
bool IHierarchyObject.EnterHierarchy(IGameManager gameManager)
{
if (IsInHierarchy)
return false;
_gameManager = gameManager;
OnEnteringHierarchy(gameManager);
OnEnteredHierarchy?.Invoke(this, gameManager);
return true;
}
protected virtual void OnExitingHierarchy(IGameManager gameManager) { }
bool IHierarchyObject.ExitHierarchy()
{
if (!IsInHierarchy || _gameManager is not IGameManager gameManager)
return false;
_gameManager = null!;
OnExitingHierarchy(gameManager);
OnExitedHierarchy?.Invoke(this, gameManager);
return true;
}
}

View File

@ -64,9 +64,9 @@ public readonly struct Circle(Vector2D center, float radius)
}
/// <summary>
/// Transforms the <see cref="Circle"/> by the specified <see cref="ITransform"/>.
/// Transforms the <see cref="Circle"/> by the specified <see cref="ITransform2D"/>.
/// </summary>
public static Circle TransformCircle(ITransform transform, Circle circle)
public static Circle TransformCircle(ITransform2D transform, Circle circle)
=> new(transform.TransformVector2D(circle.Center), circle.Radius * (transform.Scale.Magnitude / Vector2D.One.Magnitude));
/// <summary>
@ -97,8 +97,8 @@ public static class CircleExtensions
/// <inheritdoc cref="Circle.Project(Circle, Vector2D)" />
public static Projection1D ToProjection(this Circle circle, Vector2D projectionVector) => Circle.Project(circle, projectionVector);
/// <inheritdoc cref="Circle.TransformCircle(ITransform, Circle)" />
public static Circle TransformCircle(this ITransform transform, Circle circle) => Circle.TransformCircle(transform, circle);
/// <inheritdoc cref="Circle.TransformCircle(ITransform2D, Circle)" />
public static Circle TransformCircle(this ITransform2D transform, Circle circle) => Circle.TransformCircle(transform, circle);
/// <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);

View File

@ -166,7 +166,7 @@ public readonly struct Shape2D(List<Vector2D> vertices) : IEnumerable<Vector2D>
/// <param name="shape">The shape to transform.</param>
/// <param name="transform">The transform to apply.</param>
/// <returns>The transformed shape.</returns>
public static Shape2D TransformShape(Shape2D shape, ITransform transform)
public static Shape2D TransformShape(Shape2D shape, ITransform2D transform)
{
List<Vector2D> vertices = new(shape.Vertices.Count);
@ -183,7 +183,7 @@ public readonly struct Shape2D(List<Vector2D> vertices) : IEnumerable<Vector2D>
/// <param name="from">The shape to transform.</param>
/// <param name="transform">The transform to apply.</param>
/// <param name="to">The transformed shape.</param>
public static void TransformShape(Shape2D from, ITransform transform, ref Shape2D to)
public static void TransformShape(Shape2D from, ITransform2D transform, ref Shape2D to)
{
to._verticesList.Clear();
@ -241,11 +241,11 @@ public static class Shape2DExtensions
/// <inheritdoc cref="Shape2D.Project(Shape2D, Vector2D)" />
public static Projection1D ToProjection(this Shape2D shape, Vector2D projectionVector) => Shape2D.Project(shape, projectionVector);
/// <inheritdoc cref="Shape2D.TransformShape(Shape2D, ITransform)" />
public static Shape2D TransformShape(this ITransform transform, Shape2D shape) => Shape2D.TransformShape(shape, transform);
/// <inheritdoc cref="Shape2D.TransformShape(Shape2D, ITransform2D)" />
public static Shape2D TransformShape(this ITransform2D transform, Shape2D shape) => Shape2D.TransformShape(shape, transform);
/// <inheritdoc cref="Shape2D.TransformShape(Shape2D, ITransform, Shape2D)" />
public static void TransformShape(this ITransform transform, Shape2D from, ref Shape2D to) => Shape2D.TransformShape(from, transform, ref to);
/// <inheritdoc cref="Shape2D.TransformShape(Shape2D, ITransform2D, Shape2D)" />
public static void TransformShape(this ITransform2D transform, Shape2D from, ref Shape2D to) => Shape2D.TransformShape(from, transform, ref to);
/// <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);

View File

@ -5,7 +5,7 @@ namespace Syntriax.Engine.Core;
public class StateEnable : IStateEnable
{
public event IAssignable.OnUnassignedEventHandler? OnUnassigned = null;
public event IAssignableEntity.OnEntityAssignedEventHandler? OnEntityAssigned = null;
public event IHasEntity.OnEntityAssignedEventHandler? OnEntityAssigned = null;
public event IStateEnable.OnNameChangedEventHandler? OnEnabledChanged = null;
private bool _enabled = true;

View File

@ -1,297 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using Syntriax.Engine.Core.Abstract;
namespace Syntriax.Engine.Core;
[System.Diagnostics.DebuggerDisplay("Name: {GameObject.Name, nq} Position: {Position.ToString(), nq}, Scale: {Scale.ToString(), nq}, Rotation: {Rotation}")]
public class Transform : ITransform
{
public event IAssignableGameObject.OnGameObjectAssignedEventHandler? OnGameObjectAssigned = null;
public event IAssignable.OnUnassignedEventHandler? OnUnassigned = null;
public event ITransform.OnPositionChangedEventHandler? OnPositionChanged = null;
public event ITransform.OnScaleChangedEventHandler? OnScaleChanged = null;
public event ITransform.OnRotationChangedEventHandler? OnRotationChanged = null;
public event ITransform.OnParentChangedEventHandler? OnParentChanged = null;
public event ITransform.OnChildrenAddedEventHandler? OnChildrenAdded = null;
public event ITransform.OnChildrenRemovedEventHandler? OnChildrenRemoved = null;
private Vector2D _position = Vector2D.Zero;
private Vector2D _scale = Vector2D.One;
private float _rotation = 0f;
private Vector2D _localPosition = Vector2D.Zero;
private Vector2D _localScale = Vector2D.One;
private float _localRotation = 0f;
private readonly List<ITransform> _children = [];
public IGameObject GameObject { get; private set; } = null!;
public ITransform? Parent { get; private set; } = null;
public IReadOnlyList<ITransform> Children => _children;
public Vector2D Position
{
get => _position;
set
{
if (value == _position)
return;
Vector2D previousPosition = _position;
_position = value;
UpdateLocalPosition();
OnPositionChanged?.Invoke(this, _position);
}
}
public Vector2D Scale
{
get => _localScale.Scale(Parent?.Scale ?? Vector2D.One);
set
{
if (value == _scale)
return;
Vector2D previousScale = _scale;
_scale = value;
UpdateLocalScale();
OnScaleChanged?.Invoke(this, previousScale);
}
}
public float Rotation
{
get => _localRotation + (Parent?.Rotation ?? 0f);
set
{
if (value == _rotation)
return;
float previousRotation = _rotation;
_rotation = value;
UpdateLocalPosition();
OnRotationChanged?.Invoke(this, previousRotation);
}
}
public Vector2D LocalPosition
{
get => _localPosition;
set
{
if (value == _localPosition)
return;
Vector2D previousPosition = _position;
_localPosition = value;
UpdatePosition();
OnPositionChanged?.Invoke(this, previousPosition);
}
}
public Vector2D LocalScale
{
get => _localScale;
set
{
if (value == _localScale)
return;
Vector2D previousScale = _scale;
_localScale = value;
UpdateScale();
OnScaleChanged?.Invoke(this, previousScale);
}
}
public float LocalRotation
{
get => _localRotation;
set
{
if (value == _localRotation)
return;
float previousRotation = _rotation;
_localRotation = value;
UpdateRotation();
OnRotationChanged?.Invoke(this, previousRotation);
}
}
public void SetParent(ITransform? transform)
{
if (transform == this || Parent == transform)
return;
ITransform? previousParent = Parent;
if (previousParent is not null)
{
previousParent.RemoveChild(this);
previousParent.OnPositionChanged -= RecalculatePosition;
previousParent.OnScaleChanged -= RecalculateScale;
previousParent.OnRotationChanged -= RecalculateRotation;
previousParent.OnParentChanged -= NotifyChildrenOnParentChange;
}
Parent = transform;
if (transform is not null)
{
transform.AddChild(this);
transform.OnPositionChanged += RecalculatePosition;
transform.OnScaleChanged += RecalculateScale;
transform.OnRotationChanged += RecalculateRotation;
transform.OnParentChanged += NotifyChildrenOnParentChange;
}
UpdateLocalPosition();
UpdateLocalScale();
UpdateLocalRotation();
OnParentChanged?.Invoke(this, previousParent, transform);
}
public void AddChild(ITransform transform)
{
if (_children.Contains(transform))
return;
_children.Add(transform);
transform.SetParent(this);
OnChildrenAdded?.Invoke(this, transform);
}
public void RemoveChild(ITransform transform)
{
if (!_children.Remove(transform))
return;
transform.SetParent(null);
OnChildrenRemoved?.Invoke(this, transform);
}
public IEnumerator<ITransform> GetEnumerator() => _children.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => _children.GetEnumerator();
private void NotifyChildrenOnParentChange(ITransform transform, ITransform? previousParent, ITransform? newParent)
{
// TODO No idea how logical this is to propagate this to the children the way I'm doing right now.
// I was originally gonna just call `child.OnParentChanged?.Invoke(child, child.Parent);` but seems an unnecessary call too?
foreach (ITransform child in Children) // TODO CHECK ERRORS
child.SetParent(this);
}
private void RecalculatePosition(ITransform _, Vector2D previousPosition)
{
if (Parent is null)
return;
UpdatePosition();
OnPositionChanged?.Invoke(this, previousPosition);
}
private void RecalculateScale(ITransform _, Vector2D previousScale)
{
if (Parent is null)
return;
UpdateScale();
OnScaleChanged?.Invoke(this, previousScale);
}
private void RecalculateRotation(ITransform _, float previousRotation)
{
if (Parent is null)
return;
// UpdatePosition();
UpdateRotation();
// OnPositionChanged?.Invoke(this, previousPosition);
OnRotationChanged?.Invoke(this, previousRotation);
}
private void UpdateLocalPosition()
{
if (Parent is null)
_localPosition = Position;
else
_localPosition = Parent.Position.FromTo(Position).Scale(Parent.Scale);
}
private void UpdateLocalScale()
{
if (Parent is null)
_localScale = Scale;
else
_localScale = Scale.Scale(new(1f / Parent.Scale.X, 1f / Parent.Scale.Y));
}
private void UpdateLocalRotation()
{
if (Parent is null)
_localRotation = Rotation;
else
_localRotation = Rotation - Parent.Rotation;
}
private void UpdatePosition()
{
if (Parent is null)
_position = LocalPosition.Rotate(0f * Math.DegreeToRadian);
else
_position = Parent.Position + LocalPosition.Scale(new(Parent.Scale.X, Parent.Scale.Y)).Rotate(Parent.Rotation * Math.DegreeToRadian);
}
private void UpdateScale()
{
if (Parent is null)
_scale = LocalScale;
else
_scale = Vector2D.Scale(Parent.Scale, LocalScale);
}
private void UpdateRotation()
{
if (Parent is null)
_rotation = LocalRotation;
else
_rotation = Parent.Rotation + LocalRotation;
}
public bool Assign(IGameObject gameObject)
{
if (GameObject is not null && GameObject.IsInitialized)
return false;
GameObject = gameObject;
OnGameObjectAssigned?.Invoke(this);
return true;
}
public bool Unassign()
{
if (GameObject is not null && GameObject.IsInitialized)
return false;
GameObject = null!;
OnUnassigned?.Invoke(this);
return true;
}
}

255
Engine.Core/Transform2D.cs Normal file
View File

@ -0,0 +1,255 @@
using Syntriax.Engine.Core.Abstract;
namespace Syntriax.Engine.Core;
[System.Diagnostics.DebuggerDisplay("Name: {HierarchyObject.Name, nq} Position: {Position.ToString(), nq}, Scale: {Scale.ToString(), nq}, Rotation: {Rotation}")]
public class Transform2D : Behaviour, ITransform2D
{
public event ITransform2D.OnPositionChangedEventHandler? OnPositionChanged = null;
public event ITransform2D.OnScaleChangedEventHandler? OnScaleChanged = null;
public event ITransform2D.OnRotationChangedEventHandler? OnRotationChanged = null;
private Vector2D _position = Vector2D.Zero;
private Vector2D _scale = Vector2D.One;
private float _rotation = 0f;
private Vector2D _localPosition = Vector2D.Zero;
private Vector2D _localScale = Vector2D.One;
private float _localRotation = 0f;
private ITransform2D? parentTransform = null;
public Vector2D Position
{
get => _position;
set
{
if (value == _position)
return;
Vector2D previousPosition = _position;
_position = value;
UpdateLocalPosition();
OnPositionChanged?.Invoke(this, _position);
}
}
public Vector2D Scale
{
get => _scale;
set
{
if (value == _scale)
return;
Vector2D previousScale = _scale;
_scale = value;
UpdateLocalScale();
OnScaleChanged?.Invoke(this, previousScale);
}
}
public float Rotation
{
get => _rotation;
set
{
if (value == _rotation)
return;
float previousRotation = _rotation;
_rotation = value;
UpdateLocalRotation();
OnRotationChanged?.Invoke(this, previousRotation);
}
}
public Vector2D LocalPosition
{
get => _localPosition;
set
{
if (value == _localPosition)
return;
Vector2D previousPosition = _position;
_localPosition = value;
UpdatePosition();
OnPositionChanged?.Invoke(this, previousPosition);
}
}
public Vector2D LocalScale
{
get => _localScale;
set
{
if (value == _localScale)
return;
Vector2D previousScale = _scale;
_localScale = value;
UpdateScale();
OnScaleChanged?.Invoke(this, previousScale);
}
}
public float LocalRotation
{
get => _localRotation;
set
{
if (value == _localRotation)
return;
float previousRotation = _rotation;
_localRotation = value;
UpdateRotation();
OnRotationChanged?.Invoke(this, previousRotation);
}
}
private void RecalculatePosition(ITransform2D _, Vector2D previousPosition)
{
if (parentTransform is null)
return;
float previousRotation = Rotation;
UpdatePosition();
UpdateRotation();
OnPositionChanged?.Invoke(this, previousPosition);
OnRotationChanged?.Invoke(this, previousRotation);
}
private void RecalculateScale(ITransform2D _, Vector2D previousScale)
{
if (parentTransform is null)
return;
UpdateScale();
OnScaleChanged?.Invoke(this, previousScale);
}
private void RecalculateRotation(ITransform2D _, float previousRotation)
{
if (parentTransform is null)
return;
Vector2D previousPosition = Position;
UpdatePosition();
UpdateRotation();
OnPositionChanged?.Invoke(this, previousPosition);
OnRotationChanged?.Invoke(this, previousRotation);
}
private void UpdateLocalPosition()
{
if (parentTransform is null)
_localPosition = Position;
else
_localPosition = parentTransform.Position.FromTo(Position).Scale(parentTransform.Scale);
}
private void UpdateLocalScale()
{
if (parentTransform is null)
_localScale = Scale;
else
_localScale = Scale.Scale(new(1f / parentTransform.Scale.X, 1f / parentTransform.Scale.Y));
}
private void UpdateLocalRotation()
{
if (parentTransform is null)
_localRotation = Rotation;
else
_localRotation = Rotation - parentTransform.Rotation;
}
private void UpdatePosition()
{
if (parentTransform is null)
_position = LocalPosition.Rotate(0f * Math.DegreeToRadian);
else
_position = parentTransform.Position + LocalPosition.Scale(new(parentTransform.Scale.X, parentTransform.Scale.Y)).Rotate(parentTransform.Rotation * Math.DegreeToRadian);
}
private void UpdateScale()
{
if (parentTransform is null)
_scale = LocalScale;
else
_scale = (parentTransform?.Scale ?? Vector2D.One).Scale(_localScale);
}
private void UpdateRotation()
{
if (parentTransform is null)
_rotation = LocalRotation;
else
_rotation = parentTransform.Rotation + LocalRotation;
}
protected override void InitializeInternal()
{
UpdateParent(BehaviourController.HierarchyObject.Parent);
BehaviourController.HierarchyObject.OnParentChanged += OnParentChanged;
}
protected override void FinalizeInternal()
{
BehaviourController.HierarchyObject.OnParentChanged -= OnParentChanged;
}
private void UpdateParent(IHierarchyObject? parent)
{
ITransform2D? previousParent = parentTransform;
if (previousParent is not null)
{
previousParent.BehaviourController.HierarchyObject.RemoveChild(HierarchyObject);
previousParent.OnPositionChanged -= RecalculatePosition;
previousParent.OnScaleChanged -= RecalculateScale;
previousParent.OnRotationChanged -= RecalculateRotation;
previousParent.BehaviourController.HierarchyObject.OnParentChanged -= OnParentChanged;
}
parentTransform = parent?.BehaviourController.GetBehaviour<ITransform2D>();
if (parentTransform is not null)
{
parentTransform.BehaviourController.HierarchyObject.AddChild(HierarchyObject);
parentTransform.OnPositionChanged += RecalculatePosition;
parentTransform.OnScaleChanged += RecalculateScale;
parentTransform.OnRotationChanged += RecalculateRotation;
parentTransform.BehaviourController.HierarchyObject.OnParentChanged += OnParentChanged;
UpdatePosition();
UpdateScale();
UpdateRotation();
}
UpdateLocalPosition();
UpdateLocalScale();
UpdateLocalRotation();
OnPositionChanged?.Invoke(this, Position);
OnScaleChanged?.Invoke(this, Scale);
OnRotationChanged?.Invoke(this, Rotation);
}
private void OnParentChanged(IHierarchyObject sender, IHierarchyObject? previousParent, IHierarchyObject? newParent)
{
UpdateParent(newParent);
}
}

View File

@ -2,7 +2,7 @@ using Syntriax.Engine.Core.Abstract;
namespace Syntriax.Engine.Input;
public interface IButtonInputs<T> : IAssignableStateEnable
public interface IButtonInputs<T> : IHasStateEnable
{
event ButtonCallbackEventHandler? OnAnyButtonPressed;
event ButtonCallbackEventHandler? OnAnyButtonReleased;

View File

@ -5,7 +5,7 @@ namespace Syntriax.Engine.Physics2D.Abstract;
/// <summary>
/// Represents a 2D collider.
/// </summary>
public interface ICollider2D : IBehaviour, IAssignableTransform
public interface ICollider2D : IBehaviour
{
/// <summary>
/// Event triggered when a collision is detected.
@ -22,6 +22,9 @@ public interface ICollider2D : IBehaviour, IAssignableTransform
/// </summary>
event OnTriggeredEventHandler? OnTriggered;
/// <inheritdoc cref="ITransform2D" />
ITransform2D Transform { get; }
/// <summary>
/// The <see cref="IRigidBody2D"/> associated with the <see cref="ICollider2D"/>.
/// </summary>

View File

@ -6,7 +6,7 @@ namespace Syntriax.Engine.Physics2D.Abstract;
/// <summary>
/// Represents a 2D rigid body in the engine.
/// </summary>
public interface IRigidBody2D : IBehaviour, IAssignableTransform
public interface IRigidBody2D : IBehaviour2D
{
/// <summary>
/// The physics material of the <see cref="IRigidBody2D"/>.

View File

@ -4,7 +4,7 @@ using Syntriax.Engine.Physics2D.Abstract;
namespace Syntriax.Engine.Physics2D;
public abstract class Collider2DBehaviourBase : Behaviour, ICollider2D
public abstract class Collider2DBehaviourBase : Behaviour2D, ICollider2D
{
public event ICollider2D.OnCollisionDetectedEventHandler? OnCollisionDetected = null;
public event ICollider2D.OnCollisionResolvedEventHandler? OnCollisionResolved = null;
@ -16,11 +16,6 @@ public abstract class Collider2DBehaviourBase : Behaviour, ICollider2D
public IRigidBody2D? RigidBody2D => _rigidBody2D;
public bool IsTrigger { get; set; } = false;
ITransform IAssignableTransform.Transform => Transform;
public event IAssignableTransform.OnTransformAssignedEventHandler? OnTransformAssigned { add => GameObject.OnTransformAssigned += value; remove => GameObject.OnTransformAssigned -= value; }
bool IAssignableTransform.Assign(ITransform transform) => GameObject.Assign(transform);
public void Recalculate()
{
if (!NeedsRecalculation)
@ -42,10 +37,10 @@ public abstract class Collider2DBehaviourBase : Behaviour, ICollider2D
Transform.OnPositionChanged += SetNeedsRecalculationFromPosition;
Transform.OnRotationChanged += SetNeedsRecalculationFromRotation;
Transform.OnScaleChanged += SetNeedsRecalculationFromScale;
Transform.OnParentChanged += UpdateRigidBody2D;
HierarchyObject.OnParentChanged += UpdateRigidBody2D;
}
private void UpdateRigidBody2D(ITransform sender, ITransform? previousParent, ITransform? newParent)
private void UpdateRigidBody2D(IHierarchyObject sender, IHierarchyObject? previousParent, IHierarchyObject? newParent)
{
BehaviourController.TryGetBehaviourInParent(out _rigidBody2D);
}
@ -62,9 +57,9 @@ public abstract class Collider2DBehaviourBase : Behaviour, ICollider2D
_rigidBody2D = null;
}
private void SetNeedsRecalculationFromScale(ITransform sender, Vector2D previousScale) => NeedsRecalculation = true;
private void SetNeedsRecalculationFromPosition(ITransform sender, Vector2D previousPosition) => NeedsRecalculation = true;
private void SetNeedsRecalculationFromRotation(ITransform sender, float previousRotation) => NeedsRecalculation = true;
private void SetNeedsRecalculationFromScale(ITransform2D sender, Vector2D previousScale) => NeedsRecalculation = true;
private void SetNeedsRecalculationFromPosition(ITransform2D sender, Vector2D previousPosition) => NeedsRecalculation = true;
private void SetNeedsRecalculationFromRotation(ITransform2D sender, float previousRotation) => NeedsRecalculation = true;
protected override void OnFinalize()
{

View File

@ -7,7 +7,7 @@ using Syntriax.Engine.Physics2D.Abstract;
namespace Syntriax.Engine.Physics2D;
public class PhysicsCoroutineManager : HierarchyObjectBase
public class PhysicsCoroutineManager : HierarchyObject
{
private readonly List<IEnumerator> enumerators = [];
private IPhysicsEngine2D? physicsEngine = null;

View File

@ -4,7 +4,7 @@ using Syntriax.Engine.Physics2D.Abstract;
namespace Syntriax.Engine.Physics2D;
public class PhysicsEngine2DCollector : HierarchyObjectBase, IPhysicsEngine2D
public class PhysicsEngine2DCollector : HierarchyObject, IPhysicsEngine2D
{
public event IPhysicsEngine2D.OnPhysicsIterationEventHandler? OnPhysicsIteration = null;
public event IPhysicsEngine2D.OnPhysicsStepEventHandler? OnPhysicsStep = null;

View File

@ -1,13 +1,10 @@
using Syntriax.Engine.Core;
using Syntriax.Engine.Core.Abstract;
using Syntriax.Engine.Physics2D.Abstract;
namespace Syntriax.Engine.Physics2D;
public class RigidBody2D : Behaviour, IRigidBody2D
public class RigidBody2D : Behaviour2D, IRigidBody2D
{
event IAssignableTransform.OnTransformAssignedEventHandler? IAssignableTransform.OnTransformAssigned { add => GameObject.OnTransformAssigned += value; remove => GameObject.OnTransformAssigned -= value; }
private const float LOWEST_ALLOWED_MASS = 0.00001f;
private float _mass = 1f;
@ -18,8 +15,4 @@ public class RigidBody2D : Behaviour, IRigidBody2D
public bool IsStatic { get; set; } = false;
public float Mass { get => _mass; set => _mass = Core.Math.Max(value, LOWEST_ALLOWED_MASS); }
ITransform IAssignableTransform.Transform => Transform;
public bool Assign(ITransform transform) => GameObject.Assign(transform);
}