25 Commits

Author SHA1 Message Date
65dcb0c564 BREAKING CHANGE: moved yaml serialization from Engine.Serialization to Engine.Integration 2025-08-05 20:10:30 +03:00
3d183b21cd BREAKING CHANGE: renamed namespace & assembly names 2025-08-05 19:41:35 +03:00
1644a751bb feat: added LiteNetLib networking integration 2025-08-05 19:27:47 +03:00
6631cae7b0 feat: added networking system 2025-08-05 19:27:27 +03:00
3452194941 BREAKING CHANGE: removed IUniverseObject.SetParent and made Parent property settable 2025-08-05 10:46:25 +03:00
11612ff0db feat: removed IEnumerable from IUniverseObject for intellisense clarity
Use IUniverseObject.Children to access children
2025-08-05 09:11:46 +03:00
63bc94c7a6 fix: some factories not assigning fields correctly 2025-08-04 22:02:48 +03:00
e00319d7ff fix: active checks on behaviour base and universe object not working properly 2025-08-04 22:01:16 +03:00
11719440dc fix: behaviour controller extensions not null checking in case of uninitialized state 2025-08-04 20:26:45 +03:00
f246d68aa7 fix: remove behaviour not starting the reverse for loop from count - 1 2025-08-04 14:56:43 +03:00
6e87c67096 fix: wrong assert messages are corrected 2025-08-04 14:45:00 +03:00
b8217f2106 feat: last active frame interface 2025-08-03 09:43:18 +03:00
9824980cbf chore!: behaviour collector now removes behaviours on pre unregister 2025-08-03 09:23:30 +03:00
93a79cd075 feat: universe pre register and unregister events 2025-08-03 09:22:22 +03:00
f6e52abcc1 feat: testing universe entrance manager 2025-08-02 23:24:59 +03:00
03232f72e8 fix: LogTrace not having an optional stack trace parameter 2025-07-27 19:01:50 +03:00
37aca44e45 feat: monogame premultiplied color extension method added 2025-07-26 12:03:28 +03:00
9f4d95a57b perf: removed unnecessary operations on hsv colors 2025-07-26 11:59:36 +03:00
65eac57fce fix: color lerp methods fixed 2025-07-26 11:59:04 +03:00
08311acc9a chore!: removed FromTo methods from colors 2025-07-26 11:58:23 +03:00
f8fbae6130 feat: added HSVA 2025-07-26 11:56:58 +03:00
df06e8d134 feat: ticker is decoupled from stopwatch and added timer and stopwatch tickers 2025-07-25 23:24:08 +03:00
ad365dc722 feat: monogame content loader interface added 2025-07-25 21:40:57 +03:00
200e8ae7da feat: ILogger WrapWith extension method added 2025-07-21 10:25:33 +03:00
65cfaf1b4a feat: ILogger.Shared for global access 2025-07-21 10:18:00 +03:00
263 changed files with 2131 additions and 548 deletions

4
.gitmodules vendored
View File

@@ -1,3 +1,3 @@
[submodule "Engine.Serializers/YamlDotNet"]
path = Engine.Serializers/YamlDotNet
[submodule "Engine.Integration/YamlDotNet"]
path = Engine.Integration/YamlDotNet
url = git@github.com:Syntriax/YamlDotNet.git

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Indicates the class implementing it has Assignable fields that are necessary for the engine to work properly.

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IBehaviourController"/> field.

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IEntity"/> field.

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IStateEnable"/> field.

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IUniverse"/> field.

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Indicates the object is an <see cref="IAssignable"/> with an assignable <see cref="IUniverseObject"/> field.

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents an entity which can be active or not.

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents a behaviour that any object in the engine that might use to interact with itself or other objects.

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public interface IBehaviour2D : IBehaviour
{

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents a collector for the class type of <typeparamref name="T"/>.

View File

@@ -1,6 +1,6 @@
using System.Collections.Generic;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents a controller for managing <see cref="IBehaviour"/>s. Connected to an <see cref="IUniverseObject"/>.

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents a 2D camera in the engine.

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public interface ICoroutineYield
{

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents a basic entity in the engine.

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <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.

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents an entity with a name.

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents an entity with an enable state that can be toggled.

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents the transformation properties of an object such as position, scale, and rotation in 2D space.

View File

@@ -1,6 +1,6 @@
using System.Collections.Generic;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents a universe responsible for managing <see cref="IUniverseObject"/>s.
@@ -37,11 +37,21 @@ public interface IUniverse : IEntity, IEnumerable<IUniverseObject>
/// </summary>
Event<IUniverse> OnPostDraw { get; }
/// <summary>
/// Event triggered when a <see cref="IUniverseObject"/> is about to be registered to the <see cref="IUniverse"/>.
/// </summary>
Event<IUniverse, UniverseObjectRegisteredArguments> OnPreUniverseObjectRegistered { get; }
/// <summary>
/// Event triggered when a <see cref="IUniverseObject"/> is registered to the <see cref="IUniverse"/>.
/// </summary>
Event<IUniverse, UniverseObjectRegisteredArguments> OnUniverseObjectRegistered { get; }
/// <summary>
/// Event triggered when a <see cref="IUniverseObject"/> is about to be unregistered from the <see cref="IUniverse"/>.
/// </summary>
Event<IUniverse, UniverseObjectUnRegisteredArguments> OnPreUniverseObjectUnRegistered { get; }
/// <summary>
/// Event triggered when a <see cref="IUniverseObject"/> is unregistered from the <see cref="IUniverse"/>.
/// </summary>

View File

@@ -1,13 +1,13 @@
using System.Collections.Generic;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents an <see cref="IEntity"/> that can enter and exit a universe within the <see cref="IUniverse"/> system.
/// This interface allows for tracking the object's presence in the universe and provides events
/// for notifying when the see enters or exits the universe.
/// </summary>
public interface IUniverseObject : IEntity, IActive, INameable, IHasBehaviourController, IEnumerable<IUniverseObject>
public interface IUniverseObject : IEntity, IActive, INameable, IHasBehaviourController
{
/// <summary>
/// Event triggered when the <see cref="IUniverseObject"/> enters the universe.
@@ -47,7 +47,7 @@ public interface IUniverseObject : IEntity, IActive, INameable, IHasBehaviourCon
/// <summary>
/// The parent <see cref="IUniverseObject"/> of the <see cref="IUniverseObject"/>.
/// </summary>
IUniverseObject? Parent { get; }
IUniverseObject? Parent { get; set; }
/// <summary>
/// The <see cref="IUniverseObject"/>s that have this <see cref="IUniverseObject"/> as their <see cref="Parent"/>.
@@ -75,12 +75,6 @@ public interface IUniverseObject : IEntity, IActive, INameable, IHasBehaviourCon
/// </returns>
internal bool ExitUniverse();
/// <summary>
/// Sets the parent <see cref="IUniverseObject"/> of this <see cref="IUniverseObject"/>.
/// </summary>
/// <param name="universeObject">The parent <see cref="IUniverseObject"/> to set.</param>
void SetParent(IUniverseObject? universeObject);
/// <summary>
/// Adds a child <see cref="IUniverseObject"/> to this <see cref="IUniverseObject"/>.
/// </summary>

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : class, IBehaviour
{

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public class ActiveBehaviourCollectorSorted<T> : ActiveBehaviourCollector<T> where T : class, IBehaviour
{

View File

@@ -1,6 +1,6 @@
using System;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public abstract class BaseEntity : IEntity
{

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public abstract class Behaviour : BehaviourBase
{

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public abstract class Behaviour2D : Behaviour, IBehaviour2D
{

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
[System.Diagnostics.DebuggerDisplay("{GetType().Name, nq}, Priority: {Priority}, Initialized: {Initialized}")]
public abstract class BehaviourBase : BaseEntity, IBehaviour
@@ -44,6 +44,7 @@ public abstract class BehaviourBase : BaseEntity, IBehaviour
_behaviourController = behaviourController;
OnAssign(behaviourController);
behaviourController.OnUniverseObjectAssigned.AddListener(delegateOnUniverseObjectAssigned);
behaviourController.StateEnable.OnEnabledChanged.AddListener(delegateOnStateEnabledChanged);
if (behaviourController.UniverseObject is not null)
OnUniverseObjectAssigned(behaviourController);
OnBehaviourControllerAssigned?.Invoke(this);
@@ -68,6 +69,7 @@ public abstract class BehaviourBase : BaseEntity, IBehaviour
BehaviourController.UniverseObject.OnActiveChanged.RemoveListener(delegateOnUniverseObjectActiveChanged);
StateEnable.OnEnabledChanged.RemoveListener(delegateOnStateEnabledChanged);
BehaviourController.OnUniverseObjectAssigned.RemoveListener(delegateOnUniverseObjectAssigned);
BehaviourController.StateEnable.OnEnabledChanged.RemoveListener(delegateOnStateEnabledChanged);
base.UnassignInternal();
_behaviourController = null!;
}
@@ -76,6 +78,8 @@ public abstract class BehaviourBase : BaseEntity, IBehaviour
{
Debug.Assert.AssertBehaviourControllerAssigned(this);
Debug.Assert.AssertStateEnableAssigned(this);
UpdateActive();
}
private void OnStateEnabledChanged(IStateEnable sender, IStateEnable.EnabledChangedArguments args) => UpdateActive();
@@ -84,7 +88,7 @@ public abstract class BehaviourBase : BaseEntity, IBehaviour
private void UpdateActive()
{
bool previousActive = IsActive;
_isActive = StateEnable.Enabled && _behaviourController.UniverseObject.IsActive;
_isActive = StateEnable.Enabled && _behaviourController.StateEnable.Enabled && _behaviourController.UniverseObject.IsActive;
if (previousActive != IsActive)
OnActiveChanged?.Invoke(this, new(previousActive));

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
{
@@ -76,7 +76,7 @@ public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
OnUniverseObjectRegistered(universe, new(universeObject));
universe.OnUniverseObjectRegistered.AddListener(delegateOnUniverseObjectRegistered);
universe.OnUniverseObjectUnRegistered.AddListener(delegateOnUniverseObjectUnregistered);
universe.OnPreUniverseObjectUnRegistered.AddListener(delegateOnUniverseObjectUnregistered);
Universe = universe;
OnAssign(universe);
@@ -94,7 +94,7 @@ public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
OnUniverseObjectUnregistered(Universe, new(universeObject));
Universe.OnUniverseObjectRegistered.RemoveListener(delegateOnUniverseObjectRegistered);
Universe.OnUniverseObjectUnRegistered.RemoveListener(delegateOnUniverseObjectUnregistered);
Universe.OnPreUniverseObjectUnRegistered.RemoveListener(delegateOnUniverseObjectUnregistered);
Universe = null!;
OnUnassigned?.Invoke(this);

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public class BehaviourCollectorSorted<T> : BehaviourCollector<T> where T : class
{

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
[System.Diagnostics.DebuggerDisplay("Behaviour Count: {behaviours.Count}")]
public class BehaviourController : BaseEntity, IBehaviourController
@@ -72,7 +72,7 @@ public class BehaviourController : BaseEntity, IBehaviourController
public void RemoveBehaviour<T>(bool removeAll = false) where T : class, IBehaviour
{
for (int i = behaviours.Count; i >= 0; i--)
for (int i = behaviours.Count - 1; i >= 0; i--)
{
if (behaviours[i] is not T behaviour)
continue;

View File

@@ -1,7 +1,7 @@
using System.Collections;
using System.Collections.Generic;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public class CoroutineManager : Behaviour, IUpdate
{

View File

@@ -1,6 +1,6 @@
using System;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public class CoroutineYield(Func<bool> condition) : ICoroutineYield
{

View File

@@ -1,6 +1,6 @@
using System.Runtime.CompilerServices;
namespace Syntriax.Engine.Core.Debug;
namespace Engine.Core.Debug;
public static class Assert
{
@@ -10,21 +10,21 @@ public static class Assert
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void AssertBehaviourControllerAssigned(IHasBehaviourController assignable)
=> System.Diagnostics.Debug.Assert(assignable.BehaviourController is not null, $"{assignable.GetType().Name} must be initialized");
=> System.Diagnostics.Debug.Assert(assignable.BehaviourController is not null, $"{assignable.GetType().Name} must be assigned an {nameof(IBehaviourController)}");
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void AssertEntityAssigned(IHasEntity assignable)
=> System.Diagnostics.Debug.Assert(assignable.Entity is not null, $"{assignable.GetType().Name} must be initialized");
=> System.Diagnostics.Debug.Assert(assignable.Entity is not null, $"{assignable.GetType().Name} must be assigned an {nameof(IEntity)}");
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void AssertUniverseAssigned(IHasUniverse assignable)
=> System.Diagnostics.Debug.Assert(assignable.Universe is not null, $"{assignable.GetType().Name} must be initialized");
=> System.Diagnostics.Debug.Assert(assignable.Universe is not null, $"{assignable.GetType().Name} must be assigned an {nameof(IUniverse)}");
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void AssertUniverseObjectAssigned(IHasUniverseObject assignable)
=> System.Diagnostics.Debug.Assert(assignable.UniverseObject is not null, $"{assignable.GetType().Name} must be initialized");
=> System.Diagnostics.Debug.Assert(assignable.UniverseObject is not null, $"{assignable.GetType().Name} must be assigned an {nameof(IUniverseObject)}");
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void AssertStateEnableAssigned(IHasStateEnable assignable)
=> System.Diagnostics.Debug.Assert(assignable.StateEnable is not null, $"{assignable.GetType().Name} must be initialized");
=> System.Diagnostics.Debug.Assert(assignable.StateEnable is not null, $"{assignable.GetType().Name} must be assigned an {nameof(IStateEnable)}");
}

View File

@@ -1,6 +1,6 @@
using System;
namespace Syntriax.Engine.Core.Debug;
namespace Engine.Core.Debug;
public class ConsoleLogger : LoggerBase
{

View File

@@ -1,7 +1,7 @@
using System;
using System.IO;
namespace Syntriax.Engine.Core.Debug;
namespace Engine.Core.Debug;
public class FileLogger : LoggerBase
{

View File

@@ -1,7 +1,9 @@
namespace Syntriax.Engine.Core.Debug;
namespace Engine.Core.Debug;
public interface ILogger
{
static ILogger Shared { get; set; } = new ConsoleLogger();
Level FilterLevel { get; set; }
void Log(string message, Level level = Level.Info, bool force = false);

View File

@@ -1,6 +1,6 @@
using System;
namespace Syntriax.Engine.Core.Debug;
namespace Engine.Core.Debug;
public abstract class LoggerBase : ILogger
{

View File

@@ -1,8 +1,8 @@
namespace Syntriax.Engine.Core.Debug;
namespace Engine.Core.Debug;
public class LoggerContainer : Behaviour, ILogger
{
public ILogger Logger { get; set; } = new ConsoleLogger();
public ILogger Logger { get; set; } = ILogger.Shared;
public ILogger.Level FilterLevel { get => Logger.FilterLevel; set => Logger.FilterLevel = value; }
public void Log(string message, ILogger.Level level = ILogger.Level.Info, bool force = false) => Logger.Log(message, level, force);

View File

@@ -1,7 +1,7 @@
using System;
using System.Diagnostics;
namespace Syntriax.Engine.Core.Debug;
namespace Engine.Core.Debug;
public static class LoggerExtensions
{
@@ -29,7 +29,7 @@ public static class LoggerExtensions
Log(logger, caller, $"{nameof(StackTrace)}:{Environment.NewLine}{exception.StackTrace}", ILogger.Level.Trace);
}
public static void LogTrace<T>(this ILogger logger, T caller, StackTrace stackTrace, bool force = false)
public static void LogTrace<T>(this ILogger logger, T caller, StackTrace? stackTrace = null, bool force = false)
{
Log(logger, caller, $"{nameof(StackTrace)}:{Environment.NewLine}{stackTrace ?? new()}", ILogger.Level.Trace, force);
}

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core.Debug;
namespace Engine.Core.Debug;
public class LoggerWrapper(ILogger firstLogger, ILogger secondLogger) : ILogger
{

View File

@@ -0,0 +1,6 @@
namespace Engine.Core.Debug;
public static class LoggerWrapperExtensions
{
public static ILogger WrapWith(this ILogger thisLogger, ILogger logger) => new LoggerWrapper(thisLogger, logger);
}

View File

@@ -4,7 +4,8 @@
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>false</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>Syntriax.Engine.Core</RootNamespace>
<RootNamespace>Engine.Core</RootNamespace>
<AssemblyName>Engine.Core</AssemblyName>
</PropertyGroup>
</Project>

View File

@@ -1,6 +1,6 @@
using System;
namespace Syntriax.Engine.Core.Exceptions;
namespace Engine.Core.Exceptions;
public class AssignFailedException(string? message) : Exception(message)
{

View File

@@ -1,3 +1,3 @@
namespace Syntriax.Engine.Core.Exceptions;
namespace Engine.Core.Exceptions;
public class BehaviourNotFoundException(string? message) : NotFoundException(message);

View File

@@ -1,6 +1,6 @@
using System;
namespace Syntriax.Engine.Core.Exceptions;
namespace Engine.Core.Exceptions;
public class NotAssignedException(string? message) : Exception(message)
{

View File

@@ -1,6 +1,6 @@
using System;
namespace Syntriax.Engine.Core.Exceptions;
namespace Engine.Core.Exceptions;
public class NotFoundException(string? message) : Exception(message)
{

View File

@@ -1,3 +1,3 @@
namespace Syntriax.Engine.Core.Exceptions;
namespace Engine.Core.Exceptions;
public class UniverseObjectNotFoundException(string? message) : NotFoundException(message);

View File

@@ -1,9 +1,9 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Syntriax.Engine.Core.Exceptions;
using Engine.Core.Exceptions;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public static class BehaviourControllerExtensions
{
@@ -27,7 +27,7 @@ public static class BehaviourControllerExtensions
/// <param name="behaviourController">The <see cref="IBehaviourController"/> to start searching from.</param>
/// <returns>The <see cref="IBehaviour"/> of the specified type if found; otherwise, throws <see cref="BehaviourNotFoundException"/>.</returns>
public static T GetRequiredBehaviour<T>(this IBehaviourController behaviourController) where T : class
=> behaviourController.GetBehaviour<T>() ?? throw new BehaviourNotFoundException($"{behaviourController.UniverseObject.Name}'s {nameof(IBehaviourController)} does not contain any {typeof(T).FullName}");
=> behaviourController.GetBehaviour<T>() ?? throw new BehaviourNotFoundException($"{behaviourController.UniverseObject?.Name ?? "NULL"}'s {nameof(IBehaviourController)} does not contain any {typeof(T).FullName}");
/// <summary>
/// Gets an existing <see cref="IBehaviour"/> of the specified type, or adds and returns a new one if it doesn't exist.
@@ -93,7 +93,7 @@ public static class BehaviourControllerExtensions
/// <param name="behaviourController">The <see cref="IBehaviourController"/> to start searching from.</param>
/// <returns>The <see cref="IBehaviour"/> of the specified type if found; otherwise, throws <see cref="BehaviourNotFoundException"/>.</returns>
public static T GetRequiredBehaviourInParent<T>(this IBehaviourController behaviourController) where T : class
=> behaviourController.GetBehaviourInParent<T>() ?? throw new BehaviourNotFoundException($"{behaviourController.UniverseObject.Name}'s {nameof(IBehaviourController)} does not contain any {typeof(T).FullName} on any parent");
=> behaviourController.GetBehaviourInParent<T>() ?? throw new BehaviourNotFoundException($"{behaviourController.UniverseObject?.Name ?? "NULL"}'s {nameof(IBehaviourController)} does not contain any {typeof(T).FullName} on any parent");
/// <summary>
/// Gets all <see cref="IBehaviour"/>s of the specified type in it's <see cref="IUniverseObject"/>'s parents recursively and stores them in the provided list.
@@ -140,7 +140,7 @@ public static class BehaviourControllerExtensions
if (behaviourController.GetBehaviour<T>() is T localBehaviour)
return localBehaviour;
foreach (IUniverseObject child in behaviourController.UniverseObject)
foreach (IUniverseObject child in behaviourController.UniverseObject.Children)
if (GetBehaviourInChildren<T>(child.BehaviourController) is T behaviour)
return behaviour;
@@ -154,7 +154,7 @@ public static class BehaviourControllerExtensions
/// <param name="behaviourController">The <see cref="IBehaviourController"/> to start searching from.</param>
/// <returns>The <see cref="IBehaviour"/> of the specified type if found; otherwise, throws <see cref="BehaviourNotFoundException"/>.</returns>
public static T GetRequiredBehaviourInChildren<T>(this IBehaviourController behaviourController) where T : class
=> behaviourController.GetBehaviourInChildren<T>() ?? throw new BehaviourNotFoundException($"{behaviourController.UniverseObject.Name}'s {nameof(IBehaviourController)} does not contain any {typeof(T).FullName} on any children ");
=> behaviourController.GetBehaviourInChildren<T>() ?? throw new BehaviourNotFoundException($"{behaviourController.UniverseObject?.Name ?? "NULL"}'s {nameof(IBehaviourController)} does not contain any {typeof(T).FullName} on any children ");
/// <summary>
/// Gets all <see cref="IBehaviour"/>s of the specified type in it's <see cref="IUniverseObject"/>'s children recursively and stores them in the provided list.
@@ -176,7 +176,7 @@ public static class BehaviourControllerExtensions
foreach (T behaviour in cache)
behaviours.Add(behaviour);
foreach (IUniverseObject child in universeObject)
foreach (IUniverseObject child in universeObject.Children)
TraverseChildrenForBehaviour(child, behaviours, cache);
}
}

View File

@@ -1,6 +1,6 @@
using System;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public static class EnumExtensions
{

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public static class FloatExtensions
{

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public static class TransformExtensions
{

View File

@@ -1,6 +1,6 @@
using Syntriax.Engine.Core.Exceptions;
using Engine.Core.Exceptions;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public static class UniverseExtensions
{

View File

@@ -1,9 +1,9 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Syntriax.Engine.Core.Exceptions;
using Engine.Core.Exceptions;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public static class UniverseObjectExtensions
{
@@ -12,7 +12,7 @@ public static class UniverseObjectExtensions
if (!string.IsNullOrWhiteSpace(name))
universeObject.Name = name;
if (parent is not null)
universeObject.SetParent(parent);
universeObject.Parent = parent;
return universeObject;
}
@@ -81,7 +81,7 @@ public static class UniverseObjectExtensions
/// <returns>The <see cref="IUniverseObject"/> of the specified type if found; otherwise, null.</returns>
public static T? GetUniverseObjectInParent<T>(this IUniverseObject universeObject) where T : class
{
if (universeObject.GetUniverseObject<T>() is T localUniverseObject)
if (universeObject.Children.GetUniverseObject<T>() is T localUniverseObject)
return localUniverseObject;
IUniverseObject? parent = universeObject;
@@ -129,10 +129,10 @@ public static class UniverseObjectExtensions
/// <returns>The <see cref="IUniverseObject"/> of the specified type if found; otherwise, null.</returns>
public static T? GetUniverseObjectInChildren<T>(this IUniverseObject universeObject) where T : class
{
if (universeObject.GetUniverseObject<T>() is T localUniverseObject)
if (universeObject.Children.GetUniverseObject<T>() is T localUniverseObject)
return localUniverseObject;
foreach (IUniverseObject child in universeObject)
foreach (IUniverseObject child in universeObject.Children)
if (GetUniverseObjectInChildren<T>(child) is T behaviour)
return behaviour;
@@ -246,7 +246,7 @@ public static class UniverseObjectExtensions
foreach (IUniverseObject universeObject in universeObjects)
{
universeObject.Find(cache);
universeObject.Children.Find(cache);
foreach (T behaviour in cache)
instances.Add(behaviour);
}

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core.Factory.Abstract;
namespace Engine.Core.Factory.Abstract;
public interface IFactory<TInterface> where TInterface : class
{

View File

@@ -1,13 +1,13 @@
using Syntriax.Engine.Core.Exceptions;
using Engine.Core.Exceptions;
namespace Syntriax.Engine.Core.Factory;
namespace Engine.Core.Factory;
public class BehaviourControllerFactory
{
public static IBehaviourController Instantiate(IUniverseObject universeObject)
=> Instantiate<BehaviourController>(universeObject);
public static IBehaviourController Instantiate(IUniverseObject universeObject, IStateEnable? stateEnable = null)
=> Instantiate<BehaviourController>(universeObject, stateEnable);
public static T Instantiate<T>(IUniverseObject universeObject, params object?[]? args)
public static T Instantiate<T>(IUniverseObject universeObject, IStateEnable? stateEnable = null, params object?[]? args)
where T : class, IBehaviourController
{
T behaviourController = TypeFactory.Get<T>(args);
@@ -18,6 +18,17 @@ public class BehaviourControllerFactory
if (!behaviourController.Assign(universeObject))
throw AssignFailedException.From(behaviourController, universeObject);
if (stateEnable is not null)
{
if (!stateEnable.Assign(behaviourController))
throw AssignFailedException.From(stateEnable, behaviourController);
if (!behaviourController.Assign(stateEnable))
throw AssignFailedException.From(behaviourController, stateEnable);
}
else
StateEnableFactory.Instantiate(behaviourController);
return behaviourController;
}
}

View File

@@ -1,6 +1,6 @@
using Syntriax.Engine.Core.Exceptions;
using Engine.Core.Exceptions;
namespace Syntriax.Engine.Core.Factory;
namespace Engine.Core.Factory;
public class BehaviourFactory
{
@@ -12,12 +12,15 @@ public class BehaviourFactory
{
T behaviour = TypeFactory.Get<T>(args);
stateEnable ??= TypeFactory.Get<StateEnable>();
if (stateEnable is not null)
{
if (!stateEnable.Assign(behaviour))
throw AssignFailedException.From(stateEnable, behaviour);
if (!behaviour.Assign(stateEnable))
throw AssignFailedException.From(behaviour, stateEnable);
}
else
StateEnableFactory.Instantiate(behaviour);
return behaviour;
}

View File

@@ -1,7 +1,7 @@
using System;
using Syntriax.Engine.Core.Factory.Abstract;
using Engine.Core.Factory.Abstract;
namespace Syntriax.Engine.Core.Factory;
namespace Engine.Core.Factory;
public abstract class FactoryBase<TInterface> : IFactory<TInterface>
where TInterface : class

View File

@@ -1,6 +1,6 @@
using Syntriax.Engine.Core.Exceptions;
using Engine.Core.Exceptions;
namespace Syntriax.Engine.Core.Factory;
namespace Engine.Core.Factory;
public class StateEnableFactory
{

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core.Factory;
namespace Engine.Core.Factory;
public class TransformFactory
{

View File

@@ -3,7 +3,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
namespace Syntriax.Engine.Core.Factory;
namespace Engine.Core.Factory;
public static class TypeFactory
{

View File

@@ -1,6 +1,6 @@
using Syntriax.Engine.Core.Exceptions;
using Engine.Core.Exceptions;
namespace Syntriax.Engine.Core.Factory;
namespace Engine.Core.Factory;
public class UniverseObjectFactory
{
@@ -18,18 +18,25 @@ public class UniverseObjectFactory
{
T universeObject = TypeFactory.Get<T>(args);
behaviourController ??= TypeFactory.Get<BehaviourController>();
stateEnable ??= TypeFactory.Get<StateEnable>();
if (behaviourController is not null)
{
if (!behaviourController.Assign(universeObject))
throw AssignFailedException.From(behaviourController, universeObject);
if (!stateEnable.Assign(universeObject))
throw AssignFailedException.From(stateEnable, universeObject);
if (!universeObject.Assign(behaviourController))
throw AssignFailedException.From(universeObject, behaviourController);
}
else
BehaviourControllerFactory.Instantiate(universeObject);
if (stateEnable is not null)
{
if (!stateEnable.Assign(universeObject))
throw AssignFailedException.From(stateEnable, universeObject);
if (!universeObject.Assign(stateEnable))
throw AssignFailedException.From(universeObject, stateEnable);
}
else
StateEnableFactory.Instantiate(universeObject);
return universeObject;
}

View File

@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using Syntriax.Engine.Core.Debug;
using Engine.Core.Debug;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents a simple event with no parameters.
@@ -50,8 +50,8 @@ public class Event
// We use Ascending order because draw calls are running from last to first
private static readonly Comparer<ListenerData> SortByAscendingPriority = Comparer<ListenerData>.Create((x, y) => x.Priority.CompareTo(y.Priority));
private ILogger _logger = new ConsoleLogger();
public ILogger Logger { get => _logger; set => _logger = value ?? new ConsoleLogger(); }
private ILogger _logger = ILogger.Shared;
public ILogger Logger { get => _logger; set => _logger = value ?? ILogger.Shared; }
private readonly List<ListenerData> listeners = null!;
private readonly List<ListenerData> onceListeners = null!;
@@ -209,8 +209,8 @@ public class Event<TSender> where TSender : class
// We use Ascending order because draw calls are running from last to first
private static readonly Comparer<ListenerData> SortByAscendingPriority = Comparer<ListenerData>.Create((x, y) => x.Priority.CompareTo(y.Priority));
private ILogger _logger = new ConsoleLogger();
public ILogger Logger { get => _logger; set => _logger = value ?? new ConsoleLogger(); }
private ILogger _logger = ILogger.Shared;
public ILogger Logger { get => _logger; set => _logger = value ?? ILogger.Shared; }
private readonly List<ListenerData> listeners = null!;
private readonly List<ListenerData> onceListeners = null!;
@@ -376,8 +376,8 @@ public class Event<TSender, TArguments> where TSender : class
// We use Ascending order because draw calls are running from last to first
private static readonly Comparer<ListenerData> SortByAscendingPriority = Comparer<ListenerData>.Create((x, y) => x.Priority.CompareTo(y.Priority));
private ILogger _logger = new ConsoleLogger();
public ILogger Logger { get => _logger; set => _logger = value ?? new ConsoleLogger(); }
private ILogger _logger = ILogger.Shared;
public ILogger Logger { get => _logger; set => _logger = value ?? ILogger.Shared; }
private readonly List<ListenerData> listeners = null!;
private readonly List<ListenerData> onceListeners = null!;

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public interface IPool<T>
{

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public class ListPool<T> : IPool<List<T>>
{

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public class Pool<T> : IPool<T>
{

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public interface IProgressionTracker : IReadOnlyProgressionTracker
{

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public interface IReadOnlyProgressionTracker
{

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public class ProgressionTracker : IProgressionTracker
{

View File

@@ -1,6 +1,6 @@
using System.Threading.Tasks;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public record struct ProgressiveTask<T>(IReadOnlyProgressionTracker ProgressionTracker, Task<T> Task)
{

View File

@@ -1,7 +1,7 @@
using System;
using System.Numerics;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public static class Math
{

View File

@@ -1,7 +1,7 @@
using System;
using System.Numerics;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public static class MathExtensions
{

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core
namespace Engine.Core
{
// This is pretty much so the assembly gets loaded automatically because
// the builds include the assembly but sometimes doesn't link load it at startup.

View File

@@ -1,6 +1,6 @@
using System.Collections.Generic;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents an Axis-Aligned Bounding Box (AABB) in 2D space.

View File

@@ -1,6 +1,6 @@
using System.Diagnostics;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents a 2D circle.

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents an HSV color.
@@ -27,49 +27,19 @@ public readonly struct ColorHSV(float hue, float saturation, float value)
/// </summary>
public readonly float Value = value.Clamp(0f, 1f);
public static ColorHSV operator -(ColorHSV color) => new(color.Hue.OneMinus().Clamp(0f, 1f), color.Saturation.OneMinus().Clamp(0f, 1f), color.Value.OneMinus().Clamp(0f, 1f));
public static ColorHSV operator +(ColorHSV left, ColorHSV right) => new((left.Hue + right.Hue).Clamp(0f, 1f), (left.Saturation + right.Saturation).Clamp(0f, 1f), (left.Value + right.Value).Clamp(0f, 1f));
public static ColorHSV operator -(ColorHSV left, ColorHSV right) => new((left.Hue - right.Hue).Clamp(0f, 1f), (left.Saturation - right.Saturation).Clamp(0f, 1f), (left.Value - right.Value).Clamp(0f, 1f));
public static ColorHSV operator *(ColorHSV left, ColorHSV right) => new((left.Hue * right.Hue).Clamp(0f, 1f), (left.Saturation * right.Saturation).Clamp(0f, 1f), (left.Value * right.Value).Clamp(0f, 1f));
public static ColorHSV operator *(ColorHSV color, float value) => new((color.Hue * value).Clamp(0f, 1f), (color.Saturation * value).Clamp(0f, 1f), (color.Value * value).Clamp(0f, 1f));
public static ColorHSV operator *(float value, ColorHSV color) => new((color.Hue * value).Clamp(0f, 1f), (color.Saturation * value).Clamp(0f, 1f), (color.Value * value).Clamp(0f, 1f));
public static ColorHSV operator /(ColorHSV color, float value) => new((color.Hue / value).Clamp(0f, 1f), (color.Saturation / value).Clamp(0f, 1f), (color.Value / value).Clamp(0f, 1f));
public static ColorHSV operator -(ColorHSV color) => new(color.Hue.OneMinus(), color.Saturation.OneMinus(), color.Value.OneMinus());
public static ColorHSV operator +(ColorHSV left, ColorHSV right) => new(left.Hue + right.Hue, left.Saturation + right.Saturation, left.Value + right.Value);
public static ColorHSV operator -(ColorHSV left, ColorHSV right) => new(left.Hue - right.Hue, left.Saturation - right.Saturation, left.Value - right.Value);
public static ColorHSV operator *(ColorHSV left, ColorHSV right) => new(left.Hue * right.Hue, left.Saturation * right.Saturation, left.Value * right.Value);
public static ColorHSV operator *(ColorHSV color, float value) => new(color.Hue * value, color.Saturation * value, color.Value * value);
public static ColorHSV operator *(float value, ColorHSV color) => new(color.Hue * value, color.Saturation * value, color.Value * value);
public static ColorHSV operator /(ColorHSV color, float value) => new(color.Hue / value, color.Saturation / value, color.Value / value);
public static bool operator ==(ColorHSV left, ColorHSV right) => left.Hue == right.Hue && left.Saturation == right.Saturation && left.Value == right.Value;
public static bool operator !=(ColorHSV left, ColorHSV right) => left.Hue != right.Hue || left.Saturation != right.Saturation || left.Value != right.Value;
public static implicit operator ColorHSV(ColorRGBA rgba) => (ColorRGB)rgba;
public static implicit operator ColorHSV(ColorRGB rgb)
{
float hue;
float saturation;
float value;
float rd = rgb.R / 255f;
float gd = rgb.G / 255f;
float bd = rgb.B / 255f;
float max = Math.Max(rd, Math.Max(gd, bd));
float min = Math.Min(rd, Math.Min(gd, bd));
float delta = max - min;
if (delta.ApproximatelyEquals(0))
hue = 0f;
else if (max.ApproximatelyEquals(rd))
hue = 60f * ((gd - bd) / delta % 6f);
else if (max.ApproximatelyEquals(gd))
hue = 60f * (((bd - rd) / delta) + 2f);
else
hue = 60f * (((rd - gd) / delta) + 4f);
if (hue < 0f)
hue += 360f;
hue /= 360f;
saturation = max.ApproximatelyEquals(0f) ? 0f : delta / max;
value = max;
return new(hue, saturation, value);
}
public static implicit operator ColorHSV(ColorHSVA hsva) => new(hsva.Hue, hsva.Saturation, hsva.Value);
public static implicit operator ColorHSV(ColorRGBA rgba) => (ColorHSVA)rgba;
public static implicit operator ColorHSV(ColorRGB rgb) => (ColorHSVA)rgb;
/// <summary>
/// Inverts the given <see cref="ColorHSV"/>.
@@ -110,14 +80,6 @@ public readonly struct ColorHSV(float hue, float saturation, float value)
/// <returns>The result of dividing the <see cref="ColorHSV"/> by the scalar value.</returns>
public static ColorHSV Divide(ColorHSV color, float value) => color / value;
/// <summary>
/// Calculates the <see cref="ColorHSV"/> from one point to another.
/// </summary>
/// <param name="from">The starting point.</param>
/// <param name="to">The ending point.</param>
/// <returns>The <see cref="ColorHSV"/> from the starting point to the ending point.</returns>
public static ColorHSV FromTo(ColorHSV from, ColorHSV to) => to - from;
/// <summary>
/// Performs linear interpolation between two <see cref="ColorHSV"/>s.
/// </summary>
@@ -125,7 +87,14 @@ public readonly struct ColorHSV(float hue, float saturation, float value)
/// <param name="to">The ending <see cref="ColorHSV"/> (t = 1).</param>
/// <param name="t">The interpolation parameter.</param>
/// <returns>The interpolated <see cref="ColorHSV"/>.</returns>
public static ColorHSV Lerp(ColorHSV from, ColorHSV to, float t) => from + FromTo(from, to) * t;
public static ColorHSV Lerp(ColorHSV from, ColorHSV to, float t)
{
float hueDiff = to.Hue - from.Hue;
float saturationDiff = to.Saturation - from.Saturation;
float valueDiff = to.Value - from.Value;
return from + new ColorHSV(hueDiff * t, saturationDiff * t, valueDiff * t);
}
/// <summary>
/// Checks if two <see cref="ColorHSV"/>s are approximately equal within a specified epsilon range.
@@ -174,9 +143,6 @@ public static class ColorHSVExtensions
/// <inheritdoc cref="ColorHSV.Divide(ColorHSV, ColorHSV)" />
public static ColorHSV Divide(this ColorHSV color, float value) => ColorHSV.Divide(color, value);
/// <inheritdoc cref="ColorHSV.FromTo(ColorHSV, ColorHSV)" />
public static ColorHSV FromTo(this ColorHSV from, ColorHSV to) => ColorHSV.FromTo(from, to);
/// <inheritdoc cref="ColorHSV.Lerp(ColorHSV, ColorHSV, float)" />
public static ColorHSV Lerp(this ColorHSV from, ColorHSV to, float t) => ColorHSV.Lerp(from, to, t);

View File

@@ -0,0 +1,189 @@
namespace Engine.Core;
/// <summary>
/// Represents an HSV color.
/// </summary>
/// <param name="hue">Hue of the <see cref="ColorHSVA"/>.</param>
/// <param name="saturation">Saturation of the <see cref="ColorHSVA"/>.</param>
/// <param name="value">Value of the <see cref="ColorHSVA"/>.</param>
/// <param name="alpha">Alpha of the <see cref="ColorHSVA"/>.</param>
/// <remarks>
/// Initializes a new instance of the <see cref="ColorHSVA"/> struct with the specified values.
/// </remarks>
[System.Diagnostics.DebuggerDisplay("{ToString(),nq}")]
public readonly struct ColorHSVA(float hue, float saturation, float value, float alpha = 1)
{
/// <summary>
/// The Hue value of the <see cref="ColorHSVA"/>.
/// </summary>
public readonly float Hue = hue.Clamp(0f, 1f);
/// <summary>
/// The Saturation value of the <see cref="ColorHSVA"/>.
/// </summary>
public readonly float Saturation = saturation.Clamp(0f, 1f);
/// <summary>
/// The Value value of the <see cref="ColorHSVA"/>.
/// </summary>
public readonly float Value = value.Clamp(0f, 1f);
/// <summary>
/// The Alpha value of the <see cref="ColorHSVA"/>.
/// </summary>
public readonly float Alpha = alpha;
public static ColorHSVA operator -(ColorHSVA color) => new(color.Hue.OneMinus(), color.Saturation.OneMinus(), color.Value.OneMinus(), color.Alpha);
public static ColorHSVA operator +(ColorHSVA left, ColorHSVA right) => new(left.Hue + right.Hue, left.Saturation + right.Saturation, left.Value + right.Value, left.Alpha + right.Alpha);
public static ColorHSVA operator -(ColorHSVA left, ColorHSVA right) => new(left.Hue - right.Hue, left.Saturation - right.Saturation, left.Value - right.Value, left.Alpha - right.Alpha);
public static ColorHSVA operator *(ColorHSVA left, ColorHSVA right) => new(left.Hue * right.Hue, left.Saturation * right.Saturation, left.Value * right.Value, left.Alpha * right.Alpha);
public static ColorHSVA operator *(ColorHSVA color, float value) => new(color.Hue * value, color.Saturation * value, color.Value * value, color.Alpha * value);
public static ColorHSVA operator *(float value, ColorHSVA color) => new(color.Hue * value, color.Saturation * value, color.Value * value, color.Alpha * value);
public static ColorHSVA operator /(ColorHSVA color, float value) => new(color.Hue / value, color.Saturation / value, color.Value / value, color.Alpha / value);
public static bool operator ==(ColorHSVA left, ColorHSVA right) => left.Hue == right.Hue && left.Saturation == right.Saturation && left.Value == right.Value;
public static bool operator !=(ColorHSVA left, ColorHSVA right) => left.Hue != right.Hue || left.Saturation != right.Saturation || left.Value != right.Value;
public static implicit operator ColorHSVA(ColorHSV hsv) => new(hsv.Hue, hsv.Saturation, hsv.Value, 1f);
public static implicit operator ColorHSVA(ColorRGB rgb) => (ColorRGBA)rgb;
public static implicit operator ColorHSVA(ColorRGBA rgba)
{
float hue;
float saturation;
float value;
float rd = rgba.R / 255f;
float gd = rgba.G / 255f;
float bd = rgba.B / 255f;
float max = Math.Max(rd, Math.Max(gd, bd));
float min = Math.Min(rd, Math.Min(gd, bd));
float delta = max - min;
if (delta.ApproximatelyEquals(0))
hue = 0f;
else if (max.ApproximatelyEquals(rd))
hue = 60f * ((gd - bd) / delta % 6f);
else if (max.ApproximatelyEquals(gd))
hue = 60f * (((bd - rd) / delta) + 2f);
else
hue = 60f * (((rd - gd) / delta) + 4f);
if (hue < 0f)
hue += 360f;
hue /= 360f;
saturation = max.ApproximatelyEquals(0f) ? 0f : delta / max;
value = max;
return new(hue, saturation, value, rgba.A / 255f);
}
/// <summary>
/// Inverts the given <see cref="ColorHSVA"/>.
/// </summary>
/// <param name="color">The <see cref="ColorHSVA"/>.</param>
/// <returns>The inverted <see cref="ColorHSVA"/>.</returns>
public static ColorHSVA Invert(ColorHSVA color) => -color;
/// <summary>
/// Adds two <see cref="ColorHSVA"/>s.
/// </summary>
/// <param name="left">The first <see cref="ColorHSVA"/>.</param>
/// <param name="right">The second <see cref="ColorHSVA"/>.</param>
/// <returns>The sum of the two <see cref="ColorHSVA"/>s.</returns>
public static ColorHSVA Add(ColorHSVA left, ColorHSVA right) => left + right;
/// <summary>
/// Subtracts one <see cref="ColorHSVA"/> from another.
/// </summary>
/// <param name="left">The <see cref="ColorHSVA"/> to subtract from.</param>
/// <param name="right">The <see cref="ColorHSVA"/> to subtract.</param>
/// <returns>The result of subtracting the second <see cref="ColorHSVA"/> from the first.</returns>
public static ColorHSVA Subtract(ColorHSVA left, ColorHSVA right) => left - right;
/// <summary>
/// Multiplies a <see cref="ColorHSVA"/> by a scalar value.
/// </summary>
/// <param name="color">The <see cref="ColorHSVA"/>.</param>
/// <param name="value">The scalar value.</param>
/// <returns>The result of multiplying the <see cref="ColorHSVA"/> by the scalar value.</returns>
public static ColorHSVA Multiply(ColorHSVA color, float value) => color * value;
/// <summary>
/// Divides a <see cref="ColorHSVA"/> by a scalar value.
/// </summary>
/// <param name="color">The <see cref="ColorHSVA"/>.</param>
/// <param name="value">The scalar value.</param>
/// <returns>The result of dividing the <see cref="ColorHSVA"/> by the scalar value.</returns>
public static ColorHSVA Divide(ColorHSVA color, float value) => color / value;
/// <summary>
/// Performs linear interpolation between two <see cref="ColorHSVA"/>s.
/// </summary>
/// <param name="from">The starting <see cref="ColorHSVA"/> (t = 0).</param>
/// <param name="to">The ending <see cref="ColorHSVA"/> (t = 1).</param>
/// <param name="t">The interpolation parameter.</param>
/// <returns>The interpolated <see cref="ColorHSVA"/>.</returns>
public static ColorHSVA Lerp(ColorHSVA from, ColorHSVA to, float t)
{
float hueDiff = to.Hue - from.Hue;
float saturationDiff = to.Saturation - from.Saturation;
float valueDiff = to.Value - from.Value;
float alphaDiff = to.Alpha - from.Alpha;
return from + new ColorHSVA(hueDiff * t, saturationDiff * t, valueDiff * t, alphaDiff * t);
}
/// <summary>
/// Checks if two <see cref="ColorHSVA"/>s are approximately equal within a specified epsilon range.
/// </summary>
/// <param name="left">The first <see cref="ColorHSVA"/>.</param>
/// <param name="right">The second <see cref="ColorHSVA"/>.</param>
/// <param name="epsilon">The epsilon range.</param>
/// <returns><see cref="true"/> if the <see cref="ColorHSVA"/>s are approximately equal; otherwise, <see cref="false"/>.</returns>
public static bool ApproximatelyEquals(ColorHSVA left, ColorHSVA right, float epsilon = float.Epsilon)
=> left.Hue.ApproximatelyEquals(right.Hue, epsilon) && left.Saturation.ApproximatelyEquals(right.Saturation, epsilon) && left.Value.ApproximatelyEquals(right.Value, epsilon);
/// <summary>
/// Determines whether the specified object is equal to the current <see cref="ColorHSVA"/>.
/// </summary>
/// <param name="obj">The object to compare with the current <see cref="ColorHSVA"/>.</param>
/// <returns><see cref="true"/> if the specified object is equal to the current <see cref="ColorHSVA"/>; otherwise, <see cref="false"/>.</returns>
public override bool Equals(object? obj) => obj is ColorHSVA colorHSVA && this == colorHSVA;
/// <summary>
/// Generates a hash code for the <see cref="ColorHSVA"/>.
/// </summary>
/// <returns>A hash code for the <see cref="ColorHSVA"/>.</returns>
public override int GetHashCode() => System.HashCode.Combine(Hue, Saturation, Value);
/// <summary>
/// Converts the <see cref="ColorHSVA"/> to its string representation.
/// </summary>
/// <returns>A string representation of the <see cref="ColorHSVA"/>.</returns>
public override string ToString() => $"{nameof(ColorHSVA)}({Hue}, {Saturation}, {Value})";
}
/// <summary>
/// Provides extension methods for <see cref="ColorHSVA"/> type.
/// </summary>
public static class ColorHSVAExtensions
{
/// <inheritdoc cref="ColorHSVA.Add(ColorHSVA, ColorHSVA)" />
public static ColorHSVA Add(this ColorHSVA color, ColorHSVA value) => ColorHSVA.Add(color, value);
/// <inheritdoc cref="ColorHSVA.Subtract(ColorHSVA, ColorHSVA)" />
public static ColorHSVA Subtract(this ColorHSVA color, ColorHSVA value) => ColorHSVA.Subtract(color, value);
/// <inheritdoc cref="ColorHSVA.Multiply(ColorHSVA, ColorHSVA)" />
public static ColorHSVA Multiply(this ColorHSVA color, float value) => ColorHSVA.Multiply(color, value);
/// <inheritdoc cref="ColorHSVA.Divide(ColorHSVA, ColorHSVA)" />
public static ColorHSVA Divide(this ColorHSVA color, float value) => ColorHSVA.Divide(color, value);
/// <inheritdoc cref="ColorHSVA.Lerp(ColorHSVA, ColorHSVA, float)" />
public static ColorHSVA Lerp(this ColorHSVA from, ColorHSVA to, float t) => ColorHSVA.Lerp(from, to, t);
/// <inheritdoc cref="ColorHSVA.ApproximatelyEquals(ColorHSVA, ColorHSVA, float) " />
public static bool ApproximatelyEquals(this ColorHSVA left, ColorHSVA right, float epsilon = float.Epsilon) => ColorHSVA.ApproximatelyEquals(left, right, epsilon);
}

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents an RGB color.
@@ -38,30 +38,8 @@ public readonly struct ColorRGB(byte r, byte g, byte b)
public static bool operator !=(ColorRGB left, ColorRGB right) => left.R != right.R || left.G != right.G || left.B != right.B;
public static implicit operator ColorRGB(ColorRGBA rgba) => new(rgba.R, rgba.G, rgba.B);
public static implicit operator ColorRGB(ColorHSV hsv)
{
float hue = hsv.Hue * 360f;
float chroma = hsv.Value * hsv.Saturation;
float x = chroma * (1f - Math.Abs(hue / 60f % 2f - 1f));
float m = hsv.Value - chroma;
float r1 = 0f;
float g1 = 0f;
float b1 = 0f;
if (hue < 60) { r1 = chroma; g1 = x; b1 = 0; }
else if (hue < 120) { r1 = x; g1 = chroma; b1 = 0; }
else if (hue < 180) { r1 = 0; g1 = chroma; b1 = x; }
else if (hue < 240) { r1 = 0; g1 = x; b1 = chroma; }
else if (hue < 300) { r1 = x; g1 = 0; b1 = chroma; }
else if (hue <= 360) { r1 = chroma; g1 = 0; b1 = x; }
byte r = (byte)Math.RoundToInt((r1 + m) * 255);
byte g = (byte)Math.RoundToInt((g1 + m) * 255);
byte b = (byte)Math.RoundToInt((b1 + m) * 255);
return new(r, g, b);
}
public static implicit operator ColorRGB(ColorHSVA hsva) => (ColorRGBA)hsva;
public static implicit operator ColorRGB(ColorHSV hsv) => (ColorRGBA)hsv;
/// <summary>
/// Inverts the given <see cref="ColorRGB"/>.
@@ -102,14 +80,6 @@ public readonly struct ColorRGB(byte r, byte g, byte b)
/// <returns>The result of dividing the <see cref="ColorRGB"/> by the scalar value.</returns>
public static ColorRGB Divide(ColorRGB color, float value) => color / value;
/// <summary>
/// Calculates the <see cref="ColorRGB"/> from one point to another.
/// </summary>
/// <param name="from">The starting point.</param>
/// <param name="to">The ending point.</param>
/// <returns>The <see cref="ColorRGB"/> from the starting point to the ending point.</returns>
public static ColorRGB FromTo(ColorRGB from, ColorRGB to) => to - from;
/// <summary>
/// Performs linear interpolation between two <see cref="ColorRGB"/>s.
/// </summary>
@@ -117,7 +87,14 @@ public readonly struct ColorRGB(byte r, byte g, byte b)
/// <param name="to">The ending <see cref="ColorRGB"/> (t = 1).</param>
/// <param name="t">The interpolation parameter.</param>
/// <returns>The interpolated <see cref="ColorRGB"/>.</returns>
public static ColorRGB Lerp(ColorRGB from, ColorRGB to, float t) => from + FromTo(from, to) * t;
public static ColorRGB Lerp(ColorRGB from, ColorRGB to, float t)
{
int redDiff = to.R - from.R;
int greenDiff = to.G - from.G;
int blueDiff = to.B - from.B;
return from + new ColorRGB((byte)(redDiff * t), (byte)(greenDiff * t), (byte)(blueDiff * t));
}
/// <summary>
/// Determines whether the specified object is equal to the current <see cref="ColorRGB"/>.
@@ -156,9 +133,6 @@ public static class ColorRGBExtensions
/// <inheritdoc cref="ColorRGB.Divide(ColorRGB, ColorRGB)" />
public static ColorRGB Divide(this ColorRGB color, float value) => ColorRGB.Divide(color, value);
/// <inheritdoc cref="ColorRGB.FromTo(ColorRGB, ColorRGB)" />
public static ColorRGB FromTo(this ColorRGB from, ColorRGB to) => ColorRGB.FromTo(from, to);
/// <inheritdoc cref="ColorRGB.Lerp(ColorRGB, ColorRGB, float)" />
public static ColorRGB Lerp(this ColorRGB from, ColorRGB to, float t) => ColorRGB.Lerp(from, to, t);
}

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents an RGBA color.
@@ -44,7 +44,31 @@ public readonly struct ColorRGBA(byte r, byte g, byte b, byte a = 255)
public static bool operator !=(ColorRGBA left, ColorRGBA right) => left.R != right.R || left.G != right.G || left.B != right.B || left.A != right.A;
public static implicit operator ColorRGBA(ColorRGB rgb) => new(rgb.R, rgb.G, rgb.B, 255);
public static implicit operator ColorRGBA(ColorHSV hsv) => (ColorRGB)hsv;
public static implicit operator ColorRGBA(ColorHSV hsv) => (ColorHSVA)hsv;
public static implicit operator ColorRGBA(ColorHSVA hsva)
{
float hue = hsva.Hue * 360f;
float chroma = hsva.Value * hsva.Saturation;
float x = chroma * (1f - Math.Abs(hue / 60f % 2f - 1f));
float m = hsva.Value - chroma;
float r1 = 0f;
float g1 = 0f;
float b1 = 0f;
if (hue < 60) { r1 = chroma; g1 = x; b1 = 0; }
else if (hue < 120) { r1 = x; g1 = chroma; b1 = 0; }
else if (hue < 180) { r1 = 0; g1 = chroma; b1 = x; }
else if (hue < 240) { r1 = 0; g1 = x; b1 = chroma; }
else if (hue < 300) { r1 = x; g1 = 0; b1 = chroma; }
else if (hue <= 360) { r1 = chroma; g1 = 0; b1 = x; }
byte r = (byte)Math.RoundToInt((r1 + m) * 255);
byte g = (byte)Math.RoundToInt((g1 + m) * 255);
byte b = (byte)Math.RoundToInt((b1 + m) * 255);
return new(r, g, b, (byte)(hsva.Alpha * 255));
}
/// <summary>
/// Inverts the given <see cref="ColorRGBA"/>.
@@ -85,14 +109,6 @@ public readonly struct ColorRGBA(byte r, byte g, byte b, byte a = 255)
/// <returns>The result of dividing the <see cref="ColorRGBA"/> by the scalar value.</returns>
public static ColorRGBA Divide(ColorRGBA color, float value) => color / value;
/// <summary>
/// Calculates the <see cref="ColorRGBA"/> from one point to another.
/// </summary>
/// <param name="from">The starting point.</param>
/// <param name="to">The ending point.</param>
/// <returns>The <see cref="ColorRGBA"/> from the starting point to the ending point.</returns>
public static ColorRGBA FromTo(ColorRGBA from, ColorRGBA to) => to - from;
/// <summary>
/// Performs linear interpolation between two <see cref="ColorRGBA"/>s.
/// </summary>
@@ -100,7 +116,15 @@ public readonly struct ColorRGBA(byte r, byte g, byte b, byte a = 255)
/// <param name="to">The ending <see cref="ColorRGBA"/> (t = 1).</param>
/// <param name="t">The interpolation parameter.</param>
/// <returns>The interpolated <see cref="ColorRGBA"/>.</returns>
public static ColorRGBA Lerp(ColorRGBA from, ColorRGBA to, float t) => from + FromTo(from, to) * t;
public static ColorRGBA Lerp(ColorRGBA from, ColorRGBA to, float t)
{
int redDiff = to.R - from.R;
int greenDiff = to.G - from.G;
int blueDiff = to.B - from.B;
int alphaDiff = to.A - from.A;
return from + new ColorRGBA((byte)(redDiff * t), (byte)(greenDiff * t), (byte)(blueDiff * t), (byte)(alphaDiff * t));
}
/// <summary>
/// Determines whether the specified object is equal to the current <see cref="ColorRGBA"/>.
@@ -139,9 +163,6 @@ public static class ColorRGBAExtensions
/// <inheritdoc cref="ColorRGBA.Divide(ColorRGBA, ColorRGBA)" />
public static ColorRGBA Divide(this ColorRGBA color, float value) => ColorRGBA.Divide(color, value);
/// <inheritdoc cref="ColorRGBA.FromTo(ColorRGBA, ColorRGBA)" />
public static ColorRGBA FromTo(this ColorRGBA from, ColorRGBA to) => ColorRGBA.FromTo(from, to);
/// <inheritdoc cref="ColorRGBA.Lerp(ColorRGBA, ColorRGBA, float)" />
public static ColorRGBA Lerp(this ColorRGBA from, ColorRGBA to, float t) => ColorRGBA.Lerp(from, to, t);
}

View File

@@ -1,6 +1,6 @@
using System.Diagnostics.CodeAnalysis;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents a 2D line segment defined by two endpoints.

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents a <see cref="Line2DEquation"/> in the form y = mx + b.

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents a range of values along a single axis.

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents a 3D space rotation.

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents an infinite ray in 2D space.

View File

@@ -1,7 +1,7 @@
using System.Collections;
using System.Collections.Generic;
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents a shape defined by a collection of vertices.

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
[System.Diagnostics.DebuggerDisplay("A: {A.ToString(), nq}, B: {B.ToString(), nq}, B: {C.ToString(), nq}")]
public readonly struct Triangle(Vector2D A, Vector2D B, Vector2D C)

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents a two-dimensional vector.

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents a three-dimensional vector.

View File

@@ -1,6 +1,6 @@
using System;
namespace Syntriax.Engine.Core.Serialization;
namespace Engine.Core.Serialization;
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Class)]
public class IgnoreSerializationAttribute : Attribute;

View File

@@ -1,6 +1,6 @@
using System;
namespace Syntriax.Engine.Core.Serialization;
namespace Engine.Core.Serialization;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class SerializeAllAttribute : Attribute;

View File

@@ -1,6 +1,6 @@
using System;
namespace Syntriax.Engine.Core.Serialization;
namespace Engine.Core.Serialization;
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class SerializeAttribute : Attribute;

View File

@@ -1,3 +1,3 @@
namespace Syntriax.Engine.Core.Serialization;
namespace Engine.Core.Serialization;
public record class EntityReference(string? Id = null);

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
namespace Syntriax.Engine.Core.Serialization;
namespace Engine.Core.Serialization;
public class EntityRegistry
{

View File

@@ -1,6 +1,6 @@
using System;
namespace Syntriax.Engine.Core.Serialization;
namespace Engine.Core.Serialization;
public interface ISerializer
{

View File

@@ -2,9 +2,9 @@ using System;
using System.Collections.Generic;
using System.Reflection;
using Syntriax.Engine.Core.Factory;
using Engine.Core.Factory;
namespace Syntriax.Engine.Core.Serialization;
namespace Engine.Core.Serialization;
public class SerializedClass
{

View File

@@ -1,6 +1,6 @@
using System;
namespace Syntriax.Engine.Core.Serialization;
namespace Engine.Core.Serialization;
public class TypeContainer
{

View File

@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Syntriax.Engine.Core.Serialization;
namespace Engine.Core.Serialization;
public static class Utils
{

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
public class StateEnable : IStateEnable
{

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
internal static class Constants
{

View File

@@ -1,4 +1,4 @@
namespace Syntriax.Engine.Core;
namespace Engine.Core;
/// <summary>
/// Represents a <see cref="IBehaviour"/> to be notified when the draw phase of the <see cref="IUniverse"/> occurs.

View File

@@ -0,0 +1,6 @@
namespace Engine.Core;
public interface IEnterUniverse : IBehaviour
{
void EnterUniverse(IUniverse universe);
}

Some files were not shown because too many files have changed in this diff Show More