diff --git a/app/widget/CMakeLists.txt b/app/widget/CMakeLists.txt index 4dce10689..f33f5d064 100644 --- a/app/widget/CMakeLists.txt +++ b/app/widget/CMakeLists.txt @@ -25,6 +25,7 @@ add_subdirectory(flowlayout) add_subdirectory(focusablelineedit) add_subdirectory(footagecombobox) add_subdirectory(keyframeview) +add_subdirectory(manageddisplay) add_subdirectory(menu) add_subdirectory(nodecopypaste) add_subdirectory(nodeview) diff --git a/app/widget/manageddisplay/CMakeLists.txt b/app/widget/manageddisplay/CMakeLists.txt new file mode 100644 index 000000000..0f9204b08 --- /dev/null +++ b/app/widget/manageddisplay/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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 . + +set(OLIVE_SOURCES + ${OLIVE_SOURCES} + widget/manageddisplay/manageddisplay.h + widget/manageddisplay/manageddisplay.cpp + PARENT_SCOPE +) diff --git a/app/widget/manageddisplay/manageddisplay.cpp b/app/widget/manageddisplay/manageddisplay.cpp new file mode 100644 index 000000000..90db1cef6 --- /dev/null +++ b/app/widget/manageddisplay/manageddisplay.cpp @@ -0,0 +1,209 @@ +/*** + + 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 . + +***/ + +#include "manageddisplay.h" + +#include + +OLIVE_NAMESPACE_ENTER + +ManagedDisplayObject::ManagedDisplayObject(QWidget *parent) : + QOpenGLWidget(parent), + color_manager_(nullptr), + color_service_(nullptr) +{ +} + +void ManagedDisplayObject::ConnectColorManager(ColorManager *color_manager) +{ + if (color_manager_ == color_manager) { + return; + } + + if (color_manager_ != nullptr) { + disconnect(color_manager_, &ColorManager::ConfigChanged, this, &ManagedDisplayObject::ColorConfigChanged); + } + + color_manager_ = color_manager; + + if (color_manager_ != nullptr) { + connect(color_manager_, &ColorManager::ConfigChanged, this, &ManagedDisplayObject::ColorConfigChanged); + } + + ColorConfigChanged(); +} + +ColorManager *ManagedDisplayObject::color_manager() const +{ + return color_manager_; +} + +void ManagedDisplayObject::DisconnectColorManager() +{ + ConnectColorManager(nullptr); +} + +const ColorTransform &ManagedDisplayObject::GetColorTransform() const +{ + return color_transform_; +} + +void ManagedDisplayObject::ColorConfigChanged() +{ + if (!color_manager_) { + color_service_ = nullptr; + return; + } + + SetColorTransform(color_manager_->GetCompliantColorSpace(color_transform_, true)); +} + +OpenGLColorProcessorPtr ManagedDisplayObject::color_service() +{ + return color_service_; +} + +void ManagedDisplayObject::ContextCleanup() +{ + makeCurrent(); + + color_service_ = nullptr; + + doneCurrent(); +} + +void ManagedDisplayObject::MenuDisplaySelect(QAction *action) +{ + const ColorTransform& old_transform = GetColorTransform(); + + ColorTransform new_transform = color_manager()->GetCompliantColorSpace(ColorTransform(action->data().toString(), + old_transform.view(), + old_transform.look())); + + SetColorTransform(new_transform); +} + +void ManagedDisplayObject::SetColorTransform(const ColorTransform &transform) +{ + color_transform_ = transform; + SetupColorProcessor(); + update(); +} + +void ManagedDisplayObject::initializeGL() +{ + SetupColorProcessor(); + + connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &ManagedDisplayObject::ContextCleanup, Qt::DirectConnection); +} + +Menu* ManagedDisplayObject::GetDisplayMenu(QMenu* parent, bool auto_connect) +{ + QStringList displays = color_manager()->ListAvailableDisplays(); + + Menu* ocio_display_menu = new Menu(tr("Display"), parent); + + foreach (const QString& d, displays) { + QAction* action = ocio_display_menu->addAction(d); + action->setCheckable(true); + action->setChecked(color_transform_.display() == d); + action->setData(d); + } + + return ocio_display_menu; +} + +Menu* ManagedDisplayObject::GetViewMenu(QMenu* parent) +{ + QStringList views = color_manager()->ListAvailableViews(color_transform_.display()); + + Menu* ocio_view_menu = new Menu(tr("View"), parent); + + foreach (const QString& v, views) { + QAction* action = ocio_view_menu->addAction(v); + action->setCheckable(true); + action->setChecked(color_transform_.view() == v); + action->setData(v); + } + + return ocio_view_menu; +} + +Menu* ManagedDisplayObject::GetLookMenu(QMenu* parent, bool auto_connect) +{ + QStringList looks = color_manager()->ListAvailableLooks(); + + Menu* ocio_look_menu = new Menu(tr("Look"), parent); + + // Setup "no look" action + QAction* no_look_action = ocio_look_menu->addAction(tr("(None)")); + no_look_action->setCheckable(true); + no_look_action->setChecked(color_transform_.look().isEmpty()); + no_look_action->setData(QString()); + + // Set up the rest of the looks + foreach (const QString& l, looks) { + QAction* action = ocio_look_menu->addAction(l); + action->setCheckable(true); + action->setChecked(color_transform_.look() == l); + action->setData(l); + } + + return ocio_look_menu; +} + +void ManagedDisplayObject::SetupColorProcessor() +{ + if (!context()) { + return; + } + + color_service_ = nullptr; + + if (color_manager_) { + // (Re)create color processor + + try { + + color_service_ = OpenGLColorProcessor::Create(color_manager_, + color_manager_->GetReferenceColorSpace(), + color_transform_); + + makeCurrent(); + color_service_->Enable(context(), true); + doneCurrent(); + + } catch (OCIO::Exception& e) { + + QMessageBox::critical(this, + tr("OpenColorIO Error"), + tr("Failed to set color configuration: %1").arg(e.what()), + QMessageBox::Ok); + + } + + } else { + color_service_ = nullptr; + } + + emit ColorProcessorChanged(std::static_pointer_cast(color_service_)); +} + +OLIVE_NAMESPACE_EXIT diff --git a/app/widget/manageddisplay/manageddisplay.h b/app/widget/manageddisplay/manageddisplay.h new file mode 100644 index 000000000..1acba4931 --- /dev/null +++ b/app/widget/manageddisplay/manageddisplay.h @@ -0,0 +1,147 @@ +/*** + + 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 . + +***/ + +#ifndef MANAGEDDISPLAYOBJECT_H +#define MANAGEDDISPLAYOBJECT_H + +#include + +#include "render/backend/opengl/openglcolorprocessor.h" +#include "render/colormanager.h" +#include "widget/menu/menu.h" + +OLIVE_NAMESPACE_ENTER + +class ManagedDisplayObject : public QOpenGLWidget +{ + Q_OBJECT +public: + ManagedDisplayObject(QWidget* parent = nullptr); + + /** + * @brief Connect a ColorManager (ColorManagers usually belong to the Project) + */ + void ConnectColorManager(ColorManager* color_manager); + + /** + * @brief Disconnect a ColorManager (equivalent to ConnectColorManager(nullptr)) + */ + void DisconnectColorManager(); + + /** + * @brief Access currently connected ColorManager (nullptr if none) + */ + ColorManager* color_manager() const; + + /** + * @brief Get current color transform + */ + const ColorTransform& GetColorTransform() const; + + /** + * @brief Get menu that can be used to select the display transform + */ + Menu* GetDisplayMenu(QMenu* parent, bool auto_connect = true); + + /** + * @brief Get menu that can be used to select the view transform + */ + Menu* GetViewMenu(QMenu* parent, bool auto_connect = true); + + /** + * @brief Get menu that can be used to select the look transform + */ + Menu* GetLookMenu(QMenu* parent, bool auto_connect = true); + +public slots: + /** + * @brief Replaces the color transform with a new one + */ + void SetColorTransform(const ColorTransform& transform); + +signals: + /** + * @brief Emitted when the color processor changes + */ + void ColorProcessorChanged(ColorProcessorPtr processor); + +protected: + /** + * @brief Provides access to the color processor (nullptr if none is set) + */ + OpenGLColorProcessorPtr color_service(); + + /** + * @brief Override when setting up OpenGL context + */ + virtual void initializeGL() override; + +private: + /** + * @brief Call this if this user has selected a different display/view/look to recreate the processor + */ + void SetupColorProcessor(); + + /** + * @brief Cleanup function + */ + void ClearOCIOLutTexture(); + + /** + * @brief Connected color manager + */ + ColorManager* color_manager_; + + /** + * @brief Color management service + */ + OpenGLColorProcessorPtr color_service_; + + /** + * @brief Internal color transform storage + */ + ColorTransform color_transform_; + +private slots: + /** + * @brief Sets all color settings to the defaults pertaining to this configuration + */ + void ColorConfigChanged(); + + /** + * @brief Cleans up resources if context is about to be destroyed + */ + void ContextCleanup(); + + /** + * @brief If GetDisplayMenu() is called with `auto_connect` set to true, it will be connected to this + */ + void MenuDisplaySelect(QAction* action); + + /** + * @brief If GetViewMenu() is called with `auto_connect` set to true, it will be connected to this + */ + void MenuViewSelect(QAction* action); + +}; + +OLIVE_NAMESPACE_EXIT + +#endif // MANAGEDDISPLAYOBJECT_H diff --git a/app/widget/viewer/manageddisplayobject.cpp b/app/widget/viewer/manageddisplayobject.cpp new file mode 100644 index 000000000..f7541ca3f --- /dev/null +++ b/app/widget/viewer/manageddisplayobject.cpp @@ -0,0 +1,6 @@ +#include "manageddisplayobject.h" + +ManagedDisplayObject::ManagedDisplayObject() +{ + +} diff --git a/app/widget/viewer/manageddisplayobject.h b/app/widget/viewer/manageddisplayobject.h new file mode 100644 index 000000000..11de19c12 --- /dev/null +++ b/app/widget/viewer/manageddisplayobject.h @@ -0,0 +1,11 @@ +#ifndef MANAGEDDISPLAYOBJECT_H +#define MANAGEDDISPLAYOBJECT_H + + +class ManagedDisplayObject +{ +public: + ManagedDisplayObject(); +}; + +#endif // MANAGEDDISPLAYOBJECT_H diff --git a/app/widget/viewer/viewer.cpp b/app/widget/viewer/viewer.cpp index 741f768ab..bb69b93c5 100644 --- a/app/widget/viewer/viewer.cpp +++ b/app/widget/viewer/viewer.cpp @@ -541,54 +541,22 @@ void ViewerWidget::ShowContextMenu(const QPoint &pos) // Color options if (context_menu_widget_->color_manager() && color_menu_enabled_) { - const ColorTransform& transform = context_menu_widget_->GetColorTransform(); - { - QStringList displays = context_menu_widget_->color_manager()->ListAvailableDisplays(); - - Menu* ocio_display_menu = new Menu(tr("Display"), &menu); + Menu* ocio_display_menu = context_menu_widget_->GetDisplayMenu(&menu); menu.addMenu(ocio_display_menu); - connect(ocio_display_menu, &QMenu::triggered, this, &ViewerWidget::ContextMenuOCIODisplay); - foreach (const QString& d, displays) { - QAction* action = ocio_display_menu->addAction(d); - action->setCheckable(true); - action->setChecked(transform.display() == d); - action->setData(d); - } } { - QStringList views = context_menu_widget_->color_manager()->ListAvailableViews(transform.display()); - - Menu* ocio_view_menu = new Menu(tr("View"), &menu); + Menu* ocio_view_menu = context_menu_widget_->GetViewMenu(&menu); menu.addMenu(ocio_view_menu); - connect(ocio_view_menu, &QMenu::triggered, this, &ViewerWidget::ContextMenuOCIOView); - foreach (const QString& v, views) { - QAction* action = ocio_view_menu->addAction(v); - action->setCheckable(true); - action->setChecked(transform.view() == v); - action->setData(v); - } } { - QStringList looks = context_menu_widget_->color_manager()->ListAvailableLooks(); - - Menu* ocio_look_menu = new Menu(tr("Look"), &menu); + Menu* ocio_look_menu = context_menu_widget_->GetLookMenu(&menu); menu.addMenu(ocio_look_menu); - connect(ocio_look_menu, &QMenu::triggered, this, &ViewerWidget::ContextMenuOCIOLook); - QAction* no_look_action = ocio_look_menu->addAction(tr("(None)")); - no_look_action->setCheckable(true); - no_look_action->setChecked(transform.look().isEmpty()); - foreach (const QString& l, looks) { - QAction* action = ocio_look_menu->addAction(l); - action->setCheckable(true); - action->setChecked(transform.look() == l); - action->setData(l); - } } menu.addSeparator(); diff --git a/app/widget/viewer/viewerglwidget.cpp b/app/widget/viewer/viewerglwidget.cpp index 6697b3a7b..aaa94e40c 100644 --- a/app/widget/viewer/viewerglwidget.cpp +++ b/app/widget/viewer/viewerglwidget.cpp @@ -41,9 +41,8 @@ bool ViewerGLWidget::nouveau_check_done_ = false; #endif ViewerGLWidget::ViewerGLWidget(QWidget *parent) : - QOpenGLWidget(parent), + ManagedDisplayObject(parent), managed_copy_pipeline_(nullptr), - color_manager_(nullptr), has_image_(false), signal_cursor_color_(false), enable_display_referred_signal_(false) @@ -56,30 +55,6 @@ ViewerGLWidget::~ViewerGLWidget() ContextCleanup(); } -void ViewerGLWidget::ConnectColorManager(ColorManager *color_manager) -{ - if (color_manager_ == color_manager) { - return; - } - - if (color_manager_ != nullptr) { - disconnect(color_manager_, &ColorManager::ConfigChanged, this, &ViewerGLWidget::ColorConfigChanged); - } - - color_manager_ = color_manager; - - if (color_manager_ != nullptr) { - connect(color_manager_, &ColorManager::ConfigChanged, this, &ViewerGLWidget::ColorConfigChanged); - } - - ColorConfigChanged(); -} - -void ViewerGLWidget::DisconnectColorManager() -{ - ConnectColorManager(nullptr); -} - void ViewerGLWidget::SetMatrix(const QMatrix4x4 &mat) { matrix_ = mat; @@ -185,11 +160,6 @@ void ViewerGLWidget::SetEmitDrewManagedTextureEnabled(bool e) } } -ColorManager *ViewerGLWidget::color_manager() const -{ - return color_manager_; -} - void ViewerGLWidget::ConnectSibling(ViewerGLWidget *sibling) { connect(this, &ViewerGLWidget::LoadedBuffer, sibling, &ViewerGLWidget::SetImageFromLoadBuffer, Qt::QueuedConnection); @@ -208,18 +178,6 @@ void ViewerGLWidget::SetSafeMargins(const ViewerSafeMarginInfo &safe_margin) update(); } -const ColorTransform &ViewerGLWidget::GetColorTransform() const -{ - return color_transform_; -} - -void ViewerGLWidget::SetColorTransform(const ColorTransform &transform) -{ - color_transform_ = transform; - SetupColorProcessor(); - update(); -} - void ViewerGLWidget::mousePressEvent(QMouseEvent *event) { QOpenGLWidget::mousePressEvent(event); @@ -245,7 +203,7 @@ void ViewerGLWidget::mouseMoveEvent(QMouseEvent *event) int frame_y = qRound((pixel_pos.y() + 1.0f) * 0.5f * load_buffer_.height()); reference = load_buffer_.get_pixel(frame_x, frame_y); - display = color_service_->ConvertColor(reference); + display = color_service()->ConvertColor(reference); } emit CursorColor(reference, display); @@ -254,7 +212,7 @@ void ViewerGLWidget::mouseMoveEvent(QMouseEvent *event) void ViewerGLWidget::initializeGL() { - SetupColorProcessor(); + ManagedDisplayObject::initializeGL(); connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &ViewerGLWidget::ContextCleanup, Qt::DirectConnection); @@ -284,7 +242,7 @@ void ViewerGLWidget::paintGL() f->glClear(GL_COLOR_BUFFER_BIT); // We only draw if we have a pipeline - if (has_image_ && color_service_ && texture_.IsCreated()) { + if (has_image_ && color_service() && texture_.IsCreated()) { // If we're distributing our display-referred final buffer, we'll have to make a copy of it if (enable_display_referred_signal_) { @@ -317,7 +275,7 @@ void ViewerGLWidget::paintGL() f->glBindTexture(GL_TEXTURE_2D, texture_.texture()); // Blit using the color service - color_service_->ProcessOpenGL(true, matrix_); + color_service()->ProcessOpenGL(true, matrix_); // Release retrieved texture f->glBindTexture(GL_TEXTURE_2D, 0); @@ -375,16 +333,6 @@ void ViewerGLWidget::paintGL() } } -void ViewerGLWidget::ColorConfigChanged() -{ - if (!color_manager_) { - color_service_ = nullptr; - return; - } - - SetColorTransform(color_manager_->GetCompliantColorSpace(color_transform_, true)); -} - #ifdef Q_OS_LINUX void ViewerGLWidget::ShowNouveauWarning() { @@ -397,48 +345,10 @@ void ViewerGLWidget::ShowNouveauWarning() } #endif -void ViewerGLWidget::SetupColorProcessor() -{ - if (!context()) { - return; - } - - color_service_ = nullptr; - - if (color_manager_) { - // (Re)create color processor - - try { - - color_service_ = OpenGLColorProcessor::Create(color_manager_, - color_manager_->GetReferenceColorSpace(), - color_transform_); - - makeCurrent(); - color_service_->Enable(context(), true); - doneCurrent(); - - } catch (OCIO::Exception& e) { - - QMessageBox::critical(this, - tr("OpenColorIO Error"), - tr("Failed to set color configuration: %1").arg(e.what()), - QMessageBox::Ok); - - } - - } else { - color_service_ = nullptr; - } - - emit ColorProcessorChanged(std::static_pointer_cast(color_service_)); -} - void ViewerGLWidget::ContextCleanup() { makeCurrent(); - color_service_ = nullptr; managed_copy_pipeline_ = nullptr; texture_.Destroy(); managed_texture_.Destroy(); diff --git a/app/widget/viewer/viewerglwidget.h b/app/widget/viewer/viewerglwidget.h index 39620f994..e4717f220 100644 --- a/app/widget/viewer/viewerglwidget.h +++ b/app/widget/viewer/viewerglwidget.h @@ -30,6 +30,7 @@ #include "render/color.h" #include "render/colormanager.h" #include "viewersafemargininfo.h" +#include "widget/manageddisplay/manageddisplay.h" OLIVE_NAMESPACE_ENTER @@ -48,7 +49,7 @@ OLIVE_NAMESPACE_ENTER * the same texture object, use SetTexture() since it will nearly always be faster to just set it than to check *and* * set it. */ -class ViewerGLWidget : public QOpenGLWidget +class ViewerGLWidget : public ManagedDisplayObject { Q_OBJECT public: @@ -63,23 +64,11 @@ public: virtual ~ViewerGLWidget() override; - /** - * @brief Connect a ColorManager (ColorManagers usually belong to the Project) - */ - void ConnectColorManager(ColorManager* color_manager); - - /** - * @brief Disconnect a ColorManager (equivalent to ConnectColorManager(nullptr)) - */ - void DisconnectColorManager(); - /** * @brief Set an image to load and display on screen */ void SetImage(const QString& fn); - ColorManager* color_manager() const; - const QMatrix4x4& GetMatrix(); void ConnectSibling(ViewerGLWidget* sibling); @@ -87,14 +76,7 @@ public: const ViewerSafeMarginInfo& GetSafeMargin() const; void SetSafeMargins(const ViewerSafeMarginInfo& safe_margin); - const ColorTransform& GetColorTransform() const; - public slots: - /** - * @brief Replaces the color transform with a new one - */ - void SetColorTransform(const ColorTransform& transform); - /** * @brief Set the transformation matrix to draw with * @@ -160,11 +142,6 @@ signals: */ void DrewManagedTexture(OpenGLTexture* texture); - /** - * @brief Emitted when the color processor changes - */ - void ColorProcessorChanged(ColorProcessorPtr processor); - protected: /** * @brief Override the mouse press event simply to emit the DragStarted() signal @@ -191,21 +168,6 @@ protected: virtual void paintGL() override; private: - /** - * @brief Call this if this user has selected a different display/view/look to recreate the processor - */ - void SetupColorProcessor(); - - /** - * @brief Cleanup function - */ - void ClearOCIOLutTexture(); - - /** - * @brief Internal color transform storage - */ - ColorTransform color_transform_; - /** * @brief Internal reference to the OpenGL texture to draw. Set in SetTexture() and used in paintGL(). */ @@ -228,16 +190,6 @@ private: */ OpenGLShaderPtr managed_copy_pipeline_; - /** - * @brief Connected color manager - */ - ColorManager* color_manager_; - - /** - * @brief Color management service - */ - OpenGLColorProcessorPtr color_service_; - /** * @brief Drawing matrix (defaults to identity) */ @@ -266,11 +218,6 @@ private slots: */ void ContextCleanup(); - /** - * @brief Sets all color settings to the defaults pertaining to this configuration - */ - void ColorConfigChanged(); - #ifdef Q_OS_LINUX /** * @brief Shows warning messagebox if Nouveau is detected