From 93d62c5b1a06f49f5bc3249f1897e5c79de04cbb Mon Sep 17 00:00:00 2001 From: illyum Date: Sat, 14 Sep 2024 02:41:14 -0600 Subject: [PATCH] chore(refactor): use new logger api --- CMakeLists.txt | 10 +- sandbox/client.cpp | 110 ++++++++++++++----- src/FatalHandler.h | 11 ++ src/IsoEngine.cpp | 10 +- src/IsoEnginePCH.h | 1 + src/enet_client.cpp | 29 ++--- src/filepacker.cpp | 14 +-- src/platform/posix/FatalHandlerPosix.cpp | 39 ++++--- src/platform/windows/FatalHandlerWindows.cpp | 78 +++++++------ 9 files changed, 193 insertions(+), 109 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c2d14c2..2561911 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build." FORCE) endif() -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_XCODE_GENERATE_SCHEME ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) @@ -114,6 +114,11 @@ set(ENGINE_SOURCES src/scene_manager.cpp src/filepacker.cpp ) +if (WIN32) + list(APPEND ENGINE_SOURCES src/platform/windows/FatalHandlerWindows.cpp) +elseif(UNIX) + list(APPEND ENGINE_SOURCES src/platform/posix/FatalHandlerPosix.cpp) +endif() add_library(IsoEngine ${ENGINE_SOURCES}) @@ -147,7 +152,7 @@ target_link_libraries(rlImGui PRIVATE raylib ImGui) target_link_libraries(IsoEngine PRIVATE ImGui rlImGui) # Example executables (client/server) -if(BUILD_CLIENT OR BUILD_SANDBOX) +if(BUILD_CLIENT) # Client executable set(CLIENT_SOURCE "${CMAKE_CURRENT_LIST_DIR}/sandbox/client.cpp") add_executable(client ${CLIENT_SOURCE}) @@ -186,6 +191,7 @@ endif() # Build Configuration Optimizations if(CMAKE_BUILD_TYPE STREQUAL "Debug") message(STATUS "Configuring Debug build: No optimizations applied.") + target_compile_definitions(IsoEngine PRIVATE ENABLE_LOGGING) elseif(CMAKE_BUILD_TYPE STREQUAL "Release") message(STATUS "Configuring Release build: Applying moderate optimizations.") target_compile_options(IsoEngine PRIVATE -O2) diff --git a/sandbox/client.cpp b/sandbox/client.cpp index 280c3e2..cd7279e 100644 --- a/sandbox/client.cpp +++ b/sandbox/client.cpp @@ -1,45 +1,99 @@ #include "IsoEngine.h" -#include "components/transform_component.h" -#include "components/input_component.h" -#include +#include "components.h" + +#include + +#define ENABLE_LOGGING + +enum class MenuState { + MAIN_MENU, + OPTIONS, + QUIT +}; int main() { - IsoEngine engine(800, 600, nullptr); + int screenWidth = 800; + int screenHeight = 600; + IsoEngine engine(screenWidth, screenHeight, nullptr); engine.Initialize(); SceneManager& sceneManager = engine.GetSceneManager(); - entt::entity gameScene = sceneManager.CreateScene(); - sceneManager.SetActiveScene(gameScene); + entt::entity mainMenuScene = sceneManager.CreateScene(); - entt::entity player = engine.GetRegistry().create(); - engine.GetRegistry().emplace(player, 400.0f, 300.0f, 1.0f, 1.0f, 0.0f); + auto& registry = engine.GetRegistry(); - auto& inputComponent = engine.GetRegistry().emplace(player); + // Button dimensions + float buttonWidth = 200.0f; + float buttonHeight = 50.0f; + float spacing = 20.0f; // Vertical spacing between buttons - inputComponent.BindKey(InputAction::MOVE_UP, KEY_W); - inputComponent.BindKey(InputAction::MOVE_DOWN, KEY_S); - inputComponent.BindKey(InputAction::MOVE_LEFT, KEY_A); - inputComponent.BindKey(InputAction::MOVE_RIGHT, KEY_D); + // Center X position + float centerX = screenWidth / 2 - buttonWidth / 2; - inputComponent.SetActionCallback(InputAction::MOVE_UP, [&]() { - auto& transform = engine.GetRegistry().get(player); - transform.y -= 5.0f; - }); - inputComponent.SetActionCallback(InputAction::MOVE_DOWN, [&]() { - auto& transform = engine.GetRegistry().get(player); - transform.y += 5.0f; - }); - inputComponent.SetActionCallback(InputAction::MOVE_LEFT, [&]() { - auto& transform = engine.GetRegistry().get(player); - transform.x -= 5.0f; - }); - inputComponent.SetActionCallback(InputAction::MOVE_RIGHT, [&]() { - auto& transform = engine.GetRegistry().get(player); - transform.x += 5.0f; + // Y positions for each button + float singlePlayerY = screenHeight / 2 - (buttonHeight + spacing); + float quitButtonY = screenHeight / 2 + (buttonHeight + spacing); + + // Create a UI button for "Single Player" + entt::entity singlePlayerButton = registry.create(); + registry.emplace(singlePlayerButton, centerX, singlePlayerY, 1.0f, 1.0f, 0.0f); // Centered horizontally + registry.emplace(singlePlayerButton, "Single Player", buttonWidth, buttonHeight, [&]() { + std::cout << "Single Player button clicked!" << std::endl; }); + registry.emplace(singlePlayerButton, 1); // Main menu on layer 1 + // Create a "Quit" button + entt::entity quitButton = registry.create(); + registry.emplace(quitButton, centerX, quitButtonY, 1.0f, 1.0f, 0.0f); // Centered horizontally + registry.emplace(quitButton, "Quit", buttonWidth, buttonHeight, [&]() { + engine.Shutdown(); + }); + registry.emplace(quitButton, 1); // Also on layer 1 + + // Create an "F3" debug overlay on a higher layer + entt::entity debugOverlay = registry.create(); + registry.emplace(debugOverlay, 10.0f, 10.0f, 1.0f, 1.0f, 0.0f); // Placed at top-left corner + registry.emplace(debugOverlay, "FPS: 60\nPosition: (100, 200)", 300.0f, 100.0f, nullptr); + registry.emplace(debugOverlay, 2); // Debug overlay on layer 2 + + // Set active scene to the main menu + sceneManager.SetActiveScene(mainMenuScene); + + // Run the engine loop engine.Run(); engine.Shutdown(); return 0; } + + + + // entt::entity gameScene = sceneManager.CreateScene(); + // sceneManager.SetActiveScene(gameScene); + // + // entt::entity player = engine.GetRegistry().create(); + // engine.GetRegistry().emplace(player, 400.0f, 300.0f, 1.0f, 1.0f, 0.0f); + // + // auto& inputComponent = engine.GetRegistry().emplace(player); + // + // inputComponent.BindKey(InputAction::MOVE_UP, KEY_W); + // inputComponent.BindKey(InputAction::MOVE_DOWN, KEY_S); + // inputComponent.BindKey(InputAction::MOVE_LEFT, KEY_A); + // inputComponent.BindKey(InputAction::MOVE_RIGHT, KEY_D); + // + // inputComponent.SetActionCallback(InputAction::MOVE_UP, [&]() { + // auto& transform = engine.GetRegistry().get(player); + // transform.y -= 5.0f; + // }); + // inputComponent.SetActionCallback(InputAction::MOVE_DOWN, [&]() { + // auto& transform = engine.GetRegistry().get(player); + // transform.y += 5.0f; + // }); + // inputComponent.SetActionCallback(InputAction::MOVE_LEFT, [&]() { + // auto& transform = engine.GetRegistry().get(player); + // transform.x -= 5.0f; + // }); + // inputComponent.SetActionCallback(InputAction::MOVE_RIGHT, [&]() { + // auto& transform = engine.GetRegistry().get(player); + // transform.x += 5.0f; + // }); diff --git a/src/FatalHandler.h b/src/FatalHandler.h index 163049b..7549b4c 100644 --- a/src/FatalHandler.h +++ b/src/FatalHandler.h @@ -5,4 +5,15 @@ #ifndef FATALHANDLER_H #define FATALHANDLER_H +#include + + +// TODO: Implement warning popup/crash handler (platform specific) +// TODO: Separate fatal handlers for core (the engine) and app (the user's app) +// maybe let the user handle their own fatal errors if they so choose, or they can use the default? similar +// to how the user has to specify an engine application +namespace IsoEngine { + void FatalHandler(const std::string& message); +}; + #endif //FATALHANDLER_H diff --git a/src/IsoEngine.cpp b/src/IsoEngine.cpp index 749b20d..d614c61 100644 --- a/src/IsoEngine.cpp +++ b/src/IsoEngine.cpp @@ -1,4 +1,7 @@ #include "IsoEngine.h" + +#include + #include "components.h" #include @@ -16,8 +19,9 @@ void IsoEngine::Initialize() { if (network) { network->Initialize(); } - - std::cout << "Engine initialized." << std::endl; + Logger::GetCoreLogger().AddOutputStream(&std::cout); + Logger::GetAppLogger().AddOutputStream(&std::cout); + CORE_LOG_INFO("Engine initialized!"); } void IsoEngine::Run() { @@ -39,7 +43,7 @@ void IsoEngine::Shutdown() { network->Shutdown(); } - std::cout << "Engine shut down." << std::endl; + CORE_LOG_INFO("Engine shut down"); } void IsoEngine::Update() { diff --git a/src/IsoEnginePCH.h b/src/IsoEnginePCH.h index 87ca935..72b2481 100644 --- a/src/IsoEnginePCH.h +++ b/src/IsoEnginePCH.h @@ -22,6 +22,7 @@ #include #include #include +#include #endif //ISOENGINEPCH_H diff --git a/src/enet_client.cpp b/src/enet_client.cpp index 5e67b9e..c3173ce 100644 --- a/src/enet_client.cpp +++ b/src/enet_client.cpp @@ -7,17 +7,15 @@ public: ENetClient() : client(nullptr), peer(nullptr) {} void Initialize() override { - Logger& logger = Logger::GetInstance(); - if (enet_initialize() != 0) { - logger.LogError("An error occurred while initializing ENet.", "ENetClient"); - exit(EXIT_FAILURE); + CORE_LOG_FATAL("An error occurred while initializing ENet"); + throw std::runtime_error("An error occurred while initializing ENet"); } client = enet_host_create(nullptr, 1, 2, 0, 0); if (!client) { - logger.LogError("An error occurred while creating the ENet client.", "ENetClient"); - exit(EXIT_FAILURE); + CORE_LOG_FATAL("An error occurred while creating the ENet client"); + throw std::runtime_error("An error occurred while initializing ENet Client"); } ENetAddress address; @@ -26,42 +24,35 @@ public: peer = enet_host_connect(client, &address, 2, 0); if (!peer) { - logger.LogError("No available peers for initiating connection.", "ENetClient"); - exit(EXIT_FAILURE); + CORE_LOG_ERROR("No available peers for initiating connection"); } - logger.LogInfo("ENet client initialized and connected to server.", "ENetClient"); + CORE_LOG_TRACE("ENet client initialized and connected to server"); } void Shutdown() override { - Logger& logger = Logger::GetInstance(); - if (peer) { enet_peer_disconnect(peer, 0); - logger.LogInfo("Disconnected from peer.", "ENetClient"); + CORE_LOG_TRACE("Disconnected from peer"); } enet_host_destroy(client); enet_deinitialize(); - logger.LogInfo("ENet client shut down.", "ENetClient"); + CORE_LOG_TRACE("ENet client shut down"); } void SendData(const void* data, size_t size) override { - Logger& logger = Logger::GetInstance(); - if (peer) { ENetPacket* packet = enet_packet_create(data, size, ENET_PACKET_FLAG_RELIABLE); enet_peer_send(peer, 0, packet); - logger.LogDebug("Data sent to server.", "ENetClient"); + CORE_LOG_TRACE("Data sent to server"); } } void ReceiveData() override { - Logger& logger = Logger::GetInstance(); - ENetEvent event; while (enet_host_service(client, &event, 0) > 0) { if (event.type == ENET_EVENT_TYPE_RECEIVE) { - logger.LogInfo("Received packet: " + std::string(reinterpret_cast(event.packet->data)), "ENetClient"); + CORE_LOG_TRACE("Received packet: {}", std::string(reinterpret_cast(event.packet->data))); enet_packet_destroy(event.packet); } } diff --git a/src/filepacker.cpp b/src/filepacker.cpp index 45ef59f..22c4aab 100644 --- a/src/filepacker.cpp +++ b/src/filepacker.cpp @@ -11,7 +11,7 @@ bool FilePacker::Pack(const std::string &directoryPath, const std::string &outpu std::ofstream outputFile(outputBapFile, std::ios::binary); if (!outputFile) { - Logger::GetInstance().LogError("FilePacker::Pack(): Failed to open output file."); + CORE_LOG_ERROR("Failed to open output file"); return false; } @@ -33,7 +33,7 @@ bool FilePacker::Pack(const std::string &directoryPath, const std::string &outpu std::ifstream inputFile(entry.path(), std::ios::binary | std::ios::ate); if (!inputFile) { - Logger::GetInstance().LogError("FilePacker::Pack(): Failed to open file for packing: " + entry.path().string()); + CORE_LOG_ERROR("FilePacker::Pack(): Failed to open file for packing: {}", entry.path().string()); return false; } fileEntry.dataSize = inputFile.tellg(); @@ -75,7 +75,7 @@ bool FilePacker::Pack(const std::string &directoryPath, const std::string &outpu std::vector FilePacker::listFiles(const std::string& bapFile) { std::ifstream inputFile(bapFile, std::ios::binary); if (!inputFile) { - Logger::GetInstance().LogCritical("Failed to open .bap file for listing: " + bapFile); + CORE_LOG_FATAL("Failed to open .bap file for listing: {}", bapFile); throw std::runtime_error("File could not be opened"); } @@ -87,7 +87,7 @@ std::vector FilePacker::listFiles(const std::string& bapFile) { bool FilePacker::ExtractFile(const std::string& bapFile, const std::string& fileName, const std::string& outputPath) { std::ifstream inputFile(bapFile, std::ios::binary); if (!inputFile) { - Logger::GetInstance().LogError("Failed to open .bap file for extraction: " + bapFile); + CORE_LOG_ERROR("Failed to open .bap file for extraction: {}", bapFile); return false; } @@ -96,7 +96,7 @@ bool FilePacker::ExtractFile(const std::string& bapFile, const std::string& file if (fileEntry.filePath == fileName) { std::ofstream outFile(outputPath, std::ios::binary); if (!outFile) { - Logger::GetInstance().LogError("Failed to create output file: " + outputPath); + CORE_LOG_ERROR("Failed to create output file: {}", outputPath); return false; } @@ -110,7 +110,7 @@ bool FilePacker::ExtractFile(const std::string& bapFile, const std::string& file } } - Logger::GetInstance().LogError("File not found in .bap archive: " + fileName); + CORE_LOG_ERROR("File not found in .bap archive: {}", fileName); return false; } @@ -143,7 +143,7 @@ BapHeader FilePacker::ReadHeader(std::ifstream& inFile) { inFile.read(reinterpret_cast(&header.fileCount), sizeof(header.fileCount)); if (header.version != PACKER_VERSION) { - Logger::GetInstance().LogCritical("FilePacker::ReadHeader(): Wrong .bap file version."); + CORE_LOG_FATAL("FilePacker::ReadHeader(): Wrong .bap file version."); throw std::runtime_error("Invalid bap file version"); } diff --git a/src/platform/posix/FatalHandlerPosix.cpp b/src/platform/posix/FatalHandlerPosix.cpp index ade1e26..c50c262 100644 --- a/src/platform/posix/FatalHandlerPosix.cpp +++ b/src/platform/posix/FatalHandlerPosix.cpp @@ -8,22 +8,31 @@ #include #include #include +#include -void FatalHandler(const std::string& message) { - std::ofstream crashFile("crash.log", std::ios::app); - crashFile << "FATAL ERROR: " << message << std::endl; +namespace IsoEngine { - void* callstack[128]; - int frames = backtrace(callstack, 128); - char** symbols = backtrace_symbols(callstack, frames); + template + void FatalHandler(const std::string& format, Args... args) { + std::ostringstream stream; + stream << std::format(format, args...); - crashFile << "Stack trace:\n"; - for (int i = 0; i < frames; ++i) { - crashFile << symbols[i] << std::endl; + // TODO: change the name of the file to reflect the time the crash happened + std::ofstream crashFile("crash.log", std::ios::app); + crashFile << "FATAL ERROR: " << stream.str() << std::endl; + + void* callstack[128]; + int frames = backtrace(callstack, 128); + char** symbols = backtrace_symbols(callstack, frames); + + crashFile << "Stack trace:\n"; + for (int i = 0; i < frames; ++i) { + crashFile << symbols[i] << std::endl; + } + + free(symbols); + crashFile.close(); + + std::abort(); } - - free(symbols); - crashFile.close(); - - std::abort(); -} \ No newline at end of file +} diff --git a/src/platform/windows/FatalHandlerWindows.cpp b/src/platform/windows/FatalHandlerWindows.cpp index e75f4dc..1c4fa28 100644 --- a/src/platform/windows/FatalHandlerWindows.cpp +++ b/src/platform/windows/FatalHandlerWindows.cpp @@ -7,50 +7,58 @@ #include #include #include +#include #pragma comment(lib, "dbghelp.lib") -void FatalHandler(const std::string& message) { - std::ofstream crashFile("crash.log", std::ios::app); - crashFile << "FATAL ERROR: " << message << std::endl; +namespace IsoEngine { + template + void FatalHandler(const std::string &format, Args... args) { + std::ostringstream stream; + stream << std::format(format, args...); - HANDLE process = GetCurrentProcess(); - SymInitialize(process, NULL, TRUE); + // TODO: change the name of the file to reflect the time the crash happened + std::ofstream crashFile("crash.log", std::ios::app); + crashFile << "FATAL ERROR: " << stream.str() << std::endl; - CONTEXT context; - RtlCaptureContext(&context); + HANDLE process = GetCurrentProcess(); + SymInitialize(process, NULL, TRUE); - STACKFRAME64 stackFrame = {}; - stackFrame.AddrPC.Offset = context.Rip; - stackFrame.AddrPC.Mode = AddrModeFlat; - stackFrame.AddrFrame.Offset = context.Rbp; - stackFrame.AddrFrame.Mode = AddrModeFlat; - stackFrame.AddrStack.Offset = context.Rsp; - stackFrame.AddrStack.Mode = AddrModeFlat; + CONTEXT context; + RtlCaptureContext(&context); - crashFile << "Stack trace:\n"; + STACKFRAME64 stackFrame = {}; + stackFrame.AddrPC.Offset = context.Rip; + stackFrame.AddrPC.Mode = AddrModeFlat; + stackFrame.AddrFrame.Offset = context.Rbp; + stackFrame.AddrFrame.Mode = AddrModeFlat; + stackFrame.AddrStack.Offset = context.Rsp; + stackFrame.AddrStack.Mode = AddrModeFlat; - while (StackWalk64(IMAGE_FILE_MACHINE_AMD64, process, GetCurrentThread(), &stackFrame, &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) { - DWORD64 address = stackFrame.AddrPC.Offset; - if (address == 0) { - break; + crashFile << "Stack trace:\n"; + while (StackWalk64(IMAGE_FILE_MACHINE_AMD64, process, GetCurrentThread(), &stackFrame, &context, NULL, + SymFunctionTableAccess64, SymGetModuleBase64, NULL)) { + DWORD64 address = stackFrame.AddrPC.Offset; + if (address == 0) { + break; + } + + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO symbol = (PSYMBOL_INFO) buffer; + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + symbol->MaxNameLen = MAX_SYM_NAME; + + DWORD64 displacement = 0; + if (SymFromAddr(process, address, &displacement, symbol)) { + crashFile << symbol->Name << " - 0x" << std::hex << symbol->Address << std::dec << "\n"; + } else { + crashFile << "Unresolved symbol at address: 0x" << std::hex << address << std::dec << "\n"; + } } - char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; - PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; - symbol->SizeOfStruct = sizeof(SYMBOL_INFO); - symbol->MaxNameLen = MAX_SYM_NAME; + SymCleanup(process); + crashFile.close(); - DWORD64 displacement = 0; - if (SymFromAddr(process, address, &displacement, symbol)) { - crashFile << symbol->Name << " - 0x" << std::hex << symbol->Address << std::dec << "\n"; - } else { - crashFile << "Unresolved symbol at address: 0x" << std::hex << address << std::dec << "\n"; - } + std::abort(); } - - SymCleanup(process); - crashFile.close(); - - std::abort(); -} \ No newline at end of file +}