Skip to content

Commit

Permalink
Added Repeat X/Y properties to Image Layers (#3205)
Browse files Browse the repository at this point in the history
Introduce the boolean properties "Repeat X" and "Repeat Y" to Image
Layers.

The YY plugin will export these properties accordingly as "Horizontal
Tile" and "Vertical Tile". For backwards compatibility however, the
respective custom properties "htiled" and "vtiled" take precedence over
the built-in ones.

Closes #266

Co-authored-by: Thorbjørn Lindeijer <bjorn@lindeijer.nl>
  • Loading branch information
krukai and bjorn committed Dec 13, 2021
1 parent 0bc64b3 commit 0e7f813
Show file tree
Hide file tree
Showing 23 changed files with 397 additions and 181 deletions.
6 changes: 3 additions & 3 deletions docs/manual/export-yy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -189,15 +189,15 @@ The following custom properties can be set on image layers to affect the
exported background layers:

* string ``sprite`` (default: based on image filename)
* bool ``htiled`` (default: false)
* bool ``vtiled`` (default: false)
* bool ``htiled`` (default: value of Repeat X property)
* bool ``vtiled`` (default: value of Repeat Y property)
* bool ``stretch`` (default: false)
* float ``hspeed`` (default: 0.0)
* float ``vspeed`` (default: 0.0)
* float ``animationFPS`` (default: 15.0)
* int ``animationSpeedtype`` (default: 0)

Even though the custom properties such as ``htiled`` and ``vtiled`` have no
Even though the custom properties such as ``hspeed`` and ``vspeed`` have no
visual effect inside Tiled you will see the effect in the exported room inside
GameMaker.

Expand Down
12 changes: 8 additions & 4 deletions docs/manual/layers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,15 @@ Image Layers
~~~~~~~~~~~~

Image layers provide a way to quickly include a single image as
foreground or background of your map. They are currently not so useful,
because if you instead add the image as a Tileset and place it as a :ref:`Tile Object <insert-tile-tool>`,
you gain the ability to freely scale and rotate the image.
foreground or background of your map. They currently have limited
functionality and you may consider adding the image as a Tileset instead and
place it as a :ref:`Tile Object <insert-tile-tool>`. This way, you gain the
ability to freely scale and rotate the image.

The only advantage of using an image layer is that it avoids selecting /
However, image layers can be repeated along the respective axes through their
*Repeat X* and *Repeat Y* properties.

The other advantage of using an image layer is that it avoids selecting /
dragging the image while using the Select Objects tool. However, since Tiled
1.1 this can also be achieved by locking the object layer containing the tile
object you'd like to avoid interacting with.
Expand Down
8 changes: 8 additions & 0 deletions docs/reference/json-map-format.rst
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ Layer
parallaxx, double, "Horizontal :ref:`parallax factor <parallax-factor>` for this layer (default: 1). (since Tiled 1.5)"
parallaxy, double, "Vertical :ref:`parallax factor <parallax-factor>` for this layer (default: 1). (since Tiled 1.5)"
properties, array, "Array of :ref:`Properties <json-property>`"
repeatx, bool, "Whether the image drawn by this layer is repeated along the X axis. ``imagelayer`` only. (since Tiled 1.8)"
repeaty, bool, "Whether the image drawn by this layer is repeated along the Y axis. ``imagelayer`` only. (since Tiled 1.8)"
startx, int, "X coordinate where layer content starts (for infinite maps)"
starty, int, "Y coordinate where layer content starts (for infinite maps)"
tintcolor, string, "Hex-formatted :ref:`tint color <tint-color>` (#RRGGBB or #AARRGGBB) that is multiplied with any graphics drawn by this layer or any child layers (optional)."
Expand Down Expand Up @@ -750,6 +752,12 @@ A point on a polygon or a polyline, relative to the position of the object.
Changelog
---------

Tiled 1.8
~~~~~~~~~

* Added ``repeatx`` and ``repeaty`` properties to :ref:`json-layer` (applies
only to image layers at the moment).

Tiled 1.7
~~~~~~~~~

Expand Down
6 changes: 6 additions & 0 deletions docs/reference/tmx-changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ TMX Changelog
Below are described the changes/additions that were made to the
:doc:`tmx-map-format` for recent versions of Tiled.

Tiled 1.8
---------

- Added ``repeatx`` and ``repeaty`` attributes to the :ref:`tmx-imagelayer`
element.

Tiled 1.7
---------

Expand Down
2 changes: 2 additions & 0 deletions docs/reference/tmx-map-format.rst
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,8 @@ of the object.
1)
- **visible:** Whether the layer is shown (1) or hidden (0). (defaults to 1)
- **tintcolor:** A color that is multiplied with the image drawn by this layer in ``#AARRGGBB`` or ``#RRGGBB`` format (optional).
- **repeatx:** Whether the image drawn by this layer is repeated along the X axis. (since Tiled 1.8)
- **repeaty:** Whether the image drawn by this layer is repeated along the Y axis. (since Tiled 1.8)

A layer consisting of a single image.

Expand Down
10 changes: 10 additions & 0 deletions docs/scripting-doc/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1394,6 +1394,16 @@ declare class ImageLayer extends Layer {
* Reference to the image rendered by this layer.
*/
imageSource: string;

/**
* Whether the image rendered by this layer repeats along the X axis.
*/
repeatX: boolean;

/**
* Whether the image rendered by this layer repeats along the Y axis.
*/
repeatY: boolean;

/**
* Constructs a new image layer.
Expand Down
22 changes: 22 additions & 0 deletions src/libtiled/imagelayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,26 @@ class TILEDSHARED_EXPORT ImageLayer : public Layer
*/
bool isEmpty() const override;

/**
* Returns true if the image of this layer repeats along the X axis.
*/
bool repeatX() const { return mRepeatX; }

/**
* Returns true if the image of this layer repeats along the Y axis.
*/
bool repeatY() const { return mRepeatY; }

/**
* Sets whether the image of this layer repeats along the X axis.
*/
void setRepeatX(bool repeatX) { mRepeatX = repeatX; }

/**
* Sets whether the image of this layer repeats along the Y axis.
*/
void setRepeatY(bool repeatY) { mRepeatY = repeatY; }

ImageLayer *clone() const override;

protected:
Expand All @@ -123,6 +143,8 @@ class TILEDSHARED_EXPORT ImageLayer : public Layer
QUrl mImageSource;
QColor mTransparentColor;
QPixmap mImage;
bool mRepeatX = false;
bool mRepeatY = false;
};

} // namespace Tiled
3 changes: 3 additions & 0 deletions src/libtiled/mapreader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1142,6 +1142,9 @@ std::unique_ptr<ImageLayer> MapReaderPrivate::readImageLayer()
auto imageLayer = std::make_unique<ImageLayer>(name, x, y);
readLayerAttributes(*imageLayer, atts);

imageLayer->setRepeatX(atts.value(QLatin1String("repeatx")).toInt());
imageLayer->setRepeatY(atts.value(QLatin1String("repeaty")).toInt());

// Image layer pixel position moved from x/y to offsetx/offsety for
// consistency with other layers. This is here for backwards compatibility.
if (!atts.hasAttribute(QLatin1String("offsetx")))
Expand Down
24 changes: 20 additions & 4 deletions src/libtiled/maprenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,18 @@ MapRenderer::~MapRenderer()

QRectF MapRenderer::boundingRect(const ImageLayer *imageLayer) const
{
return QRectF(QPointF(), imageLayer->image().size());
QRectF bounds = QRectF(QPointF(), imageLayer->image().size());

if (imageLayer->repeatX()) {
bounds.setLeft(INT_MIN / 512);
bounds.setRight(INT_MAX / 256);
}
if (imageLayer->repeatY()) {
bounds.setTop(INT_MIN / 512);
bounds.setBottom(INT_MAX / 256);
}

return bounds;
}

QPainterPath MapRenderer::pointShape(const QPointF &position) const
Expand Down Expand Up @@ -113,9 +124,14 @@ void MapRenderer::drawImageLayer(QPainter *painter,
const ImageLayer *imageLayer,
const QRectF &exposed) const
{
Q_UNUSED(exposed)

painter->drawPixmap(QPointF(), tinted(imageLayer->image(), imageLayer->effectiveTintColor()));
painter->save();
painter->setBrush(tinted(imageLayer->image(), imageLayer->effectiveTintColor()));
painter->setPen(Qt::NoPen);
if (exposed.isNull())
painter->drawRect(boundingRect(imageLayer));
else
painter->drawRect(boundingRect(imageLayer) & exposed);
painter->restore();
}

void MapRenderer::drawPointObject(QPainter *painter, const QColor &color) const
Expand Down
5 changes: 5 additions & 0 deletions src/libtiled/maptovariantconverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,11 @@ QVariant MapToVariantConverter::toVariant(const ImageLayer &imageLayer) const
if (transColor.isValid())
imageLayerVariant[QStringLiteral("transparentcolor")] = transColor.name();

if (imageLayer.repeatX())
imageLayerVariant[QStringLiteral("repeatx")] = imageLayer.repeatX();
if (imageLayer.repeatY())
imageLayerVariant[QStringLiteral("repeaty")] = imageLayer.repeatY();

return imageLayerVariant;
}

Expand Down
5 changes: 5 additions & 0 deletions src/libtiled/mapwriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -860,6 +860,11 @@ void MapWriterPrivate::writeImageLayer(QXmlStreamWriter &w,
w.writeStartElement(QStringLiteral("imagelayer"));
writeLayerAttributes(w, imageLayer);

if (imageLayer.repeatX())
w.writeAttribute(QStringLiteral("repeatx"), QString::number(imageLayer.repeatX()));
if (imageLayer.repeatY())
w.writeAttribute(QStringLiteral("repeaty"), QString::number(imageLayer.repeatY()));

// Write the image element
const QUrl &imageSource = imageLayer.imageSource();
if (!imageSource.isEmpty()) {
Expand Down
3 changes: 3 additions & 0 deletions src/plugins/lua/luaplugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,9 @@ void LuaWriter::writeImageLayer(const ImageLayer *imageLayer)
}

writeLayerProperties(imageLayer);
mWriter.writeKeyAndValue("repeatx", imageLayer->repeatX());
mWriter.writeKeyAndValue("repeaty", imageLayer->repeatY());

writeProperties(imageLayer->properties());

mWriter.writeEndTable();
Expand Down
6 changes: 4 additions & 2 deletions src/plugins/yy/yyplugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1164,8 +1164,10 @@ static std::unique_ptr<GMRLayer> processImageLayer(const ImageLayer *imageLayer)
gmrBackgroundLayer->x = layerOffset.x();
gmrBackgroundLayer->y = layerOffset.y();

gmrBackgroundLayer->htiled = optionalProperty(imageLayer, "htiled", gmrBackgroundLayer->htiled);
gmrBackgroundLayer->vtiled = optionalProperty(imageLayer, "vtiled", gmrBackgroundLayer->vtiled);
// Give custom properties priority to ensure backwards compatibility
gmrBackgroundLayer->htiled = optionalProperty(imageLayer, "htiled", imageLayer->repeatX());
gmrBackgroundLayer->vtiled = optionalProperty(imageLayer, "vtiled", imageLayer->repeatY());

gmrBackgroundLayer->hspeed = optionalProperty(imageLayer, "hspeed", gmrBackgroundLayer->hspeed);
gmrBackgroundLayer->vspeed = optionalProperty(imageLayer, "vspeed", gmrBackgroundLayer->vspeed);
gmrBackgroundLayer->stretch = optionalProperty(imageLayer, "stretch", gmrBackgroundLayer->stretch);
Expand Down
72 changes: 0 additions & 72 deletions src/tiled/changeimagelayerproperties.cpp

This file was deleted.

63 changes: 0 additions & 63 deletions src/tiled/changeimagelayerproperties.h

This file was deleted.

0 comments on commit 0e7f813

Please sign in to comment.