From e6f24cd1204ed00d5e647aa4314e1a4eae53ea8b Mon Sep 17 00:00:00 2001 From: Jeremy Bullock Date: Tue, 19 May 2020 23:43:46 -0600 Subject: [PATCH] Test Shots (#3) --- toonz/sources/stopmotion/stopmotion.cpp | 179 ++++++++++++++- toonz/sources/stopmotion/stopmotion.h | 10 + .../stopmotion/stopmotioncontroller.cpp | 214 +++++++++++++++++- .../sources/stopmotion/stopmotioncontroller.h | 18 +- toonz/sources/stopmotion/stopmotionlight.cpp | 40 ++-- toonz/sources/stopmotion/stopmotionlight.h | 1 + toonz/sources/toonz/tpanels.cpp | 4 + 7 files changed, 438 insertions(+), 28 deletions(-) diff --git a/toonz/sources/stopmotion/stopmotion.cpp b/toonz/sources/stopmotion/stopmotion.cpp index e3aa1cba..adc65a21 100644 --- a/toonz/sources/stopmotion/stopmotion.cpp +++ b/toonz/sources/stopmotion/stopmotion.cpp @@ -11,6 +11,7 @@ #include "toutputproperties.h" #include "filebrowserpopup.h" #include "tunit.h" +#include "flipbook.h" #include "toonz/namebuilder.h" #include "toonz/preferences.h" @@ -27,6 +28,7 @@ #include "toonz/levelproperties.h" #include "toonz/tstageobjecttree.h" #include "toonzqt/menubarcommand.h" +#include "toonzqt/icongenerator.h" #include #include @@ -253,7 +255,7 @@ StopMotion::StopMotion() { ret = ret && connect(m_webcamOverlayTimer, SIGNAL(timeout()), this, SLOT(captureWebcamOnTimeout())); ret = ret && connect(m_canon, SIGNAL(newCanonImageReady()), this, - SLOT(importImage())); + SLOT(directDslrImage())); assert(ret); ret = ret && connect(m_canon, SIGNAL(canonCameraChanged(QString)), this, SLOT(onCanonCameraChanged(QString))); @@ -309,7 +311,7 @@ void StopMotion::onSceneSwitched() { setXSheetFrameNumber(xsh->getFrameCount() + 1); loadXmlFile(); buildLiveViewMap(sl); - m_sl = sl; + m_sl = sl; found = true; break; } @@ -1672,6 +1674,7 @@ bool StopMotion::importImage() { postImportProcess(); return true; } + int row = m_xSheetFrameNumber - 1; int col = app->getCurrentColumn()->getColumnIndex(); @@ -1811,6 +1814,10 @@ void StopMotion::captureWebcamImage() { //----------------------------------------------------------------------------- void StopMotion::captureWebcamOnTimeout() { + if (m_isTestShot) { + saveTestShot(); + return; + } if (getReviewTime() > 0 && !m_isTimeLapse) { m_timer->stop(); if (m_liveViewStatus > LiveViewClosed) { @@ -1864,6 +1871,15 @@ void StopMotion::captureDslrImage() { //----------------------------------------------------------------------------- +void StopMotion::directDslrImage() { + if (m_isTestShot) + saveTestShot(); + else + importImage(); +} + +//----------------------------------------------------------------------------- + void StopMotion::postImportProcess() { saveXmlFile(); if (Preferences::instance()->isShowFrameNumberWithLettersEnabled()) { @@ -1885,6 +1901,165 @@ void StopMotion::postImportProcess() { TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); } +//----------------------------------------------------------------- + +void StopMotion::takeTestShot() { + bool sessionOpen = false; +#ifdef WITH_CANON + sessionOpen = m_canon->m_sessionOpen; +#endif + if ((!m_usingWebcam && !sessionOpen) || m_userCalledPause) { + DVGui::warning(tr("Please start live view before capturing an image.")); + return; + } + m_isTestShot = true; + if (m_usingWebcam) { + if (m_light->useOverlays()) { + m_light->showOverlays(); + m_webcamOverlayTimer->start(500); + } + else { + saveTestShot(); + } + } else { + TApp *app = TApp::instance(); + ToonzScene *scene = app->getCurrentScene()->getScene(); + TFilePath parentDir = scene->decodeFilePath(TFilePath(m_filePath)); + TFilePath tempFile = parentDir + "temp.jpg"; + + if (!TFileStatus(parentDir).doesExist()) { + TSystem::mkDir(parentDir); + } + m_tempFile = tempFile.getQString(); +#ifdef WITH_CANON + m_light->showOverlays(); + m_canon->takePicture(); +#endif + } +} + +//----------------------------------------------------------------------------- + +void StopMotion::saveTestShot() { + m_isTestShot = false; + TApp *app = TApp::instance(); + ToonzScene *scene = app->getCurrentScene()->getScene(); + TXsheet *xsh = scene->getXsheet(); + + std::wstring levelName = m_levelName.toStdWString(); + if (levelName.empty()) { + DVGui::error( + tr("No level name specified: please choose a valid level name")); + return; + } + + if (m_usingWebcam) { + m_newImage = m_liveViewImage; + } + + m_light->hideOverlays(); + + /* create parent directory if it does not exist */ + TFilePath parentDir = scene->decodeFilePath(TFilePath(m_filePath)); + + TFilePath testsFolder = scene->decodeFilePath( + TFilePath(m_filePath) + TFilePath(levelName + L"_Tests")); + + TFilePath testsThumbsFolder = scene->decodeFilePath( + TFilePath(m_filePath) + TFilePath(levelName + L"_Tests") + + TFilePath("Thumbs")); + + if (!TFileStatus(parentDir).doesExist()) { + QString question; + question = tr("Folder %1 doesn't exist.\nDo you want to create it?") + .arg(toQString(parentDir)); + int ret = DVGui::MsgBox(question, QObject::tr("Yes"), QObject::tr("No")); + if (ret == 0 || ret == 2) return; + try { + TSystem::mkDir(parentDir); + DvDirModel::instance()->refreshFolder(parentDir.getParentDir()); + } catch (...) { + DVGui::error(tr("Unable to create") + toQString(parentDir)); + return; + } + } + + if (!TFileStatus(testsFolder).doesExist()) { + try { + TSystem::mkDir(testsFolder); + DvDirModel::instance()->refreshFolder(testsFolder.getParentDir()); + } catch (...) { + DVGui::error(tr("Unable to create") + toQString(testsFolder)); + return; + } + } + if (!TFileStatus(testsThumbsFolder).doesExist()) { + try { + TSystem::mkDir(testsThumbsFolder); + DvDirModel::instance()->refreshFolder(testsThumbsFolder.getParentDir()); + } catch (...) { + DVGui::error(tr("Unable to create") + toQString(testsThumbsFolder)); + return; + } + } + + TFilePathSet set = TSystem::readDirectory(testsFolder, false, true, false); + + int fileNumber = 0; + for (auto const &tempPath : set) { + if (tempPath.getUndottedType() == "jpg") { + fileNumber++; + } + } + + TFilePath levelFp = TFilePath(m_filePath) + + TFilePath(levelName + L".." + m_fileType.toStdWString()); + TFilePath actualLevelFp = scene->decodeFilePath(levelFp); + TFilePath actualFile(actualLevelFp.withFrame(fileNumber)); + TFilePath testsFile = scene->decodeFilePath( + testsFolder + + TFilePath(levelName + QString::number(fileNumber).toStdWString() + + L".jpg")); + // TFilePath testsFile(testsFp.withFrame(fileNumber)); + + TFilePath testsThumbsFile = scene->decodeFilePath( + testsThumbsFolder + + TFilePath(levelName + QString::number(fileNumber).toStdWString() + + L".jpg")); + // TFilePath testsThumbsFile(testsThumbsFp.withFrame(fileNumber)); + + TFilePath tempFile = parentDir + "temp.jpg"; + + if (!m_usingWebcam && m_canon->m_useScaledImages) { + TSystem::copyFile(testsFile, tempFile); + TSystem::deleteFile(tempFile); + } else { + JpgConverter::saveJpg(m_newImage, testsFile); + } + cv::Mat imgOriginal(m_newImage->getSize().ly, m_newImage->getSize().lx, + CV_8UC4); + // tempImage = TRaster32P(width, height); + // m_liveViewImage = TRaster32P(width, height); + int size = m_newImage->getPixelSize() * m_newImage->getSize().lx * + m_newImage->getSize().ly; + uchar *imgBuf = imgOriginal.data; + m_newImage->lock(); + uchar *rawData = m_newImage->getRawData(); + memcpy(imgBuf, rawData, size); + m_newImage->unlock(); + int w = m_newImage->getSize().lx; + double r = + (double)m_newImage->getSize().lx / (double)m_newImage->getSize().ly; + cv::Size dim(120, 120.0 / r); + cv::Mat imgThumb(dim, CV_8UC4); + cv::resize(imgOriginal, imgThumb, dim); + cv::flip(imgThumb, imgThumb, 0); + cv::imwrite(testsThumbsFile.getQString().toStdString(), imgThumb); + + emit(updateTestShots()); + FlipBook *fb = ::viewFile(testsFile); +} + //----------------------------------------------------------------------------- void StopMotion::saveXmlFile() { diff --git a/toonz/sources/stopmotion/stopmotion.h b/toonz/sources/stopmotion/stopmotion.h index c6400da1..3539e93f 100644 --- a/toonz/sources/stopmotion/stopmotion.h +++ b/toonz/sources/stopmotion/stopmotion.h @@ -10,6 +10,7 @@ #include "EDSDKTypes.h" #endif +#include "opencv2/opencv.hpp" #include "turbojpeg.h" // Toonz Includes @@ -88,6 +89,7 @@ public: bool m_drawBeneathLevels = true; bool m_isTimeLapse = false; int m_reviewTime = 2; + bool m_isTestShot = false; QString m_tempFile; TXshSimpleLevel* m_sl; @@ -191,6 +193,10 @@ public: bool loadXmlFile(); bool exportImageSequence(); + // tests + void takeTestShot(); + void saveTestShot(); + public slots: // timers void onTimeout(); @@ -199,6 +205,7 @@ public slots: void captureWebcamOnTimeout(); void update(); bool importImage(); + void directDslrImage(); void onSceneSwitched(); void onPlaybackChanged(); void onCanonCameraChanged(QString); @@ -242,6 +249,9 @@ signals: void intervalStarted(); void intervalStopped(); void intervalAmountChanged(int); + + // test shots + void updateTestShots(); }; #endif // STOPMOTION_H \ No newline at end of file diff --git a/toonz/sources/stopmotion/stopmotioncontroller.cpp b/toonz/sources/stopmotion/stopmotioncontroller.cpp index 8347e453..a26957ce 100644 --- a/toonz/sources/stopmotion/stopmotioncontroller.cpp +++ b/toonz/sources/stopmotion/stopmotioncontroller.cpp @@ -24,7 +24,8 @@ #include "tlevel_io.h" #include "toutputproperties.h" #include "tsystem.h" - +#include "tfilepath.h" +#include "flipbook.h" // TnzQt includes #include "toonzqt/filefield.h" #include "toonzqt/intfield.h" @@ -185,12 +186,14 @@ StopMotionController::StopMotionController(QWidget *parent) : QWidget(parent) { m_tabBar->addSimpleTab(tr("Options")); m_tabBar->addSimpleTab(tr("Light")); m_tabBar->addSimpleTab(tr("Motion")); + m_tabBar->addSimpleTab(tr("Tests")); m_tabBarContainer = new TabBarContainter(this); m_mainControlsPage = new QFrame(this); m_cameraSettingsPage = new QFrame(this); m_optionsPage = new QFrame(this); m_motionPage = new QFrame(this); m_lightPage = new QFrame(this); + m_testsPage = new QFrame(this); // ********************** // Make Control Page @@ -872,18 +875,53 @@ StopMotionController::StopMotionController(QWidget *parent) : QWidget(parent) { // motionOutsideLayout->addLayout(motionInsideLayout); m_motionPage->setLayout(motionOutsideLayout); + m_testsOutsideLayout = new QVBoxLayout; + m_testsOutsideLayout->setMargin(0); + m_testsOutsideLayout->setSpacing(0); + m_testsInsideLayout = new QVBoxLayout; + m_testsInsideLayout->setMargin(0); + m_testsInsideLayout->setSpacing(5); + QVBoxLayout *testsButtonLayout = new QVBoxLayout; + testsButtonLayout->setContentsMargins(0, 5, 0, 5); + testsButtonLayout->setSpacing(0); + QFrame *testShotsFrame = new QFrame(); + testShotsFrame->setContentsMargins(0, 0, 0, 0); + testShotsFrame->setStyleSheet("padding:0; margin:0;"); + + QScrollArea *testShotsArea = new QScrollArea(); + testShotsArea->setContentsMargins(0, 0, 0, 0); + testShotsArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + testShotsArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + testShotsArea->setWidgetResizable(true); + + m_takeTestButton = new QPushButton(tr("Test Shot")); + m_takeTestButton->setFixedHeight(25); + testsButtonLayout->addWidget(m_takeTestButton); + m_testsOutsideLayout->addLayout(testsButtonLayout); + + testShotsFrame->setLayout(m_testsInsideLayout); + testShotsArea->setWidget(testShotsFrame); + m_testsOutsideLayout->addWidget(testShotsArea, 500); + m_testsOutsideLayout->addStretch(); + m_testsInsideLayout->addStretch(); + m_testsPage->setLayout(m_testsOutsideLayout); + m_testsPage->setContentsMargins(0, 0, 0, 0); + m_testsPage->setStyleSheet("padding:0; margin:0;"); + QScrollArea *mainArea = makeChooserPageWithoutScrollBar(m_mainControlsPage); QScrollArea *settingsArea = makeChooserPageWithoutScrollBar(m_cameraSettingsPage); QScrollArea *optionsArea = makeChooserPageWithoutScrollBar(m_optionsPage); QScrollArea *lightArea = makeChooserPageWithoutScrollBar(m_lightPage); QScrollArea *motionArea = makeChooserPageWithoutScrollBar(m_motionPage); + QScrollArea *testsArea = makeChooserPageWithoutScrollBar(m_testsPage); mainArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); settingsArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); optionsArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); lightArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); motionArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + testsArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_stackedChooser = new QStackedWidget(this); m_stackedChooser->addWidget(mainArea); @@ -891,6 +929,7 @@ StopMotionController::StopMotionController(QWidget *parent) : QWidget(parent) { m_stackedChooser->addWidget(optionsArea); m_stackedChooser->addWidget(lightArea); m_stackedChooser->addWidget(motionArea); + m_stackedChooser->addWidget(testsArea); m_stackedChooser->setFocusPolicy(Qt::NoFocus); QFrame *opacityFrame = new QFrame(); @@ -1240,12 +1279,20 @@ StopMotionController::StopMotionController(QWidget *parent) : QWidget(parent) { ret = ret && connect(m_stopMotion->m_countdownTimer, SIGNAL(timeout()), this, SLOT(onIntervalCountDownTimeout())); + // Tests + ret = ret && connect(m_takeTestButton, SIGNAL(clicked()), this, + SLOT(onTakeTestButtonClicked())); + ret = ret && connect(m_stopMotion, SIGNAL(updateTestShots()), this, + SLOT(onRefreshTests())); + assert(ret); m_placeOnXSheetCB->setChecked( m_stopMotion->getPlaceOnXSheet() == true ? true : false); + m_useScaledFullSizeImages->setChecked( m_stopMotion->m_canon->m_useScaledImages); + m_onionOpacityFld->setValue(double(100 * m_stopMotion->getOpacity()) / 255.0); m_directShowCB->setChecked(m_stopMotion->m_webcam->getUseDirectShow()); m_useMjpgCB->setChecked(m_stopMotion->m_webcam->getUseMjpg()); @@ -1253,7 +1300,7 @@ StopMotionController::StopMotionController(QWidget *parent) : QWidget(parent) { m_drawBeneathCB->setChecked(m_stopMotion->m_drawBeneathLevels); m_liveViewOnAllFramesCB->setChecked(m_stopMotion->getAlwaysLiveView()); m_blackScreenForCapture->setChecked( - m_stopMotion->m_light->getBlackCapture() == true ? true : false); + m_stopMotion->m_light->getBlackCapture() ? true : false); if (m_stopMotion->m_light->getBlackCapture()) { m_screen1Box->setDisabled(true); m_screen2Box->setDisabled(true); @@ -1321,10 +1368,7 @@ void StopMotionController::onBlackScreenForCaptureChanged(int checked) { void StopMotionController::onBlackCaptureSignal(bool on) { m_blackScreenForCapture->blockSignals(true); - m_blackScreenForCapture->setChecked(on); - m_screen1Box->setDisabled(on); - m_screen2Box->setDisabled(on); - m_screen3Box->setDisabled(on); + updateLightsEnabled(); m_blackScreenForCapture->blockSignals(false); } @@ -1396,6 +1440,7 @@ void StopMotionController::onScreen3ColorChanged(TPixel32 color) { void StopMotionController::onScreen1OverlayChanged(bool on) { m_screen1Box->blockSignals(true); m_screen1Box->setChecked(on); + updateLightsEnabled(); m_screen1Box->blockSignals(false); } @@ -1404,6 +1449,7 @@ void StopMotionController::onScreen1OverlayChanged(bool on) { void StopMotionController::onScreen2OverlayChanged(bool on) { m_screen2Box->blockSignals(true); m_screen2Box->setChecked(on); + updateLightsEnabled(); m_screen2Box->blockSignals(false); } @@ -1412,6 +1458,7 @@ void StopMotionController::onScreen2OverlayChanged(bool on) { void StopMotionController::onScreen3OverlayChanged(bool on) { m_screen3Box->blockSignals(true); m_screen3Box->setChecked(on); + updateLightsEnabled(); m_screen3Box->blockSignals(false); } @@ -1430,6 +1477,24 @@ void StopMotionController::onTestLightsTimeout() { //----------------------------------------------------------------------------- +void StopMotionController::updateLightsEnabled() { + bool enabled = true; + if (m_blackScreenForCapture->isChecked()) { + enabled = false; + } + m_screen1Box->setEnabled(enabled); + m_screen2Box->setEnabled(enabled); + m_screen3Box->setEnabled(enabled); + if (m_blackScreenForCapture->isChecked() || m_screen1Box->isChecked() || + m_screen2Box->isChecked() || m_screen3Box->isChecked()) { + m_testLightsButton->setEnabled(true); + } else { + m_testLightsButton->setEnabled(false); + } +} + +//----------------------------------------------------------------------------- + void StopMotionController::onPlaceOnXSheetChanged(int checked) { m_stopMotion->setPlaceOnXSheet(checked); } @@ -1541,6 +1606,7 @@ void StopMotionController::onFilePathChanged(QString filePath) { void StopMotionController::onLevelNameChanged(QString levelName) { m_levelNameEdit->setText(levelName); + onRefreshTests(); } //----------------------------------------------------------------------------- @@ -2501,6 +2567,7 @@ void StopMotionController::showEvent(QShowEvent *event) { } else { m_noCameraFrame->hide(); } + onRefreshTests(); } //----------------------------------------------------------------------------- @@ -2515,6 +2582,23 @@ void StopMotionController::hideEvent(QHideEvent *event) { //----------------------------------------------------------------------------- +void StopMotionController::resizeEvent(QResizeEvent *event) { + int width = event->size().width(); + int imageWidth = 1; + if (m_testImages.size() > 0) { + imageWidth = m_testImages.at(0).width() + 30; + + int perRow = width / imageWidth; + if (perRow != m_testsImagesPerRow) { + m_testsImagesPerRow = perRow; + reflowTestShots(); + } + } + QWidget::resizeEvent(event); +} + +//----------------------------------------------------------------------------- + void StopMotionController::keyPressEvent(QKeyEvent *event) { int key = event->key(); TFrameHandle *fh = TApp::instance()->getCurrentFrame(); @@ -2756,6 +2840,7 @@ void StopMotionController::onSceneSwitched() { // m_saveInFolderPopup->updateParentFolder(); // m_saveInFileFld->setPath(m_saveInFolderPopup->getParentPath()); // m_stopMotion->refreshFrameInfo(); + onRefreshTests(); } //----------------------------------------------------------------------------- @@ -2767,3 +2852,120 @@ void StopMotionController::serialPortChanged(int index) { //----------------------------------------------------------------------------- void StopMotionController::updateStopMotion() {} + +//----------------------------------------------------------------------------- + +void StopMotionController::onTakeTestButtonClicked() { + if (m_stopMotion->m_liveViewStatus == StopMotion::LiveViewOpen) { + m_stopMotion->takeTestShot(); + } +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onRefreshTests() { + clearTests(); + m_testFullResListVector.clear(); + m_testImages.clear(); + + TApp *app = TApp::instance(); + ToonzScene *scene = app->getCurrentScene()->getScene(); + TXsheet *xsh = scene->getXsheet(); + std::wstring levelName = m_levelNameEdit->text().toStdWString(); + if (levelName == L"") return; + + TFilePath filePath = TFilePath(m_saveInFileFld->getPath()); + TFilePath parentDir = scene->decodeFilePath(filePath); + + TFilePath testsFolder = scene->decodeFilePath( + TFilePath(filePath) + TFilePath(levelName + L"_Tests")); + + TFilePath testsThumbsFolder = scene->decodeFilePath( + TFilePath(filePath) + TFilePath(levelName + L"_Tests") + + TFilePath("Thumbs")); + + // if (!TSystem::doesExistFileOrLevel(testsFolder)) return; + QString huh = QDir(testsFolder.getQString()).absolutePath(); + if (!QDir(huh).exists()) return; + + TFilePathSet set = TSystem::readDirectory(testsFolder, false, true, false); + + for (auto const &tempPath : set) { + if (tempPath.getUndottedType() == "jpg") { + TFrameId tempFrame = tempPath.getFrame(); + TFilePath justFolders = tempPath.getParentDir(); + std::string justName = tempPath.getName() + ".jpg"; + TFilePath testsThumbsFile = + scene->decodeFilePath(testsThumbsFolder + justName); + // TFilePath + // testsThumbsFile(testsThumbsFp.withFrame(tempFrame.getNumber())); + if (!TSystem::doesExistFileOrLevel(testsThumbsFile)) continue; + QPixmap thumb = QPixmap(testsThumbsFile.getQString()); + m_testFullResListVector.push_back(tempPath); + m_testImages.push_back(thumb); + } + } + if (m_testFullResListVector.size() > 0) { + int width = this->width(); + int padding = 30; + int imageWidth = m_testImages[0].width(); + int imageHeight = m_testImages[0].height(); + m_testsImagesPerRow = width / imageWidth; + } + reflowTestShots(); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::reflowTestShots() { + clearTests(); + + if (m_testFullResListVector.size() > 0) { + int padding = 20; + int imageWidth = m_testImages[0].width(); + int imageHeight = m_testImages[0].height(); + QHBoxLayout *layout = new QHBoxLayout(); + int j = 0; + for (int i = 0; i < m_testImages.size(); i++) { + QPushButton *button = new QPushButton(); + button->setIcon(QIcon(m_testImages.at(i))); + button->setFixedHeight(imageHeight + padding); + button->setFixedWidth(imageWidth + padding); + button->setIconSize(QSize(imageWidth, imageHeight)); + connect(button, &QPushButton::clicked, [=] { + FlipBook *fb = ::viewFile(m_testFullResListVector.at(i)); + }); + layout->addWidget(button); + j++; + if (j >= m_testsImagesPerRow) { + m_testHBoxes.push_back(layout); + layout = new QHBoxLayout(); + j = 0; + } + } + if (j < m_testsImagesPerRow && j > 0) { + m_testHBoxes.push_back(layout); + } + } + for (QHBoxLayout *layout : m_testHBoxes) { + // m_testsOutsideLayout->addLayout(layout); + m_testsInsideLayout->insertLayout(m_testsInsideLayout->count() - 1, layout); + } +} + +//----------------------------------------------------------------------------- + +void StopMotionController::clearTests() { + if (m_testHBoxes.size() > 0) { + for (QHBoxLayout *layout : m_testHBoxes) { + QLayoutItem *item; + while ((item = layout->takeAt(0)) != NULL) { + delete item->widget(); + delete item; + } + m_testsInsideLayout->removeItem(layout); + delete layout; + } + m_testHBoxes.clear(); + } +} \ No newline at end of file diff --git a/toonz/sources/stopmotion/stopmotioncontroller.h b/toonz/sources/stopmotion/stopmotioncontroller.h index dda7ceac..5c299227 100644 --- a/toonz/sources/stopmotion/stopmotioncontroller.h +++ b/toonz/sources/stopmotion/stopmotioncontroller.h @@ -69,13 +69,14 @@ class StopMotionController final : public QWidget { QFrame *m_optionsPage; QFrame *m_motionPage; QFrame *m_lightPage; + QFrame *m_testsPage; QFrame *m_dslrFrame; QFrame *m_webcamFrame; QFrame *m_noCameraFrame; QStackedWidget *m_stackedChooser; TabBarContainter *m_tabBarContainer; //!< Tabs container for pages QPushButton *m_toggleLiveViewButton, *m_setToCurrentXSheetFrameButton, - *m_alwaysUseLiveViewImagesButton; + *m_alwaysUseLiveViewImagesButton, *m_takeTestButton; QPushButton *m_captureButton, *m_zoomButton, *m_fileFormatOptionButton, *m_pickZoomButton, *m_focusNearButton, *m_focusFarButton, *m_focusNear2Button, *m_focusNear3Button, *m_focusFar2Button, @@ -112,6 +113,14 @@ class StopMotionController final : public QWidget { QGroupBox *m_webcamAutoFocusGB; QTimer *m_lightTestTimer; + // tests variables + std::vector m_testImages; + std::vector m_testFullResListVector; + std::vector m_testHBoxes; + QVBoxLayout *m_testsOutsideLayout; + QVBoxLayout *m_testsInsideLayout; + int m_testsImagesPerRow; + public: StopMotionController(QWidget *parent = 0); ~StopMotionController(); @@ -123,6 +132,8 @@ protected: // void mousePressEvent(QMouseEvent *event) override; // void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + void reflowTestShots(); protected slots: void refreshCameraList(QString activeCamera = ""); @@ -186,6 +197,7 @@ protected slots: void onScreen3OverlayToggled(bool); void onTestLightsPressed(); void onTestLightsTimeout(); + void updateLightsEnabled(); void onScreen1ColorChanged(TPixel32); void onScreen2ColorChanged(TPixel32); void onScreen3ColorChanged(TPixel32); @@ -268,6 +280,10 @@ protected slots: void onWebcamSaturationSliderChanged(int value); void getWebcamStatus(); + void onTakeTestButtonClicked(); + void onRefreshTests(); + void clearTests(); + public slots: void openSaveInFolderPopup(); }; diff --git a/toonz/sources/stopmotion/stopmotionlight.cpp b/toonz/sources/stopmotion/stopmotionlight.cpp index 2a949e48..09ec87bf 100644 --- a/toonz/sources/stopmotion/stopmotionlight.cpp +++ b/toonz/sources/stopmotion/stopmotionlight.cpp @@ -115,27 +115,27 @@ void StopMotionLight::showOverlays() { m_fullScreen3->setStyleSheet(style3); } } - bool shown = false; + m_shown = false; bool isTimeLapse = StopMotion::instance()->m_isTimeLapse; if ((getBlackCapture() || m_useScreen1Overlay) && !isTimeLapse) { m_fullScreen1->showFullScreen(); m_fullScreen1->setGeometry(QApplication::desktop()->screenGeometry(0)); - shown = true; + m_shown = true; } if (m_screenCount > 1 && (getBlackCapture() || m_useScreen2Overlay) && !isTimeLapse) { m_fullScreen2->showFullScreen(); m_fullScreen2->setGeometry(QApplication::desktop()->screenGeometry(1)); - shown = true; + m_shown = true; } if (m_screenCount > 2 && (getBlackCapture() || m_useScreen3Overlay) && !isTimeLapse) { m_fullScreen3->showFullScreen(); m_fullScreen3->setGeometry(QApplication::desktop()->screenGeometry(2)); - shown = true; + m_shown = true; } - if (shown) { + if (m_shown) { // this allows the full screen qdialogs to go full screen before // taking a photo qApp->processEvents(QEventLoop::AllEvents, 1500); @@ -146,26 +146,28 @@ void StopMotionLight::showOverlays() { //----------------------------------------------------------------- void StopMotionLight::hideOverlays() { - if ((getBlackCapture() || m_useScreen1Overlay)) { + if (m_shown) { + if ((getBlackCapture() || m_useScreen1Overlay)) { #ifndef WIN32 - m_fullScreen1->showNormal(); + m_fullScreen1->showNormal(); #endif - m_fullScreen1->close(); - m_fullScreen1->windowHandle()->close(); - } - if (m_screenCount > 1 && (getBlackCapture() || m_useScreen2Overlay)) { + m_fullScreen1->close(); + m_fullScreen1->windowHandle()->close(); + } + if (m_screenCount > 1 && (getBlackCapture() || m_useScreen2Overlay)) { #ifndef WIN32 - m_fullScreen2->showNormal(); + m_fullScreen2->showNormal(); #endif - m_fullScreen2->close(); - m_fullScreen2->windowHandle()->close(); - } - if (m_screenCount > 2 && (getBlackCapture() || m_useScreen3Overlay)) { + m_fullScreen2->close(); + m_fullScreen2->windowHandle()->close(); + } + if (m_screenCount > 2 && (getBlackCapture() || m_useScreen3Overlay)) { #ifndef WIN32 - m_fullScreen3->showNormal(); + m_fullScreen3->showNormal(); #endif - m_fullScreen3->close(); - m_fullScreen3->windowHandle()->close(); + m_fullScreen3->close(); + m_fullScreen3->windowHandle()->close(); + } } m_overlaysReady = false; } diff --git a/toonz/sources/stopmotion/stopmotionlight.h b/toonz/sources/stopmotion/stopmotionlight.h index 3bd06a80..d78d66bb 100644 --- a/toonz/sources/stopmotion/stopmotionlight.h +++ b/toonz/sources/stopmotion/stopmotionlight.h @@ -26,6 +26,7 @@ public: bool m_useScreen3Overlay = false; bool m_blackCapture = true; bool m_overlaysReady = false; + bool m_shown = false; int m_screenCount = 1; TPixel32 m_screen1Color, m_screen2Color, m_screen3Color = TPixel32(0, 0, 0, 255); diff --git a/toonz/sources/toonz/tpanels.cpp b/toonz/sources/toonz/tpanels.cpp index 47ae17fe..8fc0fa54 100644 --- a/toonz/sources/toonz/tpanels.cpp +++ b/toonz/sources/toonz/tpanels.cpp @@ -733,6 +733,10 @@ void ColorFieldEditorController::onColorChanged(const TPixel32 &color, bool) { ->notifyColorStyleChanged(); } +//============================================================================= +ColorFieldEditorController colorFieldEditorController; +//----------------------------------------------------------------------------- + //============================================================================= // style editor //-----------------------------------------------------------------------------