Skip to content

Commit

Permalink
Merge pull request #1698 from thabetx/various-improvements
Browse files Browse the repository at this point in the history
Various improvements for templates
  • Loading branch information
bjorn committed Aug 28, 2017
2 parents efdcb8d + 80bd1d5 commit 60d72e5
Show file tree
Hide file tree
Showing 24 changed files with 264 additions and 92 deletions.
9 changes: 5 additions & 4 deletions src/libtiled/mapobject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ MapObject::MapObject(const QString &name, const QString &type,
mObjectGroup(nullptr),
mRotation(0.0f),
mVisible(true),
mChangedProperties(0)
mChangedProperties(0),
mTemplateBase(false)
{
}

Expand Down Expand Up @@ -256,7 +257,7 @@ MapObject *MapObject::clone() const

const MapObject *MapObject::templateObject() const
{
if (!mTemplateRef.templateGroup)
if (!isTemplateInstance())
return nullptr;

auto objectTemplate = mTemplateRef.templateGroup->findTemplate(mTemplateRef.templateId);
Expand Down Expand Up @@ -303,12 +304,12 @@ void MapObject::syncWithTemplate()

bool MapObject::isTemplateInstance() const
{
return templateRef().templateGroup;
return mTemplateRef.templateGroup;
}

TemplateGroup *MapObject::templateGroup() const
{
return templateRef().templateGroup;
return mTemplateRef.templateGroup;
}

void MapObject::flipRectObject(const QTransform &flipTransform)
Expand Down
11 changes: 11 additions & 0 deletions src/libtiled/mapobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@ class TILEDSHARED_EXPORT MapObject : public Object

bool isTemplateInstance() const;

bool isTemplateBase() const;
void markAsTemplateBase();


TemplateGroup *templateGroup() const;

private:
Expand All @@ -231,6 +235,7 @@ class TILEDSHARED_EXPORT MapObject : public Object
qreal mRotation;
bool mVisible;
ChangedProperties mChangedProperties;
bool mTemplateBase;
};

/**
Expand Down Expand Up @@ -478,6 +483,12 @@ inline void MapObject::setPropertyChanged(Property property, bool state)
inline bool MapObject::propertyChanged(Property property) const
{ return mChangedProperties.testFlag(property); }

inline bool MapObject::isTemplateBase() const
{ return mTemplateBase; }

inline void MapObject::markAsTemplateBase()
{ mTemplateBase = true; }

} // namespace Tiled

#if QT_VERSION < 0x050500
Expand Down
8 changes: 4 additions & 4 deletions src/libtiled/mapwriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -803,14 +803,14 @@ void MapWriterPrivate::writeObject(QXmlStreamWriter &w,

bool isTemplateInstance = mapObject.isTemplateInstance();

if (!mapObject.isTemplateBase())
w.writeAttribute(QLatin1String("id"), QString::number(id));

if (isTemplateInstance) {
unsigned tid = mTidMapper.templateRefToTid(mapObject.templateRef());
w.writeAttribute(QLatin1String("tid"), QString::number(tid));
}

if (id != 0)
w.writeAttribute(QLatin1String("id"), QString::number(id));

if (shouldWrite(!name.isEmpty(), isTemplateInstance, mapObject.propertyChanged(MapObject::NameProperty)))
w.writeAttribute(QLatin1String("name"), name);

Expand All @@ -822,7 +822,7 @@ void MapWriterPrivate::writeObject(QXmlStreamWriter &w,
w.writeAttribute(QLatin1String("gid"), QString::number(gid));
}

if (id != 0) {
if (!mapObject.isTemplateBase()) {
w.writeAttribute(QLatin1String("x"), QString::number(pos.x()));
w.writeAttribute(QLatin1String("y"), QString::number(pos.y()));
}
Expand Down
2 changes: 1 addition & 1 deletion src/libtiled/objecttemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ inline void ObjectTemplate::setObject(const MapObject *object)
{
delete mObject;
mObject = object->clone();
mObject->setId(0);
mObject->markAsTemplateBase();
}

inline unsigned ObjectTemplate::id() const
Expand Down
54 changes: 50 additions & 4 deletions src/tiled/abstractobjecttool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,37 @@ void AbstractObjectTool::saveSelectedObject()
mapDocument()->saveSelectedObject(name, groupIndex);
}

void AbstractObjectTool::detachSelectedObjects()
{
MapDocument *currentMapDocument = mapDocument();
QList<MapObject *> templateInstances;

/**
* Stores the unique tilesets used by the templates
* to avoid creating multiple undo commands for the same tileset
*/
QSet<SharedTileset> sharedTilesets;

for (MapObject *object : mapDocument()->selectedObjects()) {
if (object->templateObject()) {
templateInstances.append(object);

if (Tile *tile = object->cell().tile())
sharedTilesets.insert(tile->tileset()->sharedPointer());
}
}

auto changeMapObjectCommand = new DetachObjects(currentMapDocument, templateInstances);

// Add any missing tileset used by the templates to the map map before detaching
for (SharedTileset sharedTileset : sharedTilesets) {
if (!currentMapDocument->map()->tilesets().contains(sharedTileset))
new AddTileset(currentMapDocument, sharedTileset, changeMapObjectCommand);
}

currentMapDocument->undoStack()->push(changeMapObjectCommand);
}

void AbstractObjectTool::changeTile()
{
QList<MapObject*> tileObjects;
Expand Down Expand Up @@ -302,12 +333,27 @@ void AbstractObjectTool::showContextMenu(MapObjectItem *clickedObjectItem,
}

if (selectedObjects.size() == 1) {
// Saving objects with embedded tilesets is disabled
auto cell = selectedObjects.first()->cell();
if (cell.isEmpty() || cell.tileset()->isExternal())
menu.addAction(tr("Save As Template"), this, SLOT(saveSelectedObject()));
MapObject *currentObject = selectedObjects.first();
if (!(currentObject->isTemplateBase() || currentObject->isTemplateInstance())) {
const Cell cell = selectedObjects.first()->cell();
// Saving objects with embedded tilesets is disabled
if (cell.isEmpty() || cell.tileset()->isExternal())
menu.addAction(tr("Save As Template"), this, SLOT(saveSelectedObject()));
}

if (currentObject->isTemplateBase()) { // Hide this operations for template base
duplicateAction->setVisible(false);
removeAction->setVisible(false);
}
}

bool anyIsTemplateInstance = std::any_of(selectedObjects.begin(),
selectedObjects.end(),
[](MapObject *object) { return object->isTemplateInstance(); });

if (anyIsTemplateInstance)
menu.addAction(tr("Detach"), this, SLOT(detachSelectedObjects()));

menu.addSeparator();
menu.addAction(tr("Flip Horizontally"), this, SLOT(flipHorizontally()), QKeySequence(tr("X")));
menu.addAction(tr("Flip Vertically"), this, SLOT(flipVertically()), QKeySequence(tr("Y")));
Expand Down
1 change: 1 addition & 0 deletions src/tiled/abstractobjecttool.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ private slots:
void removeObjects();
void resetTileSize();
void saveSelectedObject();
void detachSelectedObjects();
void changeTile();

void flipHorizontally();
Expand Down
45 changes: 45 additions & 0 deletions src/tiled/changemapobject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,48 @@ void ChangeMapObjectsTile::changeTiles()

emit mMapDocument->mapObjectModel()->objectsChanged(mMapObjects);
}

DetachObjects::DetachObjects(MapDocument *mapDocument,
QList<MapObject *> mapObjects,
QUndoCommand *parent)
: QUndoCommand(QCoreApplication::translate("Undo Commands",
"Detach %n Template Instance(s)",
nullptr, mapObjects.size()), parent)
, mMapDocument(mapDocument)
, mMapObjects(mapObjects)
{
for (const MapObject *object : mapObjects) {
mTemplateRefs.append(object->templateRef());
mProperties.append(object->properties());
}
}

void DetachObjects::redo()
{
QUndoCommand::redo(); // redo child commands

for (int i = 0; i < mMapObjects.size(); ++i) {
// Merge the instance properties into the template properties
MapObject *object = mMapObjects.at(i);
Properties newProperties = object->templateObject()->properties();
newProperties.merge(object->properties());
object->setProperties(newProperties);
object->setTemplateRef({nullptr, 0});
}

emit mMapDocument->mapObjectModel()->objectsChanged(mMapObjects);
}

void DetachObjects::undo()
{
for (int i = 0; i < mMapObjects.size(); ++i) {
MapObject *object = mMapObjects.at(i);
object->setTemplateRef(mTemplateRefs.at(i));
object->setProperties(mProperties.at(i));
object->syncWithTemplate();
}

QUndoCommand::undo(); // undo child commands

emit mMapDocument->mapObjectModel()->objectsChanged(mMapObjects);
}
19 changes: 19 additions & 0 deletions src/tiled/changemapobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,5 +111,24 @@ class ChangeMapObjectsTile : public QUndoCommand
QVector<bool> mOldChangeStates;
};

class DetachObjects : public QUndoCommand
{
public:
/**
* Creates an undo command that detaches the given template instances from their templates.
*/
DetachObjects(MapDocument *mapDocument,
QList<MapObject *> mapObjects,
QUndoCommand *parent = nullptr);

void redo() override;
void undo() override;

private:
MapDocument *mMapDocument;
QList<MapObject*> mMapObjects;
QVector<TemplateRef> mTemplateRefs;
QVector<Properties> mProperties;
};
} // namespace Internal
} // namespace Tiled
4 changes: 2 additions & 2 deletions src/tiled/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,13 @@ MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags flags)
, mDocumentManager(DocumentManager::instance())
, mTmxMapFormat(new TmxMapFormat(this))
, mTsxTilesetFormat(new TsxTilesetFormat(this))
, mTtxTemplateGroupFormat(new TtxTemplateGroupFormat(this))
, mTgxTemplateGroupFormat(new TgxTemplateGroupFormat(this))
{
mUi->setupUi(this);

PluginManager::addObject(mTmxMapFormat);
PluginManager::addObject(mTsxTilesetFormat);
PluginManager::addObject(mTtxTemplateGroupFormat);
PluginManager::addObject(mTgxTemplateGroupFormat);

ActionManager::registerAction(mUi->actionNewMap, "file.new_map");
ActionManager::registerAction(mUi->actionNewTileset, "file.new_tileset");
Expand Down
4 changes: 2 additions & 2 deletions src/tiled/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class MapView;
class ObjectTypesEditor;
class TmxMapFormat;
class TsxTilesetFormat;
class TtxTemplateGroupFormat;
class TgxTemplateGroupFormat;
class Zoomable;

/**
Expand Down Expand Up @@ -218,7 +218,7 @@ private slots:

TmxMapFormat *mTmxMapFormat;
TsxTilesetFormat *mTsxTilesetFormat;
TtxTemplateGroupFormat *mTtxTemplateGroupFormat;
TgxTemplateGroupFormat *mTgxTemplateGroupFormat;

QPointer<PreferencesDialog> mPreferencesDialog;

Expand Down
33 changes: 31 additions & 2 deletions src/tiled/mapdocument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "addremovemapobject.h"
#include "addremovetileset.h"
#include "changelayer.h"
#include "changemapobject.h"
#include "changemapobjectsorder.h"
#include "changeproperties.h"
#include "changeselectedarea.h"
Expand Down Expand Up @@ -133,8 +134,15 @@ void MapDocument::saveSelectedObject(const QString &name, int groupIndex)
if (mSelectedObjects.size() != 1)
return;

auto model = ObjectTemplateModel::instance();
model->saveObjectToDocument(mSelectedObjects.first(), name, groupIndex);
ObjectTemplateModel* model = ObjectTemplateModel::instance();
MapObject *object = mSelectedObjects.first();

if (ObjectTemplate *objectTemplate = model->saveObjectToDocument(object, name, groupIndex)) {
// Convert the saved object into an instance and clear the changed properties flags
object->setTemplateRef({objectTemplate->templateGroup(), objectTemplate->id()});
object->setChangedProperties(0);
emit objectsChanged(mSelectedObjects);
}
}

bool MapDocument::save(const QString &fileName, QString *error)
Expand Down Expand Up @@ -938,6 +946,19 @@ void MapDocument::updateTemplateInstances(const MapObject *mapObject)
emit objectsChanged(objectList);
}

void MapDocument::selectAllInstances(const MapObject *mapObject)
{
QList<MapObject*> objectList;
for (ObjectGroup *group : mMap->objectGroups()) {
for (auto object : group->objects()) {
if (object->isTemplateInstance() && object->templateObject() == mapObject) {
objectList.append(object);
}
}
}
setSelectedObjects(objectList);
}

void MapDocument::deselectObjects(const QList<MapObject *> &objects)
{
// Unset the current object when it was part of this list of objects
Expand Down Expand Up @@ -1095,6 +1116,14 @@ void MapDocument::moveObjectsDown(const QList<MapObject *> &objects)
mUndoStack->push(command.take());
}

void MapDocument::detachObjects(const QList<MapObject *> &objects)
{
if (objects.isEmpty())
return;

mUndoStack->push(new DetachObjects(this, objects));
}

void MapDocument::createRenderer()
{
if (mRenderer)
Expand Down
2 changes: 2 additions & 0 deletions src/tiled/mapdocument.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ class MapDocument : public Document
ObjectGroup *objectGroup);
void moveObjectsUp(const QList<MapObject*> &objects);
void moveObjectsDown(const QList<MapObject*> &objects);
void detachObjects(const QList<MapObject*> &objects);

/**
* Returns the layer model. Can be used to modify the layer stack of the
Expand Down Expand Up @@ -305,6 +306,7 @@ private slots:

public slots:
void updateTemplateInstances(const MapObject *mapObject);
void selectAllInstances(const MapObject *mapObject);

private:
void deselectObjects(const QList<MapObject*> &objects);
Expand Down
6 changes: 6 additions & 0 deletions src/tiled/mapdocumentactionhandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,12 @@ void MapDocumentActionHandler::moveObjectsToGroup(ObjectGroup *objectGroup)
}
}

void MapDocumentActionHandler::selectAllInstances(const MapObject *mapObject)
{
if (mMapDocument)
mMapDocument->selectAllInstances(mapObject);
}

void MapDocumentActionHandler::updateActions()
{
Map *map = nullptr;
Expand Down

0 comments on commit 60d72e5

Please sign in to comment.