diff --git a/source/base/inc/tactile/base/document/component_view.hpp b/source/base/inc/tactile/base/document/component_view.hpp index 08b676aab8..e46005a84c 100644 --- a/source/base/inc/tactile/base/document/component_view.hpp +++ b/source/base/inc/tactile/base/document/component_view.hpp @@ -2,6 +2,7 @@ #pragma once +#include "tactile/base/container/expected.hpp" #include "tactile/base/container/pair.hpp" #include "tactile/base/container/string.hpp" #include "tactile/base/int.hpp" @@ -24,8 +25,12 @@ class IComponentView * Inspects the component. * * \param visitor The visitor to use. + * + * \return + * Nothing if successful; an error code otherwise. */ - virtual void accept(IDocumentVisitor& visitor) const = 0; + [[nodiscard]] + virtual auto accept(IDocumentVisitor& visitor) const -> Result = 0; /** * Returns the name of the component. @@ -45,8 +50,7 @@ class IComponentView * An attribute key and value pair. */ [[nodiscard]] - virtual auto get_attribute(usize index) const - -> Pair = 0; + virtual auto get_attribute(usize index) const -> Pair = 0; /** * Returns the number of attributes in the component. diff --git a/source/base/inc/tactile/base/document/document.hpp b/source/base/inc/tactile/base/document/document.hpp index 2aa7d753ba..62c1975058 100644 --- a/source/base/inc/tactile/base/document/document.hpp +++ b/source/base/inc/tactile/base/document/document.hpp @@ -2,6 +2,7 @@ #pragma once +#include "tactile/base/container/expected.hpp" #include "tactile/base/container/path.hpp" #include "tactile/base/numeric/vec.hpp" #include "tactile/base/prelude.hpp" @@ -24,8 +25,12 @@ class IDocument * Inspects the document. * * \param visitor The visitor to use. + * + * \return + * Nothing if successful; an error code otherwise. */ - virtual void accept(IDocumentVisitor& visitor) const = 0; + [[nodiscard]] + virtual auto accept(IDocumentVisitor& visitor) const -> Result = 0; /** * Updates the state of the document. diff --git a/source/base/inc/tactile/base/document/layer_view.hpp b/source/base/inc/tactile/base/document/layer_view.hpp index 3de2c4b224..5d80f5a77c 100644 --- a/source/base/inc/tactile/base/document/layer_view.hpp +++ b/source/base/inc/tactile/base/document/layer_view.hpp @@ -2,6 +2,7 @@ #pragma once +#include "tactile/base/container/expected.hpp" #include "tactile/base/container/maybe.hpp" #include "tactile/base/container/string.hpp" #include "tactile/base/id.hpp" @@ -30,8 +31,12 @@ class ILayerView * Inspects the layer. * * \param visitor The visitor to use. + * + * \return + * Nothing if successful; an error code otherwise. */ - virtual void accept(IDocumentVisitor& visitor) const = 0; + [[nodiscard]] + virtual auto accept(IDocumentVisitor& visitor) const -> Result = 0; virtual void write_tile_bytes(ByteStream& byte_stream) const = 0; diff --git a/source/base/inc/tactile/base/document/map_view.hpp b/source/base/inc/tactile/base/document/map_view.hpp index 13ab0e1fe4..9501d83c17 100644 --- a/source/base/inc/tactile/base/document/map_view.hpp +++ b/source/base/inc/tactile/base/document/map_view.hpp @@ -2,6 +2,7 @@ #pragma once +#include "tactile/base/container/expected.hpp" #include "tactile/base/container/maybe.hpp" #include "tactile/base/id.hpp" #include "tactile/base/int.hpp" @@ -28,8 +29,11 @@ class IMapView * Inspects the map. * * \param visitor The visitor to use. + * + * \return + * Nothing if successful; an error code otherwise. */ - virtual void accept(IDocumentVisitor& visitor) const = 0; + virtual auto accept(IDocumentVisitor& visitor) const -> Result = 0; /** * Returns the logical size of tiles in the map. diff --git a/source/base/inc/tactile/base/document/object_view.hpp b/source/base/inc/tactile/base/document/object_view.hpp index 857539c0a7..e3fc4ff805 100644 --- a/source/base/inc/tactile/base/document/object_view.hpp +++ b/source/base/inc/tactile/base/document/object_view.hpp @@ -2,6 +2,7 @@ #pragma once +#include "tactile/base/container/expected.hpp" #include "tactile/base/container/string.hpp" #include "tactile/base/id.hpp" #include "tactile/base/layer/object_type.hpp" @@ -27,8 +28,12 @@ class IObjectView * Inspects the object. * * \param visitor The visitor to use. + * + * \return + * Nothing if successful; an error code otherwise. */ - virtual void accept(IDocumentVisitor& visitor) const = 0; + [[nodiscard]] + virtual auto accept(IDocumentVisitor& visitor) const -> Result = 0; /** * Returns a view of the parent object layer, if any. diff --git a/source/base/inc/tactile/base/document/tile_view.hpp b/source/base/inc/tactile/base/document/tile_view.hpp index d598ecd45e..77b2b85f3f 100644 --- a/source/base/inc/tactile/base/document/tile_view.hpp +++ b/source/base/inc/tactile/base/document/tile_view.hpp @@ -2,6 +2,7 @@ #pragma once +#include "tactile/base/container/expected.hpp" #include "tactile/base/container/pair.hpp" #include "tactile/base/id.hpp" #include "tactile/base/prelude.hpp" @@ -25,8 +26,12 @@ class ITileView * Inspects the tile. * * \param visitor The visitor to use. + * + * \return + * Nothing if successful; an error code otherwise. */ - virtual void accept(IDocumentVisitor& visitor) const = 0; + [[nodiscard]] + virtual auto accept(IDocumentVisitor& visitor) const -> Result = 0; /** * Returns the tileset that hosts the tile. @@ -73,8 +78,7 @@ class ITileView * A tile index and frame duration pair. */ [[nodiscard]] - virtual auto get_animation_frame(usize index) const - -> Pair = 0; + virtual auto get_animation_frame(usize index) const -> Pair = 0; /** * Returns a view of the associated metadata. diff --git a/source/base/inc/tactile/base/document/tileset_view.hpp b/source/base/inc/tactile/base/document/tileset_view.hpp index ee38c88b7e..59d0a9c95a 100644 --- a/source/base/inc/tactile/base/document/tileset_view.hpp +++ b/source/base/inc/tactile/base/document/tileset_view.hpp @@ -2,6 +2,7 @@ #pragma once +#include "tactile/base/container/expected.hpp" #include "tactile/base/container/path.hpp" #include "tactile/base/container/string.hpp" #include "tactile/base/id.hpp" @@ -26,8 +27,12 @@ class ITilesetView * Inspects the tileset. * * \param visitor The visitor to use. + * + * \return + * Nothing if successful; an error code otherwise. */ - virtual void accept(IDocumentVisitor& visitor) const = 0; + [[nodiscard]] + virtual auto accept(IDocumentVisitor& visitor) const -> Result = 0; /** * Returns the first global tile identifier associated with the tileset. diff --git a/source/base/test_util/inc/tactile/base/test_util/document_view_mocks.hpp b/source/base/test_util/inc/tactile/base/test_util/document_view_mocks.hpp index c9e581427a..771b344fbe 100644 --- a/source/base/test_util/inc/tactile/base/test_util/document_view_mocks.hpp +++ b/source/base/test_util/inc/tactile/base/test_util/document_view_mocks.hpp @@ -57,12 +57,13 @@ class ObjectViewMock : public IObjectView { ON_CALL(*this, accept).WillByDefault([this](IDocumentVisitor& visitor) { visitor.visit(*this).value(); + return kOK; }); ON_CALL(*this, get_meta).WillByDefault(testing::ReturnRef(mMeta)); } - MOCK_METHOD(void, accept, (IDocumentVisitor&), (const, override)); + MOCK_METHOD(Result, accept, (IDocumentVisitor&), (const, override)); MOCK_METHOD(const ILayerView*, get_parent_layer, (), (const, override)); @@ -100,7 +101,7 @@ class TileViewMock : public ITileView ON_CALL(*this, get_meta).WillByDefault(testing::ReturnRef(mMeta)); } - MOCK_METHOD(void, accept, (IDocumentVisitor&), (const, override)); + MOCK_METHOD(Result, accept, (IDocumentVisitor&), (const, override)); MOCK_METHOD(const ITilesetView&, get_parent_tileset, (), (const, override)); @@ -135,7 +136,7 @@ class TilesetViewMock : public ITilesetView ON_CALL(*this, get_meta).WillByDefault(testing::ReturnRef(mMeta)); } - MOCK_METHOD(void, accept, (IDocumentVisitor&), (const, override)); + MOCK_METHOD(Result, accept, (IDocumentVisitor&), (const, override)); MOCK_METHOD(TileID, get_first_tile_id, (), (const, override)); @@ -173,7 +174,7 @@ class LayerViewMock : public ILayerView ON_CALL(*this, get_meta).WillByDefault(testing::ReturnRef(mMeta)); } - MOCK_METHOD(void, accept, (IDocumentVisitor&), (const, override)); + MOCK_METHOD(Result, accept, (IDocumentVisitor&), (const, override)); MOCK_METHOD(void, write_tile_bytes, (ByteStream&), (const, override)); @@ -242,7 +243,7 @@ class MapViewMock : public IMapView ON_CALL(*this, get_meta).WillByDefault(testing::ReturnRef(mMeta)); } - MOCK_METHOD(void, accept, (IDocumentVisitor&), (const, override)); + MOCK_METHOD(Result, accept, (IDocumentVisitor&), (const, override)); MOCK_METHOD(Int2, get_tile_size, (), (const, override)); diff --git a/source/core/inc/tactile/core/document/layer_view_impl.hpp b/source/core/inc/tactile/core/document/layer_view_impl.hpp index 04a0fdc12e..7810679bae 100644 --- a/source/core/inc/tactile/core/document/layer_view_impl.hpp +++ b/source/core/inc/tactile/core/document/layer_view_impl.hpp @@ -30,7 +30,8 @@ class LayerViewImpl final : public ILayerView const ILayerView* parent_layer, EntityID layer_id); - void accept(IDocumentVisitor& visitor) const override; + [[nodiscard]] + auto accept(IDocumentVisitor& visitor) const -> Result override; void write_tile_bytes(ByteStream& byte_stream) const override; diff --git a/source/core/inc/tactile/core/document/map_document.hpp b/source/core/inc/tactile/core/document/map_document.hpp index 6b88e85bcd..01a55fdc1a 100644 --- a/source/core/inc/tactile/core/document/map_document.hpp +++ b/source/core/inc/tactile/core/document/map_document.hpp @@ -50,7 +50,8 @@ class MapDocument final : public IDocument ~MapDocument() noexcept override; - void accept(IDocumentVisitor& visitor) const override; + [[nodiscard]] + auto accept(IDocumentVisitor& visitor) const -> Result override; void update() override; diff --git a/source/core/inc/tactile/core/document/map_view_impl.hpp b/source/core/inc/tactile/core/document/map_view_impl.hpp index f43a420f15..bc78a4995f 100644 --- a/source/core/inc/tactile/core/document/map_view_impl.hpp +++ b/source/core/inc/tactile/core/document/map_view_impl.hpp @@ -26,7 +26,8 @@ class MapViewImpl final : public IMapView */ MapViewImpl(const MapDocument* document); - void accept(IDocumentVisitor& visitor) const override; + [[nodiscard]] + auto accept(IDocumentVisitor& visitor) const -> Result override; [[nodiscard]] auto get_tile_size() const -> Int2 override; diff --git a/source/core/inc/tactile/core/document/object_view_impl.hpp b/source/core/inc/tactile/core/document/object_view_impl.hpp index e14551d4ae..ea056c8cde 100644 --- a/source/core/inc/tactile/core/document/object_view_impl.hpp +++ b/source/core/inc/tactile/core/document/object_view_impl.hpp @@ -39,7 +39,8 @@ class ObjectViewImpl final : public IObjectView const ITileView* parent_tile, EntityID object_id); - void accept(IDocumentVisitor& visitor) const override; + [[nodiscard]] + auto accept(IDocumentVisitor& visitor) const -> Result override; [[nodiscard]] auto get_parent_layer() const -> const ILayerView* override; diff --git a/source/core/inc/tactile/core/document/tile_view_impl.hpp b/source/core/inc/tactile/core/document/tile_view_impl.hpp index 9a87a49eee..60d17c12ab 100644 --- a/source/core/inc/tactile/core/document/tile_view_impl.hpp +++ b/source/core/inc/tactile/core/document/tile_view_impl.hpp @@ -31,7 +31,8 @@ class TileViewImpl final : public ITileView const ITilesetView* tileset_view, EntityID tile_id); - void accept(IDocumentVisitor& visitor) const override; + [[nodiscard]] + auto accept(IDocumentVisitor& visitor) const -> Result override; [[nodiscard]] auto get_parent_tileset() const -> const ITilesetView& override; diff --git a/source/core/inc/tactile/core/document/tileset_view_impl.hpp b/source/core/inc/tactile/core/document/tileset_view_impl.hpp index 8f08b51db3..95e34b14c3 100644 --- a/source/core/inc/tactile/core/document/tileset_view_impl.hpp +++ b/source/core/inc/tactile/core/document/tileset_view_impl.hpp @@ -25,7 +25,8 @@ class TilesetViewImpl final : public ITilesetView */ TilesetViewImpl(const MapDocument* document, EntityID tileset_id); - void accept(IDocumentVisitor& visitor) const override; + [[nodiscard]] + auto accept(IDocumentVisitor& visitor) const -> Result override; [[nodiscard]] auto get_first_tile_id() const -> TileID override; diff --git a/source/core/src/tactile/core/document/layer_view_impl.cpp b/source/core/src/tactile/core/document/layer_view_impl.cpp index a0bf705889..0e12cf1ec2 100644 --- a/source/core/src/tactile/core/document/layer_view_impl.cpp +++ b/source/core/src/tactile/core/document/layer_view_impl.cpp @@ -27,18 +27,23 @@ LayerViewImpl::LayerViewImpl(const MapDocument* document, mMeta {document, mLayerId} {} -void LayerViewImpl::accept(IDocumentVisitor& visitor) const +auto LayerViewImpl::accept(IDocumentVisitor& visitor) const -> Result { const auto& registry = mDocument->get_registry(); - visitor.visit(*this); + if (const auto layer_result = visitor.visit(*this); !layer_result.has_value()) { + return propagate_unexpected(layer_result); + } if (is_group_layer(registry, mLayerId)) { const auto& group_layer = registry.get(mLayerId); for (const auto sublayer_id : group_layer.layers) { const LayerViewImpl sublayer_view {mDocument, this, sublayer_id}; - sublayer_view.accept(visitor); + if (const auto sublayer_result = sublayer_view.accept(visitor); + !sublayer_result.has_value()) { + return propagate_unexpected(sublayer_result); + } } } else if (is_object_layer(registry, mLayerId)) { @@ -46,9 +51,13 @@ void LayerViewImpl::accept(IDocumentVisitor& visitor) const for (const auto object_id : object_layer.objects) { const ObjectViewImpl object_view {mDocument, this, object_id}; - object_view.accept(visitor); + if (const auto object_result = object_view.accept(visitor); !object_result.has_value()) { + return propagate_unexpected(object_result); + } } } + + return kOK; } void LayerViewImpl::write_tile_bytes(ByteStream& byte_stream) const diff --git a/source/core/src/tactile/core/document/map_document.cpp b/source/core/src/tactile/core/document/map_document.cpp index 32c4447693..0cc75eea2c 100644 --- a/source/core/src/tactile/core/document/map_document.cpp +++ b/source/core/src/tactile/core/document/map_document.cpp @@ -87,10 +87,10 @@ TACTILE_DEFINE_MOVE(MapDocument); MapDocument::~MapDocument() noexcept = default; -void MapDocument::accept(IDocumentVisitor& visitor) const +auto MapDocument::accept(IDocumentVisitor& visitor) const -> Result { const MapViewImpl map_view {this}; - map_view.accept(visitor); + return map_view.accept(visitor); } void MapDocument::update() diff --git a/source/core/src/tactile/core/document/map_view_impl.cpp b/source/core/src/tactile/core/document/map_view_impl.cpp index 4cb13a4545..ff16f7372e 100644 --- a/source/core/src/tactile/core/document/map_view_impl.cpp +++ b/source/core/src/tactile/core/document/map_view_impl.cpp @@ -19,26 +19,35 @@ MapViewImpl::MapViewImpl(const MapDocument* document) mMeta {mDocument, mDocument->get_registry().get().root} {} -void MapViewImpl::accept(IDocumentVisitor& visitor) const +auto MapViewImpl::accept(IDocumentVisitor& visitor) const -> Result { const auto& registry = mDocument->get_registry(); const auto& map = _get_map(); const auto& root_layer = registry.get(map.root_layer); - visitor.visit(*this); + if (const auto map_result = visitor.visit(*this); !map_result.has_value()) { + return propagate_unexpected(map_result); + } for (const auto tileset_id : map.attached_tilesets) { const TilesetViewImpl tileset_view {mDocument, tileset_id}; - tileset_view.accept(visitor); + if (const auto tileset_result = tileset_view.accept(visitor); + !tileset_result.has_value()) { + return propagate_unexpected(tileset_result); + } } for (const auto layer_id : root_layer.layers) { const LayerViewImpl layer_view {mDocument, nullptr, layer_id}; - layer_view.accept(visitor); + if (const auto layer_result = layer_view.accept(visitor); !layer_result.has_value()) { + return propagate_unexpected(layer_result); + } } // TODO iterate component definitions + + return kOK; } auto MapViewImpl::get_tile_size() const -> Int2 diff --git a/source/core/src/tactile/core/document/object_view_impl.cpp b/source/core/src/tactile/core/document/object_view_impl.cpp index eae6818ec3..fd4222dcdc 100644 --- a/source/core/src/tactile/core/document/object_view_impl.cpp +++ b/source/core/src/tactile/core/document/object_view_impl.cpp @@ -30,9 +30,9 @@ ObjectViewImpl::ObjectViewImpl(const IDocument* document, mMeta {document, object_id} {} -void ObjectViewImpl::accept(IDocumentVisitor& visitor) const +auto ObjectViewImpl::accept(IDocumentVisitor& visitor) const -> Result { - visitor.visit(*this); + return visitor.visit(*this); } auto ObjectViewImpl::get_parent_layer() const -> const ILayerView* diff --git a/source/core/src/tactile/core/document/tile_view_impl.cpp b/source/core/src/tactile/core/document/tile_view_impl.cpp index 93accc1f76..ab0b8cc495 100644 --- a/source/core/src/tactile/core/document/tile_view_impl.cpp +++ b/source/core/src/tactile/core/document/tile_view_impl.cpp @@ -2,9 +2,9 @@ #include "tactile/core/document/tile_view_impl.hpp" +#include "tactile/base/document/document.hpp" #include "tactile/base/document/document_visitor.hpp" #include "tactile/core/debug/validation.hpp" -#include "tactile/base/document/document.hpp" #include "tactile/core/entity/registry.hpp" #include "tactile/core/tile/animation.hpp" #include "tactile/core/tile/tile.hpp" @@ -21,17 +21,23 @@ TileViewImpl::TileViewImpl(const IDocument* document, mMeta {document, tile_id} {} -void TileViewImpl::accept(IDocumentVisitor& visitor) const +auto TileViewImpl::accept(IDocumentVisitor& visitor) const -> Result { - visitor.visit(*this); + if (const auto tile_result = visitor.visit(*this); !tile_result.has_value()) { + return propagate_unexpected(tile_result); + } const auto& registry = mDocument->get_registry(); const auto& tile = registry.get(mTileId); for (const auto object_id : tile.objects) { const ObjectViewImpl object_view {mDocument, this, object_id}; - object_view.accept(visitor); + if (const auto object_result = object_view.accept(visitor); !object_result.has_value()) { + return propagate_unexpected(object_result); + } } + + return kOK; } auto TileViewImpl::get_parent_tileset() const -> const ITilesetView& diff --git a/source/core/src/tactile/core/document/tileset_view_impl.cpp b/source/core/src/tactile/core/document/tileset_view_impl.cpp index c031dc2643..9400d8b48c 100644 --- a/source/core/src/tactile/core/document/tileset_view_impl.cpp +++ b/source/core/src/tactile/core/document/tileset_view_impl.cpp @@ -16,26 +16,33 @@ namespace tactile { -TilesetViewImpl::TilesetViewImpl(const MapDocument* document, - const EntityID tileset_id) +TilesetViewImpl::TilesetViewImpl(const MapDocument* document, const EntityID tileset_id) : mDocument {require_not_null(document, "null document")}, mTilesetId {tileset_id}, mMeta {mDocument, mTilesetId} {} -void TilesetViewImpl::accept(IDocumentVisitor& visitor) const +auto TilesetViewImpl::accept(IDocumentVisitor& visitor) const -> Result { - visitor.visit(*this); + if (const auto tileset_result = visitor.visit(*this); !tileset_result.has_value()) { + return propagate_unexpected(tileset_result); + } const auto& registry = mDocument->get_registry(); const auto& tileset = registry.get(mTilesetId); for (const auto tile_id : tileset.tiles) { - if (!is_tile_plain(registry, tile_id)) { - const TileViewImpl tile_view {mDocument, this, tile_id}; - tile_view.accept(visitor); + if (is_tile_plain(registry, tile_id)) { + continue; + } + + const TileViewImpl tile_view {mDocument, this, tile_id}; + if (const auto tile_result = tile_view.accept(visitor); !tile_result.has_value()) { + return propagate_unexpected(tile_result); } } + + return kOK; } auto TilesetViewImpl::get_first_tile_id() const -> TileID @@ -59,10 +66,9 @@ auto TilesetViewImpl::tile_definition_count() const -> usize const auto& registry = mDocument->get_registry(); const auto& tileset = registry.get(mTilesetId); - return saturate_cast( - std::ranges::count_if(tileset.tiles, [®istry](const EntityID tile_id) { - return !is_tile_plain(registry, tile_id); - })); + return saturate_cast(std::ranges::count_if( + tileset.tiles, + [®istry](const EntityID tile_id) { return !is_tile_plain(registry, tile_id); })); } auto TilesetViewImpl::column_count() const -> usize