diff --git a/doc/changelog.dox b/doc/changelog.dox index 7eeac69f8..802079ca7 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -139,6 +139,9 @@ See also: - The @ref ResourceManager class now accepts also @ref Corrade::Containers::Pointer instances in addition to raw pointers +- The @ref AbstractResourceLoader::set() function now accepts also + @cpp nullptr @ce for explicitly setting @ref ResourceDataState::Loading or + @ref ResourceDataState::NotFound resources @subsubsection changelog-latest-changes-animation Animation library diff --git a/src/Magnum/AbstractResourceLoader.h b/src/Magnum/AbstractResourceLoader.h index d33961160..7c33eaed9 100644 --- a/src/Magnum/AbstractResourceLoader.h +++ b/src/Magnum/AbstractResourceLoader.h @@ -130,10 +130,17 @@ template class AbstractResourceLoader { /** * @brief Set loaded resource to resource manager * - * Also increments count of loaded resources. Parameter @p state must - * be either @ref ResourceDataState::Mutable or - * @ref ResourceDataState::Final. See @ref ResourceManager::set() for + * If @p data is @cpp nullptr @ce and @p state is + * @ref ResourceDataState::NotFound, increments count of not found + * resources. Otherwise, if @p data is not @cpp nullptr @ce, increments + * count of loaded resources. See @ref ResourceManager::set() for * more information. + * + * Note that resource's state is automatically set to + * @ref ResourceDataState::Loading when it is requested from + * @ref ResourceManager and it's not loaded yet, so it's not needed to + * call this function. For marking a resource as not found you can also + * use the convenience @ref setNotFound() variant. * @see @ref loadedCount() */ void set(ResourceKey key, T* data, ResourceDataState state, ResourcePolicy policy); @@ -144,7 +151,7 @@ template class AbstractResourceLoader { } /** @overload */ - template void set(ResourceKey key, U&& data, ResourceDataState state, ResourcePolicy policy) { + template::type, std::nullptr_t>::value>::type> void set(ResourceKey key, U&& data, ResourceDataState state, ResourcePolicy policy) { set(key, new typename std::decay::type(std::forward(data)), state, policy); } @@ -164,18 +171,21 @@ template class AbstractResourceLoader { } /** @overload */ - template void set(ResourceKey key, U&& data) { + template::type, std::nullptr_t>::value>::type> void set(ResourceKey key, U&& data) { set(key, new typename std::decay::type(std::forward(data))); } /** * @brief Mark resource as not found * - * Also increments count of not found resources. See also - * @ref ResourceManager::set() for more information. + * A convenience function calling @ref set() with @cpp nullptr @ce + * and @ref ResourceDataState::NotFound. * @see @ref notFoundCount() */ - void setNotFound(ResourceKey key); + void setNotFound(ResourceKey key) { + /** @todo What policy for notfound resources? */ + set(key, nullptr, ResourceDataState::NotFound, ResourcePolicy::Resident); + } #ifndef DOXYGEN_GENERATING_OUTPUT private: @@ -222,18 +232,11 @@ template void AbstractResourceLoader::load(ResourceKey key) { } template void AbstractResourceLoader::set(ResourceKey key, T* data, ResourceDataState state, ResourcePolicy policy) { - CORRADE_ASSERT(state == ResourceDataState::Mutable || state == ResourceDataState::Final, - "AbstractResourceLoader::set(): state must be either Mutable or Final", ); - ++_loadedCount; + if(data) ++_loadedCount; + if(!data && state == ResourceDataState::NotFound) ++_notFoundCount; manager->set(key, data, state, policy); } -template inline void AbstractResourceLoader::setNotFound(ResourceKey key) { - ++_notFoundCount; - /** @todo What policy for notfound resources? */ - manager->set(key, nullptr, ResourceDataState::NotFound, ResourcePolicy::Resident); -} - } #endif diff --git a/src/Magnum/Test/ResourceManagerTest.cpp b/src/Magnum/Test/ResourceManagerTest.cpp index 1fe9f9757..283018bf4 100644 --- a/src/Magnum/Test/ResourceManagerTest.cpp +++ b/src/Magnum/Test/ResourceManagerTest.cpp @@ -44,7 +44,9 @@ struct ResourceManagerTest: TestSuite::Tester { void defaults(); void clear(); void clearWhileReferenced(); + void loader(); + void loaderSetNullptr(); void debugResourceState(); }; @@ -71,7 +73,9 @@ ResourceManagerTest::ResourceManagerTest() { &ResourceManagerTest::defaults, &ResourceManagerTest::clear, &ResourceManagerTest::clearWhileReferenced, + &ResourceManagerTest::loader, + &ResourceManagerTest::loaderSetNullptr, &ResourceManagerTest::debugResourceState}); } @@ -333,6 +337,52 @@ void ResourceManagerTest::loader() { CORRADE_COMPARE(Data::count, 0); } +void ResourceManagerTest::loaderSetNullptr() { + class IntResourceLoader: public AbstractResourceLoader { + public: + void load() { + set("hello", 1337, ResourceDataState::Final, ResourcePolicy::Resident); + set("world", 42, ResourceDataState::Final, ResourcePolicy::Resident); + } + + private: + void doLoad(ResourceKey key) override { + /* Verify that calling load() with nullptr + Loading works */ + set(key, nullptr, ResourceDataState::Loading, ResourcePolicy::Resident); + set("world", nullptr, ResourceDataState::Loading, ResourcePolicy::Resident); + } + }; + + ResourceManager rm; + Containers::Pointer loaderPtr{Containers::InPlaceInit}; + IntResourceLoader& loader = *loaderPtr; + rm.setLoader(std::move(loaderPtr)); + + CORRADE_COMPARE(rm.state("hello"), ResourceState::NotLoaded); + CORRADE_COMPARE(rm.state("world"), ResourceState::NotLoaded); + + /* Loading "hello" triggers a load of "world" as well */ + Resource hello = rm.get("hello"); + CORRADE_COMPARE(hello.state(), ResourceState::Loading); + CORRADE_COMPARE(rm.state("world"), ResourceState::Loading); + CORRADE_COMPARE(loader.requestedCount(), 1); + CORRADE_COMPARE(loader.loadedCount(), 0); + CORRADE_COMPARE(loader.notFoundCount(), 0); + + /* Load the things */ + loader.load(); + CORRADE_COMPARE(hello.state(), ResourceState::Final); + CORRADE_COMPARE(*hello, 1337); + CORRADE_COMPARE(loader.requestedCount(), 1); + CORRADE_COMPARE(loader.loadedCount(), 2); + CORRADE_COMPARE(loader.notFoundCount(), 0); + + /* World is now loaded as well as a side-effect */ + Resource world = rm.get("world"); + CORRADE_COMPARE(world.state(), ResourceState::Final); + CORRADE_COMPARE(*world, 42); +} + void ResourceManagerTest::debugResourceState() { std::ostringstream out; Debug{&out} << ResourceState::Loading << ResourceState(0xbe);