X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fclipitem.cpp;h=f3a3babab39b555d59972190935b49174155802a;hb=4e1438fe486d77af1afb75825f3aa1f766715e6f;hp=91e3f583a0afc27f9f5b4d957d8d2b2c97e1f8ea;hpb=d2455bcfbc60918aa52a8bc9ebe30a721148c3cf;p=kdenlive diff --git a/src/clipitem.cpp b/src/clipitem.cpp index 91e3f583..f3a3baba 100644 --- a/src/clipitem.cpp +++ b/src/clipitem.cpp @@ -309,9 +309,14 @@ void ClipItem::initEffect(QDomElement effect, int diff) bool ClipItem::checkKeyFrames() { bool clipEffectsModified = false; - for (int ix = 0; ix < m_effectList.count(); ix ++) { - QString kfr = keyframes(ix); - if (!kfr.isEmpty()) { + // go through all effects this clip has + for (int ix = 0; ix < m_effectList.count(); ++ix) { + QStringList keyframeParams = keyframes(ix); + QStringList newKeyFrameParams; + bool effModified = false; + + // go through all params which have keyframes + foreach(const QString &kfr, keyframeParams) { const QStringList keyframes = kfr.split(';', QString::SkipEmptyParts); QStringList newKeyFrames; bool cutKeyFrame = false; @@ -320,6 +325,8 @@ bool ClipItem::checkKeyFrames() double lastValue = -1; int start = cropStart().frames(m_fps); int end = (cropStart() + cropDuration()).frames(m_fps); + + // go through all keyframes for one param foreach(const QString &str, keyframes) { int pos = str.section(':', 0, 0).toInt(); double val = str.section(':', 1, 1).toDouble(); @@ -355,26 +362,32 @@ bool ClipItem::checkKeyFrames() lastPos = pos; lastValue = val; } - if (modified) { - // update KeyFrames - setKeyframes(ix, newKeyFrames.join(";")); - clipEffectsModified = true; - } + + newKeyFrameParams.append(newKeyFrames.join(";")); + if (modified) + effModified = true; + } + + if (effModified) { + // update KeyFrames + setKeyframes(ix, newKeyFrameParams); + clipEffectsModified = true; } } return clipEffectsModified; } -void ClipItem::setKeyframes(const int ix, const QString keyframes) +void ClipItem::setKeyframes(const int ix, const QStringList keyframes) { QDomElement effect = getEffectAt(ix); if (effect.attribute("disable") == "1") return; QDomNodeList params = effect.elementsByTagName("parameter"); + int keyframeParams = 0; for (int i = 0; i < params.count(); i++) { QDomElement e = params.item(i).toElement(); if (!e.isNull() && (e.attribute("type") == "keyframe" || e.attribute("type") == "simplekeyframe")) { - e.setAttribute("keyframes", keyframes); - if (ix == m_selectedEffect) { + e.setAttribute("keyframes", keyframes.at(keyframeParams)); + if (ix == m_selectedEffect && keyframeParams == 0) { m_keyframes.clear(); double max = e.attribute("max").toDouble(); double min = e.attribute("min").toDouble(); @@ -391,9 +404,8 @@ void ClipItem::setKeyframes(const int ix, const QString keyframes) if (m_keyframes.find(m_editedKeyframe) == m_keyframes.end()) m_editedKeyframe = -1; if (m_keyframes.find(m_editedKeyframe) == m_keyframes.end()) m_editedKeyframe = -1; update(); - return; } - break; + ++keyframeParams; } } } @@ -435,18 +447,16 @@ void ClipItem::setSelectedEffect(const int ix) } } -QString ClipItem::keyframes(const int index) +QStringList ClipItem::keyframes(const int index) { - QString result; + QStringList result; QDomElement effect = effectAt(index); QDomNodeList params = effect.elementsByTagName("parameter"); for (int i = 0; i < params.count(); i++) { QDomElement e = params.item(i).toElement(); - if (!e.isNull() && (e.attribute("type") == "keyframe" || e.attribute("type") == "simplekeyframe")) { - result = e.attribute("keyframes"); - break; - } + if (!e.isNull() && (e.attribute("type") == "keyframe" || e.attribute("type") == "simplekeyframe")) + result.append(e.attribute("keyframes")); } return result; } @@ -504,11 +514,10 @@ void ClipItem::refreshClip(bool checkDuration) if (m_info.cropStart > m_maxDuration) { m_info.cropStart = GenTime(); m_info.cropDuration = qMin(m_info.cropDuration, m_maxDuration); - updateRectGeometry(); } else { m_info.cropDuration = m_maxDuration; - updateRectGeometry(); } + updateRectGeometry(); } } } @@ -646,12 +655,7 @@ DocClipBase *ClipItem::baseClip() const QDomElement ClipItem::xml() const { - QDomElement xml = m_clip->toXML(); - if (m_speed != 1.0) xml.setAttribute("speed", m_speed); - if (m_strobe > 1) xml.setAttribute("strobe", m_strobe); - if (m_audioOnly) xml.setAttribute("audio_only", 1); - else if (m_videoOnly) xml.setAttribute("video_only", 1); - return xml; + return itemXml(); } QDomElement ClipItem::itemXml() const @@ -741,8 +745,10 @@ void ClipItem::paint(QPainter *painter, painter->drawLine(l2); } if (painter->matrix().m11() == FRAME_SIZE) { - int offset = (m_info.startPos + m_info.cropStart).frames(m_fps); - doGetIntraThumbs(painter, mapped.topLeft(), m_info.cropStart.frames(m_fps), (int) mapToScene(exposed.left(), 0).x() - offset, (int) mapToScene(exposed.right(), 0).x() - offset); + int offset = (m_info.startPos - m_info.cropStart).frames(m_fps); + int left = qMax((int) m_info.startPos.frames(m_fps) + 1, (int) mapToScene(exposed.left(), 0).x()); + int right = qMin((int)(m_info.startPos + m_info.cropDuration).frames(m_fps) - 1, (int) mapToScene(exposed.right(), 0).x()); + doGetIntraThumbs(painter, mapped.topLeft(), m_info.cropStart.frames(m_fps), left - offset, right - offset); } painter->setPen(Qt::black); } @@ -975,7 +981,6 @@ QList ClipItem::snapMarkers() const GenTime pos; for (int i = 0; i < markers.size(); i++) { - pos = GenTime((int)(markers.at(i).frames(m_fps) / qAbs(m_speed) + 0.5), m_fps) - cropStart(); if (pos > GenTime()) { if (pos > cropDuration()) break; @@ -1156,7 +1161,7 @@ void ClipItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *) } */ -void ClipItem::resizeStart(int posx, bool) +void ClipItem::resizeStart(int posx, bool /*size*/) { bool sizeLimit = false; if (clipType() != IMAGE && clipType() != COLOR && clipType() != TEXT) { @@ -1205,12 +1210,13 @@ void ClipItem::resizeEnd(int posx) bool ClipItem::checkEffectsKeyframesPos(const int previous, const int current, bool fromStart) { - bool modified = false; + bool effModified = false; 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(i).toElement(); + bool modified = false; + QDomElement e = params.item(j).toElement(); if (!e.isNull() && (e.attribute("type") == "keyframe" || e.attribute("type") == "simplekeyframe")) { // parse keyframes and adjust values const QStringList keyframes = e.attribute("keyframes").split(';', QString::SkipEmptyParts); @@ -1221,16 +1227,19 @@ bool ClipItem::checkEffectsKeyframesPos(const int previous, const int current, b pos = str.section(':', 0, 0).toInt(); val = str.section(':', 1, 1).toDouble(); if (pos == previous) { + // first or last keyframe kfr[current] = val; modified = true; } else { if ((fromStart && pos >= current) || (!fromStart && pos <= current)) { + // only keyframes in range kfr[pos] = val; modified = true; } } } if (modified) { + effModified = true; QString newkfr; QMap::const_iterator k = kfr.constBegin(); while (k != kfr.constEnd()) { @@ -1238,13 +1247,12 @@ bool ClipItem::checkEffectsKeyframesPos(const int previous, const int current, b ++k; } e.setAttribute("keyframes", newkfr); - break; } } } } - if (modified && m_selectedEffect >= 0) setSelectedEffect(m_selectedEffect); - return modified; + if (effModified && m_selectedEffect >= 0) setSelectedEffect(m_selectedEffect); + return effModified; } //virtual @@ -1402,11 +1410,22 @@ EffectsParameterList ClipItem::addEffect(const QDomElement effect, bool /*animat if (effect.hasAttribute("src")) parameters.addParam("src", effect.attribute("src")); if (effect.hasAttribute("disable")) parameters.addParam("disable", effect.attribute("disable")); - QString effectId = effect.attribute("id"); if (effectId.isEmpty()) effectId = effect.attribute("tag"); parameters.addParam("id", effectId); + // special case: the affine effect need in / out points + if (effectId == "pan_zoom") { + int start = cropStart().frames(m_fps); + int end = (cropStart() + cropDuration()).frames(m_fps); + if (start < 0) { + end -= start; + start = 0; + } + parameters.addParam("in", QString::number(start)); + parameters.addParam("out", QString::number(end)); + } + QDomNodeList params = effect.elementsByTagName("parameter"); int fade = 0; for (int i = 0; i < params.count(); i++) { @@ -1510,10 +1529,13 @@ EffectsParameterList ClipItem::getEffectArgs(const QDomElement effect) { EffectsParameterList parameters; parameters.addParam("tag", effect.attribute("tag")); + if (effect.hasAttribute("region")) parameters.addParam("region", effect.attribute("region")); parameters.addParam("kdenlive_ix", effect.attribute("kdenlive_ix")); parameters.addParam("id", effect.attribute("id")); if (effect.hasAttribute("src")) parameters.addParam("src", effect.attribute("src")); if (effect.hasAttribute("disable")) parameters.addParam("disable", effect.attribute("disable")); + if (effect.hasAttribute("in")) parameters.addParam("in", effect.attribute("in")); + if (effect.hasAttribute("out")) parameters.addParam("out", effect.attribute("out")); QDomNodeList params = effect.elementsByTagName("parameter"); for (int i = 0; i < params.count(); i++) { @@ -1624,8 +1646,8 @@ int ClipItem::strobe() const void ClipItem::setSpeed(const double speed, const int strobe) { m_speed = speed; - if (m_speed <= 0 && m_speed > -1) - m_speed = 1.0; + if (m_speed <= 0 && m_speed > -1) + m_speed = 1.0; m_strobe = strobe; if (m_speed == 1.0) m_clipName = baseClip()->name(); else m_clipName = baseClip()->name() + " - " + QString::number(speed * 100, 'f', 0) + '%';