diff --git a/headers/enduro2d/high/asset.hpp b/headers/enduro2d/high/asset.hpp index 7d41c6b8..39ffd6ca 100644 --- a/headers/enduro2d/high/asset.hpp +++ b/headers/enduro2d/high/asset.hpp @@ -37,17 +37,19 @@ namespace e2d // asset // + class asset; + using asset_ptr = intrusive_ptr; + using nested_content = hash_map; + class asset : private noncopyable , public ref_counter { public: asset(); virtual ~asset() noexcept; + virtual asset_ptr find_nested_asset(str_view name) const noexcept = 0; }; - using asset_ptr = intrusive_ptr; - using nested_content = hash_map; - // // content_asset // @@ -73,7 +75,7 @@ namespace e2d template < typename T > intrusive_ptr find_nested_asset(str_view name) const noexcept; - asset_ptr find_nested_asset(str_view name) const noexcept; + asset_ptr find_nested_asset(str_view name) const noexcept override; private: Content content_; nested_content nested_content_; diff --git a/headers/enduro2d/high/library.hpp b/headers/enduro2d/high/library.hpp index 7e6af3c8..d32eb25f 100644 --- a/headers/enduro2d/high/library.hpp +++ b/headers/enduro2d/high/library.hpp @@ -11,6 +11,7 @@ #include "_high.hpp" #include "asset.hpp" +#include "address.hpp" namespace e2d { @@ -42,6 +43,12 @@ namespace e2d template < typename Asset > typename Asset::load_async_result load_asset_async(str_view address) const; + + template < typename Asset, typename Nested > + typename Nested::load_result load_asset(str_view address) const; + + template < typename Asset, typename Nested > + typename Nested::load_async_result load_asset_async(str_view address) const; private: url root_; }; diff --git a/headers/enduro2d/high/library.inl b/headers/enduro2d/high/library.inl index cd5de2e3..74749e1c 100644 --- a/headers/enduro2d/high/library.inl +++ b/headers/enduro2d/high/library.inl @@ -27,24 +27,57 @@ namespace e2d template < typename Asset > typename Asset::load_async_result library::load_asset_async(str_view address) const { + const auto main_address = address::parent(address); + const auto main_address_hash = make_hash(main_address); + if ( !modules::is_initialized>() ) { - return Asset::load_async(*this, address); + return Asset::load_async(*this, main_address); } auto& cache = the>(); - if ( auto cached_asset = cache.find(address) ) { + if ( auto cached_asset = cache.find(main_address_hash) ) { return stdex::make_resolved_promise(std::move(cached_asset)); } - return Asset::load_async(*this, address) + return Asset::load_async(*this, main_address) .then([ &cache, - address_hash = make_hash(address) + main_address_hash ](const typename Asset::load_result& new_asset){ - cache.store(address_hash, new_asset); + cache.store(main_address_hash, new_asset); return new_asset; }); } + + template < typename Asset, typename Nested > + typename Nested::load_result library::load_asset(str_view address) const { + auto p = load_asset_async(address); + + if ( modules::is_initialized() ) { + the().active_safe_wait_promise(p); + } + + return p.get_or_default(nullptr); + } + + template < typename Asset, typename Nested > + typename Nested::load_async_result library::load_asset_async(str_view address) const { + return load_asset_async(address::parent(address)) + .then([ + nested_address = address::nested(address) + ](const typename Asset::load_result& main_asset) mutable { + asset_ptr nested_asset = main_asset; + while ( nested_asset && !nested_address.empty() ) { + nested_asset = nested_asset->find_nested_asset(address::parent(nested_address)); + nested_address = address::nested(nested_address); + } + using nested_asset_type = typename Nested::asset_type; + if ( auto result = dynamic_pointer_cast(nested_asset) ) { + return result; + } + throw asset_loading_exception(); + }); + } } #endif diff --git a/untests/sources/untests_high/asset.cpp b/untests/sources/untests_high/asset.cpp index 222bc3e2..26fe03db 100644 --- a/untests/sources/untests_high/asset.cpp +++ b/untests/sources/untests_high/asset.cpp @@ -23,14 +23,22 @@ namespace } }; + class fake_nested_asset final : public content_asset { + }; + class fake_asset final : public content_asset { public: static load_async_result load_async(const library& library, str_view address) { E2D_UNUSED(library); return address == "42" ? stdex::make_resolved_promise(fake_asset::create(42, { - {"21", fake_asset::create(21)}, - {"84", fake_asset::create(84)}})) + {"21", fake_nested_asset::create(21, { + {"2", fake_nested_asset::create(2)} + })}, + {"84", fake_nested_asset::create(84, { + {"8", fake_nested_asset::create(8)} + })} + })) : stdex::make_rejected_promise(asset_loading_exception()); } }; @@ -49,8 +57,23 @@ TEST_CASE("asset"){ REQUIRE_FALSE(fa->find_nested_asset("none")); REQUIRE(fa->find_nested_asset("21")); REQUIRE_FALSE(fa->find_nested_asset("21")); - REQUIRE(fa->find_nested_asset("21")); - REQUIRE(fa->find_nested_asset("21")->content() == 21); - REQUIRE(fa->find_nested_asset("84")->content() == 84); + REQUIRE(fa->find_nested_asset("21")); + REQUIRE(fa->find_nested_asset("21")->content() == 21); + REQUIRE(fa->find_nested_asset("84")->content() == 84); + } + { + REQUIRE(l.load_asset("42:/21")); + REQUIRE(l.load_asset("42:/21")->content() == 21); + + REQUIRE_FALSE(l.load_asset("42:/21")); + REQUIRE_FALSE(l.load_asset("42:/none")); + REQUIRE_FALSE(l.load_asset("42:/none:/21")); + + REQUIRE(l.load_asset("42:/21:/2")); + REQUIRE(l.load_asset("42:/21:/2")->content() == 2); + + REQUIRE_FALSE(l.load_asset("42:/21:/2")); + REQUIRE_FALSE(l.load_asset("42:/21:/none")); + REQUIRE_FALSE(l.load_asset("42:/21:/none:/2")); } }