From: Jean-Baptiste Mardelle Date: Tue, 22 Feb 2011 19:37:09 +0000 (+0000) Subject: Keyframable rotation for affine transition X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=f53571700a2b48f5322432f5f896f5ab36b23ab9;p=kdenlive Keyframable rotation for affine transition svn path=/trunk/kdenlive/; revision=5453 --- diff --git a/src/effectstackedit.cpp b/src/effectstackedit.cpp index e3f86ea1..24bc2275 100644 --- a/src/effectstackedit.cpp +++ b/src/effectstackedit.cpp @@ -78,7 +78,8 @@ EffectStackEdit::EffectStackEdit(Monitor *monitor, QWidget *parent) : m_out(0), m_frameSize(QPoint()), m_keyframeEditor(NULL), - m_monitor(monitor) + m_monitor(monitor), + m_geometryWidget(NULL) { m_baseWidget = new QWidget(this); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); @@ -126,8 +127,7 @@ void EffectStackEdit::setFrameSize(QPoint p) break; } else { - GeometryWidget *geom = ((GeometryWidget*)m_valueItems[paramName+"geometry"]); - geom->setFrameSize(m_frameSize); + if (m_geometryWidget) m_geometryWidget->setFrameSize(m_frameSize); break; } } @@ -148,8 +148,7 @@ void EffectStackEdit::updateTimecodeFormat() if (type == "geometry") { if (KdenliveSettings::on_monitor_effects()) { - GeometryWidget *geom = (GeometryWidget*)m_valueItems[paramName+"geometry"]; - geom->updateTimecodeFormat(); + if (m_geometryWidget) m_geometryWidget->updateTimecodeFormat(); } else { Geometryval *geom = ((Geometryval*)m_valueItems[paramName+"geometry"]); geom->updateTimecodeFormat(); @@ -330,21 +329,21 @@ void EffectStackEdit::transferParamDesc(const QDomElement d, int pos, int in, in connect(pl, SIGNAL(parameterChanged()), this, SLOT(collectAllParameters())); } else if (type == "geometry") { if (KdenliveSettings::on_monitor_effects()) { - GeometryWidget *geometry = new GeometryWidget(m_monitor, m_timecode, pos, isEffect, this); - geometry->setFrameSize(m_frameSize); - geometry->slotShowScene(!disable); + m_geometryWidget = new GeometryWidget(m_monitor, m_timecode, pos, isEffect, m_params.hasAttribute("showrotation"), this); + m_geometryWidget->setFrameSize(m_frameSize); + m_geometryWidget->slotShowScene(!disable); // connect this before setupParam to make sure the monitor scene shows up at startup - connect(geometry, SIGNAL(checkMonitorPosition(int)), this, SIGNAL(checkMonitorPosition(int))); - connect(geometry, SIGNAL(parameterChanged()), this, SLOT(collectAllParameters())); + connect(m_geometryWidget, SIGNAL(checkMonitorPosition(int)), this, SIGNAL(checkMonitorPosition(int))); + connect(m_geometryWidget, SIGNAL(parameterChanged()), this, SLOT(collectAllParameters())); if (minFrame == maxFrame) - geometry->setupParam(pa, m_in, m_out); + m_geometryWidget->setupParam(pa, m_in, m_out); else - geometry->setupParam(pa, minFrame, maxFrame); - m_vbox->addWidget(geometry); - m_valueItems[paramName+"geometry"] = geometry; - connect(geometry, SIGNAL(seekToPos(int)), this, SIGNAL(seekTimeline(int))); - connect(this, SIGNAL(syncEffectsPos(int)), geometry, SLOT(slotSyncPosition(int))); - connect(this, SIGNAL(effectStateChanged(bool)), geometry, SLOT(slotShowScene(bool))); + m_geometryWidget->setupParam(pa, minFrame, maxFrame); + m_vbox->addWidget(m_geometryWidget); + m_valueItems[paramName+"geometry"] = m_geometryWidget; + connect(m_geometryWidget, SIGNAL(seekToPos(int)), this, SIGNAL(seekTimeline(int))); + connect(this, SIGNAL(syncEffectsPos(int)), m_geometryWidget, SLOT(slotSyncPosition(int))); + connect(this, SIGNAL(effectStateChanged(bool)), m_geometryWidget, SLOT(slotShowScene(bool))); } else { Geometryval *geo = new Geometryval(m_profile, m_timecode, m_frameSize, pos); if (minFrame == maxFrame) @@ -357,6 +356,9 @@ void EffectStackEdit::transferParamDesc(const QDomElement d, int pos, int in, in connect(geo, SIGNAL(seekToPos(int)), this, SIGNAL(seekTimeline(int))); connect(this, SIGNAL(syncEffectsPos(int)), geo, SLOT(slotSyncPosition(int))); } + } else if (type == "addedgeometry") { + // this is a parameter that should be linked to the geometry widget, for example rotation, shear, ... + if (m_geometryWidget) m_geometryWidget->addParameter(pa); } else if (type == "keyframe" || type == "simplekeyframe") { // keyframe editor widget if (m_keyframeEditor == NULL) { @@ -653,7 +655,7 @@ void EffectStackEdit::collectAllParameters() paramName.append("geometry"); else if (type == "keyframe") paramName.append("keyframe"); - if (type != "simplekeyframe" && !m_valueItems.contains(paramName)) { + if (type != "simplekeyframe" && type != "fixed" && type != "addedgeometry" && !m_valueItems.contains(paramName)) { kDebug() << "// Param: " << paramName << " NOT FOUND"; continue; } @@ -676,12 +678,13 @@ void EffectStackEdit::collectAllParameters() namenode.item(i) = complex->getParamDesc(); } else if (type == "geometry") { if (KdenliveSettings::on_monitor_effects()) { - GeometryWidget *geometry = ((GeometryWidget*)m_valueItems.value(paramName)); - namenode.item(i).toElement().setAttribute("value", geometry->getValue()); + if (m_geometryWidget) namenode.item(i).toElement().setAttribute("value", m_geometryWidget->getValue()); } else { Geometryval *geom = ((Geometryval*)m_valueItems.value(paramName)); namenode.item(i).toElement().setAttribute("value", geom->getValue()); } + } else if (type == "addedgeometry") { + namenode.item(i).toElement().setAttribute("value", m_geometryWidget->getExtraValue(namenode.item(i).toElement().attribute("name"))); } else if (type == "position") { PositionEdit *pedit = ((PositionEdit*)m_valueItems.value(paramName)); int pos = pedit->getPosition(); @@ -808,6 +811,7 @@ void EffectStackEdit::clearAllItems() if (wid) delete wid; } m_keyframeEditor = NULL; + m_geometryWidget = NULL; blockSignals(false); } diff --git a/src/effectstackedit.h b/src/effectstackedit.h index 012faf66..3fbd7041 100644 --- a/src/effectstackedit.h +++ b/src/effectstackedit.h @@ -40,6 +40,7 @@ struct wipeInfo { class QFrame; class Monitor; +class GeometryWidget; class EffectStackEdit : public QScrollArea { @@ -80,6 +81,7 @@ private: QPoint m_frameSize; KeyframeEdit *m_keyframeEditor; Monitor *m_monitor; + GeometryWidget *m_geometryWidget; public slots: /** @brief Called when an effect is selected, builds the UI for this effect. */ diff --git a/src/geometrywidget.cpp b/src/geometrywidget.cpp index f0d566ce..350d273a 100644 --- a/src/geometrywidget.cpp +++ b/src/geometrywidget.cpp @@ -37,7 +37,7 @@ -GeometryWidget::GeometryWidget(Monitor* monitor, Timecode timecode, int clipPos, bool isEffect, QWidget* parent): +GeometryWidget::GeometryWidget(Monitor* monitor, Timecode timecode, int clipPos, bool isEffect, bool showRotation, QWidget* parent): QWidget(parent), m_monitor(monitor), m_timePos(new TimecodeDisplay(timecode)), @@ -48,7 +48,8 @@ GeometryWidget::GeometryWidget(Monitor* monitor, Timecode timecode, int clipPos, m_rect(NULL), m_previous(NULL), m_geometry(NULL), - m_showScene(true) + m_showScene(true), + m_showRotation(showRotation) { m_ui.setupUi(this); setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Maximum); @@ -91,43 +92,22 @@ GeometryWidget::GeometryWidget(Monitor* monitor, Timecode timecode, int clipPos, connect(m_ui.buttonAddDelete, SIGNAL(clicked()), this, SLOT(slotAddDeleteKeyframe())); connect(m_ui.buttonSync, SIGNAL(toggled(bool)), this, SLOT(slotSetSynchronize(bool))); - m_spinX = new DragValue(i18n("X"), 0, 0, -1, QString(), false, this); + m_spinX = new DragValue(i18nc("x axis position", "X"), 0, 0, -1, QString(), false, this); m_spinX->setRange(-99000, 99000); m_ui.horizontalLayout->addWidget(m_spinX); - m_spinY = new DragValue(i18n("Y"), 0, 0, -1, QString(), false, this); + m_spinY = new DragValue(i18nc("y axis position", "Y"), 0, 0, -1, QString(), false, this); m_spinY->setRange(-99000, 99000); m_ui.horizontalLayout->addWidget(m_spinY); - m_spinWidth = new DragValue(i18n("W"), m_monitor->render->frameRenderWidth(), 0, -1, QString(), false, this); + m_spinWidth = new DragValue(i18nc("Frame width", "W"), m_monitor->render->frameRenderWidth(), 0, -1, QString(), false, this); m_spinWidth->setRange(1, 99000); m_ui.horizontalLayout->addWidget(m_spinWidth); - m_spinHeight = new DragValue(i18n("H"), m_monitor->render->renderHeight(), 0, -1, QString(), false, this); + m_spinHeight = new DragValue(i18nc("Frame height", "H"), m_monitor->render->renderHeight(), 0, -1, QString(), false, this); m_spinHeight->setRange(1, 99000); m_ui.horizontalLayout->addWidget(m_spinHeight); - m_ui.horizontalLayout->addStretch(10); - - m_spinSize = new DragValue(i18n("Size"), 100, 2, -1, i18n("%"), false, this); - m_spinSize->setRange(1, 99000); - m_ui.horizontalLayout2->addWidget(m_spinSize); - - m_opacity = new DragValue(i18n("Opacity"), 100, 0, -1, i18n("%"), true, this); - m_ui.horizontalLayout2->addWidget(m_opacity); - - /* - Setup of geometry controls - */ - connect(m_spinX, SIGNAL(valueChanged(int)), this, SLOT(slotSetX(int))); - connect(m_spinY, SIGNAL(valueChanged(int)), this, SLOT(slotSetY(int))); - connect(m_spinWidth, SIGNAL(valueChanged(int)), this, SLOT(slotSetWidth(int))); - connect(m_spinHeight, SIGNAL(valueChanged(int)), this, SLOT(slotSetHeight(int))); - - connect(m_spinSize, SIGNAL(valueChanged(double)), this, SLOT(slotResize(double))); - - connect(m_opacity, SIGNAL(valueChanged(int)), this, SLOT(slotSetOpacity(int))); - QMenu *menu = new QMenu(this); QAction *adjustSize = new QAction(i18n("Adjust to original size"), this); connect(adjustSize, SIGNAL(triggered()), this, SLOT(slotAdjustToFrameSize())); @@ -151,7 +131,7 @@ GeometryWidget::GeometryWidget(Monitor* monitor, Timecode timecode, int clipPos, menu->addAction(alignright); QAction *aligntop = new QAction(KIcon("kdenlive-align-top"), i18n("Align top"), this); connect(aligntop, SIGNAL(triggered()), this, SLOT(slotMoveTop())); - menu->addAction(aligntop); + menu->addAction(aligntop); QAction *alignvcenter = new QAction(KIcon("kdenlive-align-vert"), i18n("Center vertically"), this); connect(alignvcenter, SIGNAL(triggered()), this, SLOT(slotCenterV())); menu->addAction(alignvcenter); @@ -160,6 +140,80 @@ GeometryWidget::GeometryWidget(Monitor* monitor, Timecode timecode, int clipPos, menu->addAction(alignbottom); m_ui.buttonOptions->setMenu(menu); + QHBoxLayout *alignLayout = new QHBoxLayout; + alignLayout->setSpacing(0); + QToolButton *alignButton = new QToolButton; + alignButton->setDefaultAction(alignleft); + alignButton->setAutoRaise(true); + alignLayout->addWidget(alignButton); + + alignButton = new QToolButton; + alignButton->setDefaultAction(alignhcenter); + alignButton->setAutoRaise(true); + alignLayout->addWidget(alignButton); + + alignButton = new QToolButton; + alignButton->setDefaultAction(alignright); + alignButton->setAutoRaise(true); + alignLayout->addWidget(alignButton); + + alignButton = new QToolButton; + alignButton->setDefaultAction(aligntop); + alignButton->setAutoRaise(true); + alignLayout->addWidget(alignButton); + + alignButton = new QToolButton; + alignButton->setDefaultAction(alignvcenter); + alignButton->setAutoRaise(true); + alignLayout->addWidget(alignButton); + + alignButton = new QToolButton; + alignButton->setDefaultAction(alignbottom); + alignButton->setAutoRaise(true); + alignLayout->addWidget(alignButton); + + m_ui.horizontalLayout->addLayout(alignLayout); + m_ui.horizontalLayout->addStretch(10); + + m_spinSize = new DragValue(i18n("Size"), 100, 2, -1, i18n("%"), false, this); + m_spinSize->setRange(1, 99000); + m_ui.horizontalLayout2->addWidget(m_spinSize); + + m_opacity = new DragValue(i18n("Opacity"), 100, 0, -1, i18n("%"), true, this); + m_ui.horizontalLayout2->addWidget(m_opacity); + + + if (showRotation) { + m_rotateX = new DragValue(i18n("Rotate X"), 0, 0, -1, QString(), true, this); + m_rotateX->setRange(-1800, 1800); + m_rotateX->setObjectName("rotate_x"); + m_ui.horizontalLayout3->addWidget(m_rotateX); + m_rotateY = new DragValue(i18n("Rotate Y"), 0, 0, -1, QString(), true, this); + m_rotateY->setRange(-1800, 1800); + m_rotateY->setObjectName("rotate_y"); + m_ui.horizontalLayout3->addWidget(m_rotateY); + m_rotateZ = new DragValue(i18n("Rotate Z"), 0, 0, -1, QString(), true, this); + m_rotateZ->setRange(-1800, 1800); + m_rotateZ->setObjectName("rotate_z"); + m_ui.horizontalLayout3->addWidget(m_rotateZ); + connect(m_rotateX, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateGeometry())); + connect(m_rotateY, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateGeometry())); + connect(m_rotateZ, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateGeometry())); + } + + /* + Setup of geometry controls + */ + + connect(m_spinX, SIGNAL(valueChanged(int)), this, SLOT(slotSetX(int))); + connect(m_spinY, SIGNAL(valueChanged(int)), this, SLOT(slotSetY(int))); + connect(m_spinWidth, SIGNAL(valueChanged(int)), this, SLOT(slotSetWidth(int))); + connect(m_spinHeight, SIGNAL(valueChanged(int)), this, SLOT(slotSetHeight(int))); + + connect(m_spinSize, SIGNAL(valueChanged(double)), this, SLOT(slotResize(double))); + + connect(m_opacity, SIGNAL(valueChanged(int)), this, SLOT(slotSetOpacity(int))); + /*connect(m_ui.buttonMoveLeft, SIGNAL(clicked()), this, SLOT(slotMoveLeft())); connect(m_ui.buttonCenterH, SIGNAL(clicked()), this, SLOT(slotCenterH())); connect(m_ui.buttonMoveRight, SIGNAL(clicked()), this, SLOT(slotMoveRight())); @@ -193,6 +247,12 @@ GeometryWidget::~GeometryWidget() if (m_rect) delete m_rect; if (m_previous) delete m_previous; delete m_geometry; + m_extraGeometryNames.clear(); + m_extraFactors.clear(); + while (!m_extraGeometries.isEmpty()) { + Mlt::Geometry *g = m_extraGeometries.takeFirst(); + delete g; + } if (m_monitor) { m_monitor->getEffectEdit()->showVisibilityButton(false); m_monitor->slotEffectScene(false); @@ -215,6 +275,21 @@ QString GeometryWidget::getValue() const return m_geometry->serialise(); } +QString GeometryWidget::getExtraValue(const QString &name) const +{ + int ix = m_extraGeometryNames.indexOf(name); + QString val = m_extraGeometries.at(ix)->serialise(); + if (!val.contains("=")) val = val.section(',', 0, 0); + else { + QStringList list = val.split(';'); + val.clear(); + foreach (const QString value, list) { + val.append(value.section(',', 0, 0) + ';'); + } + } + return val; +} + void GeometryWidget::setupParam(const QDomElement elem, int minframe, int maxframe) { m_inPoint = minframe; @@ -255,6 +330,16 @@ void GeometryWidget::setupParam(const QDomElement elem, int minframe, int maxfra slotCheckMonitorPosition(m_monitor->render->seekFramePosition()); } +void GeometryWidget::addParameter(const QDomElement elem) +{ + Mlt::Geometry *geometry = new Mlt::Geometry(elem.attribute("value").toUtf8().data(), m_outPoint - m_inPoint, m_monitor->render->frameRenderWidth(), m_monitor->render->renderHeight()); + m_extraGeometries.append(geometry); + m_timeline->addGeometry(geometry); + m_extraFactors.append(elem.attribute("factor", "1")); + m_extraGeometryNames.append(elem.attribute("name")); + //kDebug()<<"ADDED PARAM: "<setValue(item.mix()); m_opacity->blockSignals(false); + for (int i = 0; i < m_extraGeometries.count(); i++) { + Mlt::Geometry *geom = m_extraGeometries.at(i); + QString name = m_extraGeometryNames.at(i); + if (!geom->fetch(&item, pos)) { + DragValue *widget = findChild(name); + if (widget) { + widget->blockSignals(true); + widget->setValue(item.x() * m_extraFactors.at(i).toInt()); + widget->blockSignals(false); + } + } + } + slotUpdateProperties(); if (seek && KdenliveSettings::transitionfollowcursor()) @@ -355,6 +453,18 @@ void GeometryWidget::slotAddKeyframe(int pos) item.mix(m_opacity->value()); m_geometry->insert(item); + for (int i = 0; i < m_extraGeometries.count(); i++) { + Mlt::Geometry *geom = m_extraGeometries.at(i); + QString name = m_extraGeometryNames.at(i); + DragValue *widget = findChild(name); + if (widget) { + Mlt::GeometryItem item2; + item2.frame(pos); + item2.x((double) widget->value() / m_extraFactors.at(i).toInt()); + geom->insert(item2); + } + } + m_timeline->update(); slotPositionChanged(pos, false); emit parameterChanged(); @@ -372,6 +482,11 @@ void GeometryWidget::slotDeleteKeyframe(int pos) } m_geometry->remove(pos); + for (int i = 0; i < m_extraGeometries.count(); i++) { + Mlt::Geometry *geom = m_extraGeometries.at(i); + geom->remove(pos); + } + m_timeline->update(); slotPositionChanged(pos, false); emit parameterChanged(); @@ -447,6 +562,18 @@ void GeometryWidget::slotUpdateGeometry() item.w(rectSize.width()); item.h(rectSize.height()); m_geometry->insert(item); + + for (int i = 0; i < m_extraGeometries.count(); i++) { + Mlt::Geometry *geom = m_extraGeometries.at(i); + QString name = m_extraGeometryNames.at(i); + Mlt::GeometryItem item2; + DragValue *widget = findChild(name); + if (widget && !geom->next_key(&item2, pos) && item2.frame() == pos) { + item2.x((double) widget->value() / m_extraFactors.at(i).toInt()); + geom->insert(item2); + } + } + emit parameterChanged(); } diff --git a/src/geometrywidget.h b/src/geometrywidget.h index ca9b995c..d5b43fa5 100644 --- a/src/geometrywidget.h +++ b/src/geometrywidget.h @@ -45,16 +45,20 @@ public: * @param timecode Timecode needed by timecode display widget * @param clipPos Position of the clip in timeline * @param isEffect true if used in an effect, false if used in a transition + * @param showRotation Should we show or hide the rotation sliders * @param parent (optional) Parent widget */ - GeometryWidget(Monitor *monitor, Timecode timecode, int clipPos, bool isEffect, QWidget* parent = 0); + GeometryWidget(Monitor *monitor, Timecode timecode, int clipPos, bool isEffect, bool showRotation, QWidget* parent = 0); virtual ~GeometryWidget(); /** @brief Gets the geometry as a serialized string. */ QString getValue() const; + QString getExtraValue(const QString &name) const; /** @brief Updates the timecode display according to settings (frame number or hh:mm:ss:ff) */ void updateTimecodeFormat(); /** @brief Sets the size of the original clip. */ void setFrameSize(QPoint size); + void addParameter(const QDomElement elem); + public slots: /** @brief Sets up the rect and the geometry object. * @param elem DomElement representing this effect parameter @@ -83,6 +87,9 @@ private: KeyframeHelper *m_timeline; /** Stores the different settings in the MLT geometry format. */ Mlt::Geometry *m_geometry; + QStringList m_extraGeometryNames; + QStringList m_extraFactors; + QList m_extraGeometries; bool m_showScene; DragValue *m_spinX; DragValue *m_spinY; @@ -90,7 +97,11 @@ private: DragValue *m_spinHeight; DragValue *m_spinSize; DragValue *m_opacity; + DragValue *m_rotateX; + DragValue *m_rotateY; + DragValue *m_rotateZ; QPoint m_frameSize; + bool m_showRotation; /** @brief Update monitor rect with current width / height values. */ void updateMonitorGeometry(); diff --git a/src/initeffects.cpp b/src/initeffects.cpp index d833e54e..ed27190a 100644 --- a/src/initeffects.cpp +++ b/src/initeffects.cpp @@ -772,7 +772,8 @@ void initEffects::fillTransitionsList(Mlt::Repository *repository, EffectsList * paramList.append(quickParameterFill(ret, i18n("Force Deinterlace Overlay"), "deinterlace", "bool", "0", "0", "1")); } else if (name == "affine") { tname.appendChild(ret.createTextNode(i18n("Affine"))); - paramList.append(quickParameterFill(ret, i18n("Rotate Y"), "rotate_y", "double", "0", "0", "360")); + ret.documentElement().setAttribute("showrotation", "1"); + /*paramList.append(quickParameterFill(ret, i18n("Rotate Y"), "rotate_y", "double", "0", "0", "360")); paramList.append(quickParameterFill(ret, i18n("Rotate X"), "rotate_x", "double", "0", "0", "360")); paramList.append(quickParameterFill(ret, i18n("Rotate Z"), "rotate_z", "double", "0", "0", "360")); paramList.append(quickParameterFill(ret, i18n("Fix Rotate Y"), "fix_rotate_y", "double", "0", "0", "360")); @@ -780,11 +781,23 @@ void initEffects::fillTransitionsList(Mlt::Repository *repository, EffectsList * paramList.append(quickParameterFill(ret, i18n("Fix Rotate Z"), "fix_rotate_z", "double", "0", "0", "360")); paramList.append(quickParameterFill(ret, i18n("Shear Y"), "shear_y", "double", "0", "0", "360")); paramList.append(quickParameterFill(ret, i18n("Shear X"), "shear_x", "double", "0", "0", "360")); - paramList.append(quickParameterFill(ret, i18n("Shear Z"), "shear_z", "double", "0", "0", "360")); + paramList.append(quickParameterFill(ret, i18n("Shear Z"), "shear_z", "double", "0", "0", "360"));*/ + /*paramList.append(quickParameterFill(ret, i18n("Fix Shear Y"), "fix_shear_y", "double", "0", "0", "360")); + paramList.append(quickParameterFill(ret, i18n("Fix Shear X"), "fix_shear_x", "double", "0", "0", "360")); + paramList.append(quickParameterFill(ret, i18n("Fix Shear Z"), "fix_shear_z", "double", "0", "0", "360"));*/ + + paramList.append(quickParameterFill(ret, "keyed", "keyed", "fixed", "1", "1", "1")); + paramList.append(quickParameterFill(ret, i18n("Geometry"), "geometry", "geometry", "0,0,100%,100%,100%", "0,0,100%,100%,100%", "0,0,100%,100%,100%", "", "", "", "", "", "true")); + + paramList.append(quickParameterFill(ret, i18n("Rotate X"), "rotate_x", "addedgeometry", "0", "-1800", "1800", QString(), QString(), "10")); + paramList.append(quickParameterFill(ret, i18n("Rotate Y"), "rotate_y", "addedgeometry", "0", "-1800", "1800", QString(), QString(), "10")); + paramList.append(quickParameterFill(ret, i18n("Rotate Z"), "rotate_z", "addedgeometry", "0", "-1800", "1800", QString(), QString(), "10")); + /*paramList.append(quickParameterFill(ret, i18n("Rotate Y"), "rotate_y", "simplekeyframe", "0", "-1800", "1800", QString(), QString(), "10")); + paramList.append(quickParameterFill(ret, i18n("Rotate Z"), "rotate_z", "simplekeyframe", "0", "-1800", "1800", QString(), QString(), "10"));*/ + paramList.append(quickParameterFill(ret, i18n("Fix Shear Y"), "fix_shear_y", "double", "0", "0", "360")); paramList.append(quickParameterFill(ret, i18n("Fix Shear X"), "fix_shear_x", "double", "0", "0", "360")); paramList.append(quickParameterFill(ret, i18n("Fix Shear Z"), "fix_shear_z", "double", "0", "0", "360")); - paramList.append(quickParameterFill(ret, i18n("Geometry"), "geometry", "geometry", "0,0,100%,100%,100%", "0,0,100%,100%,100%", "0,0,100%,100%,100%", "", "", "", "", "", "true")); } else if (name == "mix") { tname.appendChild(ret.createTextNode(i18n("Mix"))); } else if (name == "region") { diff --git a/src/keyframehelper.cpp b/src/keyframehelper.cpp index db326690..20c716e7 100644 --- a/src/keyframehelper.cpp +++ b/src/keyframehelper.cpp @@ -71,6 +71,20 @@ void KeyframeHelper::mousePressEvent(QMouseEvent * event) m_movingItem.h(item.h()); m_movingItem.mix(item.mix()); m_movingItem.frame(item.frame()); + + while (!m_extraMovingItems.isEmpty()) { + Mlt::GeometryItem *gitem = m_extraMovingItems.takeFirst(); + delete gitem; + } + for (int i = 0; i < m_extraGeometries.count(); i++) { + Mlt::GeometryItem *item2 = new Mlt::GeometryItem(); + if (m_extraGeometries.at(i)->next_key(item, mousePos) == 0) { + item2->x(item.x()); + item2->frame(item.frame()); + m_extraMovingItems.append(item2); + } + } + m_dragStart = event->pos(); m_movingKeyframe = true; return; @@ -114,10 +128,15 @@ void KeyframeHelper::mouseMoveEvent(QMouseEvent * event) if ((event->pos() - m_dragStart).manhattanLength() < QApplication::startDragDistance()) return; m_dragStart = QPoint(); m_geom->remove(m_movingItem.frame()); + for (int i = 0; i < m_extraGeometries.count(); i++) + m_extraGeometries[i]->remove(m_movingItem.frame()); } int pos = qBound(0, (int)(event->x() / m_scale), frameLength); if (KdenliveSettings::snaptopoints() && qAbs(pos - m_position) < 5) pos = m_position; m_movingItem.frame(pos); + for (int i = 0; i < m_extraMovingItems.count(); i++) { + m_extraMovingItems[i]->frame(pos); + } update(); return; } @@ -153,6 +172,11 @@ void KeyframeHelper::mouseReleaseEvent(QMouseEvent * event) if (m_movingKeyframe) { m_geom->insert(m_movingItem); m_movingKeyframe = false; + + for (int i = 0; i < m_extraGeometries.count(); i++) { + m_extraGeometries[i]->insert(m_extraMovingItems.at(i)); + } + emit keyframeMoved(m_position); return; } @@ -257,7 +281,16 @@ void KeyframeHelper::setKeyGeometry(Mlt::Geometry *geom, const int length) { m_geom = geom; frameLength = length; + while (!m_extraGeometries.isEmpty()) { + Mlt::Geometry *geom = m_extraGeometries.takeFirst(); + delete geom; + } update(); } +void KeyframeHelper::addGeometry(Mlt::Geometry *geom) +{ + m_extraGeometries.append(geom); +} + #include "keyframehelper.moc" diff --git a/src/keyframehelper.h b/src/keyframehelper.h index 8ddbcf27..6a01bae9 100644 --- a/src/keyframehelper.h +++ b/src/keyframehelper.h @@ -49,6 +49,7 @@ private: double m_scale; bool m_movingKeyframe; Mlt::GeometryItem m_movingItem; + QList m_extraMovingItems; QPoint m_dragStart; int m_lineHeight; bool m_drag; @@ -56,9 +57,11 @@ private: QColor m_selected; QColor m_keyframe; QColor m_keyframebg; + QList m_extraGeometries; public slots: void setKeyGeometry(Mlt::Geometry *geom, const int length); + void addGeometry(Mlt::Geometry *geom); void setValue(const int pos); signals: diff --git a/src/renderer.cpp b/src/renderer.cpp index 818797ab..5d3699d9 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -3573,8 +3573,8 @@ QMap Render::mltGetTransitionParamsFromXml(QDomElement xml) if (!e.attribute("value").isEmpty()) { map[name] = e.attribute("value"); } - if (!e.attribute("factor").isEmpty() && e.attribute("factor").toDouble() > 0) { - map[name] = QString::number(map[name].toDouble() / e.attribute("factor").toDouble()); + if (e.attribute("type") != "addedgeometry" && !e.attribute("factor").isEmpty() && e.attribute("factor").toDouble() > 0) { + map[name] = QString::number(map.value(name).toDouble() / e.attribute("factor").toDouble()); //map[name]=map[name].replace(".",","); //FIXME how to solve locale conversion of . , } diff --git a/src/widgets/geometrywidget_ui.ui b/src/widgets/geometrywidget_ui.ui index 0ada0601..026c2176 100644 --- a/src/widgets/geometrywidget_ui.ui +++ b/src/widgets/geometrywidget_ui.ui @@ -7,7 +7,7 @@ 0 0 133 - 78 + 85 @@ -135,6 +135,9 @@ + + +