+1
-1
@@ -19,6 +19,6 @@ endif()
|
||||
add_subdirectory(FastRTTI)
|
||||
add_subdirectory(glfw)
|
||||
add_subdirectory(Core)
|
||||
add_subdirectory(ModuleLib)
|
||||
add_subdirectory(TestGame)
|
||||
add_subdirectory(ProjectGenerator)
|
||||
add_subdirectory(Tests)
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
struct CoreCallBacks
|
||||
{
|
||||
void (*Quit)();
|
||||
};
|
||||
+40
-89
@@ -1,6 +1,6 @@
|
||||
#include "CoreInstance.h"
|
||||
#include "CoreInstance.hpp"
|
||||
|
||||
#include "SystemCalls.h"
|
||||
#include "SystemCalls.hpp"
|
||||
|
||||
#include <exception>
|
||||
#include <cstring>
|
||||
@@ -8,12 +8,9 @@
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
#include "RenderEngine.h"
|
||||
#include "Game/GameInstance.h"
|
||||
#include "Log/Log.h"
|
||||
#include "Game/SaveMap/SaveMap.h"
|
||||
|
||||
CoreInstance* CoreInstance::self = nullptr;
|
||||
#include "RenderEngine/RenderEngine.hpp"
|
||||
#include "Game/GameInstance.hpp"
|
||||
#include "Game/SaveMap/SaveMap.hpp"
|
||||
|
||||
extern GameInstance* GameFactory(CoreInstance&);
|
||||
|
||||
@@ -31,26 +28,24 @@ void CoreInstance::MainConfig::load(std::shared_ptr<SaveMap> 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();
|
||||
|
||||
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(), static_cast<int>(payload.size()));
|
||||
main_config_file.close();
|
||||
SaveMap load_main_config(payload);
|
||||
|
||||
main_config_.load(std::make_shared<SaveMap>(load_main_config));
|
||||
@@ -63,53 +58,46 @@ 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;
|
||||
}
|
||||
render_engine_ = new RenderEngine(*this, window_);
|
||||
|
||||
game_ = GameFactory(*this);
|
||||
if (game_ == nullptr)
|
||||
throw std::runtime_error("Fail create game instance!");
|
||||
try {
|
||||
render_engine_ = new RenderEngine(*this, window_);
|
||||
} catch (const std::exception& e)
|
||||
{
|
||||
std::cout << "[!] Init render engine: " << e.what() << '\n';
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
game_ = GameFactory(*this);
|
||||
} catch (const std::exception& e)
|
||||
{
|
||||
std::cout << "[!] Init game instance: " << e.what() << '\n';
|
||||
return;
|
||||
}
|
||||
is_ready = true;
|
||||
}
|
||||
|
||||
CoreInstance::~CoreInstance()
|
||||
{
|
||||
for (auto& module : modules_)
|
||||
System::QuitModule(module.handler);
|
||||
modules_.clear();
|
||||
|
||||
delete render_engine_;
|
||||
delete game_;
|
||||
delete render_engine_;
|
||||
|
||||
glfwDestroyWindow(window_);
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
@@ -120,40 +108,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");
|
||||
}
|
||||
|
||||
@@ -6,13 +6,15 @@
|
||||
#include <vector>
|
||||
|
||||
#include "Game/SaveMap/ISave.h"
|
||||
#include "Core/CoreCallBacks.h"
|
||||
|
||||
class SaveMap;
|
||||
class RenderEngine;
|
||||
class GameInstance;
|
||||
struct GLFWwindow;
|
||||
|
||||
/*
|
||||
* Внимательно следите, что бы у ваших объектов была "мягкая" зависимость
|
||||
*/
|
||||
class CoreInstance {
|
||||
struct Module {
|
||||
const char* name;
|
||||
@@ -44,40 +46,19 @@ class CoreInstance {
|
||||
RenderEngine* render_engine_;
|
||||
GameInstance* game_;
|
||||
|
||||
static CoreInstance* self;
|
||||
CoreCallBacks callbacks_;
|
||||
|
||||
#pragma region Callbacks
|
||||
static void Quit_callback();
|
||||
#pragma endregion
|
||||
bool is_ready = false;
|
||||
public:
|
||||
CoreInstance();
|
||||
~CoreInstance();
|
||||
|
||||
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; }
|
||||
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);
|
||||
GameInstance* GetGameInstance() const { return game_; }
|
||||
RenderEngine* GetRenderEngine() const { return render_engine_; }
|
||||
};
|
||||
@@ -0,0 +1,107 @@
|
||||
#include "ModelManager.hpp"
|
||||
|
||||
#include "Log/Log.hpp"
|
||||
|
||||
ModelManager::StaticModel::StaticModel(const std::vector<Voxel>& 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<int>(voxels_.size());
|
||||
sum_moments.y /= static_cast<int>(voxels_.size());
|
||||
sum_moments.z /= static_cast<int>(voxels_.size());
|
||||
}
|
||||
|
||||
mass_center_ = sum_moments;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
while (*buf)
|
||||
{
|
||||
h_val ^= static_cast<unsigned int>(*buf++);
|
||||
h_val *= 0x01000193;
|
||||
}
|
||||
|
||||
return h_val;
|
||||
}
|
||||
|
||||
void ModelManager::OnDestroySometimeModelCaller(const std::string& name)
|
||||
{
|
||||
Loging::Log("Free model: " + name);
|
||||
OnDestroySometimeModel.Call(name);
|
||||
}
|
||||
|
||||
ModelManager::~ModelManager()
|
||||
{
|
||||
for (const auto& [it, counter] : models)
|
||||
{
|
||||
counter.model->OnDestroy.unbind(this, &ModelManager::OnDestroySometimeModelCaller);
|
||||
}
|
||||
models.clear();
|
||||
}
|
||||
|
||||
ModelManager::StaticModel* ModelManager::LoadModel(const std::string& name)
|
||||
{
|
||||
if (name.empty())
|
||||
return nullptr;
|
||||
unsigned int hash = FNV1aHash(name.c_str());
|
||||
auto counter = models.find(hash);
|
||||
if (counter != models.cend())
|
||||
{
|
||||
++counter->second.counter;
|
||||
return counter->second.model;
|
||||
}
|
||||
|
||||
Loging::Log("Load new model: " + name);
|
||||
|
||||
std::vector<Voxel> model_data;
|
||||
// Load model_data
|
||||
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);
|
||||
OnLoadSometimeModel.Call(new_counter.model);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <Delegate/Delegate.h>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class ModelManager
|
||||
{
|
||||
public:
|
||||
struct Voxel
|
||||
{
|
||||
glm::ivec3 loc, color;
|
||||
int mass;
|
||||
};
|
||||
class StaticModel
|
||||
{
|
||||
std::string name_;
|
||||
std::vector<Voxel> voxels_;
|
||||
glm::vec3 mass_center_;
|
||||
public:
|
||||
Delegate<const std::string&> OnDestroy;
|
||||
|
||||
StaticModel(const std::vector<Voxel>& voxels, std::string name);
|
||||
~StaticModel();
|
||||
|
||||
const std::vector<Voxel>& GetVoxels() const { return voxels_; }
|
||||
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<unsigned int, owner_counter> models;
|
||||
|
||||
static unsigned int FNV1aHash (const char *buf);
|
||||
|
||||
void OnDestroySometimeModelCaller(const std::string& name);
|
||||
|
||||
public:
|
||||
Delegate<std::string> OnDestroySometimeModel;
|
||||
Delegate<StaticModel*> OnLoadSometimeModel;
|
||||
|
||||
~ModelManager();
|
||||
|
||||
StaticModel* LoadModel(const std::string& name);
|
||||
void FreeModel(const std::string& name);
|
||||
};
|
||||
@@ -1,12 +1,16 @@
|
||||
#include "RenderEngine.h"
|
||||
#include "RenderEngine.hpp"
|
||||
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <fstream>
|
||||
|
||||
#include "CoreInstance.h"
|
||||
#include "Log/Log.h"
|
||||
#include "Core/CoreInstance.hpp"
|
||||
#include "Log/Log.hpp"
|
||||
|
||||
#include "Game/GameInstance.hpp"
|
||||
#include "Game/World/World.hpp"
|
||||
#include "Game/Actors/Mesh/Mesh.hpp"
|
||||
|
||||
#include "GLFW/glfw3.h"
|
||||
|
||||
@@ -23,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;
|
||||
}
|
||||
@@ -78,10 +82,13 @@ VkVertexInputBindingDescription RenderEngine::Vertex::get_binding_description()
|
||||
std::array<VkVertexInputAttributeDescription, 2> RenderEngine::Vertex::get_vertex_attribute_descriptions()
|
||||
{
|
||||
std::array<VkVertexInputAttributeDescription, 2> 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 +105,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 +163,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 +184,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 +193,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 +221,7 @@ VkPresentModeKHR RenderEngine::choose_present_mode(const std::vector<VkPresentMo
|
||||
|
||||
VkExtent2D RenderEngine::choose_extent(const VkSurfaceCapabilitiesKHR& capabilities, GLFWwindow* window)
|
||||
{
|
||||
// Здесь вычисляется допустимое разрешение рендера
|
||||
if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max())
|
||||
return capabilities.currentExtent;
|
||||
else
|
||||
@@ -324,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;
|
||||
}
|
||||
}
|
||||
@@ -705,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);
|
||||
|
||||
@@ -717,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);
|
||||
@@ -842,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<uint32_t>(vertices.size()), 1, 0, 0);
|
||||
vkCmdDraw(command_buffer, static_cast<uint32_t>(vertices_.size()), 1, 0, 0);
|
||||
|
||||
vkCmdEndRenderPass(command_buffer);
|
||||
VK_CHECK(vkEndCommandBuffer(command_buffer));
|
||||
@@ -972,14 +986,15 @@ RenderEngine::~RenderEngine()
|
||||
|
||||
if (instance_ != VK_NULL_HANDLE)
|
||||
vkDestroyInstance(instance_, nullptr);
|
||||
|
||||
if (window_ != nullptr)
|
||||
glfwDestroyWindow(window_);
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
void RenderEngine::start()
|
||||
{
|
||||
World* world = core_.GetGameInstance()->GetWorld();
|
||||
std::vector<UType::object_ptr<Mesh>> meshes = world->GetActorsByClass<Mesh>();
|
||||
for (auto& i : meshes)
|
||||
i->load_model(i->GetModelName());
|
||||
|
||||
while (!glfwWindowShouldClose(window_))
|
||||
{
|
||||
glfwPollEvents();
|
||||
@@ -8,9 +8,10 @@
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "ModelManager.hpp"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#include <assert.h>
|
||||
#define VK_CHECK(res) assert(res == VK_SUCCESS)
|
||||
@@ -35,7 +36,6 @@ class RenderEngine
|
||||
std::vector<VkPresentModeKHR> present_modes;
|
||||
};
|
||||
|
||||
#pragma region Experemental
|
||||
struct Vertex
|
||||
{
|
||||
glm::vec2 pos;
|
||||
@@ -43,24 +43,22 @@ class RenderEngine
|
||||
static VkVertexInputBindingDescription get_binding_description();
|
||||
static std::array<VkVertexInputAttributeDescription, 2> get_vertex_attribute_descriptions();
|
||||
};
|
||||
std::vector<Vertex> vertices = {
|
||||
std::vector<Vertex> 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}}
|
||||
};
|
||||
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_;
|
||||
|
||||
static const std::vector<const char*> deviceExtensions;
|
||||
|
||||
int current_frame_ = 0;
|
||||
|
||||
CoreInstance& core_;
|
||||
|
||||
GLFWwindow* window_;
|
||||
|
||||
VkInstance instance_ = VK_NULL_HANDLE;
|
||||
VkSurfaceKHR surface_ = VK_NULL_HANDLE;
|
||||
VkPhysicalDevice physical_device_ = VK_NULL_HANDLE;
|
||||
@@ -79,7 +77,10 @@ class RenderEngine
|
||||
std::vector<VkFramebuffer> framebuffers_;
|
||||
VkCommandPool command_pool_ = VK_NULL_HANDLE;
|
||||
std::vector<VkCommandBuffer> command_buffers_;
|
||||
VkBuffer vertex_buffer_ = VK_NULL_HANDLE;
|
||||
VkDeviceMemory vertex_buffer_memory_ = VK_NULL_HANDLE;
|
||||
|
||||
// Sync objects
|
||||
std::vector<VkSemaphore> image_available_semaphores_, render_finished_semaphores_;
|
||||
std::vector<VkFence> in_flight_fences_;
|
||||
|
||||
@@ -100,6 +101,7 @@ class RenderEngine
|
||||
void create_buffer(VkDeviceSize size, VkBufferUsageFlags usage,
|
||||
VkBuffer* buffer, const std::vector<uint32_t>& 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();
|
||||
@@ -113,6 +115,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();
|
||||
@@ -123,4 +127,9 @@ public:
|
||||
|
||||
void start();
|
||||
void stop_render() const;
|
||||
|
||||
[[nodiscard]]
|
||||
GLFWwindow* get_window() const { return window_; }
|
||||
|
||||
ModelManager* GetActiveModelManager() { return &model_manager_; }
|
||||
};
|
||||
@@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
class CoreInstance;
|
||||
|
||||
struct CoreCallBacks;
|
||||
|
||||
namespace System {
|
||||
/**
|
||||
* @throws std::exception if the operation finished with failed
|
||||
* @return count CPU
|
||||
*/
|
||||
int getCountCPU();
|
||||
/*
|
||||
* @throws std::runtime_error
|
||||
* @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);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
namespace System {
|
||||
/**
|
||||
* @throws std::exception if the operation finished with failed
|
||||
* @return count CPU
|
||||
*/
|
||||
int getCountCPU();
|
||||
/*
|
||||
* @throws std::runtime_error
|
||||
* @return memory size in MB
|
||||
*/
|
||||
double getMemorySize();
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "../SystemCalls.h"
|
||||
#include "../SystemCalls.hpp"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
@@ -41,38 +41,4 @@ double System::getMemorySize() {
|
||||
return static_cast<double>(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<void(*)(CoreCallBacks*)>(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<void(*)()>(GetProcAddress(static_cast<HMODULE>(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<void(*)()>(GetProcAddress(static_cast<HMODULE>(handler), "QuitModule"));
|
||||
if(quit == nullptr) {
|
||||
throw std::runtime_error(std::to_string(GetLastError()).c_str());
|
||||
}
|
||||
quit();
|
||||
FreeLibrary(static_cast<HMODULE>(handler));
|
||||
}
|
||||
|
||||
#endif
|
||||
+3
-1
@@ -1,10 +1,12 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "CoreInstance.h"
|
||||
#include "CoreInstance.hpp"
|
||||
|
||||
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();
|
||||
|
||||
+21
-18
@@ -1,34 +1,37 @@
|
||||
#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"
|
||||
|
||||
Actor::Actor()
|
||||
void Actor::OnDestroy()
|
||||
{
|
||||
}
|
||||
|
||||
Actor::Actor() : loc_(new Vector3D), rot_(new Vector3D), scale_(new Vector3D)
|
||||
{
|
||||
SetType(Classes::Actor);
|
||||
}
|
||||
|
||||
std::shared_ptr<SaveMap> Actor::save() noexcept
|
||||
std::shared_ptr<SaveMap> Actor::save()
|
||||
{
|
||||
std::shared_ptr<SaveMap> save = std::make_shared<SaveMap>("Actor");
|
||||
save->SaveObject("loc", &loc)
|
||||
->SaveObject("rot", &rot)
|
||||
->SaveObject("scale", &scale)
|
||||
->SaveListStrings("tags", std::move(tags));
|
||||
return save;
|
||||
return std::make_shared<SaveMap>("Actor")
|
||||
->SaveObject("loc", static_cast<UType::object_ptr<ISave>>(loc_))
|
||||
->SaveObject("rot", static_cast<UType::object_ptr<ISave>>(rot_))
|
||||
->SaveObject("scale", UType::object_ptr<ISave>(scale_))
|
||||
->SaveListStrings("tags", std::move(tags));
|
||||
}
|
||||
|
||||
void Actor::load(std::shared_ptr<SaveMap> save) noexcept
|
||||
void Actor::load(std::shared_ptr<SaveMap> save)
|
||||
{
|
||||
loc = *reinterpret_cast<Vector3D*>(save->GetObject("loc"));
|
||||
rot = *reinterpret_cast<Vector3D*>(save->GetObject("rot"));
|
||||
scale = *reinterpret_cast<Vector3D*>(save->GetObject("scale"));
|
||||
loc_ = static_cast<UType::object_ptr<Vector3D>>(save->GetObject("loc"));
|
||||
rot_ = static_cast<UType::object_ptr<Vector3D>>(save->GetObject("rot"));
|
||||
scale_ = static_cast<UType::object_ptr<Vector3D>>(save->GetObject("scale"));
|
||||
tags = std::move(save->GetListString("tags"));
|
||||
}
|
||||
|
||||
void Actor::BeginPlay()
|
||||
{
|
||||
Log("Actor::BeginPlay");
|
||||
}
|
||||
|
||||
void Actor::Tick(double delta_time)
|
||||
@@ -37,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,17 +6,23 @@
|
||||
#include "RTTI_Meta.h"
|
||||
#include "Game/SaveMap/ISave.h"
|
||||
#include "Delegate/Delegate.h"
|
||||
#include "Math/Vector.h"
|
||||
#include "Math/Vector.hpp"
|
||||
#include "Types/object_ptr.hpp"
|
||||
|
||||
class World;
|
||||
GENERATE_META(Actor)
|
||||
|
||||
class Actor : public ISave, public IRTTI
|
||||
{
|
||||
Vector3D loc;
|
||||
Vector3D rot;
|
||||
Vector3D scale;
|
||||
World* world_;
|
||||
std::string name_;
|
||||
|
||||
UType::object_ptr<Vector3D> loc_, rot_, scale_;
|
||||
|
||||
std::list<std::string> tags;
|
||||
|
||||
protected:
|
||||
virtual void OnDestroy();
|
||||
public:
|
||||
Actor();
|
||||
|
||||
@@ -24,8 +30,8 @@ public:
|
||||
Delegate<const Vector3D&> OnSetActorRotate;
|
||||
|
||||
#pragma region ISave
|
||||
virtual std::shared_ptr<SaveMap> save() noexcept override;
|
||||
virtual void load(std::shared_ptr<SaveMap> save) noexcept override;
|
||||
std::shared_ptr<SaveMap> save() override;
|
||||
void load(std::shared_ptr<SaveMap> save) override;
|
||||
#pragma endregion
|
||||
|
||||
virtual void BeginPlay();
|
||||
@@ -36,16 +42,21 @@ public:
|
||||
* Вызывает делегат OnSetActorLocate
|
||||
*/
|
||||
void SetActorLocate(const Vector3D& loc) noexcept;
|
||||
inline const Vector3D& GetActorLocate() const { return loc; }
|
||||
inline const UType::object_ptr<Vector3D> GetActorLocate() const { return loc_; }
|
||||
|
||||
/*
|
||||
* Изменяет ориентацию в пространстве
|
||||
* Вызывает делегат OnSetActorRotate
|
||||
*/
|
||||
void SetActorRotate(const Vector3D& rot) noexcept;
|
||||
inline const Vector3D& GetActorRotate() const { return rot; }
|
||||
inline const UType::object_ptr<Vector3D> GetActorRotate() const { return rot_; }
|
||||
|
||||
void AddTag(const std::string& tag) noexcept;
|
||||
void RemoveTag(const std::string& tag) noexcept;
|
||||
const std::list<std::string>& GetTags() const { return tags; }
|
||||
|
||||
World* GetWorld() const { return world_; }
|
||||
const std::string& GetName() const { return name_; }
|
||||
|
||||
friend class World;
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
#include "Mesh.hpp"
|
||||
|
||||
#include "Game/SaveMap/SaveMap.hpp"
|
||||
|
||||
Mesh::Mesh()
|
||||
{
|
||||
SetType(Classes::Mesh);
|
||||
}
|
||||
|
||||
std::shared_ptr<SaveMap> Mesh::save()
|
||||
{
|
||||
return std::make_shared<SaveMap>("Mesh")
|
||||
->SaveString("model_name_", model_name_)
|
||||
->connect_to(Actor::save());
|
||||
}
|
||||
|
||||
void Mesh::load(std::shared_ptr<SaveMap> save)
|
||||
{
|
||||
Actor::load(save->getParent());
|
||||
model_name_ = save->GetString("model_name_");
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "../Actor.hpp"
|
||||
|
||||
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<SaveMap> save() override;
|
||||
virtual void load(std::shared_ptr<SaveMap> save) override;
|
||||
#pragma endregion
|
||||
|
||||
virtual void load_model(const std::string& model_name) = 0;
|
||||
const std::string& GetModelName() const { return model_name_; }
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
#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()
|
||||
{
|
||||
SetType(Classes::StaticMesh);
|
||||
}
|
||||
|
||||
std::shared_ptr<SaveMap> StaticMesh::save()
|
||||
{
|
||||
return std::make_shared<SaveMap>("StaticMesh")->connect_to(Mesh::save());
|
||||
}
|
||||
|
||||
void StaticMesh::load(std::shared_ptr<SaveMap> save)
|
||||
{
|
||||
Mesh::load(save->getParent());
|
||||
}
|
||||
|
||||
void StaticMesh::load_model(const std::string& model_name)
|
||||
{
|
||||
model_name_ = model_name;
|
||||
SetModelName(model_name);
|
||||
model_ = GetWorld()->GetGameInstance().GetCore().GetRenderEngine()->GetActiveModelManager()->LoadModel(model_name);
|
||||
}
|
||||
|
||||
void StaticMesh::OnDestroy()
|
||||
{
|
||||
Mesh::OnDestroy();
|
||||
GetWorld()->GetGameInstance().GetCore().GetRenderEngine()->GetActiveModelManager()->FreeModel(model_name_);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#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();
|
||||
|
||||
#pragma region ISave
|
||||
virtual std::shared_ptr<SaveMap> save() override;
|
||||
virtual void load(std::shared_ptr<SaveMap> save) override;
|
||||
#pragma endregion
|
||||
|
||||
void load_model(const std::string& model_name) override;
|
||||
void OnDestroy() override;
|
||||
};
|
||||
@@ -1,10 +1,12 @@
|
||||
#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<ObjectFactory> base_object_factories = {
|
||||
GENERATE_FACTORY_OBJECT(Actor)
|
||||
GENERATE_FACTORY_OBJECT(StaticMesh)
|
||||
GENERATE_FACTORY_OBJECT(Vector2D)
|
||||
GENERATE_FACTORY_OBJECT(Vector3D)
|
||||
};
|
||||
@@ -1,14 +1,14 @@
|
||||
#include "GameInstance.h"
|
||||
#include "GameInstance.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#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<WorldFactory> world_factories;
|
||||
|
||||
@@ -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<SaveMap>(data));
|
||||
}
|
||||
|
||||
GameInstance::~GameInstance()
|
||||
|
||||
@@ -17,8 +17,10 @@ class GameInstance
|
||||
std::atomic<bool> is_running = true;
|
||||
|
||||
void start();
|
||||
// Stop call from core
|
||||
void stop();
|
||||
public:
|
||||
// Stop call from game
|
||||
void quit();
|
||||
|
||||
// Init vulkan
|
||||
@@ -26,6 +28,7 @@ public:
|
||||
virtual ~GameInstance();
|
||||
|
||||
World* GetWorld() const { return world; }
|
||||
CoreInstance& GetCore() const { return core; }
|
||||
|
||||
friend class CoreInstance;
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "Resource.h"
|
||||
#include "Resource.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "IResource.h"
|
||||
#include "IResource.hpp"
|
||||
#include <mutex>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "SaveMap.h"
|
||||
#include "SaveMap.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
#include <stdexcept>
|
||||
#include "Game/ObjectFactory.h"
|
||||
#include "Game/ObjectFactory.hpp"
|
||||
|
||||
extern std::vector<ObjectFactory> factories;
|
||||
extern std::vector<ObjectFactory> base_object_factories;
|
||||
@@ -32,69 +32,72 @@ 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);
|
||||
if (0 == key_begin)
|
||||
return;
|
||||
|
||||
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);
|
||||
|
||||
std::string object_name = object_json.substr(begin, end - begin);
|
||||
ISave* object_ptr = MakeObjectByName(object_name);
|
||||
UType::object_ptr<ISave> object_ptr(MakeObjectByName(object_name));
|
||||
|
||||
object_ptr->load(std::make_shared<SaveMap>(object_json));
|
||||
save_objects[name.c_str() + 1] = object_ptr;
|
||||
@@ -102,20 +105,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<long long>();
|
||||
@@ -155,6 +158,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,14 +167,14 @@ SaveMap::SaveMap(const std::string& json_data)
|
||||
else
|
||||
value = "";
|
||||
vector_strings.push_back(value);
|
||||
j += 3;
|
||||
++j;
|
||||
}
|
||||
} else if (name[1] == 'o')
|
||||
{
|
||||
save_vector_objects[key] = std::vector<ISave*>();
|
||||
save_vector_objects[key] = std::vector<UType::object_ptr<ISave>>();
|
||||
if (arr_data.length() == 2)
|
||||
continue;
|
||||
std::vector<ISave*>& vector_object = save_vector_objects[key];
|
||||
std::vector<UType::object_ptr<ISave>>& vector_object = save_vector_objects[key];
|
||||
|
||||
size_t j = 1;
|
||||
while (j < arr_data.length())
|
||||
@@ -193,7 +198,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<ISave> object_ptr(MakeObjectByName(object_name));
|
||||
|
||||
object_ptr->load(std::make_shared<SaveMap>(object_json));
|
||||
vector_object.push_back(object_ptr);
|
||||
@@ -206,20 +211,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<long long>();
|
||||
@@ -267,10 +272,10 @@ SaveMap::SaveMap(const std::string& json_data)
|
||||
}
|
||||
} else if (name[1] == 'o')
|
||||
{
|
||||
save_list_objects[key] = std::list<ISave*>();
|
||||
save_list_objects[key] = std::list<UType::object_ptr<ISave>>();
|
||||
if (arr_data.length() == 2)
|
||||
continue;
|
||||
std::list<ISave*>& list_object = save_list_objects[key];
|
||||
std::list<UType::object_ptr<ISave>>& list_object = save_list_objects[key];
|
||||
|
||||
size_t j = 1;
|
||||
while (j < arr_data.length())
|
||||
@@ -294,7 +299,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<ISave> object_ptr(MakeObjectByName(object_name));
|
||||
|
||||
object_ptr->load(std::make_shared<SaveMap>(object_json));
|
||||
list_object.push_back(object_ptr);
|
||||
@@ -304,21 +309,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<SaveMap>(str);
|
||||
}
|
||||
}
|
||||
@@ -384,7 +389,7 @@ std::shared_ptr<SaveMap> SaveMap::SaveString(const char* name, const std::string
|
||||
return std::shared_ptr<SaveMap>(this);
|
||||
}
|
||||
|
||||
std::shared_ptr<SaveMap> SaveMap::SaveObject(const char* name, ISave* object) noexcept
|
||||
std::shared_ptr<SaveMap> SaveMap::SaveObject(const char* name, UType::object_ptr<ISave> object) noexcept
|
||||
{
|
||||
save_objects[name] = object;
|
||||
return std::shared_ptr<SaveMap>(this);
|
||||
@@ -408,7 +413,7 @@ std::shared_ptr<SaveMap> SaveMap::SaveVectorStrings(const char* name, std::vecto
|
||||
return std::shared_ptr<SaveMap>(this);
|
||||
}
|
||||
|
||||
std::shared_ptr<SaveMap> SaveMap::SaveVectorObject(const char* name, std::vector<ISave*>&& value) noexcept
|
||||
std::shared_ptr<SaveMap> SaveMap::SaveVectorObject(const char* name, std::vector<UType::object_ptr<ISave>>&& value) noexcept
|
||||
{
|
||||
save_vector_objects[name] = std::move(value);
|
||||
return std::shared_ptr<SaveMap>(this);
|
||||
@@ -432,7 +437,7 @@ std::shared_ptr<SaveMap> SaveMap::SaveListStrings(const char* name, std::list<st
|
||||
return std::shared_ptr<SaveMap>(this);
|
||||
}
|
||||
|
||||
std::shared_ptr<SaveMap> SaveMap::SaveListObject(const char* name, std::list<ISave*>&& value) noexcept
|
||||
std::shared_ptr<SaveMap> SaveMap::SaveListObject(const char* name, std::list<UType::object_ptr<ISave>>&& value) noexcept
|
||||
{
|
||||
save_list_objects[name] = std::move(value);
|
||||
return std::shared_ptr<SaveMap>(this);
|
||||
@@ -448,12 +453,12 @@ 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)
|
||||
UType::object_ptr<ISave> SaveMap::GetObject(const char* name)
|
||||
{
|
||||
return save_objects[name];
|
||||
}
|
||||
@@ -473,7 +478,7 @@ std::vector<std::string> SaveMap::GetVectorString(const char* name)
|
||||
return save_vector_strings[name];
|
||||
}
|
||||
|
||||
std::vector<ISave*>& SaveMap::GetVectorObject(const char* name)
|
||||
std::vector<UType::object_ptr<ISave>>& SaveMap::GetVectorObject(const char* name)
|
||||
{
|
||||
return save_vector_objects[name];
|
||||
}
|
||||
@@ -493,7 +498,7 @@ std::list<std::string>& SaveMap::GetListString(const char* name)
|
||||
return save_list_strings[name];
|
||||
}
|
||||
|
||||
std::list<ISave*>& SaveMap::GetListObject(const char* name)
|
||||
std::list<UType::object_ptr<ISave>>& SaveMap::GetListObject(const char* name)
|
||||
{
|
||||
return save_list_objects[name];
|
||||
}
|
||||
@@ -626,11 +631,28 @@ std::string SaveMap::serialize() noexcept
|
||||
return buffer;
|
||||
}
|
||||
|
||||
SaveMap* SaveMap::connect_to(const std::shared_ptr<SaveMap>& parent)
|
||||
std::shared_ptr<SaveMap> SaveMap::connect_to(const std::shared_ptr<SaveMap>& parent)
|
||||
{
|
||||
if (this->parent_ != nullptr)
|
||||
throw std::runtime_error("Can't connect to second parent");
|
||||
|
||||
this->parent_ = parent;
|
||||
return this;
|
||||
return std::shared_ptr<SaveMap>(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;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "ISave.h"
|
||||
#include "Types/object_ptr.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -14,22 +15,22 @@ class SaveMap final
|
||||
std::shared_ptr<SaveMap> parent_;
|
||||
|
||||
// Индивидуальные значения
|
||||
std::map<std::string, long long> save_long;
|
||||
std::map<std::string, double> save_double;
|
||||
std::map<std::string, std::string> save_string;
|
||||
std::map<std::string, ISave*> save_objects;
|
||||
std::unordered_map<std::string, long long> save_long;
|
||||
std::unordered_map<std::string, double> save_double;
|
||||
std::unordered_map<std::string, std::string> save_string;
|
||||
std::unordered_map<std::string, UType::object_ptr<ISave>> save_objects;
|
||||
|
||||
// Массивы
|
||||
std::map<std::string, std::vector<long long>> save_vector_integer;
|
||||
std::map<std::string, std::vector<double>> save_vector_double;
|
||||
std::map<std::string, std::vector<ISave*>> save_vector_objects;
|
||||
std::map<std::string, std::vector<std::string>> save_vector_strings;
|
||||
std::unordered_map<std::string, std::vector<long long>> save_vector_integer;
|
||||
std::unordered_map<std::string, std::vector<double>> save_vector_double;
|
||||
std::unordered_map<std::string, std::vector<UType::object_ptr<ISave>>> save_vector_objects;
|
||||
std::unordered_map<std::string, std::vector<std::string>> save_vector_strings;
|
||||
|
||||
// Связаные списки
|
||||
std::map<std::string, std::list<long long>> save_list_integer;
|
||||
std::map<std::string, std::list<double>> save_list_double;
|
||||
std::map<std::string, std::list<ISave*>> save_list_objects;
|
||||
std::map<std::string, std::list<std::string>> save_list_strings;
|
||||
std::unordered_map<std::string, std::list<long long>> save_list_integer;
|
||||
std::unordered_map<std::string, std::list<double>> save_list_double;
|
||||
std::unordered_map<std::string, std::list<UType::object_ptr<ISave>>> save_list_objects;
|
||||
std::unordered_map<std::string, std::list<std::string>> save_list_strings;
|
||||
|
||||
static ISave* MakeObjectByName(const std::string& name);
|
||||
|
||||
@@ -47,29 +48,29 @@ public:
|
||||
std::shared_ptr<SaveMap> SaveInteger(const char* name, int value) noexcept;
|
||||
std::shared_ptr<SaveMap> SaveDouble(const char* name, double value) noexcept;
|
||||
std::shared_ptr<SaveMap> SaveString(const char* name, const std::string& value) noexcept;
|
||||
std::shared_ptr<SaveMap> SaveObject(const char* name, ISave* object) noexcept;
|
||||
std::shared_ptr<SaveMap> SaveObject(const char* name, UType::object_ptr<ISave> object) noexcept;
|
||||
std::shared_ptr<SaveMap> SaveVectorInteger(const char* name, std::vector<long long>&& value) noexcept;
|
||||
std::shared_ptr<SaveMap> SaveVectorDouble(const char* name, std::vector<double>&& value) noexcept;
|
||||
std::shared_ptr<SaveMap> SaveVectorStrings(const char* name, std::vector<std::string>&& value) noexcept;
|
||||
std::shared_ptr<SaveMap> SaveVectorObject(const char* name, std::vector<ISave*>&& value) noexcept;
|
||||
std::shared_ptr<SaveMap> SaveVectorObject(const char* name, std::vector<UType::object_ptr<ISave>>&& value) noexcept;
|
||||
std::shared_ptr<SaveMap> SaveListInteger(const char* name, std::list<long long>&& value) noexcept;
|
||||
std::shared_ptr<SaveMap> SaveListDouble(const char* name, std::list<double>&& value) noexcept;
|
||||
std::shared_ptr<SaveMap> SaveListStrings(const char* name, std::list<std::string>&& value) noexcept;
|
||||
std::shared_ptr<SaveMap> SaveListObject(const char* name, std::list<ISave*>&& value) noexcept;
|
||||
std::shared_ptr<SaveMap> SaveListObject(const char* name, std::list<UType::object_ptr<ISave>>&& value) noexcept;
|
||||
|
||||
// Методы получения значенй
|
||||
long long GetInteger(const char* name);
|
||||
double GetDouble(const char* name);
|
||||
const char* GetString(const char* name);
|
||||
ISave* GetObject(const char* name);
|
||||
std::string GetString(const char* name);
|
||||
UType::object_ptr<ISave> GetObject(const char* name);
|
||||
std::vector<long long>& GetVectorInteger(const char* name);
|
||||
std::vector<double>& GetVectorDouble(const char* name);
|
||||
std::vector<std::string> GetVectorString(const char* name);
|
||||
std::vector<ISave*>& GetVectorObject(const char* name);
|
||||
std::vector<UType::object_ptr<ISave>>& GetVectorObject(const char* name);
|
||||
std::list<long long>& GetListInteger(const char* name);
|
||||
std::list<double>& GetListDouble(const char* name);
|
||||
std::list<std::string>& GetListString(const char* name);
|
||||
std::list<ISave*>& GetListObject(const char* name);
|
||||
std::list<UType::object_ptr<ISave>>& GetListObject(const char* name);
|
||||
|
||||
std::shared_ptr<SaveMap> getParent() const { return parent_; }
|
||||
const std::string& getClassName() const { return class_name; }
|
||||
@@ -77,5 +78,7 @@ public:
|
||||
// Собирает все токены в JSON объект
|
||||
std::string serialize() noexcept;
|
||||
|
||||
SaveMap* connect_to(const std::shared_ptr<SaveMap>& parent);
|
||||
std::shared_ptr<SaveMap> connect_to(const std::shared_ptr<SaveMap>& parent);
|
||||
|
||||
static std::string CleaningJSON(const std::string& json_data);
|
||||
};
|
||||
+32
-12
@@ -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)
|
||||
{
|
||||
@@ -8,31 +8,51 @@ World::World(GameInstance& game_instance) : game_instance(game_instance)
|
||||
|
||||
World::~World()
|
||||
{
|
||||
for (auto& actor : actors)
|
||||
delete actor;
|
||||
actors.clear();
|
||||
for (auto& i : actors_map)
|
||||
i.second->OnDestroy();
|
||||
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<SaveMap> World::save()
|
||||
{
|
||||
std::shared_ptr<SaveMap> save = std::make_shared<SaveMap>("World");
|
||||
save->SaveListObject("Actors", std::move(reinterpret_cast<std::list<ISave*>&>(actors)));
|
||||
return save;
|
||||
}
|
||||
|
||||
void World::load(std::shared_ptr<SaveMap> save)
|
||||
{
|
||||
actors = std::move(reinterpret_cast<std::list<Actor*>&>(save->GetListObject("Actors")));
|
||||
}
|
||||
std::vector<std::string> actors_IDs = save->GetVectorString("ActorsIDs");
|
||||
std::list<UType::object_ptr<Actor>> act = std::move(reinterpret_cast<std::list<UType::object_ptr<Actor>>&>(save->GetListObject("Actors")));
|
||||
|
||||
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<Actor> ptr)
|
||||
{
|
||||
if (ptr.get() == nullptr)
|
||||
return;
|
||||
|
||||
std::string name = ptr->GetName();
|
||||
actors_map.erase(name);
|
||||
ptr->OnDestroy();
|
||||
ptr.destroy();
|
||||
}
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "RTTI.h"
|
||||
#include "Game/Actors/Actor.h"
|
||||
|
||||
class GameInstance;
|
||||
|
||||
class World : public ISave
|
||||
{
|
||||
GameInstance& game_instance;
|
||||
|
||||
// Actors only
|
||||
std::list<Actor*> actors;
|
||||
|
||||
public:
|
||||
World(GameInstance& game_instance);
|
||||
~World() override;
|
||||
|
||||
virtual void BeginPlay();
|
||||
virtual void Tick(double delta_time);
|
||||
|
||||
GameInstance& GetGameInstance() const { return game_instance; }
|
||||
|
||||
#pragma region ISave
|
||||
std::shared_ptr<SaveMap> save() override;
|
||||
void load(std::shared_ptr<SaveMap> save) override;
|
||||
#pragma endregion
|
||||
|
||||
template<class T, class Container = std::vector<T*>>
|
||||
Container GetActorsByClass()
|
||||
{
|
||||
Container list;
|
||||
for (auto i = actors.cbegin(); i != actors.cend(); ++i)
|
||||
{
|
||||
if (RTTI::IsA<T>(*i))
|
||||
list.push_back(*i);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T* SpawnActorFormClass(const Vector3D& loc = { 0, 0, 0 }, const Vector3D& rot = { 0, 0, 0 })
|
||||
{
|
||||
T* object = new T();
|
||||
object->SetActorLocate(loc);
|
||||
object->SetActorRotate(rot);
|
||||
actors.push_back(object);
|
||||
return object;
|
||||
}
|
||||
|
||||
template<class Container = std::vector<Actor*>>
|
||||
Container GetActorsByTag(std::string tag)
|
||||
{
|
||||
Container container;
|
||||
|
||||
for (auto& i : actors)
|
||||
{
|
||||
const std::list<std::string>& tags = i->GetTags();
|
||||
for (auto& j : tags)
|
||||
{
|
||||
if (j == tag)
|
||||
container.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "RTTI.h"
|
||||
#include "Game/Actors/Actor.hpp"
|
||||
#include "Game/Actors/Mesh/Mesh.hpp"
|
||||
#include "Types/object_ptr.hpp"
|
||||
|
||||
class GameInstance;
|
||||
|
||||
GENERATE_META(World);
|
||||
class World : public ISave
|
||||
{
|
||||
GameInstance& game_instance;
|
||||
|
||||
std::unordered_map<std::string, UType::object_ptr<Actor>> actors_map;
|
||||
|
||||
public:
|
||||
World(GameInstance& game_instance);
|
||||
~World() override;
|
||||
|
||||
virtual void BeginPlay();
|
||||
virtual void Tick(double delta_time);
|
||||
|
||||
GameInstance& GetGameInstance() const { return game_instance; }
|
||||
|
||||
#pragma region ISave
|
||||
std::shared_ptr<SaveMap> save() override;
|
||||
void load(std::shared_ptr<SaveMap> save) override;
|
||||
#pragma endregion
|
||||
|
||||
template<class T>
|
||||
std::vector<UType::object_ptr<T>> GetActorsByClass()
|
||||
{
|
||||
std::vector<UType::object_ptr<T>> list;
|
||||
for (auto i = actors_map.cbegin(); i != actors_map.cend(); ++i)
|
||||
{
|
||||
if (T* cast_object = RTTI::dyn_cast<T, Actor>(i->second.get()))
|
||||
list.push_back(UType::object_ptr<T>(cast_object));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
UType::object_ptr<T> SpawnActorFormClass(std::string name, const Vector3D& loc = { 0, 0, 0 }, const Vector3D& rot = { 0, 0, 0 })
|
||||
{
|
||||
UType::object_ptr<T> object(new T());
|
||||
object->SetActorLocate(loc);
|
||||
object->SetActorRotate(rot);
|
||||
static_cast<Actor*>(object)->world_ = this;
|
||||
actors_map.try_emplace(name, object);
|
||||
return object;
|
||||
}
|
||||
|
||||
void DestroyActor(UType::object_ptr<Actor> ptr);
|
||||
|
||||
template<class T, class Container = std::vector<T*>>
|
||||
Container GetActorsByTag(std::string tag)
|
||||
{
|
||||
Container container;
|
||||
|
||||
for (auto& i : actors_map)
|
||||
{
|
||||
const std::list<std::string>& tags = i.second->GetTags();
|
||||
for (auto& j : tags)
|
||||
{
|
||||
if (j == tag)
|
||||
container.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
UType::object_ptr<T> GetActorByID(const std::string& id)
|
||||
{
|
||||
return actors_map[id];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include "Game/SaveMap/SaveMap.hpp"
|
||||
|
||||
class GameInstance;
|
||||
class World;
|
||||
@@ -16,7 +19,21 @@ struct WorldFactory
|
||||
#define WORLDS_LIST std::vector<WorldFactory> 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");\
|
||||
config_file.seekg(0, std::ios::end);\
|
||||
size_t file_size = config_file.tellg();\
|
||||
config_file.seekg(0, std::ios::beg);\
|
||||
std::string data;\
|
||||
data.resize(file_size);\
|
||||
config_file.read(data.data(), file_size);\
|
||||
world->load(std::make_shared<SaveMap>(data));\
|
||||
return world;\
|
||||
}},
|
||||
|
||||
/*
|
||||
* Пример использования:
|
||||
+8
-8
@@ -1,39 +1,39 @@
|
||||
#include "Log.h"
|
||||
#include "Log.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
|
||||
std::mutex mOutput;
|
||||
static 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';
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
void Log(const char* msg);
|
||||
void Log(const std::string& msg);
|
||||
|
||||
void Message(const char* msg);
|
||||
void Message(const std::string& msg);
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Loging
|
||||
{
|
||||
void Log(const char* msg);
|
||||
void Log(const std::string& msg);
|
||||
|
||||
void Message(const char* msg);
|
||||
void Message(const std::string& msg);
|
||||
}
|
||||
@@ -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)
|
||||
{}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
#include "object_ptr.hpp"
|
||||
|
||||
std::unordered_map<void*, UType::counter::counter_owners> UType::counter::owners_map;
|
||||
@@ -0,0 +1,175 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <list>
|
||||
|
||||
namespace UType
|
||||
{
|
||||
template<typename Ty>
|
||||
class object_ptr;
|
||||
|
||||
class counter
|
||||
{
|
||||
struct counter_owners
|
||||
{
|
||||
std::atomic_bool is_destroyed;
|
||||
std::mutex mutex;
|
||||
std::list<void*> 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<void*, counter_owners> owners_map;
|
||||
|
||||
public:
|
||||
template<typename Ty>
|
||||
static void add_owner(object_ptr<Ty>& 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<std::mutex> lock(counter->second.mutex);
|
||||
counter->second.owners.push_back(&ptr);
|
||||
}
|
||||
else
|
||||
ptr.ptr_.store(nullptr);
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
static void remove_owner(object_ptr<Ty>& 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<object_ptr<Ty>*>(owner)->ptr_.store(nullptr);
|
||||
delete static_cast<Ty*>(counter->first);
|
||||
owners_map.erase(counter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
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<object_ptr<Ty>*>(owner)->ptr_.store(nullptr);
|
||||
delete ptr;
|
||||
owners_map.erase(counter);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ty>
|
||||
class object_ptr
|
||||
{
|
||||
std::atomic<Ty*> ptr_;
|
||||
public:
|
||||
explicit object_ptr(Ty* ptr = nullptr)
|
||||
{
|
||||
ptr_.store(ptr);
|
||||
if (ptr) counter::add_owner<Ty>(*this);
|
||||
}
|
||||
|
||||
object_ptr(const object_ptr& ptr)
|
||||
{
|
||||
ptr_.store(ptr.ptr_);
|
||||
if (ptr.ptr_) counter::add_owner<Ty>(*this);
|
||||
}
|
||||
|
||||
object_ptr(object_ptr&& ptr) noexcept
|
||||
{
|
||||
ptr_.store(ptr.ptr_);
|
||||
if (ptr.ptr_) counter::add_owner<Ty>(*this);
|
||||
ptr.ptr_.store(nullptr);
|
||||
}
|
||||
|
||||
~object_ptr()
|
||||
{
|
||||
if (ptr_) counter::remove_owner<Ty>(*this);
|
||||
}
|
||||
|
||||
void reset(Ty* new_ptr = nullptr)
|
||||
{
|
||||
if (ptr_) counter::remove_owner<Ty>(*this);
|
||||
ptr_.store(new_ptr);
|
||||
if (new_ptr) counter::add_owner<Ty>(*this);
|
||||
}
|
||||
|
||||
void reset(const object_ptr& ptr)
|
||||
{
|
||||
if (ptr_) counter::remove_owner<Ty>(*this);
|
||||
ptr_.store(ptr.ptr_);
|
||||
if (ptr.ptr_) counter::add_owner<Ty>(*this);
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
if (ptr_) counter::remove_object<Ty>(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; }
|
||||
object_ptr<Ty>& operator=(const object_ptr<Ty>& ptr)
|
||||
{
|
||||
reset(ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename target_Ty>
|
||||
explicit operator object_ptr<target_Ty>() const noexcept
|
||||
{
|
||||
return object_ptr<target_Ty>(reinterpret_cast<target_Ty*>(ptr_.load()));
|
||||
}
|
||||
|
||||
friend class counter;
|
||||
};
|
||||
}
|
||||
@@ -13,5 +13,5 @@ template<class T> struct Meta;
|
||||
// Enum type classes
|
||||
enum class Classes
|
||||
{
|
||||
IRTTI, IResource, Actor, TestActor
|
||||
IRTTI, IResource, Actor, TestActor, Mesh, StaticMesh, World, TestWorld
|
||||
};
|
||||
|
||||
@@ -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()
|
||||
@@ -1,57 +0,0 @@
|
||||
#include "ModuleInstance.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
#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<std::mutex> lock(mModuleInstance);
|
||||
callbacks_ = callbacks;
|
||||
if(module == nullptr)
|
||||
module = Factory();
|
||||
}
|
||||
|
||||
void StartModule()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mModuleInstance);
|
||||
if (module != nullptr)
|
||||
moduleThread = new std::thread(&ModuleInstance::start, module);
|
||||
}
|
||||
|
||||
void QuitModule()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mModuleInstance);
|
||||
if(module != nullptr)
|
||||
{
|
||||
module->stop();
|
||||
moduleThread->join();
|
||||
delete module;
|
||||
module = nullptr;
|
||||
delete moduleThread;
|
||||
moduleThread = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -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<void*>(&InitModule);} \
|
||||
EXPORT void* protect_start() {return reinterpret_cast<void*>(&StartModule);} \
|
||||
EXPORT void* protect_quit() {return reinterpret_cast<void*>(&QuitModule);} \
|
||||
}\
|
||||
ModuleInstance* Factory() { return static_cast<ModuleInstance*>(new Class()); }
|
||||
|
||||
struct CoreCallBacks;
|
||||
|
||||
class ModuleInstance {
|
||||
public:
|
||||
Delegate<void> 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();
|
||||
}
|
||||
@@ -1 +1,68 @@
|
||||
{"Class name":"TestWorld","dtime":5.000000,"Parent parameters":{"Class name":"World","loActors":[]}}
|
||||
{
|
||||
"Class name": "TestWorld",
|
||||
"dtime": 5.000000,
|
||||
"Parent parameters": {
|
||||
"Class name":"World",
|
||||
"vsActorsIDs": ["TestMesh1","TestMesh2"],
|
||||
"loActors": [
|
||||
{
|
||||
"Class name": "StaticMesh",
|
||||
"Parent parameters": {
|
||||
"Class name": "Mesh",
|
||||
"smodel_name_": "TestModel",
|
||||
"Parent parameters": {
|
||||
"Class name":"Actor",
|
||||
"oloc": {
|
||||
"Class name":"Vector3D",
|
||||
"dx":1.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":[]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"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":[]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1 +1,7 @@
|
||||
{"Class name":"MainConfig","dmin_memory_size":"4096.0","imin_CPU_count":"1","sgame_name":"Test Game","sbase_world":"TestWorld","vsmodules_names":[]}
|
||||
{
|
||||
"Class name": "MainConfig",
|
||||
"dmin_memory_size": 4096.0,
|
||||
"imin_CPU_count": 1,
|
||||
"sgame_name": "Test Game",
|
||||
"sbase_world": "TestWorld"
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "TestActor.h"
|
||||
|
||||
#include "Log/Log.h"
|
||||
#include "Log/Log.hpp"
|
||||
|
||||
void TestActor::BeginPlay()
|
||||
{
|
||||
Actor::BeginPlay();
|
||||
Log("TestActor::BeginPlay");
|
||||
Loging::Log("TestActor::BeginPlay");
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "Game/Actors/Actor.h"
|
||||
#include "Game/Actors/Actor.hpp"
|
||||
|
||||
GENERATE_META(TestActor)
|
||||
class TestActor final : public Actor
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "Game/ObjectFactory.h"
|
||||
#include "Game/ObjectFactory.hpp"
|
||||
|
||||
#include "../Actors/TestActor.h"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "Game/WorldFactory.h"
|
||||
#include "Game/WorldFactory.hpp"
|
||||
|
||||
#include "../Worlds/TestWorld.h"
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "TestGameInstance.h"
|
||||
|
||||
#include "Game/Resource/Resource.h"
|
||||
#include "Game/Resource/Resource.hpp"
|
||||
#include <iostream>
|
||||
|
||||
#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)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "Game/GameInstance.h"
|
||||
#include "Game/GameInstance.hpp"
|
||||
|
||||
class TestGameInstance : public GameInstance
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{}
|
||||
@@ -10,7 +10,9 @@ TestWorld::TestWorld(GameInstance& game_instance) : World(game_instance)
|
||||
void TestWorld::BeginPlay()
|
||||
{
|
||||
World::BeginPlay();
|
||||
Log("TestWorld::BeginPlay");
|
||||
std::vector<UType::object_ptr<Actor>> meshes = GetActorsByClass<Actor>();
|
||||
for (const auto& i : meshes)
|
||||
Loging::Log("Load actor: " + i->GetName());
|
||||
}
|
||||
|
||||
void TestWorld::Tick(double delta_time)
|
||||
@@ -20,7 +22,15 @@ void TestWorld::Tick(double delta_time)
|
||||
time += delta_time;
|
||||
if (time >= 10.0)
|
||||
{
|
||||
Message("TestWorld: Time out");
|
||||
std::vector<UType::object_ptr<Mesh>> meshes = GetActorsByClass<Mesh>();
|
||||
if (!meshes.empty())
|
||||
{
|
||||
Loging::Message("TestWorld destroy: " + meshes[0]->GetName());
|
||||
DestroyActor(static_cast<UType::object_ptr<Actor>>(meshes[0]));
|
||||
time = 7.0;
|
||||
return;
|
||||
}
|
||||
Loging::Message("TestWorld: Time out");
|
||||
GetGameInstance().quit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
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
|
||||
"SaveMapTest.cpp"
|
||||
"ObjectPtrTest.cpp"
|
||||
|
||||
"${PROJECT_SOURCE_DIR}/Core/Game/SaveMap/SaveMap.cpp"
|
||||
"${PROJECT_SOURCE_DIR}/Core/Types/object_ptr.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)
|
||||
@@ -0,0 +1,59 @@
|
||||
#include <gtest/gtest.h>
|
||||
#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);
|
||||
UType::object_ptr<int> ptr(test);
|
||||
EXPECT_EQ(*ptr.get(), 123);
|
||||
|
||||
UType::object_ptr<int> 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<int> ptr(new int(123)), ptr2(ptr);
|
||||
|
||||
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<TestClass> ptr(new TestClass(test));
|
||||
EXPECT_EQ(*test, 1);
|
||||
}
|
||||
EXPECT_EQ(*test, 2);
|
||||
|
||||
*test = 0;
|
||||
{
|
||||
UType::object_ptr<TestClass> ptr(new TestClass(test));
|
||||
UType::object_ptr<TestClass> ptr2(ptr);
|
||||
EXPECT_EQ(*test, 1);
|
||||
}
|
||||
EXPECT_EQ(*test, 2);
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "Game/ObjectFactory.hpp"
|
||||
#include "Game/SaveMap/SaveMap.hpp"
|
||||
|
||||
class CustomObject : public ISave
|
||||
{
|
||||
public:
|
||||
int num;
|
||||
std::string str;
|
||||
double dbl;
|
||||
|
||||
std::shared_ptr<SaveMap> save() override
|
||||
{
|
||||
return std::make_shared<SaveMap>("CustomObject")->SaveInteger("num", num)->SaveString("str", str)->SaveDouble("dbl", dbl);
|
||||
}
|
||||
void load(std::shared_ptr<SaveMap> save) override
|
||||
{
|
||||
num = static_cast<int>(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<ObjectFactory> 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<int> test_vector_int = { 1, 2, 3 };
|
||||
std::vector<double> test_vector_double = { 1.2, 3.4, 5.6 };
|
||||
std::vector<std::string> 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<int> test_vector_int = { 1, 2, 3 };
|
||||
std::vector<double> test_vector_double = { 1.2, 3.4, 5.6 };
|
||||
std::vector<std::string> 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]);
|
||||
}
|
||||
|
||||
UType::object_ptr<CustomObject> obj = static_cast<UType::object_ptr<CustomObject>>(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);
|
||||
|
||||
std::vector<UType::object_ptr<CustomObject>> vec_obj = reinterpret_cast<std::vector<UType::object_ptr<CustomObject>>&>(save_map.GetVectorObject("CustomObjects"));
|
||||
std::vector<CustomObject*> 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].get(), *vec_obj_test[i]);
|
||||
vec_obj[i].destroy();
|
||||
delete vec_obj_test[i];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user