mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-20 21:43:06 +01:00
131 lines
3.2 KiB
C++
131 lines
3.2 KiB
C++
/*****************************************************************************
|
|
* Copyright (c) 2014-2023 OpenRCT2 developers
|
|
*
|
|
* For a complete list of all authors, please refer to contributors.md
|
|
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
|
*
|
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
|
*****************************************************************************/
|
|
|
|
#include "Location.hpp"
|
|
#include "Map.h"
|
|
#include "TileElement.h"
|
|
|
|
#include <iterator>
|
|
|
|
namespace OpenRCT2
|
|
{
|
|
namespace Detail
|
|
{
|
|
template<typename T, typename T2> T* NextMatchingTile(T2* element)
|
|
{
|
|
if (element == nullptr)
|
|
return nullptr;
|
|
|
|
for (;;)
|
|
{
|
|
auto* res = element->template as<T>();
|
|
if (res != nullptr)
|
|
return res;
|
|
|
|
if (element->IsLastForTile())
|
|
{
|
|
break;
|
|
}
|
|
element++;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
} // namespace Detail
|
|
|
|
template<typename T = TileElement> class TileElementsView
|
|
{
|
|
const CoordsXY _loc;
|
|
|
|
public:
|
|
struct Iterator
|
|
{
|
|
T* element = nullptr;
|
|
|
|
Iterator& operator++()
|
|
{
|
|
if (element == nullptr)
|
|
return *this;
|
|
|
|
if (element->IsLastForTile())
|
|
{
|
|
element = nullptr;
|
|
}
|
|
else
|
|
{
|
|
element++;
|
|
if constexpr (!std::is_same_v<T, TileElement>)
|
|
{
|
|
element = Detail::NextMatchingTile<T>(element);
|
|
}
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
Iterator operator++(int)
|
|
{
|
|
Iterator res = *this;
|
|
++(*this);
|
|
return res;
|
|
}
|
|
|
|
bool operator==(Iterator other) const
|
|
{
|
|
return element == other.element;
|
|
}
|
|
|
|
bool operator!=(Iterator other) const
|
|
{
|
|
return !(*this == other);
|
|
}
|
|
|
|
T* operator*()
|
|
{
|
|
return element;
|
|
}
|
|
|
|
const T* operator*() const
|
|
{
|
|
return element;
|
|
}
|
|
|
|
// iterator traits
|
|
using difference_type = std::ptrdiff_t;
|
|
using value_type = T;
|
|
using pointer = const T*;
|
|
using reference = const T&;
|
|
using iterator_category = std::forward_iterator_tag;
|
|
};
|
|
|
|
TileElementsView(const CoordsXY& loc)
|
|
: _loc(loc)
|
|
{
|
|
}
|
|
|
|
Iterator begin() noexcept
|
|
{
|
|
T* element = reinterpret_cast<T*>(MapGetFirstElementAt(_loc));
|
|
|
|
if constexpr (!std::is_same_v<T, TileElement>)
|
|
{
|
|
element = Detail::NextMatchingTile<T>(element);
|
|
}
|
|
|
|
return Iterator{ element };
|
|
}
|
|
|
|
Iterator end() noexcept
|
|
{
|
|
return Iterator{ nullptr };
|
|
}
|
|
};
|
|
|
|
} // namespace OpenRCT2
|