From 3af874fe2210ed063ed84fda31060f9a1d2a168f Mon Sep 17 00:00:00 2001 From: Warchamp7 Date: Thu, 13 Feb 2025 15:19:51 -0500 Subject: [PATCH 1/3] frontend: Add OBSSourceWidget --- frontend/cmake/ui-widgets.cmake | 4 + frontend/forms/OBSBasicFilters.ui | 10 +- frontend/widgets/OBSSourceWidget.cpp | 221 +++++++++++++++++++++++ frontend/widgets/OBSSourceWidget.hpp | 57 ++++++ frontend/widgets/OBSSourceWidgetView.cpp | 139 ++++++++++++++ frontend/widgets/OBSSourceWidgetView.hpp | 59 ++++++ 6 files changed, 482 insertions(+), 8 deletions(-) create mode 100644 frontend/widgets/OBSSourceWidget.cpp create mode 100644 frontend/widgets/OBSSourceWidget.hpp create mode 100644 frontend/widgets/OBSSourceWidgetView.cpp create mode 100644 frontend/widgets/OBSSourceWidgetView.hpp diff --git a/frontend/cmake/ui-widgets.cmake b/frontend/cmake/ui-widgets.cmake index dd60fbe4bbef2f..8fd510154422bb 100644 --- a/frontend/cmake/ui-widgets.cmake +++ b/frontend/cmake/ui-widgets.cmake @@ -57,6 +57,10 @@ target_sources( widgets/OBSProjector.hpp widgets/OBSQTDisplay.cpp widgets/OBSQTDisplay.hpp + widgets/OBSSourceWidget.cpp + widgets/OBSSourceWidget.hpp + widgets/OBSSourceWidgetView.cpp + widgets/OBSSourceWidgetView.hpp widgets/StatusBarWidget.cpp widgets/StatusBarWidget.hpp ) diff --git a/frontend/forms/OBSBasicFilters.ui b/frontend/forms/OBSBasicFilters.ui index c9cefaefc973bb..f89830ff9c7ebb 100644 --- a/frontend/forms/OBSBasicFilters.ui +++ b/frontend/forms/OBSBasicFilters.ui @@ -27,7 +27,7 @@ - + 0 0 @@ -249,7 +249,7 @@ - + 0 0 @@ -552,12 +552,6 @@ - - - 0 - 0 - - QFrame::NoFrame diff --git a/frontend/widgets/OBSSourceWidget.cpp b/frontend/widgets/OBSSourceWidget.cpp new file mode 100644 index 00000000000000..33184ed7d64551 --- /dev/null +++ b/frontend/widgets/OBSSourceWidget.cpp @@ -0,0 +1,221 @@ +/****************************************************************************** + Copyright (C) 2026 by Taylor Giampaolo + + 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 2 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 "OBSSourceWidget.hpp" + +#include + +#include +#include +#include + +#include "moc_OBSSourceWidget.cpp" + +constexpr int kMinWidth = 48; +constexpr int kMinHeight = 27; + +OBSSourceWidget::OBSSourceWidget(QWidget *parent) : QFrame(parent), fixedAspectRatio(0.0) +{ + layout = new QVBoxLayout(); + setLayout(layout); + + layout->setContentsMargins(0, 0, 0, 0); + + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + if (window()) { + window()->installEventFilter(this); + } + + if (parent) { + parent->installEventFilter(this); + } + + QObject *checkParent = parent; + + while (checkParent) { + QScrollArea *scrollParent = qobject_cast(checkParent); + if (scrollParent && scrollParent->widget()) { + scrollParent->widget()->installEventFilter(this); + } + + if (!checkParent->parent() || checkParent->parent() == checkParent) { + break; + } + + checkParent = checkParent->parent(); + } +} + +OBSSourceWidget::OBSSourceWidget(QWidget *parent, obs_source_t *source) : OBSSourceWidget(parent) +{ + setSource(source); +} + +void OBSSourceWidget::setFixedAspectRatio(double ratio) +{ + if (ratio > 0.0) { + fixedAspectRatio = ratio; + } else { + fixedAspectRatio = 0; + } +} + +void OBSSourceWidget::setSource(obs_source_t *source) +{ + if (!sourceView) { + sourceView = new OBSSourceWidgetView(this, source); + layout->addWidget(sourceView); + + connect(sourceView, &OBSSourceWidgetView::viewReady, this, [this]() { + updateGeometry(); + resizeSourceView(); + }); + } + + sourceView->setSource(source); +} + +void OBSSourceWidget::setForceLinearSRGB(bool enable) +{ + if (!sourceView) { + return; + } + + sourceView->setForceLinearSRGB(enable); +} + +void OBSSourceWidget::resizeSourceView() +{ + if (!sourceView) { + return; + } + + if (sourceView->sourceWidth() <= 0 || sourceView->sourceHeight() <= 0) { + return; + } + + const double aspectRatio = fixedAspectRatio > 0 + ? fixedAspectRatio + : (double)sourceView->sourceWidth() / (double)sourceView->sourceHeight(); + + // Widget only expands in one direction + const bool singleExpandDirection = (sizePolicy().horizontalPolicy() & QSizePolicy::ExpandFlag) != + (sizePolicy().verticalPolicy() & QSizePolicy::ExpandFlag); + + const int scaledWidth = std::floor(height() / aspectRatio); + const int scaledHeight = std::floor(width() / aspectRatio); + + if (fixedAspectRatio) { + setMaximumWidth(QWIDGETSIZE_MAX); + setMaximumHeight(scaledHeight); + } else if (singleExpandDirection) { + setMaximumWidth(QWIDGETSIZE_MAX); + setMaximumHeight(QWIDGETSIZE_MAX); + + if ((sizePolicy().horizontalPolicy() & QSizePolicy::ExpandFlag) == QSizePolicy::ExpandFlag) { + setMaximumHeight(scaledHeight); + } else { + setMaximumWidth(scaledWidth); + } + } + + QWindow *nativeWindow = sourceView->windowHandle(); + QRegion visible = sourceView->visibleRegion(); + if (nativeWindow) { + QPoint position = sourceView->mapTo(sourceView->nativeParentWidget(), QPoint()); + nativeWindow->setGeometry(QRect(position, sourceView->geometry().size())); + + if (!visible.isNull()) { + if (visible.boundingRect().width() > 0 && visible.boundingRect().height() > 0) { + nativeWindow->setMask(visible.boundingRect()); + } + } else { + nativeWindow->setMask(QRegion(0, 0, 1, 1)); + } + } +} + +QSize OBSSourceWidget::minimumSizeHint() const +{ + if (fixedAspectRatio > 0.0) { + const int width = int(kMinHeight * fixedAspectRatio); + + return QSize(width, kMinHeight); + } + + return QSize(kMinWidth, kMinHeight); +} + +QSize OBSSourceWidget::sizeHint() const +{ + if (sourceView) { + const int width = sourceView->sourceWidth(); + const int height = sourceView->sourceHeight(); + + if (width > 0 && height > 0) { + return QSize(width, height); + } + } + + return QSize(kMinWidth, kMinHeight); +} + +bool OBSSourceWidget::hasHeightForWidth() const +{ + return true; +} + +int OBSSourceWidget::heightForWidth(int width) const +{ + double aspectRatio = fixedAspectRatio; + + if (aspectRatio <= 0.0 && sourceView && sourceView->sourceWidth() > 0 && sourceView->sourceHeight() > 0) { + aspectRatio = double(sourceView->sourceWidth()) / double(sourceView->sourceHeight()); + } + + if (aspectRatio <= 0.0) { + aspectRatio = 16.0 / 9.0; + } + + return int(width / aspectRatio); +} + +bool OBSSourceWidget::eventFilter(QObject *, QEvent *event) +{ + if (event->type() == QEvent::Resize) { + resizeSourceView(); + } else if (event->type() == QEvent::Move) { + resizeSourceView(); + } + + return false; +} + +void OBSSourceWidget::moveEvent(QMoveEvent *event) +{ + QFrame::moveEvent(event); + resizeSourceView(); +} + +void OBSSourceWidget::resizeEvent(QResizeEvent *event) +{ + QFrame::resizeEvent(event); + resizeSourceView(); +} + +OBSSourceWidget::~OBSSourceWidget() {} diff --git a/frontend/widgets/OBSSourceWidget.hpp b/frontend/widgets/OBSSourceWidget.hpp new file mode 100644 index 00000000000000..352938b76f7072 --- /dev/null +++ b/frontend/widgets/OBSSourceWidget.hpp @@ -0,0 +1,57 @@ +/****************************************************************************** + Copyright (C) 2026 by Taylor Giampaolo + + 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 2 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 . +******************************************************************************/ + +#pragma once + +#include + +#include + +class OBSSourceWidgetView; +class QVBoxLayout; + +class OBSSourceWidget : public QFrame { + Q_OBJECT + +private: + OBSSourceWidgetView *sourceView = nullptr; + QVBoxLayout *layout; + + double fixedAspectRatio; + +public: + OBSSourceWidget(QWidget *parent); + OBSSourceWidget(QWidget *parent, obs_source_t *source); + ~OBSSourceWidget(); + + void setFixedAspectRatio(double ratio); + void setSource(obs_source_t *source); + + void setForceLinearSRGB(bool enable); + + void resizeSourceView(); + + QSize minimumSizeHint() const override; + QSize sizeHint() const override; + bool hasHeightForWidth() const override; + int heightForWidth(int width) const override; + +protected: + bool eventFilter(QObject *obj, QEvent *event) override; + void moveEvent(QMoveEvent *event) override; + void resizeEvent(QResizeEvent *event) override; +}; diff --git a/frontend/widgets/OBSSourceWidgetView.cpp b/frontend/widgets/OBSSourceWidgetView.cpp new file mode 100644 index 00000000000000..4e72a5f83bf869 --- /dev/null +++ b/frontend/widgets/OBSSourceWidgetView.cpp @@ -0,0 +1,139 @@ +/****************************************************************************** + Copyright (C) 2026 by Taylor Giampaolo + + 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 2 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 "OBSSourceWidgetView.hpp" + +#include +#include + +OBSSourceWidgetView::OBSSourceWidgetView(OBSSourceWidget *widget, obs_source_t *source) + : OBSQTDisplay(widget, Qt::Widget) +{ + setSource(source); + show(); +} + +OBSSourceWidgetView::~OBSSourceWidgetView() +{ + obs_display_remove_draw_callback(GetDisplay(), obsRender, this); + + OBSSource source = getSource(); + if (source) { + obs_source_dec_showing(source); + } +} + +void OBSSourceWidgetView::setSourceWidth(int width) +{ + if (sourceWidth() == width) { + return; + } + + sourceWidth_ = width; + emit viewReady(); +} + +void OBSSourceWidgetView::setSourceHeight(int height) +{ + if (sourceHeight() == height) { + return; + } + + sourceHeight_ = height; + emit viewReady(); +} + +void OBSSourceWidgetView::setForceLinearSRGB(bool enable) +{ + forceLinearSRGB = enable; +} + +OBSSource OBSSourceWidgetView::getSource() +{ + return OBSGetStrongRef(weakSource); +} + +void OBSSourceWidgetView::obsRender(void *data, uint32_t cx, uint32_t cy) +{ + OBSSourceWidgetView *view = reinterpret_cast(data); + + OBSSource source = view->getSource(); + if (!source) { + return; + } + + uint32_t sourceCX = std::max(obs_source_get_width(source), 1u); + uint32_t sourceCY = std::max(obs_source_get_height(source), 1u); + + int x, y; + int newCX, newCY; + float scale; + + GetScaleAndCenterPos(sourceCX, sourceCY, cx, cy, x, y, scale); + + newCX = int(scale * float(sourceCX)); + newCY = int(scale * float(sourceCY)); + + gs_viewport_push(); + gs_projection_push(); + + bool previous = false; + if (view->forceLinearSRGB) { + previous = gs_set_linear_srgb(true); + } + + gs_ortho(0.0f, float(sourceCX), 0.0f, float(sourceCY), -100.0f, 100.0f); + gs_set_viewport(x, y, newCX, newCY); + obs_source_video_render(source); + + if (view->forceLinearSRGB) { + gs_set_linear_srgb(previous); + } + gs_projection_pop(); + gs_viewport_pop(); + + view->setSourceWidth(sourceCX); + view->setSourceHeight(sourceCY); +} + +void OBSSourceWidgetView::setSource(obs_source_t *source) +{ + if (weakSource) { + obs_source_t *prevSource = OBSGetStrongRef(weakSource); + if (prevSource) { + obs_source_dec_showing(prevSource); + } + } + + weakSource = OBSGetWeakRef(source); + obs_source_inc_showing(source); + + enum obs_source_type type = obs_source_get_type(source); + bool isDrawableType = type == OBS_SOURCE_TYPE_INPUT || type == OBS_SOURCE_TYPE_SCENE || + type == OBS_SOURCE_TYPE_TRANSITION; + + auto addDrawCallback = [this]() { + obs_display_add_draw_callback(GetDisplay(), obsRender, this); + }; + + uint32_t caps = obs_source_get_output_flags(source); + if ((caps & OBS_SOURCE_VIDEO) != 0) { + if (isDrawableType) { + connect(this, &OBSQTDisplay::DisplayCreated, this, addDrawCallback); + } + } +} diff --git a/frontend/widgets/OBSSourceWidgetView.hpp b/frontend/widgets/OBSSourceWidgetView.hpp new file mode 100644 index 00000000000000..3aa26fff714076 --- /dev/null +++ b/frontend/widgets/OBSSourceWidgetView.hpp @@ -0,0 +1,59 @@ +/****************************************************************************** + Copyright (C) 2026 by Taylor Giampaolo + + 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 2 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 . +******************************************************************************/ + +#pragma once + +#include +#include + +#include +#include + +class OBSSourceWidget; + +class OBSSourceWidgetView : public OBSQTDisplay { + Q_OBJECT + +private: + OBSWeakSource weakSource = nullptr; + + static void obsRender(void *data, uint32_t cx, uint32_t cy); + + QRect prevGeometry; + + int32_t sourceWidth_; + int32_t sourceHeight_; + + bool forceLinearSRGB; + +public: + OBSSourceWidgetView(OBSSourceWidget *parent, obs_source_t *source); + ~OBSSourceWidgetView(); + + void setSource(obs_source_t *source); + void setSourceWidth(int width); + void setSourceHeight(int height); + int sourceWidth() const { return sourceWidth_; } + int sourceHeight() const { return sourceHeight_; } + + void setForceLinearSRGB(bool enable); + + OBSSource getSource(); + +signals: + void viewReady(); +}; From ade47e7d1550e4c1460feaa8deac9e5f5993a108 Mon Sep 17 00:00:00 2001 From: Warchamp7 Date: Sat, 9 May 2026 17:01:59 -0400 Subject: [PATCH 2/3] frontend: Use SourceWidget in Filters window --- frontend/dialogs/OBSBasicFilters.cpp | 76 +++------------------------- frontend/dialogs/OBSBasicFilters.hpp | 4 +- frontend/forms/OBSBasicFilters.ui | 53 ------------------- 3 files changed, 8 insertions(+), 125 deletions(-) diff --git a/frontend/dialogs/OBSBasicFilters.cpp b/frontend/dialogs/OBSBasicFilters.cpp index e34e6b5c92fb06..299340cb97e2de 100644 --- a/frontend/dialogs/OBSBasicFilters.cpp +++ b/frontend/dialogs/OBSBasicFilters.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -122,22 +123,13 @@ OBSBasicFilters::OBSBasicFilters(QWidget *parent, OBSSource source_) obs_source_inc_showing(source); - auto addDrawCallback = [this]() { - obs_display_add_draw_callback(ui->preview->GetDisplay(), OBSBasicFilters::DrawPreview, this); - }; + auto *previewWidget = new OBSSourceWidget(this, source_); + ui->rightLayout->insertWidget(0, previewWidget); - enum obs_source_type type = obs_source_get_type(source); - bool drawable_type = type == OBS_SOURCE_TYPE_INPUT || type == OBS_SOURCE_TYPE_SCENE; + previewWidget->resize(width(), ui->rightLayout->height() / 2); - if ((caps & OBS_SOURCE_VIDEO) != 0) { - ui->rightLayout->setContentsMargins(0, 0, 0, 0); - ui->preview->show(); - if (drawable_type) - connect(ui->preview, &OBSQTDisplay::DisplayCreated, this, addDrawCallback); - } else { - ui->rightLayout->setContentsMargins(0, noPreviewMargin, 0, 0); - ui->preview->hide(); - } + ui->rightLayout->setStretchFactor(0, 2); + ui->rightLayout->setStretchFactor(1, 3); #ifdef __APPLE__ ui->actionRenameFilter->setShortcut({Qt::Key_Return}); @@ -589,33 +581,9 @@ void OBSBasicFilters::closeEvent(QCloseEvent *event) if (!event->isAccepted()) return; - obs_display_remove_draw_callback(ui->preview->GetDisplay(), OBSBasicFilters::DrawPreview, this); - main->SaveProject(); } -bool OBSBasicFilters::nativeEvent(const QByteArray &, void *message, qintptr *) -{ -#ifdef _WIN32 - const MSG &msg = *static_cast(message); - switch (msg.message) { - case WM_MOVE: - for (OBSQTDisplay *const display : findChildren()) { - display->OnMove(); - } - break; - case WM_DISPLAYCHANGE: - for (OBSQTDisplay *const display : findChildren()) { - display->OnDisplayChange(); - } - } -#else - UNUSED_PARAMETER(message); -#endif - - return false; -} - /* OBS Signals */ void OBSBasicFilters::OBSSourceFilterAdded(void *param, calldata_t *data) @@ -652,38 +620,6 @@ void OBSBasicFilters::SourceRenamed(void *param, calldata_t *data) QMetaObject::invokeMethod(static_cast(param), "setWindowTitle", Q_ARG(QString, title)); } -void OBSBasicFilters::DrawPreview(void *data, uint32_t cx, uint32_t cy) -{ - OBSBasicFilters *window = static_cast(data); - - if (!window->source) - return; - - uint32_t sourceCX = max(obs_source_get_width(window->source), 1u); - uint32_t sourceCY = max(obs_source_get_height(window->source), 1u); - - int x, y; - int newCX, newCY; - float scale; - - GetScaleAndCenterPos(sourceCX, sourceCY, cx, cy, x, y, scale); - - newCX = int(scale * float(sourceCX)); - newCY = int(scale * float(sourceCY)); - - gs_viewport_push(); - gs_projection_push(); - const bool previous = gs_set_linear_srgb(true); - - gs_ortho(0.0f, float(sourceCX), 0.0f, float(sourceCY), -100.0f, 100.0f); - gs_set_viewport(x, y, newCX, newCY); - obs_source_video_render(window->source); - - gs_set_linear_srgb(previous); - gs_projection_pop(); - gs_viewport_pop(); -} - /* Qt Slots */ static bool QueryRemove(QWidget *parent, obs_source_t *source) diff --git a/frontend/dialogs/OBSBasicFilters.hpp b/frontend/dialogs/OBSBasicFilters.hpp index 0ec62854c4e03a..a5aef77a1c9f07 100644 --- a/frontend/dialogs/OBSBasicFilters.hpp +++ b/frontend/dialogs/OBSBasicFilters.hpp @@ -19,6 +19,8 @@ #include "ui_OBSBasicFilters.h" +#include + #include class OBSBasic; @@ -50,7 +52,6 @@ class OBSBasicFilters : public QDialog { static void SourceRemoved(void *param, calldata_t *data); static void SourceRenamed(void *param, calldata_t *data); static void UpdateProperties(void *data, calldata_t *params); - static void DrawPreview(void *data, uint32_t cx, uint32_t cy); QMenu *CreateAddFilterPopupMenu(bool async); @@ -121,5 +122,4 @@ private slots: protected: virtual void closeEvent(QCloseEvent *event) override; - virtual bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override; }; diff --git a/frontend/forms/OBSBasicFilters.ui b/frontend/forms/OBSBasicFilters.ui index f89830ff9c7ebb..f29d8a261f151c 100644 --- a/frontend/forms/OBSBasicFilters.ui +++ b/frontend/forms/OBSBasicFilters.ui @@ -504,53 +504,6 @@ false - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 0 - 150 - - - - - - QFrame::NoFrame @@ -644,12 +597,6 @@ - - OBSQTDisplay - QWidget -
widgets/OBSQTDisplay.hpp
- 1 -
FocusList QListWidget From fd10876de03d9e16904f608d0415f6db474363f3 Mon Sep 17 00:00:00 2001 From: Warchamp7 Date: Sat, 9 May 2026 17:02:16 -0400 Subject: [PATCH 3/3] frontend: Use SourceWidget in Properties window --- frontend/dialogs/OBSBasicProperties.cpp | 121 ++++-------------------- frontend/dialogs/OBSBasicProperties.hpp | 5 +- frontend/forms/OBSBasicProperties.ui | 57 +---------- 3 files changed, 20 insertions(+), 163 deletions(-) diff --git a/frontend/dialogs/OBSBasicProperties.cpp b/frontend/dialogs/OBSBasicProperties.cpp index f38cc742be3937..6e3e35bc11f1e7 100644 --- a/frontend/dialogs/OBSBasicProperties.cpp +++ b/frontend/dialogs/OBSBasicProperties.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -59,8 +60,9 @@ OBSBasicProperties::OBSBasicProperties(QWidget *parent, OBSSource source_) ui->setupUi(this); ui->buttonBox->button(QDialogButtonBox::Ok)->setFocus(); - if (cx > 400 && cy > 400) + if (cx > 400 && cy > 400) { resize(cx, cy); + } /* The OBSData constructor increments the reference once */ obs_data_release(oldSettings); @@ -94,21 +96,15 @@ OBSBasicProperties::OBSBasicProperties(QWidget *parent, OBSSource source_) updatePropertiesSignal.Connect(obs_source_get_signal_handler(source), "update_properties", OBSBasicProperties::UpdateProperties, this); - auto addDrawCallback = [this]() { - obs_display_add_draw_callback(ui->preview->GetDisplay(), OBSBasicProperties::DrawPreview, this); - }; - auto addTransitionDrawCallback = [this]() { - obs_display_add_draw_callback(ui->preview->GetDisplay(), OBSBasicProperties::DrawTransitionPreview, - this); - }; uint32_t caps = obs_source_get_output_flags(source); - bool drawable_type = type == OBS_SOURCE_TYPE_INPUT || type == OBS_SOURCE_TYPE_SCENE; - bool drawable_preview = (caps & OBS_SOURCE_VIDEO) != 0; + bool isSourceType = type == OBS_SOURCE_TYPE_INPUT || type == OBS_SOURCE_TYPE_SCENE; + bool hasVideo = (caps & OBS_SOURCE_VIDEO) != 0; - if (drawable_preview && drawable_type) { - ui->preview->show(); - connect(ui->preview, &OBSQTDisplay::DisplayCreated, this, addDrawCallback); + auto *previewWidget = new OBSSourceWidget(this); + ui->windowSplitter->insertWidget(0, previewWidget); + if (hasVideo && isSourceType) { + previewWidget->setSource(source_); } else if (type == OBS_SOURCE_TYPE_TRANSITION) { sourceA = obs_source_create_private("scene", "sourceA", nullptr); sourceB = obs_source_create_private("scene", "sourceB", nullptr); @@ -145,13 +141,17 @@ OBSBasicProperties::OBSBasicProperties(QWidget *parent, OBSSource source_) connect(view, &OBSPropertiesView::Changed, this, updateCallback); - ui->preview->show(); - connect(ui->preview, &OBSQTDisplay::DisplayCreated, this, addTransitionDrawCallback); - + previewWidget->setSource(sourceClone); + previewWidget->setForceLinearSRGB(true); } else { - ui->preview->hide(); + previewWidget->hide(); } + previewWidget->resize(width(), ui->windowSplitter->height() / 2); + + ui->windowSplitter->setStretchFactor(0, 2); + ui->windowSplitter->setStretchFactor(1, 3); + connect(ui->defaultsButton, &QPushButton::clicked, this, &OBSBasicProperties::restoreDefaultsClicked); } @@ -344,75 +344,10 @@ void OBSBasicProperties::on_buttonBox_clicked(QAbstractButton *button) } } -void OBSBasicProperties::DrawPreview(void *data, uint32_t cx, uint32_t cy) -{ - OBSBasicProperties *window = static_cast(data); - - if (!window->source) - return; - - uint32_t sourceCX = max(obs_source_get_width(window->source), 1u); - uint32_t sourceCY = max(obs_source_get_height(window->source), 1u); - - int x, y; - int newCX, newCY; - float scale; - - GetScaleAndCenterPos(sourceCX, sourceCY, cx, cy, x, y, scale); - - newCX = int(scale * float(sourceCX)); - newCY = int(scale * float(sourceCY)); - - gs_viewport_push(); - gs_projection_push(); - const bool previous = gs_set_linear_srgb(true); - - gs_ortho(0.0f, float(sourceCX), 0.0f, float(sourceCY), -100.0f, 100.0f); - gs_set_viewport(x, y, newCX, newCY); - obs_source_video_render(window->source); - - gs_set_linear_srgb(previous); - gs_projection_pop(); - gs_viewport_pop(); -} - -void OBSBasicProperties::DrawTransitionPreview(void *data, uint32_t cx, uint32_t cy) -{ - OBSBasicProperties *window = static_cast(data); - - if (!window->sourceClone) - return; - - uint32_t sourceCX = max(obs_source_get_width(window->sourceClone), 1u); - uint32_t sourceCY = max(obs_source_get_height(window->sourceClone), 1u); - - int x, y; - int newCX, newCY; - float scale; - - GetScaleAndCenterPos(sourceCX, sourceCY, cx, cy, x, y, scale); - - newCX = int(scale * float(sourceCX)); - newCY = int(scale * float(sourceCY)); - - gs_viewport_push(); - gs_projection_push(); - gs_ortho(0.0f, float(sourceCX), 0.0f, float(sourceCY), -100.0f, 100.0f); - gs_set_viewport(x, y, newCX, newCY); - - obs_source_video_render(window->sourceClone); - - gs_projection_pop(); - gs_viewport_pop(); -} - void OBSBasicProperties::Cleanup() { config_set_int(App()->GetAppConfig(), "PropertiesWindow", "cx", width()); config_set_int(App()->GetAppConfig(), "PropertiesWindow", "cy", height()); - - obs_display_remove_draw_callback(ui->preview->GetDisplay(), OBSBasicProperties::DrawPreview, this); - obs_display_remove_draw_callback(ui->preview->GetDisplay(), OBSBasicProperties::DrawTransitionPreview, this); } void OBSBasicProperties::reject() @@ -434,28 +369,6 @@ void OBSBasicProperties::closeEvent(QCloseEvent *event) Cleanup(); } -bool OBSBasicProperties::nativeEvent(const QByteArray &, void *message, qintptr *) -{ -#ifdef _WIN32 - const MSG &msg = *static_cast(message); - switch (msg.message) { - case WM_MOVE: - for (OBSQTDisplay *const display : findChildren()) { - display->OnMove(); - } - break; - case WM_DISPLAYCHANGE: - for (OBSQTDisplay *const display : findChildren()) { - display->OnDisplayChange(); - } - } -#else - UNUSED_PARAMETER(message); -#endif - - return false; -} - void OBSBasicProperties::Init() { show(); diff --git a/frontend/dialogs/OBSBasicProperties.hpp b/frontend/dialogs/OBSBasicProperties.hpp index 559b0579c0e666..9442f051ef33d6 100644 --- a/frontend/dialogs/OBSBasicProperties.hpp +++ b/frontend/dialogs/OBSBasicProperties.hpp @@ -19,6 +19,8 @@ #include "ui_OBSBasicProperties.h" +#include + #include class OBSBasic; @@ -49,8 +51,6 @@ class OBSBasicProperties : public QDialog { static void SourceRemoved(void *data, calldata_t *params); static void SourceRenamed(void *data, calldata_t *params); static void UpdateProperties(void *data, calldata_t *params); - static void DrawPreview(void *data, uint32_t cx, uint32_t cy); - static void DrawTransitionPreview(void *data, uint32_t cx, uint32_t cy); void UpdateCallback(void *obj, obs_data_t *settings); bool ConfirmQuit(); int CheckSettings(); @@ -69,6 +69,5 @@ private slots: protected: virtual void closeEvent(QCloseEvent *event) override; - virtual bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override; virtual void reject() override; }; diff --git a/frontend/forms/OBSBasicProperties.ui b/frontend/forms/OBSBasicProperties.ui index 4688df43d2617d..026d2cb37b8dc0 100644 --- a/frontend/forms/OBSBasicProperties.ui +++ b/frontend/forms/OBSBasicProperties.ui @@ -31,56 +31,9 @@ false - - - - 0 - 1 - - - - QFrame::NoFrame - - - QFrame::Plain - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 1 - - - - - 20 - 150 - - - - - - - + 0 1 @@ -164,14 +117,6 @@
- - - OBSQTDisplay - QWidget -
widgets/OBSQTDisplay.hpp
- 1 -
-