SHADE_Y3/SHADE_Managed/src/Scripts/ScriptStore.hxx

298 lines
14 KiB
C++

/************************************************************************************//*!
\file ScriptStore.hxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 28, 2021
\brief Contains the definitions of the GameObject managed class which define an
abstraction for working with Entities in managed code.
Note: This file is written in C++17/CLI.
Copyright (C) 2021 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#pragma once
// Project Includes
#include "Engine/Entity.hxx"
#include "Script.hxx"
#include "Serialization/SHSerialization.h"
namespace SHADE
{
/// <summary>
/// Responsible for managing all scripts attached to Entities as well as executing
/// all lifecycle functions of scripts.
/// </summary>
public ref class ScriptStore abstract sealed
{
public:
/*-----------------------------------------------------------------------------*/
/* Scripts Manipulation Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Adds a Script to a specified Entity.
/// </summary>
/// <typeparam name="T">
/// Type of script to add.
/// This needs to be a default constructable PlushieScript.
/// </typeparam>
/// <param name="entity">The entity to add a script to.</param>
/// <returns>Reference to the script added.</returns>
/// <exception cref="ArgumentException">
/// If the specified Entity is invalid.
/// </exception>
generic<typename T> where T : ref class, Script
static T AddScript(Entity entity);
/// <summary>
/// Adds a Script to a specified Entity.
/// <br/>
/// This function is meant for consumption from native code. If you are writing
/// in C# or C++/CLI, use AddScript&lt;T&gt;() instead as it is faster.
/// </summary>
/// <param name="entity">The entity to add a script to.</param>
/// <param name="scriptName">The entity to add a script to.</param>
/// <returns>
/// True if successfully added. False otherwise with the error logged to the
/// console.
/// </returns>
static bool AddScriptViaName(Entity entity, System::String^ scriptName);
/// <summary>
/// Adds a Script to a specified Entity.
/// <br/>
/// This function is meant for consumption from native code or for serialisation
/// purposes. If you are writing in C# or C++/CLI and not doing serialisation,
/// use AddScript&lt;T&gt;() instead as it is faster.
/// </summary>
/// <param name="entity">The entity to add a script to.</param>
/// <param name="scriptName">The entity to add a script to.</param>
/// <param name="createdScript">
/// Out parameter handle to the Script that was created.
/// </param>
/// <returns>
/// True if successfully added. False otherwise with the error logged to the
/// console.
/// </returns>
static bool AddScriptViaNameWithRef(Entity entity, System::String^ scriptName, [System::Runtime::InteropServices::Out] Script^% createdScript);
/// <summary>
/// Retrieves the first Script from the specified Entity that matches the
/// specified type.
/// </summary>
/// <typeparam name="T">
/// Type of script to get.
/// This needs to be a default constructable Script.
/// </typeparam>
/// <param name="entity">
/// The entity which the script to retrieve is attached.
/// </param>
/// <returns>
/// Reference to the script. This can be null if no script of the specified
/// type is attached.
/// </returns>
/// <exception cref="ArgumentException">
/// If the specified Entity is invalid.
/// </exception>
generic<typename T> where T : ref class, Script
static T GetScript(Entity entity);
/// <summary>
/// Retrieves the first Script from the specified Entity's children that matches
/// the specified type.
/// </summary>
/// <typeparam name="T">
/// Type of script to get.
/// This needs to be a default constructable Script.
/// </typeparam>
/// <param name="entity">
/// The entity which the script to retrieve is attached.
/// </param>
/// <returns>
/// Reference to the script. This can be null if no script of the specified
/// type is attached.
/// </returns>
/// <exception cref="ArgumentException">
/// If the specified Entity is invalid.
/// </exception>
generic<typename T> where T : ref class, Script
static T GetScriptInChildren(Entity entity);
/// <summary>
/// Retrieves a immutable list of scripts from the specified Entity that
/// matches the specified type.
/// <br/>
/// Note that this function allocates. It should be used sparingly.
/// </summary>
/// <typeparam name="T">
/// Type of scripts to get.
/// This needs to be a default constructable Script.
/// </typeparam>
/// <param name="entity">
/// The entity which the scripts to retrieve are attached.
/// </param>
/// <returns>
/// Immutable list of references to scripts of the specified type.
/// </returns>
generic<typename T> where T : ref class, Script
static System::Collections::Generic::IEnumerable<T> ^ GetScripts(Entity entity);
/// <summary>
/// Retrieves an immutable list of all scripts attached to a specified Entity.
/// </summary>
/// <param name="entity">
/// The entity which the scripts to retrieve are attached.
/// </param>
/// <returns>
/// Immutable list of references to scripts attached to the specified Entity.
/// This can also be null if there are no scripts at all or an invalid Entity
/// was specified.
/// </returns>
static System::Collections::Generic::IEnumerable<Script^>^ GetAllScripts(Entity entity);
/// <summary>
/// Removes all Scripts of the specified type from the specified Entity.
/// </summary>
/// <typeparam name="T">
/// Type of script to remove.
/// This needs to be a default constructable Script.
/// </typeparam>
/// <param name="entity">The entity to remove the script from.</param>
/// <exception cref="ArgumentException">
/// If the specified Entity is invalid.
/// </exception>
generic<typename T> where T : ref class, Script
static void RemoveScript(Entity entity);
/// <summary>
/// Removes a specific script from the
/// </summary>
/// <param name="entity">The entity to remove the script from.</param>
/// <param name="script">The script to remove.</param>
/// <returns>True if successfully removed. False otherwise.</returns>
static bool RemoveScript(Entity entity, Script^ script);
/// <summary>
/// Removes all Scripts attached to the specified Entity. Does not do anything
/// if the specified Entity is invalid or does not have any Scripts
/// attached.
/// </summary>
/// <param name="entity">The entity to remove the scripts from.</param>
static void RemoveAllScripts(Entity entity);
/// <summary>
/// Removes all Scripts attached to the specified Entity. Unlike
/// RemoveAllScripts(), this removes all the scripts immediately.
/// Does not do anything if the specified Entity is invalid or does not have any
/// Scripts attached.
/// </summary>
/// <param name="entity">The entity to remove the scripts from.</param>
/// <param name="callOnDestroy">
/// Whether or not to call OnDestroy on the scripts.This is ignored if not in
/// play mode.
/// </param>
static void RemoveAllScriptsImmediately(Entity entity, bool callOnDestroy);
internal:
/*-----------------------------------------------------------------------------*/
/* Lifecycle Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Initializes the ScriptStore to allocate and pre-populate reflection data.
/// </summary>
static void Init();
/// <summary>
/// Sets up scripts that were marked for initialization. This calls the Awake()
/// and Start() for Scripts that have yet to have done so.
/// </summary>
static void FrameSetUp();
/// <summary>
/// Cleans up scripts that were marked for deletion. This calls the OnDestroy()
/// for these Scripts.
/// </summary>
static void FrameCleanUp();
/// <summary>
/// Cleans up data stored in the ScriptStore to free up memory for garbage
/// collection.
/// </summary>
static void Exit();
/*-----------------------------------------------------------------------------*/
/* Script Information Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Retrieves a immutable list of available scripts that can be added.
/// </summary>
/// <returns>Immutable list of available scripts that can be added.</returns>
static System::Collections::Generic::IEnumerable<System::Type^>^ GetAvailableScriptList();
/*-----------------------------------------------------------------------------*/
/* Script Execution Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Executes FixedUpdate() for all scripts.
/// </summary>
static void ExecuteFixedUpdate();
/// <summary>
/// Executes Update() for all scripts.
/// </summary>
static void ExecuteUpdate();
/// <summary>
/// Executes LateUpdate() for all scripts.
/// </summary>
static void ExecuteLateUpdate();
/*-----------------------------------------------------------------------------*/
/* Serialisation Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Populates a YAML node with the scripts for a specified Entity.
/// <br/> <br/>
/// This function should only be called from native unmanaged code.
/// </summary>
/// <param name="entity">The Entity to Serialise.</param>
/// <param name="yamlNode">
/// Pointer to a YAML::Node that will be populated with all of the serialised
/// scripts and their associated fields.
/// </param>
/// <returns>
/// True if serialisation is successful. False if the buffer is too small for
/// the serialised output.
/// </returns>
static bool SerialiseScripts(Entity entity, System::IntPtr yamlNode);
/// <summary>
/// Processes a YAML node that contains a list of multiple scripts to be loaded
/// into the specified Entity.
/// <br/> <br/>
/// This function should only be called from native unmanaged code.
/// </summary>
/// <param name="entity">
/// The Entity to attach the deserialised Scripts to.
/// </param>
/// <param name="yaml">
/// Pointer to the YAML::Node that contains serialized script data.
/// </param>
/// <returns></returns>
static bool DeserialiseScripts(Entity entity, System::IntPtr yamlNode);
private:
/*-----------------------------------------------------------------------------*/
/* Type Definition */
/*-----------------------------------------------------------------------------*/
using ScriptList = System::Collections::Generic::List<Script^>;
using ScriptDictionary = System::Collections::Generic::Dictionary<Entity, ScriptList^>;
using ScriptQueue = System::Collections::Generic::Queue<Script^>;
/*-----------------------------------------------------------------------------*/
/* Static Data Members */
/*-----------------------------------------------------------------------------*/
static ScriptDictionary scripts;
static ScriptList awakeList;
static ScriptList startList;
static ScriptList inactiveStartList;
static ScriptQueue disposalQueue;
static System::Collections::Generic::IEnumerable<System::Type^>^ scriptTypeList;
static System::Reflection::MethodInfo^ addScriptMethod;
/*-----------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------*/
static void removeScript(Script^ script);
static void refreshScriptTypeList();
static void getGenericMethods();
static System::Type^ getScriptType(System::String^ scriptName);
static bool isEntityActive(Entity entity);
};
} // namespace PlushieAPI