Skip to content

Commit

Permalink
Scripting: Fixed UI issues after setting class values
Browse files Browse the repository at this point in the history
When setting a class value from a script, the value was not getting
converted from a JS object to a QVariantMap. This tripped up code
elsewhere, for example making the UI unable to edit the values (though
it could still display them, and they also got saved correctly).

This change adds the missing conversion from JS object to QVariantMap to
`tiled.propertyValue` and `Object.setProperty`.
  • Loading branch information
bjorn committed Jun 4, 2024
1 parent f6d6d4e commit f907c3c
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 10 deletions.
2 changes: 1 addition & 1 deletion docs/scripting-doc/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1040,7 +1040,7 @@ declare class TiledObject {
/**
* Sets the value of the custom property with the given name. Supported
* types are `bool`, `number`, `string`, {@link FilePath},
* {@link ObjectRef} and {@link MapObject}.
* {@link ObjectRef}, {@link MapObject} and {@link PropertyValue}.
*
* @note When setting a `number`, the property type will be set to either
* `int` or `float`, depending on whether it is a whole number. To force
Expand Down
2 changes: 1 addition & 1 deletion src/tiled/editableobject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ bool EditableObject::isReadOnly() const
return asset() && asset()->isReadOnly();
}

void EditableObject::setProperty(const QString &name, const QVariant &value)
void EditableObject::setPropertyImpl(const QString &name, const QVariant &value)
{
if (Document *doc = document())
asset()->push(new SetProperty(doc, { mObject }, name, fromScript(value)));
Expand Down
16 changes: 12 additions & 4 deletions src/tiled/editableobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include "object.h"

#include <QJSValue>
#include <QObject>

namespace Tiled {
Expand Down Expand Up @@ -58,7 +59,7 @@ class EditableObject : public QObject
const QString &className() const;

Q_INVOKABLE QVariant property(const QString &name) const;
Q_INVOKABLE void setProperty(const QString &name, const QVariant &value);
Q_INVOKABLE void setProperty(const QString &name, const QJSValue &value);
Q_INVOKABLE void setColorProperty(const QString &name, const QColor &value);
Q_INVOKABLE void setColorProperty(const QString &name, int r, int g, int b, int a = 255);
Q_INVOKABLE void setFloatProperty(const QString &name, qreal value);
Expand Down Expand Up @@ -87,6 +88,8 @@ public slots:
void moveOwnershipToCpp();

private:
void setPropertyImpl(const QString &name, const QVariant &value);

QVariant toScript(const QVariant &value) const;
QVariant fromScript(const QVariant &value) const;
QVariantMap toScript(const QVariantMap &value) const;
Expand All @@ -112,19 +115,24 @@ inline QVariant EditableObject::property(const QString &name) const
return toScript(mObject->property(name));
}

inline void EditableObject::setProperty(const QString &name, const QJSValue &value)
{
setPropertyImpl(name, value.toVariant());
}

inline void EditableObject::setColorProperty(const QString &name, const QColor &value)
{
setProperty(name, value);
setPropertyImpl(name, value);
}

inline void EditableObject::setColorProperty(const QString &name, int r, int g, int b, int a)
{
setProperty(name, QColor(r, g, b, a));
setPropertyImpl(name, QColor(r, g, b, a));
}

inline void EditableObject::setFloatProperty(const QString &name, qreal value)
{
setProperty(name, value);
setPropertyImpl(name, value);
}

inline QVariantMap EditableObject::properties() const
Expand Down
12 changes: 9 additions & 3 deletions src/tiled/scriptmodule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,24 +249,30 @@ ObjectRef ScriptModule::objectRef(int id) const
return { id };
}

QVariant ScriptModule::propertyValue(const QString &typeName, const QVariant &value) const
QVariant ScriptModule::propertyValue(const QString &typeName, const QJSValue &value) const
{
auto type = Object::propertyTypes().findPropertyValueType(typeName);
if (!type) {
ScriptManager::instance().throwError(QCoreApplication::translate("Script Errors", "Unknown type: %1").arg(typeName));
return {};
}

const QVariant var = value.toVariant();

switch (type->type) {
case PropertyType::PT_Invalid:
case PropertyType::PT_Class:
if (var.userType() != QVariant::Map) {
ScriptManager::instance().throwError(QCoreApplication::translate("Script Errors", "Expected object to initialize class value"));
return {};
}
break;
case PropertyType::PT_Enum:
// Call toPropertyValue to support using strings to create a value
return type->toPropertyValue(value, ExportContext());
return type->toPropertyValue(var, ExportContext());
}

return type->wrap(value);
return type->wrap(var);
}

bool ScriptModule::versionLessThan(const QString &a, const QString &b)
Expand Down
2 changes: 1 addition & 1 deletion src/tiled/scriptmodule.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ class ScriptModule : public QObject

Q_INVOKABLE Tiled::FilePath filePath(const QUrl &path) const;
Q_INVOKABLE Tiled::ObjectRef objectRef(int id) const;
Q_INVOKABLE QVariant propertyValue(const QString &typeName, const QVariant &value) const;
Q_INVOKABLE QVariant propertyValue(const QString &typeName, const QJSValue &value) const;
Q_INVOKABLE bool versionLessThan(const QString &a);
Q_INVOKABLE bool versionLessThan(const QString &a, const QString &b);

Expand Down

0 comments on commit f907c3c

Please sign in to comment.