Skip to content

Commit

Permalink
Improve TMJ roundtrip test
Browse files Browse the repository at this point in the history
  • Loading branch information
albin-johansson committed Aug 1, 2024
1 parent 1314914 commit 36d2fff
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 17 deletions.
12 changes: 6 additions & 6 deletions source/base/test_util/src/ir_presets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ auto make_complex_ir_object(const ObjectID id, const ObjectType type) -> ir::Obj
{
auto object = make_ir_object(id, type, Float2 {12, 34}, Float2 {56, 78});

object.meta = make_complex_ir_metadata(std::format("Complex object {}", id));
object.meta = make_complex_ir_metadata(std::format("complex_object {}", id));
object.tag = "this-is-a-tag";

return object;
Expand All @@ -47,7 +47,7 @@ auto make_complex_ir_object_layer(const LayerID id, ObjectID& next_object_id) ->
{
auto object_layer = make_ir_object_layer(id);

object_layer.meta = make_complex_ir_metadata(std::format("Complex layer {}", id));
object_layer.meta = make_complex_ir_metadata(std::format("complex_layer {}", id));
object_layer.opacity = 0.50f;
object_layer.visible = false;

Expand All @@ -65,7 +65,7 @@ auto make_complex_ir_tile_layer(const LayerID id, const MatrixExtent& extent) ->
{
auto tile_layer = make_ir_tile_layer(id, extent);

tile_layer.meta = make_complex_ir_metadata(std::format("Complex layer {}", id));
tile_layer.meta = make_complex_ir_metadata(std::format("complex_layer {}", id));
tile_layer.opacity = 1.0f;
tile_layer.visible = true;

Expand Down Expand Up @@ -136,7 +136,7 @@ auto make_complex_ir_tile(const TileIndex index, ObjectID& next_object_id) -> ir
{
auto tile = make_ir_tile(index);

tile.meta = make_complex_ir_metadata(std::format("Complex tile {}", index));
tile.meta = make_complex_ir_metadata(std::format("complex_tile {}", index));

tile.objects.reserve(3);
tile.objects.push_back(make_complex_ir_object(next_object_id++, ObjectType::kPoint));
Expand All @@ -156,7 +156,7 @@ auto make_complex_ir_tileset(TileID& next_tile_id, ObjectID& next_object_id) ->
{
auto tileset_ref = make_ir_tileset_ref(next_tile_id);

tileset_ref.tileset.meta = make_complex_ir_metadata("Complex tileset");
tileset_ref.tileset.meta = make_complex_ir_metadata("complex_tileset");
tileset_ref.tileset.tiles.reserve(3);
tileset_ref.tileset.tiles.push_back(make_complex_ir_tile(TileIndex {0}, next_object_id));
tileset_ref.tileset.tiles.push_back(make_complex_ir_tile(TileIndex {1}, next_object_id));
Expand All @@ -171,7 +171,7 @@ auto make_complex_ir_map(const ir::TileFormat& tile_format) -> ir::Map

auto map = make_ir_map(extent);

map.meta = make_complex_ir_metadata("Complex map");
map.meta = make_complex_ir_metadata("complex_map");
map.tile_size = Int2 {40, 30};
map.next_layer_id = 10;
map.next_object_id = 100;
Expand Down
36 changes: 36 additions & 0 deletions source/tiled_tmj_format/lib/src/tmj_format_map_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,40 @@
#include "tactile/tiled_tmj_format/tmj_format_tileset_parser.hpp"

namespace tactile {
namespace tmj_format_map_parser {

void deduce_tile_format_from_layer(const nlohmann::json& layer_json,
ir::TileFormat& tile_format)
{
if (const auto encoding_iter = layer_json.find("encoding");
encoding_iter != layer_json.end()) {
const auto& encoding = encoding_iter->get_ref<const String&>();

if (encoding == "base64") {
tile_format.encoding = TileEncoding::kBase64;
}
else {
tile_format.encoding = TileEncoding::kPlainText;
}
}

if (const auto compression_iter = layer_json.find("compression");
compression_iter != layer_json.end()) {
const auto& compression_name = compression_iter->get_ref<const String&>();

if (compression_name == "zlib") {
tile_format.compression = CompressionFormat::kZlib;
}
else if (compression_name == "zstd") {
tile_format.compression = CompressionFormat::kZstd;
}
else {
tile_format.compression = kNone;
}
}
}

} // namespace tmj_format_map_parser

auto parse_tiled_tmj_map(const IRuntime& runtime,
const nlohmann::json& map_json,
Expand Down Expand Up @@ -98,6 +132,8 @@ auto parse_tiled_tmj_map(const IRuntime& runtime,
map.layers.reserve(layers_iter->size());

for (const auto& [_, layer_json] : layers_iter->items()) {
tmj_format_map_parser::deduce_tile_format_from_layer(layer_json, map.tile_format);

if (auto layer = parse_tiled_tmj_layer(runtime, layer_json)) {
map.layers.push_back(std::move(*layer));
}
Expand Down
14 changes: 11 additions & 3 deletions source/tiled_tmj_format/lib/src/tmj_format_save_visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,17 @@ auto TmjFormatSaveVisitor::_find_layer_json(nlohmann::json& root_node,

auto TmjFormatSaveVisitor::_find_tileset_json(const TileID first_tile_id) -> nlohmann::json*
{
for (const auto& [_, tileset_node] : mMapNode.at("tilesets").items()) {
if (tileset_node.at("firstgid") == first_tile_id) {
return &tileset_node;
if (mOptions.use_external_tilesets) {
const auto external_tileset_iter = mExternalTilesetNodes.find(first_tile_id);
if (external_tileset_iter != mExternalTilesetNodes.end()) {
return &external_tileset_iter->second.json;
}
}
else {
for (const auto& [_, tileset_node] : mMapNode.at("tilesets").items()) {
if (tileset_node.at("firstgid") == first_tile_id) {
return &tileset_node;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ auto parse_tileset(const nlohmann::json& tileset_json) -> SaveFormatParseResult<
}

tileset.image_path = Path {relative_image_path};
tileset.is_embedded = !tileset_json.contains("source");

if (const auto tiles_iter = tileset_json.find("tiles"); tiles_iter != tileset_json.end()) {
tileset.tiles.reserve(tiles_iter->size());
Expand Down Expand Up @@ -218,6 +217,7 @@ auto parse_tiled_tmj_tileset(const nlohmann::json& tileset_json,

if (auto tileset = tmj_format_tileset_parser::parse_tileset(external_tileset_json)) {
tileset_ref.tileset = std::move(*tileset);
tileset_ref.tileset.is_embedded = false;
}
else {
return propagate_unexpected(tileset);
Expand All @@ -226,6 +226,7 @@ auto parse_tiled_tmj_tileset(const nlohmann::json& tileset_json,
else {
if (auto tileset = tmj_format_tileset_parser::parse_tileset(tileset_json)) {
tileset_ref.tileset = std::move(*tileset);
tileset_ref.tileset.is_embedded = true;
}
else {
return propagate_unexpected(tileset);
Expand Down
83 changes: 76 additions & 7 deletions source/tiled_tmj_format/test/src/tmj_format_roundtrip_test.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
// Copyright (C) 2024 Albin Johansson (GNU General Public License v3.0)

#include <filesystem> // current_path
#include <ostream> // ostream

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "tactile/base/container/maybe.hpp"
#include "tactile/base/container/string.hpp"
#include "tactile/base/test_util/document_view_mocks.hpp"
#include "tactile/base/test_util/ir.hpp"
#include "tactile/base/test_util/ir_eq.hpp"
Expand All @@ -22,7 +25,37 @@

namespace tactile::test {

class TmjFormatRoundtripTest : public testing::Test
struct TmjRoundtripConfig final
{
StringView map_filename;
TileEncoding encoding;
Optional<CompressionFormat> compression;
bool use_external_tilesets;
};

inline auto operator<<(std::ostream& stream, const TmjRoundtripConfig& config) -> std::ostream&
{
stream << config.map_filename;

stream << " + " << (config.encoding == TileEncoding::kBase64 ? "base64" : "plain text")
<< " encoding";

if (config.compression == CompressionFormat::kZlib) {
stream << " + zlib compression";
}
else if (config.compression == CompressionFormat::kZstd) {
stream << " + zstd compression";
}
else {
stream << " + no compression";
}

stream << " + " << (config.use_external_tilesets ? "external" : "embedded") << " tilesets";

return stream;
}

class TmjFormatRoundtripTest : public testing::TestWithParam<TmjRoundtripConfig>
{
public:
void SetUp() override
Expand Down Expand Up @@ -65,29 +98,65 @@ class TmjFormatRoundtripTest : public testing::Test
TmjFormatPlugin mTmjFormatPlugin {};
};

TEST_F(TmjFormatRoundtripTest, SaveAndLoadMapWithEmbeddedTilesets)
INSTANTIATE_TEST_SUITE_P(TMJ,
TmjFormatRoundtripTest,
testing::Values(
TmjRoundtripConfig {
.map_filename = "map_with_embedded_tilesets.tmj",
.encoding = TileEncoding::kPlainText,
.compression = kNone,
.use_external_tilesets = false,
},
TmjRoundtripConfig {
.map_filename = "map_with_external_tilesets.tmj",
.encoding = TileEncoding::kPlainText,
.compression = kNone,
.use_external_tilesets = true,
},
TmjRoundtripConfig {
.map_filename = "map_with_base64_tiles.tmj",
.encoding = TileEncoding::kBase64,
.compression = kNone,
.use_external_tilesets = false,
},
TmjRoundtripConfig {
.map_filename = "map_with_base64_zlib_tiles.tmj",
.encoding = TileEncoding::kBase64,
.compression = CompressionFormat::kZlib,
.use_external_tilesets = false,
},
TmjRoundtripConfig {
.map_filename = "map_with_base64_zstd_tiles.tmj",
.encoding = TileEncoding::kBase64,
.compression = CompressionFormat::kZstd,
.use_external_tilesets = false,
}));

TEST_P(TmjFormatRoundtripTest, SaveAndLoadMap)
{
const auto& config = GetParam();

const auto* save_format = mRuntime.get_save_format(SaveFormatId::kTiledTmj);
ASSERT_NE(save_format, nullptr);

auto ir_map = make_complex_ir_map(ir::TileFormat {
.encoding = TileEncoding::kPlainText,
.compression = kNone,
.encoding = config.encoding,
.compression = config.compression,
.compression_level = kNone,
});

for (auto& ir_tileset_ref : ir_map.tilesets) {
ir_tileset_ref.tileset.is_embedded = true;
ir_tileset_ref.tileset.is_embedded = !config.use_external_tilesets;
}

const testing::NiceMock<MapViewMock> map_view {ir_map};

const auto map_path = std::filesystem::current_path() / "roundtrip.tmj";
const auto map_path = std::filesystem::current_path() / config.map_filename;
EXPECT_CALL(map_view, get_path).WillRepeatedly(testing::Return(&map_path));

const SaveFormatWriteOptions write_options {
.base_dir = map_path.parent_path(),
.use_external_tilesets = false,
.use_external_tilesets = config.use_external_tilesets,
.use_indentation = true,
.fold_tile_layer_data = false,
};
Expand Down

0 comments on commit 36d2fff

Please sign in to comment.