Integration of .NET Scripting Backend #23
|
@ -17,10 +17,11 @@ echo "J - tracy"
|
||||||
echo "K - RTTR"
|
echo "K - RTTR"
|
||||||
echo "L - yamlcpp"
|
echo "L - yamlcpp"
|
||||||
echo "M - SDL"
|
echo "M - SDL"
|
||||||
|
echo "N - dotnet"
|
||||||
echo ---------------------------------------------------
|
echo ---------------------------------------------------
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
choice /C ABCDEFGHIJKLM /T 10 /D A
|
choice /C ABCDEFGHIJKLMN /T 10 /D A
|
||||||
set _e=%ERRORLEVEL%
|
set _e=%ERRORLEVEL%
|
||||||
|
|
||||||
if %_e%==1 goto VMA
|
if %_e%==1 goto VMA
|
||||||
|
@ -36,6 +37,7 @@ if %_e%==10 goto tracy
|
||||||
if %_e%==11 goto RTTR
|
if %_e%==11 goto RTTR
|
||||||
if %_e%==12 goto yamlcpp
|
if %_e%==12 goto yamlcpp
|
||||||
if %_e%==13 goto SDL
|
if %_e%==13 goto SDL
|
||||||
|
if %_e%==14 goto dotnet
|
||||||
|
|
||||||
:VMA
|
:VMA
|
||||||
echo -----------------------VMA----------------------------
|
echo -----------------------VMA----------------------------
|
||||||
|
@ -53,7 +55,7 @@ if %_e%==3 (goto :done) else (goto :assimp)
|
||||||
echo -----------------------assimp----------------------------
|
echo -----------------------assimp----------------------------
|
||||||
rmdir "Dependencies/assimp" /S /Q
|
rmdir "Dependencies/assimp" /S /Q
|
||||||
git clone https://github.com/SHADE-DP/assimp.git "Dependencies/assimp"
|
git clone https://github.com/SHADE-DP/assimp.git "Dependencies/assimp"
|
||||||
if %_e%==4 (goto :done) else (goto :ktx)
|
if %_e%==4 (goto :done) else (goto :spdlog)
|
||||||
|
|
||||||
@REM :ktx
|
@REM :ktx
|
||||||
@REM rmdir "Dependencies/ktx" /S /Q
|
@REM rmdir "Dependencies/ktx" /S /Q
|
||||||
|
@ -120,6 +122,20 @@ robocopy "Dependencies/SDL/tmp/SDL2-2.24.0/lib/x64" "Dependencies/SDL/lib/" /ns
|
||||||
robocopy "Dependencies/SDL/tmp/SDL2-2.24.0/include/" "Dependencies/SDL/include/" /ns /nfl /ndl /nc /njh
|
robocopy "Dependencies/SDL/tmp/SDL2-2.24.0/include/" "Dependencies/SDL/include/" /ns /nfl /ndl /nc /njh
|
||||||
rmdir "Dependencies/SDL/tmp/" /s /q
|
rmdir "Dependencies/SDL/tmp/" /s /q
|
||||||
powershell -Command "& {Remove-Item "Dependencies/SDL/SDL.zip"}"
|
powershell -Command "& {Remove-Item "Dependencies/SDL/SDL.zip"}"
|
||||||
|
if %_e%==13 (goto :done) else (goto :dotnet)
|
||||||
|
|
||||||
|
:dotnet
|
||||||
|
echo -----------------------dotnet----------------------------
|
||||||
|
rmdir "Dependencies/dotnet" /S /Q
|
||||||
|
mkdir "Dependencies/dotnet/include"
|
||||||
|
mkdir "Dependencies/dotnet/bin"
|
||||||
|
powershell -Command "& {wget https://raw.githubusercontent.com/dotnet/runtime/main/src/coreclr/hosts/inc/coreclrhost.h -OutFile "Dependencies/dotnet/include/coreclrhost.h"}"
|
||||||
|
powershell -Command "& {wget https://download.visualstudio.microsoft.com/download/pr/8686fa48-b378-424e-908b-afbd66d6e120/2d75d5c3574fb5d917c5a3cd3f624287/dotnet-sdk-6.0.400-win-x64.zip -OutFile "Dependencies/dotnet/dotnet.zip"}"
|
||||||
|
powershell -Command "& {Expand-Archive -LiteralPath Dependencies/dotnet/dotnet.zip -DestinationPath Dependencies/dotnet/tmp}"
|
||||||
|
robocopy "Dependencies/dotnet/tmp/shared/Microsoft.NETCore.App/6.0.8/" "Dependencies/dotnet/bin/" *.dll /ns /nfl /ndl /nc /njh
|
||||||
|
rmdir "Dependencies/dotnet/tmp/" /s /q
|
||||||
|
del "Dependencies/dotnet/dotnet.zip"
|
||||||
|
powershell -Command "& {Remove-Item "Dependencies/dotnet/dotnet.zip"}"
|
||||||
|
|
||||||
:done
|
:done
|
||||||
echo DONE!
|
echo DONE!
|
||||||
|
|
|
@ -13,3 +13,4 @@ IncludeDir["RTTR"] = "%{wks.location}/Dependencies/RTTR"
|
||||||
IncludeDir["reactphysics3d"] = "%{wks.location}/Dependencies/reactphysics3d"
|
IncludeDir["reactphysics3d"] = "%{wks.location}/Dependencies/reactphysics3d"
|
||||||
IncludeDir["SDL"] = "%{wks.location}/Dependencies/SDL"
|
IncludeDir["SDL"] = "%{wks.location}/Dependencies/SDL"
|
||||||
IncludeDir["VULKAN"] = "$(VULKAN_SDK)"
|
IncludeDir["VULKAN"] = "$(VULKAN_SDK)"
|
||||||
|
IncludeDir["dotnet"] = "%{wks.location}/Dependencies/dotnet"
|
||||||
|
|
11
SHADE.sln
11
SHADE.sln
|
@ -26,6 +26,13 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SHADE_Engine", "SHADE_Engin
|
||||||
{C0FF640D-2C14-8DBE-F595-301E616989EF} = {C0FF640D-2C14-8DBE-F595-301E616989EF}
|
{C0FF640D-2C14-8DBE-F595-301E616989EF} = {C0FF640D-2C14-8DBE-F595-301E616989EF}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SHADE_Managed", "SHADE_Managed\SHADE_Managed.vcxproj", "{16DB1400-829B-9036-4BD6-D9B3B755D512}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{88F1A057-74BE-FB62-9DD7-E90A890331F1} = {88F1A057-74BE-FB62-9DD7-E90A890331F1}
|
||||||
|
{C0FF640D-2C14-8DBE-F595-301E616989EF} = {C0FF640D-2C14-8DBE-F595-301E616989EF}
|
||||||
|
{3F92E998-2BF5-783D-D47A-B1F3C0BC44C0} = {3F92E998-2BF5-783D-D47A-B1F3C0BC44C0}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|x64 = Debug|x64
|
Debug|x64 = Debug|x64
|
||||||
|
@ -64,6 +71,10 @@ Global
|
||||||
{3F92E998-2BF5-783D-D47A-B1F3C0BC44C0}.Debug|x64.Build.0 = Debug|x64
|
{3F92E998-2BF5-783D-D47A-B1F3C0BC44C0}.Debug|x64.Build.0 = Debug|x64
|
||||||
{3F92E998-2BF5-783D-D47A-B1F3C0BC44C0}.Release|x64.ActiveCfg = Release|x64
|
{3F92E998-2BF5-783D-D47A-B1F3C0BC44C0}.Release|x64.ActiveCfg = Release|x64
|
||||||
{3F92E998-2BF5-783D-D47A-B1F3C0BC44C0}.Release|x64.Build.0 = Release|x64
|
{3F92E998-2BF5-783D-D47A-B1F3C0BC44C0}.Release|x64.Build.0 = Release|x64
|
||||||
|
{16DB1400-829B-9036-4BD6-D9B3B755D512}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{16DB1400-829B-9036-4BD6-D9B3B755D512}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{16DB1400-829B-9036-4BD6-D9B3B755D512}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{16DB1400-829B-9036-4BD6-D9B3B755D512}.Release|x64.Build.0 = Release|x64
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
<WarningLevel>Level4</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
<DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<AdditionalIncludeDirectories>..\Dependencies\spdlog\include;..\SHADE_Engine\src;src;include;..\Dependencies\SDL\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\Dependencies\spdlog\include;..\SHADE_Engine\src;src;..\Dependencies\dotnet\include;..\Dependencies\SDL\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||||
<Optimization>Disabled</Optimization>
|
<Optimization>Disabled</Optimization>
|
||||||
<MinimalRebuild>false</MinimalRebuild>
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
|
@ -84,7 +84,7 @@
|
||||||
<WarningLevel>Level4</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
<DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||||
<PreprocessorDefinitions>_RELEASE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_RELEASE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<AdditionalIncludeDirectories>..\Dependencies\spdlog\include;..\SHADE_Engine\src;src;include;..\Dependencies\SDL\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\Dependencies\spdlog\include;..\SHADE_Engine\src;src;..\Dependencies\dotnet\include;..\Dependencies\SDL\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<Optimization>Full</Optimization>
|
<Optimization>Full</Optimization>
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
@ -120,6 +120,9 @@
|
||||||
<ProjectReference Include="..\SHADE_Engine\SHADE_Engine.vcxproj">
|
<ProjectReference Include="..\SHADE_Engine\SHADE_Engine.vcxproj">
|
||||||
<Project>{3F92E998-2BF5-783D-D47A-B1F3C0BC44C0}</Project>
|
<Project>{3F92E998-2BF5-783D-D47A-B1F3C0BC44C0}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\SHADE_Managed\SHADE_Managed.vcxproj">
|
||||||
|
<Project>{16DB1400-829B-9036-4BD6-D9B3B755D512}</Project>
|
||||||
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
|
|
@ -37,6 +37,7 @@ project "SHADE_Application"
|
||||||
links
|
links
|
||||||
{
|
{
|
||||||
"SHADE_Engine",
|
"SHADE_Engine",
|
||||||
|
"SHADE_Managed",
|
||||||
"SDL2.lib",
|
"SDL2.lib",
|
||||||
"SDL2main.lib"
|
"SDL2main.lib"
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
|
||||||
|
#include "Scripting/SHScriptEngine.h"
|
||||||
|
|
||||||
namespace Sandbox
|
namespace Sandbox
|
||||||
{
|
{
|
||||||
bool paused = false;
|
bool paused = false;
|
||||||
|
@ -36,6 +38,8 @@ namespace Sandbox
|
||||||
#else
|
#else
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Set up scripting
|
||||||
|
SHADE::SHScriptEngine::Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SBApplication::Update(void)
|
void SBApplication::Update(void)
|
||||||
|
@ -52,6 +56,9 @@ namespace Sandbox
|
||||||
|
|
||||||
void SBApplication::Exit(void)
|
void SBApplication::Exit(void)
|
||||||
{
|
{
|
||||||
|
// Shutdown scripting
|
||||||
|
SHADE::SHScriptEngine::Exit();
|
||||||
|
|
||||||
SDL_DestroyWindow(sdlWindow);
|
SDL_DestroyWindow(sdlWindow);
|
||||||
#ifdef SHEDITOR
|
#ifdef SHEDITOR
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
<WarningLevel>Level4</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
<DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||||
<PreprocessorDefinitions>_LIB;_GLFW_INCLUDE_NONE;MSDFGEN_USE_CPP11;NOMINMAX;SH_API_EXPORT;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_LIB;_GLFW_INCLUDE_NONE;MSDFGEN_USE_CPP11;NOMINMAX;SH_API_EXPORT;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<AdditionalIncludeDirectories>src;..\Dependencies\assimp\include;..\Dependencies\imgui;..\Dependencies\imguizmo;..\Dependencies\imnodes;..\Dependencies\msdf;..\Dependencies\msdf\msdfgen;..\Dependencies\spdlog\include;..\Dependencies\tracy;..\Dependencies\VMA\include;..\Dependencies\yamlcpp\include;..\Dependencies\SDL\include;..\Dependencies\RTTR\include;..\Dependencies\reactphysics3d\include;$(VULKAN_SDK)\include;$(VULKAN_SDK)\Source\SPIRV-Reflect;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>src;..\Dependencies\assimp\include;..\Dependencies\imgui;..\Dependencies\imguizmo;..\Dependencies\imnodes;..\Dependencies\msdf;..\Dependencies\msdf\msdfgen;..\Dependencies\spdlog\include;..\Dependencies\tracy;..\Dependencies\VMA\include;..\Dependencies\yamlcpp\include;..\Dependencies\SDL\include;..\Dependencies\RTTR\include;..\Dependencies\reactphysics3d\include;$(VULKAN_SDK)\include;$(VULKAN_SDK)\Source\SPIRV-Reflect;..\Dependencies\dotnet\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||||
<Optimization>Disabled</Optimization>
|
<Optimization>Disabled</Optimization>
|
||||||
<MinimalRebuild>false</MinimalRebuild>
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
|
@ -78,7 +78,8 @@
|
||||||
</Link>
|
</Link>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>xcopy /s /r /y /q "$(SolutionDir)/Dependencies/spdlog/bin" "$(OutDir)"
|
<Command>xcopy /s /r /y /q "$(SolutionDir)/Dependencies/spdlog/bin" "$(OutDir)"
|
||||||
xcopy /r /y /q "$(SolutionDir)/Dependencies/SDL/lib/SDL2.dll" "$(OutDir)"</Command>
|
xcopy /r /y /q "$(SolutionDir)/Dependencies/SDL/lib/SDL2.dll" "$(OutDir)"
|
||||||
|
xcopy /s /r /y /q "$(SolutionDir)/Dependencies/dotnet/bin" "$(OutDir)"</Command>
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
@ -88,7 +89,7 @@ xcopy /r /y /q "$(SolutionDir)/Dependencies/SDL/lib/SDL2.dll" "$(OutDir)"</Comm
|
||||||
<WarningLevel>Level4</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
<DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||||
<PreprocessorDefinitions>_LIB;_GLFW_INCLUDE_NONE;MSDFGEN_USE_CPP11;NOMINMAX;SH_API_EXPORT;_RELEASE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_LIB;_GLFW_INCLUDE_NONE;MSDFGEN_USE_CPP11;NOMINMAX;SH_API_EXPORT;_RELEASE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<AdditionalIncludeDirectories>src;..\Dependencies\assimp\include;..\Dependencies\imgui;..\Dependencies\imguizmo;..\Dependencies\imnodes;..\Dependencies\msdf;..\Dependencies\msdf\msdfgen;..\Dependencies\spdlog\include;..\Dependencies\tracy;..\Dependencies\VMA\include;..\Dependencies\yamlcpp\include;..\Dependencies\SDL\include;..\Dependencies\RTTR\include;..\Dependencies\reactphysics3d\include;$(VULKAN_SDK)\include;$(VULKAN_SDK)\Source\SPIRV-Reflect;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>src;..\Dependencies\assimp\include;..\Dependencies\imgui;..\Dependencies\imguizmo;..\Dependencies\imnodes;..\Dependencies\msdf;..\Dependencies\msdf\msdfgen;..\Dependencies\spdlog\include;..\Dependencies\tracy;..\Dependencies\VMA\include;..\Dependencies\yamlcpp\include;..\Dependencies\SDL\include;..\Dependencies\RTTR\include;..\Dependencies\reactphysics3d\include;$(VULKAN_SDK)\include;$(VULKAN_SDK)\Source\SPIRV-Reflect;..\Dependencies\dotnet\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<Optimization>Full</Optimization>
|
<Optimization>Full</Optimization>
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
@ -108,7 +109,8 @@ xcopy /r /y /q "$(SolutionDir)/Dependencies/SDL/lib/SDL2.dll" "$(OutDir)"</Comm
|
||||||
</Link>
|
</Link>
|
||||||
<PostBuildEvent>
|
<PostBuildEvent>
|
||||||
<Command>xcopy /s /r /y /q "$(SolutionDir)/Dependencies/spdlog/bin" "$(OutDir)"
|
<Command>xcopy /s /r /y /q "$(SolutionDir)/Dependencies/spdlog/bin" "$(OutDir)"
|
||||||
xcopy /r /y /q "$(SolutionDir)/Dependencies/SDL/lib/SDL2.dll" "$(OutDir)"</Command>
|
xcopy /r /y /q "$(SolutionDir)/Dependencies/SDL/lib/SDL2.dll" "$(OutDir)"
|
||||||
|
xcopy /s /r /y /q "$(SolutionDir)/Dependencies/dotnet/bin" "$(OutDir)"</Command>
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -185,6 +187,7 @@ xcopy /r /y /q "$(SolutionDir)/Dependencies/SDL/lib/SDL2.dll" "$(OutDir)"</Comm
|
||||||
<ClInclude Include="src\Graphics\Windowing\Surface\SHVkSurface.h" />
|
<ClInclude Include="src\Graphics\Windowing\Surface\SHVkSurface.h" />
|
||||||
<ClInclude Include="src\Math\SHMath.h" />
|
<ClInclude Include="src\Math\SHMath.h" />
|
||||||
<ClInclude Include="src\Math\SHMathHelpers.h" />
|
<ClInclude Include="src\Math\SHMathHelpers.h" />
|
||||||
|
<ClInclude Include="src\Math\SHMathHelpers.hpp" />
|
||||||
<ClInclude Include="src\Math\SHMatrix.h" />
|
<ClInclude Include="src\Math\SHMatrix.h" />
|
||||||
<ClInclude Include="src\Math\SHQuaternion.h" />
|
<ClInclude Include="src\Math\SHQuaternion.h" />
|
||||||
<ClInclude Include="src\Math\Vector\SHVec2.h" />
|
<ClInclude Include="src\Math\Vector\SHVec2.h" />
|
||||||
|
@ -192,19 +195,28 @@ xcopy /r /y /q "$(SolutionDir)/Dependencies/SDL/lib/SDL2.dll" "$(OutDir)"</Comm
|
||||||
<ClInclude Include="src\Math\Vector\SHVec4.h" />
|
<ClInclude Include="src\Math\Vector\SHVec4.h" />
|
||||||
<ClInclude Include="src\Meta\SHIsDetected.h" />
|
<ClInclude Include="src\Meta\SHIsDetected.h" />
|
||||||
<ClInclude Include="src\Resource\Handle.h" />
|
<ClInclude Include="src\Resource\Handle.h" />
|
||||||
|
<ClInclude Include="src\Resource\Handle.hpp" />
|
||||||
<ClInclude Include="src\Resource\ResourceLibrary.h" />
|
<ClInclude Include="src\Resource\ResourceLibrary.h" />
|
||||||
|
<ClInclude Include="src\Resource\ResourceLibrary.hpp" />
|
||||||
<ClInclude Include="src\Resource\SparseSet.h" />
|
<ClInclude Include="src\Resource\SparseSet.h" />
|
||||||
|
<ClInclude Include="src\Resource\SparseSet.hpp" />
|
||||||
<ClInclude Include="src\SHCommonTypes.h" />
|
<ClInclude Include="src\SHCommonTypes.h" />
|
||||||
<ClInclude Include="src\SH_API.h" />
|
<ClInclude Include="src\SH_API.h" />
|
||||||
<ClInclude Include="src\SHpch.h" />
|
<ClInclude Include="src\SHpch.h" />
|
||||||
<ClInclude Include="src\Scene\SHScene.h" />
|
<ClInclude Include="src\Scene\SHScene.h" />
|
||||||
<ClInclude Include="src\Scene\SHSceneGraph.h" />
|
<ClInclude Include="src\Scene\SHSceneGraph.h" />
|
||||||
<ClInclude Include="src\Scene\SHSceneManager.h" />
|
<ClInclude Include="src\Scene\SHSceneManager.h" />
|
||||||
|
<ClInclude Include="src\Scripting\SHDotNetRuntime.h" />
|
||||||
|
<ClInclude Include="src\Scripting\SHDotNetRuntime.hpp" />
|
||||||
|
<ClInclude Include="src\Scripting\SHScriptEngine.h" />
|
||||||
<ClInclude Include="src\Tools\SHException.h" />
|
<ClInclude Include="src\Tools\SHException.h" />
|
||||||
<ClInclude Include="src\Tools\SHExceptionHandler.h" />
|
<ClInclude Include="src\Tools\SHExceptionHandler.h" />
|
||||||
<ClInclude Include="src\Tools\SHFileUtilties.h" />
|
<ClInclude Include="src\Tools\SHFileUtilties.h" />
|
||||||
<ClInclude Include="src\Tools\SHLogger.h" />
|
<ClInclude Include="src\Tools\SHLogger.h" />
|
||||||
|
<ClInclude Include="src\Tools\SHStringUtils.h" />
|
||||||
|
<ClInclude Include="src\Tools\SHStringUtils.hpp" />
|
||||||
<ClInclude Include="src\Tools\SHUtilities.h" />
|
<ClInclude Include="src\Tools\SHUtilities.h" />
|
||||||
|
<ClInclude Include="src\Tools\SHUtilities.hpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="src\ECS_Base\Components\SHComponent.cpp" />
|
<ClCompile Include="src\ECS_Base\Components\SHComponent.cpp" />
|
||||||
|
@ -274,10 +286,13 @@ xcopy /r /y /q "$(SolutionDir)/Dependencies/SDL/lib/SDL2.dll" "$(OutDir)"</Comm
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="src\Scene\SHSceneGraph.cpp" />
|
<ClCompile Include="src\Scene\SHSceneGraph.cpp" />
|
||||||
<ClCompile Include="src\Scene\SHSceneManager.cpp" />
|
<ClCompile Include="src\Scene\SHSceneManager.cpp" />
|
||||||
|
<ClCompile Include="src\Scripting\SHDotNetRuntime.cpp" />
|
||||||
|
<ClCompile Include="src\Scripting\SHScriptEngine.cpp" />
|
||||||
<ClCompile Include="src\Tools\SHException.cpp" />
|
<ClCompile Include="src\Tools\SHException.cpp" />
|
||||||
<ClCompile Include="src\Tools\SHExceptionHandler.cpp" />
|
<ClCompile Include="src\Tools\SHExceptionHandler.cpp" />
|
||||||
<ClCompile Include="src\Tools\SHFileUtilties.cpp" />
|
<ClCompile Include="src\Tools\SHFileUtilties.cpp" />
|
||||||
<ClCompile Include="src\Tools\SHLogger.cpp" />
|
<ClCompile Include="src\Tools\SHLogger.cpp" />
|
||||||
|
<ClCompile Include="src\Tools\SHStringUtils.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Dependencies\yamlcpp\yaml-cpp.vcxproj">
|
<ProjectReference Include="..\Dependencies\yamlcpp\yaml-cpp.vcxproj">
|
||||||
|
|
|
@ -115,6 +115,9 @@
|
||||||
<Filter Include="Scene">
|
<Filter Include="Scene">
|
||||||
<UniqueIdentifier>{B3F7140E-1F0C-3DBF-E88D-E01E546139F0}</UniqueIdentifier>
|
<UniqueIdentifier>{B3F7140E-1F0C-3DBF-E88D-E01E546139F0}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="Scripting">
|
||||||
|
<UniqueIdentifier>{985A7358-04C5-27CF-4D03-D974B9AC0524}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
<Filter Include="Tools">
|
<Filter Include="Tools">
|
||||||
<UniqueIdentifier>{16CF2D0E-82E3-55BF-4B65-F91EB73852F0}</UniqueIdentifier>
|
<UniqueIdentifier>{16CF2D0E-82E3-55BF-4B65-F91EB73852F0}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
@ -339,6 +342,9 @@
|
||||||
<ClInclude Include="src\Math\SHMathHelpers.h">
|
<ClInclude Include="src\Math\SHMathHelpers.h">
|
||||||
<Filter>Math</Filter>
|
<Filter>Math</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Math\SHMathHelpers.hpp">
|
||||||
|
<Filter>Math</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="src\Math\SHMatrix.h">
|
<ClInclude Include="src\Math\SHMatrix.h">
|
||||||
<Filter>Math</Filter>
|
<Filter>Math</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -360,12 +366,21 @@
|
||||||
<ClInclude Include="src\Resource\Handle.h">
|
<ClInclude Include="src\Resource\Handle.h">
|
||||||
<Filter>Resource</Filter>
|
<Filter>Resource</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Resource\Handle.hpp">
|
||||||
|
<Filter>Resource</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="src\Resource\ResourceLibrary.h">
|
<ClInclude Include="src\Resource\ResourceLibrary.h">
|
||||||
<Filter>Resource</Filter>
|
<Filter>Resource</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Resource\ResourceLibrary.hpp">
|
||||||
|
<Filter>Resource</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="src\Resource\SparseSet.h">
|
<ClInclude Include="src\Resource\SparseSet.h">
|
||||||
<Filter>Resource</Filter>
|
<Filter>Resource</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Resource\SparseSet.hpp">
|
||||||
|
<Filter>Resource</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="src\SHCommonTypes.h" />
|
<ClInclude Include="src\SHCommonTypes.h" />
|
||||||
<ClInclude Include="src\SH_API.h" />
|
<ClInclude Include="src\SH_API.h" />
|
||||||
<ClInclude Include="src\SHpch.h" />
|
<ClInclude Include="src\SHpch.h" />
|
||||||
|
@ -378,6 +393,15 @@
|
||||||
<ClInclude Include="src\Scene\SHSceneManager.h">
|
<ClInclude Include="src\Scene\SHSceneManager.h">
|
||||||
<Filter>Scene</Filter>
|
<Filter>Scene</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Scripting\SHDotNetRuntime.h">
|
||||||
|
<Filter>Scripting</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Scripting\SHDotNetRuntime.hpp">
|
||||||
|
<Filter>Scripting</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Scripting\SHScriptEngine.h">
|
||||||
|
<Filter>Scripting</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="src\Tools\SHException.h">
|
<ClInclude Include="src\Tools\SHException.h">
|
||||||
<Filter>Tools</Filter>
|
<Filter>Tools</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -390,9 +414,18 @@
|
||||||
<ClInclude Include="src\Tools\SHLogger.h">
|
<ClInclude Include="src\Tools\SHLogger.h">
|
||||||
<Filter>Tools</Filter>
|
<Filter>Tools</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Tools\SHStringUtils.h">
|
||||||
|
<Filter>Tools</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Tools\SHStringUtils.hpp">
|
||||||
|
<Filter>Tools</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="src\Tools\SHUtilities.h">
|
<ClInclude Include="src\Tools\SHUtilities.h">
|
||||||
<Filter>Tools</Filter>
|
<Filter>Tools</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Tools\SHUtilities.hpp">
|
||||||
|
<Filter>Tools</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="src\ECS_Base\Components\SHComponent.cpp">
|
<ClCompile Include="src\ECS_Base\Components\SHComponent.cpp">
|
||||||
|
@ -588,6 +621,12 @@
|
||||||
<ClCompile Include="src\Scene\SHSceneManager.cpp">
|
<ClCompile Include="src\Scene\SHSceneManager.cpp">
|
||||||
<Filter>Scene</Filter>
|
<Filter>Scene</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Scripting\SHDotNetRuntime.cpp">
|
||||||
|
<Filter>Scripting</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Scripting\SHScriptEngine.cpp">
|
||||||
|
<Filter>Scripting</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="src\Tools\SHException.cpp">
|
<ClCompile Include="src\Tools\SHException.cpp">
|
||||||
<Filter>Tools</Filter>
|
<Filter>Tools</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -600,5 +639,8 @@
|
||||||
<ClCompile Include="src\Tools\SHLogger.cpp">
|
<ClCompile Include="src\Tools\SHLogger.cpp">
|
||||||
<Filter>Tools</Filter>
|
<Filter>Tools</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Tools\SHStringUtils.cpp">
|
||||||
|
<Filter>Tools</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -12,6 +12,7 @@ project "SHADE_Engine"
|
||||||
files
|
files
|
||||||
{
|
{
|
||||||
"%{prj.location}/src/**.h",
|
"%{prj.location}/src/**.h",
|
||||||
|
"%{prj.location}/src/**.hpp",
|
||||||
"%{prj.location}/src/**.c",
|
"%{prj.location}/src/**.c",
|
||||||
"%{prj.location}/src/**.cpp",
|
"%{prj.location}/src/**.cpp",
|
||||||
"%{prj.location}/src/**.glsl",
|
"%{prj.location}/src/**.glsl",
|
||||||
|
@ -35,7 +36,8 @@ project "SHADE_Engine"
|
||||||
"%{IncludeDir.RTTR}/include",
|
"%{IncludeDir.RTTR}/include",
|
||||||
"%{IncludeDir.reactphysics3d}/include",
|
"%{IncludeDir.reactphysics3d}/include",
|
||||||
"%{IncludeDir.VULKAN}/include",
|
"%{IncludeDir.VULKAN}/include",
|
||||||
"%{IncludeDir.VULKAN}/Source/SPIRV-Reflect"
|
"%{IncludeDir.VULKAN}/Source/SPIRV-Reflect",
|
||||||
|
"%{IncludeDir.dotnet}/include",
|
||||||
}
|
}
|
||||||
|
|
||||||
libdirs
|
libdirs
|
||||||
|
@ -60,7 +62,7 @@ project "SHADE_Engine"
|
||||||
"SDL2.lib",
|
"SDL2.lib",
|
||||||
"SDL2main.lib",
|
"SDL2main.lib",
|
||||||
"shaderc_shared.lib",
|
"shaderc_shared.lib",
|
||||||
"shlwapi"
|
"shlwapi.lib"
|
||||||
}
|
}
|
||||||
|
|
||||||
disablewarnings
|
disablewarnings
|
||||||
|
@ -73,7 +75,7 @@ project "SHADE_Engine"
|
||||||
"_LIB",
|
"_LIB",
|
||||||
"_GLFW_INCLUDE_NONE",
|
"_GLFW_INCLUDE_NONE",
|
||||||
"MSDFGEN_USE_CPP11",
|
"MSDFGEN_USE_CPP11",
|
||||||
"NOMINMAX",
|
"NOMINMAX",
|
||||||
"SH_API_EXPORT"
|
"SH_API_EXPORT"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +96,8 @@ project "SHADE_Engine"
|
||||||
postbuildcommands
|
postbuildcommands
|
||||||
{
|
{
|
||||||
"xcopy /s /r /y /q \"%{IncludeDir.spdlog}/bin\" \"$(OutDir)\"",
|
"xcopy /s /r /y /q \"%{IncludeDir.spdlog}/bin\" \"$(OutDir)\"",
|
||||||
"xcopy /r /y /q \"%{IncludeDir.SDL}/lib/SDL2.dll\" \"$(OutDir)\""
|
"xcopy /r /y /q \"%{IncludeDir.SDL}/lib/SDL2.dll\" \"$(OutDir)\"",
|
||||||
|
"xcopy /s /r /y /q \"%{IncludeDir.dotnet}/bin\" \"$(OutDir)\""
|
||||||
}
|
}
|
||||||
|
|
||||||
warnings 'Extra'
|
warnings 'Extra'
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace SHADE
|
||||||
//SHEntityManager::RemoveEntity(this->entityID);
|
//SHEntityManager::RemoveEntity(this->entityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityID SHEntity::GetEID() noexcept
|
EntityID SHEntity::GetEID() const noexcept
|
||||||
{
|
{
|
||||||
return this->entityID;
|
return this->entityID;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ namespace SHADE
|
||||||
* \return uint32_t
|
* \return uint32_t
|
||||||
* The entityID of this Entity object.
|
* The entityID of this Entity object.
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
EntityID GetEID() noexcept;
|
EntityID GetEID() const noexcept;
|
||||||
|
|
||||||
/*!*************************************************************************
|
/*!*************************************************************************
|
||||||
* \brief Set the Active object
|
* \brief Set the Active object
|
||||||
|
|
|
@ -0,0 +1,198 @@
|
||||||
|
/*************************************************************************************//*!
|
||||||
|
\file SHDotNetRuntime.cpp
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 2, 2021
|
||||||
|
\brief Contains the definition of the SHDotNetRuntime class.
|
||||||
|
Implementation of code to set up code for SHDotNetRuntime is based on the
|
||||||
|
following repository:
|
||||||
|
https://github.com/mjrousos/SampleCoreCLRHost
|
||||||
|
|
||||||
|
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.
|
||||||
|
*//**************************************************************************************/
|
||||||
|
// Precompiled Header
|
||||||
|
#include <SHpch.h>
|
||||||
|
// Primary Header
|
||||||
|
#include "SHDotNetRuntime.h"
|
||||||
|
// Standard Library
|
||||||
|
#include <array>
|
||||||
|
// External Dependencies
|
||||||
|
#include <shlwapi.h> // PathRemoveFileSpecA
|
||||||
|
#include "Tools/SHLogger.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors/Destructor */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
SHDotNetRuntime::SHDotNetRuntime(bool autoInit)
|
||||||
|
{
|
||||||
|
if (autoInit)
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SHDotNetRuntime::~SHDotNetRuntime()
|
||||||
|
{
|
||||||
|
if (IsLoaded())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Exit();
|
||||||
|
}
|
||||||
|
catch (std::runtime_error& e)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR(e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Lifecycle Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void SHDotNetRuntime::Init()
|
||||||
|
{
|
||||||
|
// State checking, in case there was an unload before, we must ensure that the state is valid
|
||||||
|
if (initialised)
|
||||||
|
throw std::runtime_error("[DotNetRuntime] Failed to initialise as it was already initialised or was deinitialised into an invalid state.");
|
||||||
|
|
||||||
|
// Get the current executable directory
|
||||||
|
std::string runtimePath(MAX_PATH, '\0');
|
||||||
|
GetModuleFileNameA(nullptr, runtimePath.data(), MAX_PATH);
|
||||||
|
PathRemoveFileSpecA(runtimePath.data());
|
||||||
|
// Since PathRemoveFileSpecA() removes from data(), the size is not updated, so we must manually update it
|
||||||
|
runtimePath.resize(std::strlen(runtimePath.data()));
|
||||||
|
|
||||||
|
// Do not need to load the library if it was previously loaded
|
||||||
|
if (coreClr == nullptr)
|
||||||
|
{
|
||||||
|
// Construct the CoreCLR path
|
||||||
|
std::string coreClrPath(runtimePath); // Works
|
||||||
|
coreClrPath += "\\coreclr.dll";
|
||||||
|
|
||||||
|
// Load the CoreCLR DLL
|
||||||
|
coreClr = LoadLibraryExA(coreClrPath.c_str(), nullptr, 0);
|
||||||
|
if (!coreClr)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[DotNetRuntime] Error #" << GetLastError() << " Failed to load CoreCLR from \"" << coreClrPath << "\"\n";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2: Get CoreCLR hosting functions
|
||||||
|
initializeCoreClr = getCoreClrFunctionPtr<coreclr_initialize_ptr>("coreclr_initialize");
|
||||||
|
createManagedDelegate = getCoreClrFunctionPtr<coreclr_create_delegate_ptr>("coreclr_create_delegate");
|
||||||
|
shutdownCoreClr = getCoreClrFunctionPtr<coreclr_shutdown_ptr>("coreclr_shutdown");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3: Construct AppDomain properties used when starting the runtime
|
||||||
|
// Construct the trusted platform assemblies (TPA) list
|
||||||
|
// This is the list of assemblies that .NET Core can load as
|
||||||
|
// trusted system assemblies (similar to the .NET Framework GAC).
|
||||||
|
// For this host (as with most), assemblies next to CoreCLR will
|
||||||
|
// be included in the TPA list
|
||||||
|
std::string tpaList = buildTpaList(runtimePath);
|
||||||
|
|
||||||
|
// Define CoreCLR properties
|
||||||
|
std::array propertyKeys =
|
||||||
|
{
|
||||||
|
"TRUSTED_PLATFORM_ASSEMBLIES", // Trusted assemblies (like the GAC)
|
||||||
|
"APP_PATHS", // Directories to probe for application assemblies
|
||||||
|
// "APP_NI_PATHS", // Directories to probe for application native images (not used in this sample)
|
||||||
|
// "NATIVE_DLL_SEARCH_DIRECTORIES", // Directories to probe for native dlls (not used in this sample)
|
||||||
|
};
|
||||||
|
std::array propertyValues =
|
||||||
|
{
|
||||||
|
tpaList.c_str(),
|
||||||
|
runtimePath.c_str()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 4: Start the CoreCLR runtime
|
||||||
|
int result = initializeCoreClr
|
||||||
|
(
|
||||||
|
runtimePath.c_str(), // AppDomain base path
|
||||||
|
"SHADEHost", // AppDomain friendly name
|
||||||
|
static_cast<int>(propertyKeys.size()), // Property count
|
||||||
|
propertyKeys.data(), // Property names
|
||||||
|
propertyValues.data(), // Property values
|
||||||
|
&hostHandle, // Host handle
|
||||||
|
&domainId // AppDomain ID
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if intiialization of CoreCLR failed
|
||||||
|
throwIfFailed("[DotNetRuntime] Failed to initialize CoreCLR.", result);
|
||||||
|
|
||||||
|
initialised = true;
|
||||||
|
SHLOG_INFO("[DotNetRuntime] Successfully loaded the .NET 6.0 Runtime.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHDotNetRuntime::Exit()
|
||||||
|
{
|
||||||
|
// State checking, in case there was an unload before, we must ensure that the state is valid
|
||||||
|
if (!initialised)
|
||||||
|
throw std::runtime_error("[DotNetRuntime] Failed to deinitialise as it was not initialised before.");
|
||||||
|
|
||||||
|
// Shutdown CoreCLR
|
||||||
|
int result = shutdownCoreClr(hostHandle, domainId);
|
||||||
|
throwIfFailed("[DotNetRuntime] Failed to shut down CoreCLR.", result);
|
||||||
|
|
||||||
|
// Unset pointers
|
||||||
|
hostHandle = nullptr;
|
||||||
|
domainId = 0;
|
||||||
|
initialised = false;
|
||||||
|
|
||||||
|
SHLOG_INFO("[DotNetRuntime] Successfully shut down the .NET 6.0 Runtime.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
std::string SHDotNetRuntime::buildTpaList(const std::string& directory)
|
||||||
|
{
|
||||||
|
// Constants
|
||||||
|
static const std::string SEARCH_PATH = directory + "\\*.dll";
|
||||||
|
static constexpr char PATH_DELIMITER = ';';
|
||||||
|
|
||||||
|
// Create a osstream object to compile the string
|
||||||
|
std::ostringstream tpaList;
|
||||||
|
|
||||||
|
// Search the current directory for the TPAs (.DLLs)
|
||||||
|
WIN32_FIND_DATAA findData;
|
||||||
|
HANDLE fileHandle = FindFirstFileA(SEARCH_PATH.c_str(), &findData);
|
||||||
|
if (fileHandle != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// Append the assembly to the list
|
||||||
|
tpaList << directory << '\\' << findData.cFileName << PATH_DELIMITER;
|
||||||
|
|
||||||
|
// Note that the CLR does not guarantee which assembly will be loaded if an assembly
|
||||||
|
// is in the TPA list multiple times (perhaps from different paths or perhaps with different NI/NI.dll
|
||||||
|
// extensions. Therefore, a real host should probably add items to the list in priority order and only
|
||||||
|
// add a file if it's not already present on the list.
|
||||||
|
//
|
||||||
|
// For this simple sample, though, and because we're only loading TPA assemblies from a single path,
|
||||||
|
// and have no native images, we can ignore that complication.
|
||||||
|
}
|
||||||
|
while (FindNextFileA(fileHandle, &findData));
|
||||||
|
FindClose(fileHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tpaList.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHDotNetRuntime::throwIfFailed(const std::string& errMsg, int resultCode)
|
||||||
|
{
|
||||||
|
if (resultCode < 0)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << std::hex << std::setfill('0') << std::setw(8)
|
||||||
|
<< errMsg
|
||||||
|
<< " Error 0x" << resultCode << "\n";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,207 @@
|
||||||
|
/*************************************************************************************//*!
|
||||||
|
\file SHDotNetRuntime.h
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 2, 2021
|
||||||
|
\brief Contains the interface of a wrapper class for interfacing with the
|
||||||
|
.NET 5 Runtime.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
// Standard Libraries
|
||||||
|
#include <iomanip> // std::setfill, std::setw
|
||||||
|
#include <stdexcept> // std::runtime_error
|
||||||
|
#include <string> // std::string
|
||||||
|
#include <sstream> // std::ostringstream
|
||||||
|
// External Dependencies
|
||||||
|
#include <Windows.h> // HMODULE
|
||||||
|
#include <coreclrhost.h> // coreclr_*
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*************************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
class SHDotNetRuntime
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Class that encapsulates the state of the .NET Core Runtime lifecycle.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/*************************************************************************************/
|
||||||
|
|
||||||
|
class SHDotNetRuntime
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors/Destructor */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/***********************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Default constructor that immediately initializes the CoreCLR.
|
||||||
|
|
||||||
|
\param autoInit
|
||||||
|
If true, loads the CoreCLR by calling Init().
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***********************************************************************************/
|
||||||
|
SHDotNetRuntime(bool autoInit = true);
|
||||||
|
/***********************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Destructor that unloads the CoreCLR if it has not been unloaded yet.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***********************************************************************************/
|
||||||
|
~SHDotNetRuntime();
|
||||||
|
|
||||||
|
// Disallow copy and moving
|
||||||
|
SHDotNetRuntime(const SHDotNetRuntime&) = delete;
|
||||||
|
SHDotNetRuntime(SHDotNetRuntime&&) = delete;
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------------*/
|
||||||
|
/* Lifecycle Functions */
|
||||||
|
/*----------------------------------------------------------------------------------*/
|
||||||
|
/***********************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Loads the CoreCLR and grabs pointers to bootstrapping functions and kickstarts the
|
||||||
|
CoreCLR.
|
||||||
|
|
||||||
|
\throws std::runtime_error
|
||||||
|
Thrown if there is a failure in loading the CLR and related functions.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***********************************************************************************/
|
||||||
|
void Init();
|
||||||
|
/***********************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Unloads the CoreCLR.
|
||||||
|
|
||||||
|
\throws std::runtime_error
|
||||||
|
Thrown if there is a failure in unloading the CLR.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***********************************************************************************/
|
||||||
|
void Exit();
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------------*/
|
||||||
|
/* Usage Functions */
|
||||||
|
/*----------------------------------------------------------------------------------*/
|
||||||
|
/***********************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Checks if the DotNetRuntime has successfully been initialised.
|
||||||
|
|
||||||
|
\return
|
||||||
|
True if this DotNetRuntime has been initialised.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***********************************************************************************/
|
||||||
|
inline bool IsLoaded() const noexcept { return initialised; }
|
||||||
|
|
||||||
|
/***********************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Retrieves a function pointer from the a CLR assembly based on the specified
|
||||||
|
assembly, type and function names.
|
||||||
|
|
||||||
|
\tparam FunctionType
|
||||||
|
Type of the function pointer that the specified function name will provide.
|
||||||
|
\param assemblyName
|
||||||
|
Name of the CoreCLR assembly that contains the function.
|
||||||
|
\param typeName
|
||||||
|
Name of the CoreCLR type in the assembly that contains the function. Nested types
|
||||||
|
are separated by a period(.).
|
||||||
|
\param functionName
|
||||||
|
Name of the CoreCLR function to get a pointer to.
|
||||||
|
\return
|
||||||
|
Pointer to the function in the assembly that was specified.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***********************************************************************************/
|
||||||
|
template<typename FunctionType>
|
||||||
|
FunctionType GetFunctionPtr(const std::string_view& assemblyName,
|
||||||
|
const std::string_view& typeName,
|
||||||
|
const std::string_view& functionName) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
bool initialised = false;
|
||||||
|
// References to CoreCLR key components
|
||||||
|
HMODULE coreClr = nullptr;
|
||||||
|
void* hostHandle = nullptr;
|
||||||
|
unsigned int domainId = 0;
|
||||||
|
// Function Pointers to CoreCLR functions
|
||||||
|
coreclr_initialize_ptr initializeCoreClr = nullptr;
|
||||||
|
coreclr_create_delegate_ptr createManagedDelegate = nullptr;
|
||||||
|
coreclr_shutdown_ptr shutdownCoreClr = nullptr;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/***********************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Retrieves a function pointer from the CoreCLR based on the specified
|
||||||
|
function name.
|
||||||
|
|
||||||
|
\tparam FunctionType
|
||||||
|
Type of the function pointer that the specified function name will provide.
|
||||||
|
\param functionName
|
||||||
|
Name of the CoreCLR function to get a pointer to.
|
||||||
|
\return
|
||||||
|
Pointer to the function in the CoreCLR that was specified.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***********************************************************************************/
|
||||||
|
template<typename FunctionType>
|
||||||
|
FunctionType getCoreClrFunctionPtr(const std::string& functionName);
|
||||||
|
/***********************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Compiles a semicolon separated string of trusted platform assemblies by
|
||||||
|
searching the specified directory.
|
||||||
|
|
||||||
|
\param directory
|
||||||
|
Path to the directory where the trusted platform assemblies reside.
|
||||||
|
\return
|
||||||
|
Semicolon separated string of trusted platform assemblies.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***********************************************************************************/
|
||||||
|
static std::string buildTpaList(const std::string& directory);
|
||||||
|
/***********************************************************************************/
|
||||||
|
/*!
|
||||||
|
|
||||||
|
\brief
|
||||||
|
Takes in a Win32 result code and throws an exception it if there is an error.
|
||||||
|
|
||||||
|
\param errMsg
|
||||||
|
Error message to display if the resultCode is a failure code.
|
||||||
|
\param resultCode
|
||||||
|
Result code of the function to check.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/***********************************************************************************/
|
||||||
|
static void throwIfFailed(const std::string& errMsg, int resultCode);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "SHDotNetRuntime.hpp"
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*************************************************************************************//*!
|
||||||
|
\file SHDotNetRuntime.hpp
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 2, 2021
|
||||||
|
\brief Contains the implementation of the template functions of the
|
||||||
|
DotNetRuntime class.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
// Primary Include
|
||||||
|
#include "SHDotNetRuntime.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
template<typename FunctionType>
|
||||||
|
FunctionType SHDotNetRuntime::GetFunctionPtr(const std::string_view & assemblyName,
|
||||||
|
const std::string_view & typeName,
|
||||||
|
const std::string_view & functionName) const
|
||||||
|
{
|
||||||
|
FunctionType managedDelegate = nullptr;
|
||||||
|
int result = createManagedDelegate
|
||||||
|
(
|
||||||
|
hostHandle,
|
||||||
|
domainId,
|
||||||
|
assemblyName.data(),
|
||||||
|
typeName.data(),
|
||||||
|
functionName.data(),
|
||||||
|
reinterpret_cast<void**>(&managedDelegate)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if it failed
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << std::hex << std::setfill('0') << std::setw(8)
|
||||||
|
<< "[DotNetRuntime] Failed to get pointer to function \""
|
||||||
|
<< typeName << "." << functionName << "\" in assembly (" << assemblyName << "). "
|
||||||
|
<< "Error 0x" << result << "\n";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return managedDelegate;
|
||||||
|
}
|
||||||
|
template<typename FunctionType>
|
||||||
|
FunctionType SHDotNetRuntime::getCoreClrFunctionPtr(const std::string& functionName)
|
||||||
|
{
|
||||||
|
FunctionType fPtr = reinterpret_cast<FunctionType>(GetProcAddress(coreClr, functionName.c_str()));
|
||||||
|
if (!fPtr)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[DotNetRuntime] Unable to get pointer to function: \"" << functionName << "\"";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
return fPtr;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,506 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file SHScriptEngine.cpp
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Sep 17, 2021
|
||||||
|
\brief Contains the implementation for ScriptEngine class.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Precompiled Headers
|
||||||
|
#include <SHpch.h>
|
||||||
|
// Primary Header
|
||||||
|
#include "SHScriptEngine.h"
|
||||||
|
// Standard Library
|
||||||
|
#include <fstream> // std::fstream
|
||||||
|
#include <filesystem> // std::filesystem::canonical, std::filesystem::remove
|
||||||
|
// Project Headers
|
||||||
|
#include "Tools/SHLogger.h"
|
||||||
|
#include "Tools/SHStringUtils.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*--------------------------------------------------------------------------------*/
|
||||||
|
/* Static Definitions */
|
||||||
|
/*--------------------------------------------------------------------------------*/
|
||||||
|
const std::string SHScriptEngine::DEFAULT_CSHARP_NAMESPACE = std::string("SHADE");
|
||||||
|
SHDotNetRuntime SHScriptEngine::dotNet { false };
|
||||||
|
SHScriptEngine::CsFuncPtr SHScriptEngine::csEngineInit = nullptr;
|
||||||
|
SHScriptEngine::CsFuncPtr SHScriptEngine::csEngineLoadScripts = nullptr;
|
||||||
|
SHScriptEngine::CsFuncPtr SHScriptEngine::csEngineUnloadScripts = nullptr;
|
||||||
|
SHScriptEngine::CsFuncPtr SHScriptEngine::csEngineReloadScripts = nullptr;
|
||||||
|
SHScriptEngine::CsFuncPtr SHScriptEngine::csEngineExit = nullptr;
|
||||||
|
SHScriptEngine::CsFuncPtr SHScriptEngine::csScriptsFrameSetUp = nullptr;
|
||||||
|
SHScriptEngine::CsFuncPtr SHScriptEngine::csScriptsExecuteFixedUpdate = nullptr;
|
||||||
|
SHScriptEngine::CsFuncPtr SHScriptEngine::csScriptsExecuteUpdate = nullptr;
|
||||||
|
SHScriptEngine::CsFuncPtr SHScriptEngine::csScriptsExecuteLateUpdate = nullptr;
|
||||||
|
SHScriptEngine::CsFuncPtr SHScriptEngine::csScriptsFrameCleanUp = nullptr;
|
||||||
|
SHScriptEngine::CsScriptManipFuncPtr SHScriptEngine::csScriptsAdd = nullptr;
|
||||||
|
SHScriptEngine::CsScriptBasicFuncPtr SHScriptEngine::csScriptsRemoveAll = nullptr;
|
||||||
|
SHScriptEngine::CsScriptOptionalFuncPtr SHScriptEngine::csScriptsRemoveAllImmediately = nullptr;
|
||||||
|
SHScriptEngine::CsScriptSerialiseFuncPtr SHScriptEngine::csScriptsSerialise = nullptr;
|
||||||
|
SHScriptEngine::CsScriptDeserialiseFuncPtr SHScriptEngine::csScriptDeserialise = nullptr;
|
||||||
|
SHScriptEngine::CsScriptSerialiseYamlFuncPtr SHScriptEngine::csScriptsSerialiseYaml = nullptr;
|
||||||
|
SHScriptEngine::CsScriptSerialiseYamlFuncPtr SHScriptEngine::csScriptDeserialiseYaml = nullptr;
|
||||||
|
SHScriptEngine::CsScriptEditorFuncPtr SHScriptEngine::csEditorRenderScripts = nullptr;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Lifecycle Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void SHScriptEngine::Init()
|
||||||
|
{
|
||||||
|
// Do not allow initialization if already initialised
|
||||||
|
if (dotNet.IsLoaded())
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("[ScriptEngine] Attempted to initialise an already loaded DotNetRuntime.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dotNet.Init();
|
||||||
|
|
||||||
|
// Load all the helpers
|
||||||
|
loadFunctions();
|
||||||
|
|
||||||
|
// Generate script assembly if it hasn't been before
|
||||||
|
if (!fileExists(std::string(MANAGED_SCRIPT_LIB_NAME) + ".dll"))
|
||||||
|
{
|
||||||
|
BuildScriptAssembly();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialise the CSharp Engine
|
||||||
|
csEngineInit();
|
||||||
|
|
||||||
|
// Link events
|
||||||
|
// - Entity Destruction
|
||||||
|
/*onEntityDestroy = [this](const SHEntity& e)
|
||||||
|
{
|
||||||
|
csScriptsRemoveAll(e.GetEID());
|
||||||
|
csGOLibNotifyDestroyEntity(e.GetEID());
|
||||||
|
};
|
||||||
|
ECS::OnEntityDestroy += onEntityDestroy;*/
|
||||||
|
}
|
||||||
|
void SHScriptEngine::UnloadScriptAssembly()
|
||||||
|
{
|
||||||
|
csEngineUnloadScripts();
|
||||||
|
}
|
||||||
|
void SHScriptEngine::LoadScriptAssembly()
|
||||||
|
{
|
||||||
|
csEngineLoadScripts();
|
||||||
|
}
|
||||||
|
void SHScriptEngine::ReloadScriptAssembly()
|
||||||
|
{
|
||||||
|
csEngineReloadScripts();
|
||||||
|
}
|
||||||
|
void SHScriptEngine::ExecuteFixedUpdates()
|
||||||
|
{
|
||||||
|
csScriptsExecuteFixedUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHScriptEngine::Exit()
|
||||||
|
{
|
||||||
|
// Do not allow deinitialization if not initialised
|
||||||
|
if (!dotNet.IsLoaded())
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("[ScriptEngine] Attempted to clean up an unloaded DotNetRuntime.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unlink events
|
||||||
|
/*ECS::OnEntityCreated -= onEntityCreate;
|
||||||
|
ECS::OnEntityDestroy -= onEntityDestroy;*/
|
||||||
|
|
||||||
|
// Clean up the CSharp Engine
|
||||||
|
csEngineExit();
|
||||||
|
|
||||||
|
// Shut down the CLR
|
||||||
|
dotNet.Exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Script Manipulation Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
bool SHScriptEngine::AddScript(const SHEntity& entity, const std::string_view& scriptName)
|
||||||
|
{
|
||||||
|
return csScriptsAdd(entity.GetEID(), scriptName.data());
|
||||||
|
}
|
||||||
|
void SHScriptEngine::RemoveAllScripts(const SHEntity& entity)
|
||||||
|
{
|
||||||
|
csScriptsRemoveAll(entity.GetEID());
|
||||||
|
}
|
||||||
|
void SHScriptEngine::RemoveAllScriptsImmediately(const SHEntity& entity, bool callOnDestroy)
|
||||||
|
{
|
||||||
|
csScriptsRemoveAllImmediately(entity.GetEID(), callOnDestroy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Script Serialisation Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
std::string SHScriptEngine::SerialiseScripts(const SHEntity& entity)
|
||||||
|
{
|
||||||
|
// Create buffer needed to store serialised script data
|
||||||
|
constexpr int BUFFER_SIZE = 10240;
|
||||||
|
std::unique_ptr<char> buffer { new char[BUFFER_SIZE] };
|
||||||
|
std::memset(buffer.get(), 0, BUFFER_SIZE);
|
||||||
|
|
||||||
|
// Attempt to serialise the script
|
||||||
|
std::string result;
|
||||||
|
if (csScriptsSerialise(entity.GetEID(), buffer.get(), BUFFER_SIZE))
|
||||||
|
{
|
||||||
|
result = std::string(buffer.get());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("[ScriptEngine] Failed to serialise scripts as string buffer is too small!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return an empty string since we failed to serialise
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Script Serialisation Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void SHScriptEngine::DeserialiseScript(const SHEntity& entity, const std::string& yaml)
|
||||||
|
{
|
||||||
|
csScriptDeserialise(entity.GetEID(), yaml.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Script Editor Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void SHScriptEngine::RenderScriptsInInspector(const SHEntity& entity)
|
||||||
|
{
|
||||||
|
csEditorRenderScripts(entity.GetEID());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Static Utility Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
bool SHScriptEngine::BuildScriptAssembly(bool debug)
|
||||||
|
{
|
||||||
|
constexpr std::string_view BUILD_LOG_PATH = "../Build.log";
|
||||||
|
|
||||||
|
// Generate csproj file if it doesn't exist
|
||||||
|
static const std::filesystem::path CSPROJ_PATH = "../SHADE_Scripting.csproj";
|
||||||
|
if (!std::filesystem::exists(CSPROJ_PATH))
|
||||||
|
{
|
||||||
|
GenerateScriptsCsProjFile(CSPROJ_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare directory (delete useless files)
|
||||||
|
deleteFolder("net6.0");
|
||||||
|
deleteFolder("ref");
|
||||||
|
deleteFolder("../SHADE_Scripting");
|
||||||
|
deleteFolder("../obj");
|
||||||
|
|
||||||
|
// Attempt to build the assembly
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[ScriptEngine] Building " << (debug ? " debug " : "") << "Managed Script Assembly (" << MANAGED_SCRIPT_LIB_NAME << ")!";
|
||||||
|
SHLOG_INFO(oss.str());
|
||||||
|
oss.str("");
|
||||||
|
const bool BUILD_SUCCESS = execProcess
|
||||||
|
(
|
||||||
|
L"C:\\Windows\\system32\\cmd.exe",
|
||||||
|
L"/K \"dotnet build \"../SHADE_Scripting.csproj\" -c Debug -o \"./tmp/\" -fl -flp:LogFile=build.log;Verbosity=quiet & exit\""
|
||||||
|
) == 0;
|
||||||
|
if (BUILD_SUCCESS)
|
||||||
|
{
|
||||||
|
// Copy to built dll to the working directory and replace
|
||||||
|
std::filesystem::copy_file("./tmp/SHADE_Scripting.dll", "SHADE_Scripting.dll", std::filesystem::copy_options::overwrite_existing);
|
||||||
|
|
||||||
|
oss << "[ScriptEngine] Successfully built Managed Script Assembly (" << MANAGED_SCRIPT_LIB_NAME << ")!";
|
||||||
|
SHLOG_INFO(oss.str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oss << "[ScriptEngine] Failed to build Managed Script Assembly (" << MANAGED_SCRIPT_LIB_NAME << ")!";
|
||||||
|
SHLOG_ERROR(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up built files
|
||||||
|
deleteFolder("./tmp");
|
||||||
|
|
||||||
|
// Read the build log and output to the console
|
||||||
|
dumpBuildLog(BUILD_LOG_PATH);
|
||||||
|
// Delete the build log file since we no longer need it
|
||||||
|
deleteFile(BUILD_LOG_PATH);
|
||||||
|
|
||||||
|
return BUILD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHScriptEngine::GenerateScriptsCsProjFile(const std::filesystem::path& path)
|
||||||
|
{
|
||||||
|
// Sample
|
||||||
|
static std::string_view FILE_CONTENTS =
|
||||||
|
"<Project Sdk=\"Microsoft.NET.Sdk\">\n\
|
||||||
|
<PropertyGroup>\n\
|
||||||
|
<TargetFramework>net6.0</TargetFramework>\n\
|
||||||
|
<Platforms>x64</Platforms>\n\
|
||||||
|
<Configurations>Release;Debug</Configurations>\n\
|
||||||
|
</PropertyGroup>\n\
|
||||||
|
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n\
|
||||||
|
<OutputPath>.\\bin_Release-x64</OutputPath>\n\
|
||||||
|
<PlatformTarget>x64</PlatformTarget>\n\
|
||||||
|
</PropertyGroup>\n\
|
||||||
|
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\"> \n\
|
||||||
|
<OutputPath>.\\bin_Debug-x64</OutputPath>\n\
|
||||||
|
<PlatformTarget>x64</PlatformTarget>\n\
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>\n\
|
||||||
|
<Optimize>false</Optimize>\n\
|
||||||
|
<DebugType>full</DebugType>\n\
|
||||||
|
<DebugSymbols>true</DebugSymbols>\n\
|
||||||
|
</PropertyGroup>\n\
|
||||||
|
<ItemGroup>\n\
|
||||||
|
<Compile Remove=\"bin\\**\" />\n\
|
||||||
|
<EmbeddedResource Remove=\"Assets\\**\" />\n\
|
||||||
|
<EmbeddedResource Remove=\"bin\\**\" />\n\
|
||||||
|
<None Remove=\"bin\\**\" />\n\
|
||||||
|
</ItemGroup>\n\
|
||||||
|
<ItemGroup>\n\
|
||||||
|
<None Remove=\".gitignore\" />\n\
|
||||||
|
<None Remove=\".gitmodules\" />\n\
|
||||||
|
</ItemGroup>\n\
|
||||||
|
<ItemGroup>\n\
|
||||||
|
<Reference Include=\"SHADE_Managed\">\n\
|
||||||
|
<HintPath>.\\bin\\SHADE_Managed.dll</HintPath>\n\
|
||||||
|
</Reference>\n\
|
||||||
|
</ItemGroup>\n\
|
||||||
|
</Project>";
|
||||||
|
|
||||||
|
// Attempt to create the file
|
||||||
|
std::ofstream file(path);
|
||||||
|
if (!file.is_open())
|
||||||
|
throw std::runtime_error("Unable to create CsProj file!");
|
||||||
|
|
||||||
|
// Fill the file
|
||||||
|
file << FILE_CONTENTS;
|
||||||
|
|
||||||
|
// Close
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void SHScriptEngine::loadFunctions()
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[ScriptEngine] Loading \"" << DEFAULT_CSHARP_LIB_NAME << "\" CLR library.";
|
||||||
|
SHLOG_INFO(oss.str());
|
||||||
|
|
||||||
|
// Load functions
|
||||||
|
csEngineInit = dotNet.GetFunctionPtr<CsFuncPtr>
|
||||||
|
(
|
||||||
|
DEFAULT_CSHARP_LIB_NAME,
|
||||||
|
DEFAULT_CSHARP_NAMESPACE + ".EngineInterface",
|
||||||
|
"Init"
|
||||||
|
);
|
||||||
|
csEngineLoadScripts = dotNet.GetFunctionPtr<CsFuncPtr>
|
||||||
|
(
|
||||||
|
DEFAULT_CSHARP_LIB_NAME,
|
||||||
|
DEFAULT_CSHARP_NAMESPACE + ".EngineInterface",
|
||||||
|
"LoadScriptAssembly"
|
||||||
|
);
|
||||||
|
csEngineUnloadScripts = dotNet.GetFunctionPtr<CsFuncPtr>
|
||||||
|
(
|
||||||
|
DEFAULT_CSHARP_LIB_NAME,
|
||||||
|
DEFAULT_CSHARP_NAMESPACE + ".EngineInterface",
|
||||||
|
"UnloadScriptAssembly"
|
||||||
|
);
|
||||||
|
csEngineReloadScripts = dotNet.GetFunctionPtr<CsFuncPtr>
|
||||||
|
(
|
||||||
|
DEFAULT_CSHARP_LIB_NAME,
|
||||||
|
DEFAULT_CSHARP_NAMESPACE + ".EngineInterface",
|
||||||
|
"ReloadScriptAssembly"
|
||||||
|
);
|
||||||
|
csEngineExit = dotNet.GetFunctionPtr<CsFuncPtr>
|
||||||
|
(
|
||||||
|
DEFAULT_CSHARP_LIB_NAME,
|
||||||
|
DEFAULT_CSHARP_NAMESPACE + ".EngineInterface",
|
||||||
|
"Exit"
|
||||||
|
);
|
||||||
|
csScriptsFrameSetUp = dotNet.GetFunctionPtr<CsFuncPtr>
|
||||||
|
(
|
||||||
|
DEFAULT_CSHARP_LIB_NAME,
|
||||||
|
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
|
||||||
|
"FrameSetUp"
|
||||||
|
);
|
||||||
|
csScriptsExecuteFixedUpdate = dotNet.GetFunctionPtr<CsFuncPtr>
|
||||||
|
(
|
||||||
|
DEFAULT_CSHARP_LIB_NAME,
|
||||||
|
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
|
||||||
|
"ExecuteFixedUpdate"
|
||||||
|
);
|
||||||
|
csScriptsExecuteUpdate = dotNet.GetFunctionPtr<CsFuncPtr>
|
||||||
|
(
|
||||||
|
DEFAULT_CSHARP_LIB_NAME,
|
||||||
|
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
|
||||||
|
"ExecuteUpdate"
|
||||||
|
);
|
||||||
|
csScriptsExecuteLateUpdate = dotNet.GetFunctionPtr<CsFuncPtr>
|
||||||
|
(
|
||||||
|
DEFAULT_CSHARP_LIB_NAME,
|
||||||
|
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
|
||||||
|
"ExecuteLateUpdate"
|
||||||
|
);
|
||||||
|
csScriptsFrameCleanUp = dotNet.GetFunctionPtr<CsFuncPtr>
|
||||||
|
(
|
||||||
|
DEFAULT_CSHARP_LIB_NAME,
|
||||||
|
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
|
||||||
|
"FrameCleanUp"
|
||||||
|
);
|
||||||
|
csScriptsAdd = dotNet.GetFunctionPtr<CsScriptManipFuncPtr>
|
||||||
|
(
|
||||||
|
DEFAULT_CSHARP_LIB_NAME,
|
||||||
|
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
|
||||||
|
"AddScriptViaName"
|
||||||
|
);
|
||||||
|
csScriptsRemoveAll = dotNet.GetFunctionPtr<CsScriptBasicFuncPtr>
|
||||||
|
(
|
||||||
|
DEFAULT_CSHARP_LIB_NAME,
|
||||||
|
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
|
||||||
|
"RemoveAllScripts"
|
||||||
|
);
|
||||||
|
csScriptsRemoveAllImmediately = dotNet.GetFunctionPtr<CsScriptOptionalFuncPtr>
|
||||||
|
(
|
||||||
|
DEFAULT_CSHARP_LIB_NAME,
|
||||||
|
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
|
||||||
|
"RemoveAllScriptsImmediately"
|
||||||
|
);
|
||||||
|
/*csScriptsSerialise = dotNet.GetFunctionPtr<CsScriptSerialiseFuncPtr>
|
||||||
|
(
|
||||||
|
DEFAULT_CSHARP_LIB_NAME,
|
||||||
|
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
|
||||||
|
"SerialiseScripts"
|
||||||
|
);
|
||||||
|
csScriptsSerialiseYaml = dotNet.GetFunctionPtr<CsScriptSerialiseYamlFuncPtr>
|
||||||
|
(
|
||||||
|
DEFAULT_CSHARP_LIB_NAME,
|
||||||
|
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
|
||||||
|
"SerialiseScriptsYaml"
|
||||||
|
);
|
||||||
|
csScriptDeserialise = dotNet.GetFunctionPtr<CsScriptDeserialiseFuncPtr>
|
||||||
|
(
|
||||||
|
DEFAULT_CSHARP_LIB_NAME,
|
||||||
|
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
|
||||||
|
"DeserialiseScript"
|
||||||
|
);
|
||||||
|
csScriptDeserialiseYaml = dotNet.GetFunctionPtr<CsScriptSerialiseYamlFuncPtr>
|
||||||
|
(
|
||||||
|
DEFAULT_CSHARP_LIB_NAME,
|
||||||
|
DEFAULT_CSHARP_NAMESPACE + ".ScriptStore",
|
||||||
|
"SerialiseScriptsYaml"
|
||||||
|
);
|
||||||
|
csEditorRenderScripts = dotNet.GetFunctionPtr<CsScriptEditorFuncPtr>
|
||||||
|
(
|
||||||
|
DEFAULT_CSHARP_LIB_NAME,
|
||||||
|
DEFAULT_CSHARP_NAMESPACE + ".Editor",
|
||||||
|
"RenderScriptsInInspector"
|
||||||
|
);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHScriptEngine::dumpBuildLog(const std::string_view& buildLogPath)
|
||||||
|
{
|
||||||
|
std::ifstream buildLog(buildLogPath);
|
||||||
|
|
||||||
|
// Fail to open
|
||||||
|
if (!buildLog.is_open())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Process line by line
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(buildLog, line))
|
||||||
|
{
|
||||||
|
if (line.find("error") != line.npos)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR(line);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SHLOG_WARNING(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void SHScriptEngine::deleteFile(const std::string_view& filePath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
std::filesystem::remove(std::filesystem::canonical(filePath));
|
||||||
|
}
|
||||||
|
catch (...) {} // Ignore deletion failures
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHScriptEngine::deleteFolder(const std::string_view& filePath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
std::filesystem::remove_all(std::filesystem::canonical(filePath));
|
||||||
|
}
|
||||||
|
catch (...) {} // Ignore deletion failures
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHScriptEngine::fileExists(const std::string_view& filePath)
|
||||||
|
{
|
||||||
|
std::error_code error;
|
||||||
|
if (std::filesystem::exists(filePath, error))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD SHScriptEngine::execProcess(const std::wstring& path, const std::wstring& args)
|
||||||
|
{
|
||||||
|
STARTUPINFOW startInfo;
|
||||||
|
PROCESS_INFORMATION procInfo;
|
||||||
|
ZeroMemory(&startInfo, sizeof(startInfo));
|
||||||
|
ZeroMemory(&procInfo, sizeof(procInfo));
|
||||||
|
startInfo.cb = sizeof(startInfo);
|
||||||
|
|
||||||
|
std::wstring argsWstr = args;
|
||||||
|
|
||||||
|
// Start Process
|
||||||
|
const auto SUCCESS = CreateProcess
|
||||||
|
(
|
||||||
|
path.data(), argsWstr.data(),
|
||||||
|
nullptr, nullptr, false, NULL, nullptr, nullptr,
|
||||||
|
&startInfo, &procInfo
|
||||||
|
);
|
||||||
|
|
||||||
|
// Error Check
|
||||||
|
if (!SUCCESS)
|
||||||
|
{
|
||||||
|
auto err = GetLastError();
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[ScriptEngine] Failed to launch process. Error code: " << std::hex << err
|
||||||
|
<< " (" << SHStringUtils::GetWin32ErrorMessage(err) << ")";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for execution to end
|
||||||
|
DWORD status;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
const auto SUCCESS = GetExitCodeProcess(procInfo.hProcess, &status);
|
||||||
|
if (!SUCCESS)
|
||||||
|
{
|
||||||
|
auto err = GetLastError();
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[ScriptEngine] Failed to query process. Error code: " << std::hex << err
|
||||||
|
<< " (" << SHStringUtils::GetWin32ErrorMessage(err) << ")";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Break only if process ends
|
||||||
|
if (status != STILL_ACTIVE)
|
||||||
|
{
|
||||||
|
CloseHandle(procInfo.hProcess);
|
||||||
|
CloseHandle(procInfo.hThread);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,247 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file ScriptEngine.h
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Sep 17, 2021
|
||||||
|
\brief Contains the interface for ScriptEngine class.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
// STL Includes
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
// Project Headers
|
||||||
|
#include "SHDotNetRuntime.h"
|
||||||
|
#include "ECS_Base/SHECSMacros.h"
|
||||||
|
#include "ECS_Base/Entity/SHEntity.h"
|
||||||
|
#include "SH_API.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Manages initialisation of the DotNetRuntime and interfacing with CLR code written
|
||||||
|
/// and executed on .NET.
|
||||||
|
/// </summary>
|
||||||
|
class SH_API SHScriptEngine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Constructor */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
SHScriptEngine() = delete;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Lifecycle Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Initialises the DotNetRuntime and retrieves function pointers to all
|
||||||
|
/// functions on the CLR used to interface with the engine.
|
||||||
|
/// </summary>
|
||||||
|
static void Init();
|
||||||
|
/// <summary>
|
||||||
|
/// Loads the managed script assembly. Ensure this is only called after
|
||||||
|
/// UnloadScriptAssembly() has been called.
|
||||||
|
/// </summary>
|
||||||
|
static void UnloadScriptAssembly();
|
||||||
|
/// <summary>
|
||||||
|
/// Unloads the managed script assembly.
|
||||||
|
/// Take note that this will clear all existing scripts, ensure that the scene
|
||||||
|
/// is saved before doing so.
|
||||||
|
/// </summary>
|
||||||
|
static void LoadScriptAssembly();
|
||||||
|
/// <summary>
|
||||||
|
/// Reloads the managed script assembly.
|
||||||
|
/// Take note that this will clear all existing scripts, ensure that the scene
|
||||||
|
/// is saved before doing so.
|
||||||
|
/// </summary>
|
||||||
|
static void ReloadScriptAssembly();
|
||||||
|
/// <summary>
|
||||||
|
/// Executes the FixedUpdate()s of the Scripts that are attached to
|
||||||
|
/// Entities.
|
||||||
|
/// </summary>
|
||||||
|
static void ExecuteFixedUpdates();
|
||||||
|
/// <summary>
|
||||||
|
/// Shuts down the DotNetRuntime.
|
||||||
|
/// </summary>
|
||||||
|
static void Exit();
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Script Manipulation Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a Script to a specified Entity. Note that while you can call this
|
||||||
|
/// multiple times on a specified Entity, it will work for all intents and
|
||||||
|
/// purposes but GetScript<T>() (C# only) currently only
|
||||||
|
/// gives you the first Script added of the specified type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">The entity to add a script to.</param>
|
||||||
|
/// <param name="scriptName">Type name of the script to add.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// True if successfully added. False otherwise with the error logged to the
|
||||||
|
/// console.
|
||||||
|
/// </returns>
|
||||||
|
static bool AddScript(const SHEntity& entity, const std::string_view& scriptName);
|
||||||
|
/// <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(const SHEntity& 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(const SHEntity& entity, bool callOnDestroy);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Script Serialisation Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a JSON string that represents the set of Scripts attached to the
|
||||||
|
/// specified Entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity"> The Entity to Serialise.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// String that represents the set of scripts attached to the specified Entity.
|
||||||
|
/// </returns>
|
||||||
|
static std::string SerialiseScripts(const SHEntity& entity);
|
||||||
|
/// <summary>
|
||||||
|
/// Loads the specified JSON string and creates a Script for the specified Entity
|
||||||
|
/// based on the specified JSON string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">The Entity to deserialise a Script on to.</param>
|
||||||
|
/// <param name="yaml">
|
||||||
|
/// The YAML string that represents the Script to load into the Entity.
|
||||||
|
/// </param>
|
||||||
|
static void DeserialiseScript(const SHEntity& entity, const std::string& yaml);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Script Editor Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Renders the set of attached Scripts for the specified Entity into the
|
||||||
|
/// inspector.
|
||||||
|
/// <br/>
|
||||||
|
/// This function is meant for consumption from native code in the inspector
|
||||||
|
/// rendering code.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">The Entity to render the Scripts of.</param>
|
||||||
|
static void RenderScriptsInInspector(const SHEntity& entity);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Static Utility Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Utilises execution of a external batch file for invoking the dotnet build
|
||||||
|
/// tool to compile C# scripts in the Assets folder into the SHADE_Scripting
|
||||||
|
/// C# assembly DLL.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="debug">
|
||||||
|
/// Whether or not a debug build will be built. Only debug built C# assemblies
|
||||||
|
/// can be debugged.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>Whether or not the build succeeded.</returns>
|
||||||
|
static bool BuildScriptAssembly(bool debug = false);
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a .csproj file for editing and compiling the C# scripts.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">File path to the generated file.</param>
|
||||||
|
static void GenerateScriptsCsProjFile(const std::filesystem::path& path);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
using CsFuncPtr = void(*)(void);
|
||||||
|
using CsScriptManipFuncPtr = bool(*)(EntityID, const char*);
|
||||||
|
using CsScriptBasicFuncPtr = void(*)(EntityID);
|
||||||
|
using CsScriptOptionalFuncPtr = void(*)(EntityID, bool);
|
||||||
|
using CsScriptSerialiseFuncPtr = bool(*)(EntityID, char*, int);
|
||||||
|
using CsScriptDeserialiseFuncPtr = bool(*)(EntityID, const char*);
|
||||||
|
using CsScriptSerialiseYamlFuncPtr = bool(*)(EntityID, void*);
|
||||||
|
using CsScriptEditorFuncPtr = void(*)(EntityID);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Constants */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
static constexpr std::string_view DEFAULT_CSHARP_LIB_NAME = "SHADE_Managed";
|
||||||
|
static constexpr std::string_view MANAGED_SCRIPT_LIB_NAME = "SHADE_Scripting";
|
||||||
|
static const std::string DEFAULT_CSHARP_NAMESPACE;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
static SHDotNetRuntime dotNet;
|
||||||
|
// Function Pointers to CLR Code
|
||||||
|
// - Engine Lifecycle
|
||||||
|
static CsFuncPtr csEngineInit;
|
||||||
|
static CsFuncPtr csEngineLoadScripts;
|
||||||
|
static CsFuncPtr csEngineUnloadScripts;
|
||||||
|
static CsFuncPtr csEngineReloadScripts;
|
||||||
|
static CsFuncPtr csEngineExit;
|
||||||
|
// - Scripts Store
|
||||||
|
static CsFuncPtr csScriptsFrameSetUp;
|
||||||
|
static CsFuncPtr csScriptsExecuteFixedUpdate;
|
||||||
|
static CsFuncPtr csScriptsExecuteUpdate;
|
||||||
|
static CsFuncPtr csScriptsExecuteLateUpdate;
|
||||||
|
static CsFuncPtr csScriptsFrameCleanUp;
|
||||||
|
static CsScriptManipFuncPtr csScriptsAdd;
|
||||||
|
static CsScriptBasicFuncPtr csScriptsRemoveAll;
|
||||||
|
static CsScriptOptionalFuncPtr csScriptsRemoveAllImmediately;
|
||||||
|
static CsScriptSerialiseFuncPtr csScriptsSerialise;
|
||||||
|
static CsScriptDeserialiseFuncPtr csScriptDeserialise;
|
||||||
|
static CsScriptSerialiseYamlFuncPtr csScriptsSerialiseYaml;
|
||||||
|
static CsScriptSerialiseYamlFuncPtr csScriptDeserialiseYaml;
|
||||||
|
// - Editor
|
||||||
|
static CsScriptEditorFuncPtr csEditorRenderScripts;
|
||||||
|
// Delegates
|
||||||
|
/*ECS::EntityEvent::Delegate onEntityCreate;
|
||||||
|
ECS::EntityEvent::Delegate onEntityDestroy;*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Loads all the function pointers to CLR code that we need to execute.
|
||||||
|
/// </summary>
|
||||||
|
static void loadFunctions();
|
||||||
|
/// <summary>
|
||||||
|
/// Reads the file via the specified path that represents a build log of error
|
||||||
|
/// and warning messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buildLogPath">
|
||||||
|
/// File path to the build log of script builds done by BuildScriptAssembly() to
|
||||||
|
/// dump and process.
|
||||||
|
/// </param>
|
||||||
|
static void dumpBuildLog(const std::string_view& buildLogPath);
|
||||||
|
/// <summary>
|
||||||
|
/// Deletes the file as specified by the file path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filePath">File path to the file to delete.</param>
|
||||||
|
static void deleteFile(const std::string_view& filePath);
|
||||||
|
/// <summary>
|
||||||
|
/// Deletes the folder and all files in it as specified by the file path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filePath">File path to the file to delete.</param>
|
||||||
|
static void deleteFolder(const std::string_view& filePath);
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a specified file exists.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filePath">File path to the file to check.</param>
|
||||||
|
/// <returns> True if the file exists </returns>
|
||||||
|
static bool fileExists(const std::string_view& filePath);
|
||||||
|
static DWORD execProcess(const std::wstring& path, const std::wstring& args);
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file StringUtilities.cpp
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Nov 29, 2021
|
||||||
|
\brief Contains the definition of functions for working with strings.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Precompiled Header
|
||||||
|
#include <SHpch.h>
|
||||||
|
// Primary Header
|
||||||
|
#include "SHStringUtils.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Utility Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
std::vector<std::string> SHStringUtils::Split(const std::string& str, const char& delim)
|
||||||
|
{
|
||||||
|
return Split<char>(str, delim);
|
||||||
|
}
|
||||||
|
std::vector<std::wstring> SHStringUtils::Split(const std::wstring& str, const wchar_t& delim)
|
||||||
|
{
|
||||||
|
return Split<wchar_t>(str, delim);
|
||||||
|
}
|
||||||
|
std::string SHStringUtils::WstrToStr(const std::wstring& wstr)
|
||||||
|
{
|
||||||
|
static std::vector<char> buffer;
|
||||||
|
const int STR_SIZE = WideCharToMultiByte(CP_UTF8, 0, wstr.data(), static_cast<int>(wstr.size()), nullptr, 0, nullptr, nullptr) + 1 /* Null Terminator */;
|
||||||
|
buffer.resize(STR_SIZE);
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, wstr.data(), static_cast<int>(wstr.size()), buffer.data(), MAX_PATH, nullptr, nullptr);
|
||||||
|
return std::string(buffer.data());
|
||||||
|
}
|
||||||
|
std::wstring SHStringUtils::StrToWstr(const std::string& str)
|
||||||
|
{
|
||||||
|
static std::vector<wchar_t> buffer;
|
||||||
|
const int WSTR_SIZE = MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast<int>(str.size()), nullptr, 0) + 1 /* Null Terminator */;
|
||||||
|
buffer.resize(WSTR_SIZE);
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast<int>(str.size()), buffer.data(), WSTR_SIZE);
|
||||||
|
return std::wstring(buffer.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SHStringUtils::GetWin32ErrorMessage(unsigned long errorCode)
|
||||||
|
{
|
||||||
|
return std::system_category().message(errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file StringUtilities.h
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Nov 29, 2021
|
||||||
|
\brief Contains the declaration of functions for working with files and folders.
|
||||||
|
|
||||||
|
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
|
||||||
|
// Standard Libraries
|
||||||
|
#include <string> // std::basic_string
|
||||||
|
#include <vector> // std::vector
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Contains useful functions for operating on strings.
|
||||||
|
/// </summary>
|
||||||
|
class SHStringUtils
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Utility Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Splits a string separated by a specified delimiter into a vector of strings.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Internal type of each element in the string.</typeparam>
|
||||||
|
/// <param name="str">Read only reference to the string to split.</param>
|
||||||
|
/// <param name="delim">Read only reference to the delimiter.</param>
|
||||||
|
/// <returns>Vector of strings that have been split.</returns>
|
||||||
|
template<typename T>
|
||||||
|
static std::vector<std::basic_string<T>> Split(const std::basic_string<T>& str, const T& delim);
|
||||||
|
/// <summary>
|
||||||
|
/// Splits a string separated by a specified delimiter into a vector of strings.
|
||||||
|
/// Overload of Split<T>() to allow for string literals to be accepted.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">Read only reference to the string to split.</param>
|
||||||
|
/// <param name="delim">Read only reference to the delimiter.</param>
|
||||||
|
/// <returns>Vector of strings that have been split.</returns>
|
||||||
|
static std::vector<std::string> Split(const std::string& str, const char& delim);
|
||||||
|
/// <summary>
|
||||||
|
/// Splits a string separated by a specified delimiter into a vector of strings.
|
||||||
|
/// Overload of Split<T>() to allow for wide string literals to be accepted.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">Read only reference to the string to split.</param>
|
||||||
|
/// <param name="delim">Read only reference to the delimiter.</param>
|
||||||
|
/// <returns>Vector of strings that have been split.</returns>
|
||||||
|
static std::vector<std::wstring> Split(const std::wstring& str, const wchar_t& delim);
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a wstring to a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="wstr">wstring to convert.</param>
|
||||||
|
/// <returns>The converted wstring in string form.</returns>
|
||||||
|
static std::string WstrToStr(const std::wstring& wstr);
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a string to a wstring.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">string to convert.</param>
|
||||||
|
/// <returns>The converted string in wstring form.</returns>
|
||||||
|
static std::wstring StrToWstr(const std::string& str);
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the error message associated with a Win32 error code.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="errorCode">Win32 error code to decode.</param>
|
||||||
|
/// <returns>String that represents the Win32 error.</returns>
|
||||||
|
static std::string GetWin32ErrorMessage(unsigned long errorCode);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors/Destructors */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
SHStringUtils() = delete;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "SHStringUtils.hpp"
|
|
@ -0,0 +1,46 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file StringUtilities.hpp
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Nov 29, 2021
|
||||||
|
\brief Contains the implementation of template functions for working with files
|
||||||
|
and folders.
|
||||||
|
|
||||||
|
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
|
||||||
|
// Primary Header
|
||||||
|
#include "SHStringUtils.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Template Function Definitions */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
template<typename T>
|
||||||
|
inline std::vector<std::basic_string<T>> SHStringUtils::Split(const std::basic_string<T>& str, const T& delim)
|
||||||
|
{
|
||||||
|
std::vector<std::basic_string<T>> results;
|
||||||
|
std::basic_string<T> remaining = str;
|
||||||
|
|
||||||
|
// Go through looking for delimiters
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
const size_t DELIM_POS = remaining.find_first_of(delim);
|
||||||
|
results.emplace_back(remaining.substr(0, DELIM_POS));
|
||||||
|
|
||||||
|
// Check if we hit the end of the string
|
||||||
|
if (DELIM_POS == remaining.npos)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, cut the remainder
|
||||||
|
remaining = remaining.substr(DELIM_POS + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,113 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Components">
|
||||||
|
<UniqueIdentifier>{6B7DD516-5735-1764-C03C-F0BFAC13B254}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Engine">
|
||||||
|
<UniqueIdentifier>{DBC7D3B0-C769-FE86-B024-12DB9C6585D7}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Math">
|
||||||
|
<UniqueIdentifier>{AFF4887C-9B2B-8A0D-4418-7010302E060F}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Scripts">
|
||||||
|
<UniqueIdentifier>{4D6F1AE8-B94E-9983-C266-245A2EC5FFE4}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Utility">
|
||||||
|
<UniqueIdentifier>{594615A9-C525-9444-CE3D-1F1B3A9CFAA5}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="src\Components\Component.hxx">
|
||||||
|
<Filter>Components</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Engine\ECS.hxx">
|
||||||
|
<Filter>Engine</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Engine\EngineInterface.hxx">
|
||||||
|
<Filter>Engine</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Engine\Entity.hxx">
|
||||||
|
<Filter>Engine</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Engine\GameObject.hxx">
|
||||||
|
<Filter>Engine</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Math\Math.hxx">
|
||||||
|
<Filter>Math</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Math\Vector2.hxx">
|
||||||
|
<Filter>Math</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Math\Vector3.hxx">
|
||||||
|
<Filter>Math</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\SHpch.h" />
|
||||||
|
<ClInclude Include="src\Scripts\Script.hxx">
|
||||||
|
<Filter>Scripts</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Scripts\ScriptStore.hxx">
|
||||||
|
<Filter>Scripts</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Utility\Convert.hxx">
|
||||||
|
<Filter>Utility</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Utility\Debug.hxx">
|
||||||
|
<Filter>Utility</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Utility\DisposableAssemblyLoadContext.hxx">
|
||||||
|
<Filter>Utility</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="src\AssemblyInfo.cxx" />
|
||||||
|
<ClCompile Include="src\Components\Component.cxx">
|
||||||
|
<Filter>Components</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Engine\ECS.cxx">
|
||||||
|
<Filter>Engine</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Engine\EngineInterface.cxx">
|
||||||
|
<Filter>Engine</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Engine\Entity.cxx">
|
||||||
|
<Filter>Engine</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Engine\GameObject.cxx">
|
||||||
|
<Filter>Engine</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Math\Math.cxx">
|
||||||
|
<Filter>Math</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Math\Vector2.cxx">
|
||||||
|
<Filter>Math</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Math\Vector3.cxx">
|
||||||
|
<Filter>Math</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\SHpch.cpp" />
|
||||||
|
<ClCompile Include="src\Scripts\Script.cxx">
|
||||||
|
<Filter>Scripts</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Scripts\ScriptStore.cxx">
|
||||||
|
<Filter>Scripts</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Utility\Convert.cxx">
|
||||||
|
<Filter>Utility</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Utility\Debug.cxx">
|
||||||
|
<Filter>Utility</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Utility\DisposableAssemblyLoadContext.cxx">
|
||||||
|
<Filter>Utility</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="src\Components\Component.h++">
|
||||||
|
<Filter>Components</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="src\Engine\ECS.h++">
|
||||||
|
<Filter>Engine</Filter>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1,74 @@
|
||||||
|
project "SHADE_Managed"
|
||||||
|
kind "SharedLib"
|
||||||
|
language "C++"
|
||||||
|
clr "NetCore"
|
||||||
|
dotnetframework "net6.0"
|
||||||
|
cppdialect "C++17"
|
||||||
|
targetdir (outputdir)
|
||||||
|
objdir (interdir)
|
||||||
|
systemversion "latest"
|
||||||
|
pchheader "SHpch.h"
|
||||||
|
pchsource "%{prj.location}/src/SHpch.cpp"
|
||||||
|
staticruntime "off"
|
||||||
|
|
||||||
|
files
|
||||||
|
{
|
||||||
|
"%{prj.location}/src/**.hxx",
|
||||||
|
"%{prj.location}/src/**.h++",
|
||||||
|
"%{prj.location}/src/**.cxx",
|
||||||
|
"%{prj.location}/src/**.h",
|
||||||
|
"%{prj.location}/src/**.hpp",
|
||||||
|
"%{prj.location}/src/**.c",
|
||||||
|
"%{prj.location}/src/**.cpp",
|
||||||
|
}
|
||||||
|
|
||||||
|
includedirs
|
||||||
|
{
|
||||||
|
"%{prj.location}/src",
|
||||||
|
"%{IncludeDir.spdlog}/include",
|
||||||
|
"%{IncludeDir.imgui}",
|
||||||
|
"%{IncludeDir.imguizmo}",
|
||||||
|
"%{IncludeDir.imnodes}",
|
||||||
|
"%{IncludeDir.yamlcpp}",
|
||||||
|
"%{IncludeDir.RTTR}/include",
|
||||||
|
"%{wks.location}/SHADE_Engine/src"
|
||||||
|
}
|
||||||
|
|
||||||
|
links
|
||||||
|
{
|
||||||
|
"yaml-cpp",
|
||||||
|
"imgui",
|
||||||
|
"SHADE_Engine"
|
||||||
|
}
|
||||||
|
|
||||||
|
disablewarnings
|
||||||
|
{
|
||||||
|
"4251"
|
||||||
|
}
|
||||||
|
|
||||||
|
defines
|
||||||
|
{
|
||||||
|
"NOMINMAX"
|
||||||
|
}
|
||||||
|
|
||||||
|
flags
|
||||||
|
{
|
||||||
|
"MultiProcessorCompile"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependson
|
||||||
|
{
|
||||||
|
"yaml-cpp",
|
||||||
|
"imgui",
|
||||||
|
"SHADE_Engine"
|
||||||
|
}
|
||||||
|
|
||||||
|
warnings 'Extra'
|
||||||
|
|
||||||
|
filter "configurations:Debug"
|
||||||
|
symbols "On"
|
||||||
|
defines {"_DEBUG"}
|
||||||
|
|
||||||
|
filter "configurations:Release"
|
||||||
|
optimize "On"
|
||||||
|
defines{"_RELEASE"}
|
|
@ -0,0 +1,39 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file AssemblyInfo.cxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 24, 2021
|
||||||
|
\brief Defines the properties of this managed .NET Assembly.
|
||||||
|
|
||||||
|
Note: This file is written in C++17/CLI.
|
||||||
|
|
||||||
|
Copyright (C) 2022 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.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
#include "SHpch.h"
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------------*/
|
||||||
|
/* Using Declarations */
|
||||||
|
/*-------------------------------------------------------------------------------------*/
|
||||||
|
using namespace System;
|
||||||
|
using namespace System::Reflection;
|
||||||
|
using namespace System::Runtime::CompilerServices;
|
||||||
|
using namespace System::Runtime::InteropServices;
|
||||||
|
using namespace System::Security::Permissions;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------------*/
|
||||||
|
/* Assembly Properties */
|
||||||
|
/*-------------------------------------------------------------------------------------*/
|
||||||
|
[assembly:AssemblyTitleAttribute(L"SHADE_Managed")];
|
||||||
|
[assembly:AssemblyDescriptionAttribute(L"")];
|
||||||
|
[assembly:AssemblyConfigurationAttribute(L"")];
|
||||||
|
[assembly:AssemblyCompanyAttribute(L"")];
|
||||||
|
[assembly:AssemblyProductAttribute(L"SHADE_Managed")];
|
||||||
|
[assembly:AssemblyCopyrightAttribute(L"Copyright (C) 2022 DigiPen Institute of Technology")];
|
||||||
|
[assembly:AssemblyTrademarkAttribute(L"")];
|
||||||
|
[assembly:AssemblyCultureAttribute(L"")];
|
||||||
|
|
||||||
|
[assembly:AssemblyVersionAttribute("1.0.*")];
|
||||||
|
|
||||||
|
[assembly:ComVisible(false)];
|
|
@ -0,0 +1,107 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file Component.cxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 27, 2021
|
||||||
|
\brief Contains the definition of the functions for the Component class.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Precompiled Headers
|
||||||
|
#include "SHpch.h"
|
||||||
|
// Primary Header
|
||||||
|
#include "Components/Component.hxx"
|
||||||
|
// External Dependencies
|
||||||
|
#include "Engine/ECS.hxx"
|
||||||
|
// Project Headers
|
||||||
|
#include "Scripts/ScriptStore.hxx"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Component Access Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
generic <typename T>
|
||||||
|
T BaseComponent::AddComponent()
|
||||||
|
{
|
||||||
|
return ECS::AddComponent<T>(owner.GetEntity());
|
||||||
|
}
|
||||||
|
generic <typename T>
|
||||||
|
T BaseComponent::GetComponent()
|
||||||
|
{
|
||||||
|
return ECS::GetComponent<T>(owner.GetEntity());
|
||||||
|
}
|
||||||
|
generic <typename T>
|
||||||
|
void BaseComponent::RemoveComponent()
|
||||||
|
{
|
||||||
|
ECS::RemoveComponent<T>(owner.GetEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Script Access Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
generic <typename T>
|
||||||
|
T BaseComponent::AddScript()
|
||||||
|
{
|
||||||
|
return ScriptStore::AddScript<T>(owner.GetEntity());
|
||||||
|
}
|
||||||
|
generic <typename T>
|
||||||
|
T BaseComponent::GetScript()
|
||||||
|
{
|
||||||
|
return ScriptStore::GetScript<T>(owner.GetEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
generic <typename T>
|
||||||
|
System::Collections::Generic::IEnumerable<T>^ BaseComponent::GetScripts()
|
||||||
|
{
|
||||||
|
return ScriptStore::GetScripts<T>(owner.GetEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
generic <typename T>
|
||||||
|
void BaseComponent::RemoveScript()
|
||||||
|
{
|
||||||
|
ScriptStore::RemoveScript<T>(owner.GetEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
BaseComponent::BaseComponent(Entity entity)
|
||||||
|
: owner { entity }
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* IEquatable */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
bool BaseComponent::Equals(BaseComponent^ other)
|
||||||
|
{
|
||||||
|
if (other == nullptr)
|
||||||
|
return false;
|
||||||
|
return owner == other->owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Object */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
bool BaseComponent::Equals(Object^ o)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
BaseComponent^ cmp = safe_cast<BaseComponent^>(o);
|
||||||
|
return Equals(cmp);
|
||||||
|
}
|
||||||
|
catch (System::InvalidCastException^)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseComponent::GetHashCode()
|
||||||
|
{
|
||||||
|
return owner.GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file Component.h++
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 27, 2021
|
||||||
|
\brief Contains the definition of templated functions for the managed Component
|
||||||
|
classes.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
// Primary Include
|
||||||
|
#include "Component.hxx"
|
||||||
|
// Project includes
|
||||||
|
#include "Utility/Convert.hxx"
|
||||||
|
#include "Engine/ECS.hxx"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
template <typename NativeType>
|
||||||
|
Component<NativeType>::Component(Entity entity)
|
||||||
|
: BaseComponent { entity }
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
template <typename NativeType>
|
||||||
|
typename Component<NativeType>::NativeComponent* Component<NativeType>::GetNativeComponent()
|
||||||
|
{
|
||||||
|
return ECS::GetNativeComponent<NativeType>(owner.GetEntity());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,200 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file Component.hxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 27, 2021
|
||||||
|
\brief Contains the definition of the managed Component classes with the
|
||||||
|
declaration of functions for working with it.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
// External Dependencies
|
||||||
|
#include "ECS_Base/Components/SHComponent.h"
|
||||||
|
// Project Includes
|
||||||
|
#include "Engine/Entity.hxx"
|
||||||
|
#include "Scripts/Script.hxx"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Class that serves as the base for a wrapper class to Components in native code.
|
||||||
|
/// </summary>
|
||||||
|
public ref class BaseComponent : public System::IEquatable<BaseComponent^>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Properties */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the GameObject that this Component belongs to.
|
||||||
|
/// </summary>
|
||||||
|
property GameObject Owner
|
||||||
|
{
|
||||||
|
GameObject get() { return owner; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Component Access Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a Component to this GameObject.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of the Component to add. </typeparam>
|
||||||
|
/// <returns>Reference to the Component that was added.</returns>
|
||||||
|
generic<typename T> where T : BaseComponent
|
||||||
|
T AddComponent();
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a Component from this GameObject.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of the Component to get.</typeparam>
|
||||||
|
/// <returns>
|
||||||
|
/// Reference to the Component or null if this GameObject does not have the
|
||||||
|
/// specified Component.
|
||||||
|
/// </returns>
|
||||||
|
generic<typename T> where T : BaseComponent
|
||||||
|
T GetComponent();
|
||||||
|
/// <summary>
|
||||||
|
/// Removes a Component from this GameObject. If no Component exists to begin
|
||||||
|
/// with, nothing happens.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of the Component to get.</typeparam>
|
||||||
|
generic<typename T> where T : BaseComponent
|
||||||
|
void RemoveComponent();
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Script Access Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a Script of the specified type to this GameObject.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of Script to add.</typeparam>
|
||||||
|
/// <returns>Reference to the created Script.</returns>
|
||||||
|
generic<typename T> where T : ref class, Script
|
||||||
|
T AddScript();
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves a Script of the specified type from this GameObject.
|
||||||
|
/// If multiple Scripts of the same specified type are added on the same
|
||||||
|
/// GameObject, this will retrieve the first one added.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of Script to add.</typeparam>
|
||||||
|
/// <returns>Reference to the Script to retrieve.</returns>
|
||||||
|
generic<typename T> where T : ref class, Script
|
||||||
|
T GetScript();
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves a immutable list of Scripts of the specified type from this
|
||||||
|
/// GameObject.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of Scripts to Get.</typeparam>
|
||||||
|
/// <returns>Immutable list of Scripts of the specified type.</returns>
|
||||||
|
generic<typename T> where T : ref class, Script
|
||||||
|
System::Collections::Generic::IEnumerable<T>^ GetScripts();
|
||||||
|
/// <summary>
|
||||||
|
/// Removes all Scripts of the specified type from this GameObject.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of PLushieScripts to remove.</typeparam>
|
||||||
|
generic<typename T> where T : ref class, Script
|
||||||
|
void RemoveScript();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Constructors */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor for BaseComponent to tie it to a specific Entity.
|
||||||
|
/// Constructors of derived Components should call this Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">Entity that this Component will be tied to.</param>
|
||||||
|
BaseComponent(Entity entity);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Entity that this Component belongs to.
|
||||||
|
/// </summary>
|
||||||
|
GameObject owner;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* IEquatable */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Compares equality with an object of the same type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other">The object to compare with.</param>
|
||||||
|
/// <returns>True if both objects are the same.</returns>
|
||||||
|
virtual bool Equals(BaseComponent^ other);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Object */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Compares equality with another unboxed object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="o">The unboxed object to compare with.</param>
|
||||||
|
/// <returns>True if both objects are the same.</returns>
|
||||||
|
bool Equals(Object^ o) override;
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a unique hash for this object.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Unique hash for this object.</returns>
|
||||||
|
int GetHashCode() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// C++ template for the BaseComponent class used to generate common template-able
|
||||||
|
/// functions and types.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="NativeType">
|
||||||
|
/// Type of the native component that this Component wraps.
|
||||||
|
/// </typeparam>
|
||||||
|
template<typename NativeType>
|
||||||
|
public ref class Component : public BaseComponent
|
||||||
|
{
|
||||||
|
internal:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Type of the native component that this Component wraps.
|
||||||
|
/// </summary>
|
||||||
|
using NativeComponent = NativeType;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves a pointer to the native unmanaged component that is tied to the
|
||||||
|
/// Entity described by the owner value.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// Pointer to the native component. Will be nullptr if it does not exist.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// Thrown if the internal ID stored by this native component is invalid.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NullReferenceException">
|
||||||
|
/// Thrown if an attempt to retrieve the native component fails.
|
||||||
|
/// </exception>
|
||||||
|
NativeComponent* GetNativeComponent();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Constructors */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor for Component to tie it to a specific Entity.
|
||||||
|
/// Constructors of derived Components should call this Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">Entity that this Component will be tied to.</param>
|
||||||
|
Component(Entity entity);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "Component.h++"
|
|
@ -0,0 +1,255 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file ECS.cxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 28, 2021
|
||||||
|
\brief Contains the definition of the functions for the ECS managed static
|
||||||
|
class.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Precompiled Headers
|
||||||
|
#include "SHpch.h"
|
||||||
|
// Primary Header
|
||||||
|
#include "ECS.hxx"
|
||||||
|
// Standard Library
|
||||||
|
#include <sstream>
|
||||||
|
#include <msclr\marshal_cppstd.h>
|
||||||
|
// External Dependencies
|
||||||
|
#include "ECS_Base/System/SHEntityManager.h"
|
||||||
|
// Project Headers
|
||||||
|
#include "Utility/Convert.hxx"
|
||||||
|
#include "Utility/Debug.hxx"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Component Manipulation Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
generic <typename T>
|
||||||
|
T ECS::AddComponent(EntityID entity)
|
||||||
|
{
|
||||||
|
System::Type^ componentType = T::typeid;
|
||||||
|
|
||||||
|
// Check if entity is correct
|
||||||
|
if (!SHEntityManager::IsValidEID(entity))
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[ECS] Attempted to add Component \""
|
||||||
|
<< msclr::interop::marshal_as<std::string>(componentType->Name)
|
||||||
|
<< "\" to invalid Entity.";
|
||||||
|
Debug::LogError(oss.str());
|
||||||
|
return T();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add based on the correct component
|
||||||
|
for each(ComponentSet^ type in componentMap)
|
||||||
|
{
|
||||||
|
if (componentType == type->Type)
|
||||||
|
{
|
||||||
|
// Attempt to add
|
||||||
|
type->AddFunction(entity);
|
||||||
|
|
||||||
|
// Return the managed component
|
||||||
|
return createManagedComponent<T>(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[ECS] Failed to add unsupported Component \""
|
||||||
|
<< Convert::ToNative(componentType->Name)
|
||||||
|
<< "\" to Entity #"
|
||||||
|
<< entity;
|
||||||
|
Debug::LogError(oss.str());
|
||||||
|
return T();
|
||||||
|
}
|
||||||
|
generic <typename T>
|
||||||
|
T ECS::GetComponent(EntityID entity)
|
||||||
|
{
|
||||||
|
System::Type^ componentType = T::typeid;
|
||||||
|
|
||||||
|
// Check if entity is correct
|
||||||
|
if (!SHEntityManager::IsValidEID(entity))
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[ECS] Attempted to retrieve Component \""
|
||||||
|
<< Convert::ToNative(componentType->Name)
|
||||||
|
<< "\" from invalid Entity.";
|
||||||
|
Debug::LogError(oss.str());
|
||||||
|
return T();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get based on the correct component
|
||||||
|
for each(ComponentSet^ type in componentMap)
|
||||||
|
{
|
||||||
|
if (componentType == type->Type)
|
||||||
|
{
|
||||||
|
if (type->HasFunction(entity))
|
||||||
|
{
|
||||||
|
return createManagedComponent<T>(entity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return T();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[ECS] Failed to retrieve unsupported Component \""
|
||||||
|
<< Convert::ToNative(componentType->Name)
|
||||||
|
<< "\" to Entity #"
|
||||||
|
<< entity;
|
||||||
|
Debug::LogError(oss.str());
|
||||||
|
return T();
|
||||||
|
}
|
||||||
|
|
||||||
|
generic <typename T>
|
||||||
|
T ECS::GetComponentInChildren(EntityID entity)
|
||||||
|
{
|
||||||
|
System::Type^ componentType = T::typeid;
|
||||||
|
|
||||||
|
// Check if entity is correct
|
||||||
|
if (!SHEntityManager::IsValidEID(entity))
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[ECS] Attempted to retrieve Component \""
|
||||||
|
<< Convert::ToNative(componentType->Name)
|
||||||
|
<< "\" from invalid Entity.";
|
||||||
|
Debug::LogError(oss.str());
|
||||||
|
return T();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Transform component and get the children list
|
||||||
|
throw gcnew System::NotImplementedException;
|
||||||
|
//Pls::Transform* tf = Pls::ECS::GetComponent<Pls::Transform>(entity);
|
||||||
|
//if (tf == nullptr)
|
||||||
|
// return T();
|
||||||
|
|
||||||
|
//// Search direct children first
|
||||||
|
//for (const auto& child : tf->GetChildren())
|
||||||
|
//{
|
||||||
|
// T component = GetComponent<T>(child);
|
||||||
|
// if (component != nullptr)
|
||||||
|
// return component;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//// Search their children
|
||||||
|
//for (const auto& child : tf->GetChildren())
|
||||||
|
//{
|
||||||
|
// T script = GetComponentInChildren<T>(child);
|
||||||
|
// if (script != nullptr)
|
||||||
|
// return script;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// None here
|
||||||
|
return T();
|
||||||
|
}
|
||||||
|
|
||||||
|
generic <typename T>
|
||||||
|
T ECS::EnsureComponent(EntityID entity)
|
||||||
|
{
|
||||||
|
if (HasComponent<T>(entity))
|
||||||
|
{
|
||||||
|
AddComponent<T>(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetComponent<T>(entity);
|
||||||
|
}
|
||||||
|
generic <typename T>
|
||||||
|
bool ECS::HasComponent(EntityID entity)
|
||||||
|
{
|
||||||
|
System::Type^ componentType = T::typeid;
|
||||||
|
|
||||||
|
// Check if entity is correct
|
||||||
|
if (!SHEntityManager::IsValidEID(entity))
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[ECS] Attempted to check existence of Component \""
|
||||||
|
<< Convert::ToNative(componentType->Name)
|
||||||
|
<< "\" from invalid Entity.";
|
||||||
|
Debug::LogError(oss.str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add based on the correct component
|
||||||
|
for each(ComponentSet^ type in componentMap)
|
||||||
|
{
|
||||||
|
if (componentType == type->Type)
|
||||||
|
{
|
||||||
|
return type->HasFunction(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[ECS] Attempted to check existence of unsupported Component \""
|
||||||
|
<< msclr::interop::marshal_as<std::string>(componentType->Name)
|
||||||
|
<< "\" from Entity #"
|
||||||
|
<< entity;
|
||||||
|
Debug::LogError(oss.str());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
generic <typename T>
|
||||||
|
void ECS::RemoveComponent(EntityID entity)
|
||||||
|
{
|
||||||
|
System::Type^ componentType = T::typeid;
|
||||||
|
|
||||||
|
// Check if entity is correct
|
||||||
|
if (!SHEntityManager::IsValidEID(entity))
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[ECS] Attempted to remove Component \""
|
||||||
|
<< Convert::ToNative(componentType->Name)
|
||||||
|
<< "\" from invalid Entity.";
|
||||||
|
Debug::LogError(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add based on the correct component
|
||||||
|
for each(ComponentSet^ type in componentMap)
|
||||||
|
{
|
||||||
|
if (componentType == type->Type)
|
||||||
|
{
|
||||||
|
type->RemoveFunction(entity);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[ECS] Attempted to remove unsupported Component \""
|
||||||
|
<< msclr::interop::marshal_as<std::string>(componentType->Name)
|
||||||
|
<< "\" from Entity #"
|
||||||
|
<< entity;
|
||||||
|
Debug::LogError(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
static ECS::ECS()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
// componentMap.Add(createComponentSet<Transform, Transform>());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
generic <typename T>
|
||||||
|
T ECS::createManagedComponent(EntityID entity)
|
||||||
|
{
|
||||||
|
using namespace System::Reflection;
|
||||||
|
|
||||||
|
array<System::Object^>^ params = gcnew array<System::Object^>{ static_cast<Entity>(entity) };
|
||||||
|
return safe_cast<T>(System::Activator::CreateInstance
|
||||||
|
(
|
||||||
|
T::typeid,
|
||||||
|
BindingFlags::Instance | BindingFlags::NonPublic | BindingFlags::CreateInstance,
|
||||||
|
nullptr, params, nullptr)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file ECS.h++
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 27, 2021
|
||||||
|
\brief Contains the definition of templated functions for the managed Component
|
||||||
|
classes.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
// Primary Include
|
||||||
|
#include "ECS.hxx"
|
||||||
|
// External Dependencies
|
||||||
|
#include "ECS_Base/System/SHComponentManager.h"
|
||||||
|
#include "ECS_Base/System/SHEntityManager.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Static Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
template <typename NativeComponent>
|
||||||
|
NativeComponent* ECS::GetNativeComponent(Entity entity)
|
||||||
|
{
|
||||||
|
// Get native Entity
|
||||||
|
SHEntity* nativeEntity = SHEntityManager::GetEntityByID(entity);
|
||||||
|
|
||||||
|
// Entity Validity Check
|
||||||
|
if (nativeEntity == nullptr)
|
||||||
|
throw gcnew System::InvalidOperationException("Attempted to get native Component to an invalid Entity.");
|
||||||
|
|
||||||
|
// Null Check
|
||||||
|
NativeComponent* component = SHComponentManager::GetComponent_s<NativeComponent>(nativeEntity);
|
||||||
|
if (component == nullptr)
|
||||||
|
throw gcnew System::NullReferenceException("Attempted to get a native Component that does not exist.");
|
||||||
|
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
template<typename NativeType, typename ManagedType>
|
||||||
|
ECS::ComponentSet ECS::createComponentSet()
|
||||||
|
{
|
||||||
|
return ComponentSet
|
||||||
|
{
|
||||||
|
ManagedType::typeid,
|
||||||
|
SHComponentManager::AddComponent<NativeType>,
|
||||||
|
SHComponentManager::EnsureComponent<NativeType>,
|
||||||
|
SHComponentManager::HasComponent<NativeType>,
|
||||||
|
SHComponentManager::RemoveComponent<NativeType>
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,174 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file ECS.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
|
||||||
|
|
||||||
|
// External Dependencies
|
||||||
|
#include "ECS_Base/System/SHComponentManager.h"
|
||||||
|
// Project Includes
|
||||||
|
#include "Components/Component.hxx"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Static class which contains functions that map Pls::ECS's Component manipulation
|
||||||
|
/// functions to managed generic functions.
|
||||||
|
/// </summary>
|
||||||
|
private ref class ECS abstract sealed
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Component Manipulation Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a Component to the specified Entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of the Component to add.</typeparam>
|
||||||
|
/// <param name="entity">
|
||||||
|
/// Entity object that should have the specified Component added to.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>Reference to the Component that was added.</returns>
|
||||||
|
generic<typename T> where T : BaseComponent
|
||||||
|
static T AddComponent(EntityID entity);
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a Component from the specified Entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of the Component to get.</typeparam>
|
||||||
|
/// <param name="entity"> Entity object to get the Component from. </param>
|
||||||
|
/// <returns>
|
||||||
|
/// Reference to the Component or null if the Entity does not have the
|
||||||
|
/// specified Component.
|
||||||
|
/// </returns>
|
||||||
|
generic<typename T> where T : BaseComponent
|
||||||
|
static T GetComponent(EntityID entity);
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the first Component from the specified GameObjectt's children that
|
||||||
|
/// matches the specified type.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of the Component to get.</typeparam>
|
||||||
|
/// <param name="entity"> Entity object to get the Component from. </param>
|
||||||
|
/// <returns>
|
||||||
|
/// Reference to the Component or null if the Entity does not have the
|
||||||
|
/// specified Component.
|
||||||
|
/// </returns>
|
||||||
|
generic<typename T> where T : BaseComponent
|
||||||
|
static T GetComponentInChildren(EntityID entity);
|
||||||
|
/// <summary>
|
||||||
|
/// Ensures a Component on the specified Entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of the Component to ensure.</typeparam>
|
||||||
|
/// <param name="entity"> Entity object to ensure the Component on. </param>
|
||||||
|
/// <returns>Reference to the Component.</returns>
|
||||||
|
generic<typename T> where T : BaseComponent
|
||||||
|
static T EnsureComponent(EntityID entity);
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the specified Entity has the specified Component.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of the Component to check for.</typeparam>
|
||||||
|
/// <param name="entity">Entity object to check for the Component.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// True if the specified Entity has the specified Component. False otherwise.
|
||||||
|
/// </returns>
|
||||||
|
generic<typename T> where T : BaseComponent
|
||||||
|
static bool HasComponent(EntityID entity);
|
||||||
|
/// <summary>
|
||||||
|
/// Removes a Component from the specified Entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of the Component to remove.</typeparam>
|
||||||
|
/// <param name="entity">
|
||||||
|
/// Entity object that should have the specified Component removed from/
|
||||||
|
/// </param>
|
||||||
|
generic<typename T> where T : BaseComponent
|
||||||
|
static void RemoveComponent(EntityID entity);
|
||||||
|
|
||||||
|
internal:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Pointer to a function for Component manipulation operations.
|
||||||
|
/// </summary>
|
||||||
|
using ComponentFunc = void(*)(const EntityID&);
|
||||||
|
using ComponentHasFunc = bool(*)(const EntityID&);
|
||||||
|
/// <summary>
|
||||||
|
/// Contains a set of Component related data used for resolving operations for
|
||||||
|
/// each Component.
|
||||||
|
/// </summary>
|
||||||
|
value struct ComponentSet
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
System::Type^ Type;
|
||||||
|
ComponentFunc AddFunction;
|
||||||
|
ComponentHasFunc HasFunction;
|
||||||
|
ComponentFunc RemoveFunction;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Static Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves a pointer to the native unmanaged component of the specified
|
||||||
|
/// Entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// Pointer to the native component. Will be nullptr if it does not exist.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="System.InvalidOperationException">
|
||||||
|
/// Thrown if the Entity specified is invalid.
|
||||||
|
/// </exception>
|
||||||
|
/// <exception cref="System.NullReferenceException">
|
||||||
|
/// Thrown if an attempt to retrieve the native component fails.
|
||||||
|
/// </exception>
|
||||||
|
template<typename NativeComponent>
|
||||||
|
static NativeComponent* GetNativeComponent(Entity entity);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Constructors */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Static constructor to initialize static data
|
||||||
|
/// </summary>
|
||||||
|
static ECS();
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Static Data Members */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
static System::Collections::Generic::List<ComponentSet> componentMap;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a ComponentSet for a pair of Native and Managed Components.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="NativeType">Type of the Native Component.</typeparam>
|
||||||
|
/// <typeparam name="ManagedType">Type of the Managed Component.</typeparam>
|
||||||
|
/// <returns>ComponentSet for the parameters specified.</returns>
|
||||||
|
template<typename NativeType, typename ManagedType>
|
||||||
|
static ComponentSet createComponentSet();
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an instance of the Managed representation of a Component with a
|
||||||
|
/// native Entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of Component to create.</typeparam>
|
||||||
|
/// <param name="entity">Native Entity that this Component is tied to.</param>
|
||||||
|
/// <returns>The created Managed representation of the Component.</returns>
|
||||||
|
generic<typename T> where T : BaseComponent
|
||||||
|
static T createManagedComponent(EntityID entity);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "ECS.h++"
|
|
@ -0,0 +1,138 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file EngineInterface.cxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 28, 2021
|
||||||
|
\brief Contains the implementation of the managed EngineInterface static class.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Precompiled Headers
|
||||||
|
#include "SHpch.h"
|
||||||
|
// Primary Header
|
||||||
|
#include "EngineInterface.hxx"
|
||||||
|
// Standard Libraries
|
||||||
|
#include <sstream>
|
||||||
|
// Project Headers
|
||||||
|
#include "Utility/Convert.hxx"
|
||||||
|
#include "Utility/Debug.hxx"
|
||||||
|
#include "Scripts/ScriptStore.hxx"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Interop Static Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void EngineInterface::Init()
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
// Set up exception handler
|
||||||
|
System::AppDomain::CurrentDomain->UnhandledException += exceptionHandler;
|
||||||
|
LoadScriptAssembly();
|
||||||
|
Debug::Log("[EngineInterface] Successfully initialized managed runtime.");
|
||||||
|
SAFE_NATIVE_CALL_END_N("SHADE_Managed.EngineInterface")
|
||||||
|
}
|
||||||
|
void EngineInterface::UnloadScriptAssembly()
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[EngineInterface] Unloading " << Convert::ToNative(ManagedLibraryName) << ".dll";
|
||||||
|
ScriptStore::Exit();
|
||||||
|
|
||||||
|
// Unload the script
|
||||||
|
scriptContext->Unload();
|
||||||
|
scriptContext = nullptr;
|
||||||
|
System::GC::Collect();
|
||||||
|
System::GC::WaitForPendingFinalizers();
|
||||||
|
|
||||||
|
// Unload the assembly File
|
||||||
|
if (managedLibFile != nullptr)
|
||||||
|
{
|
||||||
|
managedLibFile->Close();
|
||||||
|
managedLibFile = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
oss.str("");
|
||||||
|
oss << "[EngineInterface] Successfully unloaded " << Convert::ToNative(ManagedLibraryName) << ".dll";
|
||||||
|
Debug::Log(oss.str());
|
||||||
|
SAFE_NATIVE_CALL_END_N("SHADE_Managed.EngineInterface")
|
||||||
|
}
|
||||||
|
void EngineInterface::LoadScriptAssembly()
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
scriptContext = gcnew DisposableAssemblyLoadContext();
|
||||||
|
loadManagedLibrary();
|
||||||
|
ScriptStore::Init();
|
||||||
|
SAFE_NATIVE_CALL_END_N("SHADE_Managed.EngineInterface")
|
||||||
|
}
|
||||||
|
void EngineInterface::ReloadScriptAssembly()
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
// Stop scripts
|
||||||
|
UnloadScriptAssembly();
|
||||||
|
// Reload assembly and restart scripts runtime
|
||||||
|
LoadScriptAssembly();
|
||||||
|
SAFE_NATIVE_CALL_END_N("SHADE_Managed.EngineInterface")
|
||||||
|
}
|
||||||
|
void EngineInterface::Exit()
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
// Clean up ScriptStore
|
||||||
|
ScriptStore::Exit();
|
||||||
|
scriptContext->Unload();
|
||||||
|
|
||||||
|
// Release exception handler
|
||||||
|
System::AppDomain::CurrentDomain->UnhandledException -= exceptionHandler;
|
||||||
|
SAFE_NATIVE_CALL_END_N("SHADE_Managed.EngineInterface")
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructor */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
static EngineInterface::EngineInterface()
|
||||||
|
{
|
||||||
|
exceptionHandler = gcnew System::UnhandledExceptionEventHandler(unhandledExceptionHandler);
|
||||||
|
managedLibPath = System::Reflection::Assembly::GetExecutingAssembly()->Location->Replace("SHADE_Managed.dll", ManagedLibraryName + ".dll");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void EngineInterface::loadManagedLibrary()
|
||||||
|
{
|
||||||
|
using namespace System::IO;
|
||||||
|
|
||||||
|
std::ostringstream oss;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
oss << "[EngineInterface] Loading " << Convert::ToNative(ManagedLibraryName) << ".dll";
|
||||||
|
managedLibFile = File::Open(managedLibPath, FileMode::Open, FileAccess::Read);
|
||||||
|
scriptContext->LoadFromStream(managedLibFile);
|
||||||
|
oss.str("");
|
||||||
|
oss << "[EngineInterface] Successfully loaded " << Convert::ToNative(ManagedLibraryName) << ".dll";
|
||||||
|
Debug::Log(oss.str());
|
||||||
|
}
|
||||||
|
catch (System::Exception^ e)
|
||||||
|
{
|
||||||
|
oss << "[EngineInterface] Unable to load " << Convert::ToNative(ManagedLibraryName) << ".dll!"
|
||||||
|
<< "(" << Convert::ToNative(e->ToString()) << ")";
|
||||||
|
Debug::LogError(oss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Exception Handler Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void EngineInterface::unhandledExceptionHandler(System::Object^, System::UnhandledExceptionEventArgs^ e)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[EngineInterface] Unhandled managed exception: "
|
||||||
|
<< Convert::ToNative(e->ExceptionObject->GetType()->ToString()) << ": "
|
||||||
|
<< Convert::ToNative(e->ExceptionObject->ToString());
|
||||||
|
Debug::LogError(oss.str());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file EngineInterface.hxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 28, 2021
|
||||||
|
\brief Contains the definitions of the managed EngineInterface static class.
|
||||||
|
|
||||||
|
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 "Utility/DisposableAssemblyLoadContext.hxx"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Static class that contains the functions for interfacing with the core
|
||||||
|
/// PlushieEngine written in C++ for managing the lifecycle of managed code.
|
||||||
|
/// </summary>
|
||||||
|
private ref class EngineInterface abstract sealed
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Constants */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the Managed Library that contains the C# scripts written externally.
|
||||||
|
/// </summary>
|
||||||
|
literal System::String^ ManagedLibraryName = "SHADE_Scripting";
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Interop Static Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Initialises all required components for managed code.
|
||||||
|
/// </summary>
|
||||||
|
static void Init();
|
||||||
|
/// <summary>
|
||||||
|
/// Unloads the managed script assembly.
|
||||||
|
/// Take note that this will clear all existing scripts, ensure that the scene
|
||||||
|
/// is saved before doing so.
|
||||||
|
/// </summary>
|
||||||
|
static void UnloadScriptAssembly();
|
||||||
|
/// <summary>
|
||||||
|
/// Loads the managed script assembly. Ensure this is only called after
|
||||||
|
/// UnloadScriptAssembly() has been called.
|
||||||
|
/// </summary>
|
||||||
|
static void LoadScriptAssembly();
|
||||||
|
/// <summary>
|
||||||
|
/// Reloads the managed script assembly.
|
||||||
|
/// Take note that this will clear all existing scripts, ensure that the scene
|
||||||
|
/// is saved before doing so.
|
||||||
|
/// Equivalent to calling UnloadScriptAssembly() and then LoadScriptAssembly().
|
||||||
|
/// </summary>
|
||||||
|
static void ReloadScriptAssembly();
|
||||||
|
/// <summary>
|
||||||
|
/// Cleans up all required components for managed code.
|
||||||
|
/// </summary>
|
||||||
|
static void Exit();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Constructor */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
static EngineInterface();
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
static DisposableAssemblyLoadContext^ scriptContext;
|
||||||
|
static System::UnhandledExceptionEventHandler^ exceptionHandler;
|
||||||
|
static System::String^ managedLibPath;
|
||||||
|
static System::IO::FileStream^ managedLibFile;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
static void loadManagedLibrary();
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Exception Handler Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
static void unhandledExceptionHandler(System::Object^ sender, System::UnhandledExceptionEventArgs^ e);
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file Entity.cxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 28, 2021
|
||||||
|
\brief Contains the definition of the functions for the EntityUtils managed
|
||||||
|
static class.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Precompiled Headers
|
||||||
|
#include "SHpch.h"
|
||||||
|
// Primary Header
|
||||||
|
#include "Entity.hxx"
|
||||||
|
// External Dependencies
|
||||||
|
#include "ECS_Base/System/SHEntityManager.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
bool EntityUtils::IsValid(Entity^ entity)
|
||||||
|
{
|
||||||
|
return SHEntityManager::IsValidEID(static_cast<EntityID>(entity));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file Entity.hxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 28, 2021
|
||||||
|
\brief Contains the definitions of a managed Entity identifier and declarations
|
||||||
|
of useful utility functions for working with Entity identifiers.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
// External Dependencies
|
||||||
|
#include "ECS_Base/Entity/SHEntity.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Managed representation of a native ECS Entity.
|
||||||
|
/// </summary>
|
||||||
|
using Entity = System::UInt32;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Static class that contains useful utility functions for working with Entity.
|
||||||
|
/// </summary>
|
||||||
|
private ref class EntityUtils abstract sealed
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the specified entity is valid. This is done by checking if it
|
||||||
|
/// matches Pls::Entity::INVALID.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">The Entity to check.</param>
|
||||||
|
/// <returns>True if the specified Entity is valid.</returns>
|
||||||
|
static bool IsValid(Entity^ entity);
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,201 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file GameObject.cxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 28, 2021
|
||||||
|
\brief Contains the definition of the functions for the GameObject managed class.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Precompiled Headers
|
||||||
|
#include "SHpch.h"
|
||||||
|
// Primary Header
|
||||||
|
#include "GameObject.hxx"
|
||||||
|
// External Dependencies
|
||||||
|
#include "ECS_Base/System/SHEntityManager.h"
|
||||||
|
// Project Headers
|
||||||
|
#include "ECS.hxx"
|
||||||
|
#include "Scripts/ScriptStore.hxx"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Static Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
GameObject GameObject::Create()
|
||||||
|
{
|
||||||
|
return GameObject(SHEntityManager::CreateEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameObject::Destroy(GameObject obj)
|
||||||
|
{
|
||||||
|
SHEntityManager::DestroyEntity(static_cast<EntityID>(obj.GetEntity()));
|
||||||
|
}
|
||||||
|
|
||||||
|
System::Nullable<GameObject> GameObject::Find(System::String ^ name)
|
||||||
|
{
|
||||||
|
// Search the GameObjectLibrary for an Entity with the specified name
|
||||||
|
throw gcnew System::NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Properties */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
System::String^ GameObject::Name::get()
|
||||||
|
{
|
||||||
|
return Convert::ToCLI(GetNativeEntity().name);
|
||||||
|
|
||||||
|
}
|
||||||
|
bool GameObject::IsActiveSelf::get()
|
||||||
|
{
|
||||||
|
return GetNativeEntity().isActive;
|
||||||
|
}
|
||||||
|
bool GameObject::IsActiveInHierarchy::get()
|
||||||
|
{
|
||||||
|
throw gcnew System::NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* GameObject Property Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void GameObject::SetName(System::String^ name)
|
||||||
|
{
|
||||||
|
GetNativeEntity().name = Convert::ToNative(name);
|
||||||
|
}
|
||||||
|
void GameObject::SetActive(bool active)
|
||||||
|
{
|
||||||
|
GetNativeEntity().isActive = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Component Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
generic <typename T>
|
||||||
|
T GameObject::AddComponent()
|
||||||
|
{
|
||||||
|
return ECS::AddComponent<T>(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
generic <typename T>
|
||||||
|
T GameObject::GetComponent()
|
||||||
|
{
|
||||||
|
return ECS::GetComponent<T>(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
generic <typename T>
|
||||||
|
T GameObject::GetComponentInChildren()
|
||||||
|
{
|
||||||
|
return ECS::GetComponentInChildren<T>(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
generic <typename T>
|
||||||
|
T GameObject::EnsureComponent()
|
||||||
|
{
|
||||||
|
return ECS::EnsureComponent<T>(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
generic <typename T>
|
||||||
|
void GameObject::RemoveComponent()
|
||||||
|
{
|
||||||
|
ECS::RemoveComponent<T>(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Script Access Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
generic <typename T>
|
||||||
|
T GameObject::AddScript()
|
||||||
|
{
|
||||||
|
return ScriptStore::AddScript<T>(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
generic <typename T>
|
||||||
|
T GameObject::GetScript()
|
||||||
|
{
|
||||||
|
return ScriptStore::GetScript<T>(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
generic <typename T>
|
||||||
|
T GameObject::GetScriptInChildren()
|
||||||
|
{
|
||||||
|
return ScriptStore::GetScriptInChildren<T>(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
generic <typename T>
|
||||||
|
System::Collections::Generic::IEnumerable<T>^ GameObject::GetScripts()
|
||||||
|
{
|
||||||
|
return ScriptStore::GetScripts<T>(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
generic <typename T>
|
||||||
|
void GameObject::RemoveScript()
|
||||||
|
{
|
||||||
|
ScriptStore::RemoveScript<T>(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
GameObject::GameObject(const SHEntity& entity)
|
||||||
|
: entity { entity.GetEID() }
|
||||||
|
{}
|
||||||
|
|
||||||
|
GameObject::GameObject(Entity entity)
|
||||||
|
: entity { entity }
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Getters */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
SHEntity& GameObject::GetNativeEntity()
|
||||||
|
{
|
||||||
|
SHEntity* nativeEntity = SHEntityManager::GetEntityByID(entity);
|
||||||
|
if (nativeEntity == nullptr)
|
||||||
|
throw gcnew System::InvalidOperationException("[GameObject] Unable to obtain native Entity for GameObject.");
|
||||||
|
|
||||||
|
return *nativeEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* IEquatable */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
bool GameObject::Equals(GameObject other)
|
||||||
|
{
|
||||||
|
return entity == other.entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Object */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
bool GameObject::Equals(Object^ o)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
GameObject^ cmp = safe_cast<GameObject^>(o);
|
||||||
|
return Equals(cmp);
|
||||||
|
}
|
||||||
|
catch (System::InvalidCastException^)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int GameObject::GetHashCode()
|
||||||
|
{
|
||||||
|
return entity.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameObject::operator==(GameObject lhs, GameObject rhs)
|
||||||
|
{
|
||||||
|
return lhs.Equals(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameObject::operator!=(GameObject lhs, GameObject rhs)
|
||||||
|
{
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,282 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file GameObject.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 "Entity.hxx"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Forward Declarations */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
ref class Script;
|
||||||
|
ref class BaseComponent;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Class Definitions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Lightweight object for an PlushieEngine Entity that allows for easy access
|
||||||
|
/// to Component and Script operations.
|
||||||
|
/// </summary>
|
||||||
|
public value class GameObject : public System::IEquatable<GameObject>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Static Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new GameObject in the current Scene. If multiple Scenes are loaded,
|
||||||
|
/// and you would like to create an object in a specific Scene, call the Scene's
|
||||||
|
/// CreateGameObject().
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>GameObject that represents the newly created GameObject.</returns>
|
||||||
|
static GameObject Create();
|
||||||
|
/// <summary>
|
||||||
|
/// Destroys the specified GameObject. Note that the specified GameObject will no
|
||||||
|
/// longer be a valid GameObject after this function is called.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">The GameObject to be destroyed.</param>
|
||||||
|
static void Destroy(GameObject obj);
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves a GameObject with the specified name. If there are multiple
|
||||||
|
/// GameObjects with the same name, the first found GameObject will be retrieved.
|
||||||
|
/// There is no guaranteed order of which GameObject is considered "first".
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">Name of the GameObject to find.</param>
|
||||||
|
/// <returns>GameObject that has the specified name. Null if not found.</returns>
|
||||||
|
static System::Nullable<GameObject> Find(System::String^ name);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Properties */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the object that this Entity represents.
|
||||||
|
/// </summary>
|
||||||
|
property System::String^ Name
|
||||||
|
{
|
||||||
|
System::String^ get();
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Whether or not this Entity alone, is active. This does not mean that this
|
||||||
|
/// object is active in the scene. For example, if this Entity's parent is not
|
||||||
|
/// active, then this Entity would also be not active.
|
||||||
|
/// </summary>
|
||||||
|
property bool IsActiveSelf
|
||||||
|
{
|
||||||
|
bool get();
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Whether or not this Entity is active in the Scene hierarchy.
|
||||||
|
/// </summary>
|
||||||
|
property bool IsActiveInHierarchy
|
||||||
|
{
|
||||||
|
bool get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* GameObject Property Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the name of this GameObject.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The name to set.</param>
|
||||||
|
void SetName(System::String^ name);
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the active state of this GameObject.
|
||||||
|
/// <br/>
|
||||||
|
/// The actual "activeness" of this GameObject is still dependent on the parents'
|
||||||
|
/// active states.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="active">
|
||||||
|
/// Whether to activate or deactivate this GameObject.
|
||||||
|
/// </param>
|
||||||
|
void SetActive(bool active);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Component Access Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a Component to this GameObject.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of the Component to add. </typeparam>
|
||||||
|
/// <returns>Reference to the Component that was added.</returns>
|
||||||
|
generic<typename T> where T : BaseComponent
|
||||||
|
T AddComponent();
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a Component from this GameObject.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of the Component to get.</typeparam>
|
||||||
|
/// <returns>
|
||||||
|
/// Reference to the Component or null if this GameObject does not have the
|
||||||
|
/// specified Component.
|
||||||
|
/// </returns>
|
||||||
|
generic<typename T> where T : BaseComponent
|
||||||
|
T GetComponent();
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the first Component from this GameObject's children that matches
|
||||||
|
/// the specified type.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of the Component to get.</typeparam>
|
||||||
|
/// <returns>
|
||||||
|
/// Reference to the Component or null if neither of this GameObject's children
|
||||||
|
/// does not have the specified Component.
|
||||||
|
/// </returns>
|
||||||
|
generic<typename T> where T : BaseComponent
|
||||||
|
T GetComponentInChildren();
|
||||||
|
/// <summary>
|
||||||
|
/// Ensures a Component on this GameObject.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of the Component to ensure.</typeparam>
|
||||||
|
/// <returns>
|
||||||
|
/// Reference to the Component.
|
||||||
|
/// </returns>
|
||||||
|
generic<typename T> where T : BaseComponent
|
||||||
|
T EnsureComponent();
|
||||||
|
/// <summary>
|
||||||
|
/// Removes a Component from this GameObject. If no Component exists to begin
|
||||||
|
/// with, nothing happens.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of the Component to get.</typeparam>
|
||||||
|
generic<typename T> where T : BaseComponent
|
||||||
|
void RemoveComponent();
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Script Access Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a Script of the specified type to this GameObject.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of Script to add.</typeparam>
|
||||||
|
/// <returns>Reference to the created Script.</returns>
|
||||||
|
generic<typename T> where T : ref class, Script
|
||||||
|
T AddScript();
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves a Script of the specified type from this GameObject.
|
||||||
|
/// If multiple Scripts of the same specified type are added on the same
|
||||||
|
/// GameObject, this will retrieve the first one added.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of Script to retrieve.</typeparam>
|
||||||
|
/// <returns>Reference to the Script to retrieve.</returns>
|
||||||
|
generic<typename T> where T : ref class, Script
|
||||||
|
T GetScript();
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves a Script of the specified type from child GameObjects.
|
||||||
|
/// If multiple Scripts of the same specified type are added on the same
|
||||||
|
/// child GameObject, this will retrieve the first one added.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of Script to retrieve.</typeparam>
|
||||||
|
/// <returns>Reference to the Script to retrieve.</returns>
|
||||||
|
generic<typename T> where T : ref class, Script
|
||||||
|
T GetScriptInChildren();
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves a immutable list of Scripts of the specified type from this
|
||||||
|
/// GameObject.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of Scripts to retrieve.</typeparam>
|
||||||
|
/// <returns>Immutable list of Scripts of the specified type.</returns>
|
||||||
|
generic<typename T> where T : ref class, Script
|
||||||
|
System::Collections::Generic::IEnumerable<T>^ GetScripts();
|
||||||
|
/// <summary>
|
||||||
|
/// Removes all Scripts of the specified type from this GameObject.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of PLushieScripts to remove.</typeparam>
|
||||||
|
generic<typename T> where T : ref class, Script
|
||||||
|
void RemoveScript();
|
||||||
|
|
||||||
|
internal:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Constructors */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor for the GameObject.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">
|
||||||
|
/// The ECS Entity that this GameObject should represent.
|
||||||
|
/// </param>
|
||||||
|
GameObject(const SHEntity& entity);
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor for the GameObject.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">
|
||||||
|
/// Managed numerical representation of the ECS Entity that this GameObject
|
||||||
|
/// should represent.
|
||||||
|
/// </param>
|
||||||
|
GameObject(Entity entity);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Getters */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the CLR Entity object that this GameObject represents.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Entity object that this GameObject represents.</returns>
|
||||||
|
inline Entity GetEntity() { return entity; }
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the native Entity object that this GameObject represents.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Native Entity object that this GameObject represents.</returns>
|
||||||
|
SHEntity& GetNativeEntity();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
Entity entity;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* IEquatable */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Compares equality with an object of the same type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other">The object to compare with.</param>
|
||||||
|
/// <returns>True if both objects are the same.</returns>
|
||||||
|
virtual bool Equals(GameObject other);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Object */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Compares equality with another unboxed object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="o">The unboxed object to compare with.</param>
|
||||||
|
/// <returns>True if both objects are the same.</returns>
|
||||||
|
bool Equals(Object^ o) override;
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a unique hash for this object.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Unique hash for this object.</returns>
|
||||||
|
int GetHashCode() override;
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if two GameObject references are the same.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">GameObject to check.</param>
|
||||||
|
/// <param name="rhs">Another GameObject to check with.</param>
|
||||||
|
/// <returns>True if both Components are the same.</returns>
|
||||||
|
static bool operator==(GameObject lhs, GameObject rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if two GameObject references are different.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">GameObject to check.</param>
|
||||||
|
/// <param name="rhs">Another GameObject to check with.</param>
|
||||||
|
/// <returns>True if both Components are different.</returns>
|
||||||
|
static bool operator!=(GameObject lhs, GameObject rhs);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file Math.cxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Nov 11, 2021
|
||||||
|
\brief Contains the implementation of the functions of the managed Math struct.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Precompiled Headers
|
||||||
|
#include "SHpch.h"
|
||||||
|
// Primary Header
|
||||||
|
#include "Math/Math.hxx"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Utility Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
double Math::Wrap(double value, double min, double max)
|
||||||
|
{
|
||||||
|
while (value < min)
|
||||||
|
{
|
||||||
|
value = max - (min - value);
|
||||||
|
}
|
||||||
|
while (value > max)
|
||||||
|
{
|
||||||
|
value = min + (value - max);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
double Math::DegreesToRadians(double degrees)
|
||||||
|
{
|
||||||
|
return degrees * Deg2Rad;
|
||||||
|
}
|
||||||
|
double Math::RadiansToDegrees(double radians)
|
||||||
|
{
|
||||||
|
return radians * Rad2Deg;
|
||||||
|
}
|
||||||
|
double Math::Lerp(double a, double b, double t)
|
||||||
|
{
|
||||||
|
return LerpUnclamped(a, b, System::Math::Clamp(t, 0.0, 1.0));
|
||||||
|
}
|
||||||
|
double Math::LerpUnclamped(double a, double b, double t)
|
||||||
|
{
|
||||||
|
return a + t * (b - a);
|
||||||
|
}
|
||||||
|
|
||||||
|
double Math::InverseLerp(double a, double b, double value)
|
||||||
|
{
|
||||||
|
return (value - a) / (b - a);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file Math.hxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Nov 11, 2021
|
||||||
|
\brief Contains the definition of the managed Math static class.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Contains utility Math functions.
|
||||||
|
/// </summary>
|
||||||
|
public ref class Math abstract sealed
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Static Constants */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Degrees-to-radians conversion constant
|
||||||
|
/// </summary>
|
||||||
|
static constexpr double Deg2Rad = System::Math::PI / 180.0;
|
||||||
|
/// <summary>
|
||||||
|
/// Radians-to-degrees conversion constant
|
||||||
|
/// </summary>
|
||||||
|
static constexpr double Rad2Deg = 180.0 / System::Math::PI;
|
||||||
|
/// <summary>
|
||||||
|
/// Small value used for single precision floating point comparisons.
|
||||||
|
/// </summary>
|
||||||
|
static constexpr float Epsilon = 0.001f;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Utility Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Wraps a value if they get to low or too high.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">Value to wrap.</param>
|
||||||
|
/// <param name="min">Minimum value to wrap at.</param>
|
||||||
|
/// <param name="max">Maximum value to wrap at.</param>
|
||||||
|
/// <returns>Wrapped value.</returns>
|
||||||
|
static double Wrap(double value, double min, double max);
|
||||||
|
/// <summary>
|
||||||
|
/// Converts an angle from degree representation to radian representation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="degrees">Degree-based angle to convert.</param>
|
||||||
|
/// <returns>The specified angle in radians.</returns>
|
||||||
|
static double DegreesToRadians(double degrees);
|
||||||
|
/// <summary>
|
||||||
|
/// Converts an angle from radian representation to degree representation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="radians">Radian-based angle to convert.</param>
|
||||||
|
/// <returns>The specified angle in degrees.</returns>
|
||||||
|
static double RadiansToDegrees(double radians);
|
||||||
|
/// <summary>
|
||||||
|
/// Linearly interpolates between a and b by t.
|
||||||
|
/// The parameter t is clamped to the range [0, 1].
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a">The start value.</param>
|
||||||
|
/// <param name="b">The end value.</param>
|
||||||
|
/// <param name="t">The interpolation value between the two double.</param>
|
||||||
|
/// <returns>The interpolated double result between the two double values.</returns>
|
||||||
|
static double Lerp(double a, double b, double t);
|
||||||
|
/// <summary>
|
||||||
|
/// Linearly interpolates between a and b by t.
|
||||||
|
/// The parameter t is not clamped and a value based on a and b is supported.
|
||||||
|
/// If t is less than zero, or greater than one, then LerpUnclamped will result
|
||||||
|
/// in a return value outside the range a to b.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a">The start value.</param>
|
||||||
|
/// <param name="b">The end value.</param>
|
||||||
|
/// <param name="t">The interpolation value between the two double.</param>
|
||||||
|
/// <returns>The interpolated double result between the two double values.</returns>
|
||||||
|
static double LerpUnclamped(double a, double b, double t);
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates the linear parameter t that produces the interpolant value within the range [a, b].
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a">Start value.</param>
|
||||||
|
/// <param name="b">End value.</param>
|
||||||
|
/// <param name="value">Value between start and end.</param>
|
||||||
|
/// <returns>Percentage of value between start and end.</returns>
|
||||||
|
static double InverseLerp(double a, double b, double value);
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,263 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file Vector2.cxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Nov 2, 2021
|
||||||
|
\brief Contains the definitions of functions of the Vector2 struct.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Precompiled Headers
|
||||||
|
#include "SHpch.h"
|
||||||
|
// Primary Header
|
||||||
|
#include "Math/Vector2.hxx"
|
||||||
|
// Standard Libraries
|
||||||
|
#include <cmath>
|
||||||
|
#include <algorithm>
|
||||||
|
// Project Headers
|
||||||
|
#include "Math.hxx"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
Vector2::Vector2(double _x)
|
||||||
|
: Vector2 { _x, 0.0 }
|
||||||
|
{}
|
||||||
|
Vector2::Vector2(double _x, double _y)
|
||||||
|
: x { _x }
|
||||||
|
, y { _y }
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Usage Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void Vector2::Normalise()
|
||||||
|
{
|
||||||
|
*this = GetNormalised();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 Vector2::GetNormalised()
|
||||||
|
{
|
||||||
|
return *this / GetMagnitude();
|
||||||
|
}
|
||||||
|
|
||||||
|
double Vector2::GetMagnitude()
|
||||||
|
{
|
||||||
|
return sqrt(x * x + y * y);
|
||||||
|
}
|
||||||
|
|
||||||
|
double Vector2::GetSqrMagnitude()
|
||||||
|
{
|
||||||
|
return x * x + y * y;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Vector2::AngleFromRightRadians()
|
||||||
|
{
|
||||||
|
return atan2(y, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
double Vector2::AngleFromRightDegrees()
|
||||||
|
{
|
||||||
|
return Math::RadiansToDegrees(AngleFromRightRadians());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Vector2::IsNearPoint(Vector2 point)
|
||||||
|
{
|
||||||
|
return IsNearPoint(point, Math::Epsilon);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Vector2::IsNearPoint(Vector2 point, double tolerance)
|
||||||
|
{
|
||||||
|
return (*this - point).GetSqrMagnitude() < (tolerance * tolerance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* IEquatable */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
bool Vector2::Equals(Object^ o)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Vector2 vec = safe_cast<Vector2>(o);
|
||||||
|
return Equals(vec);
|
||||||
|
}
|
||||||
|
catch (System::InvalidCastException^)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Object Overrides */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
bool Vector2::Equals(Vector2 other)
|
||||||
|
{
|
||||||
|
return IsNear(*this, other);
|
||||||
|
}
|
||||||
|
int Vector2::GetHashCode()
|
||||||
|
{
|
||||||
|
const int HASH = 19;
|
||||||
|
return x.GetHashCode() * HASH + y.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Static Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
bool Vector2::IsNear(Vector2 lhs, Vector2 rhs)
|
||||||
|
{
|
||||||
|
return IsNear(lhs, rhs, Math::Epsilon);
|
||||||
|
}
|
||||||
|
bool Vector2::IsNear(Vector2 lhs, Vector2 rhs, double tolerance)
|
||||||
|
{
|
||||||
|
return (std::abs(lhs.x) - std::abs(rhs.x)) < tolerance
|
||||||
|
&&
|
||||||
|
(std::abs(lhs.y) - std::abs(rhs.y)) < tolerance;
|
||||||
|
}
|
||||||
|
double Vector2::Dot(Vector2 lhs, Vector2 rhs)
|
||||||
|
{
|
||||||
|
return lhs.x * rhs.x + lhs.y * rhs.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 Vector2::Perpendicular(Vector2 lhs)
|
||||||
|
{
|
||||||
|
return Perpendicular(lhs, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 Vector2::Perpendicular(Vector2 lhs, bool inward)
|
||||||
|
{
|
||||||
|
if (inward)
|
||||||
|
{
|
||||||
|
return Vector2
|
||||||
|
(
|
||||||
|
-lhs.y, lhs.x
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Vector2
|
||||||
|
(
|
||||||
|
lhs.y, -lhs.x
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 Vector2::Project(Vector2 vec, Vector2 direction)
|
||||||
|
{
|
||||||
|
return direction.GetNormalised() * vec.GetMagnitude();
|
||||||
|
}
|
||||||
|
Vector2 Vector2::Reflect(Vector2 vec, Vector2 normal)
|
||||||
|
{
|
||||||
|
return vec - (Project(vec, normal.GetNormalised()) * 2.0);
|
||||||
|
}
|
||||||
|
Vector2 Vector2::RotateRadians(Vector2 vec, double radians)
|
||||||
|
{
|
||||||
|
const double SINE = sin(radians);
|
||||||
|
const double COSINE = cos(radians);
|
||||||
|
|
||||||
|
return Vector2
|
||||||
|
(
|
||||||
|
vec.x * COSINE - vec.y * SINE,
|
||||||
|
vec.x * SINE + vec.y * COSINE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Vector2 Vector2::RotateDegrees(Vector2 vec, double degrees)
|
||||||
|
{
|
||||||
|
return RotateRadians(vec, Math::DegreesToRadians(degrees));
|
||||||
|
}
|
||||||
|
Vector2 Vector2::Min(Vector2 lhs, Vector2 rhs)
|
||||||
|
{
|
||||||
|
double lx = lhs.x, rx = rhs.x;
|
||||||
|
double ly = lhs.y, ry = rhs.y;
|
||||||
|
|
||||||
|
return Vector2(std::min(lx, rx),
|
||||||
|
std::min(ly, ry));
|
||||||
|
}
|
||||||
|
Vector2 Vector2::Max(Vector2 lhs, Vector2 rhs)
|
||||||
|
{
|
||||||
|
double lx = lhs.x, rx = rhs.x;
|
||||||
|
double ly = lhs.y, ry = rhs.y;
|
||||||
|
|
||||||
|
return Vector2(std::max(lx, rx),
|
||||||
|
std::max(ly, ry));
|
||||||
|
}
|
||||||
|
Vector2 Vector2::Lerp(Vector2 a, Vector2 b, double t)
|
||||||
|
{
|
||||||
|
return LerpUnclamped(a, b, std::clamp(t, 0.0, 1.0));
|
||||||
|
}
|
||||||
|
Vector2 Vector2::LerpUnclamped(Vector2 a, Vector2 b, double t)
|
||||||
|
{
|
||||||
|
return a + ((b - a) * t);
|
||||||
|
}
|
||||||
|
Vector2 Vector2::MoveTowards(Vector2 current, Vector2 target, double maxDistanceDelta)
|
||||||
|
{
|
||||||
|
// Ignore if it is exactly on the same point
|
||||||
|
if (current == target)
|
||||||
|
return target;
|
||||||
|
|
||||||
|
// Calculate new position
|
||||||
|
Vector2 DELTA = (target - current).GetNormalised() * maxDistanceDelta;
|
||||||
|
Vector2 newPos = current + DELTA;
|
||||||
|
|
||||||
|
// Check if check if is behind or ahead of target
|
||||||
|
Vector2 DIFF = target - newPos;
|
||||||
|
if (Dot(DELTA, DIFF) < 0.0)
|
||||||
|
{
|
||||||
|
newPos = target;
|
||||||
|
}
|
||||||
|
return newPos;
|
||||||
|
}
|
||||||
|
Vector2 Vector2::operator+(Vector2 lhs, Vector2 rhs)
|
||||||
|
{
|
||||||
|
return Vector2
|
||||||
|
(
|
||||||
|
lhs.x + rhs.x,
|
||||||
|
lhs.y + rhs.y
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Vector2 Vector2::operator-(Vector2 lhs, Vector2 rhs)
|
||||||
|
{
|
||||||
|
return Vector2
|
||||||
|
(
|
||||||
|
lhs.x - rhs.x,
|
||||||
|
lhs.y - rhs.y
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Vector2 Vector2::operator*(Vector2 lhs, Vector2 rhs)
|
||||||
|
{
|
||||||
|
return Vector2
|
||||||
|
(
|
||||||
|
lhs.x * rhs.x,
|
||||||
|
lhs.y * rhs.y
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Vector2 Vector2::operator*(Vector2 lhs, double rhs)
|
||||||
|
{
|
||||||
|
return Vector2
|
||||||
|
(
|
||||||
|
lhs.x * rhs,
|
||||||
|
lhs.y * rhs
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Vector2 Vector2::operator/(Vector2 lhs, double rhs)
|
||||||
|
{
|
||||||
|
return Vector2
|
||||||
|
(
|
||||||
|
lhs.x / rhs,
|
||||||
|
lhs.y / rhs
|
||||||
|
);
|
||||||
|
}
|
||||||
|
bool Vector2::operator==(Vector2 lhs, Vector2 rhs)
|
||||||
|
{
|
||||||
|
return lhs.Equals(rhs);
|
||||||
|
}
|
||||||
|
bool Vector2::operator!=(Vector2 lhs, Vector2 rhs)
|
||||||
|
{
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
} // namespace PlushieAPI::Mathematics
|
|
@ -0,0 +1,396 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file Vector2.hxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Nov 2, 2021
|
||||||
|
\brief Contains the definitions of Vector2 struct.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
// Standard Libraries
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
///<summary>
|
||||||
|
/// CLR version of the the PlushieEngine's Vector2 class that represents a
|
||||||
|
/// 2-Dimensional Vector. Designed to closely match Unity's Vector2 struct.
|
||||||
|
/// </summary>
|
||||||
|
[System::Runtime::InteropServices::StructLayout(System::Runtime::InteropServices::LayoutKind::Sequential)]
|
||||||
|
public value struct Vector2 : public System::IEquatable<Vector2>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Constants */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
#pragma region Constants
|
||||||
|
///<summary>
|
||||||
|
/// Shorthand for writing Vector2(0, -1).
|
||||||
|
///</summary>
|
||||||
|
static initonly Vector2 Down = Vector2(0.0, -1.0);
|
||||||
|
///<summary>
|
||||||
|
/// Shorthand for writing Vector2(-1, 0).
|
||||||
|
///</summary>
|
||||||
|
static initonly Vector2 Left = Vector2(-1.0, 0.0);
|
||||||
|
///<summary>
|
||||||
|
/// Shorthand for writing Vector2(double.NegativeInfinity,
|
||||||
|
/// double.NegativeInfinity).
|
||||||
|
///</summary>
|
||||||
|
static initonly Vector2 NegativeInfinity = Vector2(std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest());
|
||||||
|
///<summary>
|
||||||
|
/// Shorthand for writing Vector2(1, 1).
|
||||||
|
///</summary>
|
||||||
|
static initonly Vector2 One = Vector2(1.0, 1.0);
|
||||||
|
///<summary>
|
||||||
|
/// Shorthand for writing Vector2(double.PositiveInfinity,
|
||||||
|
/// double.PositiveInfinity).
|
||||||
|
///</summary>
|
||||||
|
static initonly Vector2 PositiveInfinity = Vector2(std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
|
||||||
|
///<summary>
|
||||||
|
/// Shorthand for writing Vector2(1, 0).
|
||||||
|
///</summary>
|
||||||
|
static initonly Vector2 Right = Vector2(1.0, 0.0);
|
||||||
|
///<summary>
|
||||||
|
/// Shorthand for writing Vector2(0, 1).
|
||||||
|
///</summary>
|
||||||
|
static initonly Vector2 Up = Vector2(0.0, 1.0);
|
||||||
|
///<summary>
|
||||||
|
/// Shorthand for writing Vector2(0, 0).
|
||||||
|
///</summary>
|
||||||
|
static initonly Vector2 Zero = Vector2(0.0, 0.0);
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Public Members */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
///<summary>
|
||||||
|
/// X-component of the Vector2.
|
||||||
|
///</summary>
|
||||||
|
double x;
|
||||||
|
///<summary>
|
||||||
|
/// Y-component of the Vector2.
|
||||||
|
///</summary>
|
||||||
|
double y;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Constructors */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor to construct a Vector2 with the specified components with the
|
||||||
|
/// Y-component set to 0.0.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="_x">X-coordinate to set.</param>
|
||||||
|
Vector2(double _x);
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor to construct a Vector2 with the specified components..
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="_x">X-coordinate to set.</param>
|
||||||
|
/// <param name="_y">Y-coordinate to set.</param>
|
||||||
|
Vector2(double _x, double _y);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Usage Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Normalises this current Vector2. This changes the data of this Vector2.
|
||||||
|
/// If you would like to get a copy, use GetNormalised() instead.
|
||||||
|
/// This function does nothing to a zero vector.
|
||||||
|
/// </summary>
|
||||||
|
void Normalise();
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a copy of this Vector2 and returns a normalized version.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// Returns a normalised copy of this Vector2.
|
||||||
|
/// If this Vector2 is a zero vector, a zero vector will be returned.
|
||||||
|
/// </returns>
|
||||||
|
Vector2 GetNormalised();
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates and returns the magnitude of this Vector2. Note that this function
|
||||||
|
/// incurs a performance cost from the square root calculation. If you do not
|
||||||
|
/// need the precise magnitude, consider using GetSqrMagnitude() instead.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns the length of this Vector2.</returns>
|
||||||
|
double GetMagnitude();
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates and returns the squared magnitude of this Vector2.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns the squared length of this Vector2.</returns>
|
||||||
|
double GetSqrMagnitude();
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates and returns the angle of this vector from the right vector. This
|
||||||
|
/// function returns values between -Math.PI and Math.PI.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns the angle of this vector from the right vector in radians.</returns>
|
||||||
|
double AngleFromRightRadians();
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates and returns the angle of this vector from the right vector. This
|
||||||
|
/// function returns values between -180.0 and 180.0.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns the angle of this vector from the right vector in degrees.</returns>
|
||||||
|
double AngleFromRightDegrees();
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a specified point is near this Vector2 that represents a point with
|
||||||
|
/// a tolerance value of PLS_EPSILON.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="point">The other point to check if we are near.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// True if this Vector2 representing a point and the specified point are within
|
||||||
|
/// the range of the specified tolerance. False otherwise.
|
||||||
|
/// </returns>
|
||||||
|
bool IsNearPoint(Vector2 point);
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a specified point is near this Vector2 that represents a point.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="point">The other point to check if we are near.</param>
|
||||||
|
/// <param name="tolerance">
|
||||||
|
/// The amount of tolerance before we consider these points as "near".
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// True if this Vector2 representing a point and the specified point are within
|
||||||
|
/// the range of the specified tolerance. False otherwise.
|
||||||
|
/// </returns>
|
||||||
|
bool IsNearPoint(Vector2 point, double tolerance);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* IEquatable */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Compares equality with an object of the same type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other">The object to compare with.</param>
|
||||||
|
/// <returns>True if both objects are the same.</returns>
|
||||||
|
virtual bool Equals(Vector2 other);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Object */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Compares equality with another unboxed object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="o">The unboxed object to compare with.</param>
|
||||||
|
/// <returns>True if both objects are the same.</returns>
|
||||||
|
bool Equals(Object^ o) override;
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a unique hash for this object.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Unique hash for this object.</returns>
|
||||||
|
int GetHashCode() override;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Static Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if two specified Vector2s are near in value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector2 to check if is near in value.</param>
|
||||||
|
/// <param name="rhs">Another Vector2 to check if is near in value.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// True if the two Vector2s are within the tolerance value specified
|
||||||
|
/// </returns>
|
||||||
|
static bool IsNear(Vector2 lhs, Vector2 rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if two specified Vector2s are near in value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector2 to check if is near in value.</param>
|
||||||
|
/// <param name="rhs">Another Vector2 to check if is near in value.</param>
|
||||||
|
/// <param name="tolerance">
|
||||||
|
/// Amount of tolerance to do the comparison with.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// True if the two Vector2s are within the tolerance value specified
|
||||||
|
/// </returns>
|
||||||
|
static bool IsNear(Vector2 lhs, Vector2 rhs, double tolerance);
|
||||||
|
/// <summary>
|
||||||
|
/// Computes and returns the dot product of 2 specified Vector2s.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector2 to calculate dot product with.</param>
|
||||||
|
/// <param name="rhs">Another Vector2 to calculate dot product with.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// Scalar value representing the dot product of the two Vector2s.
|
||||||
|
/// </returns>
|
||||||
|
static double Dot(Vector2 lhs, Vector2 rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Computes the inward perpendicular Vector2 to the specified Vector2.
|
||||||
|
/// Equivalent to calling Perpendicular(lhs, true). This means, the
|
||||||
|
/// resultant Vector2 is rotated 90-degrees in a counter-clockwise.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector2 to find a perpendicular of.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// The perpendicular Vector2 relative to the specified Vector2.
|
||||||
|
/// </returns>
|
||||||
|
static Vector2 Perpendicular(Vector2 lhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Computes a perpendicular Vector2 to the specified Vector2.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector2 to find a perpendicular of.</param>
|
||||||
|
/// <param name="inward">
|
||||||
|
/// Whether the inward perpendicular Vector is retrieved. If true, the
|
||||||
|
/// resultant vector is rotated 90-degrees in a counter-clockwise.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>The perpendicular Vector2 relative to the specified Vector2.
|
||||||
|
/// </returns>
|
||||||
|
static Vector2 Perpendicular(Vector2 lhs, bool inward);
|
||||||
|
/// <summary>
|
||||||
|
/// Computes and returns a Vector2 projection.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vec">Vector2 to project.</param>
|
||||||
|
/// <param name="direction">Vector2 to project onto.</param>
|
||||||
|
/// <returns>The Vector2 that represents the projected vec onto direction.</returns>
|
||||||
|
static Vector2 Project(Vector2 vec, Vector2 direction);
|
||||||
|
/// <summary>
|
||||||
|
/// Reflects a Vector2 across another Vector2.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vec">A Vector2 to reflect.</param>
|
||||||
|
/// <param name="normal">A normal to reflect the Vector2 across.</param>
|
||||||
|
/// <returns>The Vector2 that represents vec reflected across normal.</returns>
|
||||||
|
static Vector2 Reflect(Vector2 vec, Vector2 normal);
|
||||||
|
/// <summary>
|
||||||
|
/// Rotates a Vector2 on the Z-axis by a specified angle in an anti-clockwise
|
||||||
|
/// direction.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vec">A Vector2 to rotate.</param>
|
||||||
|
/// <param name="radians">
|
||||||
|
/// Angle to rotate the vector by in an anti-clockwise direction in radians.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>The Vector2 that represents the rotated vector.</returns>
|
||||||
|
static Vector2 RotateRadians(Vector2 vec, double radians);
|
||||||
|
/// <summary>
|
||||||
|
/// Rotates a Vector2 on the Z-axis by a specified angle in an anti-clockwise
|
||||||
|
/// direction.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vec">A Vector2 to rotate.</param>
|
||||||
|
/// <param name="degrees">
|
||||||
|
/// Angle to rotate the vector by in an anti-clockwise direction in degrees.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>The Vector2 that represents the rotated vector.</returns>
|
||||||
|
static Vector2 RotateDegrees(Vector2 vec, double degrees);
|
||||||
|
/// <summary>
|
||||||
|
/// Computes and returns a Vector2 that is made from the smallest components of
|
||||||
|
/// the two specified Vector2s.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector2 to calculate minimum Vector2 with.</param>
|
||||||
|
/// <param name="rhs">Another Vector2 to calculate minimum Vector2 with.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// The Vector2 that contains the smallest components of the two specified
|
||||||
|
/// Vector2s.
|
||||||
|
/// </returns>
|
||||||
|
static Vector2 Min(Vector2 lhs, Vector2 rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Computes and returns a Vector2 that is made from the largest components of
|
||||||
|
/// the two specified Vector2s.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector2 to calculate maximum Vector2 with.</param>
|
||||||
|
/// <param name="rhs">Another Vector2 to calculate maximum Vector2 with.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// The Vector2 that contains the largest components of the two specified
|
||||||
|
/// Vector2s.
|
||||||
|
/// </returns>
|
||||||
|
static Vector2 Max(Vector2 lhs, Vector2 rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Linearly interpolates between two specified points.
|
||||||
|
/// This is most commonly used to find a point some fraction of the way along a
|
||||||
|
/// line between two endpoints.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a">The start Vector2, returned when t = 0.0.</param>
|
||||||
|
/// <param name="b">The end Vector2, returned when t = 1.0.</param>
|
||||||
|
/// <param name="t">
|
||||||
|
/// Value used to interpolate between a and b which is clamped to
|
||||||
|
/// the range[0, 1].
|
||||||
|
/// </param>
|
||||||
|
/// <returns>The interpolated Vector2.</returns>
|
||||||
|
static Vector2 Lerp(Vector2 a, Vector2 b, double t);
|
||||||
|
/// <summary>
|
||||||
|
/// Linearly interpolates between two specified points.
|
||||||
|
/// This is most commonly used to find a point some fraction of the way along a
|
||||||
|
/// line between two endpoints.
|
||||||
|
/// Unlike Lerp(), t is not clamped to a range at all.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a">The start Vector2, returned when t = 0.0.</param>
|
||||||
|
/// <param name="b">The end Vector2, returned when t = 1.0.</param>
|
||||||
|
/// <param name="t">Value used to interpolate between a and b.</param>
|
||||||
|
/// <returns>The interpolated Vector2.</returns>
|
||||||
|
static Vector2 LerpUnclamped(Vector2 a, Vector2 b, double t);
|
||||||
|
/// <summary>
|
||||||
|
/// Moves a point current towards target.
|
||||||
|
/// Similar to Lerp(), however, the function will ensure that the distance never
|
||||||
|
/// exceeds maxDistanceDelta. Negative values of maxDistanceDelta pushes the
|
||||||
|
/// vector away from target
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="current">The current position of the point.</param>
|
||||||
|
/// <param name="target">The target position to move to.</param>
|
||||||
|
/// <param name="maxDistanceDelta">Maximum distance moved per call.</param>
|
||||||
|
/// <returns>Vector representing the moved point.</returns>
|
||||||
|
static Vector2 MoveTowards(Vector2 current, Vector2 target, double maxDistanceDelta);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Overloaded Operators */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Adds two Vector2s together and returns the result.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector2 to add.</param>
|
||||||
|
/// <param name="rhs">Another Vector2 to add.</param>
|
||||||
|
/// <returns>The result of lhs added to rhs</returns>
|
||||||
|
static Vector2 operator+(Vector2 lhs, Vector2 rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Subtracts a Vector2 from another Vector2 and returns the result.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector2 to subtract from.</param>
|
||||||
|
/// <param name="rhs">Another Vector2 to subtract.</param>
|
||||||
|
/// <returns>The result of rhs subtracted from lhs.</returns>
|
||||||
|
static Vector2 operator-(Vector2 lhs, Vector2 rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates the component-wise multiplication of two Vector2s and returns the
|
||||||
|
/// result.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector2 to multiply with.</param>
|
||||||
|
/// <param name="rhs">Another Vector2 to multiply with.</param>
|
||||||
|
/// <returns>The result of rhs subtracted from lhs.</returns>
|
||||||
|
static Vector2 operator*(Vector2 lhs, Vector2 rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates the multiplication of a Vector2 with a scalar value and returns
|
||||||
|
/// the result.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector2 to multiply with.</param>
|
||||||
|
/// <param name="rhs">Scalar to multiply with.</param>
|
||||||
|
/// <returns>The result of the scalar multiplication.</returns>
|
||||||
|
static Vector2 operator*(Vector2 lhs, double rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates the division of a Vector2 with a scalar value and returns
|
||||||
|
/// the result.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Scalar to divide with.</param>
|
||||||
|
/// <param name="rhs">Vector2 to divide with.</param>
|
||||||
|
/// <returns>The result of the scalar division.</returns>
|
||||||
|
static Vector2 operator/(Vector2 lhs, double rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if two Vector2s are approximately equal. This is equivalent to
|
||||||
|
/// calling Vector2.IsNear() with default tolerance values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector2 to compare.</param>
|
||||||
|
/// <param name="rhs">Another Vector2 to compare.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// True if all components are approximately equal within the default
|
||||||
|
/// tolerance value.
|
||||||
|
/// </returns>
|
||||||
|
static bool operator==(Vector2 lhs, Vector2 rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if two Vector2s are not approximately equal. This is equivalent to
|
||||||
|
/// calling !Vector2.IsNear() with default tolerance values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector2 to compare.</param>
|
||||||
|
/// <param name="rhs">Another Vector2 to compare.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// True if all components are not approximately equal within the default
|
||||||
|
/// tolerance value.
|
||||||
|
/// </returns>
|
||||||
|
static bool operator!=(Vector2 lhs, Vector2 rhs);
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,278 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file Vector3.cxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 24, 2021
|
||||||
|
\brief Contains the definitions of functions of the Vector3 struct.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Precompiled Headers
|
||||||
|
#include "SHpch.h"
|
||||||
|
// Primary Header
|
||||||
|
#include "Vector3.hxx"
|
||||||
|
// Standard Libraries
|
||||||
|
#include <cmath>
|
||||||
|
#include <algorithm>
|
||||||
|
// Project Headers
|
||||||
|
#include "Math.hxx"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
Vector3::Vector3(double _x)
|
||||||
|
: Vector3 {_x, 0.0, 0.0}
|
||||||
|
{}
|
||||||
|
Vector3::Vector3(double _x, double _y)
|
||||||
|
: Vector3 {_x, _y, 0.0}
|
||||||
|
{}
|
||||||
|
Vector3::Vector3(double _x, double _y, double _z)
|
||||||
|
: x { _x }
|
||||||
|
, y { _y }
|
||||||
|
, z { _z }
|
||||||
|
{}
|
||||||
|
Vector3::Vector3(Vector2 vec)
|
||||||
|
: Vector3(vec.x, vec.y)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Usage Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void Vector3::Normalise()
|
||||||
|
{
|
||||||
|
*this = GetNormalised();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 Vector3::GetNormalised()
|
||||||
|
{
|
||||||
|
return *this / GetSqrMagnitude();
|
||||||
|
}
|
||||||
|
|
||||||
|
double Vector3::GetMagnitude()
|
||||||
|
{
|
||||||
|
return sqrt(x * x + y * y + z * z);
|
||||||
|
}
|
||||||
|
|
||||||
|
double Vector3::GetSqrMagnitude()
|
||||||
|
{
|
||||||
|
return x * x + y * y + z * z;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Vector3::Angle2DFromRightRadians()
|
||||||
|
{
|
||||||
|
return atan2(y, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
double Vector3::Angle2DFromRightDegrees()
|
||||||
|
{
|
||||||
|
return Math::RadiansToDegrees(Angle2DFromRightRadians());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Vector3::IsNearPoint(Vector3 point)
|
||||||
|
{
|
||||||
|
return IsNearPoint(point, Math::Epsilon);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Vector3::IsNearPoint(Vector3 point, double tolerance)
|
||||||
|
{
|
||||||
|
return (*this - point).GetSqrMagnitude() < (tolerance * tolerance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* IEquatable */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
bool Vector3::Equals(Object^ o)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Vector3 vec = safe_cast<Vector3>(o);
|
||||||
|
return Equals(vec);
|
||||||
|
}
|
||||||
|
catch (System::InvalidCastException^)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Object Overrides */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
bool Vector3::Equals(Vector3 other)
|
||||||
|
{
|
||||||
|
return IsNear(*this, other);
|
||||||
|
}
|
||||||
|
int Vector3::GetHashCode()
|
||||||
|
{
|
||||||
|
const int HASH = 19;
|
||||||
|
const int HASH2 = 23;
|
||||||
|
return x.GetHashCode() * HASH + y.GetHashCode() * HASH2 + z.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Static Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
bool Vector3::IsNear(Vector3 lhs, Vector3 rhs)
|
||||||
|
{
|
||||||
|
return IsNear(lhs, rhs, Math::Epsilon);
|
||||||
|
}
|
||||||
|
bool Vector3::IsNear(Vector3 lhs, Vector3 rhs, double tolerance)
|
||||||
|
{
|
||||||
|
return (std::abs(lhs.x) - std::abs(rhs.x)) < tolerance
|
||||||
|
&&
|
||||||
|
(std::abs(lhs.y) - std::abs(rhs.y)) < tolerance
|
||||||
|
&&
|
||||||
|
(std::abs(lhs.z) - std::abs(rhs.z)) < tolerance;
|
||||||
|
}
|
||||||
|
double Vector3::Dot(Vector3 lhs, Vector3 rhs)
|
||||||
|
{
|
||||||
|
return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;
|
||||||
|
}
|
||||||
|
Vector3 Vector3::Cross(Vector3 lhs, Vector3 rhs)
|
||||||
|
{
|
||||||
|
return Vector3(lhs.y * rhs.z - lhs.z * rhs.y,
|
||||||
|
lhs.z * rhs.x - lhs.x * rhs.z,
|
||||||
|
lhs.x * rhs.y - lhs.y * rhs.x);
|
||||||
|
}
|
||||||
|
Vector3 Vector3::Project(Vector3 vec, Vector3 direction)
|
||||||
|
{
|
||||||
|
return direction.GetNormalised() * vec.GetMagnitude();
|
||||||
|
}
|
||||||
|
Vector3 Vector3::Reflect(Vector3 vec, Vector3 normal)
|
||||||
|
{
|
||||||
|
return vec - (Project(vec, normal.GetNormalised()) * 2.0);
|
||||||
|
}
|
||||||
|
Vector3 Vector3::RotateRadians(Vector3 vec, double radians)
|
||||||
|
{
|
||||||
|
const double SINE = sin(radians);
|
||||||
|
const double COSINE = cos(radians);
|
||||||
|
|
||||||
|
return Vector3
|
||||||
|
(
|
||||||
|
vec.x * COSINE - vec.y * SINE,
|
||||||
|
vec.x * SINE + vec.y * COSINE,
|
||||||
|
vec.z
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Vector3 Vector3::RotateDegrees(Vector3 vec, double degrees)
|
||||||
|
{
|
||||||
|
return RotateRadians(vec, Math::DegreesToRadians(degrees));
|
||||||
|
}
|
||||||
|
Vector3 Vector3::Min(Vector3 lhs, Vector3 rhs)
|
||||||
|
{
|
||||||
|
double lx = lhs.x, rx = rhs.x;
|
||||||
|
double ly = lhs.y, ry = rhs.y;
|
||||||
|
double lz = lhs.z, rz = rhs.z;
|
||||||
|
|
||||||
|
return Vector3(std::min(lx, rx),
|
||||||
|
std::min(ly, ry),
|
||||||
|
std::min(lz, rz));
|
||||||
|
}
|
||||||
|
Vector3 Vector3::Max(Vector3 lhs, Vector3 rhs)
|
||||||
|
{
|
||||||
|
double lx = lhs.x, rx = rhs.x;
|
||||||
|
double ly = lhs.y, ry = rhs.y;
|
||||||
|
double lz = lhs.z, rz = rhs.z;
|
||||||
|
|
||||||
|
return Vector3(std::max(lx, rx),
|
||||||
|
std::max(ly, ry),
|
||||||
|
std::max(lz, rz));
|
||||||
|
}
|
||||||
|
Vector3 Vector3::Lerp(Vector3 a, Vector3 b, double t)
|
||||||
|
{
|
||||||
|
return LerpUnclamped(a, b, std::clamp(t, 0.0, 1.0));
|
||||||
|
}
|
||||||
|
Vector3 Vector3::LerpUnclamped(Vector3 a, Vector3 b, double t)
|
||||||
|
{
|
||||||
|
return a + ((b - a) * t);
|
||||||
|
}
|
||||||
|
Vector3 Vector3::MoveTowards(Vector3 current, Vector3 target, double maxDistanceDelta)
|
||||||
|
{
|
||||||
|
// Ignore if it is exactly on the same point
|
||||||
|
if (current == target)
|
||||||
|
return target;
|
||||||
|
|
||||||
|
// Calculate new position
|
||||||
|
Vector3 DELTA = (target - current).GetNormalised() * maxDistanceDelta;
|
||||||
|
Vector3 newPos = current + DELTA;
|
||||||
|
|
||||||
|
// Check if check if is behind or ahead of target
|
||||||
|
Vector3 DIFF = target - newPos;
|
||||||
|
if (Dot(DELTA, DIFF) < 0.0)
|
||||||
|
{
|
||||||
|
newPos = target;
|
||||||
|
}
|
||||||
|
return newPos;
|
||||||
|
}
|
||||||
|
Vector3 Vector3::operator+(Vector3 lhs, Vector3 rhs)
|
||||||
|
{
|
||||||
|
return Vector3
|
||||||
|
(
|
||||||
|
lhs.x + rhs.x,
|
||||||
|
lhs.y + rhs.y,
|
||||||
|
lhs.z + rhs.z
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Vector3 Vector3::operator-(Vector3 lhs, Vector3 rhs)
|
||||||
|
{
|
||||||
|
return Vector3
|
||||||
|
(
|
||||||
|
lhs.x - rhs.x,
|
||||||
|
lhs.y - rhs.y,
|
||||||
|
lhs.z - rhs.z
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Vector3 Vector3::operator*(Vector3 lhs, Vector3 rhs)
|
||||||
|
{
|
||||||
|
return Vector3
|
||||||
|
(
|
||||||
|
lhs.x * rhs.x,
|
||||||
|
lhs.y * rhs.y,
|
||||||
|
lhs.z * rhs.z
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Vector3 Vector3::operator*(Vector3 lhs, double rhs)
|
||||||
|
{
|
||||||
|
return Vector3
|
||||||
|
(
|
||||||
|
lhs.x * rhs,
|
||||||
|
lhs.y * rhs,
|
||||||
|
lhs.z * rhs
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Vector3 Vector3::operator/(Vector3 lhs, double rhs)
|
||||||
|
{
|
||||||
|
return Vector3
|
||||||
|
(
|
||||||
|
lhs.x / rhs,
|
||||||
|
lhs.y / rhs,
|
||||||
|
lhs.z / rhs
|
||||||
|
);
|
||||||
|
}
|
||||||
|
bool Vector3::operator==(Vector3 lhs, Vector3 rhs)
|
||||||
|
{
|
||||||
|
return lhs.Equals(rhs);
|
||||||
|
}
|
||||||
|
bool Vector3::operator!=(Vector3 lhs, Vector3 rhs)
|
||||||
|
{
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Conversion Operators */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
Vector3::operator Vector2(Vector3 vec)
|
||||||
|
{
|
||||||
|
return Vector2(vec.x, vec.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3::operator Vector3(Vector2 vec)
|
||||||
|
{
|
||||||
|
return Vector3(vec);
|
||||||
|
}
|
||||||
|
} // namespace PlushieAPI::Mathematics
|
|
@ -0,0 +1,425 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file Vector3.hxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 24, 2021
|
||||||
|
\brief Contains the definitions of Vector3 struct.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
// Standard Libraries
|
||||||
|
#include <limits>
|
||||||
|
// Project Includes
|
||||||
|
#include "Vector2.hxx"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
///<summary>
|
||||||
|
/// CLR version of the the PlushieEngine's Vector3 class that represents a
|
||||||
|
/// 3-Dimensional Vector. Designed to closely match Unity's Vector3 struct.
|
||||||
|
/// </summary>
|
||||||
|
[System::Runtime::InteropServices::StructLayout(System::Runtime::InteropServices::LayoutKind::Sequential)]
|
||||||
|
public value struct Vector3 : public System::IEquatable<Vector3>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Constants */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
#pragma region Constants
|
||||||
|
///<summary>
|
||||||
|
/// Shorthand for writing Vector3(0, 0, -1).
|
||||||
|
///</summary>
|
||||||
|
static initonly Vector3 Back = Vector3(0.0, 0.0, -1.0);
|
||||||
|
///<summary>
|
||||||
|
/// Shorthand for writing Vector3(0, -1, 0).
|
||||||
|
///</summary>
|
||||||
|
static initonly Vector3 Down = Vector3(0.0, -1.0, 0.0);
|
||||||
|
///<summary>
|
||||||
|
/// Shorthand for writing Vector3(0, 0, 1).
|
||||||
|
///</summary>
|
||||||
|
static initonly Vector3 Forward = Vector3(0.0, 0.0, 1.0);
|
||||||
|
///<summary>
|
||||||
|
/// Shorthand for writing Vector3(-1, 0, 0).
|
||||||
|
///</summary>
|
||||||
|
static initonly Vector3 Left = Vector3(-1.0, 0.0, 0.0);
|
||||||
|
///<summary>
|
||||||
|
/// Shorthand for writing Vector3(double.NegativeInfinity,
|
||||||
|
/// double.NegativeInfinity, double.NegativeInfinity).
|
||||||
|
///</summary>
|
||||||
|
static initonly Vector3 NegativeInfinity = Vector3(std::numeric_limits<double>::lowest(),
|
||||||
|
std::numeric_limits<double>::lowest(),
|
||||||
|
std::numeric_limits<double>::lowest());
|
||||||
|
///<summary>
|
||||||
|
/// Shorthand for writing Vector3(1, 1, 1).
|
||||||
|
///</summary>
|
||||||
|
static initonly Vector3 One = Vector3(1.0, 1.0, 1.0);
|
||||||
|
///<summary>
|
||||||
|
/// Shorthand for writing Vector3(double.PositiveInfinity,
|
||||||
|
/// double.PositiveInfinity, double.PositiveInfinity).
|
||||||
|
///</summary>
|
||||||
|
static initonly Vector3 PositiveInfinity = Vector3(std::numeric_limits<double>::max(),
|
||||||
|
std::numeric_limits<double>::max(),
|
||||||
|
std::numeric_limits<double>::max());
|
||||||
|
///<summary>
|
||||||
|
/// Shorthand for writing Vector3(1, 0, 0).
|
||||||
|
///</summary>
|
||||||
|
static initonly Vector3 Right = Vector3(1.0, 0.0, 0.0);
|
||||||
|
///<summary>
|
||||||
|
/// Shorthand for writing Vector3(0, 1, 0).
|
||||||
|
///</summary>
|
||||||
|
static initonly Vector3 Up = Vector3(0.0, 1.0, 0.0);
|
||||||
|
///<summary>
|
||||||
|
/// Shorthand for writing Vector3(0, 0, 0).
|
||||||
|
///</summary>
|
||||||
|
static initonly Vector3 Zero = Vector3(0.0, 0.0, 0.0);
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Public Members */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
///<summary>
|
||||||
|
/// X-component of the Vector3.
|
||||||
|
///</summary>
|
||||||
|
double x;
|
||||||
|
///<summary>
|
||||||
|
/// Y-component of the Vector3.
|
||||||
|
///</summary>
|
||||||
|
double y;
|
||||||
|
///<summary>
|
||||||
|
/// Z-component of the Vector3.
|
||||||
|
///</summary>
|
||||||
|
double z;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Constructors */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor to construct a Vector3 with the specified components with the
|
||||||
|
/// Y and Z-component set to 0.0.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="_x">X-coordinate to set.</param>
|
||||||
|
Vector3(double _x);
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor to construct a Vector3 with the specified components with the
|
||||||
|
/// Z-component set to 0.0.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="_x">X-coordinate to set.</param>
|
||||||
|
/// <param name="_y">Y-coordinate to set.</param>
|
||||||
|
Vector3(double _x, double _y);
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor to construct a Vector3 with the specified components.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="_x">X-coordinate to set.</param>
|
||||||
|
/// <param name="_y">Y-coordinate to set.</param>
|
||||||
|
/// <param name="_z">Z-coordinate to set.</param>
|
||||||
|
Vector3(double _x, double _y, double _z);
|
||||||
|
/// <summary>
|
||||||
|
/// Conversion constructor to construct a Vector3 using a Vector2.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vec"></param>
|
||||||
|
Vector3(Vector2 vec);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Usage Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Normalises this current Vector3. This changes the data of this Vector3.
|
||||||
|
/// If you would like to get a copy, use GetNormalised() instead.
|
||||||
|
/// This function does nothing to a zero vector.
|
||||||
|
/// </summary>
|
||||||
|
void Normalise();
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a copy of this Vector3 and returns a normalized version.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// Returns a normalised copy of this Vector3.
|
||||||
|
/// If this Vector3 is a zero vector, a zero vector will be returned.
|
||||||
|
/// </returns>
|
||||||
|
Vector3 GetNormalised();
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates and returns the magnitude of this Vector3. Note that this function
|
||||||
|
/// incurs a performance cost from the square root calculation. If you do not
|
||||||
|
/// need the precise magnitude, consider using GetSqrMagnitude() instead.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns the length of this Vector3.</returns>
|
||||||
|
double GetMagnitude();
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates and returns the squared magnitude of this Vector3.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns the squared length of this Vector3.</returns>
|
||||||
|
double GetSqrMagnitude();
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates and returns the angle of this vector from the right vector. This
|
||||||
|
/// function returns values between -Math.PI and Math.PI.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns the angle of this vector from the right vector in radians.</returns>
|
||||||
|
double Angle2DFromRightRadians();
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates and returns the angle of this vector from the right vector. This
|
||||||
|
/// function returns values between -180.0 and 180.0.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns the angle of this vector from the right vector in degrees.</returns>
|
||||||
|
double Angle2DFromRightDegrees();
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a specified point is near this Vector3 that represents a point with
|
||||||
|
/// a tolerance value of PLS_EPSILON.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="point">The other point to check if we are near.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// True if this Vector3 representing a point and the specified point are within
|
||||||
|
/// the range of the specified tolerance. False otherwise.
|
||||||
|
/// </returns>
|
||||||
|
bool IsNearPoint(Vector3 point);
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a specified point is near this Vector3 that represents a point.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="point">The other point to check if we are near.</param>
|
||||||
|
/// <param name="tolerance">
|
||||||
|
/// The amount of tolerance before we consider these points as "near".
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// True if this Vector3 representing a point and the specified point are within
|
||||||
|
/// the range of the specified tolerance. False otherwise.
|
||||||
|
/// </returns>
|
||||||
|
bool IsNearPoint(Vector3 point, double tolerance);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* IEquatable */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Compares equality with an object of the same type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other">The object to compare with.</param>
|
||||||
|
/// <returns>True if both objects are the same.</returns>
|
||||||
|
virtual bool Equals(Vector3 other);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Object */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Compares equality with another unboxed object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="o">The unboxed object to compare with.</param>
|
||||||
|
/// <returns>True if both objects are the same.</returns>
|
||||||
|
bool Equals(Object^ o) override;
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a unique hash for this object.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Unique hash for this object.</returns>
|
||||||
|
int GetHashCode() override;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Static Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if two specified Vector3s are near in value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector3 to check if is near in value.</param>
|
||||||
|
/// <param name="rhs">Another Vector3 to check if is near in value.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// True if the two Vector3s are within the tolerance value specified
|
||||||
|
/// </returns>
|
||||||
|
static bool IsNear(Vector3 lhs, Vector3 rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if two specified Vector3s are near in value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector3 to check if is near in value.</param>
|
||||||
|
/// <param name="rhs">Another Vector3 to check if is near in value.</param>
|
||||||
|
/// <param name="tolerance">Amount of tolerance to do the comparison with.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// True if the two Vector3s are within the tolerance value specified
|
||||||
|
/// </returns>
|
||||||
|
static bool IsNear(Vector3 lhs, Vector3 rhs, double tolerance);
|
||||||
|
/// <summary>
|
||||||
|
/// Computes and returns the dot product of 2 specified Vector3s.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector3 to calculate dot product with.</param>
|
||||||
|
/// <param name="rhs">Another Vector3 to calculate dot product with.</param>
|
||||||
|
/// <returns>Scalar value representing the dot product of the two Vector3s.</returns>
|
||||||
|
static double Dot(Vector3 lhs, Vector3 rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Computes and returns the cross product of 2 specified Vector3s.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector3 to calculate cross product with.</param>
|
||||||
|
/// <param name="rhs">Another Vector3 to calculate cross product with.</param>
|
||||||
|
/// <returns>The cross product of the two Vector3s.</returns>
|
||||||
|
static Vector3 Cross(Vector3 lhs, Vector3 rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Computes and returns a Vector3 projection.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vec">Vector3 to project.</param>
|
||||||
|
/// <param name="direction">Vector3 to project onto.</param>
|
||||||
|
/// <returns>The Vector3 that represents the projected vec onto direction.</returns>
|
||||||
|
static Vector3 Project(Vector3 vec, Vector3 direction);
|
||||||
|
/// <summary>
|
||||||
|
/// Reflects a Vector3 across another Vector3.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vec">A Vector3 to reflect.</param>
|
||||||
|
/// <param name="normal">A normal to reflect the Vector3 across.</param>
|
||||||
|
/// <returns>The Vector3 that represents vec reflected across normal.</returns>
|
||||||
|
static Vector3 Reflect(Vector3 vec, Vector3 normal);
|
||||||
|
/// <summary>
|
||||||
|
/// Rotates a Vector3 on the Z-axis by a specified angle in an anti-clockwise
|
||||||
|
/// direction.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vec">A Vector3 to rotate.</param>
|
||||||
|
/// <param name="radians">
|
||||||
|
/// Angle to rotate the vector by in an anti-clockwise direction in radians.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>The Vector3 that represents the rotated vector.</returns>
|
||||||
|
static Vector3 RotateRadians(Vector3 vec, double radians);
|
||||||
|
/// <summary>
|
||||||
|
/// Rotates a Vector3 on the Z-axis by a specified angle in an anti-clockwise
|
||||||
|
/// direction.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vec">A Vector3 to rotate.</param>
|
||||||
|
/// <param name="degrees">
|
||||||
|
/// Angle to rotate the vector by in an anti-clockwise direction in degrees.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>The Vector3 that represents the rotated vector.</returns>
|
||||||
|
static Vector3 RotateDegrees(Vector3 vec, double degrees);
|
||||||
|
/// <summary>
|
||||||
|
/// Computes and returns a Vector3 that is made from the smallest components of
|
||||||
|
/// the two specified Vector3s.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector3 to calculate minimum Vector3 with.</param>
|
||||||
|
/// <param name="rhs">Another Vector3 to calculate minimum Vector3 with.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// The Vector3 that contains the smallest components of the two specified
|
||||||
|
/// Vector3s.
|
||||||
|
/// </returns>
|
||||||
|
static Vector3 Min(Vector3 lhs, Vector3 rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Computes and returns a Vector3 that is made from the largest components of
|
||||||
|
/// the two specified Vector3s.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector3 to calculate maximum Vector3 with.</param>
|
||||||
|
/// <param name="rhs">Another Vector3 to calculate maximum Vector3 with.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// The Vector3 that contains the largest components of the two specified
|
||||||
|
/// Vector3s.
|
||||||
|
/// </returns>
|
||||||
|
static Vector3 Max(Vector3 lhs, Vector3 rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Linearly interpolates between two specified points.
|
||||||
|
/// This is most commonly used to find a point some fraction of the way along a
|
||||||
|
/// line between two endpoints.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a">The start Vector3, returned when t = 0.0.</param>
|
||||||
|
/// <param name="b">The end Vector3, returned when t = 1.0.</param>
|
||||||
|
/// <param name="t">
|
||||||
|
/// Value used to interpolate between a and b which is clamped to
|
||||||
|
/// the range[0, 1].
|
||||||
|
/// </param>
|
||||||
|
/// <returns>The interpolated Vector3.</returns>
|
||||||
|
static Vector3 Lerp(Vector3 a, Vector3 b, double t);
|
||||||
|
/// <summary>
|
||||||
|
/// Linearly interpolates between two specified points.
|
||||||
|
/// This is most commonly used to find a point some fraction of the way along a
|
||||||
|
/// line between two endpoints.
|
||||||
|
/// Unlike Lerp(), t is not clamped to a range at all.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a">The start Vector3, returned when t = 0.0.</param>
|
||||||
|
/// <param name="b">The end Vector3, returned when t = 1.0.</param>
|
||||||
|
/// <param name="t">Value used to interpolate between a and b.</param>
|
||||||
|
/// <returns>The interpolated Vector3.</returns>
|
||||||
|
static Vector3 LerpUnclamped(Vector3 a, Vector3 b, double t);
|
||||||
|
/// <summary>
|
||||||
|
/// Moves a point current towards target.
|
||||||
|
/// Similar to Lerp(), however, the function will ensure that the distance never
|
||||||
|
/// exceeds maxDistanceDelta. Negative values of maxDistanceDelta pushes the
|
||||||
|
/// vector away from target
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="current">The current position of the point.</param>
|
||||||
|
/// <param name="target">The target position to move to.</param>
|
||||||
|
/// <param name="maxDistanceDelta">Maximum distance moved per call.</param>
|
||||||
|
/// <returns>Vector representing the moved point.</returns>
|
||||||
|
static Vector3 MoveTowards(Vector3 current, Vector3 target, double maxDistanceDelta);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Overloaded Operators */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Adds two Vector3s together and returns the result.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector3 to add.</param>
|
||||||
|
/// <param name="rhs">Another Vector3 to add.</param>
|
||||||
|
/// <returns>The result of lhs added to rhs</returns>
|
||||||
|
static Vector3 operator+(Vector3 lhs, Vector3 rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Subtracts a Vector3 from another Vector3 and returns the result.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector3 to subtract from.</param>
|
||||||
|
/// <param name="rhs">Another Vector3 to subtract.</param>
|
||||||
|
/// <returns>The result of rhs subtracted from lhs.</returns>
|
||||||
|
static Vector3 operator-(Vector3 lhs, Vector3 rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates the component-wise multiplication of two Vector3s and returns the
|
||||||
|
/// result.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector3 to multiply with.</param>
|
||||||
|
/// <param name="rhs">Another Vector3 to multiply with.</param>
|
||||||
|
/// <returns>The result of rhs subtracted from lhs.</returns>
|
||||||
|
static Vector3 operator*(Vector3 lhs, Vector3 rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates the multiplication of a Vector3 with a scalar value and returns
|
||||||
|
/// the result.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector3 to multiply with.</param>
|
||||||
|
/// <param name="rhs">Scalar to multiply with.</param>
|
||||||
|
/// <returns>The result of the scalar multiplication.</returns>
|
||||||
|
static Vector3 operator*(Vector3 lhs, double rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates the division of a Vector3 with a scalar value and returns
|
||||||
|
/// the result.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Scalar to divide with.</param>
|
||||||
|
/// <param name="rhs">Vector3 to divide with.</param>
|
||||||
|
/// <returns>The result of the scalar division.</returns>
|
||||||
|
static Vector3 operator/(Vector3 lhs, double rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if two Vector3s are approximately equal. This is equivalent to
|
||||||
|
/// calling Vector3.IsNear() with default tolerance values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector3 to compare.</param>
|
||||||
|
/// <param name="rhs">Another Vector3 to compare.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// True if all components are approximately equal within the default
|
||||||
|
/// tolerance value.
|
||||||
|
/// </returns>
|
||||||
|
static bool operator==(Vector3 lhs, Vector3 rhs);
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if two Vector3s are not approximately equal. This is equivalent to
|
||||||
|
/// calling !Vector3.IsNear() with default tolerance values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Vector3 to compare.</param>
|
||||||
|
/// <param name="rhs">Another Vector3 to compare.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// True if all components are not approximately equal within the default
|
||||||
|
/// tolerance value.
|
||||||
|
/// </returns>
|
||||||
|
static bool operator!=(Vector3 lhs, Vector3 rhs);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Conversion Operators */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Explicit conversion operator to enable explicit casting from a Vector3 to a
|
||||||
|
/// Vector2.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vec">Vector3 to convert from.</param>
|
||||||
|
static explicit operator Vector2(Vector3 vec);
|
||||||
|
/// <summary>
|
||||||
|
/// Explicit conversion operator to enable explicit casting from a Vector2 to a
|
||||||
|
/// Vector3.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vec">Vector2 to convert from.</param>
|
||||||
|
static explicit operator Vector3(Vector2 vec);
|
||||||
|
};
|
||||||
|
} // namespace PlushieAPI::Mathematics
|
|
@ -0,0 +1,10 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHpch.h
|
||||||
|
* \brief Empty source file for generating SHADE Engine's precompiled header.
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2022 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.
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#include "SHpch.h"
|
|
@ -0,0 +1,31 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHpch.h
|
||||||
|
* \brief Precompiled header file for SHADE Engine.
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2022 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
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||||
|
// Windows Header Files
|
||||||
|
#include <Windows.h>
|
||||||
|
// C RunTime Header Files
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <memory.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <utility>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <map>
|
||||||
|
#include <tuple>
|
||||||
|
#include <functional>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
|
@ -0,0 +1,171 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file Script.cxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 28, 2021
|
||||||
|
\brief Contains the definition of the functions for the PlushieScript managed
|
||||||
|
class.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Precompiled Headers
|
||||||
|
#include "SHpch.h"
|
||||||
|
// Primary Header
|
||||||
|
#include "Script.hxx"
|
||||||
|
// Project Headers
|
||||||
|
#include "Utility/Debug.hxx"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Component Access Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
generic <typename T>
|
||||||
|
T Script::AddComponent()
|
||||||
|
{
|
||||||
|
return owner.AddComponent<T>();
|
||||||
|
}
|
||||||
|
generic <typename T>
|
||||||
|
T Script::GetComponent()
|
||||||
|
{
|
||||||
|
return owner.GetComponent<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
generic <typename T>
|
||||||
|
T Script::GetComponentInChildren()
|
||||||
|
{
|
||||||
|
return owner.GetComponentInChildren<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
generic <typename T>
|
||||||
|
T Script::EnsureComponent()
|
||||||
|
{
|
||||||
|
return owner.EnsureComponent<T>();
|
||||||
|
}
|
||||||
|
generic <typename T>
|
||||||
|
void Script::RemoveComponent()
|
||||||
|
{
|
||||||
|
throw gcnew System::NotImplementedException;
|
||||||
|
//ECS::RemoveComponent<T>(owner.GetNativeEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Script Access Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
generic <typename T>
|
||||||
|
T Script::AddScript()
|
||||||
|
{
|
||||||
|
throw gcnew System::NotImplementedException;
|
||||||
|
//return ScriptStore::AddScript<T>(owner.GetEntity());
|
||||||
|
}
|
||||||
|
generic <typename T>
|
||||||
|
T Script::GetScript()
|
||||||
|
{
|
||||||
|
throw gcnew System::NotImplementedException;
|
||||||
|
//return ScriptStore::GetScript<T>(owner.GetEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
generic <typename T>
|
||||||
|
T Script::GetScriptInChildren()
|
||||||
|
{
|
||||||
|
throw gcnew System::NotImplementedException;
|
||||||
|
//return ScriptStore::GetScriptInChildren<T>(owner.GetEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
generic <typename T>
|
||||||
|
System::Collections::Generic::IEnumerable<T>^ Script::GetScripts()
|
||||||
|
{
|
||||||
|
throw gcnew System::NotImplementedException;
|
||||||
|
//return ScriptStore::GetScripts<T>(owner.GetEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
generic <typename T>
|
||||||
|
void Script::RemoveScript()
|
||||||
|
{
|
||||||
|
throw gcnew System::NotImplementedException;
|
||||||
|
//ScriptStore::RemoveScript<T>(owner.GetEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* "All-time" Lifecycle Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void Script::OnAttached()
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
onAttached();
|
||||||
|
SAFE_NATIVE_CALL_END(this)
|
||||||
|
}
|
||||||
|
void Script::OnDetached()
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
onDetatched();
|
||||||
|
SAFE_NATIVE_CALL_END(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Lifecycle Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void Script::Awake()
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
awake();
|
||||||
|
SAFE_NATIVE_CALL_END(this)
|
||||||
|
}
|
||||||
|
void Script::Start()
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
start();
|
||||||
|
SAFE_NATIVE_CALL_END(this)
|
||||||
|
}
|
||||||
|
void Script::FixedUpdate()
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
fixedUpdate();
|
||||||
|
SAFE_NATIVE_CALL_END(this)
|
||||||
|
}
|
||||||
|
void Script::Update()
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
update();
|
||||||
|
SAFE_NATIVE_CALL_END(this)
|
||||||
|
}
|
||||||
|
void Script::LateUpdate()
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
lateUpdate();
|
||||||
|
SAFE_NATIVE_CALL_END(this)
|
||||||
|
}
|
||||||
|
void Script::OnDestroy()
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
onDestroy();
|
||||||
|
SAFE_NATIVE_CALL_END(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
Script::Script(GameObject gameObj)
|
||||||
|
: owner { gameObj }
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Virtual "All-Time" Lifecycle Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void Script::onAttached() {}
|
||||||
|
void Script::onDetatched() {}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Virtual Lifecycle Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void Script::awake() {}
|
||||||
|
void Script::start() {}
|
||||||
|
void Script::fixedUpdate() {}
|
||||||
|
void Script::update() {}
|
||||||
|
void Script::lateUpdate() {}
|
||||||
|
void Script::onDestroy() {}
|
||||||
|
}// namespace PlushieAPI
|
|
@ -0,0 +1,274 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file Script.hxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 28, 2021
|
||||||
|
\brief Contains the definition of the Script class.
|
||||||
|
|
||||||
|
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/GameObject.hxx"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Forward Declarations */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
ref class BaseComponent;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Class Definitions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Class that forms the basis of all "script"-objects that can be attached to
|
||||||
|
/// Entities to update each Entity's Components via C# code.
|
||||||
|
/// </summary>
|
||||||
|
public ref class Script
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Properties */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// GameObject that this Script belongs to.
|
||||||
|
/// </summary>
|
||||||
|
property GameObject Owner
|
||||||
|
{
|
||||||
|
GameObject get() { return owner; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Component Access Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a Component to the GameObject that this Script belongs to.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">
|
||||||
|
/// Type of the Component to add. Must be derived from BaseComponent.
|
||||||
|
/// </typeparam>
|
||||||
|
/// <returns>Reference to the Component that was added.</returns>
|
||||||
|
generic<typename T> where T : BaseComponent
|
||||||
|
T AddComponent();
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a Component from the GameObject that this Script belongs to.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">
|
||||||
|
/// Type of the Component to get. Must be derived from BaseComponent.
|
||||||
|
/// </typeparam>
|
||||||
|
/// <returns>Reference to the Component that was retrieved.</returns>
|
||||||
|
generic<typename T> where T : BaseComponent
|
||||||
|
T GetComponent();
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the first Component from this GameObject's children that matches
|
||||||
|
/// the specified type.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">
|
||||||
|
/// Type of the Component to get. Must be derived from BaseComponent.
|
||||||
|
/// </typeparam>
|
||||||
|
/// <returns>Reference to the Component that was retrieved.</returns>
|
||||||
|
generic<typename T> where T : BaseComponent
|
||||||
|
T GetComponentInChildren();
|
||||||
|
/// <summary>
|
||||||
|
/// Ensures a Component on the GameObject that this Script belongs to.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">
|
||||||
|
/// Type of the Component to ensure. Must be derived from BaseComponent.
|
||||||
|
/// </typeparam>
|
||||||
|
/// <returns>Reference to the Component.</returns>
|
||||||
|
generic<typename T> where T : BaseComponent
|
||||||
|
T EnsureComponent();
|
||||||
|
/// <summary>
|
||||||
|
/// Removes a Component from the GameObject that this Script belongs to.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">
|
||||||
|
/// Type of the Component to remove. Must be derived from BaseComponent.
|
||||||
|
/// </typeparam>
|
||||||
|
generic<typename T> where T : BaseComponent
|
||||||
|
void RemoveComponent();
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Script Access Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a Script to this GameObject.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">
|
||||||
|
/// Type of script to add.
|
||||||
|
/// This needs to be a default constructable Script.
|
||||||
|
/// </typeparam>
|
||||||
|
/// <returns>Reference to the script added</returns>
|
||||||
|
generic<typename T> where T : ref class, Script
|
||||||
|
T AddScript();
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the first Script from this GameObject that matches the specified
|
||||||
|
/// type.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">
|
||||||
|
/// Type of script to get.
|
||||||
|
/// This needs to be a default constructable Script.
|
||||||
|
/// </typeparam>
|
||||||
|
/// <returns>Reference to the script added</returns>
|
||||||
|
generic<typename T> where T : ref class, Script
|
||||||
|
T GetScript();
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the first Script from this GameObject'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>
|
||||||
|
/// <returns>Reference to the script added</returns>
|
||||||
|
generic<typename T> where T : ref class, Script
|
||||||
|
T GetScriptInChildren();
|
||||||
|
/// <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>
|
||||||
|
/// <returns>
|
||||||
|
/// Immutable list of references to scripts of the specified type.
|
||||||
|
/// </returns>
|
||||||
|
generic<typename T> where T : ref class, Script
|
||||||
|
System::Collections::Generic::IEnumerable<T>^ GetScripts();
|
||||||
|
/// <summary>
|
||||||
|
/// Removes all Scripts of the specified type from this GameObject.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">
|
||||||
|
/// Type of script to remove.
|
||||||
|
/// This needs to be a default constructable Script.
|
||||||
|
/// </typeparam>
|
||||||
|
generic<typename T> where T : ref class, Script
|
||||||
|
void RemoveScript();
|
||||||
|
|
||||||
|
internal:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* "All-Time" Lifecycle Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Used to call onAttached(). This is called immediately when this script is
|
||||||
|
/// attached to a GameObject.
|
||||||
|
/// </summary>
|
||||||
|
void OnAttached();
|
||||||
|
/// <summary>
|
||||||
|
/// Used to call onDetached(). This is called immediately when this script is
|
||||||
|
/// detached from a GameObject.
|
||||||
|
/// </summary>
|
||||||
|
void OnDetached();
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Lifecycle Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Used to call awake(). This should be called on the first frame that the
|
||||||
|
/// attached GameObject is active if they are a part of the scene.
|
||||||
|
/// </summary>
|
||||||
|
void Awake();
|
||||||
|
/// <summary>
|
||||||
|
/// Used to call start(). This should be called on the first frame that the
|
||||||
|
/// attached GameObject is active but always after Awake().
|
||||||
|
/// </summary>
|
||||||
|
void Start();
|
||||||
|
/// <summary>
|
||||||
|
/// Used to call fixedUpdate(). This should be called in sync with Physics
|
||||||
|
/// update steps and thus in most cases will execute more than Update() will.
|
||||||
|
/// This will be called immediately before a Physics update step.
|
||||||
|
/// </summary>
|
||||||
|
void FixedUpdate();
|
||||||
|
/// <summary>
|
||||||
|
/// Used to call update(). This should be called every frame before physics and
|
||||||
|
/// collision resolution.
|
||||||
|
/// </summary>
|
||||||
|
void Update();
|
||||||
|
/// <summary>
|
||||||
|
/// Used to call lateUpdate(). This should be called every frame after physics
|
||||||
|
/// and collision resolution but before rendering.
|
||||||
|
/// </summary>
|
||||||
|
void LateUpdate();
|
||||||
|
/// <summary>
|
||||||
|
/// Used to call onDestroy(). This should be called at the end of the frame
|
||||||
|
/// where the attached GameObject or this script is destroyed directly or
|
||||||
|
/// indirectly due to destruction of the owner.
|
||||||
|
/// </summary>
|
||||||
|
void OnDestroy();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Constructors */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor for Script to tie it to a specific GameObject.
|
||||||
|
/// Constructors of derived Scripts should call this Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="gameObj">
|
||||||
|
/// GameObject that this Script will be tied to.
|
||||||
|
/// </param>
|
||||||
|
Script(GameObject gameObj);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Virtual "All-Time" Lifecycle Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Called immediately once this script is attached to a GameObject.
|
||||||
|
/// </summary>
|
||||||
|
virtual void onAttached();
|
||||||
|
/// <summary>
|
||||||
|
/// Called immediately once this script is detached from a GameObject.
|
||||||
|
/// </summary>
|
||||||
|
virtual void onDetatched();
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Virtual Lifecycle Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Called on the first frame that the attached GameObject is active if they are
|
||||||
|
/// a part of the scene.
|
||||||
|
/// </summary>
|
||||||
|
virtual void awake();
|
||||||
|
/// <summary>
|
||||||
|
/// Called on the first frame that the attached GameObject is active but always
|
||||||
|
/// after Awake().
|
||||||
|
/// </summary>
|
||||||
|
virtual void start();
|
||||||
|
/// <summary>
|
||||||
|
/// Called every frame in sync with Physics update steps and thus in most cases
|
||||||
|
/// will execute more than update() will. This will be called immediately before
|
||||||
|
/// a Physics update step.
|
||||||
|
/// </summary>
|
||||||
|
virtual void fixedUpdate();
|
||||||
|
/// <summary>
|
||||||
|
/// Called every frame before physics and collision resolution.
|
||||||
|
/// </summary>
|
||||||
|
virtual void update();
|
||||||
|
/// <summary>
|
||||||
|
/// Called every frame after physics and collision resolution but before
|
||||||
|
/// rendering.
|
||||||
|
/// </summary>
|
||||||
|
virtual void lateUpdate();
|
||||||
|
/// <summary>
|
||||||
|
/// Called just before the end of the frame where the attached GameObject or
|
||||||
|
/// this script is destroyed directly or indirectly due to destruction of the
|
||||||
|
/// owner.
|
||||||
|
/// </summary>
|
||||||
|
virtual void onDestroy();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
GameObject owner;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace PlushieAPI
|
|
@ -0,0 +1,673 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file ScriptStore.cxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 28, 2021
|
||||||
|
\brief Contains the definition of the functions for the ScriptStore managed
|
||||||
|
static class.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Precompiled Headers
|
||||||
|
#include "SHpch.h"
|
||||||
|
// Primary Header
|
||||||
|
#include "ScriptStore.hxx"
|
||||||
|
// Standard Libraries
|
||||||
|
#include <sstream>
|
||||||
|
// External Dependencies
|
||||||
|
#include "ECS_Base/System/SHEntityManager.h"
|
||||||
|
// Project Headers
|
||||||
|
#include "Utility/Debug.hxx"
|
||||||
|
#include "Utility/Convert.hxx"
|
||||||
|
#include "Script.hxx"
|
||||||
|
#include "Engine/Entity.hxx"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Scripts Manipulation Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
generic<typename T>
|
||||||
|
T ScriptStore::AddScript(Entity entity)
|
||||||
|
{
|
||||||
|
// Check if entity exists
|
||||||
|
if (!EntityUtils::IsValid(entity))
|
||||||
|
throw gcnew System::ArgumentException("Invalid Entity provided to add a Script to.");
|
||||||
|
|
||||||
|
System::Collections::Generic::List<Script^> ^ entityScriptList;
|
||||||
|
|
||||||
|
// Check if storage for scripts of this entity exists
|
||||||
|
if (!scripts.ContainsKey(entity))
|
||||||
|
{
|
||||||
|
// Create a new list for this set of scripts
|
||||||
|
entityScriptList = gcnew System::Collections::Generic::List<Script^>();
|
||||||
|
scripts.Add(entity, entityScriptList);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entityScriptList = scripts[entity];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the script and add it in
|
||||||
|
array<Object^>^ params = gcnew array<Object^>{GameObject(entity)};
|
||||||
|
Script^ script = safe_cast<Script^>(System::Activator::CreateInstance(T::typeid, params));
|
||||||
|
entityScriptList->Add(script);
|
||||||
|
awakeList.Add(script);
|
||||||
|
startList.Add(script);
|
||||||
|
script->OnAttached();
|
||||||
|
|
||||||
|
return safe_cast<T>(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScriptStore::AddScriptViaName(Entity entity, System::String^ scriptName)
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
Script^ script;
|
||||||
|
return AddScriptViaNameWithRef(entity, scriptName, script);
|
||||||
|
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore")
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScriptStore::AddScriptViaNameWithRef(Entity entity, System::String^ scriptName, Script^% createdScript)
|
||||||
|
{
|
||||||
|
// Check if we are set up to get scripts
|
||||||
|
if (addScriptMethod == nullptr)
|
||||||
|
{
|
||||||
|
Debug::LogError("[ScriptStore] Native AddScript<T>() was not loaded. Unable to add scripts.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the script if it exists
|
||||||
|
System::Type^ scriptType = getScriptType(scriptName);
|
||||||
|
if (scriptType == nullptr)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[ScriptStore] No Script named "
|
||||||
|
<< Convert::ToNative(scriptName)
|
||||||
|
<< " found!";
|
||||||
|
Debug::LogError(oss.str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, add the script
|
||||||
|
System::Reflection::MethodInfo^ method = addScriptMethod->MakeGenericMethod(scriptType);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
array<Object^>^ params = gcnew array<Object^>{entity};
|
||||||
|
createdScript = safe_cast<Script^>(method->Invoke(nullptr, params));
|
||||||
|
}
|
||||||
|
catch (System::Exception^ e)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[ScriptStore] Failed to add Script named \"" << Convert::ToNative(scriptName)
|
||||||
|
<< "\" to Entity #" << entity << "! (" << Convert::ToNative(e->GetType()->Name) << ")";
|
||||||
|
Debug::LogError(oss.str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
generic<typename T>
|
||||||
|
T ScriptStore::GetScript(Entity entity)
|
||||||
|
{
|
||||||
|
// Check if entity exists
|
||||||
|
if (!EntityUtils::IsValid(entity))
|
||||||
|
throw gcnew System::ArgumentException("Invalid Entity provided to get a Script from.");
|
||||||
|
|
||||||
|
// Check if entity exists in the script storage
|
||||||
|
if (!scripts.ContainsKey(entity))
|
||||||
|
{
|
||||||
|
return T();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for and obtain
|
||||||
|
for each (Script^ script in scripts[entity])
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
T actualScript = safe_cast<T>(script);
|
||||||
|
return actualScript;
|
||||||
|
}
|
||||||
|
catch (System::InvalidCastException^)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return T();
|
||||||
|
}
|
||||||
|
|
||||||
|
generic <typename T>
|
||||||
|
T ScriptStore::GetScriptInChildren(Entity entity)
|
||||||
|
{
|
||||||
|
// Check if entity exists and is a valid GameObject
|
||||||
|
if (!EntityUtils::IsValid(entity))
|
||||||
|
throw gcnew System::ArgumentException("Invalid Entity provided to get a Script from.");
|
||||||
|
|
||||||
|
|
||||||
|
// Check if entity exists in the script storage
|
||||||
|
if (!scripts.ContainsKey(entity))
|
||||||
|
{
|
||||||
|
return T();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Transform component and get the children list
|
||||||
|
throw gcnew System::NotImplementedException;
|
||||||
|
//Pls::Transform* tf = Pls::ECS::GetComponent<Pls::Transform>(Convert::ToNative(entity));
|
||||||
|
//if (tf == nullptr)
|
||||||
|
// return T();
|
||||||
|
|
||||||
|
//// Search direct children first
|
||||||
|
//for (const auto& child : tf->GetChildren())
|
||||||
|
//{
|
||||||
|
// T script = GetScript<T>(Convert::ToCLI(child));
|
||||||
|
// if (script != nullptr)
|
||||||
|
// return script;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//// Search their children
|
||||||
|
//for (const auto& child : tf->GetChildren())
|
||||||
|
//{
|
||||||
|
// T script = GetScriptInChildren<T>(Convert::ToCLI(child));
|
||||||
|
// if (script != nullptr)
|
||||||
|
// return script;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// None here
|
||||||
|
return T();
|
||||||
|
}
|
||||||
|
|
||||||
|
generic <typename T>
|
||||||
|
System::Collections::Generic::IEnumerable<T>^ ScriptStore::GetScripts(Entity entity)
|
||||||
|
{
|
||||||
|
// Check if entity exists and is a valid GameObject
|
||||||
|
if (!EntityUtils::IsValid(entity))
|
||||||
|
throw gcnew System::ArgumentException("Invalid Entity provided to get a Script from.");
|
||||||
|
|
||||||
|
// Create a list to store entries
|
||||||
|
System::Collections::Generic::List<T>^ foundScripts = gcnew System::Collections::Generic::List<T>();
|
||||||
|
|
||||||
|
// Check if entity exists in the script storage
|
||||||
|
if (!scripts.ContainsKey(entity))
|
||||||
|
{
|
||||||
|
return foundScripts;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for and obtain
|
||||||
|
for each (Script^ script in scripts[entity])
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
T actualScript = safe_cast<T>(script);
|
||||||
|
foundScripts->Add(actualScript);
|
||||||
|
}
|
||||||
|
catch (System::InvalidCastException^)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return foundScripts;
|
||||||
|
}
|
||||||
|
System::Collections::Generic::IEnumerable<Script^>^ ScriptStore::GetAllScripts(Entity entity)
|
||||||
|
{
|
||||||
|
// Check if entity exists
|
||||||
|
if (!EntityUtils::IsValid(entity))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// Check if entity exists in the script storage
|
||||||
|
if (scripts.ContainsKey(entity))
|
||||||
|
{
|
||||||
|
return scripts[entity];
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
generic<typename T>
|
||||||
|
void ScriptStore::RemoveScript(Entity entity)
|
||||||
|
{
|
||||||
|
// Check if entity exists
|
||||||
|
if (!EntityUtils::IsValid(entity))
|
||||||
|
throw gcnew System::ArgumentException("Invalid Entity provided to remove a Script from.");
|
||||||
|
|
||||||
|
|
||||||
|
// Check if entity exists in the script storage
|
||||||
|
if (!scripts.ContainsKey(entity))
|
||||||
|
{
|
||||||
|
Debug::LogError("[ScriptStore] Attempted to remove a Script that does not belong to the specified Entity!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for and obtain
|
||||||
|
for each (Script^ script in scripts[entity])
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
safe_cast<T>(script);
|
||||||
|
removeScript(script);
|
||||||
|
}
|
||||||
|
catch (System::InvalidCastException^)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool ScriptStore::RemoveScript(Entity entity, Script^ script)
|
||||||
|
{
|
||||||
|
// Check if entity exists
|
||||||
|
if (!EntityUtils::IsValid(entity))
|
||||||
|
{
|
||||||
|
Debug::LogError("[ScriptStore] Attempted to remove a Script from an invalid Entity!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Check if entity exists in the script storage
|
||||||
|
if (!scripts.ContainsKey(entity))
|
||||||
|
{
|
||||||
|
Debug::LogError("[ScriptStore] Attempted to remove a Script that does not belong to the specified Entity!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the script exists to begin with
|
||||||
|
if (!scripts[entity]->Contains(script))
|
||||||
|
{
|
||||||
|
Debug::LogError("[ScriptStore] Attempted to remove a Script that does not belong to the specified Entity!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Script found, queue it for deletion
|
||||||
|
removeScript(script);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void ScriptStore::RemoveAllScripts(Entity entity)
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
// Check if entity exists
|
||||||
|
if (!EntityUtils::IsValid(entity))
|
||||||
|
{
|
||||||
|
Debug::LogError("[ScriptStore] Attempted to remove Scripts from an invalid Entity!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if entity exists in the script storage
|
||||||
|
if (!scripts.ContainsKey(entity))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Search for and clear
|
||||||
|
System::Collections::Generic::List<Script^>^ scriptList = scripts[entity];
|
||||||
|
for each (Script^ script in scriptList)
|
||||||
|
{
|
||||||
|
removeScript(script);
|
||||||
|
}
|
||||||
|
scriptList->Clear();
|
||||||
|
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore")
|
||||||
|
}
|
||||||
|
void ScriptStore::RemoveAllScriptsImmediately(Entity entity, bool callOnDestroy)
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
// Check if entity exists
|
||||||
|
if (!EntityUtils::IsValid(entity))
|
||||||
|
{
|
||||||
|
Debug::LogError("[ScriptStore] Attempted to remove Scripts from an invalid Entity!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if entity exists in the script storage
|
||||||
|
if (!scripts.ContainsKey(entity))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Clear all
|
||||||
|
System::Collections::Generic::List<Script^>^ scriptList = scripts[entity];
|
||||||
|
for each (Script ^ script in scriptList)
|
||||||
|
{
|
||||||
|
// Call OnDestroy only if indicated and also in play mode
|
||||||
|
if (callOnDestroy)
|
||||||
|
{
|
||||||
|
script->OnDestroy();
|
||||||
|
}
|
||||||
|
script->OnDetached();
|
||||||
|
|
||||||
|
// Remove scripts from awakening if they were not woken up to begin with
|
||||||
|
awakeList.Remove(script);
|
||||||
|
startList.Remove(script);
|
||||||
|
}
|
||||||
|
scriptList->Clear();
|
||||||
|
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore")
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Lifecycle Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void ScriptStore::Init()
|
||||||
|
{
|
||||||
|
// Create an enumerable list of script types
|
||||||
|
refreshScriptTypeList();
|
||||||
|
// Get stored methods for interop variants of functions
|
||||||
|
getGenericMethods();
|
||||||
|
}
|
||||||
|
void ScriptStore::FrameSetUp()
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
// Clear the awake queue
|
||||||
|
for each (Script^ script in awakeList)
|
||||||
|
{
|
||||||
|
script->Awake();
|
||||||
|
}
|
||||||
|
awakeList.Clear();
|
||||||
|
|
||||||
|
// Clear the start queue
|
||||||
|
for each (Script^ script in startList)
|
||||||
|
{
|
||||||
|
if (script->Owner.IsActiveInHierarchy)
|
||||||
|
{
|
||||||
|
script->Start();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inactiveStartList.Add(script);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
startList.Clear();
|
||||||
|
startList.AddRange(%inactiveStartList);
|
||||||
|
inactiveStartList.Clear();
|
||||||
|
|
||||||
|
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore")
|
||||||
|
}
|
||||||
|
void ScriptStore::FrameCleanUp()
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
// Clear the queue
|
||||||
|
while (disposalQueue.Count > 0)
|
||||||
|
{
|
||||||
|
Script^ script = disposalQueue.Dequeue();
|
||||||
|
/*if (Application::IsPlaying)
|
||||||
|
{
|
||||||
|
script->OnDestroy();
|
||||||
|
}*/
|
||||||
|
auto entity = script->Owner.GetEntity();
|
||||||
|
auto scriptList = scripts[script->Owner.GetEntity()];
|
||||||
|
scriptList->Remove(script);
|
||||||
|
if (scriptList->Count <= 0)
|
||||||
|
{
|
||||||
|
scripts.Remove(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore")
|
||||||
|
}
|
||||||
|
void ScriptStore::Exit()
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
// Run the deinit all scripts if needed
|
||||||
|
//if (Application::IsPlaying)
|
||||||
|
{
|
||||||
|
Debug::Log("Running OnDestroy() for scripts.");
|
||||||
|
for each (System::Collections::Generic::KeyValuePair<Entity, ScriptList^> entity in scripts)
|
||||||
|
{
|
||||||
|
for each (Script^ script in entity.Value)
|
||||||
|
{
|
||||||
|
script->OnDestroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear Script Storage
|
||||||
|
scripts.Clear();
|
||||||
|
awakeList.Clear();
|
||||||
|
startList.Clear();
|
||||||
|
disposalQueue.Clear();
|
||||||
|
scriptTypeList = nullptr;
|
||||||
|
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore")
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Script Information Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
System::Collections::Generic::IEnumerable<System::Type^>^ ScriptStore::GetAvailableScriptList()
|
||||||
|
{
|
||||||
|
return scriptTypeList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Script Execution Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void ScriptStore::ExecuteFixedUpdate()
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
for each (System::Collections::Generic::KeyValuePair<Entity, ScriptList^> entity in scripts)
|
||||||
|
{
|
||||||
|
// Check active state
|
||||||
|
if (!isEntityActive(entity.Key))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Update each script
|
||||||
|
for each (Script^ script in entity.Value)
|
||||||
|
{
|
||||||
|
script->FixedUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore")
|
||||||
|
}
|
||||||
|
void ScriptStore::ExecuteUpdate()
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
for each (System::Collections::Generic::KeyValuePair<Entity, ScriptList^> entity in scripts)
|
||||||
|
{
|
||||||
|
// Check active state
|
||||||
|
if (!isEntityActive(entity.Key))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Update each script
|
||||||
|
for each (Script^ script in entity.Value)
|
||||||
|
{
|
||||||
|
script->Update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore")
|
||||||
|
}
|
||||||
|
void ScriptStore::ExecuteLateUpdate()
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
for each (System::Collections::Generic::KeyValuePair<Entity, ScriptList^> entity in scripts)
|
||||||
|
{
|
||||||
|
// Check active state
|
||||||
|
if (!isEntityActive(entity.Key))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Update each script
|
||||||
|
for each (Script^ script in entity.Value)
|
||||||
|
{
|
||||||
|
script->LateUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore")
|
||||||
|
}
|
||||||
|
bool ScriptStore::SerialiseScripts(Entity entity, System::Text::StringBuilder^ buffer, int bufferSize)
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
// Create a buffer that we can work with temporarily
|
||||||
|
System::Text::StringBuilder^ jsonString = gcnew System::Text::StringBuilder();
|
||||||
|
|
||||||
|
// Check if entity exists, otherwise nothing
|
||||||
|
if (!EntityUtils::IsValid(entity))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
|
||||||
|
// Check if entity exists in the script storage
|
||||||
|
if (!scripts.ContainsKey(entity))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Serialise each script
|
||||||
|
System::Collections::Generic::List<Script^>^ scriptList = scripts[entity];
|
||||||
|
for (int i = 0; i < scriptList->Count; ++i)
|
||||||
|
{
|
||||||
|
throw gcnew System::NotImplementedException;
|
||||||
|
//jsonString->Append(ReflectionUtilities::Serialise(scriptList[i]));
|
||||||
|
|
||||||
|
// Only add separator if is not last script
|
||||||
|
if (i != scriptList->Count - 1)
|
||||||
|
{
|
||||||
|
jsonString->Append(",\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the size is too big
|
||||||
|
if (jsonString->Length > bufferSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Otherwise we copy it over
|
||||||
|
buffer->Clear();
|
||||||
|
buffer->Append(jsonString->ToString());
|
||||||
|
return true;
|
||||||
|
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore")
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScriptStore::DeserialiseScript(Entity entity, System::String^ yaml)
|
||||||
|
{
|
||||||
|
SAFE_NATIVE_CALL_BEGIN
|
||||||
|
// Check if entity exists, otherwise nothing
|
||||||
|
if (!EntityUtils::IsValid(entity))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Get the name of the script
|
||||||
|
const int FIRST_QUOTE = yaml->IndexOf('\"');
|
||||||
|
const int FIRST_COLON = yaml->IndexOf(':');
|
||||||
|
if (FIRST_QUOTE < 0 || FIRST_COLON < 0) // No script name, it's invalid
|
||||||
|
return false;
|
||||||
|
const int SCRIPT_NAME_START = FIRST_QUOTE + 1;
|
||||||
|
const int SCRIPT_NAME_END = FIRST_COLON - 1;
|
||||||
|
System::String^ typeName = yaml->Substring(SCRIPT_NAME_START, SCRIPT_NAME_END - SCRIPT_NAME_START);
|
||||||
|
|
||||||
|
// Create the script
|
||||||
|
Script^ script;
|
||||||
|
if (AddScriptViaNameWithRef(entity, typeName, script))
|
||||||
|
{
|
||||||
|
// Copy the data in
|
||||||
|
throw gcnew System::NotImplementedException;
|
||||||
|
//ReflectionUtilities::Deserialise(json, script);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SAFE_NATIVE_CALL_END_N("SHADE.ScriptStore")
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void ScriptStore::removeScript(Script^ script)
|
||||||
|
{
|
||||||
|
// Prepare for disposal
|
||||||
|
disposalQueue.Enqueue(script);
|
||||||
|
|
||||||
|
// Also remove it fromm awake and start queues if they were created but not initialised
|
||||||
|
awakeList.Remove(script);
|
||||||
|
startList.Remove(script);
|
||||||
|
script->OnDetached();
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
/* Select Many */
|
||||||
|
ref struct Pair
|
||||||
|
{
|
||||||
|
System::Reflection::Assembly^ assembly;
|
||||||
|
System::Type^ type;
|
||||||
|
};
|
||||||
|
|
||||||
|
System::Collections::Generic::IEnumerable<System::Type^>^ selectorFunc(System::Reflection::Assembly^ assembly)
|
||||||
|
{
|
||||||
|
return assembly->GetExportedTypes();
|
||||||
|
}
|
||||||
|
Pair^ resultSelectorFunc(System::Reflection::Assembly^ assembly, System::Type^ type)
|
||||||
|
{
|
||||||
|
Pair^ p = gcnew Pair();
|
||||||
|
p->assembly = assembly;
|
||||||
|
p->type = type;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Where */
|
||||||
|
bool predicateFunc(Pair^ pair)
|
||||||
|
{
|
||||||
|
return pair->type->IsSubclassOf(Script::typeid) && !pair->type->IsAbstract;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Select */
|
||||||
|
System::Type^ selectorFunc(Pair^ pair)
|
||||||
|
{
|
||||||
|
return pair->type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptStore::refreshScriptTypeList()
|
||||||
|
{
|
||||||
|
using namespace System;
|
||||||
|
using namespace System::Reflection;
|
||||||
|
using namespace System::Linq;
|
||||||
|
using namespace System::Collections::Generic;
|
||||||
|
|
||||||
|
/* Select Many: Types in Loaded Assemblies */
|
||||||
|
IEnumerable<Assembly^>^ assemblies = AppDomain::CurrentDomain->GetAssemblies();
|
||||||
|
Func<Assembly^, IEnumerable<Type^>^>^ collectionSelector = gcnew Func<Assembly^, IEnumerable<Type^>^>(selectorFunc);
|
||||||
|
Func<Assembly^, Type^, Pair^>^ resultSelector = gcnew Func<Assembly^, Type^, Pair^>(resultSelectorFunc);
|
||||||
|
IEnumerable<Pair^>^ selectManyResult = Enumerable::SelectMany(assemblies, collectionSelector, resultSelector);
|
||||||
|
|
||||||
|
/* Where: Are concrete Scripts */
|
||||||
|
Func<Pair^, bool>^ predicate = gcnew Func<Pair^, bool>(predicateFunc);
|
||||||
|
IEnumerable<Pair^>^ whereResult = Enumerable::Where(selectManyResult, predicate);
|
||||||
|
|
||||||
|
/* Select: Select them all */
|
||||||
|
Func<Pair^, Type^>^ selector = gcnew Func<Pair^, Type^>(selectorFunc);
|
||||||
|
scriptTypeList = Enumerable::Select(whereResult, selector);
|
||||||
|
|
||||||
|
// Log
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[ScriptStore] Successfully retrieved references to " << Enumerable::Count(scriptTypeList)
|
||||||
|
<< " Script(s) from currently loaded assemblies.";
|
||||||
|
Debug::Log(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptStore::getGenericMethods()
|
||||||
|
{
|
||||||
|
addScriptMethod = ScriptStore::typeid->GetMethod("AddScript");
|
||||||
|
if (addScriptMethod == nullptr)
|
||||||
|
{
|
||||||
|
Debug::LogError("[ScriptStore] Failed to get MethodInfo of \"AddScript<T>()\". Adding of scripts from native code will fail.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System::Type^ ScriptStore::getScriptType(System::String^ scriptName)
|
||||||
|
{
|
||||||
|
// Remove any whitespaces just in case
|
||||||
|
scriptName = scriptName->Trim();
|
||||||
|
|
||||||
|
// Look for the correct script
|
||||||
|
for each (System::Type^ type in scriptTypeList)
|
||||||
|
{
|
||||||
|
if (type->FullName == scriptName || type->Name == scriptName)
|
||||||
|
{
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScriptStore::isEntityActive(Entity entity)
|
||||||
|
{
|
||||||
|
// Get native Entity
|
||||||
|
SHEntity* nativeEntity = SHEntityManager::GetEntityByID(entity);
|
||||||
|
|
||||||
|
// Entity Validity Check
|
||||||
|
if (nativeEntity == nullptr)
|
||||||
|
throw gcnew System::InvalidOperationException("Attempted to get native Component to an invalid Entity.");
|
||||||
|
|
||||||
|
// Check active state
|
||||||
|
return nativeEntity->isActive;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,301 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\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"
|
||||||
|
|
||||||
|
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<T>() 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<T>() 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>
|
||||||
|
/// Generates a JSON string that represents the set of Scripts attached
|
||||||
|
/// to the 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="buffer">
|
||||||
|
/// StringBuilder handle that maps to a native char array that will contain the
|
||||||
|
/// serialised string.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="bufferSize">
|
||||||
|
/// The size of the char array.
|
||||||
|
/// </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::Text::StringBuilder^ buffer, int bufferSize);
|
||||||
|
/// <summary>
|
||||||
|
/// Processes a JSON string that represents a single Script and attaches
|
||||||
|
/// it onto 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">
|
||||||
|
/// JSON string that describes the Script to serialise.
|
||||||
|
/// </param>
|
||||||
|
/// <returns></returns>
|
||||||
|
static bool DeserialiseScript(Entity entity, System::String^ yaml);
|
||||||
|
|
||||||
|
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
|
|
@ -0,0 +1,45 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file Convert.cxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 28, 2021
|
||||||
|
\brief Contains the definition of the functions for the Convert managed static
|
||||||
|
class.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Precompiled Headers
|
||||||
|
#include "SHpch.h"
|
||||||
|
// Primary Header
|
||||||
|
#include "Convert.hxx"
|
||||||
|
// External Dependencies
|
||||||
|
#include "ECS_Base/System//SHEntityManager.h"
|
||||||
|
#include <msclr/marshal_cppstd.h>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* ECS Conversions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
Entity Convert::ToCLI(SHEntity entity)
|
||||||
|
{
|
||||||
|
return static_cast<Entity>(entity.GetEID());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* String Conversions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
std::string Convert::ToNative(System::String^ str)
|
||||||
|
{
|
||||||
|
return msclr::interop::marshal_as<std::string>(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
System::String^ Convert::ToCLI(const std::string& str)
|
||||||
|
{
|
||||||
|
return msclr::interop::marshal_as<System::String^>(str);
|
||||||
|
}
|
||||||
|
} // namespace PlushieAPI
|
|
@ -0,0 +1,62 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file Convert.hxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 28, 2021
|
||||||
|
\brief Contains the definition of the Convert static class and the
|
||||||
|
declaration of its functions.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
// External Dependencies
|
||||||
|
#include "ECS_Base/Entity/SHEntity.h"
|
||||||
|
// Project Includes
|
||||||
|
#include "Engine/Entity.hxx"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides functions easy and consistent syntax for converting between custom
|
||||||
|
/// managed and native types that are aligned.
|
||||||
|
/// </summary>
|
||||||
|
class Convert
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Deleted Destructors (Static Class) */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
Convert() = delete;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* ECS Conversions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Converts from a native Entity to a managed Entity (UInt32).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">Native Entity to convert from.</param>
|
||||||
|
/// <returns>Managed representation of the specified Entity.</returns>
|
||||||
|
static Entity ToCLI(SHEntity entity);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* String Conversions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Converts from a managed String to a native std::string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">The managed String to convert from.</param>
|
||||||
|
/// <returns>Native copy of a managed String.</returns>
|
||||||
|
static std::string ToNative(System::String^ str);
|
||||||
|
/// <summary>
|
||||||
|
/// Converts from a native std::Stringto a managed String.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">The native std::string to convert from.</param>
|
||||||
|
/// <returns>Managed copy of a native std::string.</returns>
|
||||||
|
static System::String^ ToCLI(const std::string& str);
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,122 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file Debug.cxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 28, 2021
|
||||||
|
\brief Contains the definition of the functions for the Debug managed static
|
||||||
|
class.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Precompiled Headers
|
||||||
|
#include "SHpch.h"
|
||||||
|
// Primary Header
|
||||||
|
#include "Debug.hxx"
|
||||||
|
// Standard Libraries
|
||||||
|
#include <sstream>
|
||||||
|
// Project Headers
|
||||||
|
#include "Convert.hxx"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Logging Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void Debug::Log(const std::string& str)
|
||||||
|
{
|
||||||
|
std::cout << str << std::endl;
|
||||||
|
}
|
||||||
|
void Debug::Log(System::String^ str)
|
||||||
|
{
|
||||||
|
System::Console::WriteLine(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Debug::Log(System::String^ str, Object^ owner)
|
||||||
|
{
|
||||||
|
Log(str, owner->GetType()->Name);
|
||||||
|
}
|
||||||
|
void Debug::Log(System::String^ str, System::String^ throwerName)
|
||||||
|
{
|
||||||
|
Log("[" + throwerName + "] " + str);
|
||||||
|
}
|
||||||
|
void Debug::Log(System::String^ str, const std::string& throwerName)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[" << throwerName << "] " << Convert::ToNative(str);
|
||||||
|
std::cout << oss.str() << std::endl;
|
||||||
|
}
|
||||||
|
void Debug::LogWarning(const std::string& str)
|
||||||
|
{
|
||||||
|
std::cout << str << std::endl;
|
||||||
|
}
|
||||||
|
void Debug::LogWarning(System::String^ str)
|
||||||
|
{
|
||||||
|
System::Console::WriteLine(str);
|
||||||
|
}
|
||||||
|
void Debug::LogWarning(System::String^ str, Object^ thrower)
|
||||||
|
{
|
||||||
|
LogWarning(str, thrower->GetType()->Name);
|
||||||
|
}
|
||||||
|
void Debug::LogWarning(System::String^ str, System::String^ throwerName)
|
||||||
|
{
|
||||||
|
LogWarning("[" + throwerName + "] " + str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Debug::LogWarning(System::String^ str, const std::string& throwerName)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[" << throwerName << "] " << Convert::ToNative(str);
|
||||||
|
std::cout << oss.str() << std::endl;
|
||||||
|
}
|
||||||
|
void Debug::LogError(const std::string& str)
|
||||||
|
{
|
||||||
|
std::cout << str << std::endl;
|
||||||
|
}
|
||||||
|
void Debug::LogError(System::String^ str)
|
||||||
|
{
|
||||||
|
System::Console::WriteLine(str);
|
||||||
|
}
|
||||||
|
void Debug::LogError(System::String^ str, Object^ thrower)
|
||||||
|
{
|
||||||
|
LogError(str, thrower->GetType()->Name);
|
||||||
|
}
|
||||||
|
void Debug::LogErrorNative(System::String^ str, const std::string& throwerName)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[" << throwerName << "] -> " << Convert::ToNative(str);
|
||||||
|
std::cout << oss.str() << std::endl;
|
||||||
|
}
|
||||||
|
void Debug::LogError(System::String^ str, System::String^ throwerName)
|
||||||
|
{
|
||||||
|
LogError("[" + throwerName + "] " + str);
|
||||||
|
}
|
||||||
|
void Debug::LogException(System::Exception^ exception)
|
||||||
|
{
|
||||||
|
LogError("Unhandled exception: " + exception->ToString(), exception->Source);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Debug::LogException(System::Exception^ exception, Object^ thrower)
|
||||||
|
{
|
||||||
|
LogError("Unhandled exception: " + exception->ToString(), thrower->GetType()->Name);
|
||||||
|
}
|
||||||
|
void Debug::LogException(const std::exception& exception, Object^ thrower)
|
||||||
|
{
|
||||||
|
LogExceptionNative(exception, Convert::ToNative(thrower->GetType()->Name));
|
||||||
|
}
|
||||||
|
void Debug::LogExceptionNative(System::Exception^ exception, const std::string& throwerName)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[" << throwerName << "] Unhandled exception: " << Convert::ToNative(exception->ToString());
|
||||||
|
std::cout << oss.str() << std::endl;
|
||||||
|
}
|
||||||
|
void Debug::LogExceptionNative(const std::exception& exception, const std::string& throwerName)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[" << throwerName << "] Unhandled exception: " << exception.what();
|
||||||
|
std::cout << oss.str() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,255 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file Debug.hxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Oct 30, 2021
|
||||||
|
\brief Contains the definition of the Debug static class and the declaration of
|
||||||
|
its functions.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
// Standard Library
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------------*/
|
||||||
|
/* Macro Functions */
|
||||||
|
/*-------------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Macro expansion that is used together with SAFE_NATIVE_CALL_END or
|
||||||
|
/// SAFE_NATIVE_CALL_END_N to wrap the body of a function with a try and catch that
|
||||||
|
/// catches native and managed exceptions. This is needed to prevent crashes when calling
|
||||||
|
/// managed code from native code.
|
||||||
|
/// </summary>
|
||||||
|
|
||||||
|
#define SAFE_NATIVE_CALL_BEGIN try {
|
||||||
|
/// <summary>
|
||||||
|
/// Macro expansion that is used together with SAFE_NATIVE_CALL_BEGIN or to wrap the body
|
||||||
|
/// of a function with a try and catch that catches native and managed exceptions. This
|
||||||
|
/// is needed to prevent crashes when calling managed code from native code.
|
||||||
|
/// <br/>
|
||||||
|
/// Use this instead of SAFE_NATIVE_CALL_END_N if passing in managed types as the owner.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="OWNER">
|
||||||
|
/// The managed object that owns the function that this macro encapsulates.
|
||||||
|
/// </param>
|
||||||
|
#define SAFE_NATIVE_CALL_END(OWNER) \
|
||||||
|
} \
|
||||||
|
catch (System::Exception^ e) \
|
||||||
|
{ \
|
||||||
|
Debug::LogException(e); \
|
||||||
|
} \
|
||||||
|
catch (const std::exception& e) \
|
||||||
|
{ \
|
||||||
|
Debug::LogException(e, OWNER); \
|
||||||
|
} \
|
||||||
|
catch (...) \
|
||||||
|
{ \
|
||||||
|
Debug::LogError("Unsupported native exception.", OWNER); \
|
||||||
|
} \
|
||||||
|
/// <summary>
|
||||||
|
/// Macro expansion that is used together with SAFE_NATIVE_CALL_BEGIN or to wrap the body
|
||||||
|
/// of a function with a try and catch that catches native and managed exceptions. This
|
||||||
|
/// is needed to prevent crashes when calling managed code from native code.
|
||||||
|
/// <br/>
|
||||||
|
/// Use this instead of SAFE_NATIVE_CALL_END if passing in a native string that specifies
|
||||||
|
/// the owner.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="OWNER">
|
||||||
|
/// The managed object that owns the function that this macro encapsulates.
|
||||||
|
/// </param>
|
||||||
|
|
||||||
|
#define SAFE_NATIVE_CALL_END_N(OWNER) \
|
||||||
|
} \
|
||||||
|
catch (System::Exception^ e) \
|
||||||
|
{ \
|
||||||
|
Debug::LogExceptionNative(e, OWNER); \
|
||||||
|
} \
|
||||||
|
catch (const std::exception& e) \
|
||||||
|
{ \
|
||||||
|
Debug::LogExceptionNative(e, OWNER); \
|
||||||
|
} \
|
||||||
|
catch (...) \
|
||||||
|
{ \
|
||||||
|
Debug::LogErrorNative("Unsupported native exception.", OWNER); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-------------------------------------------------------------------------------------*/
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Static class that contains the functions for working with time.
|
||||||
|
/// </summary>
|
||||||
|
public ref class Debug abstract sealed
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Logging Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a message to the output.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">The string to output.</param>
|
||||||
|
static void Log(const std::string& str);
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a message to the output.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">The string to output.</param>
|
||||||
|
static void Log(System::String^ str);
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a message to the output with a label such that it looks like this:
|
||||||
|
/// "[Label] Message"
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">The string to output.</param>
|
||||||
|
/// <param name="owner">
|
||||||
|
/// Object that sent the message to label the message.
|
||||||
|
/// The name of the object will be used.
|
||||||
|
/// </param>
|
||||||
|
static void Log(System::String^ str, Object^ owner);
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a message to the output with a label such that it looks like this:
|
||||||
|
/// "[Label] Message"
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">The string to output.</param>
|
||||||
|
/// <param name="throwerName">
|
||||||
|
/// Name of the object that sent the message to label the message.
|
||||||
|
/// The name of the object will be used.
|
||||||
|
/// </param>
|
||||||
|
static void Log(System::String^ str, System::String^ throwerName);
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a message to the output with a label such that it looks like this:
|
||||||
|
/// "[Label] Message"
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">The string to output.</param>
|
||||||
|
/// <param name="throwerName">
|
||||||
|
/// Name of the object that sent the message to label the message.
|
||||||
|
/// The name of the object will be used.
|
||||||
|
/// </param>
|
||||||
|
static void Log(System::String^ str, const std::string& throwerName);
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a warning message to the output.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">The string to output.</param>
|
||||||
|
static void LogWarning(const std::string& str);
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a warning message to the output.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">The string to output.</param>
|
||||||
|
static void LogWarning(System::String^ str);
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a warning message to the output with a label such that it looks like this:
|
||||||
|
/// "[Label] Message"
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">The string to output.</param>
|
||||||
|
/// <param name="thrower">
|
||||||
|
/// Object that threw the warning to label the warning message.
|
||||||
|
/// The name of the object will be used.
|
||||||
|
/// </param>
|
||||||
|
static void LogWarning(System::String^ str, Object^ thrower);
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a warning message to the output with a label such that it looks like this:
|
||||||
|
/// "[Label] Message"
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">The string to output.</param>
|
||||||
|
/// <param name="throwerName">
|
||||||
|
/// Name of the object that threw the warning to label the warning message.
|
||||||
|
/// The name of the object will be used.
|
||||||
|
/// </param>
|
||||||
|
static void LogWarning(System::String^ str, System::String^ throwerName);
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a warning message to the output with a label such that it looks like this:
|
||||||
|
/// "[Label] Message"
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">The string to output.</param>
|
||||||
|
/// <param name="throwerName">
|
||||||
|
/// Name of the object that threw the warning to label the warning message.
|
||||||
|
/// The name of the object will be used.
|
||||||
|
/// </param>
|
||||||
|
static void LogWarning(System::String^ str, const std::string& throwerName);
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a error message to the output.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">The string to output.</param>
|
||||||
|
static void LogError(const std::string& str);
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a error message to the output.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">The string to output.</param>
|
||||||
|
static void LogError(System::String^ str);
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a error message to the output with a label such that it looks like this:
|
||||||
|
/// "[Label] Message"
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">The string to output.</param>
|
||||||
|
/// <param name="thrower">
|
||||||
|
/// Object that threw the error to label the error message.
|
||||||
|
/// The name of the object will be used.
|
||||||
|
/// </param>
|
||||||
|
static void LogError(System::String^ str, Object^ thrower);
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a error message to the output with a label such that it looks like this:
|
||||||
|
/// "[Label] Message"
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">The string to output.</param>
|
||||||
|
/// <param name="throwerName">
|
||||||
|
/// Name of the object that threw the error to label the error message.
|
||||||
|
/// The name of the object will be used.
|
||||||
|
/// </param>
|
||||||
|
static void LogErrorNative(System::String^ str, const std::string& throwerName);
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a error message to the output with a label such that it looks like this:
|
||||||
|
/// "[Label] Message"
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">The string to output.</param>
|
||||||
|
/// <param name="throwerName">
|
||||||
|
/// Name of the object that threw the error to label the error message.
|
||||||
|
/// The name of the object will be used.
|
||||||
|
/// </param>
|
||||||
|
static void LogError(System::String^ str, System::String^ throwerName);
|
||||||
|
/// <summary>
|
||||||
|
/// Logs an exception that is formatted nicely to the output.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="exception">Exception to log.</param>
|
||||||
|
static void LogException(System::Exception^ exception);
|
||||||
|
/// <summary>
|
||||||
|
/// Logs an exception that is formatted nicely to the output.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="exception">Exception to log.</param>
|
||||||
|
/// <param name="thrower">
|
||||||
|
/// Object that threw the exception to label the exception message.
|
||||||
|
/// The name of the object will be used.
|
||||||
|
/// </param>
|
||||||
|
static void LogException(System::Exception^ exception, Object^ thrower);
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a native exception that is formatted nicely to the output.
|
||||||
|
/// Equivalent to calling
|
||||||
|
/// LogException(exception, Convert::ToNative(thrower->GetType()->Name));
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="exception">Native exception to log.</param>
|
||||||
|
/// <param name="thrower">
|
||||||
|
/// Object that threw the exception to label the exception message.
|
||||||
|
/// The name of the object will be used.
|
||||||
|
/// </param>
|
||||||
|
static void LogException(const std::exception& exception, Object^ thrower);
|
||||||
|
/// <summary>
|
||||||
|
/// Logs an exception that is formatted nicely to the output.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="throwerName">Name of the one responsible for the exception.</param>
|
||||||
|
/// <param name="exception">Exception to log.</param>
|
||||||
|
static void LogExceptionNative(System::Exception^ exception, const std::string& throwerName);
|
||||||
|
/// <summary>
|
||||||
|
/// Logs a native exception that is formatted nicely to the output.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="exception">Native exception to log.</param>
|
||||||
|
/// <param name="throwerName">Name of the one responsible for the exception.</param>
|
||||||
|
static void LogExceptionNative(const std::exception& exception, const std::string& throwerName);
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file DisposableAssemblyLoadContext.cxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Jan 20, 2022
|
||||||
|
\brief Contains the implementation of the managed DisposableAssemblyLoadContext
|
||||||
|
class.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Precompiled Headers
|
||||||
|
#include "SHpch.h"
|
||||||
|
// Primary Header
|
||||||
|
#include "DisposableAssemblyLoadContext.hxx"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructor */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
DisposableAssemblyLoadContext::DisposableAssemblyLoadContext()
|
||||||
|
: AssemblyLoadContext { true }
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
System::Reflection::Assembly^ DisposableAssemblyLoadContext::Load(System::Reflection::AssemblyName^)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
} // namespace PlushieAPI
|
|
@ -0,0 +1,39 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file DisposableAssemblyLoadContext.hxx
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Jan 20, 2022
|
||||||
|
\brief Contains the definitions of the managed DisposableAssemblyLoadContext
|
||||||
|
class.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Custom AssemblyLoadContext marked as collectible so that it can be unloaded.
|
||||||
|
/// </summary>
|
||||||
|
private ref class DisposableAssemblyLoadContext : public System::Runtime::Loader::AssemblyLoadContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Constructor */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Default Constructor
|
||||||
|
/// </summary>
|
||||||
|
DisposableAssemblyLoadContext();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
System::Reflection::Assembly^ Load(System::Reflection::AssemblyName^ assemblyName) override;
|
||||||
|
};
|
||||||
|
} // namespace PlushieAPI
|
|
@ -12,7 +12,7 @@ workspace "SHADE"
|
||||||
|
|
||||||
flags
|
flags
|
||||||
{
|
{
|
||||||
"MultiProcessorCompile"
|
"MultiProcessorCompile"
|
||||||
}
|
}
|
||||||
|
|
||||||
outputdir = "%{wks.location}/bin/%{cfg.buildcfg}"
|
outputdir = "%{wks.location}/bin/%{cfg.buildcfg}"
|
||||||
|
@ -20,6 +20,7 @@ workspace "SHADE"
|
||||||
|
|
||||||
include "SHADE_Engine"
|
include "SHADE_Engine"
|
||||||
include "SHADE_Application"
|
include "SHADE_Application"
|
||||||
|
include "SHADE_Managed"
|
||||||
|
|
||||||
group "Dependencies"
|
group "Dependencies"
|
||||||
include "Dependencies/msdf"
|
include "Dependencies/msdf"
|
||||||
|
|
Loading…
Reference in New Issue