ccd5052709
Applies to toonz, toonzfarm, toonzqt.
948 lines
31 KiB
C++
948 lines
31 KiB
C++
|
|
|
|
#include "exportpanel.h"
|
|
|
|
#include <QtGlobal>
|
|
|
|
// Tnz6 includes
|
|
#include "tapp.h"
|
|
#include "moviegenerator.h"
|
|
#include "menubarcommandids.h"
|
|
#include "fileselection.h"
|
|
#include "iocommand.h"
|
|
#include "filebrowser.h"
|
|
#include "flipbook.h"
|
|
#include "formatsettingspopups.h"
|
|
#include "fileviewerpopup.h"
|
|
|
|
// TnzQt includes
|
|
#include "toonzqt/icongenerator.h"
|
|
#include "toonzqt/menubarcommand.h"
|
|
#include "toonzqt/gutil.h"
|
|
#include "toonzqt/dvdialog.h"
|
|
|
|
// TnzLib includes
|
|
#include "toonz/tscenehandle.h"
|
|
#include "toonz/tcolumnhandle.h"
|
|
#include "toonz/txsheethandle.h"
|
|
#include "toonz/screensavermaker.h"
|
|
#include "toonz/toonzscene.h"
|
|
#include "toonz/tcamera.h"
|
|
#include "toonz/sceneproperties.h"
|
|
#include "toonz/onionskinmask.h"
|
|
#include "toonz/preferences.h"
|
|
#include "toutputproperties.h"
|
|
|
|
// TnzBase includes
|
|
#include "trasterfx.h"
|
|
#include "tenv.h"
|
|
|
|
// TnzCore includes
|
|
#include "timage_io.h"
|
|
#include "tfiletype.h"
|
|
#include "tstream.h"
|
|
#include "tconvert.h"
|
|
#include "tsystem.h"
|
|
#include "tiio.h"
|
|
|
|
// Qt includes
|
|
#include <QDrag>
|
|
#include <QDragEnterEvent>
|
|
#include <QDragMoveEvent>
|
|
#include <QDropEvent>
|
|
#include <QDragLeaveEvent>
|
|
#include <QUrl>
|
|
#include <QProgressDialog>
|
|
#include <QCheckBox>
|
|
#include <QPushButton>
|
|
#include <QLayout>
|
|
#include <QComboBox>
|
|
#include <QBoxLayout>
|
|
#include <QApplication>
|
|
#include <QBuffer>
|
|
#include <QPainter>
|
|
#include <QMenu>
|
|
#include <QAction>
|
|
#include <QMainWindow>
|
|
#include <QMimeData>
|
|
#include <QLabel>
|
|
|
|
//=============================================================================
|
|
// RenderLocker
|
|
//-----------------------------------------------------------------------------
|
|
|
|
class RenderLocker {
|
|
bool &m_rendering;
|
|
|
|
public:
|
|
RenderLocker(bool &rendering) : m_rendering(rendering) { m_rendering = true; }
|
|
~RenderLocker() { m_rendering = false; }
|
|
};
|
|
|
|
//=============================================================================
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
RenderController::RenderController()
|
|
: m_progressDialog(0)
|
|
, m_frame(0)
|
|
, m_rendering(false)
|
|
, m_cancelled(false)
|
|
, m_properties(0)
|
|
, m_movieExt("mov")
|
|
, m_useMarkers(false) {
|
|
m_properties = new TOutputProperties();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
RenderController::~RenderController() {}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void RenderController::setUseMarkers(bool useMarkers) {
|
|
m_useMarkers = useMarkers;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void RenderController::setMovieExt(string ext) { m_movieExt = ext; }
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool RenderController::addScene(MovieGenerator &g, ToonzScene *scene) {
|
|
int frameCount = scene->getFrameCount();
|
|
if (frameCount < 0) return false;
|
|
int r0 = 0, r1 = frameCount - 1, step = 0;
|
|
if (m_useMarkers) {
|
|
int r0M, r1M, step;
|
|
scene->getProperties()->getPreviewProperties()->getRange(r0M, r1M, step);
|
|
if (r0M <= r1M) {
|
|
r0 = r0M;
|
|
r1 = r1M;
|
|
}
|
|
}
|
|
if (r1 < r0) return false;
|
|
g.setBackgroundColor(scene->getProperties()->getBgColor());
|
|
g.addScene(*scene, r0, r1);
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool RenderController::onFrameCompleted(int frameCount) {
|
|
if (m_cancelled) {
|
|
m_cancelled = false;
|
|
return false;
|
|
}
|
|
|
|
++m_frame;
|
|
m_progressDialog->setValue(m_frame);
|
|
qApp->processEvents();
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
int RenderController::computeClipFrameCount(const TFilePath &clipPath,
|
|
bool useMarkers, int *frameOffset) {
|
|
if (frameOffset) *frameOffset = 0;
|
|
|
|
ToonzScene scene;
|
|
scene.load(clipPath);
|
|
if (useMarkers) {
|
|
int r0, r1, step;
|
|
scene.getProperties()->getPreviewProperties()->getRange(r0, r1, step);
|
|
if (r1 >= r0) {
|
|
if (frameOffset) *frameOffset = r0;
|
|
return r1 - r0 + 1;
|
|
}
|
|
}
|
|
return scene.getFrameCount();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
int RenderController::computeTotalFrameCount(
|
|
const std::vector<TFilePath> &clipList, bool useMarkers) {
|
|
int count = 0;
|
|
int i;
|
|
for (i = 0; i < (int)clipList.size(); i++)
|
|
count += computeClipFrameCount(clipList[i], useMarkers);
|
|
return count;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void RenderController::myCancel() { m_cancelled = true; }
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void RenderController::generateMovie(TFilePath outPath, bool emitSignal) {
|
|
if (outPath == TFilePath()) return;
|
|
if (m_clipList.empty()) return;
|
|
|
|
// verifico che il "generatore" sia libero.
|
|
if (m_rendering) return;
|
|
m_cancelled = false;
|
|
|
|
RenderLocker locker(m_rendering);
|
|
|
|
if (outPath.getName() == "") outPath = outPath.withName("untitled");
|
|
|
|
int sceneCount = (int)m_clipList.size();
|
|
if (sceneCount < 1) return; // non dovrebbe succedere mai
|
|
|
|
// Risoluzione e Settings
|
|
TDimension resolution(0, 0);
|
|
TFilePath fp;
|
|
TFilePath firstClipPath = fp = m_clipList[0];
|
|
int sceneIndex;
|
|
|
|
try {
|
|
getMovieProperties(firstClipPath, resolution);
|
|
|
|
for (sceneIndex = 1; sceneIndex < sceneCount; sceneIndex++) {
|
|
TDimension testResolution(0, 0);
|
|
fp = m_clipList[sceneIndex];
|
|
getMovieProperties(fp, testResolution);
|
|
if (testResolution != resolution) {
|
|
/*wstring text = L"The ";
|
|
text += fp.getLevelNameW();
|
|
text += L" scene has a different resolution from the ";
|
|
text += firstClipPath.getLevelNameW();
|
|
text += L" scene.\nThe output result may differ from what you expect. What do
|
|
you want to do?";*/
|
|
QString text =
|
|
tr("The %1 scene has a different resolution from the %2 scene.\n \
|
|
The output result may differ from what you expect. What do you want to do?")
|
|
.arg(QString::fromStdWString(fp.getLevelNameW()))
|
|
.arg(QString::fromStdWString(firstClipPath.getLevelNameW()));
|
|
int ret = DVGui::MsgBox(text, tr("Continue"), tr("Cancel"));
|
|
if (ret == 2)
|
|
return;
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
} catch (TException const &) {
|
|
QString msg;
|
|
msg = QObject::tr(
|
|
"There were problems loading the scene %1.\n Some files may be "
|
|
"missing.")
|
|
.arg(QString::fromStdWString(fp.getWideString()));
|
|
|
|
DVGui::warning(msg);
|
|
return;
|
|
} catch (...) {
|
|
QString msg = QObject::tr(
|
|
"There were problems loading the scene %1.\n Some files "
|
|
"may be missing.")
|
|
.arg(QString::fromStdWString(fp.getWideString()));
|
|
|
|
DVGui::warning(msg);
|
|
return;
|
|
}
|
|
|
|
// Inizializzo la progressBar
|
|
DVGui::ProgressDialog progress(tr("Exporting ..."), tr("Abort"), 0, 1,
|
|
TApp::instance()->getMainWindow());
|
|
progress.setWindowModality(Qt::WindowModal);
|
|
progress.setWindowTitle(tr("Exporting"));
|
|
progress.setValue(0);
|
|
progress.show();
|
|
connect(&progress, SIGNAL(canceled()), this, SLOT(myCancel()));
|
|
qApp->processEvents();
|
|
m_progressDialog = &progress;
|
|
m_frame = 0;
|
|
|
|
int totalFrameCount = computeTotalFrameCount(m_clipList, m_useMarkers);
|
|
progress.setMaximum(totalFrameCount);
|
|
|
|
try {
|
|
// Inizializzo il movieGenerator
|
|
MovieGenerator movieGenerator(outPath, resolution, *m_properties,
|
|
m_useMarkers);
|
|
movieGenerator.setListener(this);
|
|
|
|
OnionSkinMask osMask; // = app->getOnionSkinMask(false);
|
|
if (!osMask.isEmpty() && osMask.isEnabled())
|
|
movieGenerator.setOnionSkin(
|
|
TApp::instance()->getCurrentColumn()->getColumnIndex(), osMask);
|
|
movieGenerator.setSceneCount(sceneCount);
|
|
|
|
// Aggiungo i soundtrack al movieGenerator
|
|
for (sceneIndex = 0; sceneIndex < sceneCount; sceneIndex++) {
|
|
TFilePath fp = m_clipList[sceneIndex];
|
|
int frameOffset;
|
|
int sceneFrames = computeClipFrameCount(fp, m_useMarkers, &frameOffset);
|
|
if (sceneFrames == 0) continue;
|
|
ToonzScene scene;
|
|
scene.load(fp);
|
|
try {
|
|
movieGenerator.addSoundtrack(scene, frameOffset, sceneFrames);
|
|
} catch (const TException &) {
|
|
QString text = tr("The %1 scene contains an audio file with different "
|
|
"characteristics from the one used in the first "
|
|
"exported scene.\nThe audio file will not be "
|
|
"included in the rendered clip.")
|
|
.arg(QString::fromStdWString(fp.getLevelNameW()));
|
|
DVGui::warning(text);
|
|
}
|
|
}
|
|
|
|
// Aggiungo le scene al movieGenerator
|
|
for (sceneIndex = 0; sceneIndex < sceneCount; sceneIndex++) {
|
|
TFilePath fp = m_clipList[sceneIndex];
|
|
int sceneFrames = computeClipFrameCount(fp, m_useMarkers);
|
|
if (sceneFrames == 0) continue;
|
|
ToonzScene scene;
|
|
scene.load(fp);
|
|
addScene(movieGenerator, &scene);
|
|
}
|
|
|
|
movieGenerator.close();
|
|
if (m_frame >= totalFrameCount &&
|
|
Preferences::instance()->isGeneratedMovieViewEnabled()) {
|
|
if (Preferences::instance()->isDefaultViewerEnabled() &&
|
|
(outPath.getType() == "mov" || outPath.getType() == "avi" ||
|
|
outPath.getType() == "3gp")) {
|
|
QString name = QString::fromStdString(outPath.getName());
|
|
|
|
if (!TSystem::showDocument(outPath)) {
|
|
QString msg(QObject::tr("It is not possible to display the file %1: "
|
|
"no player associated with its format")
|
|
.arg(QString::fromStdWString(
|
|
outPath.withoutParentDir().getWideString())));
|
|
DVGui::warning(msg);
|
|
}
|
|
} else {
|
|
int r0 = 1, r1 = totalFrameCount, step = 1;
|
|
|
|
const TRenderSettings rs = m_properties->getRenderSettings();
|
|
|
|
double timeStretchFactor;
|
|
timeStretchFactor = (double)rs.m_timeStretchTo / rs.m_timeStretchFrom;
|
|
int numFrames = troundp((r1 - r0 + 1) * timeStretchFactor);
|
|
r0 = troundp(r0 * timeStretchFactor);
|
|
r1 = r0 + numFrames - 1;
|
|
|
|
TXsheet::SoundProperties *prop = new TXsheet::SoundProperties();
|
|
prop->m_frameRate = m_properties->getFrameRate();
|
|
TSoundTrack *snd =
|
|
TApp::instance()->getCurrentXsheet()->getXsheet()->makeSound(prop);
|
|
|
|
::viewFile(outPath, 1, totalFrameCount, step, rs.m_shrinkX, snd, 0);
|
|
}
|
|
}
|
|
} catch (TException &) {
|
|
return;
|
|
} catch (...) {
|
|
return;
|
|
}
|
|
// per sicurezza
|
|
progress.setValue(totalFrameCount);
|
|
|
|
if (emitSignal) emit movieGenerated();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void RenderController::getMovieProperties(const TFilePath &scenePath,
|
|
TDimension &resolution) {
|
|
if (scenePath == TFilePath()) return;
|
|
ToonzScene scene;
|
|
scene.loadNoResources(scenePath);
|
|
resolution = scene.getCurrentCamera()->getRes();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
TFilePath RenderController::getClipPath(int index) const {
|
|
assert(0 <= index && index < getClipCount());
|
|
return m_clipList[index];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void RenderController::setClipPath(int index, const TFilePath &path) {
|
|
assert(0 <= index && index < getClipCount());
|
|
m_clipList[index] = path;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void RenderController::addClipPath(const TFilePath &path) {
|
|
m_clipList.push_back(path);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void RenderController::insertClipPath(int index, const TFilePath &path) {
|
|
assert(0 <= index && index <= getClipCount());
|
|
m_clipList.insert(m_clipList.begin() + index, path);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void RenderController::removeClipPath(int index) {
|
|
assert(0 <= index && index < getClipCount());
|
|
m_clipList.erase(m_clipList.begin() + index);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void RenderController::resetClipList() { m_clipList.clear(); }
|
|
|
|
//=============================================================================
|
|
//
|
|
// ClipListViewer
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
ClipListViewer::ClipListViewer(QWidget *parent)
|
|
: DvItemViewer(parent)
|
|
, m_dropInsertionPoint(-1)
|
|
, m_loadSceneFromExportPanel(false) {
|
|
resetList();
|
|
setModel(this);
|
|
setAcceptDrops(true);
|
|
getPanel()->enableSingleColumn(true);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
const char *ClipListViewer::m_mimeFormat = "application/vnd.toonz.cliplist";
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
RenderController *ClipListViewer::getController() const {
|
|
return RenderController::instance();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ClipListViewer::resetList() {
|
|
if (!m_loadSceneFromExportPanel) getController()->resetClipList();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ClipListViewer::removeSelectedClips() {
|
|
if (getPanel()->getSelection()->isEmpty()) return;
|
|
int i;
|
|
for (i = getController()->getClipCount() - 1; i >= 0; i--) {
|
|
if (getPanel()->getSelection()->isSelected(i))
|
|
getController()->removeClipPath(i);
|
|
}
|
|
updateContentSize();
|
|
getPanel()->getSelection()->selectNone();
|
|
getPanel()->update();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ClipListViewer::moveSelectedClips(int dstIndex) {
|
|
std::vector<TFilePath> selectedClips;
|
|
int i;
|
|
for (i = getController()->getClipCount() - 1; i >= 0; i--)
|
|
if (getPanel()->getSelection()->isSelected(i)) {
|
|
if (i < dstIndex) dstIndex--;
|
|
selectedClips.push_back(getController()->getClipPath(i));
|
|
getController()->removeClipPath(i);
|
|
}
|
|
if (dstIndex < 0)
|
|
dstIndex = 0;
|
|
else if (dstIndex > getController()->getClipCount())
|
|
dstIndex = getController()->getClipCount();
|
|
for (i = 0; i < (int)selectedClips.size(); i++)
|
|
getController()->insertClipPath(dstIndex + i, selectedClips[i]);
|
|
getPanel()->getSelection()->selectNone();
|
|
getPanel()->update();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ClipListViewer::getSelectedClips(std::vector<TFilePath> &selectedClips) {
|
|
int i;
|
|
for (i = 0; i < getController()->getClipCount(); i++)
|
|
if (getPanel()->getSelection()->isSelected(i))
|
|
selectedClips.push_back(getController()->getClipPath(i));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
static QByteArray packStringList(const QStringList &lst) {
|
|
QByteArray ba;
|
|
QDataStream ds(&ba, QIODevice::WriteOnly);
|
|
ds << (qint32)lst.size();
|
|
int i;
|
|
for (i = 0; i < lst.size(); i++) ds << lst.at(i);
|
|
return ba;
|
|
}
|
|
|
|
static QStringList unpackStringList(const QByteArray &ba) {
|
|
QStringList lst;
|
|
QDataStream ds(ba);
|
|
qint32 n = 0;
|
|
ds >> n;
|
|
int i;
|
|
for (i = 0; i < n; i++) {
|
|
QString s;
|
|
ds >> s;
|
|
lst.append(s);
|
|
}
|
|
return lst;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ClipListViewer::startDragDrop() {
|
|
std::vector<TFilePath> selectedClips;
|
|
getSelectedClips(selectedClips);
|
|
if (selectedClips.empty()) return;
|
|
|
|
QStringList slist;
|
|
int i;
|
|
for (i = 0; i < (int)selectedClips.size(); i++)
|
|
slist << QString::fromStdWString(selectedClips[i].getWideString());
|
|
|
|
QMimeData *mimeData = new QMimeData;
|
|
mimeData->setData(m_mimeFormat, packStringList(slist));
|
|
QDrag *drag = new QDrag(this);
|
|
drag->setMimeData(mimeData);
|
|
Qt::DropAction dropAction = drag->exec(Qt::MoveAction | Qt::CopyAction);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
int ClipListViewer::getItemCount() const {
|
|
return getController()->getClipCount();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
QVariant ClipListViewer::getItemData(int index, DataType dataType,
|
|
bool isSelected) {
|
|
if (index < 0 || index >= getController()->getClipCount()) return QVariant();
|
|
TFilePath fp = getController()->getClipPath(index);
|
|
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
|
|
|
|
if (dataType == Name)
|
|
return QString::fromStdString(fp.getName());
|
|
else if (dataType == ToolTip || dataType == FullPath)
|
|
return QString::fromStdWString(fp.getWideString());
|
|
else if (dataType == Thumbnail) {
|
|
QSize iconSize = getPanel()->getIconSize();
|
|
QPixmap icon = IconGenerator::instance()->getIcon(fp);
|
|
return scalePixmapKeepingAspectRatio(icon, iconSize, Qt::transparent);
|
|
}
|
|
|
|
return QVariant();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
QMenu *ClipListViewer::getContextMenu(QWidget *parent, int index) {
|
|
QMenu *menu = new QMenu(parent);
|
|
CommandManager *cm = CommandManager::instance();
|
|
const std::set<int> &selectedIndices = getPanel()->getSelectedIndices();
|
|
if (selectedIndices.size() == 1) {
|
|
int index = *selectedIndices.begin();
|
|
if (0 <= index && index < getController()->getClipCount()) {
|
|
QAction *action = new QAction(tr("Load Scene"), menu);
|
|
connect(action, SIGNAL(triggered()), this, SLOT(loadScene()));
|
|
menu->addAction(action);
|
|
}
|
|
}
|
|
menu->addAction(cm->getAction(MI_Clear));
|
|
return menu;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ClipListViewer::setDropInsertionPoint(const QPoint &pos) {
|
|
int old = m_dropInsertionPoint;
|
|
m_dropInsertionPoint = getItemCount();
|
|
DvItemViewerPanel *panel = getPanel();
|
|
QPoint panelPos = panel->mapFromParent(pos);
|
|
int i;
|
|
for (i = 0; i < getItemCount(); i++) {
|
|
QRect itemRect = getPanel()->index2pos(i);
|
|
int y = (itemRect.bottom() + itemRect.top()) / 2;
|
|
if (panelPos.y() < y) {
|
|
m_dropInsertionPoint = i;
|
|
break;
|
|
}
|
|
}
|
|
if (old != m_dropInsertionPoint) getPanel()->update();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ClipListViewer::dragEnterEvent(QDragEnterEvent *event) {
|
|
if (event->mimeData()->hasUrls()) {
|
|
foreach (QUrl url, event->mimeData()->urls()) {
|
|
TFilePath fp(url.toLocalFile().toStdString());
|
|
if (fp.getType() != "tnz") return;
|
|
}
|
|
setDropInsertionPoint(event->pos());
|
|
event->setDropAction(Qt::CopyAction);
|
|
event->acceptProposedAction();
|
|
update();
|
|
} else if (event->mimeData()->hasFormat(m_mimeFormat)) {
|
|
setDropInsertionPoint(event->pos());
|
|
event->setDropAction(Qt::MoveAction);
|
|
event->acceptProposedAction();
|
|
update();
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ClipListViewer::dragMoveEvent(QDragMoveEvent *event) {
|
|
int oldDropInsertionPoint = m_dropInsertionPoint;
|
|
setDropInsertionPoint(event->pos());
|
|
if (oldDropInsertionPoint != m_dropInsertionPoint) update();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ClipListViewer::dropEvent(QDropEvent *event) {
|
|
if (event->mimeData()->hasUrls()) {
|
|
int j = m_dropInsertionPoint;
|
|
if (j < 0) j = getItemCount();
|
|
foreach (QUrl url, event->mimeData()->urls()) {
|
|
TFilePath fp(url.toLocalFile().toStdString());
|
|
if (fp.getType() == "tnz") getController()->insertClipPath((j++), fp);
|
|
}
|
|
event->setDropAction(Qt::CopyAction);
|
|
event->acceptProposedAction();
|
|
} else if (event->mimeData()->hasFormat(m_mimeFormat) &&
|
|
m_dropInsertionPoint >= 0) {
|
|
moveSelectedClips(m_dropInsertionPoint);
|
|
event->setDropAction(Qt::MoveAction);
|
|
event->acceptProposedAction();
|
|
}
|
|
|
|
updateContentSize();
|
|
m_dropInsertionPoint = -1;
|
|
getPanel()->update();
|
|
update();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ClipListViewer::dragLeaveEvent(QDragLeaveEvent *event) {
|
|
m_dropInsertionPoint = -1;
|
|
getPanel()->update();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ClipListViewer::enableSelectionCommands(TSelection *selection) {
|
|
selection->enableCommand(this, MI_Clear,
|
|
&ClipListViewer::removeSelectedClips);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ClipListViewer::draw(QPainter &p) {
|
|
if (m_dropInsertionPoint >= 0) {
|
|
p.setPen(Qt::black);
|
|
// p.drawLine(0,0,width(),height());
|
|
int y = getPanel()->index2pos(m_dropInsertionPoint).topLeft().y() - 2;
|
|
p.drawLine(10, y, width() - 10, y);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ClipListViewer::loadScene() {
|
|
// se non ho selezionato una sola scena, diversa da quella corrente, esco.
|
|
const std::set<int> &selectedIndices = getPanel()->getSelectedIndices();
|
|
if (selectedIndices.size() != 1) return;
|
|
int index = *selectedIndices.begin();
|
|
if (!(0 <= index && index < getController()->getClipCount())) return;
|
|
// selectedScenePath e' la scena da caricare
|
|
TFilePath selectedScenePath = getController()->getClipPath(index);
|
|
|
|
m_loadSceneFromExportPanel = true;
|
|
|
|
// se necessario salvo la scena corrente (e le assegno un filepath)
|
|
// se l'utente sceglie "cancel" esco
|
|
if (!IoCmd::saveSceneIfNeeded(tr("Load Scene"))) return;
|
|
|
|
// Nella clip list assegno un path esplicito all'eventuale scena corrente
|
|
// (se la scena corrente non e' stata salvata dall'utente elimino il
|
|
// riferimento)
|
|
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
|
|
TFilePath scenePath;
|
|
if (!scene->isUntitled()) scenePath = scene->getScenePath();
|
|
// carico la scena corrente
|
|
IoCmd::loadScene(selectedScenePath);
|
|
m_loadSceneFromExportPanel = false;
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
// ExportPanel
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#if QT_VERSION >= 0x050500
|
|
ExportPanel::ExportPanel(QWidget *parent, Qt::WindowFlags flags)
|
|
#else
|
|
ExportPanel::ExportPanel(QWidget *parent, Qt::WFlags flags)
|
|
#endif
|
|
: TPanel(parent)
|
|
, m_clipListViewer(0)
|
|
, m_saveInFileFld(0)
|
|
, m_fileNameFld(0)
|
|
, m_useMarker(0) {
|
|
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
|
|
setWindowTitle(tr("Export"));
|
|
|
|
setMinimumWidth(270);
|
|
|
|
RenderController *renderController = RenderController::instance();
|
|
|
|
QFrame *box = new QFrame(this);
|
|
box->setObjectName("exportPanel");
|
|
box->setFrameStyle(QFrame::StyledPanel);
|
|
box->setStyleSheet("#exportPanel { margin: 1px; border: 0px; }");
|
|
|
|
QVBoxLayout *mainLayout = new QVBoxLayout();
|
|
mainLayout->setMargin(0);
|
|
mainLayout->setSpacing(0);
|
|
mainLayout->setAlignment(Qt::AlignTop);
|
|
// ClipList
|
|
m_clipListViewer = new ClipListViewer(box);
|
|
m_clipListViewer->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Expanding);
|
|
|
|
TSceneHandle *sceneHandle = TApp::instance()->getCurrentScene();
|
|
|
|
connect(sceneHandle, SIGNAL(sceneSwitched()), this, SLOT(onSceneSwitched()));
|
|
|
|
// Settings Box
|
|
QFrame *settingsBox = new QFrame(box);
|
|
settingsBox->setObjectName("settingsBox");
|
|
settingsBox->setFrameStyle(QFrame::StyledPanel);
|
|
QVBoxLayout *settingsLayout = new QVBoxLayout();
|
|
settingsLayout->setMargin(15);
|
|
settingsLayout->setSpacing(5);
|
|
settingsLayout->setAlignment(Qt::AlignTop);
|
|
|
|
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
|
|
std::wstring sceneName = scene->getSceneName();
|
|
TFilePath scenePath =
|
|
scene->getProperties()->getOutputProperties()->getPath().getParentDir();
|
|
|
|
// Label + saveInFileFld
|
|
QHBoxLayout *saveIn = new QHBoxLayout;
|
|
saveIn->setMargin(0);
|
|
saveIn->setSpacing(5);
|
|
m_saveInFileFld = new DVGui::FileField(settingsBox);
|
|
m_saveInFileFld->setPath(QString::fromStdWString(scenePath.getWideString()));
|
|
QLabel *dirLabel = new QLabel(tr("Save in:"));
|
|
dirLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
|
dirLabel->setFixedSize(55, m_saveInFileFld->height());
|
|
saveIn->addWidget(dirLabel);
|
|
saveIn->addWidget(m_saveInFileFld);
|
|
|
|
// Label + m_fileNameFld
|
|
QHBoxLayout *fileNname = new QHBoxLayout;
|
|
fileNname->setMargin(0);
|
|
fileNname->setSpacing(5);
|
|
m_fileNameFld =
|
|
new DVGui::LineEdit(QString::fromStdWString(sceneName), settingsBox);
|
|
QLabel *nameLabel = new QLabel(tr("File Name:"));
|
|
nameLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
|
nameLabel->setFixedSize(55, m_fileNameFld->height());
|
|
fileNname->addWidget(nameLabel);
|
|
fileNname->addWidget(m_fileNameFld);
|
|
|
|
// file formats
|
|
QHBoxLayout *fileFormatLayout = new QHBoxLayout();
|
|
m_fileFormat = new QComboBox();
|
|
QStringList formats;
|
|
TImageWriter::getSupportedFormats(formats, true);
|
|
TLevelWriter::getSupportedFormats(formats, true);
|
|
Tiio::Writer::getSupportedFormats(formats, true);
|
|
formats.sort();
|
|
|
|
m_fileFormat->addItems(formats);
|
|
m_fileFormat->setMaximumHeight(DVGui::WidgetHeight);
|
|
connect(m_fileFormat, SIGNAL(currentIndexChanged(const QString &)),
|
|
SLOT(onFormatChanged(const QString &)));
|
|
m_fileFormat->setCurrentIndex(formats.indexOf("mov"));
|
|
|
|
QPushButton *fileFormatButton = new QPushButton(QString(tr("Options")));
|
|
fileFormatButton->setFixedSize(60, DVGui::WidgetHeight);
|
|
connect(fileFormatButton, SIGNAL(pressed()), this, SLOT(openSettingsPopup()));
|
|
QLabel *fileFormat = new QLabel(tr("File Format:"));
|
|
fileFormat->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
|
fileFormat->setFixedSize(55, fileFormatButton->height());
|
|
|
|
fileFormatLayout->addWidget(fileFormat);
|
|
fileFormatLayout->addWidget(m_fileFormat);
|
|
fileFormatLayout->addWidget(fileFormatButton);
|
|
|
|
// Use Marker checkbox
|
|
m_useMarker = new QCheckBox(tr("Use Markers"), settingsBox);
|
|
m_useMarker->setMinimumHeight(30);
|
|
m_useMarker->setChecked(false);
|
|
connect(m_useMarker, SIGNAL(toggled(bool)), this,
|
|
SLOT(onUseMarkerToggled(bool)));
|
|
|
|
// Export button
|
|
QFrame *exportBox = new QFrame(box);
|
|
exportBox->setFrameStyle(QFrame::StyledPanel);
|
|
exportBox->setObjectName("exportBox");
|
|
|
|
QVBoxLayout *exportLayout = new QVBoxLayout();
|
|
QPushButton *exportButton = new QPushButton(tr("Export"), exportBox);
|
|
exportButton->setFixedSize(65, DVGui::WidgetHeight);
|
|
connect(exportButton, SIGNAL(pressed()), this, SLOT(generateMovie()));
|
|
exportLayout->addWidget(exportButton, 0, Qt::AlignCenter);
|
|
exportBox->setLayout(exportLayout);
|
|
|
|
settingsLayout->addLayout(saveIn);
|
|
settingsLayout->addLayout(fileNname);
|
|
settingsLayout->addLayout(fileFormatLayout);
|
|
settingsLayout->addWidget(m_useMarker);
|
|
settingsBox->setLayout(settingsLayout);
|
|
|
|
if (m_clipListViewer) mainLayout->addWidget(m_clipListViewer);
|
|
mainLayout->addWidget(new DVGui::Separator("", this));
|
|
mainLayout->addWidget(settingsBox, 0);
|
|
mainLayout->addWidget(new DVGui::Separator("", this));
|
|
mainLayout->addWidget(exportBox, 0);
|
|
|
|
connect(RenderController::instance(), SIGNAL(movieGenerated()), this,
|
|
SLOT(onMovieGenerated()));
|
|
|
|
box->setLayout(mainLayout);
|
|
setWidget(box);
|
|
loadExportSettings();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
ExportPanel::~ExportPanel() { saveExportSettings(); }
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ExportPanel::loadExportSettings() {
|
|
TFilePath exportPath = TEnv::getConfigDir() + "exportsettings.txt";
|
|
if (!TSystem::doesExistFileOrLevel(exportPath)) return;
|
|
TIStream is(exportPath);
|
|
std::string tagName;
|
|
try {
|
|
while (is.matchTag(tagName)) {
|
|
if (tagName == "ExportDir") {
|
|
TFilePath outPath;
|
|
is >> outPath;
|
|
m_saveInFileFld->setPath(
|
|
QString::fromStdWString(outPath.getWideString()));
|
|
} else if (tagName == "ExportFormat") {
|
|
std::string ext;
|
|
is >> ext;
|
|
int index = m_fileFormat->findText(QString::fromStdString(ext));
|
|
m_fileFormat->setCurrentIndex(index);
|
|
} else if (tagName == "FormatSettings") {
|
|
TOutputProperties *outProp =
|
|
RenderController::instance()->getOutputPropertites();
|
|
std::string ext = m_fileFormat->currentText().toStdString();
|
|
TPropertyGroup *props = outProp->getFileFormatProperties(ext);
|
|
props->loadData(is);
|
|
} else if (tagName == "UseMarkers") {
|
|
int value;
|
|
is >> value;
|
|
m_useMarker->setChecked(value);
|
|
}
|
|
is.closeChild();
|
|
}
|
|
} catch (...) {
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ExportPanel::saveExportSettings() {
|
|
QString path = m_saveInFileFld->getPath();
|
|
TFilePath outPath(path.toStdWString());
|
|
|
|
TFilePath exportPath = TEnv::getConfigDir() + "exportsettings.txt";
|
|
TOStream os(exportPath);
|
|
os.child("ExportDir") << outPath;
|
|
std::string ext = m_fileFormat->currentText().toStdString();
|
|
os.child("ExportFormat") << ext;
|
|
|
|
os.openChild("FormatSettings");
|
|
TOutputProperties *outProp =
|
|
RenderController::instance()->getOutputPropertites();
|
|
TPropertyGroup *props = outProp->getFileFormatProperties(ext);
|
|
props->saveData(os);
|
|
os.closeChild();
|
|
|
|
os.child("UseMarkers") << (int)m_useMarker->isChecked();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ExportPanel::generateMovie() {
|
|
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
|
|
std::string ext = RenderController::instance()->getMovieExt();
|
|
QString path = m_saveInFileFld->getPath();
|
|
TFilePath outPath(path.toStdWString());
|
|
outPath = (outPath + m_fileNameFld->text().toStdWString()).withType(ext);
|
|
if (TFileType::getInfo(outPath) == TFileType::RASTER_IMAGE ||
|
|
outPath.getType() == "pct" || outPath.getType() == "pic" ||
|
|
outPath.getType() == "pict") // pct e' un formato"livello" (ha i settings
|
|
// di quicktime) ma fatto di diversi frames
|
|
outPath = outPath.withFrame(TFrameId::EMPTY_FRAME);
|
|
RenderController::instance()->generateMovie(scene->decodeFilePath(outPath));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ExportPanel::onUseMarkerToggled(bool toggled) {
|
|
RenderController::instance()->setUseMarkers(toggled);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ExportPanel::onSceneSwitched() {
|
|
if (m_clipListViewer) {
|
|
m_clipListViewer->resetList();
|
|
m_clipListViewer->update();
|
|
}
|
|
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
|
|
m_fileNameFld->setText(QString::fromStdWString(scene->getSceneName()));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ExportPanel::onFormatChanged(const QString &format) {
|
|
RenderController::instance()->setMovieExt(format.toStdString());
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ExportPanel::openSettingsPopup() {
|
|
ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
|
|
if (!scene) return;
|
|
std::string ext = RenderController::instance()->getMovieExt();
|
|
|
|
TOutputProperties *outProps =
|
|
RenderController::instance()->getOutputPropertites();
|
|
if (!outProps) {
|
|
// non dovrebbe mai capitare!
|
|
assert(0);
|
|
outProps = new TOutputProperties();
|
|
RenderController::instance()->setOutputPropertites(outProps);
|
|
}
|
|
|
|
TPropertyGroup *props = outProps->getFileFormatProperties(ext);
|
|
openFormatSettingsPopup(this, ext, props);
|
|
}
|