From 904e8bc84e6ec3e99664d4cd5c1d8360ef1bcd0c Mon Sep 17 00:00:00 2001 From: Benjamin Trotter Date: Sun, 28 May 2017 11:29:00 -0700 Subject: [PATCH 01/21] Created WangSet class, as well as some functions for wangIds --- src/libtiled/libtiled-src.pri | 6 +- src/libtiled/libtiled.qbs | 2 + src/libtiled/wangset.cpp | 146 ++++++++++++++++++++++++++++++ src/libtiled/wangset.h | 166 ++++++++++++++++++++++++++++++++++ 4 files changed, 318 insertions(+), 2 deletions(-) create mode 100644 src/libtiled/wangset.cpp create mode 100644 src/libtiled/wangset.h diff --git a/src/libtiled/libtiled-src.pri b/src/libtiled/libtiled-src.pri index 82c92b928a..7cf9179163 100644 --- a/src/libtiled/libtiled-src.pri +++ b/src/libtiled/libtiled-src.pri @@ -29,7 +29,8 @@ SOURCES += $$PWD/compression.cpp \ $$PWD/tileset.cpp \ $$PWD/tilesetformat.cpp \ $$PWD/tilesetmanager.cpp \ - $$PWD/varianttomapconverter.cpp + $$PWD/varianttomapconverter.cpp \ + $$PWD/wangset.cpp HEADERS += $$PWD/compression.h \ $$PWD/filesystemwatcher.h \ $$PWD/gidmapper.h \ @@ -65,4 +66,5 @@ HEADERS += $$PWD/compression.h \ $$PWD/tileset.h \ $$PWD/tilesetformat.h \ $$PWD/tilesetmanager.h \ - $$PWD/varianttomapconverter.h + $$PWD/varianttomapconverter.h \ + $$PWD/wangset.h diff --git a/src/libtiled/libtiled.qbs b/src/libtiled/libtiled.qbs index 305b85fe97..b02602609e 100644 --- a/src/libtiled/libtiled.qbs +++ b/src/libtiled/libtiled.qbs @@ -99,6 +99,8 @@ DynamicLibrary { "tilesetmanager.h", "varianttomapconverter.cpp", "varianttomapconverter.h", + "wangset.cpp", + "wangset.h", ] Group { diff --git a/src/libtiled/wangset.cpp b/src/libtiled/wangset.cpp new file mode 100644 index 0000000000..ebeb12e5fd --- /dev/null +++ b/src/libtiled/wangset.cpp @@ -0,0 +1,146 @@ +/* + * wangset.cpp + * Copyright 2017, Benjamin Trotter + * This file is part of libtiled. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "wangset.h" + +#include +#include + +using namespace Tiled; + +WangSet::WangSet(Tileset *tileset, + int edgeColors, + int cornerColors, + QString name, + int imageTileId): + Object(Object::TerrainType), //for now, will add unique type soon + mTileSet(tileset), + mEdgeColors(edgeColors), + mCornerColors(cornerColors), + mName(std::move(name)), + mImageTileId(imageTileId), + mWangIdToTile(QMultiMap()), + mTileIdToWangId(QMap()) +{ +} + +void WangSet::addTile(Tile *tile, unsigned wangId) +{ + Q_ASSERT(tile->tileset() == mTileSet); + + for (int i = 0; i < 8; ++i) { + Q_ASSERT(((wangId >> (i * 4)) & 0xf) <= ((i % 2)? mCornerColors : mEdgeColors)); + } + + mWangIdToTile.insert(wangId, tile); + mTileIdToWangId.insert(tile->id(), wangId); +} + + + +Tile *WangSet::getMatchingTile(unsigned wangId) const +{ + auto potentials = getAllTiles(wangId); + + if (potentials.length() > 0) + return potentials[qrand() % potentials.length()]; + else + return NULL; +} + +QList WangSet::getAllTiles(unsigned wangId) const +{ + QList list; + + //Stores the space of a wild card, followed by how many colors that space can have. + QVector wildCards; + + if (mEdgeColors > 0) { + for (int i = 0; i < 4; ++i) { + if (!(wangId & (0xf << (i * 8)))) { + wildCards.append(QPoint(i * 8, mEdgeColors)); + } + } + } + + if (mCornerColors > 0) { + for (int i = 0; i < 4; ++i) { + if (!(wangId & (0xf << (i * 8 + 4)))) { + wildCards.append(QPoint(i * 8 + 4, mCornerColors)); + } + } + } + + if (wildCards.isEmpty()) { + list.append(mWangIdToTile.values(wangId)); + } else { + QStack stack; + + for (int i = 0; i < wildCards.size(); ++i) { + stack.push(wildCards[i]); + } + + int max = wildCards.size(); + + while (!stack.isEmpty()) { + if (stack.size() == max) { + int idVariation = 0; + + for (int i = 0; i < max; ++i) { + idVariation |= stack[i].y() << stack[i].x(); + } + + list.append(mWangIdToTile.values(idVariation)); + + QPoint top = stack.pop(); + top.setY(top.y() - 1); + if (top.y() > 0) + stack.push(top); + } else { + QPoint top = stack.pop(); + top.setY(top.y() - 1); + if (top.y() > 0) { + stack.push(top); + + for (int i = stack.size(); i < max; ++i) { + stack.push(wildCards[i]); + } + } + } + } + } + + return list; +} + +unsigned WangSet::getWangIdOfTile(Tile *tile) const +{ + if (tile->tileset() == mTileSet && mTileIdToWangId.contains(tile->id())) + return mTileIdToWangId.value(tile->id()); + else + return 0; +} diff --git a/src/libtiled/wangset.h b/src/libtiled/wangset.h new file mode 100644 index 0000000000..3339287c8f --- /dev/null +++ b/src/libtiled/wangset.h @@ -0,0 +1,166 @@ +/* + * wangset.h + * Copyright 2017, Benjamin Trotter + * This file is part of libtiled. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "tile.h" +#include "tileset.h" + +#include +#include +#include +#include + +namespace Tiled { + +/** + * Represents a wang set. + */ +class TILEDSHARED_EXPORT WangSet : public Object +{ +public: + WangSet(Tileset *tileset, + int edgeColors, + int cornerColors, + QString name, + int imageTileId); + + QString name() const { return mName; } + void setName(const QString &name) { mName = name; } + + int imageTileId() const { return mImageTileId; } + void setImageTileId(int imageTileId) { mImageTileId = imageTileId; } + + Tile *imageTile() const { return mTileSet->findTile(mImageTileId); } + + int edgeColors() const { return mEdgeColors; } + int cornerColors() const { return mCornerColors; } + void setEdgeColors(int n) { mEdgeColors = n; } + void setCornerColors(int n) { mCornerColors = n; } + + /** + * @brief addTile Adds a tile to the wang set + * @param tile + * @param wangId + */ + void addTile(Tile *tile, unsigned wangId); + + /** + * @brief getMatchingTile Returns a tile matching the given wangId. + * 0s in the id are wild cards, and can be filled with any color. + * If there are multiple possible options, one will be choosen at random. + * @param wangId + * @return + */ + Tile *getMatchingTile(unsigned wangId) const; + + /** + * @brief getAllTiles Returns a list of all tiles which match a wangId + * 0s in the id are wild cards, and can be filled with any color. + * @param wangId + * @return + */ + QList getAllTiles(unsigned wangId) const; + + + /** + * @brief wangIdOfTile returns the wangId of a given tileId + * @param tileId + */ + unsigned getWangIdOfTile(Tile *tile) const; + +private: + Tileset *mTileSet; + QString mName; + int mImageTileId; + QMultiMap mWangIdToTile; + QMap mTileIdToWangId; //This could be stored in the tile object. + int mEdgeColors; + int mCornerColors; +}; + +/** + * public functions for working with "wangIds" + */ + +/** + * @brief makeWangId Constructs a wang id from given edges/corner colors + * @param a Top edge, or top right corner + * @param b Right edge, or bottom right corner + * @param c Bottom edge, or bottom left corner + * @param d Left edge, or top left corner + * @param edges Defining edges (Corners if false) + */ +unsigned makeWangId(int a, int b, int c, int d, bool edges) +{ + //Makes sure inputs aren't bigger than 15 + a = a & 0xf; + b = b & 0xf; + c = c & 0xf; + d = d & 0xf; + + int id = ((((((d << 8) | c) << 8) | b) << 8) | a) << ((!edges) * 4); + + return id; +} + +/** + * @brief getColor returns the color of a desired edge/corner of a given wang id + * @param wangId + * @param index index 0-3 with zero being the top right, and 3 left top + * @param edges requesting edge color (corners if false) + * @return + */ +int getColorOfWangId(unsigned wangId, int index, bool edges) +{ + int shift = (index * 8) + ((!edges) * 4); + + int color = (wangId >> shift) & 0xf; + + return color; +} + +/** + * @brief rotateWangId returns the given wang id rotated 90 * rotations degrees ccw + * @param wangId + * @param rotations 1-3 + * @return + */ +unsigned rotateWangId(unsigned wangId, int rotations) +{ + if (rotations < 0) + rotations = 4 + (rotations % 4); + else + rotations %= 4; + + unsigned rotated = wangId << rotations*8; + rotated = rotated | (wangId >> ((4 - rotations) * 8)); + + return rotated; +} + +} // namespace Tiled From cb8d9ae165043d59aac1d8bde5d37138c5d8b854 Mon Sep 17 00:00:00 2001 From: Benjamin Trotter Date: Mon, 29 May 2017 14:53:39 -0700 Subject: [PATCH 02/21] Moved wangId into a class of its own --- src/libtiled/wangset.cpp | 30 ++++----- src/libtiled/wangset.h | 128 +++++++++++++++++++-------------------- 2 files changed, 78 insertions(+), 80 deletions(-) diff --git a/src/libtiled/wangset.cpp b/src/libtiled/wangset.cpp index ebeb12e5fd..8859d0ecaa 100644 --- a/src/libtiled/wangset.cpp +++ b/src/libtiled/wangset.cpp @@ -43,26 +43,28 @@ WangSet::WangSet(Tileset *tileset, mCornerColors(cornerColors), mName(std::move(name)), mImageTileId(imageTileId), - mWangIdToTile(QMultiMap()), - mTileIdToWangId(QMap()) + mWangIdToTile(QMultiMap()), + mTileIdToWangId(QMap()) { } -void WangSet::addTile(Tile *tile, unsigned wangId) +void WangSet::addTile(Tile *tile, WangId wangId) { Q_ASSERT(tile->tileset() == mTileSet); - for (int i = 0; i < 8; ++i) { - Q_ASSERT(((wangId >> (i * 4)) & 0xf) <= ((i % 2)? mCornerColors : mEdgeColors)); + for (int i = 0; i < 4; ++i) { + Q_ASSERT(wangId.getColor(i,true) <= mEdgeColors); + } + + for (int i = 0; i < 4; ++i) { + Q_ASSERT(wangId.getColor(i,false) <= mCornerColors); } mWangIdToTile.insert(wangId, tile); mTileIdToWangId.insert(tile->id(), wangId); } - - -Tile *WangSet::getMatchingTile(unsigned wangId) const +Tile *WangSet::getMatchingTile(WangId wangId) const { auto potentials = getAllTiles(wangId); @@ -72,7 +74,7 @@ Tile *WangSet::getMatchingTile(unsigned wangId) const return NULL; } -QList WangSet::getAllTiles(unsigned wangId) const +QList WangSet::getAllTiles(WangId wangId) const { QList list; @@ -81,7 +83,7 @@ QList WangSet::getAllTiles(unsigned wangId) const if (mEdgeColors > 0) { for (int i = 0; i < 4; ++i) { - if (!(wangId & (0xf << (i * 8)))) { + if (!wangId.getColor(i,true)) { wildCards.append(QPoint(i * 8, mEdgeColors)); } } @@ -89,7 +91,7 @@ QList WangSet::getAllTiles(unsigned wangId) const if (mCornerColors > 0) { for (int i = 0; i < 4; ++i) { - if (!(wangId & (0xf << (i * 8 + 4)))) { + if (!wangId.getColor(i,false)) { wildCards.append(QPoint(i * 8 + 4, mCornerColors)); } } @@ -114,7 +116,7 @@ QList WangSet::getAllTiles(unsigned wangId) const idVariation |= stack[i].y() << stack[i].x(); } - list.append(mWangIdToTile.values(idVariation)); + list.append(mWangIdToTile.values(idVariation | wangId.id())); QPoint top = stack.pop(); top.setY(top.y() - 1); @@ -137,10 +139,10 @@ QList WangSet::getAllTiles(unsigned wangId) const return list; } -unsigned WangSet::getWangIdOfTile(Tile *tile) const +WangId WangSet::getWangIdOfTile(Tile *tile) const { if (tile->tileset() == mTileSet && mTileIdToWangId.contains(tile->id())) return mTileIdToWangId.value(tile->id()); else - return 0; + return WangId(0); } diff --git a/src/libtiled/wangset.h b/src/libtiled/wangset.h index 3339287c8f..22b7ff6703 100644 --- a/src/libtiled/wangset.h +++ b/src/libtiled/wangset.h @@ -37,6 +37,62 @@ namespace Tiled { +class WangId +{ +public: + WangId(unsigned id){ mId = id; } + WangId() { mId = 0; } + + inline unsigned id() const { return mId; } + inline void setId(unsigned id) { mId = id; } + + /** + * @brief getColor returns the color of a desired edge/corner of a given wang id + * @param index index 0-3 with zero being the top right, and 3 left top + * @param edges requesting edge color (corners if false) + * @return + */ + int getColor(int index, bool edges) const; + + /** + * @brief rotateWangId rotates the wang id 90 * rotations degrees ccw + * @param rotations 1-3 + * @return + */ + void rotate(int rotations); + + //used in maping + bool operator <(const WangId w) const + { + return mId < w.id(); + } + +private: + unsigned mId; +}; + +inline int WangId::getColor(int index, bool edges) const +{ + int shift = (index * 8) + ((!edges) * 4); + + int color = (mId >> shift) & 0xf; + + return color; +} + +void WangId::rotate(int rotations) +{ + if (rotations < 0) + rotations = 4 + (rotations % 4); + else + rotations %= 4; + + unsigned rotated = mId << rotations*8; + rotated = rotated | (mId >> ((4 - rotations) * 8)); + + mId = rotated; +} + /** * Represents a wang set. */ @@ -67,7 +123,7 @@ class TILEDSHARED_EXPORT WangSet : public Object * @param tile * @param wangId */ - void addTile(Tile *tile, unsigned wangId); + void addTile(Tile *tile, WangId wangId); /** * @brief getMatchingTile Returns a tile matching the given wangId. @@ -76,7 +132,7 @@ class TILEDSHARED_EXPORT WangSet : public Object * @param wangId * @return */ - Tile *getMatchingTile(unsigned wangId) const; + Tile *getMatchingTile(WangId wangId) const; /** * @brief getAllTiles Returns a list of all tiles which match a wangId @@ -84,83 +140,23 @@ class TILEDSHARED_EXPORT WangSet : public Object * @param wangId * @return */ - QList getAllTiles(unsigned wangId) const; + QList getAllTiles(WangId wangId) const; /** * @brief wangIdOfTile returns the wangId of a given tileId * @param tileId */ - unsigned getWangIdOfTile(Tile *tile) const; + WangId getWangIdOfTile(Tile *tile) const; private: Tileset *mTileSet; QString mName; int mImageTileId; - QMultiMap mWangIdToTile; - QMap mTileIdToWangId; //This could be stored in the tile object. + QMultiMap mWangIdToTile; + QMap mTileIdToWangId; //This could be stored in the tile object. int mEdgeColors; int mCornerColors; }; -/** - * public functions for working with "wangIds" - */ - -/** - * @brief makeWangId Constructs a wang id from given edges/corner colors - * @param a Top edge, or top right corner - * @param b Right edge, or bottom right corner - * @param c Bottom edge, or bottom left corner - * @param d Left edge, or top left corner - * @param edges Defining edges (Corners if false) - */ -unsigned makeWangId(int a, int b, int c, int d, bool edges) -{ - //Makes sure inputs aren't bigger than 15 - a = a & 0xf; - b = b & 0xf; - c = c & 0xf; - d = d & 0xf; - - int id = ((((((d << 8) | c) << 8) | b) << 8) | a) << ((!edges) * 4); - - return id; -} - -/** - * @brief getColor returns the color of a desired edge/corner of a given wang id - * @param wangId - * @param index index 0-3 with zero being the top right, and 3 left top - * @param edges requesting edge color (corners if false) - * @return - */ -int getColorOfWangId(unsigned wangId, int index, bool edges) -{ - int shift = (index * 8) + ((!edges) * 4); - - int color = (wangId >> shift) & 0xf; - - return color; -} - -/** - * @brief rotateWangId returns the given wang id rotated 90 * rotations degrees ccw - * @param wangId - * @param rotations 1-3 - * @return - */ -unsigned rotateWangId(unsigned wangId, int rotations) -{ - if (rotations < 0) - rotations = 4 + (rotations % 4); - else - rotations %= 4; - - unsigned rotated = wangId << rotations*8; - rotated = rotated | (wangId >> ((4 - rotations) * 8)); - - return rotated; -} - } // namespace Tiled From 4757fb69982ecbfa7fa4d06a5be0821b55c57567 Mon Sep 17 00:00:00 2001 From: Ben Trotter Date: Wed, 21 Jun 2017 11:11:26 -0700 Subject: [PATCH 03/21] Refined WangSet class, and added them into Tileset --- src/libtiled/tileset.cpp | 33 +++++++++++++++++ src/libtiled/tileset.h | 24 ++++++++++++ src/libtiled/wangset.cpp | 80 ++++++++++++++++++++++++---------------- src/libtiled/wangset.h | 52 +++++++++++++++----------- 4 files changed, 136 insertions(+), 53 deletions(-) diff --git a/src/libtiled/tileset.cpp b/src/libtiled/tileset.cpp index 25a06732d7..c3f7449f1e 100644 --- a/src/libtiled/tileset.cpp +++ b/src/libtiled/tileset.cpp @@ -32,6 +32,7 @@ #include "terrain.h" #include "tile.h" #include "tilesetformat.h" +#include "wangset.h" #include @@ -62,6 +63,7 @@ Tileset::~Tileset() { qDeleteAll(mTiles); qDeleteAll(mTerrainTypes); + qDeleteAll(mWangSets); } void Tileset::setFormat(TilesetFormat *format) @@ -505,6 +507,28 @@ void Tileset::recalculateTerrainDistances() } while (bNewConnections); } +/** + * @brief Tileset::insertWangSet Adds a wangSet. + * @param wangSet A pointer to the wangset to add. + */ +void Tileset::insertWangSet(WangSet *wangSet) +{ + Q_ASSERT(wangSet->tileset() == this); + + mWangSets.append(wangSet); +} + +/** + * @brief Tileset::takeWangSetAt Removes the wangset at a given index + * And returns it to the caller. + * @param index Index to take at. + * @return + */ +WangSet *Tileset::takeWangSetAt(int index) +{ + return mWangSets.takeAt(index); +} + /** * Adds a new tile to the end of the tileset. */ @@ -617,6 +641,7 @@ void Tileset::swap(Tileset &other) std::swap(mTiles, other.mTiles); std::swap(mNextTileId, other.mNextTileId); std::swap(mTerrainTypes, other.mTerrainTypes); + std::swap(mWangSets, other.mWangSets); std::swap(mTerrainDistancesDirty, other.mTerrainDistancesDirty); std::swap(mLoaded, other.mLoaded); std::swap(mBackgroundColor, other.mBackgroundColor); @@ -629,11 +654,15 @@ void Tileset::swap(Tileset &other) tile->mTileset = this; for (auto terrain : mTerrainTypes) terrain->mTileset = this; + for (auto wangSet : mWangSets) + wangSet->setTileset(this); for (auto tile : other.mTiles) tile->mTileset = &other; for (auto terrain : other.mTerrainTypes) terrain->mTileset = &other; + for (auto wangSet : other.mWangSets) + wangSet->setTileset(&other); } SharedTileset Tileset::clone() const @@ -669,6 +698,10 @@ SharedTileset Tileset::clone() const for (Terrain *terrain : mTerrainTypes) c->mTerrainTypes.append(terrain->clone(c.data())); + c->mWangSets.reserve(mWangSets.size()); + for (WangSet *wangSet : mWangSets) + c->mWangSets.append(wangSet->clone(c.data())); + return c; } diff --git a/src/libtiled/tileset.h b/src/libtiled/tileset.h index 62a08bdcdf..803670f902 100644 --- a/src/libtiled/tileset.h +++ b/src/libtiled/tileset.h @@ -49,6 +49,7 @@ class Tile; class Tileset; class TilesetFormat; class Terrain; +class WangSet; typedef QSharedPointer SharedTileset; @@ -184,6 +185,13 @@ class TILEDSHARED_EXPORT Tileset : public Object int terrainTransitionPenalty(int terrainType0, int terrainType1) const; + const QList &wangSets() const; + int wangSetCount() const; + WangSet *wangSet(int index) const; + + void insertWangSet(WangSet *wangSet); + WangSet *takeWangSetAt(int index); + Tile *addTile(const QPixmap &image, const QString &source = QString()); void addTiles(const QList &tiles); void removeTiles(const QList &tiles); @@ -246,6 +254,7 @@ class TILEDSHARED_EXPORT Tileset : public Object QMap mTiles; int mNextTileId; QList mTerrainTypes; + QList mWangSets; bool mTerrainDistancesDirty; bool mLoaded; QColor mBackgroundColor; @@ -553,6 +562,21 @@ inline Terrain *Tileset::terrain(int index) const return index >= 0 ? mTerrainTypes[index] : nullptr; } +inline const QList &Tileset::wangSets() const +{ + return mWangSets; +} + +inline int Tileset::wangSetCount() const +{ + return mWangSets.size(); +} + +inline WangSet *Tileset::wangSet(int index) const +{ + return index >= 0 ? mWangSets[index] : nullptr; +} + /** * Sets the next id to be used for tiles in this tileset. */ diff --git a/src/libtiled/wangset.cpp b/src/libtiled/wangset.cpp index 8859d0ecaa..dc6f214706 100644 --- a/src/libtiled/wangset.cpp +++ b/src/libtiled/wangset.cpp @@ -39,12 +39,12 @@ WangSet::WangSet(Tileset *tileset, int imageTileId): Object(Object::TerrainType), //for now, will add unique type soon mTileSet(tileset), - mEdgeColors(edgeColors), - mCornerColors(cornerColors), mName(std::move(name)), mImageTileId(imageTileId), - mWangIdToTile(QMultiMap()), - mTileIdToWangId(QMap()) + mEdgeColors(edgeColors), + mCornerColors(cornerColors)/*, + mWangIdToTile(QMultiHash()), + mTileIdToWangId(QHash())*/ { } @@ -53,20 +53,20 @@ void WangSet::addTile(Tile *tile, WangId wangId) Q_ASSERT(tile->tileset() == mTileSet); for (int i = 0; i < 4; ++i) { - Q_ASSERT(wangId.getColor(i,true) <= mEdgeColors); + Q_ASSERT(wangId.edgeColor(i) <= mEdgeColors); } for (int i = 0; i < 4; ++i) { - Q_ASSERT(wangId.getColor(i,false) <= mCornerColors); + Q_ASSERT(wangId.cornerColor(i) <= mCornerColors); } mWangIdToTile.insert(wangId, tile); mTileIdToWangId.insert(tile->id(), wangId); } -Tile *WangSet::getMatchingTile(WangId wangId) const +Tile *WangSet::findMatchingTile(WangId wangId) const { - auto potentials = getAllTiles(wangId); + auto potentials = findMatchingTiles(wangId); if (potentials.length() > 0) return potentials[qrand() % potentials.length()]; @@ -74,25 +74,38 @@ Tile *WangSet::getMatchingTile(WangId wangId) const return NULL; } -QList WangSet::getAllTiles(WangId wangId) const +typedef struct WangWildCard +{ + int index, colorCount; +} WangWildCard; + +QList WangSet::findMatchingTiles(WangId wangId) const { QList list; //Stores the space of a wild card, followed by how many colors that space can have. - QVector wildCards; + QVector wildCards; if (mEdgeColors > 0) { for (int i = 0; i < 4; ++i) { - if (!wangId.getColor(i,true)) { - wildCards.append(QPoint(i * 8, mEdgeColors)); + if (!wangId.edgeColor(i)) { + WangWildCard w; + w.index = i * 8; + w.colorCount = mEdgeColors; + + wildCards.append(w); } } } if (mCornerColors > 0) { for (int i = 0; i < 4; ++i) { - if (!wangId.getColor(i,false)) { - wildCards.append(QPoint(i * 8 + 4, mCornerColors)); + if (!wangId.cornerColor(i)) { + WangWildCard w; + w.index = i * 8 + 4; + w.colorCount = mCornerColors; + + wildCards.append(w); } } } @@ -100,11 +113,9 @@ QList WangSet::getAllTiles(WangId wangId) const if (wildCards.isEmpty()) { list.append(mWangIdToTile.values(wangId)); } else { - QStack stack; + QStack stack; - for (int i = 0; i < wildCards.size(); ++i) { - stack.push(wildCards[i]); - } + stack.append(wildCards); int max = wildCards.size(); @@ -113,19 +124,19 @@ QList WangSet::getAllTiles(WangId wangId) const int idVariation = 0; for (int i = 0; i < max; ++i) { - idVariation |= stack[i].y() << stack[i].x(); + idVariation |= stack[i].colorCount << stack[i].index; } - list.append(mWangIdToTile.values(idVariation | wangId.id())); + list.append(mWangIdToTile.values(idVariation | wangId)); - QPoint top = stack.pop(); - top.setY(top.y() - 1); - if (top.y() > 0) + WangWildCard top = stack.pop(); + top.colorCount -= 1; + if (top.colorCount > 0) stack.push(top); } else { - QPoint top = stack.pop(); - top.setY(top.y() - 1); - if (top.y() > 0) { + WangWildCard top = stack.pop(); + top.colorCount -= 1; + if (top.colorCount > 0) { stack.push(top); for (int i = stack.size(); i < max; ++i) { @@ -139,10 +150,17 @@ QList WangSet::getAllTiles(WangId wangId) const return list; } -WangId WangSet::getWangIdOfTile(Tile *tile) const +WangId WangSet::wangIdOfTile(Tile *tile) const { - if (tile->tileset() == mTileSet && mTileIdToWangId.contains(tile->id())) - return mTileIdToWangId.value(tile->id()); - else - return WangId(0); + return mTileIdToWangId.value(tile->id()); +} + +WangSet *WangSet::clone(Tileset *tileset) const +{ + WangSet *c = new WangSet(tileset, mEdgeColors, mCornerColors, mName, mImageTileId); + + c->mWangIdToTile = mWangIdToTile; + c->mTileIdToWangId = mTileIdToWangId; + + return c; } diff --git a/src/libtiled/wangset.h b/src/libtiled/wangset.h index 22b7ff6703..f06e899923 100644 --- a/src/libtiled/wangset.h +++ b/src/libtiled/wangset.h @@ -30,8 +30,8 @@ #include "tile.h" #include "tileset.h" -#include -#include +#include +#include #include #include @@ -40,47 +40,50 @@ namespace Tiled { class WangId { public: - WangId(unsigned id){ mId = id; } - WangId() { mId = 0; } + WangId(unsigned id) : mId(id) {} + WangId() : mId(0) {} - inline unsigned id() const { return mId; } + operator unsigned() const { return mId; } inline void setId(unsigned id) { mId = id; } /** * @brief getColor returns the color of a desired edge/corner of a given wang id * @param index index 0-3 with zero being the top right, and 3 left top - * @param edges requesting edge color (corners if false) * @return */ - int getColor(int index, bool edges) const; + int edgeColor(int index) const; + int cornerColor(int index) const; /** * @brief rotateWangId rotates the wang id 90 * rotations degrees ccw * @param rotations 1-3 * @return */ - void rotate(int rotations); - - //used in maping - bool operator <(const WangId w) const - { - return mId < w.id(); - } + void rotate(int rotations);\ private: unsigned mId; }; -inline int WangId::getColor(int index, bool edges) const +inline int WangId::edgeColor(int index) const +{ + int shift = (index * 8); + + int color = (mId >> shift) & 0xf; + + return color; +} + +inline int WangId::cornerColor(int index) const { - int shift = (index * 8) + ((!edges) * 4); + int shift = (index * 8) + 4; int color = (mId >> shift) & 0xf; return color; } -void WangId::rotate(int rotations) +inline void WangId::rotate(int rotations) { if (rotations < 0) rotations = 4 + (rotations % 4); @@ -105,6 +108,9 @@ class TILEDSHARED_EXPORT WangSet : public Object QString name, int imageTileId); + Tileset *tileset() const { return mTileSet; } + void setTileset(Tileset *tileset) { mTileSet = tileset; } + QString name() const { return mName; } void setName(const QString &name) { mName = name; } @@ -132,7 +138,7 @@ class TILEDSHARED_EXPORT WangSet : public Object * @param wangId * @return */ - Tile *getMatchingTile(WangId wangId) const; + Tile *findMatchingTile(WangId wangId) const; /** * @brief getAllTiles Returns a list of all tiles which match a wangId @@ -140,23 +146,25 @@ class TILEDSHARED_EXPORT WangSet : public Object * @param wangId * @return */ - QList getAllTiles(WangId wangId) const; + QList findMatchingTiles(WangId wangId) const; /** * @brief wangIdOfTile returns the wangId of a given tileId * @param tileId */ - WangId getWangIdOfTile(Tile *tile) const; + WangId wangIdOfTile(Tile *tile) const; + + WangSet *clone(Tileset *tileset) const; private: Tileset *mTileSet; QString mName; int mImageTileId; - QMultiMap mWangIdToTile; - QMap mTileIdToWangId; //This could be stored in the tile object. int mEdgeColors; int mCornerColors; + QMultiHash mWangIdToTile; + QHash mTileIdToWangId; //This could be stored in the tile object. }; } // namespace Tiled From 31689c6ecfdf5b13757e8440bdc5cac427d5b0a6 Mon Sep 17 00:00:00 2001 From: Ben Trotter Date: Wed, 21 Jun 2017 13:53:15 -0700 Subject: [PATCH 04/21] Made requested changes --- src/libtiled/wangset.cpp | 18 +++++------ src/libtiled/wangset.h | 65 +++++++++++++++++----------------------- 2 files changed, 34 insertions(+), 49 deletions(-) diff --git a/src/libtiled/wangset.cpp b/src/libtiled/wangset.cpp index dc6f214706..9edaa6fec5 100644 --- a/src/libtiled/wangset.cpp +++ b/src/libtiled/wangset.cpp @@ -38,19 +38,17 @@ WangSet::WangSet(Tileset *tileset, QString name, int imageTileId): Object(Object::TerrainType), //for now, will add unique type soon - mTileSet(tileset), + mTileset(tileset), mName(std::move(name)), mImageTileId(imageTileId), mEdgeColors(edgeColors), - mCornerColors(cornerColors)/*, - mWangIdToTile(QMultiHash()), - mTileIdToWangId(QHash())*/ + mCornerColors(cornerColors) { } void WangSet::addTile(Tile *tile, WangId wangId) { - Q_ASSERT(tile->tileset() == mTileSet); + Q_ASSERT(tile->tileset() == mTileset); for (int i = 0; i < 4; ++i) { Q_ASSERT(wangId.edgeColor(i) <= mEdgeColors); @@ -74,10 +72,10 @@ Tile *WangSet::findMatchingTile(WangId wangId) const return NULL; } -typedef struct WangWildCard +struct WangWildCard { int index, colorCount; -} WangWildCard; +}; QList WangSet::findMatchingTiles(WangId wangId) const { @@ -123,9 +121,8 @@ QList WangSet::findMatchingTiles(WangId wangId) const if (stack.size() == max) { int idVariation = 0; - for (int i = 0; i < max; ++i) { + for (int i = 0; i < max; ++i) idVariation |= stack[i].colorCount << stack[i].index; - } list.append(mWangIdToTile.values(idVariation | wangId)); @@ -139,9 +136,8 @@ QList WangSet::findMatchingTiles(WangId wangId) const if (top.colorCount > 0) { stack.push(top); - for (int i = stack.size(); i < max; ++i) { + for (int i = stack.size(); i < max; ++i) stack.push(wildCards[i]); - } } } } diff --git a/src/libtiled/wangset.h b/src/libtiled/wangset.h index f06e899923..d55e78ff3e 100644 --- a/src/libtiled/wangset.h +++ b/src/libtiled/wangset.h @@ -46,20 +46,17 @@ class WangId operator unsigned() const { return mId; } inline void setId(unsigned id) { mId = id; } - /** - * @brief getColor returns the color of a desired edge/corner of a given wang id - * @param index index 0-3 with zero being the top right, and 3 left top - * @return - */ + /* These return the color of the edge/corner of the wangId. + * 0 being the top right corner, or top edge + * */ int edgeColor(int index) const; int cornerColor(int index) const; - /** - * @brief rotateWangId rotates the wang id 90 * rotations degrees ccw - * @param rotations 1-3 - * @return - */ - void rotate(int rotations);\ + /* Rotates the wang Id clockwise by (90 * rotations) degrees. + * Meaning with one rotation, the top edge becomes the right edge, + * and the top right corner, becomes the top bottom. + * */ + void rotate(int rotations); private: unsigned mId; @@ -108,8 +105,8 @@ class TILEDSHARED_EXPORT WangSet : public Object QString name, int imageTileId); - Tileset *tileset() const { return mTileSet; } - void setTileset(Tileset *tileset) { mTileSet = tileset; } + Tileset *tileset() const { return mTileset; } + void setTileset(Tileset *tileset) { mTileset = tileset; } QString name() const { return mName; } void setName(const QString &name) { mName = name; } @@ -117,54 +114,46 @@ class TILEDSHARED_EXPORT WangSet : public Object int imageTileId() const { return mImageTileId; } void setImageTileId(int imageTileId) { mImageTileId = imageTileId; } - Tile *imageTile() const { return mTileSet->findTile(mImageTileId); } + Tile *imageTile() const { return mTileset->findTile(mImageTileId); } int edgeColors() const { return mEdgeColors; } int cornerColors() const { return mCornerColors; } void setEdgeColors(int n) { mEdgeColors = n; } void setCornerColors(int n) { mCornerColors = n; } - /** - * @brief addTile Adds a tile to the wang set - * @param tile - * @param wangId - */ + /* Adds a tile to the wang set with a given wangId + * */ void addTile(Tile *tile, WangId wangId); - /** - * @brief getMatchingTile Returns a tile matching the given wangId. - * 0s in the id are wild cards, and can be filled with any color. - * If there are multiple possible options, one will be choosen at random. - * @param wangId - * @return - */ + /* Finds a tile whos WangId matches with the one provided, + * where zeros in the id are treated as wild cards, and can be + * any color. + * */ Tile *findMatchingTile(WangId wangId) const; - /** - * @brief getAllTiles Returns a list of all tiles which match a wangId - * 0s in the id are wild cards, and can be filled with any color. - * @param wangId - * @return - */ + /* Finds all the tiles which match the given wangId, + * where zeros in the id are treated as wild cards, and can be + * any color. + * */ QList findMatchingTiles(WangId wangId) const; - /** - * @brief wangIdOfTile returns the wangId of a given tileId - * @param tileId - */ + /* Returns the wangId of a given Tile. + * */ WangId wangIdOfTile(Tile *tile) const; + /* Returns a clone of this wangset + * */ WangSet *clone(Tileset *tileset) const; private: - Tileset *mTileSet; + Tileset *mTileset; QString mName; int mImageTileId; int mEdgeColors; int mCornerColors; QMultiHash mWangIdToTile; - QHash mTileIdToWangId; //This could be stored in the tile object. + QHash mTileIdToWangId; }; } // namespace Tiled From e10151e43b1f36d7dfe216d5030ee1395b22ba08 Mon Sep 17 00:00:00 2001 From: Ben Trotter Date: Fri, 23 Jun 2017 19:04:19 -0700 Subject: [PATCH 05/21] Enabled file saving and loading. (Needs testing) --- src/libtiled/mapreader.cpp | 30 ++++++++++++++++++++++++++++++ src/libtiled/mapwriter.cpp | 30 ++++++++++++++++++++++++++++++ src/libtiled/wangset.cpp | 4 ++-- src/libtiled/wangset.h | 2 +- 4 files changed, 63 insertions(+), 3 deletions(-) diff --git a/src/libtiled/mapreader.cpp b/src/libtiled/mapreader.cpp index 1493a40f5b..931d4c585b 100644 --- a/src/libtiled/mapreader.cpp +++ b/src/libtiled/mapreader.cpp @@ -41,6 +41,7 @@ #include "tilelayer.h" #include "tilesetmanager.h" #include "terrain.h" +#include "wangset.h" #include #include @@ -84,6 +85,7 @@ class MapReaderPrivate void readTilesetGrid(Tileset &tileset); void readTilesetImage(Tileset &tileset); void readTilesetTerrainTypes(Tileset &tileset); + void readTilesetWangSet(Tileset &tileset); ImageReference readImage(); Layer *tryReadLayer(); @@ -353,6 +355,8 @@ SharedTileset MapReaderPrivate::readTileset() } } else if (xml.name() == QLatin1String("terraintypes")) { readTilesetTerrainTypes(*tileset); + } else if (xml.name() == QLatin1String("wangSets")) { + readTilesetWangSet(*tileset); } else { readUnknownElement(); } @@ -430,6 +434,13 @@ void MapReaderPrivate::readTilesetTile(Tileset &tileset) tile->setObjectGroup(readObjectGroup()); } else if (xml.name() == QLatin1String("animation")) { tile->setFrames(readAnimationFrames()); + } else if(xml.name() == QLatin1String("wangInfo")) { + const QXmlStreamAttributes wangAtts = xml.attributes(); + + WangSet *wangSet = tileset.wangSet(wangAtts.value(QLatin1String("setIndex")).toInt()); + unsigned wangId = wangAtts.value(QLatin1String("wangId")).toUInt(); + + wangSet->addTile(tile, wangId); } else { readUnknownElement(); } @@ -564,6 +575,25 @@ void MapReaderPrivate::readTilesetTerrainTypes(Tileset &tileset) } } +void MapReaderPrivate::readTilesetWangSet(Tileset &tileset) +{ + Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("wangSets")); + + while (xml.readNextStartElement()) { + if (xml.name() == QLatin1String("wangSet")) { + const QXmlStreamAttributes atts = xml.attributes(); + QString name = atts.value(QLatin1String("name")).toString(); + int edges = atts.value(QLatin1String("edges")).toInt(); + int corners = atts.value(QLatin1String("corners")).toInt(); + int tile = atts.value(QLatin1String("tile")).toInt(); + + tileset.insertWangSet(new WangSet(&tileset, edges, corners, name, tile)); + } else { + readUnknownElement(); + } + } +} + static void readLayerAttributes(Layer &layer, const QXmlStreamAttributes &atts) { diff --git a/src/libtiled/mapwriter.cpp b/src/libtiled/mapwriter.cpp index 0967858c07..1e00668df9 100644 --- a/src/libtiled/mapwriter.cpp +++ b/src/libtiled/mapwriter.cpp @@ -42,6 +42,7 @@ #include "tilelayer.h" #include "tileset.h" #include "terrain.h" +#include "wangset.h" #include #include @@ -362,6 +363,23 @@ void MapWriterPrivate::writeTileset(QXmlStreamWriter &w, const Tileset &tileset, w.writeEndElement(); } + // Write the wangsets + if (tileset.wangSetCount() > 0) { + w.writeStartElement(QLatin1String("wangSets")); + for (int i = 0; i < tileset.wangSetCount(); ++i) { + const WangSet *ws = tileset.wangSet(i); + w.writeStartElement(QLatin1String("wangSet")); + + w.writeAttribute(QLatin1String("name"),ws->name()); + w.writeAttribute(QLatin1String("edges"),QString::number(ws->edgeColors())); + w.writeAttribute(QLatin1String("corners"),QString::number(ws->cornerColors())); + w.writeAttribute(QLatin1String("tile"),QString::number(ws->imageTileId())); + + w.writeEndElement(); // + } + w.writeEndElement(); // + } + // Write the properties for those tiles that have them for (const Tile *tile : tileset.tiles()) { if (imageSource.isEmpty() || includeTile(tile)) { @@ -421,6 +439,18 @@ void MapWriterPrivate::writeTileset(QXmlStreamWriter &w, const Tileset &tileset, } w.writeEndElement(); // } + for (int i = 0; i < tileset.wangSetCount(); ++i) { + unsigned wangId = tileset.wangSet(i)->wangIdOfTile(tile); + + if(!wangId) { + w.writeStartElement(QLatin1String("wangInfo")); + w.writeAttribute(QLatin1String("setIndex"), QString::number(i)); + + //could be made more readable by spacing out the wangId into each corner. + w.writeAttribute(QLatin1String("wangId"), QString::number(wangId)); + w.writeEndElement(); // + } + } w.writeEndElement(); // } diff --git a/src/libtiled/wangset.cpp b/src/libtiled/wangset.cpp index 9edaa6fec5..ae884450db 100644 --- a/src/libtiled/wangset.cpp +++ b/src/libtiled/wangset.cpp @@ -113,7 +113,7 @@ QList WangSet::findMatchingTiles(WangId wangId) const } else { QStack stack; - stack.append(wildCards); + stack += wildCards; int max = wildCards.size(); @@ -146,7 +146,7 @@ QList WangSet::findMatchingTiles(WangId wangId) const return list; } -WangId WangSet::wangIdOfTile(Tile *tile) const +WangId WangSet::wangIdOfTile(const Tile *tile) const { return mTileIdToWangId.value(tile->id()); } diff --git a/src/libtiled/wangset.h b/src/libtiled/wangset.h index d55e78ff3e..76fc0c298a 100644 --- a/src/libtiled/wangset.h +++ b/src/libtiled/wangset.h @@ -140,7 +140,7 @@ class TILEDSHARED_EXPORT WangSet : public Object /* Returns the wangId of a given Tile. * */ - WangId wangIdOfTile(Tile *tile) const; + WangId wangIdOfTile(const Tile *tile) const; /* Returns a clone of this wangset * */ From c7e67d0147cd72598afb4399875dc592daa03b17 Mon Sep 17 00:00:00 2001 From: William Taylor Date: Fri, 23 Jun 2017 02:31:56 -0700 Subject: [PATCH 06/21] Fixed some issues with saving/loading --- src/libtiled/mapreader.cpp | 6 +++ src/libtiled/mapwriter.cpp | 2 +- src/plugins/gmx/gmxplugin.cpp | 80 ++++++++++++++++++++++++++++++++++- 3 files changed, 86 insertions(+), 2 deletions(-) diff --git a/src/libtiled/mapreader.cpp b/src/libtiled/mapreader.cpp index 931d4c585b..b84c66f05b 100644 --- a/src/libtiled/mapreader.cpp +++ b/src/libtiled/mapreader.cpp @@ -441,6 +441,9 @@ void MapReaderPrivate::readTilesetTile(Tileset &tileset) unsigned wangId = wangAtts.value(QLatin1String("wangId")).toUInt(); wangSet->addTile(tile, wangId); + + //not sure if this is necessary... seens not to work without + xml.skipCurrentElement(); } else { readUnknownElement(); } @@ -588,6 +591,9 @@ void MapReaderPrivate::readTilesetWangSet(Tileset &tileset) int tile = atts.value(QLatin1String("tile")).toInt(); tileset.insertWangSet(new WangSet(&tileset, edges, corners, name, tile)); + + //eventually will read properties. + xml.skipCurrentElement(); } else { readUnknownElement(); } diff --git a/src/libtiled/mapwriter.cpp b/src/libtiled/mapwriter.cpp index 1e00668df9..1ff8608e65 100644 --- a/src/libtiled/mapwriter.cpp +++ b/src/libtiled/mapwriter.cpp @@ -442,7 +442,7 @@ void MapWriterPrivate::writeTileset(QXmlStreamWriter &w, const Tileset &tileset, for (int i = 0; i < tileset.wangSetCount(); ++i) { unsigned wangId = tileset.wangSet(i)->wangIdOfTile(tile); - if(!wangId) { + if(wangId) { w.writeStartElement(QLatin1String("wangInfo")); w.writeAttribute(QLatin1String("setIndex"), QString::number(i)); diff --git a/src/plugins/gmx/gmxplugin.cpp b/src/plugins/gmx/gmxplugin.cpp index 406dde9ecf..c056ad7585 100644 --- a/src/plugins/gmx/gmxplugin.cpp +++ b/src/plugins/gmx/gmxplugin.cpp @@ -79,6 +79,26 @@ static QString effectiveObjectType(const MapObject *object) return QString(); } +static bool checkIfViewsDefined(const Map *map) +{ + LayerIterator iterator(map); + while (const Layer *layer = iterator.next()) { + + if (layer->layerType() != Layer::ObjectGroupType) + continue; + + const ObjectGroup *objectLayer = static_cast(layer); + + for (const MapObject *object : objectLayer->objects()) { + const QString type = effectiveObjectType(object); + if (type == "view") + return true; + } + } + + return false; +} + GmxPlugin::GmxPlugin() { } @@ -110,16 +130,72 @@ bool GmxPlugin::write(const Map *map, const QString &fileName) writeProperty(stream, map, "speed", 30); writeProperty(stream, map, "persistent", false); writeProperty(stream, map, "clearDisplayBuffer", true); + writeProperty(stream, map, "clearViewBackground", false); + + // Check if views are defined + bool enableViews = checkIfViewsDefined(map); + writeProperty(stream, map, "enableViews", enableViews); stream.writeTextElement("isometric", toString(map->orientation() == Map::Orientation::Isometric)); + // Write out views + // Last view in Object layer is the first view in the room + LayerIterator iterator(map); + if (enableViews) { + stream.writeStartElement("views"); + int viewCount = 0; + while (const Layer *layer = iterator.next()) { + + if (layer->layerType() != Layer::ObjectGroupType) + continue; + + const ObjectGroup *objectLayer = static_cast(layer); + + for (const MapObject *object : objectLayer->objects()) { + const QString type = effectiveObjectType(object); + if (type != "view") + continue; + + // GM only has 8 views so drop anything more than that + if (viewCount > 7) + break; + + viewCount++; + stream.writeStartElement("view"); + + stream.writeAttribute("visible", toString(object->isVisible())); + stream.writeAttribute("objName", QString(optionalProperty(object, "objName", QString()))); + QPointF pos = object->position(); + // Note: GM only supports ints for positioning + // so views could be off if user doesn't align to whole number + stream.writeAttribute("xview", QString::number(qRound(pos.x()))); + stream.writeAttribute("yview", QString::number(qRound(pos.y()))); + stream.writeAttribute("wview", QString::number(qRound(object->width()))); + stream.writeAttribute("hview", QString::number(qRound(object->height()))); + // Round these incase user adds properties as floats and not ints + stream.writeAttribute("xport", QString::number(qRound(optionalProperty(object, "xport", 0.0)))); + stream.writeAttribute("yport", QString::number(qRound(optionalProperty(object, "yport", 0.0)))); + stream.writeAttribute("wport", QString::number(qRound(optionalProperty(object, "wport", 1024.0)))); + stream.writeAttribute("hport", QString::number(qRound(optionalProperty(object, "hport", 768.0)))); + stream.writeAttribute("hborder", QString::number(qRound(optionalProperty(object, "hborder", 32.0)))); + stream.writeAttribute("vborder", QString::number(qRound(optionalProperty(object, "vborder", 32.0)))); + stream.writeAttribute("hspeed", QString::number(qRound(optionalProperty(object, "hspeed", -1.0)))); + stream.writeAttribute("vspeed", QString::number(qRound(optionalProperty(object, "vspeed", -1.0)))); + + stream.writeEndElement(); + } + } + + stream.writeEndElement(); + } + stream.writeStartElement("instances"); QSet usedNames; int layerCount = 0; // Write out object instances - LayerIterator iterator(map); + iterator.toFront(); while (const Layer *layer = iterator.next()) { ++layerCount; @@ -132,6 +208,8 @@ bool GmxPlugin::write(const Map *map, const QString &fileName) const QString type = effectiveObjectType(object); if (type.isEmpty()) continue; + if (type == "view") + continue; stream.writeStartElement("instance"); From 0ef5add6d311a55307d9272ad03fe73cebcc246c Mon Sep 17 00:00:00 2001 From: Benjamin Trotter Date: Sat, 24 Jun 2017 20:13:35 -0700 Subject: [PATCH 07/21] Style update --- src/libtiled/mapreader.cpp | 15 +++++++-------- src/libtiled/mapwriter.cpp | 20 ++++++++++---------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/libtiled/mapreader.cpp b/src/libtiled/mapreader.cpp index b84c66f05b..61fc9e2e8b 100644 --- a/src/libtiled/mapreader.cpp +++ b/src/libtiled/mapreader.cpp @@ -355,7 +355,7 @@ SharedTileset MapReaderPrivate::readTileset() } } else if (xml.name() == QLatin1String("terraintypes")) { readTilesetTerrainTypes(*tileset); - } else if (xml.name() == QLatin1String("wangSets")) { + } else if (xml.name() == QLatin1String("wangsets")) { readTilesetWangSet(*tileset); } else { readUnknownElement(); @@ -434,15 +434,14 @@ void MapReaderPrivate::readTilesetTile(Tileset &tileset) tile->setObjectGroup(readObjectGroup()); } else if (xml.name() == QLatin1String("animation")) { tile->setFrames(readAnimationFrames()); - } else if(xml.name() == QLatin1String("wangInfo")) { + } else if(xml.name() == QLatin1String("wanginfo")) { const QXmlStreamAttributes wangAtts = xml.attributes(); - WangSet *wangSet = tileset.wangSet(wangAtts.value(QLatin1String("setIndex")).toInt()); - unsigned wangId = wangAtts.value(QLatin1String("wangId")).toUInt(); + WangSet *wangset = tileset.wangSet(wangAtts.value(QLatin1String("setindex")).toInt()); + unsigned wangid = wangAtts.value(QLatin1String("wangid")).toUInt(); - wangSet->addTile(tile, wangId); + wangset->addTile(tile, wangid); - //not sure if this is necessary... seens not to work without xml.skipCurrentElement(); } else { readUnknownElement(); @@ -580,10 +579,10 @@ void MapReaderPrivate::readTilesetTerrainTypes(Tileset &tileset) void MapReaderPrivate::readTilesetWangSet(Tileset &tileset) { - Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("wangSets")); + Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("wangsets")); while (xml.readNextStartElement()) { - if (xml.name() == QLatin1String("wangSet")) { + if (xml.name() == QLatin1String("wangset")) { const QXmlStreamAttributes atts = xml.attributes(); QString name = atts.value(QLatin1String("name")).toString(); int edges = atts.value(QLatin1String("edges")).toInt(); diff --git a/src/libtiled/mapwriter.cpp b/src/libtiled/mapwriter.cpp index 1ff8608e65..9cb9c9a681 100644 --- a/src/libtiled/mapwriter.cpp +++ b/src/libtiled/mapwriter.cpp @@ -365,19 +365,19 @@ void MapWriterPrivate::writeTileset(QXmlStreamWriter &w, const Tileset &tileset, // Write the wangsets if (tileset.wangSetCount() > 0) { - w.writeStartElement(QLatin1String("wangSets")); + w.writeStartElement(QLatin1String("wangsets")); for (int i = 0; i < tileset.wangSetCount(); ++i) { const WangSet *ws = tileset.wangSet(i); - w.writeStartElement(QLatin1String("wangSet")); + w.writeStartElement(QLatin1String("wangset")); w.writeAttribute(QLatin1String("name"),ws->name()); w.writeAttribute(QLatin1String("edges"),QString::number(ws->edgeColors())); w.writeAttribute(QLatin1String("corners"),QString::number(ws->cornerColors())); w.writeAttribute(QLatin1String("tile"),QString::number(ws->imageTileId())); - w.writeEndElement(); // + w.writeEndElement(); // } - w.writeEndElement(); // + w.writeEndElement(); // } // Write the properties for those tiles that have them @@ -440,15 +440,15 @@ void MapWriterPrivate::writeTileset(QXmlStreamWriter &w, const Tileset &tileset, w.writeEndElement(); // } for (int i = 0; i < tileset.wangSetCount(); ++i) { - unsigned wangId = tileset.wangSet(i)->wangIdOfTile(tile); + unsigned wangid = tileset.wangSet(i)->wangIdOfTile(tile); - if(wangId) { - w.writeStartElement(QLatin1String("wangInfo")); - w.writeAttribute(QLatin1String("setIndex"), QString::number(i)); + if(wangid) { + w.writeStartElement(QLatin1String("wanginfo")); + w.writeAttribute(QLatin1String("setindex"), QString::number(i)); //could be made more readable by spacing out the wangId into each corner. - w.writeAttribute(QLatin1String("wangId"), QString::number(wangId)); - w.writeEndElement(); // + w.writeAttribute(QLatin1String("wangid"), QString::number(wangid)); + w.writeEndElement(); // } } From 74dbae3b01cb5c1d6e7c6fbbf0950affd510e462 Mon Sep 17 00:00:00 2001 From: Benjamin Trotter Date: Tue, 27 Jun 2017 09:25:03 -0700 Subject: [PATCH 08/21] Foundation for adding UI support to wangTile assignment --- .../qtc_Desktop__bdef64c0-debug.bg | Bin 0 -> 27873 bytes src/libtiled/wangset.h | 2 + src/tiled/mapdocument.h | 9 + src/tiled/tiled.qbs | 8 + src/tiled/tilesetdocument.cpp | 37 +++ src/tiled/tilesetdocument.h | 10 + src/tiled/tileseteditor.cpp | 46 ++- src/tiled/tileseteditor.h | 9 + src/tiled/tilesetwangsetmodel.cpp | 166 ++++++++++ src/tiled/tilesetwangsetmodel.h | 97 ++++++ src/tiled/wangdock.cpp | 296 ++++++++++++++++++ src/tiled/wangdock.h | 92 ++++++ src/tiled/wangsetmodel.cpp | 224 +++++++++++++ src/tiled/wangsetmodel.h | 83 +++++ src/tiled/wangsetview.cpp | 127 ++++++++ src/tiled/wangsetview.h | 60 ++++ 16 files changed, 1264 insertions(+), 2 deletions(-) create mode 100644 src/build-tiled-Desktop_Qt_5_9_0_MinGW_32bit-Debug/qtc_Desktop__bdef64c0-debug/qtc_Desktop__bdef64c0-debug.bg create mode 100644 src/tiled/tilesetwangsetmodel.cpp create mode 100644 src/tiled/tilesetwangsetmodel.h create mode 100644 src/tiled/wangdock.cpp create mode 100644 src/tiled/wangdock.h create mode 100644 src/tiled/wangsetmodel.cpp create mode 100644 src/tiled/wangsetmodel.h create mode 100644 src/tiled/wangsetview.cpp create mode 100644 src/tiled/wangsetview.h diff --git a/src/build-tiled-Desktop_Qt_5_9_0_MinGW_32bit-Debug/qtc_Desktop__bdef64c0-debug/qtc_Desktop__bdef64c0-debug.bg b/src/build-tiled-Desktop_Qt_5_9_0_MinGW_32bit-Debug/qtc_Desktop__bdef64c0-debug/qtc_Desktop__bdef64c0-debug.bg new file mode 100644 index 0000000000000000000000000000000000000000..8eefeb19a4207f8499b84b18e2d894ef657b242d GIT binary patch literal 27873 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 literal 0 HcmV?d00001 diff --git a/src/libtiled/wangset.h b/src/libtiled/wangset.h index 76fc0c298a..735cbfac48 100644 --- a/src/libtiled/wangset.h +++ b/src/libtiled/wangset.h @@ -157,3 +157,5 @@ class TILEDSHARED_EXPORT WangSet : public Object }; } // namespace Tiled + +Q_DECLARE_METATYPE(Tiled::WangSet*) diff --git a/src/tiled/mapdocument.h b/src/tiled/mapdocument.h index 39d6c7eeb3..9c9833e811 100644 --- a/src/tiled/mapdocument.h +++ b/src/tiled/mapdocument.h @@ -45,12 +45,14 @@ class MapRenderer; class MapFormat; class Terrain; class Tile; +class WangSet; namespace Internal { class LayerModel; class MapObjectModel; class TerrainModel; +class WangSetModel; class TileSelectionModel; /** @@ -166,6 +168,8 @@ class MapDocument : public Document TerrainModel *terrainModel() const { return mTerrainModel; } + WangSetModel *wangSetModel() const { return mWangSetModel; } + /** * Returns the map renderer. */ @@ -289,6 +293,10 @@ class MapDocument : public Document void tilesetTerrainAdded(Tileset *tileset, int terrainId); void tilesetTerrainAboutToBeRemoved(Tileset *tileset, Terrain *terrain); void tilesetTerrainRemoved(Tileset *tileset, Terrain *terrain); + void tilesetWangSetAboutToBeAdded(Tileset *tileset); + void tilesetWangSetAdded(Tileset *tileset); + void tilesetWangSetAboutToBeRemoved(Tileset *tileset, WangSet *wangSet); + void tilesetWangSetRemoved(Tileset *tileset); private slots: void onObjectsRemoved(const QList &objects); @@ -323,6 +331,7 @@ private slots: Layer* mCurrentLayer; MapObjectModel *mMapObjectModel; TerrainModel *mTerrainModel; + WangSetModel *mWangSetModel; }; diff --git a/src/tiled/tiled.qbs b/src/tiled/tiled.qbs index 75e6e3b764..c59edb28b5 100644 --- a/src/tiled/tiled.qbs +++ b/src/tiled/tiled.qbs @@ -389,6 +389,8 @@ QtGuiApplication { "tilesetterrainmodel.h", "tilesetview.cpp", "tilesetview.h", + "tilesetwangsetmodel.cpp", + "tilesetwangsetmodel.h", "tilestamp.cpp", "tilestamp.h", "tilestampmanager.cpp", @@ -412,6 +414,12 @@ QtGuiApplication { "varianteditorfactory.h", "variantpropertymanager.cpp", "variantpropertymanager.h", + "wangdock.cpp", + "wangdock.h", + "wangsetmodel.cpp", + "wangsetmodel.h", + "wangsetview.cpp", + "wangsetview.h", "zoomable.cpp", "zoomable.h", ] diff --git a/src/tiled/tilesetdocument.cpp b/src/tiled/tilesetdocument.cpp index d76dacd826..594bc74c34 100644 --- a/src/tiled/tilesetdocument.cpp +++ b/src/tiled/tilesetdocument.cpp @@ -23,10 +23,12 @@ #include "mapdocument.h" #include "map.h" #include "terrain.h" +#include "wangset.h" #include "tile.h" #include "tilesetformat.h" #include "tilesetmanager.h" #include "tilesetterrainmodel.h" +#include "tilesetwangsetmodel.h" #include #include @@ -58,6 +60,7 @@ TilesetDocument::TilesetDocument(const SharedTileset &tileset, const QString &fi : Document(TilesetDocumentType, fileName) , mTileset(tileset) , mTerrainModel(new TilesetTerrainModel(this, this)) + , mWangSetModel(new TilesetWangSetModel(this, this)) { mCurrentObject = tileset.data(); @@ -82,6 +85,16 @@ TilesetDocument::TilesetDocument(const SharedTileset &tileset, const QString &fi connect(mTerrainModel, &TilesetTerrainModel::terrainRemoved, this, &TilesetDocument::onTerrainRemoved); + + connect(mWangSetModel, &TilesetWangSetModel::wangSetAboutToBeAdded, + this, &TilesetDocument::onWangSetAboutToBeAdded); + connect(mWangSetModel, &TilesetWangSetModel::wangSetAdded, + this, &TilesetDocument::onWangSetAdded); + connect(mWangSetModel, &TilesetWangSetModel::wangSetAboutToBeRemoved, + this, &TilesetDocument::onWangSetAboutToBeRemoved); + connect(mWangSetModel, &TilesetWangSetModel::wangSetRemoved, + this, &TilesetDocument::onWangSetRemoved); + TilesetManager *tilesetManager = TilesetManager::instance(); tilesetManager->addReference(tileset); } @@ -362,5 +375,29 @@ void TilesetDocument::onTerrainRemoved(Terrain *terrain) emit mapDocument->tilesetTerrainRemoved(mTileset.data(), terrain); } +void TilesetDocument::onWangSetAboutToBeAdded(Tileset *tileset) +{ + for (MapDocument *mapDocument : mapDocuments()) + emit mapDocument->tilesetWangSetAboutToBeAdded(tileset); +} + +void TilesetDocument::onWangSetAdded(Tileset *tileset) +{ + for (MapDocument *mapDocument : mapDocuments()) + emit mapDocument->tilesetWangSetAdded(tileset); +} + +void TilesetDocument::onWangSetAboutToBeRemoved(WangSet *wangSet) +{ + for (MapDocument *mapDocument : mapDocuments()) + emit mapDocument->tilesetWangSetAboutToBeRemoved(mTileset.data(), wangSet); +} + +void TilesetDocument::onWangSetRemoved() +{ + for (MapDocument *mapDocument : mapDocuments()) + emit mapDocument->tilesetWangSetRemoved(mTileset.data()); +} + } // namespace Internal } // namespace Tiled diff --git a/src/tiled/tilesetdocument.h b/src/tiled/tilesetdocument.h index 6fa27ecf7d..6ed0942395 100644 --- a/src/tiled/tilesetdocument.h +++ b/src/tiled/tilesetdocument.h @@ -33,6 +33,7 @@ namespace Internal { class MapDocument; class TilesetTerrainModel; +class TilesetWangSetModel; /** * Represents an editable tileset. @@ -85,6 +86,7 @@ class TilesetDocument : public Document QList currentObjects() const override; TilesetTerrainModel *terrainModel() const { return mTerrainModel; } + TilesetWangSetModel *wangSetModel() const { return mWangSetModel; } void setTileType(Tile *tile, const QString &type); void setTileImage(Tile *tile, const QPixmap &image, const QString &source); @@ -111,6 +113,8 @@ class TilesetDocument : public Document */ void tileTerrainChanged(const QList &tiles); + void tileWangSetChanged(const QList &tiles); + /** * Emitted when the terrain probability of a tile changed. */ @@ -142,11 +146,17 @@ private slots: void onTerrainAboutToBeRemoved(Terrain *terrain); void onTerrainRemoved(Terrain *terrain); + void onWangSetAboutToBeAdded(Tileset *tileset); + void onWangSetAdded(Tileset *tileset); + void onWangSetAboutToBeRemoved(WangSet *wangSet); + void onWangSetRemoved(); + private: SharedTileset mTileset; QList mMapDocuments; TilesetTerrainModel *mTerrainModel; + TilesetWangSetModel *mWangSetModel; QList mSelectedTiles; }; diff --git a/src/tiled/tileseteditor.cpp b/src/tiled/tileseteditor.cpp index 68440877cc..3e2b4b46e2 100644 --- a/src/tiled/tileseteditor.cpp +++ b/src/tiled/tileseteditor.cpp @@ -44,6 +44,8 @@ #include "tilesetview.h" #include "undodock.h" #include "utils.h" +#include "wangdock.h" +#include "wangset.h" #include "zoomable.h" #include @@ -166,6 +168,7 @@ TilesetEditor::TilesetEditor(QObject *parent) , mUndoDock(new UndoDock(mMainWindow)) , mTerrainDock(new TerrainDock(mMainWindow)) , mTileCollisionDock(new TileCollisionDock(mMainWindow)) + , mWangDock(new WangDock(mMainWindow)) , mZoomComboBox(new QComboBox) , mTileAnimationEditor(new TileAnimationEditor(mMainWindow)) , mCurrentTilesetDocument(nullptr) @@ -173,6 +176,7 @@ TilesetEditor::TilesetEditor(QObject *parent) { mTerrainDock->setVisible(false); mTileCollisionDock->setVisible(false); + mWangDock->setVisible(false); #if QT_VERSION >= 0x050600 mMainWindow->setDockOptions(mMainWindow->dockOptions() | QMainWindow::GroupedDragging); @@ -184,11 +188,13 @@ TilesetEditor::TilesetEditor(QObject *parent) mMainWindow->addDockWidget(Qt::LeftDockWidgetArea, mUndoDock); mMainWindow->addDockWidget(Qt::RightDockWidgetArea, mTerrainDock); mMainWindow->addDockWidget(Qt::RightDockWidgetArea, mTileCollisionDock); + mMainWindow->addDockWidget(Qt::RightDockWidgetArea, mWangDock); mUndoDock->setVisible(false); QAction *editTerrain = mTerrainDock->toggleViewAction(); QAction *editCollision = mTileCollisionDock->toggleViewAction(); + QAction *editWang = mWangDock->toggleViewAction(); mAddTiles->setIcon(QIcon(QLatin1String(":images/16x16/add.png"))); mRemoveTiles->setIcon(QIcon(QLatin1String(":images/16x16/remove.png"))); @@ -196,6 +202,8 @@ TilesetEditor::TilesetEditor(QObject *parent) editTerrain->setIconVisibleInMenu(false); editCollision->setIcon(QIcon(QLatin1String(":images/48x48/tile-collision-editor.png"))); editCollision->setIconVisibleInMenu(false); + editWang->setIcon(QIcon(QLatin1String(":images/24x24/terrain.png"))); + editWang->setIconVisibleInMenu(false); Utils::setThemeIcon(mAddTiles, "add"); Utils::setThemeIcon(mRemoveTiles, "remove"); @@ -207,6 +215,7 @@ TilesetEditor::TilesetEditor(QObject *parent) mTilesetToolBar->addSeparator(); mTilesetToolBar->addAction(editTerrain); mTilesetToolBar->addAction(editCollision); + mTilesetToolBar->addAction(editWang); mMainWindow->statusBar()->addPermanentWidget(mZoomComboBox); @@ -219,11 +228,16 @@ TilesetEditor::TilesetEditor(QObject *parent) connect(editTerrain, &QAction::toggled, this, &TilesetEditor::setEditTerrain); connect(editCollision, &QAction::toggled, this, &TilesetEditor::setEditCollision); + connect(editWang, &QAction::toggled, this, &TilesetEditor::setEditWang); connect(mTerrainDock, &TerrainDock::currentTerrainChanged, this, &TilesetEditor::currentTerrainChanged); connect(mTerrainDock, &TerrainDock::addTerrainTypeRequested, this, &TilesetEditor::addTerrainType); connect(mTerrainDock, &TerrainDock::removeTerrainTypeRequested, this, &TilesetEditor::removeTerrainType); + connect(mWangDock, &WangDock::currentWangSetChanged, this, &TilesetEditor::currentWangSetChanged); + connect(mWangDock, &WangDock::addWangSetRequested, this, &TilesetEditor::addWangSet); + connect(mWangDock, &WangDock::removeWangSetRequested, this, &TilesetEditor::removeWangSet); + connect(this, &TilesetEditor::currentTileChanged, mTileAnimationEditor, &TileAnimationEditor::setTile); connect(this, &TilesetEditor::currentTileChanged, @@ -352,6 +366,7 @@ void TilesetEditor::setCurrentDocument(Document *document) mTileAnimationEditor->setTilesetDocument(tilesetDocument); mTileCollisionDock->setTilesetDocument(tilesetDocument); mTerrainDock->setDocument(document); + mWangDock->setDocument(document); mCurrentTilesetDocument = tilesetDocument; @@ -387,7 +402,8 @@ QList TilesetEditor::dockWidgets() const mPropertiesDock, mUndoDock, mTerrainDock, - mTileCollisionDock + mTileCollisionDock, + mWangDock }; } @@ -737,8 +753,10 @@ void TilesetEditor::setEditTerrain(bool editTerrain) if (TilesetView *view = currentTilesetView()) view->setEditTerrain(editTerrain); - if (editTerrain) + if (editTerrain) { mTileCollisionDock->setVisible(false); + mWangDock->setVisible(false); + } } void TilesetEditor::currentTerrainChanged(const Terrain *terrain) @@ -760,11 +778,20 @@ void TilesetEditor::setEditCollision(bool editCollision) if (editCollision) { mPropertiesDock->setDocument(mTileCollisionDock->dummyMapDocument()); mTerrainDock->setVisible(false); + mWangDock->setVisible(false); } else { mPropertiesDock->setDocument(mCurrentTilesetDocument); } } +void TilesetEditor::setEditWang(bool editWang) +{ + if (editWang) { + mTerrainDock->setVisible(false); + mTileCollisionDock->setVisible(false); + } +} + void TilesetEditor::addTerrainType() { Tileset *tileset = currentTileset(); @@ -826,6 +853,21 @@ void TilesetEditor::removeTerrainType() undoStack->endMacro(); } +void TilesetEditor::currentWangSetChanged(const WangSet *wangSet) +{ + +} + +void TilesetEditor::addWangSet() +{ + +} + +void TilesetEditor::removeWangSet() +{ + +} + void TilesetEditor::setTerrainImage(Tile *tile) { Terrain *terrain = mTerrainDock->currentTerrain(); diff --git a/src/tiled/tileseteditor.h b/src/tiled/tileseteditor.h index 424e9ac43e..d73c7e7e06 100644 --- a/src/tiled/tileseteditor.h +++ b/src/tiled/tileseteditor.h @@ -36,6 +36,7 @@ namespace Tiled { class Terrain; class Tile; class Tileset; +class WangSet; namespace Internal { @@ -47,6 +48,7 @@ class TilesetDocument; class TilesetEditorWindow; class TilesetView; class UndoDock; +class WangDock; class Zoomable; class TilesetEditor : public Editor @@ -106,12 +108,18 @@ private slots: void setEditCollision(bool editCollision); + void setEditWang(bool editWang); + void updateAddRemoveActions(); void addTerrainType(); void removeTerrainType(); void setTerrainImage(Tile *tile); + void currentWangSetChanged(const WangSet *wangSet); + void addWangSet(); + void removeWangSet(); + private: void setCurrentTile(Tile *tile); @@ -129,6 +137,7 @@ private slots: UndoDock *mUndoDock; TerrainDock *mTerrainDock; TileCollisionDock *mTileCollisionDock; + WangDock *mWangDock; QComboBox *mZoomComboBox; TileAnimationEditor *mTileAnimationEditor; diff --git a/src/tiled/tilesetwangsetmodel.cpp b/src/tiled/tilesetwangsetmodel.cpp new file mode 100644 index 0000000000..5f41836ef5 --- /dev/null +++ b/src/tiled/tilesetwangsetmodel.cpp @@ -0,0 +1,166 @@ +/* + * tilesetwangsetmodel.cpp + * Copyright 2017, Benjamin Trotter + * This file is part of libtiled. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tilesetwangsetmodel.h" + +#include "tilesetdocument.h" +#include "wangset.h" +#include "tileset.h" +#include "tile.h" + +using namespace Tiled; +using namespace Internal; + +TilesetWangSetModel::TilesetWangSetModel(TilesetDocument *mapDocument, + QObject *parent): + QAbstractListModel(parent), + mTilesetDocument(mapDocument) +{ +} + +TilesetWangSetModel::~TilesetWangSetModel() +{ +} + +QModelIndex TilesetWangSetModel::index(WangSet *wangSet) +{ + Tileset *tileset = wangSet->tileset(); + int row = tileset->wangSets().indexOf(wangSet); + + return index(row, 0); +} + +int TilesetWangSetModel::rowCount(const QModelIndex &parent) const +{ + if(!parent.isValid()) + return mTilesetDocument->tileset()->wangSetCount(); + + return 0; +} + +int TilesetWangSetModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + + return 1; +} + + +QVariant TilesetWangSetModel::data(const QModelIndex &index, int role) const +{ + if(WangSet *wangSet = wangSetAt(index)) { + switch (role) { + case Qt::DisplayRole: + case Qt::EditRole: + return wangSet->name(); + case Qt::DecorationRole: + if (Tile *imageTile = wangSet->imageTile()) + return imageTile->image(); + break; + case WangSetRole: + return QVariant::fromValue(wangSet); + } + } + + return QVariant(); +} + +bool TilesetWangSetModel::setData(const QModelIndex &index, + const QVariant &value, + int role) +{ + //TO ADD RENAME CAPABILITY + return false; +} + +Qt::ItemFlags TilesetWangSetModel::flags(const QModelIndex &index) const +{ + Qt::ItemFlags rc = QAbstractItemModel::flags(index); + if (index.isValid()) // can edit wangSet names + rc |= Qt::ItemIsEditable; + return rc; +} + +WangSet *TilesetWangSetModel::wangSetAt(const QModelIndex &index) const +{ + if (index.isValid()) + return mTilesetDocument->tileset()->wangSet(index.row()); + + return nullptr; +} + +void TilesetWangSetModel::insertWangSet(WangSet *wangSet) +{ + Tileset *tileset = mTilesetDocument->tileset().data(); + int row = tileset->wangSetCount(); + + emit wangSetAboutToBeAdded(tileset); + + beginInsertRows(QModelIndex(), row, row); + tileset->insertWangSet(wangSet); + endInsertRows(); + + emit wangSetAdded(tileset); +} + +WangSet *TilesetWangSetModel::takeWangSetAt(int index) +{ + Tileset *tileset = mTilesetDocument->tileset().data(); + + emit wangSetAboutToBeRemoved(tileset->wangSet(index)); + + beginRemoveRows(QModelIndex(), index, index); + WangSet *wangset = tileset->takeWangSetAt(index); + endRemoveRows(); + + emit wangSetRemoved(); + + return wangset; +} + +void TilesetWangSetModel::setWangSetName(int index, const QString &name) +{ + Tileset *tileset = mTilesetDocument->tileset().data(); + WangSet *wangSet = tileset->wangSet(index); + wangSet->setName(name); + emitWangSetChange(wangSet); +} + +void TilesetWangSetModel::setWangSetImage(int index, int tileId) +{ + Tileset *tileset = mTilesetDocument->tileset().data(); + WangSet *wangSet = tileset->wangSet(index); + wangSet->setImageTileId(tileId); + emitWangSetChange(wangSet); +} + +void TilesetWangSetModel::emitWangSetChange(WangSet *wangSet) +{ + const QModelIndex index = TilesetWangSetModel::index(wangSet); + emit dataChanged(index, index); + emit wangSetChanged(wangSet, index.row()); +} diff --git a/src/tiled/tilesetwangsetmodel.h b/src/tiled/tilesetwangsetmodel.h new file mode 100644 index 0000000000..59633ca09b --- /dev/null +++ b/src/tiled/tilesetwangsetmodel.h @@ -0,0 +1,97 @@ +/* + * tilesetwangsetmodel.h + * Copyright 2017, Benjamin Trotter + * This file is part of libtiled. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include + +namespace Tiled { + +class Tileset; +class WangSet; + +namespace Internal { + +class TilesetDocument; + +class TilesetWangSetModel : public QAbstractListModel +{ + Q_OBJECT + +public: + enum UserRoles { + WangSetRole = Qt::UserRole + }; + + TilesetWangSetModel(TilesetDocument *mapDocument, + QObject *parent = nullptr); + ~TilesetWangSetModel(); + + using QAbstractListModel::index; + QModelIndex index(WangSet *wangSet); + + /** + * Returns the number of rows. For the root, this is the number of wangSets + * in the tileset. + */ + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + + QVariant data(const QModelIndex &index, + int role = Qt::DisplayRole) const override; + + bool setData(const QModelIndex &index, const QVariant &value, int role) override; + + Qt::ItemFlags flags(const QModelIndex &index) const override; + + WangSet *wangSetAt(const QModelIndex &index) const; + + void insertWangSet(WangSet *wangSet); + WangSet *takeWangSetAt(int index); + void setWangSetName(int index, const QString &name); + void setWangSetImage(int index, int tileId); + +signals: + void wangSetAboutToBeAdded(Tileset *tileset); + void wangSetAdded(Tileset *tileset); + void wangSetAboutToBeRemoved(WangSet *wangSet); + void wangSetRemoved(); + + /** + * Emitted when either the name or the image of a terrain changed. + */ + void wangSetChanged(WangSet *wangSet, int index); + +private: + void emitWangSetChange(WangSet *wangSet); + + TilesetDocument *mTilesetDocument; +}; + +} // namespace Internal +} // namespace Tiled diff --git a/src/tiled/wangdock.cpp b/src/tiled/wangdock.cpp new file mode 100644 index 0000000000..b06b7f36b0 --- /dev/null +++ b/src/tiled/wangdock.cpp @@ -0,0 +1,296 @@ +/* + * wangdock.cpp + * Copyright 2017, Benjamin Trotter + * + * This file is part of Tiled. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "wangdock.h" +#include "wangsetview.h" +#include "wangsetmodel.h" +#include "documentmanager.h" +#include "map.h" +#include "mapdocument.h" +#include "tilesetdocument.h" +#include "tilesetwangsetmodel.h" +#include "utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Tiled; +using namespace Tiled::Internal; + +namespace Tiled { +namespace Internal { + +static WangSet *firstWangSet(MapDocument *MapDocument) +{ + for (const SharedTileset &tileset : MapDocument->map()->tilesets()) + if(tileset->wangSetCount() > 0) + return tileset->wangSet(0); + + return nullptr; +} + +static WangSet *firstWangSet(TilesetDocument *tilesetDocument) +{ + Tileset *tileset = tilesetDocument->tileset().data(); + if(tileset->wangSetCount() > 0) + return tileset->wangSet(0); + + return nullptr; +} + +class WangSetFilterModel : public QSortFilterProxyModel +{ +public: + WangSetFilterModel(QObject *parent = nullptr) + : QSortFilterProxyModel(parent) + { + } + + void setEnabled(bool enabled) { mEnabled = enabled; } + +protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override + { + if (!mEnabled) + return true; + if (sourceParent.isValid()) + return true; + + const QAbstractItemModel *model = sourceModel(); + const QModelIndex index = model->index(sourceRow, 0, sourceParent); + return index.isValid() && model->hasChildren(index); + } + + bool mEnabled; +}; + +} // namespace Internal +} // namespace Tiled + +WangDock::WangDock(QWidget *parent) + : QDockWidget(parent) + , mToolBar(new QToolBar(this)) + , mAddWangSet(new QAction(this)) + , mRemoveWangSet(new QAction(this)) + , mDocument(nullptr) + , mCurrentWangSet(nullptr) + , mProxyModel(new WangSetFilterModel(this)) + , mInitializing(false) +{ + setObjectName(QLatin1String("WangSetDock")); + + QWidget *w = new QWidget(this); + + mWangSetView = new WangSetView(nullptr); + mWangSetView->setModel(mProxyModel); + connect(mWangSetView->selectionModel(), &QItemSelectionModel::currentRowChanged, + this, &WangDock::refreshCurrentWangSet); + connect(mWangSetView, SIGNAL(pressed(QModelIndex)), + SLOT(indexPressed(QModelIndex))); + + connect(mProxyModel, SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(expandRows(QModelIndex,int,int))); + + mAddWangSet->setIcon(QIcon(QStringLiteral(":/images/22x22/add.png"))); + mRemoveWangSet->setIcon(QIcon(QStringLiteral(":/images/22x22/remove.png"))); + + Utils::setThemeIcon(mAddWangSet, "add"); + Utils::setThemeIcon(mRemoveWangSet, "remove"); + + mToolBar->setFloatable(false); + mToolBar->setMovable(false); + mToolBar->setIconSize(Utils::smallIconSize()); + + mToolBar->addAction(mAddWangSet); + mToolBar->addAction(mRemoveWangSet); + + QHBoxLayout *horizontal = new QHBoxLayout; + horizontal->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding)); + horizontal->addWidget(mToolBar); + + QVBoxLayout *vertical = new QVBoxLayout(w); + vertical->setMargin(0); + vertical->addWidget(mWangSetView); + vertical->addLayout(horizontal); + + connect(mAddWangSet, &QAction::triggered, + this, &WangDock::addWangSetRequested); + connect(mRemoveWangSet, &QAction::triggered, + this, &WangDock::removeWangSetRequested); + + setWidget(w); + retranslateUi(); +} + +WangDock::~WangDock() +{ +} + +static QAbstractItemModel *wangSetModel(Document *document) +{ + switch (document->type()) { + case Document::MapDocumentType: + return static_cast(document)->wangSetModel(); + case Document::TilesetDocumentType: + return static_cast(document)->wangSetModel(); + } + + return nullptr; +} + +void WangDock::setDocument(Document *document) +{ + if (mDocument == document) + return; + + if (mDocument) { + wangSetModel(mDocument)->disconnect(this); + mDocument->disconnect(this); + } + + mDocument = document; + mInitializing = true; + + if (auto mapDocument = qobject_cast(document)) { + WangSetModel *wangSetModel = mapDocument->wangSetModel(); + + mProxyModel->setEnabled(true); + mProxyModel->setSourceModel(wangSetModel); + mWangSetView->expandAll(); + + mToolBar->setVisible(false); + + } else if (auto tilesetDocument = qobject_cast(document)) { + TilesetWangSetModel *wangSetModel = tilesetDocument->wangSetModel(); + + mWangSetView->setTilesetDocument(tilesetDocument); + mProxyModel->setEnabled(false); + mProxyModel->setSourceModel(wangSetModel); + + setCurrentWangSet(firstWangSet(tilesetDocument)); + + mToolBar->setVisible(true); + + /* + * Removing a terrain usually changes the selected terrain without the + * selection changing rows, so we can't rely on the currentRowChanged + * signal. + */ + connect(wangSetModel, &TilesetWangSetModel::wangSetRemoved, + this, &WangDock::refreshCurrentWangSet); + + } else { + mProxyModel->setSourceModel(nullptr); + setCurrentWangSet(nullptr); + mToolBar->setVisible(false); + } + + mInitializing = false; +} + +void WangDock::editWangSetName(WangSet *wangSet) +{ + const QModelIndex index = wangSetIndex(wangSet); + QItemSelectionModel *selectionModel = mWangSetView->selectionModel(); + selectionModel->setCurrentIndex(index, + QItemSelectionModel::ClearAndSelect | + QItemSelectionModel::Rows); + mWangSetView->edit(index); +} + +void WangDock::changeEvent(QEvent *event) +{ + QDockWidget::changeEvent(event); + switch (event->type()) { + case QEvent::LanguageChange: + retranslateUi(); + break; + default: + break; + } +} + +void WangDock::refreshCurrentWangSet() +{ + QItemSelectionModel *selectionModel = mWangSetView->selectionModel(); + WangSet *wangSet = mWangSetView->wangSetAt(selectionModel->currentIndex()); + setCurrentWangSet(wangSet); +} + +void WangDock::indexPressed(const QModelIndex &index) +{ + if (WangSet *wangSet = mWangSetView->wangSetAt(index)) { + if (auto tilesetDocument = qobject_cast(mDocument)) + tilesetDocument->setCurrentObject((Object*)wangSet); + } +} + +void WangDock::expandRows(const QModelIndex &parent, int first, int last) +{ + if (parent.isValid()) + return; + + for (int row = first; row <= last; ++row) + mWangSetView->expand(mProxyModel->index(row, 0, parent)); +} + +void WangDock::setCurrentWangSet(WangSet *wangSet) +{ + if (mCurrentWangSet == wangSet) + return; + + mCurrentWangSet = wangSet; + + if (wangSet) { + mWangSetView->setCurrentIndex(wangSetIndex(wangSet)); + } else { + mWangSetView->selectionModel()->clearCurrentIndex(); + mWangSetView->selectionModel()->clearSelection(); + mCurrentWangSet = nullptr; + } + + if (wangSet && !mInitializing) { + if (auto tilesetDocument = qobject_cast(mDocument)) + tilesetDocument->setCurrentObject((Object*)wangSet); + } + + mRemoveWangSet->setEnabled(wangSet); + + emit currentWangSetChanged(mCurrentWangSet); +} + +void WangDock::retranslateUi() +{ + setWindowTitle(tr("Wang Sets")); + + mAddWangSet->setText(tr("Add Wang Set")); + mRemoveWangSet->setText(tr("Remove Wang Set")); +} + +QModelIndex WangDock::wangSetIndex(WangSet *wangSet) const +{ + return qobject_cast(mProxyModel->sourceModel())->index(wangSet); +} diff --git a/src/tiled/wangdock.h b/src/tiled/wangdock.h new file mode 100644 index 0000000000..b432bc1696 --- /dev/null +++ b/src/tiled/wangdock.h @@ -0,0 +1,92 @@ +/* + * wangdock.h + * Copyright 2017, Benjamin Trotter + * + * This file is part of Tiled. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#pragma once + +#include +#include + +class QModelIndex; +class QPushButton; +class QToolBar; + +namespace Tiled { + +class WangSet; + +namespace Internal { + +class Document; +class WangSetFilterModel; +class WangSetView; +class WangSetModel; +class TilesetDocument; + +class WangDock : public QDockWidget +{ + Q_OBJECT + +public: + WangDock(QWidget *parent = nullptr); + + ~WangDock(); + + void setDocument(Document *document); + + WangSet *currentWangSet() const { return mCurrentWangSet; } + + void editWangSetName(WangSet *wangSet); + +signals: + void currentWangSetChanged(const WangSet *WangSet); + + void addWangSetRequested(); + void removeWangSetRequested(); + +public slots: + void setCurrentWangSet(WangSet *wangSet); + +protected: + void changeEvent(QEvent *event) override; + +private slots: + void refreshCurrentWangSet(); + void indexPressed(const QModelIndex &index); + void expandRows(const QModelIndex &parent, int first, int last); + +private: + void retranslateUi(); + + QModelIndex wangSetIndex(WangSet *wangSet) const; + + QToolBar *mToolBar; + QAction *mAddWangSet; + QAction *mRemoveWangSet; + + Document *mDocument; + WangSetView *mWangSetView; + WangSet *mCurrentWangSet; + WangSetFilterModel *mProxyModel; + + bool mInitializing; +}; + +} // namespace Internal +} // namespace Tiled diff --git a/src/tiled/wangsetmodel.cpp b/src/tiled/wangsetmodel.cpp new file mode 100644 index 0000000000..0dfcc3252e --- /dev/null +++ b/src/tiled/wangsetmodel.cpp @@ -0,0 +1,224 @@ +/* + * wangsetmodel.cpp + * Copyright 2017, Benjamin Trotter + * + * This file is part of Tiled. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "wangsetmodel.h" + +#include "containerhelpers.h" +#include "map.h" +#include "mapdocument.h" +#include "wangset.h" +#include "tileset.h" +#include "tile.h" + +#include +#include +#include + +using namespace Tiled; +using namespace Tiled::Internal; + +WangSetModel::WangSetModel(MapDocument *mapDocument, + QObject *parent): + QAbstractItemModel(parent), + mMapDocument(mapDocument) +{ + connect(mapDocument, SIGNAL(tilesetAboutToBeAdded(int)), + this, SLOT(tilesetAboutToBeAdded(int))); + connect(mapDocument, SIGNAL(tilesetAdded(int,Tileset*)), + this, SLOT(tilesetAdded())); + connect(mapDocument, SIGNAL(tilesetAboutToBeRemoved(int)), + this, SLOT(tilesetAboutToBeRemoved(int))); + connect(mapDocument, SIGNAL(tilesetRemoved(Tileset*)), + this, SLOT(tilesetRemoved())); + connect(mapDocument, &MapDocument::tilesetNameChanged, + this, &WangSetModel::tilesetChanged); + + connect(mapDocument, &MapDocument::tilesetWangSetAboutToBeAdded, + this, &WangSetModel::wangSetAboutToBeAdded); + connect(mapDocument, &MapDocument::tilesetWangSetAdded, + this, &WangSetModel::wangSetAdded); + connect(mapDocument, &MapDocument::tilesetWangSetAboutToBeRemoved, + this, &WangSetModel::wangSetAboutToBeRemoved); + connect(mapDocument, &MapDocument::tilesetWangSetRemoved, + this, &WangSetModel::wangSetRemoved); +} + +WangSetModel::~WangSetModel() +{ +} + +QModelIndex WangSetModel::index(int row, int column, const QModelIndex &parent) const +{ + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + if (!parent.isValid()) + return createIndex(row, column); + else if (Tileset *tileset = tilesetAt(parent)) + return createIndex(row, column, tileset); + + return QModelIndex(); +} + +QModelIndex WangSetModel::index(Tileset *tileSet) const +{ + int row = indexOf(mMapDocument->map()->tilesets(), tileSet); + Q_ASSERT(row != -1); + return createIndex(row, 0); +} + +QModelIndex WangSetModel::index(WangSet *wangSet) const +{ + Tileset *tileset = wangSet->tileset(); + int row = tileset->wangSets().indexOf(wangSet); + return createIndex(row, 0, tileset); +} + +QModelIndex WangSetModel::parent(const QModelIndex &child) const +{ + if (WangSet *wangSet = wangSetAt(child)) + return index(wangSet->tileset()); + + return QModelIndex(); +} + +int WangSetModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) + return mMapDocument->map()->tilesetCount(); + else if (Tileset *tileset = tilesetAt(parent)) + return tileset->wangSetCount(); + + return 0; +} + +int WangSetModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return 1; +} + +QVariant WangSetModel::data(const QModelIndex &index, int role) const +{ + if (WangSet *wangSet = wangSetAt(index)) { + switch (role) { + case Qt::DisplayRole: + case Qt::EditRole: + return wangSet->name(); + case Qt::DecorationRole: + if (Tile *tile = wangSet->imageTile()) + return tile->image(); + break; + case WangSetRole: + return QVariant::fromValue(wangSet); + } + } else if (Tileset *tileset = tilesetAt(index)) { + switch (role) { + case Qt::DisplayRole: + return tileset->name(); + case Qt::SizeHintRole: + return QSize(1, 32); + case Qt::FontRole: { + QFont font = QApplication::font(); + font.setBold(true); + return font; + } + case Qt::BackgroundRole: { + QColor bg = QApplication::palette().alternateBase().color(); + return bg;//.darker(103); + } + } + } + + return QVariant(); +} + +Tileset *WangSetModel::tilesetAt(const QModelIndex &index) const +{ + if (!index.isValid()) + return nullptr; + if (index.parent().isValid()) // tilesets don't have parents + return nullptr; + if (index.row() >= mMapDocument->map()->tilesetCount()) + return nullptr; + + return mMapDocument->map()->tilesetAt(index.row()).data(); +} + +WangSet *WangSetModel::wangSetAt(const QModelIndex &index) const +{ + if (!index.isValid()) + return nullptr; + + if (Tileset *tileset = static_cast(index.internalPointer())) + return tileset->wangSet(index.row()); + + return nullptr; +} + +void WangSetModel::tilesetAboutToBeAdded(int index) +{ + beginInsertRows(QModelIndex(), index, index); +} + +void WangSetModel::tilesetAdded() +{ + endInsertRows(); +} + +void WangSetModel::tilesetAboutToBeRemoved(int index) +{ + beginRemoveRows(QModelIndex(), index, index); +} + +void WangSetModel::tilesetRemoved() +{ + endRemoveRows(); +} + +void WangSetModel::tilesetChanged(Tileset *tileset) +{ + const QModelIndex index = WangSetModel::index(tileset); + emit dataChanged(index, index); +} + +void WangSetModel::wangSetAboutToBeAdded(Tileset *tileset) +{ + QModelIndex parent = index(tileset); + beginInsertRows(parent, tileset->wangSetCount(), tileset->wangSetCount()); +} + +void WangSetModel::wangSetAdded(Tileset *tileset) +{ + endInsertRows(); + tilesetChanged(tileset); +} + +void WangSetModel::wangSetAboutToBeRemoved(Tileset *tileset, WangSet *wangSet) +{ + QModelIndex parent = index(tileset); + beginRemoveRows(parent, tileset->wangSets().indexOf(wangSet), tileset->wangSets().indexOf(wangSet)); +} + +void WangSetModel::wangSetRemoved(Tileset *tileset) +{ + endRemoveRows(); + tilesetChanged(tileset); +} diff --git a/src/tiled/wangsetmodel.h b/src/tiled/wangsetmodel.h new file mode 100644 index 0000000000..3e88504c67 --- /dev/null +++ b/src/tiled/wangsetmodel.h @@ -0,0 +1,83 @@ +/* + * wangsetmodel.h + * Copyright 2017, Benjamin Trotter + * + * This file is part of Tiled. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#pragma once + +#include +#include + +namespace Tiled { + +class Tileset; +class WangSet; + +namespace Internal { + +class MapDocument; + +class WangSetModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + enum UserRoles { + WangSetRole = Qt::UserRole + }; + + WangSetModel(MapDocument *mapDocument, + QObject *parent = nullptr); + + ~WangSetModel(); + + QModelIndex index(int row, int column, + const QModelIndex &parent) const override; + + QModelIndex index(Tileset *tileSet) const; + QModelIndex index(WangSet *wangSet) const; + + QModelIndex parent(const QModelIndex &child) const override; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + + QVariant data(const QModelIndex &index, + int role = Qt::DisplayRole) const override; + + Tileset *tilesetAt(const QModelIndex &index) const; + WangSet *wangSetAt(const QModelIndex &index) const; + +private slots: + void tilesetAboutToBeAdded(int index); + void tilesetAdded(); + void tilesetAboutToBeRemoved(int index); + void tilesetRemoved(); + void tilesetChanged(Tileset *tileset); + + void wangSetAboutToBeAdded(Tileset *tileset); + void wangSetAdded(Tileset *tileset); + void wangSetAboutToBeRemoved(Tileset *tileset, WangSet *wangSet); + void wangSetRemoved(Tileset *tileset); + +private: + MapDocument *mMapDocument; +}; + +} // namespace Internal +} // namespace Tiled diff --git a/src/tiled/wangsetview.cpp b/src/tiled/wangsetview.cpp new file mode 100644 index 0000000000..37c368199d --- /dev/null +++ b/src/tiled/wangsetview.cpp @@ -0,0 +1,127 @@ +/* + * wangsetview.cpp + * Copyright 2017, Benjamin Trotter + * + * This file is part of Tiled. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "wangsetview.h" + +#include "tileset.h" +#include "tilesetdocument.h" +#include "wangSet.h" +#include "wangsetmodel.h" +#include "utils.h" +#include "zoomable.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace Tiled; +using namespace Tiled::Internal; + +WangSetView::WangSetView(QWidget *parent) + : QTreeView(parent) + , mZoomable(new Zoomable(this)) + , mTilesetDocument(nullptr) +{ + setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + setRootIsDecorated(false); + setIndentation(0); + setItemsExpandable(false); + setHeaderHidden(true); + + connect(mZoomable, SIGNAL(scaleChanged(qreal)), SLOT(adjustScale())); +} + +void WangSetView::setTilesetDocument(TilesetDocument *tilesetDocument) +{ + mTilesetDocument = tilesetDocument; +} + +WangSet *WangSetView::wangSetAt(const QModelIndex &index) const +{ + const QVariant data = model()->data(index, WangSetModel::WangSetRole); + return data.value(); +} + +bool WangSetView::event(QEvent *event) +{ + if (event->type() == QEvent::ShortcutOverride) { + if (static_cast(event)->key() == Qt::Key_Tab) { + if (indexWidget(currentIndex())) { + event->accept(); + return true; + } + } + } + + return QTreeView::event(event); +} + +void WangSetView::wheelEvent(QWheelEvent *event) +{ + if (event->modifiers() & Qt::ControlModifier + && event->orientation() == Qt::Vertical) + { + mZoomable->handleWheelDelta(event->delta()); + return; + } + + QTreeView::wheelEvent(event); +} + +void WangSetView::contextMenuEvent(QContextMenuEvent *event) +{ + WangSet *wangSet = wangSetAt(indexAt(event->pos())); + if (!wangSet) + return; + if (!mTilesetDocument) + return; + + QMenu menu; + + QIcon propIcon(QLatin1String(":images/16x16/document-properties.png")); + + QAction *wangSetProperties = menu.addAction(propIcon, + tr("Wang Set &Properties...")); + Utils::setThemeIcon(wangSetProperties, "document-properties"); + + connect(wangSetProperties, SIGNAL(triggered()), + SLOT(editWangSetProperties())); + + menu.exec(event->globalPos()); +} + +void WangSetView::editWangSetProperties() +{ + WangSet *wangSet = wangSetAt(selectionModel()->currentIndex()); + + if(!wangSet) + return; + + //TODO ADD WANGSET PROPERTIES EDITING... +} + +void WangSetView::adjustScale() +{ +} + diff --git a/src/tiled/wangsetview.h b/src/tiled/wangsetview.h new file mode 100644 index 0000000000..4206734e4e --- /dev/null +++ b/src/tiled/wangsetview.h @@ -0,0 +1,60 @@ +/* + * wangsetview.h + * Copyright 2017, Benjamin Trotter + * + * This file is part of Tiled. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "wangsetmodel.h" + +#include + +namespace Tiled { +namespace Internal { + +class TilesetDocument; +class Zoomable; + +class WangSetView : public QTreeView +{ + Q_OBJECT + +public: + WangSetView(QWidget *parent = nullptr); + + void setTilesetDocument(TilesetDocument *tilesetDocument); + + Zoomable *zoomable() const { return mZoomable; } + + WangSet *wangSetAt(const QModelIndex &index) const; + +protected: + bool event(QEvent *event) override; + void wheelEvent(QWheelEvent *event) override; + void contextMenuEvent(QContextMenuEvent *event) override; + +private slots: + void editWangSetProperties(); + + void adjustScale(); + +private: + Zoomable *mZoomable; + TilesetDocument *mTilesetDocument; +}; + +} // namespace Internal +} // namespace Tiled From ff6c62421784d8feecf02373231cef3fbef771b3 Mon Sep 17 00:00:00 2001 From: Benjamin Trotter Date: Tue, 27 Jun 2017 17:12:50 -0700 Subject: [PATCH 09/21] Added a couple Undo commands, and made a bit more progress on the models and views. --- src/tiled/addremocewangset.cpp | 74 ++++++++++++++ src/tiled/addremovewangset.h | 72 +++++++++++++ src/tiled/renamewangset.cpp | 54 ++++++++++ src/tiled/renamewangset.h | 53 ++++++++++ src/tiled/tiled.qbs | 4 + src/tiled/tileseteditor.cpp | 15 +++ src/tiled/tilesetwangsetmodel.cpp | 21 +++- src/tiled/tilesetwangsetmodel.h | 2 +- src/tiled/wangdock.cpp | 59 ++++++----- src/tiled/wangdock.h | 4 +- src/tiled/wangsetmodel.cpp | 164 +++++++++++++++++++++--------- src/tiled/wangsetmodel.h | 31 +++--- src/tiled/wangsetview.h | 2 + 13 files changed, 456 insertions(+), 99 deletions(-) create mode 100644 src/tiled/addremocewangset.cpp create mode 100644 src/tiled/addremovewangset.h create mode 100644 src/tiled/renamewangset.cpp create mode 100644 src/tiled/renamewangset.h diff --git a/src/tiled/addremocewangset.cpp b/src/tiled/addremocewangset.cpp new file mode 100644 index 0000000000..48d5dd619a --- /dev/null +++ b/src/tiled/addremocewangset.cpp @@ -0,0 +1,74 @@ +/* + * addremovewangset.cpp + * Copyright 2017, Benjamin Trotter + * + * This file is part of Tiled. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "addremovewangset.h" + +#include "wangset.h" +#include "tileset.h" +#include "tilesetdocument.h" +#include "tilesetwangsetmodel.h" + +#include + +using namespace Tiled; +using namespace Internal; + +AddRemoveWangSet::AddRemoveWangSet(TilesetDocument *tilesetDocument, + int index, + WangSet *wangSet) + : mTilesetDocument(tilesetDocument) + , mIndex(index) + , mWangSet(wangSet) +{ +} + +AddRemoveWangSet::~AddRemoveWangSet() +{ + delete mWangSet; +} + +void AddRemoveWangSet::removeWangSet() +{ + Q_ASSERT(!mWangSet); + mWangSet = mTilesetDocument->wangSetModel()->takeWangSetAt(mIndex); +} + +void AddRemoveWangSet::addWangSet() +{ + Q_ASSERT(mWangSet); + mTilesetDocument->wangSetModel()->insertWangSet(mWangSet); + mWangSet = nullptr; +} + +AddWangSet::AddWangSet(TilesetDocument *tilesetDocument, WangSet *wangSet) + : AddRemoveWangSet(tilesetDocument, + wangSet->tileset()->wangSetCount(), + wangSet) +{ + setText(QCoreApplication::translate("Undo Commands", "Add Wang Set")); +} + +RemoveWangSet::RemoveWangSet(TilesetDocument *tilesetDocument, WangSet *wangset) + : AddRemoveWangSet(tilesetDocument, + tilesetDocument->wangSetModel()->index(wangset).row(), + nullptr) +{ + setText(QCoreApplication::translate("Undo Commands", "Remove Wang Set")); +} diff --git a/src/tiled/addremovewangset.h b/src/tiled/addremovewangset.h new file mode 100644 index 0000000000..1a25fcf567 --- /dev/null +++ b/src/tiled/addremovewangset.h @@ -0,0 +1,72 @@ +/* + * addremovewangset.h + * Copyright 2017, Benjamin Trotter + * + * This file is part of Tiled. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#pragma once + +#include + +namespace Tiled { + +class WangSet; +class Tileset; + +namespace Internal { + +class TilesetDocument; + +class AddRemoveWangSet : public QUndoCommand +{ +public: + AddRemoveWangSet(TilesetDocument *tilesetDocument, + int index, + WangSet *wangSet); + ~AddRemoveWangSet(); + +protected: + void addWangSet(); + void removeWangSet(); + +private: + TilesetDocument *mTilesetDocument; + Tileset *mTileset; + int mIndex; + WangSet *mWangSet; +}; + +class AddWangSet : public AddRemoveWangSet +{ +public: + AddWangSet(TilesetDocument *tilesetDocument, WangSet *wangSet); + + void undo() override { removeWangSet(); } + void redo() override { addWangSet(); } +}; + +class RemoveWangSet : public AddRemoveWangSet +{ +public: + RemoveWangSet(TilesetDocument *tilesetDocument, WangSet *wangset); + + void undo() override { addWangSet(); } + void redo() override { removeWangSet(); } +}; + +} // namespace internal +} // namespace tiled diff --git a/src/tiled/renamewangset.cpp b/src/tiled/renamewangset.cpp new file mode 100644 index 0000000000..4c3fc786da --- /dev/null +++ b/src/tiled/renamewangset.cpp @@ -0,0 +1,54 @@ +/* + * renamewangset.h + * Copyright 2017, Benjamin Trotte + * + * This file is part of Tiled. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "renamewangset.h" + +#include "wangset.h" +#include "tileset.h" +#include "tilesetdocument.h" +#include "tilesetwangsetmodel.h" + +#include + +using namespace Tiled; +using namespace Internal; + +RenameWangSet::RenameWangSet(TilesetDocument *tilesetDocument, + int index, + const QString &newName) + : QUndoCommand(QCoreApplication::translate("Undo Commands", + "Change Wang Set Name")) + , mWangSetModel(tilesetDocument->wangSetModel()) + , mTileset(tilesetDocument->tileset().data()) + , mIndex(index) + , mOldName(mTileset->wangSet(index)->name()) + , mNewName(newName) +{ +} + +void RenameWangSet::undo() +{ + mWangSetModel->setWangSetName(mIndex, mOldName); +} + +void RenameWangSet::redo() +{ + mWangSetModel->setWangSetName(mIndex, mNewName); +} diff --git a/src/tiled/renamewangset.h b/src/tiled/renamewangset.h new file mode 100644 index 0000000000..cffb08c620 --- /dev/null +++ b/src/tiled/renamewangset.h @@ -0,0 +1,53 @@ +/* + * renamewangset.h + * Copyright 2017, Benjamin Trotte + * + * This file is part of Tiled. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#pragma once + +#include + +namespace Tiled { + +class Tileset; + +namespace Internal { + +class TilesetDocument; +class TilesetWangSetModel; + +class RenameWangSet : public QUndoCommand +{ +public: + RenameWangSet(TilesetDocument *tilesetDocument, + int index, + const QString &newName); + + void undo() override; + void redo() override; + +private: + TilesetWangSetModel *mWangSetModel; + Tileset *mTileset; + int mIndex; + QString mOldName; + QString mNewName; +}; + +} // namespace Internal +} // namespace Tiled diff --git a/src/tiled/tiled.qbs b/src/tiled/tiled.qbs index c0291f3a07..825250ab6d 100644 --- a/src/tiled/tiled.qbs +++ b/src/tiled/tiled.qbs @@ -70,6 +70,7 @@ QtGuiApplication { "addpropertydialog.cpp", "addpropertydialog.h", "addpropertydialog.ui", + "addremocewangset.cpp", "addremovelayer.cpp", "addremovelayer.h", "addremovemapobject.cpp", @@ -80,6 +81,7 @@ QtGuiApplication { "addremovetileset.cpp", "addremovetileset.h", "addremovetiles.h", + "addremovewangset.h", "adjusttileindexes.cpp", "adjusttileindexes.h", "automapper.cpp", @@ -305,6 +307,8 @@ QtGuiApplication { "renamelayer.h", "renameterrain.cpp", "renameterrain.h", + "renamewangset.cpp", + "renamewangset.h", "reparentlayers.cpp", "reparentlayers.h", "replacetileset.cpp", diff --git a/src/tiled/tileseteditor.cpp b/src/tiled/tileseteditor.cpp index 3e2b4b46e2..4518b1fd46 100644 --- a/src/tiled/tileseteditor.cpp +++ b/src/tiled/tileseteditor.cpp @@ -23,6 +23,7 @@ #include "addremovemapobject.h" #include "addremoveterrain.h" #include "addremovetiles.h" +#include "addremovewangset.h" #include "changetileterrain.h" #include "erasetiles.h" #include "maintoolbar.h" @@ -860,12 +861,26 @@ void TilesetEditor::currentWangSetChanged(const WangSet *wangSet) void TilesetEditor::addWangSet() { + Tileset *tileset = currentTileset(); + if(!tileset) + return; + + //2 and 0 are default values for number of edges and corners TODO define this some where better? + WangSet *wangSet = new WangSet(tileset, 2, 0, QString(), -1); + wangSet->setName(tr("New Wang Set")); + + mCurrentTilesetDocument->undoStack()->push(new AddWangSet(mCurrentTilesetDocument, + wangSet)); + mWangDock->editWangSetName(wangSet); } void TilesetEditor::removeWangSet() { + WangSet *wangSet = mWangDock->currentWangSet(); + mCurrentTilesetDocument->undoStack()->push(new RemoveWangSet(mCurrentTilesetDocument, + wangSet)); } void TilesetEditor::setTerrainImage(Tile *tile) diff --git a/src/tiled/tilesetwangsetmodel.cpp b/src/tiled/tilesetwangsetmodel.cpp index 5f41836ef5..366401161e 100644 --- a/src/tiled/tilesetwangsetmodel.cpp +++ b/src/tiled/tilesetwangsetmodel.cpp @@ -28,6 +28,7 @@ #include "tilesetwangsetmodel.h" #include "tilesetdocument.h" +#include "renamewangset.h" #include "wangset.h" #include "tileset.h" #include "tile.h" @@ -65,7 +66,6 @@ int TilesetWangSetModel::rowCount(const QModelIndex &parent) const int TilesetWangSetModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent); - return 1; } @@ -93,7 +93,18 @@ bool TilesetWangSetModel::setData(const QModelIndex &index, const QVariant &value, int role) { - //TO ADD RENAME CAPABILITY + if(role == Qt::EditRole) { + const QString newName = value.toString(); + WangSet *wangSet = wangSetAt(index); + if (wangSet->name() != newName) { + RenameWangSet *rename = new RenameWangSet(mTilesetDocument, + mTilesetDocument->tileset()->wangSets().indexOf(wangSet), + newName); + mTilesetDocument->undoStack()->push(rename); + } + return true; + } + return false; } @@ -134,12 +145,12 @@ WangSet *TilesetWangSetModel::takeWangSetAt(int index) emit wangSetAboutToBeRemoved(tileset->wangSet(index)); beginRemoveRows(QModelIndex(), index, index); - WangSet *wangset = tileset->takeWangSetAt(index); + WangSet *wangSet = tileset->takeWangSetAt(index); endRemoveRows(); - emit wangSetRemoved(); + emit wangSetRemoved(wangSet); - return wangset; + return wangSet; } void TilesetWangSetModel::setWangSetName(int index, const QString &name) diff --git a/src/tiled/tilesetwangsetmodel.h b/src/tiled/tilesetwangsetmodel.h index 59633ca09b..f0920bc8b3 100644 --- a/src/tiled/tilesetwangsetmodel.h +++ b/src/tiled/tilesetwangsetmodel.h @@ -80,7 +80,7 @@ class TilesetWangSetModel : public QAbstractListModel void wangSetAboutToBeAdded(Tileset *tileset); void wangSetAdded(Tileset *tileset); void wangSetAboutToBeRemoved(WangSet *wangSet); - void wangSetRemoved(); + void wangSetRemoved(WangSet *wangSet); /** * Emitted when either the name or the image of a terrain changed. diff --git a/src/tiled/wangdock.cpp b/src/tiled/wangdock.cpp index b06b7f36b0..0326bb167e 100644 --- a/src/tiled/wangdock.cpp +++ b/src/tiled/wangdock.cpp @@ -18,6 +18,7 @@ * this program. If not, see . */ +#include "wangset.h" #include "wangdock.h" #include "wangsetview.h" #include "wangsetmodel.h" @@ -25,6 +26,7 @@ #include "map.h" #include "mapdocument.h" #include "tilesetdocument.h" +#include "tilesetdocumentsmodel.h" #include "tilesetwangsetmodel.h" #include "utils.h" @@ -97,6 +99,8 @@ WangDock::WangDock(QWidget *parent) , mRemoveWangSet(new QAction(this)) , mDocument(nullptr) , mCurrentWangSet(nullptr) + , mTilesetDocumentFilterModel(new TilesetDocumentsFilterModel(this)) + , mWangSetModel(new WangSetModel(mTilesetDocumentFilterModel, this)) , mProxyModel(new WangSetFilterModel(this)) , mInitializing(false) { @@ -149,38 +153,27 @@ WangDock::~WangDock() { } -static QAbstractItemModel *wangSetModel(Document *document) -{ - switch (document->type()) { - case Document::MapDocumentType: - return static_cast(document)->wangSetModel(); - case Document::TilesetDocumentType: - return static_cast(document)->wangSetModel(); - } - - return nullptr; -} - void WangDock::setDocument(Document *document) { if (mDocument == document) return; - if (mDocument) { - wangSetModel(mDocument)->disconnect(this); - mDocument->disconnect(this); + if (auto tilesetDocument = qobject_cast(mDocument)) {\ + tilesetDocument->disconnect(this); } mDocument = document; mInitializing = true; if (auto mapDocument = qobject_cast(document)) { - WangSetModel *wangSetModel = mapDocument->wangSetModel(); + mTilesetDocumentFilterModel->setMapDocument(mapDocument); mProxyModel->setEnabled(true); - mProxyModel->setSourceModel(wangSetModel); + mProxyModel->setSourceModel(mWangSetModel); mWangSetView->expandAll(); + setCurrentWangSet((firstWangSet(mapDocument))); + mToolBar->setVisible(false); } else if (auto tilesetDocument = qobject_cast(document)) { @@ -195,7 +188,7 @@ void WangDock::setDocument(Document *document) mToolBar->setVisible(true); /* - * Removing a terrain usually changes the selected terrain without the + * Removing a wangset usually changes the selected terrain without the * selection changing rows, so we can't rely on the currentRowChanged * signal. */ @@ -215,9 +208,12 @@ void WangDock::editWangSetName(WangSet *wangSet) { const QModelIndex index = wangSetIndex(wangSet); QItemSelectionModel *selectionModel = mWangSetView->selectionModel(); - selectionModel->setCurrentIndex(index, - QItemSelectionModel::ClearAndSelect | - QItemSelectionModel::Rows); + + //Changing the index seems to be causing the crashing... Needs investigation. + //selectionModel->setCurrentIndex(index, + // QItemSelectionModel::ClearAndSelect | + // QItemSelectionModel::Rows); + mWangSetView->edit(index); } @@ -242,10 +238,8 @@ void WangDock::refreshCurrentWangSet() void WangDock::indexPressed(const QModelIndex &index) { - if (WangSet *wangSet = mWangSetView->wangSetAt(index)) { - if (auto tilesetDocument = qobject_cast(mDocument)) - tilesetDocument->setCurrentObject((Object*)wangSet); - } + if (WangSet *wangSet = mWangSetView->wangSetAt(index)) + mDocument->setCurrentObject(wangSet); } void WangDock::expandRows(const QModelIndex &parent, int first, int last) @@ -272,10 +266,8 @@ void WangDock::setCurrentWangSet(WangSet *wangSet) mCurrentWangSet = nullptr; } - if (wangSet && !mInitializing) { - if (auto tilesetDocument = qobject_cast(mDocument)) - tilesetDocument->setCurrentObject((Object*)wangSet); - } + if (wangSet && !mInitializing) + mDocument->setCurrentObject(wangSet); mRemoveWangSet->setEnabled(wangSet); @@ -292,5 +284,12 @@ void WangDock::retranslateUi() QModelIndex WangDock::wangSetIndex(WangSet *wangSet) const { - return qobject_cast(mProxyModel->sourceModel())->index(wangSet); + QModelIndex sourceIndex; + + if (mDocument->type() == Document::MapDocumentType) + sourceIndex = mWangSetModel->index(wangSet); + else if (auto tilesetDocument = qobject_cast(mDocument)) + sourceIndex = tilesetDocument->wangSetModel()->index(wangSet); + + return mProxyModel->mapFromSource(sourceIndex); } diff --git a/src/tiled/wangdock.h b/src/tiled/wangdock.h index b432bc1696..b60fd89c18 100644 --- a/src/tiled/wangdock.h +++ b/src/tiled/wangdock.h @@ -38,6 +38,7 @@ class WangSetFilterModel; class WangSetView; class WangSetModel; class TilesetDocument; +class TilesetDocumentsFilterModel; class WangDock : public QDockWidget { @@ -45,7 +46,6 @@ class WangDock : public QDockWidget public: WangDock(QWidget *parent = nullptr); - ~WangDock(); void setDocument(Document *document); @@ -83,6 +83,8 @@ private slots: Document *mDocument; WangSetView *mWangSetView; WangSet *mCurrentWangSet; + TilesetDocumentsFilterModel *mTilesetDocumentFilterModel; + WangSetModel *mWangSetModel; WangSetFilterModel *mProxyModel; bool mInitializing; diff --git a/src/tiled/wangsetmodel.cpp b/src/tiled/wangsetmodel.cpp index 0dfcc3252e..7bd98c0053 100644 --- a/src/tiled/wangsetmodel.cpp +++ b/src/tiled/wangsetmodel.cpp @@ -26,6 +26,10 @@ #include "wangset.h" #include "tileset.h" #include "tile.h" +#include "tilesetdocument.h" +#include "tilesetdocumentsmodel.h" +#include "tileset.h" +#include "tilesetwangsetmodel.h" #include #include @@ -34,30 +38,21 @@ using namespace Tiled; using namespace Tiled::Internal; -WangSetModel::WangSetModel(MapDocument *mapDocument, +WangSetModel::WangSetModel(QAbstractItemModel *tilesetDocumentModel, QObject *parent): QAbstractItemModel(parent), - mMapDocument(mapDocument) -{ - connect(mapDocument, SIGNAL(tilesetAboutToBeAdded(int)), - this, SLOT(tilesetAboutToBeAdded(int))); - connect(mapDocument, SIGNAL(tilesetAdded(int,Tileset*)), - this, SLOT(tilesetAdded())); - connect(mapDocument, SIGNAL(tilesetAboutToBeRemoved(int)), - this, SLOT(tilesetAboutToBeRemoved(int))); - connect(mapDocument, SIGNAL(tilesetRemoved(Tileset*)), - this, SLOT(tilesetRemoved())); - connect(mapDocument, &MapDocument::tilesetNameChanged, - this, &WangSetModel::tilesetChanged); - - connect(mapDocument, &MapDocument::tilesetWangSetAboutToBeAdded, - this, &WangSetModel::wangSetAboutToBeAdded); - connect(mapDocument, &MapDocument::tilesetWangSetAdded, - this, &WangSetModel::wangSetAdded); - connect(mapDocument, &MapDocument::tilesetWangSetAboutToBeRemoved, - this, &WangSetModel::wangSetAboutToBeRemoved); - connect(mapDocument, &MapDocument::tilesetWangSetRemoved, - this, &WangSetModel::wangSetRemoved); + mTilesetDocumentsModel(tilesetDocumentModel) +{ + connect(mTilesetDocumentsModel, &QAbstractItemModel::rowsInserted, + this, &WangSetModel::onTilesetRowsInserted); + connect(mTilesetDocumentsModel, &QAbstractItemModel::rowsAboutToBeRemoved, + this, &WangSetModel::onTilesetRowsAboutToBeRemoved); + connect(mTilesetDocumentsModel, &QAbstractItemModel::rowsMoved, + this, &WangSetModel::onTilesetRowsMoved); + connect(mTilesetDocumentsModel, &QAbstractItemModel::layoutChanged, + this, &WangSetModel::onTilesetLayoutChanged); + connect(mTilesetDocumentsModel, &QAbstractItemModel::dataChanged, + this, &WangSetModel::onTilesetDataChanged); } WangSetModel::~WangSetModel() @@ -77,11 +72,13 @@ QModelIndex WangSetModel::index(int row, int column, const QModelIndex &parent) return QModelIndex(); } -QModelIndex WangSetModel::index(Tileset *tileSet) const +QModelIndex WangSetModel::index(Tileset *tileset) const { - int row = indexOf(mMapDocument->map()->tilesets(), tileSet); - Q_ASSERT(row != -1); - return createIndex(row, 0); + for (int row = 0; row < mTilesetDocuments.size(); ++row) + if (mTilesetDocuments.at(row)->tileset() == tileset) + return createIndex(row, 0); + + return QModelIndex(); } QModelIndex WangSetModel::index(WangSet *wangSet) const @@ -102,7 +99,7 @@ QModelIndex WangSetModel::parent(const QModelIndex &child) const int WangSetModel::rowCount(const QModelIndex &parent) const { if (!parent.isValid()) - return mMapDocument->map()->tilesetCount(); + return mTilesetDocuments.size(); else if (Tileset *tileset = tilesetAt(parent)) return tileset->wangSetCount(); @@ -150,16 +147,26 @@ QVariant WangSetModel::data(const QModelIndex &index, int role) const return QVariant(); } +Qt::ItemFlags WangSetModel::flags(const QModelIndex &index) const +{ + Qt::ItemFlags defaultFlags = QAbstractItemModel::flags(index); + + if (tilesetAt(index)) + defaultFlags &= ~Qt::ItemIsSelectable; + + return defaultFlags; +} + Tileset *WangSetModel::tilesetAt(const QModelIndex &index) const { if (!index.isValid()) return nullptr; if (index.parent().isValid()) // tilesets don't have parents return nullptr; - if (index.row() >= mMapDocument->map()->tilesetCount()) + if (index.row() >= mTilesetDocuments.size()) return nullptr; - return mMapDocument->map()->tilesetAt(index.row()).data(); + return mTilesetDocuments.at(index.row())->tileset().data(); } WangSet *WangSetModel::wangSetAt(const QModelIndex &index) const @@ -173,52 +180,113 @@ WangSet *WangSetModel::wangSetAt(const QModelIndex &index) const return nullptr; } -void WangSetModel::tilesetAboutToBeAdded(int index) +void WangSetModel::onTilesetRowsInserted(const QModelIndex &parent, int first, int last) { - beginInsertRows(QModelIndex(), index, index); + beginInsertRows(QModelIndex(), first, last); + for (int row = first; row <= last; ++row) { + const QModelIndex index = mTilesetDocumentsModel->index(row, 0, parent); + const QVariant var = mTilesetDocumentsModel->data(index, TilesetDocumentsModel::TilesetDocumentRole); + TilesetDocument *tilesetDocument = var.value(); + + mTilesetDocuments.insert(row, tilesetDocument); + + TilesetWangSetModel *tilesetWangSetModel = tilesetDocument->wangSetModel(); + connect(tilesetWangSetModel, &TilesetWangSetModel::wangSetAboutToBeAdded, + this, &WangSetModel::onWangSetAboutToBeAdded); + connect(tilesetWangSetModel, &TilesetWangSetModel::wangSetAdded, + this, &WangSetModel::onWangSetAdded); + connect(tilesetWangSetModel, &TilesetWangSetModel::wangSetAboutToBeRemoved, + this, &WangSetModel::onWangSetAboutToBeRemoved); + connect(tilesetWangSetModel, &TilesetWangSetModel::wangSetRemoved, + this, &WangSetModel::onWangSetRemoved); + } + endInsertRows(); } -void WangSetModel::tilesetAdded() +void WangSetModel::onTilesetRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last) { - endInsertRows(); + Q_UNUSED(parent) + + beginRemoveRows(QModelIndex(), first, last); + for (int index = last; index >= first; --index) { + TilesetDocument *tilesetDocument = mTilesetDocuments.takeAt(index); + tilesetDocument->wangSetModel()->disconnect(this); + } + endRemoveRows(); } -void WangSetModel::tilesetAboutToBeRemoved(int index) +void WangSetModel::onTilesetRowsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row) { - beginRemoveRows(QModelIndex(), index, index); + Q_UNUSED(parent) + Q_UNUSED(destination) + + beginMoveRows(QModelIndex(), start, end, QModelIndex(), row); + + if (start == row) + return; + + while (start <= end) { + mTilesetDocuments.move(start, row); + + if (row < start) { + ++start; + ++row; + } else { + --end; + } + } + + endMoveRows(); } -void WangSetModel::tilesetRemoved() +void WangSetModel::onTilesetLayoutChanged(const QList &parents, QAbstractItemModel::LayoutChangeHint hint) { - endRemoveRows(); + Q_UNUSED(parents) + Q_UNUSED(hint) + + // Make sure the tileset documents are still in the right order + for (int i = 0, rows = mTilesetDocuments.size(); i < rows; ++i) { + const QModelIndex index = mTilesetDocumentsModel->index(i, 0); + const QVariant var = mTilesetDocumentsModel->data(index, TilesetDocumentsModel::TilesetDocumentRole); + TilesetDocument *tilesetDocument = var.value(); + int currentIndex = mTilesetDocuments.indexOf(tilesetDocument); + if (currentIndex != i) { + Q_ASSERT(currentIndex > i); + onTilesetRowsMoved(QModelIndex(), currentIndex, currentIndex, QModelIndex(), i); + } + } } -void WangSetModel::tilesetChanged(Tileset *tileset) +void WangSetModel::onTilesetDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { - const QModelIndex index = WangSetModel::index(tileset); - emit dataChanged(index, index); + emit dataChanged(index(topLeft.row(), topLeft.column()), + index(bottomRight.row(), bottomRight.column())); } -void WangSetModel::wangSetAboutToBeAdded(Tileset *tileset) +void WangSetModel::onWangSetAboutToBeAdded(Tileset *tileset) { QModelIndex parent = index(tileset); beginInsertRows(parent, tileset->wangSetCount(), tileset->wangSetCount()); } -void WangSetModel::wangSetAdded(Tileset *tileset) +void WangSetModel::onWangSetAdded(Tileset *tileset) { endInsertRows(); - tilesetChanged(tileset); + + const QModelIndex index = WangSetModel::index(tileset); + emit dataChanged(index, index); } -void WangSetModel::wangSetAboutToBeRemoved(Tileset *tileset, WangSet *wangSet) +void WangSetModel::onWangSetAboutToBeRemoved(WangSet *wangSet) { - QModelIndex parent = index(tileset); - beginRemoveRows(parent, tileset->wangSets().indexOf(wangSet), tileset->wangSets().indexOf(wangSet)); + QModelIndex parent = index(wangSet->tileset()); + beginRemoveRows(parent, index(wangSet).row(), index(wangSet).row()); } -void WangSetModel::wangSetRemoved(Tileset *tileset) +void WangSetModel::onWangSetRemoved(WangSet *wangSet) { endRemoveRows(); - tilesetChanged(tileset); + + const QModelIndex index = WangSetModel::index(wangSet->tileset()); + emit dataChanged(index, index); } diff --git a/src/tiled/wangsetmodel.h b/src/tiled/wangsetmodel.h index 3e88504c67..2dc1c5b4a8 100644 --- a/src/tiled/wangsetmodel.h +++ b/src/tiled/wangsetmodel.h @@ -30,7 +30,7 @@ class WangSet; namespace Internal { -class MapDocument; +class TilesetDocument; class WangSetModel : public QAbstractItemModel { @@ -41,15 +41,15 @@ class WangSetModel : public QAbstractItemModel WangSetRole = Qt::UserRole }; - WangSetModel(MapDocument *mapDocument, + WangSetModel(QAbstractItemModel *tilesetDocumentModel, QObject *parent = nullptr); ~WangSetModel(); QModelIndex index(int row, int column, - const QModelIndex &parent) const override; + const QModelIndex &parent = QModelIndex()) const override; - QModelIndex index(Tileset *tileSet) const; + QModelIndex index(Tileset *tileset) const; QModelIndex index(WangSet *wangSet) const; QModelIndex parent(const QModelIndex &child) const override; @@ -60,23 +60,26 @@ class WangSetModel : public QAbstractItemModel QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + Qt::ItemFlags flags(const QModelIndex &index) const override; + Tileset *tilesetAt(const QModelIndex &index) const; WangSet *wangSetAt(const QModelIndex &index) const; private slots: - void tilesetAboutToBeAdded(int index); - void tilesetAdded(); - void tilesetAboutToBeRemoved(int index); - void tilesetRemoved(); - void tilesetChanged(Tileset *tileset); + void onTilesetRowsInserted(const QModelIndex &parent, int first, int last); + void onTilesetRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last); + void onTilesetRowsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row); + void onTilesetLayoutChanged(const QList &parents, QAbstractItemModel::LayoutChangeHint hint); + void onTilesetDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); - void wangSetAboutToBeAdded(Tileset *tileset); - void wangSetAdded(Tileset *tileset); - void wangSetAboutToBeRemoved(Tileset *tileset, WangSet *wangSet); - void wangSetRemoved(Tileset *tileset); + void onWangSetAboutToBeAdded(Tileset *tileset); + void onWangSetAdded(Tileset *tileset); + void onWangSetAboutToBeRemoved(WangSet *wangSet); + void onWangSetRemoved(WangSet *wangSet); private: - MapDocument *mMapDocument; + QAbstractItemModel *mTilesetDocumentsModel; + QList mTilesetDocuments; }; } // namespace Internal diff --git a/src/tiled/wangsetview.h b/src/tiled/wangsetview.h index 4206734e4e..9db2b046f3 100644 --- a/src/tiled/wangsetview.h +++ b/src/tiled/wangsetview.h @@ -58,3 +58,5 @@ private slots: } // namespace Internal } // namespace Tiled + +Q_DECLARE_METATYPE(Tiled::Internal::WangSetView *) From 3916cd6d87c8eb431de516a84fa008f64cf31afc Mon Sep 17 00:00:00 2001 From: Benjamin Trotter Date: Wed, 28 Jun 2017 11:58:55 -0700 Subject: [PATCH 10/21] WangSets are now able to be created and edited from the ui --- src/libtiled/mapreader.cpp | 12 ++++-- src/libtiled/mapwriter.cpp | 2 + src/libtiled/object.h | 2 + src/libtiled/wangset.cpp | 2 +- src/tiled/changewangsetdata.cpp | 57 ++++++++++++++++++++++++++ src/tiled/changewangsetdata.h | 51 +++++++++++++++++++++++ src/tiled/propertybrowser.cpp | 68 ++++++++++++++++++++++++++++++- src/tiled/propertybrowser.h | 5 +++ src/tiled/tiled.qbs | 2 + src/tiled/tilesetdocument.cpp | 27 +----------- src/tiled/tilesetdocument.h | 6 +-- src/tiled/tilesetwangsetmodel.cpp | 18 +++++++- src/tiled/tilesetwangsetmodel.h | 4 +- src/tiled/wangdock.cpp | 9 ++-- src/tiled/wangsetmodel.h | 1 - 15 files changed, 222 insertions(+), 44 deletions(-) create mode 100644 src/tiled/changewangsetdata.cpp create mode 100644 src/tiled/changewangsetdata.h diff --git a/src/libtiled/mapreader.cpp b/src/libtiled/mapreader.cpp index 79ea3d2897..f4d70b5479 100644 --- a/src/libtiled/mapreader.cpp +++ b/src/libtiled/mapreader.cpp @@ -589,10 +589,16 @@ void MapReaderPrivate::readTilesetWangSet(Tileset &tileset) int corners = atts.value(QLatin1String("corners")).toInt(); int tile = atts.value(QLatin1String("tile")).toInt(); - tileset.insertWangSet(new WangSet(&tileset, edges, corners, name, tile)); + WangSet *wangSet = new WangSet(&tileset, edges, corners, name, tile); - //eventually will read properties. - xml.skipCurrentElement(); + tileset.insertWangSet(wangSet); + + while (xml.readNextStartElement()) { + if (xml.name() == QLatin1String("properties")) + wangSet->mergeProperties(readProperties()); + else + readUnknownElement(); + } } else { readUnknownElement(); } diff --git a/src/libtiled/mapwriter.cpp b/src/libtiled/mapwriter.cpp index 06ca944bde..dff4232a95 100644 --- a/src/libtiled/mapwriter.cpp +++ b/src/libtiled/mapwriter.cpp @@ -375,6 +375,8 @@ void MapWriterPrivate::writeTileset(QXmlStreamWriter &w, const Tileset &tileset, w.writeAttribute(QLatin1String("corners"),QString::number(ws->cornerColors())); w.writeAttribute(QLatin1String("tile"),QString::number(ws->imageTileId())); + writeProperties(w, ws->properties()); + w.writeEndElement(); // } w.writeEndElement(); // diff --git a/src/libtiled/object.h b/src/libtiled/object.h index c92b2fadb0..4d1f7b6d9a 100644 --- a/src/libtiled/object.h +++ b/src/libtiled/object.h @@ -44,6 +44,7 @@ class TILEDSHARED_EXPORT Object MapObjectType, MapType, TerrainType, + WangSetType, TilesetType, TileType }; @@ -135,6 +136,7 @@ inline bool Object::isPartOfTileset() const case Object::TilesetType: case Object::TileType: case Object::TerrainType: + case Object::WangSetType: return true; default: return false; diff --git a/src/libtiled/wangset.cpp b/src/libtiled/wangset.cpp index ae884450db..38ec7d6e39 100644 --- a/src/libtiled/wangset.cpp +++ b/src/libtiled/wangset.cpp @@ -37,7 +37,7 @@ WangSet::WangSet(Tileset *tileset, int cornerColors, QString name, int imageTileId): - Object(Object::TerrainType), //for now, will add unique type soon + Object(Object::WangSetType), mTileset(tileset), mName(std::move(name)), mImageTileId(imageTileId), diff --git a/src/tiled/changewangsetdata.cpp b/src/tiled/changewangsetdata.cpp new file mode 100644 index 0000000000..23766e569c --- /dev/null +++ b/src/tiled/changewangsetdata.cpp @@ -0,0 +1,57 @@ +#include "changewangsetdata.h" + +#include "wangset.h" +#include "tileset.h" +#include "tilesetdocument.h" +#include "tilesetwangsetmodel.h" + +#include + +using namespace Tiled; +using namespace Internal; + +ChangeWangSetEdges::ChangeWangSetEdges(TilesetDocument *tilesetDocument, + int index, + int newValue) + : QUndoCommand(QCoreApplication::translate("Undo Commands", + "Change Wang Set edge count")) + , mWangSetModel(tilesetDocument->wangSetModel()) + , mTileset(tilesetDocument->tileset().data()) + , mIndex(index) + , mOldValue(mTileset->wangSet(index)->edgeColors()) + , mNewValue(newValue) +{ +} + +void ChangeWangSetEdges::undo() +{ + mWangSetModel->setWangSetEdges(mIndex, mOldValue); +} + +void ChangeWangSetEdges::redo() +{ + mWangSetModel->setWangSetEdges(mIndex, mNewValue); +} + +ChangeWangSetCorners::ChangeWangSetCorners(TilesetDocument *tilesetDocument, + int index, + int newValue) + : QUndoCommand(QCoreApplication::translate("Undo Commands", + "Change Wang Set corner count")) + , mWangSetModel(tilesetDocument->wangSetModel()) + , mTileset(tilesetDocument->tileset().data()) + , mIndex(index) + , mOldValue(mTileset->wangSet(index)->cornerColors()) + , mNewValue(newValue) +{ +} + +void ChangeWangSetCorners::undo() +{ + mWangSetModel->setWangSetCorners(mIndex, mOldValue); +} + +void ChangeWangSetCorners::redo() +{ + mWangSetModel->setWangSetCorners(mIndex, mNewValue); +} diff --git a/src/tiled/changewangsetdata.h b/src/tiled/changewangsetdata.h new file mode 100644 index 0000000000..deae56109f --- /dev/null +++ b/src/tiled/changewangsetdata.h @@ -0,0 +1,51 @@ +#pragma once + +#include + +namespace Tiled { + +class Tileset; + +namespace Internal { + +class TilesetDocument; +class TilesetWangSetModel; + +class ChangeWangSetEdges : public QUndoCommand +{ +public: + ChangeWangSetEdges(TilesetDocument *TilesetDocument, + int index, + int newValue); + + void undo() override; + void redo() override; + +private: + TilesetWangSetModel *mWangSetModel; + Tileset *mTileset; + int mIndex; + int mOldValue; + int mNewValue; +}; + +class ChangeWangSetCorners : public QUndoCommand +{ +public: + ChangeWangSetCorners(TilesetDocument *TilesetDocument, + int index, + int newValue); + + void undo() override; + void redo() override; + +private: + TilesetWangSetModel *mWangSetModel; + Tileset *mTileset; + int mIndex; + int mOldValue; + int mNewValue; +}; + +} // namespace Internal +} // namespace Tiled diff --git a/src/tiled/propertybrowser.cpp b/src/tiled/propertybrowser.cpp index 9c84fc0a51..414719463a 100644 --- a/src/tiled/propertybrowser.cpp +++ b/src/tiled/propertybrowser.cpp @@ -30,6 +30,7 @@ #include "changetile.h" #include "changetileimagesource.h" #include "changetileprobability.h" +#include "changewangsetdata.h" #include "flipmapobjects.h" #include "imagelayer.h" #include "map.h" @@ -42,6 +43,7 @@ #include "resizemapobject.h" #include "renamelayer.h" #include "renameterrain.h" +#include "renamewangset.h" #include "rotatemapobject.h" #include "terrain.h" #include "tile.h" @@ -51,9 +53,11 @@ #include "tilesetformat.h" #include "tilesetmanager.h" #include "tilesetterrainmodel.h" +#include "tilesetwangsetmodel.h" #include "utils.h" #include "varianteditorfactory.h" #include "variantpropertymanager.h" +#include "wangset.h" #include @@ -145,8 +149,10 @@ void PropertyBrowser::setDocument(Document *document) if (mDocument) { mDocument->disconnect(this); - if (mTilesetDocument) + if (mTilesetDocument) { mTilesetDocument->terrainModel()->disconnect(this); + mTilesetDocument->wangSetModel()->disconnect(this); + } } mDocument = document; @@ -194,6 +200,10 @@ void PropertyBrowser::setDocument(Document *document) TilesetTerrainModel *terrainModel = tilesetDocument->terrainModel(); connect(terrainModel, &TilesetTerrainModel::terrainChanged, this, &PropertyBrowser::terrainChanged); + + TilesetWangSetModel *wangSetModel = tilesetDocument->wangSetModel(); + connect(wangSetModel, &TilesetWangSetModel::wangSetChanged, + this, &PropertyBrowser::wangSetChanged); } if (document) { @@ -324,6 +334,12 @@ void PropertyBrowser::terrainChanged(Tileset *tileset, int index) updateProperties(); } +void PropertyBrowser::wangSetChanged(Tileset *tileset, int index) +{ + if(mObject == tileset->wangSet(index)) + updateProperties(); +} + static QVariant predefinedPropertyValue(Object *object, const QString &name) { QString objectType; @@ -349,6 +365,7 @@ static QVariant predefinedPropertyValue(Object *object, const QString &name) case Object::MapType: case Object::TerrainType: case Object::TilesetType: + case Object::WangSetType: break; } @@ -532,6 +549,7 @@ void PropertyBrowser::valueChanged(QtProperty *property, const QVariant &val) case Object::TilesetType: applyTilesetValue(id, val); break; case Object::TileType: applyTileValue(id, val); break; case Object::TerrainType: applyTerrainValue(id, val); break; + case Object::WangSetType: applyWangSetValue(id, val); break; } } @@ -832,6 +850,20 @@ void PropertyBrowser::addTerrainProperties() addProperty(groupProperty); } +void PropertyBrowser::addWangSetProperties() +{ + QtProperty *groupProperty = mGroupManager->addProperty(tr("WangSet")); + QtVariantProperty *nameProperty = addProperty(NameProperty, QVariant::String, tr("Name"), groupProperty); + QtVariantProperty *edgeProperty = addProperty(EdgeProperty, QVariant::Int, tr("Edge Count"), groupProperty); + QtVariantProperty *cornerProperty = addProperty(CornerProperty, QVariant::Int, tr("Corner Count"), groupProperty); + + nameProperty->setEnabled(mTilesetDocument); + edgeProperty->setEnabled(mTilesetDocument); + cornerProperty->setEnabled(mTilesetDocument); + + addProperty(groupProperty); +} + void PropertyBrowser::applyMapValue(PropertyId id, const QVariant &val) { QUndoCommand *command = nullptr; @@ -1210,6 +1242,32 @@ void PropertyBrowser::applyTerrainValue(PropertyId id, const QVariant &val) } } +void PropertyBrowser::applyWangSetValue(PropertyId id, const QVariant &val) +{ + Q_ASSERT(mTilesetDocument); + + WangSet *wangSet = static_cast(mObject); + + switch (id) { + case NameProperty: + mDocument->undoStack()->push(new RenameWangSet(mTilesetDocument, + mTilesetDocument->tileset()->wangSets().indexOf(wangSet), + val.toString())); + break; + case EdgeProperty: + mDocument->undoStack()->push(new ChangeWangSetEdges(mTilesetDocument, + mTilesetDocument->tileset()->wangSets().indexOf(wangSet), + val.toInt())); + break; + case CornerProperty: + mDocument->undoStack()->push(new ChangeWangSetCorners(mTilesetDocument, + mTilesetDocument->tileset()->wangSets().indexOf(wangSet), + val.toInt())); + default: + break; + } +} + /** * @warning This function does not add the property to the view. */ @@ -1337,6 +1395,7 @@ void PropertyBrowser::addProperties() case Object::TilesetType: addTilesetProperties(); break; case Object::TileType: addTileProperties(); break; case Object::TerrainType: addTerrainProperties(); break; + case Object::WangSetType: addWangSetProperties(); break; } // Make sure the color and font properties are collapsed, to save space @@ -1505,6 +1564,12 @@ void PropertyBrowser::updateProperties() mIdToProperty[NameProperty]->setValue(terrain->name()); break; } + case Object::WangSetType: { + const WangSet *wangSet = static_cast(mObject); + mIdToProperty[NameProperty]->setValue(wangSet->name()); + mIdToProperty[EdgeProperty]->setValue(wangSet->edgeColors()); + mIdToProperty[CornerProperty]->setValue(wangSet->cornerColors()); + } } mUpdating = false; @@ -1564,6 +1629,7 @@ void PropertyBrowser::updateCustomProperties() case Object::MapType: case Object::TerrainType: case Object::TilesetType: + case Object::WangSetType: break; } diff --git a/src/tiled/propertybrowser.h b/src/tiled/propertybrowser.h index d38245a2dc..4263fb4201 100644 --- a/src/tiled/propertybrowser.h +++ b/src/tiled/propertybrowser.h @@ -97,6 +97,7 @@ private slots: void tileChanged(Tile *tile); void tileTypeChanged(Tile *tile); void terrainChanged(Tileset *tileset, int index); + void wangSetChanged(Tileset *tileset, int index); void propertyAdded(Object *object, const QString &name); void propertyRemoved(Object *object, const QString &name); @@ -152,6 +153,8 @@ private slots: TileProbabilityProperty, ColumnCountProperty, IdProperty, + EdgeProperty, + CornerProperty, CustomProperty }; @@ -165,6 +168,7 @@ private slots: void addTilesetProperties(); void addTileProperties(); void addTerrainProperties(); + void addWangSetProperties(); void applyMapValue(PropertyId id, const QVariant &val); void applyMapObjectValue(PropertyId id, const QVariant &val); @@ -177,6 +181,7 @@ private slots: void applyTilesetValue(PropertyId id, const QVariant &val); void applyTileValue(PropertyId id, const QVariant &val); void applyTerrainValue(PropertyId id, const QVariant &val); + void applyWangSetValue(PropertyId id, const QVariant &val); QtVariantProperty *createProperty(PropertyId id, int type, diff --git a/src/tiled/tiled.qbs b/src/tiled/tiled.qbs index 825250ab6d..65b9c72dd6 100644 --- a/src/tiled/tiled.qbs +++ b/src/tiled/tiled.qbs @@ -132,6 +132,8 @@ QtGuiApplication { "changetileprobability.h", "changetileterrain.cpp", "changetileterrain.h", + "changewangsetdata.cpp", + "changewangsetdata.h", "clipboardmanager.cpp", "clipboardmanager.h", "colorbutton.cpp", diff --git a/src/tiled/tilesetdocument.cpp b/src/tiled/tilesetdocument.cpp index 4aaabbe110..41de8d7fd9 100644 --- a/src/tiled/tilesetdocument.cpp +++ b/src/tiled/tilesetdocument.cpp @@ -79,13 +79,6 @@ TilesetDocument::TilesetDocument(const SharedTileset &tileset, const QString &fi connect(mTerrainModel, &TilesetTerrainModel::terrainRemoved, this, &TilesetDocument::onTerrainRemoved); - - connect(mWangSetModel, &TilesetWangSetModel::wangSetAboutToBeAdded, - this, &TilesetDocument::onWangSetAboutToBeAdded); - connect(mWangSetModel, &TilesetWangSetModel::wangSetAdded, - this, &TilesetDocument::onWangSetAdded); - connect(mWangSetModel, &TilesetWangSetModel::wangSetAboutToBeRemoved, - this, &TilesetDocument::onWangSetAboutToBeRemoved); connect(mWangSetModel, &TilesetWangSetModel::wangSetRemoved, this, &TilesetDocument::onWangSetRemoved); @@ -348,25 +341,7 @@ void TilesetDocument::onTerrainRemoved(Terrain *terrain) setCurrentObject(nullptr); } -void TilesetDocument::onWangSetAboutToBeAdded(Tileset *tileset) -{ - for (MapDocument *mapDocument : mapDocuments()) - emit mapDocument->tilesetWangSetAboutToBeAdded(tileset); -} - -void TilesetDocument::onWangSetAdded(Tileset *tileset) -{ - for (MapDocument *mapDocument : mapDocuments()) - emit mapDocument->tilesetWangSetAdded(tileset); -} - -void TilesetDocument::onWangSetAboutToBeRemoved(WangSet *wangSet) -{ - for (MapDocument *mapDocument : mapDocuments()) - emit mapDocument->tilesetWangSetAboutToBeRemoved(mTileset.data(), wangSet); -} - -void TilesetDocument::onWangSetRemoved() +void TilesetDocument::onWangSetRemoved(WangSet *wangSet) { for (MapDocument *mapDocument : mapDocuments()) emit mapDocument->tilesetWangSetRemoved(mTileset.data()); diff --git a/src/tiled/tilesetdocument.h b/src/tiled/tilesetdocument.h index 1ae98b7f24..d41d1f394c 100644 --- a/src/tiled/tilesetdocument.h +++ b/src/tiled/tilesetdocument.h @@ -142,11 +142,7 @@ private slots: void onPropertiesChanged(Object *object); void onTerrainRemoved(Terrain *terrain); - - void onWangSetAboutToBeAdded(Tileset *tileset); - void onWangSetAdded(Tileset *tileset); - void onWangSetAboutToBeRemoved(WangSet *wangSet); - void onWangSetRemoved(); + void onWangSetRemoved(WangSet *wangSet); private: SharedTileset mTileset; diff --git a/src/tiled/tilesetwangsetmodel.cpp b/src/tiled/tilesetwangsetmodel.cpp index 366401161e..f9373104e0 100644 --- a/src/tiled/tilesetwangsetmodel.cpp +++ b/src/tiled/tilesetwangsetmodel.cpp @@ -161,6 +161,22 @@ void TilesetWangSetModel::setWangSetName(int index, const QString &name) emitWangSetChange(wangSet); } +void TilesetWangSetModel::setWangSetEdges(int index, int value) +{ + Tileset *tileset = mTilesetDocument->tileset().data(); + WangSet *wangSet = tileset->wangSet(index); + wangSet->setEdgeColors(value); + emitWangSetChange(wangSet); +} + +void TilesetWangSetModel::setWangSetCorners(int index, int value) +{ + Tileset *tileset = mTilesetDocument->tileset().data(); + WangSet *wangSet = tileset->wangSet(index); + wangSet->setCornerColors(value); + emitWangSetChange(wangSet); +} + void TilesetWangSetModel::setWangSetImage(int index, int tileId) { Tileset *tileset = mTilesetDocument->tileset().data(); @@ -173,5 +189,5 @@ void TilesetWangSetModel::emitWangSetChange(WangSet *wangSet) { const QModelIndex index = TilesetWangSetModel::index(wangSet); emit dataChanged(index, index); - emit wangSetChanged(wangSet, index.row()); + emit wangSetChanged(wangSet->tileset(), index.row()); } diff --git a/src/tiled/tilesetwangsetmodel.h b/src/tiled/tilesetwangsetmodel.h index f0920bc8b3..8e1dd9ed09 100644 --- a/src/tiled/tilesetwangsetmodel.h +++ b/src/tiled/tilesetwangsetmodel.h @@ -74,6 +74,8 @@ class TilesetWangSetModel : public QAbstractListModel void insertWangSet(WangSet *wangSet); WangSet *takeWangSetAt(int index); void setWangSetName(int index, const QString &name); + void setWangSetEdges(int index, int value); + void setWangSetCorners(int index, int value); void setWangSetImage(int index, int tileId); signals: @@ -85,7 +87,7 @@ class TilesetWangSetModel : public QAbstractListModel /** * Emitted when either the name or the image of a terrain changed. */ - void wangSetChanged(WangSet *wangSet, int index); + void wangSetChanged(Tileset *tileset, int index); private: void emitWangSetChange(WangSet *wangSet); diff --git a/src/tiled/wangdock.cpp b/src/tiled/wangdock.cpp index 0326bb167e..49e97f913f 100644 --- a/src/tiled/wangdock.cpp +++ b/src/tiled/wangdock.cpp @@ -108,7 +108,7 @@ WangDock::WangDock(QWidget *parent) QWidget *w = new QWidget(this); - mWangSetView = new WangSetView(nullptr); + mWangSetView = new WangSetView(w); mWangSetView->setModel(mProxyModel); connect(mWangSetView->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &WangDock::refreshCurrentWangSet); @@ -209,10 +209,9 @@ void WangDock::editWangSetName(WangSet *wangSet) const QModelIndex index = wangSetIndex(wangSet); QItemSelectionModel *selectionModel = mWangSetView->selectionModel(); - //Changing the index seems to be causing the crashing... Needs investigation. - //selectionModel->setCurrentIndex(index, - // QItemSelectionModel::ClearAndSelect | - // QItemSelectionModel::Rows); + selectionModel->setCurrentIndex(index, + QItemSelectionModel::ClearAndSelect | + QItemSelectionModel::Rows); mWangSetView->edit(index); } diff --git a/src/tiled/wangsetmodel.h b/src/tiled/wangsetmodel.h index 2dc1c5b4a8..7946c7c35c 100644 --- a/src/tiled/wangsetmodel.h +++ b/src/tiled/wangsetmodel.h @@ -43,7 +43,6 @@ class WangSetModel : public QAbstractItemModel WangSetModel(QAbstractItemModel *tilesetDocumentModel, QObject *parent = nullptr); - ~WangSetModel(); QModelIndex index(int row, int column, From acae98a7e639cdc103242c572f7da8880a6a8cba Mon Sep 17 00:00:00 2001 From: Benjamin Trotter Date: Wed, 28 Jun 2017 14:12:23 -0700 Subject: [PATCH 11/21] Added new files to tiled.pro --- src/tiled/tiled.pro | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/tiled/tiled.pro b/src/tiled/tiled.pro index d5caa888be..84b4ed3cc1 100644 --- a/src/tiled/tiled.pro +++ b/src/tiled/tiled.pro @@ -84,6 +84,7 @@ SOURCES += aboutdialog.cpp \ addremoveterrain.cpp \ addremovetiles.cpp \ addremovetileset.cpp \ + addremocewangset.cpp \ adjusttileindexes.cpp \ automapper.cpp \ automapperwrapper.cpp \ @@ -109,6 +110,7 @@ SOURCES += aboutdialog.cpp \ changetileobjectgroup.cpp \ changetileprobability.cpp \ changetileterrain.cpp \ + changewangsetdata.cpp \ clickablelabel.cpp \ clipboardmanager.cpp \ colorbutton.cpp \ @@ -190,6 +192,7 @@ SOURCES += aboutdialog.cpp \ raiselowerhelper.cpp \ renamelayer.cpp \ renameterrain.cpp \ + renamewangset.cpp \ reparentlayers.cpp \ replacetileset.cpp \ resizedialog.cpp \ @@ -230,6 +233,7 @@ SOURCES += aboutdialog.cpp \ tilesetmodel.cpp \ tilesetparametersedit.cpp \ tilesetterrainmodel.cpp \ + tilesetwangsetmodel.cpp \ tilesetview.cpp \ tilestamp.cpp \ tilestampmanager.cpp \ @@ -242,6 +246,9 @@ SOURCES += aboutdialog.cpp \ utils.cpp \ varianteditorfactory.cpp \ variantpropertymanager.cpp \ + wangsetview.cpp \ + wangsetmodel.cpp \ + wangdock.cpp \ zoomable.cpp HEADERS += aboutdialog.h \ @@ -255,6 +262,7 @@ HEADERS += aboutdialog.h \ addremoveterrain.h \ addremovetileset.h \ addremovetiles.h \ + addremovewangset.h \ adjusttileindexes.h \ automapper.h \ automapperwrapper.h \ @@ -280,6 +288,7 @@ HEADERS += aboutdialog.h \ changetileobjectgroup.h \ changetileprobability.h \ changetileterrain.h \ + changewangsetdata.h \ clickablelabel.h \ clipboardmanager.h \ colorbutton.h \ @@ -364,6 +373,7 @@ HEADERS += aboutdialog.h \ rangeset.h \ renamelayer.h \ renameterrain.h \ + renamewangset.h \ reparentlayers.h \ replacetileset.h \ resizedialog.h \ @@ -405,6 +415,7 @@ HEADERS += aboutdialog.h \ tilesetmodel.h \ tilesetparametersedit.h \ tilesetterrainmodel.h \ + tilesetwangsetmodel.h \ tilesetview.h \ tilestamp.h \ tilestampmanager.h \ @@ -418,6 +429,9 @@ HEADERS += aboutdialog.h \ utils.h \ varianteditorfactory.h \ variantpropertymanager.h \ + wangsetview.h \ + wangsetmodel.h \ + wangdock.h \ zoomable.h FORMS += aboutdialog.ui \ From 68bd9af4068e9d915e48b8c32adf571a7fb001be Mon Sep 17 00:00:00 2001 From: Benjamin Trotter Date: Wed, 28 Jun 2017 15:41:31 -0700 Subject: [PATCH 12/21] adjusted reading/writting so that all the wang set info (including tiles) stays grouped together --- src/libtiled/mapreader.cpp | 19 +++++++------- src/libtiled/mapwriter.cpp | 53 +++++++++++++++++--------------------- src/tiled/wangsetview.cpp | 3 ++- 3 files changed, 35 insertions(+), 40 deletions(-) diff --git a/src/libtiled/mapreader.cpp b/src/libtiled/mapreader.cpp index f4d70b5479..29c384d4a9 100644 --- a/src/libtiled/mapreader.cpp +++ b/src/libtiled/mapreader.cpp @@ -434,15 +434,6 @@ void MapReaderPrivate::readTilesetTile(Tileset &tileset) tile->setObjectGroup(readObjectGroup()); } else if (xml.name() == QLatin1String("animation")) { tile->setFrames(readAnimationFrames()); - } else if(xml.name() == QLatin1String("wanginfo")) { - const QXmlStreamAttributes wangAtts = xml.attributes(); - - WangSet *wangset = tileset.wangSet(wangAtts.value(QLatin1String("setindex")).toInt()); - unsigned wangid = wangAtts.value(QLatin1String("wangid")).toUInt(); - - wangset->addTile(tile, wangid); - - xml.skipCurrentElement(); } else { readUnknownElement(); } @@ -596,7 +587,15 @@ void MapReaderPrivate::readTilesetWangSet(Tileset &tileset) while (xml.readNextStartElement()) { if (xml.name() == QLatin1String("properties")) wangSet->mergeProperties(readProperties()); - else + else if (xml.name() == QLatin1String("wangsettile")) { + const QXmlStreamAttributes tileAtts = xml.attributes(); + int tileId = tileAtts.value(QLatin1String("tileid")).toInt(); + int wangId = tileAtts.value(QLatin1String("wangid")).toInt(); + + wangSet->addTile(tileset.tileAt(tileId), wangId); + + xml.skipCurrentElement(); + } else readUnknownElement(); } } else { diff --git a/src/libtiled/mapwriter.cpp b/src/libtiled/mapwriter.cpp index dff4232a95..efffa2264b 100644 --- a/src/libtiled/mapwriter.cpp +++ b/src/libtiled/mapwriter.cpp @@ -362,26 +362,6 @@ void MapWriterPrivate::writeTileset(QXmlStreamWriter &w, const Tileset &tileset, } w.writeEndElement(); } - - // Write the wangsets - if (tileset.wangSetCount() > 0) { - w.writeStartElement(QLatin1String("wangsets")); - for (int i = 0; i < tileset.wangSetCount(); ++i) { - const WangSet *ws = tileset.wangSet(i); - w.writeStartElement(QLatin1String("wangset")); - - w.writeAttribute(QLatin1String("name"),ws->name()); - w.writeAttribute(QLatin1String("edges"),QString::number(ws->edgeColors())); - w.writeAttribute(QLatin1String("corners"),QString::number(ws->cornerColors())); - w.writeAttribute(QLatin1String("tile"),QString::number(ws->imageTileId())); - - writeProperties(w, ws->properties()); - - w.writeEndElement(); // - } - w.writeEndElement(); // - } - // Write the properties for those tiles that have them for (const Tile *tile : tileset.tiles()) { if (imageSource.isEmpty() || includeTile(tile)) { @@ -441,21 +421,36 @@ void MapWriterPrivate::writeTileset(QXmlStreamWriter &w, const Tileset &tileset, } w.writeEndElement(); // } - for (int i = 0; i < tileset.wangSetCount(); ++i) { - unsigned wangid = tileset.wangSet(i)->wangIdOfTile(tile); + w.writeEndElement(); // + } + } - if(wangid) { - w.writeStartElement(QLatin1String("wanginfo")); - w.writeAttribute(QLatin1String("setindex"), QString::number(i)); + // Write the wangsets + if (tileset.wangSetCount() > 0) { + w.writeStartElement(QLatin1String("wangsets")); + for (int i = 0; i < tileset.wangSetCount(); ++i) { + const WangSet *ws = tileset.wangSet(i); + w.writeStartElement(QLatin1String("wangset")); - //could be made more readable by spacing out the wangId into each corner. - w.writeAttribute(QLatin1String("wangid"), QString::number(wangid)); - w.writeEndElement(); // + w.writeAttribute(QLatin1String("name"), ws->name()); + w.writeAttribute(QLatin1String("edges"), QString::number(ws->edgeColors())); + w.writeAttribute(QLatin1String("corners"), QString::number(ws->cornerColors())); + w.writeAttribute(QLatin1String("tile"), QString::number(ws->imageTileId())); + + //write each tile with a valid wangId + for (const Tile *tile : tileset.tiles()) { + if (int wId = ws->wangIdOfTile(tile)) { + w.writeStartElement(QLatin1String("wangsettile")); + w.writeAttribute(QLatin1String("tileid"), QString::number(tile->id())); + w.writeAttribute(QLatin1String("wangid"), QString::number(wId)); + w.writeEndElement(); // } } + writeProperties(w, ws->properties()); - w.writeEndElement(); // + w.writeEndElement(); // } + w.writeEndElement(); // } w.writeEndElement(); diff --git a/src/tiled/wangsetview.cpp b/src/tiled/wangsetview.cpp index 37c368199d..24a76eb179 100644 --- a/src/tiled/wangsetview.cpp +++ b/src/tiled/wangsetview.cpp @@ -118,7 +118,8 @@ void WangSetView::editWangSetProperties() if(!wangSet) return; - //TODO ADD WANGSET PROPERTIES EDITING... + mTilesetDocument->setCurrentObject(wangSet); + emit mTilesetDocument->editCurrentObject(); } void WangSetView::adjustScale() From 52ae86202529b99288ff300ac1ecdfdb49977fec Mon Sep 17 00:00:00 2001 From: Benjamin Trotter Date: Thu, 29 Jun 2017 10:11:18 -0700 Subject: [PATCH 13/21] Cleaned up a few things --- src/tiled/{addremocewangset.cpp => addremovewangset.cpp} | 0 src/tiled/addremovewangset.h | 1 - src/tiled/tiled.qbs | 2 +- src/tiled/tilesetdocument.cpp | 2 +- src/tiled/tilesetdocument.h | 2 +- src/tiled/tileseteditor.cpp | 2 ++ src/tiled/wangsetview.cpp | 2 +- 7 files changed, 6 insertions(+), 5 deletions(-) rename src/tiled/{addremocewangset.cpp => addremovewangset.cpp} (100%) diff --git a/src/tiled/addremocewangset.cpp b/src/tiled/addremovewangset.cpp similarity index 100% rename from src/tiled/addremocewangset.cpp rename to src/tiled/addremovewangset.cpp diff --git a/src/tiled/addremovewangset.h b/src/tiled/addremovewangset.h index 1a25fcf567..e8bca08591 100644 --- a/src/tiled/addremovewangset.h +++ b/src/tiled/addremovewangset.h @@ -45,7 +45,6 @@ class AddRemoveWangSet : public QUndoCommand private: TilesetDocument *mTilesetDocument; - Tileset *mTileset; int mIndex; WangSet *mWangSet; }; diff --git a/src/tiled/tiled.qbs b/src/tiled/tiled.qbs index 65b9c72dd6..ad50be6c13 100644 --- a/src/tiled/tiled.qbs +++ b/src/tiled/tiled.qbs @@ -70,7 +70,6 @@ QtGuiApplication { "addpropertydialog.cpp", "addpropertydialog.h", "addpropertydialog.ui", - "addremocewangset.cpp", "addremovelayer.cpp", "addremovelayer.h", "addremovemapobject.cpp", @@ -81,6 +80,7 @@ QtGuiApplication { "addremovetileset.cpp", "addremovetileset.h", "addremovetiles.h", + "addremovewangset.cpp", "addremovewangset.h", "adjusttileindexes.cpp", "adjusttileindexes.h", diff --git a/src/tiled/tilesetdocument.cpp b/src/tiled/tilesetdocument.cpp index 41de8d7fd9..7a09421cb9 100644 --- a/src/tiled/tilesetdocument.cpp +++ b/src/tiled/tilesetdocument.cpp @@ -341,7 +341,7 @@ void TilesetDocument::onTerrainRemoved(Terrain *terrain) setCurrentObject(nullptr); } -void TilesetDocument::onWangSetRemoved(WangSet *wangSet) +void TilesetDocument::onWangSetRemoved() { for (MapDocument *mapDocument : mapDocuments()) emit mapDocument->tilesetWangSetRemoved(mTileset.data()); diff --git a/src/tiled/tilesetdocument.h b/src/tiled/tilesetdocument.h index d41d1f394c..0dda612148 100644 --- a/src/tiled/tilesetdocument.h +++ b/src/tiled/tilesetdocument.h @@ -142,7 +142,7 @@ private slots: void onPropertiesChanged(Object *object); void onTerrainRemoved(Terrain *terrain); - void onWangSetRemoved(WangSet *wangSet); + void onWangSetRemoved(); private: SharedTileset mTileset; diff --git a/src/tiled/tileseteditor.cpp b/src/tiled/tileseteditor.cpp index 4518b1fd46..7488f1f56c 100644 --- a/src/tiled/tileseteditor.cpp +++ b/src/tiled/tileseteditor.cpp @@ -856,7 +856,9 @@ void TilesetEditor::removeTerrainType() void TilesetEditor::currentWangSetChanged(const WangSet *wangSet) { + //Currently not used, as assigning tiles is not yet supported. + Q_UNUSED(wangSet); } void TilesetEditor::addWangSet() diff --git a/src/tiled/wangsetview.cpp b/src/tiled/wangsetview.cpp index 24a76eb179..9b4d06bf05 100644 --- a/src/tiled/wangsetview.cpp +++ b/src/tiled/wangsetview.cpp @@ -22,7 +22,7 @@ #include "tileset.h" #include "tilesetdocument.h" -#include "wangSet.h" +#include "wangset.h" #include "wangsetmodel.h" #include "utils.h" #include "zoomable.h" From 4398cea1da6efe62a18d592ea4442255f7b7fe1c Mon Sep 17 00:00:00 2001 From: Benjamin Trotter Date: Thu, 29 Jun 2017 13:06:06 -0700 Subject: [PATCH 14/21] remoced references to 'addremocewangset --- src/tiled/tiled.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tiled/tiled.pro b/src/tiled/tiled.pro index 84b4ed3cc1..347a94c466 100644 --- a/src/tiled/tiled.pro +++ b/src/tiled/tiled.pro @@ -84,7 +84,7 @@ SOURCES += aboutdialog.cpp \ addremoveterrain.cpp \ addremovetiles.cpp \ addremovetileset.cpp \ - addremocewangset.cpp \ + addremovewangset.cpp \ adjusttileindexes.cpp \ automapper.cpp \ automapperwrapper.cpp \ From 7f58709563f15db889e7e17b1cd0e844dabfd0c0 Mon Sep 17 00:00:00 2001 From: Benjamin Trotter Date: Fri, 30 Jun 2017 08:22:27 -0700 Subject: [PATCH 15/21] Now can assign wangsets an image, added functions for getting the wangId based on surrounding tiles. --- src/libtiled/mapreader.cpp | 2 +- src/libtiled/wangset.cpp | 43 +++++++++++++++++++++++++- src/libtiled/wangset.h | 19 ++++++++++++ src/tiled/changewangsetdata.cpp | 53 ++++++++++++++++++++++++++++++--- src/tiled/changewangsetdata.h | 45 ++++++++++++++++++++++++++-- src/tiled/tileseteditor.cpp | 25 ++++++++++++++-- src/tiled/tileseteditor.h | 1 + src/tiled/tilesetview.cpp | 26 ++++++++++++++++ src/tiled/tilesetview.h | 10 +++++++ 9 files changed, 214 insertions(+), 10 deletions(-) diff --git a/src/libtiled/mapreader.cpp b/src/libtiled/mapreader.cpp index 29c384d4a9..410c3bcca0 100644 --- a/src/libtiled/mapreader.cpp +++ b/src/libtiled/mapreader.cpp @@ -592,7 +592,7 @@ void MapReaderPrivate::readTilesetWangSet(Tileset &tileset) int tileId = tileAtts.value(QLatin1String("tileid")).toInt(); int wangId = tileAtts.value(QLatin1String("wangid")).toInt(); - wangSet->addTile(tileset.tileAt(tileId), wangId); + wangSet->addTile(tileset.findOrCreateTile(tileId), wangId); xml.skipCurrentElement(); } else diff --git a/src/libtiled/wangset.cpp b/src/libtiled/wangset.cpp index 38ec7d6e39..9b5280ab9a 100644 --- a/src/libtiled/wangset.cpp +++ b/src/libtiled/wangset.cpp @@ -28,7 +28,6 @@ #include "wangset.h" #include -#include using namespace Tiled; @@ -146,6 +145,48 @@ QList WangSet::findMatchingTiles(WangId wangId) const return list; } +WangId WangSet::wangIdFromSurrounding(WangId surroundingWangIds[]) const +{ + unsigned id = 0; + + if(mEdgeColors > 0) { + for (int i = 0; i < 3; ++i) { + id |= (surroundingWangIds[i*2].edgeColor((2 + i) % 4)) << (i*8); + } + } + + if(mCornerColors > 0) { + for (int i = 0; i < 3; ++i) { + int color = surroundingWangIds[i*2 + 1].cornerColor((2 + i) % 4); + + if (!color) { + color = surroundingWangIds[i*2].cornerColor((1 + i) % 4); + } + + if (!color) { + color = surroundingWangIds[i*2 + 2].cornerColor((3 + i) % 4); + } + + id |= color << (4 + i*8); + } + } + + return id; +} + +WangId WangSet::wangIdFromSurrounding(const Tile *surroundingWangIds[]) const +{ + WangId wangIds[8]; + + for (int i = 0; i < 8; ++i) { + wangIds[i] = wangIdOfTile(surroundingWangIds[i]); + } + + WangId wangId = wangIdFromSurrounding(wangIds); + + return wangId; +} + WangId WangSet::wangIdOfTile(const Tile *tile) const { return mTileIdToWangId.value(tile->id()); diff --git a/src/libtiled/wangset.h b/src/libtiled/wangset.h index 735cbfac48..de13133d50 100644 --- a/src/libtiled/wangset.h +++ b/src/libtiled/wangset.h @@ -137,11 +137,30 @@ class TILEDSHARED_EXPORT WangSet : public Object * */ QList findMatchingTiles(WangId wangId) const; + /* Returns a wangId matching that of the provided surrounding wangIds. + * This is based off a provided array, {a, b, c, d, e, f, g, h}, + * which corrisponds to h|a|b + * g|X|c + * f|e|d + * */ + WangId wangIdFromSurrounding(WangId surroundingWangIds[]) const; + + /* Returns a wangId matching that of the provided surrounding tiles. + * This is based off a provided array, {a, b, c, d, e, f, g, h}, + * which corrisponds to h|a|b + * g|X|c + * f|e|d + * */ + WangId wangIdFromSurrounding(const Tile *surroundingWangIds[]) const; /* Returns the wangId of a given Tile. * */ WangId wangIdOfTile(const Tile *tile) const; + /* Returns whether or not the given wangId is valid in the contex of the current wangSet + * */ + bool wangIdIsValid(WangId wangId) const; + /* Returns a clone of this wangset * */ WangSet *clone(Tileset *tileset) const; diff --git a/src/tiled/changewangsetdata.cpp b/src/tiled/changewangsetdata.cpp index 23766e569c..b9e24ff735 100644 --- a/src/tiled/changewangsetdata.cpp +++ b/src/tiled/changewangsetdata.cpp @@ -1,3 +1,30 @@ +/* + * changewangsetdata.cpp + * Copyright 2017, Benjamin Trotter + * This file is part of libtiled. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include "changewangsetdata.h" #include "wangset.h" @@ -16,9 +43,8 @@ ChangeWangSetEdges::ChangeWangSetEdges(TilesetDocument *tilesetDocument, : QUndoCommand(QCoreApplication::translate("Undo Commands", "Change Wang Set edge count")) , mWangSetModel(tilesetDocument->wangSetModel()) - , mTileset(tilesetDocument->tileset().data()) , mIndex(index) - , mOldValue(mTileset->wangSet(index)->edgeColors()) + , mOldValue(tilesetDocument->tileset()->wangSet(index)->edgeColors()) , mNewValue(newValue) { } @@ -39,9 +65,8 @@ ChangeWangSetCorners::ChangeWangSetCorners(TilesetDocument *tilesetDocument, : QUndoCommand(QCoreApplication::translate("Undo Commands", "Change Wang Set corner count")) , mWangSetModel(tilesetDocument->wangSetModel()) - , mTileset(tilesetDocument->tileset().data()) , mIndex(index) - , mOldValue(mTileset->wangSet(index)->cornerColors()) + , mOldValue(tilesetDocument->tileset()->wangSet(index)->cornerColors()) , mNewValue(newValue) { } @@ -55,3 +80,23 @@ void ChangeWangSetCorners::redo() { mWangSetModel->setWangSetCorners(mIndex, mNewValue); } + +SetWangSetImage::SetWangSetImage(TilesetDocument *tilesetDocument, int index, int tileId) + : QUndoCommand(QCoreApplication::translate("Undo Commands", + "Set Wang Set Image")) + , mWangSetModel(tilesetDocument->wangSetModel()) + , mIndex(index) + , mOldImageTileId(tilesetDocument->tileset()->wangSet(index)->imageTileId()) + , mNewImageTileId(tileId) +{ +} + +void SetWangSetImage::undo() +{ + mWangSetModel->setWangSetImage(mIndex, mOldImageTileId); +} + +void SetWangSetImage::redo() +{ + mWangSetModel->setWangSetImage(mIndex, mNewImageTileId); +} diff --git a/src/tiled/changewangsetdata.h b/src/tiled/changewangsetdata.h index deae56109f..ce3f70d2e5 100644 --- a/src/tiled/changewangsetdata.h +++ b/src/tiled/changewangsetdata.h @@ -1,3 +1,30 @@ +/* + * changewangsetdata.h + * Copyright 2017, Benjamin Trotter + * This file is part of libtiled. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #pragma once #include @@ -23,7 +50,6 @@ class ChangeWangSetEdges : public QUndoCommand private: TilesetWangSetModel *mWangSetModel; - Tileset *mTileset; int mIndex; int mOldValue; int mNewValue; @@ -41,11 +67,26 @@ class ChangeWangSetCorners : public QUndoCommand private: TilesetWangSetModel *mWangSetModel; - Tileset *mTileset; int mIndex; int mOldValue; int mNewValue; }; +class SetWangSetImage : public QUndoCommand +{ +public: + SetWangSetImage(TilesetDocument *tilesetDocument, + int index, + int tileId); + + void undo() override; + void redo() override; +private: + TilesetWangSetModel *mWangSetModel; + int mIndex; + int mOldImageTileId; + int mNewImageTileId; +}; + } // namespace Internal } // namespace Tiled diff --git a/src/tiled/tileseteditor.cpp b/src/tiled/tileseteditor.cpp index 7488f1f56c..1002417477 100644 --- a/src/tiled/tileseteditor.cpp +++ b/src/tiled/tileseteditor.cpp @@ -25,6 +25,7 @@ #include "addremovetiles.h" #include "addremovewangset.h" #include "changetileterrain.h" +#include "changewangsetdata.h" #include "erasetiles.h" #include "maintoolbar.h" #include "mapdocument.h" @@ -311,6 +312,8 @@ void TilesetEditor::addDocument(Document *document) connect(view, &TilesetView::createNewTerrain, this, &TilesetEditor::addTerrainType); connect(view, &TilesetView::terrainImageSelected, this, &TilesetEditor::setTerrainImage); + connect(view, &TilesetView::wangSetImageSelected, this, &TilesetEditor::setWangSetImage); + QItemSelectionModel *s = view->selectionModel(); connect(s, &QItemSelectionModel::selectionChanged, this, &TilesetEditor::selectionChanged); connect(s, &QItemSelectionModel::currentChanged, this, &TilesetEditor::currentChanged); @@ -359,6 +362,7 @@ void TilesetEditor::setCurrentDocument(Document *document) mWidgetStack->setCurrentWidget(tilesetView); tilesetView->setEditTerrain(mTerrainDock->isVisible()); + tilesetView->setEditWangSet(mWangDock->isVisible()); tilesetView->zoomable()->setComboBox(mZoomComboBox); } @@ -787,6 +791,9 @@ void TilesetEditor::setEditCollision(bool editCollision) void TilesetEditor::setEditWang(bool editWang) { + if (TilesetView *view = currentTilesetView()) + view->setEditWangSet(editWang); + if (editWang) { mTerrainDock->setVisible(false); mTileCollisionDock->setVisible(false); @@ -856,9 +863,12 @@ void TilesetEditor::removeTerrainType() void TilesetEditor::currentWangSetChanged(const WangSet *wangSet) { - //Currently not used, as assigning tiles is not yet supported. + TilesetView *view = currentTilesetView(); + if (!view) + return; - Q_UNUSED(wangSet); + if (wangSet) + view->setWangSet(wangSet); } void TilesetEditor::addWangSet() @@ -896,6 +906,17 @@ void TilesetEditor::setTerrainImage(Tile *tile) tile->id())); } +void TilesetEditor::setWangSetImage(Tile *tile) +{ + WangSet *wangSet = mWangDock->currentWangSet(); + if(!wangSet) + return; + + mCurrentTilesetDocument->undoStack()->push(new SetWangSetImage(mCurrentTilesetDocument, + mCurrentTilesetDocument->tileset()->wangSets().indexOf(wangSet), + tile->id())); +} + void TilesetEditor::updateAddRemoveActions() { bool isCollection = false; diff --git a/src/tiled/tileseteditor.h b/src/tiled/tileseteditor.h index d73c7e7e06..72d934ef75 100644 --- a/src/tiled/tileseteditor.h +++ b/src/tiled/tileseteditor.h @@ -119,6 +119,7 @@ private slots: void currentWangSetChanged(const WangSet *wangSet); void addWangSet(); void removeWangSet(); + void setWangSetImage(Tile *tile); private: void setCurrentTile(Tile *tile); diff --git a/src/tiled/tilesetview.cpp b/src/tiled/tilesetview.cpp index 1883ffc273..dbdb800eb1 100644 --- a/src/tiled/tilesetview.cpp +++ b/src/tiled/tilesetview.cpp @@ -30,6 +30,7 @@ #include "tilesetdocument.h" #include "tilesetmodel.h" #include "utils.h" +#include "wangset.h" #include "zoomable.h" #include @@ -540,6 +541,11 @@ void TilesetView::setEditTerrain(bool enabled) viewport()->update(); } +void TilesetView::setEditWangSet(bool enabled) +{ + mEditWangSet = enabled; +} + /** * The id of the terrain currently being specified. Returns -1 when no terrain * is set (used for erasing terrain info). @@ -559,6 +565,11 @@ void TilesetView::setTerrain(const Terrain *terrain) viewport()->update(); } +void TilesetView::setWangSet(const WangSet *wangSet) +{ + mWangSet = wangSet; +} + QIcon TilesetView::imageMissingIcon() const { return QIcon::fromTheme(QLatin1String("image-missing"), mImageMissingIcon); @@ -707,6 +718,15 @@ void TilesetView::contextMenuEvent(QContextMenuEvent *event) QAction *setImage = menu.addAction(tr("Set Terrain Image")); connect(setImage, SIGNAL(triggered()), SLOT(selectTerrainImage())); } + } else if (mEditWangSet) { + selectionModel()->setCurrentIndex(index, + QItemSelectionModel::SelectCurrent | + QItemSelectionModel::Clear); + + if(mWangSet) { + QAction *setImage = menu.addAction(tr("Set WangSet Image")); + connect(setImage, SIGNAL(triggered()), SLOT(selectWangSetImage())); + } } else if (mTilesetDocument) { QAction *tileProperties = menu.addAction(propIcon, tr("Tile &Properties...")); @@ -763,6 +783,12 @@ void TilesetView::selectTerrainImage() emit terrainImageSelected(tile); } +void TilesetView::selectWangSetImage() +{ + if (Tile *tile = currentTile()) + emit wangSetImageSelected(tile); +} + void TilesetView::editTileProperties() { Q_ASSERT(mTilesetDocument); diff --git a/src/tiled/tilesetview.h b/src/tiled/tilesetview.h index c302c31754..e2ded6253d 100644 --- a/src/tiled/tilesetview.h +++ b/src/tiled/tilesetview.h @@ -27,6 +27,7 @@ namespace Tiled { class Terrain; +class WangSet; namespace Internal { @@ -91,6 +92,9 @@ class TilesetView : public QTableView */ void setEditTerrain(bool enabled); + bool isEditWangSet() const { return mEditWangSet; } + void setEditWangSet(bool enabled); + /** * Sets whether terrain editing is in "erase" mode. * \sa setEditTerrain @@ -105,6 +109,8 @@ class TilesetView : public QTableView */ void setTerrain(const Terrain *terrain); + void setWangSet(const WangSet *wangSet); + QModelIndex hoveredIndex() const { return mHoveredIndex; } int hoveredCorner() const { return mHoveredCorner; } @@ -115,6 +121,7 @@ class TilesetView : public QTableView signals: void createNewTerrain(Tile *tile); void terrainImageSelected(Tile *tile); + void wangSetImageSelected(Tile *tile); void swapTilesRequested(Tile *tileA, Tile *tileB); void changeSelectedMapObjectsTileRequested(Tile *tile); @@ -131,6 +138,7 @@ class TilesetView : public QTableView private slots: void addTerrainType(); void selectTerrainImage(); + void selectWangSetImage(); void editTileProperties(); void swapTiles(); void changeSelectedMapObjectsTile(); @@ -150,8 +158,10 @@ private slots: bool mMarkAnimatedTiles; bool mEditTerrain; + bool mEditWangSet; bool mEraseTerrain; const Terrain *mTerrain; + const WangSet *mWangSet; QModelIndex mHoveredIndex; int mHoveredCorner; bool mTerrainChanged; From bb6b98ac492a22d2d038e2590e9ab75b7abce007 Mon Sep 17 00:00:00 2001 From: Benjamin Trotter Date: Sat, 1 Jul 2017 22:25:31 -0700 Subject: [PATCH 16/21] Beging to store info about tile rotation and inversion --- src/libtiled/mapwriter.cpp | 2 +- src/libtiled/wangset.cpp | 89 ++++++++++++++++++++++++++++++++------ src/libtiled/wangset.h | 70 +++++++++++++++++++++++++++--- 3 files changed, 141 insertions(+), 20 deletions(-) diff --git a/src/libtiled/mapwriter.cpp b/src/libtiled/mapwriter.cpp index efffa2264b..fb74250c67 100644 --- a/src/libtiled/mapwriter.cpp +++ b/src/libtiled/mapwriter.cpp @@ -439,7 +439,7 @@ void MapWriterPrivate::writeTileset(QXmlStreamWriter &w, const Tileset &tileset, //write each tile with a valid wangId for (const Tile *tile : tileset.tiles()) { - if (int wId = ws->wangIdOfTile(tile)) { + if (unsigned wId = ws->wangIdOfTile(tile)) { w.writeStartElement(QLatin1String("wangsettile")); w.writeAttribute(QLatin1String("tileid"), QString::number(tile->id())); w.writeAttribute(QLatin1String("wangid"), QString::number(wId)); diff --git a/src/libtiled/wangset.cpp b/src/libtiled/wangset.cpp index 9b5280ab9a..322dcc6a8c 100644 --- a/src/libtiled/wangset.cpp +++ b/src/libtiled/wangset.cpp @@ -25,12 +25,61 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "tilelayer.h" #include "wangset.h" #include using namespace Tiled; +namespace Tiled { + +unsigned qHash(const Cell &cell) +{ + unsigned hash = cell.tileId(); + + hash |= ((cell.flippedHorizontally() << 2) + | (cell.flippedVertically() << 1) + | (cell.flippedAntiDiagonally())) << 29; + + return hash; +} + +} // namespace Tiled + +void WangTile::rotateRight() +{ + +} + +void WangTile::rotateLeft() +{ + +} + +void WangTile::flipHorizontally() +{ + +} + +void WangTile::flipVertically() +{ + +} + +Cell WangTile::makeCell() const +{ + if(!mTile) + return Cell(); + + Cell cell(mTile); + cell.setFlippedHorizontally(mFlippedHorizontally); + cell.setFlippedVertically(mFlippedVertically); + cell.setFlippedAntiDiagonally(mFlippedAntiDiagonally); + + return cell; +} + WangSet::WangSet(Tileset *tileset, int edgeColors, int cornerColors, @@ -57,18 +106,18 @@ void WangSet::addTile(Tile *tile, WangId wangId) Q_ASSERT(wangId.cornerColor(i) <= mCornerColors); } - mWangIdToTile.insert(wangId, tile); - mTileIdToWangId.insert(tile->id(), wangId); + mWangIdToWangTile.insert(wangId, WangTile(tile, wangId)); + mCellToWangId.insert(Cell(tile), wangId); } -Tile *WangSet::findMatchingTile(WangId wangId) const +WangTile WangSet::findMatchingWangTile(WangId wangId) const { - auto potentials = findMatchingTiles(wangId); + auto potentials = findMatchingWangTiles(wangId); if (potentials.length() > 0) return potentials[qrand() % potentials.length()]; else - return NULL; + return WangTile(); } struct WangWildCard @@ -76,9 +125,9 @@ struct WangWildCard int index, colorCount; }; -QList WangSet::findMatchingTiles(WangId wangId) const +QList WangSet::findMatchingWangTiles(WangId wangId) const { - QList list; + QList list; //Stores the space of a wild card, followed by how many colors that space can have. QVector wildCards; @@ -108,7 +157,7 @@ QList WangSet::findMatchingTiles(WangId wangId) const } if (wildCards.isEmpty()) { - list.append(mWangIdToTile.values(wangId)); + list.append(mWangIdToWangTile.values(wangId)); } else { QStack stack; @@ -123,7 +172,7 @@ QList WangSet::findMatchingTiles(WangId wangId) const for (int i = 0; i < max; ++i) idVariation |= stack[i].colorCount << stack[i].index; - list.append(mWangIdToTile.values(idVariation | wangId)); + list.append(mWangIdToWangTile.values(idVariation | wangId)); WangWildCard top = stack.pop(); top.colorCount -= 1; @@ -145,6 +194,13 @@ QList WangSet::findMatchingTiles(WangId wangId) const return list; } +Cell WangSet::findMatchingCell(WangId wangId) const +{ + WangTile wangTile = findMatchingWangTile(wangId); + + return wangTile.makeCell(); +} + WangId WangSet::wangIdFromSurrounding(WangId surroundingWangIds[]) const { unsigned id = 0; @@ -174,12 +230,12 @@ WangId WangSet::wangIdFromSurrounding(WangId surroundingWangIds[]) const return id; } -WangId WangSet::wangIdFromSurrounding(const Tile *surroundingWangIds[]) const +WangId WangSet::wangIdFromSurrounding(const Cell surroundingWangIds[]) const { WangId wangIds[8]; for (int i = 0; i < 8; ++i) { - wangIds[i] = wangIdOfTile(surroundingWangIds[i]); + wangIds[i] = wangIdOfCell(surroundingWangIds[i]); } WangId wangId = wangIdFromSurrounding(wangIds); @@ -189,15 +245,20 @@ WangId WangSet::wangIdFromSurrounding(const Tile *surroundingWangIds[]) const WangId WangSet::wangIdOfTile(const Tile *tile) const { - return mTileIdToWangId.value(tile->id()); + return mCellToWangId.value(Cell((Tile*)tile)); +} + +WangId WangSet::wangIdOfCell(const Cell &cell) const +{ + return mCellToWangId.value(cell); } WangSet *WangSet::clone(Tileset *tileset) const { WangSet *c = new WangSet(tileset, mEdgeColors, mCornerColors, mName, mImageTileId); - c->mWangIdToTile = mWangIdToTile; - c->mTileIdToWangId = mTileIdToWangId; + c->mWangIdToWangTile = mWangIdToWangTile; + c->mCellToWangId = mCellToWangId; return c; } diff --git a/src/libtiled/wangset.h b/src/libtiled/wangset.h index de13133d50..e9dcf0f605 100644 --- a/src/libtiled/wangset.h +++ b/src/libtiled/wangset.h @@ -29,6 +29,7 @@ #include "tile.h" #include "tileset.h" +#include "tilelayer.h" #include #include @@ -58,6 +59,14 @@ class WangId * */ void rotate(int rotations); + /* Flips the wang Id horizontally + * */ + void flipHorizontally(); + + /* Flips the wang Id vertically + * */ + void flipVertically(); + private: unsigned mId; }; @@ -93,6 +102,50 @@ inline void WangId::rotate(int rotations) mId = rotated; } +//Class for holding info about rotation and flipping. +class TILEDSHARED_EXPORT WangTile +{ +public: + WangTile(): + mTile(nullptr), + mWangId(0), + mFlippedHorizontally(false), + mFlippedVertically(false), + mFlippedAntiDiagonally(false) + {} + + WangTile(Tile *tile, + WangId wangId): + mTile(tile), + mWangId(wangId), + mFlippedHorizontally(false), + mFlippedVertically(false), + mFlippedAntiDiagonally(false) + {} + + Tile *tile() const { return mTile; } + + WangId wangId() const { return mWangId; } + + bool flippedHorizontally() const { return mFlippedHorizontally; } + bool flippedVertically() const { return mFlippedVertically; } + bool flippedAntiDiagonally() const { return mFlippedAntiDiagonally; } + + void rotateRight(); + void rotateLeft(); + void flipHorizontally(); + void flipVertically(); + + Cell makeCell() const; + +private: + Tile *mTile; + WangId mWangId; + bool mFlippedHorizontally; + bool mFlippedVertically; + bool mFlippedAntiDiagonally; +}; + /** * Represents a wang set. */ @@ -129,13 +182,18 @@ class TILEDSHARED_EXPORT WangSet : public Object * where zeros in the id are treated as wild cards, and can be * any color. * */ - Tile *findMatchingTile(WangId wangId) const; + WangTile findMatchingWangTile(WangId wangId) const; /* Finds all the tiles which match the given wangId, * where zeros in the id are treated as wild cards, and can be * any color. * */ - QList findMatchingTiles(WangId wangId) const; + QList findMatchingWangTiles(WangId wangId) const; + + /* Finds a wangTile mathcing the provided wangId, and creates, + * and returns a Cell matching the WangTile. + * */ + Cell findMatchingCell(WangId wangId) const; /* Returns a wangId matching that of the provided surrounding wangIds. * This is based off a provided array, {a, b, c, d, e, f, g, h}, @@ -151,12 +209,14 @@ class TILEDSHARED_EXPORT WangSet : public Object * g|X|c * f|e|d * */ - WangId wangIdFromSurrounding(const Tile *surroundingWangIds[]) const; + WangId wangIdFromSurrounding(const Cell surroundingWangIds[]) const; /* Returns the wangId of a given Tile. * */ WangId wangIdOfTile(const Tile *tile) const; + WangId wangIdOfCell(const Cell &cell) const; + /* Returns whether or not the given wangId is valid in the contex of the current wangSet * */ bool wangIdIsValid(WangId wangId) const; @@ -171,8 +231,8 @@ class TILEDSHARED_EXPORT WangSet : public Object int mImageTileId; int mEdgeColors; int mCornerColors; - QMultiHash mWangIdToTile; - QHash mTileIdToWangId; + QMultiHash mWangIdToWangTile; + QHash mCellToWangId; }; } // namespace Tiled From 0969d4671e860b32c786402b8bd1fb6454d2650b Mon Sep 17 00:00:00 2001 From: Benjamin Trotter Date: Sun, 2 Jul 2017 16:36:09 -0700 Subject: [PATCH 17/21] Wangsets now store info about rotation and flipping, mapreader/writer reflects this --- README.md | 1 + src/libtiled/mapreader.cpp | 16 +++++-- src/libtiled/mapwriter.cpp | 17 ++++++++ src/libtiled/wangset.cpp | 85 ++++++++++++++++++++++++++++---------- src/libtiled/wangset.h | 30 +++++++++++++- 5 files changed, 123 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 9663e24176..2aa53ce1cc 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ tilesets while also allowing each tileset to grow or shrink as necessary later. [![Build status](https://ci.appveyor.com/api/projects/status/ceb79jn5cf99y3qd/branch/master?svg=true)](https://ci.appveyor.com/project/bjorn/tiled/branch/master) [![Bountysource](https://www.bountysource.com/badge/tracker?tracker_id=52019)](https://www.bountysource.com/trackers/52019-tiled?utm_source=52019&utm_medium=shield&utm_campaign=TRACKER_BADGE) [![Translation status](https://hosted.weblate.org/widgets/tiled/-/shields-badge.svg)](https://hosted.weblate.org/engage/tiled/?utm_source=widget) +[![LiveEdu.tv](http://codiad-billauger.rhcloud.com/badges/?style=online-status-v1&channel=bjorn&offline=Follow to get notified)](https://www.liveedu.tv/bjorn/) About the Qt Version ------------------------------------------------------------------------------- diff --git a/src/libtiled/mapreader.cpp b/src/libtiled/mapreader.cpp index 410c3bcca0..55c6bfc9da 100644 --- a/src/libtiled/mapreader.cpp +++ b/src/libtiled/mapreader.cpp @@ -587,12 +587,22 @@ void MapReaderPrivate::readTilesetWangSet(Tileset &tileset) while (xml.readNextStartElement()) { if (xml.name() == QLatin1String("properties")) wangSet->mergeProperties(readProperties()); - else if (xml.name() == QLatin1String("wangsettile")) { + else if (xml.name() == QLatin1String("wangtile")) { const QXmlStreamAttributes tileAtts = xml.attributes(); int tileId = tileAtts.value(QLatin1String("tileid")).toInt(); - int wangId = tileAtts.value(QLatin1String("wangid")).toInt(); + unsigned wangId = tileAtts.value(QLatin1String("wangid")).toUInt(); + bool fH = tileAtts.value(QLatin1String("flippedhorizontally")).toInt(); + bool fV = tileAtts.value(QLatin1String("flippedvertically")).toInt(); + bool fA = tileAtts.value(QLatin1String("flippedantidiagonally")).toInt(); - wangSet->addTile(tileset.findOrCreateTile(tileId), wangId); + Tile *tile = tileset.findOrCreateTile(tileId); + + WangTile wangTile(tile, wangId); + wangTile.setFlippedHorizontally(fH); + wangTile.setFlippedVertically(fV); + wangTile.setFlippedAntiDiagonally(fA); + + wangSet->addWangTile(wangTile); xml.skipCurrentElement(); } else diff --git a/src/libtiled/mapwriter.cpp b/src/libtiled/mapwriter.cpp index fb74250c67..df0a331837 100644 --- a/src/libtiled/mapwriter.cpp +++ b/src/libtiled/mapwriter.cpp @@ -437,6 +437,23 @@ void MapWriterPrivate::writeTileset(QXmlStreamWriter &w, const Tileset &tileset, w.writeAttribute(QLatin1String("corners"), QString::number(ws->cornerColors())); w.writeAttribute(QLatin1String("tile"), QString::number(ws->imageTileId())); + for (const WangTile &wangTile : ws->wangTiles()) { + w.writeStartElement(QLatin1String("wangtile")); + w.writeAttribute(QLatin1String("tileid"), QString::number(wangTile.tile()->id())); + w.writeAttribute(QLatin1String("wangid"), QString::number(wangTile.wangId())); + + if (wangTile.flippedHorizontally()) + w.writeAttribute(QLatin1String("flippedhorizontally"), QString::number(1)); + + if (wangTile.flippedVertically()) + w.writeAttribute(QLatin1String("flippedvertically"), QString::number(1)); + + if (wangTile.flippedAntiDiagonally()) + w.writeAttribute(QLatin1String("flippedantidiagonally"), QString::number(1)); + + w.writeEndElement(); // + } + //write each tile with a valid wangId for (const Tile *tile : tileset.tiles()) { if (unsigned wId = ws->wangIdOfTile(tile)) { diff --git a/src/libtiled/wangset.cpp b/src/libtiled/wangset.cpp index 322dcc6a8c..cd5652313c 100644 --- a/src/libtiled/wangset.cpp +++ b/src/libtiled/wangset.cpp @@ -32,39 +32,61 @@ using namespace Tiled; -namespace Tiled { +unsigned cellToTileInfo(const Cell &cell) +{ + return cell.tileId() + | (cell.flippedHorizontally() << 29) + | (cell.flippedVertically() << 28) + | (cell.flippedAntiDiagonally() << 27); +} + +unsigned wangTileToTileInfo(const WangTile &wangTile) +{ + return wangTile.tile()->id() + | (wangTile.flippedHorizontally() << 29) + | (wangTile.flippedVertically() << 28) + | (wangTile.flippedAntiDiagonally() << 27); +} -unsigned qHash(const Cell &cell) +void WangTile::translate(int map[]) { - unsigned hash = cell.tileId(); + int mask = (mFlippedHorizontally << 2) + | (mFlippedVertically << 1) + | (mFlippedAntiDiagonally); - hash |= ((cell.flippedHorizontally() << 2) - | (cell.flippedVertically() << 1) - | (cell.flippedAntiDiagonally())) << 29; + mask = map[mask]; - return hash; + mFlippedHorizontally = mask & 4; + mFlippedVertically = mask & 2; + mFlippedAntiDiagonally = mask & 1; } -} // namespace Tiled - void WangTile::rotateRight() { + int map[] = {5, 4, 1, 0, 7, 6, 3, 2}; + translate(map); } void WangTile::rotateLeft() { + int map[] = {3, 2, 7, 6, 1, 0, 5, 4}; + translate(map); } void WangTile::flipHorizontally() { + int map[] = {4, 3, 6, 1, 0, 7, 2, 5}; + translate(map); } void WangTile::flipVertically() { + int map[] = {2, 5, 0, 7, 6, 1, 4, 3}; + translate(map); } Cell WangTile::makeCell() const @@ -96,18 +118,26 @@ WangSet::WangSet(Tileset *tileset, void WangSet::addTile(Tile *tile, WangId wangId) { - Q_ASSERT(tile->tileset() == mTileset); + Q_ASSERT(tile->tileset() == mTileset && wangIdIsValid(wangId)); - for (int i = 0; i < 4; ++i) { - Q_ASSERT(wangId.edgeColor(i) <= mEdgeColors); - } + mWangIdToWangTile.insert(wangId, WangTile(tile, wangId)); + mTileInfoToWangId.insert(tile->id(), wangId); +} - for (int i = 0; i < 4; ++i) { - Q_ASSERT(wangId.cornerColor(i) <= mCornerColors); - } +void WangSet::addCell(Cell &cell, WangId wangId) +{ + Q_ASSERT(cell.tileset() == mTileset && wangIdIsValid(wangId)); - mWangIdToWangTile.insert(wangId, WangTile(tile, wangId)); - mCellToWangId.insert(Cell(tile), wangId); + mWangIdToWangTile.insert(wangId, WangTile(cell, wangId)); + mTileInfoToWangId.insert(cellToTileInfo(cell), wangId); +} + +void WangSet::addWangTile(WangTile wangTile) +{ + Q_ASSERT(wangTile.tile()->tileset() == mTileset && wangIdIsValid(wangTile.wangId())); + + mWangIdToWangTile.insert(wangTile.wangId(), wangTile); + mTileInfoToWangId.insert(wangTileToTileInfo(wangTile), wangTile.wangId()); } WangTile WangSet::findMatchingWangTile(WangId wangId) const @@ -245,12 +275,25 @@ WangId WangSet::wangIdFromSurrounding(const Cell surroundingWangIds[]) const WangId WangSet::wangIdOfTile(const Tile *tile) const { - return mCellToWangId.value(Cell((Tile*)tile)); + return mTileInfoToWangId.value(tile->id()); } WangId WangSet::wangIdOfCell(const Cell &cell) const { - return mCellToWangId.value(cell); + return mTileInfoToWangId.value(cellToTileInfo(cell)); +} + +bool WangSet::wangIdIsValid(WangId wangId) const +{ + for (int i = 0; i < 4; ++i) { + if (wangId.edgeColor(i) < 0 + || wangId.edgeColor(i) > mEdgeColors + || wangId.cornerColor(i) < 0 + || wangId.cornerColor(i) > mCornerColors) + return false; + } + + return true; } WangSet *WangSet::clone(Tileset *tileset) const @@ -258,7 +301,7 @@ WangSet *WangSet::clone(Tileset *tileset) const WangSet *c = new WangSet(tileset, mEdgeColors, mCornerColors, mName, mImageTileId); c->mWangIdToWangTile = mWangIdToWangTile; - c->mCellToWangId = mCellToWangId; + c->mTileInfoToWangId = mTileInfoToWangId; return c; } diff --git a/src/libtiled/wangset.h b/src/libtiled/wangset.h index e9dcf0f605..192cac5455 100644 --- a/src/libtiled/wangset.h +++ b/src/libtiled/wangset.h @@ -41,8 +41,9 @@ namespace Tiled { class WangId { public: - WangId(unsigned id) : mId(id) {} + WangId() : mId(0) {} + WangId(unsigned id) : mId(id) {} operator unsigned() const { return mId; } inline void setId(unsigned id) { mId = id; } @@ -123,6 +124,14 @@ class TILEDSHARED_EXPORT WangTile mFlippedAntiDiagonally(false) {} + explicit WangTile(const Cell &cell, WangId wangId): + mTile(cell.tile()), + mWangId(wangId), + mFlippedHorizontally(cell.flippedHorizontally()), + mFlippedVertically(cell.flippedVertically()), + mFlippedAntiDiagonally(cell.flippedAntiDiagonally()) + {} + Tile *tile() const { return mTile; } WangId wangId() const { return mWangId; } @@ -131,6 +140,10 @@ class TILEDSHARED_EXPORT WangTile bool flippedVertically() const { return mFlippedVertically; } bool flippedAntiDiagonally() const { return mFlippedAntiDiagonally; } + void setFlippedHorizontally(bool b) { mFlippedHorizontally = b; } + void setFlippedVertically(bool b) { mFlippedVertically = b; } + void setFlippedAntiDiagonally(bool b) { mFlippedAntiDiagonally = b; } + void rotateRight(); void rotateLeft(); void flipHorizontally(); @@ -139,6 +152,10 @@ class TILEDSHARED_EXPORT WangTile Cell makeCell() const; private: + //performs a translation (either flipping or rotating) based on a one to one + //map of size 8 (from 0 - 7) + void translate(int map[]); + Tile *mTile; WangId mWangId; bool mFlippedHorizontally; @@ -178,6 +195,10 @@ class TILEDSHARED_EXPORT WangSet : public Object * */ void addTile(Tile *tile, WangId wangId); + void addCell(Cell &cell, WangId wangId); + + void addWangTile(WangTile wangTile); + /* Finds a tile whos WangId matches with the one provided, * where zeros in the id are treated as wild cards, and can be * any color. @@ -195,6 +216,8 @@ class TILEDSHARED_EXPORT WangSet : public Object * */ Cell findMatchingCell(WangId wangId) const; + QList wangTiles() const { return mWangIdToWangTile.values(); } + /* Returns a wangId matching that of the provided surrounding wangIds. * This is based off a provided array, {a, b, c, d, e, f, g, h}, * which corrisponds to h|a|b @@ -232,7 +255,10 @@ class TILEDSHARED_EXPORT WangSet : public Object int mEdgeColors; int mCornerColors; QMultiHash mWangIdToWangTile; - QHash mCellToWangId; + + //Tile info being the tileId, with the last three bits (32, 31, 30) + //being info on flip (horizontal, vertical, and antidiagonal) + QHash mTileInfoToWangId; }; } // namespace Tiled From 1df48f573c2bb5bec52e019a244448710c7ba787 Mon Sep 17 00:00:00 2001 From: Benjamin Trotter Date: Mon, 3 Jul 2017 20:29:34 -0700 Subject: [PATCH 18/21] Made requested changes --- src/libtiled/mapreader.cpp | 21 +++++++++--------- src/libtiled/mapwriter.cpp | 21 +++++------------- src/libtiled/tileset.cpp | 11 +++++++-- src/libtiled/tileset.h | 3 ++- src/libtiled/wangset.cpp | 37 ++++++++++++++----------------- src/libtiled/wangset.h | 8 +++---- src/tiled/addremovewangset.cpp | 2 +- src/tiled/changewangsetdata.cpp | 4 ++-- src/tiled/mapdocument.h | 2 -- src/tiled/propertybrowser.cpp | 17 ++++++++------ src/tiled/propertybrowser.h | 4 ++-- src/tiled/tileseteditor.cpp | 4 +++- src/tiled/tilesetwangsetmodel.cpp | 33 +++++++++++---------------- src/tiled/tilesetwangsetmodel.h | 33 +++++++++++---------------- 14 files changed, 93 insertions(+), 107 deletions(-) diff --git a/src/libtiled/mapreader.cpp b/src/libtiled/mapreader.cpp index 55c6bfc9da..bbd2a23f5d 100644 --- a/src/libtiled/mapreader.cpp +++ b/src/libtiled/mapreader.cpp @@ -85,7 +85,7 @@ class MapReaderPrivate void readTilesetGrid(Tileset &tileset); void readTilesetImage(Tileset &tileset); void readTilesetTerrainTypes(Tileset &tileset); - void readTilesetWangSet(Tileset &tileset); + void readTilesetWangSets(Tileset &tileset); ImageReference readImage(); Layer *tryReadLayer(); @@ -356,7 +356,7 @@ SharedTileset MapReaderPrivate::readTileset() } else if (xml.name() == QLatin1String("terraintypes")) { readTilesetTerrainTypes(*tileset); } else if (xml.name() == QLatin1String("wangsets")) { - readTilesetWangSet(*tileset); + readTilesetWangSets(*tileset); } else { readUnknownElement(); } @@ -568,7 +568,7 @@ void MapReaderPrivate::readTilesetTerrainTypes(Tileset &tileset) } } -void MapReaderPrivate::readTilesetWangSet(Tileset &tileset) +void MapReaderPrivate::readTilesetWangSets(Tileset &tileset) { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("wangsets")); @@ -582,18 +582,18 @@ void MapReaderPrivate::readTilesetWangSet(Tileset &tileset) WangSet *wangSet = new WangSet(&tileset, edges, corners, name, tile); - tileset.insertWangSet(wangSet); + tileset.addWangSet(wangSet); while (xml.readNextStartElement()) { - if (xml.name() == QLatin1String("properties")) + if (xml.name() == QLatin1String("properties")) { wangSet->mergeProperties(readProperties()); - else if (xml.name() == QLatin1String("wangtile")) { + } else if (xml.name() == QLatin1String("wangtile")) { const QXmlStreamAttributes tileAtts = xml.attributes(); int tileId = tileAtts.value(QLatin1String("tileid")).toInt(); unsigned wangId = tileAtts.value(QLatin1String("wangid")).toUInt(); - bool fH = tileAtts.value(QLatin1String("flippedhorizontally")).toInt(); - bool fV = tileAtts.value(QLatin1String("flippedvertically")).toInt(); - bool fA = tileAtts.value(QLatin1String("flippedantidiagonally")).toInt(); + bool fH = tileAtts.value(QLatin1String("hflip")).toInt(); + bool fV = tileAtts.value(QLatin1String("vflip")).toInt(); + bool fA = tileAtts.value(QLatin1String("dflip")).toInt(); Tile *tile = tileset.findOrCreateTile(tileId); @@ -605,8 +605,9 @@ void MapReaderPrivate::readTilesetWangSet(Tileset &tileset) wangSet->addWangTile(wangTile); xml.skipCurrentElement(); - } else + } else { readUnknownElement(); + } } } else { readUnknownElement(); diff --git a/src/libtiled/mapwriter.cpp b/src/libtiled/mapwriter.cpp index df0a331837..4a68d9275d 100644 --- a/src/libtiled/mapwriter.cpp +++ b/src/libtiled/mapwriter.cpp @@ -362,6 +362,7 @@ void MapWriterPrivate::writeTileset(QXmlStreamWriter &w, const Tileset &tileset, } w.writeEndElement(); } + // Write the properties for those tiles that have them for (const Tile *tile : tileset.tiles()) { if (imageSource.isEmpty() || includeTile(tile)) { @@ -428,8 +429,7 @@ void MapWriterPrivate::writeTileset(QXmlStreamWriter &w, const Tileset &tileset, // Write the wangsets if (tileset.wangSetCount() > 0) { w.writeStartElement(QLatin1String("wangsets")); - for (int i = 0; i < tileset.wangSetCount(); ++i) { - const WangSet *ws = tileset.wangSet(i); + for (const WangSet *ws : tileset.wangSets()) { w.writeStartElement(QLatin1String("wangset")); w.writeAttribute(QLatin1String("name"), ws->name()); @@ -443,26 +443,17 @@ void MapWriterPrivate::writeTileset(QXmlStreamWriter &w, const Tileset &tileset, w.writeAttribute(QLatin1String("wangid"), QString::number(wangTile.wangId())); if (wangTile.flippedHorizontally()) - w.writeAttribute(QLatin1String("flippedhorizontally"), QString::number(1)); + w.writeAttribute(QLatin1String("hflip"), QString::number(1)); if (wangTile.flippedVertically()) - w.writeAttribute(QLatin1String("flippedvertically"), QString::number(1)); + w.writeAttribute(QLatin1String("vflip"), QString::number(1)); if (wangTile.flippedAntiDiagonally()) - w.writeAttribute(QLatin1String("flippedantidiagonally"), QString::number(1)); + w.writeAttribute(QLatin1String("dflip"), QString::number(1)); - w.writeEndElement(); // + w.writeEndElement(); // } - //write each tile with a valid wangId - for (const Tile *tile : tileset.tiles()) { - if (unsigned wId = ws->wangIdOfTile(tile)) { - w.writeStartElement(QLatin1String("wangsettile")); - w.writeAttribute(QLatin1String("tileid"), QString::number(tile->id())); - w.writeAttribute(QLatin1String("wangid"), QString::number(wId)); - w.writeEndElement(); // - } - } writeProperties(w, ws->properties()); w.writeEndElement(); // diff --git a/src/libtiled/tileset.cpp b/src/libtiled/tileset.cpp index c3f7449f1e..ab2f566575 100644 --- a/src/libtiled/tileset.cpp +++ b/src/libtiled/tileset.cpp @@ -507,15 +507,22 @@ void Tileset::recalculateTerrainDistances() } while (bNewConnections); } +void Tileset::addWangSet(WangSet *wangSet) +{ + Q_ASSERT(wangSet->tileset() == this); + + mWangSets.append(wangSet); +} + /** * @brief Tileset::insertWangSet Adds a wangSet. * @param wangSet A pointer to the wangset to add. */ -void Tileset::insertWangSet(WangSet *wangSet) +void Tileset::insertWangSet(WangSet *wangSet, int index) { Q_ASSERT(wangSet->tileset() == this); - mWangSets.append(wangSet); + mWangSets.insert(index, wangSet); } /** diff --git a/src/libtiled/tileset.h b/src/libtiled/tileset.h index 1320dc2a6b..15742978fd 100644 --- a/src/libtiled/tileset.h +++ b/src/libtiled/tileset.h @@ -189,7 +189,8 @@ class TILEDSHARED_EXPORT Tileset : public Object int wangSetCount() const; WangSet *wangSet(int index) const; - void insertWangSet(WangSet *wangSet); + void addWangSet(WangSet *wangSet); + void insertWangSet(WangSet *wangSet, int index); WangSet *takeWangSetAt(int index); Tile *addTile(const QPixmap &image, const QString &source = QString()); diff --git a/src/libtiled/wangset.cpp b/src/libtiled/wangset.cpp index cd5652313c..1eb4a23361 100644 --- a/src/libtiled/wangset.cpp +++ b/src/libtiled/wangset.cpp @@ -118,23 +118,26 @@ WangSet::WangSet(Tileset *tileset, void WangSet::addTile(Tile *tile, WangId wangId) { - Q_ASSERT(tile->tileset() == mTileset && wangIdIsValid(wangId)); + Q_ASSERT(tile->tileset() == mTileset); + Q_ASSERT(wangIdIsValid(wangId)); mWangIdToWangTile.insert(wangId, WangTile(tile, wangId)); mTileInfoToWangId.insert(tile->id(), wangId); } -void WangSet::addCell(Cell &cell, WangId wangId) +void WangSet::addCell(const Cell &cell, WangId wangId) { - Q_ASSERT(cell.tileset() == mTileset && wangIdIsValid(wangId)); + Q_ASSERT(cell.tileset() == mTileset); + Q_ASSERT(wangIdIsValid(wangId)); mWangIdToWangTile.insert(wangId, WangTile(cell, wangId)); mTileInfoToWangId.insert(cellToTileInfo(cell), wangId); } -void WangSet::addWangTile(WangTile wangTile) +void WangSet::addWangTile(const WangTile &wangTile) { - Q_ASSERT(wangTile.tile()->tileset() == mTileset && wangIdIsValid(wangTile.wangId())); + Q_ASSERT(wangTile.tile()->tileset() == mTileset); + Q_ASSERT(wangIdIsValid(wangTile.wangId())); mWangIdToWangTile.insert(wangTile.wangId(), wangTile); mTileInfoToWangId.insert(wangTileToTileInfo(wangTile), wangTile.wangId()); @@ -235,23 +238,20 @@ WangId WangSet::wangIdFromSurrounding(WangId surroundingWangIds[]) const { unsigned id = 0; - if(mEdgeColors > 0) { - for (int i = 0; i < 3; ++i) { + if (mEdgeColors > 0) { + for (int i = 0; i < 3; ++i) id |= (surroundingWangIds[i*2].edgeColor((2 + i) % 4)) << (i*8); - } } - if(mCornerColors > 0) { + if (mCornerColors > 0) { for (int i = 0; i < 3; ++i) { int color = surroundingWangIds[i*2 + 1].cornerColor((2 + i) % 4); - if (!color) { + if (!color) color = surroundingWangIds[i*2].cornerColor((1 + i) % 4); - } - if (!color) { + if (!color) color = surroundingWangIds[i*2 + 2].cornerColor((3 + i) % 4); - } id |= color << (4 + i*8); } @@ -260,13 +260,12 @@ WangId WangSet::wangIdFromSurrounding(WangId surroundingWangIds[]) const return id; } -WangId WangSet::wangIdFromSurrounding(const Cell surroundingWangIds[]) const +WangId WangSet::wangIdFromSurrounding(const Cell surroundingCells[]) const { WangId wangIds[8]; - for (int i = 0; i < 8; ++i) { - wangIds[i] = wangIdOfCell(surroundingWangIds[i]); - } + for (int i = 0; i < 8; ++i) + wangIds[i] = wangIdOfCell(surroundingCells[i]); WangId wangId = wangIdFromSurrounding(wangIds); @@ -286,9 +285,7 @@ WangId WangSet::wangIdOfCell(const Cell &cell) const bool WangSet::wangIdIsValid(WangId wangId) const { for (int i = 0; i < 4; ++i) { - if (wangId.edgeColor(i) < 0 - || wangId.edgeColor(i) > mEdgeColors - || wangId.cornerColor(i) < 0 + if (wangId.edgeColor(i) > mEdgeColors || wangId.cornerColor(i) > mCornerColors) return false; } diff --git a/src/libtiled/wangset.h b/src/libtiled/wangset.h index 192cac5455..df9907fb37 100644 --- a/src/libtiled/wangset.h +++ b/src/libtiled/wangset.h @@ -124,7 +124,7 @@ class TILEDSHARED_EXPORT WangTile mFlippedAntiDiagonally(false) {} - explicit WangTile(const Cell &cell, WangId wangId): + WangTile(const Cell &cell, WangId wangId): mTile(cell.tile()), mWangId(wangId), mFlippedHorizontally(cell.flippedHorizontally()), @@ -195,9 +195,9 @@ class TILEDSHARED_EXPORT WangSet : public Object * */ void addTile(Tile *tile, WangId wangId); - void addCell(Cell &cell, WangId wangId); + void addCell(const Cell &cell, WangId wangId); - void addWangTile(WangTile wangTile); + void addWangTile(const WangTile &wangTile); /* Finds a tile whos WangId matches with the one provided, * where zeros in the id are treated as wild cards, and can be @@ -232,7 +232,7 @@ class TILEDSHARED_EXPORT WangSet : public Object * g|X|c * f|e|d * */ - WangId wangIdFromSurrounding(const Cell surroundingWangIds[]) const; + WangId wangIdFromSurrounding(const Cell surroundingCells[]) const; /* Returns the wangId of a given Tile. * */ diff --git a/src/tiled/addremovewangset.cpp b/src/tiled/addremovewangset.cpp index 48d5dd619a..462760b8fb 100644 --- a/src/tiled/addremovewangset.cpp +++ b/src/tiled/addremovewangset.cpp @@ -53,7 +53,7 @@ void AddRemoveWangSet::removeWangSet() void AddRemoveWangSet::addWangSet() { Q_ASSERT(mWangSet); - mTilesetDocument->wangSetModel()->insertWangSet(mWangSet); + mTilesetDocument->wangSetModel()->insertWangSet(mWangSet, mIndex); mWangSet = nullptr; } diff --git a/src/tiled/changewangsetdata.cpp b/src/tiled/changewangsetdata.cpp index b9e24ff735..0774f3a0be 100644 --- a/src/tiled/changewangsetdata.cpp +++ b/src/tiled/changewangsetdata.cpp @@ -60,8 +60,8 @@ void ChangeWangSetEdges::redo() } ChangeWangSetCorners::ChangeWangSetCorners(TilesetDocument *tilesetDocument, - int index, - int newValue) + int index, + int newValue) : QUndoCommand(QCoreApplication::translate("Undo Commands", "Change Wang Set corner count")) , mWangSetModel(tilesetDocument->wangSetModel()) diff --git a/src/tiled/mapdocument.h b/src/tiled/mapdocument.h index 9c9833e811..1fe744c2f1 100644 --- a/src/tiled/mapdocument.h +++ b/src/tiled/mapdocument.h @@ -166,8 +166,6 @@ class MapDocument : public Document MapObjectModel *mapObjectModel() const { return mMapObjectModel; } - TerrainModel *terrainModel() const { return mTerrainModel; } - WangSetModel *wangSetModel() const { return mWangSetModel; } /** diff --git a/src/tiled/propertybrowser.cpp b/src/tiled/propertybrowser.cpp index 414719463a..6449b97d53 100644 --- a/src/tiled/propertybrowser.cpp +++ b/src/tiled/propertybrowser.cpp @@ -336,7 +336,7 @@ void PropertyBrowser::terrainChanged(Tileset *tileset, int index) void PropertyBrowser::wangSetChanged(Tileset *tileset, int index) { - if(mObject == tileset->wangSet(index)) + if (mObject == tileset->wangSet(index)) updateProperties(); } @@ -854,8 +854,11 @@ void PropertyBrowser::addWangSetProperties() { QtProperty *groupProperty = mGroupManager->addProperty(tr("WangSet")); QtVariantProperty *nameProperty = addProperty(NameProperty, QVariant::String, tr("Name"), groupProperty); - QtVariantProperty *edgeProperty = addProperty(EdgeProperty, QVariant::Int, tr("Edge Count"), groupProperty); - QtVariantProperty *cornerProperty = addProperty(CornerProperty, QVariant::Int, tr("Corner Count"), groupProperty); + QtVariantProperty *edgeProperty = addProperty(EdgeCountProperty, QVariant::Int, tr("Edge Count"), groupProperty); + QtVariantProperty *cornerProperty = addProperty(CornerCountProperty, QVariant::Int, tr("Corner Count"), groupProperty); + + edgeProperty->setAttribute(QLatin1String("minimum"), 0); + cornerProperty->setAttribute(QLatin1String("minimum"), 0); nameProperty->setEnabled(mTilesetDocument); edgeProperty->setEnabled(mTilesetDocument); @@ -1254,12 +1257,12 @@ void PropertyBrowser::applyWangSetValue(PropertyId id, const QVariant &val) mTilesetDocument->tileset()->wangSets().indexOf(wangSet), val.toString())); break; - case EdgeProperty: + case EdgeCountProperty: mDocument->undoStack()->push(new ChangeWangSetEdges(mTilesetDocument, mTilesetDocument->tileset()->wangSets().indexOf(wangSet), val.toInt())); break; - case CornerProperty: + case CornerCountProperty: mDocument->undoStack()->push(new ChangeWangSetCorners(mTilesetDocument, mTilesetDocument->tileset()->wangSets().indexOf(wangSet), val.toInt())); @@ -1567,8 +1570,8 @@ void PropertyBrowser::updateProperties() case Object::WangSetType: { const WangSet *wangSet = static_cast(mObject); mIdToProperty[NameProperty]->setValue(wangSet->name()); - mIdToProperty[EdgeProperty]->setValue(wangSet->edgeColors()); - mIdToProperty[CornerProperty]->setValue(wangSet->cornerColors()); + mIdToProperty[EdgeCountProperty]->setValue(wangSet->edgeColors()); + mIdToProperty[CornerCountProperty]->setValue(wangSet->cornerColors()); } } diff --git a/src/tiled/propertybrowser.h b/src/tiled/propertybrowser.h index 4263fb4201..38fc85ae7b 100644 --- a/src/tiled/propertybrowser.h +++ b/src/tiled/propertybrowser.h @@ -153,8 +153,8 @@ private slots: TileProbabilityProperty, ColumnCountProperty, IdProperty, - EdgeProperty, - CornerProperty, + EdgeCountProperty, + CornerCountProperty, CustomProperty }; diff --git a/src/tiled/tileseteditor.cpp b/src/tiled/tileseteditor.cpp index 1002417477..38e9048cfb 100644 --- a/src/tiled/tileseteditor.cpp +++ b/src/tiled/tileseteditor.cpp @@ -874,7 +874,7 @@ void TilesetEditor::currentWangSetChanged(const WangSet *wangSet) void TilesetEditor::addWangSet() { Tileset *tileset = currentTileset(); - if(!tileset) + if (!tileset) return; //2 and 0 are default values for number of edges and corners TODO define this some where better? @@ -890,6 +890,8 @@ void TilesetEditor::addWangSet() void TilesetEditor::removeWangSet() { WangSet *wangSet = mWangDock->currentWangSet(); + if(!wangSet) + return; mCurrentTilesetDocument->undoStack()->push(new RemoveWangSet(mCurrentTilesetDocument, wangSet)); diff --git a/src/tiled/tilesetwangsetmodel.cpp b/src/tiled/tilesetwangsetmodel.cpp index f9373104e0..dc35a6f802 100644 --- a/src/tiled/tilesetwangsetmodel.cpp +++ b/src/tiled/tilesetwangsetmodel.cpp @@ -1,28 +1,21 @@ /* * tilesetwangsetmodel.cpp * Copyright 2017, Benjamin Trotter - * This file is part of libtiled. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * This file is part of Tiled. * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . */ #include "tilesetwangsetmodel.h" @@ -124,7 +117,7 @@ WangSet *TilesetWangSetModel::wangSetAt(const QModelIndex &index) const return nullptr; } -void TilesetWangSetModel::insertWangSet(WangSet *wangSet) +void TilesetWangSetModel::insertWangSet(WangSet *wangSet, int index) { Tileset *tileset = mTilesetDocument->tileset().data(); int row = tileset->wangSetCount(); @@ -132,7 +125,7 @@ void TilesetWangSetModel::insertWangSet(WangSet *wangSet) emit wangSetAboutToBeAdded(tileset); beginInsertRows(QModelIndex(), row, row); - tileset->insertWangSet(wangSet); + tileset->insertWangSet(wangSet, index); endInsertRows(); emit wangSetAdded(tileset); diff --git a/src/tiled/tilesetwangsetmodel.h b/src/tiled/tilesetwangsetmodel.h index 8e1dd9ed09..9593aa0c92 100644 --- a/src/tiled/tilesetwangsetmodel.h +++ b/src/tiled/tilesetwangsetmodel.h @@ -1,28 +1,21 @@ /* * tilesetwangsetmodel.h * Copyright 2017, Benjamin Trotter - * This file is part of libtiled. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * This file is part of Tiled. * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . */ #pragma once @@ -47,7 +40,7 @@ class TilesetWangSetModel : public QAbstractListModel WangSetRole = Qt::UserRole }; - TilesetWangSetModel(TilesetDocument *mapDocument, + explicit TilesetWangSetModel(TilesetDocument *mapDocument, QObject *parent = nullptr); ~TilesetWangSetModel(); @@ -71,7 +64,7 @@ class TilesetWangSetModel : public QAbstractListModel WangSet *wangSetAt(const QModelIndex &index) const; - void insertWangSet(WangSet *wangSet); + void insertWangSet(WangSet *wangSet, int index); WangSet *takeWangSetAt(int index); void setWangSetName(int index, const QString &name); void setWangSetEdges(int index, int value); From 888ea7b26942d4ed45af550f080e5a9ab4bc0702 Mon Sep 17 00:00:00 2001 From: Benjamin Trotter Date: Mon, 3 Jul 2017 20:36:34 -0700 Subject: [PATCH 19/21] fixed issue in 'wangIdFromSurrounding' --- src/libtiled/wangset.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libtiled/wangset.cpp b/src/libtiled/wangset.cpp index 1eb4a23361..130b8b4e10 100644 --- a/src/libtiled/wangset.cpp +++ b/src/libtiled/wangset.cpp @@ -239,12 +239,12 @@ WangId WangSet::wangIdFromSurrounding(WangId surroundingWangIds[]) const unsigned id = 0; if (mEdgeColors > 0) { - for (int i = 0; i < 3; ++i) + for (int i = 0; i < 4; ++i) id |= (surroundingWangIds[i*2].edgeColor((2 + i) % 4)) << (i*8); } if (mCornerColors > 0) { - for (int i = 0; i < 3; ++i) { + for (int i = 0; i < 4; ++i) { int color = surroundingWangIds[i*2 + 1].cornerColor((2 + i) % 4); if (!color) From 825774acf49941348f1c3d16d59113a1f58b6823 Mon Sep 17 00:00:00 2001 From: Benjamin Trotter Date: Tue, 4 Jul 2017 10:50:37 -0700 Subject: [PATCH 20/21] Made requested changes! --- src/libtiled/tileset.cpp | 2 +- src/libtiled/tileset.h | 2 +- src/libtiled/wangset.cpp | 4 ++-- src/tiled/addremovewangset.cpp | 2 +- src/tiled/changewangsetdata.cpp | 4 ++-- src/tiled/mapdocument.h | 14 -------------- src/tiled/tilesetdocument.cpp | 6 +++--- src/tiled/tilesetdocument.h | 2 +- src/tiled/tileseteditor.cpp | 4 ++-- src/tiled/tilesetview.cpp | 2 +- src/tiled/tilesetwangsetmodel.cpp | 10 +++++----- src/tiled/tilesetwangsetmodel.h | 2 +- src/tiled/wangdock.cpp | 4 ++-- src/tiled/wangsetview.cpp | 2 +- 14 files changed, 23 insertions(+), 37 deletions(-) diff --git a/src/libtiled/tileset.cpp b/src/libtiled/tileset.cpp index ab2f566575..02957eedfd 100644 --- a/src/libtiled/tileset.cpp +++ b/src/libtiled/tileset.cpp @@ -518,7 +518,7 @@ void Tileset::addWangSet(WangSet *wangSet) * @brief Tileset::insertWangSet Adds a wangSet. * @param wangSet A pointer to the wangset to add. */ -void Tileset::insertWangSet(WangSet *wangSet, int index) +void Tileset::insertWangSet(int index, WangSet *wangSet) { Q_ASSERT(wangSet->tileset() == this); diff --git a/src/libtiled/tileset.h b/src/libtiled/tileset.h index 15742978fd..a20ec834c2 100644 --- a/src/libtiled/tileset.h +++ b/src/libtiled/tileset.h @@ -190,7 +190,7 @@ class TILEDSHARED_EXPORT Tileset : public Object WangSet *wangSet(int index) const; void addWangSet(WangSet *wangSet); - void insertWangSet(WangSet *wangSet, int index); + void insertWangSet(int index, WangSet *wangSet); WangSet *takeWangSetAt(int index); Tile *addTile(const QPixmap &image, const QString &source = QString()); diff --git a/src/libtiled/wangset.cpp b/src/libtiled/wangset.cpp index 130b8b4e10..71092fd7fd 100644 --- a/src/libtiled/wangset.cpp +++ b/src/libtiled/wangset.cpp @@ -91,7 +91,7 @@ void WangTile::flipVertically() Cell WangTile::makeCell() const { - if(!mTile) + if (!mTile) return Cell(); Cell cell(mTile); @@ -251,7 +251,7 @@ WangId WangSet::wangIdFromSurrounding(WangId surroundingWangIds[]) const color = surroundingWangIds[i*2].cornerColor((1 + i) % 4); if (!color) - color = surroundingWangIds[i*2 + 2].cornerColor((3 + i) % 4); + color = surroundingWangIds[(i*2 + 2) % 8].cornerColor((3 + i) % 4); id |= color << (4 + i*8); } diff --git a/src/tiled/addremovewangset.cpp b/src/tiled/addremovewangset.cpp index 462760b8fb..d9a190a789 100644 --- a/src/tiled/addremovewangset.cpp +++ b/src/tiled/addremovewangset.cpp @@ -53,7 +53,7 @@ void AddRemoveWangSet::removeWangSet() void AddRemoveWangSet::addWangSet() { Q_ASSERT(mWangSet); - mTilesetDocument->wangSetModel()->insertWangSet(mWangSet, mIndex); + mTilesetDocument->wangSetModel()->insertWangSet(mIndex, mWangSet); mWangSet = nullptr; } diff --git a/src/tiled/changewangsetdata.cpp b/src/tiled/changewangsetdata.cpp index 0774f3a0be..1a7e167e02 100644 --- a/src/tiled/changewangsetdata.cpp +++ b/src/tiled/changewangsetdata.cpp @@ -60,8 +60,8 @@ void ChangeWangSetEdges::redo() } ChangeWangSetCorners::ChangeWangSetCorners(TilesetDocument *tilesetDocument, - int index, - int newValue) + int index, + int newValue) : QUndoCommand(QCoreApplication::translate("Undo Commands", "Change Wang Set corner count")) , mWangSetModel(tilesetDocument->wangSetModel()) diff --git a/src/tiled/mapdocument.h b/src/tiled/mapdocument.h index 1fe744c2f1..eec251b565 100644 --- a/src/tiled/mapdocument.h +++ b/src/tiled/mapdocument.h @@ -51,8 +51,6 @@ namespace Internal { class LayerModel; class MapObjectModel; -class TerrainModel; -class WangSetModel; class TileSelectionModel; /** @@ -166,8 +164,6 @@ class MapDocument : public Document MapObjectModel *mapObjectModel() const { return mMapObjectModel; } - WangSetModel *wangSetModel() const { return mWangSetModel; } - /** * Returns the map renderer. */ @@ -287,14 +283,6 @@ class MapDocument : public Document void tilesetTileOffsetChanged(Tileset *tileset); void tileTypeChanged(Tile *tile); void tileImageSourceChanged(Tile *tile); - void tilesetTerrainAboutToBeAdded(Tileset *tileset, int terrainId); - void tilesetTerrainAdded(Tileset *tileset, int terrainId); - void tilesetTerrainAboutToBeRemoved(Tileset *tileset, Terrain *terrain); - void tilesetTerrainRemoved(Tileset *tileset, Terrain *terrain); - void tilesetWangSetAboutToBeAdded(Tileset *tileset); - void tilesetWangSetAdded(Tileset *tileset); - void tilesetWangSetAboutToBeRemoved(Tileset *tileset, WangSet *wangSet); - void tilesetWangSetRemoved(Tileset *tileset); private slots: void onObjectsRemoved(const QList &objects); @@ -328,8 +316,6 @@ private slots: MapRenderer *mRenderer; Layer* mCurrentLayer; MapObjectModel *mMapObjectModel; - TerrainModel *mTerrainModel; - WangSetModel *mWangSetModel; }; diff --git a/src/tiled/tilesetdocument.cpp b/src/tiled/tilesetdocument.cpp index 7a09421cb9..32b1b4ff24 100644 --- a/src/tiled/tilesetdocument.cpp +++ b/src/tiled/tilesetdocument.cpp @@ -341,10 +341,10 @@ void TilesetDocument::onTerrainRemoved(Terrain *terrain) setCurrentObject(nullptr); } -void TilesetDocument::onWangSetRemoved() +void TilesetDocument::onWangSetRemoved(WangSet *wangSet) { - for (MapDocument *mapDocument : mapDocuments()) - emit mapDocument->tilesetWangSetRemoved(mTileset.data()); + if (wangSet == mCurrentObject) + setCurrentObject(nullptr); } } // namespace Internal diff --git a/src/tiled/tilesetdocument.h b/src/tiled/tilesetdocument.h index 0dda612148..d41d1f394c 100644 --- a/src/tiled/tilesetdocument.h +++ b/src/tiled/tilesetdocument.h @@ -142,7 +142,7 @@ private slots: void onPropertiesChanged(Object *object); void onTerrainRemoved(Terrain *terrain); - void onWangSetRemoved(); + void onWangSetRemoved(WangSet *wangSet); private: SharedTileset mTileset; diff --git a/src/tiled/tileseteditor.cpp b/src/tiled/tileseteditor.cpp index 38e9048cfb..32021601ed 100644 --- a/src/tiled/tileseteditor.cpp +++ b/src/tiled/tileseteditor.cpp @@ -890,7 +890,7 @@ void TilesetEditor::addWangSet() void TilesetEditor::removeWangSet() { WangSet *wangSet = mWangDock->currentWangSet(); - if(!wangSet) + if (!wangSet) return; mCurrentTilesetDocument->undoStack()->push(new RemoveWangSet(mCurrentTilesetDocument, @@ -911,7 +911,7 @@ void TilesetEditor::setTerrainImage(Tile *tile) void TilesetEditor::setWangSetImage(Tile *tile) { WangSet *wangSet = mWangDock->currentWangSet(); - if(!wangSet) + if (!wangSet) return; mCurrentTilesetDocument->undoStack()->push(new SetWangSetImage(mCurrentTilesetDocument, diff --git a/src/tiled/tilesetview.cpp b/src/tiled/tilesetview.cpp index dbdb800eb1..412989111d 100644 --- a/src/tiled/tilesetview.cpp +++ b/src/tiled/tilesetview.cpp @@ -723,7 +723,7 @@ void TilesetView::contextMenuEvent(QContextMenuEvent *event) QItemSelectionModel::SelectCurrent | QItemSelectionModel::Clear); - if(mWangSet) { + if (mWangSet) { QAction *setImage = menu.addAction(tr("Set WangSet Image")); connect(setImage, SIGNAL(triggered()), SLOT(selectWangSetImage())); } diff --git a/src/tiled/tilesetwangsetmodel.cpp b/src/tiled/tilesetwangsetmodel.cpp index dc35a6f802..def294d88e 100644 --- a/src/tiled/tilesetwangsetmodel.cpp +++ b/src/tiled/tilesetwangsetmodel.cpp @@ -50,7 +50,7 @@ QModelIndex TilesetWangSetModel::index(WangSet *wangSet) int TilesetWangSetModel::rowCount(const QModelIndex &parent) const { - if(!parent.isValid()) + if (!parent.isValid()) return mTilesetDocument->tileset()->wangSetCount(); return 0; @@ -65,7 +65,7 @@ int TilesetWangSetModel::columnCount(const QModelIndex &parent) const QVariant TilesetWangSetModel::data(const QModelIndex &index, int role) const { - if(WangSet *wangSet = wangSetAt(index)) { + if (WangSet *wangSet = wangSetAt(index)) { switch (role) { case Qt::DisplayRole: case Qt::EditRole: @@ -86,7 +86,7 @@ bool TilesetWangSetModel::setData(const QModelIndex &index, const QVariant &value, int role) { - if(role == Qt::EditRole) { + if (role == Qt::EditRole) { const QString newName = value.toString(); WangSet *wangSet = wangSetAt(index); if (wangSet->name() != newName) { @@ -117,7 +117,7 @@ WangSet *TilesetWangSetModel::wangSetAt(const QModelIndex &index) const return nullptr; } -void TilesetWangSetModel::insertWangSet(WangSet *wangSet, int index) +void TilesetWangSetModel::insertWangSet(int index, WangSet *wangSet) { Tileset *tileset = mTilesetDocument->tileset().data(); int row = tileset->wangSetCount(); @@ -125,7 +125,7 @@ void TilesetWangSetModel::insertWangSet(WangSet *wangSet, int index) emit wangSetAboutToBeAdded(tileset); beginInsertRows(QModelIndex(), row, row); - tileset->insertWangSet(wangSet, index); + tileset->insertWangSet(index, wangSet); endInsertRows(); emit wangSetAdded(tileset); diff --git a/src/tiled/tilesetwangsetmodel.h b/src/tiled/tilesetwangsetmodel.h index 9593aa0c92..d32ea80c92 100644 --- a/src/tiled/tilesetwangsetmodel.h +++ b/src/tiled/tilesetwangsetmodel.h @@ -64,7 +64,7 @@ class TilesetWangSetModel : public QAbstractListModel WangSet *wangSetAt(const QModelIndex &index) const; - void insertWangSet(WangSet *wangSet, int index); + void insertWangSet(int index, WangSet *wangSet); WangSet *takeWangSetAt(int index); void setWangSetName(int index, const QString &name); void setWangSetEdges(int index, int value); diff --git a/src/tiled/wangdock.cpp b/src/tiled/wangdock.cpp index 49e97f913f..f7f2c34774 100644 --- a/src/tiled/wangdock.cpp +++ b/src/tiled/wangdock.cpp @@ -48,7 +48,7 @@ namespace Internal { static WangSet *firstWangSet(MapDocument *MapDocument) { for (const SharedTileset &tileset : MapDocument->map()->tilesets()) - if(tileset->wangSetCount() > 0) + if (tileset->wangSetCount() > 0) return tileset->wangSet(0); return nullptr; @@ -57,7 +57,7 @@ static WangSet *firstWangSet(MapDocument *MapDocument) static WangSet *firstWangSet(TilesetDocument *tilesetDocument) { Tileset *tileset = tilesetDocument->tileset().data(); - if(tileset->wangSetCount() > 0) + if (tileset->wangSetCount() > 0) return tileset->wangSet(0); return nullptr; diff --git a/src/tiled/wangsetview.cpp b/src/tiled/wangsetview.cpp index 9b4d06bf05..3ccbad225a 100644 --- a/src/tiled/wangsetview.cpp +++ b/src/tiled/wangsetview.cpp @@ -115,7 +115,7 @@ void WangSetView::editWangSetProperties() { WangSet *wangSet = wangSetAt(selectionModel()->currentIndex()); - if(!wangSet) + if (!wangSet) return; mTilesetDocument->setCurrentObject(wangSet); From 0d3f3539bf515dd04274f93c6fc5bc4361cf826d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Tue, 4 Jul 2017 20:32:15 +0200 Subject: [PATCH 21/21] Removed file that should not be in version control --- .../qtc_Desktop__bdef64c0-debug.bg | Bin 27873 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/build-tiled-Desktop_Qt_5_9_0_MinGW_32bit-Debug/qtc_Desktop__bdef64c0-debug/qtc_Desktop__bdef64c0-debug.bg diff --git a/src/build-tiled-Desktop_Qt_5_9_0_MinGW_32bit-Debug/qtc_Desktop__bdef64c0-debug/qtc_Desktop__bdef64c0-debug.bg b/src/build-tiled-Desktop_Qt_5_9_0_MinGW_32bit-Debug/qtc_Desktop__bdef64c0-debug/qtc_Desktop__bdef64c0-debug.bg deleted file mode 100644 index 8eefeb19a4207f8499b84b18e2d894ef657b242d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27873 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