using System.Diagnostics.CodeAnalysis; using Syntriax.Engine.Core.Abstract; namespace Syntriax.Engine.Core; public static class BehaviourControllerExtensions { /// <summary> /// Tries to get a <see cref="IBehaviour"/> of the specified type. /// </summary> /// <typeparam name="T">The type of <see cref="IBehaviour"/> to get.</typeparam> /// <param name="behaviourController">The <see cref="IBehaviourController"/> to search in.</param> /// <param name="behaviour">When this method returns, contains the <see cref="IBehaviour"/> of the specified type, if found; otherwise, null.</param> /// <returns><see cref="true"/> if a <see cref="IBehaviour"/> of the specified type was found; otherwise, <see cref="false"/>.</returns> public static bool TryGetBehaviour<T>(this IBehaviourController behaviourController, [NotNullWhen(returnValue: true)] out T? behaviour) { behaviour = behaviourController.GetBehaviour<T>(); return behaviour is not null; } /// <summary> /// Gets an existing <see cref="IBehaviour"/> of the specified type, or adds and returns a new one if it doesn't exist. /// </summary> /// <typeparam name="T">The type of <see cref="IBehaviour"/> to get or add.</typeparam> /// <param name="behaviourController">The <see cref="IBehaviourController"/> to search in.</param> /// <param name="args">Optional arguments to pass to the constructor of the <see cref="IBehaviour"/> if a new one is added.</param> /// <returns>The existing or newly added <see cref="IBehaviour"/> of the specified type.</returns> public static T GetOrAddBehaviour<T>(this IBehaviourController behaviourController, params object?[]? args) where T : class, IBehaviour => behaviourController.GetBehaviour<T>() ?? behaviourController.AddBehaviour<T>(args); /// <summary> /// Tries to get a <see cref="IBehaviour"/> of the specified type in the parent hierarchy. /// </summary> /// <typeparam name="T">The type of <see cref="IBehaviour"/> to get.</typeparam> /// <param name="behaviourController">The <see cref="IBehaviourController"/> to start searching from.</param> /// <param name="behaviour">When this method returns, contains the <see cref="IBehaviour"/> of the specified type, if found; otherwise, null.</param> /// <returns><see cref="true"/> if a <see cref="IBehaviour"/> of the specified type was found in the parent hierarchy; otherwise, <see cref="false"/>.</returns> public static bool TryGetBehaviourInParent<T>(this IBehaviourController behaviourController, [NotNullWhen(returnValue: true)] out T? behaviour) where T : class { behaviour = GetBehaviourInParent<T>(behaviourController); return behaviour is not null; } /// <summary> /// Gets a <see cref="IBehaviour"/> of the specified type in the parent hierarchy. /// </summary> /// <typeparam name="T">The type of <see cref="IBehaviour"/> to get.</typeparam> /// <param name="behaviourController">The <see cref="IBehaviourController"/> to start searching from.</param> /// <returns>The <see cref="IBehaviour"/> of the specified type if found; otherwise, null.</returns> public static T? GetBehaviourInParent<T>(this IBehaviourController behaviourController) where T : class { IBehaviourController? controller = behaviourController; while (controller is not null) { if (behaviourController.GetBehaviour<T>() is T behaviour) return behaviour; controller = controller.HierarchyObject.Parent?.BehaviourController; } return default; } /// <summary> /// Tries to get a <see cref="IBehaviour"/> of the specified type in the child hierarchy. /// </summary> /// <typeparam name="T">The type of <see cref="IBehaviour"/> to get.</typeparam> /// <param name="behaviourController">The <see cref="IBehaviourController"/> to start searching from.</param> /// <param name="behaviour">When this method returns, contains the <see cref="IBehaviour"/> of the specified type, if found; otherwise, null.</param> /// <returns><see cref="true"/> if a <see cref="IBehaviour"/> of the specified type was found in the child hierarchy; otherwise, <see cref="false"/>.</returns> public static bool TryGetBehaviourInChildren<T>(this IBehaviourController behaviourController, [NotNullWhen(returnValue: true)] out T? behaviour) where T : class { behaviour = GetBehaviourInChildren<T>(behaviourController); return behaviour is not null; } /// <summary> /// Gets a <see cref="IBehaviour"/> of the specified type in the child hierarchy. /// </summary> /// <typeparam name="T">The type of <see cref="IBehaviour"/> to get.</typeparam> /// <param name="behaviourController">The <see cref="IBehaviourController"/> to start searching from.</param> /// <returns>The <see cref="IBehaviour"/> of the specified type if found; otherwise, null.</returns> public static T? GetBehaviourInChildren<T>(this IBehaviourController behaviourController) where T : class { if (behaviourController.GetBehaviour<T>() is T localBehaviour) return localBehaviour; foreach (IHierarchyObject child in behaviourController.HierarchyObject) if (GetBehaviourInChildren<T>(child.BehaviourController) is T behaviour) return behaviour; return default; } }