X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fgeometrywidget.cpp;h=321ab76fecb8500362922d3e6e92e2aba66512d2;hb=fe9316d603bb2da1f779493975ac12051f7e04b9;hp=bb9fa8a24e8d385d2e15c14bed405b45153deb31;hpb=48821a20a9e723128ef0c8c77b5885e9712f086e;p=kdenlive diff --git a/src/geometrywidget.cpp b/src/geometrywidget.cpp index bb9fa8a2..321ab76f 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)), @@ -46,12 +46,16 @@ GeometryWidget::GeometryWidget(Monitor* monitor, Timecode timecode, int clipPos, m_outPoint(1), m_isEffect(isEffect), 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); MonitorEditWidget *edit = monitor->getEffectEdit(); + edit->removeCustomControls(); + edit->addCustomButton(KIcon("transform-crop"), i18n("Show previous keyframe"), this, SLOT(slotShowPreviousKeyFrame(bool)), true, KdenliveSettings::onmonitoreffects_geometryshowprevious()); edit->showVisibilityButton(true); m_scene = edit->getScene(); @@ -88,43 +92,18 @@ 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, -1, QString(), false, this); - m_spinX->setRange(-10000, 10000); + m_spinX = new DragValue(i18nc("x axis position", "X"), 0, 0, -99000, 99000, -1, QString(), false, this); m_ui.horizontalLayout->addWidget(m_spinX); - m_spinY = new DragValue(i18n("Y"), 0, -1, QString(), false, this); - m_spinY->setRange(-10000, 10000); + m_spinY = new DragValue(i18nc("y axis position", "Y"), 0, 0, -99000, 99000, -1, QString(), false, this); m_ui.horizontalLayout->addWidget(m_spinY); - m_spinWidth = new DragValue(i18n("W"), m_monitor->render->frameRenderWidth(), -1, QString(), false, this); - m_spinWidth->setRange(1, 10000); + m_spinWidth = new DragValue(i18nc("Frame width", "W"), m_monitor->render->frameRenderWidth(), 0, 1, 99000, -1, QString(), false, this); m_ui.horizontalLayout->addWidget(m_spinWidth); - m_spinHeight = new DragValue(i18n("H"), m_monitor->render->renderHeight(), -1, QString(), false, this); - m_spinHeight->setRange(1, 10000); + m_spinHeight = new DragValue(i18nc("Frame height", "H"), m_monitor->render->renderHeight(), 0, 1, 99000, -1, QString(), false, this); m_ui.horizontalLayout->addWidget(m_spinHeight); - m_ui.horizontalLayout->addStretch(10); - - m_spinSize = new DragValue(i18n("Size"), 100, -1, i18n("%"), false, this); - m_spinSize->setRange(1, 10000); - m_ui.horizontalLayout2->addWidget(m_spinSize); - - m_opacity = new DragValue(i18n("Opacity"), 100, -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(int)), this, SLOT(slotResize(int))); - - 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())); @@ -148,7 +127,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); @@ -157,6 +136,76 @@ 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, 99000, -1, i18n("%"), false, this); + m_ui.horizontalLayout2->addWidget(m_spinSize); + + m_opacity = new DragValue(i18n("Opacity"), 100, 0, 0, 100, -1, i18n("%"), true, this); + m_ui.horizontalLayout2->addWidget(m_opacity); + + + if (showRotation) { + m_rotateX = new DragValue(i18n("Rotate X"), 0, 0, -1800, 1800, -1, QString(), true, this); + m_rotateX->setObjectName("rotate_x"); + m_ui.horizontalLayout3->addWidget(m_rotateX); + m_rotateY = new DragValue(i18n("Rotate Y"), 0, 0, -1800, 1800, -1, QString(), true, this); + m_rotateY->setObjectName("rotate_y"); + m_ui.horizontalLayout3->addWidget(m_rotateY); + m_rotateZ = new DragValue(i18n("Rotate Z"), 0, 0, -1800, 1800, -1, QString(), true, this); + m_rotateZ->setObjectName("rotate_z"); + m_ui.horizontalLayout3->addWidget(m_rotateZ); + connect(m_rotateX, SIGNAL(valueChanged(double)), this, SLOT(slotUpdateGeometry())); + connect(m_rotateY, SIGNAL(valueChanged(double)), this, SLOT(slotUpdateGeometry())); + connect(m_rotateZ, SIGNAL(valueChanged(double)), this, SLOT(slotUpdateGeometry())); + } + + /* + Setup of geometry controls + */ + + connect(m_spinX, SIGNAL(valueChanged(double)), this, SLOT(slotSetX(double))); + connect(m_spinY, SIGNAL(valueChanged(double)), this, SLOT(slotSetY(double))); + connect(m_spinWidth, SIGNAL(valueChanged(double)), this, SLOT(slotSetWidth(double))); + connect(m_spinHeight, SIGNAL(valueChanged(double)), this, SLOT(slotSetHeight(double))); + + connect(m_spinSize, SIGNAL(valueChanged(double)), this, SLOT(slotResize(double))); + + connect(m_opacity, SIGNAL(valueChanged(double)), this, SLOT(slotSetOpacity(double))); + /*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())); @@ -187,13 +236,27 @@ GeometryWidget::~GeometryWidget() delete m_spinHeight; delete m_opacity; m_scene->removeItem(m_rect); + 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); } } +void GeometryWidget::slotShowPreviousKeyFrame(bool show) +{ + KdenliveSettings::setOnmonitoreffects_geometryshowprevious(show); + slotPositionChanged(-1, false); +} + void GeometryWidget::updateTimecodeFormat() { m_timePos->slotUpdateTimeCodeFormat(); @@ -204,6 +267,22 @@ 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(';', QString::SkipEmptyParts); + val.clear(); + val.append(list.takeFirst().section('/', 0, 0)); + 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; @@ -219,9 +298,9 @@ void GeometryWidget::setupParam(const QDomElement elem, int minframe, int maxfra m_ui.widgetTimeWrapper->setHidden(true); } else { m_ui.widgetTimeWrapper->setHidden(false); - m_timeline->setKeyGeometry(m_geometry, m_outPoint - m_inPoint - 1); + m_timeline->setKeyGeometry(m_geometry, m_outPoint - m_inPoint); m_timeline->update(); - m_timePos->setRange(0, m_outPoint - m_inPoint - 1); + m_timePos->setRange(0, m_outPoint - m_inPoint); } // no opacity @@ -244,12 +323,21 @@ 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: "<maximum() > 0 && KdenliveSettings::transitionfollowcursor()) { - relTimelinePos = qMax(0, relTimelinePos); - relTimelinePos = qMin(relTimelinePos, m_timePos->maximum()); + relTimelinePos = qBound(0, relTimelinePos, m_timePos->maximum()); if (relTimelinePos != m_timePos->getValue()) slotPositionChanged(relTimelinePos, false); } @@ -268,6 +356,7 @@ void GeometryWidget::slotPositionChanged(int pos, bool seek) m_timeline->blockSignals(false); Mlt::GeometryItem item; + Mlt::GeometryItem previousItem; if (m_geometry->fetch(&item, pos) || item.key() == false) { // no keyframe m_rect->setEnabled(false); @@ -283,6 +372,31 @@ void GeometryWidget::slotPositionChanged(int pos, bool seek) m_ui.buttonAddDelete->setIcon(KIcon("edit-delete")); m_ui.buttonAddDelete->setToolTip(i18n("Delete keyframe")); } + + if (KdenliveSettings::onmonitoreffects_geometryshowprevious() == false || m_geometry->prev_key(&previousItem, pos - 1) || previousItem.frame() == item.frame()) { + if (m_previous) { + m_scene->removeItem(m_previous); + } + } + else if (m_previous && m_previous->scene() && m_previous->data(Qt::UserRole).toInt() == previousItem.frame()) { + // previous frame already here, do nothing + } + else { + if (m_previous == NULL) { + m_previous = new QGraphicsRectItem(0, 0, previousItem.w(), previousItem.h()); + m_previous->setBrush(QColor(200, 200, 0, 20)); + m_previous->setPen(QPen(Qt::white, 0, Qt::DotLine)); + m_previous->setPos(previousItem.x(), previousItem.y()); + m_previous->setZValue(-1); + m_previous->setEnabled(false); + } + else { + m_previous->setPos(previousItem.x(), previousItem.y()); + m_previous->setRect(0, 0, previousItem.w(), previousItem.h()); + } + m_previous->setData(Qt::UserRole, previousItem.frame()); + if (m_previous->scene() == 0) m_scene->addItem(m_previous); + } m_rect->setPos(item.x(), item.y()); m_rect->setRect(0, 0, item.w(), item.h()); @@ -291,6 +405,19 @@ void GeometryWidget::slotPositionChanged(int pos, bool seek) m_opacity->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()) @@ -319,6 +446,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(); @@ -336,6 +475,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(); @@ -411,6 +555,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(); } @@ -418,11 +574,11 @@ void GeometryWidget::slotUpdateProperties() { QRectF rectSize = m_rect->rect().normalized(); QPointF rectPos = m_rect->pos(); - int size; - if (rectSize.width() / m_monitor->render->dar() < rectSize.height()) - size = (int)((rectSize.width() * 100.0 / m_monitor->render->frameRenderWidth()) + 0.5); + double size; + if (rectSize.width() / m_monitor->render->dar() > rectSize.height()) + size = rectSize.width() * 100.0 / m_monitor->render->frameRenderWidth(); else - size = (int)((rectSize.height() * 100.0 / m_monitor->render->renderHeight()) + 0.5); + size = rectSize.height() * 100.0 / m_monitor->render->renderHeight(); m_spinX->blockSignals(true); m_spinY->blockSignals(true); @@ -444,32 +600,38 @@ void GeometryWidget::slotUpdateProperties() } -void GeometryWidget::slotSetX(int value) +void GeometryWidget::slotSetX(double value) { m_rect->setPos(value, m_spinY->value()); slotUpdateGeometry(); } -void GeometryWidget::slotSetY(int value) +void GeometryWidget::slotSetY(double value) { m_rect->setPos(m_spinX->value(), value); slotUpdateGeometry(); } -void GeometryWidget::slotSetWidth(int value) +void GeometryWidget::slotSetWidth(double value) { m_rect->setRect(0, 0, value, m_spinHeight->value()); slotUpdateGeometry(); } -void GeometryWidget::slotSetHeight(int value) +void GeometryWidget::slotSetHeight(double value) { m_rect->setRect(0, 0, m_spinWidth->value(), value); slotUpdateGeometry(); } +void GeometryWidget::updateMonitorGeometry() +{ + m_rect->setRect(0, 0, m_spinWidth->value(), m_spinHeight->value()); + slotUpdateGeometry(); +} -void GeometryWidget::slotResize(int value) + +void GeometryWidget::slotResize(double value) { m_rect->setRect(0, 0, (int)((m_monitor->render->frameRenderWidth() * value / 100.0) + 0.5), @@ -478,7 +640,7 @@ void GeometryWidget::slotResize(int value) } -void GeometryWidget::slotSetOpacity(int value) +void GeometryWidget::slotSetOpacity(double value) { int pos = m_timePos->getValue(); Mlt::GeometryItem item; @@ -550,23 +712,46 @@ void GeometryWidget::setFrameSize(QPoint size) void GeometryWidget::slotAdjustToFrameSize() { - if (m_frameSize == QPoint()) m_frameSize = QPoint(m_monitor->render->frameRenderWidth(), m_monitor->render->renderHeight()); - m_spinWidth->setValue(m_frameSize.x()); + if (m_frameSize == QPoint() || m_frameSize.x() == 0 || m_frameSize.y() == 0) { + m_frameSize = QPoint(m_monitor->render->frameRenderWidth(), m_monitor->render->renderHeight()); + } + m_spinWidth->blockSignals(true); + m_spinHeight->blockSignals(true); + m_spinWidth->setValue((int) (m_frameSize.x() / m_monitor->render->sar() + 0.5)); m_spinHeight->setValue(m_frameSize.y()); + m_spinWidth->blockSignals(false); + m_spinHeight->blockSignals(false); + updateMonitorGeometry(); } void GeometryWidget::slotFitToWidth() { - if (m_frameSize == QPoint()) m_frameSize = QPoint(m_monitor->render->frameRenderWidth(), m_monitor->render->renderHeight()); - double factor = 100.0 * m_monitor->render->frameRenderWidth() / m_frameSize.x() + 0.5; - m_spinSize->setValue(factor); + if (m_frameSize == QPoint() || m_frameSize.x() == 0 || m_frameSize.y() == 0) { + m_frameSize = QPoint(m_monitor->render->frameRenderWidth(), m_monitor->render->renderHeight()); + } + double factor = (double) m_monitor->render->frameRenderWidth() / m_frameSize.x() * m_monitor->render->sar(); + m_spinWidth->blockSignals(true); + m_spinHeight->blockSignals(true); + m_spinHeight->setValue((int) (m_frameSize.y() * factor + 0.5)); + m_spinWidth->setValue(m_monitor->render->frameRenderWidth()); + m_spinWidth->blockSignals(false); + m_spinHeight->blockSignals(false); + updateMonitorGeometry(); } void GeometryWidget::slotFitToHeight() { - if (m_frameSize == QPoint()) m_frameSize = QPoint(m_monitor->render->frameRenderWidth(), m_monitor->render->renderHeight()); - double factor = 100.0 * m_monitor->render->renderHeight() / m_frameSize.y() + 0.5; - m_spinSize->setValue(factor); + if (m_frameSize == QPoint() || m_frameSize.x() == 0 || m_frameSize.y() == 0) { + m_frameSize = QPoint(m_monitor->render->frameRenderWidth(), m_monitor->render->renderHeight()); + } + double factor = (double) m_monitor->render->renderHeight() / m_frameSize.y(); + m_spinWidth->blockSignals(true); + m_spinHeight->blockSignals(true); + m_spinHeight->setValue(m_monitor->render->renderHeight()); + m_spinWidth->setValue((int) (m_frameSize.x() / m_monitor->render->sar() * factor + 0.5)); + m_spinWidth->blockSignals(false); + m_spinHeight->blockSignals(false); + updateMonitorGeometry(); } #include "geometrywidget.moc"