Commit e3b4bf11 authored by Dan Dennedy's avatar Dan Dennedy

Add animation feature to Slideshow Clip.

svn path=/trunk/kdenlive/; revision=4791
parent 2d58605f
......@@ -372,7 +372,10 @@ void ClipManager::slotAddColorClipFile(const QString name, const QString color,
m_doc->commandStack()->push(command);
}
void ClipManager::slotAddSlideshowClipFile(const QString name, const QString path, int count, const QString duration, const bool loop, const bool crop, const bool fade, const QString &luma_duration, const QString &luma_file, const int softness, QString group, const QString &groupId)
void ClipManager::slotAddSlideshowClipFile(const QString name, const QString path, int count, const QString duration,
const bool loop, const bool crop, const bool fade,
const QString &luma_duration, const QString &luma_file, const int softness,
const QString &animation, QString group, const QString &groupId)
{
QDomDocument doc;
QDomElement prod = doc.createElement("producer");
......@@ -391,6 +394,7 @@ void ClipManager::slotAddSlideshowClipFile(const QString name, const QString pat
prod.setAttribute("fade", fade);
prod.setAttribute("softness", QString::number(softness));
prod.setAttribute("luma_file", luma_file);
prod.setAttribute("animation", animation);
if (!group.isEmpty()) {
prod.setAttribute("groupname", group);
prod.setAttribute("groupid", groupId);
......
......@@ -76,7 +76,10 @@ Q_OBJECT public:
void slotAddTextTemplateClip(QString titleName, const KUrl path, const QString group, const QString &groupId);
void slotAddXmlClipFile(const QString name, const QDomElement xml, const QString group, const QString &groupId);
void slotAddColorClipFile(const QString name, const QString color, QString duration, const QString group, const QString &groupId);
void slotAddSlideshowClipFile(const QString name, const QString path, int count, const QString duration, const bool loop, const bool crop, const bool fade, const QString &luma_duration, const QString &luma_file, const int softness, const QString group, const QString &groupId);
void slotAddSlideshowClipFile(const QString name, const QString path, int count, const QString duration,
const bool loop, const bool crop,const bool fade,
const QString &luma_duration, const QString &luma_file, const int softness,
const QString &animation, const QString group, const QString &groupId);
DocClipBase *getClipById(QString clipId);
const QList <DocClipBase *> getClipByResource(QString resource);
void slotDeleteClips(QStringList ids);
......
......@@ -183,11 +183,22 @@ ClipProperties::ClipProperties(DocClipBase *clip, Timecode tc, double fps, QWidg
m_view.image_type->addItem("TGA (*.tga)", "tga");
m_view.image_type->addItem("TIFF (*.tiff)", "tiff");
m_view.image_type->addItem("Open EXR (*.exr)", "exr");
m_view.animation->addItem(i18n("None"), QString());
m_view.animation->addItem(i18n("Pan"), "Pan");
m_view.animation->addItem(i18n("Pan, low-pass"), "Pan, low-pass");
m_view.animation->addItem(i18n("Pan and zoom"), "Pan and zoom");
m_view.animation->addItem(i18n("Pan and zoom, low-pass"), "Pan and zoom, low-pass");
m_view.animation->addItem(i18n("Zoom"), "Zoom");
m_view.animation->addItem(i18n("Zoom, low-pass"), "Zoom, low-pass");
m_view.slide_loop->setChecked(props.value("loop").toInt());
m_view.slide_crop->setChecked(props.value("crop").toInt());
m_view.slide_fade->setChecked(props.value("fade").toInt());
m_view.luma_softness->setValue(props.value("softness").toInt());
if (!props.value("animation").isEmpty())
m_view.animation->setCurrentItem(props.value("animation"));
else
m_view.animation->setCurrentIndex(0);
QString path = props.value("resource");
QString ext = path.section('.', -1);
for (int i = 0; i < m_view.image_type->count(); i++) {
......@@ -631,6 +642,15 @@ QMap <QString, QString> ClipProperties::properties()
}
}
QString animation = m_view.animation->itemData(m_view.animation->currentIndex()).toString();
if (animation != m_old_props.value("animation")) {
if (animation.isEmpty()) {
props["animation"].clear();
} else {
props["animation"] = animation;
}
m_clipNeedsRefresh = true;
}
}
return props;
}
......
......@@ -28,6 +28,7 @@
#include "kdenlivesettings.h"
#include "kthumb.h"
#include "clipmanager.h"
#include "slideshowclip.h"
#include <KIO/NetAccess>
#include <KDebug>
......@@ -650,6 +651,49 @@ void DocClipBase::slotRefreshProducer()
if (!getProperty("out").isEmpty()) m_clipProducer->set_in_and_out(getProperty("in").toInt(), getProperty("out").toInt());*/
setProducerProperty("ttl", getProperty("ttl").toInt());
//m_clipProducer->set("id", getProperty("id"));
if (!getProperty("animation").isEmpty()) {
Mlt::Service clipService(m_baseTrackProducers.at(0)->get_service());
int ct = 0;
Mlt::Filter *filter = clipService.filter(ct);
while (filter) {
if (strcmp(filter->get("mlt_service"), "affine") == 0) {
break;
}
else if (strcmp(filter->get("mlt_service"), "boxblur") == 0) {
clipService.detach(*filter);
} else ct++;
filter = clipService.filter(ct);
}
if (!filter || strcmp(filter->get("mlt_service"), "affine")) {
// filter does not exist, create it.
Mlt::Filter *filter = new Mlt::Filter(*(m_baseTrackProducers.at(0)->profile()), "affine");
if (filter && filter->is_valid()) {
int cycle = getProperty("ttl").toInt();
QString geometry = SlideshowClip::animationToGeometry(getProperty("animation"), cycle);
if (!geometry.isEmpty()) {
if (getProperty("animation").contains("low-pass")) {
Mlt::Filter *blur = new Mlt::Filter(*(m_baseTrackProducers.at(0)->profile()), "boxblur");
if (blur && blur->is_valid())
clipService.attach(*blur);
}
filter->set("transition.geometry", geometry.toUtf8().data());
filter->set("transition.cycle", cycle);
clipService.attach(*filter);
}
}
}
} else {
Mlt::Service clipService(m_baseTrackProducers.at(0)->get_service());
int ct = 0;
Mlt::Filter *filter = clipService.filter(0);
while (filter) {
if (strcmp(filter->get("mlt_service"), "affine") == 0 || strcmp(filter->get("mlt_service"), "boxblur") == 0) {
clipService.detach(*filter);
} else ct++;
filter = clipService.filter(ct);
}
}
if (getProperty("fade") == "1") {
// we want a fade filter effect
kDebug() << "//////////// FADE WANTED";
......@@ -665,8 +709,8 @@ void DocClipBase::slotRefreshProducer()
}
if (filter && strcmp(filter->get("mlt_service"), "luma") == 0) {
filter->set("period", getProperty("ttl").toInt() - 1);
filter->set("luma.out", getProperty("luma_duration").toInt());
filter->set("cycle", getProperty("ttl").toInt());
filter->set("duration", getProperty("luma_duration").toInt());
QString resource = getProperty("luma_file");
char *tmp = (char *) qstrdup(resource.toUtf8().data());
filter->set("luma.resource", tmp);
......@@ -678,8 +722,8 @@ void DocClipBase::slotRefreshProducer()
} else {
// filter does not exist, create it...
Mlt::Filter *filter = new Mlt::Filter(*(m_baseTrackProducers.at(0)->profile()), "luma");
filter->set("period", getProperty("ttl").toInt() - 1);
filter->set("luma.out", getProperty("luma_duration").toInt());
filter->set("cycle", getProperty("ttl").toInt());
filter->set("duration", getProperty("luma_duration").toInt());
QString resource = getProperty("luma_file");
char *tmp = (char *) qstrdup(resource.toUtf8().data());
filter->set("luma.resource", tmp);
......
......@@ -1074,9 +1074,15 @@ void KdenliveDoc::slotCreateColorClip(const QString &name, const QString &color,
emit selectLastAddedClip(QString::number(m_clipManager->lastClipId()));
}
void KdenliveDoc::slotCreateSlideshowClipFile(const QString name, const QString path, int count, const QString duration, const bool loop, const bool crop, const bool fade, const QString &luma_duration, const QString &luma_file, const int softness, QString group, const QString &groupId)
{
m_clipManager->slotAddSlideshowClipFile(name, path, count, duration, loop, crop, fade, luma_duration, luma_file, softness, group, groupId);
void KdenliveDoc::slotCreateSlideshowClipFile(const QString name, const QString path, int count, const QString duration,
const bool loop, const bool crop, const bool fade,
const QString &luma_duration, const QString &luma_file, const int softness,
const QString &animation, QString group, const QString &groupId)
{
m_clipManager->slotAddSlideshowClipFile(name, path, count, duration, loop,
crop, fade, luma_duration,
luma_file, softness,
animation, group, groupId);
setModified(true);
emit selectLastAddedClip(QString::number(m_clipManager->lastClipId()));
}
......
......@@ -154,7 +154,10 @@ private:
public slots:
void slotCreateXmlClip(const QString &name, const QDomElement xml, QString group, const QString &groupId);
void slotCreateColorClip(const QString &name, const QString &color, const QString &duration, QString group, const QString &groupId);
void slotCreateSlideshowClipFile(const QString name, const QString path, int count, const QString duration, const bool loop, const bool crop, const bool fade, const QString &luma_duration, const QString &luma_file, const int softness, QString group, const QString &groupId);
void slotCreateSlideshowClipFile(const QString name, const QString path, int count, const QString duration,
const bool loop, const bool crop, const bool fade,
const QString &luma_duration, const QString &luma_file, const int softness,
const QString &animation, QString group, const QString &groupId);
void slotCreateTextClip(QString group, const QString &groupId, const QString &templatePath = QString());
void slotCreateTextTemplateClip(QString group, const QString &groupId, KUrl path);
/** Set to true if document needs saving, false otherwise */
......
......@@ -1103,7 +1103,10 @@ void ProjectList::slotAddClip(const QList <QUrl> givenList, const QString &group
fileName.chop(1);
}
m_doc->slotCreateSlideshowClipFile(fileName, pattern, count, m_timecode.reformatSeparators(KdenliveSettings::sequence_duration()), false, false, false, m_timecode.getTimecodeFromFrames(int(ceil(m_timecode.fps()))), QString(), 0, groupInfo.at(0), groupInfo.at(1));
m_doc->slotCreateSlideshowClipFile(fileName, pattern, count, m_timecode.reformatSeparators(KdenliveSettings::sequence_duration()),
false, false, false,
m_timecode.getTimecodeFromFrames(int(ceil(m_timecode.fps()))), QString(), 0,
QString(), groupInfo.at(0), groupInfo.at(1));
return;
}
}
......@@ -1191,8 +1194,10 @@ void ProjectList::slotAddSlideshowClip()
if (dia->exec() == QDialog::Accepted) {
QStringList groupInfo = getGroup();
m_doc->slotCreateSlideshowClipFile(dia->clipName(), dia->selectedPath(), dia->imageCount(), dia->clipDuration(), dia->loop(), dia->crop(), dia->fade(),
dia->lumaDuration(), dia->lumaFile(), dia->softness(), groupInfo.at(0), groupInfo.at(1));
m_doc->slotCreateSlideshowClipFile(dia->clipName(), dia->selectedPath(), dia->imageCount(), dia->clipDuration(),
dia->loop(), dia->crop(), dia->fade(),
dia->lumaDuration(), dia->lumaFile(), dia->softness(),
dia->animation(), groupInfo.at(0), groupInfo.at(1));
}
delete dia;
}
......
......@@ -27,6 +27,7 @@
#include "kdenlivesettings.h"
#include "kthumb.h"
#include "definitions.h"
#include "slideshowclip.h"
#include <mlt++/Mlt.h>
......@@ -712,13 +713,31 @@ void Render::getFileProperties(const QDomElement xml, const QString &clipId, int
Mlt::Frame *frame = producer->get_frame();
if (xml.attribute("type").toInt() == SLIDESHOW) {
if (xml.hasAttribute("ttl")) producer->set("ttl", xml.attribute("ttl").toInt());
int ttl = xml.hasAttribute("ttl") ? xml.attribute("ttl").toInt() : 0;
if (ttl) producer->set("ttl", ttl);
if (!xml.attribute("animation").isEmpty()) {
Mlt::Filter *filter = new Mlt::Filter(*m_mltProfile, "affine");
if (filter && filter->is_valid()) {
int cycle = ttl;
QString geometry = SlideshowClip::animationToGeometry(xml.attribute("animation"), cycle);
if (!geometry.isEmpty()) {
if (xml.attribute("animation").contains("low-pass")) {
Mlt::Filter *blur = new Mlt::Filter(*m_mltProfile, "boxblur");
if (blur && blur->is_valid())
producer->attach(*blur);
}
filter->set("transition.geometry", geometry.toUtf8().data());
filter->set("transition.cycle", cycle);
producer->attach(*filter);
}
}
}
if (xml.attribute("fade") == "1") {
// user wants a fade effect to slideshow
Mlt::Filter *filter = new Mlt::Filter(*m_mltProfile, "luma");
if (filter && filter->is_valid()) {
if (xml.hasAttribute("ttl")) filter->set("period", xml.attribute("ttl").toInt() - 1);
if (xml.hasAttribute("luma_duration") && !xml.attribute("luma_duration").isEmpty()) filter->set("luma.out", xml.attribute("luma_duration").toInt());
if (ttl) filter->set("cycle", ttl);
if (xml.hasAttribute("luma_duration") && !xml.attribute("luma_duration").isEmpty()) filter->set("duration", xml.attribute("luma_duration").toInt());
if (xml.hasAttribute("luma_file") && !xml.attribute("luma_file").isEmpty()) {
char *tmp = decodedString(xml.attribute("luma_file"));
filter->set("luma.resource", tmp);
......@@ -728,8 +747,7 @@ void Render::getFileProperties(const QDomElement xml, const QString &clipId, int
filter->set("luma.softness", (double) soft / 100.0);
}
}
Mlt::Service clipService(producer->get_service());
clipService.attach(*filter);
producer->attach(*filter);
}
}
if (xml.attribute("crop") == "1") {
......
......@@ -58,6 +58,13 @@ SlideshowClip::SlideshowClip(Timecode tc, QWidget * parent) :
m_view.image_type->addItem("TGA (*.tga)", "tga");
m_view.image_type->addItem("TIFF (*.tiff)", "tiff");
m_view.image_type->addItem("Open EXR (*.exr)", "exr");
m_view.animation->addItem(i18n("None"), QString());
m_view.animation->addItem(i18n("Pan"), "Pan");
m_view.animation->addItem(i18n("Pan, low-pass"), "Pan, low-pass");
m_view.animation->addItem(i18n("Pan and zoom"), "Pan and zoom");
m_view.animation->addItem(i18n("Pan and zoom, low-pass"), "Pan and zoom, low-pass");
m_view.animation->addItem(i18n("Zoom"), "Zoom");
m_view.animation->addItem(i18n("Zoom, low-pass"), "Zoom, low-pass");
m_view.clip_duration->setInputMask("");
m_view.clip_duration->setValidator(m_timecode.validator());
......@@ -378,6 +385,12 @@ QString SlideshowClip::lumaFile() const
return m_view.luma_file->itemData(m_view.luma_file->currentIndex()).toString();
}
QString SlideshowClip::animation() const
{
if (m_view.animation->itemData(m_view.animation->currentIndex()).isNull()) return QString();
return m_view.animation->itemData(m_view.animation->currentIndex()).toString();
}
void SlideshowClip::slotUpdateDurationFormat(int ix)
{
bool framesFormat = ix == 1;
......@@ -414,7 +427,24 @@ void SlideshowClip::slotMethodChanged(bool active)
parseFolder();
}
// static
QString SlideshowClip::animationToGeometry(const QString &animation, int &ttl)
{
QString geometry;
if (animation.startsWith("Pan and zoom")) {
geometry = QString().sprintf("0=0,0:100%%x100%%;%d=-14%%,-14%%:120%%x120%%;%d=-5%%,-5%%:110%%x110%%;%d=0,0:110%%x110%%;%d=0,-5%%:110%%x110%%;%d=-5%%,0:110%%x110%%",
ttl-1, ttl, ttl*2 - 1, ttl*2, ttl*3 - 1 );
ttl *= 3;
} else if (animation.startsWith("Pan")) {
geometry = QString().sprintf("0=-5%%,-5%%:110%%x110%%;%d=0,0:110%%x110%%;%d=0,0:110%%x110%%;%d=0,-5%%:110%%x110%%;%d=0,-5%%:110%%x110%%;%d=-5%%,-5%%:110%%x110%%;%d=0,-5%%:110%%x110%%;%d=-5%%,0:110%%x110%%",
ttl-1, ttl, ttl*2 - 1, ttl*2, ttl*3 - 1, ttl*3, ttl*4 - 1 );
ttl *= 4;
} else if (animation.startsWith("Zoom")) {
geometry = QString().sprintf("0=0,0:100%%x100%%;%d=-14%%,-14%%:120%%x120%%",
ttl-1, ttl );
}
return geometry;
}
#include "slideshowclip.moc"
......
......@@ -47,11 +47,14 @@ public:
bool fade() const;
QString lumaFile() const;
int softness() const;
QString animation() const;
/** @brief Check if there are several files with filename pattern, like: image_001.jpg, image_002.jpg,... */
static int sequenceCount(KUrl file);
/** @brief return the url pattern for selected slideshow. */
static QString selectedPath(KUrl url, bool isMime, QString extension, int *count);
/** @brief Convert the selection animation style into an affine geometry string. */
static QString animationToGeometry(const QString &animation, int &ttl);
private slots:
void parseFolder();
......
......@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>302</width>
<height>424</height>
<width>306</width>
<height>478</height>
</rect>
</property>
<property name="windowTitle">
......@@ -392,14 +392,14 @@
</property>
</widget>
</item>
<item row="8" column="0" colspan="3">
<item row="9" column="0" colspan="3">
<widget class="QLabel" name="slide_info">
<property name="text">
<string>No image found</string>
</property>
</widget>
</item>
<item row="9" column="1">
<item row="10" column="1">
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
......@@ -419,6 +419,16 @@
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_animation">
<property name="text">
<string>Animation</string>
</property>
</widget>
</item>
<item row="8" column="1" colspan="2">
<widget class="KComboBox" name="animation"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_4">
......
......@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>287</width>
<height>453</height>
<width>290</width>
<height>507</height>
</rect>
</property>
<property name="windowTitle">
......@@ -245,10 +245,10 @@
</property>
</widget>
</item>
<item row="8" column="0" colspan="4">
<item row="9" column="0" colspan="4">
<widget class="KListWidget" name="icon_list"/>
</item>
<item row="9" column="0" colspan="4">
<item row="10" column="0" colspan="4">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QCheckBox" name="show_thumbs">
......@@ -279,7 +279,7 @@
</item>
</layout>
</item>
<item row="10" column="2" colspan="2">
<item row="11" column="2" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
......@@ -296,6 +296,23 @@
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Animation</string>
</property>
</widget>
</item>
<item row="8" column="2" colspan="2">
<widget class="KComboBox" name="animation">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment