-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 01/05/2010 12:39 AM, jb wrote: > On Monday 04 January 2010 22:51:56 Till Theato wrote: >> Rotation on all axes adds the possibility to "integrate" a title into >> the video. You can make it look like the text was written on a object in >> the video. >> >> Might this be worth advancing the syntax of kdenlive titles so it can >> represent rotation? > > Hi! > > Sure, the kdenlive title syntax must be updated to support new features. > But you must be aware of one important issue in the design of the titler > module: > > Kdenlive produces xml data, and then, the MLT kdenlivetitle producer (in > modules/qimage) creates a QGraphicsScene and loads the xml into it. > > The big problem is that using a QGraphicsScene like that in an MLT module is > not really supported by Qt. > > You are supposed to have a full Qt QApplication to use a QGraphicsScene, but > when MLT is used inside Kdenlive, we cannot create a new QApplication because > MLT is running in a thread of Kdenlive. > > So we re-use the QApplication from Kdenlive, but it is in a different thread > and that leads to some issues, for example using QPixmap crashes the MLT > kdenlivetitle producer... > > so before going too far, I think you should first try to check that the > features you want to implement work inside the MLT kdenlivetitle producer...
Thanks for your background information! The attached patch works without changes on the MLT side. It should basically work, but there are some problems i wasn't able to fix: Resizing rotated items with the mouse doesn't work very well. When loading a title, the zoom of rotated items is wrong. Help is welcome. I'm not sure what is done in TitleWidget::slotValueChanged as it only applies to images. Could someone please explain the calculations and their meaning to me? regards ttill -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAktHeIYACgkQzwEyz7QP6nTb3QCfUvR/YPNYRjTtbwNQxlkW4J/U XzUAnRpaiSjmubo5LP6QZpBCRmXDyuFe =0VUt -----END PGP SIGNATURE-----
Index: src/widgets/titlewidget_ui.ui =================================================================== --- src/widgets/titlewidget_ui.ui (revision 4218) +++ src/widgets/titlewidget_ui.ui (working copy) @@ -248,11 +248,25 @@ <item row="3" column="0"> <widget class="QLabel" name="label_15"> <property name="text"> - <string>Rotate:</string> + <string>Rotate X:</string> </property> </widget> </item> - <item row="4" column="0" colspan="2"> + <item row="4" column="0"> + <widget class="QLabel" name="label_20"> + <property name="text"> + <string>Rotate Y:</string> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="label_21"> + <property name="text"> + <string>Rotate Z:</string> + </property> + </widget> + </item> + <item row="6" column="0" colspan="2"> <layout class="QGridLayout" name="gridLayout_3"> <item row="0" column="0"> <widget class="QToolButton" name="itemleft"> @@ -311,7 +325,7 @@ </item> </layout> </item> - <item row="5" column="0" colspan="2"> + <item row="7" column="0" colspan="2"> <widget class="QFrame" name="effect_frame"> <property name="frameShape"> <enum>QFrame::StyledPanel</enum> @@ -492,7 +506,7 @@ </layout> </widget> </item> - <item row="6" column="0" colspan="2"> + <item row="8" column="0" colspan="2"> <widget class="QTabWidget" name="tabWidget"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> @@ -646,8 +660,14 @@ </widget> </item> <item row="3" column="1"> - <widget class="KoSliderCombo" name="itemrotate"/> + <widget class="KoSliderCombo" name="itemrotatex"/> </item> + <item row="4" column="1"> + <widget class="KoSliderCombo" name="itemrotatey"/> + </item> + <item row="5" column="1"> + <widget class="KoSliderCombo" name="itemrotatez"/> + </item> </layout> </widget> </widget> Index: src/titlewidget.cpp =================================================================== --- src/titlewidget.cpp (revision 4218) +++ src/titlewidget.cpp (working copy) @@ -97,11 +97,23 @@ backgroundAlpha->setValue(0); backgroundAlpha->setToolTip(i18n("Background color opacity")); - itemrotate->setMinimum(-360); - itemrotate->setMaximum(360); - itemrotate->setDecimals(0); - itemrotate->setValue(0); - itemrotate->setToolTip(i18n("Rotation")); + itemrotatex->setMinimum(-360); + itemrotatex->setMaximum(360); + itemrotatex->setDecimals(0); + itemrotatex->setValue(0); + itemrotatex->setToolTip(i18n("Rotation around the X axis")); + + itemrotatey->setMinimum(-360); + itemrotatey->setMaximum(360); + itemrotatey->setDecimals(0); + itemrotatey->setValue(0); + itemrotatey->setToolTip(i18n("Rotation around the Y axis")); + + itemrotatez->setMinimum(-360); + itemrotatez->setMaximum(360); + itemrotatez->setDecimals(0); + itemrotatez->setValue(0); + itemrotatez->setToolTip(i18n("Rotation around the Z axis")); rectBAlpha->setMinimum(0); rectBAlpha->setMaximum(255); @@ -164,7 +176,9 @@ connect(zValue, SIGNAL(valueChanged(int)), this, SLOT(zIndexChanged(int))); connect(itemzoom, SIGNAL(valueChanged(int)), this, SLOT(itemScaled(int))); - connect(itemrotate, SIGNAL(valueChanged(qreal, bool)), this, SLOT(itemRotate(qreal))); + connect(itemrotatex, SIGNAL(valueChanged(qreal, bool)), this, SLOT(itemRotateX(qreal))); + connect(itemrotatey, SIGNAL(valueChanged(qreal, bool)), this, SLOT(itemRotateY(qreal))); + connect(itemrotatez, SIGNAL(valueChanged(qreal, bool)), this, SLOT(itemRotateZ(qreal))); connect(itemhcenter, SIGNAL(clicked()), this, SLOT(itemHCenter())); connect(itemvcenter, SIGNAL(clicked()), this, SLOT(itemVCenter())); connect(itemtop, SIGNAL(clicked()), this, SLOT(itemTop())); @@ -772,7 +786,9 @@ value_w->blockSignals(true); value_h->blockSignals(true); itemzoom->blockSignals(true); - itemrotate->blockSignals(true); + itemrotatex->blockSignals(true); + itemrotatey->blockSignals(true); + itemrotatez->blockSignals(true); if (l.size() == 0) { effect_stack->setHidden(true); effect_frame->setEnabled(false); @@ -789,17 +805,23 @@ if (blockX) origin_x_left->blockSignals(false); if (blockY) origin_y_top->blockSignals(false); itemzoom->setEnabled(false); - itemrotate->setEnabled(false); + itemrotatex->setEnabled(false); + itemrotatey->setEnabled(false); + itemrotatez->setEnabled(false); frame_properties->setEnabled(false); } else if (l.size() == 1) { effect_frame->setEnabled(true); frame_properties->setEnabled(true); if (l.at(0) != m_startViewport && l.at(0) != m_endViewport) { itemzoom->setEnabled(true); - itemrotate->setEnabled(true); + itemrotatex->setEnabled(true); + itemrotatey->setEnabled(true); + itemrotatez->setEnabled(true); } else { itemzoom->setEnabled(false); - itemrotate->setEnabled(false); + itemrotatex->setEnabled(false); + itemrotatey->setEnabled(false); + itemrotatez->setEnabled(false); updateInfoText(); } if (l.at(0)->type() == TEXTITEM) { @@ -965,13 +987,17 @@ } zValue->setValue((int)l.at(0)->zValue()); itemzoom->setValue((int)(m_transformations.value(l.at(0)).scalex * 100.0 + 0.5)); - itemrotate->setValue((int)(m_transformations.value(l.at(0)).rotate)); + itemrotatex->setValue((int)(m_transformations.value(l.at(0)).rotatex)); + itemrotatey->setValue((int)(m_transformations.value(l.at(0)).rotatey)); + itemrotatez->setValue((int)(m_transformations.value(l.at(0)).rotatez)); value_x->blockSignals(false); value_y->blockSignals(false); value_w->blockSignals(false); value_h->blockSignals(false); itemzoom->blockSignals(false); - itemrotate->blockSignals(false); + itemrotatex->blockSignals(false); + itemrotatey->blockSignals(false); + itemrotatez->blockSignals(false); } } @@ -995,7 +1021,8 @@ // Ratio width:height double phi = (double) i->boundingRect().width() / i->boundingRect().height(); - double alpha = (double) t.rotate / 180.0 * M_PI; + // TODO: proper calculation for rotation around 3 axes + double alpha = (double) t.rotatez / 180.0 * M_PI; // New length double length = val; @@ -1019,7 +1046,9 @@ t.scaley = scale; QTransform qtrans; qtrans.scale(scale, scale); - qtrans.rotate(t.rotate); + qtrans.rotate(t.rotatex, Qt::XAxis); + qtrans.rotate(t.rotatey, Qt::YAxis); + qtrans.rotate(t.rotatez, Qt::ZAxis); i->setTransform(qtrans); m_transformations[i] = t; @@ -1153,14 +1182,20 @@ void TitleWidget::updateRotZoom(QGraphicsItem *i) { itemzoom->blockSignals(true); - itemrotate->blockSignals(false); + itemrotatex->blockSignals(true); + itemrotatey->blockSignals(true); + itemrotatez->blockSignals(true); Transform t = m_transformations.value(i); itemzoom->setValue((int)(t.scalex * 100.0 + 0.5)); - itemrotate->setValue((int)(t.rotate)); + itemrotatex->setValue((int)(t.rotatex)); + itemrotatey->setValue((int)(t.rotatey)); + itemrotatez->setValue((int)(t.rotatez)); itemzoom->blockSignals(false); - itemrotate->blockSignals(false); + itemrotatex->blockSignals(false); + itemrotatey->blockSignals(false); + itemrotatez->blockSignals(false); } /** \brief Updates the position of an item by reading coordinates from the text fields */ @@ -1444,22 +1479,54 @@ x.scaley = (double)val / 100.0; QTransform qtrans; qtrans.scale(x.scalex, x.scaley); - qtrans.rotate(x.rotate); + qtrans.rotate(x.rotatex, Qt::XAxis); + qtrans.rotate(x.rotatey, Qt::YAxis); + qtrans.rotate(x.rotatez, Qt::ZAxis); l[0]->setTransform(qtrans); m_transformations[l.at(0)] = x; updateDimension(l.at(0)); } } -void TitleWidget::itemRotate(qreal val) +void TitleWidget::itemRotateX(qreal val) { + itemRotate(val, 0); +} + +void TitleWidget::itemRotateY(qreal val) +{ + itemRotate(val, 1); +} + +void TitleWidget::itemRotateZ(qreal val) +{ + itemRotate(val, 2); +} + +void TitleWidget::itemRotate(qreal val, int axis) +{ QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems(); if (l.size() == 1) { Transform x = m_transformations[l.at(0)]; - x.rotate = val; + switch(axis) { + case 0: + x.rotatex = val; + break; + case 1: + x.rotatey = val; + break; + case 2: + x.rotatez = val; + break; + } + + l[0]->setData(103, QList<QVariant>() << QVariant(x.rotatex) << QVariant(x.rotatey) << QVariant(x.rotatez)); + QTransform qtrans; qtrans.scale(x.scalex, x.scaley); - qtrans.rotate(x.rotate); + qtrans.rotate(x.rotatex, Qt::XAxis); + qtrans.rotate(x.rotatey, Qt::YAxis); + qtrans.rotate(x.rotatez, Qt::ZAxis); l[0]->setTransform(qtrans); m_transformations[l.at(0)] = x; updateDimension(l.at(0)); @@ -1669,7 +1736,29 @@ Transform x; x.scalex = t.m11(); x.scaley = t.m22(); - x.rotate = 180. / PI * atan2(-t.m21(), t.m11()); + if(!items.at(i)->data(103).isNull()) { + QList<QVariant> rotlist = items.at(i)->data(103).toList(); + if(rotlist.count() >= 3) { + x.rotatex = rotlist[0].toDouble(); + x.rotatey = rotlist[1].toDouble(); + x.rotatez = rotlist[2].toDouble(); + + // Try to adjust zoom + t.rotate(x.rotatex * (-1), Qt::XAxis); + t.rotate(x.rotatey * (-1), Qt::YAxis); + t.rotate(x.rotatez * (-1), Qt::ZAxis); + x.scalex = t.m11(); + x.scaley = t.m22(); + } else { + x.rotatex = 0; + x.rotatey = 0; + x.rotatez = 0; + } + } else { + x.rotatex = 0; + x.rotatey = 0; + x.rotatez = 180. / PI * atan2(-t.m21(), t.m11()); + } m_transformations[items.at(i)] = x; } // mbd: Update the GUI color selectors to match the stuff from the loaded document @@ -1793,7 +1882,9 @@ } align_box->setEnabled(anim); itemzoom->setEnabled(!anim); - itemrotate->setEnabled(!anim); + itemrotatex->setEnabled(!anim); + itemrotatey->setEnabled(!anim); + itemrotatez->setEnabled(!anim); frame_toolbar->setEnabled(!anim); toolbar_stack->setEnabled(!anim); if (anim) { @@ -1833,7 +1924,9 @@ } align_box->setEnabled(anim); itemzoom->setEnabled(!anim); - itemrotate->setEnabled(!anim); + itemrotatex->setEnabled(!anim); + itemrotatey->setEnabled(!anim); + itemrotatez->setEnabled(!anim); frame_toolbar->setEnabled(!anim); toolbar_stack->setEnabled(!anim); if (anim) { Index: src/titledocument.cpp =================================================================== --- src/titledocument.cpp (revision 4218) +++ src/titledocument.cpp (working copy) @@ -131,6 +131,10 @@ pos.setAttribute("y", item->pos().y()); QTransform transform = item->transform(); QDomElement tr = doc.createElement("transform"); + if(!item->data(103).isNull()) { + QList<QVariant> rotlist = item->data(103).toList(); + tr.setAttribute("rotation", QString("%1,%2,%3").arg(rotlist[0].toDouble()).arg(rotlist[1].toDouble()).arg(rotlist[2].toDouble())); + } tr.appendChild(doc.createTextNode( QString("%1,%2,%3,%4,%5,%6,%7,%8,%9").arg( transform.m11()).arg(transform.m12()).arg(transform.m13()).arg(transform.m21()).arg(transform.m22()).arg(transform.m23()).arg(transform.m31()).arg(transform.m32()).arg(transform.m33()) @@ -347,6 +351,7 @@ items.item(i).namedItem("position").attributes().namedItem("y").nodeValue().toDouble()); gitem->setPos(p); gitem->setTransform(stringToTransform(items.item(i).namedItem("position").firstChild().firstChild().nodeValue())); + gitem->setData(103, stringToList(items.item(i).namedItem("position").firstChild().attributes().namedItem("rotation").nodeValue())); int zValue = items.item(i).attributes().namedItem("z-index").nodeValue().toInt(); if (zValue > maxZValue) maxZValue = zValue; gitem->setZValue(zValue); @@ -428,6 +433,7 @@ return QColor(); return QColor(l.at(0).toInt(), l.at(1).toInt(), l.at(2).toInt(), l.at(3).toInt());; } + QTransform TitleDocument::stringToTransform(const QString& s) { QStringList l = s.split(','); @@ -440,6 +446,14 @@ ); } +QList<QVariant> TitleDocument::stringToList(const QString & s) +{ + QStringList l = s.split(','); + if(l.size() < 3) + return QList<QVariant>(); + return QList<QVariant>() << QVariant(l.at(0).toDouble()) << QVariant(l.at(1).toDouble()) << QVariant(l.at(2).toDouble()); +} + int TitleDocument::frameWidth() const { return m_width; Index: src/titlewidget.h =================================================================== --- src/titlewidget.h (revision 4218) +++ src/titlewidget.h (working copy) @@ -36,10 +36,12 @@ Transform() { scalex = 1.0; scaley = 1.0; - rotate = 0.0; + rotatex = 0.0; + rotatey = 0.0; + rotatez = 0.0; } double scalex, scaley; - double rotate; + double rotatex, rotatey, rotatez; }; class TitleWidget : public QDialog , public Ui::TitleWidget_UI @@ -163,6 +165,8 @@ qreal maxZIndex(); qreal zIndexBounds(bool maxBound); + + void itemRotate(qreal val, int axis); public slots: void slotNewText(QGraphicsTextItem *tt); @@ -173,7 +177,9 @@ void setupViewports(); void zIndexChanged(int); void itemScaled(int); - void itemRotate(qreal); + void itemRotateX(qreal); + void itemRotateY(qreal); + void itemRotateZ(qreal); void saveTitle(KUrl url = KUrl()); void loadTitle(KUrl url = KUrl()); Index: src/titledocument.h =================================================================== --- src/titledocument.h (revision 4218) +++ src/titledocument.h (working copy) @@ -51,6 +51,7 @@ QRectF stringToRect(const QString &); QColor stringToColor(const QString &); QTransform stringToTransform(const QString &); + QList<QVariant> stringToList(const QString &); }; #endif
------------------------------------------------------------------------------ This SF.Net email is sponsored by the Verizon Developer Community Take advantage of Verizon's best-in-class app development support A streamlined, 14 day to market process makes app distribution fast and easy Join now and get one step closer to millions of Verizon customers http://p.sf.net/sfu/verizon-dev2dev
_______________________________________________ Kdenlive-devel mailing list Kdenlive-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kdenlive-devel