diff --git a/examples/29_grid.cc b/examples/29_grid.cc index e2874cd..f464d6d 100644 --- a/examples/29_grid.cc +++ b/examples/29_grid.cc @@ -118,6 +118,15 @@ int main() { grids[current].grid.hover(renderer.mapPixelToCoords(event.mouseCursor.coords)); break; + case gf::EventType::MouseButtonPressed: + { + auto coords = renderer.mapPixelToCoords(event.mouseButton.coords); + auto localCoords = gf::transform(grids[current].grid.getInverseTransform(), coords); + auto position = grids[current].grid.getCells().computeCoordinates(localCoords); + std::cout << "Position: " << position.x << ',' << position.y << '\n'; + break; + } + default: break; } diff --git a/include/gf/Grid.h b/include/gf/Grid.h index 36e8566..2443ef5 100644 --- a/include/gf/Grid.h +++ b/include/gf/Grid.h @@ -92,6 +92,13 @@ inline namespace v1 { */ static Grid createHexagonal(Vector2i gridSize, float radius, CellAxis axis, CellIndex index); + /** + * @brief Get the underlying cells + */ + const Cells& getCells() const { + return *m_properties; + } + /** * @brief Set the grid size * diff --git a/library/core/Cells_Hexagonal.cc b/library/core/Cells_Hexagonal.cc index 762abe7..ba6d73d 100644 --- a/library/core/Cells_Hexagonal.cc +++ b/library/core/Cells_Hexagonal.cc @@ -22,6 +22,7 @@ #include +#include #include #include @@ -116,50 +117,113 @@ inline namespace v1 { } Vector2i HexagonalCells::computeCoordinates(Vector2f position) const noexcept { - // good approximation but would need some tweaking - - Vector2i coords = gf::vec(0, 0); float offset = computeOffset(m_tileSize, m_sideLength, m_axis); + Vector2i coords = {}; switch (m_axis) { - case CellAxis::X: - coords.x = static_cast(position.x / (m_tileSize.width - offset)); - switch (m_index) { - case CellIndex::Odd: - if (coords.x % 2 == 0) { - coords.y = static_cast(position.y / m_tileSize.height); + case CellAxis::X: { + const float lx = m_tileSize.width - offset; + + const float qx = std::floor(position.x / lx); + const float rx = position.x - qx * lx; + const float nrx = rx / offset; + + const float halfy = m_tileSize.height / 2.0f; + const float qy = std::floor(position.y / halfy); + const float ry = position.y - qy * halfy; + const float nry = ry / halfy; + + const int x = static_cast(qx); + const int y = static_cast(qy); + + coords = vec(x, y); + + if ((m_index == CellIndex::Even) == (parity(x) == 0)) { + --coords.y; + } + + coords.y = static_cast(std::floor(coords.y / 2.0f)); + + if (rx < offset) { + if ((m_index == CellIndex::Even) == (parity(x) == 0)) { + if (parity(y) == 0) { + if (nrx < nry) { + --coords.x; + ++coords.y; + } } else { - coords.y = static_cast((position.y - m_tileSize.height / 2) / m_tileSize.height); + if (nrx + nry < 1) { + --coords.x; + } } - break; - case CellIndex::Even: - if (coords.x % 2 != 0) { - coords.y = static_cast(position.y / m_tileSize.height); + } else { + if (parity(y) == 0) { + if (nrx + nry < 1) { + --coords.x; + --coords.y; + } } else { - coords.y = static_cast((position.y - m_tileSize.height / 2) / m_tileSize.height); + if (nrx < nry) { + --coords.x; + } } - break; + } } + break; - case CellAxis::Y: - coords.y = static_cast(position.y / (m_tileSize.height - offset)); - switch (m_index) { - case CellIndex::Odd: - if (coords.y % 2 == 0) { - coords.x = static_cast(position.x / m_tileSize.width); + } + + case CellAxis::Y: { + const float ly = m_tileSize.height - offset; + + const float qy = std::floor(position.y / ly); + const float ry = position.y - qy * ly; + const float nry = ry / offset; + + const float halfx = m_tileSize.width / 2.0f; + const float qx = std::floor(position.x / halfx); + const float rx = position.x - qx * halfx; + const float nrx = rx / halfx; + + const int x = static_cast(qx); + const int y = static_cast(qy); + + coords = vec(x, y); + + if ((m_index == CellIndex::Even) == (parity(y) == 0)) { + --coords.x; + } + + coords.x = static_cast(std::floor(coords.x / 2.0f)); + + if (ry < offset) { + if ((m_index == CellIndex::Even) == (parity(y) == 0)) { + if (parity(x) == 0) { + if (nrx > nry) { + --coords.y; + ++coords.x; + } } else { - coords.x = static_cast((position.x - m_tileSize.width / 2) / m_tileSize.width); + if (nrx + nry < 1) { + --coords.y; + } } - break; - case CellIndex::Even: - if (coords.y % 2 != 0) { - coords.x = static_cast(position.x / m_tileSize.width); + } else { + if (parity(x) == 0) { + if (nrx + nry < 1) { + --coords.y; + --coords.x; + } } else { - coords.x = static_cast((position.x - m_tileSize.width / 2) / m_tileSize.width); + if (nrx > nry) { + --coords.y; + } } - break; + } } + break; + } } return coords; diff --git a/library/core/Cells_Orthogonal.cc b/library/core/Cells_Orthogonal.cc index 63900cc..a2c2852 100644 --- a/library/core/Cells_Orthogonal.cc +++ b/library/core/Cells_Orthogonal.cc @@ -40,7 +40,7 @@ inline namespace v1 { } Vector2i OrthogonalCells::computeCoordinates(Vector2f position) const noexcept { - return position / m_tileSize; + return vec(static_cast(std::floor(position.x / m_tileSize.width)), static_cast(std::floor(position.y / m_tileSize.height))); } Polyline OrthogonalCells::computePolyline(Vector2i coords) const { diff --git a/library/core/Cells_Staggered.cc b/library/core/Cells_Staggered.cc index 6f771c4..f063f47 100644 --- a/library/core/Cells_Staggered.cc +++ b/library/core/Cells_Staggered.cc @@ -92,14 +92,6 @@ inline namespace v1 { return RectF::fromPositionSize(base, m_tileSize); } - namespace { - - bool isDiagonallySplit(CellIndex index, int x, int y) { - return (index == CellIndex::Even) == (parity(x) == parity(y)); - } - - } - Vector2i StaggeredCells::computeCoordinates(Vector2f position) const noexcept { const Vector2f half = m_tileSize / 2.0f; @@ -116,26 +108,28 @@ inline namespace v1 { gf::Vector2i coords = vec(x, y); + const bool isDiagonallySplit = (m_index == CellIndex::Even) == (parity(x) == parity(y)); + if (m_axis == CellAxis::X) { - if ((isDiagonallySplit(m_index, x, y) && rx < ry) || (!isDiagonallySplit(m_index, x, y) && (rx + ry) < 1)) { + if ((isDiagonallySplit && rx < ry) || (!isDiagonallySplit && (rx + ry) < 1)) { --coords.x; } - coords.y = y / 2; + coords.y = static_cast(std::floor(qy / 2)); - if (parity(y) == 0 && ((isDiagonallySplit(m_index, x, y) && rx > ry) || (!isDiagonallySplit(m_index, x, y) && (rx + ry) < 1))) { + if (parity(y) == 0 && ((isDiagonallySplit && rx > ry) || (!isDiagonallySplit && (rx + ry) < 1))) { --coords.y; } // Log::info("position: %g %g\tq: %g %g\tr: %g %g\tcoords: %d %d\n", position.x, position.y, qx, qy, rx, ry, coords.x, coords.y); } else { - if ((isDiagonallySplit(m_index, x, y) && rx > ry) || (!isDiagonallySplit(m_index, x, y) && (rx + ry) < 1)) { + if ((isDiagonallySplit && rx > ry) || (!isDiagonallySplit && (rx + ry) < 1)) { --coords.y; } - coords.x = x / 2; + coords.x = static_cast(std::floor(qx / 2)); - if (parity(x) == 0 && ((isDiagonallySplit(m_index, x, y) && rx < ry) || (!isDiagonallySplit(m_index, x, y) && (rx + ry) < 1))) { + if (parity(x) == 0 && ((isDiagonallySplit && rx < ry) || (!isDiagonallySplit && (rx + ry) < 1))) { --coords.x; } }