diff --git a/SHADE_Application/SHADE_Application.vcxproj b/SHADE_Application/SHADE_Application.vcxproj
index 37c97b1c..d83a0c64 100644
--- a/SHADE_Application/SHADE_Application.vcxproj
+++ b/SHADE_Application/SHADE_Application.vcxproj
@@ -60,7 +60,7 @@
SBpch.h
Level4
_DEBUG;%(PreprocessorDefinitions)
- .;..\SHADE_Engine\src;src;%(AdditionalIncludeDirectories)
+ ..\Dependencies\spdlog\include;..\SHADE_Engine\src;src;%(AdditionalIncludeDirectories)
EditAndContinue
Disabled
false
@@ -80,7 +80,7 @@
SBpch.h
Level4
_RELEASE;%(PreprocessorDefinitions)
- .;..\SHADE_Engine\src;src;%(AdditionalIncludeDirectories)
+ ..\Dependencies\spdlog\include;..\SHADE_Engine\src;src;%(AdditionalIncludeDirectories)
Full
true
true
diff --git a/SHADE_Application/SHADE_Application.vcxproj.filters b/SHADE_Application/SHADE_Application.vcxproj.filters
new file mode 100644
index 00000000..1234632d
--- /dev/null
+++ b/SHADE_Application/SHADE_Application.vcxproj.filters
@@ -0,0 +1,30 @@
+
+
+
+
+ {D9DE78AF-4594-F1A4-CE88-EB7B3A3DE8A8}
+
+
+ {86EEB3D0-7290-DEA6-5B4B-F2FA478C65F7}
+
+
+
+
+ Application
+
+
+
+ Scenes
+
+
+
+
+ Application
+
+
+
+ Scenes
+
+
+
+
\ No newline at end of file
diff --git a/SHADE_Application/premake5.lua b/SHADE_Application/premake5.lua
index 60a87928..35440432 100644
--- a/SHADE_Application/premake5.lua
+++ b/SHADE_Application/premake5.lua
@@ -21,8 +21,7 @@ project "SHADE_Application"
includedirs
{
- "%{IncludeDir.GLFW}",
- "%{IncludeDir.GLAD}",
+ "%{IncludeDir.spdlog}/include",
"../SHADE_Engine/src",
"src"
}
diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp
index 58aded2b..c420a37f 100644
--- a/SHADE_Application/src/Application/SBApplication.cpp
+++ b/SHADE_Application/src/Application/SBApplication.cpp
@@ -15,6 +15,8 @@ namespace Sandbox
bool paused = false;
void SBApplication::Initialize(void)
{
+
+
#ifdef SHEDITOR
#else
#endif
diff --git a/SHADE_Application/src/WinMain.cpp b/SHADE_Application/src/WinMain.cpp
index 89005432..50be1289 100644
--- a/SHADE_Application/src/WinMain.cpp
+++ b/SHADE_Application/src/WinMain.cpp
@@ -1,5 +1,7 @@
#include "SBpch.h"
#include
+#include
+#include
#include "Application/SBApplication.h"
@@ -15,15 +17,35 @@
#define DBG_NEW new
#endif
-INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
- PSTR lpCmdLine, INT nCmdShow)
+INT WINAPI WinMain
+(
+ _In_ HINSTANCE /*hInstance*/,
+ _In_opt_ HINSTANCE /*hPrevInstance*/,
+ _In_ PSTR /*lpCmdLine*/,
+ _In_ INT /*nCmdShow*/
+)
{
- #ifndef SHEDITOR
- ShowWindow(::GetConsoleWindow(), SW_HIDE);
- #endif
+ const SHADE::SHLogger::Config LOGGER_CONFIG{ .directoryPath = "./logs/" };
+ SHADE::SHLogger::Initialise(LOGGER_CONFIG);
- SHADE::SHEngine::Run();
- _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
+ try
+ {
+ #ifndef SHEDITOR
+ //ShowWindow(::GetConsoleWindow(), SW_HIDE);
+ #endif
+
+ SHLOG_INFO("sup")
+
+ SHADE::SHEngine::Run();
+ _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
+ }
+ catch(...)
+ {
+ SHADE::SHExceptionHandler::HandleException(std::current_exception());
+ SHADE::SHLogger::Shutdown();
+ }
+
+ SHADE::SHLogger::Shutdown();
return 0;
}
\ No newline at end of file
diff --git a/SHADE_Engine/SHADE_Engine.vcxproj b/SHADE_Engine/SHADE_Engine.vcxproj
index 15d38e26..dcc0f3c8 100644
--- a/SHADE_Engine/SHADE_Engine.vcxproj
+++ b/SHADE_Engine/SHADE_Engine.vcxproj
@@ -117,9 +117,12 @@
+
-
+
+
+
@@ -129,10 +132,13 @@
-
Create
+
+
+
+
@@ -157,4 +163,4 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/SHADE_Engine/SHADE_Engine.vcxproj.filters b/SHADE_Engine/SHADE_Engine.vcxproj.filters
index 02a36cbf..8d62d05b 100644
--- a/SHADE_Engine/SHADE_Engine.vcxproj.filters
+++ b/SHADE_Engine/SHADE_Engine.vcxproj.filters
@@ -19,6 +19,15 @@
{B3E3FAFD-9FDD-2350-884A-BA6074E389BC}
+
+ {AC05897C-983C-8A0D-4129-70102D3F060F}
+
+
+ {B3F7140E-1F0C-3DBF-E88D-E01E546139F0}
+
+
+ {16CF2D0E-82E3-55BF-4B65-F91EB73852F0}
+
@@ -63,10 +72,25 @@
Engine
+
+ Meta
+
-
-
-
+
+ Scene
+
+
+ Scene
+
+
+ Tools
+
+
+ Tools
+
+
+ Tools
+
@@ -91,6 +115,17 @@
Engine
-
+
+ Scene
+
+
+ Tools
+
+
+ Tools
+
+
+ Tools
+
\ No newline at end of file
diff --git a/SHADE_Engine/src/SHpch.cpp b/SHADE_Engine/src/SHpch.cpp
index a7fec85b..2a36c693 100644
--- a/SHADE_Engine/src/SHpch.cpp
+++ b/SHADE_Engine/src/SHpch.cpp
@@ -1 +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"
\ No newline at end of file
diff --git a/SHADE_Engine/src/SHpch.h b/SHADE_Engine/src/SHpch.h
index e69de29b..19bd69b6 100644
--- a/SHADE_Engine/src/SHpch.h
+++ b/SHADE_Engine/src/SHpch.h
@@ -0,0 +1,12 @@
+/****************************************************************************************
+ * \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
+
+#include
\ No newline at end of file
diff --git a/SHADE_Engine/src/Tools/SHException.cpp b/SHADE_Engine/src/Tools/SHException.cpp
new file mode 100644
index 00000000..a5d08b18
--- /dev/null
+++ b/SHADE_Engine/src/Tools/SHException.cpp
@@ -0,0 +1,51 @@
+/****************************************************************************************
+ * \file SHException.cpp
+ * \author Diren D Bharwani, diren.dbharwani, 390002520
+ * \brief Implementation for custom exception types of 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.
+****************************************************************************************/
+
+#include
+
+// Primary Header
+#include "SHException.h"
+
+namespace SHADE
+{
+ /*-----------------------------------------------------------------------------------*/
+ /* Constructors & Destructor Definitions */
+ /*-----------------------------------------------------------------------------------*/
+
+ SHException::SHException(std::string msg, const std::source_location& src) noexcept
+ : message { std::move(msg) }
+ , origin { src }
+ {}
+
+ /*-----------------------------------------------------------------------------------*/
+ /* Public Function Member Definitions */
+ /*-----------------------------------------------------------------------------------*/
+
+ const char* SHException::what() const noexcept
+ {
+ std::stringstream ss;
+ ss << "SHException " << GetOriginString();
+ message = ss.str();
+
+ return message.c_str();
+ }
+
+ /*-----------------------------------------------------------------------------------*/
+ /* Private Function Member Definitions */
+ /*-----------------------------------------------------------------------------------*/
+
+ std::string SHException::GetOriginString() const noexcept
+ {
+ std::stringstream ss;
+ ss << "[" << origin.file_name() << ", " << origin.line() << "]";
+ return ss.str();
+ }
+
+} // namespace SHADE
\ No newline at end of file
diff --git a/SHADE_Engine/src/Tools/SHException.h b/SHADE_Engine/src/Tools/SHException.h
new file mode 100644
index 00000000..251217eb
--- /dev/null
+++ b/SHADE_Engine/src/Tools/SHException.h
@@ -0,0 +1,84 @@
+/****************************************************************************************
+ * \file SHException.h
+ * \author Diren D Bharwani, diren.dbharwani, 390002520
+ * \brief Interface for custom exception types of 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
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+// Project Headers
+#include "SHLogger.h"
+
+namespace SHADE
+{
+ /*-----------------------------------------------------------------------------------*/
+ /* Concepts */
+ /*-----------------------------------------------------------------------------------*/
+
+ template
+ concept IsException = std::is_base_of_v;
+
+ /*-----------------------------------------------------------------------------------*/
+ /* Type Definitions */
+ /*-----------------------------------------------------------------------------------*/
+
+ /**
+ * @brief Base exception type thrown by SHADE Engine.
+ */
+ class SHException : public std::exception
+ {
+ public:
+ /*---------------------------------------------------------------------------------*/
+ /* Constructors & Destructor */
+ /*---------------------------------------------------------------------------------*/
+
+ SHException
+ (
+ std::string msg = "",
+ const std::source_location& src = std::source_location::current()
+ ) noexcept;
+
+ /*---------------------------------------------------------------------------------*/
+ /* Function Members */
+ /*---------------------------------------------------------------------------------*/
+
+ const char* what() const noexcept override;
+
+ protected:
+ /*---------------------------------------------------------------------------------*/
+ /* Data Members */
+ /*---------------------------------------------------------------------------------*/
+ mutable std::string message;
+
+ /*---------------------------------------------------------------------------------*/
+ /* Function Members */
+ /*---------------------------------------------------------------------------------*/
+
+ std::string GetOriginString() const noexcept;
+
+ private:
+ /*---------------------------------------------------------------------------------*/
+ /* Data Members */
+ /*---------------------------------------------------------------------------------*/
+ const std::source_location& origin;
+ };
+}
+
+#define SHASSERT(cond, msg) \
+ if (!(cond)) \
+ { \
+ SHLOGV_CRITICAL(msg) \
+ std::abort(); \
+ }
+
diff --git a/SHADE_Engine/src/Tools/SHExceptionHandler.cpp b/SHADE_Engine/src/Tools/SHExceptionHandler.cpp
new file mode 100644
index 00000000..ff6df05c
--- /dev/null
+++ b/SHADE_Engine/src/Tools/SHExceptionHandler.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************************
+ * \file SHExceptionHandler.cpp
+ * \author Diren D Bharwani, diren.dbharwani, 390002520
+ * \brief Implementation for SHADE Engine's exception handler.
+ *
+ * \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
+
+// Primary Header
+#include "SHExceptionHandler.h"
+
+// Project Headers
+#include "SHException.h"
+#include "SHLogger.h"
+
+namespace SHADE
+{
+ /*-----------------------------------------------------------------------------------*/
+ /* Static Function Member Definitions */
+ /*-----------------------------------------------------------------------------------*/
+
+ bool SHExceptionHandler::HandleException(const std::exception_ptr& exceptionPtr)
+ {
+ try
+ {
+ // Re-throw all valid exception types
+ if (exceptionPtr)
+ {
+ std::rethrow_exception(exceptionPtr);
+ }
+ }
+ catch (const std::exception& e)
+ {
+ SHLOG_CRITICAL(e.what())
+ }
+ catch (...)
+ {
+ // Catch any non-std::exception derived types and consider them as unknown.
+ SHLOG_CRITICAL("SHADE Engine has experienced an unknown fatal error!")
+ }
+
+ return false;
+ }
+
+} // namespace SHADE
\ No newline at end of file
diff --git a/SHADE_Engine/src/Tools/SHExceptionHandler.h b/SHADE_Engine/src/Tools/SHExceptionHandler.h
new file mode 100644
index 00000000..dd1d7596
--- /dev/null
+++ b/SHADE_Engine/src/Tools/SHExceptionHandler.h
@@ -0,0 +1,37 @@
+/****************************************************************************************
+ * \file SHExceptionHandler.h
+ * \author Diren D Bharwani, diren.dbharwani, 390002520
+ * \brief Interface for SHADE Engine's exception handler.
+ *
+ * \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
+
+#include
+
+namespace SHADE
+{
+ /*-----------------------------------------------------------------------------------*/
+ /* Type Definitions */
+ /*-----------------------------------------------------------------------------------*/
+
+ class SHExceptionHandler
+ {
+ public:
+ /*---------------------------------------------------------------------------------*/
+ /* Static Function Members */
+ /*---------------------------------------------------------------------------------*/
+
+ /**
+ * @brief Catches and logs any exceptions thrown. If the exception's type is
+ * SHAssertException, the application will not end unless crashOnAssert is set
+ * to true.
+ * @param exceptionPtr Pointer to the exception that was caught.
+ * @returns True if the application should continue running after an exception was caught.
+ */
+ static bool HandleException(const std::exception_ptr& exceptionPtr);
+ };
+} // namespace SHADE
\ No newline at end of file
diff --git a/SHADE_Engine/src/Tools/SHLogger.cpp b/SHADE_Engine/src/Tools/SHLogger.cpp
new file mode 100644
index 00000000..7b39e979
--- /dev/null
+++ b/SHADE_Engine/src/Tools/SHLogger.cpp
@@ -0,0 +1,441 @@
+/****************************************************************************************
+ * \file SHLogger.cpp
+ * \author Diren D Bharwani, diren.dbharwani, 390002520
+ * \brief Implementation for SHADE Engine's logger.
+ *
+ * \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
+
+// Primary Header
+#include "SHLogger.h"
+
+#include
+#include
+
+#include
+#include
+
+/*-------------------------------------------------------------------------------------*/
+/* Local Helper Function Declarations */
+/*-------------------------------------------------------------------------------------*/
+std::string GetDatePattern (SHADE::SHLogger::DateFormat fmt);
+std::string GetClockPattern (bool is24HR);
+
+namespace SHADE
+{
+ /*-----------------------------------------------------------------------------------*/
+ /* Static Data Member Definitions */
+ /*-----------------------------------------------------------------------------------*/
+ unsigned char SHLogger::configFlags = DEFAULT_CONFIG_FLAG;
+ SHLogger::DateFormat SHLogger::dateFormat = SHLogger::DateFormat::DD_MM_YY;
+ std::string SHLogger::trivialPattern;
+ std::string SHLogger::verbosePattern;
+
+ std::string SHLogger::fileName;
+ std::filesystem::path SHLogger::directoryPath;
+
+ /*-----------------------------------------------------------------------------------*/
+ /* Setter Function Definitions */
+ /*-----------------------------------------------------------------------------------*/
+
+ void SHLogger::SetConfig(const Config& config) noexcept
+ {
+ unsigned char flags = 0U;
+
+ if (config.showTime)
+ flags |= 1U << 0;
+
+ if (config.clockFormat == ClockFormat::_24HR)
+ flags |= 1U << 1;
+
+ if (config.showDate)
+ flags |= 1U << 2;
+
+ if (config.showFunctionFileName)
+ flags |= 1U << 3;
+
+ if (config.showFunctionLineNumber)
+ flags |= 1U << 4;
+
+ configFlags = flags;
+ dateFormat = config.dateFormat;
+
+ fileName = config.fileName;
+ directoryPath = config.directoryPath;
+
+ UpdatePatterns();
+ }
+
+ void SHLogger::SetShowTime(bool showTime) noexcept
+ {
+ constexpr char RAW = 1U << 0;
+ showTime ? configFlags |= RAW : configFlags &= ~(RAW);
+ UpdatePatterns();
+ }
+
+ void SHLogger::SetShowDate(bool showDate) noexcept
+ {
+ constexpr char RAW = 1U << 2;
+ showDate ? configFlags |= RAW : configFlags &= ~(RAW);
+ UpdatePatterns();
+ }
+
+ void SHLogger::SetShowFunctionFileName(bool showFunctionFileName) noexcept
+ {
+ constexpr char RAW = 1U << 3;
+ showFunctionFileName ? configFlags |= RAW : configFlags &= ~(RAW);
+ UpdatePatterns();
+ }
+
+ void SHLogger::SetShowFunctionLineNumber(bool showFunctionLineNumber) noexcept
+ {
+ constexpr char RAW = 1U << 4;
+ showFunctionLineNumber ? configFlags |= RAW : configFlags &= ~(RAW);
+ UpdatePatterns();
+ }
+
+ void SHLogger::SetClockFormat(ClockFormat newClockFormat) noexcept
+ {
+ constexpr char RAW = 1U << 1;
+ newClockFormat == ClockFormat::_24HR ? configFlags |= RAW : configFlags &= ~(RAW);
+ UpdatePatterns();
+ }
+
+ void SHLogger::SetDateFormat(DateFormat newDateFormat) noexcept
+ {
+ dateFormat = newDateFormat;
+ UpdatePatterns();
+ }
+
+ void SHLogger::SetFileName(const std::string& logFileName) noexcept
+ {
+ if (CheckInitialisation("Logger has already been initialised!"))
+ return;
+
+ fileName = logFileName;
+ }
+
+ void SHLogger::SetDirectoryPath(const std::filesystem::path& logDirectoryPath) noexcept
+ {
+ if (CheckInitialisation("Logger has already been initialised!"))
+ return;
+
+ if (!is_directory(logDirectoryPath))
+ {
+ spdlog::get(SHLOGGER_NAME)->info("Supplied path is not a directory!");
+ return;
+ }
+
+ directoryPath = logDirectoryPath;
+ }
+
+ void SHLogger::SetFlushTime(int seconds) noexcept
+ {
+ spdlog::flush_every(std::chrono::seconds(seconds));
+ }
+
+ /*-----------------------------------------------------------------------------------*/
+ /* Public Function Member Definitions */
+ /*-----------------------------------------------------------------------------------*/
+
+ void SHLogger::Initialise(const Config& config)
+ {
+ SetConfig(config);
+
+ // Initialise default fileName if fileName was not set
+ if (fileName.empty())
+ {
+ // Get current date and time
+ const auto NOW = std::time(nullptr);
+ std::tm localTime;
+ localtime_s(&localTime, &NOW);
+
+ std::stringstream tmp;
+ tmp << "SHADE Log_" << std::put_time(&localTime, "%F %H.%M.%S") << ".txt";
+
+ fileName = tmp.str();
+ }
+
+ CreateConsole();
+
+ try
+ {
+ std::vector sinks;
+
+ // Colour console
+ const auto& COLOUR_CONSOLE_SINK = sinks.emplace_back(std::make_shared());
+ COLOUR_CONSOLE_SINK->set_pattern("%^" + trivialPattern + "%v%$");
+
+ // File
+ const std::string FULL_FILE_PATH = directoryPath.string() + fileName;
+ const auto& FILE_SINK = sinks.emplace_back(std::make_shared(FULL_FILE_PATH));
+ FILE_SINK->set_pattern(trivialPattern + "%v");
+
+ // Create and register logger with spdlog
+ const auto LOGGER = std::make_shared(SHLOGGER_NAME, sinks.begin(), sinks.end());
+ LOGGER->set_level(spdlog::level::trace);
+ LOGGER->flush_on(spdlog::level::trace);
+ register_logger(LOGGER);
+
+ // Flush every 3 seconds
+ spdlog::flush_every(std::chrono::seconds(config.flushTime));
+
+ configFlags |= (1U << 7);
+ }
+ catch (const spdlog::spdlog_ex& e)
+ {
+ std::cout << "Log initialisation failed: " << e.what() << std::endl;
+ }
+ }
+
+ void SHLogger::Shutdown() noexcept
+ {
+ spdlog::shutdown();
+ }
+
+ void SHLogger::UseTrivialPattern() noexcept
+ {
+ auto& sinks = spdlog::get(SHLOGGER_NAME)->sinks();
+ sinks[0]->set_pattern("%^" + trivialPattern + "%v%$"); // Colour Console Sink
+ sinks[1]->set_pattern(trivialPattern + "%v"); // File Sink
+ }
+
+ void SHLogger::UseVerbosePattern() noexcept
+ {
+ auto& sinks = spdlog::get(SHLOGGER_NAME)->sinks();
+ sinks[0]->set_pattern("%^" + verbosePattern + "%v%$"); // Colour Console Sink
+ sinks[1]->set_pattern(verbosePattern + "%v"); // File Sink
+ }
+
+ /*-----------------------------------------------------------------------------------*/
+ /* Private Function Member Definitions */
+ /*-----------------------------------------------------------------------------------*/
+
+ bool SHLogger::CreateConsole()
+ {
+ bool result = false;
+ DestroyConsole();
+
+ if (AllocConsole())
+ {
+ const HANDLE CONSOLE = GetStdHandle(STD_OUTPUT_HANDLE);
+
+ // Set the screen buffer to be big enough to scroll some text
+ CONSOLE_SCREEN_BUFFER_INFO conInfo;
+ GetConsoleScreenBufferInfo(CONSOLE, &conInfo);
+
+ if (conInfo.dwSize.Y < DEFAULT_CONSOLE_LEN)
+ {
+ conInfo.dwSize.Y = DEFAULT_CONSOLE_LEN;
+ }
+
+ SetConsoleScreenBufferSize(CONSOLE, conInfo.dwSize);
+
+ result = RedirectConsoleIO();
+ }
+
+ return result;
+ }
+
+ bool SHLogger::RedirectConsoleIO()
+ {
+ bool result = true;
+
+ FILE* fp;
+
+ // Redirect STDIN if the console has an input handle
+ if (GetStdHandle(STD_INPUT_HANDLE) != INVALID_HANDLE_VALUE)
+ {
+ if (freopen_s(&fp, "CONIN$", "r", stdin) != 0)
+ {
+ result = false;
+ }
+ else
+ {
+ setvbuf(stdin, nullptr, _IONBF, 0);
+ }
+ }
+
+ // Redirect STDOUT if the console has an output handle
+ if (GetStdHandle(STD_OUTPUT_HANDLE) != INVALID_HANDLE_VALUE)
+ {
+ if (freopen_s(&fp, "CONOUT$", "w", stdout) != 0)
+ {
+ result = false;
+ }
+ else
+ {
+ setvbuf(stdout, nullptr, _IONBF, 0);
+ }
+ }
+
+ // Redirect STDERR if the console has an error handle
+ if (GetStdHandle(STD_ERROR_HANDLE) != INVALID_HANDLE_VALUE)
+ {
+ if (freopen_s(&fp, "CONOUT$", "w", stderr) != 0)
+ {
+ result = false;
+ }
+ else
+ {
+ setvbuf(stderr, nullptr, _IONBF, 0);
+ }
+ }
+
+ // Make C++ standard streams point to console as well.
+ std::ios::sync_with_stdio(true);
+
+ // Clear the error state for each of the C++ standard streams.
+ std::wcin.clear();
+ std::cin.clear();
+ std::wcout.clear();
+ std::cout.clear();
+ std::wcerr.clear();
+ std::cerr.clear();
+
+ return result;
+ }
+
+
+ bool SHLogger::DestroyConsole()
+ {
+ bool result = true;
+ FILE* fP;
+
+ // Just to be safe, redirect standard IO to NUL before releasing.
+
+ // Redirect STDIN to NUL
+ if (freopen_s(&fP, "NUL:", "r", stdin) != 0)
+ {
+ result = false;
+ }
+ else
+ {
+ setvbuf(stdin, nullptr, _IONBF, 0);
+ }
+
+
+ // Redirect STDOUT to NUL
+ if (freopen_s(&fP, "NUL:", "w", stdout) != 0)
+ {
+ result = false;
+ }
+ else
+ {
+ setvbuf(stdout, nullptr, _IONBF, 0);
+ }
+
+ // Redirect STDERR to NUL
+ if (freopen_s(&fP, "NUL:", "w", stderr) != 0)
+ {
+ result = false;
+ }
+ else
+ {
+ setvbuf(stderr, nullptr, _IONBF, 0);
+ }
+
+ // Detach console
+ if (result)
+ return FreeConsole();
+
+ return result;
+ }
+
+ bool SHLogger::CheckInitialisation(const std::string_view& msg)
+ {
+ const bool INITIALISED = configFlags & (1U << 7);
+ if (INITIALISED)
+ {
+ spdlog::get(SHLOGGER_NAME)->warn(msg);
+ return true;
+ }
+
+ return false;
+ }
+
+ void SHLogger::UpdatePatterns()
+ {
+ const std::string DATE_TIME_PATTERN = BuildDateTimePattern();
+ const std::string VERBOSE_PATTERN = BuildVerbosePattern();
+
+ trivialPattern = DATE_TIME_PATTERN;
+ verbosePattern = DATE_TIME_PATTERN + VERBOSE_PATTERN;
+ }
+
+ std::string SHLogger::BuildDateTimePattern()
+ {
+ const bool SHOW_TIME = configFlags & (1U << 0);
+ const bool SHOW_DATE = configFlags & (1U << 2);
+
+ std::string pattern;
+ if (SHOW_DATE || SHOW_TIME)
+ {
+ pattern.append("[");
+ {
+ if (SHOW_DATE)
+ {
+ pattern.append(GetDatePattern(dateFormat));
+ }
+
+ // Put a space in between date and time
+ if (SHOW_DATE && SHOW_TIME)
+ {
+ pattern.append(" ");
+ }
+
+ if (SHOW_TIME)
+ {
+ const bool IS_24HR = configFlags & (1U << 1);
+ pattern.append(GetClockPattern(IS_24HR));
+ }
+ }
+ pattern.append("] ");
+ }
+
+ return pattern;
+ }
+
+ std::string SHLogger::BuildVerbosePattern()
+ {
+ const bool SHOW_SRC_FILE = configFlags & (1U << 3);
+ const bool SHOW_SRC_LINE = configFlags & (1U << 4);
+
+ std::string pattern { "[" };
+ if (SHOW_SRC_FILE)
+ {
+ pattern.append("%s, ");
+ if (SHOW_SRC_LINE)
+ {
+ pattern.append("%#, ");
+ }
+ }
+
+ pattern.append("%!] ");
+ return pattern;
+ }
+
+} // namespace SHADE
+
+std::string GetDatePattern(SHADE::SHLogger::DateFormat fmt)
+{
+ switch (fmt)
+ {
+ case SHADE::SHLogger::DateFormat::DD_MM_YY: return std::string { "%d-%m-%Y" };
+ case SHADE::SHLogger::DateFormat::MM_DD_YY: return std::string { "%m-%d-%Y" };
+ case SHADE::SHLogger::DateFormat::YY_MM_DD: return std::string { "%Y-%m-%d" };
+ case SHADE::SHLogger::DateFormat::DD_Mth_YY: return std::string { "%d %b, %Y" };
+ case SHADE::SHLogger::DateFormat::Mth_DD_YY: return std::string { "%b %d, %Y" };
+
+ default: return std::string { "%d-%m-%Y" };
+ }
+}
+
+std::string GetClockPattern(bool is24HR)
+{
+ return is24HR ? "%H:%M:%S" : "%I:%M:%S %p";
+}
\ No newline at end of file
diff --git a/SHADE_Engine/src/Tools/SHLogger.h b/SHADE_Engine/src/Tools/SHLogger.h
new file mode 100644
index 00000000..ac5f9308
--- /dev/null
+++ b/SHADE_Engine/src/Tools/SHLogger.h
@@ -0,0 +1,174 @@
+/****************************************************************************************
+ * \file SHLogger.h
+ * \author Diren D Bharwani, diren.dbharwani, 390002520
+ * \brief Interface for SHADE Engine's logger.
+ *
+ * \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
+
+#include
+#include
+
+#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE
+#include
+
+/*-------------------------------------------------------------------------------------*/
+/* Macros */
+/*-------------------------------------------------------------------------------------*/
+#define SHLOGGER_NAME "SHLogger"
+
+namespace SHADE
+{
+ /*-----------------------------------------------------------------------------------*/
+ /* Type Definitions */
+ /*-----------------------------------------------------------------------------------*/
+
+ class SHLogger
+ {
+ public:
+ /*---------------------------------------------------------------------------------*/
+ /* Type Definitions */
+ /*---------------------------------------------------------------------------------*/
+
+ enum class ClockFormat { _12HR, _24HR };
+
+ enum class DateFormat
+ {
+ DD_MM_YY // 25-12-2022
+ , MM_DD_YY // 12-25-2022
+ , YY_MM_DD // 2022-12-25
+ , DD_Mth_YY // 25 Dec, 2022
+ , Mth_DD_YY // Dec 25, 2022
+ };
+
+ /**
+ * @brief Defines configuration parameters for the logger.
+ */
+ struct Config
+ {
+ /*-------------------------------------------------------------------------------*/
+ /* Data Members */
+ /*-------------------------------------------------------------------------------*/
+ bool showTime = true;
+ bool showDate = true;
+ bool showFunctionFileName = true;
+ bool showFunctionLineNumber = true;
+
+ ClockFormat clockFormat = ClockFormat::_12HR;
+ DateFormat dateFormat = DateFormat::DD_MM_YY;
+ std::string fileName;
+ std::filesystem::path directoryPath;
+
+ int flushTime = 1;
+ };
+
+ /*---------------------------------------------------------------------------------*/
+ /* Getter Functions */
+ /*---------------------------------------------------------------------------------*/
+
+ [[nodiscard]] static const std::string& GetTrivialPattern () noexcept { return trivialPattern; }
+ [[nodiscard]] static const std::string& GetVerbosePattern () noexcept { return verbosePattern; }
+
+ /*---------------------------------------------------------------------------------*/
+ /* Setter Functions */
+ /*---------------------------------------------------------------------------------*/
+
+ static void SetTrivialPattern (const std::string& pattern) noexcept { trivialPattern = pattern; }
+ static void SetVerbosePattern (const std::string& pattern) noexcept { verbosePattern = pattern; }
+
+ static void SetConfig (const Config& config) noexcept;
+
+ static void SetShowTime (bool showTime) noexcept;
+ static void SetShowDate (bool showDate) noexcept;
+ static void SetShowFunctionFileName (bool showFunctionFileName) noexcept;
+ static void SetShowFunctionLineNumber (bool showFunctionLineNumber) noexcept;
+
+ static void SetClockFormat (ClockFormat newClockFormat) noexcept;
+ static void SetDateFormat (DateFormat newDateFormat) noexcept;
+
+
+
+ static void SetFileName (const std::string& logFileName) noexcept;
+ static void SetDirectoryPath (const std::filesystem::path& logDirectoryPath) noexcept;
+
+ static void SetFlushTime (int seconds) noexcept;
+ static void SetFlushTime (size_t seconds) noexcept { spdlog::flush_every(std::chrono::seconds(seconds)); }
+
+ /*---------------------------------------------------------------------------------*/
+ /* Function Members */
+ /*---------------------------------------------------------------------------------*/
+
+ /**
+ * @brief Creates a console and a file to log to.
+ * @param[in] config The configuration parameters for the logger.
+ */
+ static void Initialise (const Config& config = Config{});
+ static void Shutdown () noexcept;
+
+ /**
+ * @brief The next message logged by the logger will be set to follow the trivial pattern.
+ */
+ static void UseTrivialPattern () noexcept;
+ /**
+ * @brief The next message logged by the logger will be set to follow the verbose pattern.
+ */
+ static void UseVerbosePattern () noexcept;
+
+ private:
+ /*---------------------------------------------------------------------------------*/
+ /* Data Members */
+ /*---------------------------------------------------------------------------------*/
+ static constexpr char DEFAULT_CONFIG_FLAG = 0b00011101; // 00011101
+ static constexpr short DEFAULT_CONSOLE_LEN = 1024;
+
+ static unsigned char configFlags; // Initialised 0 0 FuncLine# FuncFileName Date TimeFormat Time
+ static DateFormat dateFormat;
+
+ static std::string trivialPattern;
+ static std::string verbosePattern;
+
+ static std::string fileName;
+ static std::filesystem::path directoryPath; // For file logging
+
+ /*---------------------------------------------------------------------------------*/
+ /* Function Members */
+ /*---------------------------------------------------------------------------------*/
+ static bool CreateConsole ();
+ static bool RedirectConsoleIO ();
+ static bool DestroyConsole ();
+
+ static bool CheckInitialisation (const std::string_view& msg);
+ static void UpdatePatterns ();
+ static std::string BuildDateTimePattern();
+ static std::string BuildVerbosePattern ();
+ };
+
+} // namespace SHADE
+
+/*-------------------------------------------------------------------------------------*/
+/* Macros */
+/*-------------------------------------------------------------------------------------*/
+
+#ifdef _DEBUG
+ #define SHLOG_TRACE(format, ...) SHADE::SHLogger::UseTrivialPattern(); SPDLOG_LOGGER_TRACE(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__);
+ #define SHLOGV_TRACE(format, ...) SHADE::SHLogger::UseVerbosePattern(); SPDLOG_LOGGER_TRACE(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__);
+#endif
+
+#define SHLOG_INFO(format, ...) SHADE::SHLogger::UseTrivialPattern(); SPDLOG_LOGGER_INFO(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__);
+#define SHLOGV_INFO(format, ...) SHADE::SHLogger::UseVerbosePattern(); SPDLOG_LOGGER_INFO(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__);
+
+#define SHLOG_WARNING(format, ...) SHADE::SHLogger::UseTrivialPattern(); SPDLOG_LOGGER_WARN(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__);
+#define SHLOGV_WARNING(format, ...) SHADE::SHLogger::UseVerbosePattern(); SPDLOG_LOGGER_WARN(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__);
+
+#define SHLOG_ERROR(format, ...) SHADE::SHLogger::UseTrivialPattern(); SPDLOG_LOGGER_ERROR(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__);
+#define SHLOGV_ERROR(format, ...) SHADE::SHLogger::UseVerbosePattern(); SPDLOG_LOGGER_ERROR(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__);
+
+#define SHLOG_CRITICAL(format, ...) SHADE::SHLogger::UseTrivialPattern(); SPDLOG_LOGGER_CRITICAL(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__);
+#define SHLOGV_CRITICAL(format, ...) SHADE::SHLogger::UseVerbosePattern(); SPDLOG_LOGGER_CRITICAL(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__);
+
+// Misc Logging Macros
+#define SHLOG_FLOOR() SHADE::SHLogger::UseTrivialPattern(); SPDLOG_LOGGER_INFO(spdlog::get(SHLOGGER_NAME), "--------------------------------");
\ No newline at end of file