Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add options to customize "MatchOutsideMap" behavior #2141

Merged
merged 6 commits into from Jun 20, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
64 changes: 57 additions & 7 deletions src/tiled/automapper.cpp
Expand Up @@ -42,6 +42,12 @@

using namespace Tiled;

// Should i leave this function here?
inline static int wrap(int value, int bound)
{
JoaoBaptMG marked this conversation as resolved.
Show resolved Hide resolved
return (value % bound + bound) % bound;
}

bjorn marked this conversation as resolved.
Show resolved Hide resolved
/*
* About the order of the methods in this file.
* The Automapper class has 3 bigger public functions, that is
Expand Down Expand Up @@ -108,6 +114,16 @@ bool AutoMapper::setupRuleMapProperties()
mOptions.matchOutsideMap = value.toBool();
continue;
}
} else if (name.compare(QLatin1String("OverflowBorder"), Qt::CaseInsensitive) == 0) {
if (value.canConvert(QVariant::Bool)) {
mOptions.overflowBorder = value.toBool();
continue;
}
} else if (name.compare(QLatin1String("WrapBorder"), Qt::CaseInsensitive) == 0) {
if (value.canConvert(QVariant::Bool)) {
mOptions.wrapBorder = value.toBool();
continue;
}
} else if (name.compare(QLatin1String("AutomappingRadius"), Qt::CaseInsensitive) == 0) {
if (value.canConvert(QVariant::Int)) {
mOptions.autoMappingRadius = value.toInt();
Expand All @@ -124,6 +140,17 @@ bool AutoMapper::setupRuleMapProperties()
"Ignoring this property.")
.arg(mRulePath, name, value.toString()) + QLatin1Char('\n');
}

// OverflowBorder and WrapBorder make no sense for infinite maps
if (mMapWork->infinite()) {
mOptions.overflowBorder = false;
mOptions.wrapBorder = false;
}

// Each of the border options imply MatchOutsideMap
if (mOptions.overflowBorder || mOptions.wrapBorder)
mOptions.matchOutsideMap = true;

bjorn marked this conversation as resolved.
Show resolved Hide resolved
return true;
}

Expand Down Expand Up @@ -627,12 +654,24 @@ static bool layerMatchesConditions(const TileLayer &setLayer,
#endif
for (int x = rect.left(); x <= rect.right(); ++x) {
for (int y = rect.top(); y <= rect.bottom(); ++y) {
int xd = x + offset.x();
int yd = y + offset.y();
bjorn marked this conversation as resolved.
Show resolved Hide resolved

if (!options.matchOutsideMap &&
!setLayer.contains(x + offset.x(), y + offset.y()))
!setLayer.contains(xd, yd))
return false;

const Cell &setCell = setLayer.cellAt(x + offset.x(),
y + offset.y());
// Those two options are guaranteed to be false if the map is infinite,
// so no "invalid" width/height accessing here.
if (options.wrapBorder) {
xd = wrap(xd, setLayer.width());
yd = wrap(yd, setLayer.height());
} else if (options.overflowBorder) {
xd = qBound(0, xd, setLayer.width() - 1);
yd = qBound(0, yd, setLayer.height() - 1);
bjorn marked this conversation as resolved.
Show resolved Hide resolved
}

const Cell &setCell = setLayer.cellAt(xd, yd);

// First check listNo. If any tile matches there, we can
// immediately know there is no match.
Expand Down Expand Up @@ -836,11 +875,14 @@ void AutoMapper::copyTileRegion(const TileLayer *srcLayer, int srcX, int srcY,
int endX = dstX + width;
int endY = dstY + height;

if (!mMapWork->infinite()) {
int dwidth = dstLayer->width();
int dheight = dstLayer->height();

if (!mOptions.wrapBorder && !mMapWork->infinite()) {
startX = qMax(0, startX);
startY = qMax(0, startY);
endX = qMin(dstLayer->width(), endX);
endY = qMin(dstLayer->height(), endY);
endX = qMin(dwidth, endX);
endY = qMin(dheight, endY);
}

const int offsetX = srcX - dstX;
Expand All @@ -851,7 +893,15 @@ void AutoMapper::copyTileRegion(const TileLayer *srcLayer, int srcX, int srcY,
const Cell &cell = srcLayer->cellAt(x + offsetX, y + offsetY);
if (!cell.isEmpty()) {
// this is without graphics update, it's done afterwards for all
dstLayer->setCell(x, y, cell);
int xd = x;
int yd = y;

// WrapBorder is only true on finite maps
if (mOptions.wrapBorder) {
xd = wrap(xd, dwidth);
yd = wrap(yd, dheight);
}
dstLayer->setCell(xd, yd, cell);
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions src/tiled/automapper.h
Expand Up @@ -95,6 +95,18 @@ class AutoMapper : public QObject
*/
bool matchOutsideMap = true;

/**
* If "matchOutsideMap" is true, treat the out-of-bounds tiles as if they
* were the nearest inbound tile possible
*/
bool overflowBorder = false;

/**
* If "matchOutsideMap" is true, wrap the map in the edges to apply the
* automapping rules
*/
bool wrapBorder = false;

/**
* Determines if a rule is allowed to overlap itself.
*/
Expand Down