]> git.sesse.net Git - kdenlive/commitdiff
- Properly handle pan and zoom effect during cut
authorTill Theato <root@ttill.de>
Sun, 5 Sep 2010 12:16:55 +0000 (12:16 +0000)
committerTill Theato <root@ttill.de>
Sun, 5 Sep 2010 12:16:55 +0000 (12:16 +0000)
- Improve handling of pan and zoom effect during resize

svn path=/trunk/kdenlive/; revision=4838

src/clipitem.cpp
src/clipitem.h
src/customtrackview.cpp
src/customtrackview.h

index c2cc136169d78842fb5af6646bfef19dd80c5905..f05103fc281bf973883d0ab79ab48396ccfd864f 100644 (file)
@@ -1210,7 +1210,7 @@ void ClipItem::resizeEnd(int posx)
 }
 
 
-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++) {
@@ -1252,16 +1252,6 @@ bool ClipItem::checkEffectsKeyframesPos(const int previous, const int current, b
                     }
                     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());
             }
         }
     }
@@ -1785,5 +1775,81 @@ void ClipItem::doGetIntraThumbs(QPainter *painter, const QPointF startPos, int o
     }
 }
 
+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"
index 8e474f38740a1b3f8d2a0b1ff71a02f32896f632..473ec862949c0c483a63162ab9755c982aefae35 100644 (file)
@@ -156,10 +156,18 @@ public:
     * @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);
index 4969629f82f9169b848486364780f8249737f621..ce581afd519c3ad1e4786c4d2e19e4b2f90da8dd 100644 (file)
@@ -1990,6 +1990,10 @@ ClipItem *CustomTrackView::cutClip(ItemInfo info, GenTime cutTime, bool cut, boo
             slotRefreshEffects(item);
         if (dup->checkKeyFrames())
             slotRefreshEffects(dup);
+
+        updatePanZoom(item);
+        updatePanZoom(dup, cutTime - item->startPos());
+
         item->baseClip()->addReference();
         m_document->updateClip(item->baseClip()->getId());
         setDocumentModified();
@@ -2031,6 +2035,9 @@ ClipItem *CustomTrackView::cutClip(ItemInfo info, GenTime cutTime, bool cut, boo
         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);
@@ -4408,13 +4415,9 @@ void CustomTrackView::prepareResizeClipStart(AbstractClipItem* item, ItemInfo ol
                 }
             }
 
-            /*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:
@@ -4532,8 +4535,10 @@ void CustomTrackView::prepareResizeClipEnd(AbstractClipItem* item, ItemInfo oldI
                     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:
@@ -6447,4 +6452,17 @@ EffectsParameterList CustomTrackView::getEffectArgs(const QDomElement effect)
         }
     }
     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));
+    }
+}
index 89ecc1684c9d6af266d022899e6c204a33928c13..c437b0731cb2f55632becd53c51a452583ff1bf6 100644 (file)
@@ -392,6 +392,13 @@ private:
     /** @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();