Skip to content

Commit

Permalink
Replace tile identifier types
Browse files Browse the repository at this point in the history
  • Loading branch information
albin-johansson committed Nov 18, 2023
1 parent 1011e1d commit 1d688c5
Show file tree
Hide file tree
Showing 20 changed files with 111 additions and 82 deletions.
5 changes: 3 additions & 2 deletions modules/core/inc/tactile/core/io/ir.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "tactile/core/map/layer/layer_type.hpp"
#include "tactile/core/map/layer/object_type.hpp"
#include "tactile/core/map/tile_encoding.hpp"
#include "tactile/core/misc/id_types.hpp"
#include "tactile/core/misc/tile_matrix.hpp"
#include "tactile/core/prelude.hpp"

Expand Down Expand Up @@ -139,8 +140,8 @@ struct Tileset final {
* \brief Intermediate representation of a tileset reference.
*/
struct TilesetRef final {
Tileset tileset; ///< The tileset definition.
int32 first_tile_id; ///< The first tile identifier associated with the tileset.
Tileset tileset; ///< The tileset definition.
TileID first_tile_id; ///< The first tile identifier associated with the tileset.

[[nodiscard]] auto operator==(const TilesetRef&) const -> bool = default;
};
Expand Down
1 change: 1 addition & 0 deletions modules/core/inc/tactile/core/map/layer/tile_layer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "tactile/core/container/vector.hpp"
#include "tactile/core/map/layer/layer.hpp"
#include "tactile/core/map/layer/layer_behavior_delegate.hpp"
#include "tactile/core/misc/id_types.hpp"
#include "tactile/core/misc/tile_matrix.hpp"
#include "tactile/core/misc/tile_pos.hpp"
#include "tactile/core/prelude.hpp"
Expand Down
19 changes: 17 additions & 2 deletions modules/core/inc/tactile/core/misc/id_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,33 @@

#pragma once

#include "tactile/core/functional/hash.hpp"
#include "tactile/core/misc/strong_type.hpp"
#include "tactile/core/prelude.hpp"

namespace tactile {

/** \brief Strong type of layer identifiers. */
/** \brief Strong type for local tile identifiers. */
TACTILE_STRONG_TYPE(TileIndex, int32);

/** \brief Strong type for global tile identifiers. */
TACTILE_STRONG_TYPE(TileID, int32);

/** \brief Strong type for layer identifiers. */
TACTILE_STRONG_TYPE(LayerID, int32);

/** \brief Strong type of object identifiers. */
/** \brief Strong type for object identifiers. */
TACTILE_STRONG_TYPE(ObjectID, int32);

/** \brief Strong type for object references. */
TACTILE_STRONG_TYPE(ObjectRef, int32);

inline constexpr TileID kEmptyTile {0};

} // namespace tactile

TACTILE_IMPLEMENT_HASH(tactile::TileIndex, value.value);
TACTILE_IMPLEMENT_HASH(tactile::TileID, value.value);
TACTILE_IMPLEMENT_HASH(tactile::LayerID, value.value);
TACTILE_IMPLEMENT_HASH(tactile::ObjectID, value.value);
TACTILE_IMPLEMENT_HASH(tactile::ObjectRef, value.value);
18 changes: 11 additions & 7 deletions modules/core/inc/tactile/core/misc/strong_type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@
/**
* \brief Simple macro useful for defining simple (but effective) strong types.
*/
#define TACTILE_STRONG_TYPE(Name, UnderlyingType) \
struct Name final { \
UnderlyingType value; \
\
constexpr auto operator==(const Name&) const noexcept -> bool = default; \
constexpr auto operator<=>(const Name&) const noexcept \
-> std::strong_ordering = default; \
#define TACTILE_STRONG_TYPE(Name, ValueType) \
struct Name final { \
using value_type = ValueType; \
\
ValueType value; \
\
[[nodiscard]] constexpr auto operator==(const Name&) const noexcept \
-> bool = default; \
\
[[nodiscard]] constexpr auto operator<=>(const Name&) const noexcept \
-> std::strong_ordering = default; \
}
1 change: 1 addition & 0 deletions modules/core/inc/tactile/core/misc/tile_matrix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "tactile/core/api.hpp"
#include "tactile/core/container/vector.hpp"
#include "tactile/core/misc/id_types.hpp"
#include "tactile/core/prelude.hpp"

namespace tactile {
Expand Down
5 changes: 0 additions & 5 deletions modules/core/inc/tactile/core/prelude.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,6 @@ using float64 = double;
static_assert(sizeof(float32) == 4);
static_assert(sizeof(float64) == 8);

using TileIndex = int32; ///< For local tile identifiers.
using TileID = int32; ///< For global tile identifiers.

inline constexpr TileID kEmptyTile = 0;

namespace int_literals {

/** \brief Literal operator for ssize, equivalent to 'z' from C++23. */
Expand Down
1 change: 1 addition & 0 deletions modules/core/inc/tactile/core/tileset/tile_animation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "tactile/core/api.hpp"
#include "tactile/core/container/vector.hpp"
#include "tactile/core/misc/id_types.hpp"
#include "tactile/core/prelude.hpp"
#include "tactile/core/type/chrono.hpp"

Expand Down
8 changes: 4 additions & 4 deletions modules/core/src/tactile/core/io/tile_matrix_encoding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace tactile {
using namespace int_literals;

// Update the documentation if the representation of TileID changes.
static_assert(std::same_as<TileID, int32>);
static_assert(std::same_as<TileID::value_type, int32>);

auto tile_matrix_to_byte_stream(const TileMatrix& matrix) -> ByteStream
{
Expand All @@ -32,7 +32,7 @@ auto tile_matrix_to_byte_stream(const TileMatrix& matrix) -> ByteStream
for (usize row = 0; row < row_count; ++row) {
for (usize col = 0; col < col_count; ++col) {
// Tile identifiers are always stored as little endian values.
const auto tile_id = to_little_endian(matrix[row][col]);
const auto tile_id = to_little_endian(matrix[row][col].value);
each_byte(tile_id, [&](const uint8 byte) { byte_stream.push_back(byte); });
}
}
Expand All @@ -48,7 +48,7 @@ auto tile_matrix_from_byte_stream(const ByteStream& byte_stream,
const auto tile_count = byte_stream.size() / sizeof(TileID);

for (usize tile_index = 0; tile_index < tile_count; ++tile_index) {
TileID tile_id {};
TileID::value_type tile_id {};

const auto byte_index = tile_index * sizeof tile_id;
std::memcpy(&tile_id, &byte_stream[byte_index], sizeof tile_id);
Expand All @@ -64,7 +64,7 @@ auto tile_matrix_from_byte_stream(const ByteStream& byte_stream,
}

const auto [row, col] = to_matrix_index(tile_index, matrix_extent.col_count);
tile_matrix[row][col] = tile_id;
tile_matrix[row][col] = TileID {tile_id};
}

return tile_matrix;
Expand Down
48 changes: 25 additions & 23 deletions modules/core/test/io/tile_matrix_encoding_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ TEST(TileMatrixEncoding, TileMatrixToByteStream)
// [ 10, 20, 30 ]
// [ 40, 50, 60 ]
auto tile_matrix = make_tile_matrix(extent);
tile_matrix[0][0] = 0xFACE;
tile_matrix[0][1] = 0xDEAD;
tile_matrix[0][2] = 0x1234BEEF;
tile_matrix[1][0] = 0x0012FEED;
tile_matrix[1][1] = 0xFADE;
tile_matrix[1][2] = 0xABCD;
tile_matrix[0][0] = TileID {0xFACE};
tile_matrix[0][1] = TileID {0xDEAD};
tile_matrix[0][2] = TileID {0x1234BEEF};
tile_matrix[1][0] = TileID {0x0012FEED};
tile_matrix[1][1] = TileID {0xFADE};
tile_matrix[1][2] = TileID {0xABCD};

const auto byte_stream = tile_matrix_to_byte_stream(tile_matrix);
ASSERT_EQ(byte_stream.size(), extent.row_count * extent.col_count * sizeof(TileID));
Expand Down Expand Up @@ -68,9 +68,9 @@ TEST(TileMatrixEncoding, TileMatrixFromByteStream)
{
const MatrixExtent extent {3, 4};
const TileMatrix initial_tile_matrix = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{TileID {1}, TileID {2}, TileID {3}, TileID {4}},
{TileID {5}, TileID {6}, TileID {7}, TileID {8}},
{TileID {9}, TileID {10}, TileID {11}, TileID {12}},
};

const auto byte_stream = tile_matrix_to_byte_stream(initial_tile_matrix);
Expand All @@ -97,9 +97,9 @@ TEST_P(TileMatrixEncodingCompressionModes, Base64EncodeAndDecodeTileMatrix)

const MatrixExtent extent {3, 4};
const TileMatrix initial_tile_matrix = {
{0x100, 0x200, 0x300, 0x400},
{0x500, 0x600, 0x700, 0x800},
{0x900, 0xA00, 0xB00, 0xC00},
{TileID {0x100}, TileID {0x200}, TileID {0x300}, TileID {0x400}},
{TileID {0x500}, TileID {0x600}, TileID {0x700}, TileID {0x800}},
{TileID {0x900}, TileID {0xA00}, TileID {0xB00}, TileID {0xC00}},
};

const auto encoded_tiles =
Expand All @@ -123,22 +123,24 @@ TEST_P(TileMatrixEncodingCompressionModes,

const MatrixExtent extent {3, 4};

const auto tile00 = static_cast<TileID>(0x100u | kTiledFlippedVerticallyBit);
const auto tile03 = static_cast<TileID>(0x400u | kTiledFlippedDiagonallyBit);
const auto tile12 = static_cast<TileID>(0x700u | kTiledTileFlippingMask);
const auto tile21 = static_cast<TileID>(0xA00u | kTiledRotatedHexagonal120Bit);
const auto tile23 = static_cast<TileID>(0xC00u | kTiledFlippedHorizontallyBit);
// clang-format off
const auto tile00 = static_cast<TileID::value_type>(0x100u | kTiledFlippedVerticallyBit);
const auto tile03 = static_cast<TileID::value_type>(0x400u | kTiledFlippedDiagonallyBit);
const auto tile12 = static_cast<TileID::value_type>(0x700u | kTiledTileFlippingMask);
const auto tile21 = static_cast<TileID::value_type>(0xA00u | kTiledRotatedHexagonal120Bit);
const auto tile23 = static_cast<TileID::value_type>(0xC00u | kTiledFlippedHorizontallyBit);
// clang-format on

const TileMatrix initial_tile_matrix = {
{tile00, 0x200, 0x300, tile03},
{0x500, 0x600, tile12, 0x800},
{0x900, tile21, 0xB00, tile23},
{TileID {tile00}, TileID {0x200}, TileID {0x300}, TileID {tile03}},
{TileID {0x500}, TileID {0x600}, TileID {tile12}, TileID {0x800}},
{TileID {0x900}, TileID {tile21}, TileID {0xB00}, TileID {tile23}},
};

const TileMatrix expected_tile_matrix = {
{0x100, 0x200, 0x300, 0x400},
{0x500, 0x600, 0x700, 0x800},
{0x900, 0xA00, 0xB00, 0xC00},
{TileID {0x100}, TileID {0x200}, TileID {0x300}, TileID {0x400}},
{TileID {0x500}, TileID {0x600}, TileID {0x700}, TileID {0x800}},
{TileID {0x900}, TileID {0xA00}, TileID {0xB00}, TileID {0xC00}},
};

const auto encoded_tiles =
Expand Down
13 changes: 13 additions & 0 deletions modules/core/test/misc/id_types_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (C) 2023 Albin Johansson (GNU General Public License v3.0)

#include "tactile/core/misc/id_types.hpp"

#include <gtest/gtest.h>

using namespace tactile;

/// \tests tactile::kEmptyTile
TEST(IdTypes, TileID)
{
EXPECT_EQ(kEmptyTile.value, 0);
}
8 changes: 1 addition & 7 deletions modules/core/test/prelude_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,6 @@ TEST(Prelude, CompilerDetection)
EXPECT_EQ(compiler_sum, 1);
}

/// \tests tactile::kEmptyTile
TEST(Prelude, EmptyTileConstant)
{
EXPECT_EQ(kEmptyTile, 0);
}

TEST(Prelude, InterfaceClassMacro)
{
class IDummy final {
Expand All @@ -117,4 +111,4 @@ TEST(Prelude, InterfaceClassMacro)
EXPECT_TRUE(std::is_nothrow_move_constructible_v<IDummy>);
EXPECT_TRUE(std::is_nothrow_move_assignable_v<IDummy>);
EXPECT_TRUE(std::has_virtual_destructor_v<IDummy>);
}
}
18 changes: 10 additions & 8 deletions modules/main/test/io/save/base64_map_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,19 +69,21 @@ TEST_P(Base64MapTest, SaveAndLoadBase64TileLayer)
map.tile_format.encoding = TileEncoding::kBase64;
map.tile_format.compression = test_data.compression_mode;

// clang-format off
auto& tile_layer = map.layers.emplace_back();
tile_layer.width = map.col_count;
tile_layer.height = map.row_count;
tile_layer.tiles = TileMatrix {
TileRow {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09},
TileRow {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19},
TileRow {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29},
TileRow {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39},
TileRow {0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49},
TileRow {0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59},
TileRow {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69},
TileRow {0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79},
TileRow {TileID{0x00}, TileID{0x01}, TileID{0x02}, TileID{0x03}, TileID{0x04}, TileID{0x05}, TileID{0x06}, TileID{0x07}, TileID{0x08}, TileID{0x09}},
TileRow {TileID{0x10}, TileID{0x11}, TileID{0x12}, TileID{0x13}, TileID{0x14}, TileID{0x15}, TileID{0x16}, TileID{0x17}, TileID{0x18}, TileID{0x19}},
TileRow {TileID{0x20}, TileID{0x21}, TileID{0x22}, TileID{0x23}, TileID{0x24}, TileID{0x25}, TileID{0x26}, TileID{0x27}, TileID{0x28}, TileID{0x29}},
TileRow {TileID{0x30}, TileID{0x31}, TileID{0x32}, TileID{0x33}, TileID{0x34}, TileID{0x35}, TileID{0x36}, TileID{0x37}, TileID{0x38}, TileID{0x39}},
TileRow {TileID{0x40}, TileID{0x41}, TileID{0x42}, TileID{0x43}, TileID{0x44}, TileID{0x45}, TileID{0x46}, TileID{0x47}, TileID{0x48}, TileID{0x49}},
TileRow {TileID{0x50}, TileID{0x51}, TileID{0x52}, TileID{0x53}, TileID{0x54}, TileID{0x55}, TileID{0x56}, TileID{0x57}, TileID{0x58}, TileID{0x59}},
TileRow {TileID{0x60}, TileID{0x61}, TileID{0x62}, TileID{0x63}, TileID{0x64}, TileID{0x65}, TileID{0x66}, TileID{0x67}, TileID{0x68}, TileID{0x69}},
TileRow {TileID{0x70}, TileID{0x71}, TileID{0x72}, TileID{0x73}, TileID{0x74}, TileID{0x75}, TileID{0x76}, TileID{0x77}, TileID{0x78}, TileID{0x79}},
};
// clang-format on

const SaveFormatWriteOptions write_options = {
.base_dir = map_directory,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ auto _emit_tile_layer(JSON& layer_json,

for (usize row = 0; row < layer.height; ++row) {
for (usize col = 0; col < layer.width; ++col) {
tile_data_json += JSON(layer.tiles[row][col]);
tile_data_json += JSON(layer.tiles[row][col].value);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ auto _emit_tile_animation_array(const ir::Tile& tile) -> JSON
for (const auto& animation_frame : tile.animation) {
auto animation_frame_json = JSON::object();

animation_frame_json["tileid"] = animation_frame.tile_index;
animation_frame_json["tileid"] = animation_frame.tile_index.value;
animation_frame_json["duration"] = animation_frame.duration_ms;

animation_json_array += std::move(animation_frame_json);
Expand All @@ -49,7 +49,7 @@ auto _emit_tile_animation_array(const ir::Tile& tile) -> JSON
auto emit_tile_definition(const ir::Tile& tile) -> JSON
{
auto tile_json = JSON::object();
tile_json["id"] = tile.index;
tile_json["id"] = tile.index.value;

if (!tile.meta.properties.empty()) {
tile_json["properties"] = emit_property_array(tile.meta);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ auto _determine_external_tileset_filename(const ir::TilesetRef& tileset_ref) ->
{
return !tileset_ref.tileset.meta.name.empty()
? tileset_ref.tileset.meta.name
: fmt::format("tileset_{}.tmj", tileset_ref.first_tile_id);
: fmt::format("tileset_{}.tmj", tileset_ref.first_tile_id.value);
}

} // namespace
Expand All @@ -66,7 +66,7 @@ auto emit_embedded_tileset(const ir::Tileset& tileset,
const SaveFormatWriteOptions& options) -> Result<JSON>
{
auto embedded_tileset_json = JSON::object();
embedded_tileset_json["firstgid"] = first_tile_id;
embedded_tileset_json["firstgid"] = first_tile_id.value;

return _add_common_tileset_attributes(tileset, options, embedded_tileset_json)
.and_then([&]() -> Result<JSON> { return std::move(embedded_tileset_json); });
Expand All @@ -77,7 +77,7 @@ auto emit_external_tileset(const ir::TilesetRef& tileset_ref,
{
auto external_tileset_json = JSON::object();

external_tileset_json["firstgid"] = tileset_ref.first_tile_id;
external_tileset_json["firstgid"] = tileset_ref.first_tile_id.value;
external_tileset_json["source"] = _determine_external_tileset_filename(tileset_ref);

return external_tileset_json;
Expand All @@ -95,7 +95,7 @@ auto emit_tileset_ref(const ir::TilesetRef& tileset_ref,
return _add_common_tileset_attributes(tileset_ref.tileset,
options,
external_tileset_json)
.and_then([&] {
.and_then([&] {
const StreamToFileOptions stream_options {
.indentation = options.use_indentation ? 2 : 0,
.binary_mode = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ auto _parse_tile_layer_csv_data(const JSON& tile_data_json, const MatrixExtent&
for (const auto& [_, value_json] : tile_data_json.items()) {
if (value_json.is_number_integer()) {
const auto [row, col] = to_matrix_index(tile_index, extent.col_count);
tile_matrix[row][col] = value_json.get<TileID>();
tile_matrix[row][col] = TileID {value_json.get<TileID::value_type>()};

++tile_index;
}
Expand Down
Loading

0 comments on commit 1d688c5

Please sign in to comment.