From 24b42fb0e006192d07cbb67da39d16098d841ee7 Mon Sep 17 00:00:00 2001 From: jcbk101 Date: Wed, 14 Aug 2024 21:30:21 -0400 Subject: [PATCH] Per-object opacity initial push --- src/libtiled/mapobject.cpp | 11 +++++++++ src/libtiled/mapobject.h | 22 ++++++++++++++++++ src/libtiled/mapreader.cpp | 7 ++++++ src/libtiled/maprenderer.cpp | 4 +++- src/libtiled/maptovariantconverter.cpp | 4 ++++ src/libtiled/mapwriter.cpp | 5 +++++ src/libtiled/tilelayer.h | 5 +++++ src/libtiled/varianttomapconverter.cpp | 8 +++++++ src/plugins/lua/luaplugin.cpp | 2 ++ src/plugins/python/pythonbind.cpp | 31 ++++++++++++++++++++++++++ src/plugins/python/tiledbinding.py | 3 +++ src/tiled/editablemapobject.cpp | 6 +++++ src/tiled/editablemapobject.h | 12 ++++++++++ src/tiled/mapobjectitem.cpp | 2 ++ src/tiled/objectselectionitem.cpp | 2 ++ src/tiled/objectselectiontool.cpp | 4 +++- src/tiled/objectselectiontool.h | 2 ++ src/tiled/propertybrowser.cpp | 15 +++++++++++++ src/tmxviewer/tmxviewer.cpp | 2 ++ 19 files changed, 145 insertions(+), 2 deletions(-) diff --git a/src/libtiled/mapobject.cpp b/src/libtiled/mapobject.cpp index a517801a98..dfaf31e22e 100644 --- a/src/libtiled/mapobject.cpp +++ b/src/libtiled/mapobject.cpp @@ -312,6 +312,8 @@ QVariant MapObject::mapObjectProperty(Property property) const case PositionProperty: return mPos; case SizeProperty: return mSize; case RotationProperty: return mRotation; + // BONGO + case OpacityProperty: return mOpacity; case CellProperty: Q_ASSERT(false); break; case ShapeProperty: return mShape; case TemplateProperty: Q_ASSERT(false); break; @@ -334,6 +336,7 @@ void MapObject::setMapObjectProperty(Property property, const QVariant &value) case PositionProperty: setPosition(value.toPointF()); break; case SizeProperty: setSize(value.toSizeF()); break; case RotationProperty: setRotation(value.toReal()); break; + case OpacityProperty: setOpacity(value.toReal()); break; case CellProperty: Q_ASSERT(false); break; case ShapeProperty: setShape(value.value()); break; case TemplateProperty: Q_ASSERT(false); break; @@ -374,6 +377,8 @@ MapObject *MapObject::clone() const o->setShape(mShape); o->setCell(mCell); o->setRotation(mRotation); + // BONGO + o->setOpacity(mOpacity); o->setVisible(mVisible); o->setChangedProperties(mChangedProperties); o->setObjectTemplate(mObjectTemplate); @@ -389,6 +394,8 @@ void MapObject::copyPropertiesFrom(const MapObject *object) setShape(object->shape()); setCell(object->cell()); setRotation(object->rotation()); + // BONGO + setOpacity(object->opacity()); setVisible(object->isVisible()); setProperties(object->properties()); setChangedProperties(object->changedProperties()); @@ -428,6 +435,10 @@ void MapObject::syncWithTemplate() if (!propertyChanged(MapObject::RotationProperty)) setRotation(base->rotation()); + // BONGO + if (!propertyChanged(MapObject::OpacityProperty)) + setOpacity(base->opacity()); + if (!propertyChanged(MapObject::VisibleProperty)) setVisible(base->isVisible()); } diff --git a/src/libtiled/mapobject.h b/src/libtiled/mapobject.h index 4e8ae8ab27..54a1c39faa 100644 --- a/src/libtiled/mapobject.h +++ b/src/libtiled/mapobject.h @@ -121,6 +121,8 @@ class TILEDSHARED_EXPORT MapObject : public Object ShapeProperty = 1 << 11, TemplateProperty = 1 << 12, CustomProperties = 1 << 13, + // BONGO + OpacityProperty = 1 << 14, AllProperties = 0xFF }; @@ -200,6 +202,10 @@ class TILEDSHARED_EXPORT MapObject : public Object qreal rotation() const; void setRotation(qreal rotation); + // BONGO + qreal opacity() const; + void setOpacity(qreal opacity); + Alignment alignment(const Map *map = nullptr) const; bool isVisible() const; @@ -247,6 +253,8 @@ class TILEDSHARED_EXPORT MapObject : public Object const ObjectTemplate *mObjectTemplate = nullptr; ObjectGroup *mObjectGroup = nullptr; qreal mRotation = 0.0; + // BONGO + qreal mOpacity = 1.0; bool mVisible = true; bool mTemplateBase = false; ChangedProperties mChangedProperties; @@ -479,6 +487,20 @@ inline qreal MapObject::rotation() const inline void MapObject::setRotation(qreal rotation) { mRotation = rotation; } +/** + * BONGO: Add Opacity for objects + * returns current opacity +*/ +inline qreal MapObject::opacity() const +{ return mOpacity; } + +/** + * BONGO: Add Opacity for objects + * sets new opacity +*/ +inline void MapObject::setOpacity(qreal opacity) +{ mOpacity = opacity; } + inline bool MapObject::isVisible() const { return mVisible; } diff --git a/src/libtiled/mapreader.cpp b/src/libtiled/mapreader.cpp index 820eed8b43..06b8f9e9b6 100644 --- a/src/libtiled/mapreader.cpp +++ b/src/libtiled/mapreader.cpp @@ -1222,6 +1222,13 @@ std::unique_ptr MapReaderPrivate::readObject() object->setPropertyChanged(MapObject::RotationProperty); } + // BONGO + const qreal opacity = atts.value(QLatin1String("opacity")).toDouble(&ok); + if (ok) { + object->setOpacity(opacity); + object->setPropertyChanged(MapObject::OpacityProperty); + } + if (gid) { object->setCell(cellForGid(gid)); object->setPropertyChanged(MapObject::CellProperty); diff --git a/src/libtiled/maprenderer.cpp b/src/libtiled/maprenderer.cpp index acfa47e284..50e510da40 100644 --- a/src/libtiled/maprenderer.cpp +++ b/src/libtiled/maprenderer.cpp @@ -452,7 +452,9 @@ void CellRenderer::render(const Cell &cell, const QPointF &screenPos, const QSiz fragment.scaleX = size.width() / imageRect.width(); fragment.scaleY = size.height() / imageRect.height(); fragment.rotation = 0; - fragment.opacity = 1; +// fragment.opacity = 1; + // BONGO + fragment.opacity = cell.getOpacity(); const auto fillMode = tile->tileset()->fillMode(); if (fillMode == Tileset::PreserveAspectFit) { diff --git a/src/libtiled/maptovariantconverter.cpp b/src/libtiled/maptovariantconverter.cpp index 93e7fb882f..0ef41d65b1 100644 --- a/src/libtiled/maptovariantconverter.cpp +++ b/src/libtiled/maptovariantconverter.cpp @@ -586,6 +586,10 @@ QVariant MapToVariantConverter::toVariant(const MapObject &object) const if (notTemplateInstance || object.propertyChanged(MapObject::RotationProperty)) objectVariant[QStringLiteral("rotation")] = object.rotation(); + // BONGO + if (notTemplateInstance || object.propertyChanged(MapObject::OpacityProperty)) + objectVariant[QStringLiteral("opacity")] = object.opacity(); + if (notTemplateInstance || object.propertyChanged(MapObject::VisibleProperty)) objectVariant[QStringLiteral("visible")] = object.isVisible(); diff --git a/src/libtiled/mapwriter.cpp b/src/libtiled/mapwriter.cpp index d6c4f3265d..f4bd3be6b0 100644 --- a/src/libtiled/mapwriter.cpp +++ b/src/libtiled/mapwriter.cpp @@ -756,6 +756,11 @@ void MapWriterPrivate::writeObject(QXmlStreamWriter &w, if (shouldWrite(rotation != 0.0, isTemplateInstance, mapObject.propertyChanged(MapObject::RotationProperty))) w.writeAttribute(QStringLiteral("rotation"), QString::number(rotation)); + // BONGO + const qreal opacity = mapObject.opacity(); + if (shouldWrite(opacity != 1.0, isTemplateInstance, mapObject.propertyChanged(MapObject::OpacityProperty))) + w.writeAttribute(QStringLiteral("opacity"), QString::number(opacity)); + if (shouldWrite(!mapObject.isVisible(), isTemplateInstance, mapObject.propertyChanged(MapObject::VisibleProperty))) w.writeAttribute(QStringLiteral("visible"), QLatin1String(mapObject.isVisible() ? "1" : "0")); diff --git a/src/libtiled/tilelayer.h b/src/libtiled/tilelayer.h index e38aa40c4b..4fe1a6b625 100644 --- a/src/libtiled/tilelayer.h +++ b/src/libtiled/tilelayer.h @@ -123,6 +123,9 @@ class TILEDSHARED_EXPORT Cell void setRotatedHexagonal120(bool v) { v ? _flags |= RotatedHexagonal120 : _flags &= ~RotatedHexagonal120; } void rotate(RotateDirection direction); + // BONGO + float getOpacity() const { return _opacity; } + void setOpacity(float mOpacity) { _opacity = mOpacity; } bool checked() const { return _flags & Checked; } void setChecked(bool checked) { checked ? _flags |= Checked : _flags &= ~Checked; } @@ -138,6 +141,8 @@ class TILEDSHARED_EXPORT Cell Tileset *_tileset = nullptr; int _tileId = -1; int _flags = 0; + //BONGO + float _opacity = 1.0; }; inline Tile *Cell::tile() const diff --git a/src/libtiled/varianttomapconverter.cpp b/src/libtiled/varianttomapconverter.cpp index 2c2b9bf3b5..7db16731f2 100644 --- a/src/libtiled/varianttomapconverter.cpp +++ b/src/libtiled/varianttomapconverter.cpp @@ -722,6 +722,8 @@ std::unique_ptr VariantToMapConverter::toMapObject(const QVariantMap const qreal width = variantMap[QStringLiteral("width")].toReal(); const qreal height = variantMap[QStringLiteral("height")].toReal(); const qreal rotation = variantMap[QStringLiteral("rotation")].toReal(); + // BONGO + const qreal opacity = variantMap[QStringLiteral("opacity")].toReal(); QString className = variantMap[QStringLiteral("class")].toString(); if (className.isEmpty()) // fallback for compatibility @@ -738,6 +740,12 @@ std::unique_ptr VariantToMapConverter::toMapObject(const QVariantMap object->setPropertyChanged(MapObject::RotationProperty); } + // BONGO + if (variantMap.contains(QLatin1String("opacity"))) { + object->setOpacity(opacity); + object->setPropertyChanged(MapObject::OpacityProperty); + } + if (!templateVariant.isNull()) { // This object is a template instance QString templateFileName = resolvePath(mDir, templateVariant); auto objectTemplate = TemplateManager::instance()->loadObjectTemplate(templateFileName); diff --git a/src/plugins/lua/luaplugin.cpp b/src/plugins/lua/luaplugin.cpp index e8d53b2d37..de9bbae3d2 100644 --- a/src/plugins/lua/luaplugin.cpp +++ b/src/plugins/lua/luaplugin.cpp @@ -730,6 +730,8 @@ void LuaWriter::writeMapObject(const Tiled::MapObject *mapObject) mWriter.writeKeyAndValue("width", mapObject->width()); mWriter.writeKeyAndValue("height", mapObject->height()); mWriter.writeKeyAndValue("rotation", mapObject->rotation()); + // BONGO + mWriter.writeKeyAndValue("opacity", mapObject->opacity()); if (!mapObject->cell().isEmpty()) mWriter.writeKeyAndValue("gid", mGidMapper.cellToGid(mapObject->cell())); diff --git a/src/plugins/python/pythonbind.cpp b/src/plugins/python/pythonbind.cpp index 18d5f5cb3d..8cf1e2a32c 100644 --- a/src/plugins/python/pythonbind.cpp +++ b/src/plugins/python/pythonbind.cpp @@ -6996,6 +6996,17 @@ _wrap_PyTiledMapObject_rotation(PyTiledMapObject *self, PyObject *PYBINDGEN_UNUS return py_retval; } +/* BONGO */ +PyObject * +_wrap_PyTiledMapObject_opacity(PyTiledMapObject *self, PyObject *PYBINDGEN_UNUSED(_args), PyObject *PYBINDGEN_UNUSED(_kwargs)) +{ + PyObject *py_retval; + double retval; + + retval = self->obj->opacity(); + py_retval = Py_BuildValue((char *) "d", retval); + return py_retval; +} PyObject * _wrap_PyTiledMapObject_setCell(PyTiledMapObject *self, PyObject *args, PyObject *kwargs) @@ -7082,6 +7093,22 @@ _wrap_PyTiledMapObject_setRotation(PyTiledMapObject *self, PyObject *args, PyObj return py_retval; } +/* BONGO */ +PyObject * +_wrap_PyTiledMapObject_setOpacity(PyTiledMapObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *py_retval; + double r; + const char *keywords[] = {"r", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "d", (char **) keywords, &r)) { + return NULL; + } + self->obj->setOpacity(r); + Py_INCREF(Py_None); + py_retval = Py_None; + return py_retval; +} PyObject * _wrap_PyTiledMapObject_setShape(PyTiledMapObject *self, PyObject *args, PyObject *kwargs) @@ -7272,11 +7299,15 @@ static PyMethodDef PyTiledMapObject_methods[] = { {(char *) "name", (PyCFunction) _wrap_PyTiledMapObject_name, METH_NOARGS, "name()\n\n" }, {(char *) "objectGroup", (PyCFunction) _wrap_PyTiledMapObject_objectGroup, METH_NOARGS, "objectGroup()\n\n" }, {(char *) "rotation", (PyCFunction) _wrap_PyTiledMapObject_rotation, METH_NOARGS, "rotation()\n\n" }, + /* BONGO */ + {(char *) "opacity", (PyCFunction) _wrap_PyTiledMapObject_opacity, METH_NOARGS, "opacity()\n\n" }, {(char *) "setCell", (PyCFunction) _wrap_PyTiledMapObject_setCell, METH_KEYWORDS|METH_VARARGS, "setCell(c)\n\ntype: c: Tiled::Cell const" }, {(char *) "setHeight", (PyCFunction) _wrap_PyTiledMapObject_setHeight, METH_KEYWORDS|METH_VARARGS, "setHeight(h)\n\ntype: h: double" }, {(char *) "setName", (PyCFunction) _wrap_PyTiledMapObject_setName, METH_KEYWORDS|METH_VARARGS, "setName(n)\n\ntype: n: QString" }, {(char *) "setPosition", (PyCFunction) _wrap_PyTiledMapObject_setPosition, METH_KEYWORDS|METH_VARARGS, "setPosition(pos)\n\ntype: pos: QPointF" }, {(char *) "setRotation", (PyCFunction) _wrap_PyTiledMapObject_setRotation, METH_KEYWORDS|METH_VARARGS, "setRotation(r)\n\ntype: r: double" }, + /* BONGO */ + {(char *) "setOpacity", (PyCFunction) _wrap_PyTiledMapObject_setOpacity, METH_KEYWORDS|METH_VARARGS, "setOpacity(r)\n\ntype: r: double" }, {(char *) "setShape", (PyCFunction) _wrap_PyTiledMapObject_setShape, METH_KEYWORDS|METH_VARARGS, "setShape(s)\n\ntype: s: Tiled::MapObject::Shape" }, {(char *) "setSize", (PyCFunction) _wrap_PyTiledMapObject_setSize, METH_KEYWORDS|METH_VARARGS, "setSize(size)\n\ntype: size: QSizeF" }, {(char *) "setType", (PyCFunction) _wrap_PyTiledMapObject_setType, METH_KEYWORDS|METH_VARARGS, "setType(n)\n\ntype: n: QString" }, diff --git a/src/plugins/python/tiledbinding.py b/src/plugins/python/tiledbinding.py index 2901f270aa..30db3fb834 100755 --- a/src/plugins/python/tiledbinding.py +++ b/src/plugins/python/tiledbinding.py @@ -280,6 +280,9 @@ def _decorate(obj, *args, **kwargs): cls_mapobject.add_method('objectGroup', retval('Tiled::ObjectGroup*',reference_existing_object=True), []) cls_mapobject.add_method('rotation', 'double', []) cls_mapobject.add_method('setRotation', None, [('double','r')]) +# BONGO +cls_mapobject.add_method('opacity', 'double', []) +cls_mapobject.add_method('setOpacity', None, [('double','opacity')]) cls_mapobject.add_method('isVisible', 'bool', []) cls_mapobject.add_method('setVisible', None, [('bool','v')]) cls_mapobject.add_method('name', 'QString', []) diff --git a/src/tiled/editablemapobject.cpp b/src/tiled/editablemapobject.cpp index 23e67ec53f..4a931a0fcf 100644 --- a/src/tiled/editablemapobject.cpp +++ b/src/tiled/editablemapobject.cpp @@ -190,6 +190,12 @@ void EditableMapObject::setRotation(qreal rotation) setMapObjectProperty(MapObject::RotationProperty, rotation); } +// BONGO +void EditableMapObject::setOpacity(qreal opacity) +{ + setMapObjectProperty(MapObject::OpacityProperty, opacity); +} + void EditableMapObject::setVisible(bool visible) { setMapObjectProperty(MapObject::VisibleProperty, visible); diff --git a/src/tiled/editablemapobject.h b/src/tiled/editablemapobject.h index a43b971f1f..080ad1ee46 100644 --- a/src/tiled/editablemapobject.h +++ b/src/tiled/editablemapobject.h @@ -63,6 +63,8 @@ class EditableMapObject : public EditableObject Q_PROPERTY(qreal height READ height WRITE setHeight) Q_PROPERTY(QSizeF size READ size WRITE setSize) Q_PROPERTY(qreal rotation READ rotation WRITE setRotation) + // BONGO + Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity) Q_PROPERTY(bool visible READ isVisible WRITE setVisible) Q_PROPERTY(QJSValue polygon READ polygon WRITE setPolygon) Q_PROPERTY(QString text READ text WRITE setText) @@ -114,6 +116,8 @@ class EditableMapObject : public EditableObject qreal height() const; QSizeF size() const; qreal rotation() const; + // BONGO + qreal opacity() const; bool isVisible() const; QJSValue polygon() const; QString text() const; @@ -149,6 +153,8 @@ public slots: void setHeight(qreal height); void setSize(QSizeF size); void setRotation(qreal rotation); + // BONGO + void setOpacity(qreal opacity); void setVisible(bool visible); void setPolygon(QJSValue polygon); void setPolygon(const QPolygonF &polygon); @@ -219,6 +225,12 @@ inline qreal EditableMapObject::rotation() const return mapObject()->rotation(); } +// BONGO +inline qreal EditableMapObject::opacity() const +{ + return mapObject()->opacity(); +} + inline bool EditableMapObject::isVisible() const { return mapObject()->isVisible(); diff --git a/src/tiled/mapobjectitem.cpp b/src/tiled/mapobjectitem.cpp index 70c679fecb..173fb4e293 100644 --- a/src/tiled/mapobjectitem.cpp +++ b/src/tiled/mapobjectitem.cpp @@ -89,6 +89,8 @@ void MapObjectItem::syncWithMapObject() setPos(pixelPos); setRotation(mObject->rotation()); + // BONGO + setOpacity(mObject->opacity()); if (mBoundingRect != bounds) { // Notify the graphics scene about the geometry change in advance diff --git a/src/tiled/objectselectionitem.cpp b/src/tiled/objectselectionitem.cpp index 572e6650d2..1cfeeafe57 100644 --- a/src/tiled/objectselectionitem.cpp +++ b/src/tiled/objectselectionitem.cpp @@ -110,6 +110,8 @@ void MapObjectOutline::syncWithMapObject(const MapRenderer &renderer) setPos(pixelPos); setRotation(mObject->rotation()); + // BONGO + setOpacity(mObject->opacity()); setFlag(QGraphicsItem::ItemIgnoresTransformations, mObject->shape() == MapObject::Point); diff --git a/src/tiled/objectselectiontool.cpp b/src/tiled/objectselectiontool.cpp index 758eb7a113..a778639a30 100644 --- a/src/tiled/objectselectiontool.cpp +++ b/src/tiled/objectselectiontool.cpp @@ -1657,7 +1657,9 @@ void ObjectSelectionTool::saveSelectionState() mapObject->position(), mapObject->size(), mapObject->polygon(), - mapObject->rotation() + mapObject->rotation(), + // BONGO + mapObject->opacity() }; mMovingObjects.append(object); } diff --git a/src/tiled/objectselectiontool.h b/src/tiled/objectselectiontool.h index 6b01a4b66a..4cd9e739c6 100644 --- a/src/tiled/objectselectiontool.h +++ b/src/tiled/objectselectiontool.h @@ -167,6 +167,8 @@ class ObjectSelectionTool : public AbstractObjectTool QSizeF oldSize; QPolygonF oldPolygon; qreal oldRotation; + // BONGO + qreal oldOpacity; }; QVector mMovingObjects; diff --git a/src/tiled/propertybrowser.cpp b/src/tiled/propertybrowser.cpp index 511a33eee1..4fa085faa7 100644 --- a/src/tiled/propertybrowser.cpp +++ b/src/tiled/propertybrowser.cpp @@ -845,6 +845,12 @@ void PropertyBrowser::addMapObjectProperties() tr("Flipping"), groupProperty); flippingProperty->setAttribute(QLatin1String("flagNames"), mFlippingFlagNames); + + // BONGO + QtVariantProperty *opacityProperty = addProperty(OpacityProperty, QMetaType::Double, tr("Opacity"), groupProperty); + opacityProperty->setAttribute(QLatin1String("minimum"), 0.0); + opacityProperty->setAttribute(QLatin1String("maximum"), 1.0); + opacityProperty->setAttribute(QLatin1String("singleStep"), 0.1); } if (mMapObjectFlags & ObjectIsText) { @@ -1296,6 +1302,13 @@ QUndoCommand *PropertyBrowser::applyMapObjectValueTo(PropertyId id, const QVaria val.toDouble()); } break; + // BONGO + case OpacityProperty:{ + command = new ChangeMapObject(mDocument, mapObject, + MapObject::OpacityProperty, + val.toReal()); + break; + } case FlippingProperty: { const int flippingFlags = val.toInt(); @@ -1913,6 +1926,8 @@ void PropertyBrowser::updateProperties() if (mapObject->cell().flippedVertically()) flippingFlags |= 2; mIdToProperty[FlippingProperty]->setValue(flippingFlags); + // BONGO + mIdToProperty[OpacityProperty]->setValue(mapObject->opacity()); } if (flags & ObjectIsText) { diff --git a/src/tmxviewer/tmxviewer.cpp b/src/tmxviewer/tmxviewer.cpp index e00ea748ef..52065f6427 100644 --- a/src/tmxviewer/tmxviewer.cpp +++ b/src/tmxviewer/tmxviewer.cpp @@ -65,6 +65,8 @@ class MapObjectItem : public QGraphicsItem setPos(pixelPos); setRotation(mapObject->rotation()); + // BONGO + setOpacity(mapObject->opacity()); } QRectF boundingRect() const override