#include "cornerswidget.h"
#include "monitor.h"
#include "monitorscene.h"
-#include "monitorscenecontrolwidget.h"
+#include "monitoreditwidget.h"
#include "onmonitoritems/onmonitorcornersitem.h"
#include "renderer.h"
+#include "kdenlivesettings.h"
#include <QGraphicsView>
-#include <QHBoxLayout>
+#include <QGridLayout>
+#include <QToolButton>
#include <KIcon>
-CornersWidget::CornersWidget(Monitor* monitor, int clipPos, bool isEffect, int factor, QWidget* parent) :
- QWidget(parent),
+inline int lerp( const int a, const int b, double t )
+{
+ return a + (b - a) * t;
+}
+
+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_pos(0)
{
- m_ui.setupUi(this);
-
- m_scene = monitor->getEffectScene();
+ MonitorEditWidget *edit = monitor->getEffectEdit();
+ edit->showVisibilityButton(true);
+ m_scene = edit->getScene();
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->addWidget(m_config->getShowHideButton());
- layout->addWidget(m_config);
-
- 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)));
+ // TODO: Better Icons
+ QToolButton *buttonShowControls = new QToolButton();
+ buttonShowControls->setIcon(KIcon("transform-move"));
+ buttonShowControls->setToolTip(i18n("Show additional controls"));
+ buttonShowControls->setCheckable(true);
+ buttonShowControls->setAutoRaise(true);
+ buttonShowControls->setChecked(KdenliveSettings::onmonitoreffects_cornersshowcontrols());
+ connect(buttonShowControls, SIGNAL(toggled(bool)), this, SLOT(slotShowControls(bool)));
+ edit->addCustomControl(buttonShowControls);
+
+ QToolButton *buttonShowLines = new QToolButton();
+ buttonShowLines->setIcon(KIcon("insert-horizontal-rule"));
+ buttonShowLines->setToolTip(i18n("Show/Hide the lines connecting the corners"));
+ buttonShowLines->setCheckable(true);
+ buttonShowControls->setAutoRaise(true);
+ buttonShowLines->setChecked(KdenliveSettings::onmonitoreffects_cornersshowlines());
+ connect(buttonShowLines, SIGNAL(toggled(bool)), this, SLOT(slotShowLines(bool)));
+ edit->addCustomControl(buttonShowLines);
+
+ connect(edit, SIGNAL(showEdit(bool)), this, SLOT(slotShowScene(bool)));
connect(m_monitor, SIGNAL(renderPosition(int)), this, SLOT(slotCheckMonitorPosition(int)));
connect(m_scene, SIGNAL(actionFinished()), this, SLOT(slotUpdateProperties()));
+ connect(m_scene, SIGNAL(addKeyframe()), this, SLOT(slotInsertKeyframe()));
+
+ connect(keyframe_list, SIGNAL(cellChanged(int, int)), this, SLOT(slotUpdateItem()));
}
CornersWidget::~CornersWidget()
{
- delete m_config;
m_scene->removeItem(m_item);
delete m_item;
- if (m_monitor)
+ if (m_monitor) {
+ MonitorEditWidget *edit = m_monitor->getEffectEdit();
+ edit->showVisibilityButton(false);
+ edit->removeCustomControls();
m_monitor->slotEffectScene(false);
+ }
}
-void CornersWidget::setRange(int minframe, int maxframe)
+void CornersWidget::addParameter(QDomElement e, int activeKeyframe)
{
- m_inPoint = minframe;
- m_outPoint = maxframe;
- slotCheckMonitorPosition(m_monitor->render->seekFramePosition());
+ KeyframeEdit::addParameter(e, activeKeyframe);
+
+ if (!m_item->polygon().count())
+ slotUpdateItem();
}
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());
+ if (keyframe_list->columnCount() < 8)
+ return;
+
+ QTableWidgetItem *keyframe, *keyframeOld;
+ keyframe = keyframeOld = keyframe_list->item(0, 0);
+ for (int row = 0; row < keyframe_list->rowCount(); ++row) {
+ keyframeOld = keyframe;
+ keyframe = keyframe_list->item(row, 0);
+ if (getPos(row) >= m_pos)
+ break;
+ }
- m_item->setPolygon(QPolygonF() << c1 << c2 << c3 << c4);
+ QList<QPointF> points, pointsPrev, pointsNext;
+ pointsPrev = getPoints(keyframeOld);
+ pointsNext = getPoints(keyframe);
+ if (pointsPrev.count() != 4 || pointsNext.count() != 4)
+ return;
- emit parameterChanged();
+ qreal position = (m_pos - getPos(keyframeOld->row())) / (qreal)( getPos(keyframe->row()) - getPos(keyframeOld->row()) + 1 );
+
+ if (keyframeOld == keyframe) {
+ points = pointsNext;
+ } else {
+ for (int i = 0; i < 4; ++i)
+ points.append(QLineF(pointsPrev.at(i), pointsNext.at(i)).pointAt(position));
+ }
+
+ m_scene->blockSignals(true);
+ m_item->setPolygon(QPolygonF() << points.at(0) << points.at(1) << points.at(2) << points.at(3));
+ m_scene->blockSignals(false);
+
+ bool enable = getPos(keyframe->row()) == m_pos || keyframe_list->rowCount() == 1;
+ m_item->setEnabled(enable);
+ m_scene->setEnabled(enable);
}
-void CornersWidget::slotUpdateProperties(bool changed)
+void CornersWidget::slotUpdateProperties()
{
- 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);
-
- if (changed)
- emit parameterChanged();
-}
+ if (keyframe_list->columnCount() < 8)
+ return;
+ QPolygonF pol = m_item->polygon();
-QPolygon CornersWidget::getValue()
-{
- 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;
+ 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;
+
+ slotAdjustKeyframeInfo(false);
}
-void CornersWidget::setValue(const QPolygon& points)
+QList<QPointF> CornersWidget::getPoints(QTableWidgetItem* keyframe)
{
- 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);
+ QList<QPointF> points;
+
+ if (!keyframe)
+ return points;
- slotUpdateProperties(false);
+ double val;
+ for (int col = 0; col < 8; col++) {
+ if (!keyframe_list->item(keyframe->row(), col))
+ return QList<QPointF>();
+ val = (keyframe_list->item(keyframe->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());
+ }
+ return points;
}
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)
slotCheckMonitorPosition(m_monitor->render->seekFramePosition());
}
-void CornersWidget::slotResetCorner1()
+void CornersWidget::slotShowLines(bool show)
{
- blockSignals(true);
- m_ui.spinX1->setValue(0);
- m_ui.spinY1->setValue(0);
- blockSignals(false);
- slotUpdateItem();
+ KdenliveSettings::setOnmonitoreffects_cornersshowlines(show);
+ m_item->update();
}
-void CornersWidget::slotResetCorner2()
+void CornersWidget::slotShowControls(bool show)
{
- blockSignals(true);
- m_ui.spinX2->setValue(m_monitor->render->frameRenderWidth());
- m_ui.spinY2->setValue(0);
- blockSignals(false);
- slotUpdateItem();
+ KdenliveSettings::setOnmonitoreffects_cornersshowcontrols(show);
+ m_item->update();
}
-void CornersWidget::slotResetCorner3()
+void CornersWidget::slotSyncPosition(int relTimelinePos)
{
- blockSignals(true);
- m_ui.spinX3->setValue(m_monitor->render->frameRenderWidth());
- m_ui.spinY3->setValue(m_monitor->render->renderHeight());
- blockSignals(false);
- slotUpdateItem();
+ if (keyframe_list->rowCount()) {
+ relTimelinePos = qBound(0, relTimelinePos, m_max);
+ if (relTimelinePos != m_pos) {
+ m_pos = relTimelinePos;
+ slotUpdateItem();
+ }
+ }
}
-void CornersWidget::slotResetCorner4()
+void CornersWidget::slotInsertKeyframe()
{
- blockSignals(true);
- m_ui.spinX4->setValue(0);
- m_ui.spinY4->setValue(m_monitor->render->renderHeight());
- blockSignals(false);
- slotUpdateItem();
+ keyframe_list->blockSignals(true);
+
+ int row;
+ QTableWidgetItem *keyframe, *keyframeOld;
+ keyframe = keyframeOld = keyframe_list->item(0, 0);
+ for (row = 0; row < keyframe_list->rowCount(); ++row) {
+ keyframeOld = keyframe;
+ keyframe = keyframe_list->item(row, 0);
+ if (getPos(row) >= m_pos)
+ break;
+ }
+
+
+ int pos2;
+ if (row == keyframe_list->rowCount()) {
+ pos2 = m_max;
+ } else {
+ pos2 = getPos(row);
+ if (pos2 == m_pos)
+ return;
+ }
+
+ int pos1 = 0;
+ if (row > 0)
+ pos1 = getPos(row - 1);
+
+ int col = keyframe_list->currentColumn();
+ double pos = (m_pos - pos1) / (double)(pos2 - pos1 + 1);
+
+ keyframe_list->insertRow(row);
+ keyframe_list->setVerticalHeaderItem(row, new QTableWidgetItem(getPosString(m_pos)));
+
+ QPolygonF pol = m_item->polygon();
+ double val;
+ for (int i = 0; i < keyframe_list->columnCount(); i++) {
+ if (i < 8) {
+ if (i % 2 == 0)
+ val = pol.at(i / 2).x() / (double)m_monitor->render->frameRenderWidth();
+ else
+ val = pol.at(i / 2).y() / (double)m_monitor->render->renderHeight();
+ val *= 2000;
+ val += 2000;
+ keyframe_list->setItem(row, i, new QTableWidgetItem(QString::number((int)val)));
+ } else {
+ keyframe_list->setItem(row, i, new QTableWidgetItem(QString::number(lerp(keyframe_list->item(keyframeOld->row(), i)->text().toInt(), keyframe_list->item(keyframe->row(), i)->text().toInt(), pos))));
+ }
+ }
+
+ keyframe_list->resizeRowsToContents();
+ slotAdjustKeyframeInfo();
+ keyframe_list->blockSignals(false);
+ generateAllParams();
+ button_delete->setEnabled(true);
+ keyframe_list->setCurrentCell(row, col);
+ keyframe_list->selectRow(row);
}
#include "cornerswidget.moc"