Files
oak-editor/app/widget/viewer/viewer.h
T
itsmattkc 53ae25a7cb nodes: optimize node graph changes by only updating from inputs that changed
A huge optimization that ensures only the parts of a node graph that have
changed get pushed to the renderer. For thread-safety, the node graph is
copied elsewhere so that users can make changes asynchronously and the graph
can update when its threads are ready. Up until now, if an input value changed,
every node's values would be re-copied, or worse, if a connection was changed,
the entire graph would be recopied. This has been negligible in testing since
we've been largely testing with small graphs, but for massive projects, it's
important that this be as optimized as possible.
2020-04-26 04:16:15 +10:00

257 lines
6.0 KiB
C++

/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef VIEWER_WIDGET_H
#define VIEWER_WIDGET_H
#include <QFile>
#include <QLabel>
#include <QPushButton>
#include <QScrollBar>
#include <QTimer>
#include <QWidget>
#include "audiowaveformview.h"
#include "common/rational.h"
#include "node/output/viewer/viewer.h"
#include "panel/scope/scope.h"
#include "render/backend/opengl/openglbackend.h"
#include "render/backend/opengl/opengltexture.h"
#include "render/backend/audio/audiobackend.h"
#include "viewerdisplay.h"
#include "viewersizer.h"
#include "viewerwindow.h"
#include "widget/playbackcontrols/playbackcontrols.h"
#include "widget/timebased/timebased.h"
OLIVE_NAMESPACE_ENTER
/**
* @brief An OpenGL-based viewer widget with playback controls (a PlaybackControls widget).
*/
class ViewerWidget : public TimeBasedWidget
{
Q_OBJECT
public:
ViewerWidget(QWidget* parent = nullptr);
void SetPlaybackControlsEnabled(bool enabled);
void SetTimeRulerEnabled(bool enabled);
void TogglePlayPause();
bool IsPlaying() const;
void ConnectViewerNode(ViewerOutput* node, ColorManager *color_manager = nullptr);
/**
* @brief Enable or disable the color management menu
*
* While the Viewer is _always_ color managed, In some contexts, the color management may be controlled from an
* external UI making the menu unnecessary.
*/
void SetColorMenuEnabled(bool enabled);
void SetOverrideSize(int width, int height);
void SetMatrix(const QMatrix4x4& mat);
/**
* @brief Creates a ViewerWindow widget and places it full screen on another screen
*
* If `screen` is nullptr, the screen will be automatically selected as whichever one contains the mouse cursor.
*/
void SetFullScreen(QScreen* screen = nullptr);
void ForceUpdate();
VideoRenderBackend* video_renderer() const;
ColorManager* color_manager() const;
public slots:
void Play(bool in_to_out_only);
void Play();
void Pause();
void ShuttleLeft();
void ShuttleStop();
void ShuttleRight();
void SetColorTransform(const ColorTransform& transform);
/**
* @brief Wrapper for ViewerGLWidget::SetSignalCursorColorEnabled()
*/
void SetSignalCursorColorEnabled(bool e);
/**
* @brief Wrapper for ViewerGLWidget::SetEmitDrewManagedTextureEnabled()
*/
void SetEmitDrewManagedTextureEnabled(bool e);
signals:
/**
* @brief Wrapper for ViewerGLWidget::CursorColor()
*/
void CursorColor(const Color& reference, const Color& display);
/**
* @brief Wrapper for ViewerGLWidget::LoadedBuffer()
*/
void LoadedBuffer(Frame* load_buffer);
/**
* @brief Wrapper for ViewerGLWidget::LoadedTexture()
*/
void LoadedTexture(OpenGLTexture* texture);
/**
* @brief Wrapper for ViewerGLWidget::DrewManagedTexture()
*/
void DrewManagedTexture(OpenGLTexture* texture);
/**
* @brief Request a scope panel
*
* As a widget, we don't handle panels, but a parent panel may pick this signal up.
*/
void RequestScopePanel(ScopePanel::Type type);
/**
* @brief Wrapper for ViewerGLWidget::ColorProcessorChanged()
*/
void ColorProcessorChanged(ColorProcessorPtr processor);
/**
* @brief Wrapper for ViewerGLWidget::ColorManagerChanged()
*/
void ColorManagerChanged(ColorManager* color_manager);
protected:
virtual void TimebaseChangedEvent(const rational &) override;
virtual void TimeChangedEvent(const int64_t &) override;
virtual void ConnectNodeInternal(ViewerOutput *) override;
virtual void DisconnectNodeInternal(ViewerOutput *) override;
virtual void ConnectedNodeChanged(ViewerOutput*n) override;
virtual void ScaleChangedEvent(const double& s) override;
virtual void resizeEvent(QResizeEvent *event) override;
OpenGLBackend* video_renderer_;
AudioBackend* audio_renderer_;
PlaybackControls* controls_;
const QList<ViewerDisplayWidget *> &gl_widgets() const;
ViewerDisplayWidget* main_gl_widget() const;
private:
void UpdateTimeInternal(int64_t i);
void UpdateTextureFromNode(const rational &time);
void PlayInternal(int speed, bool in_to_out_only);
void PushScrubbedAudio();
int CalculateDivider();
void UpdateMinimumScale();
void SetColorTransform(const ColorTransform& transform, ViewerDisplayWidget* sender);
QStackedWidget* stack_;
ViewerSizer* sizer_;
qint64 start_msec_;
int64_t start_timestamp_;
int playback_speed_;
qint64 frame_cache_job_time_;
int64_t last_time_;
bool color_menu_enabled_;
int divider_;
ColorManager* override_color_manager_;
bool time_changed_from_timer_;
bool play_in_to_out_only_;
AudioWaveformView* waveform_view_;
QList<ViewerWindow*> windows_;
QList<ViewerDisplayWidget*> gl_widgets_;
ViewerDisplayWidget* context_menu_widget_;
private slots:
void PlaybackTimerUpdate();
void RendererCachedTime(const rational& time, qint64 job_time);
void SizeChangedSlot(int width, int height);
void LengthChangedSlot(const rational& length);
void UpdateRendererParameters();
void ShowContextMenu(const QPoint& pos);
void SetDividerFromMenu(QAction* action);
void SetZoomFromMenu(QAction* action);
void InvalidateVisible(NodeInput *source);
void UpdateStack();
void ContextMenuSetFullScreen(QAction* action);
void ContextMenuDisableSafeMargins();
void ContextMenuSetSafeMargins();
void ContextMenuSetCustomSafeMargins();
void WindowAboutToClose();
void ContextMenuScopeTriggered(QAction* action);
};
OLIVE_NAMESPACE_EXIT
#endif // VIEWER_WIDGET_H