From b11e44d778c3a19f32e7b40dcc9347589a6603bc Mon Sep 17 00:00:00 2001 From: Darby Johnston Date: Tue, 20 Feb 2024 13:19:08 -0800 Subject: [PATCH] Move background options to the renderer --- lib/tlCore/Mesh.cpp | 72 ++++++++++++++++++++++ lib/tlCore/Mesh.h | 12 +++- lib/tlDevice/BMDOutputDevice.cpp | 26 ++++++-- lib/tlDevice/BMDOutputDevice.h | 6 +- lib/tlPlay/ViewportModel.h | 6 +- lib/tlPlayApp/App.cpp | 8 +++ lib/tlPlayApp/MainWindow.cpp | 16 ++--- lib/tlPlayApp/SecondaryWindow.cpp | 16 ++--- lib/tlPlayApp/ViewTool.cpp | 75 +++++++++-------------- lib/tlPlayQtApp/App.cpp | 8 +++ lib/tlPlayQtApp/MainWindow.cpp | 18 +++--- lib/tlPlayQtApp/SecondaryWindow.cpp | 16 ++--- lib/tlPlayQtApp/ViewTool.cpp | 59 ++++++------------ lib/tlQtWidget/TimelineViewport.cpp | 44 ++++--------- lib/tlQtWidget/TimelineViewport.h | 6 +- lib/tlTimeline/BackgroundOptions.cpp | 13 ++-- lib/tlTimeline/BackgroundOptions.h | 10 +-- lib/tlTimeline/BackgroundOptionsInline.h | 5 +- lib/tlTimeline/IRender.h | 4 +- lib/tlTimelineGL/Render.h | 6 +- lib/tlTimelineGL/RenderShaders_GL_4_1.cpp | 1 - lib/tlTimelineGL/RenderVideo.cpp | 70 +++++++++++++++++---- lib/tlTimelineUI/TimelineViewport.cpp | 53 +++++----------- lib/tlTimelineUI/TimelineViewport.h | 6 +- lib/tlUI/DrawUtil.cpp | 72 ---------------------- lib/tlUI/DrawUtil.h | 7 --- 26 files changed, 321 insertions(+), 314 deletions(-) diff --git a/lib/tlCore/Mesh.cpp b/lib/tlCore/Mesh.cpp index 1b0376bca..8764b7d0c 100644 --- a/lib/tlCore/Mesh.cpp +++ b/lib/tlCore/Mesh.cpp @@ -78,6 +78,78 @@ namespace tl return out; } + geom::TriangleMesh2 checkers( + const math::Box2i& box, + const image::Color4f& color0, + const image::Color4f& color1, + const math::Size2i& checkerSize) + { + geom::TriangleMesh2 out; + + // X points. + std::vector xs; + int x = box.min.x; + for (; x < box.max.x; x += checkerSize.w) + { + xs.push_back(x); + } + if (x >= box.max.x) + { + xs.push_back(box.max.x); + } + + // Y points. + std::vector ys; + int y = box.min.y; + for (; y < box.max.y; y += checkerSize.h) + { + ys.push_back(y); + } + if (y >= box.max.y) + { + ys.push_back(box.max.y); + } + + if (!xs.empty() && !ys.empty()) + { + // 2D points. + for (int j = 0; j < ys.size(); ++j) + { + for (int i = 0; i < xs.size(); ++i) + { + out.v.push_back(math::Vector2f(xs[i], ys[j])); + } + } + + // Colors. + out.c.push_back(math::Vector4f(color0.r, color0.g, color0.b, color0.a)); + out.c.push_back(math::Vector4f(color1.r, color1.g, color1.b, color1.a)); + + // Triangles. + for (int j = 0; j < ys.size() - 1; ++j) + { + for (int i = 0; i < xs.size() - 1; ++i) + { + const int v0 = j * xs.size() + i + 1; + const int v1 = j * xs.size() + (i + 1) + 1; + const int v2 = (j + 1) * xs.size() + (i + 1) + 1; + const int v3 = (j + 1) * xs.size() + i + 1; + const int c = (j + i) % 2 + 1; + out.triangles.push_back({ + geom::Vertex2(v0, 0, c), + geom::Vertex2(v1, 0, c), + geom::Vertex2(v2, 0, c) }); + out.triangles.push_back({ + geom::Vertex2(v2, 0, c), + geom::Vertex2(v3, 0, c), + geom::Vertex2(v0, 0, c) }); + } + } + } + + return out; + } + TriangleMesh3 sphere( float radius, size_t xResolution, diff --git a/lib/tlCore/Mesh.h b/lib/tlCore/Mesh.h index 194606d4e..560351a63 100644 --- a/lib/tlCore/Mesh.h +++ b/lib/tlCore/Mesh.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include @@ -68,12 +69,19 @@ namespace tl std::vector triangles; }; - //! Create a two-dimensional axis aligned box mesh. + //! Create a two-dimensional box mesh. TriangleMesh2 box(const math::Box2i&, bool flipV = false); - //! Create a two-dimensional axis aligned box mesh. + //! Create a two-dimensional box mesh. TriangleMesh2 box(const math::Box2f&, bool flipV = false); + //! Create a mesh for drawing checkers. + geom::TriangleMesh2 checkers( + const math::Box2i&, + const image::Color4f& color0, + const image::Color4f& color1, + const math::Size2i& checkerSize); + //! Edge function. float edge( const math::Vector2f& p, diff --git a/lib/tlDevice/BMDOutputDevice.cpp b/lib/tlDevice/BMDOutputDevice.cpp index d75ec414e..8b6cd5dc6 100644 --- a/lib/tlDevice/BMDOutputDevice.cpp +++ b/lib/tlDevice/BMDOutputDevice.cpp @@ -68,6 +68,7 @@ namespace tl HDRMode hdrMode = HDRMode::FromFile; image::HDRData hdrData; timeline::CompareOptions compareOptions; + timeline::BackgroundOptions backgroundOptions; math::Vector2i viewPos; double viewZoom = 1.0; bool frameView = true; @@ -327,6 +328,16 @@ namespace tl p.thread.cv.notify_one(); } + void OutputDevice::setBackgroundOptions(const timeline::BackgroundOptions& value) + { + TLRENDER_P(); + { + std::unique_lock lock(p.mutex.mutex); + p.mutex.backgroundOptions = value; + } + p.thread.cv.notify_one(); + } + void OutputDevice::setOverlay(const std::shared_ptr& value) { TLRENDER_P(); @@ -510,6 +521,7 @@ namespace tl std::vector imageOptions; std::vector displayOptions; timeline::CompareOptions compareOptions; + timeline::BackgroundOptions backgroundOptions; timeline::Playback playback = timeline::Playback::Stop; otime::RationalTime currentTime = time::invalidTime; float volume = 1.F; @@ -536,7 +548,7 @@ namespace tl timeout, [this, config, enabled, ocioOptions, lutOptions, imageOptions, - displayOptions, compareOptions, + displayOptions, compareOptions, backgroundOptions, playback, currentTime, volume, mute, audioOffset, audioData] { @@ -550,6 +562,7 @@ namespace tl _p->thread.hdrMode != _p->mutex.hdrMode || _p->thread.hdrData != _p->mutex.hdrData || compareOptions != _p->mutex.compareOptions || + backgroundOptions != _p->mutex.backgroundOptions || _p->thread.viewPos != _p->mutex.viewPos || _p->thread.viewZoom != _p->mutex.viewZoom || _p->thread.frameView != _p->mutex.frameView || @@ -584,6 +597,7 @@ namespace tl p.thread.hdrMode != p.mutex.hdrMode || p.thread.hdrData != p.mutex.hdrData || compareOptions != p.mutex.compareOptions || + backgroundOptions != p.mutex.backgroundOptions || p.thread.viewPos != p.mutex.viewPos || p.thread.viewZoom != p.mutex.viewZoom || p.thread.frameView != p.mutex.frameView || @@ -597,6 +611,7 @@ namespace tl p.thread.hdrMode = p.mutex.hdrMode; p.thread.hdrData = p.mutex.hdrData; compareOptions = p.mutex.compareOptions; + backgroundOptions = p.mutex.backgroundOptions; p.thread.viewPos = p.mutex.viewPos; p.thread.viewZoom = p.mutex.viewZoom; p.thread.frameView = p.mutex.frameView; @@ -671,7 +686,8 @@ namespace tl lutOptions, imageOptions, displayOptions, - compareOptions); + compareOptions, + backgroundOptions); } catch (const std::exception& e) { @@ -916,7 +932,8 @@ namespace tl const timeline::LUTOptions& lutOptions, const std::vector& imageOptions, const std::vector& displayOptions, - const timeline::CompareOptions& compareOptions) + const timeline::CompareOptions& compareOptions, + const timeline::BackgroundOptions& backgroundOptions) { TLRENDER_P(); @@ -977,7 +994,8 @@ namespace tl timeline::getBoxes(compareOptions.mode, p.thread.sizes), imageOptions, displayOptions, - compareOptions); + compareOptions, + backgroundOptions); if (p.thread.overlay) { p.thread.render->setTransform(pm); diff --git a/lib/tlDevice/BMDOutputDevice.h b/lib/tlDevice/BMDOutputDevice.h index 1004efbf1..af1715fa1 100644 --- a/lib/tlDevice/BMDOutputDevice.h +++ b/lib/tlDevice/BMDOutputDevice.h @@ -89,6 +89,9 @@ namespace tl //! Set the comparison options. void setCompareOptions(const timeline::CompareOptions&); + //! Set the background options. + void setBackgroundOptions(const timeline::BackgroundOptions&); + //! Set the overlay. void setOverlay(const std::shared_ptr&); @@ -120,7 +123,8 @@ namespace tl const timeline::LUTOptions&, const std::vector&, const std::vector&, - const timeline::CompareOptions&); + const timeline::CompareOptions&, + const timeline::BackgroundOptions&); void _read(); TLRENDER_PRIVATE(); diff --git a/lib/tlPlay/ViewportModel.h b/lib/tlPlay/ViewportModel.h index fd5d4eaf9..a0bc01d57 100644 --- a/lib/tlPlay/ViewportModel.h +++ b/lib/tlPlay/ViewportModel.h @@ -39,13 +39,13 @@ namespace tl const std::shared_ptr&, const std::shared_ptr&); - //! Get the timeline viewport background options. + //! Get the background options. const timeline::BackgroundOptions& getBackgroundOptions() const; - //! Observer the timeline viewport background options. + //! Observe the background options. std::shared_ptr > observeBackgroundOptions() const; - //! Set the timeline viewport background options. + //! Set the background options. void setBackgroundOptions(const timeline::BackgroundOptions&); private: diff --git a/lib/tlPlayApp/App.cpp b/lib/tlPlayApp/App.cpp index 3feaaf11e..27c98e879 100644 --- a/lib/tlPlayApp/App.cpp +++ b/lib/tlPlayApp/App.cpp @@ -88,6 +88,7 @@ namespace tl std::shared_ptr > imageOptionsObserver; std::shared_ptr > displayOptionsObserver; std::shared_ptr > compareOptionsObserver; + std::shared_ptr > backgroundOptionsObserver; #endif // TLRENDER_BMD }; @@ -639,6 +640,13 @@ namespace tl { _p->bmdOutputDevice->setCompareOptions(value); }); + + p.backgroundOptionsObserver = observer::ValueObserver::create( + p.viewportModel->observeBackgroundOptions(), + [this](const timeline::BackgroundOptions& value) + { + _p->bmdOutputDevice->setBackgroundOptions(value); + }); #endif // TLRENDER_BMD } diff --git a/lib/tlPlayApp/MainWindow.cpp b/lib/tlPlayApp/MainWindow.cpp index bd9d3e823..ac929776a 100644 --- a/lib/tlPlayApp/MainWindow.cpp +++ b/lib/tlPlayApp/MainWindow.cpp @@ -156,12 +156,12 @@ namespace tl std::shared_ptr > speedObserver2; std::shared_ptr > playbackObserver; std::shared_ptr > currentTimeObserver; - std::shared_ptr > backgroundOptionsObserver; std::shared_ptr > ocioOptionsObserver; std::shared_ptr > lutOptionsObserver; std::shared_ptr > imageOptionsObserver; std::shared_ptr > displayOptionsObserver; std::shared_ptr > compareOptionsObserver; + std::shared_ptr > backgroundOptionsObserver; std::shared_ptr > muteObserver; std::shared_ptr > logObserver; }; @@ -550,13 +550,6 @@ namespace tl } }); - p.backgroundOptionsObserver = observer::ValueObserver::create( - app->getViewportModel()->observeBackgroundOptions(), - [this](const timeline::BackgroundOptions& value) - { - _p->timelineViewport->setBackgroundOptions(value); - }); - p.ocioOptionsObserver = observer::ValueObserver::create( app->getColorModel()->observeOCIOOptions(), [this](const timeline::OCIOOptions& value) @@ -602,6 +595,13 @@ namespace tl _p->timelineViewport->setCompareOptions(value); }); + p.backgroundOptionsObserver = observer::ValueObserver::create( + app->getViewportModel()->observeBackgroundOptions(), + [this](const timeline::BackgroundOptions& value) + { + _p->timelineViewport->setBackgroundOptions(value); + }); + p.muteObserver = observer::ValueObserver::create( app->getAudioModel()->observeMute(), [this](bool value) diff --git a/lib/tlPlayApp/SecondaryWindow.cpp b/lib/tlPlayApp/SecondaryWindow.cpp index 9b9fe63d3..aaa2434b0 100644 --- a/lib/tlPlayApp/SecondaryWindow.cpp +++ b/lib/tlPlayApp/SecondaryWindow.cpp @@ -22,12 +22,12 @@ namespace tl std::shared_ptr viewport; std::shared_ptr > > playersObserver; - std::shared_ptr > backgroundOptionsObserver; std::shared_ptr > ocioOptionsObserver; std::shared_ptr > lutOptionsObserver; std::shared_ptr > imageOptionsObserver; std::shared_ptr > displayOptionsObserver; std::shared_ptr > compareOptionsObserver; + std::shared_ptr > backgroundOptionsObserver; }; void SecondaryWindow::_init( @@ -49,13 +49,6 @@ namespace tl _p->viewport->setPlayers(value); }); - p.backgroundOptionsObserver = observer::ValueObserver::create( - app->getViewportModel()->observeBackgroundOptions(), - [this](const timeline::BackgroundOptions& value) - { - _p->viewport->setBackgroundOptions(value); - }); - p.ocioOptionsObserver = observer::ValueObserver::create( app->getColorModel()->observeOCIOOptions(), [this](const timeline::OCIOOptions& value) @@ -90,6 +83,13 @@ namespace tl { _p->viewport->setCompareOptions(value); }); + + p.backgroundOptionsObserver = observer::ValueObserver::create( + app->getViewportModel()->observeBackgroundOptions(), + [this](const timeline::BackgroundOptions& value) + { + _p->viewport->setBackgroundOptions(value); + }); } SecondaryWindow::SecondaryWindow() : diff --git a/lib/tlPlayApp/ViewTool.cpp b/lib/tlPlayApp/ViewTool.cpp index 4c18b975b..01fddef0b 100644 --- a/lib/tlPlayApp/ViewTool.cpp +++ b/lib/tlPlayApp/ViewTool.cpp @@ -25,11 +25,10 @@ namespace tl struct BackgroundWidget::Private { std::shared_ptr typeComboBox; - std::shared_ptr solidColorSwatch; - std::shared_ptr checkersColor0Swatch; - std::shared_ptr checkersColor1Swatch; + std::shared_ptr color0Swatch; + std::shared_ptr color1Swatch; std::shared_ptr checkersSizeSlider; - std::shared_ptr layout; + std::shared_ptr layout; std::shared_ptr > optionsObservers; }; @@ -46,36 +45,32 @@ namespace tl timeline::getBackgroundLabels(), context); - p.solidColorSwatch = ui::ColorSwatch::create(context); - p.solidColorSwatch->setEditable(true); - - p.checkersColor0Swatch = ui::ColorSwatch::create(context); - p.checkersColor0Swatch->setEditable(true); - p.checkersColor1Swatch = ui::ColorSwatch::create(context); - p.checkersColor1Swatch->setEditable(true); + p.color0Swatch = ui::ColorSwatch::create(context); + p.color0Swatch->setEditable(true); + p.color1Swatch = ui::ColorSwatch::create(context); + p.color1Swatch->setEditable(true); p.checkersSizeSlider = ui::IntEditSlider::create(context); p.checkersSizeSlider->setRange(math::IntRange(10, 100)); - p.layout = ui::VerticalLayout::create(context, shared_from_this()); + p.layout = ui::GridLayout::create(context, shared_from_this()); p.layout->setMarginRole(ui::SizeRole::MarginSmall); p.layout->setSpacingRole(ui::SizeRole::SpacingSmall); + auto label = ui::Label::create("Type:", context, p.layout); + p.layout->setGridPos(label, 0, 0); p.typeComboBox->setParent(p.layout); - auto groupBox = ui::GroupBox::create("Solid", context, p.layout); - p.solidColorSwatch->setParent(groupBox); - groupBox = ui::GroupBox::create("Checkers", context, p.layout); - auto gridLayout = ui::GridLayout::create(context, groupBox); - auto label = ui::Label::create("Color 0:", context, gridLayout); - gridLayout->setGridPos(label, 0, 0); - p.checkersColor0Swatch->setParent(gridLayout); - gridLayout->setGridPos(p.checkersColor0Swatch, 0, 1); - label = ui::Label::create("Color 1:", context, gridLayout); - gridLayout->setGridPos(label, 1, 0); - p.checkersColor1Swatch->setParent(gridLayout); - gridLayout->setGridPos(p.checkersColor1Swatch, 1, 1); - label = ui::Label::create("Size:", context, gridLayout); - gridLayout->setGridPos(label, 2, 0); - p.checkersSizeSlider->setParent(gridLayout); - gridLayout->setGridPos(p.checkersSizeSlider, 2, 1); + p.layout->setGridPos(p.typeComboBox, 0, 1); + label = ui::Label::create("Color 0:", context, p.layout); + p.layout->setGridPos(label, 1, 0); + p.color0Swatch->setParent(p.layout); + p.layout->setGridPos(p.color0Swatch, 1, 1); + label = ui::Label::create("Color 1:", context, p.layout); + p.layout->setGridPos(label, 2, 0); + p.color1Swatch->setParent(p.layout); + p.layout->setGridPos(p.color1Swatch, 2, 1); + label = ui::Label::create("Checkers size:", context, p.layout); + p.layout->setGridPos(label, 3, 0); + p.checkersSizeSlider->setParent(p.layout); + p.layout->setGridPos(p.checkersSizeSlider, 3, 1); p.optionsObservers = observer::ValueObserver::create( app->getViewportModel()->observeBackgroundOptions(), @@ -96,35 +91,24 @@ namespace tl } }); - p.solidColorSwatch->setCallback( - [appWeak](const image::Color4f& value) - { - if (auto app = appWeak.lock()) - { - auto options = app->getViewportModel()->getBackgroundOptions(); - options.solidColor = value; - app->getViewportModel()->setBackgroundOptions(options); - } - }); - - p.checkersColor0Swatch->setCallback( + p.color0Swatch->setCallback( [appWeak](const image::Color4f& value) { if (auto app = appWeak.lock()) { auto options = app->getViewportModel()->getBackgroundOptions(); - options.checkersColor0 = value; + options.color0 = value; app->getViewportModel()->setBackgroundOptions(options); } }); - p.checkersColor1Swatch->setCallback( + p.color1Swatch->setCallback( [appWeak](const image::Color4f& value) { if (auto app = appWeak.lock()) { auto options = app->getViewportModel()->getBackgroundOptions(); - options.checkersColor1 = value; + options.color1 = value; app->getViewportModel()->setBackgroundOptions(options); } }); @@ -175,9 +159,8 @@ namespace tl { TLRENDER_P(); p.typeComboBox->setCurrentIndex(static_cast(value.type)); - p.solidColorSwatch->setColor(value.solidColor); - p.checkersColor0Swatch->setColor(value.checkersColor0); - p.checkersColor1Swatch->setColor(value.checkersColor1); + p.color0Swatch->setColor(value.color0); + p.color1Swatch->setColor(value.color1); p.checkersSizeSlider->setValue(value.checkersSize.w); } diff --git a/lib/tlPlayQtApp/App.cpp b/lib/tlPlayQtApp/App.cpp index c945ac577..f065f7c1b 100644 --- a/lib/tlPlayQtApp/App.cpp +++ b/lib/tlPlayQtApp/App.cpp @@ -111,6 +111,7 @@ namespace tl std::shared_ptr > imageOptionsObserver; std::shared_ptr > displayOptionsObserver; std::shared_ptr > compareOptionsObserver; + std::shared_ptr > backgroundOptionsObserver; #endif // TLRENDER_BMD }; @@ -819,6 +820,13 @@ namespace tl { _p->bmdOutputDevice->setCompareOptions(value); }); + + p.backgroundOptionsObserver = observer::ValueObserver::create( + p.viewportModel->observeBackgroundOptions(), + [this](const timeline::BackgroundOptions& value) + { + _p->bmdOutputDevice->setBackgroundOptions(value); + }); #endif // TLRENDER_BMD } diff --git a/lib/tlPlayQtApp/MainWindow.cpp b/lib/tlPlayQtApp/MainWindow.cpp index 42eb4b243..1e4c2f903 100644 --- a/lib/tlPlayQtApp/MainWindow.cpp +++ b/lib/tlPlayQtApp/MainWindow.cpp @@ -117,11 +117,11 @@ namespace tl std::shared_ptr > aIndexObserver; std::shared_ptr > bIndexesObserver; std::shared_ptr > compareOptionsObserver; - std::shared_ptr > backgroundOptionsObserver; std::shared_ptr > ocioOptionsObserver; std::shared_ptr > lutOptionsObserver; std::shared_ptr > displayOptionsObserver; std::shared_ptr > imageOptionsObserver; + std::shared_ptr > backgroundOptionsObserver; std::shared_ptr > volumeObserver; std::shared_ptr > muteObserver; std::shared_ptr > logObserver; @@ -432,13 +432,6 @@ namespace tl _widgetUpdate(); }); - p.backgroundOptionsObserver = observer::ValueObserver::create( - app->viewportModel()->observeBackgroundOptions(), - [this](const timeline::BackgroundOptions& value) - { - _widgetUpdate(); - }); - p.ocioOptionsObserver = observer::ValueObserver::create( app->colorModel()->observeOCIOOptions(), [this](const timeline::OCIOOptions&) @@ -464,6 +457,13 @@ namespace tl _widgetUpdate(); }); + p.backgroundOptionsObserver = observer::ValueObserver::create( + app->viewportModel()->observeBackgroundOptions(), + [this](const timeline::BackgroundOptions& value) + { + _widgetUpdate(); + }); + p.volumeObserver = observer::ValueObserver::create( app->audioModel()->observeVolume(), [this](float) @@ -856,6 +856,8 @@ namespace tl p.timelineViewport->setDisplayOptions(displayOptions); p.timelineViewport->setCompareOptions( p.app->filesModel()->getCompareOptions()); + p.timelineViewport->setBackgroundOptions( + p.app->viewportModel()->getBackgroundOptions()); p.timelineWidget->setPlayer( (!p.timelinePlayers.empty() && p.timelinePlayers[0]) ? diff --git a/lib/tlPlayQtApp/SecondaryWindow.cpp b/lib/tlPlayQtApp/SecondaryWindow.cpp index 3117df0c1..f77751430 100644 --- a/lib/tlPlayQtApp/SecondaryWindow.cpp +++ b/lib/tlPlayQtApp/SecondaryWindow.cpp @@ -26,12 +26,12 @@ namespace tl qtwidget::TimelineViewport* viewport = nullptr; - std::shared_ptr > backgroundOptionsObserver; std::shared_ptr > ocioOptionsObserver; std::shared_ptr > lutOptionsObserver; std::shared_ptr > imageOptionsObserver; std::shared_ptr > displayOptionsObserver; std::shared_ptr > compareOptionsObserver; + std::shared_ptr > backgroundOptionsObserver; }; SecondaryWindow::SecondaryWindow( @@ -70,13 +70,6 @@ namespace tl _p->viewport->setTimelinePlayers(value); }); - p.backgroundOptionsObserver = observer::ValueObserver::create( - app->viewportModel()->observeBackgroundOptions(), - [this](const timeline::BackgroundOptions& value) - { - _p->viewport->setBackgroundOptions(value); - }); - p.ocioOptionsObserver = observer::ValueObserver::create( app->colorModel()->observeOCIOOptions(), [this](const timeline::OCIOOptions& value) @@ -111,6 +104,13 @@ namespace tl { _p->viewport->setCompareOptions(value); }); + + p.backgroundOptionsObserver = observer::ValueObserver::create( + app->viewportModel()->observeBackgroundOptions(), + [this](const timeline::BackgroundOptions& value) + { + _p->viewport->setBackgroundOptions(value); + }); } SecondaryWindow::~SecondaryWindow() diff --git a/lib/tlPlayQtApp/ViewTool.cpp b/lib/tlPlayQtApp/ViewTool.cpp index 9840f57a3..f0cd39522 100644 --- a/lib/tlPlayQtApp/ViewTool.cpp +++ b/lib/tlPlayQtApp/ViewTool.cpp @@ -24,9 +24,8 @@ namespace tl struct BackgroundWidget::Private { QComboBox* typeComboBox = nullptr; - qtwidget::ColorSwatch* solidColorSwatch = nullptr; - qtwidget::ColorSwatch* checkersColor0Swatch = nullptr; - qtwidget::ColorSwatch* checkersColor1Swatch = nullptr; + qtwidget::ColorSwatch* color0Swatch = nullptr; + qtwidget::ColorSwatch* color1Swatch = nullptr; qtwidget::IntEditSlider* checkersSizeSlider = nullptr; std::shared_ptr > optionsObservers; @@ -44,32 +43,20 @@ namespace tl p.typeComboBox->addItem(QString::fromUtf8(i.c_str())); } - p.solidColorSwatch = new qtwidget::ColorSwatch; - p.solidColorSwatch->setEditable(true); + p.color0Swatch = new qtwidget::ColorSwatch; + p.color0Swatch->setEditable(true); - p.checkersColor0Swatch = new qtwidget::ColorSwatch; - p.checkersColor0Swatch->setEditable(true); - - p.checkersColor1Swatch = new qtwidget::ColorSwatch; - p.checkersColor1Swatch->setEditable(true); + p.color1Swatch = new qtwidget::ColorSwatch; + p.color1Swatch->setEditable(true); p.checkersSizeSlider = new qtwidget::IntEditSlider; p.checkersSizeSlider->setRange(math::IntRange(10, 100)); - auto layout = new QVBoxLayout; - layout->addWidget(p.typeComboBox); - auto groupBox = new QGroupBox(tr("Solid")); - auto vLayout = new QVBoxLayout; - vLayout->addWidget(p.solidColorSwatch); - groupBox->setLayout(vLayout); - layout->addWidget(groupBox); - groupBox = new QGroupBox(tr("Checkers")); - auto formLayout = new QFormLayout; - formLayout->addRow(tr("Color 0:"), p.checkersColor0Swatch); - formLayout->addRow(tr("Color 1:"), p.checkersColor1Swatch); - formLayout->addRow(tr("Size:"), p.checkersSizeSlider); - groupBox->setLayout(formLayout); - layout->addWidget(groupBox); + auto layout = new QFormLayout; + layout->addRow(tr("Type:"), p.typeComboBox); + layout->addRow(tr("Color 0:"), p.color0Swatch); + layout->addRow(tr("Color 1:"), p.color1Swatch); + layout->addRow(tr("Checkers size:"), p.checkersSizeSlider); setLayout(layout); connect( @@ -83,33 +70,24 @@ namespace tl }); connect( - p.solidColorSwatch, - &qtwidget::ColorSwatch::colorChanged, - [app](const image::Color4f& value) - { - auto options = app->viewportModel()->getBackgroundOptions(); - options.solidColor = value; - app->viewportModel()->setBackgroundOptions(options); - }); - - connect( - p.checkersColor0Swatch, + p.color0Swatch, &qtwidget::ColorSwatch::colorChanged, [app](const image::Color4f& value) { auto options = app->viewportModel()->getBackgroundOptions(); - options.checkersColor0 = value; + options.color0 = value; app->viewportModel()->setBackgroundOptions(options); }); connect( - p.checkersColor1Swatch, + p.color1Swatch, &qtwidget::ColorSwatch::colorChanged, [app](const image::Color4f& value) { auto options = app->viewportModel()->getBackgroundOptions(); - options.checkersColor1 = value; + options.color1 = value; app->viewportModel()->setBackgroundOptions(options); }); + connect( p.checkersSizeSlider, &qtwidget::IntEditSlider::valueChanged, @@ -136,9 +114,8 @@ namespace tl { TLRENDER_P(); p.typeComboBox->setCurrentIndex(static_cast(value.type)); - p.solidColorSwatch->setColor(value.solidColor); - p.checkersColor0Swatch->setColor(value.checkersColor0); - p.checkersColor1Swatch->setColor(value.checkersColor1); + p.color0Swatch->setColor(value.color0); + p.color1Swatch->setColor(value.color1); p.checkersSizeSlider->setValue(value.checkersSize.w); } diff --git a/lib/tlQtWidget/TimelineViewport.cpp b/lib/tlQtWidget/TimelineViewport.cpp index 931b6e399..2dc5b5874 100644 --- a/lib/tlQtWidget/TimelineViewport.cpp +++ b/lib/tlQtWidget/TimelineViewport.cpp @@ -27,12 +27,12 @@ namespace tl struct TimelineViewport::Private { std::weak_ptr context; - timeline::BackgroundOptions backgroundOptions; timeline::OCIOOptions ocioOptions; timeline::LUTOptions lutOptions; std::vector imageOptions; std::vector displayOptions; timeline::CompareOptions compareOptions; + timeline::BackgroundOptions backgroundOptions; QVector > timelinePlayers; std::vector timelineSizes; std::vector videoData; @@ -86,16 +86,6 @@ namespace tl makeCurrent(); } - void TimelineViewport::setBackgroundOptions(const timeline::BackgroundOptions& value) - { - TLRENDER_P(); - if (value == p.backgroundOptions) - return; - p.backgroundOptions = value; - p.doRender = true; - update(); - } - void TimelineViewport::setOCIOOptions(const timeline::OCIOOptions& value) { TLRENDER_P(); @@ -146,6 +136,16 @@ namespace tl update(); } + void TimelineViewport::setBackgroundOptions(const timeline::BackgroundOptions& value) + { + TLRENDER_P(); + if (value == p.backgroundOptions) + return; + p.backgroundOptions = value; + p.doRender = true; + update(); + } + void TimelineViewport::setTimelinePlayers(const QVector >& value) { TLRENDER_P(); @@ -419,25 +419,6 @@ namespace tl p.render->begin(viewportSize); p.render->setOCIOOptions(p.ocioOptions); p.render->setLUTOptions(p.lutOptions); - switch (p.backgroundOptions.type) - { - case timeline::Background::Solid: - p.render->clearViewport( - p.backgroundOptions.solidColor); - break; - case timeline::Background::Checkers: - p.render->clearViewport(image::Color4f(0.F, 0.F, 0.F)); - p.render->drawColorMesh( - ui::checkers( - math::Box2i(0, 0, viewportSize.w, viewportSize.h), - p.backgroundOptions.checkersColor0, - p.backgroundOptions.checkersColor1, - p.backgroundOptions.checkersSize), - math::Vector2i(), - image::Color4f(1.F, 1.F, 1.F)); - break; - default: break; - } if (!p.videoData.empty()) { math::Matrix4x4f vm; @@ -456,7 +437,8 @@ namespace tl timeline::getBoxes(p.compareOptions.mode, p.timelineSizes), p.imageOptions, p.displayOptions, - p.compareOptions); + p.compareOptions, + p.backgroundOptions); _droppedFramesUpdate(p.videoData[0].time); } diff --git a/lib/tlQtWidget/TimelineViewport.h b/lib/tlQtWidget/TimelineViewport.h index f4a5f1063..16c0a2a79 100644 --- a/lib/tlQtWidget/TimelineViewport.h +++ b/lib/tlQtWidget/TimelineViewport.h @@ -35,9 +35,6 @@ namespace tl virtual ~TimelineViewport(); - //! Set the background options. - void setBackgroundOptions(const timeline::BackgroundOptions&); - //! Set the OpenColorIO options. void setOCIOOptions(const timeline::OCIOOptions&); @@ -53,6 +50,9 @@ namespace tl //! Set the comparison options. void setCompareOptions(const timeline::CompareOptions&); + //! Set the background options. + void setBackgroundOptions(const timeline::BackgroundOptions&); + //! Set the timeline players. void setTimelinePlayers(const QVector >&); diff --git a/lib/tlTimeline/BackgroundOptions.cpp b/lib/tlTimeline/BackgroundOptions.cpp index 0edd303d5..4c113c07f 100644 --- a/lib/tlTimeline/BackgroundOptions.cpp +++ b/lib/tlTimeline/BackgroundOptions.cpp @@ -14,7 +14,8 @@ namespace tl TLRENDER_ENUM_IMPL( Background, "Solid", - "Checkers"); + "Checkers", + "Gradient"); TLRENDER_ENUM_SERIALIZE_IMPL(Background); void to_json(nlohmann::json& json, const BackgroundOptions& in) @@ -22,9 +23,8 @@ namespace tl json = nlohmann::json { { "type", in.type }, - { "solidColor", in.solidColor }, - { "checkersColor0", in.checkersColor0 }, - { "checkersColor1", in.checkersColor1 }, + { "color0", in.color0 }, + { "color1", in.color1 }, { "checkersSize", in.checkersSize }, }; } @@ -32,9 +32,8 @@ namespace tl void from_json(const nlohmann::json& json, BackgroundOptions& out) { json.at("type").get_to(out.type); - json.at("solidColor").get_to(out.solidColor); - json.at("checkersColor0").get_to(out.checkersColor0); - json.at("checkersColor1").get_to(out.checkersColor1); + json.at("color0").get_to(out.color0); + json.at("color1").get_to(out.color1); json.at("checkersSize").get_to(out.checkersSize); } } diff --git a/lib/tlTimeline/BackgroundOptions.h b/lib/tlTimeline/BackgroundOptions.h index 84deb9093..4d4771e17 100644 --- a/lib/tlTimeline/BackgroundOptions.h +++ b/lib/tlTimeline/BackgroundOptions.h @@ -17,6 +17,7 @@ namespace tl { Solid, Checkers, + Gradient, Count, First = Solid @@ -27,11 +28,10 @@ namespace tl //! Background options. struct BackgroundOptions { - Background type = Background::Solid; - image::Color4f solidColor = image::Color4f(0.F, 0.F, 0.F); - image::Color4f checkersColor0 = image::Color4f(1.F, 1.F, 1.F); - image::Color4f checkersColor1 = image::Color4f(0.F, 0.F, 0.F); - math::Size2i checkersSize = math::Size2i(100, 100); + Background type = Background::Solid; + image::Color4f color0 = image::Color4f(0.F, 0.F, 0.F); + image::Color4f color1 = image::Color4f(0.F, 0.F, 0.F); + math::Size2i checkersSize = math::Size2i(100, 100); bool operator == (const BackgroundOptions&) const; bool operator != (const BackgroundOptions&) const; diff --git a/lib/tlTimeline/BackgroundOptionsInline.h b/lib/tlTimeline/BackgroundOptionsInline.h index bedfd5e82..45206430f 100644 --- a/lib/tlTimeline/BackgroundOptionsInline.h +++ b/lib/tlTimeline/BackgroundOptionsInline.h @@ -10,9 +10,8 @@ namespace tl { return type == other.type && - solidColor == other.solidColor && - checkersColor0 == other.checkersColor0 && - checkersColor1 == other.checkersColor1 && + color0 == other.color0 && + color1 == other.color1 && checkersSize == other.checkersSize; } diff --git a/lib/tlTimeline/IRender.h b/lib/tlTimeline/IRender.h index 9bc47d493..c5de9b782 100644 --- a/lib/tlTimeline/IRender.h +++ b/lib/tlTimeline/IRender.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include #include @@ -120,7 +121,8 @@ namespace tl const std::vector&, const std::vector& = {}, const std::vector& = {}, - const CompareOptions& = CompareOptions()) = 0; + const CompareOptions& = CompareOptions(), + const BackgroundOptions& = BackgroundOptions()) = 0; protected: std::weak_ptr _context; diff --git a/lib/tlTimelineGL/Render.h b/lib/tlTimelineGL/Render.h index d85de5f7d..fb49dc7a7 100644 --- a/lib/tlTimelineGL/Render.h +++ b/lib/tlTimelineGL/Render.h @@ -91,11 +91,15 @@ namespace tl const std::vector&, const std::vector& = {}, const std::vector& = {}, - const timeline::CompareOptions& = timeline::CompareOptions()) override; + const timeline::CompareOptions& = timeline::CompareOptions(), + const timeline::BackgroundOptions& = timeline::BackgroundOptions()) override; private: void _displayShader(); + void _drawBackground( + const std::vector&, + const timeline::BackgroundOptions&); void _drawVideoA( const std::vector&, const std::vector&, diff --git a/lib/tlTimelineGL/RenderShaders_GL_4_1.cpp b/lib/tlTimelineGL/RenderShaders_GL_4_1.cpp index c98089640..a1be0008e 100644 --- a/lib/tlTimelineGL/RenderShaders_GL_4_1.cpp +++ b/lib/tlTimelineGL/RenderShaders_GL_4_1.cpp @@ -500,7 +500,6 @@ namespace tl " outColor.r = outColor.r * scale + offset;\n" " outColor.g = outColor.g * scale + offset;\n" " outColor.b = outColor.b * scale + offset;\n" - " outColor.a = outColor.a * scale + offset;\n" " }\n" "}\n"). arg(args[0]). diff --git a/lib/tlTimelineGL/RenderVideo.cpp b/lib/tlTimelineGL/RenderVideo.cpp index be873b12f..6da444ddf 100644 --- a/lib/tlTimelineGL/RenderVideo.cpp +++ b/lib/tlTimelineGL/RenderVideo.cpp @@ -19,8 +19,10 @@ namespace tl const std::vector& boxes, const std::vector& imageOptions, const std::vector& displayOptions, - const timeline::CompareOptions& compareOptions) + const timeline::CompareOptions& compareOptions, + const timeline::BackgroundOptions& backgroundOptions) { + _drawBackground(boxes, backgroundOptions); switch (compareOptions.mode) { case timeline::CompareMode::A: @@ -89,6 +91,59 @@ namespace tl } } + void Render::_drawBackground( + const std::vector& boxes, + const timeline::BackgroundOptions& options) + { + for (const auto& box : boxes) + { + switch (options.type) + { + case timeline::Background::Solid: + drawRect(box, options.color0); + break; + case timeline::Background::Checkers: + drawColorMesh( + geom::checkers(box, options.color0, options.color1, options.checkersSize), + math::Vector2i(), + image::Color4f(1.F, 1.F, 1.F)); + break; + case timeline::Background::Gradient: + { + geom::TriangleMesh2 mesh; + mesh.v.push_back(math::Vector2f(box.min.x, box.min.y)); + mesh.v.push_back(math::Vector2f(box.max.x, box.min.y)); + mesh.v.push_back(math::Vector2f(box.max.x, box.max.y)); + mesh.v.push_back(math::Vector2f(box.min.x, box.max.y)); + mesh.c.push_back(math::Vector4f( + options.color0.r, + options.color0.g, + options.color0.b, + options.color0.a)); + mesh.c.push_back(math::Vector4f( + options.color1.r, + options.color1.g, + options.color1.b, + options.color1.a)); + mesh.triangles.push_back({ + geom::Vertex2(1, 0, 1), + geom::Vertex2(2, 0, 1), + geom::Vertex2(3, 0, 2), }); + mesh.triangles.push_back({ + geom::Vertex2(3, 0, 2), + geom::Vertex2(4, 0, 2), + geom::Vertex2(1, 0, 1), }); + drawColorMesh( + mesh, + math::Vector2i(), + image::Color4f(1.F, 1.F, 1.F)); + break; + } + default: break; + } + } + } + void Render::_drawVideoA( const std::vector& videoData, const std::vector& boxes, @@ -692,18 +747,7 @@ namespace tl if (p.buffers["video"]) { - switch (imageOptions ? imageOptions->alphaBlend : timeline::AlphaBlend::Straight) - { - case timeline::AlphaBlend::None: - glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO); - break; - case timeline::AlphaBlend::Straight: - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - break; - case timeline::AlphaBlend::Premultiplied: - glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - break; - } + glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glViewport( viewportPrev[0], diff --git a/lib/tlTimelineUI/TimelineViewport.cpp b/lib/tlTimelineUI/TimelineViewport.cpp index ac6193027..ebfd54317 100644 --- a/lib/tlTimelineUI/TimelineViewport.cpp +++ b/lib/tlTimelineUI/TimelineViewport.cpp @@ -19,7 +19,6 @@ namespace tl { struct TimelineViewport::Private { - timeline::BackgroundOptions backgroundOptions; timeline::OCIOOptions ocioOptions; timeline::LUTOptions lutOptions; timeline::RenderOptions renderOptions; @@ -27,6 +26,7 @@ namespace tl std::vector displayOptions; timeline::CompareOptions compareOptions; std::function compareCallback; + timeline::BackgroundOptions backgroundOptions; std::vector > players; std::vector timelineSizes; std::vector videoData; @@ -97,16 +97,6 @@ namespace tl return out; } - void TimelineViewport::setBackgroundOptions(const timeline::BackgroundOptions& value) - { - TLRENDER_P(); - if (value == p.backgroundOptions) - return; - p.backgroundOptions = value; - p.doRender = true; - _updates |= ui::Update::Draw; - } - void TimelineViewport::setOCIOOptions(const timeline::OCIOOptions& value) { TLRENDER_P(); @@ -162,6 +152,16 @@ namespace tl _p->compareCallback = value; } + void TimelineViewport::setBackgroundOptions(const timeline::BackgroundOptions& value) + { + TLRENDER_P(); + if (value == p.backgroundOptions) + return; + p.backgroundOptions = value; + p.doRender = true; + _updates |= ui::Update::Draw; + } + void TimelineViewport::setPlayers(const std::vector >& value) { TLRENDER_P(); @@ -371,32 +371,7 @@ namespace tl event.render->setRenderSize(size); event.render->setViewport(math::Box2i(0, 0, g.w(), g.h())); event.render->setClipRectEnabled(false); - event.render->setTransform(math::ortho( - 0.F, - static_cast(g.w()), - static_cast(g.h()), - 0.F, - -1.F, - 1.F)); - switch (p.backgroundOptions.type) - { - case timeline::Background::Solid: - event.render->clearViewport( - p.backgroundOptions.solidColor); - break; - case timeline::Background::Checkers: - event.render->clearViewport(image::Color4f(0.F, 0.F, 0.F)); - event.render->drawColorMesh( - ui::checkers( - math::Box2i(0, 0, g.w(), g.h()), - p.backgroundOptions.checkersColor0, - p.backgroundOptions.checkersColor1, - p.backgroundOptions.checkersSize * _displayScale), - math::Vector2i(), - image::Color4f(1.F, 1.F, 1.F)); - break; - default: break; - } + event.render->clearViewport(image::Color4f(0.F, 0.F, 0.F)); event.render->setOCIOOptions(p.ocioOptions); event.render->setLUTOptions(p.lutOptions); if (!p.videoData.empty()) @@ -417,7 +392,8 @@ namespace tl timeline::getBoxes(p.compareOptions.mode, p.timelineSizes), p.imageOptions, p.displayOptions, - p.compareOptions); + p.compareOptions, + p.backgroundOptions); _droppedFramesUpdate(p.videoData[0].time); } @@ -545,6 +521,7 @@ namespace tl case ui::Key::Backspace: event.accept = true; setFrameView(true); + break; default: break; } } diff --git a/lib/tlTimelineUI/TimelineViewport.h b/lib/tlTimelineUI/TimelineViewport.h index a2384323b..9aa69b904 100644 --- a/lib/tlTimelineUI/TimelineViewport.h +++ b/lib/tlTimelineUI/TimelineViewport.h @@ -33,9 +33,6 @@ namespace tl const std::shared_ptr&, const std::shared_ptr& parent = nullptr); - //! Set the background options. - void setBackgroundOptions(const timeline::BackgroundOptions&); - //! Set the OpenColorIO options. void setOCIOOptions(const timeline::OCIOOptions&); @@ -54,6 +51,9 @@ namespace tl //! Set the comparison callback. void setCompareCallback(const std::function&); + //! Set the background options. + void setBackgroundOptions(const timeline::BackgroundOptions&); + //! Set the timeline players. void setPlayers(const std::vector >&); diff --git a/lib/tlUI/DrawUtil.cpp b/lib/tlUI/DrawUtil.cpp index 45de3a723..f49c5051f 100644 --- a/lib/tlUI/DrawUtil.cpp +++ b/lib/tlUI/DrawUtil.cpp @@ -342,77 +342,5 @@ namespace tl return out; } - - geom::TriangleMesh2 checkers( - const math::Box2i& box, - const image::Color4f& color0, - const image::Color4f& color1, - const math::Size2i& checkerSize) - { - geom::TriangleMesh2 out; - - // X points. - std::vector xs; - int x = box.min.x; - for (; x < box.max.x; x += checkerSize.w) - { - xs.push_back(x); - } - if (x >= box.max.x) - { - xs.push_back(box.max.x); - } - - // Y points. - std::vector ys; - int y = box.min.y; - for (; y < box.max.y; y += checkerSize.h) - { - ys.push_back(y); - } - if (y >= box.max.y) - { - ys.push_back(box.max.y); - } - - if (!xs.empty() && !ys.empty()) - { - // 2D points. - for (int j = 0; j < ys.size(); ++j) - { - for (int i = 0; i < xs.size(); ++i) - { - out.v.push_back(math::Vector2f(xs[i], ys[j])); - } - } - - // Colors. - out.c.push_back(math::Vector4f(color0.r, color0.g, color0.b, color0.a)); - out.c.push_back(math::Vector4f(color1.r, color1.g, color1.b, color1.a)); - - // Triangles. - for (int j = 0; j < ys.size() - 1; ++j) - { - for (int i = 0; i < xs.size() - 1; ++i) - { - const int v0 = j * xs.size() + i + 1; - const int v1 = j * xs.size() + (i + 1) + 1; - const int v2 = (j + 1) * xs.size() + (i + 1) + 1; - const int v3 = (j + 1) * xs.size() + i + 1; - const int c = (j + i) % 2 + 1; - out.triangles.push_back({ - geom::Vertex2(v0, 0, c), - geom::Vertex2(v1, 0, c), - geom::Vertex2(v2, 0, c) }); - out.triangles.push_back({ - geom::Vertex2(v2, 0, c), - geom::Vertex2(v3, 0, c), - geom::Vertex2(v0, 0, c) }); - } - } - } - - return out; - } } } diff --git a/lib/tlUI/DrawUtil.h b/lib/tlUI/DrawUtil.h index 049560a95..90883e9d9 100644 --- a/lib/tlUI/DrawUtil.h +++ b/lib/tlUI/DrawUtil.h @@ -37,12 +37,5 @@ namespace tl int cornerRadius, const float alpha = .2F, size_t resolution = 8); - - //! Create a mesh for drawing checkers. - geom::TriangleMesh2 checkers( - const math::Box2i&, - const image::Color4f& color0, - const image::Color4f& color1, - const math::Size2i& checkerSize); } }