From f159071bf76e4478afeb01720128424ee6c6526e Mon Sep 17 00:00:00 2001 From: Jeremy Bullock Date: Dec 23 2019 11:24:44 +0000 Subject: Canon DSLR and Stop Motion Support (#2635) * Stop Motion Features Please note that this feature won't appear in the nightly build until some related changes are completed. --- diff --git a/doc/how_to_build_win.md b/doc/how_to_build_win.md index fd29505..08d6ada 100644 --- a/doc/how_to_build_win.md +++ b/doc/how_to_build_win.md @@ -70,6 +70,23 @@ Rename the following files: 1. Open `$opentoonz/toonz/build/OpenToonz.sln` and change to `Debug` or `Release` in the top bar. 2. The output will be in the corresponding folder in `$opentoonz/toonz/build/` +## Building with extended stop motion support for webcams and Canon DSLR cameras. +You will need three additional libraries. + - [OpenCV](https://opencv.org/) + - [libjpeg-turbo](https://www.libjpeg-turbo.org/) + - The Canon SDK. This requires applying for the Canon developer program and downloading the SDK. + +Copy the following folders into the `$opentoonz/thirdparty` folder. + - Copy the Header and library folders from the Canon SDK to `$opentoonz/thirdparty/canon` + - Make sure that the library is the one from the EDSDK_64 folder. + - Copy the lib and include folders from libjpeg-turbo64 into `$opentoonz/thirdparty/libjpeg-turbo64`. + - Copy the include folder from opencv2/build into `$opentoonz/thirdparty/opencv2` + - Copy the lib folder from opencv2/build/x64/vc15 into `$opentoonz/thirdparty/opencv2` + +Check the checkbox in CMake to build with stop motion support. + +To run the program with stop motion support, you will need to copy the .dll files from opencv2, libjpeg-turbo and the Canon SDK into the folder where your project is built. + ## Running the Program ### Setting Up the Program's Path 1. Copy the entire contents of `$opentoonz/toonz/build/Release` to an appropriate folder. diff --git a/stuff/config/qss/Blue/Blue.qss b/stuff/config/qss/Blue/Blue.qss index 834f586..3546927 100644 --- a/stuff/config/qss/Blue/Blue.qss +++ b/stuff/config/qss/Blue/Blue.qss @@ -151,6 +151,7 @@ QGroupBox { qproperty-BottomBelowLineColor: #212223; } .tab-flat, +#StopMotionTabBar::tab, #StyleEditorTabBar::tab, #PaletteTabBar::tab, #FxSettingsTabBar::tab { @@ -161,6 +162,7 @@ QGroupBox { padding: 3 4 3 4; } .tab-flat:hover, +#StopMotionTabBar::tab:hover, #StyleEditorTabBar::tab:hover, #PaletteTabBar::tab:hover, #FxSettingsTabBar::tab:hover { @@ -168,6 +170,7 @@ QGroupBox { color: #94969a; } .tab-flat:selected, +#StopMotionTabBar::tab:selected, #StyleEditorTabBar::tab:selected, #PaletteTabBar::tab:selected, #FxSettingsTabBar::tab:selected { @@ -176,6 +179,7 @@ QGroupBox { border-bottom-color: #414345; } .tab-flat:only-one, +#StopMotionTabBar::tab:only-one, #StyleEditorTabBar::tab:only-one, #PaletteTabBar::tab:only-one, #FxSettingsTabBar::tab:only-one { @@ -1159,6 +1163,29 @@ PencilTestPopup { font-size: 17px; } /* ----------------------------------------------------------------------------- + Stop Motion Controller +----------------------------------------------------------------------------- */ +#StopMotionController QScrollArea { + margin: 8; +} +#StopMotionController QPushButton { + margin: 2 1; + padding: 0; +} +#StopMotionController #TabBarContainer { + margin-left: -4; +} +#StopMotionController #bottomWidget { + border-top: 1 solid #212223; + padding: 3 2 8 3; +} +#StopMotionController #bottomWidget QPushButton { + padding: 3 5; +} +#StopMotionTabBar::tab::first { + border-left: 1 solid #212223; +} +/* ----------------------------------------------------------------------------- Unknowns + Legacy ----------------------------------------------------------------------------- */ #StartupLabel { diff --git a/stuff/config/qss/Dark/Dark.qss b/stuff/config/qss/Dark/Dark.qss index 18d74b9..2fc49e3 100644 --- a/stuff/config/qss/Dark/Dark.qss +++ b/stuff/config/qss/Dark/Dark.qss @@ -151,6 +151,7 @@ QGroupBox { qproperty-BottomBelowLineColor: #161616; } .tab-flat, +#StopMotionTabBar::tab, #StyleEditorTabBar::tab, #PaletteTabBar::tab, #FxSettingsTabBar::tab { @@ -161,6 +162,7 @@ QGroupBox { padding: 3 4 3 4; } .tab-flat:hover, +#StopMotionTabBar::tab:hover, #StyleEditorTabBar::tab:hover, #PaletteTabBar::tab:hover, #FxSettingsTabBar::tab:hover { @@ -168,6 +170,7 @@ QGroupBox { color: #8b8b8b; } .tab-flat:selected, +#StopMotionTabBar::tab:selected, #StyleEditorTabBar::tab:selected, #PaletteTabBar::tab:selected, #FxSettingsTabBar::tab:selected { @@ -176,6 +179,7 @@ QGroupBox { border-bottom-color: #303030; } .tab-flat:only-one, +#StopMotionTabBar::tab:only-one, #StyleEditorTabBar::tab:only-one, #PaletteTabBar::tab:only-one, #FxSettingsTabBar::tab:only-one { @@ -1159,6 +1163,29 @@ PencilTestPopup { font-size: 17px; } /* ----------------------------------------------------------------------------- + Stop Motion Controller +----------------------------------------------------------------------------- */ +#StopMotionController QScrollArea { + margin: 8; +} +#StopMotionController QPushButton { + margin: 2 1; + padding: 0; +} +#StopMotionController #TabBarContainer { + margin-left: -4; +} +#StopMotionController #bottomWidget { + border-top: 1 solid #161616; + padding: 3 2 8 3; +} +#StopMotionController #bottomWidget QPushButton { + padding: 3 5; +} +#StopMotionTabBar::tab::first { + border-left: 1 solid #161616; +} +/* ----------------------------------------------------------------------------- Unknowns + Legacy ----------------------------------------------------------------------------- */ #StartupLabel { diff --git a/stuff/config/qss/Default/Default.qss b/stuff/config/qss/Default/Default.qss index a40646d..dc2f370 100644 --- a/stuff/config/qss/Default/Default.qss +++ b/stuff/config/qss/Default/Default.qss @@ -151,6 +151,7 @@ QGroupBox { qproperty-BottomBelowLineColor: #272727; } .tab-flat, +#StopMotionTabBar::tab, #StyleEditorTabBar::tab, #PaletteTabBar::tab, #FxSettingsTabBar::tab { @@ -161,6 +162,7 @@ QGroupBox { padding: 3 4 3 4; } .tab-flat:hover, +#StopMotionTabBar::tab:hover, #StyleEditorTabBar::tab:hover, #PaletteTabBar::tab:hover, #FxSettingsTabBar::tab:hover { @@ -168,6 +170,7 @@ QGroupBox { color: #a1a1a1; } .tab-flat:selected, +#StopMotionTabBar::tab:selected, #StyleEditorTabBar::tab:selected, #PaletteTabBar::tab:selected, #FxSettingsTabBar::tab:selected { @@ -176,6 +179,7 @@ QGroupBox { border-bottom-color: #484848; } .tab-flat:only-one, +#StopMotionTabBar::tab:only-one, #StyleEditorTabBar::tab:only-one, #PaletteTabBar::tab:only-one, #FxSettingsTabBar::tab:only-one { @@ -1159,6 +1163,29 @@ PencilTestPopup { font-size: 17px; } /* ----------------------------------------------------------------------------- + Stop Motion Controller +----------------------------------------------------------------------------- */ +#StopMotionController QScrollArea { + margin: 8; +} +#StopMotionController QPushButton { + margin: 2 1; + padding: 0; +} +#StopMotionController #TabBarContainer { + margin-left: -4; +} +#StopMotionController #bottomWidget { + border-top: 1 solid #272727; + padding: 3 2 8 3; +} +#StopMotionController #bottomWidget QPushButton { + padding: 3 5; +} +#StopMotionTabBar::tab::first { + border-left: 1 solid #272727; +} +/* ----------------------------------------------------------------------------- Unknowns + Legacy ----------------------------------------------------------------------------- */ #StartupLabel { diff --git a/stuff/config/qss/Default/less/layouts/misc.less b/stuff/config/qss/Default/less/layouts/misc.less index d1fb1b9..b22dbc9 100644 --- a/stuff/config/qss/Default/less/layouts/misc.less +++ b/stuff/config/qss/Default/less/layouts/misc.less @@ -26,6 +26,44 @@ PencilTestPopup { } /* ----------------------------------------------------------------------------- + Stop Motion Controller +----------------------------------------------------------------------------- */ + +#StopMotionController { + & QScrollArea { + margin: 8; + } + & QPushButton { + // Adds spacing to buttons, but this setting may be temporary + margin: 2 1; + padding: 0; + } + & #TabBarContainer { + margin-left: -4; // reset left edge margin + } + & #bottomWidget { + border-top: 1 solid @accent; + padding: 3 2 8 3; + & QPushButton { + // override above margin reset + padding: 3 5; + } + } +} + +#StopMotionTabBar { + &::tab { + &:extend(.tab-flat all); + &::first { + // add a border to first item on + // the left side due to the spacer + // coded in the cpp file + border-left: 1 solid @accent; + } + } +} + +/* ----------------------------------------------------------------------------- Unknowns + Legacy ----------------------------------------------------------------------------- */ // below are classes that are unknown and considered legacy diff --git a/stuff/config/qss/Light/Light.qss b/stuff/config/qss/Light/Light.qss index 8503827..a3608db 100644 --- a/stuff/config/qss/Light/Light.qss +++ b/stuff/config/qss/Light/Light.qss @@ -151,6 +151,7 @@ QGroupBox { qproperty-BottomBelowLineColor: #404040; } .tab-flat, +#StopMotionTabBar::tab, #StyleEditorTabBar::tab, #PaletteTabBar::tab, #FxSettingsTabBar::tab { @@ -161,6 +162,7 @@ QGroupBox { padding: 3 4 3 4; } .tab-flat:hover, +#StopMotionTabBar::tab:hover, #StyleEditorTabBar::tab:hover, #PaletteTabBar::tab:hover, #FxSettingsTabBar::tab:hover { @@ -168,6 +170,7 @@ QGroupBox { color: #fff; } .tab-flat:selected, +#StopMotionTabBar::tab:selected, #StyleEditorTabBar::tab:selected, #PaletteTabBar::tab:selected, #FxSettingsTabBar::tab:selected { @@ -176,6 +179,7 @@ QGroupBox { border-bottom-color: #808080; } .tab-flat:only-one, +#StopMotionTabBar::tab:only-one, #StyleEditorTabBar::tab:only-one, #PaletteTabBar::tab:only-one, #FxSettingsTabBar::tab:only-one { @@ -1159,6 +1163,29 @@ PencilTestPopup { font-size: 17px; } /* ----------------------------------------------------------------------------- + Stop Motion Controller +----------------------------------------------------------------------------- */ +#StopMotionController QScrollArea { + margin: 8; +} +#StopMotionController QPushButton { + margin: 2 1; + padding: 0; +} +#StopMotionController #TabBarContainer { + margin-left: -4; +} +#StopMotionController #bottomWidget { + border-top: 1 solid #404040; + padding: 3 2 8 3; +} +#StopMotionController #bottomWidget QPushButton { + padding: 3 5; +} +#StopMotionTabBar::tab::first { + border-left: 1 solid #404040; +} +/* ----------------------------------------------------------------------------- Unknowns + Legacy ----------------------------------------------------------------------------- */ #StartupLabel { diff --git a/thirdparty/canon/.gitignore b/thirdparty/canon/.gitignore new file mode 100644 index 0000000..7551faf --- /dev/null +++ b/thirdparty/canon/.gitignore @@ -0,0 +1,2 @@ +Header/* +library/* \ No newline at end of file diff --git a/thirdparty/canon/copy_canon_sdk.txt b/thirdparty/canon/copy_canon_sdk.txt new file mode 100644 index 0000000..20bfeeb --- /dev/null +++ b/thirdparty/canon/copy_canon_sdk.txt @@ -0,0 +1,2 @@ +Copy the Header and library folders from the Canon SDK to this folder. +Make sure that the library is the one from the EDSDK_64 folder. \ No newline at end of file diff --git a/thirdparty/libjpeg-turbo64/.gitignore b/thirdparty/libjpeg-turbo64/.gitignore new file mode 100644 index 0000000..0a61909 --- /dev/null +++ b/thirdparty/libjpeg-turbo64/.gitignore @@ -0,0 +1,2 @@ +include/* +lib/* diff --git a/thirdparty/libjpeg-turbo64/.gitkeep b/thirdparty/libjpeg-turbo64/.gitkeep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/thirdparty/libjpeg-turbo64/.gitkeep diff --git a/thirdparty/libjpeg-turbo64/copy_libjpeg-turbo64.txt b/thirdparty/libjpeg-turbo64/copy_libjpeg-turbo64.txt new file mode 100644 index 0000000..d507ae6 --- /dev/null +++ b/thirdparty/libjpeg-turbo64/copy_libjpeg-turbo64.txt @@ -0,0 +1 @@ +Copy the lib and include folders from libjpeg-turbo64 into this folder. \ No newline at end of file diff --git a/thirdparty/opencv2/.gitignore b/thirdparty/opencv2/.gitignore new file mode 100644 index 0000000..01d5602 --- /dev/null +++ b/thirdparty/opencv2/.gitignore @@ -0,0 +1,2 @@ +lib/* +include/* diff --git a/thirdparty/opencv2/.gitkeep b/thirdparty/opencv2/.gitkeep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/thirdparty/opencv2/.gitkeep diff --git a/thirdparty/opencv2/copy_opencv2.txt b/thirdparty/opencv2/copy_opencv2.txt new file mode 100644 index 0000000..899d66d --- /dev/null +++ b/thirdparty/opencv2/copy_opencv2.txt @@ -0,0 +1,2 @@ +Copy the include folder from opencv2/build into this folder +Copy the lib folder from opencv2/build/x64/vc15 into this folder \ No newline at end of file diff --git a/toonz/sources/CMakeLists.txt b/toonz/sources/CMakeLists.txt index 32a5828..76d23d0 100644 --- a/toonz/sources/CMakeLists.txt +++ b/toonz/sources/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.11) +cmake_minimum_required(VERSION 2.8.11) set(CMAKE_BUILD_TYPE_INIT Release) @@ -101,6 +101,7 @@ endif() option(WITH_SYSTEM_LZO "Use the system LZO library instead of 'thirdpary'" ${_init_SYSTEM_LZO}) option(WITH_SYSTEM_SUPERLU "Use the system SuperLU library instead of 'thirdpary'" ${_init_SYSTEM_SUPERLU}) +option(WITH_STOPMOTION "Build with Stop Motion features - Requires Canon SDK" OFF) # avoid using again option_defaults_clear() @@ -258,12 +259,27 @@ if(Qt5Core_VERSION VERSION_LESS QT_MINIMUM_VERSION) endif() unset(QT_MINIMUM_VERSION) -if(BUILD_ENV_MSVC) +if(BUILD_ENV_MSVC AND NOT WITH_STOPMOTION) + include_directories( + SYSTEM + ${SDKROOT}/glut/3.7.6/include + ${SDKROOT}/zlib-1.2.8 + ${SDKROOT}/LibJPEG/jpeg-9 + ) + add_definitions( + -DGLUT_NO_LIB_PRAGMA + ) +endif() + +if(BUILD_ENV_MSVC AND WITH_STOPMOTION) include_directories( SYSTEM ${SDKROOT}/glut/3.7.6/include ${SDKROOT}/zlib-1.2.8 ${SDKROOT}/LibJPEG/jpeg-9 + ${SDKROOT}/canon/Header + ${SDKROOT}/libjpeg-turbo64/include + ${SDKROOT}/opencv2/include ) add_definitions( -DGLUT_NO_LIB_PRAGMA @@ -330,6 +346,14 @@ if(BUILD_ENV_MSVC) set(SUPERLU_LIB ${SDKROOT}/superlu/SuperLU_${MSVC_LIB_VERSION}_${PLATFORM}.lib) set(OPENBLAS_LIB ${SDKROOT}/openblas/libopenblas_${PLATFORM}.lib) set(USB_LIB) # unused + if (WITH_STOPMOTION) + set(CANON_LIB ${SDKROOT}/canon/library/EDSDK.lib) + set(TURBOJPEG_LIB ${SDKROOT}/libjpeg-turbo64/lib/turbojpeg.lib) + set(OPENCV_LIB + optimized ${SDKROOT}/opencv2/lib/opencv_world412.lib + debug ${SDKROOT}/opencv2/lib/opencv_world412d.lib + ) + endif() if(PLATFORM EQUAL 32) set(QT_LIB ${SDKROOT}/quicktime/QT73SDK/Libraries/QTMLClient.lib) endif() diff --git a/toonz/sources/include/toonz/levelproperties.h b/toonz/sources/include/toonz/levelproperties.h index c6c4531..93ce2f0 100644 --- a/toonz/sources/include/toonz/levelproperties.h +++ b/toonz/sources/include/toonz/levelproperties.h @@ -48,11 +48,13 @@ public: //! adpoted. bool m_whiteTransp, //!< [default: false] Whether white should be - //! visualized as transparent. - m_premultiply; //!< [default: false] Whether level images should + //! visualized as transparent. + m_premultiply, //!< [default: false] Whether level images should //! be - //! premultiplied by Toonz for alpha compositing (because they - //! are not). + //! premultiplied by Toonz for alpha compositing (because they + //! are not). + m_isStopMotionLevel; + public: LevelOptions(); //!< Constructs with default values. @@ -220,6 +222,13 @@ ie } bool whiteTransp() const { return m_options.m_whiteTransp; } + void setIsStopMotion(bool isStopMotion) // Is this level used for Stop Motion + + { + m_options.m_isStopMotionLevel = isStopMotion; + } + bool isStopMotionLevel() const { return m_options.m_isStopMotionLevel; } + private: TPointD m_imageDpi; diff --git a/toonz/sources/include/toonz/ttileset.h b/toonz/sources/include/toonz/ttileset.h index c2cefcd..3e64e0c 100644 --- a/toonz/sources/include/toonz/ttileset.h +++ b/toonz/sources/include/toonz/ttileset.h @@ -84,7 +84,7 @@ public: Tile(const TRasterCM32P &ras, const TPoint &p); ~Tile(); QString id() const override { - return "TileCM" + QString::number((uintptr_t)this); + return "TileCM" + QString::number((uintptr_t) this); } Tile *clone() const override; @@ -124,7 +124,7 @@ public: Tile(const TRasterP &ras, const TPoint &p); ~Tile(); QString id() const override { - return "TTileSet32::Tile" + QString::number((uintptr_t)this); + return "TTileSet32::Tile" + QString::number((uintptr_t) this); } Tile *clone() const override; diff --git a/toonz/sources/stopmotion/stopmotion.cpp b/toonz/sources/stopmotion/stopmotion.cpp new file mode 100644 index 0000000..3b92539 --- /dev/null +++ b/toonz/sources/stopmotion/stopmotion.cpp @@ -0,0 +1,4013 @@ +#include "stopmotion.h" + +#ifdef WIN32 +#include +#include +#include +#include +#pragma comment(lib, "Mfplat.lib") +#pragma comment(lib, "Mf.lib") +#pragma comment(lib, "Mfreadwrite.lib") +#pragma comment(lib, "mfuuid.lib") +#pragma comment(lib, "shlwapi.lib") +#endif + +// TnzCore includes +#include "menubarcommandids.h" +#include "tapp.h" +#include "tenv.h" +#include "tsystem.h" +#include "filebrowsermodel.h" +#include "penciltestpopup.h" +#include "tlevel_io.h" +#include "toutputproperties.h" + +#include "toonz/namebuilder.h" +#include "toonz/preferences.h" +#include "toonz/tcamera.h" +#include "toonz/tcolumnhandle.h" +#include "toonz/tframehandle.h" +#include "toonz/levelset.h" +#include "toonz/sceneproperties.h" +#include "toonz/toonzscene.h" +#include "toonz/tscenehandle.h" +#include "toonz/stage.h" +#include "toonz/txsheethandle.h" +#include "toonz/txshlevelhandle.h" +#include "toonz/txshsimplelevel.h" +#include "toonz/levelproperties.h" +#include "toonz/tstageobjecttree.h" + +#include "toonzqt/menubarcommand.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Connected camera +TEnv::IntVar StopMotionUseScaledImages("StopMotionUseScaledImages", 0); +TEnv::IntVar StopMotionOpacity("StopMotionOpacity", 100); +TEnv::IntVar StopMotionUseDirectShow("StopMotionUseDirectShow", 1); +TEnv::IntVar StopMotionAlwaysLiveView("StopMotionAlwaysLiveView", 0); + +TEnv::IntVar StopMotionBlackCapture("StopMotionBlackCapture", 0); +TEnv::IntVar StopMotionPlaceOnXSheet("StopMotionPlaceOnXSheet", 1); +TEnv::IntVar StopMotionReviewTime("StopMotionReviewTime", 1); +TEnv::IntVar StopMotionUseMjpg("StopMotionUseMjpg", 1); +TEnv::IntVar StopMotionUseNumpad("StopMotionUseNumpad", 0); + +// Connected camera +TEnv::StringVar StopMotionCameraName("CamCapCameraName", ""); +// Camera resolution +TEnv::StringVar StopMotionCameraResolution("CamCapCameraResolution", ""); + +namespace { +bool l_quitLoop = false; + +TPointD getCurrentCameraDpi() { + TCamera *camera = + TApp::instance()->getCurrentScene()->getScene()->getCurrentCamera(); + TDimensionD size = camera->getSize(); + TDimension res = camera->getRes(); + return TPointD(res.lx / size.lx, res.ly / size.ly); +} + +//----------------------------------------------------------------------------- + +bool findCell(TXsheet *xsh, int col, const TXshCell &targetCell, + int &bottomRowWithTheSameLevel) { + bottomRowWithTheSameLevel = -1; + TXshColumnP column = const_cast(xsh)->getColumn(col); + if (!column) return false; + + TXshCellColumn *cellColumn = column->getCellColumn(); + if (!cellColumn) return false; + + int r0, r1; + if (!cellColumn->getRange(r0, r1)) return false; + + for (int r = r0; r <= r1; r++) { + TXshCell cell = cellColumn->getCell(r); + if (cell == targetCell) { + bottomRowWithTheSameLevel = r; + return true; + } + if (cell.m_level == targetCell.m_level) bottomRowWithTheSameLevel = r; + } + + return false; +} + +//----------------------------------------------------------------------------- + +QChar numToLetter(int letterNum) { + switch (letterNum) { + case 0: + return QChar(); + break; + case 1: + return 'A'; + break; + case 2: + return 'B'; + break; + case 3: + return 'C'; + break; + case 4: + return 'D'; + break; + case 5: + return 'E'; + break; + case 6: + return 'F'; + break; + case 7: + return 'G'; + break; + case 8: + return 'H'; + break; + case 9: + return 'I'; + break; + default: + return QChar(); + break; + } +} + +//----------------------------------------------------------------------------- + +QString convertToFrameWithLetter(int value, int length = -1) { + QString str; + str.setNum((int)(value / 10)); + while (str.length() < length) str.push_front("0"); + QChar letter = numToLetter(value % 10); + if (!letter.isNull()) str.append(letter); + return str; +} + +//----------------------------------------------------------------------------- + +QString fidsToString(const std::vector &fids, + bool letterOptionEnabled) { + if (fids.empty()) return StopMotion::tr("No", "frame id"); + QString retStr(""); + if (letterOptionEnabled) { + bool beginBlock = true; + for (int f = 0; f < fids.size() - 1; f++) { + int num = fids[f].getNumber(); + int next_num = fids[f + 1].getNumber(); + + if (num % 10 == 0 && num + 10 == next_num) { + if (beginBlock) { + retStr += convertToFrameWithLetter(num) + " - "; + beginBlock = false; + } + } else { + retStr += convertToFrameWithLetter(num) + ", "; + beginBlock = true; + } + } + retStr += convertToFrameWithLetter(fids.back().getNumber()); + } else { + bool beginBlock = true; + for (int f = 0; f < fids.size() - 1; f++) { + int num = fids[f].getNumber(); + int next_num = fids[f + 1].getNumber(); + if (num + 1 == next_num) { + if (beginBlock) { + retStr += QString::number(num) + " - "; + beginBlock = false; + } + } else { + retStr += QString::number(num) + ", "; + beginBlock = true; + } + } + retStr += QString::number(fids.back().getNumber()); + } + return retStr; +} + +//----------------------------------------------------------------------------- + +bool getRasterLevelSize(TXshLevel *level, TDimension &dim) { + std::vector fids; + level->getFids(fids); + if (fids.empty()) return false; + TXshSimpleLevel *simpleLevel = level->getSimpleLevel(); + if (!simpleLevel) return false; + TRasterImageP rimg = (TRasterImageP)simpleLevel->getFrame(fids[0], false); + if (!rimg || rimg->isEmpty()) return false; + + dim = rimg->getRaster()->getSize(); + return true; +} + +}; // namespace + +//============================================================================= +//============================================================================= + +JpgConverter::JpgConverter() {} +JpgConverter::~JpgConverter() {} + +void JpgConverter::setStream(EdsStreamRef stream) { m_stream = stream; } + +void JpgConverter::convertFromJpg() { + unsigned __int64 mySize = 0; + unsigned char *data = NULL; + EdsError err = EdsGetPointer(m_stream, (EdsVoid **)&data); + err = EdsGetLength(m_stream, &mySize); + + int width, height, pixelFormat; + int inSubsamp, inColorspace; + tjhandle tjInstance = NULL; + unsigned char *imgBuf = NULL; + tjInstance = tjInitDecompress(); + tjDecompressHeader3(tjInstance, data, mySize, &width, &height, &inSubsamp, + &inColorspace); + + if (width < 0 || height < 0) { + emit(imageReady(false)); + return; + } + + pixelFormat = TJPF_BGRX; + imgBuf = (unsigned char *)tjAlloc(width * height * tjPixelSize[pixelFormat]); + int flags = 0; +#ifdef WIN32 + flags |= TJFLAG_BOTTOMUP; +#endif + int factorsNum; + tjscalingfactor scalingFactor = {1, 1}; + tjscalingfactor *factor = tjGetScalingFactors(&factorsNum); + int i = 0; + int tempWidth, tempHeight; + while (i < factorsNum) { + scalingFactor = factor[i]; + i++; + tempWidth = TJSCALED(width, scalingFactor); + tempHeight = TJSCALED(height, scalingFactor); + } + tjDecompress2(tjInstance, data, mySize, imgBuf, width, + width * tjPixelSize[pixelFormat], height, pixelFormat, flags); + + m_finalImage = TRaster32P(width, height); + m_finalImage->lock(); + uchar *rawData = m_finalImage->getRawData(); + memcpy(rawData, imgBuf, width * height * tjPixelSize[pixelFormat]); + m_finalImage->unlock(); + + tjFree(imgBuf); + imgBuf = NULL; + tjDestroy(tjInstance); + tjInstance = NULL; + + if (m_stream != NULL) { + EdsRelease(m_stream); + m_stream = NULL; + } + data = NULL; + emit(imageReady(true)); +} + +void JpgConverter::run() { convertFromJpg(); } + +//----------------------------------------------------------------------------- + +StopMotion::StopMotion() { + m_opacity = StopMotionOpacity; + m_useScaledImages = StopMotionUseScaledImages; + buildAvMap(); + buildIsoMap(); + buildTvMap(); + buildModeMap(); + buildExposureMap(); + buildWhiteBalanceMap(); + buildColorTemperatures(); + buildImageQualityMap(); + buildPictureStyleMap(); + m_useDirectShow = StopMotionUseDirectShow; + m_useMjpg = StopMotionUseMjpg; + m_alwaysLiveView = StopMotionAlwaysLiveView; + m_blackCapture = StopMotionBlackCapture; + m_placeOnXSheet = StopMotionPlaceOnXSheet; + m_reviewTime = StopMotionReviewTime; + m_useNumpadShortcuts = StopMotionUseNumpad; + m_numpadForStyleSwitching = + Preferences::instance()->isUseNumpadForSwitchingStylesEnabled(); + setUseNumpadShortcuts(m_useNumpadShortcuts); + m_turnOnRewind = Preferences::instance()->rewindAfterPlaybackEnabled(); + m_timer = new QTimer(this); + m_reviewTimer = new QTimer(this); + m_reviewTimer->setSingleShot(true); + + m_fullScreen1 = new QDialog(); + m_fullScreen1->setModal(false); + m_fullScreen1->setStyleSheet("background-color:black;"); + m_screenCount = QApplication::desktop()->screenCount(); + if (m_screenCount > 1) { + m_fullScreen2 = new QDialog(); + m_fullScreen2->setModal(false); + m_fullScreen2->setStyleSheet("background-color:black;"); + if (m_screenCount == 3) { + m_fullScreen3 = new QDialog(); + m_fullScreen3->setModal(false); + m_fullScreen3->setStyleSheet("background-color:black;"); + } + } + + TXsheetHandle *xsheetHandle = TApp::instance()->getCurrentXsheet(); + TSceneHandle *sceneHandle = TApp::instance()->getCurrentScene(); + TFrameHandle *frameHandle = TApp::instance()->getCurrentFrame(); + bool ret = true; + + ret = ret && + connect(xsheetHandle, SIGNAL(xsheetSwitched()), this, SLOT(update())); + ret = ret && connect(m_reviewTimer, SIGNAL(timeout()), this, + SLOT(onReviewTimeout())); + ret = ret && connect(m_timer, SIGNAL(timeout()), this, SLOT(onTimeout())); + ret = + ret && connect(this, SIGNAL(newImageReady()), this, SLOT(importImage())); + ret = ret && connect(sceneHandle, SIGNAL(sceneSwitched()), this, + SLOT(onSceneSwitched())); + ret = ret && connect(frameHandle, SIGNAL(isPlayingStatusChanged()), this, + SLOT(onPlaybackChanged())); + assert(ret); + + ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); + + setToNextNewLevel(); + m_filePath = scene->getDefaultLevelPath(OVL_TYPE, m_levelName.toStdWString()) + .getParentDir() + .getQString(); + + // set handler for a camera detected + initializeCanonSDK(); + if (!m_error) + m_error = EdsSetCameraAddedHandler(StopMotion::handleCameraAddedEvent, + (EdsVoid *)this); +} + +//----------------------------------------------------------------- + +StopMotion::~StopMotion() { + if (m_liveViewStatus != LiveViewClosed) endLiveView(); + if (m_sessionOpen) closeCameraSession(); + if (m_camera) releaseCamera(); + if (m_cameraList != NULL) releaseCameraList(); + if (m_isSDKLoaded) closeCanonSDK(); + setUseNumpadShortcuts(false); +} + +//----------------------------------------------------------------------------- + +void StopMotion::onSceneSwitched() { + TApp *app = TApp::instance(); + ToonzScene *scene = app->getCurrentScene()->getScene(); + TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + setToNextNewLevel(); + m_filePath = scene->getDefaultLevelPath(OVL_TYPE, m_levelName.toStdWString()) + .getParentDir() + .getQString(); + m_frameNumber = 1; + m_xSheetFrameNumber = 0; + + TLevelSet *levelSet = scene->getLevelSet(); + std::vector levels; + levelSet->listLevels(levels); + int size = levels.size(); + for (int i = 0; i < size; i++) { + TXshLevel *level = levels[i]; + if (level->getType() == OVL_XSHLEVEL) { + TXshSimpleLevel *sl = 0; + sl = level->getSimpleLevel(); + bool isStopMotionLevel = sl->getProperties()->isStopMotionLevel(); + if (isStopMotionLevel) { + m_filePath = sl->getPath().getParentDir().getQString(); + m_levelName = QString::fromStdWString(sl->getName()); + m_frameNumber = sl->getFrameCount() + 1; + setXSheetFrameNumber(xsh->getFrameCount() + 1); + break; + } + } + } + emit(levelNameChanged(m_levelName)); + emit(filePathChanged(m_filePath)); + emit(frameNumberChanged(m_frameNumber)); + emit(xSheetFrameNumberChanged(m_xSheetFrameNumber)); + refreshFrameInfo(); +} + +//----------------------------------------------------------------- + +void StopMotion::onPlaybackChanged() { + if (TApp::instance()->getCurrentFrame()->isPlaying() || m_liveViewStatus == 0) + return; + + int r0, r1, step; + ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); + scene->getProperties()->getPreviewProperties()->getRange(r0, r1, step); + if (r1 > -1) return; + + int frame = TApp::instance()->getCurrentFrame()->getFrame(); + int lastFrame = TApp::instance()->getCurrentFrame()->getMaxFrameIndex(); + if (frame == 0 || frame == lastFrame) { + TApp::instance()->getCurrentFrame()->setFrame(m_xSheetFrameNumber - 1); + } +} + +//----------------------------------------------------------------- + +void StopMotion::setOpacity(int opacity) { + m_opacity = opacity; + StopMotionOpacity = m_opacity; + emit(opacityChanged(m_opacity)); +} + +//----------------------------------------------------------------- + +void StopMotion::lowerOpacity() { + int opacity = round((double)m_opacity / 255.0 * 10.0); + opacity *= 10; + opacity -= 10; + m_opacity = double(opacity) / 100.0 * 255.0; + m_opacity = max(0, m_opacity); + StopMotionOpacity = m_opacity; + emit(opacityChanged(m_opacity)); +} + +//----------------------------------------------------------------- + +void StopMotion::raiseOpacity() { + int opacity = round((double)m_opacity / 255.0 * 10.0); + opacity *= 10; + opacity += 10; + m_opacity = double(opacity) / 100.0 * 255.0; + m_opacity = min(255, m_opacity); + StopMotionOpacity = m_opacity; + emit(opacityChanged(m_opacity)); +} + +//----------------------------------------------------------------- + +void StopMotion::setUseScaledImages(bool on) { + m_useScaledImages = on; + StopMotionUseScaledImages = int(on); + emit(scaleFullSizeImagesSignal(on)); +} + +//----------------------------------------------------------------- + +void StopMotion::setAlwaysLiveView(bool on) { + m_alwaysLiveView = on; + StopMotionAlwaysLiveView = int(on); + emit(liveViewOnAllFramesSignal(on)); +} + +//----------------------------------------------------------------- + +void StopMotion::setBlackCapture(bool on) { + m_blackCapture = on; + StopMotionBlackCapture = int(on); + emit(blackCaptureSignal(on)); +} + +//----------------------------------------------------------------- + +void StopMotion::setPlaceOnXSheet(bool on) { + m_placeOnXSheet = on; + StopMotionPlaceOnXSheet = int(on); + emit(placeOnXSheetSignal(on)); +} + +//----------------------------------------------------------------- + +void StopMotion::setReviewTime(int time) { + m_reviewTime = time; + StopMotionReviewTime = time; + emit(reviewTimeChangedSignal(time)); +} + +//----------------------------------------------------------------- + +void StopMotion::setUseMjpg(bool on) { + m_useMjpg = on; + StopMotionUseMjpg = int(on); + emit(useMjpgSignal(on)); +} + +//----------------------------------------------------------------- + +void StopMotion::jumpToCameraFrame() { + TApp::instance()->getCurrentFrame()->setFrame(m_xSheetFrameNumber - 1); +} + +//----------------------------------------------------------------- + +void StopMotion::setUseNumpadShortcuts(bool on) { + m_useNumpadShortcuts = on; + StopMotionUseNumpad = int(on); + emit(useNumpadSignal(on)); +} + +void StopMotion::toggleNumpadShortcuts(bool on) { + // can't just return if this feature is off + // it could have been toggled while the camera was active + if (!m_useNumpadShortcuts) on = false; + CommandManager *comm = CommandManager::instance(); + + if (on) { + // if turning it on, get all old shortcuts + if (m_numpadForStyleSwitching) { + Preferences::instance()->setValue(useNumpadForSwitchingStyles, false); + } + std::string shortcut; + QAction *action; + for (int i = 0; i <= 9; i++) { + shortcut = QString::number(i).toStdString(); + action = comm->getActionFromShortcut(shortcut); + if (action) { + m_oldActionMap.insert( + std::pair(shortcut, action)); + action->setShortcut(QKeySequence("")); + action = NULL; + } + } + shortcut = "+"; + action = comm->getActionFromShortcut(shortcut); + if (action) { + m_oldActionMap.insert( + std::pair(shortcut, action)); + action = NULL; + } + shortcut = "-"; + action = comm->getActionFromShortcut(shortcut); + if (action) { + m_oldActionMap.insert( + std::pair(shortcut, action)); + action = NULL; + } + shortcut = "Return"; + action = comm->getActionFromShortcut(shortcut); + if (action) { + m_oldActionMap.insert( + std::pair(shortcut, action)); + action = NULL; + } + shortcut = "*"; + action = comm->getActionFromShortcut(shortcut); + if (action) { + m_oldActionMap.insert( + std::pair(shortcut, action)); + action = NULL; + } + + // now set all new shortcuts + action = comm->getAction(MI_PrevDrawing); + if (action) { + action->setShortcut(QKeySequence("1")); + action = NULL; + } + action = comm->getAction(MI_NextDrawing); + if (action) { + action->setShortcut(QKeySequence("2")); + action = NULL; + } + action = comm->getAction(MI_StopMotionJumpToCamera); + if (action) { + action->setShortcut(QKeySequence("3")); + action = NULL; + } + action = comm->getAction(MI_Loop); + if (action) { + action->setShortcut(QKeySequence("8")); + action = NULL; + } + action = comm->getAction(MI_Play); + if (action) { + action->setShortcut(QKeySequence("0")); + action = NULL; + } + action = comm->getAction(MI_StopMotionRaiseOpacity); + if (action) { + action->setShortcut(QKeySequence("+")); + action = NULL; + } + action = comm->getAction(MI_StopMotionLowerOpacity); + if (action) { + action->setShortcut(QKeySequence("-")); + action = NULL; + } + action = comm->getAction(MI_StopMotionCapture); + if (action) { + action->setShortcut(QKeySequence("Enter")); + action = NULL; + } + action = comm->getAction(MI_StopMotionToggleLiveView); + if (action) { + action->setShortcut(QKeySequence("5")); + action = NULL; + } + action = comm->getAction(MI_StopMotionToggleZoom); + if (action) { + action->setShortcut(QKeySequence("*")); + action = NULL; + } + + } else { + // unset the new shortcuts first + QAction *action; + action = comm->getAction(MI_PrevDrawing); + if (action) { + action->setShortcut( + QKeySequence(comm->getShortcutFromAction(action).c_str())); + action = NULL; + } + action = comm->getAction(MI_NextDrawing); + if (action) { + action->setShortcut( + QKeySequence(comm->getShortcutFromAction(action).c_str())); + action = NULL; + } + action = comm->getAction(MI_StopMotionJumpToCamera); + if (action) { + action->setShortcut( + QKeySequence(comm->getShortcutFromAction(action).c_str())); + action = NULL; + } + action = comm->getAction(MI_Loop); + if (action) { + action->setShortcut( + QKeySequence(comm->getShortcutFromAction(action).c_str())); + action = NULL; + } + action = comm->getAction(MI_Play); + if (action) { + action->setShortcut( + QKeySequence(comm->getShortcutFromAction(action).c_str())); + action = NULL; + } + action = comm->getAction(MI_StopMotionCapture); + if (action) { + action->setShortcut( + QKeySequence(comm->getShortcutFromAction(action).c_str())); + action = NULL; + } + action = comm->getAction(MI_StopMotionLowerOpacity); + if (action) { + action->setShortcut( + QKeySequence(comm->getShortcutFromAction(action).c_str())); + action = NULL; + } + action = comm->getAction(MI_StopMotionRaiseOpacity); + if (action) { + action->setShortcut( + QKeySequence(comm->getShortcutFromAction(action).c_str())); + action = NULL; + } + action = comm->getAction(MI_StopMotionToggleLiveView); + if (action) { + action->setShortcut( + QKeySequence(comm->getShortcutFromAction(action).c_str())); + action = NULL; + } + action = comm->getAction(MI_StopMotionToggleZoom); + if (action) { + action->setShortcut( + QKeySequence(comm->getShortcutFromAction(action).c_str())); + action = NULL; + } + + // now put back the old shortcuts + auto it = m_oldActionMap.begin(); + while (it != m_oldActionMap.end()) { + it->second->setShortcut(QKeySequence(it->first.c_str())); + it++; + } + if (m_numpadForStyleSwitching) { + std::string shortcut; + QAction *action; + for (int i = 0; i <= 9; i++) { + shortcut = QString::number(i).toStdString(); + action = comm->getActionFromShortcut(shortcut); + if (action) { + action->setShortcut(QKeySequence("")); + action = NULL; + } + } + Preferences::instance()->setValue(useNumpadForSwitchingStyles, true); + } + } +} + +//----------------------------------------------------------------- + +void StopMotion::setXSheetFrameNumber(int frameNumber) { + m_xSheetFrameNumber = frameNumber; + loadLineUpImage(); + emit(xSheetFrameNumberChanged(m_xSheetFrameNumber)); + TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); +} + +//----------------------------------------------------------------- + +bool StopMotion::loadLineUpImage() { + if (m_liveViewStatus < 1) return false; + m_hasLineUpImage = false; + // first see if the level exists in the current level set + ToonzScene *currentScene = TApp::instance()->getCurrentScene()->getScene(); + TLevelSet *levelSet = currentScene->getLevelSet(); + + std::wstring levelName = m_levelName.toStdWString(); + + // level with the same name + TXshLevel *level_sameName = levelSet->getLevel(levelName); + + TFilePath levelFp = TFilePath(m_filePath) + + TFilePath(levelName + L".." + m_fileType.toStdWString()); + + // level with the same path + TXshLevel *level_samePath = levelSet->getLevel(*(currentScene), levelFp); + + TFilePath actualLevelFp = currentScene->decodeFilePath(levelFp); + TXshSimpleLevelP sl; + if (level_sameName && level_samePath && level_sameName == level_samePath) { + sl = dynamic_cast(level_sameName); + bool isRasterLevel = sl && (sl->getType() == OVL_XSHLEVEL); + if (!isRasterLevel) { + return false; + } + } else + return false; + + // next we need to find the column the level is on + + TApp *app = TApp::instance(); + TXsheet *xsh = currentScene->getXsheet(); + int row; + if (m_xSheetFrameNumber == 1) { + row = 0; + } else { + row = m_xSheetFrameNumber - 2; + } + int col = app->getCurrentColumn()->getColumnIndex(); + + int foundCol = -1; + // most possibly, it's in the current column + int rowCheck; + findCell(xsh, col, TXshCell(level_sameName, TFrameId(1)), rowCheck); + if (rowCheck >= 0) { + foundCol = col; + } else { + // search entire xsheet + for (int c = 0; c < xsh->getColumnCount(); c++) { + if (c == col) continue; + findCell(xsh, c, TXshCell(level_sameName, TFrameId(1)), rowCheck); + if (rowCheck >= 0) { + foundCol = c; + } + } + } + if (rowCheck < 0) return false; + + // note found row represents the last row found that uses + // the active level + + TFrameId frameId = xsh->getCell(row, foundCol).getFrameId(); + + int frameNumber = frameId.getNumber(); + + if (m_usingWebcam) { + if (frameNumber > 0) { + m_lineUpImage = sl->getFrame(frameId, false)->raster(); + m_hasLineUpImage = true; + return true; + } else + return false; + } + + // now check to see if a file actually exists there + TFilePath liveViewFolder = currentScene->decodeFilePath( + TFilePath(m_filePath) + TFilePath(levelName + L"_LiveView")); + TFilePath liveViewFp = currentScene->decodeFilePath( + liveViewFolder + TFilePath(levelName + L"..jpg")); + TFilePath liveViewFile(liveViewFp.withFrame(frameNumber)); + if (TFileStatus(liveViewFile).doesExist()) { + if (loadJpg(liveViewFile, m_lineUpImage)) { + m_hasLineUpImage = true; + return true; + } + } + return false; +} + +//----------------------------------------------------------------- + +void StopMotion::setFrameNumber(int frameNumber) { + m_frameNumber = frameNumber; + emit(frameNumberChanged(m_frameNumber)); +} + +//----------------------------------------------------------------------------- + +void StopMotion::nextFrame() { + if (Preferences::instance()->isShowFrameNumberWithLettersEnabled()) { + int f = m_frameNumber; + if (f % 10 == 0) // next number + m_frameNumber = ((int)(f / 10) + 1) * 10; + else // next alphabet + m_frameNumber = f + 1; + } else + m_frameNumber = m_frameNumber + 1; + emit(frameNumberChanged(m_frameNumber)); + refreshFrameInfo(); +} + +//----------------------------------------------------------------------------- + +void StopMotion::lastFrame() {} + +//----------------------------------------------------------------------------- + +void StopMotion::previousFrame() { + int f = m_frameNumber; + if (f > 1) { + if (Preferences::instance()->isShowFrameNumberWithLettersEnabled()) { + if (f % 10 == 0) // next number + m_frameNumber = ((int)(f / 10) - 1) * 10; + else // next alphabet + m_frameNumber = f - 1; + } else + m_frameNumber = f - 1; + emit(frameNumberChanged(m_frameNumber)); + refreshFrameInfo(); + } +} + +//----------------------------------------------------------------- + +void StopMotion::setLevelName(QString levelName) { m_levelName = levelName; } + +//----------------------------------------------------------------- + +void StopMotion::nextName() { + std::unique_ptr nameCreator(new FlexibleNameCreator()); + if (!nameCreator->setCurrent(m_levelName.toStdWString())) { + setToNextNewLevel(); + return; + } + + std::wstring levelName = nameCreator->getNext(); + updateLevelNameAndFrame(levelName); +} + +//----------------------------------------------------------------- + +void StopMotion::previousName() { + std::unique_ptr nameCreator(new FlexibleNameCreator()); + + std::wstring levelName; + + // if the current level name is non-sequencial, then try to switch the last + // sequencial level in the scene. + if (!nameCreator->setCurrent(m_levelName.toStdWString())) { + TLevelSet *levelSet = + TApp::instance()->getCurrentScene()->getScene()->getLevelSet(); + nameCreator->setCurrent(L"ZZ"); + for (;;) { + levelName = nameCreator->getPrevious(); + if (levelSet->getLevel(levelName) != 0) break; + if (levelName == L"A") { + setToNextNewLevel(); + return; + } + } + } else + levelName = nameCreator->getPrevious(); + + updateLevelNameAndFrame(levelName); +} + +//----------------------------------------------------------------- + +void StopMotion::setFileType(QString fileType) { + m_fileType = fileType; + emit(fileTypeChanged(m_fileType)); +} + +//----------------------------------------------------------------- + +void StopMotion::setFilePath(QString filePath) { + m_filePath = filePath; + + ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); + TFilePath saveInPath(filePath.toStdWString()); + scene->getProperties()->setCameraCaptureSaveInPath(saveInPath); + refreshFrameInfo(); + + emit(filePathChanged(m_filePath)); +} + +//----------------------------------------------------------------- + +void StopMotion::setSubsamplingValue(int subsampling) { + m_subsampling = subsampling; +} + +//----------------------------------------------------------------- + +void StopMotion::getSubsampling() { + ToonzScene *currentScene = TApp::instance()->getCurrentScene()->getScene(); + TLevelSet *levelSet = currentScene->getLevelSet(); + + std::wstring levelName = m_levelName.toStdWString(); + + // level with the same name + TXshLevel *level_sameName = levelSet->getLevel(levelName); + + TFilePath levelFp = TFilePath(m_filePath) + + TFilePath(levelName + L".." + m_fileType.toStdWString()); + + // level with the same path + TXshLevel *level_samePath = levelSet->getLevel(*(currentScene), levelFp); + + TFilePath actualLevelFp = currentScene->decodeFilePath(levelFp); + + if (level_sameName && level_samePath && level_sameName == level_samePath) { + TXshSimpleLevelP m_sl; + m_sl = dynamic_cast(level_sameName); + bool isRasterLevel = m_sl && (m_sl->getType() == OVL_XSHLEVEL); + if (isRasterLevel) { + int currSubsampling = m_sl->getProperties()->getSubsampling(); + m_subsampling = currSubsampling; + emit(subsamplingChanged(m_subsampling)); + } else + emit(subsamplingChanged(-1)); + } else + emit(subsamplingChanged(-1)); +} + +//----------------------------------------------------------------------------- + +void StopMotion::update() { getSubsampling(); } + +//----------------------------------------------------------------------------- + +void StopMotion::setSubsampling() { + ToonzScene *currentScene = TApp::instance()->getCurrentScene()->getScene(); + TLevelSet *levelSet = currentScene->getLevelSet(); + + std::wstring levelName = m_levelName.toStdWString(); + + // level with the same name + TXshLevel *level_sameName = levelSet->getLevel(levelName); + + TFilePath levelFp = TFilePath(m_filePath) + + TFilePath(levelName + L".." + m_fileType.toStdWString()); + + // level with the same path + TXshLevel *level_samePath = levelSet->getLevel(*(currentScene), levelFp); + + TFilePath actualLevelFp = currentScene->decodeFilePath(levelFp); + + if (level_sameName && level_samePath && level_sameName == level_samePath) { + TXshSimpleLevelP m_sl; + m_sl = dynamic_cast(level_sameName); + bool isRasterLevel = m_sl && (m_sl->getType() & RASTER_TYPE); + if (isRasterLevel) { + int currSubsampling = m_sl->getProperties()->getSubsampling(); + int newSubsampling = m_subsampling; + if (currSubsampling != newSubsampling) { + m_sl->getProperties()->setSubsampling(newSubsampling); + m_sl->invalidateFrames(); + TApp::instance()->getCurrentScene()->setDirtyFlag(true); + TApp::instance() + ->getCurrentXsheet() + ->getXsheet() + ->getStageObjectTree() + ->invalidateAll(); + TApp::instance()->getCurrentLevel()->notifyLevelChange(); + emit(subsamplingChanged(m_subsampling)); + } + } + } +} + +//----------------------------------------------------------------------------- + +void StopMotion::onTimeout() { + int currentFrame = TApp::instance()->getCurrentFrame()->getFrame(); + // int destinationFrame = m_xSheetFrameNumber - 1; + if (m_liveViewStatus > 0 && m_liveViewStatus < 3 && + !TApp::instance()->getCurrentFrame()->isPlaying()) { + if (getAlwaysLiveView() || (currentFrame == m_xSheetFrameNumber - 1)) { + if (!m_usingWebcam) + downloadEVFData(); + else + getWebcamImage(); + if (getAlwaysLiveView() && currentFrame != m_xSheetFrameNumber - 1 || + m_pickLiveViewZoom) { + m_showLineUpImage = false; + } else { + m_showLineUpImage = true; + } + } else if (m_liveViewStatus == 2) { + m_liveViewStatus = 3; + TApp::instance()->getCurrentScene()->notifySceneChanged(); + } + } else if (m_liveViewStatus == 3 && !m_userCalledPause) { + if (getAlwaysLiveView() || (currentFrame == m_xSheetFrameNumber - 1)) { + if (!m_usingWebcam) + downloadEVFData(); + else + getWebcamImage(); + } + } +} + +//----------------------------------------------------------------------------- + +void StopMotion::onReviewTimeout() { + if (m_liveViewStatus > 0) { + m_liveViewStatus = 2; + m_timer->start(40); + } + TApp::instance()->getCurrentFrame()->setFrame(m_xSheetFrameNumber - 1); +} + +//----------------------------------------------------------------------------- + +bool StopMotion::importImage() { + if (getBlackCapture()) { + m_fullScreen1->hide(); + + if (m_screenCount > 1) { + m_fullScreen2->hide(); + + if (m_screenCount == 3) { + m_fullScreen3->hide(); + } + } + } + if (getReviewTime() > 0) { + m_reviewTimer->start(getReviewTime() * 1000); + } + + 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 false; + } + + if (m_usingWebcam) { + m_newImage = m_liveViewImage; + } + int frameNumber = m_frameNumber; + + /* create parent directory if it does not exist */ + TFilePath parentDir = scene->decodeFilePath(TFilePath(m_filePath)); + TFilePath fullResFolder = scene->decodeFilePath( + TFilePath(m_filePath) + TFilePath(levelName + L"_FullRes")); + TFilePath liveViewFolder = scene->decodeFilePath( + TFilePath(m_filePath) + TFilePath(levelName + L"_LiveView")); + + TFilePath levelFp = TFilePath(m_filePath) + + TFilePath(levelName + L".." + m_fileType.toStdWString()); + TFilePath actualLevelFp = scene->decodeFilePath(levelFp); + + TFilePath fullResFp = + scene->decodeFilePath(fullResFolder + TFilePath(levelName + L"..jpg")); + TFilePath fullResFile(fullResFp.withFrame(frameNumber)); + + TFilePath liveViewFp = + scene->decodeFilePath(liveViewFolder + TFilePath(levelName + L"..jpg")); + TFilePath liveViewFile(liveViewFp.withFrame(frameNumber)); + + TFilePath tempFile = parentDir + "temp.jpg"; + + TXshSimpleLevel *sl = 0; + TXshLevel *level = scene->getLevelSet()->getLevel(levelName); + enum State { NEWLEVEL = 0, ADDFRAME, OVERWRITE } state; + + /* if the level already exists in the scene cast */ + if (level) { + /* if the existing level is not a raster level, then return */ + if (level->getType() != OVL_XSHLEVEL) { + DVGui::error( + tr("The level name specified is already used: please choose a " + "different level name.")); + return false; + } + /* if the existing level does not match file path and pixel size, then + * return */ + sl = level->getSimpleLevel(); + if (scene->decodeFilePath(sl->getPath()) != actualLevelFp) { + DVGui::error( + tr("The save in path specified does not match with the existing " + "level.")); + return false; + } + if (sl->getProperties()->getImageRes() != + TDimension(m_newImage->getLx(), m_newImage->getLy())) { + DVGui::error(tr( + "The captured image size does not match with the existing level.")); + return false; + } + /* if the level already have the same frame, then ask if overwrite it */ + TFilePath frameFp(actualLevelFp.withFrame(frameNumber)); + if (TFileStatus(frameFp).doesExist()) { + QString question = + tr("File %1 already exists.\nDo you want to overwrite it?") + .arg(toQString(frameFp)); + int ret = DVGui::MsgBox(question, QObject::tr("Overwrite"), + QObject::tr("Cancel")); + if (ret == 0 || ret == 2) return false; + state = OVERWRITE; + } else + state = ADDFRAME; + } + /* if the level does not exist in the scene cast */ + else { + /* if the file does exist, load it first */ + if (TSystem::doesExistFileOrLevel(actualLevelFp)) { + level = scene->loadLevel(actualLevelFp); + if (!level) { + DVGui::error(tr("Failed to load %1.").arg(toQString(actualLevelFp))); + return false; + } + + /* if the loaded level does not match in pixel size, then return */ + sl = level->getSimpleLevel(); + if (!sl || + sl->getProperties()->getImageRes() != + TDimension(m_newImage->getLx(), m_newImage->getLy())) { + DVGui::error( + tr("The captured image size does not match with the existing " + "level.")); + return false; + } + + /* confirm overwrite */ + TFilePath frameFp(actualLevelFp.withFrame(frameNumber)); + if (TFileStatus(frameFp).doesExist()) { + QString question = + tr("File %1 already exists.\nDo you want to overwrite it?") + .arg(toQString(frameFp)); + int ret = DVGui::MsgBox(question, QObject::tr("Overwrite"), + QObject::tr("Cancel")); + if (ret == 0 || ret == 2) return false; + } + } + /* if the file does not exist, then create a new level */ + else { + TXshLevel *level = scene->createNewLevel(OVL_XSHLEVEL, levelName, + TDimension(), 0, levelFp); + sl = level->getSimpleLevel(); + sl->setPath(levelFp, true); + sl->getProperties()->setDpiPolicy(LevelProperties::DP_CustomDpi); + TPointD dpi; + // Right now always set the dpi to scale to the camera width + if (Preferences::instance()->getPixelsOnly() && false) + dpi = getCurrentCameraDpi(); + // Compute the dpi so that the image will fit + // to the camera frame + else { + TCamera *camera = + TApp::instance()->getCurrentScene()->getScene()->getCurrentCamera(); + TDimensionD size = camera->getSize(); + double minimumDpi = std::min(m_newImage->getLx() / size.lx, + m_newImage->getLy() / size.ly); + dpi = TPointD(minimumDpi, minimumDpi); + } + sl->getProperties()->setDpi(dpi.x); + sl->getProperties()->setImageDpi(dpi); + sl->getProperties()->setImageRes( + TDimension(m_newImage->getLx(), m_newImage->getLy())); + } + + state = NEWLEVEL; + getSubsampling(); + } + + 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 false; + try { + TSystem::mkDir(parentDir); + DvDirModel::instance()->refreshFolder(parentDir.getParentDir()); + } catch (...) { + DVGui::error(tr("Unable to create") + toQString(parentDir)); + return false; + } + } + if (!m_usingWebcam) { + if (!TFileStatus(fullResFolder).doesExist()) { + try { + TSystem::mkDir(fullResFolder); + DvDirModel::instance()->refreshFolder(fullResFolder.getParentDir()); + } catch (...) { + DVGui::error(tr("Unable to create") + toQString(fullResFolder)); + return false; + } + } + if (!TFileStatus(liveViewFolder).doesExist()) { + try { + TSystem::mkDir(liveViewFolder); + DvDirModel::instance()->refreshFolder(liveViewFolder.getParentDir()); + } catch (...) { + DVGui::error(tr("Unable to create") + toQString(liveViewFolder)); + return false; + } + } + } + + // move the temp file + if (!m_usingWebcam) { + if (m_useScaledImages) { + TSystem::copyFile(fullResFile, tempFile); + TSystem::deleteFile(tempFile); + } + if (m_hasLineUpImage) { + saveJpg(m_lineUpImage, liveViewFile); + } + } + + TFrameId fid(frameNumber); + TPointD levelDpi = sl->getDpi(); + /* create the raster */ + TRaster32P raster = m_newImage; + + TRasterImageP ri(raster); + ri->setDpi(levelDpi.x, levelDpi.y); + + /* setting the frame */ + sl->setFrame(fid, ri); + + /* set dirty flag */ + sl->getProperties()->setDirtyFlag(true); + sl->getProperties()->setIsStopMotion(true); + sl->setIsReadOnly(true); + + // if (m_saveOnCaptureCB->isChecked()) sl->save(); + // for now always save. This can be tweaked later + sl->save(); + + /* placement in xsheet */ + if (!getPlaceOnXSheet()) { + postImportProcess(); + return true; + } + int row = m_xSheetFrameNumber - 1; + int col = app->getCurrentColumn()->getColumnIndex(); + + // if the level is newly created or imported, then insert a new column + if (state == NEWLEVEL) { + if (!xsh->isColumnEmpty(col)) { + col += 1; + xsh->insertColumn(col); + } + xsh->insertCells(row, col); + xsh->setCell(row, col, TXshCell(sl, fid)); + app->getCurrentColumn()->setColumnIndex(col); + if (getReviewTime() == 0) app->getCurrentFrame()->setFrame(row + 1); + m_xSheetFrameNumber = row + 2; + emit(xSheetFrameNumberChanged(m_xSheetFrameNumber)); + postImportProcess(); + // if (m_newImage->getLx() > 2000) { + // m_subsampling = 4; + // setSubsampling(); + //} + return true; + } + + // state == OVERWRITE, ADDFRAME + + // if the same cell is already in the column, then just replace the content + // and do not set a new cell + int foundCol, foundRow = -1; + // most possibly, it's in the current column + int rowCheck; + if (findCell(xsh, col, TXshCell(sl, fid), rowCheck)) { + postImportProcess(); + return true; + } + if (rowCheck >= 0) { + foundRow = rowCheck; + foundCol = col; + } + // search entire xsheet + for (int c = 0; c < xsh->getColumnCount(); c++) { + if (c == col) continue; + if (findCell(xsh, c, TXshCell(sl, fid), rowCheck)) { + postImportProcess(); + return true; + } + if (rowCheck >= 0) { + foundRow = rowCheck; + foundCol = c; + } + } + + // note found row represents the last row found that uses + // the active level + + // if there is a column containing the same level + if (foundRow >= 0) { + // put the cell at the bottom + xsh->insertCells(row, foundCol); + xsh->setCell(row, foundCol, TXshCell(sl, fid)); + app->getCurrentColumn()->setColumnIndex(foundCol); + if (getReviewTime() == 0) app->getCurrentFrame()->setFrame(row + 1); + m_xSheetFrameNumber = row + 2; + emit(xSheetFrameNumberChanged(m_xSheetFrameNumber)); + } + // if the level is registered in the scene, but is not placed in the xsheet, + // then insert a new column + else { + if (!xsh->isColumnEmpty(col)) { + col += 1; + xsh->insertColumn(col); + } + xsh->setCell(row, col, TXshCell(sl, fid)); + app->getCurrentColumn()->setColumnIndex(col); + if (getReviewTime() == 0) app->getCurrentFrame()->setFrame(row + 1); + m_xSheetFrameNumber = row + 2; + emit(xSheetFrameNumberChanged(m_xSheetFrameNumber)); + } + postImportProcess(); + return true; +} + +//----------------------------------------------------------------- + +void StopMotion::captureImage() { + if (!m_usingWebcam && !m_sessionOpen) { + DVGui::warning("Please start live view before capturing an image."); + return; + } + if (m_usingWebcam) { + if (!m_hasLiveViewImage) { + DVGui::warning("Cannot capture webcam image unless live view is active."); + return; + } + if (getReviewTime() > 0) { + m_timer->stop(); + if (m_liveViewStatus > 0) { + m_liveViewStatus = 3; + } + } + m_lineUpImage = m_liveViewImage; + m_hasLineUpImage = true; + emit(newLiveViewImageReady()); + importImage(); + return; + } + if (getBlackCapture()) { + m_fullScreen1->showFullScreen(); + m_fullScreen1->setGeometry(QApplication::desktop()->screenGeometry(0)); + if (m_screenCount > 1) { + m_fullScreen2->showFullScreen(); + m_fullScreen2->setGeometry(QApplication::desktop()->screenGeometry(1)); + + if (m_screenCount == 3) { + m_fullScreen3->showFullScreen(); + m_fullScreen3->setGeometry(QApplication::desktop()->screenGeometry(2)); + } + } + // this allows the full screen qdialogs to go full screen before + // taking a photo + qApp->processEvents(QEventLoop::AllEvents, 1500); + } + + if (getReviewTime() > 0) { + m_timer->stop(); + } + + if (m_liveViewStatus > 0) { + m_liveViewStatus = 3; + } + + if (m_hasLiveViewImage) { + m_lineUpImage = m_liveViewImage; + m_hasLineUpImage = true; + emit(newLiveViewImageReady()); + } + + TApp *app = TApp::instance(); + ToonzScene *scene = app->getCurrentScene()->getScene(); + + int frameNumber = m_frameNumber; + std::wstring levelName = m_levelName.toStdWString(); + + TFilePath parentDir = scene->decodeFilePath(TFilePath(m_filePath)); + TFilePath tempFile = parentDir + "temp.jpg"; + + if (!TFileStatus(parentDir).doesExist()) { + TSystem::mkDir(parentDir); + } + m_tempFile = tempFile.getQString(); + takePicture(); +} + +//----------------------------------------------------------------------------- + +void StopMotion::saveJpg(TRaster32P image, TFilePath path) { + unsigned char *jpegBuf = NULL; /* Dynamically allocate the JPEG buffer */ + unsigned long jpegSize = 0; + int pixelFormat = TJPF_BGRX; + int outQual = 95; + int subSamp = TJSAMP_411; + bool success = false; + tjhandle tjInstance; + + int width = image->getLx(); + int height = image->getLy(); + int flags = 0; +#ifdef WIN32 + flags |= TJFLAG_BOTTOMUP; +#endif + + image->lock(); + uchar *rawData = image->getRawData(); + if ((tjInstance = tjInitCompress()) != NULL) { + if (tjCompress2(tjInstance, rawData, width, 0, height, pixelFormat, + &jpegBuf, &jpegSize, subSamp, outQual, flags) >= 0) { + success = true; + } + } + image->unlock(); + tjDestroy(tjInstance); + tjInstance = NULL; + + if (success) { + /* Write the JPEG image to disk. */ + QFile fullImage(path.getQString()); + fullImage.open(QIODevice::WriteOnly); + QDataStream dataStream(&fullImage); + dataStream.writeRawData((const char *)jpegBuf, jpegSize); + fullImage.close(); + } + tjFree(jpegBuf); + jpegBuf = NULL; +} + +//----------------------------------------------------------------------------- + +bool StopMotion::loadJpg(TFilePath path, TRaster32P &image) { + long size; + int inSubsamp, inColorspace, width, height; + unsigned long jpegSize; + unsigned char *jpegBuf; + FILE *jpegFile; + QString qPath = path.getQString(); + QByteArray ba = qPath.toLocal8Bit(); + const char *c_path = ba.data(); + bool success = true; + tjhandle tjInstance; + + /* Read the JPEG file into memory. */ + if ((jpegFile = fopen(c_path, "rb")) == NULL) success = false; + if (success && fseek(jpegFile, 0, SEEK_END) < 0 || + ((size = ftell(jpegFile)) < 0) || fseek(jpegFile, 0, SEEK_SET) < 0) + success = false; + if (success && size == 0) success = false; + jpegSize = (unsigned long)size; + if (success && (jpegBuf = (unsigned char *)tjAlloc(jpegSize)) == NULL) + success = false; + if (success && fread(jpegBuf, jpegSize, 1, jpegFile) < 1) success = false; + fclose(jpegFile); + jpegFile = NULL; + + if (success && (tjInstance = tjInitDecompress()) == NULL) success = false; + + if (success && + tjDecompressHeader3(tjInstance, jpegBuf, jpegSize, &width, &height, + &inSubsamp, &inColorspace) < 0) + success = false; + + int pixelFormat = TJPF_BGRX; + unsigned char *imgBuf = NULL; + if (success && + (imgBuf = tjAlloc(width * height * tjPixelSize[pixelFormat])) == NULL) + success = false; + + int flags = 0; +#ifdef WIN32 + flags |= TJFLAG_BOTTOMUP; +#endif + if (success && + tjDecompress2(tjInstance, jpegBuf, jpegSize, imgBuf, width, 0, height, + pixelFormat, flags) < 0) + success = false; + tjFree(jpegBuf); + jpegBuf = NULL; + tjDestroy(tjInstance); + tjInstance = NULL; + + image = TRaster32P(width, height); + image->lock(); + uchar *rawData = image->getRawData(); + memcpy(rawData, imgBuf, width * height * tjPixelSize[pixelFormat]); + image->unlock(); + + tjFree(imgBuf); + imgBuf = NULL; + + return success; +} + +//----------------------------------------------------------------------------- + +void StopMotion::postImportProcess() { + if (Preferences::instance()->isShowFrameNumberWithLettersEnabled()) { + int f = m_frameNumber; + if (f % 10 == 0) // next number + m_frameNumber = ((int)(f / 10) + 1) * 10; + else // next alphabet + m_frameNumber = f + 1; + } else + m_frameNumber += 1; + emit(frameNumberChanged(m_frameNumber)); + /* notify */ + refreshFrameInfo(); + TApp::instance()->getCurrentScene()->notifySceneChanged(); + TApp::instance()->getCurrentScene()->notifyCastChange(); + TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); +} + +//----------------------------------------------------------------------------- + +// Refresh information that how many & which frames are saved for the current +// level +void StopMotion::refreshFrameInfo() { + if ((!m_sessionOpen && m_liveViewStatus < 2) && !m_usingWebcam) { + m_frameInfoText = ""; + return; + } + + QString tooltipStr, labelStr; + enum InfoType { NEW = 0, ADD, OVERWRITE, WARNING } infoType(WARNING); + + static QColor infoColors[4] = {Qt::cyan, Qt::green, Qt::yellow, Qt::red}; + + ToonzScene *currentScene = TApp::instance()->getCurrentScene()->getScene(); + TLevelSet *levelSet = currentScene->getLevelSet(); + + std::wstring levelName = m_levelName.toStdWString(); + int frameNumber = m_frameNumber; + + TDimension stopMotionRes; + bool checkRes = true; + if (m_usingWebcam) + stopMotionRes = m_liveViewImageDimensions; + + else if (m_useScaledImages || !getCurrentImageQuality().contains("Large")) { + stopMotionRes = m_proxyImageDimensions; + if (m_proxyImageDimensions == TDimension(0, 0)) { + checkRes = false; + } + } else + stopMotionRes = m_fullImageDimensions; + + bool letterOptionEnabled = + Preferences::instance()->isShowFrameNumberWithLettersEnabled(); + + // level with the same name + TXshLevel *level_sameName = levelSet->getLevel(levelName); + + TFilePath levelFp = TFilePath(m_filePath) + + TFilePath(levelName + L".." + m_fileType.toStdWString()); + + // level with the same path + TXshLevel *level_samePath = levelSet->getLevel(*(currentScene), levelFp); + + TFilePath actualLevelFp = currentScene->decodeFilePath(levelFp); + + // level existence + bool levelExist = TSystem::doesExistFileOrLevel(actualLevelFp); + + // frame existence + TFilePath frameFp(actualLevelFp.withFrame(frameNumber)); + bool frameExist = false; + if (levelExist) frameExist = TFileStatus(frameFp).doesExist(); + + // reset acceptable camera size + m_allowedCameraSize = QSize(); + + // ### CASE 1 ### + // If there is no same level registered in the scene cast + if (!level_sameName && !level_samePath) { + // If there is a level in the file system + if (levelExist) { + TLevelReaderP lr; + TLevelP level_p; + try { + lr = TLevelReaderP(actualLevelFp); + } catch (...) { + // TODO: output something + m_frameInfoText = tr("UNDEFINED WARNING"); + return; + } + if (!lr) { + // TODO: output something + m_frameInfoText = tr("UNDEFINED WARNING"); + return; + } + try { + level_p = lr->loadInfo(); + } catch (...) { + // TODO: output something + m_frameInfoText = tr("UNDEFINED WARNING"); + return; + } + if (!level_p) { + // TODO: output something + m_frameInfoText = tr("UNDEFINED WARNING"); + return; + } + int frameCount = level_p->getFrameCount(); + TLevel::Iterator it = level_p->begin(); + std::vector fids; + for (int i = 0; it != level_p->end(); ++it, ++i) + fids.push_back(it->first); + + tooltipStr += + tr("The level is not registered in the scene, but exists in the file " + "system."); + + // check resolution + const TImageInfo *ii; + try { + ii = lr->getImageInfo(fids[0]); + } catch (...) { + // TODO: output something + m_frameInfoText = tr("UNDEFINED WARNING"); + return; + } + TDimension dim(ii->m_lx, ii->m_ly); + // if the saved images has not the same resolution as the current camera + // resolution + if (checkRes && m_hasLiveViewImage && stopMotionRes != dim) { + tooltipStr += tr("\nWARNING : Image size mismatch. The saved image " + "size is %1 x %2.") + .arg(dim.lx) + .arg(dim.ly); + labelStr += tr("WARNING "); + infoType = WARNING; + } + // if the resolutions are matched + { + if (frameCount == 1) + tooltipStr += tr("\nFrame %1 exists.") + .arg(fidsToString(fids, letterOptionEnabled)); + else + tooltipStr += tr("\nFrames %1 exist.") + .arg(fidsToString(fids, letterOptionEnabled)); + // if the frame exists, then it will be overwritten + if (frameExist) { + labelStr += tr("OVERWRITE 1 of"); + infoType = OVERWRITE; + } else { + labelStr += tr("ADD to"); + infoType = ADD; + } + if (frameCount == 1) + labelStr += tr(" %1 frame").arg(frameCount); + else + labelStr += tr(" %1 frames").arg(frameCount); + } + m_allowedCameraSize = QSize(dim.lx, dim.ly); + } + // If no level exists in the file system, then it will be a new level + else { + tooltipStr += tr("The level will be newly created."); + labelStr += tr("NEW"); + infoType = NEW; + } + } + // ### CASE 2 ### + // If there is already the level registered in the scene cast + else if (level_sameName && level_samePath && + level_sameName == level_samePath) { + tooltipStr += tr("The level is already registered in the scene."); + if (!levelExist) tooltipStr += tr("\nNOTE : The level is not saved."); + + std::vector fids; + level_sameName->getFids(fids); + + // check resolution + TDimension dim; + bool ret = getRasterLevelSize(level_sameName, dim); + if (!ret) { + tooltipStr += + tr("\nWARNING : Failed to get image size of the existing level %1.") + .arg(QString::fromStdWString(levelName)); + labelStr += tr("WARNING "); + infoType = WARNING; + } + // if the saved images has not the same resolution as the current camera + // resolution + else if (checkRes && m_hasLiveViewImage && stopMotionRes != dim) { + tooltipStr += tr("\nWARNING : Image size mismatch. The existing level " + "size is %1 x %2.") + .arg(dim.lx) + .arg(dim.ly); + labelStr += tr("WARNING "); + infoType = WARNING; + } + // if the resolutions are matched + { + int frameCount = fids.size(); + if (fids.size() == 1) + tooltipStr += tr("\nFrame %1 exists.") + .arg(fidsToString(fids, letterOptionEnabled)); + else + tooltipStr += tr("\nFrames %1 exist.") + .arg(fidsToString(fids, letterOptionEnabled)); + // Check if the target frame already exist in the level + bool hasFrame = false; + for (int f = 0; f < frameCount; f++) { + if (fids.at(f).getNumber() == frameNumber) { + hasFrame = true; + break; + } + } + // If there is already the frame then it will be overwritten + if (hasFrame) { + labelStr += tr("OVERWRITE 1 of"); + infoType = OVERWRITE; + } + // Or, the frame will be added to the level + else { + labelStr += tr("ADD to"); + infoType = ADD; + } + if (frameCount == 1) + labelStr += tr(" %1 frame").arg(frameCount); + else + labelStr += tr(" %1 frames").arg(frameCount); + } + m_allowedCameraSize = QSize(dim.lx, dim.ly); + } + // ### CASE 3 ### + // If there are some conflicts with the existing level. + else { + if (level_sameName) { + TFilePath anotherPath = level_sameName->getPath(); + tooltipStr += + tr("WARNING : Level name conflicts. There already is a level %1 in the scene with the path\ + \n %2.") + .arg(QString::fromStdWString(levelName)) + .arg(toQString(anotherPath)); + // check resolution + TDimension dim; + bool ret = getRasterLevelSize(level_sameName, dim); + if (ret && checkRes && m_hasLiveViewImage && stopMotionRes != dim) + tooltipStr += tr("\nWARNING : Image size mismatch. The size of level " + "with the same name is is %1 x %2.") + .arg(dim.lx) + .arg(dim.ly); + m_allowedCameraSize = QSize(dim.lx, dim.ly); + } + if (level_samePath) { + std::wstring anotherName = level_samePath->getName(); + if (!tooltipStr.isEmpty()) tooltipStr += QString("\n"); + tooltipStr += + tr("WARNING : Level path conflicts. There already is a level with the path %1\ + \n in the scene with the name %2.") + .arg(toQString(levelFp)) + .arg(QString::fromStdWString(anotherName)); + // check resolution + TDimension dim; + bool ret = getRasterLevelSize(level_samePath, dim); + if (ret && checkRes && m_hasLiveViewImage && stopMotionRes != dim) + tooltipStr += tr("\nWARNING : Image size mismatch. The size of level " + "with the same path is %1 x %2.") + .arg(dim.lx) + .arg(dim.ly); + m_allowedCameraSize = QSize(dim.lx, dim.ly); + } + labelStr += tr("WARNING"); + infoType = WARNING; + } + + QColor infoColor = infoColors[(int)infoType]; + m_infoColorName = infoColor.name(); + m_frameInfoText = labelStr; + m_frameInfoToolTip = tooltipStr; + emit(frameInfoTextChanged(m_frameInfoText)); +} + +//----------------------------------------------------------------------------- + +void StopMotion::updateLevelNameAndFrame(std::wstring levelName) { + if (levelName != m_levelName.toStdWString()) { + m_levelName = QString::fromStdWString(levelName); + loadLineUpImage(); + } + emit(levelNameChanged(m_levelName)); + // m_previousLevelButton->setDisabled(levelName == L"A"); + + // set the start frame 10 if the option in preferences + // "Show ABC Appendix to the Frame Number in Xsheet Cell" is active. + // (frame 10 is displayed as "1" with this option) + bool withLetter = + Preferences::instance()->isShowFrameNumberWithLettersEnabled(); + + TLevelSet *levelSet = + TApp::instance()->getCurrentScene()->getScene()->getLevelSet(); + TXshLevel *level_p = levelSet->getLevel(levelName); + int startFrame; + if (!level_p) { + startFrame = withLetter ? 10 : 1; + } else { + std::vector fids; + level_p->getFids(fids); + if (fids.empty()) { + startFrame = withLetter ? 10 : 1; + } else { + int lastNum = fids.back().getNumber(); + startFrame = withLetter ? ((int)(lastNum / 10) + 1) * 10 : lastNum + 1; + } + } + m_frameNumber = startFrame; + emit(frameNumberChanged(startFrame)); + refreshFrameInfo(); + getSubsampling(); +} + +//----------------------------------------------------------------------------- + +void StopMotion::setToNextNewLevel() { + const std::unique_ptr nameBuilder(NameBuilder::getBuilder(L"")); + + TLevelSet *levelSet = + TApp::instance()->getCurrentScene()->getScene()->getLevelSet(); + ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); + std::wstring levelName = L""; + + // Select a different unique level name in case it already exists (either in + // scene or on disk) + TFilePath fp; + TFilePath actualFp; + for (;;) { + levelName = nameBuilder->getNext(); + + if (levelSet->getLevel(levelName) != 0) continue; + + fp = TFilePath(m_filePath) + + TFilePath(levelName + L".." + m_fileType.toStdWString()); + actualFp = scene->decodeFilePath(fp); + + if (TSystem::doesExistFileOrLevel(actualFp)) { + continue; + } + + break; + } + + updateLevelNameAndFrame(levelName); +} + +//----------------------------------------------------------------- + +void StopMotion::refreshCameraList() { emit(updateCameraList()); } + +//----------------------------------------------------------------- + +void StopMotion::changeCameras(int index) { + QList cameras = QCameraInfo::availableCameras(); + + // if selected the non-connected state, then disconnect the current camera + if (index == 0) { + m_active = false; + m_webcamDeviceName = QString(); + m_webcamDescription = QString(); + m_webcamIndex = -1; + m_proxyDpi = TPointD(0.0, 0.0); + m_proxyImageDimensions = TDimension(0, 0); + + if (m_sessionOpen || m_usingWebcam) { + if (m_liveViewStatus > 0) { + endLiveView(); + } + closeCameraSession(); + m_usingWebcam = false; + } + + setTEnvCameraName(""); + + emit(newCameraSelected(index, false)); + toggleNumpadShortcuts(false); + return; + } + + // There is a "Select Camera" as the first index + index -= 1; + m_active = true; + + // Check if its a webcam or DSLR + // Webcams are listed first, so see if one of them is selected + if (index > cameras.size() - 1) { + m_usingWebcam = false; + } else { + m_usingWebcam = true; + m_webcamIndex = index; + } + + // in case the camera is not changed + if (m_usingWebcam) { + if (cameras.at(index).deviceName() == m_webcamDeviceName) { + return; + } + + if (m_sessionOpen) { + if (m_liveViewStatus > 0) { + endLiveView(); + closeCameraSession(); + } + } + + setWebcam(new QCamera(cameras.at(index))); + m_webcamDeviceName = cameras.at(index).deviceName(); + m_webcamDescription = cameras.at(index).description(); + +#ifdef MACOSX + // this line is needed only in macosx + m_stopMotion->getWebcam()->setViewfinder(m_dummyViewFinder); +#endif + + // loading new camera + getWebcam()->load(); + + m_webcamResolutions.clear(); + + m_webcamResolutions = getWebcam()->supportedViewfinderResolutions(); + int sizeCount = m_webcamResolutions.count(); + + int width; + int height; + for (int s = 0; s < m_webcamResolutions.size(); s++) { + width = m_webcamResolutions.at(s).width(); + height = m_webcamResolutions.at(s).height(); + } + + getWebcam()->unload(); + + setWebcamResolution( + QString(QString::number(width) + " x " + QString::number(height))); + setTEnvCameraName(m_webcamDescription.toStdString()); + emit(newCameraSelected(index + 1, true)); + emit(webcamResolutionsChanged()); + emit(newWebcamResolutionSelected(sizeCount - 1)); + + } else { + m_webcamDeviceName = QString(); + m_webcamDescription = QString(); + m_webcamIndex = -1; + openCameraSession(); + setTEnvCameraName(getCameraName()); + emit(newCameraSelected(index + 1, false)); + } + if (m_useNumpadShortcuts) toggleNumpadShortcuts(true); + m_liveViewDpi = TPointD(0.0, 0.0); + refreshFrameInfo(); +} + +//----------------------------------------------------------------- + +QList StopMotion::getWebcams() { + m_webcams.clear(); + m_webcams = QCameraInfo::availableCameras(); + return m_webcams; +} + +//----------------------------------------------------------------- + +void StopMotion::setWebcam(QCamera *camera) { m_webcam = camera; } + +//----------------------------------------------------------------- + +bool StopMotion::translateIndex(int index) { + // We are using Qt to get the camera info and supported resolutions, but + // we are using OpenCV to actually get the images. + // The camera index from OpenCV and from Qt don't always agree, + // So this checks the name against the correct index. + m_webcamIndex = index; + +#ifdef WIN32 + +// Thanks to: +// https://elcharolin.wordpress.com/2017/08/28/webcam-capture-with-the-media-foundation-sdk/ +// for the webcam enumeration here + +#define CLEAN_ATTRIBUTES() \ + if (attributes) { \ + attributes->Release(); \ + attributes = NULL; \ + } \ + for (DWORD i = 0; i < count; i++) { \ + if (&devices[i]) { \ + devices[i]->Release(); \ + devices[i] = NULL; \ + } \ + } \ + CoTaskMemFree(devices); \ + return hr; + + HRESULT hr = S_OK; + + // this is important!! + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + + UINT32 count = 0; + IMFAttributes *attributes = NULL; + IMFActivate **devices = NULL; + + if (FAILED(hr)) { + CLEAN_ATTRIBUTES() + } + // Create an attribute store to specify enumeration parameters. + hr = MFCreateAttributes(&attributes, 1); + + if (FAILED(hr)) { + CLEAN_ATTRIBUTES() + } + + // The attribute to be requested is devices that can capture video + hr = attributes->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, + MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID); + if (FAILED(hr)) { + CLEAN_ATTRIBUTES() + } + // Enummerate the video capture devices + hr = MFEnumDeviceSources(attributes, &devices, &count); + + if (FAILED(hr)) { + CLEAN_ATTRIBUTES() + } + // if there are any available devices + if (count > 0) { + WCHAR *nameString = NULL; + // Get the human-friendly name of the device + UINT32 cchName; + + for (int i = 0; i < count; i++) { + hr = devices[i]->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, + &nameString, &cchName); + std::string desc = m_webcamDescription.toStdString(); + if (nameString == m_webcamDescription.toStdWString()) { + m_webcamIndex = i; + break; + } + // devices[0]->ShutdownObject(); + } + + CoTaskMemFree(nameString); + } + // clean + CLEAN_ATTRIBUTES() +#else + return true; +#endif +} + +//----------------------------------------------------------------- + +bool StopMotion::initWebcam(int index) { + if (!m_useDirectShow) { + // the webcam order obtained from Qt isn't always the same order as + // the one obtained from OpenCV without DirectShow + translateIndex(index); + m_cvWebcam.open(m_webcamIndex); + } else { + m_webcamIndex = index; + m_cvWebcam.open(m_webcamIndex, cv::CAP_DSHOW); + } + if (m_cvWebcam.isOpened() == false) { + return false; + } + + return true; +} + +//----------------------------------------------------------------- + +void StopMotion::releaseWebcam() { + m_cvWebcam.release(); + m_liveViewStatus = 0; + emit(liveViewStopped()); +} + +//----------------------------------------------------------------- + +void StopMotion::setWebcamResolution(QString resolution) { + m_cvWebcam.release(); + + // resolution is written in the itemText with the format " x + // " (e.g. "800 x 600") + QStringList texts = resolution.split(' '); + // the splited text must be "" "x" and "" + if (texts.size() != 3) return; + int tempStatus = m_liveViewStatus; + m_liveViewStatus = 0; + bool startTimer = false; + if (m_timer->isActive()) { + m_timer->stop(); + startTimer = true; + } + qApp->processEvents(QEventLoop::AllEvents, 1000); + + m_webcamWidth = texts[0].toInt(); + m_webcamHeight = texts[2].toInt(); + + m_liveViewDpi = TPointD(0.0, 0.0); + m_liveViewStatus = tempStatus; + if (startTimer) m_timer->start(40); + + // update env + setTEnvCameraResolution(resolution.toStdString()); + + refreshFrameInfo(); + + int index = m_webcamResolutions.indexOf(QSize(m_webcamWidth, m_webcamHeight)); + emit(newWebcamResolutionSelected(index)); +} + +//----------------------------------------------------------------- + +void StopMotion::getWebcamImage() { + bool error = false; + cv::Mat imgOriginal; + cv::Mat imgCorrected; + + if (m_cvWebcam.isOpened() == false) { + initWebcam(m_webcamIndex); + // mjpg is used by many webcams + // opencv runs very slow on some webcams without it. + if (m_useMjpg) { + m_cvWebcam.set(cv::CAP_PROP_FOURCC, + cv::VideoWriter::fourcc('m', 'j', 'p', 'g')); + m_cvWebcam.set(cv::CAP_PROP_FOURCC, + cv::VideoWriter::fourcc('M', 'J', 'P', 'G')); + } + m_cvWebcam.set(3, m_webcamWidth); + m_cvWebcam.set(4, m_webcamHeight); + if (!m_cvWebcam.isOpened()) { + m_hasLiveViewImage = false; + error = true; + } + } + + bool blnFrameReadSuccessfully = + m_cvWebcam.read(imgOriginal); // get next frame + + if (!blnFrameReadSuccessfully || + imgOriginal.empty()) { // if frame not read successfully + std::cout << "error: frame not read from webcam\n"; + error = true; // print error message to std out + } + + if (!error) { + cv::cvtColor(imgOriginal, imgCorrected, cv::COLOR_BGR2BGRA); + cv::flip(imgCorrected, imgCorrected, 0); + int width = m_cvWebcam.get(3); + int height = m_cvWebcam.get(4); + int size = imgCorrected.total() * imgCorrected.elemSize(); + + m_liveViewImage = TRaster32P(width, height); + m_liveViewImage->lock(); + uchar *imgBuf = imgCorrected.data; + uchar *rawData = m_liveViewImage->getRawData(); + memcpy(rawData, imgBuf, size); + m_liveViewImage->unlock(); + m_hasLiveViewImage = true; + m_liveViewStatus = 2; + if (m_hasLiveViewImage && + (m_liveViewDpi.x == 0.0 || m_liveViewImageDimensions.lx == 0)) { + TCamera *camera = + TApp::instance()->getCurrentScene()->getScene()->getCurrentCamera(); + TDimensionD size = camera->getSize(); + m_liveViewImageDimensions = + TDimension(m_liveViewImage->getLx(), m_liveViewImage->getLy()); + double minimumDpi = std::min(m_liveViewImageDimensions.lx / size.lx, + m_liveViewImageDimensions.ly / size.ly); + m_liveViewDpi = TPointD(minimumDpi, minimumDpi); + + m_fullImageDimensions = m_liveViewImageDimensions; + + m_fullImageDpi = m_liveViewDpi; + + emit(newDimensions()); + } + + emit(newLiveViewImageReady()); + } else + m_hasLiveViewImage = false; +} + +//----------------------------------------------------------------- + +void StopMotion::setUseDirectShow(int state) { + m_useDirectShow = state; + StopMotionUseDirectShow = state; + emit(useDirectShowSignal(state)); +} + +//----------------------------------------------------------------- + +bool StopMotion::toggleLiveView() { + if ((m_sessionOpen || m_usingWebcam) && m_liveViewStatus == 0) { + m_liveViewDpi = TPointD(0.0, 0.0); + m_liveViewImageDimensions = TDimension(0, 0); + if (!m_usingWebcam) { + startLiveView(); + } else + m_liveViewStatus = 1; + loadLineUpImage(); + m_timer->start(40); + emit(liveViewChanged(true)); + Preferences::instance()->setValue(rewindAfterPlayback, false); + TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); + return true; + } else if ((m_sessionOpen || m_usingWebcam) && m_liveViewStatus > 0) { + if (!m_usingWebcam) + endLiveView(); + else + releaseWebcam(); + m_timer->stop(); + emit(liveViewChanged(false)); + if (m_turnOnRewind) { + Preferences::instance()->setValue(rewindAfterPlayback, true); + } + TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); + return false; + } else { + DVGui::warning(tr("No camera selected.")); + return false; + } +} + +//----------------------------------------------------------------- + +void StopMotion::pauseLiveView() { + if (m_liveViewStatus == 2) { + m_liveViewStatus = 3; + m_userCalledPause = true; + emit(liveViewStopped()); + } else if (m_liveViewStatus == 3) { + m_liveViewStatus = 2; + m_userCalledPause = false; + } +} + +//----------------------------------------------------------------- + +EdsError StopMotion::initializeCanonSDK() { + m_error = EdsInitializeSDK(); + if (m_error == EDS_ERR_OK) { + m_isSDKLoaded = true; + } + return m_error; +} + +//----------------------------------------------------------------- + +EdsCameraListRef StopMotion::getCameraList() { + if (!m_isSDKLoaded) initializeCanonSDK(); + if (m_isSDKLoaded) { + m_error = EdsGetCameraList(&m_cameraList); + } + return m_cameraList; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::releaseCameraList() { + if (m_cameraList != NULL) m_error = EdsRelease(m_cameraList); + return m_error; +} + +//----------------------------------------------------------------- + +int StopMotion::getCameraCount() { + if (m_cameraList == NULL) { + getCameraList(); + } + if (m_cameraList != NULL) { + m_error = EdsGetChildCount(m_cameraList, &m_count); + if (m_count == 0) { + m_error = EDS_ERR_DEVICE_NOT_FOUND; + m_sessionOpen = false; + m_liveViewStatus = 0; + } + return m_count; + } else + return -1; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::getCamera(int index) { + if (m_count == 0) { + m_error = EDS_ERR_DEVICE_NOT_FOUND; + } + if (m_count > 0) { + m_error = EdsGetChildAtIndex(m_cameraList, index, &m_camera); + } + return m_error; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::releaseCamera() { + if (m_camera != NULL) { + m_error = EdsRelease(m_camera); + } + return m_error; +} + +//----------------------------------------------------------------- + +void StopMotion::cameraAdded() { + if (!m_active) refreshCameraList(); +} + +//----------------------------------------------------------------- + +void StopMotion::closeCanonSDK() { + if (m_isSDKLoaded) { + EdsTerminateSDK(); + } +} + +//----------------------------------------------------------------- + +EdsError StopMotion::openCameraSession() { + if (m_camera != NULL) { + m_error = EdsOpenSession(m_camera); + if (m_error == EDS_ERR_OK) m_sessionOpen = true; + } + m_error = + EdsSetObjectEventHandler(m_camera, kEdsObjectEvent_All, + StopMotion::handleObjectEvent, (EdsVoid *)this); + + m_error = EdsSetPropertyEventHandler(m_camera, kEdsPropertyEvent_All, + StopMotion::handlePropertyEvent, + (EdsVoid *)this); + + m_error = EdsSetCameraStateEventHandler(m_camera, kEdsStateEvent_All, + StopMotion::handleStateEvent, + (EdsVoid *)this); + + // We can't handle raw images yet, so make sure we are getting jpgs + if (getCurrentImageQuality().contains("RAW")) + setImageQuality("Large Fine Jpeg"); + + EdsUInt32 saveto = kEdsSaveTo_Host; + m_error = EdsSetPropertyData(m_camera, kEdsPropID_SaveTo, 0, + sizeof(EdsUInt32), &saveto); + EdsCapacity newCapacity = {0x7FFFFFFF, 0x1000, 1}; + m_error = EdsSetCapacity(m_camera, newCapacity); + return m_error; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::closeCameraSession() { + if (m_camera != NULL) { + m_error = EdsCloseSession(m_camera); + m_sessionOpen = false; + } + return m_error; +} + +//----------------------------------------------------------------- + +void StopMotion::refreshOptions() { + getAvailableShutterSpeeds(); + getAvailableIso(); + getAvailableApertures(); + getAvailableExposureCompensations(); + getAvailableWhiteBalances(); + buildColorTemperatures(); + getAvailableImageQualities(); + getAvailablePictureStyles(); +} + +//----------------------------------------------------------------- + +std::string StopMotion::getCameraName() { + EdsChar name[EDS_MAX_NAME]; + EdsError err = EDS_ERR_OK; + EdsDataType dataType; + EdsUInt32 dataSize; + m_error = EdsGetPropertySize(m_camera, kEdsPropID_ProductName, 0, &dataType, + &dataSize); + + if (m_error == EDS_ERR_OK) { + m_error = + EdsGetPropertyData(m_camera, kEdsPropID_ProductName, 0, dataSize, name); + } + m_cameraName = name; + return m_cameraName; +} + +//----------------------------------------------------------------- + +QString StopMotion::getMode() { + EdsError err = EDS_ERR_OK; + EdsDataType modeType; + EdsUInt32 size; + EdsUInt32 data; + + err = EdsGetPropertySize(m_camera, kEdsPropID_AEMode, 0, &modeType, &size); + err = EdsGetPropertyData(m_camera, kEdsPropID_AEMode, 0, sizeof(size), &data); + + return QString::fromStdString(m_modeMap[data]); +} + +//----------------------------------------------------------------- + +EdsError StopMotion::getAvailableIso() { + EdsPropertyDesc *IsoDesc = new EdsPropertyDesc; + EdsError err = EDS_ERR_OK; + m_isoOptions.clear(); + + err = EdsGetPropertyDesc(m_camera, kEdsPropID_ISOSpeed, IsoDesc); + int count = IsoDesc->numElements; + if (count > 0) { + int i = 0; + while (i < count) { + m_isoOptions.push_back( + QString::fromStdString(m_isoMap[IsoDesc->propDesc[i]])); + i++; + } + } + delete IsoDesc; + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::getAvailableShutterSpeeds() { + EdsPropertyDesc *TvDesc = new EdsPropertyDesc; + EdsError err = EDS_ERR_OK; + m_shutterSpeedOptions.clear(); + + err = EdsGetPropertyDesc(m_camera, kEdsPropID_Tv, TvDesc); + int count = TvDesc->numElements; + if (count > 0) { + int i = 0; + while (i < count) { + m_shutterSpeedOptions.push_back( + QString::fromStdString(m_tvMap[TvDesc->propDesc[i]])); + i++; + } + } + delete TvDesc; + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::getAvailableApertures() { + EdsPropertyDesc *AvDesc = new EdsPropertyDesc; + EdsError err = EDS_ERR_OK; + m_apertureOptions.clear(); + + err = EdsGetPropertyDesc(m_camera, kEdsPropID_Av, AvDesc); + int count = AvDesc->numElements; + if (count > 0) { + int i = 0; + while (i < count) { + m_apertureOptions.push_back( + QString::fromStdString(m_avMap[AvDesc->propDesc[i]])); + i++; + } + } + delete AvDesc; + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::getAvailableExposureCompensations() { + EdsPropertyDesc *exposureDesc = new EdsPropertyDesc; + EdsError err = EDS_ERR_OK; + m_exposureOptions.clear(); + + err = EdsGetPropertyDesc(m_camera, kEdsPropID_ExposureCompensation, + exposureDesc); + int count = exposureDesc->numElements; + if (count > 0) { + int i = 0; + while (i < count) { + m_exposureOptions.push_back( + QString::fromStdString(m_exposureMap[exposureDesc->propDesc[i]])); + i++; + } + } + delete exposureDesc; + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::getAvailableWhiteBalances() { + EdsPropertyDesc *whiteBalanceDesc = new EdsPropertyDesc; + EdsError err = EDS_ERR_OK; + m_whiteBalanceOptions.clear(); + + err = EdsGetPropertyDesc(m_camera, kEdsPropID_WhiteBalance, whiteBalanceDesc); + int count = whiteBalanceDesc->numElements; + if (count > 0) { + int i = 0; + while (i < count) { + m_whiteBalanceOptions.push_back(QString::fromStdString( + m_whiteBalanceMap[whiteBalanceDesc->propDesc[i]])); + i++; + } + } + delete whiteBalanceDesc; + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::getAvailableImageQualities() { + EdsPropertyDesc *imageQualityDesc = new EdsPropertyDesc; + EdsError err = EDS_ERR_OK; + m_imageQualityOptions.clear(); + + err = EdsGetPropertyDesc(m_camera, kEdsPropID_ImageQuality, imageQualityDesc); + int count = imageQualityDesc->numElements; + if (count > 0) { + int i = 0; + while (i < count) { + QString quality = QString::fromStdString( + m_imageQualityMap[imageQualityDesc->propDesc[i]]); + if (!quality.contains("RAW")) { + m_imageQualityOptions.push_back(quality); + } + i++; + } + } + delete imageQualityDesc; + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::getAvailablePictureStyles() { + EdsPropertyDesc *pictureStyleDesc = new EdsPropertyDesc; + EdsError err = EDS_ERR_OK; + m_pictureStyleOptions.clear(); + + err = EdsGetPropertyDesc(m_camera, kEdsPropID_PictureStyle, pictureStyleDesc); + int count = pictureStyleDesc->numElements; + if (count > 0) { + int i = 0; + while (i < count) { + m_pictureStyleOptions.push_back(QString::fromStdString( + m_pictureStyleMap[pictureStyleDesc->propDesc[i]])); + i++; + } + } + delete pictureStyleDesc; + return err; +} + +//----------------------------------------------------------------- + +void StopMotion::buildColorTemperatures() { + m_colorTempOptions.clear(); + int i = 2800; + while (i <= 10000) { + m_colorTempOptions.push_back(QString::number(i)); + i += 100; + } +} + +//----------------------------------------------------------------- + +QString StopMotion::getCurrentShutterSpeed() { + EdsError err = EDS_ERR_OK; + EdsDataType tvType; + EdsUInt32 size; + EdsUInt32 data; + + err = EdsGetPropertySize(m_camera, kEdsPropID_Tv, 0, &tvType, &size); + err = EdsGetPropertyData(m_camera, kEdsPropID_Tv, 0, sizeof(size), &data); + + return QString::fromStdString(m_tvMap[data]); +} + +//----------------------------------------------------------------- + +QString StopMotion::getCurrentIso() { + EdsError err = EDS_ERR_OK; + EdsDataType isoType; + EdsUInt32 size; + EdsUInt32 data; + + err = EdsGetPropertySize(m_camera, kEdsPropID_ISOSpeed, 0, &isoType, &size); + err = + EdsGetPropertyData(m_camera, kEdsPropID_ISOSpeed, 0, sizeof(size), &data); + + return QString::fromStdString(m_isoMap[data]); +} + +//----------------------------------------------------------------- + +QString StopMotion::getCurrentAperture() { + EdsError err = EDS_ERR_OK; + EdsDataType avType; + EdsUInt32 size; + EdsUInt32 data; + + err = EdsGetPropertySize(m_camera, kEdsPropID_Av, 0, &avType, &size); + err = EdsGetPropertyData(m_camera, kEdsPropID_Av, 0, sizeof(size), &data); + + return QString::fromStdString(m_avMap[data]); +} + +//----------------------------------------------------------------- + +QString StopMotion::getCurrentExposureCompensation() { + EdsError err = EDS_ERR_OK; + EdsDataType exposureType; + EdsUInt32 size; + EdsUInt32 data; + + err = EdsGetPropertySize(m_camera, kEdsPropID_ExposureCompensation, 0, + &exposureType, &size); + err = EdsGetPropertyData(m_camera, kEdsPropID_ExposureCompensation, 0, + sizeof(size), &data); + + return QString::fromStdString(m_exposureMap[data]); +} + +//----------------------------------------------------------------- + +QString StopMotion::getCurrentWhiteBalance() { + EdsError err = EDS_ERR_OK; + EdsDataType whiteBalanceType; + EdsUInt32 size; + EdsUInt32 data; + + err = EdsGetPropertySize(m_camera, kEdsPropID_WhiteBalance, 0, + &whiteBalanceType, &size); + err = EdsGetPropertyData(m_camera, kEdsPropID_WhiteBalance, 0, sizeof(size), + &data); + std::string wbString = m_whiteBalanceMap[data]; + return QString::fromStdString(m_whiteBalanceMap[data]); +} + +//----------------------------------------------------------------- + +QString StopMotion::getCurrentImageQuality() { + EdsError err = EDS_ERR_OK; + EdsDataType imageQualityType; + EdsUInt32 size; + EdsUInt32 data; + + err = EdsGetPropertySize(m_camera, kEdsPropID_ImageQuality, 0, + &imageQualityType, &size); + err = EdsGetPropertyData(m_camera, kEdsPropID_ImageQuality, 0, sizeof(size), + &data); + std::string wbString = m_imageQualityMap[data]; + return QString::fromStdString(m_imageQualityMap[data]); +} + +//----------------------------------------------------------------- + +QString StopMotion::getCurrentPictureStyle() { + EdsError err = EDS_ERR_OK; + EdsDataType pictureStyleType; + EdsUInt32 size; + EdsUInt32 data; + + err = EdsGetPropertySize(m_camera, kEdsPropID_PictureStyle, 0, + &pictureStyleType, &size); + err = EdsGetPropertyData(m_camera, kEdsPropID_PictureStyle, 0, sizeof(size), + &data); + std::string wbString = m_pictureStyleMap[data]; + return QString::fromStdString(m_pictureStyleMap[data]); +} + +//----------------------------------------------------------------- + +QString StopMotion::getCurrentColorTemperature() { + EdsError err = EDS_ERR_OK; + EdsDataType colorTempType; + EdsUInt32 size; + EdsUInt32 data; + + err = EdsGetPropertySize(m_camera, kEdsPropID_ColorTemperature, 0, + &colorTempType, &size); + err = EdsGetPropertyData(m_camera, kEdsPropID_ColorTemperature, 0, + sizeof(size), &data); + + return QString::number(data); +} + +//----------------------------------------------------------------- + +EdsError StopMotion::setShutterSpeed(QString shutterSpeed) { + EdsError err = EDS_ERR_OK; + EdsUInt32 value; + auto it = m_tvMap.begin(); + while (it != m_tvMap.end()) { + if (it->second == shutterSpeed.toStdString()) { + value = it->first; + break; + } + it++; + } + + err = EdsSetPropertyData(m_camera, kEdsPropID_Tv, 0, sizeof(value), &value); + emit(shutterSpeedChangedSignal(shutterSpeed)); + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::setIso(QString iso) { + EdsError err = EDS_ERR_OK; + EdsUInt32 value; + auto it = m_isoMap.begin(); + while (it != m_isoMap.end()) { + if (it->second == iso.toStdString()) { + value = it->first; + break; + } + it++; + } + + err = EdsSetPropertyData(m_camera, kEdsPropID_ISOSpeed, 0, sizeof(value), + &value); + emit(isoChangedSignal(iso)); + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::setAperture(QString aperture) { + EdsError err = EDS_ERR_OK; + EdsUInt32 value; + auto it = m_avMap.begin(); + while (it != m_avMap.end()) { + if (it->second == aperture.toStdString()) { + value = it->first; + break; + } + it++; + } + + err = EdsSetPropertyData(m_camera, kEdsPropID_Av, 0, sizeof(value), &value); + emit(apertureChangedSignal(aperture)); + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::setExposureCompensation(QString exposure) { + EdsError err = EDS_ERR_OK; + EdsUInt32 value; + auto it = m_exposureMap.begin(); + while (it != m_exposureMap.end()) { + if (it->second == exposure.toStdString()) { + value = it->first; + break; + } + it++; + } + + err = EdsSetPropertyData(m_camera, kEdsPropID_ExposureCompensation, 0, + sizeof(value), &value); + emit(exposureChangedSignal(exposure)); + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::setWhiteBalance(QString whiteBalance) { + EdsError err = EDS_ERR_OK; + EdsUInt32 value; + auto it = m_whiteBalanceMap.begin(); + while (it != m_whiteBalanceMap.end()) { + if (it->second == whiteBalance.toStdString()) { + value = it->first; + break; + } + it++; + } + + err = EdsSetPropertyData(m_camera, kEdsPropID_WhiteBalance, 0, sizeof(value), + &value); + emit(whiteBalanceChangedSignal(whiteBalance)); + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::setImageQuality(QString quality) { + EdsError err = EDS_ERR_OK; + EdsUInt32 value; + auto it = m_imageQualityMap.begin(); + while (it != m_imageQualityMap.end()) { + if (it->second == quality.toStdString()) { + value = it->first; + break; + } + it++; + } + + err = EdsSetPropertyData(m_camera, kEdsPropID_ImageQuality, 0, sizeof(value), + &value); + emit(imageQualityChangedSignal(quality)); + m_proxyImageDimensions = TDimension(0, 0); + m_proxyDpi = TPointD(0.0, 0.0); + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::setPictureStyle(QString style) { + EdsError err = EDS_ERR_OK; + EdsUInt32 value; + auto it = m_pictureStyleMap.begin(); + while (it != m_pictureStyleMap.end()) { + if (it->second == style.toStdString()) { + value = it->first; + break; + } + it++; + } + + err = EdsSetPropertyData(m_camera, kEdsPropID_PictureStyle, 0, sizeof(value), + &value); + err = EdsSetPropertyData(m_camera, kEdsPropID_PictureStyle, 0, sizeof(value), + &value); + emit(pictureStyleChangedSignal(style)); + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::setColorTemperature(QString temp) { + EdsError err = EDS_ERR_OK; + EdsUInt32 value; + value = temp.toInt(); + + err = EdsSetPropertyData(m_camera, kEdsPropID_ColorTemperature, 0, + sizeof(value), &value); + err = EdsSetPropertyData(m_camera, kEdsPropID_Evf_ColorTemperature, 0, + sizeof(value), &value); + emit(colorTemperatureChangedSignal(temp)); + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::downloadImage(EdsBaseRef object) { + EdsError err = EDS_ERR_OK; + EdsStreamRef stream = NULL; + EdsDirectoryItemInfo dirItemInfo; + + err = EdsGetDirectoryItemInfo(object, &dirItemInfo); + err = EdsCreateMemoryStream(0, &stream); + err = EdsDownload(object, dirItemInfo.size, stream); + EdsDownloadComplete(object); + + // tj code + + unsigned __int64 mySize = 0; + unsigned char *data = NULL; + err = EdsGetPointer(stream, (EdsVoid **)&data); + err = EdsGetLength(stream, &mySize); + + int width, height, pixelFormat; + // long size; + int inSubsamp, inColorspace; + // unsigned long jpegSize; + tjhandle tjInstance = NULL; + unsigned char *imgBuf = NULL; + tjInstance = tjInitDecompress(); + tjDecompressHeader3(tjInstance, data, mySize, &width, &height, &inSubsamp, + &inColorspace); + + pixelFormat = TJPF_BGRX; + imgBuf = (unsigned char *)tjAlloc(width * height * tjPixelSize[pixelFormat]); + int flags = 0; +#ifdef WIN32 + flags |= TJFLAG_BOTTOMUP; +#endif + int tempWidth, tempHeight; + + if (m_useScaledImages) { + int factorsNum; + tjscalingfactor scalingFactor = {1, 1}; + tjscalingfactor *factor = tjGetScalingFactors(&factorsNum); + int intRatio = (float)width / (float)height * 100.0; + int i = 0; + + TCamera *camera = + TApp::instance()->getCurrentScene()->getScene()->getCurrentCamera(); + TDimension res = camera->getRes(); + + // find the scaling factor that is at least as big as the current camera + while (i < factorsNum) { + scalingFactor = factor[i]; + tempWidth = TJSCALED(width, scalingFactor); + if (tempWidth < res.lx && i > 0) { + scalingFactor = factor[i - 1]; + break; + } + i++; + } + // make sure the scaling factor has the right aspect ratio + while (i >= 0) { + tempWidth = TJSCALED(width, scalingFactor); + tempHeight = TJSCALED(height, scalingFactor); + if ((int)((float)tempWidth / (float)tempHeight * 100.0) == intRatio) { + break; + } + i--; + scalingFactor = factor[i]; + } + } else { + tempWidth = width; + tempHeight = height; + } + + if (m_useScaledImages || !getCurrentImageQuality().contains("Large")) { + TCamera *camera = + TApp::instance()->getCurrentScene()->getScene()->getCurrentCamera(); + TDimensionD size = camera->getSize(); + m_proxyImageDimensions = TDimension(tempWidth, tempHeight); + double minimumDpi = std::min(m_proxyImageDimensions.lx / size.lx, + m_proxyImageDimensions.ly / size.ly); + m_proxyDpi = TPointD(minimumDpi, minimumDpi); + } + + tjDecompress2(tjInstance, data, mySize, imgBuf, tempWidth, + tempWidth * tjPixelSize[pixelFormat], tempHeight, pixelFormat, + flags); + + m_newImage = TRaster32P(tempWidth, tempHeight); + m_newImage->lock(); + uchar *rawData = m_newImage->getRawData(); + memcpy(rawData, imgBuf, tempWidth * tempHeight * tjPixelSize[pixelFormat]); + m_newImage->unlock(); + + tjFree(imgBuf); + imgBuf = NULL; + tjDestroy(tjInstance); + tjInstance = NULL; + + // end tj code + + if (m_useScaledImages) { + QFile fullImage(m_tempFile); + fullImage.open(QIODevice::WriteOnly); + QDataStream dataStream(&fullImage); + dataStream.writeRawData((const char *)data, mySize); + fullImage.close(); + } + + EdsRelease(stream); + stream = NULL; + if (object) EdsRelease(object); + + if (err == EDS_ERR_OK) { + emit(newImageReady()); + } + + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::takePicture() { + EdsError err; + err = EdsSendCommand(m_camera, kEdsCameraCommand_PressShutterButton, + kEdsCameraCommand_ShutterButton_Completely_NonAF); + err = EdsSendCommand(m_camera, kEdsCameraCommand_PressShutterButton, + kEdsCameraCommand_ShutterButton_OFF); + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::startLiveView() { + if (m_camera && m_sessionOpen) { + EdsError err = EDS_ERR_OK; + // Get the output device for the live view image + EdsUInt32 device; + err = EdsGetPropertyData(m_camera, kEdsPropID_Evf_OutputDevice, 0, + sizeof(device), &device); + // PC live view starts by setting the PC as the output device for the live + // view image. + if (err == EDS_ERR_OK) { + device |= kEdsEvfOutputDevice_PC; + err = EdsSetPropertyData(m_camera, kEdsPropID_Evf_OutputDevice, 0, + sizeof(device), &device); + } + if (err == EDS_ERR_OK) { + m_liveViewStatus = LiveViewStarting; + } + // A property change event notification is issued from the camera if + // property settings are made successfully. Start downloading of the live + // view image once the property change notification arrives. + return err; + } else + return EDS_ERR_DEVICE_NOT_FOUND; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::endLiveView() { + EdsError err = EDS_ERR_OK; + // Get the output device for the live view image + EdsUInt32 device; + err = EdsGetPropertyData(m_camera, kEdsPropID_Evf_OutputDevice, 0, + sizeof(device), &device); + // PC live view ends if the PC is disconnected from the live view image output + // device. + if (err == EDS_ERR_OK) { + device &= ~kEdsEvfOutputDevice_PC; + err = EdsSetPropertyData(m_camera, kEdsPropID_Evf_OutputDevice, 0, + sizeof(device), &device); + } + m_liveViewStatus = LiveViewClosed; + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::zoomLiveView() { + if (!m_sessionOpen) return EDS_ERR_DEVICE_INVALID; + EdsError err = EDS_ERR_OK; + + if (m_liveViewZoom == 1) { + m_liveViewZoom = 5; + m_zooming = true; + } else if (m_liveViewZoom == 5) { + m_liveViewZoom = 1; + m_zooming = false; + } + + err = EdsSetPropertyData(m_camera, kEdsPropID_Evf_Zoom, 0, + sizeof(m_liveViewZoom), &m_liveViewZoom); + if (m_liveViewZoom == 5) setZoomPoint(); + + return err; +} + +//----------------------------------------------------------------- + +void StopMotion::makeZoomPoint(TPointD pos) { + m_liveViewZoomPickPoint = pos; + double maxFullWidth = + (double)m_fullImageDimensions.lx / m_fullImageDpi.x * Stage::inch; + double maxFullHeight = + (double)m_fullImageDimensions.ly / m_fullImageDpi.y * Stage::inch; + double newX = m_liveViewZoomPickPoint.x + maxFullWidth / 2.0; + double newY = -m_liveViewZoomPickPoint.y + maxFullHeight / 2.0; + m_calculatedZoomPoint.x = newX / Stage::inch * m_fullImageDpi.x; + m_calculatedZoomPoint.y = newY / Stage::inch * m_fullImageDpi.x; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::setZoomPoint() { + EdsError err = EDS_ERR_OK; + + EdsPoint zoomPoint; + if (m_liveViewZoomPickPoint == TPointD(0.0, 0.0)) { + m_calculatedZoomPoint = + TPoint(m_fullImageDimensions.lx / 2, m_fullImageDimensions.ly / 2); + m_finalZoomPoint.x = m_calculatedZoomPoint.x - (m_zoomRect.x / 2); + m_finalZoomPoint.y = m_calculatedZoomPoint.y - (m_zoomRect.y / 2); + } else { + m_finalZoomPoint.x = m_calculatedZoomPoint.x - (m_zoomRect.x / 2); + m_finalZoomPoint.y = m_calculatedZoomPoint.y - (m_zoomRect.y / 2); + if (m_finalZoomPoint.x < 0) m_finalZoomPoint.x = 0; + if (m_finalZoomPoint.y < 0) m_finalZoomPoint.y = 0; + if (m_finalZoomPoint.x > m_fullImageDimensions.lx - (m_zoomRect.x)) { + m_finalZoomPoint.x = m_fullImageDimensions.lx - (m_zoomRect.x); + } + if (m_finalZoomPoint.y > m_fullImageDimensions.ly - (m_zoomRect.y)) { + m_finalZoomPoint.y = m_fullImageDimensions.ly - (m_zoomRect.y); + } + } + + zoomPoint.x = m_finalZoomPoint.x; + zoomPoint.y = m_finalZoomPoint.y; + + // make sure this is set AFTER starting zoom + err = EdsSetPropertyData(m_camera, kEdsPropID_Evf_ZoomPosition, 0, + sizeof(zoomPoint), &zoomPoint); + + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::downloadEVFData() { + EdsError err = EDS_ERR_OK; + EdsStreamRef stream = NULL; + EdsEvfImageRef evfImage = NULL; + + // Create memory stream. + err = EdsCreateMemoryStream(0, &stream); + // Create EvfImageRef. + if (err == EDS_ERR_OK) { + err = EdsCreateEvfImageRef(stream, &evfImage); + } + // Download live view image data. + if (err == EDS_ERR_OK) { + err = EdsDownloadEvfImage(m_camera, evfImage); + } + + EdsDataType evfZoom; + EdsDataType evfZoomPos; + EdsDataType evfZoomRect; + EdsUInt32 size; + EdsUInt32 sizePos; + EdsUInt32 sizeRect; + EdsUInt32 sizeImagePos; + EdsUInt32 sizeCoordSys; + EdsUInt32 zoomAmount; + EdsPoint zoomPos; + EdsRect zoomRect; + EdsPoint imagePos; + EdsSize coordSys; + + err = EdsGetPropertySize(evfImage, kEdsPropID_Evf_Zoom, 0, &evfZoom, &size); + err = EdsGetPropertyData(evfImage, kEdsPropID_Evf_Zoom, 0, sizeof(size), + &zoomAmount); + + // this is the top corner? of the zoomed image + err = EdsGetPropertySize(evfImage, kEdsPropID_Evf_ZoomPosition, 0, + &evfZoomPos, &sizePos); + err = EdsGetPropertyData(evfImage, kEdsPropID_Evf_ZoomPosition, 0, sizePos, + &zoomPos); + // this is the top corner of the zoomed image and the size of the zoomed image + err = EdsGetPropertySize(evfImage, kEdsPropID_Evf_ZoomRect, 0, &evfZoomRect, + &sizeRect); + err = EdsGetPropertyData(evfImage, kEdsPropID_Evf_ZoomRect, 0, sizeRect, + &zoomRect); + + err = EdsGetPropertySize(evfImage, kEdsPropID_Evf_ImagePosition, 0, + &evfZoomRect, &sizeImagePos); + err = EdsGetPropertyData(evfImage, kEdsPropID_Evf_ImagePosition, 0, + sizeImagePos, &imagePos); + // this returns the size of the full image + err = EdsGetPropertySize(evfImage, kEdsPropID_Evf_CoordinateSystem, 0, + &evfZoomRect, &sizeCoordSys); + err = EdsGetPropertyData(evfImage, kEdsPropID_Evf_CoordinateSystem, 0, + sizeCoordSys, &coordSys); + + m_zoomRect = TPoint(zoomRect.size.width, zoomRect.size.height); + if (zoomAmount == 5 && m_zoomRect == TPoint(0, 0)) { + setZoomPoint(); + } + + // Get the incidental data of the image. + if (err == EDS_ERR_OK) { + JpgConverter *converter = new JpgConverter; + converter->setStream(stream); + converter->setScale(m_useScaledImages); + + connect(converter, SIGNAL(imageReady(bool)), this, SLOT(onImageReady(bool)), + Qt::QueuedConnection); + connect(converter, SIGNAL(finished()), this, SLOT(onFinished()), + Qt::QueuedConnection); + + converter->start(); + + while (!l_quitLoop) + QCoreApplication::processEvents(QEventLoop::AllEvents | + QEventLoop::WaitForMoreEvents); + + l_quitLoop = false; + m_liveViewImage = converter->getImage(); + m_hasLiveViewImage = true; + delete converter; + if (!m_converterSucceeded) return EDS_ERR_UNEXPECTED_EXCEPTION; + + // make sure not to set to LiveViewOpen if it has been turned off + if (m_liveViewStatus > 0) { + m_liveViewStatus = LiveViewOpen; + } + emit(newLiveViewImageReady()); + + if (m_hasLiveViewImage && + (m_liveViewDpi.x == 0.0 || m_liveViewImageDimensions.lx == 0)) { + TCamera *camera = + TApp::instance()->getCurrentScene()->getScene()->getCurrentCamera(); + TDimensionD size = camera->getSize(); + m_liveViewImageDimensions = + TDimension(m_liveViewImage->getLx(), m_liveViewImage->getLy()); + double minimumDpi = std::min(m_liveViewImageDimensions.lx / size.lx, + m_liveViewImageDimensions.ly / size.ly); + m_liveViewDpi = TPointD(minimumDpi, minimumDpi); + + m_fullImageDimensions = TDimension(coordSys.width, coordSys.height); + minimumDpi = std::min(m_fullImageDimensions.lx / size.lx, + m_fullImageDimensions.ly / size.ly); + m_fullImageDpi = TPointD(minimumDpi, minimumDpi); + + emit(newDimensions()); + } + } + + if (stream != NULL) { + EdsRelease(stream); + } + stream = NULL; + if (evfImage != NULL) { + EdsRelease(evfImage); + evfImage = NULL; + } + + // calculate dpi data + + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::focusNear() { + EdsError err = EDS_ERR_OK; + err = EdsSendCommand(m_camera, kEdsCameraCommand_DriveLensEvf, + kEdsEvfDriveLens_Near1); + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::focusFar() { + EdsError err = EDS_ERR_OK; + err = EdsSendCommand(m_camera, kEdsCameraCommand_DriveLensEvf, + kEdsEvfDriveLens_Far1); + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::focusNear2() { + EdsError err = EDS_ERR_OK; + err = EdsSendCommand(m_camera, kEdsCameraCommand_DriveLensEvf, + kEdsEvfDriveLens_Near2); + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::focusFar2() { + EdsError err = EDS_ERR_OK; + err = EdsSendCommand(m_camera, kEdsCameraCommand_DriveLensEvf, + kEdsEvfDriveLens_Far2); + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::focusNear3() { + EdsError err = EDS_ERR_OK; + err = EdsSendCommand(m_camera, kEdsCameraCommand_DriveLensEvf, + kEdsEvfDriveLens_Near3); + return err; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::focusFar3() { + EdsError err = EDS_ERR_OK; + err = EdsSendCommand(m_camera, kEdsCameraCommand_DriveLensEvf, + kEdsEvfDriveLens_Far3); + return err; +} + +//----------------------------------------------------------------- + +void StopMotion::onImageReady(const bool &status) { + m_converterSucceeded = status; +} + +//----------------------------------------------------------------- + +void StopMotion::onFinished() { l_quitLoop = true; } + +//----------------------------------------------------------------- +//----------------------------------------------------------------- + +EdsError StopMotion::handleObjectEvent(EdsObjectEvent event, EdsBaseRef object, + EdsVoid *context) { + if (event == kEdsObjectEvent_DirItemRequestTransfer) { + instance()->downloadImage(object); + } + + return EDS_ERR_OK; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::handlePropertyEvent(EdsPropertyEvent event, + EdsPropertyID property, + EdsUInt32 param, EdsVoid *context) { + if (property == kEdsPropID_Evf_OutputDevice && + event == kEdsPropertyEvent_PropertyChanged) { + if (instance()->m_liveViewStatus == LiveViewStarting) + instance()->m_liveViewStatus = LiveViewOpen; + } + if (property == kEdsPropID_AEMode && + event == kEdsPropertyEvent_PropertyChanged) { + emit(instance()->modeChanged()); + } + + if (property == kEdsPropID_Av && + event == kEdsPropertyEvent_PropertyDescChanged) { + emit(instance()->apertureOptionsChanged()); + } + + if (property == kEdsPropID_Tv && + event == kEdsPropertyEvent_PropertyDescChanged) { + emit(instance()->shutterSpeedOptionsChanged()); + } + if (property == kEdsPropID_ISOSpeed && + event == kEdsPropertyEvent_PropertyDescChanged) { + emit(instance()->isoOptionsChanged()); + } + if (property == kEdsPropID_ExposureCompensation && + event == kEdsPropertyEvent_PropertyDescChanged) { + emit(instance()->exposureOptionsChanged()); + } + if (property == kEdsPropID_WhiteBalance && + event == kEdsPropertyEvent_PropertyDescChanged) { + emit(instance()->whiteBalanceOptionsChanged()); + } + if (property == kEdsPropID_PictureStyle && + event == kEdsPropertyEvent_PropertyDescChanged) { + emit(instance()->pictureStyleOptionsChanged()); + } + if (property == kEdsPropID_ImageQuality && + event == kEdsPropertyEvent_PropertyDescChanged) { + emit(instance()->imageQualityOptionsChanged()); + } + + return EDS_ERR_OK; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::handleStateEvent(EdsStateEvent event, EdsUInt32 parameter, + EdsVoid *context) { + if (event == kEdsStateEvent_Shutdown) { + if (instance()->m_sessionOpen) { + instance()->closeCameraSession(); + instance()->releaseCamera(); + instance()->m_liveViewStatus = LiveViewClosed; + emit(instance()->cameraChanged()); + } + } + return EDS_ERR_OK; +} + +//----------------------------------------------------------------- + +EdsError StopMotion::handleCameraAddedEvent(EdsVoid *context) { + instance()->cameraAdded(); + return EDS_ERR_OK; +} + +//----------------------------------------------------------------- + +void StopMotion::buildAvMap() { + m_avMap.insert(std::pair(0x00, "00")); + m_avMap.insert(std::pair(0x08, "1")); + m_avMap.insert(std::pair(0x0B, "1.1")); + m_avMap.insert(std::pair(0x0C, "1.2")); + m_avMap.insert(std::pair(0x0D, "1.2")); + m_avMap.insert(std::pair(0x10, "1.4")); + m_avMap.insert(std::pair(0x13, "1.6")); + m_avMap.insert(std::pair(0x14, "1.8")); + m_avMap.insert(std::pair(0x15, "1.8")); + m_avMap.insert(std::pair(0x18, "2")); + m_avMap.insert(std::pair(0x1B, "2.2")); + m_avMap.insert(std::pair(0x1C, "2.5")); + m_avMap.insert(std::pair(0x1D, "2.5")); + m_avMap.insert(std::pair(0x20, "2.8")); + m_avMap.insert(std::pair(0x23, "3.2")); + m_avMap.insert(std::pair(0x24, "3.5")); + m_avMap.insert(std::pair(0x25, "3.5")); + m_avMap.insert(std::pair(0x28, "4")); + m_avMap.insert(std::pair(0x2B, "4.5")); + m_avMap.insert(std::pair(0x2C, "4.5")); + m_avMap.insert(std::pair(0x2D, "5.0")); + m_avMap.insert(std::pair(0x30, "5.6")); + m_avMap.insert(std::pair(0x33, "6.3")); + m_avMap.insert(std::pair(0x34, "6.7")); + m_avMap.insert(std::pair(0x35, "7.1")); + m_avMap.insert(std::pair(0x38, "8")); + m_avMap.insert(std::pair(0x3B, "9")); + m_avMap.insert(std::pair(0x3C, "9.5")); + m_avMap.insert(std::pair(0x3D, "10")); + m_avMap.insert(std::pair(0x40, "11")); + m_avMap.insert(std::pair(0x43, "13")); + m_avMap.insert(std::pair(0x44, "13")); + m_avMap.insert(std::pair(0x45, "14")); + m_avMap.insert(std::pair(0x48, "16")); + m_avMap.insert(std::pair(0x4B, "18")); + m_avMap.insert(std::pair(0x4C, "19")); + m_avMap.insert(std::pair(0x4D, "20")); + m_avMap.insert(std::pair(0x50, "22")); + m_avMap.insert(std::pair(0x53, "25")); + m_avMap.insert(std::pair(0x54, "27")); + m_avMap.insert(std::pair(0x55, "29")); + m_avMap.insert(std::pair(0x58, "32")); + m_avMap.insert(std::pair(0x5B, "36")); + m_avMap.insert(std::pair(0x5C, "38")); + m_avMap.insert(std::pair(0x5D, "40")); + m_avMap.insert(std::pair(0x60, "45")); + m_avMap.insert(std::pair(0x63, "51")); + m_avMap.insert(std::pair(0x64, "54")); + m_avMap.insert(std::pair(0x65, "57")); + m_avMap.insert(std::pair(0x68, "64")); + m_avMap.insert(std::pair(0x6B, "72")); + m_avMap.insert(std::pair(0x6C, "76")); + m_avMap.insert(std::pair(0x6D, "80")); + m_avMap.insert(std::pair(0x70, "91")); + m_avMap.insert(std::pair(0xFF, "Auto")); + m_avMap.insert(std::pair(0xffffffff, "unknown")); +} + +//----------------------------------------------------------------- + +void StopMotion::buildIsoMap() { + m_isoMap.insert(std::pair(0x00, "Auto")); + m_isoMap.insert(std::pair(0x28, "6")); + m_isoMap.insert(std::pair(0x30, "12")); + m_isoMap.insert(std::pair(0x38, "25")); + m_isoMap.insert(std::pair(0x40, "50")); + m_isoMap.insert(std::pair(0x48, "100")); + m_isoMap.insert(std::pair(0x4b, "125")); + m_isoMap.insert(std::pair(0x4d, "160")); + m_isoMap.insert(std::pair(0x50, "200")); + m_isoMap.insert(std::pair(0x53, "250")); + m_isoMap.insert(std::pair(0x55, "320")); + m_isoMap.insert(std::pair(0x58, "400")); + m_isoMap.insert(std::pair(0x5b, "500")); + m_isoMap.insert(std::pair(0x5d, "640")); + m_isoMap.insert(std::pair(0x60, "800")); + m_isoMap.insert(std::pair(0x63, "1000")); + m_isoMap.insert(std::pair(0x65, "1250")); + m_isoMap.insert(std::pair(0x68, "1600")); + m_isoMap.insert(std::pair(0x6b, "2000")); + m_isoMap.insert(std::pair(0x6d, "2500")); + m_isoMap.insert(std::pair(0x70, "3200")); + m_isoMap.insert(std::pair(0x73, "4000")); + m_isoMap.insert(std::pair(0x75, "5000")); + m_isoMap.insert(std::pair(0x78, "6400")); + m_isoMap.insert(std::pair(0x7b, "8000")); + m_isoMap.insert(std::pair(0x7d, "10000")); + m_isoMap.insert(std::pair(0x80, "12800")); + m_isoMap.insert(std::pair(0x83, "16000")); + m_isoMap.insert(std::pair(0x85, "20000")); + m_isoMap.insert(std::pair(0x88, "25600")); + m_isoMap.insert(std::pair(0x8b, "32000")); + m_isoMap.insert(std::pair(0x8d, "40000")); + m_isoMap.insert(std::pair(0x90, "51200")); + m_isoMap.insert(std::pair(0x98, "102400")); + m_isoMap.insert(std::pair(0xa0, "204800")); + m_isoMap.insert(std::pair(0xa8, "409600")); + m_isoMap.insert(std::pair(0xffffffff, "unknown")); +} + +//----------------------------------------------------------------- + +void StopMotion::buildTvMap() { + m_tvMap.insert(std::pair(0x04, "Auto")); + m_tvMap.insert(std::pair(0x0c, "Bulb")); + m_tvMap.insert(std::pair(0x10, "30\"")); + m_tvMap.insert(std::pair(0x13, "25\"")); + m_tvMap.insert(std::pair(0x14, "20\"")); + m_tvMap.insert(std::pair(0x15, "20\"")); + m_tvMap.insert(std::pair(0x18, "15\"")); + m_tvMap.insert(std::pair(0x1B, "13\"")); + m_tvMap.insert(std::pair(0x1C, "10\"")); + m_tvMap.insert(std::pair(0x1D, "10\"")); + m_tvMap.insert(std::pair(0x20, "8\"")); + m_tvMap.insert(std::pair(0x23, "6\"")); + m_tvMap.insert(std::pair(0x24, "6\"")); + m_tvMap.insert(std::pair(0x25, "5\"")); + m_tvMap.insert(std::pair(0x28, "4\"")); + m_tvMap.insert(std::pair(0x2B, "3\"2")); + m_tvMap.insert(std::pair(0x2C, "3\"")); + m_tvMap.insert(std::pair(0x2D, "2\"5")); + m_tvMap.insert(std::pair(0x30, "2\"")); + m_tvMap.insert(std::pair(0x33, "1\"6")); + m_tvMap.insert(std::pair(0x34, "1\"5")); + m_tvMap.insert(std::pair(0x35, "1\"3")); + m_tvMap.insert(std::pair(0x38, "1\"")); + m_tvMap.insert(std::pair(0x3B, "0\"8")); + m_tvMap.insert(std::pair(0x3C, "0\"7")); + m_tvMap.insert(std::pair(0x3D, "0\"6")); + m_tvMap.insert(std::pair(0x40, "0\"5")); + m_tvMap.insert(std::pair(0x43, "0\"4")); + m_tvMap.insert(std::pair(0x44, "0\"3")); + m_tvMap.insert(std::pair(0x45, "0\"3")); + m_tvMap.insert(std::pair(0x48, "1/4")); + m_tvMap.insert(std::pair(0x4B, "1/5")); + m_tvMap.insert(std::pair(0x4C, "1/6")); + m_tvMap.insert(std::pair(0x4D, "1/6")); + m_tvMap.insert(std::pair(0x50, "1/8")); + m_tvMap.insert(std::pair(0x53, "1/10")); + m_tvMap.insert(std::pair(0x54, "1/10")); + m_tvMap.insert(std::pair(0x55, "1/13")); + m_tvMap.insert(std::pair(0x58, "1/15")); + m_tvMap.insert(std::pair(0x5B, "1/20")); + m_tvMap.insert(std::pair(0x5C, "1/20")); + m_tvMap.insert(std::pair(0x5D, "1/25")); + m_tvMap.insert(std::pair(0x60, "1/30")); + m_tvMap.insert(std::pair(0x63, "1/40")); + m_tvMap.insert(std::pair(0x64, "1/45")); + m_tvMap.insert(std::pair(0x65, "1/50")); + m_tvMap.insert(std::pair(0x68, "1/60")); + m_tvMap.insert(std::pair(0x6B, "1/80")); + m_tvMap.insert(std::pair(0x6C, "1/90")); + m_tvMap.insert(std::pair(0x6D, "1/100")); + m_tvMap.insert(std::pair(0x70, "1/125")); + m_tvMap.insert(std::pair(0x73, "1/160")); + m_tvMap.insert(std::pair(0x74, "1/180")); + m_tvMap.insert(std::pair(0x75, "1/200")); + m_tvMap.insert(std::pair(0x78, "1/250")); + m_tvMap.insert(std::pair(0x7B, "1/320")); + m_tvMap.insert(std::pair(0x7C, "1/350")); + m_tvMap.insert(std::pair(0x7D, "1/400")); + m_tvMap.insert(std::pair(0x80, "1/500")); + m_tvMap.insert(std::pair(0x83, "1/640")); + m_tvMap.insert(std::pair(0x84, "1/750")); + m_tvMap.insert(std::pair(0x85, "1/800")); + m_tvMap.insert(std::pair(0x88, "1/1000")); + m_tvMap.insert(std::pair(0x8B, "1/1250")); + m_tvMap.insert(std::pair(0x8C, "1/1500")); + m_tvMap.insert(std::pair(0x8D, "1/1600")); + m_tvMap.insert(std::pair(0x90, "1/2000")); + m_tvMap.insert(std::pair(0x93, "1/2500")); + m_tvMap.insert(std::pair(0x94, "1/3000")); + m_tvMap.insert(std::pair(0x95, "1/3200")); + m_tvMap.insert(std::pair(0x98, "1/4000")); + m_tvMap.insert(std::pair(0x9B, "1/5000")); + m_tvMap.insert(std::pair(0x9C, "1/6000")); + m_tvMap.insert(std::pair(0x9D, "1/6400")); + m_tvMap.insert(std::pair(0xA0, "1/8000")); + m_tvMap.insert(std::pair(0xffffffff, "unknown")); +} + +//----------------------------------------------------------------- + +void StopMotion::buildModeMap() { + m_modeMap.insert(std::pair(0, "P")); + m_modeMap.insert(std::pair(1, "Tv")); + m_modeMap.insert(std::pair(2, "Av")); + m_modeMap.insert(std::pair(3, "M")); + m_modeMap.insert(std::pair(55, "FV")); + m_modeMap.insert(std::pair(4, "Bulb")); + m_modeMap.insert(std::pair(5, "A-DEP")); + m_modeMap.insert(std::pair(6, "DEP")); + m_modeMap.insert(std::pair(7, "C1")); + m_modeMap.insert(std::pair(16, "C2")); + m_modeMap.insert(std::pair(17, "C3")); + m_modeMap.insert(std::pair(8, "Lock")); + m_modeMap.insert(std::pair(9, "GreenMode")); + m_modeMap.insert(std::pair(10, "Night Portrait")); + m_modeMap.insert(std::pair(11, "Sports")); + m_modeMap.insert(std::pair(13, "LandScape")); + m_modeMap.insert(std::pair(14, "Close-Up")); + m_modeMap.insert(std::pair(15, "No Strobo")); + m_modeMap.insert(std::pair(12, "Portrait")); + m_modeMap.insert(std::pair(19, "Creative Auto")); + m_modeMap.insert(std::pair(20, "Movies")); + m_modeMap.insert(std::pair(25, "SCN")); + m_modeMap.insert( + std::pair(22, "Scene Intelligent Auto")); + m_modeMap.insert(std::pair(29, "Creative filters")); + m_modeMap.insert(std::pair(0xffffffff, "unknown")); +} + +//----------------------------------------------------------------- + +void StopMotion::buildExposureMap() { + m_exposureMap.insert(std::pair(0x28, "+5")); + m_exposureMap.insert(std::pair(0x25, "+4 2/3")); + m_exposureMap.insert(std::pair(0x24, "+4 1/2")); + m_exposureMap.insert(std::pair(0x23, "+4 1/3")); + m_exposureMap.insert(std::pair(0x20, "+4")); + m_exposureMap.insert(std::pair(0x1D, "+3 2/3")); + m_exposureMap.insert(std::pair(0x1C, "+3 1/2")); + m_exposureMap.insert(std::pair(0x1B, "+3 1/3")); + + m_exposureMap.insert(std::pair(0x18, "+3")); + m_exposureMap.insert(std::pair(0x15, "+2 2/3")); + m_exposureMap.insert(std::pair(0x14, "+2 1/2")); + m_exposureMap.insert(std::pair(0x13, "+2 1/3")); + m_exposureMap.insert(std::pair(0x10, "+2")); + m_exposureMap.insert(std::pair(0x0d, "+1 2/3")); + m_exposureMap.insert(std::pair(0x0c, "+1 1/2")); + m_exposureMap.insert(std::pair(0x0b, "+1 1/3")); + m_exposureMap.insert(std::pair(0x08, "+1")); + m_exposureMap.insert(std::pair(0x05, "+2/3")); + m_exposureMap.insert(std::pair(0x04, "+1/2")); + m_exposureMap.insert(std::pair(0x03, "+1/3")); + m_exposureMap.insert(std::pair(0x00, "0")); + m_exposureMap.insert(std::pair(0xfd, "-1/3")); + m_exposureMap.insert(std::pair(0xfc, "-1/2")); + m_exposureMap.insert(std::pair(0xfb, "-2/3")); + m_exposureMap.insert(std::pair(0xf8, "-1")); + m_exposureMap.insert(std::pair(0xf5, "-1 1/3")); + m_exposureMap.insert(std::pair(0xf4, "-1 1/2")); + m_exposureMap.insert(std::pair(0xf3, "-1 2/3")); + m_exposureMap.insert(std::pair(0xf0, "-2")); + m_exposureMap.insert(std::pair(0xed, "-2 1/3")); + m_exposureMap.insert(std::pair(0xec, "-2 1/2")); + m_exposureMap.insert(std::pair(0xeb, "-2 2/3")); + m_exposureMap.insert(std::pair(0xe8, "-3")); + + m_exposureMap.insert(std::pair(0xE5, "-3 1/3")); + m_exposureMap.insert(std::pair(0xE4, "-3 1/2")); + m_exposureMap.insert(std::pair(0xE3, "-3 2/3")); + m_exposureMap.insert(std::pair(0xE0, "-4")); + m_exposureMap.insert(std::pair(0xDD, "-4 1/3")); + m_exposureMap.insert(std::pair(0xDC, "-4 1/2")); + m_exposureMap.insert(std::pair(0xDB, "-4 2/3")); + m_exposureMap.insert(std::pair(0xD8, "-5")); + + m_exposureMap.insert( + std::pair(0xffffffff, "unknown")); +} + +//----------------------------------------------------------------- + +void StopMotion::buildWhiteBalanceMap() { + m_whiteBalanceMap.insert( + std::pair(0, "Auto: Ambience Priority")); + m_whiteBalanceMap.insert(std::pair(1, "Daylight")); + m_whiteBalanceMap.insert(std::pair(2, "Cloudy")); + m_whiteBalanceMap.insert(std::pair(3, "Tungsten")); + m_whiteBalanceMap.insert( + std::pair(4, "Fluorescent")); + m_whiteBalanceMap.insert(std::pair(5, "Flash")); + m_whiteBalanceMap.insert(std::pair(6, "Manual")); + m_whiteBalanceMap.insert(std::pair(8, "Shade")); + m_whiteBalanceMap.insert( + std::pair(9, "Color Temperature")); + m_whiteBalanceMap.insert(std::pair(10, "Custom 1")); + m_whiteBalanceMap.insert(std::pair(11, "Custom 2")); + m_whiteBalanceMap.insert(std::pair(12, "Custom 3")); + m_whiteBalanceMap.insert(std::pair(15, "Manual 2")); + m_whiteBalanceMap.insert(std::pair(16, "Manual 3")); + m_whiteBalanceMap.insert(std::pair(18, "Manual 4")); + m_whiteBalanceMap.insert(std::pair(19, "Manual 5")); + m_whiteBalanceMap.insert(std::pair(20, "Custom 4")); + m_whiteBalanceMap.insert(std::pair(21, "Custom 5")); + m_whiteBalanceMap.insert( + std::pair(23, "Auto: White Priority")); +} + +//----------------------------------------------------------------- + +void StopMotion::buildImageQualityMap() { + m_imageQualityMap.insert( + std::pair(EdsImageQuality_LR, "RAW")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_LRLJF, "RAW + Large Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_LRMJF, "RAW + Middle Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_LRSJF, "RAW + Small Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_LRLJN, "RAW + Large Normal Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_LRMJN, "RAW + Middle Normal Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_LRSJN, "RAW + Small Normal Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_LRS1JF, "RAW + Small1 Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_LRS1JN, "RAW + Small1 Normal Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_LRS2JF, "RAW + Small2 Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_LRS3JF, "RAW + Small3 Jpeg")); + + m_imageQualityMap.insert(std::pair( + EdsImageQuality_LRLJ, "RAW + Large Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_LRM1J, "RAW + Middle1 Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_LRM2J, "RAW + Middle2 Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_LRSJ, "RAW + Small Jpeg")); + + m_imageQualityMap.insert(std::pair( + EdsImageQuality_MR, "Middle Raw(Small RAW1)")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_MRLJF, "Middle Raw(Small RAW1) + Large Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_MRMJF, "Middle Raw(Small RAW1) + Middle Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_MRSJF, "Middle Raw(Small RAW1) + Small Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_MRLJN, "Middle Raw(Small RAW1) + Large Normal Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_MRMJN, "Middle Raw(Small RAW1) + Middle Normal Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_MRSJN, "Middle Raw(Small RAW1) + Small Normal Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_MRS1JF, "Middle RAW + Small1 Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_MRS1JN, "Middle RAW + Small1 Normal Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_MRS2JF, "Middle RAW + Small2 Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_MRS3JF, "Middle RAW + Small3 Jpeg")); + + m_imageQualityMap.insert(std::pair( + EdsImageQuality_MRLJ, "Middle Raw + Large Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_MRM1J, "Middle Raw + Middle1 Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_MRM2J, "Middle Raw + Middle2 Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_MRSJ, "Middle Raw + Small Jpeg")); + + m_imageQualityMap.insert(std::pair( + EdsImageQuality_SR, "Small RAW(Small RAW2)")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_SRLJF, "Small RAW(Small RAW2) + Large Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_SRMJF, "Small RAW(Small RAW2) + Middle Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_SRSJF, "Small RAW(Small RAW2) + Small Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_SRLJN, "Small RAW(Small RAW2) + Large Normal Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_SRMJN, "Small RAW(Small RAW2) + Middle Normal Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_SRSJN, "Small RAW(Small RAW2) + Small Normal Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_SRS1JF, "Small RAW + Small1 Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_SRS1JN, "Small RAW + Small1 Normal Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_SRS2JF, "Small RAW + Small2 Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_SRS3JF, "Small RAW + Small3 Jpeg")); + + m_imageQualityMap.insert(std::pair( + EdsImageQuality_SRLJ, "Small RAW + Large Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_SRM1J, "Small RAW + Middle1 Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_SRM2J, "Small RAW + Middle2 Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_SRSJ, "Small RAW + Small Jpeg")); + + m_imageQualityMap.insert( + std::pair(EdsImageQuality_CR, "CRAW")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_CRLJF, "CRAW + Large Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_CRMJF, "CRAW + Middle Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_CRM1JF, "CRAW + Middle1 Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_CRM2JF, "CRAW + Middle2 Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_CRSJF, "CRAW + Small Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_CRS1JF, "CRAW + Small1 Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_CRS2JF, "CRAW + Small2 Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_CRS3JF, "CRAW + Small3 Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_CRLJN, "CRAW + Large Normal Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_CRMJN, "CRAW + Middle Normal Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_CRM1JN, "CRAW + Middle1 Normal Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_CRM2JN, "CRAW + Middle2 Normal Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_CRSJN, "CRAW + Small Normal Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_CRS1JN, "CRAW + Small1 Normal Jpeg")); + + m_imageQualityMap.insert(std::pair( + EdsImageQuality_CRLJ, "CRAW + Large Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_CRM1J, "CRAW + Middle1 Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_CRM2J, "CRAW + Middle2 Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_CRSJ, "CRAW + Small Jpeg")); + + m_imageQualityMap.insert(std::pair( + EdsImageQuality_LJF, "Large Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_LJN, "Large Normal Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_MJF, "Middle Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_MJN, "Middle Normal Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_SJF, "Small Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_SJN, "Small Normal Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_S1JF, "Small1 Fine Jpeg")); + m_imageQualityMap.insert(std::pair( + EdsImageQuality_S1JN, "Small1 Normal Jpeg")); + m_imageQualityMap.insert( + std::pair(EdsImageQuality_S2JF, "Small2 Jpeg")); + m_imageQualityMap.insert( + std::pair(EdsImageQuality_S3JF, "Small3 Jpeg")); + + m_imageQualityMap.insert( + std::pair(EdsImageQuality_LJ, "Large Jpeg")); + m_imageQualityMap.insert( + std::pair(EdsImageQuality_M1J, "Middle1 Jpeg")); + m_imageQualityMap.insert( + std::pair(EdsImageQuality_M2J, "Middle2 Jpeg")); + m_imageQualityMap.insert( + std::pair(EdsImageQuality_SJ, "Small Jpeg")); +} + +//----------------------------------------------------------------- + +void StopMotion::buildPictureStyleMap() { + m_pictureStyleMap.insert(std::pair( + kEdsPictureStyle_Standard, "Standard")); + m_pictureStyleMap.insert(std::pair( + kEdsPictureStyle_Portrait, "Portrait")); + m_pictureStyleMap.insert(std::pair( + kEdsPictureStyle_Landscape, "Landscape")); + m_pictureStyleMap.insert( + std::pair(kEdsPictureStyle_Neutral, "Neutral")); + m_pictureStyleMap.insert(std::pair( + kEdsPictureStyle_Faithful, "Faithful")); + m_pictureStyleMap.insert(std::pair( + kEdsPictureStyle_Monochrome, "Monochrome")); + m_pictureStyleMap.insert( + std::pair(kEdsPictureStyle_Auto, "Auto")); + m_pictureStyleMap.insert(std::pair( + kEdsPictureStyle_FineDetail, "Fine Detail")); + m_pictureStyleMap.insert( + std::pair(kEdsPictureStyle_User1, "User 1")); + m_pictureStyleMap.insert( + std::pair(kEdsPictureStyle_User2, "User 2")); + m_pictureStyleMap.insert( + std::pair(kEdsPictureStyle_User3, "User 3")); + m_pictureStyleMap.insert( + std::pair(kEdsPictureStyle_PC1, "Computer 1")); + m_pictureStyleMap.insert( + std::pair(kEdsPictureStyle_PC2, "Computer 2")); + m_pictureStyleMap.insert( + std::pair(kEdsPictureStyle_PC3, "Computer 3")); +} + +//----------------------------------------------------------------- +std::string StopMotion::getTEnvCameraName() { return StopMotionCameraName; } +//----------------------------------------------------------------- +void StopMotion::setTEnvCameraName(std::string name) { + StopMotionCameraName = name; +} +//----------------------------------------------------------------- +std::string StopMotion::getTEnvCameraResolution() { + return StopMotionCameraResolution; +} +//----------------------------------------------------------------- +void StopMotion::setTEnvCameraResolution(std::string resolution) { + StopMotionCameraResolution = resolution; +} + +//============================================================================= + +class StopMotionCaptureCommand : public MenuItemHandler { +public: + StopMotionCaptureCommand() : MenuItemHandler(MI_StopMotionCapture) {} + void execute() { + StopMotion *sm = StopMotion::instance(); + if (sm->m_liveViewStatus > 0) sm->captureImage(); + } +} StopMotionCaptureCommand; + +//============================================================================= + +class StopMotionRaiseOpacityCommand : public MenuItemHandler { +public: + StopMotionRaiseOpacityCommand() + : MenuItemHandler(MI_StopMotionRaiseOpacity) {} + void execute() { + StopMotion *sm = StopMotion::instance(); + if (sm->m_liveViewStatus > 0) sm->raiseOpacity(); + } +} StopMotionRaiseOpacityCommand; + +//============================================================================= + +class StopMotionLowerOpacityCommand : public MenuItemHandler { +public: + StopMotionLowerOpacityCommand() + : MenuItemHandler(MI_StopMotionLowerOpacity) {} + void execute() { + StopMotion *sm = StopMotion::instance(); + if (sm->m_liveViewStatus > 0) sm->lowerOpacity(); + } +} StopMotionLowerOpacityCommand; + +//============================================================================= + +class StopMotionToggleLiveViewCommand : public MenuItemHandler { +public: + StopMotionToggleLiveViewCommand() + : MenuItemHandler(MI_StopMotionToggleLiveView) {} + void execute() { + StopMotion *sm = StopMotion::instance(); + sm->pauseLiveView(); + } +} StopMotionToggleLiveViewCommand; + +//============================================================================= + +class StopMotionToggleZoomCommand : public MenuItemHandler { +public: + StopMotionToggleZoomCommand() : MenuItemHandler(MI_StopMotionToggleZoom) {} + void execute() { + StopMotion *sm = StopMotion::instance(); + sm->zoomLiveView(); + } +} StopMotionToggleZoomCommand; + +//============================================================================= + +class StopMotionLowerSubsamplingCommand : public MenuItemHandler { +public: + StopMotionLowerSubsamplingCommand() + : MenuItemHandler(MI_StopMotionLowerSubsampling) {} + void execute() { + StopMotion *sm = StopMotion::instance(); + sm->setSubsamplingValue(std::max(1, sm->getSubsamplingValue() - 1)); + sm->setSubsampling(); + } +} StopMotionLowerSubsamplingCommand; + +//============================================================================= + +class StopMotionRaiseSubsamplingCommand : public MenuItemHandler { +public: + StopMotionRaiseSubsamplingCommand() + : MenuItemHandler(MI_StopMotionRaiseSubsampling) {} + void execute() { + StopMotion *sm = StopMotion::instance(); + sm->setSubsamplingValue(std::min(30, sm->getSubsamplingValue() + 1)); + sm->setSubsampling(); + } +} StopMotionRaiseSubsamplingCommand; + +//============================================================================= + +class StopMotionJumpToCameraCommand : public MenuItemHandler { +public: + StopMotionJumpToCameraCommand() + : MenuItemHandler(MI_StopMotionJumpToCamera) {} + void execute() { + StopMotion *sm = StopMotion::instance(); + sm->jumpToCameraFrame(); + } +} StopMotionJumpToCameraCommand; \ No newline at end of file diff --git a/toonz/sources/stopmotion/stopmotion.h b/toonz/sources/stopmotion/stopmotion.h new file mode 100644 index 0000000..09f76fd --- /dev/null +++ b/toonz/sources/stopmotion/stopmotion.h @@ -0,0 +1,380 @@ +#pragma once + +#ifndef STOPMOTION_H +#define STOPMOTION_H + +#ifdef WITH_STOPMOTION +// Canon Includes +#include "EDSDK.h" +#include "EDSDKErrors.h" +#include "EDSDKTypes.h" +#include "turbojpeg.h" +#include "opencv2/opencv.hpp" + +// Toonz Includes +#include "traster.h" +#include "toonzqt/gutil.h" +#include "toonzqt/dvdialog.h" + +#include + +class QCamera; +class QCameraInfo; +class QDialog; +class QTimer; + +enum ASPECT_RATIO { FOUR_THREE = 0, THREE_TWO, SIXTEEN_NINE, OTHER_RATIO }; +#endif + +#include +//============================================================================= +// JpgConverter +//----------------------------------------------------------------------------- + +class JpgConverter : public QThread { + Q_OBJECT +#ifdef WITH_STOPMOTION + EdsStreamRef m_stream; + TRaster32P m_finalImage; + bool m_scale = false; + int m_scaleWidth = 0; + +public: + JpgConverter(); + ~JpgConverter(); + void setStream(EdsStreamRef stream); + void setScale(bool scale) { m_scale = scale; } + void setScaleWidth(bool scaleWidth) { m_scaleWidth = scaleWidth; } + TRaster32P getImage() { return m_finalImage; } + void convertFromJpg(); + +protected: + void run() override; + +#endif +signals: + void imageReady(bool); +}; + +class StopMotion : public QObject { // Singleton + Q_OBJECT + +public: + static StopMotion* instance() { + static StopMotion _instance; + return &_instance; + }; +#ifdef WITH_STOPMOTION + +private: + StopMotion(); + ~StopMotion(); + + int m_opacity = 255.0; + int m_xSheetFrameNumber = 1; + int m_frameNumber = 1; + int m_subsampling = 1; + QString m_levelName = ""; + QString m_fileType = "jpg"; + QString m_filePath = "+extras"; + QString m_frameInfoText = ""; + QString m_infoColorName = ""; + QString m_frameInfoToolTip = ""; + QSize m_allowedCameraSize; + QStringList m_isoOptions, m_shutterSpeedOptions, m_apertureOptions, + m_exposureOptions, m_whiteBalanceOptions, m_colorTempOptions, + m_imageQualityOptions, m_pictureStyleOptions; + std::map m_avMap, m_tvMap, m_isoMap, m_modeMap, + m_exposureMap, m_whiteBalanceMap, m_imageQualityMap, m_pictureStyleMap; + QDialog *m_fullScreen1, *m_fullScreen2, *m_fullScreen3; + int m_screenCount; + bool m_useMjpg = true; + bool m_useNumpadShortcuts = false; + bool m_numpadForStyleSwitching = true; + bool m_turnOnRewind = false; + + QTimer* m_reviewTimer; + std::map m_oldActionMap; + + // Webcam Properties + QList m_webcams; + QCamera* m_webcam; + cv::VideoCapture m_cvWebcam; + + static EdsError EDSCALLBACK handleObjectEvent(EdsObjectEvent event, + EdsBaseRef object, + EdsVoid* context); + + static EdsError EDSCALLBACK handlePropertyEvent(EdsPropertyEvent event, + EdsPropertyID property, + EdsUInt32 param, + EdsVoid* context); + + static EdsError EDSCALLBACK handleStateEvent(EdsStateEvent event, + EdsUInt32 parameter, + EdsVoid* context); + static EdsError EDSCALLBACK handleCameraAddedEvent(EdsVoid* context); + + void buildAvMap(); + void buildTvMap(); + void buildIsoMap(); + void buildModeMap(); + void buildExposureMap(); + void buildWhiteBalanceMap(); + void buildImageQualityMap(); + void buildPictureStyleMap(); + +public: + enum LiveViewStatus { + LiveViewClosed = 0, + LiveViewStarting, + LiveViewOpen, + LiveViewPaused + }; + + JpgConverter* m_converter; + bool m_useScaledImages = true; + bool m_usingWebcam = false; + bool m_blackCapture = true; + bool m_placeOnXSheet = true; + int m_reviewTime = 2; + int m_liveViewStatus = LiveViewClosed; + bool m_hasLiveViewImage, m_hasLineUpImage, m_showLineUpImage; + bool m_alwaysLiveView = false; + bool m_active = false; + bool m_userCalledPause = false; + bool m_converterSucceeded = false; + QString m_tempFile; + QTimer* m_timer; + QList m_webcamResolutions; + + // Canon Public Properties + EdsError m_error = EDS_ERR_OK; + bool m_isSDKLoaded = false; + EdsUInt32 m_count = 0; + EdsCameraListRef m_cameraList = NULL; + EdsCameraRef m_camera = NULL; + bool m_sessionOpen = false; + bool m_zooming = false; + std::string m_cameraName; + TRaster32P m_liveViewImage, m_newImage, m_lineUpImage; + TDimension m_liveViewImageDimensions = TDimension(0, 0); + TDimension m_fullImageDimensions = TDimension(0, 0); + TDimension m_proxyImageDimensions = TDimension(0, 0); + TPointD m_proxyDpi = TPointD(0.0, 0.0); + TPointD m_liveViewDpi = TPointD(0.0, 0.0); + TPointD m_fullImageDpi = TPointD(0.0, 0.0); + TPoint m_liveViewZoomOffset = TPoint(0, 0); + EdsUInt32 m_liveViewZoom = 1; + bool m_pickLiveViewZoom = false; + TPointD m_liveViewZoomPickPoint = TPointD(0.0, 0.0); + TPoint m_zoomRect = TPoint(0, 0); + TPoint m_calculatedZoomPoint = TPoint(0, 0); + TPoint m_finalZoomPoint = TPoint(0, 0); + + // Webcam Public Properties + QString m_webcamDeviceName; + QString m_webcamDescription; + int m_webcamIndex = -1; + bool m_useDirectShow = true; + int m_webcamWidth = 0; + int m_webcamHeight = 0; + + void setOpacity(int opacity); + int getOpacity() { return m_opacity; } + void setUseScaledImages(bool on); + bool getUseScaledImages() { return m_useScaledImages; } + void setAlwaysLiveView(bool on); + bool getAlwaysLiveView() { return m_alwaysLiveView; } + void setBlackCapture(bool on); + bool getBlackCapture() { return m_blackCapture; } + void setPlaceOnXSheet(bool on); + bool getPlaceOnXSheet() { return m_placeOnXSheet; } + void setUseMjpg(bool on); + bool getUseMjpg() { return m_useMjpg; } + void setUseNumpadShortcuts(bool on); + bool getUseNumpadShortcuts() { return m_useNumpadShortcuts; } + void toggleNumpadShortcuts(bool on); + void setReviewTime(int time); + int getReviewTime() { return m_reviewTime; } + void setXSheetFrameNumber(int frameNumber); + int getXSheetFrameNumber() { return m_xSheetFrameNumber; } + void setFrameNumber(int frameNumber); + int getFrameNumber() { return m_frameNumber; } + void setLevelName(QString levelName); + QString getLevelName() { return m_levelName; } + void setFileType(QString fileType); + QString getFileType() { return m_fileType; } + void setFilePath(QString filePath); + QString getFilePath() { return m_filePath; } + void updateLevelNameAndFrame(std::wstring levelName); + void setToNextNewLevel(); + void nextFrame(); + void previousFrame(); + void lastFrame(); + void nextName(); + void previousName(); + + QString getFrameInfoText() { return m_frameInfoText; } + QString getInfoColorName() { return m_infoColorName; } + QString getFrameInfoToolTip() { return m_frameInfoToolTip; } + bool toggleLiveView(); + void pauseLiveView(); + void getSubsampling(); + void setSubsampling(); + int getSubsamplingValue() { return m_subsampling; } + void setSubsamplingValue(int subsampling); + void captureImage(); + void postImportProcess(); + void refreshFrameInfo(); + void refreshCameraList(); + void changeCameras(int index); + void raiseOpacity(); + void lowerOpacity(); + void jumpToCameraFrame(); + + std::string getTEnvCameraName(); + void setTEnvCameraName(std::string name); + std::string getTEnvCameraResolution(); + void setTEnvCameraResolution(std::string resolution); + + void saveJpg(TRaster32P, TFilePath path); + bool loadJpg(TFilePath path, TRaster32P& image); + bool loadLineUpImage(); + + // Webcam Commands + QList getWebcams(); + QCamera* getWebcam() { return m_webcam; } + void setWebcam(QCamera* camera); + bool initWebcam(int index = 0); + void releaseWebcam(); + void setWebcamResolution(QString resolution); + void getWebcamImage(); + bool translateIndex(int index); + bool getUseDirectShow() { return m_useDirectShow; } + void setUseDirectShow(int state); + QList getWebcamResolutions() { return m_webcamResolutions; } + // void changeResolutions(int index); + + // Canon Commands + EdsError initializeCanonSDK(); + void closeCanonSDK(); + EdsCameraListRef getCameraList(); + EdsError releaseCameraList(); + int getCameraCount(); + EdsError getCamera(int index); + EdsError releaseCamera(); + void cameraAdded(); + EdsError openCameraSession(); + EdsError closeCameraSession(); + std::string getCameraName(); + EdsError downloadImage(EdsBaseRef object); + EdsError takePicture(); + EdsError startLiveView(); + EdsError endLiveView(); + EdsError downloadEVFData(); + QStringList getIsoOptions() { return m_isoOptions; } + QStringList getShutterSpeedOptions() { return m_shutterSpeedOptions; } + QStringList getApertureOptions() { return m_apertureOptions; } + QStringList getExposureOptions() { return m_exposureOptions; } + QStringList getWhiteBalanceOptions() { return m_whiteBalanceOptions; } + QStringList getColorTemperatureOptions() { return m_colorTempOptions; } + QStringList getImageQualityOptions() { return m_imageQualityOptions; } + QStringList getPictureStyleOptions() { return m_pictureStyleOptions; } + EdsError getAvailableShutterSpeeds(); + EdsError getAvailableIso(); + EdsError getAvailableApertures(); + EdsError getAvailableExposureCompensations(); + EdsError getAvailableWhiteBalances(); + EdsError getAvailableImageQualities(); + EdsError getAvailablePictureStyles(); + void buildColorTemperatures(); + QString getCurrentShutterSpeed(); + QString getCurrentIso(); + QString getCurrentAperture(); + QString getCurrentExposureCompensation(); + QString getCurrentWhiteBalance(); + QString getCurrentColorTemperature(); + QString getCurrentImageQuality(); + QString getCurrentPictureStyle(); + EdsError setShutterSpeed(QString shutterSpeed); + EdsError setIso(QString iso); + EdsError setAperture(QString aperture); + EdsError setExposureCompensation(QString exposure); + EdsError setWhiteBalance(QString whiteBalance); + EdsError setColorTemperature(QString temp); + EdsError setImageQuality(QString quality); + EdsError setPictureStyle(QString style); + QString getMode(); + void refreshOptions(); + EdsError zoomLiveView(); + EdsError setZoomPoint(); + void makeZoomPoint(TPointD pos); + EdsError focusNear(); + EdsError focusFar(); + EdsError focusNear2(); + EdsError focusFar2(); + EdsError focusNear3(); + EdsError focusFar3(); + +#endif // WITH_STOPMOTION +public slots: + void onImageReady(const bool&); + void onFinished(); + void onTimeout(); + void onReviewTimeout(); + void update(); + bool importImage(); + void onSceneSwitched(); + void onPlaybackChanged(); + +signals: + void newLiveViewImageReady(); + void liveViewStopped(); + void newImageReady(); + void cameraChanged(); + void optionsChanged(); + void liveViewChanged(bool); + void newCameraSelected(int, bool); + void webcamResolutionsChanged(); + void newWebcamResolutionSelected(int); + + void apertureOptionsChanged(); + void isoOptionsChanged(); + void shutterSpeedOptionsChanged(); + void exposureOptionsChanged(); + void whiteBalanceOptionsChanged(); + void colorTemperatureChanged(); + void imageQualityOptionsChanged(); + void pictureStyleOptionsChanged(); + void apertureChangedSignal(QString); + void isoChangedSignal(QString); + void shutterSpeedChangedSignal(QString); + void exposureChangedSignal(QString); + void whiteBalanceChangedSignal(QString); + void colorTemperatureChangedSignal(QString); + void imageQualityChangedSignal(QString); + void pictureStyleChangedSignal(QString); + void modeChanged(); + + void newDimensions(); + void subsamplingChanged(int); + void filePathChanged(QString); + void levelNameChanged(QString); + void fileTypeChanged(QString); + void xSheetFrameNumberChanged(int); + void frameNumberChanged(int); + void frameInfoTextChanged(QString); + void opacityChanged(int); + void scaleFullSizeImagesSignal(bool); + void blackCaptureSignal(bool); + void liveViewOnAllFramesSignal(bool); + void placeOnXSheetSignal(bool); + void useMjpgSignal(bool); + void useNumpadSignal(bool); + void useDirectShowSignal(bool); + void reviewTimeChangedSignal(int); + void updateCameraList(); +}; + +#endif // STOPMOTION_H \ No newline at end of file diff --git a/toonz/sources/stopmotion/stopmotioncontroller.cpp b/toonz/sources/stopmotion/stopmotioncontroller.cpp new file mode 100644 index 0000000..d27d30d --- /dev/null +++ b/toonz/sources/stopmotion/stopmotioncontroller.cpp @@ -0,0 +1,1730 @@ +#include "stopmotioncontroller.h" + +// TnzLib includes +#include "toonz/levelset.h" +#include "toonz/preferences.h" +#include "toonz/sceneproperties.h" +#include "toonz/toonzscene.h" +#include "toonz/tcamera.h" +#include "toonz/tcolumnhandle.h" +#include "toonz/tframehandle.h" +#include "toonz/tscenehandle.h" +#include "toonz/txshcell.h" +#include "toonz/txsheethandle.h" +#include "toonz/txshlevelhandle.h" +#include "toonz/txshsimplelevel.h" +#include "toonz/tstageobjecttree.h" + +// TnzCore includes +#include "filebrowsermodel.h" +#include "formatsettingspopups.h" +#include "tapp.h" +#include "tenv.h" +#include "tlevel_io.h" +#include "toutputproperties.h" +#include "tsystem.h" + +// TnzQt includes +#include "toonzqt/filefield.h" +#include "toonzqt/intfield.h" +#include "toonzqt/menubarcommand.h" + +// Qt includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#endif + +namespace { + +//----------------------------------------------------------------------------- + +#ifdef _WIN32 +void openCaptureFilterSettings(const QWidget *parent, + const QString &cameraName) { + HRESULT hr; + + ICreateDevEnum *createDevEnum = NULL; + IEnumMoniker *enumMoniker = NULL; + IMoniker *moniker = NULL; + + IBaseFilter *deviceFilter; + + ISpecifyPropertyPages *specifyPropertyPages; + CAUUID cauuid; + // set parent's window handle in order to make the dialog modal + HWND ghwndApp = (HWND)(parent->winId()); + + // initialize COM + CoInitialize(NULL); + + // get device list + CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, + IID_ICreateDevEnum, (PVOID *)&createDevEnum); + + // create EnumMoniker + createDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, + &enumMoniker, 0); + if (enumMoniker == NULL) { + // if no connected devices found + return; + } + + // reset EnumMoniker + enumMoniker->Reset(); + + // find target camera + ULONG fetched = 0; + bool isCameraFound = false; + while (hr = enumMoniker->Next(1, &moniker, &fetched), hr == S_OK) { + // get friendly name (= device name) of the camera + IPropertyBag *pPropertyBag; + moniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropertyBag); + VARIANT var; + var.vt = VT_BSTR; + VariantInit(&var); + + pPropertyBag->Read(L"FriendlyName", &var, 0); + + QString deviceName = QString::fromWCharArray(var.bstrVal); + + VariantClear(&var); + + if (deviceName == cameraName) { + // bind monkier to the filter + moniker->BindToObject(0, 0, IID_IBaseFilter, (void **)&deviceFilter); + + // release moniker etc. + moniker->Release(); + enumMoniker->Release(); + createDevEnum->Release(); + + isCameraFound = true; + break; + } + } + + // if no matching camera found + if (!isCameraFound) return; + + // open capture filter popup + hr = deviceFilter->QueryInterface(IID_ISpecifyPropertyPages, + (void **)&specifyPropertyPages); + if (hr == S_OK) { + hr = specifyPropertyPages->GetPages(&cauuid); + + hr = OleCreatePropertyFrame(ghwndApp, 30, 30, NULL, 1, + (IUnknown **)&deviceFilter, cauuid.cElems, + (GUID *)cauuid.pElems, 0, 0, NULL); + + CoTaskMemFree(cauuid.pElems); + specifyPropertyPages->Release(); + } +} +#endif + +//----------------------------------------------------------------------------- + +QScrollArea *makeChooserPage(QWidget *chooser) { + QScrollArea *scrollArea = new QScrollArea(); + scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + scrollArea->setWidgetResizable(true); + scrollArea->setWidget(chooser); + return scrollArea; +} + +//----------------------------------------------------------------------------- + +QScrollArea *makeChooserPageWithoutScrollBar(QWidget *chooser) { + QScrollArea *scrollArea = new QScrollArea(); + scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + scrollArea->setWidgetResizable(true); + scrollArea->setWidget(chooser); + return scrollArea; +} + +} // namespace + +//***************************************************************************** +// StopMotionController implementation +//***************************************************************************** + +StopMotionController::StopMotionController(QWidget *parent) : QWidget(parent) { + m_stopMotion = StopMotion::instance(); + m_tabBar = new DVGui::TabBar(this); + m_tabBar->setDrawBase(false); + m_tabBar->setObjectName("StopMotionTabBar"); + m_tabBar->addSimpleTab(tr("Controls")); + m_tabBar->addSimpleTab(tr("Settings")); + m_tabBar->addSimpleTab(tr("Options")); + m_tabBarContainer = new TabBarContainter(this); + m_mainControlsPage = new QFrame(); + m_cameraSettingsPage = new QFrame(); + m_optionsPage = new QFrame(); + + // ********************** + // Make Control Page + // ********************** + + m_saveInFolderPopup = new PencilTestSaveInFolderPopup(this); + m_cameraListCombo = new QComboBox(this); + m_resolutionCombo = new QComboBox(this); + m_resolutionCombo->setFixedWidth(fontMetrics().width("0000 x 0000") + 25); + m_resolutionLabel = new QLabel(tr("Resolution: "), this); + QPushButton *refreshCamListButton = new QPushButton(tr("Refresh"), this); + refreshCamListButton->setFixedHeight(28); + refreshCamListButton->setStyleSheet("padding: 0 2;"); + QGroupBox *fileFrame = new QGroupBox(tr("File"), this); + m_levelNameEdit = new LevelNameLineEdit(this); + +#ifdef _WIN32 + m_captureFilterSettingsBtn = new QPushButton(this); +#else + m_captureFilterSettingsBtn = 0; +#endif + if (m_captureFilterSettingsBtn) { + m_captureFilterSettingsBtn->setObjectName("GearButton"); + m_captureFilterSettingsBtn->setFixedSize(28, 28); + m_captureFilterSettingsBtn->setIconSize(QSize(15, 15)); + m_captureFilterSettingsBtn->setToolTip(tr("Webcam Settings...")); + } + + // set the start frame 10 if the option in preferences + // "Show ABC Appendix to the Frame Number in Xsheet Cell" is active. + // (frame 10 is displayed as "1" with this option) + int startFrame = + Preferences::instance()->isShowFrameNumberWithLettersEnabled() ? 10 : 1; + m_frameNumberEdit = new FrameNumberLineEdit(this, startFrame); + m_frameInfoLabel = new QLabel("", this); + m_fileTypeCombo = new QComboBox(this); + m_fileFormatOptionButton = new QPushButton(tr("Options"), this); + m_fileFormatOptionButton->setFixedHeight(28); + m_fileFormatOptionButton->setStyleSheet("padding: 0 2;"); + m_xSheetFrameNumberEdit = new DVGui::IntLineEdit(this, 1, 1); + m_saveInFileFld = + new DVGui::FileField(this, m_saveInFolderPopup->getParentPath()); + QToolButton *nextLevelButton = new QToolButton(this); + m_previousLevelButton = new QToolButton(this); + QPushButton *nextOpenLevelButton = new QPushButton(this); + QToolButton *nextFrameButton = new QToolButton(this); + m_previousFrameButton = new QToolButton(this); + QPushButton *lastFrameButton = new QPushButton(this); + QToolButton *nextXSheetFrameButton = new QToolButton(this); + m_previousXSheetFrameButton = new QToolButton(this); + m_onionOpacityFld = new DVGui::IntField(this); + m_captureButton = new QPushButton(tr("Capture"), this); + // QPushButton *subfolderButton = new QPushButton(tr("Subfolder"), this); + m_fileTypeCombo->addItems({"jpg", "png", "tga", "tif"}); + m_fileTypeCombo->setCurrentIndex(0); + + fileFrame->setObjectName("CleanupSettingsFrame"); + m_frameNumberEdit->setObjectName("LargeSizedText"); + m_frameInfoLabel->setAlignment(Qt::AlignRight); + nextLevelButton->setFixedSize(24, 24); + nextLevelButton->setArrowType(Qt::RightArrow); + nextLevelButton->setToolTip(tr("Next Level")); + nextOpenLevelButton->setText(tr("Next New")); + nextOpenLevelButton->setFixedHeight(28); + nextOpenLevelButton->setStyleSheet("padding: 0 2;"); + nextOpenLevelButton->setSizePolicy(QSizePolicy::Maximum, + QSizePolicy::Maximum); + m_previousLevelButton->setFixedSize(24, 24); + m_previousLevelButton->setArrowType(Qt::LeftArrow); + m_previousLevelButton->setToolTip(tr("Previous Level")); + nextFrameButton->setFixedSize(24, 24); + nextFrameButton->setArrowType(Qt::RightArrow); + nextFrameButton->setToolTip(tr("Next Frame")); + lastFrameButton->setText(tr("Last Frame")); + lastFrameButton->setFixedHeight(28); + lastFrameButton->setStyleSheet("padding: 0 2;"); + lastFrameButton->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + m_previousFrameButton->setFixedSize(24, 24); + m_previousFrameButton->setArrowType(Qt::LeftArrow); + m_previousFrameButton->setToolTip(tr("Previous Frame")); + + m_xSheetFrameNumberEdit->setObjectName("LargeSizedText"); + nextXSheetFrameButton->setFixedSize(24, 24); + nextXSheetFrameButton->setArrowType(Qt::RightArrow); + nextXSheetFrameButton->setToolTip(tr("Next XSheet Frame")); + m_previousXSheetFrameButton->setFixedSize(24, 24); + m_previousXSheetFrameButton->setArrowType(Qt::LeftArrow); + m_previousXSheetFrameButton->setToolTip(tr("Previous XSheet Frame")); + + m_setToCurrentXSheetFrameButton = new QPushButton(this); + m_setToCurrentXSheetFrameButton->setText(tr("Current Frame")); + m_setToCurrentXSheetFrameButton->setFixedHeight(28); + m_setToCurrentXSheetFrameButton->setSizePolicy(QSizePolicy::Maximum, + QSizePolicy::Maximum); + m_setToCurrentXSheetFrameButton->setStyleSheet("padding: 2px;"); + m_setToCurrentXSheetFrameButton->setToolTip( + tr("Set to the Current Playhead Location")); + + m_onionOpacityFld->setRange(0, 100); + m_onionOpacityFld->setValue(100); + m_onionOpacityFld->setDisabled(false); + m_toggleLiveViewButton = new QPushButton(tr("Start Live View")); + m_toggleLiveViewButton->setObjectName("LargeSizedText"); + m_toggleLiveViewButton->setFixedHeight(35); + m_captureButton->setObjectName("LargeSizedText"); + m_captureButton->setFixedHeight(35); + QCommonStyle style; + m_captureButton->setIcon(style.standardIcon(QStyle::SP_DialogOkButton)); + m_captureButton->setIconSize(QSize(20, 20)); + + // subfolderButton->setObjectName("SubfolderButton"); + // subfolderButton->setIconSize(QSize(15, 15)); + m_saveInFileFld->setMaximumWidth(380); + m_levelNameEdit->setMaximumWidth(380); + + m_saveInFolderPopup->hide(); + m_zoomButton = new QPushButton(tr("Zoom"), this); + m_zoomButton->setFixedHeight(28); + m_zoomButton->setStyleSheet("padding: 0 2;"); + m_zoomButton->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + m_pickZoomButton = new QPushButton(tr("Pick Zoom"), this); + m_pickZoomButton->setStyleSheet("padding: 0 2;"); + m_pickZoomButton->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + m_pickZoomButton->setFixedHeight(28); + m_focusNearButton = new QPushButton(tr("<"), this); + m_focusNearButton->setFixedSize(32, 28); + m_focusFarButton = new QPushButton(tr(">"), this); + m_focusFarButton->setFixedSize(32, 28); + m_focusNear2Button = new QPushButton(tr("<<"), this); + m_focusNear2Button->setFixedSize(32, 28); + m_focusFar2Button = new QPushButton(tr(">>"), this); + m_focusFar2Button->setFixedSize(32, 28); + m_focusNear3Button = new QPushButton(tr("<<<"), this); + m_focusNear3Button->setFixedSize(32, 28); + m_focusFar3Button = new QPushButton(tr(">>>"), this); + m_focusFar3Button->setFixedSize(32, 28); + //*****//**** + + QVBoxLayout *controlLayout = new QVBoxLayout(); + controlLayout->setSpacing(0); + controlLayout->setMargin(5); + + { + { + QGridLayout *camLay = new QGridLayout(); + camLay->setMargin(0); + camLay->setSpacing(3); + { + camLay->addWidget(new QLabel(tr("Camera:"), this), 0, 0, + Qt::AlignRight); + camLay->addWidget(m_cameraListCombo, 0, 1, Qt::AlignLeft); + camLay->addWidget(refreshCamListButton, 0, 2, Qt::AlignLeft); + if (m_captureFilterSettingsBtn) { + camLay->addWidget(m_captureFilterSettingsBtn, 0, 3, Qt::AlignLeft); + camLay->addWidget(m_resolutionLabel, 1, 0, Qt::AlignRight); + camLay->addWidget(m_resolutionCombo, 1, 1, 1, 3, Qt::AlignLeft); + camLay->setColumnStretch(3, 30); + } else { + camLay->addWidget(m_resolutionLabel, 1, 0, Qt::AlignRight); + camLay->addWidget(m_resolutionCombo, 1, 1, 1, 2, Qt::AlignLeft); + camLay->setColumnStretch(2, 30); + } + } + controlLayout->addLayout(camLay, 0); + + QVBoxLayout *fileLay = new QVBoxLayout(); + fileLay->setMargin(8); + fileLay->setSpacing(5); + { + QGridLayout *levelLay = new QGridLayout(); + levelLay->setMargin(0); + levelLay->setHorizontalSpacing(3); + levelLay->setVerticalSpacing(5); + { + levelLay->addWidget(new QLabel(tr("Name:"), this), 0, 0, + Qt::AlignRight); + QHBoxLayout *nameLay = new QHBoxLayout(); + nameLay->setMargin(0); + nameLay->setSpacing(2); + { + nameLay->addWidget(m_previousLevelButton, 0); + nameLay->addWidget(m_levelNameEdit, 1); + nameLay->addWidget(nextLevelButton, 0); + nameLay->addWidget(nextOpenLevelButton, 0); + } + levelLay->addLayout(nameLay, 0, 1); + + levelLay->addWidget(new QLabel(tr("Frame:"), this), 1, 0, + Qt::AlignRight); + + QHBoxLayout *frameLay = new QHBoxLayout(); + frameLay->setMargin(0); + frameLay->setSpacing(2); + { + frameLay->addWidget(m_previousFrameButton, 0); + frameLay->addWidget(m_frameNumberEdit, 1); + frameLay->addWidget(nextFrameButton, 0); + frameLay->addWidget(lastFrameButton, 0); + frameLay->addWidget(m_frameInfoLabel, 1, Qt::AlignVCenter); + } + levelLay->addLayout(frameLay, 1, 1); + } + levelLay->setColumnStretch(0, 0); + levelLay->setColumnStretch(1, 1); + fileLay->addLayout(levelLay, 0); + + QHBoxLayout *fileTypeLay = new QHBoxLayout(); + fileTypeLay->setMargin(0); + fileTypeLay->setSpacing(3); + { + fileTypeLay->addWidget(new QLabel(tr("File Type:"), this), 0); + fileTypeLay->addWidget(m_fileTypeCombo, 1); + fileTypeLay->addSpacing(10); + fileTypeLay->addWidget(m_fileFormatOptionButton); + } + fileLay->addLayout(fileTypeLay, 0); + + QHBoxLayout *saveInLay = new QHBoxLayout(); + saveInLay->setMargin(0); + saveInLay->setSpacing(3); + { + saveInLay->addWidget(new QLabel(tr("Save In:"), this), 0); + saveInLay->addWidget(m_saveInFileFld, 1); + } + fileLay->addLayout(saveInLay, 0); + // fileLay->addWidget(subfolderButton, 0); + } + fileFrame->setLayout(fileLay); + controlLayout->addWidget(fileFrame, 0); + + QGridLayout *displayLay = new QGridLayout(); + displayLay->setMargin(8); + displayLay->setHorizontalSpacing(3); + displayLay->setVerticalSpacing(5); + { + displayLay->addWidget(new QLabel(tr("XSheet Frame:"), this), 0, 0, + Qt::AlignRight); + QHBoxLayout *xsheetLay = new QHBoxLayout(); + xsheetLay->setMargin(0); + xsheetLay->setSpacing(2); + { + xsheetLay->addWidget(m_previousXSheetFrameButton, Qt::AlignLeft); + xsheetLay->addWidget(m_xSheetFrameNumberEdit, Qt::AlignLeft); + xsheetLay->addWidget(nextXSheetFrameButton, Qt::AlignLeft); + xsheetLay->addWidget(m_setToCurrentXSheetFrameButton, + Qt::AlignCenter); + xsheetLay->addStretch(50); + } + displayLay->addLayout(xsheetLay, 0, 1); + } + displayLay->setColumnStretch(0, 0); + displayLay->setColumnStretch(1, 1); + controlLayout->addLayout(displayLay, 0); + controlLayout->addStretch(1); + controlLayout->addSpacing(5); + controlLayout->addStretch(1); + } + + m_mainControlsPage->setLayout(controlLayout); + + // Make Settings Page + + m_isoCombo = new QComboBox(this); + m_shutterSpeedCombo = new QComboBox(this); + m_exposureCombo = new QComboBox(this); + m_apertureCombo = new QComboBox(this); + m_whiteBalanceCombo = new QComboBox(this); + m_kelvinCombo = new QComboBox(this); + m_imageQualityCombo = new QComboBox(this); + m_pictureStyleCombo = new QComboBox(this); + m_cameraSettingsLabel = new QLabel(tr("Camera Model"), this); + m_cameraModeLabel = new QLabel(tr("Camera Mode"), this); + m_kelvinLabel = new QLabel(tr("Temperature: "), this); + m_isoCombo->setFixedWidth(fontMetrics().width("000000") + 25); + m_shutterSpeedCombo->setFixedWidth(fontMetrics().width("000000") + 25); + m_apertureCombo->setFixedWidth(fontMetrics().width("000000") + 25); + m_exposureCombo->setFixedWidth(fontMetrics().width("000000") + 25); + QVBoxLayout *settingsLayout = new QVBoxLayout; + settingsLayout->setSpacing(0); + settingsLayout->setMargin(5); + + QGridLayout *settingsGridLayout = new QGridLayout; + { + settingsGridLayout->setMargin(0); + settingsGridLayout->setSpacing(3); + settingsGridLayout->addWidget(m_cameraSettingsLabel, 0, 0, 1, 2, + Qt::AlignCenter); + settingsGridLayout->addWidget(m_cameraModeLabel, 1, 0, 1, 2, + Qt::AlignCenter); + settingsGridLayout->addWidget(new QLabel(tr("Shutter Speed: ")), 2, 0, + Qt::AlignRight); + settingsGridLayout->addWidget(m_shutterSpeedCombo, 2, 1, Qt::AlignLeft); + settingsGridLayout->addWidget(new QLabel(tr("Iso: ")), 3, 0, + Qt::AlignRight); + settingsGridLayout->addWidget(m_isoCombo, 3, 1, Qt::AlignLeft); + settingsGridLayout->addWidget(new QLabel(tr("Aperture: ")), 4, 0, + Qt::AlignRight); + settingsGridLayout->addWidget(m_apertureCombo, 4, 1, Qt::AlignLeft); + settingsGridLayout->addWidget(new QLabel(tr("Exposure: ")), 5, 0, + Qt::AlignRight); + settingsGridLayout->addWidget(m_exposureCombo, 5, 1, Qt::AlignLeft); + settingsGridLayout->addWidget(new QLabel(tr("Image Quality: ")), 6, 0, + Qt::AlignRight); + settingsGridLayout->addWidget(m_imageQualityCombo, 6, 1, Qt::AlignLeft); + settingsGridLayout->addWidget(new QLabel(tr("Picture Style: ")), 7, 0, + Qt::AlignRight); + settingsGridLayout->addWidget(m_pictureStyleCombo, 7, 1, Qt::AlignLeft); + settingsGridLayout->addWidget(new QLabel(tr("White Balance: ")), 8, 0, + Qt::AlignRight); + settingsGridLayout->addWidget(m_whiteBalanceCombo, 8, 1, Qt::AlignLeft); + settingsGridLayout->addWidget(m_kelvinLabel, 9, 0, Qt::AlignRight); + settingsGridLayout->addWidget(m_kelvinCombo, 9, 1, Qt::AlignLeft); + + settingsGridLayout->setColumnStretch(1, 30); + } + settingsLayout->addLayout(settingsGridLayout, 0); + m_focusAndZoomLayout = new QHBoxLayout; + m_focusAndZoomLayout->addStretch(); + m_focusAndZoomLayout->addWidget(m_focusNear3Button, Qt::AlignCenter); + m_focusAndZoomLayout->addWidget(m_focusNear2Button, Qt::AlignCenter); + m_focusAndZoomLayout->addWidget(m_focusNearButton, Qt::AlignCenter); + m_focusAndZoomLayout->addWidget(m_zoomButton, Qt::AlignCenter); + m_focusAndZoomLayout->addWidget(m_pickZoomButton, Qt::AlignCenter); + m_focusAndZoomLayout->addWidget(m_focusFarButton, Qt::AlignCenter); + m_focusAndZoomLayout->addWidget(m_focusFar2Button, Qt::AlignCenter); + m_focusAndZoomLayout->addWidget(m_focusFar3Button, Qt::AlignCenter); + m_focusAndZoomLayout->addStretch(); + // settingsLayout->addStretch(); + settingsLayout->addLayout(m_focusAndZoomLayout); + settingsLayout->addStretch(); + m_cameraSettingsPage->setLayout(settingsLayout); + + // Make Options Page + QGroupBox *webcamBox = new QGroupBox(tr("Webcam Options"), this); + QGroupBox *dslrBox = new QGroupBox(tr("DSLR Options"), this); + m_postCaptureReviewFld = new DVGui::IntField(this); + m_postCaptureReviewFld->setRange(0, 10); + + m_subsamplingFld = new DVGui::IntField(this); + m_subsamplingFld->setRange(1, 30); + m_subsamplingFld->setDisabled(true); + m_blackScreenForCapture = new QCheckBox(this); + + m_placeOnXSheetCB = new QCheckBox(this); + m_placeOnXSheetCB->setToolTip(tr("Place the frame in the XSheet")); + + m_useScaledFullSizeImages = new QCheckBox(this); + m_directShowLabel = new QLabel(tr("Use Direct Show Webcam Drivers"), this); + m_directShowCB = new QCheckBox(this); + m_useMjpgCB = new QCheckBox(this); + m_useNumpadCB = new QCheckBox(this); + + m_liveViewOnAllFramesCB = new QCheckBox(this); + QVBoxLayout *optionsOutsideLayout = new QVBoxLayout; + QGridLayout *optionsLayout = new QGridLayout; + optionsLayout->setSpacing(3); + optionsLayout->setMargin(5); + QGridLayout *webcamLayout = new QGridLayout; + QGridLayout *dslrLayout = new QGridLayout; + QGridLayout *checkboxLayout = new QGridLayout; + + dslrLayout->addWidget(m_blackScreenForCapture, 0, 0, Qt::AlignRight); + dslrLayout->addWidget(new QLabel(tr("Black Screen for Capture")), 0, 1, + Qt::AlignLeft); + dslrLayout->addWidget(m_useScaledFullSizeImages, 1, 0, Qt::AlignRight); + dslrLayout->addWidget(new QLabel(tr("Use Reduced Resolution Images")), 1, 1, + Qt::AlignLeft); + dslrLayout->setColumnStretch(1, 30); + dslrBox->setLayout(dslrLayout); + dslrBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Maximum); + optionsOutsideLayout->addWidget(dslrBox, Qt::AlignCenter); + + webcamLayout->addWidget(m_directShowCB, 0, 0, Qt::AlignRight); + webcamLayout->addWidget(m_directShowLabel, 0, 1, Qt::AlignLeft); + webcamLayout->addWidget(m_useMjpgCB, 1, 0, Qt::AlignRight); + webcamLayout->addWidget(new QLabel(tr("Use MJPG with Webcam")), 1, 1, + Qt::AlignLeft); + webcamLayout->setColumnStretch(1, 30); + webcamBox->setLayout(webcamLayout); + webcamBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Maximum); + optionsOutsideLayout->addWidget(webcamBox, Qt::AlignCenter); + + checkboxLayout->addWidget(m_placeOnXSheetCB, 0, 0, 1, 1, Qt::AlignRight); + checkboxLayout->addWidget(new QLabel(tr("Place on XSheet")), 0, 1, + Qt::AlignLeft); + checkboxLayout->addWidget(m_useNumpadCB, 1, 0, Qt::AlignRight); + checkboxLayout->addWidget( + new QLabel(tr("Use Numpad Shortcuts When Active")), 1, 1, + Qt::AlignLeft); + checkboxLayout->addWidget(m_liveViewOnAllFramesCB, 2, 0, Qt::AlignRight); + checkboxLayout->addWidget(new QLabel(tr("Show Live View on All Frames")), 2, + 1, Qt::AlignLeft); + + checkboxLayout->setColumnStretch(1, 30); + optionsOutsideLayout->addLayout(checkboxLayout, Qt::AlignLeft); + + optionsLayout->addWidget(new QLabel(tr("Capture Review Time: ")), 0, 0, + Qt::AlignRight); + optionsLayout->addWidget(m_postCaptureReviewFld, 0, 1); + optionsLayout->addWidget(new QLabel(tr("Level Subsampling: ")), 1, 0, + Qt::AlignRight); + optionsLayout->addWidget(m_subsamplingFld, 1, 1); + optionsLayout->setColumnStretch(1, 30); + optionsLayout->setRowStretch(2, 30); + optionsOutsideLayout->addLayout(optionsLayout, Qt::AlignLeft); + optionsOutsideLayout->addStretch(); + + m_optionsPage->setLayout(optionsOutsideLayout); + + QScrollArea *mainArea = makeChooserPageWithoutScrollBar(m_mainControlsPage); + QScrollArea *settingsArea = + makeChooserPageWithoutScrollBar(m_cameraSettingsPage); + QScrollArea *optionsArea = makeChooserPageWithoutScrollBar(m_optionsPage); + + m_stackedChooser = new QStackedWidget(this); + m_stackedChooser->addWidget(mainArea); + m_stackedChooser->addWidget(settingsArea); + m_stackedChooser->addWidget(optionsArea); + m_stackedChooser->setFocusPolicy(Qt::NoFocus); + + QFrame *opacityFrame = new QFrame(); + QHBoxLayout *opacityLay = new QHBoxLayout(); + opacityLay->addWidget(new QLabel(tr("Opacity:"), this), 0); + opacityLay->addWidget(m_onionOpacityFld, 1); + opacityFrame->setLayout(opacityLay); + opacityFrame->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Maximum); + + QFrame *controlButtonFrame = new QFrame(); + QHBoxLayout *controlButtonLay = new QHBoxLayout(); + controlButtonLay->addWidget(m_captureButton, 0); + controlButtonLay->addWidget(m_toggleLiveViewButton, 0); + controlButtonFrame->setLayout(controlButtonLay); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->setMargin(0); + mainLayout->setSpacing(0); + { + QHBoxLayout *hLayout = new QHBoxLayout; + hLayout->setMargin(0); + { + hLayout->addSpacing(4); + hLayout->addWidget(m_tabBar); + hLayout->addStretch(); + } + m_tabBarContainer->setLayout(hLayout); + + mainLayout->addWidget(m_tabBarContainer, 0, 0); + mainLayout->addWidget(m_stackedChooser, 1, 0); + mainLayout->addWidget(opacityFrame, 0); + mainLayout->addWidget(controlButtonFrame, 0); + setLayout(mainLayout); + m_tabBarContainer->layout()->update(); + } + } + + TSceneHandle *sceneHandle = TApp::instance()->getCurrentScene(); + TXsheetHandle *xsheetHandle = TApp::instance()->getCurrentXsheet(); + + bool ret = true; + + // Outside Connections + ret = ret && connect(sceneHandle, SIGNAL(sceneSwitched()), this, + SLOT(onSceneSwitched())); + ret = ret && + connect(xsheetHandle, SIGNAL(xsheetSwitched()), this, SLOT(update())); + + // UI SIGNALS + ret = ret && connect(m_tabBar, SIGNAL(currentChanged(int)), this, + SLOT(setPage(int))); + + // Control Page + ret = ret && connect(refreshCamListButton, SIGNAL(pressed()), this, + SLOT(refreshCameraListCalled())); + ret = ret && connect(m_cameraListCombo, SIGNAL(activated(int)), this, + SLOT(onCameraListComboActivated(int))); + ret = ret && connect(m_resolutionCombo, SIGNAL(activated(const QString &)), + this, SLOT(onResolutionComboActivated(const QString &))); + if (m_captureFilterSettingsBtn) + ret = ret && connect(m_captureFilterSettingsBtn, SIGNAL(pressed()), this, + SLOT(onCaptureFilterSettingsBtnPressed())); + ret = ret && connect(m_fileFormatOptionButton, SIGNAL(pressed()), this, + SLOT(onFileFormatOptionButtonPressed())); + ret = ret && connect(m_levelNameEdit, SIGNAL(levelNameEdited()), this, + SLOT(onLevelNameEdited())); + ret = ret && + connect(nextLevelButton, SIGNAL(pressed()), this, SLOT(onNextName())); + ret = ret && connect(m_previousLevelButton, SIGNAL(pressed()), this, + SLOT(onPreviousName())); + ret = ret && connect(nextOpenLevelButton, SIGNAL(pressed()), this, + SLOT(onNextNewLevel())); + ret = ret && + connect(nextFrameButton, SIGNAL(pressed()), this, SLOT(onNextFrame())); + ret = ret && + connect(lastFrameButton, SIGNAL(pressed()), this, SLOT(onLastFrame())); + ret = ret && connect(m_previousFrameButton, SIGNAL(pressed()), this, + SLOT(onPreviousFrame())); + ret = ret && connect(nextXSheetFrameButton, SIGNAL(pressed()), this, + SLOT(onNextXSheetFrame())); + ret = ret && connect(m_previousXSheetFrameButton, SIGNAL(pressed()), this, + SLOT(onPreviousXSheetFrame())); + ret = ret && connect(m_setToCurrentXSheetFrameButton, SIGNAL(pressed()), this, + SLOT(setToCurrentXSheetFrame())); + ret = ret && connect(m_onionOpacityFld, SIGNAL(valueEditedByHand()), this, + SLOT(onOnionOpacityFldEdited())); + ret = ret && connect(m_onionOpacityFld, SIGNAL(valueChanged(bool)), this, + SLOT(onOnionOpacitySliderChanged(bool))); + ret = ret && connect(m_captureButton, SIGNAL(clicked(bool)), this, + SLOT(onCaptureButtonClicked(bool))); + // ret = ret && connect(subfolderButton, SIGNAL(clicked(bool)), this, + // SLOT(openSaveInFolderPopup())); + ret = ret && connect(m_saveInFileFld, SIGNAL(pathChanged()), this, + SLOT(onSaveInPathEdited())); + ret = ret && connect(m_fileTypeCombo, SIGNAL(activated(int)), this, + SLOT(onFileTypeActivated())); + ret = ret && connect(m_frameNumberEdit, SIGNAL(editingFinished()), this, + SLOT(onFrameNumberChanged())); + ret = ret && connect(m_xSheetFrameNumberEdit, SIGNAL(editingFinished()), this, + SLOT(onXSheetFrameNumberChanged())); + ret = ret && connect(m_toggleLiveViewButton, SIGNAL(clicked()), this, + SLOT(onLiveViewToggleClicked())); + ret = ret && connect(m_stopMotion, SIGNAL(filePathChanged(QString)), this, + SLOT(onFilePathChanged(QString))); + ret = ret && connect(m_stopMotion, SIGNAL(levelNameChanged(QString)), this, + SLOT(onLevelNameChanged(QString))); + ret = ret && connect(m_stopMotion, SIGNAL(fileTypeChanged(QString)), this, + SLOT(onFileTypeChanged(QString))); + ret = ret && connect(m_stopMotion, SIGNAL(frameInfoTextChanged(QString)), + this, SLOT(onFrameInfoTextChanged(QString))); + ret = ret && connect(m_stopMotion, SIGNAL(xSheetFrameNumberChanged(int)), + this, SLOT(onXSheetFrameNumberChanged(int))); + ret = ret && connect(m_stopMotion, SIGNAL(frameNumberChanged(int)), this, + SLOT(onFrameNumberChanged(int))); + ret = ret && connect(m_stopMotion, SIGNAL(opacityChanged(int)), this, + SLOT(onOpacityChanged(int))); + + // Options Page + ret = ret && connect(m_useScaledFullSizeImages, SIGNAL(stateChanged(int)), + this, SLOT(onScaleFullSizeImagesChanged(int))); + ret = ret && connect(m_liveViewOnAllFramesCB, SIGNAL(stateChanged(int)), this, + SLOT(onLiveViewOnAllFramesChanged(int))); + ret = ret && connect(m_blackScreenForCapture, SIGNAL(stateChanged(int)), this, + SLOT(onBlackScreenForCaptureChanged(int))); + ret = ret && connect(m_placeOnXSheetCB, SIGNAL(stateChanged(int)), this, + SLOT(onPlaceOnXSheetChanged(int))); + ret = ret && connect(m_directShowCB, SIGNAL(stateChanged(int)), this, + SLOT(onUseDirectShowChanged(int))); + ret = ret && connect(m_useMjpgCB, SIGNAL(stateChanged(int)), this, + SLOT(onUseMjpgChanged(int))); + ret = ret && connect(m_useNumpadCB, SIGNAL(stateChanged(int)), this, + SLOT(onUseNumpadChanged(int))); + ret = ret && connect(m_postCaptureReviewFld, SIGNAL(valueEditedByHand()), + this, SLOT(onCaptureReviewFldEdited())); + ret = ret && connect(m_postCaptureReviewFld, SIGNAL(valueChanged(bool)), this, + SLOT(onCaptureReviewSliderChanged(bool))); + ret = ret && connect(m_subsamplingFld, SIGNAL(valueEditedByHand()), this, + SLOT(onSubsamplingFldEdited())); + ret = ret && connect(m_subsamplingFld, SIGNAL(valueChanged(bool)), this, + SLOT(onSubsamplingSliderChanged(bool))); + ret = ret && connect(m_stopMotion, SIGNAL(subsamplingChanged(int)), this, + SLOT(onSubsamplingChanged(int))); + ret = ret && connect(m_stopMotion, SIGNAL(scaleFullSizeImagesSignal(bool)), + this, SLOT(onScaleFullSizeImagesSignal(bool))); + ret = ret && connect(m_stopMotion, SIGNAL(blackCaptureSignal(bool)), this, + SLOT(onBlackCaptureSignal(bool))); + ret = ret && connect(m_stopMotion, SIGNAL(liveViewOnAllFramesSignal(bool)), + this, SLOT(onLiveViewOnAllFramesSignal(bool))); + ret = ret && connect(m_stopMotion, SIGNAL(placeOnXSheetSignal(bool)), this, + SLOT(onPlaceOnXSheetSignal(bool))); + ret = ret && connect(m_stopMotion, SIGNAL(useDirectShowSignal(bool)), this, + SLOT(onUseDirectShowSignal(bool))); + ret = ret && connect(m_stopMotion, SIGNAL(useMjpgSignal(bool)), this, + SLOT(onUseMjpgSignal(bool))); + ret = ret && connect(m_stopMotion, SIGNAL(useNumpadSignal(bool)), this, + SLOT(onUseNumpadSignal(bool))); + ret = ret && connect(m_stopMotion, SIGNAL(reviewTimeChangedSignal(int)), this, + SLOT(onReviewTimeChangedSignal(int))); + + // From Stop Motion Main + ret = ret && connect(m_stopMotion, SIGNAL(newDimensions()), this, + SLOT(updateDimensions())); + ret = ret && connect(m_stopMotion, SIGNAL(updateCameraList()), this, + SLOT(refreshCameraList())); + ret = ret && connect(m_stopMotion, SIGNAL(liveViewChanged(bool)), this, + SLOT(onLiveViewChanged(bool))); + ret = ret && connect(m_stopMotion, SIGNAL(newCameraSelected(int, bool)), this, + SLOT(onNewCameraSelected(int, bool))); + ret = ret && connect(m_stopMotion, SIGNAL(cameraChanged()), this, + SLOT(refreshCameraList())); + ret = ret && connect(m_stopMotion, SIGNAL(optionsChanged()), this, + SLOT(refreshOptionsLists())); + + // EOS Connections + ret = ret && + connect(m_zoomButton, SIGNAL(pressed()), this, SLOT(onZoomPressed())); + ret = ret && connect(m_pickZoomButton, SIGNAL(pressed()), this, + SLOT(onPickZoomPressed())); + ret = ret && connect(m_focusNearButton, SIGNAL(pressed()), this, + SLOT(onFocusNear())); + ret = ret && + connect(m_focusFarButton, SIGNAL(pressed()), this, SLOT(onFocusFar())); + ret = ret && connect(m_focusNear2Button, SIGNAL(pressed()), this, + SLOT(onFocusNear2())); + ret = ret && connect(m_focusFar2Button, SIGNAL(pressed()), this, + SLOT(onFocusFar2())); + ret = ret && connect(m_focusNear3Button, SIGNAL(pressed()), this, + SLOT(onFocusNear3())); + ret = ret && connect(m_focusFar3Button, SIGNAL(pressed()), this, + SLOT(onFocusFar3())); + ret = ret && connect(m_stopMotion, SIGNAL(apertureChangedSignal(QString)), + this, SLOT(onApertureChangedSignal(QString))); + ret = ret && connect(m_stopMotion, SIGNAL(isoChangedSignal(QString)), this, + SLOT(onIsoChangedSignal(QString))); + ret = ret && connect(m_stopMotion, SIGNAL(shutterSpeedChangedSignal(QString)), + this, SLOT(onShutterSpeedChangedSignal(QString))); + ret = ret && connect(m_stopMotion, SIGNAL(exposureChangedSignal(QString)), + this, SLOT(onExposureChangedSignal(QString))); + ret = ret && connect(m_stopMotion, SIGNAL(whiteBalanceChangedSignal(QString)), + this, SLOT(onWhiteBalanceChangedSignal(QString))); + ret = ret && connect(m_stopMotion, SIGNAL(imageQualityChangedSignal(QString)), + this, SLOT(onImageQualityChangedSignal(QString))); + ret = ret && connect(m_stopMotion, SIGNAL(pictureStyleChangedSignal(QString)), + this, SLOT(onPictureStyleChangedSignal(QString))); + ret = ret && + connect(m_stopMotion, SIGNAL(colorTemperatureChangedSignal(QString)), + this, SLOT(onColorTemperatureChangedSignal(QString))); + ret = ret && connect(m_apertureCombo, SIGNAL(currentIndexChanged(int)), this, + SLOT(onApertureChanged(int))); + ret = ret && connect(m_shutterSpeedCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(onShutterSpeedChanged(int))); + ret = ret && connect(m_isoCombo, SIGNAL(currentIndexChanged(int)), this, + SLOT(onIsoChanged(int))); + ret = ret && connect(m_exposureCombo, SIGNAL(currentIndexChanged(int)), this, + SLOT(onExposureChanged(int))); + ret = ret && connect(m_whiteBalanceCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(onWhiteBalanceChanged(int))); + ret = ret && connect(m_kelvinCombo, SIGNAL(currentIndexChanged(int)), this, + SLOT(onColorTemperatureChanged(int))); + ret = ret && connect(m_imageQualityCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(onImageQualityChanged(int))); + ret = ret && connect(m_pictureStyleCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(onPictureStyleChanged(int))); + ret = ret && connect(m_stopMotion, SIGNAL(apertureOptionsChanged()), this, + SLOT(refreshApertureList())); + ret = ret && connect(m_stopMotion, SIGNAL(shutterSpeedOptionsChanged()), this, + SLOT(refreshShutterSpeedList())); + ret = ret && connect(m_stopMotion, SIGNAL(isoOptionsChanged()), this, + SLOT(refreshIsoList())); + ret = ret && connect(m_stopMotion, SIGNAL(exposureOptionsChanged()), this, + SLOT(refreshExposureList())); + ret = ret && connect(m_stopMotion, SIGNAL(whiteBalanceOptionsChanged()), this, + SLOT(refreshWhiteBalanceList())); + ret = ret && connect(m_stopMotion, SIGNAL(imageQualityOptionsChanged()), this, + SLOT(refreshImageQualityList())); + ret = ret && connect(m_stopMotion, SIGNAL(pictureStyleOptionsChanged()), this, + SLOT(refreshPictureStyleList())); + ret = ret && + connect(m_stopMotion, SIGNAL(modeChanged()), this, SLOT(refreshMode())); + + // Webcam Specific Connections + ret = ret && connect(m_stopMotion, SIGNAL(webcamResolutionsChanged()), this, + SLOT(onWebcamResolutionsChanged())); + ret = ret && connect(m_stopMotion, SIGNAL(newWebcamResolutionSelected(int)), + this, SLOT(onNewWebcamResolutionSelected(int))); + + assert(ret); + + m_placeOnXSheetCB->setChecked( + m_stopMotion->getPlaceOnXSheet() == true ? true : false); + m_useScaledFullSizeImages->setChecked(m_stopMotion->m_useScaledImages); + m_onionOpacityFld->setValue(double(100 * m_stopMotion->getOpacity()) / 255.0); + m_directShowCB->setChecked(m_stopMotion->getUseDirectShow()); + m_useMjpgCB->setChecked(m_stopMotion->getUseMjpg()); + m_useNumpadCB->setChecked(m_stopMotion->getUseNumpadShortcuts()); + m_liveViewOnAllFramesCB->setChecked(m_stopMotion->getAlwaysLiveView()); + m_blackScreenForCapture->setChecked( + m_stopMotion->getBlackCapture() == true ? true : false); + m_postCaptureReviewFld->setValue(m_stopMotion->getReviewTime()); + + refreshCameraList(); + onSceneSwitched(); + m_stopMotion->setToNextNewLevel(); + m_saveInFileFld->setPath(m_stopMotion->getFilePath()); +} + +//----------------------------------------------------------------------------- + +StopMotionController::~StopMotionController() {} + +//----------------------------------------------------------------------------- + +void StopMotionController::setPage(int index) { + if (m_stopMotion->m_usingWebcam && index > 0) index += 1; + m_stackedChooser->setCurrentIndex(index); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onScaleFullSizeImagesChanged(int checked) { + m_stopMotion->setUseScaledImages(checked > 0 ? true : false); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onScaleFullSizeImagesSignal(bool on) { + m_useScaledFullSizeImages->setChecked(on); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onLiveViewOnAllFramesChanged(int checked) { + m_stopMotion->setAlwaysLiveView(checked > 0 ? true : false); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onLiveViewOnAllFramesSignal(bool on) { + m_liveViewOnAllFramesCB->setChecked(on); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onBlackScreenForCaptureChanged(int checked) { + m_stopMotion->setBlackCapture(checked); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onBlackCaptureSignal(bool on) { + m_blackScreenForCapture->setChecked(on); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onPlaceOnXSheetChanged(int checked) { + m_stopMotion->setPlaceOnXSheet(checked); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onPlaceOnXSheetSignal(bool on) { + m_placeOnXSheetCB->setChecked(on); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onUseDirectShowChanged(int checked) { + m_stopMotion->setUseDirectShow(checked); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onUseDirectShowSignal(bool on) { + m_directShowCB->setChecked(on); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onUseMjpgChanged(int checked) { + m_stopMotion->setUseMjpg(checked); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onUseMjpgSignal(bool on) { + m_useMjpgCB->setChecked(on); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onUseNumpadChanged(int checked) { + m_stopMotion->setUseNumpadShortcuts(checked); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onUseNumpadSignal(bool on) { + m_useNumpadCB->setChecked(on); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onCaptureReviewFldEdited() { + m_stopMotion->setReviewTime(m_postCaptureReviewFld->getValue()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onCaptureReviewSliderChanged(bool ignore) { + m_stopMotion->setReviewTime(m_postCaptureReviewFld->getValue()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onReviewTimeChangedSignal(int time) { + m_postCaptureReviewFld->setValue(time); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onSubsamplingChanged(int subsampling) { + if (subsampling < 1) { + m_subsamplingFld->setValue(1); + m_subsamplingFld->setDisabled(true); + } else { + m_subsamplingFld->setValue(subsampling); + m_subsamplingFld->setEnabled(true); + } +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onFrameNumberChanged(int frameNumber) { + m_frameNumberEdit->setValue(frameNumber); + m_previousFrameButton->setDisabled(frameNumber == 1); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onXSheetFrameNumberChanged(int frameNumber) { + m_xSheetFrameNumberEdit->setValue(frameNumber); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onFilePathChanged(QString filePath) { + m_saveInFileFld->setPath(filePath); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onLevelNameChanged(QString levelName) { + m_levelNameEdit->setText(levelName); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onFileTypeChanged(QString fileType) { + m_fileTypeCombo->setCurrentText(fileType); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onFrameInfoTextChanged(QString infoText) { + m_frameInfoLabel->setText(infoText); + m_frameInfoLabel->setStyleSheet(QString("QLabel{color: %1;}\ + QLabel QWidget{ color: black;}") + .arg(m_stopMotion->getInfoColorName())); + m_frameInfoLabel->setToolTip(m_stopMotion->getFrameInfoToolTip()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onSubsamplingFldEdited() { + m_stopMotion->setSubsamplingValue(m_subsamplingFld->getValue()); + m_stopMotion->setSubsampling(); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onSubsamplingSliderChanged(bool ignore) { + m_stopMotion->setSubsamplingValue(m_subsamplingFld->getValue()); + m_stopMotion->setSubsampling(); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::refreshCameraListCalled() { + m_stopMotion->refreshCameraList(); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::refreshCameraList() { + m_cameraListCombo->clear(); + + QList webcams = m_stopMotion->getWebcams(); + + int count = m_stopMotion->getCameraCount() + webcams.count(); + if (count < 1) { + m_cameraListCombo->addItem(tr("No camera detected.")); + m_cameraSettingsLabel->setText(tr("No camera detected")); + m_cameraModeLabel->setText(""); + m_cameraListCombo->setDisabled(true); + m_captureButton->setDisabled(true); + m_toggleLiveViewButton->setDisabled(true); + m_toggleLiveViewButton->setText("Start Live View"); + } else { + int maxTextLength = 0; + m_cameraListCombo->addItem(tr("- Select camera -")); + if (webcams.count() > 0) { + for (int c = 0; c < webcams.size(); c++) { + std::string name = webcams.at(c).deviceName().toStdString(); + QString camDesc = webcams.at(c).description(); + m_cameraListCombo->addItem(camDesc); + maxTextLength = std::max(maxTextLength, fontMetrics().width(camDesc)); + } + } + if (m_stopMotion->getCameraCount() > 0) { + QString name; + m_stopMotion->getCamera(0); + m_stopMotion->openCameraSession(); + name = QString::fromStdString(m_stopMotion->getCameraName()); + m_stopMotion->closeCameraSession(); + m_cameraSettingsLabel->setText(name); + m_cameraListCombo->addItem(name); + maxTextLength = std::max(maxTextLength, fontMetrics().width(name)); + } + m_cameraListCombo->setMaximumWidth(maxTextLength + 25); + m_cameraListCombo->setEnabled(true); + m_cameraListCombo->setCurrentIndex(0); + m_captureButton->setEnabled(true); + m_toggleLiveViewButton->setEnabled(true); + } + m_stopMotion->updateLevelNameAndFrame(m_levelNameEdit->text().toStdWString()); + refreshOptionsLists(); + refreshMode(); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::refreshOptionsLists() { + m_apertureCombo->blockSignals(true); + m_isoCombo->blockSignals(true); + m_shutterSpeedCombo->blockSignals(true); + m_exposureCombo->blockSignals(true); + m_whiteBalanceCombo->blockSignals(true); + m_kelvinCombo->blockSignals(true); + m_imageQualityCombo->blockSignals(true); + m_pictureStyleCombo->blockSignals(true); + + m_isoCombo->clear(); + m_shutterSpeedCombo->clear(); + m_apertureCombo->clear(); + m_exposureCombo->clear(); + + if (m_stopMotion->getCameraCount() == 0) { + m_resolutionCombo->setDisabled(true); + m_shutterSpeedCombo->setDisabled(true); + m_isoCombo->setDisabled(true); + m_apertureCombo->setDisabled(true); + m_exposureCombo->setDisabled(true); + m_whiteBalanceCombo->setDisabled(true); + m_kelvinCombo->setDisabled(true); + m_imageQualityCombo->setDisabled(true); + m_pictureStyleCombo->setDisabled(true); + return; + } + + refreshApertureList(); + refreshShutterSpeedList(); + refreshIsoList(); + refreshExposureList(); + refreshWhiteBalanceList(); + refreshImageQualityList(); + refreshPictureStyleList(); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::refreshMode() { + if (m_stopMotion->getCameraCount() == 0) { + m_cameraModeLabel->setText(""); + return; + } + QString mode = m_stopMotion->getMode(); + m_cameraModeLabel->setText(tr("Mode: ") + mode); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::refreshApertureList() { + m_apertureCombo->blockSignals(true); + m_apertureCombo->clear(); + m_stopMotion->getAvailableApertures(); + m_apertureCombo->addItems(m_stopMotion->getApertureOptions()); + + if (m_apertureCombo->count() == 0) { + m_apertureCombo->addItem(tr("Auto")); + m_apertureCombo->setDisabled(true); + } else { + m_apertureCombo->setEnabled(true); + m_apertureCombo->setCurrentText(m_stopMotion->getCurrentAperture()); + } + m_apertureCombo->blockSignals(false); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::refreshShutterSpeedList() { + m_shutterSpeedCombo->blockSignals(true); + m_shutterSpeedCombo->clear(); + m_stopMotion->getAvailableShutterSpeeds(); + m_shutterSpeedCombo->addItems(m_stopMotion->getShutterSpeedOptions()); + + if (m_shutterSpeedCombo->count() == 0) { + m_shutterSpeedCombo->addItem(tr("Auto")); + m_shutterSpeedCombo->setDisabled(true); + } else { + m_shutterSpeedCombo->setEnabled(true); + m_shutterSpeedCombo->setCurrentText(m_stopMotion->getCurrentShutterSpeed()); + } + m_shutterSpeedCombo->blockSignals(false); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::refreshIsoList() { + m_isoCombo->blockSignals(true); + m_isoCombo->clear(); + m_stopMotion->getAvailableIso(); + m_isoCombo->addItems(m_stopMotion->getIsoOptions()); + + if (m_isoCombo->count() == 0) { + m_isoCombo->addItem(tr("Auto")); + m_isoCombo->setDisabled(true); + } else { + m_isoCombo->setEnabled(true); + std::string currIso = m_stopMotion->getCurrentIso().toStdString(); + m_isoCombo->setCurrentText(m_stopMotion->getCurrentIso()); + } + m_isoCombo->blockSignals(false); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::refreshExposureList() { + m_exposureCombo->blockSignals(true); + m_exposureCombo->clear(); + m_stopMotion->getAvailableExposureCompensations(); + m_exposureCombo->addItems(m_stopMotion->getExposureOptions()); + + if (m_exposureCombo->count() == 0) { + m_exposureCombo->addItem(tr("Disabled")); + m_exposureCombo->setDisabled(true); + } else { + m_exposureCombo->setEnabled(true); + m_exposureCombo->setCurrentText( + m_stopMotion->getCurrentExposureCompensation()); + } + m_exposureCombo->blockSignals(false); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::refreshWhiteBalanceList() { + m_whiteBalanceCombo->blockSignals(true); + m_whiteBalanceCombo->clear(); + m_stopMotion->getAvailableWhiteBalances(); + m_whiteBalanceCombo->addItems(m_stopMotion->getWhiteBalanceOptions()); + + if (m_whiteBalanceCombo->count() == 0) { + m_whiteBalanceCombo->addItem(tr("Disabled")); + m_whiteBalanceCombo->setDisabled(true); + } else { + m_whiteBalanceCombo->setEnabled(true); + m_whiteBalanceCombo->setCurrentText(m_stopMotion->getCurrentWhiteBalance()); + } + m_whiteBalanceCombo->blockSignals(false); + refreshColorTemperatureList(); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::refreshColorTemperatureList() { + m_kelvinCombo->blockSignals(true); + m_kelvinCombo->clear(); + m_kelvinCombo->addItems(m_stopMotion->getColorTemperatureOptions()); + std::string ct = m_stopMotion->getCurrentWhiteBalance().toStdString(); + int kCount = m_kelvinCombo->count(); + if (m_kelvinCombo->count() == 0 || + m_stopMotion->getCurrentWhiteBalance() != "Color Temperature") { + // m_kelvinCombo->addItem(tr("Disabled")); + m_kelvinCombo->setDisabled(true); + m_kelvinCombo->hide(); + m_kelvinLabel->hide(); + } else { + m_kelvinCombo->show(); + m_kelvinLabel->show(); + m_kelvinCombo->setEnabled(true); + m_kelvinCombo->setCurrentText(m_stopMotion->getCurrentColorTemperature()); + } + m_kelvinCombo->blockSignals(false); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::refreshImageQualityList() { + m_imageQualityCombo->blockSignals(true); + m_imageQualityCombo->clear(); + m_stopMotion->getAvailableImageQualities(); + m_imageQualityCombo->addItems(m_stopMotion->getImageQualityOptions()); + + if (m_imageQualityCombo->count() == 0) { + m_imageQualityCombo->addItem(tr("Disabled")); + m_imageQualityCombo->setDisabled(true); + } else { + m_imageQualityCombo->setEnabled(true); + m_imageQualityCombo->setCurrentText(m_stopMotion->getCurrentImageQuality()); + } + m_imageQualityCombo->blockSignals(false); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::refreshPictureStyleList() { + m_pictureStyleCombo->blockSignals(true); + m_pictureStyleCombo->clear(); + m_stopMotion->getAvailablePictureStyles(); + m_pictureStyleCombo->addItems(m_stopMotion->getPictureStyleOptions()); + + if (m_pictureStyleCombo->count() == 0) { + m_pictureStyleCombo->addItem(tr("Disabled")); + m_pictureStyleCombo->setDisabled(true); + } else { + m_pictureStyleCombo->setEnabled(true); + m_pictureStyleCombo->setCurrentText(m_stopMotion->getCurrentPictureStyle()); + } + m_pictureStyleCombo->blockSignals(false); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onCameraListComboActivated(int comboIndex) { + QList cameras = QCameraInfo::availableCameras(); + if (cameras.size() + m_stopMotion->getCameraCount() != + m_cameraListCombo->count() - 1) + return; + + m_stopMotion->changeCameras(comboIndex); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onNewCameraSelected(int index, bool useWebcam) { + if (index < m_cameraListCombo->count()) + m_cameraListCombo->setCurrentIndex(index); + if (index == 0) { + m_cameraListCombo->setCurrentIndex(index); + m_resolutionCombo->hide(); + m_resolutionLabel->hide(); + } + if (useWebcam) { + if (m_tabBar->tabText(1) == "Settings") { + m_tabBar->removeTab(1); + } + m_resolutionCombo->show(); + m_resolutionCombo->setEnabled(true); + m_resolutionLabel->show(); + m_captureFilterSettingsBtn->show(); + } else { + m_resolutionCombo->hide(); + m_resolutionLabel->hide(); + m_captureFilterSettingsBtn->hide(); + if (m_tabBar->tabText(1) == "Options") { + m_tabBar->insertTab(1, "Settings"); + } + } +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onWebcamResolutionsChanged() { + m_resolutionCombo->clear(); + QList resolutions = m_stopMotion->getWebcamResolutions(); + for (int s = 0; s < resolutions.size(); s++) { + m_resolutionCombo->addItem(QString("%1 x %2") + .arg(resolutions.at(s).width()) + .arg(resolutions.at(s).height())); + } +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onNewWebcamResolutionSelected(int index) { + m_resolutionCombo->setCurrentIndex(index); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onResolutionComboActivated(const QString &itemText) { + m_stopMotion->setWebcamResolution(itemText); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onCaptureFilterSettingsBtnPressed() { + if (!m_stopMotion->getWebcam() || m_stopMotion->m_webcamDeviceName.isNull()) + return; + + QList cameras = QCameraInfo::availableCameras(); + for (int c = 0; c < cameras.size(); c++) { + if (cameras.at(c).deviceName() == m_stopMotion->m_webcamDeviceName) { +#ifdef _WIN32 + openCaptureFilterSettings(this, cameras.at(c).description()); +#endif + return; + } + } +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onFileFormatOptionButtonPressed() { + if (m_fileTypeCombo->currentIndex() == 0) return; + // Tentatively use the preview output settings + ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); + if (!scene) return; + TOutputProperties *prop = scene->getProperties()->getPreviewProperties(); + std::string ext = m_fileTypeCombo->currentText().toStdString(); + openFormatSettingsPopup(this, ext, prop->getFileFormatProperties(ext)); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onLevelNameEdited() { + m_stopMotion->updateLevelNameAndFrame(m_levelNameEdit->text().toStdWString()); +} + +//----------------------------------------------------------------------------- +void StopMotionController::onNextName() { m_stopMotion->nextName(); } + +//----------------------------------------------------------------------------- + +void StopMotionController::onNextNewLevel() { + m_stopMotion->setToNextNewLevel(); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onPreviousName() { m_stopMotion->previousName(); } + +//----------------------------------------------------------------------------- + +void StopMotionController::onNextFrame() { m_stopMotion->nextFrame(); } + +//----------------------------------------------------------------------------- + +void StopMotionController::onLastFrame() {} + +//----------------------------------------------------------------------------- + +void StopMotionController::onPreviousFrame() { m_stopMotion->previousFrame(); } + +//----------------------------------------------------------------------------- + +void StopMotionController::onNextXSheetFrame() { + m_stopMotion->setXSheetFrameNumber(m_stopMotion->getXSheetFrameNumber() + 1); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onPreviousXSheetFrame() { + m_stopMotion->setXSheetFrameNumber(m_stopMotion->getXSheetFrameNumber() - 1); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::setToCurrentXSheetFrame() { + int frameNumber = TApp::instance()->getCurrentFrame()->getFrame() + 1; + m_stopMotion->setXSheetFrameNumber(frameNumber); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::updateDimensions() { + m_stopMotion->refreshFrameInfo(); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onFrameCaptured(QImage &image) {} + +//----------------------------------------------------------------------------- + +void StopMotionController::onApertureChanged(int index) { + m_stopMotion->setAperture(m_apertureCombo->currentText()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onApertureChangedSignal(QString text) { + m_apertureCombo->setCurrentText(m_stopMotion->getCurrentAperture()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onShutterSpeedChanged(int index) { + m_stopMotion->setShutterSpeed(m_shutterSpeedCombo->currentText()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onShutterSpeedChangedSignal(QString text) { + m_shutterSpeedCombo->setCurrentText(m_stopMotion->getCurrentShutterSpeed()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onIsoChanged(int index) { + m_stopMotion->setIso(m_isoCombo->currentText()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onIsoChangedSignal(QString text) { + m_isoCombo->setCurrentText(m_stopMotion->getCurrentIso()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onExposureChanged(int index) { + m_stopMotion->setExposureCompensation(m_exposureCombo->currentText()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onExposureChangedSignal(QString text) { + m_exposureCombo->setCurrentText( + m_stopMotion->getCurrentExposureCompensation()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onWhiteBalanceChanged(int index) { + m_stopMotion->setWhiteBalance(m_whiteBalanceCombo->currentText()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onWhiteBalanceChangedSignal(QString text) { + m_whiteBalanceCombo->setCurrentText(m_stopMotion->getCurrentWhiteBalance()); + refreshColorTemperatureList(); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onColorTemperatureChanged(int index) { + m_stopMotion->setColorTemperature(m_kelvinCombo->currentText()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onColorTemperatureChangedSignal(QString text) { + m_kelvinCombo->setCurrentText(m_stopMotion->getCurrentColorTemperature()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onImageQualityChanged(int index) { + m_stopMotion->setImageQuality(m_imageQualityCombo->currentText()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onImageQualityChangedSignal(QString text) { + m_imageQualityCombo->setCurrentText(m_stopMotion->getCurrentImageQuality()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onPictureStyleChanged(int index) { + m_stopMotion->setPictureStyle(m_pictureStyleCombo->currentText()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onPictureStyleChangedSignal(QString text) { + m_pictureStyleCombo->setCurrentText(m_stopMotion->getCurrentPictureStyle()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onZoomPressed() { m_stopMotion->zoomLiveView(); } + +//----------------------------------------------------------------------------- + +void StopMotionController::onPickZoomPressed() { + m_stopMotion->m_pickLiveViewZoom = true; +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onFocusNear() { m_stopMotion->focusNear(); } + +//----------------------------------------------------------------------------- + +void StopMotionController::onFocusFar() { m_stopMotion->focusFar(); } + +//----------------------------------------------------------------------------- + +void StopMotionController::onFocusNear2() { m_stopMotion->focusNear2(); } + +//----------------------------------------------------------------------------- + +void StopMotionController::onFocusFar2() { m_stopMotion->focusFar2(); } + +//----------------------------------------------------------------------------- + +void StopMotionController::onFocusNear3() { m_stopMotion->focusNear3(); } + +//----------------------------------------------------------------------------- + +void StopMotionController::onFocusFar3() { m_stopMotion->focusFar3(); } + +//----------------------------------------------------------------------------- + +void StopMotionController::showEvent(QShowEvent *event) {} + +//----------------------------------------------------------------------------- + +void StopMotionController::hideEvent(QHideEvent *event) { + // disconnect(m_apertureCombo, SIGNAL(currentIndexChanged(int)), this, + // SLOT(onApertureChanged(int))); + // disconnect(m_shutterSpeedCombo, SIGNAL(currentIndexChanged(int)), this, + // SLOT(onShutterSpeedChanged(int))); + // disconnect(m_isoCombo, SIGNAL(currentIndexChanged(int)), this, + // SLOT(onIsoChanged(int))); + // disconnect(m_exposureCombo, SIGNAL(currentIndexChanged(int)), this, + // SLOT(onExposureChanged(int))); + + // disconnect(m_stopMotion, SIGNAL(cameraChanged()), this, + // SLOT(refreshCameraList())); + // disconnect(m_stopMotion, SIGNAL(optionsChanged()), this, + // SLOT(refreshOptionsLists())); + // disconnect(m_stopMotion, SIGNAL(apertureOptionsChanged()), this, + // SLOT(refreshApertureList())); + // disconnect(m_stopMotion, SIGNAL(shutterSpeedOptionsChanged()), this, + // SLOT(refreshShutterSpeedList())); + // disconnect(m_stopMotion, SIGNAL(isoOptionsChanged()), this, + // SLOT(refreshIsoList())); + // disconnect(m_stopMotion, SIGNAL(exposureOptionsChanged()), this, + // SLOT(refreshExposureList())); + // disconnect(m_stopMotion, SIGNAL(modeChanged()), this, SLOT(refreshMode())); +} + +////----------------------------------------------------------------------------- +// +// void StopMotionController::keyPressEvent(QKeyEvent *event) { +// // override return (or enter) key as shortcut key for capturing +// if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) { +// // show button-clicking animation followed by calling +// // onCaptureButtonClicked() +// m_captureButton->animateClick(); +// event->accept(); +// } else +// event->ignore(); +//} +// +////----------------------------------------------------------------------------- +// +// void StopMotionController::mousePressEvent(QMouseEvent *event) {} + +//----------------------------------------------------------------------------- + +void StopMotionController::onLiveViewToggleClicked() { + m_stopMotion->toggleLiveView(); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onLiveViewChanged(bool on) { + if (on) { + m_toggleLiveViewButton->setText(tr("Stop Live View")); + + } else + m_toggleLiveViewButton->setText(tr("Start Live View")); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onOnionOpacityFldEdited() { + int value = (int)(255.0f * (float)m_onionOpacityFld->getValue() / 100.0f); + m_stopMotion->setOpacity(value); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onOnionOpacitySliderChanged(bool ignore) { + int value = (int)(255.0f * (float)m_onionOpacityFld->getValue() / 100.0f); + m_stopMotion->setOpacity(value); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onOpacityChanged(int opacity) { + m_onionOpacityFld->setValue(double(100 * opacity) / 255.0); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onCaptureButtonClicked(bool on) { + m_stopMotion->captureImage(); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::openSaveInFolderPopup() { + if (m_saveInFolderPopup->exec()) { + QString oldPath = m_saveInFileFld->getPath(); + m_saveInFileFld->setPath(m_saveInFolderPopup->getPath()); + if (oldPath == m_saveInFileFld->getPath()) + m_stopMotion->setToNextNewLevel(); + else { + onSaveInPathEdited(); + } + } +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onFileTypeActivated() { + m_stopMotion->setFileType(m_fileTypeCombo->currentText()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onFrameNumberChanged() { + m_stopMotion->setFrameNumber(m_frameNumberEdit->getValue()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onXSheetFrameNumberChanged() { + m_stopMotion->setXSheetFrameNumber(m_xSheetFrameNumberEdit->getValue()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onSaveInPathEdited() { + m_stopMotion->setFilePath(m_saveInFileFld->getPath()); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::onSceneSwitched() { + // m_saveInFolderPopup->updateParentFolder(); + // m_saveInFileFld->setPath(m_saveInFolderPopup->getParentPath()); + // m_stopMotion->refreshFrameInfo(); +} + +//----------------------------------------------------------------------------- + +void StopMotionController::updateStopMotion() {} diff --git a/toonz/sources/stopmotion/stopmotioncontroller.h b/toonz/sources/stopmotion/stopmotioncontroller.h new file mode 100644 index 0000000..2f66707 --- /dev/null +++ b/toonz/sources/stopmotion/stopmotioncontroller.h @@ -0,0 +1,206 @@ +#pragma once + +#ifndef STOPMOTIONCONTROLLER_H +#define STOPMOTIONCONTROLLER_H + +// TnzCore includes +#include "stopmotion.h" +#include "penciltestpopup.h" + +// TnzQt includes +#include "toonzqt/tabbar.h" +#include "toonzqt/gutil.h" + +// Qt includes +#include +#include +#include +#include +#include +#include + +#undef DVAPI +#undef DVVAR +#ifdef TOONZQT_EXPORTS +#define DVAPI DV_EXPORT_API +#define DVVAR DV_EXPORT_VAR +#else +#define DVAPI DV_IMPORT_API +#define DVVAR DV_IMPORT_VAR +#endif + +//============================================= + +// Forward declarations + +class TColorStyle; +class TPalette; + +class TXshLevelHandle; + +class QGridLayout; +class QLabel; +class QStackedWidget; +class QSlider; +class QRadioButton; +class QButtonGroup; +class QPushButton; +class QTabWidget; +class QToolBar; +class QTimer; + +//============================================================================= +// StopMotionController +//----------------------------------------------------------------------------- + +class StopMotionController final : public QWidget { + Q_OBJECT + StopMotion *m_stopMotion; + + QWidget *m_parent; + TXshLevelHandle + *m_levelHandle; //!< for clearing the level cache when the color changed + + DVGui::TabBar *m_tabBar; + QFrame *m_mainControlsPage; + QFrame *m_cameraSettingsPage; + QFrame *m_optionsPage; + QStackedWidget *m_stackedChooser; + TabBarContainter *m_tabBarContainer; //!< Tabs container for style types. + QPushButton *m_toggleLiveViewButton, *m_setToCurrentXSheetFrameButton; + QPushButton *m_fileFormatOptionButton, *m_captureButton, *m_zoomButton, + *m_pickZoomButton, *m_focusNearButton, *m_focusFarButton, + *m_focusNear2Button, *m_focusNear3Button, *m_focusFar2Button, + *m_focusFar3Button, *m_captureFilterSettingsBtn; + QHBoxLayout *m_focusAndZoomLayout; + QLabel *m_frameInfoLabel, *m_cameraSettingsLabel, *m_cameraModeLabel, + *m_kelvinLabel, *m_resolutionLabel, *m_directShowLabel; + QToolButton *m_previousLevelButton, *m_previousFrameButton, + *m_previousXSheetFrameButton; + + QComboBox *m_cameraListCombo, *m_fileTypeCombo, *m_isoCombo, + *m_shutterSpeedCombo, *m_exposureCombo, *m_apertureCombo, + *m_whiteBalanceCombo, *m_kelvinCombo, *m_resolutionCombo, + *m_imageQualityCombo, *m_pictureStyleCombo; + LevelNameLineEdit *m_levelNameEdit; + QCheckBox *m_blackScreenForCapture, *m_useScaledFullSizeImages, + *m_placeOnXSheetCB, *m_directShowCB, *m_liveViewOnAllFramesCB, + *m_useMjpgCB, *m_useNumpadCB; + DVGui::FileField *m_saveInFileFld; + DVGui::IntLineEdit *m_xSheetFrameNumberEdit; + FrameNumberLineEdit *m_frameNumberEdit; + DVGui::IntField *m_onionOpacityFld, *m_postCaptureReviewFld, + *m_subsamplingFld; + PencilTestSaveInFolderPopup *m_saveInFolderPopup; + +public: + StopMotionController(QWidget *parent = 0); + ~StopMotionController(); + +protected: + void updateStopMotion(); + void showEvent(QShowEvent *event); + void hideEvent(QHideEvent *event); + // void mousePressEvent(QMouseEvent *event) override; + // void keyPressEvent(QKeyEvent *event); + +protected slots: + void refreshCameraList(); + void refreshCameraListCalled(); + void refreshOptionsLists(); + void refreshApertureList(); + void refreshShutterSpeedList(); + void refreshIsoList(); + void refreshExposureList(); + void refreshWhiteBalanceList(); + void refreshColorTemperatureList(); + void refreshImageQualityList(); + void refreshPictureStyleList(); + void onCameraListComboActivated(int index); + void onResolutionComboActivated(const QString &itemText); + void onCaptureFilterSettingsBtnPressed(); + void onFileFormatOptionButtonPressed(); + void onLevelNameEdited(); + void onNextName(); + void onPreviousName(); + void onNextFrame(); + void onPreviousFrame(); + void onNextNewLevel(); + void onLastFrame(); + void onFileTypeActivated(); + void onFrameNumberChanged(); + void onXSheetFrameNumberChanged(); + void onFrameCaptured(QImage &image); + void onOnionOpacityFldEdited(); + void onOnionOpacitySliderChanged(bool ignore); + void onLiveViewToggleClicked(); + void onCaptureButtonClicked(bool); + void setPage(int); + void onScaleFullSizeImagesChanged(int checked); + void onBlackScreenForCaptureChanged(int checked); + void onPlaceOnXSheetChanged(int checked); + void onUseMjpgChanged(int checked); + void onUseDirectShowChanged(int checked); + void onLiveViewOnAllFramesChanged(int checked); + void onUseNumpadChanged(int checked); + void updateDimensions(); + void onSaveInPathEdited(); + void onSceneSwitched(); + void onPreviousXSheetFrame(); + void onNextXSheetFrame(); + void setToCurrentXSheetFrame(); + void onApertureChanged(int index); + void onShutterSpeedChanged(int index); + void onIsoChanged(int index); + void onExposureChanged(int index); + void onWhiteBalanceChanged(int index); + void onColorTemperatureChanged(int index); + void onImageQualityChanged(int index); + void onPictureStyleChanged(int index); + void refreshMode(); + void onZoomPressed(); + void onPickZoomPressed(); + void onFocusNear(); + void onFocusFar(); + void onFocusNear2(); + void onFocusFar2(); + void onFocusNear3(); + void onFocusFar3(); + void onCaptureReviewFldEdited(); + void onCaptureReviewSliderChanged(bool ignore); + void onSubsamplingFldEdited(); + void onSubsamplingSliderChanged(bool ignore); + void onSubsamplingChanged(int); + void onFilePathChanged(QString); + void onLevelNameChanged(QString); + void onFileTypeChanged(QString); + void onXSheetFrameNumberChanged(int); + void onFrameNumberChanged(int); + void onFrameInfoTextChanged(QString); + void onOpacityChanged(int opacity); + void onScaleFullSizeImagesSignal(bool); + void onBlackCaptureSignal(bool); + void onLiveViewOnAllFramesSignal(bool); + void onPlaceOnXSheetSignal(bool); + void onUseMjpgSignal(bool); + void onUseDirectShowSignal(bool); + void onReviewTimeChangedSignal(int); + void onUseNumpadSignal(bool); + void onLiveViewChanged(bool); + void onNewCameraSelected(int, bool); + void onWebcamResolutionsChanged(); + void onNewWebcamResolutionSelected(int); + void onApertureChangedSignal(QString); + void onIsoChangedSignal(QString); + void onShutterSpeedChangedSignal(QString); + void onExposureChangedSignal(QString); + void onWhiteBalanceChangedSignal(QString); + void onColorTemperatureChangedSignal(QString); + void onImageQualityChangedSignal(QString); + void onPictureStyleChangedSignal(QString); + +public slots: + void openSaveInFolderPopup(); +}; + +#endif // STOPMOTIONCONTROLLER_H diff --git a/toonz/sources/toonz/CMakeLists.txt b/toonz/sources/toonz/CMakeLists.txt index 4ea4287..c7bad2b 100644 --- a/toonz/sources/toonz/CMakeLists.txt +++ b/toonz/sources/toonz/CMakeLists.txt @@ -122,6 +122,14 @@ set(MOC_HEADERS xshtoolbar.h ) +if(WITH_STOPMOTION) +set(MOC_HEADERS + ${MOC_HEADERS} + ../stopmotion/stopmotion.h + ../stopmotion/stopmotioncontroller.h +) +endif() + set(HEADERS ${MOC_HEADERS} celldata.h @@ -346,6 +354,14 @@ set(SOURCES predict3d.cpp ) +if(WITH_STOPMOTION) +set(SOURCES + ${SOURCES} + ../stopmotion/stopmotion.cpp + ../stopmotion/stopmotioncontroller.cpp +) +endif() + add_translation(toonz ${HEADERS} ${SOURCES}) set(OBJCSOURCES filebrowsermodel.cpp) @@ -400,6 +416,11 @@ include_directories( ../../sources/toonzqt ) +if (WITH_STOPMOTION) +include_directories(../../sources/stopmotion) + add_definitions(-DWITH_STOPMOTION) +endif() + if(BUILD_ENV_APPLE) include_directories(../../sources/mousedragfilter) endif() @@ -415,7 +436,15 @@ if(BUILD_TARGET_WIN) endif() endif() -if(BUILD_ENV_MSVC) +if(BUILD_ENV_MSVC AND WITH_STOPMOTION) + target_link_libraries(OpenToonz + Qt5::WinMain Qt5::Core Qt5::Gui Qt5::Network Qt5::OpenGL Qt5::Svg Qt5::Xml + Qt5::Script Qt5::Widgets Qt5::PrintSupport Qt5::Multimedia + ${GL_LIB} ${GLUT_LIB} + ${CANON_LIB} ${TURBOJPEG_LIB} ${OPENCV_LIB} strmiids + tnzcore tnzbase toonzlib colorfx tnzext image sound toonzqt tnztools tnzstdfx tfarm + ) +elseif(BUILD_ENV_MSVC) target_link_libraries(OpenToonz Qt5::WinMain Qt5::Core Qt5::Gui Qt5::Network Qt5::OpenGL Qt5::Svg Qt5::Xml Qt5::Script Qt5::Widgets Qt5::PrintSupport Qt5::Multimedia diff --git a/toonz/sources/toonz/mainwindow.cpp b/toonz/sources/toonz/mainwindow.cpp index 1f8ee89..f2756bf 100644 --- a/toonz/sources/toonz/mainwindow.cpp +++ b/toonz/sources/toonz/mainwindow.cpp @@ -1972,6 +1972,11 @@ void MainWindow::defineActions() { createMenuWindowsAction(MI_OpenToolbar, tr("&Toolbar"), ""); createMenuWindowsAction(MI_OpenToolOptionBar, tr("&Tool Option Bar"), ""); createMenuWindowsAction(MI_OpenCommandToolbar, tr("&Command Bar"), ""); +#ifdef WITH_STOPMOTION + createMenuWindowsAction(MI_OpenStopMotionPanel, tr("&Stop Motion Controls"), + ""); + +#endif createMenuWindowsAction(MI_OpenLevelView, tr("&Viewer"), ""); #ifdef LINETEST createMenuWindowsAction(MI_OpenLineTestCapture, tr("&LineTest Capture"), ""); @@ -2291,6 +2296,20 @@ void MainWindow::defineActions() { ToolCommandType); createMiscAction("A_FxSchematicToggle", tr("Toggle FX/Stage schematic"), ""); +#ifdef WITH_STOPMOTION + createAction(MI_StopMotionCapture, tr("Capture Stop Motion Frame"), "Enter"); + createAction(MI_StopMotionRaiseOpacity, tr("Raise Stop Motion Opacity"), ""); + createAction(MI_StopMotionLowerOpacity, tr("Lower Stop Motion Opacity"), ""); + createAction(MI_StopMotionToggleLiveView, tr("Toggle Stop Motion Live View"), + ""); + createAction(MI_StopMotionToggleZoom, tr("Toggle Stop Motion Zoom"), ""); + createAction(MI_StopMotionLowerSubsampling, + tr("Lower Stop Motion Level Subsampling"), ""); + createAction(MI_StopMotionRaiseSubsampling, + tr("Raise Stop Motion Level Subsampling"), ""); + createAction(MI_StopMotionJumpToCamera, tr("Go to Stop Motion Insert Frame"), + ""); +#endif } //----------------------------------------------------------------------------- diff --git a/toonz/sources/toonz/menubar.cpp b/toonz/sources/toonz/menubar.cpp index 6594948..65a38f4 100644 --- a/toonz/sources/toonz/menubar.cpp +++ b/toonz/sources/toonz/menubar.cpp @@ -1423,6 +1423,9 @@ QMenuBar *StackedMenuBar::createFullMenuBar() { addMenuItem(windowsMenu, MI_OpenTMessage); addMenuItem(windowsMenu, MI_OpenHistoryPanel); addMenuItem(windowsMenu, MI_AudioRecording); +#ifdef WITH_STOPMOTION + addMenuItem(windowsMenu, MI_OpenStopMotionPanel); +#endif addMenuItem(windowsMenu, MI_StartupPopup); #ifdef LINETEST windowsMenu->addSeparator(); diff --git a/toonz/sources/toonz/menubarcommandids.h b/toonz/sources/toonz/menubarcommandids.h index 489a2f9..382250b 100644 --- a/toonz/sources/toonz/menubarcommandids.h +++ b/toonz/sources/toonz/menubarcommandids.h @@ -95,6 +95,7 @@ #define MI_OpenCommandToolbar "MI_OpenCommandToolbar" #define MI_OpenToolOptionBar "MI_OpenToolOptionBar" #define MI_OpenLevelView "MI_OpenLevelView" +#define MI_OpenStopMotionPanel "MI_OpenStopMotionPanel" #ifdef LINETEST #define MI_OpenExport "MI_OpenExport" #define MI_OpenLineTestView "MI_OpenLineTestView" @@ -351,6 +352,15 @@ #define MI_TouchGestureControl "MI_TouchGestureControl" #define MI_SeparateColors "MI_SeparateColors" +#define MI_StopMotionCapture "MI_StopMotionCapture" +#define MI_StopMotionRaiseOpacity "MI_StopMotionRaiseOpacity" +#define MI_StopMotionLowerOpacity "MI_StopMotionLowerOpacity" +#define MI_StopMotionToggleLiveView "MI_StopMotionToggleLiveView" +#define MI_StopMotionToggleZoom "MI_StopMotionToggleZoom" +#define MI_StopMotionLowerSubsampling "MI_StopMotionLowerSubsampling" +#define MI_StopMotionRaiseSubsampling "MI_StopMotionRaiseSubsampling" +#define MI_StopMotionJumpToCamera "MI_StopMotionJumpToCamera" + #define MI_OpenOnlineManual "MI_OpenOnlineManual" #define MI_ClearCacheFolder "MI_ClearCacheFolder" #endif diff --git a/toonz/sources/toonz/sceneviewer.cpp b/toonz/sources/toonz/sceneviewer.cpp index 2a545c0..d01d002 100644 --- a/toonz/sources/toonz/sceneviewer.cpp +++ b/toonz/sources/toonz/sceneviewer.cpp @@ -11,6 +11,7 @@ #include "menubarcommandids.h" #include "ruler.h" #include "locatorpopup.h" +#include "../stopmotion/stopmotion.h" // TnzTools includes #include "tools/cursors.h" @@ -577,6 +578,9 @@ SceneViewer::SceneViewer(ImageUtils::FullScreenWidget *parent) , m_isBusyOnTabletMove(false) { m_visualSettings.m_sceneProperties = TApp::instance()->getCurrentScene()->getScene()->getProperties(); +#ifdef WITH_STOPMOTION + m_stopMotion = StopMotion::instance(); +#endif // Enables multiple key input. setAttribute(Qt::WA_KeyCompression); // Enables input methods for Asian languages. @@ -847,6 +851,13 @@ void SceneViewer::showEvent(QShowEvent *) { connect(app, SIGNAL(tabletLeft()), this, SLOT(resetTabletStatus())); + if (m_stopMotion) { + connect(m_stopMotion, SIGNAL(newLiveViewImageReady()), this, + SLOT(onNewStopMotionImageReady())); + connect(m_stopMotion, SIGNAL(liveViewStopped()), this, + SLOT(onStopMotionLiveViewStopped())); + } + if (m_hRuler && m_vRuler) { if (!viewRulerToggle.getStatus()) { m_hRuler->hide(); @@ -901,6 +912,14 @@ void SceneViewer::hideEvent(QHideEvent *) { if (toolHandle) toolHandle->disconnect(this); disconnect(app, SIGNAL(tabletLeft()), this, SLOT(resetTabletStatus())); + + if (!m_stopMotion == NULL) { + disconnect(m_stopMotion, SIGNAL(newImageReady()), this, + SLOT(onNewStopMotionImageReady())); + disconnect(m_stopMotion, SIGNAL(liveViewStopped()), this, + SLOT(onStopMotionLiveViewStopped())); + } + // hide locator if (m_locator && m_locator->isVisible()) m_locator->hide(); } @@ -923,6 +942,41 @@ double SceneViewer::getHGuide(int index) { return m_hRuler->getGuide(index); } //----------------------------------------------------------------------------- +void SceneViewer::onNewStopMotionImageReady() { +#ifdef WITH_STOPMOTION + if (m_stopMotion->m_hasLineUpImage) { + // if (m_hasStopMotionLineUpImage) delete m_stopMotionLineUpImage; + // is there a way to do this without cloning the image twice? + // TRasterImageP image = m_stopMotion->m_lineUpImage->clone(); + m_stopMotionLineUpImage = + (TRasterImageP)m_stopMotion->m_lineUpImage->clone(); + // m_stopMotionLineUpImage = (TRasterImage *)image->cloneImage(); + m_stopMotionLineUpImage->setDpi(m_stopMotion->m_liveViewDpi.x, + m_stopMotion->m_liveViewDpi.y); + m_hasStopMotionLineUpImage = true; + } + if (m_stopMotion->m_hasLiveViewImage) { + // if (m_hasStopMotionImage) delete m_stopMotionImage; + // is there a way to do this without cloning the image twice? + // TRasterImageP image = m_stopMotion->m_liveViewImage->clone(); + m_stopMotionImage = m_stopMotion->m_liveViewImage->clone(); + // m_stopMotionImage = (TRasterImage *)image->cloneImage(); + m_stopMotionImage->setDpi(m_stopMotion->m_liveViewDpi.x, + m_stopMotion->m_liveViewDpi.y); + m_hasStopMotionImage = true; + if (m_stopMotion->m_pickLiveViewZoom) { + setToolCursor(this, ToolCursor::ZoomCursor); + } + onSceneChanged(); + } +#endif +} + +//----------------------------------------------------------------------------- + +void SceneViewer::onStopMotionLiveViewStopped() { onSceneChanged(); } + +//----------------------------------------------------------------------------- void SceneViewer::initializeGL() { initializeOpenGLFunctions(); @@ -1700,6 +1754,29 @@ void SceneViewer::drawScene() { Stage::visit(painter, args); } +#ifdef WITH_STOPMOTION + if (!frameHandle->isPlaying() && m_stopMotion->m_liveViewStatus == 2) { + if (m_hasStopMotionLineUpImage && m_stopMotion->m_showLineUpImage) { + Stage::Player smPlayer; + double dpiX, dpiY; + m_stopMotionLineUpImage->getDpi(dpiX, dpiY); + smPlayer.m_dpiAff = TScale(Stage::inch / dpiX, Stage::inch / dpiY); + smPlayer.m_opacity = 255; + painter.onRasterImage(m_stopMotionLineUpImage.getPointer(), smPlayer); + } + if (m_hasStopMotionImage) { + Stage::Player smPlayer; + double dpiX, dpiY; + m_stopMotionImage->getDpi(dpiX, dpiY); + smPlayer.m_dpiAff = TScale(Stage::inch / dpiX, Stage::inch / dpiY); + bool hide_opacity = + m_stopMotion->m_zooming || m_stopMotion->m_pickLiveViewZoom; + smPlayer.m_opacity = hide_opacity ? 255.0 : m_stopMotion->getOpacity(); + painter.onRasterImage(m_stopMotionImage.getPointer(), smPlayer); + } + } +#endif + assert(glGetError() == 0); painter.flushRasterImages(); diff --git a/toonz/sources/toonz/sceneviewer.h b/toonz/sources/toonz/sceneviewer.h index f8974bd..7d5eeca 100644 --- a/toonz/sources/toonz/sceneviewer.h +++ b/toonz/sources/toonz/sceneviewer.h @@ -38,6 +38,7 @@ class QGestureEvent; class QTouchEvent; class QOpenGLFramebufferObject; class LutCalibrator; +class StopMotion; namespace ImageUtils { class FullScreenWidget; @@ -144,6 +145,10 @@ class SceneViewer final : public GLWidgetForHighDpi, TRaster32P m_3DSideL; TRaster32P m_3DSideR; TRaster32P m_3DTop; + TRasterImageP m_stopMotionImage, m_stopMotionLineUpImage; + StopMotion *m_stopMotion = NULL; + bool m_hasStopMotionImage = false; + bool m_hasStopMotionLineUpImage = false; TPointD m_sideRasterPos; TPointD m_topRasterPos; @@ -438,6 +443,9 @@ public slots: void releaseBusyOnTabletMove() { m_isBusyOnTabletMove = false; } void onContextAboutToBeDestroyed(); + void onNewStopMotionImageReady(); + void onStopMotionLiveViewStopped(); + signals: void onZoomChanged(); diff --git a/toonz/sources/toonz/sceneviewerevents.cpp b/toonz/sources/toonz/sceneviewerevents.cpp index f8af69c..61e9442 100644 --- a/toonz/sources/toonz/sceneviewerevents.cpp +++ b/toonz/sources/toonz/sceneviewerevents.cpp @@ -17,6 +17,10 @@ #include "locatorpopup.h" #include "cellselection.h" +#ifdef WITH_STOPMOTION +#include "stopmotion.h" +#endif + // TnzQt includes #include "toonzqt/tselectionhandle.h" #include "toonzqt/styleselection.h" @@ -580,6 +584,11 @@ void SceneViewer::onMove(const TMouseEvent &event) { tool->mouseMove(pos, event); } if (!cursorSet) setToolCursor(this, tool->getCursorId()); + +#ifdef WITH_STOPMOTION + if (StopMotion::instance()->m_pickLiveViewZoom) + setToolCursor(this, ToolCursor::ZoomCursor); +#endif m_pos = curPos; m_tabletMove = false; m_toolSwitched = false; @@ -721,6 +730,17 @@ void SceneViewer::onPress(const TMouseEvent &event) { pos.x /= m_dpiScale.x; pos.y /= m_dpiScale.y; } + +#ifdef WITH_STOPMOTION + // grab screen picking for stop motion live view zoom + if (StopMotion::instance()->m_pickLiveViewZoom) { + StopMotion::instance()->m_pickLiveViewZoom = false; + StopMotion::instance()->makeZoomPoint(pos); + if (tool) setToolCursor(this, tool->getCursorId()); + if (m_mouseButton != Qt::RightButton) return; + } +#endif + // separate tablet and mouse events if (m_tabletEvent && m_tabletState == Touched) { TApp::instance()->getCurrentTool()->setToolBusy(true); diff --git a/toonz/sources/toonz/tpanels.cpp b/toonz/sources/toonz/tpanels.cpp index f800f34..36627cd 100644 --- a/toonz/sources/toonz/tpanels.cpp +++ b/toonz/sources/toonz/tpanels.cpp @@ -24,6 +24,10 @@ #include "historypane.h" #include "cleanupsettingspane.h" +#ifdef WITH_STOPMOTION +#include "stopmotioncontroller.h" +#endif + #ifdef LINETEST #include "linetestpane.h" #include "linetestcapturepane.h" @@ -1361,6 +1365,34 @@ OpenFloatingPanel openHistoryPanelCommand(MI_OpenHistoryPanel, "HistoryPanel", QObject::tr("History")); //============================================================================= +#ifdef WITH_STOPMOTION +//============================================================================= +// StopMotion Controller +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- + +class StopMotionPanelFactory final : public TPanelFactory { +public: + StopMotionPanelFactory() : TPanelFactory("StopMotionController") {} + + void initialize(TPanel *panel) override { + StopMotionController *stopMotionController = + new StopMotionController(panel); + panel->setWidget(stopMotionController); + panel->setWindowTitle(QObject::tr("Stop Motion Controller")); + panel->setIsMaximizable(false); + } +} stopMotionPanelFactory; + +//============================================================================= +OpenFloatingPanel openStopMotionPanelCommand( + MI_OpenStopMotionPanel, "StopMotionController", + QObject::tr("Stop Motion Controller")); +//----------------------------------------------------------------------------- + +#endif + //============================================================================= // FxSettings //----------------------------------------------------------------------------- diff --git a/toonz/sources/toonz/tpanels.h b/toonz/sources/toonz/tpanels.h index 60e59cd..8b0aba6 100644 --- a/toonz/sources/toonz/tpanels.h +++ b/toonz/sources/toonz/tpanels.h @@ -17,6 +17,7 @@ class PaletteViewer; class TPaletteHandle; class StyleEditor; +class StopMotionController; class TLevel; class StudioPaletteViewer; class TPanelTitleBarButton; diff --git a/toonz/sources/toonz/xshrowviewer.cpp b/toonz/sources/toonz/xshrowviewer.cpp index 092fb57..2a2d546 100644 --- a/toonz/sources/toonz/xshrowviewer.cpp +++ b/toonz/sources/toonz/xshrowviewer.cpp @@ -12,6 +12,7 @@ #include "cellselection.h" #include "menubarcommandids.h" #include "toonzqt/menubarcommand.h" +#include "../stopmotion/stopmotion.h" #include "toonz/toonzscene.h" #include "tconvert.h" @@ -370,8 +371,26 @@ void RowArea::drawCurrentRowGadget(QPainter &p, int r0, int r1) { p.fillRect(header, m_viewer->getCurrentRowBgColor()); } +#ifdef WITH_STOPMOTION //----------------------------------------------------------------------------- +void RowArea::drawStopMotionCameraIndicator(QPainter &p) { + int cameraRow = StopMotion::instance()->getXSheetFrameNumber() - 1; + if (cameraRow < 0) return; + + QPoint topLeft = m_viewer->positionToXY(CellPosition(cameraRow, 0)); + if (!m_viewer->orientation()->isVerticalTimeline()) topLeft.setY(0); + QRect header = m_viewer->orientation() + ->rect(PredefinedRect::FRAME_HEADER) + .translated(topLeft); + int frameAdj = m_viewer->getFrameZoomAdjustment(); + header.adjust(1, 1, -frameAdj, 0); + p.fillRect(header, Qt::GlobalColor::darkGreen); +} + +//----------------------------------------------------------------------------- +#endif + void RowArea::drawOnionSkinBackground(QPainter &p, int r0, int r1) { const Orientation *o = m_viewer->orientation(); @@ -830,6 +849,15 @@ void RowArea::paintEvent(QPaintEvent *event) { // current frame drawCurrentRowGadget(p, r0, r1); +#ifdef WITH_STOPMOTION + StopMotion *stopMotion = StopMotion::instance(); + if (stopMotion->getPlaceOnXSheet() && + (stopMotion->m_liveViewStatus > 0)) { + drawStopMotionCameraIndicator(p); + } + +#endif + if (TApp::instance()->getCurrentFrame()->isEditingScene() && Preferences::instance()->isCurrentTimelineIndicatorEnabled() && !m_viewer->orientation()->isVerticalTimeline()) diff --git a/toonz/sources/toonz/xshrowviewer.h b/toonz/sources/toonz/xshrowviewer.h index cb8e8e8..3bf9763 100644 --- a/toonz/sources/toonz/xshrowviewer.h +++ b/toonz/sources/toonz/xshrowviewer.h @@ -55,6 +55,10 @@ class RowArea final : public QWidget { void drawCurrentTimeLine(QPainter &p); void drawShiftTraceMarker(QPainter &p); +#ifdef WITH_STOPMOTION + void drawStopMotionCameraIndicator(QPainter &p); +#endif + DragTool *getDragTool() const; void setDragTool(DragTool *dragTool); diff --git a/toonz/sources/toonzlib/levelproperties.cpp b/toonz/sources/toonzlib/levelproperties.cpp index ebde85c..3ec1db9 100644 --- a/toonz/sources/toonzlib/levelproperties.cpp +++ b/toonz/sources/toonzlib/levelproperties.cpp @@ -15,7 +15,8 @@ LevelOptions::LevelOptions() , m_antialias(0) , m_dpiPolicy(DP_ImageDpi) , m_whiteTransp(false) - , m_premultiply(false) {} + , m_premultiply(false) + , m_isStopMotionLevel(false) {} //----------------------------------------------------------------------------- @@ -24,6 +25,7 @@ bool LevelOptions::operator==(const LevelOptions &other) const { m_whiteTransp == other.m_whiteTransp && m_dpiPolicy == other.m_dpiPolicy && m_antialias == other.m_antialias && + m_isStopMotionLevel == other.m_isStopMotionLevel && (m_dpiPolicy == LevelOptions::DP_ImageDpi || m_dpi == other.m_dpi)); } diff --git a/toonz/sources/toonzlib/stagevisitor.cpp b/toonz/sources/toonzlib/stagevisitor.cpp index e62ff4b..5018bc0 100644 --- a/toonz/sources/toonzlib/stagevisitor.cpp +++ b/toonz/sources/toonzlib/stagevisitor.cpp @@ -467,6 +467,14 @@ void RasterPainter::flushRasterImages() { int lx = rect.getLx(), ly = rect.getLy(); TDimension dim(lx, ly); + // this is needed since a stop motion live view + // doesn't register as a node correctly + // there is probably a better way to do this. + if (rect.getLx() == 0 && lx == 0) { + rect = m_clipRect; + dim = m_dim; + } + // Build a raster buffer of sufficient size to hold said union. // The buffer is per-thread cached in order to improve the rendering speed. if (!threadBuffers.hasLocalData()) diff --git a/toonz/sources/toonzlib/txshsimplelevel.cpp b/toonz/sources/toonzlib/txshsimplelevel.cpp index 96596f9..e48b4fe 100644 --- a/toonz/sources/toonzlib/txshsimplelevel.cpp +++ b/toonz/sources/toonzlib/txshsimplelevel.cpp @@ -907,6 +907,7 @@ void TXshSimpleLevel::loadData(TIStream &is) { int doPremultiply = 0; int whiteTransp = 0; int antialiasSoftness = 0; + int isStopMotionLevel = 0; LevelProperties::DpiPolicy dpiPolicy = LevelProperties::DP_ImageDpi; if (is.getTagParam("dpix", v)) xdpi = std::stod(v); if (is.getTagParam("dpiy", v)) ydpi = std::stod(v); @@ -918,6 +919,9 @@ void TXshSimpleLevel::loadData(TIStream &is) { if (is.getTagParam("premultiply", v)) doPremultiply = std::stoi(v); if (is.getTagParam("antialias", v)) antialiasSoftness = std::stoi(v); if (is.getTagParam("whiteTransp", v)) whiteTransp = std::stoi(v); + if (is.getTagParam("isStopMotionLevel", v)) + isStopMotionLevel = std::stoi(v); + m_properties->setDpiPolicy(dpiPolicy); m_properties->setDpi(TPointD(xdpi, ydpi)); @@ -925,6 +929,8 @@ void TXshSimpleLevel::loadData(TIStream &is) { m_properties->setDoPremultiply(doPremultiply); m_properties->setDoAntialias(antialiasSoftness); m_properties->setWhiteTransp(whiteTransp); + m_properties->setIsStopMotion(isStopMotionLevel); + if (isStopMotionLevel == 1) setIsReadOnly(true); } else throw TException("unexpected tag " + tagName); } else { @@ -1366,6 +1372,9 @@ void TXshSimpleLevel::saveData(TOStream &os) { attr["premultiply"] = std::to_string(getProperties()->doPremultiply()); } else if (getProperties()->whiteTransp()) { attr["whiteTransp"] = std::to_string(getProperties()->whiteTransp()); + } else if (getProperties()->isStopMotionLevel()) { + attr["isStopMotionLevel"] = + std::to_string(getProperties()->isStopMotionLevel()); } if (m_type == TZI_XSHLEVEL) attr["type"] = "s"; @@ -2318,6 +2327,7 @@ bool TXshSimpleLevel::isFrameReadOnly(TFrameId fid) { // the OS level if (getType() == OVL_XSHLEVEL || getType() == TZI_XSHLEVEL || getType() == MESH_XSHLEVEL) { + if (getProperties()->isStopMotionLevel()) return true; TFilePath fullPath = getScene()->decodeFilePath(m_path); std::string fileType = fullPath.getType(); if (fileType == "psd" || fileType == "gif" || fileType == "mp4" ||