shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
#include "exportcameratrackpopup.h"
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
// Tnz6 includes
shun-iwasawa 72dfb1
#include "tapp.h"
shun-iwasawa 72dfb1
#include "mainwindow.h"
shun-iwasawa 72dfb1
#include "filebrowser.h"
shun-iwasawa 72dfb1
#include "menubarcommandids.h"
shun-iwasawa 72dfb1
//// TnzQt includes
shun-iwasawa 72dfb1
#include "toonzqt/colorfield.h"
shun-iwasawa 72dfb1
#include "toonzqt/filefield.h"
shun-iwasawa 72dfb1
#include "toonzqt/doublefield.h"
shun-iwasawa 72dfb1
//// TnzLib includes
shun-iwasawa 72dfb1
#include "toonz/txsheet.h"
shun-iwasawa 72dfb1
#include "toonz/tcamera.h"
shun-iwasawa 72dfb1
#include "toonz/txshlevel.h"
shun-iwasawa 72dfb1
#include "toonz/txshsimplelevel.h"
shun-iwasawa 72dfb1
#include "toonz/txshcell.h"
shun-iwasawa 72dfb1
#include "toonz/tstageobjecttree.h"
shun-iwasawa 72dfb1
#include "toonz/toonzscene.h"
shun-iwasawa 72dfb1
#include "toonz/txshleveltypes.h"
shun-iwasawa 72dfb1
#include "toonz/dpiscale.h"
shun-iwasawa 72dfb1
#include "toonz/tproject.h"
shun-iwasawa 72dfb1
#include "toonz/txsheethandle.h"
shun-iwasawa 72dfb1
#include "toonz/tscenehandle.h"
shun-iwasawa 72dfb1
#include "filebrowserpopup.h"
shun-iwasawa 72dfb1
//// TnzCore includes
shun-iwasawa 72dfb1
#include "trop.h"
shun-iwasawa 72dfb1
#include "tsystem.h"
shun-iwasawa 72dfb1
#include "tenv.h"
shun-iwasawa 72dfb1
#include "tropcm.h"
shun-iwasawa 72dfb1
#include "tpalette.h"
shun-iwasawa 72dfb1
//// Qt includes
shun-iwasawa 72dfb1
#include <qlabel></qlabel>
shun-iwasawa 72dfb1
#include <qpushbutton></qpushbutton>
shun-iwasawa 72dfb1
#include <qimage></qimage>
shun-iwasawa 72dfb1
#include <qpainter></qpainter>
shun-iwasawa 72dfb1
#include <qpainterpath></qpainterpath>
shun-iwasawa 72dfb1
#include <qscrollbar></qscrollbar>
shun-iwasawa 72dfb1
#include <qmouseevent></qmouseevent>
shun-iwasawa 72dfb1
#include <qcheckbox></qcheckbox>
shun-iwasawa 72dfb1
#include <qcombobox></qcombobox>
shun-iwasawa 72dfb1
#include <qlineedit></qlineedit>
shun-iwasawa 72dfb1
#include <qfontcombobox></qfontcombobox>
shun-iwasawa 72dfb1
#include <qhboxlayout></qhboxlayout>
shun-iwasawa 72dfb1
#include <qvboxlayout></qvboxlayout>
shun-iwasawa 72dfb1
#include <qgridlayout></qgridlayout>
shun-iwasawa 72dfb1
#include <qgroupbox></qgroupbox>
shun-iwasawa 72dfb1
#include <qregexpvalidator></qregexpvalidator>
shun-iwasawa 72dfb1
#include <qpolygonf></qpolygonf>
shun-iwasawa 72dfb1
#include <qvector2d></qvector2d>
shun-iwasawa 72dfb1
#include <qfontmetricsf></qfontmetricsf>
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
TEnv::DoubleVar CameraTrackExportBgOpacity("CameraTrackExportBgOpacity", 0.5);
shun-iwasawa 72dfb1
TEnv::StringVar CameraTrackExportLineColor(
shun-iwasawa 72dfb1
    "CameraTrackExportLineColor", QColor(Qt::red).name().toStdString());
shun-iwasawa 72dfb1
TEnv::IntVar CameraTrackExportCamRectOnKeys("CameraTrackExportCamRectOnKeys",
shun-iwasawa 72dfb1
                                            1);
shun-iwasawa 72dfb1
TEnv::IntVar CameraTrackExportCamRectOnTags("CameraTrackExportCamRectOnTags",
shun-iwasawa 72dfb1
                                            0);
shun-iwasawa 72dfb1
TEnv::IntVar CameraTrackExportLineTL("CameraTrackExportLineTL", 0);
shun-iwasawa 72dfb1
TEnv::IntVar CameraTrackExportLineTR("CameraTrackExportLineTR", 0);
shun-iwasawa 72dfb1
TEnv::IntVar CameraTrackExportLineCenter("CameraTrackExportLineCenter", 1);
shun-iwasawa 72dfb1
TEnv::IntVar CameraTrackExportLineBL("CameraTrackExportLineBL", 0);
shun-iwasawa 72dfb1
TEnv::IntVar CameraTrackExportLineBR("CameraTrackExportLineBR", 0);
shun-iwasawa 72dfb1
TEnv::IntVar CameraTrackExportGraduationInterval(
shun-iwasawa 72dfb1
    "CameraTrackExportGraduationInterval", 1);
shun-iwasawa 72dfb1
TEnv::IntVar CameraTrackExportNumberAt("CameraTrackExportNumberAt",
shun-iwasawa 72dfb1
                                       (int)Qt::TopLeftCorner);
shun-iwasawa 72dfb1
TEnv::IntVar CameraTrackExportNumbersOnLine("CameraTrackExportNumbersOnLine",
shun-iwasawa 72dfb1
                                            1);
shun-iwasawa 72dfb1
TEnv::StringVar CameraTrackExportFont("CameraTrackExportFont", "");
shun-iwasawa 72dfb1
TEnv::IntVar CameraTrackExportFontSize("CameraTrackExportFontSize", 30);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
namespace {
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
void getCameraPlacement(TAffine& aff, TXsheet* xsh, double row,
shun-iwasawa 72dfb1
                        const TStageObjectId& objId,
shun-iwasawa 72dfb1
                        const TStageObjectId& cameraId) {
shun-iwasawa 72dfb1
  TStageObject* pegbar =
shun-iwasawa 72dfb1
      xsh->getStageObjectTree()->getStageObject(objId, false);
shun-iwasawa 72dfb1
  if (!pegbar) return;
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  TAffine objAff  = pegbar->getPlacement(row);
shun-iwasawa 72dfb1
  double objZ     = pegbar->getZ(row);
shun-iwasawa 72dfb1
  double noScaleZ = pegbar->getGlobalNoScaleZ();
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  TStageObject* camera = xsh->getStageObject(cameraId);
shun-iwasawa 72dfb1
  TAffine cameraAff    = camera->getPlacement(row);
shun-iwasawa 72dfb1
  double cameraZ       = camera->getZ(row);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  bool isVisible = TStageObject::perspective(aff, cameraAff, cameraZ, objAff,
shun-iwasawa 72dfb1
                                             objZ, noScaleZ);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  aff = aff.inv() * cameraAff;
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
// recursively find key frame
shun-iwasawa 72dfb1
bool isKey(int frame, TStageObject* obj, TXsheet* xsh) {
shun-iwasawa 72dfb1
  if (obj->isKeyframe(frame)) return true;
shun-iwasawa 72dfb1
  if (obj->getParent() != TStageObjectId::NoneId)
shun-iwasawa 72dfb1
    return isKey(frame, xsh->getStageObject(obj->getParent()), xsh);
shun-iwasawa 72dfb1
  return false;
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
void drawOutlinedText(QPainter& p, const QPointF& pos, const QString& str) {
shun-iwasawa 72dfb1
  QPainterPath path;
shun-iwasawa 72dfb1
  path.addText(pos, p.font(), str);
shun-iwasawa 72dfb1
  p.setPen(QPen(Qt::white, 3));
shun-iwasawa 72dfb1
  p.drawPath(path);
shun-iwasawa 72dfb1
  p.setPen(Qt::NoPen);
shun-iwasawa 72dfb1
  p.drawPath(path);
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
// {0,1,2,3,6,8,9,10} => "1-4,7,9-11"
shun-iwasawa 72dfb1
QString framesToString(const QList<int>& frames) {</int>
shun-iwasawa 72dfb1
  QString frameStr;
shun-iwasawa 72dfb1
  bool prevIsHyphen = false;
shun-iwasawa 72dfb1
  for (int i = 0; i < frames.size(); i++) {
shun-iwasawa 72dfb1
    int f = frames.at(i);
shun-iwasawa 72dfb1
    if (i == 0) {
shun-iwasawa 72dfb1
      frameStr = QString::number(f + 1);
shun-iwasawa 72dfb1
      continue;
shun-iwasawa 72dfb1
    }
shun-iwasawa 72dfb1
    if (i == frames.size() - 1) {
shun-iwasawa 72dfb1
      if (prevIsHyphen)
shun-iwasawa 72dfb1
        frameStr += QString::number(f + 1);
shun-iwasawa 72dfb1
      else
shun-iwasawa 72dfb1
        frameStr += ", " + QString::number(f + 1);
shun-iwasawa 72dfb1
      break;
shun-iwasawa 72dfb1
    }
shun-iwasawa 72dfb1
    if (frames.at(i - 1) == f - 1) {
shun-iwasawa 72dfb1
      if (frames.at(i + 1) == f + 1) {
shun-iwasawa 72dfb1
        if (prevIsHyphen)
shun-iwasawa 72dfb1
          continue;
shun-iwasawa 72dfb1
        else {
shun-iwasawa 72dfb1
          frameStr += "-";
shun-iwasawa 72dfb1
          prevIsHyphen = true;
shun-iwasawa 72dfb1
        }
shun-iwasawa 72dfb1
      } else {
shun-iwasawa 72dfb1
        if (prevIsHyphen) {
shun-iwasawa 72dfb1
          frameStr += QString::number(f + 1);
shun-iwasawa 72dfb1
          prevIsHyphen = false;
shun-iwasawa 72dfb1
        } else {
shun-iwasawa 72dfb1
          frameStr += ", " + QString::number(f + 1);
shun-iwasawa 72dfb1
        }
shun-iwasawa 72dfb1
      }
shun-iwasawa 72dfb1
    } else {
shun-iwasawa 72dfb1
      frameStr += ", " + QString::number(f + 1);
shun-iwasawa 72dfb1
    }
shun-iwasawa 72dfb1
  }
shun-iwasawa 72dfb1
  return frameStr;
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
}  // namespace
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
//-----------------------------------------------------------------------------
shun-iwasawa 72dfb1
CameraTrackPreviewPane::CameraTrackPreviewPane(QWidget* parent)
shun-iwasawa 72dfb1
    : QWidget(parent), m_scaleFactor(1.0) {}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
void CameraTrackPreviewPane::paintEvent(QPaintEvent* event) {
shun-iwasawa 72dfb1
  QPainter painter(this);
shun-iwasawa 72dfb1
  painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
shun-iwasawa 72dfb1
  painter.setRenderHint(QPainter::Antialiasing, true);
shun-iwasawa 72dfb1
  QSize pmSize((double)m_pixmap.width() * m_scaleFactor,
shun-iwasawa 72dfb1
               (double)m_pixmap.height() * m_scaleFactor);
shun-iwasawa 72dfb1
  painter.drawPixmap(
shun-iwasawa 72dfb1
      0, 0,
shun-iwasawa 72dfb1
      m_pixmap.scaled(pmSize, Qt::KeepAspectRatio, Qt::SmoothTransformation));
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
void CameraTrackPreviewPane::setPixmap(QPixmap pm) {
shun-iwasawa 72dfb1
  m_pixmap = pm;
shun-iwasawa 72dfb1
  resize(pm.size() * m_scaleFactor);
shun-iwasawa 72dfb1
  update();
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
void CameraTrackPreviewPane::doZoom(double d_scale) {
shun-iwasawa 72dfb1
  m_scaleFactor += d_scale;
shun-iwasawa 72dfb1
  if (m_scaleFactor > 1.0)
shun-iwasawa 72dfb1
    m_scaleFactor = 1.0;
shun-iwasawa 72dfb1
  else if (m_scaleFactor < 0.1)
shun-iwasawa 72dfb1
    m_scaleFactor = 0.1;
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  resize(m_pixmap.size() * m_scaleFactor);
shun-iwasawa 72dfb1
  update();
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
void CameraTrackPreviewPane::fitScaleTo(QSize size) {
shun-iwasawa 72dfb1
  double tmp_scaleFactor =
shun-iwasawa 72dfb1
      std::min((double)size.width() / (double)m_pixmap.width(),
shun-iwasawa 72dfb1
               (double)size.height() / (double)m_pixmap.height());
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  m_scaleFactor = tmp_scaleFactor;
shun-iwasawa 72dfb1
  if (m_scaleFactor > 1.0)
shun-iwasawa 72dfb1
    m_scaleFactor = 1.0;
shun-iwasawa 72dfb1
  else if (m_scaleFactor < 0.1)
shun-iwasawa 72dfb1
    m_scaleFactor = 0.1;
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  resize(m_pixmap.size() * m_scaleFactor);
shun-iwasawa 72dfb1
  update();
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
//-----------------------------------------------------------------------------
shun-iwasawa 72dfb1
void CameraTrackPreviewArea::mousePressEvent(QMouseEvent* e) {
shun-iwasawa 72dfb1
  m_mousePos = e->pos();
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
void CameraTrackPreviewArea::mouseMoveEvent(QMouseEvent* e) {
shun-iwasawa 72dfb1
  QPoint d = m_mousePos - e->pos();
shun-iwasawa 72dfb1
  horizontalScrollBar()->setValue(horizontalScrollBar()->value() + d.x());
shun-iwasawa 72dfb1
  verticalScrollBar()->setValue(verticalScrollBar()->value() + d.y());
shun-iwasawa 72dfb1
  m_mousePos = e->pos();
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
void CameraTrackPreviewArea::contextMenuEvent(QContextMenuEvent* event) {
shun-iwasawa 72dfb1
  QMenu* menu        = new QMenu(this);
shun-iwasawa 72dfb1
  QAction* fitAction = menu->addAction(tr("Fit To Window"));
shun-iwasawa 72dfb1
  connect(fitAction, SIGNAL(triggered()), this, SLOT(fitToWindow()));
shun-iwasawa 72dfb1
  menu->exec(event->globalPos());
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
void CameraTrackPreviewArea::fitToWindow() {
shun-iwasawa 72dfb1
  dynamic_cast<cameratrackpreviewpane*>(widget())->fitScaleTo(rect().size());</cameratrackpreviewpane*>
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
void CameraTrackPreviewArea::wheelEvent(QWheelEvent* event) {
shun-iwasawa 72dfb1
  int delta = 0;
shun-iwasawa 72dfb1
  switch (event->source()) {
shun-iwasawa 72dfb1
  case Qt::MouseEventNotSynthesized: {
shun-iwasawa 72dfb1
    delta = event->angleDelta().y();
shun-iwasawa 72dfb1
  }
shun-iwasawa 72dfb1
  case Qt::MouseEventSynthesizedBySystem: {
shun-iwasawa 72dfb1
    QPoint numPixels  = event->pixelDelta();
shun-iwasawa 72dfb1
    QPoint numDegrees = event->angleDelta() / 8;
shun-iwasawa 72dfb1
    if (!numPixels.isNull()) {
shun-iwasawa 72dfb1
      delta = event->pixelDelta().y();
shun-iwasawa 72dfb1
    } else if (!numDegrees.isNull()) {
shun-iwasawa 72dfb1
      QPoint numSteps = numDegrees / 15;
shun-iwasawa 72dfb1
      delta           = numSteps.y();
shun-iwasawa 72dfb1
    }
shun-iwasawa 72dfb1
    break;
shun-iwasawa 72dfb1
  }
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  default:  // Qt::MouseEventSynthesizedByQt,
shun-iwasawa 72dfb1
            // Qt::MouseEventSynthesizedByApplication
shun-iwasawa 72dfb1
  {
shun-iwasawa 72dfb1
    std::cout << "not supported event: Qt::MouseEventSynthesizedByQt, "
shun-iwasawa 72dfb1
                 "Qt::MouseEventSynthesizedByApplication"
shun-iwasawa 72dfb1
              << std::endl;
shun-iwasawa 72dfb1
    break;
shun-iwasawa 72dfb1
  }
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  }  // end switch
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  if (delta == 0) {
shun-iwasawa 72dfb1
    event->accept();
shun-iwasawa 72dfb1
    return;
shun-iwasawa 72dfb1
  }
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  dynamic_cast<cameratrackpreviewpane*>(widget())->doZoom((delta > 0) ? 0.1</cameratrackpreviewpane*>
shun-iwasawa 72dfb1
                                                                      : -0.1);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  event->accept();
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
//********************************************************************************
shun-iwasawa 72dfb1
//    ExportCameraTrackPopup  implementation
shun-iwasawa 72dfb1
//********************************************************************************
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
ExportCameraTrackPopup::ExportCameraTrackPopup()
shun-iwasawa 72dfb1
    : DVGui::Dialog(TApp::instance()->getMainWindow(), false, false,
shun-iwasawa 72dfb1
                    "ExportCameraTrack") {
shun-iwasawa 72dfb1
  setWindowTitle(tr("Export Camera Track"));
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  m_previewPane = new CameraTrackPreviewPane(this);
shun-iwasawa 72dfb1
  m_previewArea = new CameraTrackPreviewArea(this);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  m_targetColumnCombo = new QComboBox(this);
shun-iwasawa 72dfb1
  m_bgOpacityField    = new DVGui::DoubleField(this);
shun-iwasawa 72dfb1
  m_lineColorFld      = new DVGui::ColorField(this, false, TPixel32(255, 0, 0));
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  m_cameraRectOnKeysCB   = new QCheckBox(tr("Draw On Keyframes"), this);
shun-iwasawa 72dfb1
  m_cameraRectOnTagsCB   = new QCheckBox(tr("Draw On Navigation Tags"), this);
shun-iwasawa 72dfb1
  m_cameraRectFramesEdit = new QLineEdit(this);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  m_lineTL_CB               = new QCheckBox(tr("Top Left"), this);
shun-iwasawa 72dfb1
  m_lineTR_CB               = new QCheckBox(tr("Top Right"), this);
shun-iwasawa 72dfb1
  m_lineCenter_CB           = new QCheckBox(tr("Center"), this);
shun-iwasawa 72dfb1
  m_lineBL_CB               = new QCheckBox(tr("Bottom Left"), this);
shun-iwasawa 72dfb1
  m_lineBR_CB               = new QCheckBox(tr("Bottom Right"), this);
shun-iwasawa 72dfb1
  m_graduationIntervalCombo = new QComboBox(this);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  m_numberAtCombo   = new QComboBox(this);
shun-iwasawa 72dfb1
  m_numbersOnLineCB = new QCheckBox(tr("Draw Numbers On Track Line"), this);
shun-iwasawa 72dfb1
  m_fontCombo       = new QFontComboBox(this);
shun-iwasawa 72dfb1
  m_fontSizeEdit    = new DVGui::IntLineEdit(this, 30, 5, 300);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  QPushButton* exportButton = new QPushButton(tr("Export"), this);
shun-iwasawa 72dfb1
  QPushButton* cancelButton = new QPushButton(tr("Cancel"), this);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  //----------
shun-iwasawa 72dfb1
  m_previewArea->setWidget(m_previewPane);
shun-iwasawa 72dfb1
  m_previewArea->setAlignment(Qt::AlignCenter);
shun-iwasawa 72dfb1
  m_previewArea->setBackgroundRole(QPalette::Dark);
shun-iwasawa 72dfb1
  m_previewArea->setStyleSheet("background-color:gray;");
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  m_targetColumnCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents);
shun-iwasawa 72dfb1
  m_bgOpacityField->setRange(0.0, 1.0);
shun-iwasawa 72dfb1
  m_bgOpacityField->setValue(0.5);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  m_cameraRectFramesEdit->setValidator(
shun-iwasawa 72dfb1
      new QRegExpValidator(QRegExp("^(\\d+,)*\\d+$"), this));
shun-iwasawa 72dfb1
  m_cameraRectFramesEdit->setToolTip(
shun-iwasawa 72dfb1
      tr("Specify frame numbers where the camera rectangles will be drawn. "
shun-iwasawa 72dfb1
         "Separate numbers by comma \",\" ."));
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  m_numberAtCombo->addItem(tr("Top Left"), (int)Qt::TopLeftCorner);
shun-iwasawa 72dfb1
  m_numberAtCombo->addItem(tr("Top Right"), (int)Qt::TopRightCorner);
shun-iwasawa 72dfb1
  m_numberAtCombo->addItem(tr("Bottom Left"), (int)Qt::BottomLeftCorner);
shun-iwasawa 72dfb1
  m_numberAtCombo->addItem(tr("Bottom Right"), (int)Qt::BottomRightCorner);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  m_graduationIntervalCombo->addItem(tr("None"), 0);
shun-iwasawa 72dfb1
  m_graduationIntervalCombo->addItem(tr("All frames"), 1);
shun-iwasawa 72dfb1
  m_graduationIntervalCombo->addItem(tr("Every 2 frames"), 2);
shun-iwasawa 72dfb1
  m_graduationIntervalCombo->addItem(tr("Every 3 frames"), 3);
shun-iwasawa 72dfb1
  m_graduationIntervalCombo->addItem(tr("Every 4 frames"), 4);
shun-iwasawa 72dfb1
  m_graduationIntervalCombo->addItem(tr("Every 5 frames"), 5);
shun-iwasawa 72dfb1
  m_graduationIntervalCombo->addItem(tr("Every 6 frames"), 6);
shun-iwasawa 72dfb1
  m_graduationIntervalCombo->addItem(tr("Every 8 frames"), 8);
shun-iwasawa 72dfb1
  m_graduationIntervalCombo->addItem(tr("Every 10 frames"), 10);
shun-iwasawa 72dfb1
  m_graduationIntervalCombo->addItem(tr("Every 12 frames"), 12);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  exportButton->setFocusPolicy(Qt::NoFocus);
shun-iwasawa 72dfb1
  cancelButton->setFocusPolicy(Qt::NoFocus);
shun-iwasawa 72dfb1
  //----------
shun-iwasawa 72dfb1
  QHBoxLayout* mainLay = new QHBoxLayout();
shun-iwasawa 72dfb1
  mainLay->setMargin(0);
shun-iwasawa 72dfb1
  mainLay->setSpacing(5);
shun-iwasawa 72dfb1
  {
shun-iwasawa 72dfb1
    mainLay->addWidget(m_previewArea, 1);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    QVBoxLayout* rightLay = new QVBoxLayout();
shun-iwasawa 72dfb1
    rightLay->setMargin(10);
shun-iwasawa 72dfb1
    rightLay->setSpacing(10);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    QGridLayout* appearanceLay = new QGridLayout();
shun-iwasawa 72dfb1
    appearanceLay->setMargin(0);
shun-iwasawa 72dfb1
    appearanceLay->setHorizontalSpacing(5);
shun-iwasawa 72dfb1
    appearanceLay->setVerticalSpacing(10);
shun-iwasawa 72dfb1
    {
shun-iwasawa 72dfb1
      appearanceLay->addWidget(new QLabel(tr("Target Column:"), this), 0, 0,
shun-iwasawa 72dfb1
                               Qt::AlignRight | Qt::AlignVCenter);
shun-iwasawa 72dfb1
      appearanceLay->addWidget(m_targetColumnCombo, 0, 1, Qt::AlignLeft);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
      appearanceLay->addWidget(new QLabel(tr("Background:"), this), 1, 0,
shun-iwasawa 72dfb1
                               Qt::AlignRight | Qt::AlignVCenter);
shun-iwasawa 72dfb1
      appearanceLay->addWidget(m_bgOpacityField, 1, 1);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
      appearanceLay->addWidget(new QLabel(tr("Line Color:"), this), 2, 0,
shun-iwasawa 72dfb1
                               Qt::AlignRight | Qt::AlignVCenter);
shun-iwasawa 72dfb1
      appearanceLay->addWidget(m_lineColorFld, 2, 1, Qt::AlignLeft);
shun-iwasawa 72dfb1
    }
shun-iwasawa 72dfb1
    appearanceLay->setColumnStretch(1, 1);
shun-iwasawa 72dfb1
    rightLay->addLayout(appearanceLay, 0);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    QGroupBox* cameraRectGB    = new QGroupBox(tr("Camera Rectangles"), this);
shun-iwasawa 72dfb1
    QGridLayout* cameraRectLay = new QGridLayout();
shun-iwasawa 72dfb1
    cameraRectLay->setMargin(10);
shun-iwasawa 72dfb1
    cameraRectLay->setHorizontalSpacing(5);
shun-iwasawa 72dfb1
    cameraRectLay->setVerticalSpacing(10);
shun-iwasawa 72dfb1
    {
shun-iwasawa 72dfb1
      cameraRectLay->addWidget(m_cameraRectOnKeysCB, 0, 0, 1, 2, Qt::AlignLeft);
shun-iwasawa 72dfb1
      cameraRectLay->addWidget(m_cameraRectOnTagsCB, 1, 0, 1, 2, Qt::AlignLeft);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
      cameraRectLay->addWidget(new QLabel(tr("Specify Frames Manually:"), this),
shun-iwasawa 72dfb1
                               2, 0, Qt::AlignRight | Qt::AlignVCenter);
shun-iwasawa 72dfb1
      cameraRectLay->addWidget(m_cameraRectFramesEdit, 2, 1);
shun-iwasawa 72dfb1
    }
shun-iwasawa 72dfb1
    cameraRectLay->setColumnStretch(1, 1);
shun-iwasawa 72dfb1
    cameraRectGB->setLayout(cameraRectLay);
shun-iwasawa 72dfb1
    rightLay->addWidget(cameraRectGB, 0);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    QGroupBox* trackLineGB    = new QGroupBox(tr("Track Lines"), this);
shun-iwasawa 72dfb1
    QGridLayout* trackLineLay = new QGridLayout();
shun-iwasawa 72dfb1
    trackLineLay->setMargin(10);
shun-iwasawa 72dfb1
    trackLineLay->setHorizontalSpacing(10);
shun-iwasawa 72dfb1
    trackLineLay->setVerticalSpacing(10);
shun-iwasawa 72dfb1
    {
shun-iwasawa 72dfb1
      trackLineLay->addWidget(m_lineTL_CB, 0, 0);
shun-iwasawa 72dfb1
      trackLineLay->addWidget(m_lineTR_CB, 0, 1);
shun-iwasawa 72dfb1
      trackLineLay->addWidget(m_lineCenter_CB, 1, 0, Qt::AlignRight);
shun-iwasawa 72dfb1
      trackLineLay->addWidget(m_lineBL_CB, 2, 0);
shun-iwasawa 72dfb1
      trackLineLay->addWidget(m_lineBR_CB, 2, 1);
shun-iwasawa 72dfb1
      trackLineLay->addWidget(
shun-iwasawa 72dfb1
          new QLabel(tr("Graduation Marks Interval:"), this), 3, 0,
shun-iwasawa 72dfb1
          Qt::AlignRight | Qt::AlignVCenter);
shun-iwasawa 72dfb1
      trackLineLay->addWidget(m_graduationIntervalCombo, 3, 1, Qt::AlignLeft);
shun-iwasawa 72dfb1
    }
shun-iwasawa 72dfb1
    trackLineLay->setColumnStretch(1, 1);
shun-iwasawa 72dfb1
    trackLineGB->setLayout(trackLineLay);
shun-iwasawa 72dfb1
    rightLay->addWidget(trackLineGB, 0);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    QGroupBox* frameNumberGB    = new QGroupBox(tr("Frame Numbers"), this);
shun-iwasawa 72dfb1
    QGridLayout* frameNumberLay = new QGridLayout();
shun-iwasawa 72dfb1
    frameNumberLay->setMargin(10);
shun-iwasawa 72dfb1
    frameNumberLay->setHorizontalSpacing(5);
shun-iwasawa 72dfb1
    frameNumberLay->setVerticalSpacing(10);
shun-iwasawa 72dfb1
    {
shun-iwasawa 72dfb1
      frameNumberLay->addWidget(new QLabel(tr("Camera Rect Corner:"), this), 0,
shun-iwasawa 72dfb1
                                0, Qt::AlignRight | Qt::AlignVCenter);
shun-iwasawa 72dfb1
      frameNumberLay->addWidget(m_numberAtCombo, 0, 1, Qt::AlignLeft);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
      frameNumberLay->addWidget(m_numbersOnLineCB, 1, 0, 1, 2);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
      frameNumberLay->addWidget(new QLabel(tr("Font Family:"), this), 2, 0,
shun-iwasawa 72dfb1
                                Qt::AlignRight | Qt::AlignVCenter);
shun-iwasawa 72dfb1
      frameNumberLay->addWidget(m_fontCombo, 2, 1, Qt::AlignLeft);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
      frameNumberLay->addWidget(new QLabel(tr("Font Size:"), this), 3, 0,
shun-iwasawa 72dfb1
                                Qt::AlignRight | Qt::AlignVCenter);
shun-iwasawa 72dfb1
      frameNumberLay->addWidget(m_fontSizeEdit, 3, 1, Qt::AlignLeft);
shun-iwasawa 72dfb1
    }
shun-iwasawa 72dfb1
    frameNumberLay->setColumnStretch(1, 1);
shun-iwasawa 72dfb1
    frameNumberGB->setLayout(frameNumberLay);
shun-iwasawa 72dfb1
    rightLay->addWidget(frameNumberGB, 0);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    rightLay->addStretch(1);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    QHBoxLayout* buttonsLay = new QHBoxLayout();
shun-iwasawa 72dfb1
    buttonsLay->setMargin(5);
shun-iwasawa 72dfb1
    buttonsLay->setSpacing(20);
shun-iwasawa 72dfb1
    {
shun-iwasawa 72dfb1
      buttonsLay->addWidget(exportButton, 0);
shun-iwasawa 72dfb1
      buttonsLay->addWidget(cancelButton, 0);
shun-iwasawa 72dfb1
    }
shun-iwasawa 72dfb1
    rightLay->setAlignment(Qt::AlignCenter);
shun-iwasawa 72dfb1
    rightLay->addLayout(buttonsLay, 0);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    mainLay->addLayout(rightLay, 0);
shun-iwasawa 72dfb1
  }
shun-iwasawa 72dfb1
  m_topLayout->addLayout(mainLay, 1);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  //----------
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  loadSettings();
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  connect(m_targetColumnCombo, SIGNAL(activated(int)), this,
shun-iwasawa 72dfb1
          SLOT(updatePreview()));
shun-iwasawa 72dfb1
  connect(m_bgOpacityField, SIGNAL(valueEditedByHand()), this,
shun-iwasawa 72dfb1
          SLOT(updatePreview()));
shun-iwasawa 72dfb1
  connect(m_lineColorFld, SIGNAL(colorChanged(const TPixel32&, bool)), this,
shun-iwasawa 72dfb1
          SLOT(updatePreview()));
shun-iwasawa 72dfb1
  connect(m_cameraRectOnKeysCB, SIGNAL(clicked(bool)), this,
shun-iwasawa 72dfb1
          SLOT(updatePreview()));
shun-iwasawa 72dfb1
  connect(m_cameraRectOnTagsCB, SIGNAL(clicked(bool)), this,
shun-iwasawa 72dfb1
          SLOT(updatePreview()));
shun-iwasawa 72dfb1
  connect(m_cameraRectFramesEdit, SIGNAL(editingFinished()), this,
shun-iwasawa 72dfb1
          SLOT(updatePreview()));
shun-iwasawa 72dfb1
  connect(m_lineTL_CB, SIGNAL(clicked(bool)), this, SLOT(updatePreview()));
shun-iwasawa 72dfb1
  connect(m_lineTR_CB, SIGNAL(clicked(bool)), this, SLOT(updatePreview()));
shun-iwasawa 72dfb1
  connect(m_lineCenter_CB, SIGNAL(clicked(bool)), this, SLOT(updatePreview()));
shun-iwasawa 72dfb1
  connect(m_lineBL_CB, SIGNAL(clicked(bool)), this, SLOT(updatePreview()));
shun-iwasawa 72dfb1
  connect(m_lineBR_CB, SIGNAL(clicked(bool)), this, SLOT(updatePreview()));
shun-iwasawa 72dfb1
  connect(m_graduationIntervalCombo, SIGNAL(activated(int)), this,
shun-iwasawa 72dfb1
          SLOT(updatePreview()));
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  connect(m_numberAtCombo, SIGNAL(activated(int)), this, SLOT(updatePreview()));
shun-iwasawa 72dfb1
  connect(m_numbersOnLineCB, SIGNAL(clicked(bool)), this,
shun-iwasawa 72dfb1
          SLOT(updatePreview()));
shun-iwasawa 72dfb1
  connect(m_fontCombo, SIGNAL(currentFontChanged(const QFont&)), this,
shun-iwasawa 72dfb1
          SLOT(updatePreview()));
shun-iwasawa 72dfb1
  connect(m_fontSizeEdit, SIGNAL(editingFinished()), this,
shun-iwasawa 72dfb1
          SLOT(updatePreview()));
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  connect(cancelButton, SIGNAL(clicked()), this, SLOT(close()));
shun-iwasawa 72dfb1
  connect(exportButton, SIGNAL(clicked()), this, SLOT(onExport()));
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
//--------------------------------------------------------------
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
// register settings to the user env file on close
shun-iwasawa 72dfb1
void ExportCameraTrackPopup::saveSettings() {
shun-iwasawa 72dfb1
  CameraTrackExportBgOpacity = m_bgOpacityField->getValue();
shun-iwasawa 72dfb1
  TPixel32 col               = m_lineColorFld->getColor();
shun-iwasawa 72dfb1
  CameraTrackExportLineColor = QColor(col.r, col.g, col.b).name().toStdString();
shun-iwasawa 72dfb1
  CameraTrackExportCamRectOnKeys = (m_cameraRectOnKeysCB->isChecked()) ? 1 : 0;
shun-iwasawa 72dfb1
  CameraTrackExportCamRectOnTags = (m_cameraRectOnTagsCB->isChecked()) ? 1 : 0;
shun-iwasawa 72dfb1
  CameraTrackExportLineTL        = (m_lineTL_CB->isChecked()) ? 1 : 0;
shun-iwasawa 72dfb1
  CameraTrackExportLineTR        = (m_lineTR_CB->isChecked()) ? 1 : 0;
shun-iwasawa 72dfb1
  CameraTrackExportLineCenter    = (m_lineCenter_CB->isChecked()) ? 1 : 0;
shun-iwasawa 72dfb1
  CameraTrackExportLineBL        = (m_lineBL_CB->isChecked()) ? 1 : 0;
shun-iwasawa 72dfb1
  CameraTrackExportLineBR        = (m_lineBR_CB->isChecked()) ? 1 : 0;
shun-iwasawa 72dfb1
  CameraTrackExportGraduationInterval =
shun-iwasawa 72dfb1
      m_graduationIntervalCombo->currentData().toInt();
shun-iwasawa 72dfb1
  CameraTrackExportNumberAt      = m_numberAtCombo->currentData().toInt();
shun-iwasawa 72dfb1
  CameraTrackExportNumbersOnLine = (m_numbersOnLineCB->isChecked()) ? 1 : 0;
shun-iwasawa 72dfb1
  CameraTrackExportFont     = m_fontCombo->currentFont().family().toStdString();
shun-iwasawa 72dfb1
  CameraTrackExportFontSize = m_fontSizeEdit->getValue();
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
//--------------------------------------------------------------
shun-iwasawa 72dfb1
//
shun-iwasawa 72dfb1
// load settings from the user env file on ctor
shun-iwasawa 72dfb1
void ExportCameraTrackPopup::loadSettings() {
shun-iwasawa 72dfb1
  m_bgOpacityField->setValue(CameraTrackExportBgOpacity);
shun-iwasawa 72dfb1
  QColor lineColor(QString::fromStdString(CameraTrackExportLineColor));
shun-iwasawa 72dfb1
  m_lineColorFld->setColor(
shun-iwasawa 72dfb1
      TPixel32(lineColor.red(), lineColor.green(), lineColor.blue()));
shun-iwasawa 72dfb1
  m_cameraRectOnKeysCB->setChecked(CameraTrackExportCamRectOnKeys != 0);
shun-iwasawa 72dfb1
  m_cameraRectOnTagsCB->setChecked(CameraTrackExportCamRectOnTags != 0);
shun-iwasawa 72dfb1
  m_lineTL_CB->setChecked(CameraTrackExportLineTL != 0);
shun-iwasawa 72dfb1
  m_lineTR_CB->setChecked(CameraTrackExportLineTR != 0);
shun-iwasawa 72dfb1
  m_lineCenter_CB->setChecked(CameraTrackExportLineCenter != 0);
shun-iwasawa 72dfb1
  m_lineBL_CB->setChecked(CameraTrackExportLineBL != 0);
shun-iwasawa 72dfb1
  m_lineBR_CB->setChecked(CameraTrackExportLineBR != 0);
shun-iwasawa 72dfb1
  m_graduationIntervalCombo->setCurrentIndex(
shun-iwasawa 72dfb1
      m_graduationIntervalCombo->findData(
shun-iwasawa 72dfb1
          (int)CameraTrackExportGraduationInterval));
shun-iwasawa 72dfb1
  m_numberAtCombo->setCurrentIndex(
shun-iwasawa 72dfb1
      m_numberAtCombo->findData((int)CameraTrackExportNumberAt));
shun-iwasawa 72dfb1
  m_numbersOnLineCB->setChecked(CameraTrackExportNumbersOnLine != 0);
shun-iwasawa 72dfb1
  QString tmplFont = QString::fromStdString(CameraTrackExportFont);
shun-iwasawa 72dfb1
  if (!tmplFont.isEmpty()) m_fontCombo->setCurrentFont(QFont(tmplFont));
shun-iwasawa 72dfb1
  m_fontSizeEdit->setValue(CameraTrackExportFontSize);
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
//--------------------------------------------------------------
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
void ExportCameraTrackPopup::initialize() {
shun-iwasawa 72dfb1
  updateTargetColumnComboItems();
shun-iwasawa 72dfb1
  updatePreview();
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
//--------------------------------------------------------------
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
void ExportCameraTrackPopup::updateTargetColumnComboItems() {
shun-iwasawa 72dfb1
  m_targetColumnCombo->clear();
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene();
shun-iwasawa 72dfb1
  TXsheet* xsh      = TApp::instance()->getCurrentXsheet()->getXsheet();
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  for (int col = 0; col < xsh->getColumnCount(); col++) {
shun-iwasawa 72dfb1
    TXshLevelP level;
shun-iwasawa 72dfb1
    int r0, r1;
shun-iwasawa 72dfb1
    xsh->getCellRange(col, r0, r1);
shun-iwasawa 72dfb1
    if (r1 < 0) continue;
shun-iwasawa 72dfb1
    for (int r = r0; r <= r1; r++)
shun-iwasawa 72dfb1
      if (level = xsh->getCell(r, col).m_level) {
shun-iwasawa 72dfb1
        break;
shun-iwasawa 72dfb1
      }
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    if (!level) continue;
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    int type = level->getType();
shun-iwasawa 72dfb1
    if (!(type & RASTER_TYPE)) continue;
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    TXshSimpleLevelP sl = level->getSimpleLevel();
shun-iwasawa 72dfb1
    if (!sl) continue;
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    QString itemName = tr("Col %1 (%2)")
shun-iwasawa 72dfb1
                           .arg(col + 1)
shun-iwasawa 72dfb1
                           .arg(QString::fromStdWString(sl->getName()));
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    m_targetColumnCombo->addItem(itemName, col);
shun-iwasawa 72dfb1
  }
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
//--------------------------------------------------------------
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
QImage ExportCameraTrackPopup::generateCameraTrackImg(
shun-iwasawa 72dfb1
    const ExportCameraTrackInfo& info, bool isPreview) {
shun-iwasawa 72dfb1
  ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene();
shun-iwasawa 72dfb1
  TXsheet* xsh      = TApp::instance()->getCurrentXsheet()->getXsheet();
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  // obtain target level
shun-iwasawa 72dfb1
  TXshLevelP level;
shun-iwasawa 72dfb1
  TFrameId fId;
shun-iwasawa 72dfb1
  int r0, r1;
shun-iwasawa 72dfb1
  xsh->getCellRange(info.columnId, r0, r1);
shun-iwasawa 72dfb1
  if (r1 < 0) return QImage();
shun-iwasawa 72dfb1
  for (int r = r0; r <= r1; r++)
shun-iwasawa 72dfb1
    if (level = xsh->getCell(r, info.columnId).m_level) {
shun-iwasawa 72dfb1
      fId = xsh->getCell(r, info.columnId).getFrameId();
shun-iwasawa 72dfb1
      break;
shun-iwasawa 72dfb1
    }
shun-iwasawa 72dfb1
  if (!level) return QImage();
shun-iwasawa 72dfb1
  int type = level->getType();
shun-iwasawa 72dfb1
  if (!(type & RASTER_TYPE)) return QImage();
shun-iwasawa 72dfb1
  TXshSimpleLevelP sl = level->getSimpleLevel();
shun-iwasawa 72dfb1
  if (!sl) return QImage();
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  // construct output image
shun-iwasawa 72dfb1
  TStageObjectId cameraId = xsh->getStageObjectTree()->getCurrentCameraId();
shun-iwasawa 72dfb1
  TCamera* camera         = xsh->getStageObject(cameraId)->getCamera();
shun-iwasawa 72dfb1
  TDimension camDim       = camera->getRes();
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  TDimension imgRes = sl->getResolution();
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  TImageP tImg = sl->getFullsampledFrame(fId, ImageManager::dontPutInCache);
shun-iwasawa 72dfb1
  TRaster32P imgRas(tImg->raster()->getSize());
shun-iwasawa 72dfb1
  TRaster32P src32   = tImg->raster();
shun-iwasawa 72dfb1
  TRasterCM32P srcCM = tImg->raster();
shun-iwasawa 72dfb1
  if (src32)
shun-iwasawa 72dfb1
    imgRas = src32;
shun-iwasawa 72dfb1
  else if (srcCM)
shun-iwasawa 72dfb1
    TRop::convert(imgRas, srcCM, tImg->getPalette(), TRect());
shun-iwasawa 72dfb1
  else
shun-iwasawa 72dfb1
    TRop::convert(imgRas, tImg->raster());
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  QImage colImg(imgRas->getRawData(), imgRes.lx, imgRes.ly,
shun-iwasawa 72dfb1
                QImage::Format_ARGB32_Premultiplied);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  QImage img = colImg.mirrored(false, true);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  TPointD imgDpi = sl->getImageDpi();
shun-iwasawa 72dfb1
  if (imgDpi != TPointD()) {
shun-iwasawa 72dfb1
    img.setDotsPerMeterX((int)std::round(imgDpi.x / 0.0254));
shun-iwasawa 72dfb1
    img.setDotsPerMeterY((int)std::round(imgDpi.y / 0.0254));
shun-iwasawa 72dfb1
  }
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  // draw
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  enum CornerId {
shun-iwasawa 72dfb1
    TopLeft     = Qt::TopLeftCorner,
shun-iwasawa 72dfb1
    TopRight    = Qt::TopRightCorner,
shun-iwasawa 72dfb1
    BottomLeft  = Qt::BottomLeftCorner,
shun-iwasawa 72dfb1
    BottomRight = Qt::BottomRightCorner,
shun-iwasawa 72dfb1
    Center      = Qt::BottomRightCorner + 1
shun-iwasawa 72dfb1
  };
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  QMap<int, qpainterpath=""> trackPaths;  // [ CornerId, Path data ]</int,>
shun-iwasawa 72dfb1
  QList<qmap<int, qpointf="">></qmap<int,>
shun-iwasawa 72dfb1
      cornerPointsTrack;  // [ CornerId, Position ] for each frame
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  if (info.lineTL) trackPaths.insert((int)TopLeft, QPainterPath());
shun-iwasawa 72dfb1
  if (info.lineTR) trackPaths.insert((int)TopRight, QPainterPath());
shun-iwasawa 72dfb1
  if (info.lineCenter) trackPaths.insert((int)Center, QPainterPath());
shun-iwasawa 72dfb1
  if (info.lineBL) trackPaths.insert((int)BottomLeft, QPainterPath());
shun-iwasawa 72dfb1
  if (info.lineBR) trackPaths.insert((int)BottomRight, QPainterPath());
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  TAffine aff;
shun-iwasawa 72dfb1
  TAffine dpiAffInv = getDpiAffine(sl.getPointer(), fId, true).inv();
shun-iwasawa 72dfb1
  TAffine camDpiAff = getDpiAffine(camera);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  TStageObjectId colId = TStageObjectId::ColumnId(info.columnId);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  QMap<int, tpointd=""> camCorners = {</int,>
shun-iwasawa 72dfb1
      {(int)TopLeft, TPointD(-camDim.lx / 2, camDim.ly / 2)},
shun-iwasawa 72dfb1
      {(int)TopRight, TPointD(camDim.lx / 2, camDim.ly / 2)},
shun-iwasawa 72dfb1
      {(int)BottomLeft, TPointD(-camDim.lx / 2, -camDim.ly / 2)},
shun-iwasawa 72dfb1
      {(int)BottomRight, TPointD(camDim.lx / 2, -camDim.ly / 2)},
shun-iwasawa 72dfb1
      {(int)Center, TPointD()}};
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  for (int f = 0; f < scene->getFrameCount(); f++) {
shun-iwasawa 72dfb1
    getCameraPlacement(aff, xsh, (double)f, colId, cameraId);
shun-iwasawa 72dfb1
    TAffine affTmp = dpiAffInv * aff * camDpiAff;
shun-iwasawa 72dfb1
    //  corner points
shun-iwasawa 72dfb1
    QMap<int, qpointf=""> cornerPoints;</int,>
shun-iwasawa 72dfb1
    for (int c = TopLeft; c <= Center; c++) {
shun-iwasawa 72dfb1
      TPointD p = affTmp * camCorners[c];
shun-iwasawa 72dfb1
      cornerPoints.insert(c, QPointF(p.x, -p.y));
shun-iwasawa 72dfb1
    }
shun-iwasawa 72dfb1
    cornerPointsTrack.append(cornerPoints);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    if (trackPaths.isEmpty()) continue;
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    // track paths will plot every 0.1 frames
shun-iwasawa 72dfb1
    for (int df = 0; df < 10; df++) {
shun-iwasawa 72dfb1
      double tmpF = (double)f + (double)df * 0.1;
shun-iwasawa 72dfb1
      getCameraPlacement(aff, xsh, (double)tmpF, colId, cameraId);
shun-iwasawa 72dfb1
      affTmp = dpiAffInv * aff * camDpiAff;
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
      for (int c = TopLeft; c <= Center; c++) {
shun-iwasawa 72dfb1
        if (!trackPaths.contains(c)) continue;
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
        TPointD p = affTmp * camCorners[c];
shun-iwasawa 72dfb1
        if (f == 0 && df == 0)
shun-iwasawa 72dfb1
          trackPaths[c].moveTo(QPointF(p.x, -p.y));
shun-iwasawa 72dfb1
        else
shun-iwasawa 72dfb1
          trackPaths[c].lineTo(QPointF(p.x, -p.y));
shun-iwasawa 72dfb1
      }
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
      if (f == scene->getFrameCount() - 1) break;
shun-iwasawa 72dfb1
    }
shun-iwasawa 72dfb1
  }
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  QPainter p(&img);
shun-iwasawa 72dfb1
  p.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  p.setBrush(QColor(255, 255, 255, 255. * (1. - info.bgOpacity)));
shun-iwasawa 72dfb1
  p.setPen(Qt::NoPen);
shun-iwasawa 72dfb1
  p.drawRect(0, 0, imgRes.lx, imgRes.ly);
shun-iwasawa 72dfb1
  p.translate(imgRes.lx / 2.0, imgRes.ly / 2.0);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  // camera rect
shun-iwasawa 72dfb1
  QSet<int> rectFrames = info.cameraRectFrames;</int>
shun-iwasawa 72dfb1
  if (info.cameraRectOnKeys || info.cameraRectOnTags) {
shun-iwasawa 72dfb1
    // check keyframes
shun-iwasawa 72dfb1
    for (int f = 0; f < scene->getFrameCount(); f++) {
shun-iwasawa 72dfb1
      if (rectFrames.contains(f)) continue;
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
      if (info.cameraRectOnKeys &&
shun-iwasawa 72dfb1
          (isKey(f, xsh->getStageObject(cameraId), xsh) ||
shun-iwasawa 72dfb1
           isKey(f, xsh->getStageObject(colId), xsh)))
shun-iwasawa 72dfb1
        rectFrames.insert(f);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
      else if (info.cameraRectOnTags && xsh->isFrameTagged(f))
shun-iwasawa 72dfb1
        rectFrames.insert(f);
shun-iwasawa 72dfb1
    }
shun-iwasawa 72dfb1
  }
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  struct cameraRectData {
shun-iwasawa 72dfb1
    QPolygonF polygon;
shun-iwasawa 72dfb1
    QVector<qpointf> centerCrossPoints;</qpointf>
shun-iwasawa 72dfb1
    QPointF textPos;
shun-iwasawa 72dfb1
    QVector2D offsetVec;
shun-iwasawa 72dfb1
    QList<int> frames;</int>
shun-iwasawa 72dfb1
  };
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  QList<camerarectdata></camerarectdata>
shun-iwasawa 72dfb1
      camRectDataList;  // gather frames with the same camera rectangle
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  for (auto rectFrame : rectFrames) {
shun-iwasawa 72dfb1
    if (rectFrame < 0 || cornerPointsTrack.size() <= rectFrame) continue;
shun-iwasawa 72dfb1
    QMap<int, qpointf=""> cornerPoints = cornerPointsTrack.at(rectFrame);</int,>
shun-iwasawa 72dfb1
    QPolygonF camRectPolygon({cornerPoints[TopLeft], cornerPoints[TopRight],
shun-iwasawa 72dfb1
                              cornerPoints[BottomRight],
shun-iwasawa 72dfb1
                              cornerPoints[BottomLeft]});
shun-iwasawa 72dfb1
    QVector<qpointf> centerCrossPoints = {</qpointf>
shun-iwasawa 72dfb1
        cornerPoints[TopLeft] * 0.51 + cornerPoints[BottomRight] * 0.49,
shun-iwasawa 72dfb1
        cornerPoints[TopLeft] * 0.49 + cornerPoints[BottomRight] * 0.51,
shun-iwasawa 72dfb1
        cornerPoints[TopRight] * 0.51 + cornerPoints[BottomLeft] * 0.49,
shun-iwasawa 72dfb1
        cornerPoints[TopRight] * 0.49 + cornerPoints[BottomLeft] * 0.51};
shun-iwasawa 72dfb1
    QPointF textPos = cornerPoints[(int)info.numberAt];
shun-iwasawa 72dfb1
    int oppositeId;
shun-iwasawa 72dfb1
    switch ((int)info.numberAt) {
shun-iwasawa 72dfb1
    case TopLeft:
shun-iwasawa 72dfb1
      oppositeId = TopRight;
shun-iwasawa 72dfb1
      break;
shun-iwasawa 72dfb1
    case TopRight:
shun-iwasawa 72dfb1
      oppositeId = TopLeft;
shun-iwasawa 72dfb1
      break;
shun-iwasawa 72dfb1
    case BottomLeft:
shun-iwasawa 72dfb1
      oppositeId = BottomRight;
shun-iwasawa 72dfb1
      break;
shun-iwasawa 72dfb1
    case BottomRight:
shun-iwasawa 72dfb1
      oppositeId = BottomLeft;
shun-iwasawa 72dfb1
      break;
shun-iwasawa 72dfb1
    }
shun-iwasawa 72dfb1
    QVector2D offsetVec =
shun-iwasawa 72dfb1
        QVector2D(textPos - cornerPoints[oppositeId]).normalized();
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    bool found = false;
shun-iwasawa 72dfb1
    for (int i = 0; i < camRectDataList.size(); i++)
shun-iwasawa 72dfb1
      if (camRectDataList[i].polygon == camRectPolygon) {
shun-iwasawa 72dfb1
        found = true;
shun-iwasawa 72dfb1
        camRectDataList[i].frames.append(rectFrame);
shun-iwasawa 72dfb1
        break;
shun-iwasawa 72dfb1
      }
shun-iwasawa 72dfb1
    if (!found)
shun-iwasawa 72dfb1
      camRectDataList.append(
shun-iwasawa 72dfb1
          {camRectPolygon, centerCrossPoints, textPos, offsetVec, {rectFrame}});
shun-iwasawa 72dfb1
  }
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  p.setFont(info.font);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  for (auto& data : camRectDataList) {
shun-iwasawa 72dfb1
    p.setPen(QPen(info.lineColor, 2));
shun-iwasawa 72dfb1
    p.setBrush(Qt::NoBrush);
shun-iwasawa 72dfb1
    p.drawPolygon(data.polygon);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    // draw cross mark at center of the frame
shun-iwasawa 72dfb1
    bool drawCross = true;
shun-iwasawa 72dfb1
    // if the graduation mark is at the camera center, do not draw the cross
shun-iwasawa 72dfb1
    if (info.lineCenter && info.graduationInterval > 0) {
shun-iwasawa 72dfb1
      for (auto frame : data.frames)
shun-iwasawa 72dfb1
        if (frame % info.graduationInterval == 0) {
shun-iwasawa 72dfb1
          drawCross = false;
shun-iwasawa 72dfb1
          break;
shun-iwasawa 72dfb1
        }
shun-iwasawa 72dfb1
    }
shun-iwasawa 72dfb1
    if (drawCross) {
shun-iwasawa 72dfb1
      p.setPen(QPen(info.lineColor, 1));
shun-iwasawa 72dfb1
      p.drawLines(data.centerCrossPoints);
shun-iwasawa 72dfb1
    }
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    // generate frame number string
shun-iwasawa 72dfb1
    std::sort(data.frames.begin(), data.frames.end());
shun-iwasawa 72dfb1
    QString frameStr = framesToString(data.frames);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    // draw frame number string
shun-iwasawa 72dfb1
    QFontMetricsF fm(info.font);
shun-iwasawa 72dfb1
    QRectF textRect = fm.boundingRect(frameStr).adjusted(-5, 0, 5, 0);
shun-iwasawa 72dfb1
    QPointF textPos = data.textPos + QPointF(5, 0);
shun-iwasawa 72dfb1
    textRect.translate(textPos);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    while (data.polygon.intersects(textRect)) {
shun-iwasawa 72dfb1
      textRect.translate(data.offsetVec.toPointF());
shun-iwasawa 72dfb1
      textPos += QPointF(data.offsetVec.toPointF());
shun-iwasawa 72dfb1
    }
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    p.setBrush(info.lineColor);
shun-iwasawa 72dfb1
    drawOutlinedText(p, textPos, frameStr);
shun-iwasawa 72dfb1
  }
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  QFont smallFont(info.font);
shun-iwasawa 72dfb1
  smallFont.setPixelSize(info.font.pixelSize() * 2 / 3);
shun-iwasawa 72dfb1
  p.setFont(smallFont);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  // track lines
shun-iwasawa 72dfb1
  QMap<int, qpainterpath="">::const_iterator itr = trackPaths.constBegin();</int,>
shun-iwasawa 72dfb1
  while (itr != trackPaths.constEnd()) {
shun-iwasawa 72dfb1
    if (info.lineCenter && itr.key() != Center)
shun-iwasawa 72dfb1
      p.setPen(QPen(info.lineColor, 1, Qt::DashLine));
shun-iwasawa 72dfb1
    else
shun-iwasawa 72dfb1
      p.setPen(QPen(info.lineColor, 1));
shun-iwasawa 72dfb1
    p.setBrush(Qt::NoBrush);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    p.drawPath(itr.value());
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    if (info.graduationInterval == 0 ||
shun-iwasawa 72dfb1
        (info.lineCenter && itr.key() != Center)) {
shun-iwasawa 72dfb1
      ++itr;
shun-iwasawa 72dfb1
      continue;
shun-iwasawa 72dfb1
    }
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    // draw graduation
shun-iwasawa 72dfb1
    QList<qpair<qpointf, qlist<int="">>> graduations;</qpair<qpointf,>
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    for (int f = 0; f < scene->getFrameCount(); f++) {
shun-iwasawa 72dfb1
      if (f % info.graduationInterval != 0) continue;
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
      QPointF gPos = cornerPointsTrack[f].value(itr.key());
shun-iwasawa 72dfb1
      QPointF prev =
shun-iwasawa 72dfb1
          (f == 0) ? gPos : cornerPointsTrack[f - 1].value(itr.key());
shun-iwasawa 72dfb1
      QPointF next = (f == scene->getFrameCount() - 1)
shun-iwasawa 72dfb1
                         ? gPos
shun-iwasawa 72dfb1
                         : cornerPointsTrack[f + 1].value(itr.key());
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
      QPointF graduationVec =
shun-iwasawa 72dfb1
          QVector2D(next - prev).normalized().toPointF() * 5.0;
shun-iwasawa 72dfb1
      graduationVec = QPointF(-graduationVec.y(), graduationVec.x());
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
      p.drawLine(gPos - graduationVec, gPos + graduationVec);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
      // draw frame
shun-iwasawa 72dfb1
      if (!info.numbersOnLine) continue;
shun-iwasawa 72dfb1
      if (itr.key() != Center && rectFrames.contains(f)) continue;
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
      bool found = false;
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
      for (auto& g : graduations) {
shun-iwasawa 72dfb1
        if (g.first == gPos) {
shun-iwasawa 72dfb1
          found = true;
shun-iwasawa 72dfb1
          g.second.append(f);
shun-iwasawa 72dfb1
          break;
shun-iwasawa 72dfb1
        }
shun-iwasawa 72dfb1
      }
shun-iwasawa 72dfb1
      if (!found) graduations.append(QPair<qpointf, qlist<int="">>(gPos, {f}));</qpointf,>
shun-iwasawa 72dfb1
    }
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    for (auto& g : graduations) {
shun-iwasawa 72dfb1
      std::sort(g.second.begin(), g.second.end());
shun-iwasawa 72dfb1
      QString frameStr = framesToString(g.second);
shun-iwasawa 72dfb1
      QFontMetricsF fm(smallFont);
shun-iwasawa 72dfb1
      QRectF textRect = fm.boundingRect(frameStr).adjusted(-5, 0, 5, 0);
shun-iwasawa 72dfb1
      QPointF pos     = g.first + QPointF(5, 0);
shun-iwasawa 72dfb1
      if (info.numberAt == Qt::TopLeftCorner ||
shun-iwasawa 72dfb1
          info.numberAt == Qt::BottomLeftCorner)
shun-iwasawa 72dfb1
        pos += QPointF(-textRect.width(), 0);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
      p.setBrush(info.lineColor);
shun-iwasawa 72dfb1
      drawOutlinedText(p, pos, frameStr);
shun-iwasawa 72dfb1
    }
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
    ++itr;
shun-iwasawa 72dfb1
  }
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  return img;
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
//--------------------------------------------------------------
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
void ExportCameraTrackPopup::getInfoFromUI(ExportCameraTrackInfo& info) {
shun-iwasawa 72dfb1
  // target column
shun-iwasawa 72dfb1
  if (m_targetColumnCombo->count() == 0) return;
shun-iwasawa 72dfb1
  info.columnId = m_targetColumnCombo->currentData().toInt();
shun-iwasawa 72dfb1
  // appearance settimgs
shun-iwasawa 72dfb1
  info.bgOpacity    = m_bgOpacityField->getValue();
shun-iwasawa 72dfb1
  TPixel32 lineTCol = m_lineColorFld->getColor();
shun-iwasawa 72dfb1
  info.lineColor    = QColor((int)lineTCol.r, (int)lineTCol.g, (int)lineTCol.b);
shun-iwasawa 72dfb1
  // camera rect settings
shun-iwasawa 72dfb1
  info.cameraRectOnKeys = m_cameraRectOnKeysCB->isChecked();
shun-iwasawa 72dfb1
  info.cameraRectOnTags = m_cameraRectOnTagsCB->isChecked();
shun-iwasawa 72dfb1
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
shun-iwasawa 72dfb1
  QStringList framesStrList =
shun-iwasawa 72dfb1
      m_cameraRectFramesEdit->text().split(",", Qt::SkipEmptyParts);
shun-iwasawa 72dfb1
#else
shun-iwasawa 72dfb1
  QStringList framesStrList =
shun-iwasawa 72dfb1
      m_cameraRectFramesEdit->text().split(",", QString::SkipEmptyParts);
shun-iwasawa 72dfb1
#endif
shun-iwasawa 72dfb1
  for (auto fStr : framesStrList) {
shun-iwasawa 72dfb1
    bool ok;
shun-iwasawa 72dfb1
    int f = fStr.toInt(&ok);
shun-iwasawa 72dfb1
    if (ok) info.cameraRectFrames.insert(f - 1);
shun-iwasawa 72dfb1
  }
shun-iwasawa 72dfb1
  // track line settings
shun-iwasawa 72dfb1
  info.lineTL             = m_lineTL_CB->isChecked();
shun-iwasawa 72dfb1
  info.lineTR             = m_lineTR_CB->isChecked();
shun-iwasawa 72dfb1
  info.lineCenter         = m_lineCenter_CB->isChecked();
shun-iwasawa 72dfb1
  info.lineBL             = m_lineBL_CB->isChecked();
shun-iwasawa 72dfb1
  info.lineBR             = m_lineBR_CB->isChecked();
shun-iwasawa 72dfb1
  info.graduationInterval = m_graduationIntervalCombo->currentData().toInt();
shun-iwasawa 72dfb1
  // frame number settings
shun-iwasawa 72dfb1
  info.numberAt      = (Qt::Corner)(m_numberAtCombo->currentData().toInt());
shun-iwasawa 72dfb1
  info.numbersOnLine = m_numbersOnLineCB->isChecked();
shun-iwasawa 72dfb1
  ;
shun-iwasawa 72dfb1
  info.font = m_fontCombo->currentFont();
shun-iwasawa 72dfb1
  info.font.setPixelSize(m_fontSizeEdit->getValue());
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
//--------------------------------------------------------------
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
void ExportCameraTrackPopup::updatePreview() {
shun-iwasawa 72dfb1
  ExportCameraTrackInfo info;
shun-iwasawa 72dfb1
  getInfoFromUI(info);
shun-iwasawa 72dfb1
  if (info.columnId == -1) return;
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  QImage img = generateCameraTrackImg(info, true);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  m_previewPane->setPixmap(QPixmap::fromImage(img));
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
//--------------------------------------------------------------
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
void ExportCameraTrackPopup::onExport() {
shun-iwasawa 72dfb1
  ExportCameraTrackInfo info;
shun-iwasawa 72dfb1
  getInfoFromUI(info);
shun-iwasawa 72dfb1
  if (info.columnId == -1) return;
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  QImage img = generateCameraTrackImg(info, false);
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene();
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  static GenericSaveFilePopup* savePopup = 0;
shun-iwasawa 72dfb1
  if (!savePopup) {
shun-iwasawa 72dfb1
    savePopup =
shun-iwasawa 72dfb1
        new GenericSaveFilePopup(QObject::tr("Export Camera Track Image"));
shun-iwasawa 72dfb1
    savePopup->setFilterTypes({"jpg", "jpeg", "bmp", "png", "tif"});
shun-iwasawa 72dfb1
  }
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  if (!scene->isUntitled())
shun-iwasawa 72dfb1
    savePopup->setFolder(scene->getScenePath().getParentDir());
shun-iwasawa 72dfb1
  else
shun-iwasawa 72dfb1
    savePopup->setFolder(
shun-iwasawa 72dfb1
        TProjectManager::instance()->getCurrentProject()->getScenesPath());
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  TXsheet* xsh            = TApp::instance()->getCurrentXsheet()->getXsheet();
shun-iwasawa 72dfb1
  TStageObjectId cameraId = xsh->getStageObjectTree()->getCurrentCameraId();
shun-iwasawa 72dfb1
  std::string cameraName  = xsh->getStageObject(cameraId)->getName();
shun-iwasawa 72dfb1
  savePopup->setFilename(TFilePath(cameraName + ".tif"));
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  TFilePath fp = savePopup->getPath();
shun-iwasawa 72dfb1
  if (fp.isEmpty()) return;
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  std::string type = fp.getType();
shun-iwasawa 72dfb1
  if (type == "")
shun-iwasawa 72dfb1
    fp = fp.withType("tif");
shun-iwasawa 72dfb1
  else if (type != "jpg" && type != "jpeg" && type != "bmp" && type != "png" &&
shun-iwasawa 72dfb1
           type != "tif") {
shun-iwasawa 72dfb1
    DVGui::MsgBoxInPopup(DVGui::WARNING,
shun-iwasawa 72dfb1
                         tr("Please specify one of the following file formats; "
shun-iwasawa 72dfb1
                            "jpg, jpeg, bmp, png, and tif"));
shun-iwasawa 72dfb1
    return;
shun-iwasawa 72dfb1
  }
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
  img.save(fp.getQString());
shun-iwasawa 72dfb1
}
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
//********************************************************************************
shun-iwasawa 72dfb1
//    Export Camera Track Command  instantiation
shun-iwasawa 72dfb1
//********************************************************************************
shun-iwasawa 72dfb1
shun-iwasawa 72dfb1
OpenPopupCommandHandler<exportcameratrackpopup> ExportCameraTrackPopupCommand(</exportcameratrackpopup>
shun-iwasawa 72dfb1
    MI_ExportCameraTrack);