From 81fa608cdebd431d8eed157815bd9ebea17b9156 Mon Sep 17 00:00:00 2001 From: Warchamp7 Date: Wed, 31 Jul 2024 10:53:59 -0400 Subject: [PATCH] UI: Add preview scrollbars This adds scrollbars to the preview, so users can move around the preview without using the spacebar + clicking. Co-Authored-By: Clayton Groeneveld <19962531+cg2121@users.noreply.github.com> --- UI/cmake/legacy.cmake | 2 + UI/cmake/ui-elements.cmake | 2 + UI/data/locale/en-US.ini | 1 + UI/data/themes/Yami.obt | 53 +++++++++ UI/forms/OBSBasic.ui | 217 ++++++++++++++++++++++++++++-------- UI/preview-controls.cpp | 137 +++++++++++++++++++++++ UI/preview-controls.hpp | 81 ++++++++++++++ UI/window-basic-main.cpp | 77 ++++++++++++- UI/window-basic-main.hpp | 12 ++ UI/window-basic-preview.cpp | 84 ++++++++++++++ UI/window-basic-preview.hpp | 25 ++++- 11 files changed, 638 insertions(+), 53 deletions(-) create mode 100644 UI/preview-controls.cpp create mode 100644 UI/preview-controls.hpp diff --git a/UI/cmake/legacy.cmake b/UI/cmake/legacy.cmake index c38c11d3e..d25e900db 100644 --- a/UI/cmake/legacy.cmake +++ b/UI/cmake/legacy.cmake @@ -211,6 +211,8 @@ target_sources( menu-button.hpp mute-checkbox.hpp noncheckable-button.hpp + preview-controls.cpp + preview-controls.hpp remote-text.cpp remote-text.hpp scene-tree.cpp diff --git a/UI/cmake/ui-elements.cmake b/UI/cmake/ui-elements.cmake index 2a93088ae..99d4060ec 100644 --- a/UI/cmake/ui-elements.cmake +++ b/UI/cmake/ui-elements.cmake @@ -58,6 +58,8 @@ target_sources( menu-button.hpp mute-checkbox.hpp noncheckable-button.hpp + preview-controls.cpp + preview-controls.hpp remote-text.cpp remote-text.hpp scene-tree.cpp diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index b3303340c..04f0e0a61 100644 --- a/UI/data/locale/en-US.ini +++ b/UI/data/locale/en-US.ini @@ -785,6 +785,7 @@ Basic.MainMenu.Edit.Scale="Preview &Scaling" Basic.MainMenu.Edit.Scale.Window="Scale to Window" Basic.MainMenu.Edit.Scale.Canvas="Canvas (%1x%2)" Basic.MainMenu.Edit.Scale.Output="Output (%1x%2)" +Basic.MainMenu.Edit.Scale.Manual="Scaled (%1x%2)" Basic.MainMenu.Edit.Transform="&Transform" Basic.MainMenu.Edit.Transform.EditTransform="&Edit Transform..." Basic.MainMenu.Edit.Transform.CopyTransform="Copy Transform" diff --git a/UI/data/themes/Yami.obt b/UI/data/themes/Yami.obt index b97f65abe..7c515f5bd 100644 --- a/UI/data/themes/Yami.obt +++ b/UI/data/themes/Yami.obt @@ -105,6 +105,7 @@ --font_base: calc(1pt * var(--font_base_value)); --font_small: calc(0.9pt * var(--font_base_value)); + --font_xsmall: calc(0.85pt * var(--font_base_value)); --font_large: calc(1.1pt * var(--font_base_value)); --font_xlarge: calc(1.5pt * var(--font_base_value)); @@ -634,6 +635,11 @@ QScrollBar::handle:horizontal { min-width: 32px; } +QScrollBar::handle:disabled { + background: transparent; + border-color: transparent; +} + /* Source Context Bar */ #contextContainer { @@ -1963,3 +1969,50 @@ OBSBasicStats { OBSBasicAdvAudio #scrollAreaWidgetContents { background: var(--bg_base); } + +#previewScalePercent, +#previewScalingMode { + background: transparent; + color: var(--text_muted); + font-size: var(--font_xsmall); + height: 14px; + max-height: 14px; + padding: 0px var(--padding_xlarge); + margin: 0; + border: none; + border-radius: 0; +} + +#previewXContainer { + border: 1px solid var(--grey6); +} + +#previewScalingMode { + border: 1px solid var(--grey6); +} + +#previewScalingMode:hover, +#previewScalingMode:focus { + border-color: var(--input_border_hover); +} + +#previewXScrollBar, +#previewYScrollBar { + background: transparent; + border: 1px solid var(--grey6); + border-radius: 0; +} + +#previewXScrollBar { + border-left: none; + height: 16px; +} + +#previewXScrollBar::handle, +#previewYScrollBar::handle { + margin: 3px; +} + +#previewYScrollBar { + width: 16px; +} \ No newline at end of file diff --git a/UI/forms/OBSBasic.ui b/UI/forms/OBSBasic.ui index 052d86735..b97fe0950 100644 --- a/UI/forms/OBSBasic.ui +++ b/UI/forms/OBSBasic.ui @@ -69,6 +69,21 @@ + + 0 + + + 1 + + + 1 + + + 1 + + + 1 + @@ -152,53 +167,151 @@ - - - 0 - - - - - - 0 - 0 - - - - StudioMode.PreviewSceneName - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - previewProgramLabels - - - - - - - - 0 - 0 - - - - - 32 - 32 - - - - Qt::ClickFocus - - - Qt::CustomContextMenu - - - - - + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + StudioMode.PreviewSceneName + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + previewProgramLabels + + + + + + + 0 + + + + + + 0 + 0 + + + + + 32 + 32 + + + + Qt::ClickFocus + + + Qt::CustomContextMenu + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 100% + + + Qt::AlignCenter + + + + + + + + Basic.MainMenu.Edit.Scale.Window + + + + + Basic.MainMenu.Edit.Scale.Canvas + + + + + + + + + 0 + 0 + + + + -200 + + + 200 + + + 10 + + + 100 + + + Qt::Horizontal + + + + + + + + + + Qt::Vertical + + + + + + + @@ -2150,6 +2263,16 @@
window-dock.hpp
1 + + OBSPreviewScalingLabel + QLabel +
preview-controls.hpp
+
+ + OBSPreviewScalingComboBox + QComboBox +
preview-controls.hpp
+
diff --git a/UI/preview-controls.cpp b/UI/preview-controls.cpp new file mode 100644 index 000000000..ba4d6d400 --- /dev/null +++ b/UI/preview-controls.cpp @@ -0,0 +1,137 @@ +/****************************************************************************** + Copyright (C) 2024 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 "preview-controls.hpp" +#include + +/* Preview Scale Label */ +void OBSPreviewScalingLabel::PreviewScaleChanged(float scale) +{ + previewScale = scale; + UpdateScaleLabel(); +} + +void OBSPreviewScalingLabel::UpdateScaleLabel() +{ + float previewScalePercent = floor(100.0f * previewScale); + setText(QString::number(previewScalePercent) + "%"); +} + +/* Preview Scaling ComboBox */ +void OBSPreviewScalingComboBox::PreviewFixedScalingChanged(bool fixed) +{ + if (fixedScaling == fixed) + return; + + fixedScaling = fixed; + UpdateSelection(); +} + +void OBSPreviewScalingComboBox::CanvasResized(uint32_t width, uint32_t height) +{ + SetCanvasSize(width, height); + UpdateCanvasText(); +} + +void OBSPreviewScalingComboBox::OutputResized(uint32_t width, uint32_t height) +{ + SetOutputSize(width, height); + + bool canvasMatchesOutput = output_width == canvas_width && + output_height == canvas_height; + + SetScaleOutputEnabled(!canvasMatchesOutput); + UpdateOutputText(); +} + +void OBSPreviewScalingComboBox::PreviewScaleChanged(float scale) +{ + previewScale = scale; + + if (fixedScaling) { + UpdateSelection(); + UpdateAllText(); + } else { + UpdateScaledText(); + } +} + +void OBSPreviewScalingComboBox::SetScaleOutputEnabled(bool show) +{ + if (scaleOutputEnabled == show) + return; + + scaleOutputEnabled = show; + + if (scaleOutputEnabled) { + addItem(QTStr("Basic.MainMenu.Edit.Scale.Output")); + } else { + removeItem(2); + } +} + +void OBSPreviewScalingComboBox::UpdateAllText() +{ + UpdateCanvasText(); + UpdateOutputText(); + UpdateScaledText(); +} + +void OBSPreviewScalingComboBox::UpdateCanvasText() +{ + QString text = QTStr("Basic.MainMenu.Edit.Scale.Canvas"); + text = text.arg(QString::number(canvas_width), + QString::number(canvas_height)); + setItemText(1, text); +} + +void OBSPreviewScalingComboBox::UpdateOutputText() +{ + if (scaleOutputEnabled) { + QString text = QTStr("Basic.MainMenu.Edit.Scale.Output"); + text = text.arg(QString::number(output_width), + QString::number(output_height)); + setItemText(2, text); + } +} + +void OBSPreviewScalingComboBox::UpdateScaledText() +{ + QString text = QTStr("Basic.MainMenu.Edit.Scale.Manual"); + text = text.arg(QString::number(floor(canvas_width * previewScale)), + QString::number(floor(canvas_height * previewScale))); + setPlaceholderText(text); +} + +void OBSPreviewScalingComboBox::UpdateSelection() +{ + QSignalBlocker sb(this); + float outputScale = float(output_width) / float(canvas_width); + + if (!fixedScaling) { + setCurrentIndex(0); + } else { + if (previewScale == 1.0f) { + setCurrentIndex(1); + } else if (scaleOutputEnabled && + (previewScale == outputScale)) { + setCurrentIndex(2); + } else { + setCurrentIndex(-1); + } + } +} diff --git a/UI/preview-controls.hpp b/UI/preview-controls.hpp new file mode 100644 index 000000000..360d992cd --- /dev/null +++ b/UI/preview-controls.hpp @@ -0,0 +1,81 @@ +/****************************************************************************** + Copyright (C) 2024 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 OBSPreviewScalingLabel : public QLabel { + Q_OBJECT + +public: + OBSPreviewScalingLabel(QWidget *parent = nullptr) : QLabel(parent) {} + +public slots: + void PreviewScaleChanged(float scale); + +private: + float previewScale = 0.0f; + void UpdateScaleLabel(); +}; + +class OBSPreviewScalingComboBox : public QComboBox { + Q_OBJECT + +public: + OBSPreviewScalingComboBox(QWidget *parent = nullptr) : QComboBox(parent) + { + } + + inline void SetCanvasSize(uint32_t width, uint32_t height) + { + canvas_width = width; + canvas_height = height; + }; + inline void SetOutputSize(uint32_t width, uint32_t height) + { + output_width = width; + output_height = height; + }; + void UpdateAllText(); + +public slots: + void PreviewScaleChanged(float scale); + void PreviewFixedScalingChanged(bool fixed); + void CanvasResized(uint32_t width, uint32_t height); + void OutputResized(uint32_t width, uint32_t height); + +private: + uint32_t canvas_width = 0; + uint32_t canvas_height = 0; + + uint32_t output_width = 0; + uint32_t output_height = 0; + + float previewScale = 0.0f; + + bool fixedScaling = false; + + bool scaleOutputEnabled = false; + void SetScaleOutputEnabled(bool show); + + void UpdateCanvasText(); + void UpdateOutputText(); + void UpdateScaledText(); + void UpdateSelection(); +}; diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index 04e71bfff..f131f6f18 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -464,6 +464,7 @@ OBSBasic::OBSBasic(QWidget *parent) ResizePreview(ovi.base_width, ovi.base_height); UpdateContextBarVisibility(); + UpdatePreviewScrollbars(); dpi = devicePixelRatioF(); }; dpi = devicePixelRatioF(); @@ -471,6 +472,30 @@ OBSBasic::OBSBasic(QWidget *parent) connect(windowHandle(), &QWindow::screenChanged, displayResize); connect(ui->preview, &OBSQTDisplay::DisplayResized, displayResize); + /* TODO: Move these into window-basic-preview */ + /* Preview Scaling label */ + connect(ui->preview, &OBSBasicPreview::scalingChanged, + ui->previewScalePercent, + &OBSPreviewScalingLabel::PreviewScaleChanged); + + /* Preview Scaling dropdown */ + connect(ui->preview, &OBSBasicPreview::scalingChanged, + ui->previewScalingMode, + &OBSPreviewScalingComboBox::PreviewScaleChanged); + + connect(ui->preview, &OBSBasicPreview::fixedScalingChanged, + ui->previewScalingMode, + &OBSPreviewScalingComboBox::PreviewFixedScalingChanged); + + connect(ui->previewScalingMode, + &OBSPreviewScalingComboBox::currentIndexChanged, this, + &OBSBasic::PreviewScalingModeChanged); + + connect(this, &OBSBasic::CanvasResized, ui->previewScalingMode, + &OBSPreviewScalingComboBox::CanvasResized); + connect(this, &OBSBasic::OutputResized, ui->previewScalingMode, + &OBSPreviewScalingComboBox::OutputResized); + delete shortcutFilter; shortcutFilter = CreateShortcutFilter(); installEventFilter(shortcutFilter); @@ -1386,6 +1411,7 @@ retryScene: ui->preview->SetScrollingOffset(scrollOffX, scrollOffY); } ui->preview->SetFixedScaling(fixedScaling); + emit ui->preview->DisplayResized(); if (vcamEnabled) { @@ -2176,6 +2202,7 @@ void OBSBasic::OBSInit() InitOBSCallbacks(); InitHotkeys(); + ui->preview->Init(); /* hack to prevent elgato from loading its own QtNetwork that it tries * to ship with */ @@ -4924,6 +4951,9 @@ int OBSBasic::ResetVideo() obs_set_video_levels(sdr_white_level, hdr_nominal_peak_level); OBSBasicStats::InitializeValues(); OBSProjector::UpdateMultiviewProjectors(); + + emit CanvasResized(ovi.base_width, ovi.base_height); + emit OutputResized(ovi.output_width, ovi.output_height); } return ret; @@ -5013,8 +5043,10 @@ void OBSBasic::ResizePreview(uint32_t cx, uint32_t cy) obs_get_video_info(&ovi); if (isFixedScaling) { - ui->preview->ClampScrollingOffsets(); previewScale = ui->preview->GetScalingAmount(); + + ui->preview->ClampScrollingOffsets(); + GetCenterPosFromFixedScale( int(cx), int(cy), targetSize.width() - PREVIEW_EDGE_SIZE * 2, @@ -5031,6 +5063,8 @@ void OBSBasic::ResizePreview(uint32_t cx, uint32_t cy) previewX, previewY, previewScale); } + ui->preview->SetScalingAmount(previewScale); + previewX += float(PREVIEW_EDGE_SIZE); previewY += float(PREVIEW_EDGE_SIZE); } @@ -9169,7 +9203,7 @@ void OBSBasic::on_actionHorizontalCenter_triggered() void OBSBasic::EnablePreviewDisplay(bool enable) { obs_display_set_enabled(ui->preview->GetDisplay(), enable); - ui->preview->setVisible(enable); + ui->previewContainer->setVisible(enable); ui->previewDisabledWidget->setVisible(!enable); } @@ -9765,6 +9799,7 @@ void OBSBasic::on_actionScaleWindow_triggered() { ui->preview->SetFixedScaling(false); ui->preview->ResetScrollingOffset(); + emit ui->preview->DisplayResized(); } @@ -9772,6 +9807,7 @@ void OBSBasic::on_actionScaleCanvas_triggered() { ui->preview->SetFixedScaling(true); ui->preview->SetScalingLevel(0); + emit ui->preview->DisplayResized(); } @@ -9785,8 +9821,8 @@ void OBSBasic::on_actionScaleOutput_triggered() // log base ZOOM_SENSITIVITY of x = log(x) / log(ZOOM_SENSITIVITY) int32_t approxScalingLevel = int32_t(round(log(scalingAmount) / log(ZOOM_SENSITIVITY))); - ui->preview->SetScalingLevel(approxScalingLevel); - ui->preview->SetScalingAmount(scalingAmount); + ui->preview->SetScalingLevelAndAmount(approxScalingLevel, + scalingAmount); emit ui->preview->DisplayResized(); } @@ -11093,3 +11129,36 @@ void OBSBasic::OnEvent(enum obs_frontend_event event) if (api) api->on_event(event); } + +void OBSBasic::UpdatePreviewScrollbars() +{ + if (!ui->preview->IsFixedScaling()) { + ui->previewXScrollBar->setRange(0, 0); + ui->previewYScrollBar->setRange(0, 0); + } +} + +void OBSBasic::on_previewXScrollBar_valueChanged(int value) +{ + emit PreviewXScrollBarMoved(value); +} + +void OBSBasic::on_previewYScrollBar_valueChanged(int value) +{ + emit PreviewYScrollBarMoved(value); +} + +void OBSBasic::PreviewScalingModeChanged(int value) +{ + switch (value) { + case 0: + on_actionScaleWindow_triggered(); + break; + case 1: + on_actionScaleCanvas_triggered(); + break; + case 2: + on_actionScaleOutput_triggered(); + break; + }; +} diff --git a/UI/window-basic-main.hpp b/UI/window-basic-main.hpp index de11ea29d..aaca40237 100644 --- a/UI/window-basic-main.hpp +++ b/UI/window-basic-main.hpp @@ -670,6 +670,7 @@ private: std::string lastReplay; void UpdatePreviewOverflowSettings(); + void UpdatePreviewScrollbars(); bool streamingStarting = false; @@ -810,6 +811,11 @@ private slots: void AudioMixerPasteFilters(); void SourcePasteFilters(OBSSource source, OBSSource dstSource); + void on_previewXScrollBar_valueChanged(int value); + void on_previewYScrollBar_valueChanged(int value); + + void PreviewScalingModeChanged(int value); + void ColorChange(); SourceTreeItem *GetItemWidgetFromSceneItem(obs_sceneitem_t *sceneItem); @@ -1292,6 +1298,12 @@ signals: /* Studio Mode signal */ void PreviewProgramModeChanged(bool enabled); + void CanvasResized(uint32_t width, uint32_t height); + void OutputResized(uint32_t width, uint32_t height); + + /* Preview signals */ + void PreviewXScrollBarMoved(int value); + void PreviewYScrollBarMoved(int value); private: std::unique_ptr ui; diff --git a/UI/window-basic-preview.cpp b/UI/window-basic-preview.cpp index 848ce2ad8..7d6ced49b 100644 --- a/UI/window-basic-preview.cpp +++ b/UI/window-basic-preview.cpp @@ -39,6 +39,15 @@ OBSBasicPreview::~OBSBasicPreview() obs_leave_graphics(); } +void OBSBasicPreview::Init() +{ + OBSBasic *main = OBSBasic::Get(); + connect(main, &OBSBasic::PreviewXScrollBarMoved, this, + &OBSBasicPreview::XScrollBarMoved); + connect(main, &OBSBasic::PreviewYScrollBarMoved, this, + &OBSBasicPreview::YScrollBarMoved); +} + vec2 OBSBasicPreview::GetMouseEventPos(QMouseEvent *event) { OBSBasic *main = reinterpret_cast(App()->GetMainWindow()); @@ -2327,7 +2336,21 @@ void OBSBasicPreview::SetScalingAmount(float newScalingAmountVal) { scrollingOffset.x *= newScalingAmountVal / scalingAmount; scrollingOffset.y *= newScalingAmountVal / scalingAmount; + + if (scalingAmount == newScalingAmountVal) + return; + scalingAmount = newScalingAmountVal; + emit scalingChanged(scalingAmount); +} + +void OBSBasicPreview::SetScalingLevelAndAmount(int32_t newScalingLevelVal, + float newScalingAmountVal) +{ + newScalingLevelVal = std::clamp(newScalingLevelVal, -MAX_SCALING_LEVEL, + MAX_SCALING_LEVEL); + scalingLevel = newScalingLevelVal; + SetScalingAmount(newScalingAmountVal); } OBSBasicPreview *OBSBasicPreview::Get() @@ -2689,4 +2712,65 @@ void OBSBasicPreview::ClampScrollingOffsets() scrollingOffset.x = std::clamp(scrollingOffset.x, -offset.x, offset.x); scrollingOffset.y = std::clamp(scrollingOffset.y, -offset.y, offset.y); + + UpdateXScrollBar(offset.x); + UpdateYScrollBar(offset.y); +} + +void OBSBasicPreview::XScrollBarMoved(int value) +{ + updatingXScrollBar = true; + scrollingOffset.x = float(-value); + + emit DisplayResized(); + updatingXScrollBar = false; +} + +void OBSBasicPreview::YScrollBarMoved(int value) +{ + updatingYScrollBar = true; + scrollingOffset.y = float(-value); + + emit DisplayResized(); + updatingYScrollBar = false; +} + +void OBSBasicPreview::UpdateXScrollBar(float cx) +{ + if (updatingXScrollBar) + return; + + OBSBasic *main = OBSBasic::Get(); + + if (!main->ui->previewXScrollBar->isVisible()) + return; + + main->ui->previewXScrollBar->setRange(int(-cx), int(cx)); + + QSize targetSize = GetPixelSize(this); + main->ui->previewXScrollBar->setPageStep(targetSize.width() / + std::min(scalingAmount, 1.0f)); + + QSignalBlocker sig(main->ui->previewXScrollBar); + main->ui->previewXScrollBar->setValue(int(-scrollingOffset.x)); +} + +void OBSBasicPreview::UpdateYScrollBar(float cy) +{ + if (updatingYScrollBar) + return; + + OBSBasic *main = OBSBasic::Get(); + + if (!main->ui->previewYScrollBar->isVisible()) + return; + + main->ui->previewYScrollBar->setRange(int(-cy), int(cy)); + + QSize targetSize = GetPixelSize(this); + main->ui->previewYScrollBar->setPageStep(targetSize.height() / + std::min(scalingAmount, 1.0f)); + + QSignalBlocker sig(main->ui->previewYScrollBar); + main->ui->previewYScrollBar->setValue(int(-scrollingOffset.y)); } diff --git a/UI/window-basic-preview.hpp b/UI/window-basic-preview.hpp index 132df402a..719da894e 100644 --- a/UI/window-basic-preview.hpp +++ b/UI/window-basic-preview.hpp @@ -8,6 +8,7 @@ #include #include "qt-display.hpp" #include "obs-app.hpp" +#include "preview-controls.hpp" class OBSBasic; class QMouseEvent; @@ -18,8 +19,8 @@ class QMouseEvent; #define ITEM_BOTTOM (1 << 3) #define ITEM_ROT (1 << 4) -#define MAX_SCALING_LEVEL 20 -#define MAX_SCALING_AMOUNT 10.0f +#define MAX_SCALING_LEVEL 32 +#define MAX_SCALING_AMOUNT 8.0f #define ZOOM_SENSITIVITY pow(MAX_SCALING_AMOUNT, 1.0f / MAX_SCALING_LEVEL) #define SPACER_LABEL_MARGIN 6.0f @@ -81,6 +82,8 @@ private: int32_t scalingLevel = 0; float scalingAmount = 1.0f; float groupRot = 0.0f; + bool updatingXScrollBar = false; + bool updatingYScrollBar = false; std::vector hoveredPreviewItems; std::vector selectedItems; @@ -124,11 +127,17 @@ private: OBSDataAutoRelease wrapper = nullptr; bool changed; +private slots: + void XScrollBarMoved(int value); + void YScrollBarMoved(int value); + public: OBSBasicPreview(QWidget *parent, Qt::WindowFlags flags = Qt::WindowFlags()); ~OBSBasicPreview(); + void Init(); + static OBSBasicPreview *Get(); virtual void keyPressEvent(QKeyEvent *event) override; @@ -150,12 +159,18 @@ public: inline void SetFixedScaling(bool newFixedScalingVal) { + if (fixedScaling == newFixedScalingVal) + return; + fixedScaling = newFixedScalingVal; + emit fixedScalingChanged(fixedScaling); } inline bool IsFixedScaling() const { return fixedScaling; } void SetScalingLevel(int32_t newScalingLevelVal); void SetScalingAmount(float newScalingAmountVal); + void SetScalingLevelAndAmount(int32_t newScalingLevelVal, + float newScalingAmountVal); inline int32_t GetScalingLevel() const { return scalingLevel; } inline float GetScalingAmount() const { return scalingAmount; } @@ -198,4 +213,10 @@ public: void DrawSpacingHelpers(); void ClampScrollingOffsets(); + void UpdateXScrollBar(float cx); + void UpdateYScrollBar(float cy); + +signals: + void scalingChanged(float scalingAmount); + void fixedScalingChanged(bool isFixed); };