From e7d5cf920e6aa9e067bbec40734c5e6a568819e2 Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Sun, 5 Oct 2025 14:25:01 +0700 Subject: [PATCH 01/19] Move destroy window and glfw to CoreInstnace from render engine --- Core/Core/CoreInstance.cpp | 17 ++++++++++++----- Core/Core/RenderEngine.cpp | 4 ---- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Core/Core/CoreInstance.cpp b/Core/Core/CoreInstance.cpp index e6fb345..fdb8fe0 100644 --- a/Core/Core/CoreInstance.cpp +++ b/Core/Core/CoreInstance.cpp @@ -63,14 +63,18 @@ CoreInstance::CoreInstance() window_ = glfwCreateWindow(800, 600, main_config_.game_name.c_str(), nullptr, nullptr); if (window_ == nullptr) { - glfwTerminate(); - throw std::runtime_error("Fail create window"); + std::cout << "[!] Init render engine: Fail create window\n"; + return; + } + try { + render_engine_ = new RenderEngine(*this, window_); + } catch (const std::exception& e) + { + std::cout << "[!] Init render engine: " << e.what() << '\n'; + throw; } - render_engine_ = new RenderEngine(*this, window_); game_ = GameFactory(*this); - if (game_ == nullptr) - throw std::runtime_error("Fail create game instance!"); } CoreInstance::~CoreInstance() @@ -81,6 +85,9 @@ CoreInstance::~CoreInstance() delete render_engine_; delete game_; + + glfwDestroyWindow(window_); + glfwTerminate(); } void CoreInstance::start() diff --git a/Core/Core/RenderEngine.cpp b/Core/Core/RenderEngine.cpp index d4c4d5c..ccc8ec1 100644 --- a/Core/Core/RenderEngine.cpp +++ b/Core/Core/RenderEngine.cpp @@ -972,10 +972,6 @@ RenderEngine::~RenderEngine() if (instance_ != VK_NULL_HANDLE) vkDestroyInstance(instance_, nullptr); - - if (window_ != nullptr) - glfwDestroyWindow(window_); - glfwTerminate(); } void RenderEngine::start() From bd8b0aec96ec43d3cf91a7b83625a12e50e0fc41 Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Sun, 5 Oct 2025 14:28:39 +0700 Subject: [PATCH 02/19] Fix validate create instance --- Core/Core/CoreInstance.cpp | 14 +++++++++++--- Core/Core/CoreInstance.h | 5 ++++- Core/Core/main.cpp | 2 ++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Core/Core/CoreInstance.cpp b/Core/Core/CoreInstance.cpp index fdb8fe0..9f5ae64 100644 --- a/Core/Core/CoreInstance.cpp +++ b/Core/Core/CoreInstance.cpp @@ -71,10 +71,18 @@ CoreInstance::CoreInstance() } catch (const std::exception& e) { std::cout << "[!] Init render engine: " << e.what() << '\n'; - throw; + return; } - - game_ = GameFactory(*this); + + try + { + game_ = GameFactory(*this); + } catch (const std::exception& e) + { + std::cout << "[!] Init game instance: " << e.what() << '\n'; + return; + } + is_ready = true; } CoreInstance::~CoreInstance() diff --git a/Core/Core/CoreInstance.h b/Core/Core/CoreInstance.h index 43ee59f..fbd793c 100644 --- a/Core/Core/CoreInstance.h +++ b/Core/Core/CoreInstance.h @@ -47,6 +47,8 @@ class CoreInstance { static CoreInstance* self; CoreCallBacks callbacks_; + bool is_ready = false; + #pragma region Callbacks static void Quit_callback(); #pragma endregion @@ -56,7 +58,8 @@ public: void start(); void quit(); - + + bool IsReady() const { return is_ready; } int getCountCPU() const { return countCPU_; } double getMemorySize() const { return memorySize_; } const std::string& getBaseWorldName() const { return main_config_.base_world; } diff --git a/Core/Core/main.cpp b/Core/Core/main.cpp index e456cd3..3ac734d 100644 --- a/Core/Core/main.cpp +++ b/Core/Core/main.cpp @@ -5,6 +5,8 @@ int main(int argc, char* argv[]) { try { CoreInstance core; + if (core.IsReady() == false) + return 0; std::cout << "CPU: " << core.getCountCPU() << std::endl; std::cout << "Memory: " << core.getMemorySize() << std::endl; core.start(); From bb48fb6dfbb3574250eae70350b03ed591d551b0 Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Tue, 7 Oct 2025 20:12:10 +0700 Subject: [PATCH 03/19] Move load config for world to factory --- Core/Game/GameInstance.cpp | 8 -------- Core/Game/WorldFactory.h | 15 ++++++++++++++- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/Core/Game/GameInstance.cpp b/Core/Game/GameInstance.cpp index 43c5f37..9a61a4b 100644 --- a/Core/Game/GameInstance.cpp +++ b/Core/Game/GameInstance.cpp @@ -19,13 +19,6 @@ GameInstance::GameInstance(CoreInstance& core) : core(core) // Init directories std::filesystem::create_directories(std::filesystem::path("./Resources")); - std::ifstream file("./Worlds/" + base_world + ".world"); - if (file.fail()) - throw std::runtime_error("Can't open world file"); - - std::string data; - std::getline(file, data); - for (auto& factories : world_factories) { if (factories.world_name == base_world) @@ -38,7 +31,6 @@ GameInstance::GameInstance(CoreInstance& core) : core(core) if (world == nullptr) throw std::runtime_error("Can't find world"); - world->load(std::make_shared(data)); } GameInstance::~GameInstance() diff --git a/Core/Game/WorldFactory.h b/Core/Game/WorldFactory.h index 9f29920..29e7dbb 100644 --- a/Core/Game/WorldFactory.h +++ b/Core/Game/WorldFactory.h @@ -1,6 +1,9 @@ #pragma once #include +#include +#include +#include "Game/SaveMap/SaveMap.h" class GameInstance; class World; @@ -16,7 +19,17 @@ struct WorldFactory #define WORLDS_LIST std::vector world_factories = // Генерирует элемент списка -#define GENERATE_WORLD_FACTORY(Class, WorldName) WorldFactory{#WorldName, [](GameInstance& game_insance)->World* { return new Class(game_insance); }}, +#define GENERATE_WORLD_FACTORY(Class, WorldName) WorldFactory{#WorldName,\ +[](GameInstance& game_insance)->World* {\ + Class* world = new Class(game_insance);\ + std::ifstream config_file("./Worlds/" #WorldName ".world");\ + if (config_file.fail())\ + throw std::runtime_error("Can't open world file");\ + std::string data;\ + std::getline(config_file, data);\ + world->load(std::make_shared(data));\ + return world;\ +}}, /* * Пример использования: From d5261561ed0de455775cc873f75163131b4ccb72 Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Tue, 7 Oct 2025 21:07:54 +0700 Subject: [PATCH 04/19] Remove old module system --- CMakeLists.txt | 1 - Core/Core/CoreInstance.cpp | 76 ++---------------------------- Core/Core/CoreInstance.h | 25 ---------- Core/Core/SystemCalls.h | 19 -------- Core/Core/Windows/WindowsCalls.cpp | 34 ------------- Core/Game/GameInstance.h | 2 + ModuleLib/CMakeLists.txt | 14 ------ ModuleLib/ModuleInstance.cpp | 57 ---------------------- ModuleLib/ModuleInstance.h | 47 ------------------ TestGame/main_config.conf | 2 +- 10 files changed, 6 insertions(+), 271 deletions(-) delete mode 100644 ModuleLib/CMakeLists.txt delete mode 100644 ModuleLib/ModuleInstance.cpp delete mode 100644 ModuleLib/ModuleInstance.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d6e0a6..93282a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,5 @@ endif() add_subdirectory(FastRTTI) add_subdirectory(glfw) add_subdirectory(Core) -add_subdirectory(ModuleLib) add_subdirectory(TestGame) add_subdirectory(ProjectGenerator) diff --git a/Core/Core/CoreInstance.cpp b/Core/Core/CoreInstance.cpp index 9f5ae64..cbe0ceb 100644 --- a/Core/Core/CoreInstance.cpp +++ b/Core/Core/CoreInstance.cpp @@ -13,8 +13,6 @@ #include "Log/Log.h" #include "Game/SaveMap/SaveMap.h" -CoreInstance* CoreInstance::self = nullptr; - extern GameInstance* GameFactory(CoreInstance&); std::shared_ptr CoreInstance::MainConfig::save() @@ -31,17 +29,8 @@ void CoreInstance::MainConfig::load(std::shared_ptr save) min_CPU_count = save->GetInteger("min_CPU_count"); } -void CoreInstance::Quit_callback() -{ - self->game_->quit(); -} - CoreInstance::CoreInstance() { - self = this; - - callbacks_.Quit = &Quit_callback; - countCPU_ = System::getCountCPU(); memorySize_ = System::getMemorySize(); @@ -87,8 +76,6 @@ CoreInstance::CoreInstance() CoreInstance::~CoreInstance() { - for (auto& module : modules_) - System::QuitModule(module.handler); modules_.clear(); delete render_engine_; @@ -100,31 +87,11 @@ CoreInstance::~CoreInstance() void CoreInstance::start() { - for (auto& name : main_config_.modules_names) - { - try - { - void* handler = System::InitModule(name.c_str(), &callbacks_); - modules_.push_back(Module {name.c_str(), handler}); - } catch (const std::exception& e) - { - std::cout << e.what() << '\n'; - } - } - - for (auto& module : modules_) - { - try - { - System::StartModule(module.handler); - } catch (const std::exception& e) - { - std::cout << e.what() << '\n'; - } - } - std::thread game_thread(&GameInstance::start, game_); + + // Main thread is render render_engine_->start(); + game_->stop(); game_thread.join(); } @@ -135,40 +102,3 @@ void CoreInstance::quit() render_engine_->stop_render(); } -void* CoreInstance::getHandlerModule(const char* name) const -{ - for (const auto& module : modules_) - { - if (std::strcmp(module.name, name) == 0) - return module.handler; - } - throw std::runtime_error("Module not found"); -} - -void* CoreInstance::enableModule(const char* name) -{ - for (const auto& module : modules_) - { - if (std::strcmp(module.name, name) == 0) - throw std::runtime_error("Module already enabled"); - } - - void* module = System::InitModule(name, &callbacks_); - modules_.push_back({ name, module }); - return module; -} - -void CoreInstance::disableModule(const char* name) -{ - for (auto i = modules_.cbegin(); i != modules_.cend(); ++i) - { - if (std::strcmp(i->name, name) == 0) - { - System::QuitModule(i->handler); - modules_.erase(i); - break; - } - } - - throw std::runtime_error("Module not found"); -} diff --git a/Core/Core/CoreInstance.h b/Core/Core/CoreInstance.h index fbd793c..c6add8e 100644 --- a/Core/Core/CoreInstance.h +++ b/Core/Core/CoreInstance.h @@ -44,14 +44,8 @@ class CoreInstance { RenderEngine* render_engine_; GameInstance* game_; - static CoreInstance* self; - CoreCallBacks callbacks_; bool is_ready = false; - -#pragma region Callbacks - static void Quit_callback(); -#pragma endregion public: CoreInstance(); ~CoreInstance(); @@ -64,23 +58,4 @@ public: double getMemorySize() const { return memorySize_; } const std::string& getBaseWorldName() const { return main_config_.base_world; } const std::string& getGameName() const { return main_config_.game_name; } - - /** - * @throws std::runtime_error if module isn't enabled - * @throws std::runtime_error if module not found - * @return module handler - */ - void* getHandlerModule(const char* name) const noexcept(false); - /** - * @throws std::runtime_error if the module already enabled - * @throws std::runtime_error if the module isn't found - * @throws std::runtime_error if the module doesn't contain InitModule or StartModule - * @retuen module handler - */ - void* enableModule(const char* name) noexcept(false); - /** - * @throws std::runtime_error if the module isn't found - * @throws std::runtime_error module isn't contain QuitModule function - */ - void disableModule(const char* name) noexcept(false); }; diff --git a/Core/Core/SystemCalls.h b/Core/Core/SystemCalls.h index 2a7f8e2..4bfbaac 100644 --- a/Core/Core/SystemCalls.h +++ b/Core/Core/SystemCalls.h @@ -15,23 +15,4 @@ namespace System { * @return memory size in MB */ double getMemorySize(); - - /** - * Load module and init handler - * @throws std::runtime_error if module not found - * @return module handler - */ - void* InitModule(const char* ModuleName, CoreCallBacks* callbacks); - - /** - * Start module - * @throws std::runtime_error if module not contains StartModule function - */ - void StartModule(void* handler) noexcept(false); - - /** - * Call stop module - * @throws std::runtime_error if module not contains QuitModule function - */ - void QuitModule(void* handler) noexcept(false); } diff --git a/Core/Core/Windows/WindowsCalls.cpp b/Core/Core/Windows/WindowsCalls.cpp index ad05a22..e735662 100644 --- a/Core/Core/Windows/WindowsCalls.cpp +++ b/Core/Core/Windows/WindowsCalls.cpp @@ -41,38 +41,4 @@ double System::getMemorySize() { return static_cast(memStatus.ullTotalPhys) / 1024. / 1024.; } -void* System::InitModule(const char* ModuleName, CoreCallBacks* callbacks) { - std::string fileName = ModuleName; - fileName += ".dll"; - - HMODULE hModule = LoadLibraryA(fileName.c_str()); - if(hModule == nullptr) - throw std::runtime_error(std::to_string(GetLastError()).c_str()); - - void(*load)(CoreCallBacks*) = reinterpret_cast(GetProcAddress(hModule, "InitModule")); - if(load == nullptr) { - throw std::runtime_error(std::to_string(GetLastError()).c_str()); - } - load(callbacks); - - return hModule; -} - -void System::StartModule(void* handler) { - void(*start)() = reinterpret_cast(GetProcAddress(static_cast(handler), "StartModule")); - if(start == nullptr) { - throw std::runtime_error(std::to_string(GetLastError()).c_str()); - } - start(); -} - -void System::QuitModule(void* handler) { - void(*quit)() = reinterpret_cast(GetProcAddress(static_cast(handler), "QuitModule")); - if(quit == nullptr) { - throw std::runtime_error(std::to_string(GetLastError()).c_str()); - } - quit(); - FreeLibrary(static_cast(handler)); -} - #endif \ No newline at end of file diff --git a/Core/Game/GameInstance.h b/Core/Game/GameInstance.h index 3da336a..ac26b8c 100644 --- a/Core/Game/GameInstance.h +++ b/Core/Game/GameInstance.h @@ -17,8 +17,10 @@ class GameInstance std::atomic is_running = true; void start(); + // Stop call from core void stop(); public: + // Stop call from game void quit(); // Init vulkan diff --git a/ModuleLib/CMakeLists.txt b/ModuleLib/CMakeLists.txt deleted file mode 100644 index 37f27f8..0000000 --- a/ModuleLib/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -set(MODULE_LIB_NAME ModuleLib) - -file(GLOB_RECURSE SRC "*.cpp" "*.c" "*.h" "*.hpp") - -add_library(${MODULE_LIB_NAME} STATIC ${SRC}) - -target_include_directories(${MODULE_LIB_NAME} PRIVATE - ${PROJECT_SOURCE_DIR}/Core - ${PROJECT_SOURCE_DIR}/Delegate -) - -if(UNIX AND NOT APPLE) - target_compile_options(${MODULE_LIB_NAME} PRIVATE -fPIC) -endif() diff --git a/ModuleLib/ModuleInstance.cpp b/ModuleLib/ModuleInstance.cpp deleted file mode 100644 index 0de6931..0000000 --- a/ModuleLib/ModuleInstance.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "ModuleInstance.h" - -#include -#include - -#include "Core/CoreCallBacks.h" - -extern ModuleInstance* Factory(); - -static std::mutex mModuleInstance; -static ModuleInstance* module = nullptr; -static std::thread* moduleThread; -// Don't free. It's memory free in core -static CoreCallBacks* callbacks_; - -void ModuleInstance::start() -{ -} - -void ModuleInstance::stop() -{ - onStop.Call(); -} - -void ModuleInstance::QuitGame() -{ - callbacks_->Quit(); -} - -void InitModule(CoreCallBacks* callbacks) -{ - std::lock_guard lock(mModuleInstance); - callbacks_ = callbacks; - if(module == nullptr) - module = Factory(); -} - -void StartModule() -{ - std::lock_guard lock(mModuleInstance); - if (module != nullptr) - moduleThread = new std::thread(&ModuleInstance::start, module); -} - -void QuitModule() -{ - std::lock_guard lock(mModuleInstance); - if(module != nullptr) - { - module->stop(); - moduleThread->join(); - delete module; - module = nullptr; - delete moduleThread; - moduleThread = nullptr; - } -} diff --git a/ModuleLib/ModuleInstance.h b/ModuleLib/ModuleInstance.h deleted file mode 100644 index fc53ca6..0000000 --- a/ModuleLib/ModuleInstance.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include "Delegate/Delegate.h" - -#ifdef _WIN32 -#define EXPORT __declspec(dllexport) -#elif __linux__ -#define EXPORT -#else -#error message("Unknow platform") -#endif -/* -* This macro protects -* module callbacks from GB -*/ -#define PROTECTION_FROM_GB(Class) \ -extern "C" {\ -EXPORT void* protect_init() {return reinterpret_cast(&InitModule);} \ -EXPORT void* protect_start() {return reinterpret_cast(&StartModule);} \ -EXPORT void* protect_quit() {return reinterpret_cast(&QuitModule);} \ -}\ -ModuleInstance* Factory() { return static_cast(new Class()); } - -struct CoreCallBacks; - -class ModuleInstance { -public: - Delegate onStop; - - virtual ~ModuleInstance() = default; - - virtual void start(); - void stop(); - - void QuitGame(); -}; - -extern "C" { - // Create module instance - EXPORT void InitModule(CoreCallBacks* callbacks); - - // Start module instance - EXPORT void StartModule(); - - // Stop module when core calls this - EXPORT void QuitModule(); -} diff --git a/TestGame/main_config.conf b/TestGame/main_config.conf index a51e392..1edecc2 100644 --- a/TestGame/main_config.conf +++ b/TestGame/main_config.conf @@ -1 +1 @@ -{"Class name":"MainConfig","dmin_memory_size":"4096.0","imin_CPU_count":"1","sgame_name":"Test Game","sbase_world":"TestWorld","vsmodules_names":[]} \ No newline at end of file +{"Class name":"MainConfig","dmin_memory_size":"4096.0","imin_CPU_count":"1","sgame_name":"Test Game","sbase_world":"TestWorld"} \ No newline at end of file From 2b2ed1f050dc1ba6295ae81aa1ae97e45c5101ca Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Tue, 7 Oct 2025 21:18:11 +0700 Subject: [PATCH 05/19] Clear code --- Core/Core/RenderEngine.cpp | 10 ++++++++++ Core/Core/RenderEngine.h | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/Core/Core/RenderEngine.cpp b/Core/Core/RenderEngine.cpp index ccc8ec1..35cd6e9 100644 --- a/Core/Core/RenderEngine.cpp +++ b/Core/Core/RenderEngine.cpp @@ -78,10 +78,13 @@ VkVertexInputBindingDescription RenderEngine::Vertex::get_binding_description() std::array RenderEngine::Vertex::get_vertex_attribute_descriptions() { std::array descriptions; + // Bind vertex loc descriptions[0].binding = 0; descriptions[0].location = 0; descriptions[0].format = VK_FORMAT_R32G32_SFLOAT; descriptions[0].offset = offsetof(Vertex, pos); + + // Bind color descriptions[1].binding = 0; descriptions[1].location = 1; descriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT; @@ -98,6 +101,7 @@ bool RenderEngine::is_device_suitable(VkPhysicalDevice device, VkSurfaceKHR surf vkGetPhysicalDeviceFeatures(device, &device_features); try { + // Ловить исключения имеет смысыл только здесь QueueFamilyIndices indices = find_queue_family_indices(device, surface); } catch (...) { return false; @@ -155,8 +159,10 @@ RenderEngine::QueueFamilyIndices RenderEngine::find_queue_family_indices(VkPhysi // Find present VkBool32 present_support = false; VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, queue_family_indices.graphics_family.value(), surface, &present_support)); + // Если графическая очередь поддерживет презентацию кадров, то используем её if (present_support == VK_TRUE) queue_family_indices.present_family = queue_family_indices.graphics_family; + // иначе ищем другую подходящую очередь else { for(uint32_t i = 0; i < family_properties.size(); ++i) @@ -174,6 +180,8 @@ RenderEngine::QueueFamilyIndices RenderEngine::find_queue_family_indices(VkPhysi if (queue_family_indices.present_family.has_value() == false) throw std::runtime_error("Failed to find a present queue family"); + // С начала пытаемся найти очередь специалезированную + // для копирования отличную от графической for(uint32_t i = 0; i < family_properties.size(); ++i) { if (i == queue_family_indices.graphics_family.value()) @@ -181,6 +189,7 @@ RenderEngine::QueueFamilyIndices RenderEngine::find_queue_family_indices(VkPhysi if (family_properties[i].queueFlags & VK_QUEUE_TRANSFER_BIT) queue_family_indices.transfer_family = i; } + // Если не находим, то используем графическую if (queue_family_indices.transfer_family.has_value() == false) queue_family_indices.transfer_family = queue_family_indices.graphics_family; return queue_family_indices; @@ -208,6 +217,7 @@ VkPresentModeKHR RenderEngine::choose_present_mode(const std::vector::max()) return capabilities.currentExtent; else diff --git a/Core/Core/RenderEngine.h b/Core/Core/RenderEngine.h index cdef903..c7d5f32 100644 --- a/Core/Core/RenderEngine.h +++ b/Core/Core/RenderEngine.h @@ -60,7 +60,9 @@ class RenderEngine int current_frame_ = 0; CoreInstance& core_; + GLFWwindow* window_; + VkInstance instance_ = VK_NULL_HANDLE; VkSurfaceKHR surface_ = VK_NULL_HANDLE; VkPhysicalDevice physical_device_ = VK_NULL_HANDLE; @@ -80,6 +82,7 @@ class RenderEngine VkCommandPool command_pool_ = VK_NULL_HANDLE; std::vector command_buffers_; + // Sync objects std::vector image_available_semaphores_, render_finished_semaphores_; std::vector in_flight_fences_; @@ -123,4 +126,6 @@ public: void start(); void stop_render() const; + + GLFWwindow* get_window() const { return window_; } }; \ No newline at end of file From fedffa763424e6df221c57e02a10b5960d71015d Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Fri, 10 Oct 2025 19:39:30 +0700 Subject: [PATCH 06/19] Add classes Mesh and StaticMesh --- Core/Core/CoreInstance.h | 2 +- Core/Core/RenderEngine.cpp | 9 +++++++++ Core/Game/Actors/Actor.cpp | 15 +++++++-------- Core/Game/Actors/Actor.h | 5 ++--- Core/Game/Actors/Mesh/Mesh.cpp | 21 +++++++++++++++++++++ Core/Game/Actors/Mesh/Mesh.hpp | 24 ++++++++++++++++++++++++ Core/Game/Actors/Mesh/StaticMesh.cpp | 26 ++++++++++++++++++++++++++ Core/Game/Actors/Mesh/StaticMesh.hpp | 17 +++++++++++++++++ Core/Game/BaseObjectFactory.cpp | 2 ++ Core/Game/SaveMap/SaveMap.cpp | 4 ++-- Core/Game/SaveMap/SaveMap.h | 2 +- Core/Game/World/World.h | 7 ++++--- FastRTTI/RTTI_Meta.h | 2 +- TestGame/Worlds/TestWorld.world | 2 +- 14 files changed, 118 insertions(+), 20 deletions(-) create mode 100644 Core/Game/Actors/Mesh/Mesh.cpp create mode 100644 Core/Game/Actors/Mesh/Mesh.hpp create mode 100644 Core/Game/Actors/Mesh/StaticMesh.cpp create mode 100644 Core/Game/Actors/Mesh/StaticMesh.hpp diff --git a/Core/Core/CoreInstance.h b/Core/Core/CoreInstance.h index c6add8e..8e13676 100644 --- a/Core/Core/CoreInstance.h +++ b/Core/Core/CoreInstance.h @@ -44,7 +44,6 @@ class CoreInstance { RenderEngine* render_engine_; GameInstance* game_; - bool is_ready = false; public: CoreInstance(); @@ -58,4 +57,5 @@ public: double getMemorySize() const { return memorySize_; } const std::string& getBaseWorldName() const { return main_config_.base_world; } const std::string& getGameName() const { return main_config_.game_name; } + GameInstance* GetGameInstance() const { return game_; } }; diff --git a/Core/Core/RenderEngine.cpp b/Core/Core/RenderEngine.cpp index 35cd6e9..753a3e1 100644 --- a/Core/Core/RenderEngine.cpp +++ b/Core/Core/RenderEngine.cpp @@ -8,6 +8,10 @@ #include "CoreInstance.h" #include "Log/Log.h" +#include "Game/GameInstance.h" +#include "Game/World/World.h" +#include "Game/Actors/Mesh/Mesh.hpp" + #include "GLFW/glfw3.h" const std::vector RenderEngine::deviceExtensions = { @@ -986,6 +990,11 @@ RenderEngine::~RenderEngine() void RenderEngine::start() { + World* world = core_.GetGameInstance()->GetWorld(); + std::vector meshes = world->GetActorsByClass(); + for (auto& i : meshes) + i->load_model(i->GetModelName()); + while (!glfwWindowShouldClose(window_)) { glfwPollEvents(); diff --git a/Core/Game/Actors/Actor.cpp b/Core/Game/Actors/Actor.cpp index 99d7f43..4781b32 100644 --- a/Core/Game/Actors/Actor.cpp +++ b/Core/Game/Actors/Actor.cpp @@ -8,17 +8,16 @@ Actor::Actor() SetType(Classes::Actor); } -std::shared_ptr Actor::save() noexcept +std::shared_ptr Actor::save() { - std::shared_ptr save = std::make_shared("Actor"); - save->SaveObject("loc", &loc) - ->SaveObject("rot", &rot) - ->SaveObject("scale", &scale) - ->SaveListStrings("tags", std::move(tags)); - return save; + return std::make_shared("Actor") + ->SaveObject("loc", &loc) + ->SaveObject("rot", &rot) + ->SaveObject("scale", &scale) + ->SaveListStrings("tags", std::move(tags)); } -void Actor::load(std::shared_ptr save) noexcept +void Actor::load(std::shared_ptr save) { loc = *reinterpret_cast(save->GetObject("loc")); rot = *reinterpret_cast(save->GetObject("rot")); diff --git a/Core/Game/Actors/Actor.h b/Core/Game/Actors/Actor.h index 6e5841b..0ab89e1 100644 --- a/Core/Game/Actors/Actor.h +++ b/Core/Game/Actors/Actor.h @@ -9,7 +9,6 @@ #include "Math/Vector.h" GENERATE_META(Actor) - class Actor : public ISave, public IRTTI { Vector3D loc; @@ -24,8 +23,8 @@ public: Delegate OnSetActorRotate; #pragma region ISave - virtual std::shared_ptr save() noexcept override; - virtual void load(std::shared_ptr save) noexcept override; + virtual std::shared_ptr save() override; + virtual void load(std::shared_ptr save) override; #pragma endregion virtual void BeginPlay(); diff --git a/Core/Game/Actors/Mesh/Mesh.cpp b/Core/Game/Actors/Mesh/Mesh.cpp new file mode 100644 index 0000000..4e007d9 --- /dev/null +++ b/Core/Game/Actors/Mesh/Mesh.cpp @@ -0,0 +1,21 @@ +#include "Mesh.hpp" + +#include "Game/SaveMap/SaveMap.h" + +Mesh::Mesh() +{ + SetType(Classes::Mesh); +} + +std::shared_ptr Mesh::save() +{ + return std::make_shared("Mesh") + ->SaveString("model_name_", model_name_) + ->connect_to(Actor::save()); +} + +void Mesh::load(std::shared_ptr save) +{ + Actor::load(save->getParent()); + model_name_ = save->GetString("model_name_"); +} \ No newline at end of file diff --git a/Core/Game/Actors/Mesh/Mesh.hpp b/Core/Game/Actors/Mesh/Mesh.hpp new file mode 100644 index 0000000..ffe9dac --- /dev/null +++ b/Core/Game/Actors/Mesh/Mesh.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include + +#include "../Actor.h" + +GENERATE_META(Mesh) +class Mesh : public Actor +{ + std::string model_name_; +protected: + void SetModelName(const std::string& new_model_name) { model_name_ = new_model_name; } + +public: + Mesh(); + +#pragma region ISave + virtual std::shared_ptr save() override; + virtual void load(std::shared_ptr save) override; +#pragma endregion + + virtual void load_model(const std::string& model_name) = 0; + const std::string& GetModelName() const { return model_name_; } +}; diff --git a/Core/Game/Actors/Mesh/StaticMesh.cpp b/Core/Game/Actors/Mesh/StaticMesh.cpp new file mode 100644 index 0000000..f1081fc --- /dev/null +++ b/Core/Game/Actors/Mesh/StaticMesh.cpp @@ -0,0 +1,26 @@ +#include "StaticMesh.hpp" + +#include "Log/Log.h" +#include "Game/SaveMap/SaveMap.h" + +StaticMesh::StaticMesh() +{ + SetType(Classes::StaticMesh); +} + +std::shared_ptr StaticMesh::save() +{ + return std::make_shared("StaticMesh")->connect_to(Mesh::save()); +} + +void StaticMesh::load(std::shared_ptr save) +{ + Mesh::load(save->getParent()); +} + +void StaticMesh::load_model(const std::string& model_name) +{ + SetModelName(model_name); + // TODO + Message("Load mesh: " + model_name); +} diff --git a/Core/Game/Actors/Mesh/StaticMesh.hpp b/Core/Game/Actors/Mesh/StaticMesh.hpp new file mode 100644 index 0000000..8d53982 --- /dev/null +++ b/Core/Game/Actors/Mesh/StaticMesh.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "Mesh.hpp" + +GENERATE_META(StaticMesh) +class StaticMesh : public Mesh +{ +public: + StaticMesh(); + +#pragma region ISave + virtual std::shared_ptr save() override; + virtual void load(std::shared_ptr save) override; +#pragma endregion + + void load_model(const std::string& model_name) override; +}; diff --git a/Core/Game/BaseObjectFactory.cpp b/Core/Game/BaseObjectFactory.cpp index 6edc75b..1991b16 100644 --- a/Core/Game/BaseObjectFactory.cpp +++ b/Core/Game/BaseObjectFactory.cpp @@ -1,10 +1,12 @@ #include "ObjectFactory.h" +#include "Actors/Mesh/StaticMesh.hpp" #include "Game/Actors/Actor.h" #include "Math/Vector.h" std::vector base_object_factories = { GENERATE_FACTORY_OBJECT(Actor) + GENERATE_FACTORY_OBJECT(StaticMesh) GENERATE_FACTORY_OBJECT(Vector2D) GENERATE_FACTORY_OBJECT(Vector3D) }; \ No newline at end of file diff --git a/Core/Game/SaveMap/SaveMap.cpp b/Core/Game/SaveMap/SaveMap.cpp index 93f1417..8b933cb 100644 --- a/Core/Game/SaveMap/SaveMap.cpp +++ b/Core/Game/SaveMap/SaveMap.cpp @@ -626,11 +626,11 @@ std::string SaveMap::serialize() noexcept return buffer; } -SaveMap* SaveMap::connect_to(const std::shared_ptr& parent) +std::shared_ptr SaveMap::connect_to(const std::shared_ptr& parent) { if (this->parent_ != nullptr) throw std::runtime_error("Can't connect to second parent"); this->parent_ = parent; - return this; + return std::shared_ptr(this); } diff --git a/Core/Game/SaveMap/SaveMap.h b/Core/Game/SaveMap/SaveMap.h index 7e6de79..7115f64 100644 --- a/Core/Game/SaveMap/SaveMap.h +++ b/Core/Game/SaveMap/SaveMap.h @@ -77,5 +77,5 @@ public: // Собирает все токены в JSON объект std::string serialize() noexcept; - SaveMap* connect_to(const std::shared_ptr& parent); + std::shared_ptr connect_to(const std::shared_ptr& parent); }; diff --git a/Core/Game/World/World.h b/Core/Game/World/World.h index 1b5f402..87ea13e 100644 --- a/Core/Game/World/World.h +++ b/Core/Game/World/World.h @@ -6,6 +6,7 @@ #include "RTTI.h" #include "Game/Actors/Actor.h" +#include "Game/Actors/Mesh/Mesh.hpp" class GameInstance; @@ -36,8 +37,8 @@ public: Container list; for (auto i = actors.cbegin(); i != actors.cend(); ++i) { - if (RTTI::IsA(*i)) - list.push_back(*i); + if (T* cast_object = RTTI::dyn_cast(*i)) + list.push_back(cast_object); } return list; } @@ -52,7 +53,7 @@ public: return object; } - template> + template> Container GetActorsByTag(std::string tag) { Container container; diff --git a/FastRTTI/RTTI_Meta.h b/FastRTTI/RTTI_Meta.h index a222b70..ac33feb 100644 --- a/FastRTTI/RTTI_Meta.h +++ b/FastRTTI/RTTI_Meta.h @@ -13,5 +13,5 @@ template struct Meta; // Enum type classes enum class Classes { - IRTTI, IResource, Actor, TestActor + IRTTI, IResource, Actor, TestActor, Mesh, StaticMesh }; diff --git a/TestGame/Worlds/TestWorld.world b/TestGame/Worlds/TestWorld.world index 7bdcf01..9291601 100644 --- a/TestGame/Worlds/TestWorld.world +++ b/TestGame/Worlds/TestWorld.world @@ -1 +1 @@ -{"Class name":"TestWorld","dtime":5.000000,"Parent parameters":{"Class name":"World","loActors":[]}} \ No newline at end of file +{"Class name":"TestWorld","dtime":5.000000,"Parent parameters":{"Class name":"World","loActors":[{"Class name":"StaticMesh","Parent parameters":{"Class name":"Mesh","smodel_name_":"TestModel","Parent parameters":{"Class name":"Actor","oloc":{"Class name":"Vector3D","dx":"0.0","dy":"0.0","dz":"0.0"},"orot":{"Class name":"Vector3D","dx":"0.0","dy":"0.0","dz":"0.0"},"oscale":{"Class name":"Vector3D","dx":"0.0","dy":"0.0","dz":"0.0"},"tags":[]}}}]}} \ No newline at end of file From 8819114b6380ed3c80641d439059db63de68c944 Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Mon, 13 Oct 2025 19:31:27 +0700 Subject: [PATCH 07/19] Add GetWorld to Actor. Integrate google test. Add Model manager class. Rename *.h to *.hpp files --- CMakeLists.txt | 1 + Core/Core/CoreCallBacks.h | 6 - Core/Core/CoreInstance.cpp | 13 +- .../Core/{CoreInstance.h => CoreInstance.hpp} | 5 +- Core/Core/RenderEngine/ModelManager.cpp | 73 ++++++++++ Core/Core/RenderEngine/ModelManager.hpp | 47 +++++++ Core/Core/{ => RenderEngine}/RenderEngine.cpp | 10 +- .../RenderEngine.hpp} | 6 + Core/Core/{SystemCalls.h => SystemCalls.hpp} | 0 Core/Core/Windows/WindowsCalls.cpp | 2 +- Core/Core/main.cpp | 2 +- Core/Game/Actors/Actor.cpp | 17 ++- Core/Game/Actors/{Actor.h => Actor.hpp} | 14 +- Core/Game/Actors/Mesh/Mesh.cpp | 2 +- Core/Game/Actors/Mesh/Mesh.hpp | 2 +- Core/Game/BaseObjectFactory.cpp | 6 +- Core/Game/GameInstance.cpp | 10 +- .../Game/{GameInstance.h => GameInstance.hpp} | 1 + .../{ObjectFactory.h => ObjectFactory.hpp} | 0 .../Resource/{IResource.h => IResource.hpp} | 0 Core/Game/Resource/Resource.cpp | 2 +- .../Resource/{Resource.h => Resource.hpp} | 2 +- Core/Game/SaveMap/SaveMap.cpp | 4 +- Core/Game/SaveMap/{SaveMap.h => SaveMap.hpp} | 0 Core/Game/World/World.cpp | 7 +- Core/Game/World/{World.h => World.hpp} | 4 +- .../Game/{WorldFactory.h => WorldFactory.hpp} | 2 +- Core/Log/Log.cpp | 2 +- Core/Log/{Log.h => Log.hpp} | 0 Core/Math/Vector.cpp | 4 +- Core/Math/{Vector.h => Vector.hpp} | 0 Core/Types/UString.cpp | 131 ++++++++++++++++++ Core/Types/UString.hpp | 32 +++++ FastRTTI/RTTI_Meta.h | 2 +- TestGame/src/Actors/TestActor.cpp | 2 +- TestGame/src/Actors/TestActor.h | 2 +- TestGame/src/Factories/ObjectFactory.cpp | 2 +- TestGame/src/Factories/WorldFactory.cpp | 2 +- TestGame/src/TestGameInstance.cpp | 6 +- TestGame/src/TestGameInstance.h | 2 +- TestGame/src/Worlds/TestWorld.cpp | 6 +- TestGame/src/Worlds/TestWorld.h | 3 +- Tests/CMakeLists.txt | 24 ++++ Tests/UStringTest.cpp | 25 ++++ 44 files changed, 424 insertions(+), 59 deletions(-) delete mode 100644 Core/Core/CoreCallBacks.h rename Core/Core/{CoreInstance.h => CoreInstance.hpp} (86%) create mode 100644 Core/Core/RenderEngine/ModelManager.cpp create mode 100644 Core/Core/RenderEngine/ModelManager.hpp rename Core/Core/{ => RenderEngine}/RenderEngine.cpp (99%) rename Core/Core/{RenderEngine.h => RenderEngine/RenderEngine.hpp} (97%) rename Core/Core/{SystemCalls.h => SystemCalls.hpp} (100%) rename Core/Game/Actors/{Actor.h => Actor.hpp} (87%) rename Core/Game/{GameInstance.h => GameInstance.hpp} (92%) rename Core/Game/{ObjectFactory.h => ObjectFactory.hpp} (100%) rename Core/Game/Resource/{IResource.h => IResource.hpp} (100%) rename Core/Game/Resource/{Resource.h => Resource.hpp} (98%) rename Core/Game/SaveMap/{SaveMap.h => SaveMap.hpp} (100%) rename Core/Game/World/{World.h => World.hpp} (94%) rename Core/Game/{WorldFactory.h => WorldFactory.hpp} (96%) rename Core/Log/{Log.h => Log.hpp} (100%) rename Core/Math/{Vector.h => Vector.hpp} (100%) create mode 100644 Core/Types/UString.cpp create mode 100644 Core/Types/UString.hpp create mode 100644 Tests/CMakeLists.txt create mode 100644 Tests/UStringTest.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 93282a8..9bd95eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,3 +21,4 @@ add_subdirectory(glfw) add_subdirectory(Core) add_subdirectory(TestGame) add_subdirectory(ProjectGenerator) +add_subdirectory(Tests) diff --git a/Core/Core/CoreCallBacks.h b/Core/Core/CoreCallBacks.h deleted file mode 100644 index 9a0ecfd..0000000 --- a/Core/Core/CoreCallBacks.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -struct CoreCallBacks -{ - void (*Quit)(); -}; \ No newline at end of file diff --git a/Core/Core/CoreInstance.cpp b/Core/Core/CoreInstance.cpp index cbe0ceb..7d2e47b 100644 --- a/Core/Core/CoreInstance.cpp +++ b/Core/Core/CoreInstance.cpp @@ -1,6 +1,6 @@ -#include "CoreInstance.h" +#include "CoreInstance.hpp" -#include "SystemCalls.h" +#include "SystemCalls.hpp" #include #include @@ -8,10 +8,9 @@ #include #include -#include "RenderEngine.h" -#include "Game/GameInstance.h" -#include "Log/Log.h" -#include "Game/SaveMap/SaveMap.h" +#include "RenderEngine/RenderEngine.hpp" +#include "Game/GameInstance.hpp" +#include "Game/SaveMap/SaveMap.hpp" extern GameInstance* GameFactory(CoreInstance&); @@ -78,8 +77,8 @@ CoreInstance::~CoreInstance() { modules_.clear(); - delete render_engine_; delete game_; + delete render_engine_; glfwDestroyWindow(window_); glfwTerminate(); diff --git a/Core/Core/CoreInstance.h b/Core/Core/CoreInstance.hpp similarity index 86% rename from Core/Core/CoreInstance.h rename to Core/Core/CoreInstance.hpp index 8e13676..260e0bd 100644 --- a/Core/Core/CoreInstance.h +++ b/Core/Core/CoreInstance.hpp @@ -6,13 +6,15 @@ #include #include "Game/SaveMap/ISave.h" -#include "Core/CoreCallBacks.h" class SaveMap; class RenderEngine; class GameInstance; struct GLFWwindow; +/* + * Внимательно следите, что бы у ваших объектов была "мягкая" зависимость + */ class CoreInstance { struct Module { const char* name; @@ -58,4 +60,5 @@ public: const std::string& getBaseWorldName() const { return main_config_.base_world; } const std::string& getGameName() const { return main_config_.game_name; } GameInstance* GetGameInstance() const { return game_; } + RenderEngine* GetRenderEngine() const { return render_engine_; } }; diff --git a/Core/Core/RenderEngine/ModelManager.cpp b/Core/Core/RenderEngine/ModelManager.cpp new file mode 100644 index 0000000..0bb347e --- /dev/null +++ b/Core/Core/RenderEngine/ModelManager.cpp @@ -0,0 +1,73 @@ +#include "ModelManager.hpp" + +ModelManager::StaticModel::StaticModel(const std::vector& voxels, std::string name): +name_(std::move(name)), +voxels_(voxels) +{ + glm::ivec3 sum_moments{0, 0, 0}; + int sum_masses = 0; + + for (auto& i : voxels_) + { + sum_moments += glm::ivec3{i.loc.x * i.mass, i.loc.y * i.mass, i.loc.z * i.mass}; + sum_masses += i.mass; + } + + if(sum_masses != 0) + sum_moments /= sum_masses; + else if (!voxels_.empty()) + { + sum_moments.x /= static_cast(voxels_.size()); + sum_moments.y /= static_cast(voxels_.size()); + sum_moments.z /= static_cast(voxels_.size()); + } + + mass_center_ = sum_moments; +} + +ModelManager::StaticModel::~StaticModel() +{ + OnDestroy.Call(name_); +} + +unsigned int ModelManager::FNV1aHash(const char* buf) +{ + unsigned int h_val = 0x811c9dc5; + + while (*buf) + { + h_val ^= static_cast(*buf++); + h_val *= 0x01000193; + } + + return h_val; +} + +void ModelManager::OnDestroySometimeModelCaller(const std::string& name) +{ + OnDestroySometimeModel.Call(name); +} + +ModelManager::~ModelManager() +{ + for (const auto& [it, model] : models) + { + model->OnDestroy.unbind(this, &ModelManager::OnDestroySometimeModelCaller); + } + models.clear(); +} + +std::shared_ptr ModelManager::LoadModel(const std::string& name) +{ + unsigned int hash = FNV1aHash(name.c_str()); + auto model = models.find(hash); + if (model != models.cend()) + return model->second; + + std::vector model_data; + // Load model_data + auto newModel = std::make_shared(model_data, name); + newModel->OnDestroy.bind(this, &ModelManager::OnDestroySometimeModelCaller); + models[hash] = newModel; + return models[hash]; +} diff --git a/Core/Core/RenderEngine/ModelManager.hpp b/Core/Core/RenderEngine/ModelManager.hpp new file mode 100644 index 0000000..3779329 --- /dev/null +++ b/Core/Core/RenderEngine/ModelManager.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include +#include +#include +#include +#include + +class ModelManager +{ +public: + struct Voxel + { + glm::ivec3 loc, color; + int mass; + }; + class StaticModel + { + std::string name_; + std::vector voxels_; + glm::vec3 mass_center_; + public: + Delegate OnDestroy; + + StaticModel(const std::vector& voxels, std::string name); + ~StaticModel(); + + const std::vector& GetVoxels() const { return voxels_; } + glm::vec3 GetMassCenter() const { return mass_center_; } + const std::string& GetName() const { return name_; } + }; + +private: + + std::unordered_map> models; + + static unsigned int FNV1aHash (const char *buf); + + void OnDestroySometimeModelCaller(const std::string& name); + +public: + Delegate OnDestroySometimeModel; + + ~ModelManager(); + + std::shared_ptr LoadModel(const std::string& name); +}; \ No newline at end of file diff --git a/Core/Core/RenderEngine.cpp b/Core/Core/RenderEngine/RenderEngine.cpp similarity index 99% rename from Core/Core/RenderEngine.cpp rename to Core/Core/RenderEngine/RenderEngine.cpp index 753a3e1..2d1683d 100644 --- a/Core/Core/RenderEngine.cpp +++ b/Core/Core/RenderEngine/RenderEngine.cpp @@ -1,15 +1,15 @@ -#include "RenderEngine.h" +#include "RenderEngine.hpp" #include #include #include #include -#include "CoreInstance.h" -#include "Log/Log.h" +#include "Core/CoreInstance.hpp" +#include "Log/Log.hpp" -#include "Game/GameInstance.h" -#include "Game/World/World.h" +#include "Game/GameInstance.hpp" +#include "Game/World/World.hpp" #include "Game/Actors/Mesh/Mesh.hpp" #include "GLFW/glfw3.h" diff --git a/Core/Core/RenderEngine.h b/Core/Core/RenderEngine/RenderEngine.hpp similarity index 97% rename from Core/Core/RenderEngine.h rename to Core/Core/RenderEngine/RenderEngine.hpp index c7d5f32..4a1ae17 100644 --- a/Core/Core/RenderEngine.h +++ b/Core/Core/RenderEngine/RenderEngine.hpp @@ -11,6 +11,8 @@ #include #include +#include "ModelManager.hpp" + #ifdef _DEBUG #include #define VK_CHECK(res) assert(res == VK_SUCCESS) @@ -55,6 +57,8 @@ class RenderEngine void copy_memory(VkBuffer src, VkBuffer dst, VkDeviceSize size); #pragma endregion + ModelManager model_manager_; + static const std::vector deviceExtensions; int current_frame_ = 0; @@ -128,4 +132,6 @@ public: void stop_render() const; GLFWwindow* get_window() const { return window_; } + + ModelManager* GetActiveModelManager() { return &model_manager_; } }; \ No newline at end of file diff --git a/Core/Core/SystemCalls.h b/Core/Core/SystemCalls.hpp similarity index 100% rename from Core/Core/SystemCalls.h rename to Core/Core/SystemCalls.hpp diff --git a/Core/Core/Windows/WindowsCalls.cpp b/Core/Core/Windows/WindowsCalls.cpp index e735662..81824f4 100644 --- a/Core/Core/Windows/WindowsCalls.cpp +++ b/Core/Core/Windows/WindowsCalls.cpp @@ -1,6 +1,6 @@ #ifdef _WIN32 -#include "../SystemCalls.h" +#include "../SystemCalls.hpp" #include diff --git a/Core/Core/main.cpp b/Core/Core/main.cpp index 3ac734d..be5bc25 100644 --- a/Core/Core/main.cpp +++ b/Core/Core/main.cpp @@ -1,6 +1,6 @@ #include -#include "CoreInstance.h" +#include "CoreInstance.hpp" int main(int argc, char* argv[]) { try { diff --git a/Core/Game/Actors/Actor.cpp b/Core/Game/Actors/Actor.cpp index 4781b32..dce154a 100644 --- a/Core/Game/Actors/Actor.cpp +++ b/Core/Game/Actors/Actor.cpp @@ -1,7 +1,12 @@ -#include "Actor.h" +#include "Actor.hpp" -#include "Game/SaveMap/SaveMap.h" -#include "Log/Log.h" +#include "Game/SaveMap/SaveMap.hpp" +#include "Game/World/World.hpp" +#include "Log/Log.hpp" + +void Actor::OnDestroy() +{ +} Actor::Actor() { @@ -55,3 +60,9 @@ void Actor::RemoveTag(const std::string& tag) noexcept { tags.remove(tag); } + +void Actor::Destroy() +{ + OnDestroy(); + //world_->actors.remove(this); +} diff --git a/Core/Game/Actors/Actor.h b/Core/Game/Actors/Actor.hpp similarity index 87% rename from Core/Game/Actors/Actor.h rename to Core/Game/Actors/Actor.hpp index 0ab89e1..5901a48 100644 --- a/Core/Game/Actors/Actor.h +++ b/Core/Game/Actors/Actor.hpp @@ -6,16 +6,23 @@ #include "RTTI_Meta.h" #include "Game/SaveMap/ISave.h" #include "Delegate/Delegate.h" -#include "Math/Vector.h" +#include "Math/Vector.hpp" +class World; GENERATE_META(Actor) + class Actor : public ISave, public IRTTI { + World* world_; + Vector3D loc; Vector3D rot; Vector3D scale; std::list tags; + +protected: + virtual void OnDestroy(); public: Actor(); @@ -47,4 +54,9 @@ public: void AddTag(const std::string& tag) noexcept; void RemoveTag(const std::string& tag) noexcept; const std::list& GetTags() const { return tags; } + void Destroy(); + + World* GetWorld() const { return world_; } + + friend class World; }; diff --git a/Core/Game/Actors/Mesh/Mesh.cpp b/Core/Game/Actors/Mesh/Mesh.cpp index 4e007d9..52c0f14 100644 --- a/Core/Game/Actors/Mesh/Mesh.cpp +++ b/Core/Game/Actors/Mesh/Mesh.cpp @@ -1,6 +1,6 @@ #include "Mesh.hpp" -#include "Game/SaveMap/SaveMap.h" +#include "Game/SaveMap/SaveMap.hpp" Mesh::Mesh() { diff --git a/Core/Game/Actors/Mesh/Mesh.hpp b/Core/Game/Actors/Mesh/Mesh.hpp index ffe9dac..7c0e65a 100644 --- a/Core/Game/Actors/Mesh/Mesh.hpp +++ b/Core/Game/Actors/Mesh/Mesh.hpp @@ -2,7 +2,7 @@ #include -#include "../Actor.h" +#include "../Actor.hpp" GENERATE_META(Mesh) class Mesh : public Actor diff --git a/Core/Game/BaseObjectFactory.cpp b/Core/Game/BaseObjectFactory.cpp index 1991b16..1b5418c 100644 --- a/Core/Game/BaseObjectFactory.cpp +++ b/Core/Game/BaseObjectFactory.cpp @@ -1,8 +1,8 @@ -#include "ObjectFactory.h" +#include "ObjectFactory.hpp" #include "Actors/Mesh/StaticMesh.hpp" -#include "Game/Actors/Actor.h" -#include "Math/Vector.h" +#include "Game/Actors/Actor.hpp" +#include "Math/Vector.hpp" std::vector base_object_factories = { GENERATE_FACTORY_OBJECT(Actor) diff --git a/Core/Game/GameInstance.cpp b/Core/Game/GameInstance.cpp index 9a61a4b..abb70be 100644 --- a/Core/Game/GameInstance.cpp +++ b/Core/Game/GameInstance.cpp @@ -1,14 +1,14 @@ -#include "GameInstance.h" +#include "GameInstance.hpp" #include #include #include #include -#include "Core/CoreInstance.h" -#include "Game/WorldFactory.h" -#include "SaveMap/SaveMap.h" -#include "Game/World/World.h" +#include "Core/CoreInstance.hpp" +#include "Game/WorldFactory.hpp" +#include "SaveMap/SaveMap.hpp" +#include "Game/World/World.hpp" extern std::vector world_factories; diff --git a/Core/Game/GameInstance.h b/Core/Game/GameInstance.hpp similarity index 92% rename from Core/Game/GameInstance.h rename to Core/Game/GameInstance.hpp index ac26b8c..8357518 100644 --- a/Core/Game/GameInstance.h +++ b/Core/Game/GameInstance.hpp @@ -28,6 +28,7 @@ public: virtual ~GameInstance(); World* GetWorld() const { return world; } + CoreInstance& GetCore() const { return core; } friend class CoreInstance; }; diff --git a/Core/Game/ObjectFactory.h b/Core/Game/ObjectFactory.hpp similarity index 100% rename from Core/Game/ObjectFactory.h rename to Core/Game/ObjectFactory.hpp diff --git a/Core/Game/Resource/IResource.h b/Core/Game/Resource/IResource.hpp similarity index 100% rename from Core/Game/Resource/IResource.h rename to Core/Game/Resource/IResource.hpp diff --git a/Core/Game/Resource/Resource.cpp b/Core/Game/Resource/Resource.cpp index e96bbb6..479db4b 100644 --- a/Core/Game/Resource/Resource.cpp +++ b/Core/Game/Resource/Resource.cpp @@ -1,4 +1,4 @@ -#include "Resource.h" +#include "Resource.hpp" #include #include diff --git a/Core/Game/Resource/Resource.h b/Core/Game/Resource/Resource.hpp similarity index 98% rename from Core/Game/Resource/Resource.h rename to Core/Game/Resource/Resource.hpp index 44d08e9..e719af1 100644 --- a/Core/Game/Resource/Resource.h +++ b/Core/Game/Resource/Resource.hpp @@ -1,6 +1,6 @@ #pragma once -#include "IResource.h" +#include "IResource.hpp" #include #include #include diff --git a/Core/Game/SaveMap/SaveMap.cpp b/Core/Game/SaveMap/SaveMap.cpp index 8b933cb..426baf8 100644 --- a/Core/Game/SaveMap/SaveMap.cpp +++ b/Core/Game/SaveMap/SaveMap.cpp @@ -1,8 +1,8 @@ -#include "SaveMap.h" +#include "SaveMap.hpp" #include #include -#include "Game/ObjectFactory.h" +#include "Game/ObjectFactory.hpp" extern std::vector factories; extern std::vector base_object_factories; diff --git a/Core/Game/SaveMap/SaveMap.h b/Core/Game/SaveMap/SaveMap.hpp similarity index 100% rename from Core/Game/SaveMap/SaveMap.h rename to Core/Game/SaveMap/SaveMap.hpp diff --git a/Core/Game/World/World.cpp b/Core/Game/World/World.cpp index 591b539..b14731b 100644 --- a/Core/Game/World/World.cpp +++ b/Core/Game/World/World.cpp @@ -1,6 +1,6 @@ -#include "World.h" +#include "World.hpp" -#include "Game/SaveMap/SaveMap.h" +#include "Game/SaveMap/SaveMap.hpp" World::World(GameInstance& game_instance) : game_instance(game_instance) { @@ -35,4 +35,7 @@ std::shared_ptr World::save() void World::load(std::shared_ptr save) { actors = std::move(reinterpret_cast&>(save->GetListObject("Actors"))); + + for (auto& i : actors) + i->world_ = this; } \ No newline at end of file diff --git a/Core/Game/World/World.h b/Core/Game/World/World.hpp similarity index 94% rename from Core/Game/World/World.h rename to Core/Game/World/World.hpp index 87ea13e..df899e8 100644 --- a/Core/Game/World/World.h +++ b/Core/Game/World/World.hpp @@ -5,11 +5,12 @@ #include #include "RTTI.h" -#include "Game/Actors/Actor.h" +#include "Game/Actors/Actor.hpp" #include "Game/Actors/Mesh/Mesh.hpp" class GameInstance; +GENERATE_META(World); class World : public ISave { GameInstance& game_instance; @@ -49,6 +50,7 @@ public: T* object = new T(); object->SetActorLocate(loc); object->SetActorRotate(rot); + static_cast(object)->world_ = this; actors.push_back(object); return object; } diff --git a/Core/Game/WorldFactory.h b/Core/Game/WorldFactory.hpp similarity index 96% rename from Core/Game/WorldFactory.h rename to Core/Game/WorldFactory.hpp index 29e7dbb..5e8a006 100644 --- a/Core/Game/WorldFactory.h +++ b/Core/Game/WorldFactory.hpp @@ -3,7 +3,7 @@ #include #include #include -#include "Game/SaveMap/SaveMap.h" +#include "Game/SaveMap/SaveMap.hpp" class GameInstance; class World; diff --git a/Core/Log/Log.cpp b/Core/Log/Log.cpp index 2b0c4e7..8bae583 100644 --- a/Core/Log/Log.cpp +++ b/Core/Log/Log.cpp @@ -1,4 +1,4 @@ -#include "Log.h" +#include "Log.hpp" #include #include diff --git a/Core/Log/Log.h b/Core/Log/Log.hpp similarity index 100% rename from Core/Log/Log.h rename to Core/Log/Log.hpp diff --git a/Core/Math/Vector.cpp b/Core/Math/Vector.cpp index bac260a..a86d94b 100644 --- a/Core/Math/Vector.cpp +++ b/Core/Math/Vector.cpp @@ -1,6 +1,6 @@ -#include "Vector.h" +#include "Vector.hpp" -#include "Game/SaveMap/SaveMap.h" +#include "Game/SaveMap/SaveMap.hpp" Vector2D::Vector2D(const double x, const double y) : x(x), y(y) {} diff --git a/Core/Math/Vector.h b/Core/Math/Vector.hpp similarity index 100% rename from Core/Math/Vector.h rename to Core/Math/Vector.hpp diff --git a/Core/Types/UString.cpp b/Core/Types/UString.cpp new file mode 100644 index 0000000..16745cc --- /dev/null +++ b/Core/Types/UString.cpp @@ -0,0 +1,131 @@ +#include "UString.hpp" + +#include + +unsigned int UString::FNV1aHash(const char* buf) +{ + unsigned int h_val = 0x811c9dc5; + + while (*buf) + { + h_val ^= static_cast(*buf++); + h_val *= 0x01000193; + } + + return h_val; +} + +UString::UString(const char* str) +{ + if (str == nullptr) + return; + size_ = strlen(str); + + str_ = new char[size_ + 1]; + for (size_t i = 0; i < size_; ++i) + str_[i] = str[i]; + str_[size_] = '\0'; + + hash_ = FNV1aHash(str); +} + +UString::UString(const UString& str) : size_(str.size_) +{ + if (size_ != 0 && str.str_ != nullptr) + { + str_ = new char[str.size_ + 1]; + strcpy_s(str_, size_ + 1, str.str_); + } + hash_ = str.hash_; +} + +UString::UString(UString&& str) noexcept +{ + is_moved_.store(true); + str_ = str.str_; + size_ = str.size_; + hash_ = str.hash_; +} + +UString::~UString() +{ + if (is_moved_.load() == false) + delete[] str_; +} + +UString& UString::operator=(const UString& str) +{ + if (&str != this) + { + if (size_ != 0 && str.str_ != nullptr) + { + str_ = new char[str.size_]; + strcpy_s(str_, size_, str.str_); + } + } + is_moved_.store(false); + hash_ = FNV1aHash(str_); + return *this; +} + +UString& UString::operator=(UString&& str) noexcept +{ + str.is_moved_.store(true); + str_ = str.str_; + size_ = str.size_; + is_moved_.store(false); + hash_ = FNV1aHash(str_); + return *this; +} + +void UString::operator+=(const UString& str) +{ + char* new_str = new char[size_ + str.size_ + 1]; + strcpy_s(new_str, size_ + str.size_ + 1, str_); + strcpy_s(new_str + size_, str.size_ + 1, str.str_); + + if (is_moved_.load() == false) + delete[] str_; + str_ = new_str; + size_ += str.size_; + + is_moved_.store(false); + hash_ = FNV1aHash(str_); +} + +void UString::operator+=(const char* str) +{ + size_t str_size = strlen(str); + char* new_str = new char[size_ + str_size + 1]; + strcpy_s(new_str, size_ + str_size + 1, str_); + strcpy_s(new_str + size_, str_size + 1, str); + + if (is_moved_.load() == false) + delete[] str_; + str_ = new_str; + size_ += str_size; + + is_moved_.store(false); + hash_ = FNV1aHash(str_); +} + +bool UString::operator==(const UString& str) const +{ + return hash_ == str.hash_; +} + +bool UString::operator==(const char* str) const +{ + unsigned int hash = FNV1aHash(str); + return hash_ == hash; +} + +bool UString::operator!=(const UString& str) const +{ + return !(*this == str); +} + +bool UString::operator!=(const char* str) const +{ + return !(*this == str); +} diff --git a/Core/Types/UString.hpp b/Core/Types/UString.hpp new file mode 100644 index 0000000..8c863ae --- /dev/null +++ b/Core/Types/UString.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +class UString +{ + unsigned int hash_ = 0; + std::atomic_bool is_moved_ = false; + char* str_ = nullptr; + size_t size_ = 0; + + static unsigned int FNV1aHash (const char *buf); +public: + UString(const char* str); + UString(const UString& str); + UString(UString&& str) noexcept; + ~UString(); + + UString& operator=(const UString& str); + UString& operator=(UString&& str) noexcept; + void operator+=(const UString& str); + void operator+=(const char* str); + bool operator==(const UString& str) const; + bool operator==(const char* str) const; + bool operator!=(const UString& str) const; + bool operator!=(const char* str) const; + + size_t length() const { return size_; } + const char* c_str() const { return str_; } + std::string std_str() const { return std::string(str_, size_); } +}; diff --git a/FastRTTI/RTTI_Meta.h b/FastRTTI/RTTI_Meta.h index ac33feb..d348cee 100644 --- a/FastRTTI/RTTI_Meta.h +++ b/FastRTTI/RTTI_Meta.h @@ -13,5 +13,5 @@ template struct Meta; // Enum type classes enum class Classes { - IRTTI, IResource, Actor, TestActor, Mesh, StaticMesh + IRTTI, IResource, Actor, TestActor, Mesh, StaticMesh, World, TestWorld }; diff --git a/TestGame/src/Actors/TestActor.cpp b/TestGame/src/Actors/TestActor.cpp index da903e9..1d398f1 100644 --- a/TestGame/src/Actors/TestActor.cpp +++ b/TestGame/src/Actors/TestActor.cpp @@ -1,6 +1,6 @@ #include "TestActor.h" -#include "Log/Log.h" +#include "Log/Log.hpp" void TestActor::BeginPlay() { diff --git a/TestGame/src/Actors/TestActor.h b/TestGame/src/Actors/TestActor.h index ebecad9..b27b1b0 100644 --- a/TestGame/src/Actors/TestActor.h +++ b/TestGame/src/Actors/TestActor.h @@ -1,6 +1,6 @@ #pragma once -#include "Game/Actors/Actor.h" +#include "Game/Actors/Actor.hpp" GENERATE_META(TestActor) class TestActor final : public Actor diff --git a/TestGame/src/Factories/ObjectFactory.cpp b/TestGame/src/Factories/ObjectFactory.cpp index 4690e4b..0c8baf5 100644 --- a/TestGame/src/Factories/ObjectFactory.cpp +++ b/TestGame/src/Factories/ObjectFactory.cpp @@ -1,4 +1,4 @@ -#include "Game/ObjectFactory.h" +#include "Game/ObjectFactory.hpp" #include "../Actors/TestActor.h" diff --git a/TestGame/src/Factories/WorldFactory.cpp b/TestGame/src/Factories/WorldFactory.cpp index 74185dd..b44b49d 100644 --- a/TestGame/src/Factories/WorldFactory.cpp +++ b/TestGame/src/Factories/WorldFactory.cpp @@ -1,4 +1,4 @@ -#include "Game/WorldFactory.h" +#include "Game/WorldFactory.hpp" #include "../Worlds/TestWorld.h" diff --git a/TestGame/src/TestGameInstance.cpp b/TestGame/src/TestGameInstance.cpp index fe4677e..e062916 100644 --- a/TestGame/src/TestGameInstance.cpp +++ b/TestGame/src/TestGameInstance.cpp @@ -1,10 +1,10 @@ #include "TestGameInstance.h" -#include "Game/Resource/Resource.h" +#include "Game/Resource/Resource.hpp" #include -#include "Game/SaveMap/SaveMap.h" -#include "Game/World/World.h" +#include "Game/SaveMap/SaveMap.hpp" +#include "Game/World/World.hpp" GENERATE_FACTORY_GAME_INSTANCE(TestGameInstance) TestGameInstance::TestGameInstance(CoreInstance& core) : GameInstance(core) diff --git a/TestGame/src/TestGameInstance.h b/TestGame/src/TestGameInstance.h index 15f50f6..e68e9f5 100644 --- a/TestGame/src/TestGameInstance.h +++ b/TestGame/src/TestGameInstance.h @@ -1,6 +1,6 @@ #pragma once -#include "Game/GameInstance.h" +#include "Game/GameInstance.hpp" class TestGameInstance : public GameInstance { diff --git a/TestGame/src/Worlds/TestWorld.cpp b/TestGame/src/Worlds/TestWorld.cpp index b40064b..9b8731f 100644 --- a/TestGame/src/Worlds/TestWorld.cpp +++ b/TestGame/src/Worlds/TestWorld.cpp @@ -1,8 +1,8 @@ #include "TestWorld.h" -#include "Game/GameInstance.h" -#include "Game/SaveMap/SaveMap.h" -#include "Log/Log.h" +#include "Game/GameInstance.hpp" +#include "Game/SaveMap/SaveMap.hpp" +#include "Log/Log.hpp" TestWorld::TestWorld(GameInstance& game_instance) : World(game_instance) {} diff --git a/TestGame/src/Worlds/TestWorld.h b/TestGame/src/Worlds/TestWorld.h index 1e6081b..a54a1c1 100644 --- a/TestGame/src/Worlds/TestWorld.h +++ b/TestGame/src/Worlds/TestWorld.h @@ -1,7 +1,8 @@ #pragma once -#include "Game/World/World.h" +#include "Game/World/World.hpp" +GENERATE_META(TestWorld) class TestWorld final : public World { double time = 0; diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt new file mode 100644 index 0000000..025c18c --- /dev/null +++ b/Tests/CMakeLists.txt @@ -0,0 +1,24 @@ +include(FetchContent) +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/refs/tags/v1.15.0.zip + DOWNLOAD_EXTRACT_TIMESTAMP true +) +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(googletest) + +enable_testing() + +file(GLOB SRC "UStringTest.cpp" "${PROJECT_SOURCE_DIR}/Core/Types/UString.cpp") + +add_executable(Tests ${SRC}) +target_link_libraries(Tests PRIVATE + GTest::gtest_main +) +target_include_directories(Tests PRIVATE + ${PROJECT_SOURCE_DIR}/Core +) + + +include(GoogleTest) +gtest_discover_tests(Tests) \ No newline at end of file diff --git a/Tests/UStringTest.cpp b/Tests/UStringTest.cpp new file mode 100644 index 0000000..19de15d --- /dev/null +++ b/Tests/UStringTest.cpp @@ -0,0 +1,25 @@ +#include +#include "Types/UString.hpp" +#include + +TEST(UStringTest, creae_string) +{ + UString str("Hello, World!"); + EXPECT_EQ(str, "Hello, World!"); + EXPECT_NE(str, "Hello, UwU!"); + EXPECT_EQ(str.length(), 13); +} + +TEST(UStringTest, concatenate_string) +{ + UString str1("Hello, "); + UString str2("World!"); + str1 += str2; + EXPECT_EQ(str1, "Hello, World!"); + EXPECT_EQ(str1.length(), 13); + + UString str3("Hello, "); + str3 += "UwU!"; + EXPECT_EQ(str3, "Hello, UwU!"); + EXPECT_EQ(str3.length(), 11); +} \ No newline at end of file From 87c72e4a48ecf0c4d3ca3047edfed643ed5b40db Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Mon, 13 Oct 2025 21:06:23 +0700 Subject: [PATCH 08/19] Add tests for SaveMap --- Core/Game/Actors/Mesh/StaticMesh.cpp | 4 +- Core/Game/SaveMap/SaveMap.cpp | 90 ++++++++----- Core/Game/SaveMap/SaveMap.hpp | 4 +- TestGame/Worlds/TestWorld.world | 2 +- TestGame/main_config.conf | 2 +- Tests/CMakeLists.txt | 9 +- Tests/SaveMapTest.cpp | 185 +++++++++++++++++++++++++++ 7 files changed, 255 insertions(+), 41 deletions(-) create mode 100644 Tests/SaveMapTest.cpp diff --git a/Core/Game/Actors/Mesh/StaticMesh.cpp b/Core/Game/Actors/Mesh/StaticMesh.cpp index f1081fc..89af642 100644 --- a/Core/Game/Actors/Mesh/StaticMesh.cpp +++ b/Core/Game/Actors/Mesh/StaticMesh.cpp @@ -1,7 +1,7 @@ #include "StaticMesh.hpp" -#include "Log/Log.h" -#include "Game/SaveMap/SaveMap.h" +#include "Log/Log.hpp" +#include "Game/SaveMap/SaveMap.hpp" StaticMesh::StaticMesh() { diff --git a/Core/Game/SaveMap/SaveMap.cpp b/Core/Game/SaveMap/SaveMap.cpp index 426baf8..17a8c6c 100644 --- a/Core/Game/SaveMap/SaveMap.cpp +++ b/Core/Game/SaveMap/SaveMap.cpp @@ -32,63 +32,64 @@ SaveMap::SaveMap(const char* class_name) : class_name(class_name) SaveMap::SaveMap(const std::string& json_data) { - for (size_t i = 0; i < json_data.length() - 1;) + std::string json_data_blank = CleaningJSON(json_data); + for (size_t i = 0; i < json_data_blank.length() - 1;) { - size_t key_begin = i = json_data.find_first_of('\"', i) + 1; - size_t key_end = i = json_data.find_first_of('\"', i); + size_t key_begin = i = json_data_blank.find_first_of('\"', i) + 1; + size_t key_end = i = json_data_blank.find_first_of('\"', i); - std::string name = json_data.substr(key_begin, key_end - key_begin); + std::string name = json_data_blank.substr(key_begin, key_end - key_begin); if (class_name.empty()) { - size_t begin = json_data.find(':', i) + 2; - size_t end = i = json_data.find('\"', begin); + size_t begin = json_data_blank.find(':', i) + 2; + size_t end = i = json_data_blank.find('\"', begin); i++; - class_name = json_data.substr(begin, end - begin); + class_name = json_data_blank.substr(begin, end - begin); continue; } if (name[0] == 'i') { - size_t begin = json_data.find(':', i) + 2; - size_t end = i = json_data.find_first_of(",}", i); + size_t begin = json_data_blank.find(':', i) + 1; + size_t end = i = json_data_blank.find_first_of(",}", i); i++; - std::string value = json_data.substr(begin, end - begin - 1); + std::string value = json_data_blank.substr(begin, end - begin); save_long[name.c_str() + 1] = std::stoll(value); } else if (name[0] == 'd') { - size_t begin = json_data.find(':', i) + 2; - size_t end = i = json_data.find_first_of(",}", i); + size_t begin = json_data_blank.find(':', i) + 1; + size_t end = i = json_data_blank.find_first_of(",}", i); i++; - std::string value = json_data.substr(begin, end - begin - 1); + std::string value = json_data_blank.substr(begin, end - begin); save_double[name.c_str() + 1] = std::stod(value); } else if (name[0] == 's') { - size_t begin = json_data.find(':', i) + 2; - size_t end = i = json_data.find('\"', begin); + size_t begin = json_data_blank.find(':', i) + 2; + size_t end = i = json_data_blank.find('\"', begin); i++; std::string value; if (begin != end) - value = json_data.substr(begin, end - begin); + value = json_data_blank.substr(begin, end - begin); else value = ""; save_string[name.c_str() + 1] = value; } else if (name[0] == 'o') { - size_t begin = i = json_data.find('{', i); + size_t begin = i = json_data_blank.find('{', i); int open = 1, close = 0; while (close < open) { i++; - if (json_data[i] == '{') + if (json_data_blank[i] == '{') open++; - else if (json_data[i] == '}') + else if (json_data_blank[i] == '}') close++; } size_t end = i; i++; - std::string object_json = json_data.substr(begin, end - begin + 1); + std::string object_json = json_data_blank.substr(begin, end - begin + 1); begin = object_json.find(':') + 2; end = object_json.find('\"', begin); @@ -102,20 +103,20 @@ SaveMap::SaveMap(const std::string& json_data) { std::string key = name.substr(2, name.length() - 2); - size_t begin_arr = i = json_data.find('[', i); + size_t begin_arr = i = json_data_blank.find('[', i); int open = 1, close = 0; while (close < open) { i++; - if (json_data[i] == '[') + if (json_data_blank[i] == '[') open++; - else if (json_data[i] == ']') + else if (json_data_blank[i] == ']') close++; } size_t end_arr = i; i++; - std::string arr_data = json_data.substr(begin_arr, end_arr - begin_arr + 1); + std::string arr_data = json_data_blank.substr(begin_arr, end_arr - begin_arr + 1); if (name[1] == 'i') { save_vector_integer[key] = std::vector(); @@ -155,6 +156,8 @@ SaveMap::SaveMap(const std::string& json_data) while (j < arr_data.length()) { size_t begin = arr_data.find('\"', j) + 1; + if (begin == std::string::npos + 1) + break; size_t end = j = arr_data.find('\"', begin); std::string value; if (begin != end) @@ -162,7 +165,7 @@ SaveMap::SaveMap(const std::string& json_data) else value = ""; vector_strings.push_back(value); - j += 3; + ++j; } } else if (name[1] == 'o') { @@ -206,20 +209,20 @@ SaveMap::SaveMap(const std::string& json_data) { std::string key = name.substr(2, name.length() - 2); - size_t begin_arr = i = json_data.find('[', i); + size_t begin_arr = i = json_data_blank.find('[', i); int open = 1, close = 0; while (close < open) { i++; - if (json_data[i] == '[') + if (json_data_blank[i] == '[') open++; - else if (json_data[i] == ']') + else if (json_data_blank[i] == ']') close++; } size_t end_arr = i; i++; - std::string arr_data = json_data.substr(begin_arr, end_arr - begin_arr + 1); + std::string arr_data = json_data_blank.substr(begin_arr, end_arr - begin_arr + 1); if (name[1] == 'i') { save_list_integer[key] = std::list(); @@ -304,21 +307,21 @@ SaveMap::SaveMap(const std::string& json_data) } } else if (name == "Parent parameters") { - size_t parent_begin = i = json_data.find('{', i); + size_t parent_begin = i = json_data_blank.find('{', i); int open = 1, close = 0; while (close < open) { i++; - if (json_data[i] == '{') + if (json_data_blank[i] == '{') open++; - else if (json_data[i] == '}') + else if (json_data_blank[i] == '}') close++; } size_t parent_end = i; i++; - std::string str = json_data.substr(parent_begin, parent_end - parent_begin + 1); + std::string str = json_data_blank.substr(parent_begin, parent_end - parent_begin + 1); parent_ = std::make_shared(str); } } @@ -448,9 +451,9 @@ double SaveMap::GetDouble(const char* name) return save_double[name]; } -const char* SaveMap::GetString(const char* name) +std::string SaveMap::GetString(const char* name) { - return save_string[name].c_str(); + return save_string[name]; } ISave* SaveMap::GetObject(const char* name) @@ -634,3 +637,20 @@ std::shared_ptr SaveMap::connect_to(const std::shared_ptr& par this->parent_ = parent; return std::shared_ptr(this); } + +std::string SaveMap::CleaningJSON(const std::string& json_data) +{ + std::string blank_str; + blank_str.reserve(json_data.length()); + + bool open_str = false; + for (auto i : json_data) + { + if (i == '\"') + open_str = !open_str; + if (open_str || (i != ' ' && i != '\t' && i != '\n' && i != '\r')) + blank_str += i; + } + + return blank_str; +} diff --git a/Core/Game/SaveMap/SaveMap.hpp b/Core/Game/SaveMap/SaveMap.hpp index 7115f64..e20abd1 100644 --- a/Core/Game/SaveMap/SaveMap.hpp +++ b/Core/Game/SaveMap/SaveMap.hpp @@ -60,7 +60,7 @@ public: // Методы получения значенй long long GetInteger(const char* name); double GetDouble(const char* name); - const char* GetString(const char* name); + std::string GetString(const char* name); ISave* GetObject(const char* name); std::vector& GetVectorInteger(const char* name); std::vector& GetVectorDouble(const char* name); @@ -78,4 +78,6 @@ public: std::string serialize() noexcept; std::shared_ptr connect_to(const std::shared_ptr& parent); + + static std::string CleaningJSON(const std::string& json_data); }; diff --git a/TestGame/Worlds/TestWorld.world b/TestGame/Worlds/TestWorld.world index 9291601..b63c26a 100644 --- a/TestGame/Worlds/TestWorld.world +++ b/TestGame/Worlds/TestWorld.world @@ -1 +1 @@ -{"Class name":"TestWorld","dtime":5.000000,"Parent parameters":{"Class name":"World","loActors":[{"Class name":"StaticMesh","Parent parameters":{"Class name":"Mesh","smodel_name_":"TestModel","Parent parameters":{"Class name":"Actor","oloc":{"Class name":"Vector3D","dx":"0.0","dy":"0.0","dz":"0.0"},"orot":{"Class name":"Vector3D","dx":"0.0","dy":"0.0","dz":"0.0"},"oscale":{"Class name":"Vector3D","dx":"0.0","dy":"0.0","dz":"0.0"},"tags":[]}}}]}} \ No newline at end of file +{"Class name":"TestWorld","dtime":5.000000,"Parent parameters":{"Class name":"World","loActors":[{"Class name":"StaticMesh","Parent parameters":{"Class name":"Mesh","smodel_name_":"TestModel","Parent parameters":{"Class name":"Actor","oloc":{"Class name":"Vector3D","dx":0.0,"dy":0.0,"dz":0.0},"orot":{"Class name":"Vector3D","dx":0.0,"dy":0.0,"dz":0.0},"oscale":{"Class name":"Vector3D","dx":0.0,"dy":0.0,"dz":0.0},"tags":[]}}}]}} \ No newline at end of file diff --git a/TestGame/main_config.conf b/TestGame/main_config.conf index 1edecc2..e2d7189 100644 --- a/TestGame/main_config.conf +++ b/TestGame/main_config.conf @@ -1 +1 @@ -{"Class name":"MainConfig","dmin_memory_size":"4096.0","imin_CPU_count":"1","sgame_name":"Test Game","sbase_world":"TestWorld"} \ No newline at end of file +{"Class name":"MainConfig","dmin_memory_size":4096.0,"imin_CPU_count":1,"sgame_name":"Test Game","sbase_world":"TestWorld"} \ No newline at end of file diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 025c18c..8e0ad46 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1,3 +1,4 @@ +set(CMAKE_CXX_STANDARD 17) include(FetchContent) FetchContent_Declare( googletest @@ -9,7 +10,13 @@ FetchContent_MakeAvailable(googletest) enable_testing() -file(GLOB SRC "UStringTest.cpp" "${PROJECT_SOURCE_DIR}/Core/Types/UString.cpp") +file(GLOB SRC + "UStringTest.cpp" + "SaveMapTest.cpp" + + "${PROJECT_SOURCE_DIR}/Core/Types/UString.cpp" + "${PROJECT_SOURCE_DIR}/Core/Game/SaveMap/SaveMap.cpp" +) add_executable(Tests ${SRC}) target_link_libraries(Tests PRIVATE diff --git a/Tests/SaveMapTest.cpp b/Tests/SaveMapTest.cpp new file mode 100644 index 0000000..29fa958 --- /dev/null +++ b/Tests/SaveMapTest.cpp @@ -0,0 +1,185 @@ +#include +#include + +#include "Game/ObjectFactory.hpp" +#include "Game/SaveMap/SaveMap.hpp" + +class CustomObject : public ISave +{ +public: + int num; + std::string str; + double dbl; + + std::shared_ptr save() override + { + return std::make_shared("CustomObject")->SaveInteger("num", num)->SaveString("str", str)->SaveDouble("dbl", dbl); + } + void load(std::shared_ptr save) override + { + num = save->GetInteger("num"); + str = save->GetString("str"); + dbl = save->GetDouble("dbl"); + } + + bool operator==(const CustomObject& obj) const + { + return num == obj.num && str == obj.str && dbl == obj.dbl; + } +}; + +FACTORIES_LIST { + GENERATE_FACTORY_OBJECT(CustomObject) +}; +// A compatibility plug +std::vector base_object_factories = {}; + +TEST(SaveMapTest, check_clean) +{ + std::string start_json = +"{\n" +"\t\"id\": 1,\n" +"\t\"name\": \"Ivan Ivanov\",\n" +"\t\"age\": 28,\n" +"\t\"email\": \"ivan@example.com\",\n" +"\t\"roles\": [\"user\", \"editor\", \"moderator\"]\n" +"}"; + std::string end_json = "{\"id\":1,\"name\":\"Ivan Ivanov\",\"age\":28,\"email\":\"ivan@example.com\",\"roles\":[\"user\",\"editor\",\"moderator\"]}"; + + EXPECT_EQ(SaveMap::CleaningJSON(start_json), end_json); +} + +TEST(SaveMapTest, check_load_base_type) +{ + std::string json = +"{\n" + "\t\"Class name\": \"test class\",\n" + "\t\"iTestInt\": 123,\n" + "\t\"dTestDouble\": 123.56,\n" + "\t\"sTestString\": \"string str\",\n" + "\t\"viTestVectorInt\": [\n" + "\t\t1,\n" + "\t\t2,\n" + "\t\t3\n" + "\t],\n" + "\t\"vdTestVectorDouble\": [\n" + "\t\t1.2,\n" + "\t\t3.4,\n" + "\t\t5.6\n" + "\t],\n" + "\t\t\"vsTestVectorString\": [\n" + "\t\t\"str 1\",\n" + "\t\t\"2 str\",\n" + "\t\t\"str 3 str\"\n" + "\t]\n" +"}"; + + std::vector test_vector_int = { 1, 2, 3 }; + std::vector test_vector_double = { 1.2, 3.4, 5.6 }; + std::vector test_vector_string = { "str 1", "2 str", "str 3 str" }; + SaveMap save_map(json); + + EXPECT_EQ(save_map.GetInteger("TestInt"), 123); + EXPECT_EQ(save_map.GetDouble("TestDouble"), 123.56); + EXPECT_EQ(save_map.GetString("TestString"), "string str"); + + EXPECT_EQ(save_map.GetVectorInteger("TestVectorInt").size(), 3); + EXPECT_EQ(save_map.GetVectorDouble("TestVectorDouble").size(), 3); + EXPECT_EQ(save_map.GetVectorString("TestVectorString").size(), 3); + for (auto i = 0; i < 3; i++) + { + EXPECT_EQ(test_vector_int[i], save_map.GetVectorInteger("TestVectorInt")[i]); + EXPECT_EQ(test_vector_double[i], save_map.GetVectorDouble("TestVectorDouble")[i]); + EXPECT_EQ(test_vector_string[i], save_map.GetVectorString("TestVectorString")[i]); + } +} + +TEST(SaveMapTest, check_load_with_custom_type) +{ + std::string json = + "{\n" + "\t\"Class name\": \"test class\",\n" + "\t\"iTestInt\": 123,\n" + "\t\"dTestDouble\": 123.56,\n" + "\t\"sTestString\": \"string str\",\n" + "\t\"viTestVectorInt\": [\n" + "\t\t1,\n" + "\t\t2,\n" + "\t\t3\n" + "\t],\n" + "\t\"vdTestVectorDouble\": [\n" + "\t\t1.2,\n" + "\t\t3.4,\n" + "\t\t5.6\n" + "\t],\n" + "\t\t\"vsTestVectorString\": [\n" + "\t\t\"str 1\",\n" + "\t\t\"2 str\",\n" + "\t\t\"str 3 str\"\n" + "\t],\n" + "\t\"oCustomObject\": {\n" + "\t\t\"Class name\": \"CustomObject\",\n" + "\t\t\"inum\": 123,\n" + "\"sstr\": \"str123\",\n" + "\t\t\"ddbl\": 123.45\n" + "\t},\n" + "\"voCustomObjects\": [" + "{" + "\"Class name\": \"CustomObject\"," + "\"inum\": 123," + "\"sstr\": \"str123\"," + "\"ddbl\": 123.45" + "}," + "{" + "\"Class name\": \"CustomObject\"," + "\"inum\": 321," + "\"sstr\": \"str321\"," + "\"ddbl\": 543.21" + "}" + "]" +"}"; + + std::vector test_vector_int = { 1, 2, 3 }; + std::vector test_vector_double = { 1.2, 3.4, 5.6 }; + std::vector test_vector_string = { "str 1", "2 str", "str 3 str" }; + SaveMap save_map(json); + + EXPECT_EQ(save_map.GetInteger("TestInt"), 123); + EXPECT_EQ(save_map.GetDouble("TestDouble"), 123.56); + EXPECT_EQ(save_map.GetString("TestString"), "string str"); + + EXPECT_EQ(save_map.GetVectorInteger("TestVectorInt").size(), 3); + EXPECT_EQ(save_map.GetVectorDouble("TestVectorDouble").size(), 3); + EXPECT_EQ(save_map.GetVectorString("TestVectorString").size(), 3); + for (auto i = 0; i < 3; i++) + { + EXPECT_EQ(test_vector_int[i], save_map.GetVectorInteger("TestVectorInt")[i]); + EXPECT_EQ(test_vector_double[i], save_map.GetVectorDouble("TestVectorDouble")[i]); + EXPECT_EQ(test_vector_string[i], save_map.GetVectorString("TestVectorString")[i]); + } + + CustomObject* obj = reinterpret_cast(save_map.GetObject("CustomObject")); + CustomObject test_obj; + test_obj.num = 123; + test_obj.str = "str123"; + test_obj.dbl = 123.45; + EXPECT_EQ(*obj, test_obj); + + std::vector vec_obj = reinterpret_cast&>(save_map.GetVectorObject("CustomObjects")); + std::vector vec_obj_test = { + new CustomObject, + new CustomObject, + }; + vec_obj_test[0]->num = 123; + vec_obj_test[0]->str = "str123"; + vec_obj_test[0]->dbl = 123.45; + vec_obj_test[1]->num = 321; + vec_obj_test[1]->str = "str321"; + vec_obj_test[1]->dbl = 543.21; + for (auto i = 0; i < 2; i++) + { + EXPECT_EQ(*vec_obj[i], *vec_obj_test[i]); + delete vec_obj[i]; + delete vec_obj_test[i]; + } +} \ No newline at end of file From 189a6d43fec161146a5482fd63e75b4fdb41e140 Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Wed, 15 Oct 2025 18:20:27 +0700 Subject: [PATCH 09/19] Remove UString. And replaced std::map to std::unordered_map --- Core/Game/SaveMap/SaveMap.hpp | 26 +++---- Core/Types/UString.cpp | 131 ---------------------------------- Core/Types/UString.hpp | 32 --------- Tests/CMakeLists.txt | 2 - Tests/UStringTest.cpp | 25 ------- 5 files changed, 13 insertions(+), 203 deletions(-) delete mode 100644 Core/Types/UString.cpp delete mode 100644 Core/Types/UString.hpp delete mode 100644 Tests/UStringTest.cpp diff --git a/Core/Game/SaveMap/SaveMap.hpp b/Core/Game/SaveMap/SaveMap.hpp index e20abd1..efebe20 100644 --- a/Core/Game/SaveMap/SaveMap.hpp +++ b/Core/Game/SaveMap/SaveMap.hpp @@ -2,7 +2,7 @@ #include "ISave.h" -#include +#include #include #include #include @@ -14,22 +14,22 @@ class SaveMap final std::shared_ptr parent_; // Индивидуальные значения - std::map save_long; - std::map save_double; - std::map save_string; - std::map save_objects; + std::unordered_map save_long; + std::unordered_map save_double; + std::unordered_map save_string; + std::unordered_map save_objects; // Массивы - std::map> save_vector_integer; - std::map> save_vector_double; - std::map> save_vector_objects; - std::map> save_vector_strings; + std::unordered_map> save_vector_integer; + std::unordered_map> save_vector_double; + std::unordered_map> save_vector_objects; + std::unordered_map> save_vector_strings; // Связаные списки - std::map> save_list_integer; - std::map> save_list_double; - std::map> save_list_objects; - std::map> save_list_strings; + std::unordered_map> save_list_integer; + std::unordered_map> save_list_double; + std::unordered_map> save_list_objects; + std::unordered_map> save_list_strings; static ISave* MakeObjectByName(const std::string& name); diff --git a/Core/Types/UString.cpp b/Core/Types/UString.cpp deleted file mode 100644 index 16745cc..0000000 --- a/Core/Types/UString.cpp +++ /dev/null @@ -1,131 +0,0 @@ -#include "UString.hpp" - -#include - -unsigned int UString::FNV1aHash(const char* buf) -{ - unsigned int h_val = 0x811c9dc5; - - while (*buf) - { - h_val ^= static_cast(*buf++); - h_val *= 0x01000193; - } - - return h_val; -} - -UString::UString(const char* str) -{ - if (str == nullptr) - return; - size_ = strlen(str); - - str_ = new char[size_ + 1]; - for (size_t i = 0; i < size_; ++i) - str_[i] = str[i]; - str_[size_] = '\0'; - - hash_ = FNV1aHash(str); -} - -UString::UString(const UString& str) : size_(str.size_) -{ - if (size_ != 0 && str.str_ != nullptr) - { - str_ = new char[str.size_ + 1]; - strcpy_s(str_, size_ + 1, str.str_); - } - hash_ = str.hash_; -} - -UString::UString(UString&& str) noexcept -{ - is_moved_.store(true); - str_ = str.str_; - size_ = str.size_; - hash_ = str.hash_; -} - -UString::~UString() -{ - if (is_moved_.load() == false) - delete[] str_; -} - -UString& UString::operator=(const UString& str) -{ - if (&str != this) - { - if (size_ != 0 && str.str_ != nullptr) - { - str_ = new char[str.size_]; - strcpy_s(str_, size_, str.str_); - } - } - is_moved_.store(false); - hash_ = FNV1aHash(str_); - return *this; -} - -UString& UString::operator=(UString&& str) noexcept -{ - str.is_moved_.store(true); - str_ = str.str_; - size_ = str.size_; - is_moved_.store(false); - hash_ = FNV1aHash(str_); - return *this; -} - -void UString::operator+=(const UString& str) -{ - char* new_str = new char[size_ + str.size_ + 1]; - strcpy_s(new_str, size_ + str.size_ + 1, str_); - strcpy_s(new_str + size_, str.size_ + 1, str.str_); - - if (is_moved_.load() == false) - delete[] str_; - str_ = new_str; - size_ += str.size_; - - is_moved_.store(false); - hash_ = FNV1aHash(str_); -} - -void UString::operator+=(const char* str) -{ - size_t str_size = strlen(str); - char* new_str = new char[size_ + str_size + 1]; - strcpy_s(new_str, size_ + str_size + 1, str_); - strcpy_s(new_str + size_, str_size + 1, str); - - if (is_moved_.load() == false) - delete[] str_; - str_ = new_str; - size_ += str_size; - - is_moved_.store(false); - hash_ = FNV1aHash(str_); -} - -bool UString::operator==(const UString& str) const -{ - return hash_ == str.hash_; -} - -bool UString::operator==(const char* str) const -{ - unsigned int hash = FNV1aHash(str); - return hash_ == hash; -} - -bool UString::operator!=(const UString& str) const -{ - return !(*this == str); -} - -bool UString::operator!=(const char* str) const -{ - return !(*this == str); -} diff --git a/Core/Types/UString.hpp b/Core/Types/UString.hpp deleted file mode 100644 index 8c863ae..0000000 --- a/Core/Types/UString.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include - -class UString -{ - unsigned int hash_ = 0; - std::atomic_bool is_moved_ = false; - char* str_ = nullptr; - size_t size_ = 0; - - static unsigned int FNV1aHash (const char *buf); -public: - UString(const char* str); - UString(const UString& str); - UString(UString&& str) noexcept; - ~UString(); - - UString& operator=(const UString& str); - UString& operator=(UString&& str) noexcept; - void operator+=(const UString& str); - void operator+=(const char* str); - bool operator==(const UString& str) const; - bool operator==(const char* str) const; - bool operator!=(const UString& str) const; - bool operator!=(const char* str) const; - - size_t length() const { return size_; } - const char* c_str() const { return str_; } - std::string std_str() const { return std::string(str_, size_); } -}; diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 8e0ad46..3c605de 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -11,10 +11,8 @@ FetchContent_MakeAvailable(googletest) enable_testing() file(GLOB SRC - "UStringTest.cpp" "SaveMapTest.cpp" - "${PROJECT_SOURCE_DIR}/Core/Types/UString.cpp" "${PROJECT_SOURCE_DIR}/Core/Game/SaveMap/SaveMap.cpp" ) diff --git a/Tests/UStringTest.cpp b/Tests/UStringTest.cpp deleted file mode 100644 index 19de15d..0000000 --- a/Tests/UStringTest.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include "Types/UString.hpp" -#include - -TEST(UStringTest, creae_string) -{ - UString str("Hello, World!"); - EXPECT_EQ(str, "Hello, World!"); - EXPECT_NE(str, "Hello, UwU!"); - EXPECT_EQ(str.length(), 13); -} - -TEST(UStringTest, concatenate_string) -{ - UString str1("Hello, "); - UString str2("World!"); - str1 += str2; - EXPECT_EQ(str1, "Hello, World!"); - EXPECT_EQ(str1.length(), 13); - - UString str3("Hello, "); - str3 += "UwU!"; - EXPECT_EQ(str3, "Hello, UwU!"); - EXPECT_EQ(str3.length(), 11); -} \ No newline at end of file From 4e58512567b8d76e0336c0037c1c75aa0abc514a Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Wed, 15 Oct 2025 18:49:28 +0700 Subject: [PATCH 10/19] Replaced hard pointers to shared_ptr in SaveMap --- Core/Game/SaveMap/SaveMap.cpp | 32 +++++++++++------------ Core/Game/SaveMap/SaveMap.hpp | 20 +++++++------- Tests/SaveMapTest.cpp | 49 +++++------------------------------ 3 files changed, 32 insertions(+), 69 deletions(-) diff --git a/Core/Game/SaveMap/SaveMap.cpp b/Core/Game/SaveMap/SaveMap.cpp index 17a8c6c..01a6301 100644 --- a/Core/Game/SaveMap/SaveMap.cpp +++ b/Core/Game/SaveMap/SaveMap.cpp @@ -7,18 +7,18 @@ extern std::vector factories; extern std::vector base_object_factories; -ISave* SaveMap::MakeObjectByName(const std::string& name) +std::shared_ptr SaveMap::MakeObjectByName(const std::string& name) { for (ObjectFactory& factory : base_object_factories) { if (name == factory.name) { - return factory.factory(); + return std::shared_ptr(factory.factory()); } } for (ObjectFactory& factory : factories) { if (name == factory.name) { - return factory.factory(); + return std::shared_ptr(factory.factory()); } } throw std::runtime_error("Object not found"); @@ -95,7 +95,7 @@ SaveMap::SaveMap(const std::string& json_data) end = object_json.find('\"', begin); std::string object_name = object_json.substr(begin, end - begin); - ISave* object_ptr = MakeObjectByName(object_name); + std::shared_ptr object_ptr = MakeObjectByName(object_name); object_ptr->load(std::make_shared(object_json)); save_objects[name.c_str() + 1] = object_ptr; @@ -169,10 +169,10 @@ SaveMap::SaveMap(const std::string& json_data) } } else if (name[1] == 'o') { - save_vector_objects[key] = std::vector(); + save_vector_objects[key] = std::vector>(); if (arr_data.length() == 2) continue; - std::vector& vector_object = save_vector_objects[key]; + std::vector>& vector_object = save_vector_objects[key]; size_t j = 1; while (j < arr_data.length()) @@ -196,7 +196,7 @@ SaveMap::SaveMap(const std::string& json_data) size_t end_name = object_json.find('\"', begin_name); std::string object_name = object_json.substr(begin_name, end_name - begin_name); - ISave* object_ptr = MakeObjectByName(object_name); + std::shared_ptr object_ptr = MakeObjectByName(object_name); object_ptr->load(std::make_shared(object_json)); vector_object.push_back(object_ptr); @@ -270,10 +270,10 @@ SaveMap::SaveMap(const std::string& json_data) } } else if (name[1] == 'o') { - save_list_objects[key] = std::list(); + save_list_objects[key] = std::list>(); if (arr_data.length() == 2) continue; - std::list& list_object = save_list_objects[key]; + std::list>& list_object = save_list_objects[key]; size_t j = 1; while (j < arr_data.length()) @@ -297,7 +297,7 @@ SaveMap::SaveMap(const std::string& json_data) size_t end_name = object_json.find('\"', begin_name); std::string object_name = object_json.substr(begin_name, end_name - begin_name); - ISave* object_ptr = MakeObjectByName(object_name); + std::shared_ptr object_ptr = MakeObjectByName(object_name); object_ptr->load(std::make_shared(object_json)); list_object.push_back(object_ptr); @@ -387,7 +387,7 @@ std::shared_ptr SaveMap::SaveString(const char* name, const std::string return std::shared_ptr(this); } -std::shared_ptr SaveMap::SaveObject(const char* name, ISave* object) noexcept +std::shared_ptr SaveMap::SaveObject(const char* name, std::shared_ptr object) noexcept { save_objects[name] = object; return std::shared_ptr(this); @@ -411,7 +411,7 @@ std::shared_ptr SaveMap::SaveVectorStrings(const char* name, std::vecto return std::shared_ptr(this); } -std::shared_ptr SaveMap::SaveVectorObject(const char* name, std::vector&& value) noexcept +std::shared_ptr SaveMap::SaveVectorObject(const char* name, std::vector>&& value) noexcept { save_vector_objects[name] = std::move(value); return std::shared_ptr(this); @@ -435,7 +435,7 @@ std::shared_ptr SaveMap::SaveListStrings(const char* name, std::list(this); } -std::shared_ptr SaveMap::SaveListObject(const char* name, std::list&& value) noexcept +std::shared_ptr SaveMap::SaveListObject(const char* name, std::list>&& value) noexcept { save_list_objects[name] = std::move(value); return std::shared_ptr(this); @@ -456,7 +456,7 @@ std::string SaveMap::GetString(const char* name) return save_string[name]; } -ISave* SaveMap::GetObject(const char* name) +std::shared_ptr& SaveMap::GetObject(const char* name) { return save_objects[name]; } @@ -476,7 +476,7 @@ std::vector SaveMap::GetVectorString(const char* name) return save_vector_strings[name]; } -std::vector& SaveMap::GetVectorObject(const char* name) +std::vector>& SaveMap::GetVectorObject(const char* name) { return save_vector_objects[name]; } @@ -496,7 +496,7 @@ std::list& SaveMap::GetListString(const char* name) return save_list_strings[name]; } -std::list& SaveMap::GetListObject(const char* name) +std::list>& SaveMap::GetListObject(const char* name) { return save_list_objects[name]; } diff --git a/Core/Game/SaveMap/SaveMap.hpp b/Core/Game/SaveMap/SaveMap.hpp index efebe20..0649c7e 100644 --- a/Core/Game/SaveMap/SaveMap.hpp +++ b/Core/Game/SaveMap/SaveMap.hpp @@ -17,21 +17,21 @@ class SaveMap final std::unordered_map save_long; std::unordered_map save_double; std::unordered_map save_string; - std::unordered_map save_objects; + std::unordered_map> save_objects; // Массивы std::unordered_map> save_vector_integer; std::unordered_map> save_vector_double; - std::unordered_map> save_vector_objects; + std::unordered_map>> save_vector_objects; std::unordered_map> save_vector_strings; // Связаные списки std::unordered_map> save_list_integer; std::unordered_map> save_list_double; - std::unordered_map> save_list_objects; + std::unordered_map>> save_list_objects; std::unordered_map> save_list_strings; - static ISave* MakeObjectByName(const std::string& name); + static std::shared_ptr MakeObjectByName(const std::string& name); public: // Создаёт пустой объект для заполнения @@ -47,29 +47,29 @@ public: std::shared_ptr SaveInteger(const char* name, int value) noexcept; std::shared_ptr SaveDouble(const char* name, double value) noexcept; std::shared_ptr SaveString(const char* name, const std::string& value) noexcept; - std::shared_ptr SaveObject(const char* name, ISave* object) noexcept; + std::shared_ptr SaveObject(const char* name, std::shared_ptr object) noexcept; std::shared_ptr SaveVectorInteger(const char* name, std::vector&& value) noexcept; std::shared_ptr SaveVectorDouble(const char* name, std::vector&& value) noexcept; std::shared_ptr SaveVectorStrings(const char* name, std::vector&& value) noexcept; - std::shared_ptr SaveVectorObject(const char* name, std::vector&& value) noexcept; + std::shared_ptr SaveVectorObject(const char* name, std::vector>&& value) noexcept; std::shared_ptr SaveListInteger(const char* name, std::list&& value) noexcept; std::shared_ptr SaveListDouble(const char* name, std::list&& value) noexcept; std::shared_ptr SaveListStrings(const char* name, std::list&& value) noexcept; - std::shared_ptr SaveListObject(const char* name, std::list&& value) noexcept; + std::shared_ptr SaveListObject(const char* name, std::list>&& value) noexcept; // Методы получения значенй long long GetInteger(const char* name); double GetDouble(const char* name); std::string GetString(const char* name); - ISave* GetObject(const char* name); + std::shared_ptr& GetObject(const char* name); std::vector& GetVectorInteger(const char* name); std::vector& GetVectorDouble(const char* name); std::vector GetVectorString(const char* name); - std::vector& GetVectorObject(const char* name); + std::vector>& GetVectorObject(const char* name); std::list& GetListInteger(const char* name); std::list& GetListDouble(const char* name); std::list& GetListString(const char* name); - std::list& GetListObject(const char* name); + std::list>& GetListObject(const char* name); std::shared_ptr getParent() const { return parent_; } const std::string& getClassName() const { return class_name; } diff --git a/Tests/SaveMapTest.cpp b/Tests/SaveMapTest.cpp index 29fa958..acc2391 100644 --- a/Tests/SaveMapTest.cpp +++ b/Tests/SaveMapTest.cpp @@ -17,7 +17,7 @@ public: } void load(std::shared_ptr save) override { - num = save->GetInteger("num"); + num = static_cast(save->GetInteger("num")); str = save->GetString("str"); dbl = save->GetDouble("dbl"); } @@ -99,24 +99,6 @@ TEST(SaveMapTest, check_load_with_custom_type) std::string json = "{\n" "\t\"Class name\": \"test class\",\n" - "\t\"iTestInt\": 123,\n" - "\t\"dTestDouble\": 123.56,\n" - "\t\"sTestString\": \"string str\",\n" - "\t\"viTestVectorInt\": [\n" - "\t\t1,\n" - "\t\t2,\n" - "\t\t3\n" - "\t],\n" - "\t\"vdTestVectorDouble\": [\n" - "\t\t1.2,\n" - "\t\t3.4,\n" - "\t\t5.6\n" - "\t],\n" - "\t\t\"vsTestVectorString\": [\n" - "\t\t\"str 1\",\n" - "\t\t\"2 str\",\n" - "\t\t\"str 3 str\"\n" - "\t],\n" "\t\"oCustomObject\": {\n" "\t\t\"Class name\": \"CustomObject\",\n" "\t\t\"inum\": 123,\n" @@ -138,34 +120,17 @@ TEST(SaveMapTest, check_load_with_custom_type) "}" "]" "}"; - - std::vector test_vector_int = { 1, 2, 3 }; - std::vector test_vector_double = { 1.2, 3.4, 5.6 }; - std::vector test_vector_string = { "str 1", "2 str", "str 3 str" }; SaveMap save_map(json); + - EXPECT_EQ(save_map.GetInteger("TestInt"), 123); - EXPECT_EQ(save_map.GetDouble("TestDouble"), 123.56); - EXPECT_EQ(save_map.GetString("TestString"), "string str"); - - EXPECT_EQ(save_map.GetVectorInteger("TestVectorInt").size(), 3); - EXPECT_EQ(save_map.GetVectorDouble("TestVectorDouble").size(), 3); - EXPECT_EQ(save_map.GetVectorString("TestVectorString").size(), 3); - for (auto i = 0; i < 3; i++) - { - EXPECT_EQ(test_vector_int[i], save_map.GetVectorInteger("TestVectorInt")[i]); - EXPECT_EQ(test_vector_double[i], save_map.GetVectorDouble("TestVectorDouble")[i]); - EXPECT_EQ(test_vector_string[i], save_map.GetVectorString("TestVectorString")[i]); - } - - CustomObject* obj = reinterpret_cast(save_map.GetObject("CustomObject")); + std::shared_ptr obj = reinterpret_cast&>(save_map.GetObject("CustomObject")); CustomObject test_obj; test_obj.num = 123; test_obj.str = "str123"; test_obj.dbl = 123.45; - EXPECT_EQ(*obj, test_obj); + EXPECT_EQ(*obj.get(), test_obj); - std::vector vec_obj = reinterpret_cast&>(save_map.GetVectorObject("CustomObjects")); + std::vector> vec_obj = reinterpret_cast>&>(save_map.GetVectorObject("CustomObjects")); std::vector vec_obj_test = { new CustomObject, new CustomObject, @@ -178,8 +143,6 @@ TEST(SaveMapTest, check_load_with_custom_type) vec_obj_test[1]->dbl = 543.21; for (auto i = 0; i < 2; i++) { - EXPECT_EQ(*vec_obj[i], *vec_obj_test[i]); - delete vec_obj[i]; - delete vec_obj_test[i]; + EXPECT_EQ(*vec_obj[i].get(), *vec_obj_test[i]); } } \ No newline at end of file From 938b76ac075b2cf67c846a64ea793fd131091ff6 Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Wed, 15 Oct 2025 18:59:42 +0700 Subject: [PATCH 11/19] Revert "Replaced hard pointers to shared_ptr in SaveMap" This reverts commit 4e58512567b8d76e0336c0037c1c75aa0abc514a. --- Core/Game/SaveMap/SaveMap.cpp | 32 +++++++++++----------- Core/Game/SaveMap/SaveMap.hpp | 20 +++++++------- Tests/SaveMapTest.cpp | 51 ++++++++++++++++++++++++++++++----- 3 files changed, 70 insertions(+), 33 deletions(-) diff --git a/Core/Game/SaveMap/SaveMap.cpp b/Core/Game/SaveMap/SaveMap.cpp index 01a6301..17a8c6c 100644 --- a/Core/Game/SaveMap/SaveMap.cpp +++ b/Core/Game/SaveMap/SaveMap.cpp @@ -7,18 +7,18 @@ extern std::vector factories; extern std::vector base_object_factories; -std::shared_ptr SaveMap::MakeObjectByName(const std::string& name) +ISave* SaveMap::MakeObjectByName(const std::string& name) { for (ObjectFactory& factory : base_object_factories) { if (name == factory.name) { - return std::shared_ptr(factory.factory()); + return factory.factory(); } } for (ObjectFactory& factory : factories) { if (name == factory.name) { - return std::shared_ptr(factory.factory()); + return factory.factory(); } } throw std::runtime_error("Object not found"); @@ -95,7 +95,7 @@ SaveMap::SaveMap(const std::string& json_data) end = object_json.find('\"', begin); std::string object_name = object_json.substr(begin, end - begin); - std::shared_ptr object_ptr = MakeObjectByName(object_name); + ISave* object_ptr = MakeObjectByName(object_name); object_ptr->load(std::make_shared(object_json)); save_objects[name.c_str() + 1] = object_ptr; @@ -169,10 +169,10 @@ SaveMap::SaveMap(const std::string& json_data) } } else if (name[1] == 'o') { - save_vector_objects[key] = std::vector>(); + save_vector_objects[key] = std::vector(); if (arr_data.length() == 2) continue; - std::vector>& vector_object = save_vector_objects[key]; + std::vector& vector_object = save_vector_objects[key]; size_t j = 1; while (j < arr_data.length()) @@ -196,7 +196,7 @@ SaveMap::SaveMap(const std::string& json_data) size_t end_name = object_json.find('\"', begin_name); std::string object_name = object_json.substr(begin_name, end_name - begin_name); - std::shared_ptr object_ptr = MakeObjectByName(object_name); + ISave* object_ptr = MakeObjectByName(object_name); object_ptr->load(std::make_shared(object_json)); vector_object.push_back(object_ptr); @@ -270,10 +270,10 @@ SaveMap::SaveMap(const std::string& json_data) } } else if (name[1] == 'o') { - save_list_objects[key] = std::list>(); + save_list_objects[key] = std::list(); if (arr_data.length() == 2) continue; - std::list>& list_object = save_list_objects[key]; + std::list& list_object = save_list_objects[key]; size_t j = 1; while (j < arr_data.length()) @@ -297,7 +297,7 @@ SaveMap::SaveMap(const std::string& json_data) size_t end_name = object_json.find('\"', begin_name); std::string object_name = object_json.substr(begin_name, end_name - begin_name); - std::shared_ptr object_ptr = MakeObjectByName(object_name); + ISave* object_ptr = MakeObjectByName(object_name); object_ptr->load(std::make_shared(object_json)); list_object.push_back(object_ptr); @@ -387,7 +387,7 @@ std::shared_ptr SaveMap::SaveString(const char* name, const std::string return std::shared_ptr(this); } -std::shared_ptr SaveMap::SaveObject(const char* name, std::shared_ptr object) noexcept +std::shared_ptr SaveMap::SaveObject(const char* name, ISave* object) noexcept { save_objects[name] = object; return std::shared_ptr(this); @@ -411,7 +411,7 @@ std::shared_ptr SaveMap::SaveVectorStrings(const char* name, std::vecto return std::shared_ptr(this); } -std::shared_ptr SaveMap::SaveVectorObject(const char* name, std::vector>&& value) noexcept +std::shared_ptr SaveMap::SaveVectorObject(const char* name, std::vector&& value) noexcept { save_vector_objects[name] = std::move(value); return std::shared_ptr(this); @@ -435,7 +435,7 @@ std::shared_ptr SaveMap::SaveListStrings(const char* name, std::list(this); } -std::shared_ptr SaveMap::SaveListObject(const char* name, std::list>&& value) noexcept +std::shared_ptr SaveMap::SaveListObject(const char* name, std::list&& value) noexcept { save_list_objects[name] = std::move(value); return std::shared_ptr(this); @@ -456,7 +456,7 @@ std::string SaveMap::GetString(const char* name) return save_string[name]; } -std::shared_ptr& SaveMap::GetObject(const char* name) +ISave* SaveMap::GetObject(const char* name) { return save_objects[name]; } @@ -476,7 +476,7 @@ std::vector SaveMap::GetVectorString(const char* name) return save_vector_strings[name]; } -std::vector>& SaveMap::GetVectorObject(const char* name) +std::vector& SaveMap::GetVectorObject(const char* name) { return save_vector_objects[name]; } @@ -496,7 +496,7 @@ std::list& SaveMap::GetListString(const char* name) return save_list_strings[name]; } -std::list>& SaveMap::GetListObject(const char* name) +std::list& SaveMap::GetListObject(const char* name) { return save_list_objects[name]; } diff --git a/Core/Game/SaveMap/SaveMap.hpp b/Core/Game/SaveMap/SaveMap.hpp index 0649c7e..efebe20 100644 --- a/Core/Game/SaveMap/SaveMap.hpp +++ b/Core/Game/SaveMap/SaveMap.hpp @@ -17,21 +17,21 @@ class SaveMap final std::unordered_map save_long; std::unordered_map save_double; std::unordered_map save_string; - std::unordered_map> save_objects; + std::unordered_map save_objects; // Массивы std::unordered_map> save_vector_integer; std::unordered_map> save_vector_double; - std::unordered_map>> save_vector_objects; + std::unordered_map> save_vector_objects; std::unordered_map> save_vector_strings; // Связаные списки std::unordered_map> save_list_integer; std::unordered_map> save_list_double; - std::unordered_map>> save_list_objects; + std::unordered_map> save_list_objects; std::unordered_map> save_list_strings; - static std::shared_ptr MakeObjectByName(const std::string& name); + static ISave* MakeObjectByName(const std::string& name); public: // Создаёт пустой объект для заполнения @@ -47,29 +47,29 @@ public: std::shared_ptr SaveInteger(const char* name, int value) noexcept; std::shared_ptr SaveDouble(const char* name, double value) noexcept; std::shared_ptr SaveString(const char* name, const std::string& value) noexcept; - std::shared_ptr SaveObject(const char* name, std::shared_ptr object) noexcept; + std::shared_ptr SaveObject(const char* name, ISave* object) noexcept; std::shared_ptr SaveVectorInteger(const char* name, std::vector&& value) noexcept; std::shared_ptr SaveVectorDouble(const char* name, std::vector&& value) noexcept; std::shared_ptr SaveVectorStrings(const char* name, std::vector&& value) noexcept; - std::shared_ptr SaveVectorObject(const char* name, std::vector>&& value) noexcept; + std::shared_ptr SaveVectorObject(const char* name, std::vector&& value) noexcept; std::shared_ptr SaveListInteger(const char* name, std::list&& value) noexcept; std::shared_ptr SaveListDouble(const char* name, std::list&& value) noexcept; std::shared_ptr SaveListStrings(const char* name, std::list&& value) noexcept; - std::shared_ptr SaveListObject(const char* name, std::list>&& value) noexcept; + std::shared_ptr SaveListObject(const char* name, std::list&& value) noexcept; // Методы получения значенй long long GetInteger(const char* name); double GetDouble(const char* name); std::string GetString(const char* name); - std::shared_ptr& GetObject(const char* name); + ISave* GetObject(const char* name); std::vector& GetVectorInteger(const char* name); std::vector& GetVectorDouble(const char* name); std::vector GetVectorString(const char* name); - std::vector>& GetVectorObject(const char* name); + std::vector& GetVectorObject(const char* name); std::list& GetListInteger(const char* name); std::list& GetListDouble(const char* name); std::list& GetListString(const char* name); - std::list>& GetListObject(const char* name); + std::list& GetListObject(const char* name); std::shared_ptr getParent() const { return parent_; } const std::string& getClassName() const { return class_name; } diff --git a/Tests/SaveMapTest.cpp b/Tests/SaveMapTest.cpp index acc2391..29fa958 100644 --- a/Tests/SaveMapTest.cpp +++ b/Tests/SaveMapTest.cpp @@ -17,7 +17,7 @@ public: } void load(std::shared_ptr save) override { - num = static_cast(save->GetInteger("num")); + num = save->GetInteger("num"); str = save->GetString("str"); dbl = save->GetDouble("dbl"); } @@ -99,6 +99,24 @@ TEST(SaveMapTest, check_load_with_custom_type) std::string json = "{\n" "\t\"Class name\": \"test class\",\n" + "\t\"iTestInt\": 123,\n" + "\t\"dTestDouble\": 123.56,\n" + "\t\"sTestString\": \"string str\",\n" + "\t\"viTestVectorInt\": [\n" + "\t\t1,\n" + "\t\t2,\n" + "\t\t3\n" + "\t],\n" + "\t\"vdTestVectorDouble\": [\n" + "\t\t1.2,\n" + "\t\t3.4,\n" + "\t\t5.6\n" + "\t],\n" + "\t\t\"vsTestVectorString\": [\n" + "\t\t\"str 1\",\n" + "\t\t\"2 str\",\n" + "\t\t\"str 3 str\"\n" + "\t],\n" "\t\"oCustomObject\": {\n" "\t\t\"Class name\": \"CustomObject\",\n" "\t\t\"inum\": 123,\n" @@ -120,17 +138,34 @@ TEST(SaveMapTest, check_load_with_custom_type) "}" "]" "}"; - SaveMap save_map(json); - - std::shared_ptr obj = reinterpret_cast&>(save_map.GetObject("CustomObject")); + std::vector test_vector_int = { 1, 2, 3 }; + std::vector test_vector_double = { 1.2, 3.4, 5.6 }; + std::vector test_vector_string = { "str 1", "2 str", "str 3 str" }; + SaveMap save_map(json); + + EXPECT_EQ(save_map.GetInteger("TestInt"), 123); + EXPECT_EQ(save_map.GetDouble("TestDouble"), 123.56); + EXPECT_EQ(save_map.GetString("TestString"), "string str"); + + EXPECT_EQ(save_map.GetVectorInteger("TestVectorInt").size(), 3); + EXPECT_EQ(save_map.GetVectorDouble("TestVectorDouble").size(), 3); + EXPECT_EQ(save_map.GetVectorString("TestVectorString").size(), 3); + for (auto i = 0; i < 3; i++) + { + EXPECT_EQ(test_vector_int[i], save_map.GetVectorInteger("TestVectorInt")[i]); + EXPECT_EQ(test_vector_double[i], save_map.GetVectorDouble("TestVectorDouble")[i]); + EXPECT_EQ(test_vector_string[i], save_map.GetVectorString("TestVectorString")[i]); + } + + CustomObject* obj = reinterpret_cast(save_map.GetObject("CustomObject")); CustomObject test_obj; test_obj.num = 123; test_obj.str = "str123"; test_obj.dbl = 123.45; - EXPECT_EQ(*obj.get(), test_obj); + EXPECT_EQ(*obj, test_obj); - std::vector> vec_obj = reinterpret_cast>&>(save_map.GetVectorObject("CustomObjects")); + std::vector vec_obj = reinterpret_cast&>(save_map.GetVectorObject("CustomObjects")); std::vector vec_obj_test = { new CustomObject, new CustomObject, @@ -143,6 +178,8 @@ TEST(SaveMapTest, check_load_with_custom_type) vec_obj_test[1]->dbl = 543.21; for (auto i = 0; i < 2; i++) { - EXPECT_EQ(*vec_obj[i].get(), *vec_obj_test[i]); + EXPECT_EQ(*vec_obj[i], *vec_obj_test[i]); + delete vec_obj[i]; + delete vec_obj_test[i]; } } \ No newline at end of file From 136235749a3a98d965e8a384cf109cce7c2a090c Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Fri, 17 Oct 2025 21:11:09 +0700 Subject: [PATCH 12/19] Add custom soft pointer "object_ptr" and tests for this --- Core/Types/object_ptr.cpp | 3 + Core/Types/object_ptr.hpp | 164 ++++++++++++++++++++++++++++++++++++++ Tests/CMakeLists.txt | 2 + Tests/ObjectPtrTest.cpp | 26 ++++++ 4 files changed, 195 insertions(+) create mode 100644 Core/Types/object_ptr.cpp create mode 100644 Core/Types/object_ptr.hpp create mode 100644 Tests/ObjectPtrTest.cpp diff --git a/Core/Types/object_ptr.cpp b/Core/Types/object_ptr.cpp new file mode 100644 index 0000000..eb83a39 --- /dev/null +++ b/Core/Types/object_ptr.cpp @@ -0,0 +1,3 @@ +#include "object_ptr.hpp" + +std::unordered_map UType::counter::owners_map; \ No newline at end of file diff --git a/Core/Types/object_ptr.hpp b/Core/Types/object_ptr.hpp new file mode 100644 index 0000000..1e144b5 --- /dev/null +++ b/Core/Types/object_ptr.hpp @@ -0,0 +1,164 @@ + +#pragma once + +#include +#include +#include + +namespace UType +{ + template + class object_ptr; + + class counter + { + struct counter_owners + { + std::atomic_bool is_destroyed; + std::mutex mutex; + std::list owners; + + counter_owners() + : is_destroyed(false) + { + } + + counter_owners(const counter_owners&) = delete; + counter_owners& operator=(const counter_owners&) = delete; + + counter_owners(counter_owners&& other) noexcept + : is_destroyed(other.is_destroyed.load()) + , owners(std::move(other.owners)) + { + } + + counter_owners& operator=(counter_owners&& other) noexcept + { + if (this != &other) + { + is_destroyed.store(other.is_destroyed.load()); + owners = std::move(other.owners); + } + return *this; + } + }; + static std::unordered_map owners_map; + + public: + template +static void add_owner(object_ptr& ptr) + { + auto counter = owners_map.find(ptr.ptr_.load()); + if (counter == owners_map.end()) + { + counter_owners owners; + owners.owners.push_back(&ptr); + auto [it, inserted] = owners_map.try_emplace(ptr.ptr_.load(), std::move(owners)); + if (!inserted) + { + ptr.ptr_.store(nullptr); + } + } + else if (!counter->second.is_destroyed) + { + std::lock_guard lock(counter->second.mutex); + counter->second.owners.push_back(&ptr); + } + else + ptr.ptr_.store(nullptr); + } + + template + static void remove_owner(object_ptr& ptr) + { + auto counter = owners_map.find(ptr.ptr_); + if (counter != owners_map.end()) + { + counter->second.owners.remove(&ptr); + + if (counter->second.is_destroyed) + { + ptr.ptr_.store(nullptr); + } + else if (counter->second.owners.empty()) + { + counter->second.is_destroyed.store(true); + for (auto& owner : counter->second.owners) + static_cast*>(owner)->ptr_.store(nullptr); + delete static_cast(counter->first); + owners_map.erase(counter); + } + } + } + + template + static void remove_object(Ty* ptr) + { + auto counter = owners_map.find(ptr); + if (counter != owners_map.end()) + { + counter->second.is_destroyed.store(true); + for (auto& owner : counter->second.owners) + static_cast*>(owner)->ptr_.store(nullptr); + delete ptr; + owners_map.erase(counter); + } + } + }; + + template + class object_ptr + { + std::atomic ptr_; + public: + object_ptr(Ty* ptr = nullptr) + { + ptr_.store(ptr); + if (ptr) counter::add_owner(*this); + } + + object_ptr(const object_ptr& ptr) + { + ptr_.store(ptr.ptr_); + if (ptr.ptr_) counter::add_owner(*this); + } + + object_ptr(object_ptr&& ptr) noexcept + { + ptr_.store(ptr.ptr_); + if (ptr.ptr_) counter::add_owner(*this); + ptr.ptr_.store(nullptr); + } + + ~object_ptr() + { + if (ptr_) counter::remove_owner(*this); + } + + void reset(Ty* new_ptr = nullptr) + { + if (ptr_) counter::remove_owner(*this); + ptr_.store(new_ptr); + if (new_ptr) counter::add_owner(*this); + } + + void reset(const object_ptr& ptr) + { + if (ptr_) counter::remove_owner(*this); + ptr_.store(ptr.ptr_); + if (ptr.ptr_) counter::add_owner(*this); + } + + void destroy() + { + if (ptr_) counter::remove_object(ptr_); + } + + Ty* get() const noexcept { return ptr_.load(); } + Ty& operator*() const noexcept { return *ptr_; } + Ty* operator->() const noexcept { return ptr_.load(); } + operator bool() const noexcept { return ptr_.load() != nullptr; } + + friend class counter; + }; +} \ No newline at end of file diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 3c605de..696181f 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -12,8 +12,10 @@ enable_testing() file(GLOB SRC "SaveMapTest.cpp" + "ObjectPtrTest.cpp" "${PROJECT_SOURCE_DIR}/Core/Game/SaveMap/SaveMap.cpp" + "${PROJECT_SOURCE_DIR}/Core/Types/object_ptr.cpp" ) add_executable(Tests ${SRC}) diff --git a/Tests/ObjectPtrTest.cpp b/Tests/ObjectPtrTest.cpp new file mode 100644 index 0000000..dafe324 --- /dev/null +++ b/Tests/ObjectPtrTest.cpp @@ -0,0 +1,26 @@ +#include +#include "Types/object_ptr.hpp" + +TEST(object_ptr_test, base_test) +{ + int* test = new int(123); + UType::object_ptr ptr(test); + EXPECT_EQ(*ptr.get(), 123); + + UType::object_ptr ptr2(ptr); + EXPECT_EQ(*ptr2.get(), 123); + EXPECT_EQ(ptr2.get(), ptr.get()); + + ptr.destroy(); + EXPECT_EQ(ptr.get(), nullptr); + EXPECT_EQ(ptr2.get(), nullptr); +} + +TEST(object_ptr_test, check_destry) +{ + UType::object_ptr ptr(new int(123)), ptr2(ptr); + + ptr.destroy(); + EXPECT_EQ(ptr.get(), nullptr); + EXPECT_EQ(ptr2.get(), nullptr); +} \ No newline at end of file From 137522cefa6057ac3a212240911fe01cc00671c5 Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Fri, 17 Oct 2025 21:39:30 +0700 Subject: [PATCH 13/19] Move to object_ptr --- Core/Game/Actors/Actor.cpp | 16 ++++++++-------- Core/Game/Actors/Actor.hpp | 9 ++++----- Core/Game/SaveMap/SaveMap.cpp | 26 +++++++++++++------------- Core/Game/SaveMap/SaveMap.hpp | 19 ++++++++++--------- Core/Game/World/World.cpp | 6 ++---- Core/Game/World/World.hpp | 5 +++-- Core/Types/object_ptr.hpp | 13 ++++++++++++- Tests/SaveMapTest.cpp | 12 ++++++------ 8 files changed, 58 insertions(+), 48 deletions(-) diff --git a/Core/Game/Actors/Actor.cpp b/Core/Game/Actors/Actor.cpp index dce154a..8269f6e 100644 --- a/Core/Game/Actors/Actor.cpp +++ b/Core/Game/Actors/Actor.cpp @@ -16,17 +16,17 @@ Actor::Actor() std::shared_ptr Actor::save() { return std::make_shared("Actor") - ->SaveObject("loc", &loc) - ->SaveObject("rot", &rot) - ->SaveObject("scale", &scale) + ->SaveObject("loc", static_cast>(loc)) + ->SaveObject("rot", static_cast>(rot)) + ->SaveObject("scale", UType::object_ptr(scale)) ->SaveListStrings("tags", std::move(tags)); } void Actor::load(std::shared_ptr save) { - loc = *reinterpret_cast(save->GetObject("loc")); - rot = *reinterpret_cast(save->GetObject("rot")); - scale = *reinterpret_cast(save->GetObject("scale")); + loc = static_cast>(save->GetObject("loc")); + rot = static_cast>(save->GetObject("rot")); + scale = static_cast>(save->GetObject("scale")); tags = std::move(save->GetListString("tags")); } @@ -41,13 +41,13 @@ void Actor::Tick(double delta_time) void Actor::SetActorLocate(const Vector3D& loc) noexcept { - this->loc = loc; + *this->loc = loc; OnSetActorLocate.Call(loc); } void Actor::SetActorRotate(const Vector3D& rot) noexcept { - this->rot = rot; + *this->rot = rot; OnSetActorRotate.Call(rot); } diff --git a/Core/Game/Actors/Actor.hpp b/Core/Game/Actors/Actor.hpp index 5901a48..bf93162 100644 --- a/Core/Game/Actors/Actor.hpp +++ b/Core/Game/Actors/Actor.hpp @@ -7,6 +7,7 @@ #include "Game/SaveMap/ISave.h" #include "Delegate/Delegate.h" #include "Math/Vector.hpp" +#include "Types/object_ptr.hpp" class World; GENERATE_META(Actor) @@ -15,9 +16,7 @@ class Actor : public ISave, public IRTTI { World* world_; - Vector3D loc; - Vector3D rot; - Vector3D scale; + UType::object_ptr loc, rot, scale; std::list tags; @@ -42,14 +41,14 @@ public: * Вызывает делегат OnSetActorLocate */ void SetActorLocate(const Vector3D& loc) noexcept; - inline const Vector3D& GetActorLocate() const { return loc; } + inline const UType::object_ptr GetActorLocate() const { return loc; } /* * Изменяет ориентацию в пространстве * Вызывает делегат OnSetActorRotate */ void SetActorRotate(const Vector3D& rot) noexcept; - inline const Vector3D& GetActorRotate() const { return rot; } + inline const UType::object_ptr GetActorRotate() const { return rot; } void AddTag(const std::string& tag) noexcept; void RemoveTag(const std::string& tag) noexcept; diff --git a/Core/Game/SaveMap/SaveMap.cpp b/Core/Game/SaveMap/SaveMap.cpp index 17a8c6c..dc148f1 100644 --- a/Core/Game/SaveMap/SaveMap.cpp +++ b/Core/Game/SaveMap/SaveMap.cpp @@ -95,7 +95,7 @@ SaveMap::SaveMap(const std::string& json_data) end = object_json.find('\"', begin); std::string object_name = object_json.substr(begin, end - begin); - ISave* object_ptr = MakeObjectByName(object_name); + UType::object_ptr object_ptr(MakeObjectByName(object_name)); object_ptr->load(std::make_shared(object_json)); save_objects[name.c_str() + 1] = object_ptr; @@ -169,10 +169,10 @@ SaveMap::SaveMap(const std::string& json_data) } } else if (name[1] == 'o') { - save_vector_objects[key] = std::vector(); + save_vector_objects[key] = std::vector>(); if (arr_data.length() == 2) continue; - std::vector& vector_object = save_vector_objects[key]; + std::vector>& vector_object = save_vector_objects[key]; size_t j = 1; while (j < arr_data.length()) @@ -196,7 +196,7 @@ SaveMap::SaveMap(const std::string& json_data) size_t end_name = object_json.find('\"', begin_name); std::string object_name = object_json.substr(begin_name, end_name - begin_name); - ISave* object_ptr = MakeObjectByName(object_name); + UType::object_ptr object_ptr(MakeObjectByName(object_name)); object_ptr->load(std::make_shared(object_json)); vector_object.push_back(object_ptr); @@ -270,10 +270,10 @@ SaveMap::SaveMap(const std::string& json_data) } } else if (name[1] == 'o') { - save_list_objects[key] = std::list(); + save_list_objects[key] = std::list>(); if (arr_data.length() == 2) continue; - std::list& list_object = save_list_objects[key]; + std::list>& list_object = save_list_objects[key]; size_t j = 1; while (j < arr_data.length()) @@ -297,7 +297,7 @@ SaveMap::SaveMap(const std::string& json_data) size_t end_name = object_json.find('\"', begin_name); std::string object_name = object_json.substr(begin_name, end_name - begin_name); - ISave* object_ptr = MakeObjectByName(object_name); + UType::object_ptr object_ptr(MakeObjectByName(object_name)); object_ptr->load(std::make_shared(object_json)); list_object.push_back(object_ptr); @@ -387,7 +387,7 @@ std::shared_ptr SaveMap::SaveString(const char* name, const std::string return std::shared_ptr(this); } -std::shared_ptr SaveMap::SaveObject(const char* name, ISave* object) noexcept +std::shared_ptr SaveMap::SaveObject(const char* name, UType::object_ptr object) noexcept { save_objects[name] = object; return std::shared_ptr(this); @@ -411,7 +411,7 @@ std::shared_ptr SaveMap::SaveVectorStrings(const char* name, std::vecto return std::shared_ptr(this); } -std::shared_ptr SaveMap::SaveVectorObject(const char* name, std::vector&& value) noexcept +std::shared_ptr SaveMap::SaveVectorObject(const char* name, std::vector>&& value) noexcept { save_vector_objects[name] = std::move(value); return std::shared_ptr(this); @@ -435,7 +435,7 @@ std::shared_ptr SaveMap::SaveListStrings(const char* name, std::list(this); } -std::shared_ptr SaveMap::SaveListObject(const char* name, std::list&& value) noexcept +std::shared_ptr SaveMap::SaveListObject(const char* name, std::list>&& value) noexcept { save_list_objects[name] = std::move(value); return std::shared_ptr(this); @@ -456,7 +456,7 @@ std::string SaveMap::GetString(const char* name) return save_string[name]; } -ISave* SaveMap::GetObject(const char* name) +UType::object_ptr SaveMap::GetObject(const char* name) { return save_objects[name]; } @@ -476,7 +476,7 @@ std::vector SaveMap::GetVectorString(const char* name) return save_vector_strings[name]; } -std::vector& SaveMap::GetVectorObject(const char* name) +std::vector>& SaveMap::GetVectorObject(const char* name) { return save_vector_objects[name]; } @@ -496,7 +496,7 @@ std::list& SaveMap::GetListString(const char* name) return save_list_strings[name]; } -std::list& SaveMap::GetListObject(const char* name) +std::list>& SaveMap::GetListObject(const char* name) { return save_list_objects[name]; } diff --git a/Core/Game/SaveMap/SaveMap.hpp b/Core/Game/SaveMap/SaveMap.hpp index efebe20..d3d2549 100644 --- a/Core/Game/SaveMap/SaveMap.hpp +++ b/Core/Game/SaveMap/SaveMap.hpp @@ -1,6 +1,7 @@ #pragma once #include "ISave.h" +#include "Types/object_ptr.hpp" #include #include @@ -17,18 +18,18 @@ class SaveMap final std::unordered_map save_long; std::unordered_map save_double; std::unordered_map save_string; - std::unordered_map save_objects; + std::unordered_map> save_objects; // Массивы std::unordered_map> save_vector_integer; std::unordered_map> save_vector_double; - std::unordered_map> save_vector_objects; + std::unordered_map>> save_vector_objects; std::unordered_map> save_vector_strings; // Связаные списки std::unordered_map> save_list_integer; std::unordered_map> save_list_double; - std::unordered_map> save_list_objects; + std::unordered_map>> save_list_objects; std::unordered_map> save_list_strings; static ISave* MakeObjectByName(const std::string& name); @@ -47,29 +48,29 @@ public: std::shared_ptr SaveInteger(const char* name, int value) noexcept; std::shared_ptr SaveDouble(const char* name, double value) noexcept; std::shared_ptr SaveString(const char* name, const std::string& value) noexcept; - std::shared_ptr SaveObject(const char* name, ISave* object) noexcept; + std::shared_ptr SaveObject(const char* name, UType::object_ptr object) noexcept; std::shared_ptr SaveVectorInteger(const char* name, std::vector&& value) noexcept; std::shared_ptr SaveVectorDouble(const char* name, std::vector&& value) noexcept; std::shared_ptr SaveVectorStrings(const char* name, std::vector&& value) noexcept; - std::shared_ptr SaveVectorObject(const char* name, std::vector&& value) noexcept; + std::shared_ptr SaveVectorObject(const char* name, std::vector>&& value) noexcept; std::shared_ptr SaveListInteger(const char* name, std::list&& value) noexcept; std::shared_ptr SaveListDouble(const char* name, std::list&& value) noexcept; std::shared_ptr SaveListStrings(const char* name, std::list&& value) noexcept; - std::shared_ptr SaveListObject(const char* name, std::list&& value) noexcept; + std::shared_ptr SaveListObject(const char* name, std::list>&& value) noexcept; // Методы получения значенй long long GetInteger(const char* name); double GetDouble(const char* name); std::string GetString(const char* name); - ISave* GetObject(const char* name); + UType::object_ptr GetObject(const char* name); std::vector& GetVectorInteger(const char* name); std::vector& GetVectorDouble(const char* name); std::vector GetVectorString(const char* name); - std::vector& GetVectorObject(const char* name); + std::vector>& GetVectorObject(const char* name); std::list& GetListInteger(const char* name); std::list& GetListDouble(const char* name); std::list& GetListString(const char* name); - std::list& GetListObject(const char* name); + std::list>& GetListObject(const char* name); std::shared_ptr getParent() const { return parent_; } const std::string& getClassName() const { return class_name; } diff --git a/Core/Game/World/World.cpp b/Core/Game/World/World.cpp index b14731b..09482dd 100644 --- a/Core/Game/World/World.cpp +++ b/Core/Game/World/World.cpp @@ -8,8 +8,6 @@ World::World(GameInstance& game_instance) : game_instance(game_instance) World::~World() { - for (auto& actor : actors) - delete actor; actors.clear(); } @@ -28,13 +26,13 @@ void World::Tick(double delta_time) std::shared_ptr World::save() { std::shared_ptr save = std::make_shared("World"); - save->SaveListObject("Actors", std::move(reinterpret_cast&>(actors))); + save->SaveListObject("Actors", std::move(reinterpret_cast>&>(actors))); return save; } void World::load(std::shared_ptr save) { - actors = std::move(reinterpret_cast&>(save->GetListObject("Actors"))); + actors = std::move(reinterpret_cast>&>(save->GetListObject("Actors"))); for (auto& i : actors) i->world_ = this; diff --git a/Core/Game/World/World.hpp b/Core/Game/World/World.hpp index df899e8..f936e07 100644 --- a/Core/Game/World/World.hpp +++ b/Core/Game/World/World.hpp @@ -7,6 +7,7 @@ #include "RTTI.h" #include "Game/Actors/Actor.hpp" #include "Game/Actors/Mesh/Mesh.hpp" +#include "Types/object_ptr.hpp" class GameInstance; @@ -16,7 +17,7 @@ class World : public ISave GameInstance& game_instance; // Actors only - std::list actors; + std::list> actors; public: World(GameInstance& game_instance); @@ -38,7 +39,7 @@ public: Container list; for (auto i = actors.cbegin(); i != actors.cend(); ++i) { - if (T* cast_object = RTTI::dyn_cast(*i)) + if (T* cast_object = RTTI::dyn_cast((*i).get())) list.push_back(cast_object); } return list; diff --git a/Core/Types/object_ptr.hpp b/Core/Types/object_ptr.hpp index 1e144b5..3b8414b 100644 --- a/Core/Types/object_ptr.hpp +++ b/Core/Types/object_ptr.hpp @@ -111,7 +111,7 @@ static void add_owner(object_ptr& ptr) { std::atomic ptr_; public: - object_ptr(Ty* ptr = nullptr) + explicit object_ptr(Ty* ptr = nullptr) { ptr_.store(ptr); if (ptr) counter::add_owner(*this); @@ -158,6 +158,17 @@ static void add_owner(object_ptr& ptr) Ty& operator*() const noexcept { return *ptr_; } Ty* operator->() const noexcept { return ptr_.load(); } operator bool() const noexcept { return ptr_.load() != nullptr; } + object_ptr& operator=(const object_ptr& ptr) + { + reset(ptr); + return *this; + } + + template + explicit operator object_ptr() const noexcept + { + return object_ptr(reinterpret_cast(ptr_.load())); + } friend class counter; }; diff --git a/Tests/SaveMapTest.cpp b/Tests/SaveMapTest.cpp index 29fa958..a69874b 100644 --- a/Tests/SaveMapTest.cpp +++ b/Tests/SaveMapTest.cpp @@ -17,7 +17,7 @@ public: } void load(std::shared_ptr save) override { - num = save->GetInteger("num"); + num = static_cast(save->GetInteger("num")); str = save->GetString("str"); dbl = save->GetDouble("dbl"); } @@ -158,14 +158,14 @@ TEST(SaveMapTest, check_load_with_custom_type) EXPECT_EQ(test_vector_string[i], save_map.GetVectorString("TestVectorString")[i]); } - CustomObject* obj = reinterpret_cast(save_map.GetObject("CustomObject")); + UType::object_ptr obj = static_cast>(save_map.GetObject("CustomObject")); CustomObject test_obj; test_obj.num = 123; test_obj.str = "str123"; test_obj.dbl = 123.45; - EXPECT_EQ(*obj, test_obj); + EXPECT_EQ(*obj.get(), test_obj); - std::vector vec_obj = reinterpret_cast&>(save_map.GetVectorObject("CustomObjects")); + std::vector> vec_obj = reinterpret_cast>&>(save_map.GetVectorObject("CustomObjects")); std::vector vec_obj_test = { new CustomObject, new CustomObject, @@ -178,8 +178,8 @@ TEST(SaveMapTest, check_load_with_custom_type) vec_obj_test[1]->dbl = 543.21; for (auto i = 0; i < 2; i++) { - EXPECT_EQ(*vec_obj[i], *vec_obj_test[i]); - delete vec_obj[i]; + EXPECT_EQ(*vec_obj[i].get(), *vec_obj_test[i]); + vec_obj[i].destroy(); delete vec_obj_test[i]; } } \ No newline at end of file From bed233e56c03956af58e91b4a1dda96fd67dfbee Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Sat, 18 Oct 2025 13:03:26 +0700 Subject: [PATCH 14/19] Fix load configs --- Core/Core/CoreInstance.cpp | 11 +++++++-- Core/Game/SaveMap/SaveMap.cpp | 2 ++ Core/Game/WorldFactory.hpp | 6 ++++- TestGame/Worlds/TestWorld.world | 40 ++++++++++++++++++++++++++++++++- TestGame/main_config.conf | 8 ++++++- 5 files changed, 62 insertions(+), 5 deletions(-) diff --git a/Core/Core/CoreInstance.cpp b/Core/Core/CoreInstance.cpp index 7d2e47b..3d316d5 100644 --- a/Core/Core/CoreInstance.cpp +++ b/Core/Core/CoreInstance.cpp @@ -34,11 +34,18 @@ CoreInstance::CoreInstance() memorySize_ = System::getMemorySize(); std::ifstream main_config_file(main_config_name); + std::string payload; + if (main_config_file.fail()) throw std::runtime_error("Fail open main config file"); - std::string payload; - std::getline(main_config_file, payload); + main_config_file.seekg(0, std::ios::end); + size_t size_config = main_config_file.tellg(); + main_config_file.seekg(0, std::ios::beg); + payload.resize(size_config); + + main_config_file.read(payload.data(), payload.size()); + main_config_file.close(); SaveMap load_main_config(payload); main_config_.load(std::make_shared(load_main_config)); diff --git a/Core/Game/SaveMap/SaveMap.cpp b/Core/Game/SaveMap/SaveMap.cpp index dc148f1..ec18bf5 100644 --- a/Core/Game/SaveMap/SaveMap.cpp +++ b/Core/Game/SaveMap/SaveMap.cpp @@ -37,6 +37,8 @@ SaveMap::SaveMap(const std::string& json_data) { size_t key_begin = i = json_data_blank.find_first_of('\"', i) + 1; size_t key_end = i = json_data_blank.find_first_of('\"', i); + if (0 == key_begin) + return; std::string name = json_data_blank.substr(key_begin, key_end - key_begin); diff --git a/Core/Game/WorldFactory.hpp b/Core/Game/WorldFactory.hpp index 5e8a006..d9ac6d0 100644 --- a/Core/Game/WorldFactory.hpp +++ b/Core/Game/WorldFactory.hpp @@ -25,8 +25,12 @@ struct WorldFactory std::ifstream config_file("./Worlds/" #WorldName ".world");\ if (config_file.fail())\ throw std::runtime_error("Can't open world file");\ + config_file.seekg(0, std::ios::end);\ + size_t file_size = config_file.tellg();\ + config_file.seekg(0, std::ios::beg);\ std::string data;\ - std::getline(config_file, data);\ + data.resize(file_size);\ + config_file.read(data.data(), file_size);\ world->load(std::make_shared(data));\ return world;\ }}, diff --git a/TestGame/Worlds/TestWorld.world b/TestGame/Worlds/TestWorld.world index b63c26a..ada8632 100644 --- a/TestGame/Worlds/TestWorld.world +++ b/TestGame/Worlds/TestWorld.world @@ -1 +1,39 @@ -{"Class name":"TestWorld","dtime":5.000000,"Parent parameters":{"Class name":"World","loActors":[{"Class name":"StaticMesh","Parent parameters":{"Class name":"Mesh","smodel_name_":"TestModel","Parent parameters":{"Class name":"Actor","oloc":{"Class name":"Vector3D","dx":0.0,"dy":0.0,"dz":0.0},"orot":{"Class name":"Vector3D","dx":0.0,"dy":0.0,"dz":0.0},"oscale":{"Class name":"Vector3D","dx":0.0,"dy":0.0,"dz":0.0},"tags":[]}}}]}} \ No newline at end of file +{ + "Class name": "TestWorld", + "dtime": 5.000000, + "Parent parameters": { + "Class name":"World", + "vsActorsIDs": ["Mesh"], + "loActors": [ + { + "Class name": "StaticMesh", + "Parent parameters": { + "Class name": "Mesh", + "smodel_name_": "TestModel", + "Parent parameters": { + "Class name":"Actor", + "oloc": { + "Class name":"Vector3D", + "dx":0.0, + "dy":0.0, + "dz":0.0 + }, + "orot": { + "Class name":"Vector3D", + "dx":0.0, + "dy":0.0, + "dz":0.0 + }, + "oscale": { + "Class name": "Vector3D", + "dx": 0.0, + "dy": 0.0, + "dz": 0.0 + }, + "tags":[] + } + } + } + ] + } +} \ No newline at end of file diff --git a/TestGame/main_config.conf b/TestGame/main_config.conf index e2d7189..9f00330 100644 --- a/TestGame/main_config.conf +++ b/TestGame/main_config.conf @@ -1 +1,7 @@ -{"Class name":"MainConfig","dmin_memory_size":4096.0,"imin_CPU_count":1,"sgame_name":"Test Game","sbase_world":"TestWorld"} \ No newline at end of file +{ + "Class name": "MainConfig", + "dmin_memory_size": 4096.0, + "imin_CPU_count": 1, + "sgame_name": "Test Game", + "sbase_world": "TestWorld" +} \ No newline at end of file From 0ec86e3de8b4c8e14efaaeeda7e39e53ad5be5ed Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Sat, 18 Oct 2025 14:26:22 +0700 Subject: [PATCH 15/19] Move world on unordered_map and object_ptr --- Core/Core/RenderEngine/RenderEngine.cpp | 2 +- Core/Game/Actors/Actor.cpp | 8 +----- Core/Game/Actors/Actor.hpp | 3 +- Core/Game/World/World.cpp | 37 ++++++++++++++++++------- Core/Game/World/World.hpp | 34 ++++++++++++++--------- TestGame/Worlds/TestWorld.world | 14 +++++----- TestGame/src/Worlds/TestWorld.cpp | 7 +++++ Tests/ObjectPtrTest.cpp | 33 ++++++++++++++++++++++ 8 files changed, 99 insertions(+), 39 deletions(-) diff --git a/Core/Core/RenderEngine/RenderEngine.cpp b/Core/Core/RenderEngine/RenderEngine.cpp index 2d1683d..7d643f2 100644 --- a/Core/Core/RenderEngine/RenderEngine.cpp +++ b/Core/Core/RenderEngine/RenderEngine.cpp @@ -991,7 +991,7 @@ RenderEngine::~RenderEngine() void RenderEngine::start() { World* world = core_.GetGameInstance()->GetWorld(); - std::vector meshes = world->GetActorsByClass(); + std::vector> meshes = world->GetActorsByClass(); for (auto& i : meshes) i->load_model(i->GetModelName()); diff --git a/Core/Game/Actors/Actor.cpp b/Core/Game/Actors/Actor.cpp index 8269f6e..12c7973 100644 --- a/Core/Game/Actors/Actor.cpp +++ b/Core/Game/Actors/Actor.cpp @@ -8,7 +8,7 @@ void Actor::OnDestroy() { } -Actor::Actor() +Actor::Actor() : loc(new Vector3D), rot(new Vector3D), scale(new Vector3D) { SetType(Classes::Actor); } @@ -60,9 +60,3 @@ void Actor::RemoveTag(const std::string& tag) noexcept { tags.remove(tag); } - -void Actor::Destroy() -{ - OnDestroy(); - //world_->actors.remove(this); -} diff --git a/Core/Game/Actors/Actor.hpp b/Core/Game/Actors/Actor.hpp index bf93162..fb7108d 100644 --- a/Core/Game/Actors/Actor.hpp +++ b/Core/Game/Actors/Actor.hpp @@ -15,6 +15,7 @@ GENERATE_META(Actor) class Actor : public ISave, public IRTTI { World* world_; + std::string name_; UType::object_ptr loc, rot, scale; @@ -53,9 +54,9 @@ public: void AddTag(const std::string& tag) noexcept; void RemoveTag(const std::string& tag) noexcept; const std::list& GetTags() const { return tags; } - void Destroy(); World* GetWorld() const { return world_; } + const std::string& GetName() const { return name_; } friend class World; }; diff --git a/Core/Game/World/World.cpp b/Core/Game/World/World.cpp index 09482dd..bceb99c 100644 --- a/Core/Game/World/World.cpp +++ b/Core/Game/World/World.cpp @@ -8,32 +8,49 @@ World::World(GameInstance& game_instance) : game_instance(game_instance) World::~World() { - actors.clear(); + actors_map.clear(); } void World::BeginPlay() { - for (auto& i : actors) - i->BeginPlay(); + for (auto& i : actors_map) + i.second->BeginPlay(); } void World::Tick(double delta_time) { - for (auto& i : actors) - i->Tick(delta_time); + for (auto& i : actors_map) + i.second->Tick(delta_time); } std::shared_ptr World::save() { std::shared_ptr save = std::make_shared("World"); - save->SaveListObject("Actors", std::move(reinterpret_cast>&>(actors))); return save; } void World::load(std::shared_ptr save) { - actors = std::move(reinterpret_cast>&>(save->GetListObject("Actors"))); + std::vector actors_IDs = save->GetVectorString("ActorsIDs"); + std::list> act = std::move(reinterpret_cast>&>(save->GetListObject("Actors"))); - for (auto& i : actors) - i->world_ = this; -} \ No newline at end of file + size_t i_id = 0; + for (auto& i : act) + { + auto[it, flag] = actors_map.try_emplace(actors_IDs[i_id], i); + it->second->world_ = this; + it->second->name_ = it->first; + i_id++; + } +} + +void World::DestroyActor(UType::object_ptr ptr) +{ + if (ptr.get() == nullptr) + return; + + std::string name = ptr->GetName(); + actors_map.erase(name); + ptr->OnDestroy(); + ptr.destroy(); +} diff --git a/Core/Game/World/World.hpp b/Core/Game/World/World.hpp index f936e07..dfeef07 100644 --- a/Core/Game/World/World.hpp +++ b/Core/Game/World/World.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -16,8 +17,7 @@ class World : public ISave { GameInstance& game_instance; - // Actors only - std::list> actors; + std::unordered_map> actors_map; public: World(GameInstance& game_instance); @@ -33,37 +33,39 @@ public: void load(std::shared_ptr save) override; #pragma endregion - template> - Container GetActorsByClass() + template + std::vector> GetActorsByClass() { - Container list; - for (auto i = actors.cbegin(); i != actors.cend(); ++i) + std::vector> list; + for (auto i = actors_map.cbegin(); i != actors_map.cend(); ++i) { - if (T* cast_object = RTTI::dyn_cast((*i).get())) - list.push_back(cast_object); + if (T* cast_object = RTTI::dyn_cast(i->second.get())) + list.push_back(UType::object_ptr(cast_object)); } return list; } template - T* SpawnActorFormClass(const Vector3D& loc = { 0, 0, 0 }, const Vector3D& rot = { 0, 0, 0 }) + UType::object_ptr SpawnActorFormClass(std::string name, const Vector3D& loc = { 0, 0, 0 }, const Vector3D& rot = { 0, 0, 0 }) { - T* object = new T(); + UType::object_ptr object(new T()); object->SetActorLocate(loc); object->SetActorRotate(rot); static_cast(object)->world_ = this; - actors.push_back(object); + actors_map.try_emplace(name, object); return object; } + void DestroyActor(UType::object_ptr ptr); + template> Container GetActorsByTag(std::string tag) { Container container; - for (auto& i : actors) + for (auto& i : actors_map) { - const std::list& tags = i->GetTags(); + const std::list& tags = i.second->GetTags(); for (auto& j : tags) { if (j == tag) @@ -73,5 +75,11 @@ public: return container; } + + template + UType::object_ptr GetActorByID(const std::string& id) + { + return actors_map[id]; + } }; diff --git a/TestGame/Worlds/TestWorld.world b/TestGame/Worlds/TestWorld.world index ada8632..6b3ccfe 100644 --- a/TestGame/Worlds/TestWorld.world +++ b/TestGame/Worlds/TestWorld.world @@ -3,7 +3,7 @@ "dtime": 5.000000, "Parent parameters": { "Class name":"World", - "vsActorsIDs": ["Mesh"], + "vsActorsIDs": ["TestMesh1"], "loActors": [ { "Class name": "StaticMesh", @@ -14,9 +14,9 @@ "Class name":"Actor", "oloc": { "Class name":"Vector3D", - "dx":0.0, - "dy":0.0, - "dz":0.0 + "dx":1.0, + "dy":-1.0, + "dz":1.0 }, "orot": { "Class name":"Vector3D", @@ -26,9 +26,9 @@ }, "oscale": { "Class name": "Vector3D", - "dx": 0.0, - "dy": 0.0, - "dz": 0.0 + "dx": 1.0, + "dy": 1.0, + "dz": 1.0 }, "tags":[] } diff --git a/TestGame/src/Worlds/TestWorld.cpp b/TestGame/src/Worlds/TestWorld.cpp index 9b8731f..a2def3c 100644 --- a/TestGame/src/Worlds/TestWorld.cpp +++ b/TestGame/src/Worlds/TestWorld.cpp @@ -21,6 +21,13 @@ void TestWorld::Tick(double delta_time) if (time >= 10.0) { Message("TestWorld: Time out"); + std::vector> meshes = GetActorsByClass(); + if (!meshes.empty()) + { + DestroyActor(static_cast>(meshes[0])); + time = 7.0; + return; + } GetGameInstance().quit(); } } diff --git a/Tests/ObjectPtrTest.cpp b/Tests/ObjectPtrTest.cpp index dafe324..d6704fc 100644 --- a/Tests/ObjectPtrTest.cpp +++ b/Tests/ObjectPtrTest.cpp @@ -1,6 +1,21 @@ #include #include "Types/object_ptr.hpp" +class TestClass +{ + int* test_ptr_; +public: + TestClass(int* test_ptr) : test_ptr_(test_ptr) + { + *test_ptr_ = 1; + } + + ~TestClass() + { + *test_ptr_ = 2; + } +}; + TEST(object_ptr_test, base_test) { int* test = new int(123); @@ -23,4 +38,22 @@ TEST(object_ptr_test, check_destry) ptr.destroy(); EXPECT_EQ(ptr.get(), nullptr); EXPECT_EQ(ptr2.get(), nullptr); +} + +TEST(object_ptr_test, check_destroy) +{ + int* test = new int(0); + { + UType::object_ptr ptr(new TestClass(test)); + EXPECT_EQ(*test, 1); + } + EXPECT_EQ(*test, 2); + + *test = 0; + { + UType::object_ptr ptr(new TestClass(test)); + UType::object_ptr ptr2(ptr); + EXPECT_EQ(*test, 1); + } + EXPECT_EQ(*test, 2); } \ No newline at end of file From cafad476796fba3fff25c56b8a3d7b23ea4c26b1 Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Sat, 18 Oct 2025 14:48:33 +0700 Subject: [PATCH 16/19] Fix model manager. It's version stable for model manager --- Core/Core/RenderEngine/ModelManager.cpp | 54 ++++++++++++++++++++----- Core/Core/RenderEngine/ModelManager.hpp | 14 ++++++- Core/Game/Actors/Mesh/StaticMesh.cpp | 14 ++++++- Core/Game/Actors/Mesh/StaticMesh.hpp | 5 +++ Core/Game/World/World.cpp | 2 + TestGame/Worlds/TestWorld.world | 31 +++++++++++++- 6 files changed, 105 insertions(+), 15 deletions(-) diff --git a/Core/Core/RenderEngine/ModelManager.cpp b/Core/Core/RenderEngine/ModelManager.cpp index 0bb347e..aeaddf9 100644 --- a/Core/Core/RenderEngine/ModelManager.cpp +++ b/Core/Core/RenderEngine/ModelManager.cpp @@ -1,5 +1,7 @@ #include "ModelManager.hpp" +#include "Log/Log.hpp" + ModelManager::StaticModel::StaticModel(const std::vector& voxels, std::string name): name_(std::move(name)), voxels_(voxels) @@ -30,6 +32,10 @@ ModelManager::StaticModel::~StaticModel() OnDestroy.Call(name_); } +ModelManager::owner_counter::owner_counter(const owner_counter& other) : counter(other.counter.load()), model(other.model) +{ +} + unsigned int ModelManager::FNV1aHash(const char* buf) { unsigned int h_val = 0x811c9dc5; @@ -45,29 +51,57 @@ unsigned int ModelManager::FNV1aHash(const char* buf) void ModelManager::OnDestroySometimeModelCaller(const std::string& name) { + Log("Free model: " + name); OnDestroySometimeModel.Call(name); } ModelManager::~ModelManager() { - for (const auto& [it, model] : models) + for (const auto& [it, counter] : models) { - model->OnDestroy.unbind(this, &ModelManager::OnDestroySometimeModelCaller); + counter.model->OnDestroy.unbind(this, &ModelManager::OnDestroySometimeModelCaller); } models.clear(); } -std::shared_ptr ModelManager::LoadModel(const std::string& name) +ModelManager::StaticModel* ModelManager::LoadModel(const std::string& name) { + if (name.empty()) + return nullptr; unsigned int hash = FNV1aHash(name.c_str()); - auto model = models.find(hash); - if (model != models.cend()) - return model->second; + auto counter = models.find(hash); + if (counter != models.cend()) + { + ++counter->second.counter; + return counter->second.model; + } + Log("Load new model: " + name); + std::vector model_data; // Load model_data - auto newModel = std::make_shared(model_data, name); - newModel->OnDestroy.bind(this, &ModelManager::OnDestroySometimeModelCaller); - models[hash] = newModel; - return models[hash]; + owner_counter new_counter; + new_counter.counter.store(1); + new_counter.model = new StaticModel(model_data, name); + new_counter.model->OnDestroy.bind(this, &ModelManager::OnDestroySometimeModelCaller); + models.try_emplace(hash, new_counter); + + return new_counter.model; +} + +void ModelManager::FreeModel(const std::string& name) +{ + if (name.empty()) + return; + + unsigned int hash = FNV1aHash(name.c_str()); + auto counter = models.find(hash); + --counter->second.counter; + + StaticModel* model = counter->second.model; + if (counter->second.counter.load() == 0) + { + models.erase(hash); + delete model; + } } diff --git a/Core/Core/RenderEngine/ModelManager.hpp b/Core/Core/RenderEngine/ModelManager.hpp index 3779329..29fbfc5 100644 --- a/Core/Core/RenderEngine/ModelManager.hpp +++ b/Core/Core/RenderEngine/ModelManager.hpp @@ -29,10 +29,19 @@ public: glm::vec3 GetMassCenter() const { return mass_center_; } const std::string& GetName() const { return name_; } }; + + struct owner_counter + { + std::atomic_ullong counter; + StaticModel* model; + + owner_counter() = default; + owner_counter(const owner_counter& other); + }; private: - std::unordered_map> models; + std::unordered_map models; static unsigned int FNV1aHash (const char *buf); @@ -43,5 +52,6 @@ public: ~ModelManager(); - std::shared_ptr LoadModel(const std::string& name); + StaticModel* LoadModel(const std::string& name); + void FreeModel(const std::string& name); }; \ No newline at end of file diff --git a/Core/Game/Actors/Mesh/StaticMesh.cpp b/Core/Game/Actors/Mesh/StaticMesh.cpp index 89af642..86b8a4e 100644 --- a/Core/Game/Actors/Mesh/StaticMesh.cpp +++ b/Core/Game/Actors/Mesh/StaticMesh.cpp @@ -1,7 +1,11 @@ #include "StaticMesh.hpp" +#include "Core/CoreInstance.hpp" +#include "Core/RenderEngine/RenderEngine.hpp" +#include "Game/GameInstance.hpp" #include "Log/Log.hpp" #include "Game/SaveMap/SaveMap.hpp" +#include "Game/World/World.hpp" StaticMesh::StaticMesh() { @@ -20,7 +24,13 @@ void StaticMesh::load(std::shared_ptr save) void StaticMesh::load_model(const std::string& model_name) { + model_name_ = model_name; SetModelName(model_name); - // TODO - Message("Load mesh: " + model_name); + model_ = GetWorld()->GetGameInstance().GetCore().GetRenderEngine()->GetActiveModelManager()->LoadModel(model_name); +} + +void StaticMesh::OnDestroy() +{ + Mesh::OnDestroy(); + GetWorld()->GetGameInstance().GetCore().GetRenderEngine()->GetActiveModelManager()->FreeModel(model_name_); } diff --git a/Core/Game/Actors/Mesh/StaticMesh.hpp b/Core/Game/Actors/Mesh/StaticMesh.hpp index 8d53982..f3f2cb6 100644 --- a/Core/Game/Actors/Mesh/StaticMesh.hpp +++ b/Core/Game/Actors/Mesh/StaticMesh.hpp @@ -1,10 +1,14 @@ #pragma once #include "Mesh.hpp" +#include "Core/RenderEngine/ModelManager.hpp" GENERATE_META(StaticMesh) + class StaticMesh : public Mesh { + std::string model_name_; + ModelManager::StaticModel* model_ = nullptr; public: StaticMesh(); @@ -14,4 +18,5 @@ public: #pragma endregion void load_model(const std::string& model_name) override; + void OnDestroy() override; }; diff --git a/Core/Game/World/World.cpp b/Core/Game/World/World.cpp index bceb99c..694d925 100644 --- a/Core/Game/World/World.cpp +++ b/Core/Game/World/World.cpp @@ -8,6 +8,8 @@ World::World(GameInstance& game_instance) : game_instance(game_instance) World::~World() { + for (auto& i : actors_map) + i.second->OnDestroy(); actors_map.clear(); } diff --git a/TestGame/Worlds/TestWorld.world b/TestGame/Worlds/TestWorld.world index 6b3ccfe..0a5e7f2 100644 --- a/TestGame/Worlds/TestWorld.world +++ b/TestGame/Worlds/TestWorld.world @@ -3,7 +3,7 @@ "dtime": 5.000000, "Parent parameters": { "Class name":"World", - "vsActorsIDs": ["TestMesh1"], + "vsActorsIDs": ["TestMesh1","TestMesh2"], "loActors": [ { "Class name": "StaticMesh", @@ -33,6 +33,35 @@ "tags":[] } } + }, + { + "Class name": "StaticMesh", + "Parent parameters": { + "Class name": "Mesh", + "smodel_name_": "TestModel", + "Parent parameters": { + "Class name":"Actor", + "oloc": { + "Class name":"Vector3D", + "dx":0.0, + "dy":-1.0, + "dz":1.0 + }, + "orot": { + "Class name":"Vector3D", + "dx":0.0, + "dy":0.0, + "dz":0.0 + }, + "oscale": { + "Class name": "Vector3D", + "dx": 1.0, + "dy": 1.0, + "dz": 1.0 + }, + "tags":[] + } + } } ] } From 450b3839c6e900edbf57a43a31a9593002e542aa Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Sat, 18 Oct 2025 16:14:14 +0700 Subject: [PATCH 17/19] Refactor --- Core/Core/RenderEngine/ModelManager.cpp | 2 +- Core/Core/RenderEngine/ModelManager.hpp | 1 + Core/Core/RenderEngine/RenderEngine.hpp | 12 +++++------- Core/Game/Actors/Actor.cpp | 1 - 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Core/Core/RenderEngine/ModelManager.cpp b/Core/Core/RenderEngine/ModelManager.cpp index aeaddf9..121ccd8 100644 --- a/Core/Core/RenderEngine/ModelManager.cpp +++ b/Core/Core/RenderEngine/ModelManager.cpp @@ -85,7 +85,7 @@ ModelManager::StaticModel* ModelManager::LoadModel(const std::string& name) new_counter.model = new StaticModel(model_data, name); new_counter.model->OnDestroy.bind(this, &ModelManager::OnDestroySometimeModelCaller); models.try_emplace(hash, new_counter); - + OnLoadSometimeModel.Call(new_counter.model); return new_counter.model; } diff --git a/Core/Core/RenderEngine/ModelManager.hpp b/Core/Core/RenderEngine/ModelManager.hpp index 29fbfc5..77fad10 100644 --- a/Core/Core/RenderEngine/ModelManager.hpp +++ b/Core/Core/RenderEngine/ModelManager.hpp @@ -49,6 +49,7 @@ private: public: Delegate OnDestroySometimeModel; + Delegate OnLoadSometimeModel; ~ModelManager(); diff --git a/Core/Core/RenderEngine/RenderEngine.hpp b/Core/Core/RenderEngine/RenderEngine.hpp index 4a1ae17..a9c652f 100644 --- a/Core/Core/RenderEngine/RenderEngine.hpp +++ b/Core/Core/RenderEngine/RenderEngine.hpp @@ -37,7 +37,6 @@ class RenderEngine std::vector present_modes; }; -#pragma region Experemental struct Vertex { glm::vec2 pos; @@ -50,12 +49,6 @@ class RenderEngine {{0.5f, 0.5f}, {0.0f, 1.0f, 0.0f}}, {{-0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}} }; - VkBuffer vertex_buffer_ = VK_NULL_HANDLE; - VkDeviceMemory vertex_buffer_memory_ = VK_NULL_HANDLE; - uint32_t find_memory_type(uint32_t typeFilter, VkMemoryPropertyFlags properties) const; - void allocate_vertex_buffer(); - void copy_memory(VkBuffer src, VkBuffer dst, VkDeviceSize size); -#pragma endregion ModelManager model_manager_; @@ -85,6 +78,8 @@ class RenderEngine std::vector framebuffers_; VkCommandPool command_pool_ = VK_NULL_HANDLE; std::vector command_buffers_; + VkBuffer vertex_buffer_ = VK_NULL_HANDLE; + VkDeviceMemory vertex_buffer_memory_ = VK_NULL_HANDLE; // Sync objects std::vector image_available_semaphores_, render_finished_semaphores_; @@ -107,6 +102,7 @@ class RenderEngine void create_buffer(VkDeviceSize size, VkBufferUsageFlags usage, VkBuffer* buffer, const std::vector& queue_families); void allocate_memory(VkBuffer buffer, VkMemoryPropertyFlags property, VkDeviceMemory* device_memory); + uint32_t find_memory_type(uint32_t typeFilter, VkMemoryPropertyFlags properties) const; void create_instance(); void create_surface(); @@ -120,6 +116,8 @@ class RenderEngine void create_command_pool(); void allocate_command_buffers(); void create_sync_objects(); + void allocate_vertex_buffer(); + void copy_memory(VkBuffer src, VkBuffer dst, VkDeviceSize size); void record_command_buffer(VkCommandBuffer command_buffer, uint32_t image_index) const; void draw_frame(); diff --git a/Core/Game/Actors/Actor.cpp b/Core/Game/Actors/Actor.cpp index 12c7973..550d9a6 100644 --- a/Core/Game/Actors/Actor.cpp +++ b/Core/Game/Actors/Actor.cpp @@ -32,7 +32,6 @@ void Actor::load(std::shared_ptr save) void Actor::BeginPlay() { - Log("Actor::BeginPlay"); } void Actor::Tick(double delta_time) From d79258e191fc1176a515c0b767b0ad7df93e0b26 Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Sat, 18 Oct 2025 16:39:43 +0700 Subject: [PATCH 18/19] Refactor --- Core/Core/RenderEngine/ModelManager.cpp | 4 ++-- Core/Core/RenderEngine/RenderEngine.cpp | 4 ++-- Core/Log/Log.cpp | 12 ++++++------ Core/Log/Log.hpp | 11 +++++++---- TestGame/src/Actors/TestActor.cpp | 2 +- TestGame/src/Worlds/TestWorld.cpp | 7 +++++-- 6 files changed, 23 insertions(+), 17 deletions(-) diff --git a/Core/Core/RenderEngine/ModelManager.cpp b/Core/Core/RenderEngine/ModelManager.cpp index 121ccd8..5d51dcd 100644 --- a/Core/Core/RenderEngine/ModelManager.cpp +++ b/Core/Core/RenderEngine/ModelManager.cpp @@ -51,7 +51,7 @@ unsigned int ModelManager::FNV1aHash(const char* buf) void ModelManager::OnDestroySometimeModelCaller(const std::string& name) { - Log("Free model: " + name); + Loging::Log("Free model: " + name); OnDestroySometimeModel.Call(name); } @@ -76,7 +76,7 @@ ModelManager::StaticModel* ModelManager::LoadModel(const std::string& name) return counter->second.model; } - Log("Load new model: " + name); + Loging::Log("Load new model: " + name); std::vector model_data; // Load model_data diff --git a/Core/Core/RenderEngine/RenderEngine.cpp b/Core/Core/RenderEngine/RenderEngine.cpp index 7d643f2..141482a 100644 --- a/Core/Core/RenderEngine/RenderEngine.cpp +++ b/Core/Core/RenderEngine/RenderEngine.cpp @@ -27,7 +27,7 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback( std::string msg = "validation layer: "; msg += pCallbackData->pMessage; - Log(msg); + Loging::Log(msg); return VK_FALSE; } @@ -338,7 +338,7 @@ void RenderEngine::pick_physical_device() physical_device_ = device; VkPhysicalDeviceProperties device_properties; vkGetPhysicalDeviceProperties(physical_device_, &device_properties); - Log("Using device: " + std::string(device_properties.deviceName)); + Loging::Log("Using device: " + std::string(device_properties.deviceName)); break; } } diff --git a/Core/Log/Log.cpp b/Core/Log/Log.cpp index 8bae583..e31faa3 100644 --- a/Core/Log/Log.cpp +++ b/Core/Log/Log.cpp @@ -6,34 +6,34 @@ std::mutex mOutput; #ifdef _DEBUG -void Log(const char* msg) +void Loging::Log(const char* msg) { std::lock_guard lock(mOutput); std::cout << msg << '\n'; } -void Log(const std::string& msg) +void Loging::Log(const std::string& msg) { std::lock_guard lock(mOutput); std::cout << msg << '\n'; } #else -void Log(const char* msg) +void Loging::Log(const char* msg) { } -void Log(const std::string& msg) +void Loging::Log(const std::string& msg) { } #endif -void Message(const char* msg) +void Loging::Message(const char* msg) { std::lock_guard lock(mOutput); std::cout << msg << '\n'; } -void Message(const std::string& msg) +void Loging::Message(const std::string& msg) { std::lock_guard lock(mOutput); std::cout << msg << '\n'; diff --git a/Core/Log/Log.hpp b/Core/Log/Log.hpp index 8027a10..3ba073c 100644 --- a/Core/Log/Log.hpp +++ b/Core/Log/Log.hpp @@ -2,8 +2,11 @@ #include -void Log(const char* msg); -void Log(const std::string& msg); +namespace Loging +{ + void Log(const char* msg); + void Log(const std::string& msg); -void Message(const char* msg); -void Message(const std::string& msg); \ No newline at end of file + void Message(const char* msg); + void Message(const std::string& msg); +} diff --git a/TestGame/src/Actors/TestActor.cpp b/TestGame/src/Actors/TestActor.cpp index 1d398f1..c5fe540 100644 --- a/TestGame/src/Actors/TestActor.cpp +++ b/TestGame/src/Actors/TestActor.cpp @@ -5,5 +5,5 @@ void TestActor::BeginPlay() { Actor::BeginPlay(); - Log("TestActor::BeginPlay"); + Loging::Log("TestActor::BeginPlay"); } \ No newline at end of file diff --git a/TestGame/src/Worlds/TestWorld.cpp b/TestGame/src/Worlds/TestWorld.cpp index a2def3c..fe65334 100644 --- a/TestGame/src/Worlds/TestWorld.cpp +++ b/TestGame/src/Worlds/TestWorld.cpp @@ -10,7 +10,9 @@ TestWorld::TestWorld(GameInstance& game_instance) : World(game_instance) void TestWorld::BeginPlay() { World::BeginPlay(); - Log("TestWorld::BeginPlay"); + std::vector> meshes = GetActorsByClass(); + for (const auto& i : meshes) + Loging::Log("Load actor: " + i->GetName()); } void TestWorld::Tick(double delta_time) @@ -20,14 +22,15 @@ void TestWorld::Tick(double delta_time) time += delta_time; if (time >= 10.0) { - Message("TestWorld: Time out"); std::vector> meshes = GetActorsByClass(); if (!meshes.empty()) { + Loging::Message("TestWorld destroy: " + meshes[0]->GetName()); DestroyActor(static_cast>(meshes[0])); time = 7.0; return; } + Loging::Message("TestWorld: Time out"); GetGameInstance().quit(); } } From 1ba310ba92a1ccd2b0aac80f93099b719a77fb2c Mon Sep 17 00:00:00 2001 From: Jiga228 Date: Sat, 18 Oct 2025 17:08:50 +0700 Subject: [PATCH 19/19] Refactor --- Core/Core/CoreInstance.cpp | 2 +- Core/Core/RenderEngine/RenderEngine.cpp | 6 +++--- Core/Core/RenderEngine/RenderEngine.hpp | 4 ++-- Core/Core/SystemCalls.hpp | 4 ---- Core/Game/Actors/Actor.cpp | 18 +++++++++--------- Core/Game/Actors/Actor.hpp | 10 +++++----- Core/Log/Log.cpp | 2 +- 7 files changed, 21 insertions(+), 25 deletions(-) diff --git a/Core/Core/CoreInstance.cpp b/Core/Core/CoreInstance.cpp index 3d316d5..ae6eb40 100644 --- a/Core/Core/CoreInstance.cpp +++ b/Core/Core/CoreInstance.cpp @@ -44,7 +44,7 @@ CoreInstance::CoreInstance() main_config_file.seekg(0, std::ios::beg); payload.resize(size_config); - main_config_file.read(payload.data(), payload.size()); + main_config_file.read(payload.data(), static_cast(payload.size())); main_config_file.close(); SaveMap load_main_config(payload); diff --git a/Core/Core/RenderEngine/RenderEngine.cpp b/Core/Core/RenderEngine/RenderEngine.cpp index 141482a..ef3089c 100644 --- a/Core/Core/RenderEngine/RenderEngine.cpp +++ b/Core/Core/RenderEngine/RenderEngine.cpp @@ -719,7 +719,7 @@ void RenderEngine::allocate_vertex_buffer() VkBuffer staging_buffer = VK_NULL_HANDLE; VkDeviceMemory staging_buffer_memory = VK_NULL_HANDLE; - VkDeviceSize size_buffer = sizeof(vertices[0]) * vertices.size(); + VkDeviceSize size_buffer = sizeof(vertices_[0]) * vertices_.size(); create_buffer(size_buffer, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, &staging_buffer, transfer_index); allocate_memory(staging_buffer, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &staging_buffer_memory); @@ -731,7 +731,7 @@ void RenderEngine::allocate_vertex_buffer() void* data; VK_CHECK(vkMapMemory(device_, staging_buffer_memory, 0, size_buffer, 0, &data)); - memcpy(data, vertices.data(), size_buffer); + memcpy(data, vertices_.data(), size_buffer); vkUnmapMemory(device_, staging_buffer_memory); copy_memory(staging_buffer, vertex_buffer_, size_buffer); @@ -856,7 +856,7 @@ void RenderEngine::record_command_buffer(VkCommandBuffer command_buffer, uint32_ scissor.extent = swapchain_extent_; vkCmdSetScissor(command_buffer, 0, 1, &scissor); - vkCmdDraw(command_buffer, static_cast(vertices.size()), 1, 0, 0); + vkCmdDraw(command_buffer, static_cast(vertices_.size()), 1, 0, 0); vkCmdEndRenderPass(command_buffer); VK_CHECK(vkEndCommandBuffer(command_buffer)); diff --git a/Core/Core/RenderEngine/RenderEngine.hpp b/Core/Core/RenderEngine/RenderEngine.hpp index a9c652f..9d47584 100644 --- a/Core/Core/RenderEngine/RenderEngine.hpp +++ b/Core/Core/RenderEngine/RenderEngine.hpp @@ -8,7 +8,6 @@ #define GLFW_INCLUDE_VULKAN #include -#include #include #include "ModelManager.hpp" @@ -44,7 +43,7 @@ class RenderEngine static VkVertexInputBindingDescription get_binding_description(); static std::array get_vertex_attribute_descriptions(); }; - std::vector vertices = { + std::vector vertices_ = { {{0.0f, -0.5f}, {1.0f, 0.0f, 0.0f}}, {{0.5f, 0.5f}, {0.0f, 1.0f, 0.0f}}, {{-0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}} @@ -129,6 +128,7 @@ public: void start(); void stop_render() const; + [[nodiscard]] GLFWwindow* get_window() const { return window_; } ModelManager* GetActiveModelManager() { return &model_manager_; } diff --git a/Core/Core/SystemCalls.hpp b/Core/Core/SystemCalls.hpp index 4bfbaac..aa56531 100644 --- a/Core/Core/SystemCalls.hpp +++ b/Core/Core/SystemCalls.hpp @@ -1,9 +1,5 @@ #pragma once -class CoreInstance; - -struct CoreCallBacks; - namespace System { /** * @throws std::exception if the operation finished with failed diff --git a/Core/Game/Actors/Actor.cpp b/Core/Game/Actors/Actor.cpp index 550d9a6..14a7fe7 100644 --- a/Core/Game/Actors/Actor.cpp +++ b/Core/Game/Actors/Actor.cpp @@ -8,7 +8,7 @@ void Actor::OnDestroy() { } -Actor::Actor() : loc(new Vector3D), rot(new Vector3D), scale(new Vector3D) +Actor::Actor() : loc_(new Vector3D), rot_(new Vector3D), scale_(new Vector3D) { SetType(Classes::Actor); } @@ -16,17 +16,17 @@ Actor::Actor() : loc(new Vector3D), rot(new Vector3D), scale(new Vector3D) std::shared_ptr Actor::save() { return std::make_shared("Actor") - ->SaveObject("loc", static_cast>(loc)) - ->SaveObject("rot", static_cast>(rot)) - ->SaveObject("scale", UType::object_ptr(scale)) + ->SaveObject("loc", static_cast>(loc_)) + ->SaveObject("rot", static_cast>(rot_)) + ->SaveObject("scale", UType::object_ptr(scale_)) ->SaveListStrings("tags", std::move(tags)); } void Actor::load(std::shared_ptr save) { - loc = static_cast>(save->GetObject("loc")); - rot = static_cast>(save->GetObject("rot")); - scale = static_cast>(save->GetObject("scale")); + loc_ = static_cast>(save->GetObject("loc")); + rot_ = static_cast>(save->GetObject("rot")); + scale_ = static_cast>(save->GetObject("scale")); tags = std::move(save->GetListString("tags")); } @@ -40,13 +40,13 @@ void Actor::Tick(double delta_time) void Actor::SetActorLocate(const Vector3D& loc) noexcept { - *this->loc = loc; + *this->loc_ = loc; OnSetActorLocate.Call(loc); } void Actor::SetActorRotate(const Vector3D& rot) noexcept { - *this->rot = rot; + *this->rot_ = rot; OnSetActorRotate.Call(rot); } diff --git a/Core/Game/Actors/Actor.hpp b/Core/Game/Actors/Actor.hpp index fb7108d..2a4787f 100644 --- a/Core/Game/Actors/Actor.hpp +++ b/Core/Game/Actors/Actor.hpp @@ -17,7 +17,7 @@ class Actor : public ISave, public IRTTI World* world_; std::string name_; - UType::object_ptr loc, rot, scale; + UType::object_ptr loc_, rot_, scale_; std::list tags; @@ -30,8 +30,8 @@ public: Delegate OnSetActorRotate; #pragma region ISave - virtual std::shared_ptr save() override; - virtual void load(std::shared_ptr save) override; + std::shared_ptr save() override; + void load(std::shared_ptr save) override; #pragma endregion virtual void BeginPlay(); @@ -42,14 +42,14 @@ public: * Вызывает делегат OnSetActorLocate */ void SetActorLocate(const Vector3D& loc) noexcept; - inline const UType::object_ptr GetActorLocate() const { return loc; } + inline const UType::object_ptr GetActorLocate() const { return loc_; } /* * Изменяет ориентацию в пространстве * Вызывает делегат OnSetActorRotate */ void SetActorRotate(const Vector3D& rot) noexcept; - inline const UType::object_ptr GetActorRotate() const { return rot; } + inline const UType::object_ptr GetActorRotate() const { return rot_; } void AddTag(const std::string& tag) noexcept; void RemoveTag(const std::string& tag) noexcept; diff --git a/Core/Log/Log.cpp b/Core/Log/Log.cpp index e31faa3..184acc4 100644 --- a/Core/Log/Log.cpp +++ b/Core/Log/Log.cpp @@ -3,7 +3,7 @@ #include #include -std::mutex mOutput; +static std::mutex mOutput; #ifdef _DEBUG void Loging::Log(const char* msg)