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 @@
1
+
+ OBSPreviewScalingLabel
+ QLabel
+
+
+
+ OBSPreviewScalingComboBox
+ QComboBox
+
+
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);
};