diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ba442ede9c..54039c3fea 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5432,8 +5432,8 @@ void Application::toggleLogDialog() { // The frame will take too long to pack, the timer slot will // not execute properly, and the GIF will appear sped-up. // This is unacceptable and is probably a blocker for release. -#define SNAPSNOT_ANIMATED_WIDTH (300) -#define SNAPSNOT_ANIMATED_FRAMERATE_FPS (50) // This value should divide evenly into 100 +#define SNAPSNOT_ANIMATED_WIDTH (400) +#define SNAPSNOT_ANIMATED_FRAMERATE_FPS (25) // This value should divide evenly into 100 #define SNAPSNOT_ANIMATED_DURATION_SECS (3) #define SNAPSNOT_ANIMATED_FRAME_DELAY_MSEC (1000/SNAPSNOT_ANIMATED_FRAMERATE_FPS) @@ -5451,60 +5451,80 @@ void Application::takeSnapshot(bool notify, float aspectRatio) { QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio)); // If we're in the middle of capturing a GIF... - if (_currentAnimatedSnapshotFrame != 0) + if (_animatedSnapshotFirstFrameTimestamp != 0) { // Notify the window scripting interface that we've taken a Snapshot emit DependencyManager::get()->snapshotTaken(path, notify); // Protect against clobbering it and return immediately. // (Perhaps with a "snapshot failed" message? - return; } + else + { + // Reset the current animated snapshot frame + qApp->_animatedSnapshotFirstFrameTimestamp = 0; + // Reset the current animated snapshot frame timestamp + qApp->_animatedSnapshotTimestamp = 0; - // Reset the current animated snapshot frame - _currentAnimatedSnapshotFrame = 0; + // Change the extension of the future GIF saved snapshot file to "gif" + qApp->_animatedSnapshotPath = path.replace("jpg", "gif"); - // Change the extension of the future GIF saved snapshot file to "gif" - _animatedSnapshotPath = path.replace("jpg", "gif"); + // Ensure the snapshot timer is Precise (attempted millisecond precision) + qApp->animatedSnapshotTimer.setTimerType(Qt::PreciseTimer); - // Ensure the snapshot timer is Precise (attempted millisecond precision) - animatedSnapshotTimer.setTimerType(Qt::PreciseTimer); + // Connect the animatedSnapshotTimer QTimer to the lambda slot function + connect(&(qApp->animatedSnapshotTimer), &QTimer::timeout, [=] { + // Get a screenshot from the display, then scale the screenshot down, + // then convert it to the image format the GIF library needs, + // then save all that to the QImage named "frame" + QImage frame(qApp->getActiveDisplayPlugin()->getScreenshot(aspectRatio)); + frame = frame.scaledToWidth(SNAPSNOT_ANIMATED_WIDTH); + frame = frame.convertToFormat(QImage::Format_RGBA8888); - // Connect the animatedSnapshotTimer QTimer to the lambda slot function - connect(&(qApp->animatedSnapshotTimer), &QTimer::timeout, [=] { - // Get a screenshot from the display, then scale the screenshot down, - // then convert it to the image format the GIF library needs, - // then save all that to the QImage named "frame" - QImage frame(qApp->getActiveDisplayPlugin()->getScreenshot(aspectRatio)); - frame = frame.scaledToWidth(SNAPSNOT_ANIMATED_WIDTH).convertToFormat(QImage::Format_RGBA8888); + // If this is the first frame... + if (qApp->_animatedSnapshotTimestamp == 0) + { + // Write out the header and beginning of the GIF file + GifBegin(&(qApp->_animatedSnapshotGifWriter), qPrintable(qApp->_animatedSnapshotPath), frame.width(), frame.height(), SNAPSNOT_ANIMATED_FRAME_DELAY_MSEC / 10); + // Write the first to the gif + GifWriteFrame(&(qApp->_animatedSnapshotGifWriter), + (uint8_t*)frame.bits(), + frame.width(), + frame.height(), + SNAPSNOT_ANIMATED_FRAME_DELAY_MSEC / 10); + // Record the current frame timestamp + qApp->_animatedSnapshotTimestamp = QDateTime::currentMSecsSinceEpoch(); + qApp->_animatedSnapshotFirstFrameTimestamp = qApp->_animatedSnapshotTimestamp; + } + else + { + // Write the frame to the gif + GifWriteFrame(&(qApp->_animatedSnapshotGifWriter), + (uint8_t*)frame.bits(), + frame.width(), + frame.height(), + round(((float)(QDateTime::currentMSecsSinceEpoch() - qApp->_animatedSnapshotTimestamp)) / 10)); + // Record the current frame timestamp + qApp->_animatedSnapshotTimestamp = QDateTime::currentMSecsSinceEpoch(); - // If this is the first frame... - if (qApp->_currentAnimatedSnapshotFrame == 0) - { - // Write out the header and beginning of the GIF file - GifBegin(&(qApp->_animatedSnapshotGifWriter), qPrintable(qApp->_animatedSnapshotPath), frame.width(), frame.height(), SNAPSNOT_ANIMATED_FRAME_DELAY_MSEC / 10, 8, false); - } + // If that was the last frame... + if ((qApp->_animatedSnapshotTimestamp - qApp->_animatedSnapshotFirstFrameTimestamp) >= (SNAPSNOT_ANIMATED_DURATION_SECS * 1000)) + { + // Reset the current frame timestamp + qApp->_animatedSnapshotTimestamp = 0; + qApp->_animatedSnapshotFirstFrameTimestamp = 0; + // Write out the end of the GIF + GifEnd(&(qApp->_animatedSnapshotGifWriter)); + // Notify the Window Scripting Interface that the snapshot was taken + emit DependencyManager::get()->snapshotTaken(qApp->_animatedSnapshotPath, false); + // Stop the snapshot QTimer + qApp->animatedSnapshotTimer.stop(); + } + } + }); - // Write the frame to the gif - GifWriteFrame(&(qApp->_animatedSnapshotGifWriter), (uint8_t*)frame.bits(), frame.width(), frame.height(), SNAPSNOT_ANIMATED_FRAME_DELAY_MSEC/10, 8, false); - // Increment the current snapshot frame count - qApp->_currentAnimatedSnapshotFrame++; - - // If that was the last frame... - if (qApp->_currentAnimatedSnapshotFrame >= SNAPSNOT_ANIMATED_NUM_FRAMES) - { - // Reset the current frame number - qApp->_currentAnimatedSnapshotFrame = 0; - // Write out the end of the GIF - GifEnd(&(qApp->_animatedSnapshotGifWriter)); - // Notify the Window Scripting Interface that the snapshot was taken - emit DependencyManager::get()->snapshotTaken(qApp->_animatedSnapshotPath, false); - // Stop the snapshot QTimer - qApp->animatedSnapshotTimer.stop(); - } - }); - - // Start the animatedSnapshotTimer QTimer - argument for this is in milliseconds - animatedSnapshotTimer.start(SNAPSNOT_ANIMATED_FRAME_DELAY_MSEC); + // Start the animatedSnapshotTimer QTimer - argument for this is in milliseconds + qApp->animatedSnapshotTimer.start(SNAPSNOT_ANIMATED_FRAME_DELAY_MSEC); + } }); } void Application::shareSnapshot(const QString& path) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 963b4c8072..092b2d6c1d 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -613,7 +613,8 @@ private: QTimer animatedSnapshotTimer; GifWriter _animatedSnapshotGifWriter; - uint32_t _currentAnimatedSnapshotFrame { 0 }; + quint64 _animatedSnapshotTimestamp{ 0 }; + quint64 _animatedSnapshotFirstFrameTimestamp{ 0 }; QString _animatedSnapshotPath; };