Skip to content

Commit

Permalink
Merge pull request #2941 from svipal/master
Browse files Browse the repository at this point in the history
Added support for custom enum properties
  • Loading branch information
bjorn authored Jun 29, 2021
2 parents 2eb1077 + 795461a commit 4cdcdb1
Show file tree
Hide file tree
Showing 52 changed files with 1,682 additions and 387 deletions.
30 changes: 29 additions & 1 deletion examples/examples.tiled-project
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,33 @@
".",
"../tests"
],
"objectTypesFile": "objecttypes.xml"
"objectTypesFile": "objecttypes.xml",
"propertyTypes": [
{
"id": 1,
"name": "BodyType",
"values": [
"Static",
"Dynamic"
]
},
{
"id": 2,
"name": "EnemyType",
"values": [
"Neutral",
"Friendly",
"Aggressive"
]
},
{
"id": 3,
"name": "State",
"values": [
"Open",
"Closed",
"Locked"
]
}
]
}
8 changes: 8 additions & 0 deletions src/libtiled/containerhelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,11 @@ inline bool contains(const Container &container, Value value)
container.end(),
value) != container.end();
}

template<typename Container, typename Pred>
inline bool contains_where(const Container &container, Pred pred)
{
return std::find_if(container.begin(),
container.end(),
pred) != container.end();
}
2 changes: 2 additions & 0 deletions src/libtiled/libtiled-src.pri
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ SOURCES += $$PWD/compression.cpp \
$$PWD/plugin.cpp \
$$PWD/pluginmanager.cpp \
$$PWD/properties.cpp \
$$PWD/propertytype.cpp \
$$PWD/savefile.cpp \
$$PWD/staggeredrenderer.cpp \
$$PWD/templatemanager.cpp \
Expand Down Expand Up @@ -75,6 +76,7 @@ HEADERS += $$PWD/compression.h \
$$PWD/plugin.h \
$$PWD/pluginmanager.h \
$$PWD/properties.h \
$$PWD/propertytype.h \
$$PWD/savefile.h \
$$PWD/staggeredrenderer.h \
$$PWD/templatemanager.h \
Expand Down
2 changes: 2 additions & 0 deletions src/libtiled/libtiled.qbs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ DynamicLibrary {
"pluginmanager.h",
"properties.cpp",
"properties.h",
"propertytype.cpp",
"propertytype.h",
"savefile.cpp",
"savefile.h",
"staggeredrenderer.cpp",
Expand Down
15 changes: 7 additions & 8 deletions src/libtiled/mapreader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1429,8 +1429,12 @@ void MapReaderPrivate::readProperty(Properties *properties)

const QXmlStreamAttributes atts = xml.attributes();
QString propertyName = atts.value(QLatin1String("name")).toString();

ExportValue exportValue;
exportValue.typeName = atts.value(QLatin1String("type")).toString();
exportValue.propertyTypeName = atts.value(QLatin1String("propertytype")).toString();

QString propertyValue = atts.value(QLatin1String("value")).toString();
QString propertyType = atts.value(QLatin1String("type")).toString();

while (xml.readNext() != QXmlStreamReader::Invalid) {
if (xml.isEndElement()) {
Expand All @@ -1443,14 +1447,9 @@ void MapReaderPrivate::readProperty(Properties *properties)
}
}

QVariant variant(propertyValue);

if (!propertyType.isEmpty()) {
int type = nameToType(propertyType);
variant = fromExportValue(variant, type, mPath);
}
exportValue.value = propertyValue;

properties->insert(propertyName, variant);
properties->insert(propertyName, exportValue.toPropertyValue(mPath.path()));
}


Expand Down
30 changes: 18 additions & 12 deletions src/libtiled/maptovariantconverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -336,8 +336,8 @@ QVariant MapToVariantConverter::toVariant(const Properties &properties) const
Properties::const_iterator it = properties.constBegin();
Properties::const_iterator it_end = properties.constEnd();
for (; it != it_end; ++it) {
const QVariant value = toExportValue(it.value(), mDir);
variantMap[it.key()] = value;
const auto exportValue = ExportValue::fromPropertyValue(it.value(), mDir.path());
variantMap[it.key()] = exportValue.value;
}

return variantMap;
Expand All @@ -349,8 +349,11 @@ QVariant MapToVariantConverter::propertyTypesToVariant(const Properties &propert

Properties::const_iterator it = properties.constBegin();
Properties::const_iterator it_end = properties.constEnd();
for (; it != it_end; ++it)
variantMap[it.key()] = typeToName(it.value().userType());
for (; it != it_end; ++it) {
const auto exportValue = ExportValue::fromPropertyValue(it.value());
// TODO: Support custom property types in json1? Maybe with a customPropertyTypesToVariant...
variantMap[it.key()] = exportValue.typeName;
}

return variantMap;
}
Expand Down Expand Up @@ -753,11 +756,11 @@ void MapToVariantConverter::addProperties(QVariantMap &variantMap,
Properties::const_iterator it = properties.constBegin();
Properties::const_iterator it_end = properties.constEnd();
for (; it != it_end; ++it) {
int type = it.value().userType();
const QVariant value = toExportValue(it.value(), mDir);
const auto exportValue = ExportValue::fromPropertyValue(it.value(), mDir.path());

propertiesMap[it.key()] = value;
propertyTypesMap[it.key()] = typeToName(type);
propertiesMap[it.key()] = exportValue.value;
propertyTypesMap[it.key()] = exportValue.typeName;
// TODO: Support custom property types in json1? Maybe with a customPropertyTypesMap...
}

variantMap[QStringLiteral("properties")] = propertiesMap;
Expand All @@ -768,13 +771,16 @@ void MapToVariantConverter::addProperties(QVariantMap &variantMap,
Properties::const_iterator it = properties.constBegin();
Properties::const_iterator it_end = properties.constEnd();
for (; it != it_end; ++it) {
int type = it.value().userType();
const QVariant value = toExportValue(it.value(), mDir);
const auto exportValue = ExportValue::fromPropertyValue(it.value(), mDir.path());

QVariantMap propertyVariantMap;
propertyVariantMap[QStringLiteral("name")] = it.key();
propertyVariantMap[QStringLiteral("value")] = value;
propertyVariantMap[QStringLiteral("type")] = typeToName(type);
propertyVariantMap[QStringLiteral("value")] = exportValue.value;
propertyVariantMap[QStringLiteral("type")] = exportValue.typeName;

if (!exportValue.propertyTypeName.isEmpty())
propertyVariantMap[QStringLiteral("propertytype")] = exportValue.propertyTypeName;

propertiesVariantList << propertyVariantMap;
}

Expand Down
32 changes: 13 additions & 19 deletions src/libtiled/mapwriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -388,11 +388,8 @@ void MapWriterPrivate::writeTileset(QXmlStreamWriter &w, const Tileset &tileset,
const QUrl &imageSource = tileset.imageSource();
if (!imageSource.isEmpty()) {
w.writeStartElement(QStringLiteral("image"));
QString source;
if (mUseAbsolutePaths)
source = imageSource.toString(QUrl::PreferLocalFile);
else
source = toFileReference(imageSource, mDir);
QString source = toFileReference(imageSource, mUseAbsolutePaths ? QString()
: mDir.path());
w.writeAttribute(QStringLiteral("source"), source);

const QColor transColor = tileset.transparentColor();
Expand Down Expand Up @@ -445,11 +442,8 @@ void MapWriterPrivate::writeTileset(QXmlStreamWriter &w, const Tileset &tileset,
w.writeCharacters(QString::fromLatin1(buffer.data().toBase64()));
w.writeEndElement(); // </data>
} else {
QString source;
if (mUseAbsolutePaths)
source = tile->imageSource().toString(QUrl::PreferLocalFile);
else
source = toFileReference(tile->imageSource(), mDir);
QString source = toFileReference(tile->imageSource(), mUseAbsolutePaths ? QString()
: mDir.path());
w.writeAttribute(QStringLiteral("source"), source);
}

Expand Down Expand Up @@ -871,8 +865,8 @@ void MapWriterPrivate::writeImageLayer(QXmlStreamWriter &w,
if (!imageSource.isEmpty()) {
w.writeStartElement(QStringLiteral("image"));

QString source = mUseAbsolutePaths ? imageSource.toString(QUrl::PreferLocalFile)
: toFileReference(imageSource, mDir);
QString source = toFileReference(imageSource, mUseAbsolutePaths ? QString()
: mDir.path());

w.writeAttribute(QStringLiteral("source"), source);

Expand Down Expand Up @@ -922,14 +916,14 @@ void MapWriterPrivate::writeProperties(QXmlStreamWriter &w,
w.writeStartElement(QStringLiteral("property"));
w.writeAttribute(QStringLiteral("name"), it.key());

int type = it.value().userType();
QString typeName = typeToName(type);
if (typeName != QLatin1String("string"))
w.writeAttribute(QStringLiteral("type"), typeName);
const auto exportValue = ExportValue::fromPropertyValue(it.value(), mUseAbsolutePaths ? QString()
: mDir.path());
if (exportValue.typeName != QLatin1String("string"))
w.writeAttribute(QStringLiteral("type"), exportValue.typeName);
if (!exportValue.propertyTypeName.isEmpty())
w.writeAttribute(QStringLiteral("propertytype"), exportValue.propertyTypeName);

QVariant exportValue = mUseAbsolutePaths ? toExportValue(it.value())
: toExportValue(it.value(), mDir);
QString value = exportValue.toString();
QString value = exportValue.value.toString();

if (value.contains(QLatin1Char('\n')))
w.writeCharacters(value);
Expand Down
20 changes: 19 additions & 1 deletion src/libtiled/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
namespace Tiled {

ObjectTypes Object::mObjectTypes;

PropertyTypes Object::mPropertyTypes;
Object::~Object()
{}

Expand Down Expand Up @@ -145,4 +145,22 @@ void Object::setObjectTypes(const ObjectTypes &objectTypes)
mObjectTypes = objectTypes;
}

void Object::setPropertyTypes(const PropertyTypes &propertyTypes)
{
mPropertyTypes = propertyTypes;
}

/**
* Returns a pointer to the PropertyType matching the given \a typeId, or
* nullptr if it can't be found.
*/
const PropertyType *Object::propertyType(int typeId)
{
for (const PropertyType &propertyType : Object::propertyTypes()) {
if (propertyType.id == typeId)
return &propertyType;
}
return nullptr;
}

} // namespace Tiled
10 changes: 8 additions & 2 deletions src/libtiled/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@

#pragma once

#include "properties.h"
#include "objecttypes.h"
#include "properties.h"
#include "propertytype.h"

namespace Tiled {

Expand Down Expand Up @@ -110,7 +111,7 @@ class TILEDSHARED_EXPORT Object
* Returns the type of the object's \a name property, as a string.
*/
QString propertyType(const QString &name) const
{ return typeToName(mProperties.value(name).userType()); }
{ return typeName(mProperties.value(name)); }

/**
* Returns whether this object has a property with the given \a name.
Expand All @@ -133,14 +134,19 @@ class TILEDSHARED_EXPORT Object
bool isPartOfTileset() const;

static void setObjectTypes(const ObjectTypes &objectTypes);
static void setPropertyTypes(const PropertyTypes &propertyTypes);
static const ObjectTypes &objectTypes()
{ return mObjectTypes; }
static const PropertyTypes &propertyTypes()
{ return mPropertyTypes; }
static const PropertyType *propertyType(int typeId);

private:
const TypeId mTypeId;
Properties mProperties;

static ObjectTypes mObjectTypes;
static PropertyTypes mPropertyTypes;
};


Expand Down
49 changes: 25 additions & 24 deletions src/libtiled/objecttypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ static QJsonObject toJson(const ObjectType &objectType, const QDir &fileDir)
const QString NAME = QStringLiteral("name");
const QString VALUE = QStringLiteral("value");
const QString TYPE = QStringLiteral("type");
const QString PROPERTY_TYPE = QStringLiteral("propertytype");
const QString COLOR = QStringLiteral("color");
const QString PROPERTIES = QStringLiteral("properties");

Expand All @@ -63,15 +64,15 @@ static QJsonObject toJson(const ObjectType &objectType, const QDir &fileDir)
while (it.hasNext()) {
it.next();

int type = it.value().userType();

const QString typeName = typeToName(type);
const QVariant exportValue = toExportValue(it.value(), fileDir);
const auto exportValue = ExportValue::fromPropertyValue(it.value(), fileDir.path());

QJsonObject propertyJson;
propertyJson.insert(NAME, it.key());
propertyJson.insert(TYPE, typeName);
propertyJson.insert(VALUE, QJsonValue::fromVariant(exportValue));
propertyJson.insert(TYPE, exportValue.typeName);
propertyJson.insert(VALUE, QJsonValue::fromVariant(exportValue.value));

if (!exportValue.propertyTypeName.isEmpty())
propertyJson.insert(PROPERTY_TYPE, exportValue.propertyTypeName);

propertiesJson.append(propertyJson);
}
Expand Down Expand Up @@ -101,15 +102,14 @@ static void fromJson(const QJsonObject &object, ObjectType &objectType, const QD
for (const QJsonValue &property : properties) {
const QJsonObject propertyObject = property.toObject();
const QString name = propertyObject.value(QLatin1String("name")).toString();
const QString typeName = propertyObject.value(QLatin1String("type")).toString();
QVariant value = propertyObject.value(QLatin1String("value")).toVariant();

if (!typeName.isEmpty()) {
int type = nameToType(typeName);
value = fromExportValue(value, type, fileDir);
}
ExportValue exportValue;
exportValue.value = propertyObject.value(QLatin1String("value")).toVariant();
exportValue.typeName = propertyObject.value(QLatin1String("type")).toString();
exportValue.propertyTypeName = propertyObject.value(QLatin1String("propertytype")).toString();

objectType.defaultProperties.insert(name, value);
objectType.defaultProperties.insert(name,
exportValue.toPropertyValue(fileDir.path()));
}
}

Expand Down Expand Up @@ -142,14 +142,17 @@ static void writeObjectTypesXml(QFileDevice *device,
while (it.hasNext()) {
it.next();

int type = it.value().userType();
const auto exportValue = ExportValue::fromPropertyValue(it.value(), fileDir.path());

writer.writeStartElement(QStringLiteral("property"));
writer.writeAttribute(QStringLiteral("name"), it.key());
writer.writeAttribute(QStringLiteral("type"), typeToName(type));
writer.writeAttribute(QStringLiteral("type"), exportValue.typeName);

if (!exportValue.propertyTypeName.isEmpty())
writer.writeAttribute(QStringLiteral("propertytype"), exportValue.propertyTypeName);

if (!it.value().isNull()) {
const QString value = toExportValue(it.value(), fileDir).toString();
const QString value = exportValue.value.toString();
writer.writeAttribute(QStringLiteral("default"), value);
}

Expand All @@ -170,16 +173,14 @@ static void readObjectTypePropertyXml(QXmlStreamReader &xml,
Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("property"));

const QXmlStreamAttributes atts = xml.attributes();
QString name(atts.value(QLatin1String("name")).toString());
QString typeName(atts.value(QLatin1String("type")).toString());
QVariant defaultValue(atts.value(QLatin1String("default")).toString());
const QString name = atts.value(QLatin1String("name")).toString();

if (!typeName.isEmpty()) {
int type = nameToType(typeName);
defaultValue = fromExportValue(defaultValue, type, fileDir);
}
ExportValue exportValue;
exportValue.value = atts.value(QLatin1String("default")).toString();
exportValue.typeName = atts.value(QLatin1String("type")).toString();
exportValue.propertyTypeName = atts.value(QLatin1String("propertytype")).toString();

props.insert(name, defaultValue);
props.insert(name, exportValue.toPropertyValue(fileDir.path()));

xml.skipCurrentElement();
}
Expand Down
Loading

0 comments on commit 4cdcdb1

Please sign in to comment.