Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Enable replacing an object with a template #1793

Merged
merged 5 commits into from
Nov 29, 2017

Conversation

thabetx
Copy link
Contributor

@thabetx thabetx commented Oct 21, 2017

Solves #1722

Works exactly like the replace tile feature.

replace_template

I had to move the selected template from the template creation tool into the tool manager so it can be used across all the tools, just like the tile.

Copy link
Member

@bjorn bjorn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thabetx Thank you so much for coming back to this! Overall your change looks very good. I've added a number of comments.

Usability wise, I think a minor improvement could be to mention the template name in the menu item, like Replace with "Rock" Template in the case of your demonstration above.

{
mapDocument()->undoStack()->push(new ReplaceObjectsWithTemplate(mapDocument(),
mapDocument()->selectedObjects(),
{objectTemplate()->templateGroup(), objectTemplate()->id()}));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the new templateRef method you added here. :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason I didn't commit that 😅.

@@ -22,6 +22,7 @@
#include "abstracttool.h"

#include "mapdocument.h"
#include "templatesdock.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't look like you need this include here?

@@ -204,6 +204,20 @@ void DetachObjects::undo()
emit mMapDocument->mapObjectModel()->objectsChanged(mMapObjects);
}

void copyProperties(const MapObject *source, MapObject *target) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coding style: please place the { on its own line for function definitions.

Please mark this function static.

Could this potentially be implemented as MapObject::operator=(const MapObject &other), so it could be done like *target = *source? Or does this have different semantics than assignment? At least having it in MapObject would make it easier not to forget adding more things to it later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the = operator looks like a good idea, it copies everything except id and position so I think i's okay but 'm not sure.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I guess operator= could be expected to copy those as well, so probably better to leave this as a special function.

for (int i = 0; i < mMapObjects.size(); ++i) {
MapObject *current = mMapObjects.at(i);
MapObject *old = mOldMapObjects.at(i);
copyProperties(old, current);;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove second ;



ReplaceObjectsWithTemplate::ReplaceObjectsWithTemplate(MapDocument *mapDocument,
const QList<MapObject *> &mapObjects,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation missing a space.

}

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

ReplaceObjectsWithTemplate::~ReplaceObjectsWithTemplate()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please define the destructor right after the constructor (matching the order in the header file).

@@ -139,7 +139,7 @@ void MapDocument::saveSelectedObject(const QString &name, int groupIndex)

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->setTemplateRef(objectTemplate->templateRef());
object->setChangedProperties(0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually these lines should be covered by an undo command, right? Now that you've written ReplaceObjectsWithTemplate, you should probably use it here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, currently this would be a partial undo, as removing from the template group is not implemented. But at least it would reset the object to being a normal object.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think partial undo would be fine here.

@thabetx
Copy link
Contributor Author

thabetx commented Oct 28, 2017

I like the option to add the name of the template in the context menu. It makes things clearer.

target->setShape(source->shape());
target->setCell(source->cell());
target->setRotation(source->rotation());
target->setVisible(source->VisibleProperty);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just noticed this little issue. I won't change it now on master to avoid conflicts, so please fix this to source->isVisible() as part of this PR.

@thabetx
Copy link
Contributor Author

thabetx commented Nov 4, 2017

I cleaned the code and made some fixes and changes.

Replacing was enabled for tile objects only, so I fixed that as well, but now when replacing a non-tile object e.g. a polygon with a template, Tiled will crash. I think the reason is that the two objects have different sets of properties and when the properties dock is asked to update it can't set the properties of the new object.

So I will be looking into it and will do some more testing.

@bjorn
Copy link
Member

bjorn commented Nov 4, 2017

Replacing was enabled for tile objects only, so I fixed that as well, but now when replacing a non-tile object e.g. a polygon with a template, Tiled will crash. I think the reason is that the two objects have different sets of properties and when the properties dock is asked to update it can't set the properties of the new object.

Ah, you're right. This new Replace by Template action is the first action that allows changing the actual type of an object, and some properties are only created for certain objects (like flipping for tile objects, and width/height only for rectangles, tiles and ellipses). So the PropertyBrowser will need some changes for this.

auto replaceTemplateAction = menu.addAction(tr("Replace With Template"), this, SLOT(replaceObjectsWithTemplate()));

if (selectedTemplate)
replaceTemplateAction->setText(tr("Replace With \"") + selectedTemplate->name() + tr("\" Template"));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not nice for the translator. You should instead use a parameter, like so:

tr("Replace With \"%1\" Template").arg(selectedTemplate->name())

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright.

Conflicts:
	src/libtiled/objecttemplate.h
	src/tiled/createtemplatetool.cpp
	src/tiled/mapdocument.cpp
	src/tiled/mapscene.cpp
@bjorn
Copy link
Member

bjorn commented Nov 21, 2017

Alright, I've merged master and in the process fixed that translation string and corrected ReplaceObjectsWithTemplate::redo.

The remaining issue is the crashing when changing the kind of object through replacing it with a template.

By replacing an object with a template, it is possible to change whether
it has dimensions, or whether it is a tile or a text object. This
affects which properties should be listed.

The easiest way to adjust the list of properties is to refresh it
entirely when necessary.
@bjorn bjorn merged commit 6404b3d into mapeditor:master Nov 29, 2017
@thabetx
Copy link
Contributor Author

thabetx commented Nov 29, 2017

Hello bjron, thank you for the updates, I was stuck at updating the properties and the custom properties. I tested it and it's working great.

I will try working on #1823 .

Again thank you :).

@bjorn
Copy link
Member

bjorn commented Nov 29, 2017

Hello bjorn, thank you for the updates, I was stuck at updating the properties and the custom properties. I tested it and it's working great.

No problem, I just needed this to be finished since I'm trying to move forward with a 1.1 release, which means finishing up the loose ends.

I will try working on #1823.

Ah, I was about to look into it myself too, especially since I introduced this one recently, but feel free to have a look into it. It's probably not a hard one to fix.

@thabetx
Copy link
Contributor Author

thabetx commented Nov 29, 2017

Okay you can continue looking into it, I will try improving broken links.

Undoing after fixing doesn't reset and I will also look into fixing broken tileset link inside the template #1732 .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants