Merge pull request #1294 from mildmongrel/tablezone_refactor_001

tablezone refactor and cleanup
This commit is contained in:
Zach 2015-07-25 22:45:06 -07:00
commit ac4c745521
3 changed files with 164 additions and 83 deletions

View file

@ -2389,6 +2389,7 @@ void Player::setMirrored(bool _mirrored)
void Player::processSceneSizeChange(int newPlayerWidth)
{
// Extend table (and hand, if horizontal) to accomodate the new player width.
qreal tableWidth = newPlayerWidth - CARD_HEIGHT - 15 - counterAreaWidth - stack->boundingRect().width();
if (!settingsCache->getHorizontalHand())
tableWidth -= hand->boundingRect().width();

View file

@ -31,9 +31,9 @@ TableZone::TableZone(Player *_p, QGraphicsItem *parent)
updateBgPixmap();
height = 2 * BOX_LINE_WIDTH + TABLEROWS * (CARD_HEIGHT + 20) + 2 * PADDING_Y;
width = MIN_WIDTH + 2 * MARGIN_X + 2 * BOX_LINE_WIDTH;
currentMinimumWidth = MIN_WIDTH;
height = MARGIN_TOP + MARGIN_BOTTOM + TABLEROWS * CARD_HEIGHT + (TABLEROWS-1) * PADDING_Y;
width = MIN_WIDTH;
currentMinimumWidth = width;
setCacheMode(DeviceCoordinateCache);
#if QT_VERSION < 0x050000
@ -115,10 +115,12 @@ void TableZone::paintZoneOutline(QPainter *painter) {
@painter QPainter object
*/
void TableZone::paintLandDivider(QPainter *painter){
painter->setPen(QColor(255, 255, 255, 40));
qreal separatorY = 2 * (CARD_HEIGHT + 20 + PADDING_Y) + BOX_LINE_WIDTH - PADDING_Y / 2;
// Place the line 2 grid heights down then back it off just enough to allow
// some space between a 3-card stack and the land area.
qreal separatorY = MARGIN_TOP + 2 * (CARD_HEIGHT + PADDING_Y) - STACKED_CARD_OFFSET_Y / 2;
if (isInverted())
separatorY = height - separatorY;
painter->setPen(QColor(255, 255, 255, 40));
painter->drawLine(QPointF(0, separatorY), QPointF(width, separatorY));
}
@ -165,30 +167,9 @@ void TableZone::reorganizeCards()
{
QList<ArrowItem *> arrowsToUpdate;
// Calculate table grid distortion so that the mapping functions work properly
QMap<int, int> gridPointStackCount;
for (int i = 0; i < cards.size(); ++i) {
const QPoint &gridPoint = cards[i]->getGridPos();
if (gridPoint.x() == -1)
continue;
const int key = gridPoint.x() / 3 + gridPoint.y() * 1000;
gridPointStackCount.insert(key, gridPointStackCount.value(key, 0) + 1);
}
gridPointWidth.clear();
for (int i = 0; i < cards.size(); ++i) {
const QPoint &gridPoint = cards[i]->getGridPos();
if (gridPoint.x() == -1)
continue;
const int key = gridPoint.x() / 3 + gridPoint.y() * 1000;
const int stackCount = gridPointStackCount.value(key, 0);
if (stackCount == 1)
gridPointWidth.insert(key, CARD_WIDTH * (1 + cards[i]->getAttachedCards().size() / 3.0));
else
gridPointWidth.insert(key, CARD_WIDTH * (1 + (stackCount - 1) / 3.0));
}
// Calculate card stack widths so mapping functions work properly
computeCardStackWidths();
for (int i = 0; i < cards.size(); ++i) {
QPoint gridPoint = cards[i]->getGridPos();
if (gridPoint.x() == -1)
@ -199,7 +180,7 @@ void TableZone::reorganizeCards()
qreal y = mapPoint.y();
int numberAttachedCards = cards[i]->getAttachedCards().size();
qreal actualX = x + numberAttachedCards * CARD_WIDTH / 3.0;
qreal actualX = x + numberAttachedCards * STACKED_CARD_OFFSET_X;
qreal actualY = y;
if (numberAttachedCards)
actualY += 15;
@ -212,7 +193,7 @@ void TableZone::reorganizeCards()
while (attachedCardIterator.hasNext()) {
++j;
CardItem *attachedCard = attachedCardIterator.next();
qreal childX = actualX - j * CARD_WIDTH / 3.0;
qreal childX = actualX - j * STACKED_CARD_OFFSET_X;
qreal childY = y + 5;
attachedCard->setPos(childX, childY);
attachedCard->setRealZValue((childY + CARD_HEIGHT) * 100000 + (childX + 1) * 100);
@ -271,13 +252,19 @@ CardItem *TableZone::takeCard(int position, int cardId, bool canResize)
void TableZone::resizeToContents()
{
int xMax = 0;
// Find rightmost card position, which includes the left margin amount.
for (int i = 0; i < cards.size(); ++i)
if (cards[i]->pos().x() > xMax)
xMax = (int) cards[i]->pos().x();
xMax += 2 * CARD_WIDTH;
if (xMax < MIN_WIDTH)
xMax = MIN_WIDTH;
currentMinimumWidth = xMax + 2 * MARGIN_X + 2 * BOX_LINE_WIDTH;
// Minimum width is the rightmost card position plus enough room for
// another card with padding, then margin.
currentMinimumWidth = xMax + (2 * CARD_WIDTH) + PADDING_X + MARGIN_RIGHT;
if (currentMinimumWidth < MIN_WIDTH)
currentMinimumWidth = MIN_WIDTH;
if (currentMinimumWidth != width) {
prepareGeometryChange();
width = currentMinimumWidth;
@ -294,6 +281,7 @@ CardItem *TableZone::getCardFromGrid(const QPoint &gridPoint) const
return 0;
}
CardItem *TableZone::getCardFromCoords(const QPointF &point) const
{
QPoint gridPoint = mapToGrid(point);
@ -301,57 +289,110 @@ CardItem *TableZone::getCardFromCoords(const QPointF &point) const
}
void TableZone::computeCardStackWidths()
{
// Each card stack is three grid points worth of card locations.
// First pass: compute the number of cards at each card stack.
QMap<int, int> cardStackCount;
for (int i = 0; i < cards.size(); ++i) {
const QPoint &gridPoint = cards[i]->getGridPos();
if (gridPoint.x() == -1)
continue;
const int key = getCardStackMapKey(gridPoint.x() / 3, gridPoint.y());
cardStackCount.insert(key, cardStackCount.value(key, 0) + 1);
}
// Second pass: compute the width at each card stack.
cardStackWidth.clear();
for (int i = 0; i < cards.size(); ++i) {
const QPoint &gridPoint = cards[i]->getGridPos();
if (gridPoint.x() == -1)
continue;
const int key = getCardStackMapKey(gridPoint.x() / 3, gridPoint.y());
const int stackCount = cardStackCount.value(key, 0);
if (stackCount == 1)
cardStackWidth.insert(key, CARD_WIDTH + cards[i]->getAttachedCards().size() * STACKED_CARD_OFFSET_X);
else
cardStackWidth.insert(key, CARD_WIDTH + (stackCount - 1) * STACKED_CARD_OFFSET_X);
}
}
QPointF TableZone::mapFromGrid(QPoint gridPoint) const
{
qreal x, y;
x = MARGIN_X + (gridPoint.x() % 3) * CARD_WIDTH / 3.0;
// Start with margin plus stacked card offset
x = MARGIN_LEFT + (gridPoint.x() % 3) * STACKED_CARD_OFFSET_X;
// Add in width of card stack plus padding for each column
for (int i = 0; i < gridPoint.x() / 3; ++i)
x += gridPointWidth.value(gridPoint.y() * 1000 + i, CARD_WIDTH) + PADDING_X;
{
const int key = getCardStackMapKey(i, gridPoint.y());
x += cardStackWidth.value(key, CARD_WIDTH) + PADDING_X;
}
if (isInverted())
gridPoint.setY(2 - gridPoint.y());
gridPoint.setY(TABLEROWS - 1 - gridPoint.y());
y = BOX_LINE_WIDTH + gridPoint.y() * (CARD_HEIGHT + PADDING_Y + 20) + (gridPoint.x() % TABLEROWS) * 10;
/*
if (isInverted())
y = height - CARD_HEIGHT - y;
*/
// Start with margin plus stacked card offset
y = MARGIN_TOP + (gridPoint.x() % 3) * STACKED_CARD_OFFSET_Y;
// Add in card size and padding for each row
for (int i = 0; i < gridPoint.y(); ++i)
y += CARD_HEIGHT + PADDING_Y;
return QPointF(x, y);
}
QPoint TableZone::mapToGrid(const QPointF &mapPoint) const
{
qreal x = mapPoint.x() - MARGIN_X;
qreal y = mapPoint.y();
/* if (isInverted())
y = height - y;
*/ y -= BOX_LINE_WIDTH;
if (x < 0)
x = 0;
else if (x > width - CARD_WIDTH - MARGIN_X)
x = width - CARD_WIDTH - MARGIN_X;
if (y < 0)
y = 0;
else if (y > height - CARD_HEIGHT)
y = height - CARD_HEIGHT;
int resultY = round(y / (CARD_HEIGHT + PADDING_Y + 20));
if (isInverted())
resultY = TABLEROWS - 1 - resultY;
// Begin by calculating the y-coordinate of the grid space, which will be
// used for the x-coordinate.
int baseX = -1;
qreal oldTempX = 0, tempX = 0;
do {
++baseX;
oldTempX = tempX;
tempX += gridPointWidth.value(resultY * 1000 + baseX, CARD_WIDTH) + PADDING_X;
} while (tempX < x + 1);
qreal xdiff = x - oldTempX;
int resultX = baseX * 3 + qMin((int) floor(xdiff * 3 / CARD_WIDTH), 2);
return QPoint(resultX, resultY);
// Offset point by the margin amount to reference point within grid area.
int y = mapPoint.y() - MARGIN_TOP;
// Below calculation effectively rounds to the nearest grid point.
const int gridPointHeight = CARD_HEIGHT + PADDING_Y;
int gridPointY = (y + gridPointHeight / 2) / gridPointHeight;
gridPointY = clampValidTableRow(gridPointY);
if (isInverted())
gridPointY = TABLEROWS - 1 - gridPointY;
// Calculating the x-coordinate of the grid space requires adding up the
// widths of each card stack along the row.
// Offset point by the margin amount to reference point within grid area.
int x = mapPoint.x() - MARGIN_LEFT;
// Maximum value is a card width from the right margin, referenced to the
// grid area.
const int xMax = width - MARGIN_LEFT - MARGIN_RIGHT - CARD_WIDTH;
int xStack = 0;
int xNextStack = 0;
int nextStackCol = 0;
while ((xNextStack <= x) && (xNextStack <= xMax)) {
xStack = xNextStack;
const int key = getCardStackMapKey(nextStackCol, gridPointY);
xNextStack += cardStackWidth.value(key, CARD_WIDTH) + PADDING_X;
nextStackCol++;
}
int stackCol = qMax(nextStackCol - 1, 0);
// Have the stack column, need to refine to the grid column. Take the
// difference between the point and the stack point and divide by stacked
// card offsets.
int xDiff = x - xStack;
int gridPointX = stackCol * 3 + qMin(xDiff / STACKED_CARD_OFFSET_X, 2);
return QPoint(gridPointX, gridPointY);
}

View file

@ -20,13 +20,34 @@ signals:
void sizeChanged();
private:
static const int BOX_LINE_WIDTH = 10;
static const int PADDING_X = 35;
static const int PADDING_Y = 10;
static const int MARGIN_X = 20;
static const int MIN_WIDTH = 10 * CARD_WIDTH / 2;
static const int TABLEROWS = 3;
/*
Margins between table edges and cards, paddings between cards
*/
static const int MARGIN_LEFT = 20;
static const int MARGIN_RIGHT = 15;
static const int MARGIN_TOP = 10;
static const int MARGIN_BOTTOM = 30;
static const int PADDING_X = 35;
static const int PADDING_Y = 30;
/*
Minimum width of the table zone including margins.
*/
static const int MIN_WIDTH = MARGIN_LEFT + (5 * CARD_WIDTH) + MARGIN_RIGHT;
/*
Offset sizes when cards are stacked on each other in the grid
*/
static const int STACKED_CARD_OFFSET_X = CARD_WIDTH / 3;
static const int STACKED_CARD_OFFSET_Y = PADDING_Y / 3;
/*
Width of the box line drawn in the margin around the active player's area
*/
static const int BOX_LINE_WIDTH = 10;
/*
Default background color, inactive mask and boarder gradient
*/
@ -38,11 +59,15 @@ private:
/*
Size and shape variables
*/
QMap<int, int> gridPointWidth;
int width;
int height;
int currentMinimumWidth;
/*
Internal cache for widths of stacks of cards by row and column.
*/
QMap<int, int> cardStackWidth;
/*
Holds any custom background image for the TableZone
*/
@ -114,11 +139,9 @@ public:
*/
CardItem *getCardFromCoords(const QPointF &point) const;
QPointF mapFromGrid(QPoint gridPoint) const;
QPoint mapToGrid(const QPointF &mapPoint) const;
QPointF closestGridPoint(const QPointF &point);
int clampValidTableRow(const int row);
static int clampValidTableRow(const int row);
/**
Removes a card from view.
@ -137,7 +160,7 @@ public:
void resizeToContents();
int getMinimumWidth() const { return currentMinimumWidth; }
void setWidth(qreal _width){ prepareGeometryChange(); width = _width;};
void setWidth(qreal _width) { prepareGeometryChange(); width = _width; }
qreal getWidth() const { return width; }
void setActive(bool _active) { active = _active; update(); }
@ -147,6 +170,22 @@ protected:
private:
void paintZoneOutline(QPainter *painter);
void paintLandDivider(QPainter *painter);
/*
Calculates card stack widths so mapping functions work properly
*/
void computeCardStackWidths();
/*
Mapping functions for points to/from gridpoints.
*/
QPointF mapFromGrid(QPoint gridPoint) const;
QPoint mapToGrid(const QPointF &mapPoint) const;
/*
Helper function to create a single key from a card stack location.
*/
int getCardStackMapKey (int x, int y) const { return x + (y * 1000); }
};
#endif