mirror of
https://github.com/MadeOfJelly/MushMachine.git
synced 2025-08-23 07:56:40 +02:00
initial import, >900commits predate this
This commit is contained in:
17
framework/resource_manager/CMakeLists.txt
Normal file
17
framework/resource_manager/CMakeLists.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
cmake_minimum_required(VERSION 3.2)
|
||||
project(resource_manager CXX)
|
||||
|
||||
add_library(resource_manager INTERFACE)
|
||||
|
||||
target_include_directories(resource_manager INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
||||
|
||||
target_link_libraries(resource_manager INTERFACE
|
||||
entt
|
||||
logger
|
||||
)
|
||||
|
||||
if (BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
|
145
framework/resource_manager/src/mm/resource_manager.hpp
Normal file
145
framework/resource_manager/src/mm/resource_manager.hpp
Normal file
@@ -0,0 +1,145 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <entt/config/config.h>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
|
||||
#include <mm/logger.hpp>
|
||||
#define LOGRM(x) LOG("ResourceManager", x)
|
||||
|
||||
namespace MM {
|
||||
|
||||
// modeled heavily after entt::resource_cache
|
||||
// https://github.com/skypjack/entt/blob/master/src/entt/resource/cache.hpp
|
||||
template<typename Resource>
|
||||
class ResourceManager {
|
||||
public:
|
||||
using res_id_type = typename entt::hashed_string::hash_type;
|
||||
using handle_type = std::shared_ptr<Resource>;
|
||||
using container_type = std::unordered_map<res_id_type, handle_type>;
|
||||
using size_type = typename container_type::size_type;
|
||||
|
||||
private:
|
||||
ResourceManager(void) = default;
|
||||
|
||||
container_type _storage;
|
||||
|
||||
public:
|
||||
ResourceManager(ResourceManager const&) = delete;
|
||||
void operator=(ResourceManager const&) = delete;
|
||||
|
||||
static ResourceManager& ref(void) {
|
||||
static ResourceManager<Resource> instance{};
|
||||
return instance;
|
||||
}
|
||||
|
||||
// Loader s must implement a load method
|
||||
template<typename Loader, typename... Args>
|
||||
bool load(const res_id_type id, Args &&... args) {
|
||||
//static_assert(std::is_base_of<entt::resource_loader<Loader, Resource>, Loader>::value);
|
||||
|
||||
if (!contains(id)) {
|
||||
handle_type r = Loader{}.load(std::forward<Args>(args)...);
|
||||
if (static_cast<bool>(r)) {
|
||||
_storage[id] = std::move(r);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// string overload
|
||||
template<typename Loader, typename... Args>
|
||||
bool load(const char* id, Args &&... args) {
|
||||
return load<Loader>(entt::hashed_string{id}.value(), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename Loader, typename... Args>
|
||||
bool reload(const res_id_type id, Args &&... args) {
|
||||
discard(id);
|
||||
return load<Loader>(id, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// string overload
|
||||
template<typename Loader, typename... Args>
|
||||
bool reload(const char* id, Args &&... args) {
|
||||
return reload<Loader>(entt::hashed_string{id}.value(), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void discard(const res_id_type id) ENTT_NOEXCEPT {
|
||||
if (auto it = _storage.find(id); it != _storage.end()) {
|
||||
_storage.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void discard(const char* id) ENTT_NOEXCEPT {
|
||||
discard(entt::hashed_string{id}.value());
|
||||
}
|
||||
|
||||
void each(std::function<void(res_id_type, std::shared_ptr<Resource>)>& fn) {
|
||||
for (auto& it : _storage) {
|
||||
fn(it.first, it.second);
|
||||
}
|
||||
}
|
||||
|
||||
size_type size(void) const {
|
||||
return _storage.size();
|
||||
}
|
||||
|
||||
bool empty(void) const {
|
||||
return _storage.empty();
|
||||
}
|
||||
|
||||
void clear(void) ENTT_NOEXCEPT {
|
||||
_storage.clear();
|
||||
}
|
||||
|
||||
bool contains(const res_id_type id) const ENTT_NOEXCEPT {
|
||||
return (_storage.find(id) != _storage.cend());
|
||||
}
|
||||
|
||||
handle_type get(const res_id_type id) const {
|
||||
auto it = _storage.find(id);
|
||||
if (it == _storage.end()) {
|
||||
if (id != "default"_hs) {
|
||||
LOGRM("not in cache, loading default...");
|
||||
return get("default"_hs);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: fix
|
||||
//handle_type get(const char* id) const {
|
||||
//return get(entt::hashed_string{id}.value());
|
||||
//}
|
||||
|
||||
// reverse lookup
|
||||
std::optional<res_id_type> id_from_handle(const std::shared_ptr<Resource>& handle) {
|
||||
if (static_cast<bool>(handle)) {
|
||||
auto it = std::find_if(_storage.cbegin(), _storage.cend(), [&](auto& v) { return handle == v.second; });
|
||||
if (it != _storage.cend()) {
|
||||
return it->first;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace MM
|
||||
|
||||
#undef LOGRM
|
||||
|
14
framework/resource_manager/test/CMakeLists.txt
Normal file
14
framework/resource_manager/test/CMakeLists.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
add_executable(resource_test
|
||||
resource_test.cpp
|
||||
)
|
||||
|
||||
target_include_directories(resource_test PRIVATE ".")
|
||||
|
||||
target_link_libraries(resource_test
|
||||
#engine
|
||||
resource_manager
|
||||
gtest_main
|
||||
)
|
||||
|
||||
add_test(NAME resource_test COMMAND resource_test)
|
||||
|
78
framework/resource_manager/test/resource_test.cpp
Normal file
78
framework/resource_manager/test/resource_test.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <mm/resource_manager.hpp>
|
||||
|
||||
#include <entt/resource/cache.hpp>
|
||||
|
||||
// disable, this just tests entt and not MM
|
||||
#if 0
|
||||
TEST(EngineResourceManagerTest, entt_cache) {
|
||||
struct type_entt_cache_test {
|
||||
int val;
|
||||
};
|
||||
entt::resource_cache<type_entt_cache_test> cache{};
|
||||
|
||||
ASSERT_TRUE(cache.empty());
|
||||
|
||||
struct type_entt_cache_test_loader final : entt::resource_loader<type_entt_cache_test_loader, type_entt_cache_test> {
|
||||
std::shared_ptr<type_entt_cache_test> load(int value) const {
|
||||
return std::shared_ptr<type_entt_cache_test>(new type_entt_cache_test{value});
|
||||
}
|
||||
};
|
||||
|
||||
ASSERT_TRUE(cache.load<type_entt_cache_test_loader>("test1"_hs, 1));
|
||||
ASSERT_EQ(cache.size(), 1);
|
||||
auto h_test1 = cache.handle("test1"_hs);
|
||||
ASSERT_TRUE(static_cast<bool>(h_test1));
|
||||
//ASSERT_EQ(*h_test1, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(EngineResourceManagerTest, basic) {
|
||||
struct type_test {
|
||||
int val;
|
||||
};
|
||||
auto& rm = MM::ResourceManager<type_test>::ref();
|
||||
|
||||
ASSERT_TRUE(rm.empty());
|
||||
|
||||
struct type_test_loader final {
|
||||
std::shared_ptr<type_test> load(int value) const {
|
||||
return std::shared_ptr<type_test>(new type_test{value});
|
||||
}
|
||||
};
|
||||
|
||||
ASSERT_TRUE(rm.load<type_test_loader>("test1", 1));
|
||||
ASSERT_FALSE(rm.empty());
|
||||
ASSERT_EQ(rm.size(), 1);
|
||||
ASSERT_TRUE(rm.contains("test1"_hs));
|
||||
|
||||
{
|
||||
auto h_test1 = rm.get("test1"_hs);
|
||||
ASSERT_TRUE(static_cast<bool>(h_test1));
|
||||
ASSERT_EQ(h_test1->val, 1);
|
||||
|
||||
ASSERT_TRUE(rm.reload<type_test_loader>("test1", 3));
|
||||
ASSERT_EQ(rm.size(), 1);
|
||||
ASSERT_TRUE(static_cast<bool>(h_test1));
|
||||
auto h_test1_2 = rm.get("test1"_hs);
|
||||
ASSERT_TRUE(static_cast<bool>(h_test1_2));
|
||||
ASSERT_NE(h_test1->val, h_test1_2->val);
|
||||
|
||||
{
|
||||
auto rt = rm.id_from_handle(h_test1_2);
|
||||
ASSERT_TRUE(static_cast<bool>(rt));
|
||||
ASSERT_EQ(rt, "test1"_hs);
|
||||
}
|
||||
|
||||
|
||||
rm.discard("test1");
|
||||
ASSERT_TRUE(rm.empty());
|
||||
|
||||
{
|
||||
auto rt = rm.id_from_handle(h_test1_2);
|
||||
ASSERT_FALSE(static_cast<bool>(rt));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user