From 551a8d38219bd1ccd96636b87df49264fa330c8c Mon Sep 17 00:00:00 2001 From: Till Theato Date: Sat, 8 Jan 2011 21:51:22 +0000 Subject: [PATCH] Make c0rners keyframable svn path=/trunk/kdenlive/; revision=5304 --- effects/frei0r_c0rners.xml | 46 ++--- src/cornerswidget.cpp | 218 +++++--------------- src/cornerswidget.h | 46 +---- src/effectstackedit.cpp | 46 +---- src/keyframeedit.cpp | 3 +- src/keyframeedit.h | 12 +- src/onmonitoritems/onmonitorcornersitem.cpp | 5 + src/widgets/keyframeeditor_ui.ui | 10 +- 8 files changed, 111 insertions(+), 275 deletions(-) diff --git a/effects/frei0r_c0rners.xml b/effects/frei0r_c0rners.xml index 07854667..175e69c1 100644 --- a/effects/frei0r_c0rners.xml +++ b/effects/frei0r_c0rners.xml @@ -4,56 +4,54 @@ Four corners geometry engine Marko Cebokli - - - Corners widget - - - + Corner 1 X - + Corner 1 Y - + Corner 2 X - + Corner 2 Y - + Corner 3 X - + Corner 3 Y - + Corner 4 X - + Corner 4 Y + + + Stretch X + + + + Stretch Y + + + + Feather Alpha + Enable Stretch - - - Stretch X - - - - Stretch Y - - Nearest neighbor,Bilinear,Bicubic smooth,Bicubic sharp,Spline 4x4,Spline 6x6,Lanczos Interpolator @@ -63,8 +61,6 @@ Transparent Background - - Feather Alpha - + diff --git a/src/cornerswidget.cpp b/src/cornerswidget.cpp index 380c9b7b..f252b2c8 100644 --- a/src/cornerswidget.cpp +++ b/src/cornerswidget.cpp @@ -26,34 +26,24 @@ #include "kdenlivesettings.h" #include -#include +#include #include -CornersWidget::CornersWidget(Monitor* monitor, int clipPos, bool isEffect, int factor, QWidget* parent) : - QWidget(parent), +CornersWidget::CornersWidget(Monitor *monitor, QDomElement e, int minFrame, int maxFrame, Timecode tc, int activeKeyframe, QWidget* parent) : + KeyframeEdit(e, minFrame, maxFrame, tc, activeKeyframe, parent), m_monitor(monitor), - m_clipPos(clipPos), - m_inPoint(0), - m_outPoint(1), - m_isEffect(isEffect), - m_showScene(true), - m_factor(factor) + m_showScene(true) { - m_ui.setupUi(this); - m_scene = monitor->getEffectScene(); m_item = new OnMonitorCornersItem(m_scene); m_scene->addItem(m_item); - m_config = new MonitorSceneControlWidget(m_scene, m_ui.frameConfig); - QHBoxLayout *layout = new QHBoxLayout(m_ui.frameConfig); - layout->setContentsMargins(0, 0, 0, 0); - layout->addWidget(m_config); - QHBoxLayout *layout2 = new QHBoxLayout(m_ui.widgetConfigButton); - layout2->setContentsMargins(0, 0, 0, 0); - layout2->addWidget(m_config->getShowHideButton()); + m_config = new MonitorSceneControlWidget(m_scene, this); + QGridLayout *l = static_cast(layout()); + l->addWidget(m_config->getShowHideButton(), 1, 1); + l->addWidget(m_config, 1, 2); QToolButton *buttonShowLines = new QToolButton(m_config); // TODO: Better Icons @@ -71,44 +61,12 @@ CornersWidget::CornersWidget(Monitor* monitor, int clipPos, bool isEffect, int f connect(buttonShowControls, SIGNAL(toggled(bool)), this, SLOT(slotShowControls(bool))); m_config->addWidget(buttonShowControls, 0, 3); - int width = m_monitor->render->frameRenderWidth(); - int height = m_monitor->render->renderHeight(); - - m_ui.spinX1->setRange(-width, width * 2); - m_ui.spinX2->setRange(-width, width * 2); - m_ui.spinX3->setRange(-width, width * 2); - m_ui.spinX4->setRange(-width, width * 2); - m_ui.spinY1->setRange(-height, height * 2); - m_ui.spinY2->setRange(-height, height * 2); - m_ui.spinY3->setRange(-height, height * 2); - m_ui.spinY4->setRange(-height, height * 2); - - m_ui.toolReset1->setIcon(KIcon("edit-undo")); - m_ui.toolReset1->setToolTip(i18n("Reset Corner 1")); - m_ui.toolReset2->setIcon(KIcon("edit-undo")); - m_ui.toolReset2->setToolTip(i18n("Reset Corner 2")); - m_ui.toolReset3->setIcon(KIcon("edit-undo")); - m_ui.toolReset3->setToolTip(i18n("Reset Corner 3")); - m_ui.toolReset4->setIcon(KIcon("edit-undo")); - m_ui.toolReset4->setToolTip(i18n("Reset Corner 4")); - - connect(m_ui.spinX1, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateItem())); - connect(m_ui.spinX2, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateItem())); - connect(m_ui.spinX3, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateItem())); - connect(m_ui.spinX4, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateItem())); - connect(m_ui.spinY1, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateItem())); - connect(m_ui.spinY2, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateItem())); - connect(m_ui.spinY3, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateItem())); - connect(m_ui.spinY4, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateItem())); - - connect(m_ui.toolReset1, SIGNAL(clicked()), this, SLOT(slotResetCorner1())); - connect(m_ui.toolReset2, SIGNAL(clicked()), this, SLOT(slotResetCorner2())); - connect(m_ui.toolReset3, SIGNAL(clicked()), this, SLOT(slotResetCorner3())); - connect(m_ui.toolReset4, SIGNAL(clicked()), this, SLOT(slotResetCorner4())); - connect(m_config, SIGNAL(showScene(bool)), this, SLOT(slotShowScene(bool))); connect(m_monitor, SIGNAL(renderPosition(int)), this, SLOT(slotCheckMonitorPosition(int))); connect(m_scene, SIGNAL(actionFinished()), this, SLOT(slotUpdateProperties())); + + connect(keyframe_list, SIGNAL(itemSelectionChanged()), this, SLOT(slotUpdateItem())); + connect(keyframe_list, SIGNAL(cellChanged(int, int)), this, SLOT(slotUpdateItem())); } CornersWidget::~CornersWidget() @@ -120,95 +78,61 @@ CornersWidget::~CornersWidget() m_monitor->slotEffectScene(false); } -void CornersWidget::setRange(int minframe, int maxframe) -{ - m_inPoint = minframe; - m_outPoint = maxframe; - slotCheckMonitorPosition(m_monitor->render->seekFramePosition()); -} - void CornersWidget::slotUpdateItem() { - QPointF c1(m_ui.spinX1->value(), m_ui.spinY1->value()); - QPointF c2(m_ui.spinX2->value(), m_ui.spinY2->value()); - QPointF c3(m_ui.spinX3->value(), m_ui.spinY3->value()); - QPointF c4(m_ui.spinX4->value(), m_ui.spinY4->value()); - - m_item->setPolygon(QPolygonF() << c1 << c2 << c3 << c4); - - emit parameterChanged(); -} - -void CornersWidget::slotUpdateProperties(bool changed) -{ - QPolygon pol = m_item->polygon().toPolygon(); - blockSignals(true); - m_ui.spinX1->setValue(pol.at(0).x()); - m_ui.spinX2->setValue(pol.at(1).x()); - m_ui.spinX3->setValue(pol.at(2).x()); - m_ui.spinX4->setValue(pol.at(3).x()); - m_ui.spinY1->setValue(pol.at(0).y()); - m_ui.spinY2->setValue(pol.at(1).y()); - m_ui.spinY3->setValue(pol.at(2).y()); - m_ui.spinY4->setValue(pol.at(3).y()); - blockSignals(false); + QList points; + + QTableWidgetItem *item = keyframe_list->currentItem(); + if (!item || keyframe_list->columnCount() < 8) + return; + + double val; + for (int col = 0; col < 8; col++) { + if (!keyframe_list->item(item->row(), col)) + return; + val = (keyframe_list->item(item->row(), col)->text().toInt() - 2000) / 2000.; + if (col % 2 == 0) + points << QPointF(val * m_monitor->render->frameRenderWidth(), 0); + else + points[col / 2].setY(val * m_monitor->render->renderHeight()); + } - if (changed) - emit parameterChanged(); + m_scene->blockSignals(true); + m_item->setPolygon(QPolygonF() << points.at(0) << points.at(1) << points.at(2) << points.at(3)); + m_scene->blockSignals(false); } - -QPolygon CornersWidget::getValue() +void CornersWidget::slotUpdateProperties() { - qreal width = m_monitor->render->frameRenderWidth(); - qreal height = m_monitor->render->renderHeight(); - QPolygon corners = m_item->polygon().toPolygon(); - QPolygon points; - QPoint p; - for (int i = 0; i < 4; ++i) { - p = corners.at(i); - p.setX((p.x() / width + 1) / 3.0 * m_factor); - p.setY((p.y() / height + 1) / 3.0 * m_factor); - points << p; + if (keyframe_list->columnCount() < 8) + return; + + QPolygonF pol = m_item->polygon(); + + QTableWidgetItem *item = keyframe_list->currentItem(); + double val; + for (int col = 0; col < 8; col++) { + if (col % 2 == 0) + val = pol.at(col / 2).x() / (double)m_monitor->render->frameRenderWidth(); + else + val = pol.at(col / 2).y() / (double)m_monitor->render->renderHeight(); + val *= 2000; + val += 2000; + QTableWidgetItem *nitem = keyframe_list->item(item->row(), col); + if (nitem->text().toInt() != (int)val) + nitem->setText(QString::number((int)val)); } - return points; -} -void CornersWidget::setValue(const QPolygon& points) -{ - int width = m_monitor->render->frameRenderWidth(); - int height = m_monitor->render->renderHeight(); - QPolygonF corners; - QPoint p; - for (int i = 0; i < 4; ++i) { - p = points.at(i); - p.setX((p.x() / (qreal)m_factor * 3 - 1) * width); - p.setY((p.y() / (qreal)m_factor * 3 - 1) * height); - corners << p; - } - m_item->setPolygon(corners); + slotAdjustKeyframeInfo(false); - slotUpdateProperties(false); + if (changed) + emit parameterChanged(); } void CornersWidget::slotCheckMonitorPosition(int renderPos) { - if (m_showScene) { - /* - We do only get the position in timeline if this geometry belongs to a transition, - therefore we need two ways here. - */ - if (m_isEffect) { - emit checkMonitorPosition(renderPos); - } else { - if (renderPos >= m_clipPos && renderPos <= m_clipPos + m_outPoint - m_inPoint) { - if (!m_scene->views().at(0)->isVisible()) - m_monitor->slotEffectScene(true); - } else { - m_monitor->slotEffectScene(false); - } - } - } + if (m_showScene) + emit checkMonitorPosition(renderPos); } void CornersWidget::slotShowScene(bool show) @@ -232,40 +156,4 @@ void CornersWidget::slotShowControls(bool show) m_item->update(); } -void CornersWidget::slotResetCorner1() -{ - blockSignals(true); - m_ui.spinX1->setValue(0); - m_ui.spinY1->setValue(0); - blockSignals(false); - slotUpdateItem(); -} - -void CornersWidget::slotResetCorner2() -{ - blockSignals(true); - m_ui.spinX2->setValue(m_monitor->render->frameRenderWidth()); - m_ui.spinY2->setValue(0); - blockSignals(false); - slotUpdateItem(); -} - -void CornersWidget::slotResetCorner3() -{ - blockSignals(true); - m_ui.spinX3->setValue(m_monitor->render->frameRenderWidth()); - m_ui.spinY3->setValue(m_monitor->render->renderHeight()); - blockSignals(false); - slotUpdateItem(); -} - -void CornersWidget::slotResetCorner4() -{ - blockSignals(true); - m_ui.spinX4->setValue(0); - m_ui.spinY4->setValue(m_monitor->render->renderHeight()); - blockSignals(false); - slotUpdateItem(); -} - #include "cornerswidget.moc" diff --git a/src/cornerswidget.h b/src/cornerswidget.h index 160e59ef..f4a02232 100644 --- a/src/cornerswidget.h +++ b/src/cornerswidget.h @@ -21,9 +21,8 @@ #ifndef CORNERSWIDGET_H #define CORNERSWIDGET_H -#include "ui_cornerswidget_ui.h" +#include "keyframeedit.h" -#include class QDomElement; class Monitor; @@ -32,7 +31,7 @@ class OnMonitorCornersItem; class MonitorSceneControlWidget; -class CornersWidget : public QWidget +class CornersWidget : public KeyframeEdit { Q_OBJECT public: @@ -42,68 +41,37 @@ public: * @param isEffect true if used in an effect, false if used in a transition * @param factor Factor by which the parameters differ from the range 0-1 * @param parent (optional) Parent widget */ - CornersWidget(Monitor *monitor, int clipPos, bool isEffect, int factor, QWidget* parent = 0); + CornersWidget(Monitor *monitor, QDomElement e, int minFrame, int maxFrame, Timecode tc, int activeKeyframe, QWidget* parent = 0); virtual ~CornersWidget(); - /** @brief Returns a polygon representing the corners in the range 0 - factor. */ - QPolygon getValue(); - - /** @brief Takes a polygon @param points in the range 0 - factor and converts it into range (- frame width|height) - (2*frame width|height). */ - void setValue(const QPolygon &points); - - /** @brief Takes in and outpoint of the clip to know when to show the on-monitor scene. - * @param minframe In point of the clip - * @param maxframe Out point of the clip */ - void setRange(int minframe, int maxframe); - public slots: /** @brief Switches from normal monitor to monitor scene according to @param show. */ void slotShowScene(bool show = true); private: - Ui::CornersWidget_UI m_ui; Monitor *m_monitor; - /** Position of the clip in timeline. */ - int m_clipPos; - /** In point of the clip (crop from start). */ - int m_inPoint; - /** Out point of the clip (crop from end). */ - int m_outPoint; - bool m_isEffect; MonitorScene *m_scene; OnMonitorCornersItem *m_item; bool m_showScene; MonitorSceneControlWidget *m_config; - int m_factor; private slots: /** @brief Makes sure the monitor effect scene is only visible if the clip this geometry belongs to is visible. * @param renderPos Postion of the Monitor / Timeline cursor */ void slotCheckMonitorPosition(int renderPos); - /** @brief Updates the on-monitor item according to the spinboxes. */ + /** @brief Updates the on-monitor item according current values in the keyframe editor. */ void slotUpdateItem(); - /** @brief Updates the spinboxes according to the on-monitor item. - * @param changed (default = true) Whether to emit parameterChanged */ - void slotUpdateProperties(bool changed = true); + /** @brief Updates the keyframe editor according to the on-monitor item. */ + void slotUpdateProperties(); /** @brief Shows/Hides the lines connecting the corners in the on-monitor item according to @param show. */ void slotShowLines(bool show = true); + /** @brief Shows/Hides additional controls on the monitor according to @param show. */ void slotShowControls(bool show = true); - /* - * These functions reset the positions of the corners. - * The default values in the effect XML file are not considered, but - * the position the corner would have without this effect applied. - */ - void slotResetCorner1(); - void slotResetCorner2(); - void slotResetCorner3(); - void slotResetCorner4(); - signals: - void parameterChanged(); void checkMonitorPosition(int); }; diff --git a/src/effectstackedit.cpp b/src/effectstackedit.cpp index d15a3806..176052b4 100644 --- a/src/effectstackedit.cpp +++ b/src/effectstackedit.cpp @@ -315,7 +315,17 @@ void EffectStackEdit::transferParamDesc(const QDomElement d, int pos, int in, in } else if (type == "keyframe" || type == "simplekeyframe") { // keyframe editor widget if (m_keyframeEditor == NULL) { - KeyframeEdit *geo = new KeyframeEdit(pa, m_in, m_in + m_out, m_timecode, e.attribute("active_keyframe", "-1").toInt()); + KeyframeEdit *geo; + if (pa.attribute("widget") == "corners") { + // we want a corners-keyframe-widget + CornersWidget *corners = new CornersWidget(m_monitor, pa, m_in, m_in + m_out, m_timecode, e.attribute("active_keyframe", "-1").toInt(), this); + corners->slotShowScene(!disable); + connect(corners, SIGNAL(checkMonitorPosition(int)), this, SIGNAL(checkMonitorPosition(int))); + connect(this, SIGNAL(effectStateChanged(bool)), corners, SLOT(slotShowScene(bool))); + geo = static_cast(corners); + } else { + geo = new KeyframeEdit(pa, m_in, m_in + m_out, m_timecode, e.attribute("active_keyframe", "-1").toInt()); + } m_vbox->addWidget(geo); m_valueItems[paramName+"keyframe"] = geo; m_keyframeEditor = geo; @@ -388,29 +398,6 @@ void EffectStackEdit::transferParamDesc(const QDomElement d, int pos, int in, in QString depends = pa.attribute("depends"); if (!depends.isEmpty()) meetDependency(paramName, type, EffectsList::parameter(e, depends)); - } else if (type == "corners") { - CornersWidget *corners = new CornersWidget(m_monitor, pos, isEffect, pa.attribute("factor").toInt(), this); - corners->slotShowScene(!disable); - connect(corners, SIGNAL(checkMonitorPosition(int)), this, SIGNAL(checkMonitorPosition(int))); - if (minFrame == maxFrame) - corners->setRange(m_in, m_out); - else - corners->setRange(minFrame, maxFrame); - - QString xName = pa.attribute("xpoints"); - QString yName = pa.attribute("ypoints"); - QPolygon points; - int x, y; - for (int j = 1; j <= 4; ++j) { - x = EffectsList::parameter(e, QString(xName).replace("%i", QString::number(j))).toInt(); - y = EffectsList::parameter(e, QString(yName).replace("%i", QString::number(j))).toInt(); - points << QPoint(x, y); - } - corners->setValue(points); - m_vbox->addWidget(corners); - connect(corners, SIGNAL(parameterChanged()), this, SLOT(collectAllParameters())); - connect(this, SIGNAL(effectStateChanged(bool)), corners, SLOT(slotShowScene(bool))); - m_valueItems[paramName] = corners; } else if (type == "wipe") { Wipeval *wpval = new Wipeval; wpval->setupUi(toFillin); @@ -676,17 +663,6 @@ void EffectStackEdit::collectAllParameters() QString depends = pa.attributes().namedItem("depends").nodeValue(); if (!depends.isEmpty()) meetDependency(paramName, type, EffectsList::parameter(newparam, depends)); - } else if (type == "corners") { - CornersWidget *corners = ((CornersWidget*)m_valueItems.value(paramName)); - QString xName = pa.attributes().namedItem("xpoints").nodeValue(); - QString yName = pa.attributes().namedItem("ypoints").nodeValue(); - QPolygon points = corners->getValue(); - QPoint p; - for (int j = 1; j <= 4; ++j) { - p = points.at(j - 1); - EffectsList::setParameter(newparam, QString(xName).replace("%i", QString::number(j)), QString::number(p.x())); - EffectsList::setParameter(newparam, QString(yName).replace("%i", QString::number(j)), QString::number(p.y())); - } } else if (type == "wipe") { Wipeval *wp = (Wipeval*)m_valueItems.value(paramName); wipeInfo info; diff --git a/src/keyframeedit.cpp b/src/keyframeedit.cpp index ffe75496..cc050c18 100644 --- a/src/keyframeedit.cpp +++ b/src/keyframeedit.cpp @@ -53,7 +53,7 @@ KeyframeEdit::KeyframeEdit(QDomElement e, int minFrame, int maxFrame, Timecode t connect(keyframe_list, SIGNAL(cellChanged(int, int)), this, SLOT(slotGenerateParams(int, int))); m_position = new PositionEdit(i18n("Position"), 0, 0, 1, tc, widgetTable); - ((QGridLayout*)widgetTable->layout())->addWidget(m_position, 2, 0, 1, -1); + ((QGridLayout*)widgetTable->layout())->addWidget(m_position, 3, 0, 1, -1); m_showButtons = new QButtonGroup(this); m_slidersLayout = new QGridLayout(param_sliders); @@ -127,7 +127,6 @@ void KeyframeEdit::addParameter(QDomElement e, int activeKeyframe) if (e.attribute("intimeline") == "1") radio->setChecked(true); - // make the radiobutton stay at the top QVBoxLayout *radioLayout = new QVBoxLayout(this); radioLayout->addWidget(radio, 0, Qt::AlignTop); m_slidersLayout->addLayout(radioLayout, columnId, 1); diff --git a/src/keyframeedit.h b/src/keyframeedit.h index 8dc1d5de..24377bc7 100644 --- a/src/keyframeedit.h +++ b/src/keyframeedit.h @@ -94,6 +94,14 @@ public: /** @brief Makes the first parameter visible in timeline if no parameter is selected. */ void checkVisibleParam(); +protected: + /** @brief Gets the position of a keyframe from the table. + * @param row Row of the keyframe in the table */ + int getPos(int row); + +protected slots: + void slotAdjustKeyframeInfo(bool seek = true); + private: QList m_params; int m_min; @@ -104,9 +112,6 @@ private: PositionEdit *m_position; void generateAllParams(); - /** @brief Gets the position of a keyframe from the table. - * @param row Row of the keyframe in the table */ - int getPos(int row); /** @brief Converts a frame value to timecode considering the frames vs. HH:MM:SS:FF setting. * @return timecode */ QString getPosString(int pos); @@ -115,7 +120,6 @@ private slots: void slotDeleteKeyframe(); void slotAddKeyframe(); void slotGenerateParams(int row, int column); - void slotAdjustKeyframeInfo(bool seek = true); void slotAdjustKeyframePos(int value); void slotAdjustKeyframeValue(int value); /** @brief Turns the seek to keyframe position setting on/off. diff --git a/src/onmonitoritems/onmonitorcornersitem.cpp b/src/onmonitoritems/onmonitorcornersitem.cpp index 663814b1..d5a288a9 100644 --- a/src/onmonitoritems/onmonitorcornersitem.cpp +++ b/src/onmonitoritems/onmonitorcornersitem.cpp @@ -43,6 +43,8 @@ OnMonitorCornersItem::OnMonitorCornersItem(MonitorScene* scene, QGraphicsItem* p OnMonitorCornersItem::cornersActions OnMonitorCornersItem::getMode(QPointF pos, int *corner) { *corner = -1; + if (polygon().count() != 4) + return NoAction; QPainterPath mouseArea; pos = mapFromScene(pos); @@ -144,6 +146,9 @@ void OnMonitorCornersItem::paint(QPainter* painter, const QStyleOptionGraphicsIt if (KdenliveSettings::onmonitoreffects_cornersshowlines()) QGraphicsPolygonItem::paint(painter, option, widget); + if (polygon().count() != 4) + return; + double baseSize = 1 / painter->matrix().m11(); painter->setRenderHint(QPainter::Antialiasing); painter->setBrush(QBrush(Qt::yellow)); diff --git a/src/widgets/keyframeeditor_ui.ui b/src/widgets/keyframeeditor_ui.ui index 109d3dce..122925d4 100644 --- a/src/widgets/keyframeeditor_ui.ui +++ b/src/widgets/keyframeeditor_ui.ui @@ -40,7 +40,7 @@ 0 - + true @@ -62,7 +62,7 @@ - + A @@ -72,7 +72,7 @@ - + D @@ -82,7 +82,7 @@ - + Reset the parameters to their default values @@ -92,7 +92,7 @@ - + Seek to active keyframe -- 2.39.2