/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. // Description : A dialog for batch-rendering sequences #ifndef CRYINCLUDE_EDITOR_TRACKVIEW_SEQUENCEBATCHRENDERDIALOG_H #define CRYINCLUDE_EDITOR_TRACKVIEW_SEQUENCEBATCHRENDERDIALOG_H #pragma once #include <AzFramework/StringFunc/StringFunc.h> class CMFCButton; #include <QDialog> #include <QTimer> #include <QFutureWatcher> class QStringListModel; namespace Ui { class SequenceBatchRenderDialog; } class CSequenceBatchRenderDialog : public QDialog , public IMovieListener { public: CSequenceBatchRenderDialog(float fps, QWidget* pParent = nullptr); virtual ~CSequenceBatchRenderDialog(); void reject() override; // overriding so Qt doesn't cancel protected: void OnInitDialog(); void OnAddRenderItem(); void OnRemoveRenderItem(); void OnClearRenderItems(); void OnUpdateRenderItem(); void OnLoadPreset(); void OnSavePreset(); void OnGo(); void OnDone(); void OnSequenceSelected(); void OnRenderItemSelChange(); void OnFPSEditChange(); void OnFPSChange(); void OnImageFormatChange(); void OnResolutionSelected(); void OnStartFrameChange(); void OnEndFrameChange(); void OnLoadBatch(); void OnSaveBatch(); void OnBuffersSelected(); void OnKickIdle(); void OnCancelRender(); void SaveOutputOptions(const QString& pathname) const; bool LoadOutputOptions(const QString& pathname); QString m_ffmpegPluginStatusMsg; bool m_bFFMPEGCommandAvailable; float m_fpsForTimeToFrameConversion; // FPS setting in TrackView struct SRenderItem { IAnimSequence* pSequence; IAnimNode* pDirectorNode; Range frameRange; int resW, resH; int fps; ICaptureKey::CaptureFileFormat formatIndex; ICaptureKey::CaptureBufferType bufferIndex; QString folder; QString prefix; QStringList cvars; bool disableDebugInfo; bool bCreateVideo; SRenderItem() : pSequence(NULL) , pDirectorNode(NULL) , disableDebugInfo(false) , bCreateVideo(false) {} bool operator==(const SRenderItem& item) { if (pSequence == item.pSequence && pDirectorNode == item.pDirectorNode && frameRange == item.frameRange && resW == item.resW && resH == item.resH && fps == item.fps && formatIndex == item.formatIndex && bufferIndex == item.bufferIndex && folder == item.folder && prefix == item.prefix && cvars == item.cvars && disableDebugInfo == item.disableDebugInfo && bCreateVideo == item.bCreateVideo) { return true; } else { return false; } } }; std::vector<SRenderItem> m_renderItems; // Capture States enum class CaptureState { Idle, WarmingUpAfterResChange, EnteringGameMode, BeginPlayingSequence, Capturing, End, FFMPEGProcessing, Finalize }; struct SRenderContext { int currentItemIndex; float expectedTotalTime; float spentTime; int flagBU; Range rangeBU; int cvarCustomResWidthBU, cvarCustomResHeightBU; int cvarDisplayInfoBU; int framesSpentInCurrentPhase; IAnimNode* pActiveDirectorBU; ICaptureKey captureOptions; bool processingFFMPEG; // Signals when an mpeg is finished being processed. QFutureWatcher<void> processingFFMPEGWatcher; // True if the user canceled a render. bool canceled; // The sequence that triggered the CaptureState::Ending. IAnimSequence* endingSequence; // Current capture state. CaptureState captureState; bool IsInRendering() const { return currentItemIndex >= 0; } SRenderContext() : currentItemIndex(-1) , expectedTotalTime(0) , spentTime(0) , flagBU(0) , pActiveDirectorBU(NULL) , cvarCustomResWidthBU(0) , cvarCustomResHeightBU(0) , cvarDisplayInfoBU(0) , framesSpentInCurrentPhase(0) , processingFFMPEG(false) , canceled(false) , endingSequence(nullptr) , captureState(CaptureState::Idle) {} }; SRenderContext m_renderContext; // Custom validator to make sure the prefix is a valid part of a filename. class CPrefixValidator : public QValidator { public: CPrefixValidator(QObject* parent) : QValidator(parent) {} QValidator::State validate(QString& input, int& pos) const override { bool valid = input.isEmpty() || AzFramework::StringFunc::Path::IsValid(input.toUtf8().data()); return valid ? QValidator::State::Acceptable : QValidator::State::Invalid; } }; // Custom values from resolution/FPS combo boxes int m_customResW, m_customResH; int m_customFPS; void InitializeContext(); virtual void OnMovieEvent(IMovieListener::EMovieEvent event, IAnimSequence* pSequence); void CaptureItemStart(); // Capture State Updates void OnUpdateWarmingUpAfterResChange(); void OnUpdateEnteringGameMode(); void OnUpdateBeginPlayingSequence(); void OnUpdateCapturing(); void OnUpdateEnd(IAnimSequence* pSequence); void OnUpdateFFMPEGProcessing(); void OnUpdateFinalize(); bool SetUpNewRenderItem(SRenderItem& item); void AddItem(const SRenderItem& item); QString GetCaptureItemString(const SRenderItem& item) const; protected slots: void OnKickIdleTimout(); bool GetResolutionFromCustomResText(const char* customResText, int& retCustomWidth, int& retCustomHeight) const; private: void CheckForEnableUpdateButton(); void stashActiveViewportResolution(); void UpdateSpinnerProgressMessage(const char* description); void EnterCaptureState(CaptureState captureState); void SetEnableEditorIdleProcessing(bool enabled); QScopedPointer<Ui::SequenceBatchRenderDialog> m_ui; QStringListModel* m_renderListModel; QTimer m_renderTimer; bool m_editorIdleProcessingEnabled; int32 CV_TrackViewRenderOutputCapturing; QScopedPointer<CPrefixValidator> m_prefixValidator; }; #endif // CRYINCLUDE_EDITOR_TRACKVIEW_SEQUENCEBATCHRENDERDIALOG_H