mirror of
https://github.com/enduro2d/enduro2d.git
synced 2025-12-15 08:15:38 +07:00
Merge branch 'feature/asset_dependencies' into feature/gobject
This commit is contained in:
@@ -50,11 +50,10 @@ namespace e2d
|
|||||||
class content_asset;
|
class content_asset;
|
||||||
class asset;
|
class asset;
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
class asset_cache;
|
|
||||||
class asset_cache_base;
|
|
||||||
|
|
||||||
class library;
|
class library;
|
||||||
|
class asset_cache;
|
||||||
|
class asset_group;
|
||||||
|
class asset_dependencies;
|
||||||
|
|
||||||
class atlas;
|
class atlas;
|
||||||
class flipbook;
|
class flipbook;
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#include "_high.hpp"
|
#include "_high.hpp"
|
||||||
|
|
||||||
|
#include "address.hpp"
|
||||||
|
|
||||||
namespace e2d
|
namespace e2d
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
@@ -22,17 +24,6 @@ namespace e2d
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
|
||||||
// bad_asset_factory_operation
|
|
||||||
//
|
|
||||||
|
|
||||||
class bad_asset_factory_operation final : public exception {
|
|
||||||
public:
|
|
||||||
const char* what() const noexcept final {
|
|
||||||
return "bad asset factory operation";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// asset
|
// asset
|
||||||
//
|
//
|
||||||
@@ -45,9 +36,9 @@ namespace e2d
|
|||||||
: private noncopyable
|
: private noncopyable
|
||||||
, public ref_counter<asset> {
|
, public ref_counter<asset> {
|
||||||
public:
|
public:
|
||||||
asset();
|
asset() = default;
|
||||||
virtual ~asset() noexcept;
|
virtual ~asset() noexcept = default;
|
||||||
virtual asset_ptr find_nested_asset(str_view name) const noexcept = 0;
|
virtual asset_ptr find_nested_asset(str_view nested_address) const noexcept = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -73,9 +64,9 @@ namespace e2d
|
|||||||
|
|
||||||
const Content& content() const noexcept;
|
const Content& content() const noexcept;
|
||||||
|
|
||||||
template < typename T >
|
template < typename NestedAsset >
|
||||||
intrusive_ptr<T> find_nested_asset(str_view name) const noexcept;
|
typename NestedAsset::ptr find_nested_asset(str_view nested_address) const noexcept;
|
||||||
asset_ptr find_nested_asset(str_view name) const noexcept override;
|
asset_ptr find_nested_asset(str_view nested_address) const noexcept override;
|
||||||
private:
|
private:
|
||||||
Content content_;
|
Content content_;
|
||||||
nested_content nested_content_;
|
nested_content nested_content_;
|
||||||
@@ -87,60 +78,57 @@ namespace e2d
|
|||||||
|
|
||||||
class asset_cache_base : private noncopyable {
|
class asset_cache_base : private noncopyable {
|
||||||
public:
|
public:
|
||||||
asset_cache_base();
|
asset_cache_base() = default;
|
||||||
virtual ~asset_cache_base() noexcept;
|
virtual ~asset_cache_base() noexcept = default;
|
||||||
|
|
||||||
static std::size_t unload_all_unused_assets() noexcept;
|
virtual std::size_t asset_count() const noexcept = 0;
|
||||||
virtual std::size_t unload_self_unused_assets() noexcept = 0;
|
virtual std::size_t unload_unused_assets() noexcept = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// typed_asset_cache
|
||||||
|
//
|
||||||
|
|
||||||
|
template < typename Asset >
|
||||||
|
class typed_asset_cache : public asset_cache_base {
|
||||||
|
public:
|
||||||
|
using asset_ptr = typename Asset::ptr;
|
||||||
|
public:
|
||||||
|
typed_asset_cache() = default;
|
||||||
|
~typed_asset_cache() noexcept final = default;
|
||||||
|
|
||||||
|
asset_ptr find(str_hash address) const noexcept;
|
||||||
|
void store(str_hash address, const asset_ptr& asset);
|
||||||
|
|
||||||
|
std::size_t asset_count() const noexcept override;
|
||||||
|
std::size_t unload_unused_assets() noexcept override;
|
||||||
private:
|
private:
|
||||||
static std::mutex mutex_;
|
hash_map<str_hash, asset_ptr> assets_;
|
||||||
static hash_set<asset_cache_base*> caches_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// asset_cache
|
// asset_cache
|
||||||
//
|
//
|
||||||
|
|
||||||
template < typename Asset >
|
class asset_cache final {
|
||||||
class asset_cache : public asset_cache_base
|
|
||||||
, public module<asset_cache<Asset>> {
|
|
||||||
public:
|
public:
|
||||||
using asset_ptr = typename Asset::ptr;
|
asset_cache() = default;
|
||||||
public:
|
~asset_cache() noexcept = default;
|
||||||
asset_cache(library& l);
|
|
||||||
~asset_cache() noexcept final;
|
|
||||||
|
|
||||||
asset_ptr find(str_hash address) const noexcept;
|
|
||||||
void store(str_hash address, const asset_ptr& asset);
|
|
||||||
|
|
||||||
void clear() noexcept;
|
|
||||||
std::size_t asset_count() const noexcept;
|
|
||||||
|
|
||||||
std::size_t unload_self_unused_assets() noexcept override;
|
|
||||||
private:
|
|
||||||
library& library_;
|
|
||||||
mutable std::mutex mutex_;
|
|
||||||
hash_map<str_hash, asset_ptr> assets_;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// asset_factory
|
|
||||||
//
|
|
||||||
|
|
||||||
class asset_factory : public module<asset_factory> {
|
|
||||||
public:
|
|
||||||
using asset_creator = std::function<
|
|
||||||
stdex::promise<asset_ptr>(const library& library, str_view address)>;
|
|
||||||
public:
|
|
||||||
asset_factory();
|
|
||||||
~asset_factory() noexcept final;
|
|
||||||
|
|
||||||
template < typename Asset >
|
template < typename Asset >
|
||||||
asset_factory& register_asset(str_hash type);
|
void store(str_hash address, const typename Asset::ptr& asset);
|
||||||
asset_factory& register_creator(str_hash type, asset_creator creator);
|
|
||||||
|
template < typename Asset >
|
||||||
|
typename Asset::ptr find(str_hash address) const noexcept;
|
||||||
|
|
||||||
|
template < typename Asset >
|
||||||
|
std::size_t asset_count() const noexcept;
|
||||||
|
std::size_t asset_count() const noexcept;
|
||||||
|
|
||||||
|
std::size_t unload_unused_assets() noexcept;
|
||||||
private:
|
private:
|
||||||
std::mutex mutex_;
|
using asset_cache_uptr = std::unique_ptr<asset_cache_base>;
|
||||||
hash_map<str_hash, asset_creator> creators_;
|
hash_map<utils::type_family_id, asset_cache_uptr> caches_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,33 +56,29 @@ namespace e2d
|
|||||||
}
|
}
|
||||||
|
|
||||||
template < typename Asset, typename Content >
|
template < typename Asset, typename Content >
|
||||||
template < typename T >
|
template < typename NestedAsset >
|
||||||
intrusive_ptr<T> content_asset<Asset, Content>::find_nested_asset(str_view name) const noexcept {
|
typename NestedAsset::ptr content_asset<Asset, Content>::find_nested_asset(str_view nested_address) const noexcept {
|
||||||
return dynamic_pointer_cast<T>(find_nested_asset(name));
|
return dynamic_pointer_cast<NestedAsset>(find_nested_asset(nested_address));
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename Asset, typename Content >
|
template < typename Asset, typename Content >
|
||||||
asset_ptr content_asset<Asset, Content>::find_nested_asset(str_view name) const noexcept {
|
asset_ptr content_asset<Asset, Content>::find_nested_asset(str_view address) const noexcept {
|
||||||
const auto iter = nested_content_.find(name);
|
const auto iter = nested_content_.find(make_hash(address::parent(address)));
|
||||||
return iter != nested_content_.end()
|
if ( iter == nested_content_.end() ) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
const str nested_asset = address::nested(address);
|
||||||
|
return nested_asset.empty()
|
||||||
? iter->second
|
? iter->second
|
||||||
: nullptr;
|
: iter->second->find_nested_asset(nested_asset);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// asset_cache
|
// typed_asset_cache
|
||||||
//
|
//
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
asset_cache<T>::asset_cache(library& l)
|
typename typed_asset_cache<T>::asset_ptr typed_asset_cache<T>::find(str_hash address) const noexcept {
|
||||||
: library_(l) {}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
asset_cache<T>::~asset_cache() noexcept = default;
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
typename asset_cache<T>::asset_ptr asset_cache<T>::find(str_hash address) const noexcept {
|
|
||||||
std::lock_guard<std::mutex> guard(mutex_);
|
|
||||||
const auto iter = assets_.find(address);
|
const auto iter = assets_.find(address);
|
||||||
return iter != assets_.end()
|
return iter != assets_.end()
|
||||||
? iter->second
|
? iter->second
|
||||||
@@ -90,26 +86,17 @@ namespace e2d
|
|||||||
}
|
}
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
void asset_cache<T>::store(str_hash address, const asset_ptr& asset) {
|
void typed_asset_cache<T>::store(str_hash address, const asset_ptr& asset) {
|
||||||
std::lock_guard<std::mutex> guard(mutex_);
|
|
||||||
assets_[address] = asset;
|
assets_[address] = asset;
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
void asset_cache<T>::clear() noexcept {
|
std::size_t typed_asset_cache<T>::asset_count() const noexcept {
|
||||||
std::lock_guard<std::mutex> guard(mutex_);
|
|
||||||
assets_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
std::size_t asset_cache<T>::asset_count() const noexcept {
|
|
||||||
std::lock_guard<std::mutex> guard(mutex_);
|
|
||||||
return assets_.size();
|
return assets_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
std::size_t asset_cache<T>::unload_self_unused_assets() noexcept {
|
std::size_t typed_asset_cache<T>::unload_unused_assets() noexcept {
|
||||||
std::lock_guard<std::mutex> guard(mutex_);
|
|
||||||
std::size_t result = 0u;
|
std::size_t result = 0u;
|
||||||
for ( auto iter = assets_.begin(); iter != assets_.end(); ) {
|
for ( auto iter = assets_.begin(); iter != assets_.end(); ) {
|
||||||
if ( !iter->second || 1 == iter->second->use_count() ) {
|
if ( !iter->second || 1 == iter->second->use_count() ) {
|
||||||
@@ -123,27 +110,61 @@ namespace e2d
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// asset_factory
|
// asset_cache
|
||||||
//
|
//
|
||||||
|
|
||||||
template < typename Asset >
|
template < typename Asset >
|
||||||
asset_factory& asset_factory::register_asset(str_hash type) {
|
void asset_cache::store(str_hash address, const typename Asset::ptr& asset) {
|
||||||
return register_creator(type, [](const library& library, str_view address) {
|
const auto family = utils::type_family<Asset>::id();
|
||||||
return Asset::load_async(library, address)
|
const auto iter = caches_.find(family);
|
||||||
.then([](const typename Asset::load_result& result){
|
typed_asset_cache<Asset>* cache = iter != caches_.end() && iter->second
|
||||||
return static_pointer_cast<asset>(result);
|
? static_cast<typed_asset_cache<Asset>*>(iter->second.get())
|
||||||
});
|
: nullptr;
|
||||||
});
|
if ( !cache ) {
|
||||||
|
cache = static_cast<typed_asset_cache<Asset>*>(caches_.emplace(
|
||||||
|
family,
|
||||||
|
std::make_unique<typed_asset_cache<Asset>>()).first->second.get());
|
||||||
|
}
|
||||||
|
cache->store(address, asset);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline asset_factory& asset_factory::register_creator(str_hash type, asset_creator creator) {
|
template < typename Asset >
|
||||||
std::lock_guard<std::mutex> guard(mutex_);
|
typename Asset::ptr asset_cache::find(str_hash address) const noexcept {
|
||||||
bool success = creators_.insert(
|
const auto iter = caches_.find(utils::type_family<Asset>::id());
|
||||||
std::make_pair(type, std::move(creator))).second;
|
const typed_asset_cache<Asset>* cache = iter != caches_.end() && iter->second
|
||||||
if ( !success ) {
|
? static_cast<const typed_asset_cache<Asset>*>(iter->second.get())
|
||||||
throw bad_asset_factory_operation();
|
: nullptr;
|
||||||
}
|
return cache
|
||||||
return *this;
|
? cache->find(address)
|
||||||
|
: nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename Asset >
|
||||||
|
std::size_t asset_cache::asset_count() const noexcept {
|
||||||
|
const auto iter = caches_.find(utils::type_family<Asset>::id());
|
||||||
|
return iter != caches_.end() && iter->second
|
||||||
|
? iter->second->asset_count()
|
||||||
|
: 0u;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::size_t asset_cache::asset_count() const noexcept {
|
||||||
|
return std::accumulate(
|
||||||
|
caches_.begin(), caches_.end(), std::size_t(0),
|
||||||
|
[](std::size_t acc, const auto& p){
|
||||||
|
return p.second
|
||||||
|
? acc + p.second->asset_count()
|
||||||
|
: acc;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::size_t asset_cache::unload_unused_assets() noexcept {
|
||||||
|
return std::accumulate(
|
||||||
|
caches_.begin(), caches_.end(), std::size_t(0),
|
||||||
|
[](std::size_t acc, const auto& p){
|
||||||
|
return p.second
|
||||||
|
? acc + p.second->unload_unused_assets()
|
||||||
|
: acc;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,32 +11,73 @@
|
|||||||
#include "_high.hpp"
|
#include "_high.hpp"
|
||||||
|
|
||||||
#include "asset.hpp"
|
#include "asset.hpp"
|
||||||
#include "address.hpp"
|
|
||||||
|
|
||||||
namespace e2d
|
namespace e2d
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// bad_library_operation
|
// library_cancelled_exception
|
||||||
//
|
//
|
||||||
|
|
||||||
class bad_library_operation final : public exception {
|
class library_cancelled_exception : public exception {
|
||||||
public:
|
const char* what() const noexcept override {
|
||||||
const char* what() const noexcept final {
|
return "library cancelled exception";
|
||||||
return "bad library operation";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// loading_asset_base
|
||||||
|
//
|
||||||
|
|
||||||
|
class loading_asset_base;
|
||||||
|
using loading_asset_base_iptr = intrusive_ptr<loading_asset_base>;
|
||||||
|
|
||||||
|
class loading_asset_base
|
||||||
|
: private noncopyable
|
||||||
|
, public ref_counter<loading_asset_base> {
|
||||||
|
public:
|
||||||
|
loading_asset_base() = default;
|
||||||
|
virtual ~loading_asset_base() noexcept = default;
|
||||||
|
|
||||||
|
virtual void cancel() noexcept = 0;
|
||||||
|
virtual str_hash address() const noexcept = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// loading_asset
|
||||||
|
//
|
||||||
|
|
||||||
|
template < typename Asset >
|
||||||
|
class loading_asset : public loading_asset_base {
|
||||||
|
public:
|
||||||
|
using ptr = intrusive_ptr<loading_asset>;
|
||||||
|
using promise_type = typename Asset::load_async_result;
|
||||||
|
public:
|
||||||
|
loading_asset(str_hash address, promise_type promise);
|
||||||
|
~loading_asset() noexcept override = default;
|
||||||
|
|
||||||
|
void cancel() noexcept override;
|
||||||
|
str_hash address() const noexcept override;
|
||||||
|
|
||||||
|
const promise_type& promise() const noexcept;
|
||||||
|
private:
|
||||||
|
str_hash address_;
|
||||||
|
promise_type promise_;
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// library
|
// library
|
||||||
//
|
//
|
||||||
|
|
||||||
class library final : public module<library> {
|
class library final : public module<library> {
|
||||||
public:
|
public:
|
||||||
library(const url& root);
|
library(const url& root, deferrer& deferrer);
|
||||||
~library() noexcept final;
|
~library() noexcept final;
|
||||||
|
|
||||||
const url& root() const noexcept;
|
const url& root() const noexcept;
|
||||||
|
const asset_cache& cache() const noexcept;
|
||||||
|
|
||||||
std::size_t unload_unused_assets() noexcept;
|
std::size_t unload_unused_assets() noexcept;
|
||||||
|
std::size_t loading_asset_count() const noexcept;
|
||||||
|
|
||||||
template < typename Asset >
|
template < typename Asset >
|
||||||
typename Asset::load_result load_main_asset(str_view address) const;
|
typename Asset::load_result load_main_asset(str_view address) const;
|
||||||
@@ -49,8 +90,103 @@ namespace e2d
|
|||||||
|
|
||||||
template < typename Asset, typename Nested = Asset >
|
template < typename Asset, typename Nested = Asset >
|
||||||
typename Nested::load_async_result load_asset_async(str_view address) const;
|
typename Nested::load_async_result load_asset_async(str_view address) const;
|
||||||
|
private:
|
||||||
|
template < typename Asset >
|
||||||
|
vector<loading_asset_base_iptr>::iterator
|
||||||
|
find_loading_asset_iter_(str_hash address) const noexcept;
|
||||||
|
|
||||||
|
template < typename Asset >
|
||||||
|
typename loading_asset<Asset>::ptr
|
||||||
|
find_loading_asset_(str_hash address) const noexcept;
|
||||||
|
|
||||||
|
template < typename Asset >
|
||||||
|
void remove_loading_asset_(str_hash address) const noexcept;
|
||||||
|
|
||||||
|
void cancel_all_loading_assets_() noexcept;
|
||||||
private:
|
private:
|
||||||
url root_;
|
url root_;
|
||||||
|
deferrer& deferrer_;
|
||||||
|
std::atomic<bool> cancelled_{false};
|
||||||
|
private:
|
||||||
|
mutable asset_cache cache_;
|
||||||
|
mutable std::recursive_mutex mutex_;
|
||||||
|
mutable vector<loading_asset_base_iptr> loading_assets_;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// asset_group
|
||||||
|
//
|
||||||
|
|
||||||
|
class asset_group {
|
||||||
|
public:
|
||||||
|
asset_group() = default;
|
||||||
|
~asset_group() noexcept = default;
|
||||||
|
|
||||||
|
template < typename Iter >
|
||||||
|
asset_group& add_assets(Iter first, Iter last);
|
||||||
|
|
||||||
|
template < typename Container >
|
||||||
|
asset_group& add_assets(Container&& container);
|
||||||
|
|
||||||
|
asset_group& add_asset(str_view address, const asset_ptr& asset);
|
||||||
|
|
||||||
|
template < typename Asset, typename Nested = Asset >
|
||||||
|
typename Nested::load_result find_asset(str_view address) const;
|
||||||
|
private:
|
||||||
|
vector<std::pair<str, asset_ptr>> assets_;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// asset_dependency_base
|
||||||
|
//
|
||||||
|
|
||||||
|
class asset_dependency_base;
|
||||||
|
using asset_dependency_base_iptr = intrusive_ptr<asset_dependency_base>;
|
||||||
|
|
||||||
|
class asset_dependency_base
|
||||||
|
: private noncopyable
|
||||||
|
, public ref_counter<asset_dependency_base> {
|
||||||
|
public:
|
||||||
|
asset_dependency_base() = default;
|
||||||
|
virtual ~asset_dependency_base() noexcept = default;
|
||||||
|
|
||||||
|
virtual const str& main_address() const noexcept = 0;
|
||||||
|
virtual stdex::promise<asset_ptr> load_async(const library& library) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// asset_dependency
|
||||||
|
//
|
||||||
|
|
||||||
|
template < typename Asset >
|
||||||
|
class asset_dependency : public asset_dependency_base {
|
||||||
|
public:
|
||||||
|
using asset_type = Asset;
|
||||||
|
using load_result = typename Asset::load_result;
|
||||||
|
public:
|
||||||
|
asset_dependency(str_view address);
|
||||||
|
~asset_dependency() noexcept override;
|
||||||
|
|
||||||
|
const str& main_address() const noexcept override;
|
||||||
|
stdex::promise<asset_ptr> load_async(const library& library) override;
|
||||||
|
private:
|
||||||
|
str main_address_;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// asset_dependencies
|
||||||
|
//
|
||||||
|
|
||||||
|
class asset_dependencies final {
|
||||||
|
public:
|
||||||
|
asset_dependencies() = default;
|
||||||
|
~asset_dependencies() noexcept = default;
|
||||||
|
|
||||||
|
template < typename Asset >
|
||||||
|
asset_dependencies& add_dependency(str_view address);
|
||||||
|
stdex::promise<asset_group> load_async(const library& library);
|
||||||
|
private:
|
||||||
|
vector<asset_dependency_base_iptr> dependencies_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,74 +13,277 @@
|
|||||||
|
|
||||||
namespace e2d
|
namespace e2d
|
||||||
{
|
{
|
||||||
|
//
|
||||||
|
// loading_asset
|
||||||
|
//
|
||||||
|
|
||||||
|
template < typename Asset >
|
||||||
|
loading_asset<Asset>::loading_asset(str_hash address, promise_type promise)
|
||||||
|
: address_(address)
|
||||||
|
, promise_(std::move(promise)) {}
|
||||||
|
|
||||||
|
template < typename Asset >
|
||||||
|
void loading_asset<Asset>::cancel() noexcept {
|
||||||
|
promise_.reject(library_cancelled_exception());
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename Asset >
|
||||||
|
str_hash loading_asset<Asset>::address() const noexcept {
|
||||||
|
return address_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename Asset >
|
||||||
|
const typename loading_asset<Asset>::promise_type& loading_asset<Asset>::promise() const noexcept {
|
||||||
|
return promise_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// library
|
||||||
|
//
|
||||||
|
|
||||||
|
inline library::library(const url& root, deferrer& deferrer)
|
||||||
|
: root_(root)
|
||||||
|
, deferrer_(deferrer) {}
|
||||||
|
|
||||||
|
inline library::~library() noexcept {
|
||||||
|
std::unique_lock<std::recursive_mutex> lock(mutex_);
|
||||||
|
cancelled_.store(true);
|
||||||
|
cancel_all_loading_assets_();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const url& library::root() const noexcept {
|
||||||
|
return root_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const asset_cache& library::cache() const noexcept {
|
||||||
|
return cache_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::size_t library::unload_unused_assets() noexcept {
|
||||||
|
return cache_.unload_unused_assets();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::size_t library::loading_asset_count() const noexcept {
|
||||||
|
std::lock_guard<std::recursive_mutex> guard(mutex_);
|
||||||
|
return loading_assets_.size();
|
||||||
|
}
|
||||||
|
|
||||||
template < typename Asset >
|
template < typename Asset >
|
||||||
typename Asset::load_result library::load_main_asset(str_view address) const {
|
typename Asset::load_result library::load_main_asset(str_view address) const {
|
||||||
auto p = load_main_asset_async<Asset>(address);
|
auto p = load_main_asset_async<Asset>(address);
|
||||||
|
deferrer_.active_safe_wait_promise(p);
|
||||||
if ( modules::is_initialized<deferrer>() ) {
|
|
||||||
the<deferrer>().active_safe_wait_promise(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
return p.get_or_default(nullptr);
|
return p.get_or_default(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename Asset >
|
template < typename Asset >
|
||||||
typename Asset::load_async_result library::load_main_asset_async(str_view address) const {
|
typename Asset::load_async_result library::load_main_asset_async(str_view address) const {
|
||||||
const auto main_address = address::parent(address);
|
if ( cancelled_ ) {
|
||||||
const auto main_address_hash = make_hash(main_address);
|
return stdex::make_rejected_promise<typename Asset::load_result>(library_cancelled_exception());
|
||||||
|
|
||||||
if ( !modules::is_initialized<asset_cache<Asset>>() ) {
|
|
||||||
return Asset::load_async(*this, main_address);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& cache = the<asset_cache<Asset>>();
|
const str main_address = address::parent(address);
|
||||||
if ( auto cached_asset = cache.find(main_address_hash) ) {
|
const str_hash main_address_hash = make_hash(main_address);
|
||||||
|
|
||||||
|
std::lock_guard<std::recursive_mutex> guard(mutex_);
|
||||||
|
|
||||||
|
if ( auto cached_asset = cache_.find<Asset>(main_address_hash) ) {
|
||||||
return stdex::make_resolved_promise(std::move(cached_asset));
|
return stdex::make_resolved_promise(std::move(cached_asset));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Asset::load_async(*this, main_address)
|
if ( auto asset = find_loading_asset_<Asset>(main_address_hash) ) {
|
||||||
.then([
|
return asset->promise();
|
||||||
&cache,
|
}
|
||||||
main_address_hash
|
|
||||||
](const typename Asset::load_result& new_asset){
|
auto p = Asset::load_async(*this, main_address)
|
||||||
cache.store(main_address_hash, new_asset);
|
.then([
|
||||||
return new_asset;
|
this,
|
||||||
});
|
main_address_hash
|
||||||
|
](const typename Asset::load_result& new_asset){
|
||||||
|
std::lock_guard<std::recursive_mutex> guard(mutex_);
|
||||||
|
cache_.store<Asset>(main_address_hash, new_asset);
|
||||||
|
remove_loading_asset_<Asset>(main_address_hash);
|
||||||
|
return new_asset;
|
||||||
|
}).except([
|
||||||
|
this,
|
||||||
|
main_address_hash
|
||||||
|
](std::exception_ptr e) -> typename Asset::load_result {
|
||||||
|
std::lock_guard<std::recursive_mutex> guard(mutex_);
|
||||||
|
remove_loading_asset_<Asset>(main_address_hash);
|
||||||
|
std::rethrow_exception(e);
|
||||||
|
});
|
||||||
|
|
||||||
|
loading_assets_.push_back(new loading_asset<Asset>(address, p));
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename Asset, typename Nested >
|
template < typename Asset, typename Nested >
|
||||||
typename Nested::load_result library::load_asset(str_view address) const {
|
typename Nested::load_result library::load_asset(str_view address) const {
|
||||||
auto p = load_asset_async<Asset, Nested>(address);
|
auto p = load_asset_async<Asset, Nested>(address);
|
||||||
|
deferrer_.active_safe_wait_promise(p);
|
||||||
if ( modules::is_initialized<deferrer>() ) {
|
|
||||||
the<deferrer>().active_safe_wait_promise(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
return p.get_or_default(nullptr);
|
return p.get_or_default(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename Asset, typename Nested >
|
template < typename Asset, typename Nested >
|
||||||
typename Nested::load_async_result library::load_asset_async(str_view address) const {
|
typename Nested::load_async_result library::load_asset_async(str_view address) const {
|
||||||
return load_main_asset_async<Asset>(address::parent(address))
|
return load_main_asset_async<Asset>(address)
|
||||||
.then([
|
.then([
|
||||||
address = str(address)
|
nested_address = address::nested(address)
|
||||||
](const typename Asset::load_result& main_asset){
|
](const typename Asset::load_result& main_asset){
|
||||||
asset_ptr nested_asset = main_asset;
|
typename Nested::load_result nested_asset = nested_address.empty()
|
||||||
str nested_address = address::nested(address);
|
? dynamic_pointer_cast<Nested>(main_asset)
|
||||||
|
: main_asset->template find_nested_asset<Nested>(nested_address);
|
||||||
while ( nested_asset && !nested_address.empty() ) {
|
if ( nested_asset ) {
|
||||||
nested_asset = nested_asset->find_nested_asset(address::parent(nested_address));
|
return nested_asset;
|
||||||
nested_address = address::nested(nested_address);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
using nested_asset_type = typename Nested::asset_type;
|
|
||||||
if ( auto result = dynamic_pointer_cast<nested_asset_type>(nested_asset) ) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw asset_loading_exception();
|
throw asset_loading_exception();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template < typename Asset >
|
||||||
|
vector<loading_asset_base_iptr>::iterator
|
||||||
|
library::find_loading_asset_iter_(str_hash address) const noexcept {
|
||||||
|
return std::find_if(
|
||||||
|
loading_assets_.begin(), loading_assets_.end(),
|
||||||
|
[address](const loading_asset_base_iptr& asset) noexcept {
|
||||||
|
return asset->address() == address
|
||||||
|
&& dynamic_pointer_cast<loading_asset<Asset>>(asset);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename Asset >
|
||||||
|
typename loading_asset<Asset>::ptr
|
||||||
|
library::find_loading_asset_(str_hash address) const noexcept {
|
||||||
|
auto iter = find_loading_asset_iter_<Asset>(address);
|
||||||
|
return iter != loading_assets_.end()
|
||||||
|
? static_pointer_cast<loading_asset<Asset>>(*iter)
|
||||||
|
: nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename Asset >
|
||||||
|
void library::remove_loading_asset_(str_hash address) const noexcept {
|
||||||
|
auto iter = find_loading_asset_iter_<Asset>(address);
|
||||||
|
if ( iter != loading_assets_.end() ) {
|
||||||
|
loading_assets_.erase(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void library::cancel_all_loading_assets_() noexcept {
|
||||||
|
for ( const auto& asset : loading_assets_ ) {
|
||||||
|
asset->cancel();
|
||||||
|
}
|
||||||
|
loading_assets_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// asset_group
|
||||||
|
//
|
||||||
|
|
||||||
|
template < typename Iter >
|
||||||
|
asset_group& asset_group::add_assets(Iter first, Iter last) {
|
||||||
|
for ( auto iter = first; iter != last; ++iter ) {
|
||||||
|
add_asset(iter->first, iter->second);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename Container >
|
||||||
|
asset_group& asset_group::add_assets(Container&& container) {
|
||||||
|
return add_assets(std::begin(container), std::end(container));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline asset_group& asset_group::add_asset(str_view address, const asset_ptr& asset) {
|
||||||
|
str main_address = address::parent(address);
|
||||||
|
auto iter = std::upper_bound(
|
||||||
|
assets_.begin(), assets_.end(), main_address,
|
||||||
|
[](const str& l, const auto& r){
|
||||||
|
return l < r.first;
|
||||||
|
});
|
||||||
|
assets_.insert(iter, std::make_pair(std::move(main_address), asset));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename Asset, typename Nested >
|
||||||
|
typename Nested::load_result asset_group::find_asset(str_view address) const {
|
||||||
|
const str main_address = address::parent(address);
|
||||||
|
const str nested_address = address::nested(address);
|
||||||
|
auto iter = std::lower_bound(
|
||||||
|
assets_.begin(), assets_.end(), main_address,
|
||||||
|
[](const auto& l, const str& r) noexcept {
|
||||||
|
return l.first < r;
|
||||||
|
});
|
||||||
|
for ( ; iter != assets_.end() && iter->first == main_address; ++iter ) {
|
||||||
|
asset_ptr main_asset = iter->second;
|
||||||
|
typename Asset::load_result typed_main_asset = dynamic_pointer_cast<Asset>(main_asset);
|
||||||
|
if ( !typed_main_asset ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
typename Nested::load_result nested_asset = nested_address.empty()
|
||||||
|
? dynamic_pointer_cast<Nested>(typed_main_asset)
|
||||||
|
: typed_main_asset->template find_nested_asset<Nested>(nested_address);
|
||||||
|
if ( nested_asset ) {
|
||||||
|
return nested_asset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// asset_dependency
|
||||||
|
//
|
||||||
|
|
||||||
|
template < typename Asset >
|
||||||
|
asset_dependency<Asset>::asset_dependency(str_view address)
|
||||||
|
: main_address_(address::parent(address)) {}
|
||||||
|
|
||||||
|
template < typename Asset >
|
||||||
|
asset_dependency<Asset>::~asset_dependency() noexcept = default;
|
||||||
|
|
||||||
|
template < typename Asset >
|
||||||
|
const str& asset_dependency<Asset>::main_address() const noexcept {
|
||||||
|
return main_address_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename Asset >
|
||||||
|
stdex::promise<asset_ptr> asset_dependency<Asset>::load_async(const library& library) {
|
||||||
|
return library.load_main_asset_async<Asset>(main_address())
|
||||||
|
.then([](const typename Asset::load_result& main_asset){
|
||||||
|
return asset_ptr(main_asset);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// asset_dependencies
|
||||||
|
//
|
||||||
|
|
||||||
|
template < typename Asset >
|
||||||
|
asset_dependencies& asset_dependencies::add_dependency(str_view address) {
|
||||||
|
asset_dependency_base_iptr dep(new asset_dependency<Asset>(address));
|
||||||
|
auto iter = std::upper_bound(
|
||||||
|
dependencies_.begin(), dependencies_.end(), dep->main_address(),
|
||||||
|
[](const str& l, const auto& r){
|
||||||
|
return l < r->main_address();
|
||||||
|
});
|
||||||
|
dependencies_.insert(iter, std::move(dep));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline stdex::promise<asset_group> asset_dependencies::load_async(const library& library) {
|
||||||
|
vector<stdex::promise<std::pair<str, asset_ptr>>> promises;
|
||||||
|
promises.reserve(dependencies_.size());
|
||||||
|
std::transform(
|
||||||
|
dependencies_.begin(), dependencies_.end(), std::back_inserter(promises),
|
||||||
|
[&library](const asset_dependency_base_iptr& dep){
|
||||||
|
return dep->load_async(library)
|
||||||
|
.then([main_address = dep->main_address()](const asset_ptr& asset){
|
||||||
|
return std::make_pair(main_address, asset);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return stdex::make_all_promise(std::move(promises))
|
||||||
|
.then([](const vector<std::pair<str, asset_ptr>>& results){
|
||||||
|
return asset_group()
|
||||||
|
.add_assets(results.begin(), results.end());
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -39,13 +39,13 @@ namespace e2d
|
|||||||
|
|
||||||
namespace e2d
|
namespace e2d
|
||||||
{
|
{
|
||||||
using str = basic_string<char>;
|
using str = basic_string<char>;
|
||||||
using wstr = basic_string<wchar_t>;
|
using wstr = basic_string<wchar_t>;
|
||||||
using str16 = basic_string<char16_t>;
|
using str16 = basic_string<char16_t>;
|
||||||
using str32 = basic_string<char32_t>;
|
using str32 = basic_string<char32_t>;
|
||||||
|
|
||||||
using str_view = basic_string_view<char>;
|
using str_view = basic_string_view<char>;
|
||||||
using wstr_view = basic_string_view<wchar_t>;
|
using wstr_view = basic_string_view<wchar_t>;
|
||||||
using str16_view = basic_string_view<char16_t>;
|
using str16_view = basic_string_view<char16_t>;
|
||||||
using str32_view = basic_string_view<char32_t>;
|
using str32_view = basic_string_view<char32_t>;
|
||||||
|
|
||||||
@@ -147,4 +147,36 @@ namespace e2d { namespace utils
|
|||||||
constexpr std::underlying_type_t<E> enum_to_underlying(E e) noexcept {
|
constexpr std::underlying_type_t<E> enum_to_underlying(E e) noexcept {
|
||||||
return static_cast<std::underlying_type_t<E>>(e);
|
return static_cast<std::underlying_type_t<E>>(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// type_family
|
||||||
|
//
|
||||||
|
|
||||||
|
using type_family_id = u32;
|
||||||
|
|
||||||
|
namespace impl
|
||||||
|
{
|
||||||
|
template < typename Void = void >
|
||||||
|
class type_family_base {
|
||||||
|
static_assert(
|
||||||
|
std::is_void<Void>::value &&
|
||||||
|
std::is_unsigned<type_family_id>::value,
|
||||||
|
"unexpected internal error");
|
||||||
|
protected:
|
||||||
|
static type_family_id last_id_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename Void >
|
||||||
|
type_family_id type_family_base<Void>::last_id_ = 0u;
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
class type_family final : public impl::type_family_base<> {
|
||||||
|
public:
|
||||||
|
static type_family_id id() noexcept {
|
||||||
|
static type_family_id self_id = ++last_id_;
|
||||||
|
assert(self_id > 0u && "type_family_id overflow");
|
||||||
|
return self_id;
|
||||||
|
}
|
||||||
|
};
|
||||||
}}
|
}}
|
||||||
|
|||||||
15
scripts/pvs_analyze.sh
Executable file
15
scripts/pvs_analyze.sh
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
BUILD_DIR=`dirname "$BASH_SOURCE"`/../build
|
||||||
|
mkdir -p $BUILD_DIR/pvs_analyze
|
||||||
|
cd $BUILD_DIR/pvs_analyze
|
||||||
|
rm -rf pvs_report
|
||||||
|
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=On ../..
|
||||||
|
pvs-studio-analyzer analyze\
|
||||||
|
-e ../../untests\
|
||||||
|
-e ../../modules\
|
||||||
|
-e ../../sources/3rdparty\
|
||||||
|
-o pvs_report.log\
|
||||||
|
-j8
|
||||||
|
plog-converter -a GA:1,2 -t fullhtml -o pvs_report pvs_report.log
|
||||||
|
open pvs_report/index.html
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* This file is part of the "Enduro2D"
|
|
||||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
|
||||||
* Copyright (C) 2018-2019, by Matvey Cherevko (blackmatov@gmail.com)
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include <enduro2d/high/asset.hpp>
|
|
||||||
|
|
||||||
namespace e2d
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// asset
|
|
||||||
//
|
|
||||||
|
|
||||||
asset::asset() = default;
|
|
||||||
asset::~asset() noexcept = default;
|
|
||||||
|
|
||||||
//
|
|
||||||
// asset_cache_base
|
|
||||||
//
|
|
||||||
|
|
||||||
std::mutex asset_cache_base::mutex_;
|
|
||||||
hash_set<asset_cache_base*> asset_cache_base::caches_;
|
|
||||||
|
|
||||||
asset_cache_base::asset_cache_base() {
|
|
||||||
std::lock_guard<std::mutex> guard(mutex_);
|
|
||||||
caches_.insert(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
asset_cache_base::~asset_cache_base() noexcept {
|
|
||||||
std::lock_guard<std::mutex> guard(mutex_);
|
|
||||||
caches_.erase(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t asset_cache_base::unload_all_unused_assets() noexcept {
|
|
||||||
std::lock_guard<std::mutex> guard(mutex_);
|
|
||||||
return std::accumulate(caches_.begin(), caches_.end(), std::size_t(0),
|
|
||||||
[](std::size_t acc, asset_cache_base* cache){
|
|
||||||
return acc + cache->unload_self_unused_assets();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// asset_factory
|
|
||||||
//
|
|
||||||
|
|
||||||
asset_factory::asset_factory() = default;
|
|
||||||
asset_factory::~asset_factory() noexcept = default;
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* This file is part of the "Enduro2D"
|
|
||||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
|
||||||
* Copyright (C) 2018-2019, by Matvey Cherevko (blackmatov@gmail.com)
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#include <enduro2d/high/library.hpp>
|
|
||||||
|
|
||||||
namespace e2d
|
|
||||||
{
|
|
||||||
library::library(const url& root)
|
|
||||||
: root_(root) {}
|
|
||||||
|
|
||||||
library::~library() noexcept = default;
|
|
||||||
|
|
||||||
const url& library::root() const noexcept {
|
|
||||||
return root_;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t library::unload_unused_assets() noexcept {
|
|
||||||
return asset_cache_base::unload_all_unused_assets();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,20 +9,6 @@
|
|||||||
#include <enduro2d/high/world.hpp>
|
#include <enduro2d/high/world.hpp>
|
||||||
#include <enduro2d/high/library.hpp>
|
#include <enduro2d/high/library.hpp>
|
||||||
|
|
||||||
#include <enduro2d/high/assets/atlas_asset.hpp>
|
|
||||||
#include <enduro2d/high/assets/binary_asset.hpp>
|
|
||||||
#include <enduro2d/high/assets/flipbook_asset.hpp>
|
|
||||||
#include <enduro2d/high/assets/image_asset.hpp>
|
|
||||||
#include <enduro2d/high/assets/material_asset.hpp>
|
|
||||||
#include <enduro2d/high/assets/mesh_asset.hpp>
|
|
||||||
#include <enduro2d/high/assets/model_asset.hpp>
|
|
||||||
#include <enduro2d/high/assets/prefab_asset.hpp>
|
|
||||||
#include <enduro2d/high/assets/shader_asset.hpp>
|
|
||||||
#include <enduro2d/high/assets/shape_asset.hpp>
|
|
||||||
#include <enduro2d/high/assets/sprite_asset.hpp>
|
|
||||||
#include <enduro2d/high/assets/text_asset.hpp>
|
|
||||||
#include <enduro2d/high/assets/texture_asset.hpp>
|
|
||||||
|
|
||||||
#include <enduro2d/high/systems/flipbook_system.hpp>
|
#include <enduro2d/high/systems/flipbook_system.hpp>
|
||||||
#include <enduro2d/high/systems/render_system.hpp>
|
#include <enduro2d/high/systems/render_system.hpp>
|
||||||
|
|
||||||
@@ -129,53 +115,12 @@ namespace e2d
|
|||||||
|
|
||||||
starter::starter(int argc, char *argv[], const parameters& params) {
|
starter::starter(int argc, char *argv[], const parameters& params) {
|
||||||
safe_module_initialize<engine>(argc, argv, params.engine_params());
|
safe_module_initialize<engine>(argc, argv, params.engine_params());
|
||||||
safe_module_initialize<library>(params.library_root());
|
safe_module_initialize<library>(params.library_root(), the<deferrer>());
|
||||||
safe_module_initialize<asset_cache<atlas_asset>>(the<library>());
|
|
||||||
safe_module_initialize<asset_cache<binary_asset>>(the<library>());
|
|
||||||
safe_module_initialize<asset_cache<flipbook_asset>>(the<library>());
|
|
||||||
safe_module_initialize<asset_cache<image_asset>>(the<library>());
|
|
||||||
safe_module_initialize<asset_cache<material_asset>>(the<library>());
|
|
||||||
safe_module_initialize<asset_cache<mesh_asset>>(the<library>());
|
|
||||||
safe_module_initialize<asset_cache<model_asset>>(the<library>());
|
|
||||||
safe_module_initialize<asset_cache<prefab_asset>>(the<library>());
|
|
||||||
safe_module_initialize<asset_cache<shader_asset>>(the<library>());
|
|
||||||
safe_module_initialize<asset_cache<shape_asset>>(the<library>());
|
|
||||||
safe_module_initialize<asset_cache<sprite_asset>>(the<library>());
|
|
||||||
safe_module_initialize<asset_cache<text_asset>>(the<library>());
|
|
||||||
safe_module_initialize<asset_cache<texture_asset>>(the<library>());
|
|
||||||
safe_module_initialize<asset_factory>()
|
|
||||||
.register_asset<atlas_asset>("atlas")
|
|
||||||
.register_asset<binary_asset>("binary")
|
|
||||||
.register_asset<flipbook_asset>("flipbook")
|
|
||||||
.register_asset<image_asset>("image")
|
|
||||||
.register_asset<material_asset>("material")
|
|
||||||
.register_asset<mesh_asset>("mesh")
|
|
||||||
.register_asset<model_asset>("model")
|
|
||||||
.register_asset<prefab_asset>("prefab")
|
|
||||||
.register_asset<shader_asset>("shader")
|
|
||||||
.register_asset<shape_asset>("shape")
|
|
||||||
.register_asset<sprite_asset>("sprite")
|
|
||||||
.register_asset<text_asset>("text")
|
|
||||||
.register_asset<texture_asset>("texture");
|
|
||||||
safe_module_initialize<world>();
|
safe_module_initialize<world>();
|
||||||
}
|
}
|
||||||
|
|
||||||
starter::~starter() noexcept {
|
starter::~starter() noexcept {
|
||||||
modules::shutdown<world>();
|
modules::shutdown<world>();
|
||||||
modules::shutdown<asset_factory>();
|
|
||||||
modules::shutdown<asset_cache<texture_asset>>();
|
|
||||||
modules::shutdown<asset_cache<text_asset>>();
|
|
||||||
modules::shutdown<asset_cache<sprite_asset>>();
|
|
||||||
modules::shutdown<asset_cache<shape_asset>>();
|
|
||||||
modules::shutdown<asset_cache<shader_asset>>();
|
|
||||||
modules::shutdown<asset_cache<prefab_asset>>();
|
|
||||||
modules::shutdown<asset_cache<model_asset>>();
|
|
||||||
modules::shutdown<asset_cache<mesh_asset>>();
|
|
||||||
modules::shutdown<asset_cache<material_asset>>();
|
|
||||||
modules::shutdown<asset_cache<image_asset>>();
|
|
||||||
modules::shutdown<asset_cache<flipbook_asset>>();
|
|
||||||
modules::shutdown<asset_cache<binary_asset>>();
|
|
||||||
modules::shutdown<asset_cache<atlas_asset>>();
|
|
||||||
modules::shutdown<library>();
|
modules::shutdown<library>();
|
||||||
modules::shutdown<engine>();
|
modules::shutdown<engine>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,36 +44,43 @@ namespace
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("asset"){
|
TEST_CASE("asset") {
|
||||||
safe_starter_initializer initializer;
|
safe_starter_initializer initializer;
|
||||||
library& l = the<library>();
|
library& l = the<library>();
|
||||||
{
|
SECTION("nested_assets") {
|
||||||
REQUIRE_FALSE(l.load_asset<fake_asset>("none"));
|
{
|
||||||
|
REQUIRE_FALSE(l.load_asset<fake_asset>("none"));
|
||||||
|
|
||||||
auto fa = l.load_asset<fake_asset>("42");
|
auto fa = l.load_asset<fake_asset>("42");
|
||||||
REQUIRE(fa);
|
REQUIRE(fa);
|
||||||
REQUIRE(fa->content() == 42);
|
REQUIRE(fa->content() == 42);
|
||||||
|
|
||||||
REQUIRE_FALSE(fa->find_nested_asset("none"));
|
REQUIRE_FALSE(fa->find_nested_asset("none"));
|
||||||
REQUIRE(fa->find_nested_asset("21"));
|
REQUIRE(fa->find_nested_asset("21"));
|
||||||
REQUIRE_FALSE(fa->find_nested_asset<binary_asset>("21"));
|
REQUIRE(fa->find_nested_asset("21:/2"));
|
||||||
REQUIRE(fa->find_nested_asset<fake_nested_asset>("21"));
|
REQUIRE_FALSE(fa->find_nested_asset<binary_asset>("21"));
|
||||||
REQUIRE(fa->find_nested_asset<fake_nested_asset>("21")->content() == 21);
|
REQUIRE_FALSE(fa->find_nested_asset<binary_asset>("21:/2"));
|
||||||
REQUIRE(fa->find_nested_asset<fake_nested_asset>("84")->content() == 84);
|
REQUIRE(fa->find_nested_asset<fake_nested_asset>("21"));
|
||||||
}
|
REQUIRE(fa->find_nested_asset<fake_nested_asset>("21:/2"));
|
||||||
{
|
REQUIRE(fa->find_nested_asset<fake_nested_asset>("21")->content() == 21);
|
||||||
REQUIRE(l.load_asset<fake_asset, fake_nested_asset>("42:/21"));
|
REQUIRE(fa->find_nested_asset<fake_nested_asset>("21:/2")->content() == 2);
|
||||||
REQUIRE(l.load_asset<fake_asset, fake_nested_asset>("42:/21")->content() == 21);
|
REQUIRE(fa->find_nested_asset<fake_nested_asset>("84")->content() == 84);
|
||||||
|
REQUIRE(fa->find_nested_asset<fake_nested_asset>("84:/8")->content() == 8);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
REQUIRE(l.load_asset<fake_asset, fake_nested_asset>("42:/21"));
|
||||||
|
REQUIRE(l.load_asset<fake_asset, fake_nested_asset>("42:/21")->content() == 21);
|
||||||
|
|
||||||
REQUIRE_FALSE(l.load_asset<fake_asset, binary_asset>("42:/21"));
|
REQUIRE_FALSE(l.load_asset<fake_asset, binary_asset>("42:/21"));
|
||||||
REQUIRE_FALSE(l.load_asset<fake_asset, fake_nested_asset>("42:/none"));
|
REQUIRE_FALSE(l.load_asset<fake_asset, fake_nested_asset>("42:/none"));
|
||||||
REQUIRE_FALSE(l.load_asset<fake_asset, fake_nested_asset>("42:/none:/21"));
|
REQUIRE_FALSE(l.load_asset<fake_asset, fake_nested_asset>("42:/none:/21"));
|
||||||
|
|
||||||
REQUIRE(l.load_asset<fake_asset, fake_nested_asset>("42:/21:/2"));
|
REQUIRE(l.load_asset<fake_asset, fake_nested_asset>("42:/21:/2"));
|
||||||
REQUIRE(l.load_asset<fake_asset, fake_nested_asset>("42:/21:/2")->content() == 2);
|
REQUIRE(l.load_asset<fake_asset, fake_nested_asset>("42:/21:/2")->content() == 2);
|
||||||
|
|
||||||
REQUIRE_FALSE(l.load_asset<fake_asset, binary_asset>("42:/21:/2"));
|
REQUIRE_FALSE(l.load_asset<fake_asset, binary_asset>("42:/21:/2"));
|
||||||
REQUIRE_FALSE(l.load_asset<fake_asset, fake_nested_asset>("42:/21:/none"));
|
REQUIRE_FALSE(l.load_asset<fake_asset, fake_nested_asset>("42:/21:/none"));
|
||||||
REQUIRE_FALSE(l.load_asset<fake_asset, fake_nested_asset>("42:/21:/none:/2"));
|
REQUIRE_FALSE(l.load_asset<fake_asset, fake_nested_asset>("42:/21:/none:/2"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,44 @@ namespace
|
|||||||
TEST_CASE("library"){
|
TEST_CASE("library"){
|
||||||
safe_starter_initializer initializer;
|
safe_starter_initializer initializer;
|
||||||
library& l = the<library>();
|
library& l = the<library>();
|
||||||
|
{
|
||||||
|
binary_asset::ptr b1;
|
||||||
|
binary_asset::ptr b2;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto p1 = l.load_asset_async<binary_asset>("binary_asset.bin");
|
||||||
|
auto p2 = l.load_asset_async<binary_asset>("binary_asset.bin");
|
||||||
|
|
||||||
|
the<deferrer>().active_safe_wait_promise(p1);
|
||||||
|
the<deferrer>().active_safe_wait_promise(p2);
|
||||||
|
|
||||||
|
b1 = p1.get();
|
||||||
|
b2 = p2.get();
|
||||||
|
REQUIRE(b1 == b2);
|
||||||
|
}
|
||||||
|
|
||||||
|
b1.reset();
|
||||||
|
b2.reset();
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
|
REQUIRE(1u == l.unload_unused_assets());
|
||||||
|
REQUIRE(l.cache().asset_count<binary_asset>() == 0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
{
|
||||||
|
auto p1 = l.load_asset_async<binary_asset>("binary_asset.bin");
|
||||||
|
REQUIRE(l.loading_asset_count() == 1);
|
||||||
|
the<deferrer>().active_safe_wait_promise(p1);
|
||||||
|
REQUIRE(l.loading_asset_count() == 0);
|
||||||
|
|
||||||
|
auto p2 = l.load_asset_async<binary_asset>("none_asset");
|
||||||
|
REQUIRE(l.loading_asset_count() == 1);
|
||||||
|
the<deferrer>().active_safe_wait_promise(p2);
|
||||||
|
REQUIRE(l.loading_asset_count() == 0);
|
||||||
|
}
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
|
REQUIRE(1u == l.unload_unused_assets());
|
||||||
|
}
|
||||||
{
|
{
|
||||||
auto text_res = l.load_asset<text_asset>("text_asset.txt");
|
auto text_res = l.load_asset<text_asset>("text_asset.txt");
|
||||||
REQUIRE(text_res);
|
REQUIRE(text_res);
|
||||||
@@ -36,15 +74,17 @@ TEST_CASE("library"){
|
|||||||
REQUIRE(text_res_from_cache);
|
REQUIRE(text_res_from_cache);
|
||||||
REQUIRE(text_res_from_cache.get() == text_res.get());
|
REQUIRE(text_res_from_cache.get() == text_res.get());
|
||||||
|
|
||||||
REQUIRE(0u == the<asset_cache<text_asset>>().unload_self_unused_assets());
|
REQUIRE(0u == l.unload_unused_assets());
|
||||||
REQUIRE(the<asset_cache<text_asset>>().asset_count() == 1);
|
REQUIRE(l.cache().asset_count() == 1);
|
||||||
|
REQUIRE(l.cache().asset_count<text_asset>() == 1);
|
||||||
|
|
||||||
text_res.reset();
|
text_res.reset();
|
||||||
text_res_from_cache.reset();
|
text_res_from_cache.reset();
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
REQUIRE(1u == the<asset_cache<text_asset>>().unload_self_unused_assets());
|
REQUIRE(1u == l.unload_unused_assets());
|
||||||
REQUIRE(the<asset_cache<text_asset>>().asset_count() == 0);
|
REQUIRE(l.cache().asset_count() == 0);
|
||||||
|
REQUIRE(l.cache().asset_count<text_asset>() == 0);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto text_res = l.load_asset<text_asset>("text_asset.txt");
|
auto text_res = l.load_asset<text_asset>("text_asset.txt");
|
||||||
@@ -56,12 +96,14 @@ TEST_CASE("library"){
|
|||||||
REQUIRE(binary_res->content() == buffer("world", 5));
|
REQUIRE(binary_res->content() == buffer("world", 5));
|
||||||
|
|
||||||
REQUIRE(0u == l.unload_unused_assets());
|
REQUIRE(0u == l.unload_unused_assets());
|
||||||
|
REQUIRE(l.cache().asset_count() == 2);
|
||||||
|
|
||||||
text_res.reset();
|
text_res.reset();
|
||||||
binary_res.reset();
|
binary_res.reset();
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
REQUIRE(2u == l.unload_unused_assets());
|
REQUIRE(2u == l.unload_unused_assets());
|
||||||
|
REQUIRE(l.cache().asset_count() == 0);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto empty_res = l.load_asset<binary_asset>("empty_asset");
|
auto empty_res = l.load_asset<binary_asset>("empty_asset");
|
||||||
@@ -72,19 +114,19 @@ TEST_CASE("library"){
|
|||||||
REQUIRE(image_res);
|
REQUIRE(image_res);
|
||||||
REQUIRE(!image_res->content().empty());
|
REQUIRE(!image_res->content().empty());
|
||||||
|
|
||||||
REQUIRE(the<asset_cache<image_asset>>().find("image.png"));
|
REQUIRE(l.cache().find<image_asset>("image.png"));
|
||||||
REQUIRE(the<asset_cache<binary_asset>>().find("image.png"));
|
REQUIRE(l.cache().find<binary_asset>("image.png"));
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
the<asset_cache<binary_asset>>().unload_self_unused_assets();
|
l.unload_unused_assets();
|
||||||
REQUIRE(the<asset_cache<image_asset>>().find("image.png"));
|
REQUIRE(l.cache().find<image_asset>("image.png"));
|
||||||
REQUIRE_FALSE(the<asset_cache<binary_asset>>().find("image.png"));
|
REQUIRE_FALSE(l.cache().find<binary_asset>("image.png"));
|
||||||
|
|
||||||
image_res.reset();
|
image_res.reset();
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
the<asset_cache<image_asset>>().unload_self_unused_assets();
|
l.unload_unused_assets();
|
||||||
REQUIRE_FALSE(the<asset_cache<image_asset>>().find("image.png"));
|
REQUIRE_FALSE(l.cache().find<image_asset>("image.png"));
|
||||||
REQUIRE_FALSE(the<asset_cache<binary_asset>>().find("image.png"));
|
REQUIRE_FALSE(l.cache().find<binary_asset>("image.png"));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
if ( modules::is_initialized<render>() ) {
|
if ( modules::is_initialized<render>() ) {
|
||||||
@@ -284,3 +326,39 @@ TEST_CASE("library"){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("asset_dependencies") {
|
||||||
|
safe_starter_initializer initializer;
|
||||||
|
library& l = the<library>();
|
||||||
|
{
|
||||||
|
auto ad = asset_dependencies()
|
||||||
|
.add_dependency<text_asset>("text_asset.txt")
|
||||||
|
.add_dependency<binary_asset>("binary_asset.bin");
|
||||||
|
auto g1_p = ad.load_async(l);
|
||||||
|
the<deferrer>().active_safe_wait_promise(g1_p);
|
||||||
|
asset_group g1 = g1_p.get();
|
||||||
|
REQUIRE(g1.find_asset<text_asset>("text_asset.txt"));
|
||||||
|
REQUIRE(g1.find_asset<binary_asset>("binary_asset.bin"));
|
||||||
|
|
||||||
|
ad.add_dependency<text_asset>("none_asset");
|
||||||
|
auto g2_p = ad.load_async(l);
|
||||||
|
the<deferrer>().active_safe_wait_promise(g2_p);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
if ( modules::is_initialized<render>() ) {
|
||||||
|
auto ad = asset_dependencies()
|
||||||
|
.add_dependency<atlas_asset>("atlas.json:/sprite");
|
||||||
|
auto g1_p = ad.load_async(l);
|
||||||
|
the<deferrer>().active_safe_wait_promise(g1_p);
|
||||||
|
asset_group g1 = g1_p.get();
|
||||||
|
REQUIRE(g1.find_asset<atlas_asset>("atlas.json")
|
||||||
|
== l.load_asset<atlas_asset>("atlas.json"));
|
||||||
|
REQUIRE(g1.find_asset<atlas_asset, sprite_asset>("atlas.json:/sprite")
|
||||||
|
== l.load_asset<atlas_asset, sprite_asset>("atlas.json:/sprite"));
|
||||||
|
|
||||||
|
ad.add_dependency<sprite_asset>("atlas.json:/sprite");
|
||||||
|
auto g2_p = ad.load_async(l);
|
||||||
|
the<deferrer>().active_safe_wait_promise(g2_p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -49,4 +49,11 @@ TEST_CASE("utils") {
|
|||||||
42u, str1, str1 + std::strlen(str1)
|
42u, str1, str1 + std::strlen(str1)
|
||||||
) == utils::sdbm_hash(42u, str2));
|
) == utils::sdbm_hash(42u, str2));
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
utils::type_family_id id1 = utils::type_family<str16>::id();
|
||||||
|
utils::type_family_id id2 = utils::type_family<str32>::id();
|
||||||
|
REQUIRE(id1 != id2);
|
||||||
|
REQUIRE(id1 == utils::type_family<str16>::id());
|
||||||
|
REQUIRE(id2 == utils::type_family<str32>::id());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user