From: Jean-Baptiste Mardelle Date: Thu, 30 Oct 2008 16:52:44 +0000 (+0000) Subject: Workaround problems with clip transparency. Transparency is now achieved by inserting... X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=ff7d517ae54b265c5769a4c411ffa0671f0f9aab;p=kdenlive Workaround problems with clip transparency. Transparency is now achieved by inserting a transition in timeline. This "automatic" transition moves automatically with the clip (at least it tries). Probably not perfect but I think it is an acceptable workaround for: http://www.kdenlive.org:80/mantis/view.php?id=220 svn path=/branches/KDE4/; revision=2600 --- diff --git a/src/clipitem.cpp b/src/clipitem.cpp index 21746741..e9f81b2c 100644 --- a/src/clipitem.cpp +++ b/src/clipitem.cpp @@ -709,11 +709,7 @@ OPERATIONTYPE ClipItem::operationMode(QPointF pos) { } QRectF rect = sceneBoundingRect(); const double scale = projectScene()->scale(); - double maximumOffset; - if (scale > 3) maximumOffset = 25 / scale; - else maximumOffset = 6 / scale; - - //kDebug()<<"// Item rect: "<setText(props.value("channels")); CLIPTYPE t = m_clip->clipType(); + if (t != AUDIO && t != AV) { + m_view.clip_force_aindex->setEnabled(false); + } + + if (t != VIDEO && t != AV) { + m_view.clip_force_vindex->setEnabled(false); + } + if (t == IMAGE) { m_view.tabWidget->removeTab(SLIDETAB); m_view.tabWidget->removeTab(COLORTAB); diff --git a/src/customtrackview.cpp b/src/customtrackview.cpp index a354d524..ac804748 100644 --- a/src/customtrackview.cpp +++ b/src/customtrackview.cpp @@ -1128,6 +1128,13 @@ void CustomTrackView::dropEvent(QDropEvent * event) { m_document->updateClip(item->baseClip()->getId()); ItemInfo info; info = item->info(); + if (item->baseClip()->isTransparent()) { + // add transparency transition + int endTrack = getPreviousVideoTrack(info.track); + Transition *tr = new Transition(info, endTrack, m_document->fps(), MainWindow::transitions.getEffectByTag("composite", "alphatransparency"), true); + scene()->addItem(tr); + m_document->renderer()->mltAddTransition(tr->transitionTag(), endTrack, m_scene->m_tracksList.count() - info.track, info.startPos, info.endPos, tr->toXML()); + } info.track = m_scene->m_tracksList.count() - item->track(); m_document->renderer()->mltInsertClip(info, item->xml(), item->baseClip()->producer()); item->setSelected(true); @@ -1274,6 +1281,16 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event) { if (success) { MoveClipCommand *command = new MoveClipCommand(this, m_dragItemInfo, info, false); m_commandStack->push(command); + ClipItem *item = static_cast (m_dragItem); + if (item->baseClip()->isTransparent()) { + // Also move automatic transition + Transition *tr = getTransitionItemAt((int) m_dragItemInfo.startPos.frames(m_document->fps()) + 1, m_dragItemInfo.track); + if (tr && tr->isAutomatic()) { + tr->updateTransitionEndTrack(getPreviousVideoTrack(info.track)); + m_document->renderer()->mltMoveTransition(tr->transitionTag(), m_scene->m_tracksList.count() - m_dragItemInfo.track, m_scene->m_tracksList.count() - info.track, tr->transitionEndTrack(), m_dragItemInfo.startPos, m_dragItemInfo.endPos, info.startPos, info.endPos); + tr->setPos((int) info.startPos.frames(m_document->fps()), (int)(info.track * m_tracksHeight + 1)); + } + } } else { // undo last move and emit error message MoveClipCommand *command = new MoveClipCommand(this, info, m_dragItemInfo, true); @@ -1459,6 +1476,16 @@ void CustomTrackView::deleteClip(ItemInfo info) { if (item->isSelected()) emit clipItemSelected(NULL); item->baseClip()->removeReference(); m_document->updateClip(item->baseClip()->getId()); + + if (item->baseClip()->isTransparent()) { + // also remove automatic transition + Transition *tr = getTransitionItemAt((int) info.startPos.frames(m_document->fps()) + 1, info.track); + if (tr && tr->isAutomatic()) { + m_document->renderer()->mltDeleteTransition(tr->transitionTag(), tr->transitionEndTrack(), m_scene->m_tracksList.count() - info.track, info.startPos, info.endPos, tr->toXML()); + scene()->removeItem(tr); + delete tr; + } + } scene()->removeItem(item); delete item; m_document->renderer()->mltRemoveClip(m_scene->m_tracksList.count() - info.track, info.startPos); @@ -1549,6 +1576,14 @@ void CustomTrackView::addClip(QDomElement xml, const QString &clipId, ItemInfo i ClipItem *item = new ClipItem(baseclip, info, m_document->fps()); item->setEffectList(effects); scene()->addItem(item); + if (item->baseClip()->isTransparent()) { + // add transparency transition + int endTrack = getPreviousVideoTrack(info.track); + Transition *tr = new Transition(info, endTrack, m_document->fps(), MainWindow::transitions.getEffectByTag("composite", "alphatransparency"), true); + scene()->addItem(tr); + m_document->renderer()->mltAddTransition(tr->transitionTag(), endTrack, m_scene->m_tracksList.count() - info.track, info.startPos, info.endPos, tr->toXML()); + } + baseclip->addReference(); m_document->updateClip(baseclip->getId()); info.track = m_scene->m_tracksList.count() - info.track; @@ -1621,6 +1656,15 @@ void CustomTrackView::moveClip(const ItemInfo start, const ItemInfo end) { bool success = m_document->renderer()->mltMoveClip((int)(m_scene->m_tracksList.count() - start.track), (int)(m_scene->m_tracksList.count() - end.track), (int) start.startPos.frames(m_document->fps()), (int)end.startPos.frames(m_document->fps())); if (success) { item->setPos((int) end.startPos.frames(m_document->fps()), (int)(end.track * m_tracksHeight + 1)); + if (item->baseClip()->isTransparent()) { + // Also move automatic transition + Transition *tr = getTransitionItemAt((int) start.startPos.frames(m_document->fps()) + 1, start.track); + if (tr && tr->isAutomatic()) { + tr->updateTransitionEndTrack(getPreviousVideoTrack(end.track)); + m_document->renderer()->mltMoveTransition(tr->transitionTag(), m_scene->m_tracksList.count() - start.track, m_scene->m_tracksList.count() - end.track, tr->transitionEndTrack(), start.startPos, start.endPos, end.startPos, end.endPos); + tr->setPos((int) end.startPos.frames(m_document->fps()), (int)(end.track * m_tracksHeight + 1)); + } + } } else { // undo last move and emit error message emit displayMessage(i18n("Cannot move clip to position %1seconds", QString::number(end.startPos.seconds(), 'g', 2)), ErrorMessage); diff --git a/src/initeffects.cpp b/src/initeffects.cpp index b4805ee6..4d8a5bab 100644 --- a/src/initeffects.cpp +++ b/src/initeffects.cpp @@ -653,10 +653,15 @@ void initEffects::fillTransitionsList(Mlt::Repository * repository, EffectsList* */ } - QString wipetrans = "WipeSlide image from one side to anotherDirection Align"; + QString wipetrans = "WipeSlide image from one side to anotherDirection Align"; QDomDocument ret; ret.setContent(wipetrans); transitions->append(ret.documentElement()); + + QString alphatrans = "Alpha transparencyMake alpha channel transparentDirectionRescaleAlign"; + QDomDocument ret2; + ret2.setContent(alphatrans); + transitions->append(ret2.documentElement()); } QDomElement initEffects::quickParameterFill(QDomDocument & doc, QString name, QString tag, QString type, QString def, QString min, QString max, QString list, QString listdisplaynames, QString factor, QString namedesc, QString format) { diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index c1b2073d..7e2ed60c 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -285,9 +285,15 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, QWidget *parent QMenu *transitionsMenu = new QMenu(i18n("Add Transition"), this); QStringList effects = transitions.effectNames(); - foreach(const QString &name, effects) { - action = new QAction(name, this); - action->setData(name); + + effectsList.clear(); + for (int ix = 0; ix < transitions.count(); ix++) { + effectInfo = transitions.effectIdInfo(ix); + effectsList.insert(effectInfo.at(0).toLower(), effectInfo); + } + foreach(QStringList value, effectsList) { + action = new QAction(value.at(0), this); + action->setData(value); transitionsMenu->addAction(action); } connect(transitionsMenu, SIGNAL(triggered(QAction *)), this, SLOT(slotAddTransition(QAction *))); @@ -1473,9 +1479,12 @@ void MainWindow::slotAddProjectClip(KUrl url) { void MainWindow::slotAddTransition(QAction *result) { if (!result) return; - QDomElement effect = transitions.getEffectByName(result->data().toString()); + QStringList info = result->data().toStringList(); + if (info.isEmpty()) return; + QDomElement transition = transitions.getEffectByTag(info.at(1), info.at(2)); + //QDomElement effect = transitions.getEffectByName(result->data().toString()); if (m_activeTimeline) { - m_activeTimeline->projectView()->slotAddTransitionToSelectedClips(effect); + m_activeTimeline->projectView()->slotAddTransitionToSelectedClips(transition); } } diff --git a/src/renderer.cpp b/src/renderer.cpp index 44075de0..36df5e29 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -1308,8 +1308,8 @@ void Render::mltInsertClip(ItemInfo info, QDomElement element, Mlt::Producer *pr Mlt::Producer *clip = prod->cut((int) info.cropStart.frames(m_fps), (int)(info.endPos - info.startPos + info.cropStart).frames(m_fps) - 1); int newIndex = trackPlaylist.insert_at((int) info.startPos.frames(m_fps), *clip, 1); - if (QString(prod->get("transparency")).toInt() == 1) - mltAddClipTransparency(info, info.track - 1, QString(prod->get("id")).toInt()); + /*if (QString(prod->get("transparency")).toInt() == 1) + mltAddClipTransparency(info, info.track - 1, QString(prod->get("id")).toInt());*/ mlt_service_unlock(service.get_service()); @@ -1427,8 +1427,8 @@ bool Render::mltRemoveClip(int track, GenTime position) { Mlt::Producer clip(trackPlaylist.get_clip(clipIndex)); trackPlaylist.replace_with_blank(clipIndex); trackPlaylist.consolidate_blanks(0); - if (QString(clip.parent().get("transparency")).toInt() == 1) - mltDeleteTransparency((int) position.frames(m_fps), track, QString(clip.parent().get("id")).toInt()); + /*if (QString(clip.parent().get("transparency")).toInt() == 1) + mltDeleteTransparency((int) position.frames(m_fps), track, QString(clip.parent().get("id")).toInt());*/ /* // Display playlist info kDebug()<<"//// AFTER"; @@ -1854,20 +1854,9 @@ bool Render::mltResizeClipEnd(ItemInfo info, GenTime clipDuration) { trackPlaylist.consolidate_blanks(0); - /* // Display playlist info - kDebug()<<"//////////// AFTER RESIZE"; - for (int i = 0; i < trackPlaylist.count(); i++) { - int blankStart = trackPlaylist.clip_start(i); - int blankDuration = trackPlaylist.clip_length(i) - 1; - QString blk; - if (trackPlaylist.is_blank(i)) blk = "(blank)"; - kDebug()<<"CLIP "<refresh(); - //tractor.refresh(); if (info.track != 0 && clipIndex == trackPlaylist.count()) mltCheckLength(); - if (QString(clip->parent().get("transparency")).toInt() == 1) { + /*if (QString(clip->parent().get("transparency")).toInt() == 1) { //mltResizeTransparency(previousStart, previousStart, previousStart + newDuration, track, QString(clip->parent().get("id")).toInt()); mltDeleteTransparency(info.startPos.frames(m_fps), info.track, QString(clip->parent().get("id")).toInt()); ItemInfo transpinfo; @@ -1875,7 +1864,7 @@ bool Render::mltResizeClipEnd(ItemInfo info, GenTime clipDuration) { transpinfo.endPos = info.startPos + clipDuration; transpinfo.track = info.track; mltAddClipTransparency(transpinfo, info.track - 1, QString(clip->parent().get("id")).toInt()); - } + }*/ m_isBlocked = false; return true; } @@ -1939,7 +1928,7 @@ bool Render::mltResizeClipStart(ItemInfo info, GenTime diff) { else trackPlaylist.resize_clip(blankIndex, 0, blankLength + moveFrame - 1); } trackPlaylist.consolidate_blanks(0); - if (QString(clip->parent().get("transparency")).toInt() == 1) { + /*if (QString(clip->parent().get("transparency")).toInt() == 1) { //mltResizeTransparency(previousStart, (int) moveEnd.frames(m_fps), (int) (moveEnd + out - in).frames(m_fps), track, QString(clip->parent().get("id")).toInt()); mltDeleteTransparency(info.startPos.frames(m_fps), info.track, QString(clip->parent().get("id")).toInt()); ItemInfo transpinfo; @@ -1947,7 +1936,7 @@ bool Render::mltResizeClipStart(ItemInfo info, GenTime diff) { transpinfo.endPos = info.startPos + diff + (info.endPos - info.startPos); transpinfo.track = info.track; mltAddClipTransparency(transpinfo, info.track - 1, QString(clip->parent().get("id")).toInt()); - } + }*/ m_isBlocked = false; //m_mltConsumer->set("refresh", 1); mlt_service_unlock(service.get_service()); @@ -1987,9 +1976,9 @@ bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEn } else { trackPlaylist.consolidate_blanks(0); int newIndex = trackPlaylist.insert_at(moveEnd, clipProducer, 1); - if (QString(clipProducer.parent().get("transparency")).toInt() == 1) { + /*if (QString(clipProducer.parent().get("transparency")).toInt() == 1) { mltMoveTransparency(moveStart, moveEnd, startTrack, endTrack, QString(clipProducer.parent().get("id")).toInt()); - } + }*/ if (newIndex + 1 == trackPlaylist.count()) checkLength = true; } //mlt_service_unlock(service.get_service()); @@ -2007,10 +1996,10 @@ bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEn destTrackPlaylist.consolidate_blanks(1); int newIndex = destTrackPlaylist.insert_at(moveEnd, clipProducer, 1); destTrackPlaylist.consolidate_blanks(0); - if (QString(clipProducer.parent().get("transparency")).toInt() == 1) { + /*if (QString(clipProducer.parent().get("transparency")).toInt() == 1) { kDebug() << "//////// moving clip transparency"; mltMoveTransparency(moveStart, moveEnd, startTrack, endTrack, QString(clipProducer.parent().get("id")).toInt()); - } + }*/ if (clipIndex > trackPlaylist.count()) checkLength = true; else if (newIndex + 1 == destTrackPlaylist.count()) checkLength = true; } @@ -2167,7 +2156,7 @@ void Render::mltDeleteTransition(QString tag, int a_track, int b_track, GenTime mlt_type = mlt_properties_get(properties, "mlt_type"); resource = mlt_properties_get(properties, "mlt_service"); } - if (do_refresh) m_mltConsumer->set("refresh", 1); + //if (do_refresh) m_mltConsumer->set("refresh", 1); } QMap Render::mltGetTransitionParamsFromXml(QDomElement xml) { @@ -2357,8 +2346,8 @@ void Render::mltAddTransition(QString tag, int a_track, int b_track, GenTime in, transition->set_in_and_out((int) in.frames(m_fps), (int) out.frames(m_fps)); QMap::Iterator it; QString key; - - kDebug() << " ------ ADDING TRANSITION PARAMs: " << args.count(); + if (xml.attribute("automatic") == "1") transition->set("automatic", 1); + //kDebug() << " ------ ADDING TRANSITION PARAMs: " << args.count(); for (it = args.begin(); it != args.end(); ++it) { key = it.key(); diff --git a/src/trackview.cpp b/src/trackview.cpp index d2028873..de5eb9bd 100644 --- a/src/trackview.cpp +++ b/src/trackview.cpp @@ -177,6 +177,8 @@ void TrackView::parseDocument(QDomDocument doc) { bool transitionAdd = true; int a_track = 0; int b_track = 0; + bool isAutomatic = false; + QString mlt_geometry; QString mlt_service; for (int k = 0; k < transitionparams.count(); k++) { p = transitionparams.item(k).toElement(); @@ -186,16 +188,45 @@ void TrackView::parseDocument(QDomDocument doc) { if (paramName == "internal_added" && p.text() == "237") { transitionAdd = false; //kDebug() << "// TRANSITRION " << i << " IS NOT VALID (INTERN ADDED)"; - break; + //break; } else if (paramName == "a_track") a_track = p.text().toInt(); else if (paramName == "b_track") b_track = m_projectTracks - 1 - p.text().toInt(); else if (paramName == "mlt_service") mlt_service = p.text(); + else if (paramName == "geometry") mlt_geometry = p.text(); + else if (paramName == "automatic" && p.text() == "1") isAutomatic = true;; } } - if (transitionAdd) { + if (transitionAdd || mlt_service != "mix") { // Transition should be added to the scene ItemInfo transitionInfo; - QDomElement base = MainWindow::transitions.getEffectByTag(mlt_service, QString()).cloneNode().toElement(); + QString transitionId; + if (mlt_service == "composite") { + kDebug() << "//////////\n\nADDING COMPO TRANS\n\n " << mlt_geometry << "\n\n//////////"; + if (mlt_geometry == "0%,0%:100%x100%") transitionId = "alphatransparency"; + else if (mlt_geometry.count(';') == 1) { + mlt_geometry.remove(QChar('%'), Qt::CaseInsensitive); + mlt_geometry.replace(QChar('x'), QChar(','), Qt::CaseInsensitive); + QString start = mlt_geometry.section(';', 0, 0); + start = start.section(':', 0, 1); + start.replace(QChar(':'), QChar(','), Qt::CaseInsensitive); + QString end = mlt_geometry.section('=', 1, 1); + end = end.section(':', 0, 1); + end.replace(QChar(':'), QChar(','), Qt::CaseInsensitive); + start.append(',' + end); + QStringList numbers = start.split(',', QString::SkipEmptyParts); + bool isWipeTransition = true; + int checkNumber; + for (int i = 0; i < numbers.size(); ++i) { + checkNumber = qAbs(numbers.at(i).toInt()); + if (checkNumber != 0 && checkNumber != 100) { + isWipeTransition = false; + break; + } + } + if (isWipeTransition) transitionId = "wipe"; + } + } + QDomElement base = MainWindow::transitions.getEffectByTag(mlt_service, transitionId).cloneNode().toElement(); for (int k = 0; k < transitionparams.count(); k++) { p = transitionparams.item(k).toElement(); @@ -229,7 +260,7 @@ void TrackView::parseDocument(QDomDocument doc) { transitionInfo.endPos = GenTime(e.attribute("out").toInt(), m_doc->fps()); transitionInfo.track = b_track; //kDebug() << "/////////////// +++++++++++ ADDING TRANSITION ON TRACK: " << b_track << ", TOTAL TRKA: " << m_projectTracks; - Transition *tr = new Transition(transitionInfo, a_track, m_doc->fps(), base); + Transition *tr = new Transition(transitionInfo, a_track, m_doc->fps(), base, isAutomatic); m_scene->addItem(tr); } } diff --git a/src/transition.cpp b/src/transition.cpp index b4d71c7d..2ed6523a 100644 --- a/src/transition.cpp +++ b/src/transition.cpp @@ -33,7 +33,7 @@ #include "customtrackscene.h" #include "mainwindow.h" -Transition::Transition(const ItemInfo info, int transitiontrack, double fps, QDomElement params) : AbstractClipItem(info, QRectF(), fps), m_gradient(QLinearGradient(0, 0, 0, 0)) { +Transition::Transition(const ItemInfo info, int transitiontrack, double fps, QDomElement params, bool automaticTransition) : AbstractClipItem(info, QRectF(), fps), m_gradient(QLinearGradient(0, 0, 0, 0)), m_automaticTransition(automaticTransition) { setRect(0, 0, (qreal)(info.endPos - info.startPos).frames(fps) - 0.02, (qreal)(KdenliveSettings::trackheight() / 3 * 2 - 1)); setPos((qreal) info.startPos.frames(fps), (qreal)(info.track * KdenliveSettings::trackheight() + KdenliveSettings::trackheight() / 3 * 2)); @@ -52,7 +52,8 @@ Transition::Transition(const ItemInfo info, int transitiontrack, double fps, QDo } else { m_parameters = params; } - + if (m_automaticTransition) m_parameters.setAttribute("automatic", 1); + else if (m_parameters.attribute("automatic") == "1") m_automaticTransition = true; m_name = m_parameters.elementsByTagName("name").item(0).toElement().text(); m_secondClip = 0; setFlags(QGraphicsItem::ItemClipsToShape | QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable); @@ -78,6 +79,10 @@ QString Transition::transitionTag() const { return m_parameters.attribute("tag"); } +bool Transition::isAutomatic() const { + return m_automaticTransition; +} + void Transition::setTransitionParameters(const QDomElement params) { m_parameters = params; m_name = m_parameters.elementsByTagName("name").item(0).toElement().text(); @@ -207,9 +212,12 @@ QVariant Transition::itemChange(GraphicsItemChange change, const QVariant &value OPERATIONTYPE Transition::operationMode(QPointF pos) { + const double scale = projectScene()->scale(); + double maximumOffset = 6 / scale; + QRectF rect = sceneBoundingRect(); - if (qAbs((int)(pos.x() - rect.x())) < 6) return RESIZESTART; - else if (qAbs((int)(pos.x() - (rect.right()))) < 6) return RESIZEEND; + if (qAbs((int)(pos.x() - rect.x())) < maximumOffset) return RESIZESTART; + else if (qAbs((int)(pos.x() - (rect.right()))) < maximumOffset) return RESIZEEND; return MOVE; } diff --git a/src/transition.h b/src/transition.h index 41f7d7da..30b81379 100644 --- a/src/transition.h +++ b/src/transition.h @@ -40,7 +40,7 @@ class Transition : public AbstractClipItem { Q_OBJECT public: - Transition(const ItemInfo info, int transitiontrack, double fps, QDomElement params = QDomElement()); + Transition(const ItemInfo info, int transitiontrack, double fps, QDomElement params = QDomElement(), bool automaticTransition = false); virtual ~Transition(); virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, @@ -68,6 +68,7 @@ public: void updateTransitionEndTrack(int newtrack); const ClipItem *referencedClip() const; Transition *clone(); + bool isAutomatic() const; protected: virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); @@ -76,6 +77,9 @@ private: bool m_singleClip; QLinearGradient m_gradient; QString m_name; + + /** true if the transition was added automatically and should be moved with its clip */ + bool m_automaticTransition; /** contains the transition parameters */ QDomElement m_parameters; /** The clip to which the transition is attached */