Further Point refactoring (#1111)

* Split up viewport transforms

* Make naming more concistent

* Move into namespace, make constexpr
This commit is contained in:
Duncan 2021-08-17 11:59:41 +01:00 committed by GitHub
parent 055def4215
commit a48d0c7c74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 89 additions and 23 deletions

View File

@ -620,7 +620,7 @@ namespace OpenLoco::Audio
}
volume += calculateVolumeFromViewport(id, loc, *viewport);
pan = viewport->mapToUi(vpos).x;
pan = viewport->viewportToScreen(vpos).x;
if (volume < -10000)
{
return;

View File

@ -96,6 +96,16 @@ namespace OpenLoco::Math::Vector
{
return { static_cast<T>(x / rhs), static_cast<T>(y / rhs) };
}
constexpr const TVector2 operator<<(const uint8_t rhs) const
{
return { static_cast<T>(x << rhs), static_cast<T>(y << rhs) };
}
constexpr const TVector2 operator>>(const uint8_t rhs) const
{
return { static_cast<T>(x >> rhs), static_cast<T>(y >> rhs) };
}
};
template<typename T, T TResolution = 1>

View File

@ -377,7 +377,7 @@ namespace OpenLoco::Ui::ViewportInteraction
uint32_t nearestDistance = std::numeric_limits<uint32_t>().max();
Vehicles::VehicleBase* nearestVehicle = nullptr;
auto targetPosition = viewport->uiToMap({ tempX, tempY });
auto targetPosition = viewport->screenToViewport({ tempX, tempY });
for (auto v : EntityManager::VehicleList())
{
@ -993,7 +993,7 @@ namespace OpenLoco::Ui::ViewportInteraction
continue;
chosenV = vp;
auto vpPos = vp->uiToMap({ screenPos.x, screenPos.y });
auto vpPos = vp->screenToViewport({ screenPos.x, screenPos.y });
_context1->zoom_level = vp->zoom;
_context1->x = (0xFFFF << vp->zoom) & vpPos.x;
_context1->y = (0xFFFF << vp->zoom) & vpPos.y;
@ -1058,7 +1058,7 @@ namespace OpenLoco::Ui::ViewportInteraction
const auto minPosition = info.pos; // E40128/A
const auto maxPosition = info.pos + Pos2{ 31, 31 }; // E4012C/E
auto mapPos = info.pos + Pos2{ 16, 16 };
const auto initialVPPos = viewport->uiToMap(screenCoords);
const auto initialVPPos = viewport->screenToViewport(screenCoords);
for (int32_t i = 0; i < 5; i++)
{
@ -1091,7 +1091,7 @@ namespace OpenLoco::Ui::ViewportInteraction
const auto minPosition = info.pos; // E40128/A
const auto maxPosition = info.pos + Pos2{ 31, 31 }; // E4012C/E
auto mapPos = info.pos + Pos2{ 16, 16 };
const auto initialVPPos = viewport->uiToMap(screenCoords);
const auto initialVPPos = viewport->screenToViewport(screenCoords);
for (int32_t i = 0; i < 5; i++)
{

View File

@ -33,7 +33,7 @@ namespace OpenLoco::Ui
return;
}
auto intersection = contextRect.intersection(viewRect);
paint(context, uiToMap(intersection));
paint(context, screenToViewport(intersection));
}
// 0x0045A1A4

View File

@ -54,6 +54,18 @@ namespace OpenLoco::Ui
constexpr uint32_t station_names_displayed = 1 << 10;
}
struct Viewport;
namespace ScreenToViewport
{
[[nodiscard]] constexpr Point applyTransform(const Point& uiPoint, const Viewport& vp);
}
namespace ViewportToScreen
{
[[nodiscard]] constexpr Point applyTransform(const Point& vpPoint, const Viewport& vp);
}
struct Viewport
{
int16_t width; // 0x00
@ -117,29 +129,27 @@ namespace OpenLoco::Ui
/**
* Maps a 2D viewport position to a UI (screen) position.
*/
Point mapToUi(const viewport_pos& vpos) const
Point viewportToScreen(const viewport_pos& vpos) const
{
auto uiX = x + ((vpos.x - view_x) >> zoom);
auto uiY = y + ((vpos.y - view_y) >> zoom);
return Point(uiX, uiY);
const auto vpPoint = ViewportToScreen::applyTransform({ vpos.x, vpos.y }, *this);
return vpPoint;
}
/**
* Maps a UI (screen) position to a 2D viewport position.
*/
viewport_pos uiToMap(const Point& pos) const
viewport_pos screenToViewport(const Point& pos) const
{
int16_t viewport_x = ((pos.x - x) << zoom) + view_x;
int16_t viewport_y = ((pos.y - y) << zoom) + view_y;
return { viewport_x, viewport_y };
const auto vpPoint = ScreenToViewport::applyTransform(pos, *this);
return { vpPoint.x, vpPoint.y };
}
/**
* Maps a UI (screen) rectangle to a 2D viewport rectangle.
*/
Rect uiToMap(const Rect& rect)
Rect screenToViewport(const Rect& rect)
{
auto leftTop = uiToMap(Point(rect.left(), rect.top()));
auto rightBottom = uiToMap(Point(rect.right(), rect.bottom()));
auto leftTop = screenToViewport(Point(rect.left(), rect.top()));
auto rightBottom = screenToViewport(Point(rect.right(), rect.bottom()));
return Rect::fromLTRB(leftTop.x, leftTop.y, rightBottom.x, rightBottom.y);
}
@ -162,4 +172,50 @@ namespace OpenLoco::Ui
int16_t saved_view_x; // 0x2
int16_t saved_view_y; // 0x4
};
namespace ScreenToViewport
{
[[nodiscard]] constexpr Point uiOffsetTransform(const Point& uiPoint, const Viewport& vp)
{
return uiPoint - Point{ vp.x, vp.y };
}
[[nodiscard]] constexpr Point scaleTransform(const Point& uiPoint, const Viewport& vp)
{
return uiPoint << vp.zoom;
}
[[nodiscard]] constexpr Point viewOffsetTransform(const Point& point, const Viewport& vp)
{
return point + Point{ vp.view_x, vp.view_y };
}
[[nodiscard]] constexpr Point applyTransform(const Point& uiPoint, const Viewport& vp)
{
return viewOffsetTransform(scaleTransform(uiOffsetTransform(uiPoint, vp), vp), vp);
}
}
namespace ViewportToScreen
{
[[nodiscard]] constexpr Point uiOffsetTransform(const Point& uiPoint, const Viewport& vp)
{
return uiPoint + Point{ vp.x, vp.y };
}
[[nodiscard]] constexpr Point scaleTransform(const Point& uiPoint, const Viewport& vp)
{
return uiPoint >> vp.zoom;
}
[[nodiscard]] constexpr Point viewOffsetTransform(const Point& point, const Viewport& vp)
{
return point - Point{ vp.view_x, vp.view_y };
}
[[nodiscard]] constexpr Point applyTransform(const Point& vpPoint, const Viewport& vp)
{
return uiOffsetTransform(scaleTransform(viewOffsetTransform(vpPoint, vp), vp), vp);
}
}
}

View File

@ -141,7 +141,7 @@ namespace OpenLoco::Ui
if (vp->containsUi(mouse))
{
viewport_pos vpos = vp->uiToMap(mouse);
viewport_pos vpos = vp->screenToViewport(mouse);
Map::Pos2 position = viewportCoordToMapCoord(vpos.x, vpos.y, z, WindowManager::getCurrentRotation());
if (position.x <= 0x2FFF && position.y <= 0x2FFF)
{

View File

@ -659,11 +659,11 @@ namespace OpenLoco::Ui::Windows::Construction
bool isPointCloserToNextOrPreviousTile(const Point& point, const Viewport& viewport)
{
const auto vpPosNext = gameToScreen(*_nextTile + Map::Pos3(16, 16, 0), viewport.getRotation());
const auto uiPosNext = viewport.mapToUi(vpPosNext);
const auto uiPosNext = viewport.viewportToScreen(vpPosNext);
const auto distanceToNext = Math::Vector::manhattanDistance(uiPosNext, point);
const auto vpPosPrevious = gameToScreen(*_previousTile + Map::Pos3(16, 16, 0), viewport.getRotation());
const auto uiPosPrevious = viewport.mapToUi(vpPosPrevious);
const auto uiPosPrevious = viewport.viewportToScreen(vpPosPrevious);
const auto distanceToPrevious = Math::Vector::manhattanDistance(uiPosPrevious, point);
return distanceToNext < distanceToPrevious;

View File

@ -3537,7 +3537,7 @@ namespace OpenLoco::Ui::Windows::Vehicle
}
auto viewPos = Map::gameToScreen(*nodeLoc, res.second->getRotation());
auto uiPos = res.second->mapToUi(viewPos);
auto uiPos = res.second->viewportToScreen(viewPos);
auto distance = Math::Vector::manhattanDistance(uiPos, Point{ x, y });
if (distance < bestDistance)
{
@ -3611,7 +3611,7 @@ namespace OpenLoco::Ui::Windows::Vehicle
{
auto potentialLoc = roadFirstTile + moveInfo.loc;
auto viewPos = Map::gameToScreen(potentialLoc, viewport.getRotation());
auto uiPos = viewport.mapToUi(viewPos);
auto uiPos = viewport.viewportToScreen(viewPos);
auto distance = Math::Vector::manhattanDistance(uiPos, cursorLoc);
if (distance < bestDistance)
{
@ -3717,7 +3717,7 @@ namespace OpenLoco::Ui::Windows::Vehicle
{
auto potentialLoc = trackFirstTile + moveInfo.loc;
auto viewPos = Map::gameToScreen(potentialLoc, viewport.getRotation());
auto uiPos = viewport.mapToUi(viewPos);
auto uiPos = viewport.viewportToScreen(viewPos);
auto distance = Math::Vector::manhattanDistance(uiPos, cursorLoc);
if (distance < bestDistance)
{