use WorldCoordinates in ArenaView too
This commit is contained in:
@@ -1,21 +1,61 @@
|
||||
#include "WorldCoordinates.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
WorldCoordinates::WorldCoordinates(QSize widgetSize_px, int worldHeight_tiles,
|
||||
float viewCenterX_tiles)
|
||||
: m_tilePx(1.0f)
|
||||
, m_viewportWidthTiles(0.0f)
|
||||
, m_viewLeftTiles(0.0f)
|
||||
, m_worldHeightTiles(worldHeight_tiles)
|
||||
namespace
|
||||
{
|
||||
// A zero-height widget, a not-yet-shown widget, or a degenerate world size
|
||||
// would otherwise make every conversion divide by zero.
|
||||
float sanitizeTilePx(float tilePx)
|
||||
{
|
||||
return tilePx > 0.0f ? tilePx : 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
WorldCoordinates WorldCoordinates::scrolling(QSize widgetSize_px,
|
||||
int worldHeight_tiles,
|
||||
float viewCenterX_tiles)
|
||||
{
|
||||
float tilePx = 1.0f;
|
||||
if (worldHeight_tiles > 0)
|
||||
{
|
||||
m_tilePx = static_cast<float>(widgetSize_px.height())
|
||||
/ static_cast<float>(worldHeight_tiles);
|
||||
tilePx = static_cast<float>(widgetSize_px.height())
|
||||
/ static_cast<float>(worldHeight_tiles);
|
||||
}
|
||||
m_viewportWidthTiles = static_cast<float>(widgetSize_px.width()) / m_tilePx;
|
||||
m_viewLeftTiles = viewCenterX_tiles - m_viewportWidthTiles / 2.0f;
|
||||
tilePx = sanitizeTilePx(tilePx);
|
||||
|
||||
const float viewportWidthTiles = static_cast<float>(widgetSize_px.width()) / tilePx;
|
||||
return WorldCoordinates(tilePx, static_cast<float>(widgetSize_px.width()),
|
||||
viewCenterX_tiles - viewportWidthTiles / 2.0f,
|
||||
worldHeight_tiles);
|
||||
}
|
||||
|
||||
WorldCoordinates WorldCoordinates::fitToWorld(QSize widgetSize_px,
|
||||
int worldWidth_tiles,
|
||||
int worldHeight_tiles)
|
||||
{
|
||||
float tilePx = 1.0f;
|
||||
if (worldWidth_tiles > 0 && worldHeight_tiles > 0)
|
||||
{
|
||||
// The tighter of the two fits, so the whole world stays on screen.
|
||||
tilePx = std::min(
|
||||
static_cast<float>(widgetSize_px.height()) / static_cast<float>(worldHeight_tiles),
|
||||
static_cast<float>(widgetSize_px.width()) / static_cast<float>(worldWidth_tiles));
|
||||
}
|
||||
tilePx = sanitizeTilePx(tilePx);
|
||||
|
||||
return WorldCoordinates(tilePx, static_cast<float>(widgetSize_px.width()),
|
||||
0.0f, worldHeight_tiles);
|
||||
}
|
||||
|
||||
WorldCoordinates::WorldCoordinates(float tilePx, float viewportWidth_px,
|
||||
float viewLeft_tiles, int worldHeight_tiles)
|
||||
: m_tilePx(tilePx)
|
||||
, m_viewportWidthTiles(viewportWidth_px / tilePx)
|
||||
, m_viewLeftTiles(viewLeft_tiles)
|
||||
, m_worldHeightTiles(worldHeight_tiles)
|
||||
{
|
||||
}
|
||||
|
||||
float WorldCoordinates::getTilePx() const
|
||||
|
||||
@@ -8,28 +8,37 @@
|
||||
#include <QVector2D>
|
||||
|
||||
// Immutable snapshot of the world <-> widget transform for one viewport state
|
||||
// (REQ-GW-COORDS, REQ-GW-TILE-SIZE). Tiles are square and sized so the world
|
||||
// height exactly fills the viewport height; there is no zoom (REQ-UI-NO-ZOOM),
|
||||
// so the only free parameter is the horizontal scroll position.
|
||||
// (REQ-GW-COORDS). Tiles are square; the two factories below differ only in how
|
||||
// the tile size and the left edge are derived, and everything downstream of that
|
||||
// is shared.
|
||||
//
|
||||
// The transform is a value: it is constructed from the viewport size, the world
|
||||
// height, and the view center, and never observes them again. A caller therefore
|
||||
// builds one per frame (or per event) rather than holding one across a resize or
|
||||
// a scroll, which would silently go stale.
|
||||
// The transform is a value: it is constructed from the viewport size and the view
|
||||
// state, and never observes them again. A caller therefore builds one per frame
|
||||
// (or per event) rather than holding one across a resize or a scroll, which would
|
||||
// silently go stale.
|
||||
class WorldCoordinates
|
||||
{
|
||||
public:
|
||||
// `viewCenterX_tiles` is the world X at the center of the viewport, matching
|
||||
// how the scroll position is stored and clamped (REQ-GW-SCROLL-LIMIT).
|
||||
WorldCoordinates(QSize widgetSize_px, int worldHeight_tiles,
|
||||
float viewCenterX_tiles);
|
||||
// The scrolling game world: the tile size is whatever makes the world height
|
||||
// exactly fill the viewport height (REQ-GW-TILE-SIZE, no zoom per
|
||||
// REQ-UI-NO-ZOOM), and the view pans horizontally. `viewCenterX_tiles` is the
|
||||
// world X at the center of the viewport, matching how the scroll position is
|
||||
// stored and clamped (REQ-GW-SCROLL-LIMIT).
|
||||
static WorldCoordinates scrolling(QSize widgetSize_px, int worldHeight_tiles,
|
||||
float viewCenterX_tiles);
|
||||
|
||||
// Side length of one tile in pixels. Degenerate world heights yield 1.0 so
|
||||
// callers never divide by zero.
|
||||
// A whole world shown at once with no scrolling, as the balancing tool's arena
|
||||
// does: the tile size is whichever axis is the tighter fit, so nothing is cut
|
||||
// off, and the world origin sits at the widget's top-left. A viewport wider
|
||||
// than the fitted world leaves empty space to the right rather than centering.
|
||||
static WorldCoordinates fitToWorld(QSize widgetSize_px, int worldWidth_tiles,
|
||||
int worldHeight_tiles);
|
||||
|
||||
// Side length of one tile in pixels. Always positive: a degenerate world or
|
||||
// viewport size falls back to 1.0 so no conversion below divides by zero.
|
||||
float getTilePx() const;
|
||||
float getViewportWidthTiles() const;
|
||||
// World X (tiles) at the left edge of the viewport, derived from the view
|
||||
// center the constructor was given.
|
||||
// World X (tiles) at the left edge of the viewport.
|
||||
float getViewLeftTiles() const;
|
||||
|
||||
QPointF worldToWidget(QVector2D worldPos) const;
|
||||
@@ -44,6 +53,9 @@ public:
|
||||
QRect getViewportRect() const;
|
||||
|
||||
private:
|
||||
WorldCoordinates(float tilePx, float viewportWidth_px, float viewLeft_tiles,
|
||||
int worldHeight_tiles);
|
||||
|
||||
float m_tilePx;
|
||||
float m_viewportWidthTiles;
|
||||
float m_viewLeftTiles;
|
||||
|
||||
Reference in New Issue
Block a user