model and sprite loaders

This commit is contained in:
2019-02-27 05:30:39 +07:00
parent a6a0bb1943
commit 10c13a7607
6 changed files with 233 additions and 6 deletions

View File

@@ -17,6 +17,75 @@ namespace
return "model asset loading exception";
}
};
const char* model_asset_schema_source = R"json(
{
"type" : "object",
"required" : [ "mesh" ],
"additionalProperties" : false,
"properties" : {
"mesh" : { "$ref": "#/common_definitions/address" },
"materials" : {
"type" : "array",
"items" : { "$ref" : "#/common_definitions/address" }
}
}
})json";
const rapidjson::SchemaDocument& model_asset_schema() {
static std::mutex mutex;
static std::unique_ptr<rapidjson::SchemaDocument> schema;
std::lock_guard<std::mutex> guard(mutex);
if ( !schema ) {
rapidjson::Document doc;
if ( doc.Parse(model_asset_schema_source).HasParseError() ) {
the<debug>().error("ASSETS: Failed to parse model asset schema");
throw model_asset_loading_exception();
}
json_utils::add_common_schema_definitions(doc);
schema = std::make_unique<rapidjson::SchemaDocument>(doc);
}
return *schema;
}
stdex::promise<model> parse_model(
library& library,
str_view parent_address,
const rapidjson::Value& root)
{
E2D_ASSERT(root.HasMember("mesh") && root["mesh"].IsString());
auto mesh_p = library.load_asset_async<mesh_asset>(
path::combine(parent_address, root["mesh"].GetString()));
vector<stdex::promise<material_asset::load_result>> materials_p;
if ( root.HasMember("materials") ) {
E2D_ASSERT(root["materials"].IsArray());
const auto& materials_json = root["materials"];
materials_p.reserve(materials_json.Size());
for ( rapidjson::SizeType i = 0; i < materials_json.Size(); ++i ) {
E2D_ASSERT(materials_json[i].IsString());
materials_p.emplace_back(
library.load_asset_async<material_asset>(
path::combine(parent_address, materials_json[i].GetString())));
}
}
return stdex::make_tuple_promise(std::make_tuple(
std::move(mesh_p),
stdex::make_all_promise(materials_p)))
.then([](const std::tuple<
mesh_asset::load_result,
vector<material_asset::load_result>
>& results){
model content;
content.set_mesh(std::get<0>(results));
content.set_materials(std::get<1>(results));
return content;
});
}
}
namespace e2d
@@ -25,9 +94,27 @@ namespace e2d
library& library, str_view address)
{
return library.load_asset_async<json_asset>(address)
.then([](const json_asset::load_result& model_data){
model mdl;
return model_asset::create(std::move(mdl));
.then([
&library,
parent_address = path::parent_path(address)
](const json_asset::load_result& model_data){
if ( !modules::is_initialized<deferrer>() ) {
throw model_asset_loading_exception();
}
return the<deferrer>().do_in_worker_thread([model_data](){
const rapidjson::Document& doc = model_data->content();
rapidjson::SchemaValidator validator(model_asset_schema());
if ( !doc.Accept(validator) ) {
throw model_asset_loading_exception();
}
})
.then([&library, parent_address, model_data](){
return parse_model(
library, parent_address, model_data->content());
})
.then([](const model& model){
return model_asset::create(model);
});
});
}
}

View File

@@ -17,6 +17,95 @@ namespace
return "sprite asset loading exception";
}
};
const char* sprite_asset_schema_source = R"json(
{
"type" : "object",
"required" : [ "size", "pivot", "texrect" ],
"additionalProperties" : false,
"properties" : {
"size" : { "$ref": "#/common_definitions/v2" },
"pivot" : { "$ref": "#/common_definitions/v2" },
"texrect" : { "$ref": "#/common_definitions/b2" },
"texture" : { "$ref": "#/common_definitions/address" },
"material" : { "$ref": "#/common_definitions/address" }
}
})json";
const rapidjson::SchemaDocument& sprite_asset_schema() {
static std::mutex mutex;
static std::unique_ptr<rapidjson::SchemaDocument> schema;
std::lock_guard<std::mutex> guard(mutex);
if ( !schema ) {
rapidjson::Document doc;
if ( doc.Parse(sprite_asset_schema_source).HasParseError() ) {
the<debug>().error("ASSETS: Failed to parse sprite asset schema");
throw sprite_asset_loading_exception();
}
json_utils::add_common_schema_definitions(doc);
schema = std::make_unique<rapidjson::SchemaDocument>(doc);
}
return *schema;
}
stdex::promise<sprite> parse_sprite(
library& library,
str_view parent_address,
const rapidjson::Value& root)
{
v2f size;
E2D_ASSERT(root.HasMember("size"));
if ( !json_utils::try_parse_value(root["size"], size) ) {
return stdex::make_rejected_promise<sprite>(
sprite_asset_loading_exception());
}
v2f pivot;
E2D_ASSERT(root.HasMember("pivot"));
if ( !json_utils::try_parse_value(root["pivot"], pivot) ) {
return stdex::make_rejected_promise<sprite>(
sprite_asset_loading_exception());
}
b2f texrect;
E2D_ASSERT(root.HasMember("texrect"));
if ( !json_utils::try_parse_value(root["texrect"], texrect) ) {
return stdex::make_rejected_promise<sprite>(
sprite_asset_loading_exception());
}
E2D_ASSERT(!root.HasMember("texture") || root["texture"].IsString());
auto texture_p = root.HasMember("texture")
? library.load_asset_async<texture_asset>(path::combine(
parent_address,
root["texture"].GetString()))
: stdex::make_resolved_promise(texture_asset::ptr());
E2D_ASSERT(!root.HasMember("material") || root["material"].IsString());
auto material_p = root.HasMember("material")
? library.load_asset_async<material_asset>(path::combine(
parent_address,
root["material"].GetString()))
: stdex::make_resolved_promise(material_asset::ptr());
return stdex::make_tuple_promise(std::make_tuple(
std::move(texture_p),
std::move(material_p)
)).then([size, pivot, texrect](const std::tuple<
texture_asset::load_result,
material_asset::load_result
>& results){
sprite content;
content.set_size(size);
content.set_pivot(pivot);
content.set_texrect(texrect);
content.set_texture(std::get<0>(results));
content.set_material(std::get<1>(results));
return content;
});
}
}
namespace e2d
@@ -25,9 +114,27 @@ namespace e2d
library& library, str_view address)
{
return library.load_asset_async<json_asset>(address)
.then([](const json_asset::load_result& sprite_data){
sprite spr;
return sprite_asset::create(std::move(spr));
.then([
&library,
parent_address = path::parent_path(address)
](const json_asset::load_result& sprite_data){
if ( !modules::is_initialized<deferrer>() ) {
throw sprite_asset_loading_exception();
}
return the<deferrer>().do_in_worker_thread([sprite_data](){
const rapidjson::Document& doc = sprite_data->content();
rapidjson::SchemaValidator validator(sprite_asset_schema());
if ( !doc.Accept(validator) ) {
throw sprite_asset_loading_exception();
}
})
.then([&library, parent_address, sprite_data](){
return parse_sprite(
library, parent_address, sprite_data->content());
})
.then([](const sprite& sprite){
return sprite_asset::create(sprite);
});
});
}
}

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1ab164b79bb190d2ffb325801de93a71b5d7059ad78da21b324532c680029951
size 20856

View File

@@ -0,0 +1,6 @@
{
"mesh" : "mesh.e2d_mesh",
"materials" : [
"material.json"
]
}

View File

@@ -0,0 +1,7 @@
{
"size" : { "x" : 10, "y" : 20 },
"pivot" : { "x" : 0.5, "y" : 0.7 },
"texrect" : { "w" : 0.5, "h" : 1 },
"texture" : "image.png",
"material" : "material.json"
}

View File

@@ -94,6 +94,23 @@ TEST_CASE("library"){
auto texture_res = l.load_asset<texture_asset>("image.png");
REQUIRE(texture_res);
REQUIRE(texture_res->content());
auto sprite_res = l.load_asset<sprite_asset>("sprite.json");
REQUIRE(sprite_res);
REQUIRE(sprite_res->content().size() == v2f(10.f, 20.f));
REQUIRE(sprite_res->content().pivot() == v2f(0.5f, 0.7f));
REQUIRE(sprite_res->content().texrect() == b2f(0.5f, 1.f));
REQUIRE(sprite_res->content().texture());
REQUIRE(sprite_res->content().material());
auto model_res = l.load_asset<model_asset>("model.json");
REQUIRE(model_res);
REQUIRE(model_res->content().mesh());
REQUIRE(model_res->content().material_count() == 1);
REQUIRE(model_res->content().material(0));
REQUIRE_FALSE(model_res->content().mesh()->content().vertices().empty());
REQUIRE(model_res->content().mesh()->content().indices_submesh_count() == 1);
REQUIRE_FALSE(model_res->content().mesh()->content().indices(0).empty());
}
}
{