From 5fa2963c0cdbe4c099e9e900ded1071ec159b54b Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Mon, 1 Apr 2019 21:22:36 +0700 Subject: [PATCH] separate asset and library headers --- headers/enduro2d/high/_all.hpp | 2 + headers/enduro2d/high/_high.hpp | 4 +- headers/enduro2d/high/asset.hpp | 115 ++++++++++++++++++++ headers/enduro2d/high/asset.inl | 126 ++++++++++++++++++++++ headers/enduro2d/high/library.hpp | 128 +---------------------- headers/enduro2d/high/library.inl | 56 ---------- headers/enduro2d/high/sprite.hpp | 1 - sources/enduro2d/high/asset.cpp | 42 ++++++++ sources/enduro2d/high/library.cpp | 34 ------ sources/enduro2d/high/sprite.cpp | 3 - untests/sources/untests_high/asset.cpp | 56 ++++++++++ untests/sources/untests_high/library.cpp | 77 +++++--------- 12 files changed, 372 insertions(+), 272 deletions(-) create mode 100644 headers/enduro2d/high/asset.hpp create mode 100644 headers/enduro2d/high/asset.inl create mode 100644 sources/enduro2d/high/asset.cpp create mode 100644 untests/sources/untests_high/asset.cpp diff --git a/headers/enduro2d/high/_all.hpp b/headers/enduro2d/high/_all.hpp index 83f9bdb3..92a3c077 100644 --- a/headers/enduro2d/high/_all.hpp +++ b/headers/enduro2d/high/_all.hpp @@ -30,6 +30,8 @@ #include "systems/render_system.hpp" #include "address.hpp" +#include "asset.hpp" +#include "asset.inl" #include "atlas.hpp" #include "library.hpp" #include "library.inl" diff --git a/headers/enduro2d/high/_high.hpp b/headers/enduro2d/high/_high.hpp index 5edbafb4..ba9755a9 100644 --- a/headers/enduro2d/high/_high.hpp +++ b/headers/enduro2d/high/_high.hpp @@ -45,12 +45,12 @@ namespace e2d class content_asset; class asset; - class library; - template < typename T > class asset_cache; class asset_cache_base; + class library; + class atlas; class model; class node; diff --git a/headers/enduro2d/high/asset.hpp b/headers/enduro2d/high/asset.hpp new file mode 100644 index 00000000..25d1e21d --- /dev/null +++ b/headers/enduro2d/high/asset.hpp @@ -0,0 +1,115 @@ +/******************************************************************************* + * This file is part of the "Enduro2D" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2018-2019 Matvey Cherevko + ******************************************************************************/ + +#ifndef E2D_INCLUDE_GUARD_1122A7CA62954AEF9E0A787064D28F73 +#define E2D_INCLUDE_GUARD_1122A7CA62954AEF9E0A787064D28F73 +#pragma once + +#include "_high.hpp" + +namespace e2d +{ + // + // asset_loading_exception + // + + class asset_loading_exception : public exception { + const char* what() const noexcept override { + return "asset loading exception"; + } + }; + + // + // asset + // + + class asset + : private noncopyable + , public ref_counter { + public: + asset(); + virtual ~asset() noexcept; + }; + + using asset_ptr = intrusive_ptr; + using nested_content = hash_map; + + // + // content_asset + // + + template < typename Asset, typename Content > + class content_asset : public asset { + public: + using asset_type = Asset; + using content_type = Content; + + using ptr = intrusive_ptr; + using load_result = intrusive_ptr; + using load_async_result = stdex::promise; + public: + static load_result create(); + static load_result create(Content content); + static load_result create(Content content, nested_content nested_content); + + void fill(Content content); + void fill(Content content, nested_content nested_content); + + const Content& content() const noexcept; + + template < typename T > + intrusive_ptr find_nested_asset(str_view name) const noexcept; + asset_ptr find_nested_asset(str_view name) const noexcept; + private: + Content content_; + nested_content nested_content_; + }; + + // + // asset_cache_base + // + + class asset_cache_base : private noncopyable { + public: + asset_cache_base(); + virtual ~asset_cache_base() noexcept; + + static std::size_t unload_all_unused_assets() noexcept; + virtual std::size_t unload_self_unused_assets() noexcept = 0; + private: + static std::mutex mutex_; + static hash_set caches_; + }; + + // + // asset_cache + // + + template < typename Asset > + class asset_cache : public asset_cache_base + , public module> { + public: + using asset_ptr = typename Asset::ptr; + public: + asset_cache(library& l); + ~asset_cache() noexcept final; + + asset_ptr find(str_hash address) const; + 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 assets_; + }; +} + +#include "asset.inl" +#endif diff --git a/headers/enduro2d/high/asset.inl b/headers/enduro2d/high/asset.inl new file mode 100644 index 00000000..2450775a --- /dev/null +++ b/headers/enduro2d/high/asset.inl @@ -0,0 +1,126 @@ +/******************************************************************************* + * This file is part of the "Enduro2D" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2018-2019 Matvey Cherevko + ******************************************************************************/ + +#ifndef E2D_INCLUDE_GUARD_6FD0B1DD12004CF78E7AC5FBBC36E854 +#define E2D_INCLUDE_GUARD_6FD0B1DD12004CF78E7AC5FBBC36E854 +#pragma once + +#include "_high.hpp" +#include "asset.hpp" + +namespace e2d +{ + // + // content_asset + // + + template < typename Asset, typename Content > + typename content_asset::load_result + content_asset::create() { + return load_result(new Asset()); + } + + template < typename Asset, typename Content > + typename content_asset::load_result + content_asset::create(Content content) { + auto result = create(); + result->fill(std::move(content)); + return result; + } + + template < typename Asset, typename Content > + typename content_asset::load_result + content_asset::create(Content content, nested_content nested_content) { + auto result = create(); + result->fill(std::move(content), std::move(nested_content)); + return result; + } + + template < typename Asset, typename Content > + void content_asset::fill(Content content) { + content_ = std::move(content); + } + + template < typename Asset, typename Content > + void content_asset::fill(Content content, nested_content nested_content) { + content_ = std::move(content); + nested_content_ = std::move(nested_content); + } + + template < typename Asset, typename Content > + const Content& content_asset::content() const noexcept { + return content_; + } + + template < typename Asset, typename Content > + template < typename T > + intrusive_ptr content_asset::find_nested_asset(str_view name) const noexcept { + return dynamic_pointer_cast(find_nested_asset(name)); + } + + template < typename Asset, typename Content > + asset_ptr content_asset::find_nested_asset(str_view name) const noexcept { + const auto iter = nested_content_.find(name); + return iter != nested_content_.end() + ? iter->second + : nullptr; + } + + // + // asset_cache + // + + template < typename T > + asset_cache::asset_cache(library& l) + : library_(l) {} + + template < typename T > + asset_cache::~asset_cache() noexcept = default; + + template < typename T > + typename asset_cache::asset_ptr asset_cache::find(str_hash address) const { + std::lock_guard guard(mutex_); + const auto iter = assets_.find(address); + return iter != assets_.end() + ? iter->second + : nullptr; + } + + template < typename T > + void asset_cache::store(str_hash address, const asset_ptr& asset) { + std::lock_guard guard(mutex_); + assets_[address] = asset; + } + + template < typename T > + void asset_cache::clear() noexcept { + std::lock_guard guard(mutex_); + assets_.clear(); + } + + template < typename T > + std::size_t asset_cache::asset_count() const noexcept { + std::lock_guard guard(mutex_); + return assets_.size(); + } + + template < typename T > + std::size_t asset_cache::unload_self_unused_assets() noexcept { + std::lock_guard guard(mutex_); + std::size_t result = 0u; + for ( auto iter = assets_.begin(); iter != assets_.end(); ) { + if ( !iter->second || 1 == iter->second->use_count() ) { + iter = assets_.erase(iter); + ++result; + } else { + ++iter; + } + } + return result; + } +} + +#endif diff --git a/headers/enduro2d/high/library.hpp b/headers/enduro2d/high/library.hpp index d9127c29..7e6af3c8 100644 --- a/headers/enduro2d/high/library.hpp +++ b/headers/enduro2d/high/library.hpp @@ -10,6 +10,8 @@ #include "_high.hpp" +#include "asset.hpp" + namespace e2d { // @@ -23,90 +25,6 @@ namespace e2d } }; - // - // asset_loading_exception - // - - class asset_loading_exception : public exception { - const char* what() const noexcept override { - return "asset loading exception"; - } - }; - - // - // asset - // - - class asset - : private noncopyable - , public ref_counter { - public: - asset() = default; - virtual ~asset() noexcept = default; - }; - - using asset_ptr = intrusive_ptr; - using nested_content = hash_map; - - // - // content_asset - // - - template < typename Asset, typename Content > - class content_asset : public asset { - public: - using asset_type = Asset; - using content_type = Content; - - using ptr = intrusive_ptr; - using load_result = intrusive_ptr; - using load_async_result = stdex::promise; - public: - static load_result create() { - return load_result(new Asset()); - } - - static load_result create(Content content) { - auto result = create(); - result->fill(std::move(content)); - return result; - } - - static load_result create(Content content, nested_content nested_content) { - auto result = create(); - result->fill(std::move(content), std::move(nested_content)); - return result; - } - - void fill(Content content) { - content_ = std::move(content); - } - - void fill(Content content, nested_content nested_content) { - content_ = std::move(content); - nested_content_ = std::move(nested_content); - } - - const Content& content() const noexcept { - return content_; - } - - asset_ptr find_nested_asset(str_view name) const noexcept { - const auto iter = nested_content_.find(name); - return iter != nested_content_.end() - ? iter->second - : nullptr; - } - - template < typename T > - intrusive_ptr find_nested_asset(str_view name) const noexcept { - return dynamic_pointer_cast(find_nested_asset(name)); - } - private: - Content content_; - nested_content nested_content_; - }; - // // library // @@ -127,48 +45,6 @@ namespace e2d private: url root_; }; - - // - // asset_cache_base - // - - class asset_cache_base : private noncopyable { - public: - asset_cache_base(); - virtual ~asset_cache_base() noexcept; - - static std::size_t unload_all_unused_assets() noexcept; - virtual std::size_t unload_self_unused_assets() noexcept = 0; - private: - static std::mutex mutex_; - static hash_set caches_; - }; - - // - // asset_cache - // - - template < typename Asset > - class asset_cache : public asset_cache_base - , public module> { - public: - using asset_ptr = typename Asset::ptr; - public: - asset_cache(library& l); - ~asset_cache() noexcept final; - - asset_ptr find(str_hash address) const; - 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 assets_; - }; } #include "library.inl" diff --git a/headers/enduro2d/high/library.inl b/headers/enduro2d/high/library.inl index 008cd066..cd5de2e3 100644 --- a/headers/enduro2d/high/library.inl +++ b/headers/enduro2d/high/library.inl @@ -13,9 +13,6 @@ namespace e2d { - // - // library - // template < typename Asset > typename Asset::load_result library::load_asset(str_view address) const { @@ -48,59 +45,6 @@ namespace e2d return new_asset; }); } - - // - // asset_cache - // - - template < typename T > - asset_cache::asset_cache(library& l) - : library_(l) {} - - template < typename T > - asset_cache::~asset_cache() noexcept = default; - - template < typename T > - typename asset_cache::asset_ptr asset_cache::find(str_hash address) const { - std::lock_guard guard(mutex_); - const auto iter = assets_.find(address); - return iter != assets_.end() - ? iter->second - : nullptr; - } - - template < typename T > - void asset_cache::store(str_hash address, const asset_ptr& asset) { - std::lock_guard guard(mutex_); - assets_[address] = asset; - } - - template < typename T > - void asset_cache::clear() noexcept { - std::lock_guard guard(mutex_); - assets_.clear(); - } - - template < typename T > - std::size_t asset_cache::asset_count() const noexcept { - std::lock_guard guard(mutex_); - return assets_.size(); - } - - template < typename T > - std::size_t asset_cache::unload_self_unused_assets() noexcept { - std::lock_guard guard(mutex_); - std::size_t result = 0u; - for ( auto iter = assets_.begin(); iter != assets_.end(); ) { - if ( !iter->second || 1 == iter->second->use_count() ) { - iter = assets_.erase(iter); - ++result; - } else { - ++iter; - } - } - return result; - } } #endif diff --git a/headers/enduro2d/high/sprite.hpp b/headers/enduro2d/high/sprite.hpp index 435d3bb5..066d86d7 100644 --- a/headers/enduro2d/high/sprite.hpp +++ b/headers/enduro2d/high/sprite.hpp @@ -42,7 +42,6 @@ namespace e2d const texture_asset::ptr& texture() const noexcept; const material_asset::ptr& material() const noexcept; private: - v2f size_; v2f pivot_; b2f texrect_; texture_asset::ptr texture_; diff --git a/sources/enduro2d/high/asset.cpp b/sources/enduro2d/high/asset.cpp new file mode 100644 index 00000000..a9590bf7 --- /dev/null +++ b/sources/enduro2d/high/asset.cpp @@ -0,0 +1,42 @@ +/******************************************************************************* + * This file is part of the "Enduro2D" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2018-2019 Matvey Cherevko + ******************************************************************************/ + +#include + +namespace e2d +{ + // + // asset + // + + asset::asset() = default; + asset::~asset() noexcept = default; + + // + // asset_cache_base + // + + std::mutex asset_cache_base::mutex_; + hash_set asset_cache_base::caches_; + + asset_cache_base::asset_cache_base() { + std::lock_guard guard(mutex_); + caches_.insert(this); + } + + asset_cache_base::~asset_cache_base() noexcept { + std::lock_guard guard(mutex_); + caches_.erase(this); + } + + std::size_t asset_cache_base::unload_all_unused_assets() noexcept { + std::lock_guard 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(); + }); + } +} diff --git a/sources/enduro2d/high/library.cpp b/sources/enduro2d/high/library.cpp index 4fc83c1e..08e9ed1a 100644 --- a/sources/enduro2d/high/library.cpp +++ b/sources/enduro2d/high/library.cpp @@ -6,17 +6,8 @@ #include -namespace -{ - using namespace e2d; -} - namespace e2d { - // - // library - // - library::library(const url& root) : root_(root) {} @@ -29,29 +20,4 @@ namespace e2d std::size_t library::unload_unused_assets() noexcept { return asset_cache_base::unload_all_unused_assets(); } - - // - // asset_cache_base - // - - std::mutex asset_cache_base::mutex_; - hash_set asset_cache_base::caches_; - - asset_cache_base::asset_cache_base() { - std::lock_guard guard(mutex_); - caches_.insert(this); - } - - asset_cache_base::~asset_cache_base() noexcept { - std::lock_guard guard(mutex_); - caches_.erase(this); - } - - std::size_t asset_cache_base::unload_all_unused_assets() noexcept { - std::lock_guard 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(); - }); - } } diff --git a/sources/enduro2d/high/sprite.cpp b/sources/enduro2d/high/sprite.cpp index 211fac7b..8efdb882 100644 --- a/sources/enduro2d/high/sprite.cpp +++ b/sources/enduro2d/high/sprite.cpp @@ -28,7 +28,6 @@ namespace e2d } void sprite::clear() noexcept { - size_ = v2f::zero(); pivot_ = v2f::zero(); texrect_ = b2f::zero(); texture_.reset(); @@ -37,7 +36,6 @@ namespace e2d void sprite::swap(sprite& other) noexcept { using std::swap; - swap(size_, other.size_); swap(pivot_, other.pivot_); swap(texrect_, other.texrect_); swap(texture_, other.texture_); @@ -55,7 +53,6 @@ namespace e2d sprite& sprite::assign(const sprite& other) { if ( this != &other ) { sprite s; - s.size_ = other.size_; s.pivot_ = other.pivot_; s.texrect_ = other.texrect_; s.texture_ = other.texture_; diff --git a/untests/sources/untests_high/asset.cpp b/untests/sources/untests_high/asset.cpp new file mode 100644 index 00000000..222bc3e2 --- /dev/null +++ b/untests/sources/untests_high/asset.cpp @@ -0,0 +1,56 @@ +/******************************************************************************* + * This file is part of the "Enduro2D" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2018-2019 Matvey Cherevko + ******************************************************************************/ + +#include "_high.hpp" +using namespace e2d; + +namespace +{ + class safe_starter_initializer final : private noncopyable { + public: + safe_starter_initializer() { + modules::initialize(0, nullptr, + starter::parameters( + engine::parameters("asset_untests", "enduro2d") + .without_graphics(true))); + } + + ~safe_starter_initializer() noexcept { + modules::shutdown(); + } + }; + + 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)}})) + : stdex::make_rejected_promise(asset_loading_exception()); + } + }; +} + +TEST_CASE("asset"){ + safe_starter_initializer initializer; + library& l = the(); + { + REQUIRE_FALSE(l.load_asset("none")); + + auto fa = l.load_asset("42"); + REQUIRE(fa); + REQUIRE(fa->content() == 42); + + 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); + } +} diff --git a/untests/sources/untests_high/library.cpp b/untests/sources/untests_high/library.cpp index 55223f4d..f79e205e 100644 --- a/untests/sources/untests_high/library.cpp +++ b/untests/sources/untests_high/library.cpp @@ -22,37 +22,6 @@ namespace modules::shutdown(); } }; - - 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)}})) - : stdex::make_rejected_promise(asset_loading_exception()); - } - }; -} - -TEST_CASE("asset"){ - safe_starter_initializer initializer; - library& l = the(); - { - REQUIRE_FALSE(l.load_asset("none")); - - auto fa = l.load_asset("42"); - REQUIRE(fa); - REQUIRE(fa->content() == 42); - - 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); - } } TEST_CASE("library"){ @@ -130,25 +99,33 @@ TEST_CASE("library"){ auto material_res = l.load_asset("material.json"); REQUIRE(material_res); - auto atlas_res = l.load_asset("atlas.json"); - REQUIRE(atlas_res); - REQUIRE(atlas_res->content().texture() == texture_res); - REQUIRE(atlas_res->content().regions().size() == 1); - REQUIRE(atlas_res->content().find_region("sprite")); - REQUIRE(atlas_res->content().find_region("sprite")->name == make_hash("sprite")); - REQUIRE(atlas_res->content().find_region("sprite")->pivot == v2f(1.f,2.f)); - REQUIRE(atlas_res->content().find_region("sprite")->texrect == b2f(5.f,6.f,7.f,8.f)); - REQUIRE_FALSE(atlas_res->content().find_region("sprite2")); - REQUIRE(atlas_res->content().shape_regions().size() == 1); - REQUIRE(atlas_res->content().find_shape_region("shape_sprite")); - REQUIRE(atlas_res->content().find_shape_region("shape_sprite")->name == make_hash("shape_sprite")); - REQUIRE(atlas_res->content().find_shape_region("shape_sprite")->pivot == v2f(3.f,4.f)); - REQUIRE(atlas_res->content().find_shape_region("shape_sprite")->points == vector{ - {1.f, 2.f}, - {3.f, 4.f}, - {5.f, 6.f} - }); - REQUIRE_FALSE(atlas_res->content().find_shape_region("shape_sprite2")); + { + auto atlas_res = l.load_asset("atlas.json"); + REQUIRE(atlas_res); + + REQUIRE(atlas_res->content().texture() == texture_res); + REQUIRE(atlas_res->content().regions().size() == 1); + REQUIRE(atlas_res->content().shape_regions().size() == 1); + + const atlas::region* region = atlas_res->content().find_region("sprite"); + REQUIRE(region); + REQUIRE(region->name == make_hash("sprite")); + REQUIRE(region->pivot == v2f(1.f,2.f)); + REQUIRE(region->texrect == b2f(5.f,6.f,7.f,8.f)); + + const atlas::shape_region* shape_region = atlas_res->content().find_shape_region("shape_sprite"); + REQUIRE(shape_region); + REQUIRE(shape_region->name == make_hash("shape_sprite")); + REQUIRE(shape_region->pivot == v2f(3.f,4.f)); + REQUIRE(shape_region->points == vector{ + {1.f, 2.f}, + {3.f, 4.f}, + {5.f, 6.f} + }); + + REQUIRE_FALSE(atlas_res->content().find_region("sprite2")); + REQUIRE_FALSE(atlas_res->content().find_shape_region("shape_sprite2")); + } { auto sprite_res = l.load_asset("sprite_a.json");