Skip to content

Commit

Permalink
Convert custom properties for each object individually
Browse files Browse the repository at this point in the history
To avoid synchronizing the value for all selected objects.
  • Loading branch information
bjorn committed Jan 9, 2025
1 parent 2ae2c84 commit ae2b717
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 33 deletions.
62 changes: 42 additions & 20 deletions src/tiled/changeproperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ SetProperty::SetProperty(Document *document,
const QString &name,
const QVariant &value,
QUndoCommand *parent)
: SetProperty(document, objects, QStringList(name), value, parent)
: SetProperty(document, objects, QStringList(name), QVariantList { value },
parent)
{
}

Expand All @@ -132,19 +133,24 @@ SetProperty::SetProperty(Document *document,
const QStringList &path,
const QVariant &value,
QUndoCommand *parent)
: SetProperty(document, objects, path, QVariantList { value }, parent)
{
}

SetProperty::SetProperty(Document *document,
const QList<Object *> &objects,
const QStringList &path,
const QVariantList &values,
QUndoCommand *parent)
: QUndoCommand(parent)
, mDocument(document)
, mObjects(objects)
, mName(path.first())
, mPath(path)
, mValue(value)
, mValues(values)
{
for (Object *obj : objects) {
ObjectProperty prop;
prop.existed = obj->hasProperty(mName);
prop.previousValue = obj->property(mName);
mProperties.append(prop);
}
for (Object *obj : objects)
mPreviousValues.append(obj->property(mName));

if (mObjects.size() > 1 || mObjects.at(0)->hasProperty(mName))
setText(QCoreApplication::translate("Undo Commands", "Set Property"));
Expand All @@ -155,17 +161,20 @@ SetProperty::SetProperty(Document *document,
void SetProperty::undo()
{
for (int i = 0; i < mObjects.size(); ++i) {
if (mProperties.at(i).existed)
mDocument->setProperty(mObjects.at(i), mName, mProperties.at(i).previousValue);
if (mPreviousValues.at(i).isValid())
mDocument->setProperty(mObjects.at(i), mName, mPreviousValues.at(i));
else
mDocument->removeProperty(mObjects.at(i), mName);
}
}

void SetProperty::redo()
{
for (Object *obj : std::as_const(mObjects))
mDocument->setPropertyMember(obj, mPath, mValue);
for (int i = 0; i < mObjects.size(); ++i) {
auto obj = mObjects.at(i);
auto &value = mValues.size() == 1 ? mValues.at(0) : mValues.at(i);
mDocument->setPropertyMember(obj, mPath, value);
}
}

bool SetProperty::mergeWith(const QUndoCommand *other)
Expand All @@ -175,12 +184,19 @@ bool SetProperty::mergeWith(const QUndoCommand *other)
// the old value already remembered on this undo command.
auto o = static_cast<const SetProperty*>(other);
if (mDocument == o->mDocument && mPath == o->mPath && mObjects == o->mObjects) {
mValue = o->mValue;
mValues = o->mValues;

bool obsolete = true;
for (int i = 0; i < mObjects.size(); ++i) {
auto &previousValue = mPreviousValues[i];
auto &value = mValues.size() == 1 ? mValues.at(0) : mValues.at(i);
if (previousValue != value) {
obsolete = false;
break;
}
}

setObsolete(std::all_of(mProperties.cbegin(), mProperties.cend(),
[this] (const ObjectProperty &p) {
return p.existed && p.previousValue == mValue;
}));
setObsolete(obsolete);

return true;
}
Expand Down Expand Up @@ -226,16 +242,22 @@ RenameProperty::RenameProperty(Document *document,
// Remove the old name from all objects
new RemoveProperty(document, objects, oldName, this);

QList<Object*> setOnObjects;
QVariantList values;

// Different objects may have different values for the same property,
// or may not have a value at all.
for (Object *object : objects) {
if (!object->hasProperty(oldName))
continue;

const QList<Object*> objects { object };
const QVariant value = object->property(oldName);
setOnObjects.append(object);
values.append(object->property(oldName));
}

new SetProperty(document, objects, newName, value, this);
if (!setOnObjects.isEmpty()) {
new SetProperty(document, setOnObjects,
QStringList { newName }, values, this);
}
}

Expand Down
23 changes: 17 additions & 6 deletions src/tiled/changeproperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ class SetProperty : public QUndoCommand
const QString &name,
const QVariant &value,
QUndoCommand *parent = nullptr);

/**
* Constructs a new 'Set Property' command.
*
Expand All @@ -115,6 +116,20 @@ class SetProperty : public QUndoCommand
const QVariant &value,
QUndoCommand *parent = nullptr);

/**
* Constructs a new 'Set Property' command.
*
* @param document the document owning the objects
* @param objects the objects of which the property should be changed
* @param path the path to a property member
* @param values the new values of the property, one for each object
*/
SetProperty(Document *document,
const QList<Object*> &objects,
const QStringList &path,
const QVariantList &values,
QUndoCommand *parent = nullptr);

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

Expand All @@ -123,16 +138,12 @@ class SetProperty : public QUndoCommand
bool mergeWith(const QUndoCommand *other) final;

private:
struct ObjectProperty {
QVariant previousValue;
bool existed;
};
QVector<ObjectProperty> mProperties;
Document *mDocument;
QList<Object*> mObjects;
QString mName;
QStringList mPath;
QVariant mValue;
QVariantList mValues;
QVariantList mPreviousValues;
};

class RemoveProperty : public QUndoCommand
Expand Down
22 changes: 15 additions & 7 deletions src/tiled/propertieswidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2827,15 +2827,23 @@ void PropertiesWidget::showContextMenu(const QPoint &pos)
QUndoStack *undoStack = mDocument->undoStack();
undoStack->beginMacro(QCoreApplication::translate("Tiled::PropertiesDock", "Convert Property/Properties", nullptr, properties.size()));

for (const QString &propertyName : propertyNames) {
QVariant propertyValue = object->property(propertyName);
const int toType = selectedItem->data().toInt();

int toType = selectedItem->data().toInt();
propertyValue.convert(toType);
for (const QString &propertyName : propertyNames) {
QList<Object*> objects;
QVariantList values;

for (auto obj : mDocument->currentObjects()) {
QVariant propertyValue = obj->property(propertyName);
if (propertyValue.convert(toType)) {
objects.append(obj);
values.append(propertyValue);
}
}

undoStack->push(new SetProperty(mDocument,
mDocument->currentObjects(),
propertyName, propertyValue));
undoStack->push(new SetProperty(mDocument, objects,
QStringList { propertyName },
values));
}

undoStack->endMacro();
Expand Down

0 comments on commit ae2b717

Please sign in to comment.