}
-bool ClipItem::checkEffectsKeyframesPos(const int previous, const int current, bool fromStart, int renderWidth, int renderHeight)
+bool ClipItem::checkEffectsKeyframesPos(const int previous, const int current, bool fromStart)
{
bool effModified = false;
for (int i = 0; i < m_effectList.count(); i++) {
}
e.setAttribute("keyframes", newkfr);
}
- } else if (e.attribute("type") == "geometry" && !e.hasAttribute("fixed")) {
- Mlt::Geometry geometry(e.attribute("value").toUtf8().data(), cropDuration().frames(fps()), renderWidth, renderHeight);
-
- Mlt::GeometryItem item;
- while (!geometry.next_key(&item, cropDuration().frames(fps()))) {
- geometry.remove(item.frame());
- modified = true;
- }
-
- e.setAttribute("value", geometry.serialise());
}
}
}
}
}
+QList <int> ClipItem::updatePanZoom(int width, int height, int cut)
+{
+ QList <int> effectPositions;
+ for (int i = 0; i < m_effectList.count(); i++) {
+ QDomElement effect = m_effectList.at(i);
+ QDomNodeList params = effect.elementsByTagName("parameter");
+ for (int j = 0; j < params.count(); j++) {
+ QDomElement e = params.item(j).toElement();
+ if (e.isNull())
+ continue;
+ if (e.attribute("type") == "geometry" && !e.hasAttribute("fixed")) {
+ effectPositions << i;
+
+ int in = cropStart().frames(fps());
+ int out = in + cropDuration().frames(fps());
+ if (in < 0) {
+ out -= in;
+ in = 0;
+ }
+ int dur = out - in - 1;
+
+ effect.setAttribute("in", in);
+ effect.setAttribute("out", out);
+
+ Mlt::Geometry geometry(e.attribute("value").toUtf8().data(), dur, width, height);
+ Mlt::GeometryItem item;
+ bool endFrameAdded = false;
+ if (cut == 0) {
+ while (!geometry.next_key(&item, dur)) {
+ if (!endFrameAdded) {
+ // add keyframe at the end with interpolated value
+
+ // but only once ;)
+ endFrameAdded = true;
+
+ Mlt::GeometryItem endItem;
+ Mlt::GeometryItem interp;
+ geometry.fetch(&interp, dur - 1);
+ endItem.frame(dur - 1);
+ endItem.x(interp.x());
+ endItem.y(interp.y());
+ endItem.w(interp.w());
+ endItem.h(interp.h());
+ endItem.mix(interp.mix());
+ geometry.insert(&endItem);
+ }
+ geometry.remove(item.frame());
+ }
+ } else {
+ Mlt::Geometry origGeometry(e.attribute("value").toUtf8().data(), dur, width, height);
+ // remove keyframes before cut point
+ while (!geometry.prev_key(&item, cut - 1) && item.frame() < cut)
+ geometry.remove(item.frame());
+
+ // add a keyframe at new pos 0
+ origGeometry.fetch(&item, cut);
+ item.frame(0);
+ geometry.insert(&item);
+
+ // move exisiting keyframes by -cut
+ while (!origGeometry.next_key(&item, cut)) {
+ geometry.remove(item.frame());
+ origGeometry.remove(item.frame());
+ item.frame(item.frame() - cut);
+ geometry.insert(&item);
+ }
+
+ }
+
+ e.setAttribute("value", geometry.serialise());
+ }
+ }
+ }
+
+ return effectPositions;
+}
#include "clipitem.moc"
* @param current New crop value
* @param fromStart true = crop from start, false = crop from end
* @return true if anything was modified */
- bool checkEffectsKeyframesPos(const int previous, const int current, bool fromStart, int renderWidth = 0, int renderHeight = 0);
+ bool checkEffectsKeyframesPos(const int previous, const int current, bool fromStart);
void insertKeyframe(QDomElement effect, int pos, int val);
void movedKeyframe(QDomElement effect, int oldpos, int newpos, double value);
void updateKeyframes(QDomElement effect);
+ /** @brief Updates the keyframes in the pan and zoom effect to fit the clips cropDuration.
+ * @param width Render width
+ * @param height Render height
+ * @param cut (optional) if clip was cut, cut position relative to the original's clip position
+ * @return List of the pan and zoom effects indexes
+ *
+ * Can be used for all effects using mlt_geometry with keyframes, but at the moment Pan & Zoom is the only one. */
+ QList <int> updatePanZoom(int width, int height, int cut = 0);
protected:
//virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event);
slotRefreshEffects(item);
if (dup->checkKeyFrames())
slotRefreshEffects(dup);
+
+ updatePanZoom(item);
+ updatePanZoom(dup, cutTime - item->startPos());
+
item->baseClip()->addReference();
m_document->updateClip(item->baseClip()->getId());
setDocumentModified();
bool success = m_document->renderer()->mltResizeClipEnd(clipinfo, info.endPos - info.startPos);
if (success) {
item->resizeEnd((int) info.endPos.frames(m_document->fps()));
+
+ updatePanZoom(item);
+
setDocumentModified();
} else {
emit displayMessage(i18n("Error when resizing clip"), ErrorMessage);
}
}
- /*int panZoomPos = clip->hasEffect("affine", "pan_zoom");
- if (panZoomPos != -1) {
- doc.appendChild(doc.importNode(clip->effectAt(panZoomPos), true));
- indexes.append(panZoomPos);
- }*/
+ updatePanZoom(clip);
- if (clip->checkEffectsKeyframesPos(oldInfo.cropStart.frames(m_document->fps()), clip->cropStart().frames(m_document->fps()), true, m_document->width(), m_document->height())) {
+ if (clip->checkEffectsKeyframesPos(oldInfo.cropStart.frames(m_document->fps()), clip->cropStart().frames(m_document->fps()), true)) {
// Keyframes were modified, updateClip
QDomNodeList effs = doc.elementsByTagName("effect");
// Hack:
indexes.append(i);
}
}
+
+ updatePanZoom(clip);
- if (clip->checkEffectsKeyframesPos((oldInfo.cropStart + oldInfo.endPos - oldInfo.startPos).frames(m_document->fps()) - 1, (clip->cropStart() + clip->cropDuration()).frames(m_document->fps()) - 1, false, m_document->width(), m_document->height())) {
+ if (clip->checkEffectsKeyframesPos((oldInfo.cropStart + oldInfo.endPos - oldInfo.startPos).frames(m_document->fps()) - 1, (clip->cropStart() + clip->cropDuration()).frames(m_document->fps()) - 1, false)) {
// Keyframes were modified, updateClip
QDomNodeList effs = doc.elementsByTagName("effect");
// Hack:
}
}
return parameters;
-}
\ No newline at end of file
+}
+
+void CustomTrackView::updatePanZoom(ClipItem* item, GenTime cutPos)
+{
+ QList <int> effects = item->updatePanZoom(m_document->width(), m_document->height(), cutPos.frames(m_document->fps()));
+ for (int i = 0; i < effects.count(); ++i) {
+ if (!m_document->renderer()->mltEditEffect(m_document->tracksCount() - item->track(), item->startPos(), getEffectArgs(item->effectAt(effects.at(i)))))
+ emit displayMessage(i18n("Problem editing effect"), ErrorMessage);
+
+ // if effect is displayed, update the effect edit widget with new clip duration
+ if (item->isSelected() && effects.at(i) == item->selectedEffectIndex())
+ emit clipItemSelected(item, effects.at(i));
+ }
+}
/** @brief Gets the effect parameters that will be passed to Mlt. */
EffectsParameterList getEffectArgs(const QDomElement effect);
+ /** @brief Updates @param item's pan and zoom effect after resize or cut.
+ * @param item clip whose pan and zoom effect should be updated
+ * @param cutPos (optional) if clip was cut, cut position relative to the original's clip position
+ *
+ */
+ void updatePanZoom(ClipItem *item, GenTime cutPos = GenTime());
+
private slots:
void slotRefreshGuides();
void slotEnableRefresh();