mirror of
https://github.com/enduro2d/enduro2d.git
synced 2026-09-28 19:02:23 +07:00
basic content assets
This commit is contained in:
@@ -1 +1,2 @@
|
||||
*.zip filter=lfs diff=lfs merge=lfs -text
|
||||
*.bin filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
@@ -8,4 +8,6 @@
|
||||
|
||||
#include "_high.hpp"
|
||||
|
||||
#include "assets.hpp"
|
||||
#include "library.hpp"
|
||||
#include "library.inl"
|
||||
|
||||
@@ -6,9 +6,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../core/_core.hpp"
|
||||
#include "../core/_all.hpp"
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
class asset;
|
||||
class library;
|
||||
class text_asset;
|
||||
class binary_asset;
|
||||
|
||||
template < typename T >
|
||||
class asset_cache;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "Enduro2D"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2018 Matvey Cherevko
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "_high.hpp"
|
||||
#include "library.hpp"
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
template < typename T >
|
||||
class content_asset : public asset {
|
||||
public:
|
||||
content_asset(T content)
|
||||
: content_(std::move(content)) {}
|
||||
|
||||
const T& content() const noexcept {
|
||||
return content_;
|
||||
}
|
||||
private:
|
||||
T content_;
|
||||
};
|
||||
|
||||
class text_asset final : public content_asset<str> {
|
||||
public:
|
||||
using content_asset<str>::content_asset;
|
||||
static std::shared_ptr<text_asset> load(library& library, const url& url);
|
||||
};
|
||||
|
||||
class binary_asset final : public content_asset<buffer> {
|
||||
public:
|
||||
using content_asset<buffer>::content_asset;
|
||||
static std::shared_ptr<binary_asset> load(library& library, const url& url);
|
||||
};
|
||||
}
|
||||
@@ -4,12 +4,18 @@
|
||||
* Copyright (C) 2018 Matvey Cherevko
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef E2D_INCLUDE_GUARD_C3A242D805B8481AB9F778BA8F272D72
|
||||
#define E2D_INCLUDE_GUARD_C3A242D805B8481AB9F778BA8F272D72
|
||||
#pragma once
|
||||
|
||||
#include "_high.hpp"
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
//
|
||||
// bad_library_operation
|
||||
//
|
||||
|
||||
class bad_library_operation final : public exception {
|
||||
public:
|
||||
const char* what() const noexcept final {
|
||||
@@ -17,12 +23,54 @@ namespace e2d
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// asset
|
||||
//
|
||||
|
||||
class asset : private noncopyable {
|
||||
public:
|
||||
asset();
|
||||
virtual ~asset() noexcept;
|
||||
};
|
||||
using asset_ptr = std::shared_ptr<asset>;
|
||||
|
||||
//
|
||||
// library
|
||||
//
|
||||
|
||||
class library final : public module<library> {
|
||||
public:
|
||||
library();
|
||||
library(const url& root);
|
||||
~library() noexcept final;
|
||||
|
||||
template < typename T >
|
||||
std::shared_ptr<T> load_asset(str_view address);
|
||||
private:
|
||||
class internal_state;
|
||||
std::unique_ptr<internal_state> state_;
|
||||
url root_;
|
||||
};
|
||||
|
||||
//
|
||||
// asset_cache
|
||||
//
|
||||
|
||||
template < typename T >
|
||||
class asset_cache : public module<asset_cache<T>> {
|
||||
public:
|
||||
asset_cache(library& l);
|
||||
~asset_cache() noexcept final;
|
||||
|
||||
std::shared_ptr<T> find(str_hash address) const;
|
||||
void store(str_hash address, const std::shared_ptr<T>& asset);
|
||||
|
||||
void clear();
|
||||
void unload_unused_assets();
|
||||
std::size_t asset_count() const noexcept;
|
||||
private:
|
||||
library& library_;
|
||||
mutable std::mutex mutex_;
|
||||
hash_map<str_hash, std::shared_ptr<T>> assets_;
|
||||
};
|
||||
}
|
||||
|
||||
#include "library.inl"
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "Enduro2D"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2018 Matvey Cherevko
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef E2D_INCLUDE_GUARD_C9B4A08B2E2A4A659AB390BDC6EBEFE8
|
||||
#define E2D_INCLUDE_GUARD_C9B4A08B2E2A4A659AB390BDC6EBEFE8
|
||||
#pragma once
|
||||
|
||||
#include "_high.hpp"
|
||||
#include "library.hpp"
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
//
|
||||
// library
|
||||
//
|
||||
|
||||
template < typename T >
|
||||
std::shared_ptr<T> library::load_asset(str_view address) {
|
||||
const auto asset_url = root_ / address;
|
||||
|
||||
if ( !modules::is_initialized<asset_cache<T>>() ) {
|
||||
return T::load(*this, asset_url);
|
||||
}
|
||||
|
||||
auto& cache = the<asset_cache<T>>();
|
||||
|
||||
const auto cached_asset = cache.find(address);
|
||||
if ( cached_asset ) {
|
||||
return cached_asset;
|
||||
}
|
||||
|
||||
const auto new_asset = T::load(*this, asset_url);
|
||||
if ( new_asset ) {
|
||||
cache.store(address, new_asset);
|
||||
return new_asset;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//
|
||||
// asset_cache
|
||||
//
|
||||
|
||||
template < typename T >
|
||||
asset_cache<T>::asset_cache(library& l)
|
||||
: library_(l) {}
|
||||
|
||||
template < typename T >
|
||||
asset_cache<T>::~asset_cache() noexcept = default;
|
||||
|
||||
template < typename T >
|
||||
std::shared_ptr<T> asset_cache<T>::find(str_hash address) const {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
const auto iter = assets_.find(address);
|
||||
return iter != assets_.end()
|
||||
? iter->second
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
void asset_cache<T>::store(str_hash address, const std::shared_ptr<T>& asset) {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
assets_[address] = asset;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
void asset_cache<T>::clear() {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
assets_.clear();
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
void asset_cache<T>::unload_unused_assets() {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
for ( auto iter = assets_.begin(); iter != assets_.end(); ) {
|
||||
if ( iter->second.unique() ) {
|
||||
iter = assets_.erase(iter);
|
||||
} else {
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
std::size_t asset_cache<T>::asset_count() const noexcept {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
return assets_.size();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,67 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "Enduro2D"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2018 Matvey Cherevko
|
||||
******************************************************************************/
|
||||
|
||||
#include <enduro2d/high/assets.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
using namespace e2d;
|
||||
}
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
//
|
||||
// text_asset
|
||||
//
|
||||
|
||||
std::shared_ptr<text_asset> text_asset::load(library& library, const url& url) {
|
||||
E2D_UNUSED(library);
|
||||
|
||||
input_stream_uptr stream = the<vfs>().open(url);
|
||||
if ( !stream ) {
|
||||
the<debug>().error("ASSETS: Failed to open text asset file:\n"
|
||||
"--> Url: %0",
|
||||
url);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
str content;
|
||||
if ( !streams::try_read_tail(content, stream) ) {
|
||||
the<debug>().error("ASSETS: Failed to read text asset file:\n"
|
||||
"--> Url: %0",
|
||||
url);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_shared<text_asset>(std::move(content));
|
||||
}
|
||||
|
||||
//
|
||||
// binary_asset
|
||||
//
|
||||
|
||||
std::shared_ptr<binary_asset> binary_asset::load(library& library, const url& url) {
|
||||
E2D_UNUSED(library);
|
||||
|
||||
input_stream_uptr stream = the<vfs>().open(url);
|
||||
if ( !stream ) {
|
||||
the<debug>().error("ASSETS: Failed to open binary asset file:\n"
|
||||
"--> Url: %0",
|
||||
url);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
buffer content;
|
||||
if ( !streams::try_read_tail(content, stream) ) {
|
||||
the<debug>().error("ASSETS: Failed to read binary asset file:\n"
|
||||
"--> Url: %0",
|
||||
url);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_shared<binary_asset>(std::move(content));
|
||||
}
|
||||
}
|
||||
@@ -6,20 +6,26 @@
|
||||
|
||||
#include <enduro2d/high/library.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
using namespace e2d;
|
||||
}
|
||||
|
||||
namespace e2d
|
||||
{
|
||||
//
|
||||
// library::internal_state
|
||||
// asset
|
||||
//
|
||||
|
||||
class library::internal_state final : private e2d::noncopyable {
|
||||
};
|
||||
asset::asset() = default;
|
||||
asset::~asset() noexcept = default;
|
||||
|
||||
//
|
||||
// library
|
||||
//
|
||||
|
||||
library::library()
|
||||
: state_(new internal_state()){}
|
||||
library::library(const url& root)
|
||||
: root_(root) {}
|
||||
|
||||
library::~library() noexcept = default;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:486ea46224d1bb4fb680f34f7c9ad96a8f24ec88be73ea8e5a6c65260e9cb8a7
|
||||
size 5
|
||||
@@ -0,0 +1 @@
|
||||
hello
|
||||
@@ -8,4 +8,69 @@
|
||||
using namespace e2d;
|
||||
|
||||
TEST_CASE("library"){
|
||||
modules::initialize<vfs>();
|
||||
modules::initialize<debug>();
|
||||
modules::initialize<window>(v2u{640, 480}, "Enduro2D", false);
|
||||
modules::initialize<render>(the<debug>(), the<window>());
|
||||
modules::initialize<library>(url{"resources://bin/library"});
|
||||
modules::initialize<asset_cache<text_asset>>(the<library>());
|
||||
modules::initialize<asset_cache<binary_asset>>(the<library>());
|
||||
{
|
||||
the<debug>().register_sink<debug_console_sink>();
|
||||
the<vfs>().register_scheme<filesystem_file_source>("file");
|
||||
}
|
||||
{
|
||||
str resources;
|
||||
REQUIRE(filesystem::extract_predef_path(
|
||||
resources,
|
||||
filesystem::predef_path::resources));
|
||||
REQUIRE(the<vfs>().register_scheme_alias(
|
||||
"resources",
|
||||
{"file", resources}));
|
||||
}
|
||||
{
|
||||
library& l = the<library>();
|
||||
|
||||
auto text_res = l.load_asset<text_asset>("text_asset.txt");
|
||||
REQUIRE(text_res);
|
||||
REQUIRE(text_res->content() == "hello");
|
||||
|
||||
auto binary_res = l.load_asset<binary_asset>("binary_asset.bin");
|
||||
REQUIRE(binary_res);
|
||||
REQUIRE(binary_res->content() == buffer("world", 5));
|
||||
|
||||
auto empty_res = l.load_asset<binary_asset>("empty_asset");
|
||||
REQUIRE_FALSE(empty_res);
|
||||
|
||||
auto binary_res_from_cache = l.load_asset<binary_asset>("binary_asset.bin");
|
||||
REQUIRE(binary_res == binary_res_from_cache);
|
||||
|
||||
REQUIRE(the<asset_cache<text_asset>>().asset_count() == 1);
|
||||
REQUIRE(the<asset_cache<binary_asset>>().asset_count() == 1);
|
||||
|
||||
the<asset_cache<text_asset>>().unload_unused_assets();
|
||||
the<asset_cache<binary_asset>>().unload_unused_assets();
|
||||
|
||||
REQUIRE(the<asset_cache<text_asset>>().asset_count() == 1);
|
||||
REQUIRE(the<asset_cache<binary_asset>>().asset_count() == 1);
|
||||
|
||||
text_res.reset();
|
||||
the<asset_cache<text_asset>>().unload_unused_assets();
|
||||
REQUIRE(the<asset_cache<text_asset>>().asset_count() == 0);
|
||||
REQUIRE(the<asset_cache<binary_asset>>().asset_count() == 1);
|
||||
|
||||
binary_res.reset();
|
||||
the<asset_cache<binary_asset>>().unload_unused_assets();
|
||||
REQUIRE(the<asset_cache<binary_asset>>().asset_count() == 1);
|
||||
binary_res_from_cache.reset();
|
||||
the<asset_cache<binary_asset>>().unload_unused_assets();
|
||||
REQUIRE(the<asset_cache<binary_asset>>().asset_count() == 0);
|
||||
}
|
||||
modules::shutdown<asset_cache<binary_asset>>();
|
||||
modules::shutdown<asset_cache<text_asset>>();
|
||||
modules::shutdown<library>();
|
||||
modules::shutdown<render>();
|
||||
modules::shutdown<window>();
|
||||
modules::shutdown<debug>();
|
||||
modules::shutdown<vfs>();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user