diff --git a/src/libtiled/objectgroup.h b/src/libtiled/objectgroup.h index 07765ebdbd..3abacd4a7e 100644 --- a/src/libtiled/objectgroup.h +++ b/src/libtiled/objectgroup.h @@ -238,3 +238,4 @@ TILEDSHARED_EXPORT ObjectGroup::DrawOrder drawOrderFromString(const QString &); } // namespace Tiled Q_DECLARE_METATYPE(Tiled::ObjectGroup*) +Q_DECLARE_METATYPE(Tiled::ObjectGroup::DrawOrder) diff --git a/src/libtiled/tileset.h b/src/libtiled/tileset.h index c7b5b01156..934adfdbfe 100644 --- a/src/libtiled/tileset.h +++ b/src/libtiled/tileset.h @@ -739,5 +739,9 @@ inline void Tileset::setTransformationFlags(TransformationFlags flags) Q_DECLARE_METATYPE(Tiled::Tileset*) Q_DECLARE_METATYPE(Tiled::SharedTileset) +Q_DECLARE_METATYPE(Tiled::Tileset::Orientation) +Q_DECLARE_METATYPE(Tiled::Tileset::TileRenderSize) +Q_DECLARE_METATYPE(Tiled::Tileset::FillMode) +Q_DECLARE_METATYPE(Tiled::Tileset::TransformationFlags) Q_DECLARE_OPERATORS_FOR_FLAGS(Tiled::Tileset::TransformationFlags) diff --git a/src/tiled/changeevents.h b/src/tiled/changeevents.h index c5e4061f27..0dbf599280 100644 --- a/src/tiled/changeevents.h +++ b/src/tiled/changeevents.h @@ -164,7 +164,7 @@ class TileLayerChangeEvent : public LayerChangeEvent class ImageLayerChangeEvent : public LayerChangeEvent { public: - enum TileLayerProperty { + enum ImageLayerProperty { TransparentColorProperty = 1 << 7, ImageSourceProperty = 1 << 8, RepeatProperty = 1 << 9, diff --git a/src/tiled/propertieswidget.cpp b/src/tiled/propertieswidget.cpp index 740da361a8..c7d4cc67f0 100644 --- a/src/tiled/propertieswidget.cpp +++ b/src/tiled/propertieswidget.cpp @@ -22,12 +22,15 @@ #include "actionmanager.h" #include "addpropertydialog.h" +#include "changeimagelayerproperty.h" #include "changelayer.h" #include "changemapproperty.h" +#include "changeobjectgroupproperties.h" #include "changeproperties.h" #include "clipboardmanager.h" #include "compression.h" #include "mapdocument.h" +#include "objectgroup.h" #include "preferences.h" #include "propertybrowser.h" #include "tilesetchanges.h" @@ -568,6 +571,7 @@ class LayerProperties : public QObject , mLayer(layer) { // todo: would be nicer to avoid the SpinBox and use a custom widget + // might also be nice to embed this in the header instead of using a property mIdProperty = editorFactory->createProperty( tr("ID"), [this]() { return mLayer->id(); }, @@ -634,7 +638,7 @@ class LayerProperties : public QObject this, &LayerProperties::onChanged); } - void populateEditor(VariantEditor *editor) + virtual void populateEditor(VariantEditor *editor) { editor->addHeader(tr("Layer")); editor->addProperty(mIdProperty); @@ -649,24 +653,27 @@ class LayerProperties : public QObject editor->addProperty(mParallaxFactorProperty); } -private: - void onChanged(const ChangeEvent &event) +protected: + virtual void onChanged(const ChangeEvent &event) { if (event.type != ChangeEvent::LayerChanged) return; - const auto properties = static_cast(event).properties; - if (properties & LayerChangeEvent::VisibleProperty) + const auto &layerChange = static_cast(event); + if (layerChange.layer != mLayer) + return; + + if (layerChange.properties & LayerChangeEvent::VisibleProperty) emit mVisibleProperty->valueChanged(); - if (properties & LayerChangeEvent::LockedProperty) + if (layerChange.properties & LayerChangeEvent::LockedProperty) emit mLockedProperty->valueChanged(); - if (properties & LayerChangeEvent::OpacityProperty) + if (layerChange.properties & LayerChangeEvent::OpacityProperty) emit mOpacityProperty->valueChanged(); - if (properties & LayerChangeEvent::TintColorProperty) + if (layerChange.properties & LayerChangeEvent::TintColorProperty) emit mTintColorProperty->valueChanged(); - if (properties & LayerChangeEvent::OffsetProperty) + if (layerChange.properties & LayerChangeEvent::OffsetProperty) emit mOffsetProperty->valueChanged(); - if (properties & LayerChangeEvent::ParallaxFactorProperty) + if (layerChange.properties & LayerChangeEvent::ParallaxFactorProperty) emit mParallaxFactorProperty->valueChanged(); } @@ -689,6 +696,148 @@ class LayerProperties : public QObject Property *mParallaxFactorProperty; }; +class ImageLayerProperties : public LayerProperties +{ + Q_OBJECT + +public: + ImageLayerProperties(MapDocument *mapDocument, ImageLayer *layer, ValueTypeEditorFactory *editorFactory, QObject *parent = nullptr) + : LayerProperties(mapDocument, layer, editorFactory, parent) + { + // todo: set a file filter for selecting images (or map files?) + mImageProperty = editorFactory->createProperty( + tr("Image Source"), + [this]() { return imageLayer()->imageSource(); }, + [this](const QVariant &value) { + push(new ChangeImageLayerImageSource(mMapDocument, { imageLayer() }, value.toUrl())); + }); + + mTransparentColorProperty = editorFactory->createProperty( + tr("Transparent Color"), + [this]() { return imageLayer()->transparentColor(); }, + [this](const QVariant &value) { + push(new ChangeImageLayerTransparentColor(mMapDocument, { imageLayer() }, value.value())); + }); + + // todo: consider merging Repeat X and Y into a single property + mRepeatXProperty = editorFactory->createProperty( + tr("Repeat X"), + [this]() { return imageLayer()->repeatX(); }, + [this](const QVariant &value) { + push(new ChangeImageLayerRepeatX(mMapDocument, { imageLayer() }, value.toBool())); + }); + + mRepeatYProperty = editorFactory->createProperty( + tr("Repeat Y"), + [this]() { return imageLayer()->repeatY(); }, + [this](const QVariant &value) { + push(new ChangeImageLayerRepeatY(mMapDocument, { imageLayer() }, value.toBool())); + }); + } + + void populateEditor(VariantEditor *editor) override + { + LayerProperties::populateEditor(editor); + editor->addHeader(tr("Image Layer")); + editor->addProperty(mImageProperty); + editor->addProperty(mTransparentColorProperty); + editor->addSeparator(); + editor->addProperty(mRepeatXProperty); + editor->addProperty(mRepeatYProperty); + } + +private: + void onChanged(const ChangeEvent &event) override + { + LayerProperties::onChanged(event); + + if (event.type != ChangeEvent::ImageLayerChanged) + return; + + const auto &layerChange = static_cast(event); + if (layerChange.layer != mLayer) + return; + + if (layerChange.properties & ImageLayerChangeEvent::ImageSourceProperty) + emit mImageProperty->valueChanged(); + if (layerChange.properties & ImageLayerChangeEvent::TransparentColorProperty) + emit mTransparentColorProperty->valueChanged(); + if (layerChange.properties & ImageLayerChangeEvent::RepeatProperty) { + emit mRepeatXProperty->valueChanged(); + emit mRepeatYProperty->valueChanged(); + } + } + + ImageLayer *imageLayer() const + { + return static_cast(mLayer); + } + + Property *mImageProperty; + Property *mTransparentColorProperty; + Property *mRepeatXProperty; + Property *mRepeatYProperty; +}; + +class ObjectGroupProperties : public LayerProperties +{ + Q_OBJECT + +public: + ObjectGroupProperties(MapDocument *mapDocument, ObjectGroup *layer, ValueTypeEditorFactory *editorFactory, QObject *parent = nullptr) + : LayerProperties(mapDocument, layer, editorFactory, parent) + { + mColorProperty = editorFactory->createProperty( + tr("Color"), + [this]() { return objectGroup()->color(); }, + [this](const QVariant &value) { + push(new ChangeObjectGroupColor(mMapDocument, { objectGroup() }, value.value())); + }); + + mDrawOrderProperty = editorFactory->createProperty( + tr("Draw Order"), + [this]() { return QVariant::fromValue(objectGroup()->drawOrder()); }, + [this](const QVariant &value) { + ObjectGroup::DrawOrder drawOrder = static_cast(value.toInt()); + push(new ChangeObjectGroupDrawOrder(mMapDocument, { objectGroup() }, drawOrder)); + }); + } + + void populateEditor(VariantEditor *editor) override + { + LayerProperties::populateEditor(editor); + editor->addHeader(tr("Object Layer")); + editor->addProperty(mColorProperty); + editor->addProperty(mDrawOrderProperty); + } + +private: + void onChanged(const ChangeEvent &event) override + { + LayerProperties::onChanged(event); + + if (event.type != ChangeEvent::ObjectGroupChanged) + return; + + const auto &layerChange = static_cast(event); + if (layerChange.objectGroup != objectGroup()) + return; + + if (layerChange.properties & ObjectGroupChangeEvent::ColorProperty) + emit mColorProperty->valueChanged(); + if (layerChange.properties & ObjectGroupChangeEvent::DrawOrderProperty) + emit mDrawOrderProperty->valueChanged(); + } + + ObjectGroup *objectGroup() const + { + return static_cast(mLayer); + } + + Property *mColorProperty; + Property *mDrawOrderProperty; +}; + class TilesetProperties : public QObject { Q_OBJECT @@ -913,9 +1062,29 @@ void PropertiesWidget::currentObjectChanged(Object *object) case Object::LayerType: { auto mapDocument = static_cast(mDocument); auto layer = static_cast(object); - auto properties = new LayerProperties(mapDocument, layer, mDefaultEditorFactory.get(), this); - properties->populateEditor(mPropertyBrowser); - mPropertiesObject = properties; + LayerProperties *layerProperties = nullptr; + + switch (layer->layerType()) { + case Layer::ImageLayerType: + layerProperties = new ImageLayerProperties(mapDocument, + static_cast(layer), + mDefaultEditorFactory.get(), this); + break; + case Layer::ObjectGroupType: + layerProperties = new ObjectGroupProperties(mapDocument, + static_cast(layer), + mDefaultEditorFactory.get(), this); + break; + case Layer::TileLayerType: + case Layer::GroupLayerType: + layerProperties = new LayerProperties(mapDocument, + layer, + mDefaultEditorFactory.get(), this); + break; + } + + layerProperties->populateEditor(mPropertyBrowser); + mPropertiesObject = layerProperties; } case Object::MapObjectType: break; @@ -1422,6 +1591,13 @@ void PropertiesWidget::registerEditorFactories() tr("Stretch"), tr("Preserve Aspect Ratio"), })); + + registerEditorFactory(qMetaTypeId(), + std::make_unique( + QStringList { + tr("Top Down"), + tr("Index Order"), + })); } void PropertiesWidget::registerEditorFactory(int type, std::unique_ptr factory) diff --git a/src/tiled/varianteditor.cpp b/src/tiled/varianteditor.cpp index 7037a6337a..854b52d5c7 100644 --- a/src/tiled/varianteditor.cpp +++ b/src/tiled/varianteditor.cpp @@ -21,6 +21,7 @@ #include "varianteditor.h" #include "colorbutton.h" +#include "fileedit.h" #include "utils.h" #include "propertyeditorwidgets.h" @@ -82,6 +83,34 @@ class StringEditorFactory : public EditorFactory } }; +class UrlEditorFactory : public EditorFactory +{ +public: + QWidget *createEditor(Property *property, QWidget *parent) override + { + auto editor = new FileEdit(parent); + editor->setFilter(m_filter); + + auto syncEditor = [=] { + editor->setFileUrl(property->value().toUrl()); + }; + syncEditor(); + + QObject::connect(property, &Property::valueChanged, editor, syncEditor); + QObject::connect(editor, &FileEdit::fileUrlChanged, property, &Property::setValue); + + return editor; + } + + void setFilter(const QString &filter) + { + m_filter = filter; + } + +private: + QString m_filter; +}; + class IntEditorFactory : public EditorFactory { public: @@ -581,6 +610,7 @@ ValueTypeEditorFactory::ValueTypeEditorFactory() registerEditorFactory(QMetaType::QRectF, std::make_unique()); registerEditorFactory(QMetaType::QSize, std::make_unique()); registerEditorFactory(QMetaType::QString, std::make_unique()); + registerEditorFactory(QMetaType::QUrl, std::make_unique()); } void ValueTypeEditorFactory::registerEditorFactory(int type, std::unique_ptr factory)