Explorar o código

frontend: Add preview zoom controls

cg2121 hai 1 ano
pai
achega
86f7475f14

+ 3 - 0
frontend/data/locale/en-US.ini

@@ -796,6 +796,9 @@ 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.Scale.ZoomIn="Zoom In"
+Basic.MainMenu.Edit.Scale.ZoomOut="Zoom Out"
+Basic.MainMenu.Edit.Scale.ResetZoom="Reset Zoom"
 Basic.MainMenu.Edit.Transform="&Transform"
 Basic.MainMenu.Edit.Transform.EditTransform="&Edit Transform..."
 Basic.MainMenu.Edit.Transform.CopyTransform="Copy Transform"

+ 32 - 0
frontend/data/themes/Yami.obt

@@ -1972,6 +1972,11 @@ OBSBasicAdvAudio #scrollAreaWidgetContents {
     border-color: var(--input_border_hover);
 }
 
+#previewScalingMode:on {
+    background-color: var(--input_bg_focus);
+    border-color: var(--input_border_focus);
+}
+
 #previewXScrollBar,
 #previewYScrollBar {
     background: transparent;
@@ -1992,3 +1997,30 @@ OBSBasicAdvAudio #scrollAreaWidgetContents {
 #previewYScrollBar {
     width: 16px;
 }
+
+#previewZoomInButton {
+    border: none;
+    border-radius: 0px;
+    outline: none;
+}
+
+#previewZoomOutButton {
+    border: none;
+    border-radius: 0px;
+    outline: none;
+}
+
+#previewZoomInButton:!hover,
+#previewZoomOutButton:!hover {
+    background-color: transparent;
+}
+
+#previewZoomInButton:pressed,
+#previewZoomOutButton:pressed {
+    background-color: var(--button_bg);
+}
+
+#previewZoomInButton:focus,
+#previewZoomOutButton:focus {
+    border: 1px solid var(--input_border_hover);
+}

+ 145 - 2
frontend/forms/OBSBasic.ui

@@ -249,6 +249,53 @@
                 <property name="bottomMargin">
                  <number>0</number>
                 </property>
+                <item>
+                 <widget class="QPushButton" name="previewZoomInButton">
+                  <property name="sizePolicy">
+                   <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                   </sizepolicy>
+                  </property>
+                  <property name="minimumSize">
+                   <size>
+                    <width>20</width>
+                    <height>16</height>
+                   </size>
+                  </property>
+                  <property name="maximumSize">
+                   <size>
+                    <width>20</width>
+                    <height>16</height>
+                   </size>
+                  </property>
+                  <property name="toolTip">
+                   <string>Basic.MainMenu.Edit.Scale.ZoomIn</string>
+                  </property>
+                  <property name="accessibleName">
+                   <string>Basic.MainMenu.Edit.Scale.ZoomIn</string>
+                  </property>
+                  <property name="text">
+                   <string/>
+                  </property>
+                  <property name="icon">
+                   <iconset resource="obs.qrc">
+                    <normaloff>:/res/images/plus.svg</normaloff>:/res/images/plus.svg</iconset>
+                  </property>
+                  <property name="iconSize">
+                   <size>
+                    <width>8</width>
+                    <height>8</height>
+                   </size>
+                  </property>
+                  <property name="toolButton" stdset="0">
+                   <bool>true</bool>
+                  </property>
+                  <property name="class" stdset="0">
+                   <string>icon-plus</string>
+                  </property>
+                 </widget>
+                </item>
                 <item>
                  <widget class="OBSPreviewScalingLabel" name="previewScalePercent">
                   <property name="text">
@@ -259,6 +306,53 @@
                   </property>
                  </widget>
                 </item>
+                <item>
+                 <widget class="QPushButton" name="previewZoomOutButton">
+                  <property name="sizePolicy">
+                   <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+                    <horstretch>0</horstretch>
+                    <verstretch>0</verstretch>
+                   </sizepolicy>
+                  </property>
+                  <property name="minimumSize">
+                   <size>
+                    <width>20</width>
+                    <height>16</height>
+                   </size>
+                  </property>
+                  <property name="maximumSize">
+                   <size>
+                    <width>20</width>
+                    <height>16</height>
+                   </size>
+                  </property>
+                  <property name="toolTip">
+                   <string>Basic.MainMenu.Edit.Scale.ZoomOut</string>
+                  </property>
+                  <property name="accessibleName">
+                   <string>Basic.MainMenu.Edit.Scale.ZoomOut</string>
+                  </property>
+                  <property name="text">
+                   <string/>
+                  </property>
+                  <property name="icon">
+                   <iconset resource="obs.qrc">
+                    <normaloff>:/res/images/minus.svg</normaloff>:/res/images/minus.svg</iconset>
+                  </property>
+                  <property name="iconSize">
+                   <size>
+                    <width>8</width>
+                    <height>8</height>
+                   </size>
+                  </property>
+                  <property name="toolButton" stdset="0">
+                   <bool>true</bool>
+                  </property>
+                  <property name="class" stdset="0">
+                   <string>icon-minus</string>
+                  </property>
+                 </widget>
+                </item>
                 <item>
                  <widget class="OBSPreviewScalingComboBox" name="previewScalingMode">
                   <item>
@@ -273,6 +367,22 @@
                   </item>
                  </widget>
                 </item>
+                <item>
+                 <spacer name="horizontalSpacer_5">
+                  <property name="orientation">
+                   <enum>Qt::Horizontal</enum>
+                  </property>
+                  <property name="sizeType">
+                   <enum>QSizePolicy::Fixed</enum>
+                  </property>
+                  <property name="sizeHint" stdset="0">
+                   <size>
+                    <width>4</width>
+                    <height>0</height>
+                   </size>
+                  </property>
+                 </spacer>
+                </item>
                 <item>
                  <widget class="QScrollBar" name="previewXScrollBar">
                   <property name="sizePolicy">
@@ -690,6 +800,10 @@
      <addaction name="actionScaleWindow"/>
      <addaction name="actionScaleCanvas"/>
      <addaction name="actionScaleOutput"/>
+     <addaction name="separator"/>
+     <addaction name="actionPreviewZoomIn"/>
+     <addaction name="actionPreviewZoomOut"/>
+     <addaction name="actionPreviewResetZoom"/>
     </widget>
     <action name="actionCopySource">
      <property name="text">
@@ -1160,7 +1274,7 @@
              <rect>
               <x>0</x>
               <y>0</y>
-              <width>225</width>
+              <width>323</width>
               <height>16</height>
              </rect>
             </property>
@@ -1214,7 +1328,7 @@
               <x>0</x>
               <y>0</y>
               <width>16</width>
-              <height>192</height>
+              <height>28</height>
              </rect>
             </property>
             <property name="sizePolicy">
@@ -2213,6 +2327,35 @@
     <string>List</string>
    </property>
   </action>
+  <action name="actionPreview">
+   <property name="text">
+    <string>Preview</string>
+   </property>
+  </action>
+  <action name="actionPreviewZoomIn">
+   <property name="enabled">
+    <bool>false</bool>
+   </property>
+   <property name="text">
+    <string>Basic.MainMenu.Edit.Scale.ZoomIn</string>
+   </property>
+  </action>
+  <action name="actionPreviewZoomOut">
+   <property name="enabled">
+    <bool>false</bool>
+   </property>
+   <property name="text">
+    <string>Basic.MainMenu.Edit.Scale.ZoomOut</string>
+   </property>
+  </action>
+  <action name="actionPreviewResetZoom">
+   <property name="enabled">
+    <bool>false</bool>
+   </property>
+   <property name="text">
+    <string>Basic.MainMenu.Edit.Scale.ResetZoom</string>
+   </property>
+  </action>
  </widget>
  <customwidgets>
   <customwidget>

+ 17 - 1
frontend/widgets/OBSBasic.cpp

@@ -326,7 +326,7 @@ OBSBasic::OBSBasic(QWidget *parent) : OBSMainWindow(parent), undo_s(ui), ui(new
 			ResizePreview(ovi.base_width, ovi.base_height);
 
 		UpdateContextBarVisibility();
-		UpdatePreviewScrollbars();
+		UpdatePreviewControls();
 		dpi = devicePixelRatioF();
 	};
 	dpi = devicePixelRatioF();
@@ -349,6 +349,22 @@ OBSBasic::OBSBasic(QWidget *parent) : OBSMainWindow(parent), undo_s(ui), ui(new
 	connect(ui->previewScalingMode, &OBSPreviewScalingComboBox::currentIndexChanged, this,
 		&OBSBasic::PreviewScalingModeChanged);
 
+	/* Preview Controls */
+	connect(ui->previewXScrollBar, &QScrollBar::sliderMoved, ui->preview, &OBSBasicPreview::xScrollBarChanged);
+	connect(ui->previewYScrollBar, &QScrollBar::valueChanged, ui->preview, &OBSBasicPreview::yScrollBarChanged);
+
+	connect(ui->previewZoomInButton, &QPushButton::clicked, ui->preview, &OBSBasicPreview::increaseScalingLevel);
+	connect(ui->previewZoomOutButton, &QPushButton::clicked, ui->preview, &OBSBasicPreview::decreaseScalingLevel);
+
+	/* Preview Actions */
+	connect(ui->actionScaleWindow, &QAction::triggered, this, &OBSBasic::setPreviewScalingWindow);
+	connect(ui->actionScaleCanvas, &QAction::triggered, this, &OBSBasic::setPreviewScalingCanvas);
+	connect(ui->actionScaleOutput, &QAction::triggered, this, &OBSBasic::setPreviewScalingOutput);
+
+	connect(ui->actionPreviewZoomIn, &QAction::triggered, ui->preview, &OBSBasicPreview::increaseScalingLevel);
+	connect(ui->actionPreviewZoomOut, &QAction::triggered, ui->preview, &OBSBasicPreview::decreaseScalingLevel);
+	connect(ui->actionPreviewResetZoom, &QAction::triggered, ui->preview, &OBSBasicPreview::resetScalingLevel);
+
 	connect(this, &OBSBasic::CanvasResized, ui->previewScalingMode, &OBSPreviewScalingComboBox::CanvasResized);
 	connect(this, &OBSBasic::OutputResized, ui->previewScalingMode, &OBSPreviewScalingComboBox::OutputResized);
 

+ 8 - 9
frontend/widgets/OBSBasic.hpp

@@ -813,7 +813,7 @@ private:
 	float GetDevicePixelRatio();
 
 	void UpdatePreviewOverflowSettings();
-	void UpdatePreviewScrollbars();
+	void UpdatePreviewControls();
 
 	/* OBS Callbacks */
 	static void RenderMain(void *data, uint32_t cx, uint32_t cy);
@@ -821,9 +821,6 @@ private:
 	void ResizePreview(uint32_t cx, uint32_t cy);
 
 private slots:
-	void on_previewXScrollBar_valueChanged(int value);
-	void on_previewYScrollBar_valueChanged(int value);
-
 	void PreviewScalingModeChanged(int value);
 
 	void ColorChange();
@@ -831,12 +828,13 @@ private slots:
 	void EnablePreview();
 	void DisablePreview();
 
+	void setPreviewScalingWindow();
+	void setPreviewScalingCanvas();
+	void setPreviewScalingOutput();
+
 	void on_actionLockPreview_triggered();
 
 	void on_scalingMenu_aboutToShow();
-	void on_actionScaleWindow_triggered();
-	void on_actionScaleCanvas_triggered();
-	void on_actionScaleOutput_triggered();
 
 	void on_preview_customContextMenuRequested();
 	void on_previewDisabledWidget_customContextMenuRequested();
@@ -860,8 +858,9 @@ signals:
 	void OutputResized(uint32_t width, uint32_t height);
 
 	/* Preview signals */
-	void PreviewXScrollBarMoved(int value);
-	void PreviewYScrollBarMoved(int value);
+	void PreviewZoomIn();
+	void PreviewZoomOut();
+	void PreviewResetZoom();
 
 	/* -------------------------------------
 	 * MARK: - OBSBasic_Profiles

+ 35 - 13
frontend/widgets/OBSBasicPreview.cpp

@@ -31,12 +31,7 @@ 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);
-}
+void OBSBasicPreview::Init() {}
 
 vec2 OBSBasicPreview::GetMouseEventPos(QMouseEvent *event)
 {
@@ -525,10 +520,9 @@ void OBSBasicPreview::wheelEvent(QWheelEvent *event)
 		const int delta = event->angleDelta().y();
 		if (delta != 0) {
 			if (delta > 0)
-				SetScalingLevel(scalingLevel + 1);
+				increaseScalingLevel();
 			else
-				SetScalingLevel(scalingLevel - 1);
-			emit DisplayResized();
+				decreaseScalingLevel();
 		}
 	}
 
@@ -2171,6 +2165,10 @@ void OBSBasicPreview::SetScalingAmount(float newScalingAmountVal)
 
 	scalingAmount = newScalingAmountVal;
 	emit scalingChanged(scalingAmount);
+
+	if (!fixedScaling) {
+		scalingLevel = std::round(log(scalingAmount) / log(ZOOM_SENSITIVITY));
+	}
 }
 
 void OBSBasicPreview::SetScalingLevelAndAmount(int32_t newScalingLevelVal, float newScalingAmountVal)
@@ -2180,6 +2178,30 @@ void OBSBasicPreview::SetScalingLevelAndAmount(int32_t newScalingLevelVal, float
 	SetScalingAmount(newScalingAmountVal);
 }
 
+void OBSBasicPreview::increaseScalingLevel()
+{
+	SetFixedScaling(true);
+	SetScalingLevel(scalingLevel + 1);
+
+	emit DisplayResized();
+}
+
+void OBSBasicPreview::decreaseScalingLevel()
+{
+	SetFixedScaling(true);
+	SetScalingLevel(scalingLevel - 1);
+
+	emit DisplayResized();
+}
+
+void OBSBasicPreview::resetScalingLevel()
+{
+	SetScalingLevel(0);
+	ResetScrollingOffset();
+
+	emit DisplayResized();
+}
+
 OBSBasicPreview *OBSBasicPreview::Get()
 {
 	return OBSBasic::Get()->ui->preview;
@@ -2531,22 +2553,22 @@ void OBSBasicPreview::ClampScrollingOffsets()
 	UpdateYScrollBar(offset.y);
 }
 
-void OBSBasicPreview::XScrollBarMoved(int value)
+void OBSBasicPreview::xScrollBarChanged(int value)
 {
 	updatingXScrollBar = true;
 	scrollingOffset.x = float(-value);
 
-	emit DisplayResized();
 	updatingXScrollBar = false;
+	emit DisplayResized();
 }
 
-void OBSBasicPreview::YScrollBarMoved(int value)
+void OBSBasicPreview::yScrollBarChanged(int value)
 {
 	updatingYScrollBar = true;
 	scrollingOffset.y = float(-value);
 
-	emit DisplayResized();
 	updatingYScrollBar = false;
+	emit DisplayResized();
 }
 
 void OBSBasicPreview::UpdateXScrollBar(float cx)

+ 6 - 4
frontend/widgets/OBSBasicPreview.hpp

@@ -116,10 +116,6 @@ 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();
@@ -158,6 +154,9 @@ public:
 	void SetScalingLevel(int32_t newScalingLevelVal);
 	void SetScalingAmount(float newScalingAmountVal);
 	void SetScalingLevelAndAmount(int32_t newScalingLevelVal, float newScalingAmountVal);
+	void increaseScalingLevel();
+	void decreaseScalingLevel();
+	void resetScalingLevel();
 	inline int32_t GetScalingLevel() const { return scalingLevel; }
 	inline float GetScalingAmount() const { return scalingAmount; }
 
@@ -166,6 +165,9 @@ public:
 	inline float GetScrollX() const { return scrollingOffset.x; }
 	inline float GetScrollY() const { return scrollingOffset.y; }
 
+	void xScrollBarChanged(int value);
+	void yScrollBarChanged(int value);
+
 	inline void SetOverflowHidden(bool hidden) { overflowHidden = hidden; }
 	inline void SetOverflowSelectionHidden(bool hidden) { overflowSelectionHidden = hidden; }
 	inline void SetOverflowAlwaysVisible(bool visible) { overflowAlwaysVisible = visible; }

+ 1 - 0
frontend/widgets/OBSBasic_MainControls.cpp

@@ -513,6 +513,7 @@ void OBSBasic::on_actionFullscreenInterface_triggered()
 void OBSBasic::on_resetUI_triggered()
 {
 	on_resetDocks_triggered();
+	setPreviewScalingWindow();
 
 	ui->toggleListboxToolbars->setChecked(true);
 	ui->toggleContextBar->setChecked(true);

+ 22 - 15
frontend/widgets/OBSBasic_Preview.cpp

@@ -399,7 +399,7 @@ void OBSBasic::on_scalingMenu_aboutToShow()
 	UpdatePreviewScalingMenu();
 }
 
-void OBSBasic::on_actionScaleWindow_triggered()
+void OBSBasic::setPreviewScalingWindow()
 {
 	ui->preview->SetFixedScaling(false);
 	ui->preview->ResetScrollingOffset();
@@ -407,7 +407,7 @@ void OBSBasic::on_actionScaleWindow_triggered()
 	emit ui->preview->DisplayResized();
 }
 
-void OBSBasic::on_actionScaleCanvas_triggered()
+void OBSBasic::setPreviewScalingCanvas()
 {
 	ui->preview->SetFixedScaling(true);
 	ui->preview->SetScalingLevel(0);
@@ -415,7 +415,7 @@ void OBSBasic::on_actionScaleCanvas_triggered()
 	emit ui->preview->DisplayResized();
 }
 
-void OBSBasic::on_actionScaleOutput_triggered()
+void OBSBasic::setPreviewScalingOutput()
 {
 	obs_video_info ovi;
 	obs_get_video_info(&ovi);
@@ -626,35 +626,42 @@ float OBSBasic::GetDevicePixelRatio()
 	return dpi;
 }
 
-void OBSBasic::UpdatePreviewScrollbars()
+void OBSBasic::UpdatePreviewControls()
 {
+	const int scalingLevel = ui->preview->GetScalingLevel();
+
 	if (!ui->preview->IsFixedScaling()) {
 		ui->previewXScrollBar->setRange(0, 0);
 		ui->previewYScrollBar->setRange(0, 0);
+
+		ui->actionPreviewResetZoom->setEnabled(false);
+
+		return;
 	}
-}
 
-void OBSBasic::on_previewXScrollBar_valueChanged(int value)
-{
-	emit PreviewXScrollBarMoved(value);
-}
+	const bool minZoom = scalingLevel == MAX_SCALING_LEVEL;
+	const bool maxZoom = scalingLevel == -MAX_SCALING_LEVEL;
 
-void OBSBasic::on_previewYScrollBar_valueChanged(int value)
-{
-	emit PreviewYScrollBarMoved(value);
+	ui->actionPreviewZoomIn->setEnabled(!minZoom);
+	ui->previewZoomInButton->setEnabled(!minZoom);
+
+	ui->actionPreviewZoomOut->setEnabled(!maxZoom);
+	ui->previewZoomOutButton->setEnabled(!maxZoom);
+
+	ui->actionPreviewResetZoom->setEnabled(scalingLevel != 0);
 }
 
 void OBSBasic::PreviewScalingModeChanged(int value)
 {
 	switch (value) {
 	case 0:
-		on_actionScaleWindow_triggered();
+		setPreviewScalingWindow();
 		break;
 	case 1:
-		on_actionScaleCanvas_triggered();
+		setPreviewScalingCanvas();
 		break;
 	case 2:
-		on_actionScaleOutput_triggered();
+		setPreviewScalingOutput();
 		break;
 	};
 }