Skip to content

Commit

Permalink
Add attached tileset class
Browse files Browse the repository at this point in the history
  • Loading branch information
albin-johansson committed Nov 24, 2023
1 parent e8799e2 commit ed43611
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 0 deletions.
89 changes: 89 additions & 0 deletions modules/core/inc/tactile/core/tileset/attached_tileset.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright (C) 2023 Albin Johansson (GNU General Public License v3.0)

#pragma once

#include "tactile/core/api.hpp"
#include "tactile/core/container/smart_ptr.hpp"
#include "tactile/core/functional/maybe.hpp"
#include "tactile/core/misc/id_types.hpp"
#include "tactile/core/prelude.hpp"
#include "tactile/core/tileset/tileset.hpp"

namespace tactile {

/**
* \brief Represents a tileset that is attached to a map.
*
* \see `Tileset`
*/
class TACTILE_CORE_API AttachedTileset final {
public:
/**
* \brief Creates an attached tileset.
*
* \param tileset the associated tileset.
* \param first_tile_id the global tile identifier to associate with the first tile.
*/
AttachedTileset(Shared<Tileset> tileset, TileID first_tile_id);

/**
* \brief Converts a tile identifier to a tile index.
*
* \pre The tile identifier must be associated with the attached tileset.
*
* \param tile_id the tile identifier.
*
* \return a tile index.
*
* \see `has_tile()`
*/
[[nodiscard]]
auto to_index(TileID tile_id) const -> TileIndex;

/**
* \brief Indicates whether a tile identifier is contained in the tileset.
*
* \param tile_id the tile identifier.
*
* \return true if the identifier is valid; false otherwise.
*/
[[nodiscard]]
auto has_tile(TileID tile_id) const -> bool;

/**
* \brief Returns the first (lowest) associated tile identifier.
*
* \return a tile identifier.
*/
[[nodiscard]]
auto get_first_tile_id() const -> TileID;

/**
* \brief Returns the last (greatest) associated tile identifier.
*
* \return a tile identifier.
*/
[[nodiscard]]
auto get_last_tile_id() const -> TileID;

/**
* \brief Returns the associated tileset.
*
* \return a tileset reference.
*/
[[nodiscard]]
auto get_tileset() -> Tileset&;

/**
* \copydoc get_tileset()
*/
[[nodiscard]]
auto get_tileset() const -> const Tileset&;

private:
Shared<Tileset> mTileset;
TileID mFirstTileId;
TileID mLastTileId;
};

} // namespace tactile
49 changes: 49 additions & 0 deletions modules/core/src/tactile/core/tileset/attached_tileset.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (C) 2023 Albin Johansson (GNU General Public License v3.0)

#include "tactile/core/tileset/attached_tileset.hpp"

#include <utility> // move

#include "tactile/core/debug/assert.hpp"
#include "tactile/core/debug/error.hpp"

namespace tactile {

AttachedTileset::AttachedTileset(Shared<Tileset> tileset, const TileID first_tile_id)
: mTileset {tileset ? std::move(tileset) : throw RuntimeError {"Null tileset"}},
mFirstTileId {first_tile_id},
mLastTileId {first_tile_id.value + (mTileset->tile_count() - 1)}
{}

auto AttachedTileset::to_index(const TileID tile_id) const -> TileIndex
{
TACTILE_ASSERT(has_tile(tile_id));
return TileIndex {tile_id.value - mFirstTileId.value};
}

auto AttachedTileset::has_tile(const TileID tile_id) const -> bool
{
return tile_id >= mFirstTileId && tile_id <= mLastTileId;
}

auto AttachedTileset::get_first_tile_id() const -> TileID
{
return mFirstTileId;
}

auto AttachedTileset::get_last_tile_id() const -> TileID
{
return mLastTileId;
}

auto AttachedTileset::get_tileset() -> Tileset&
{
return *mTileset;
}

auto AttachedTileset::get_tileset() const -> const Tileset&
{
return *mTileset;
}

} // namespace tactile
59 changes: 59 additions & 0 deletions modules/core/test/tileset/attached_tileset_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (C) 2023 Albin Johansson (GNU General Public License v3.0)

#include "tactile/core/tileset/attached_tileset.hpp"

#include <gtest/gtest.h>

#include "tactile/core/debug/error.hpp"
#include "testutil/tileset_helpers.hpp"

using namespace tactile;

/// \tests tactile::AttachedTileset::AttachedTileset
TEST(AttachedTileset, ConstructorWithNullTileset)
{
EXPECT_THROW(AttachedTileset(nullptr, TileID {1}), RuntimeError);
}

/// \tests tactile::AttachedTileset::to_index
TEST(AttachedTileset, ToIndex)
{
const auto tileset_info = test::make_dummy_tileset_info();
const auto tileset = make_shared<Tileset>(tileset_info);

const AttachedTileset attached_tileset {tileset, TileID {42}};
const auto first_id = attached_tileset.get_first_tile_id();
const auto last_id = attached_tileset.get_last_tile_id();

EXPECT_EQ(attached_tileset.to_index(first_id), TileIndex {0});
EXPECT_EQ(attached_tileset.to_index(last_id), TileIndex {tileset->tile_count() - 1});
}

/// \tests tactile::AttachedTileset::has_tile
TEST(AttachedTileset, HasTile)
{
const auto tileset_info = test::make_dummy_tileset_info();
const auto tileset = make_shared<Tileset>(tileset_info);

const AttachedTileset attached_tileset {tileset, TileID {1}};
const auto first_id = attached_tileset.get_first_tile_id();
const auto last_id = attached_tileset.get_last_tile_id();

EXPECT_TRUE(attached_tileset.has_tile(first_id));
EXPECT_TRUE(attached_tileset.has_tile(last_id));

EXPECT_FALSE(attached_tileset.has_tile(TileID {first_id.value - 1}));
EXPECT_FALSE(attached_tileset.has_tile(TileID {last_id.value + 1}));
}

/// \tests tactile::AttachedTileset::get_first_tile_id
/// \tests tactile::AttachedTileset::get_last_tile_id
TEST(AttachedTileset, TileIdentifiers)
{
const auto tileset_info = test::make_dummy_tileset_info();
const auto tileset = make_shared<Tileset>(tileset_info);
const AttachedTileset attached_tileset {tileset, TileID {27}};

EXPECT_EQ(attached_tileset.get_first_tile_id(), TileID {27});
EXPECT_EQ(attached_tileset.get_last_tile_id(), TileID {27 + tileset->tile_count() - 1});
}

0 comments on commit ed43611

Please sign in to comment.