فهرست منبع

UI: Add t-bar to studio mode

Co-authored-by: Jim <[email protected]>
Clayton Groeneveld 5 سال پیش
والد
کامیت
68d88fa4c6
6فایلهای تغییر یافته به همراه213 افزوده شده و 6 حذف شده
  1. 33 0
      UI/data/themes/Acri.qss
  2. 25 0
      UI/data/themes/Dark.qss
  3. 33 0
      UI/data/themes/Rachni.qss
  4. 26 0
      UI/data/themes/System.qss
  5. 86 5
      UI/window-basic-main-transitions.cpp
  6. 10 1
      UI/window-basic-main.hpp

+ 33 - 0
UI/data/themes/Acri.qss

@@ -1050,3 +1050,36 @@ SceneTree#scenes {
 * [themeID="replayIconSmall"] {
     qproperty-icon: url(./Dark/save.svg);
 }
+
+/* Studio Mode T-Bar */
+
+QSlider[themeID="tBarSlider"] {
+	height: 80px;
+}
+
+QSlider::groove:horizontal[themeID="tBarSlider"] {
+	height: 5px;
+	margin: 0 12px;
+	background-color: QLinearGradient(x1: 0, y1: 0, x2: 0, y2: 1,
+		stop: 0 rgb(31,30,31),
+		stop: 0.75 rgb(50, 49, 50));
+	border: none;
+	border-radius: 2px;
+}
+
+QSlider::sub-page:horizontal[themeID="tBarSlider"] {
+	height: 5px;
+	margin: 0 12px;
+	background-color: QLinearGradient(x1: 0, y1: 0, x2: 0, y2: 1,
+		stop: 0 rgb(31,30,31),
+		stop: 0.75 rgb(50, 49, 50));
+	border: none;
+	border-radius: 2px;
+}
+
+QSlider::handle:horizontal[themeID="tBarSlider"] {
+	background-color: #d2d2d2;
+	width: 25px;
+	height: 80px;
+	margin: -24px -12px;
+}

+ 25 - 0
UI/data/themes/Dark.qss

@@ -815,3 +815,28 @@ SceneTree {
 * [themeID="replayIconSmall"] {
     qproperty-icon: url(./Dark/save.svg);
 }
+
+/* Studio Mode T-Bar */
+
+QSlider[themeID="tBarSlider"] {
+	height: 80px;
+}
+
+QSlider::groove:horizontal[themeID="tBarSlider"] {
+	border: 1px solid #4c4c4c;
+	height: 5px;
+	background: rgb(31,30,31);;
+	margin: 0 12px;
+}
+
+QSlider::sub-page:horizontal[themeID="tBarSlider"] {
+	background: rgb(31,30,31);;
+	border: 1px solid #4c4c4c;
+}
+
+QSlider::handle:horizontal[themeID="tBarSlider"] {
+	background-color: #d2d2d2;
+	width: 25px;
+	height: 80px;
+	margin: -24px -12px;
+}

+ 33 - 0
UI/data/themes/Rachni.qss

@@ -1378,3 +1378,36 @@ SceneTree#scenes {
 * [themeID="replayIconSmall"] {
     qproperty-icon: url(./Dark/save.svg);
 }
+
+/* Studio Mode T-Bar */
+
+QSlider[themeID="tBarSlider"] {
+	height: 80px;
+}
+
+QSlider::groove:horizontal[themeID="tBarSlider"] {
+	height: 5px;
+	margin: 0 12px;
+	background-color: QLinearGradient(x1: 1, y1: 0, x2: 0, y2: 0,
+		stop: 0 rgb(35, 38, 41), /* Dark Gray */
+		stop: 0.75 rgb(50, 49, 50));
+	border: none;
+	border-radius: 2px;
+}
+
+QSlider::sub-page:horizontal[themeID="tBarSlider"] {
+	height: 5px;
+	margin: 0 12px;
+	background-color: QLinearGradient(x1: 1, y1: 0, x2: 0, y2: 0,
+		stop: 0 rgb(35, 38, 41), /* Dark Gray */
+		stop: 0.75 rgb(50, 49, 50));
+	border: none;
+	border-radius: 2px;
+}
+
+QSlider::handle:horizontal[themeID="tBarSlider"] {
+	background-color: #d2d2d2;
+	width: 25px;
+	height: 80px;
+	margin: -24px -12px;
+}

+ 26 - 0
UI/data/themes/System.qss

@@ -246,3 +246,29 @@ SceneTree {
 * [themeID="replayIconSmall"] {
     qproperty-icon: url(:res/images/save.svg);
 }
+
+/* Studio Mode T-Bar */
+
+QSlider[themeID="tBarSlider"] {
+	height: 80px;
+}
+
+QSlider::groove:horizontal[themeID="tBarSlider"] {
+	border: 1px solid #4c4c4c;
+	height: 5px;
+	background: #DCD9D7;
+	margin: 0 12px;
+}
+
+QSlider::sub-page:horizontal[themeID="tBarSlider"] {
+	background: #DCD9D7;
+	border: 1px solid #4c4c4c;
+}
+
+QSlider::handle:horizontal[themeID="tBarSlider"] {
+	background-color: #f3f3f3;
+	border: 1px solid #4c4c4c;
+	width: 25px;
+	height: 80px;
+	margin: -24px -12px;
+}

+ 86 - 5
UI/window-basic-main-transitions.cpp

@@ -306,7 +306,7 @@ void OBSBasic::TransitionFullyStopped()
 
 void OBSBasic::TransitionToScene(OBSSource source, bool force,
 				 bool quickTransition, int quickDuration,
-				 bool black)
+				 bool black, bool manual)
 {
 	obs_scene_t *scene = obs_scene_from_source(source);
 	bool usingPreviewProgram = IsPreviewProgramMode();
@@ -316,7 +316,8 @@ void OBSBasic::TransitionToScene(OBSSource source, bool force,
 	OBSWeakSource lastProgramScene;
 
 	if (usingPreviewProgram) {
-		lastProgramScene = programScene;
+		if (!tBarActive)
+			lastProgramScene = programScene;
 		programScene = OBSGetWeakRef(source);
 
 		if (swapScenesMode && !force && !black) {
@@ -341,12 +342,16 @@ void OBSBasic::TransitionToScene(OBSSource source, bool force,
 	OBSSource transition = obs_get_output_source(0);
 	obs_source_release(transition);
 
-	bool stillTransitioning = obs_transition_get_time(transition) < 1.0f;
+	float t = obs_transition_get_time(transition);
+	bool stillTransitioning = (!tBarActive && t < 1.0f) ||
+				  (tBarActive && t > 0.0f) || tBarDown;
 
 	// If actively transitioning, block new transitions from starting
 	if (usingPreviewProgram && stillTransitioning)
 		goto cleanup;
 
+	tBarActive = false;
+
 	if (force) {
 		obs_transition_set(transition, source);
 		if (api)
@@ -390,8 +395,13 @@ void OBSBasic::TransitionToScene(OBSSource source, bool force,
 		if (quickTransition)
 			duration = quickDuration;
 
-		bool success = obs_transition_start(
-			transition, OBS_TRANSITION_MODE_AUTO, duration, source);
+		enum obs_transition_mode mode =
+			manual ? OBS_TRANSITION_MODE_MANUAL
+			       : OBS_TRANSITION_MODE_AUTO;
+
+		bool success = obs_transition_start(transition, mode, duration,
+						    source);
+
 		if (!success)
 			TransitionFullyStopped();
 	}
@@ -444,6 +454,8 @@ void OBSBasic::SetTransition(OBSSource transition)
 	ui->transitionRemove->setEnabled(configurable);
 	ui->transitionProps->setEnabled(configurable);
 
+	EnableTBar();
+
 	if (api)
 		api->on_event(OBS_FRONTEND_EVENT_TRANSITION_CHANGED);
 }
@@ -765,6 +777,10 @@ void OBSBasic::TransitionClicked()
 		TransitionToScene(GetCurrentScene());
 }
 
+#define T_BAR_PRECISION 1024
+#define T_BAR_PRECISION_F ((float)T_BAR_PRECISION)
+#define T_BAR_CLAMP (T_BAR_PRECISION / 10)
+
 void OBSBasic::CreateProgramOptions()
 {
 	programOptions = new QWidget();
@@ -796,9 +812,19 @@ void OBSBasic::CreateProgramOptions()
 	mainButtonLayout->addWidget(transitionButton);
 	mainButtonLayout->addWidget(configTransitions);
 
+	tBar = new QSlider(Qt::Horizontal);
+	tBar->setMinimum(0);
+	tBar->setMaximum(T_BAR_PRECISION - 1);
+
+	tBar->setProperty("themeID", "tBarSlider");
+
+	connect(tBar, SIGNAL(sliderMoved(int)), this, SLOT(TBarChanged(int)));
+	connect(tBar, SIGNAL(sliderReleased()), this, SLOT(TBarReleased()));
+
 	layout->addStretch(0);
 	layout->addLayout(mainButtonLayout);
 	layout->addLayout(quickTransitions);
+	layout->addWidget(tBar);
 	layout->addStretch(0);
 
 	programOptions->setLayout(layout);
@@ -871,6 +897,58 @@ void OBSBasic::CreateProgramOptions()
 	connect(configTransitions, &QAbstractButton::clicked, onConfig);
 }
 
+void OBSBasic::TBarReleased()
+{
+	int val = tBar->value();
+
+	if ((tBar->maximum() - val) <= T_BAR_CLAMP) {
+		obs_transition_set_manual_time(GetCurrentTransition(), 1.0f);
+		tBar->blockSignals(true);
+		tBar->setValue(0);
+		tBar->blockSignals(false);
+		tBarActive = false;
+
+	} else if (val <= T_BAR_CLAMP) {
+		obs_transition_set_manual_time(GetCurrentTransition(), 0.0f);
+		tBar->blockSignals(true);
+		tBar->setValue(0);
+		tBar->blockSignals(false);
+	}
+
+	tBarDown = false;
+}
+
+void OBSBasic::TBarChanged(int value)
+{
+	if (!tBarDown) {
+		obs_transition_set_manual_torque(GetCurrentTransition(), 8.0f,
+						 0.05f);
+		TransitionToScene(GetCurrentSceneSource(), false, false, false,
+				  0, true);
+		tBarActive = true;
+		tBarDown = true;
+	}
+
+	obs_transition_set_manual_time(GetCurrentTransition(),
+				       (float)value / T_BAR_PRECISION_F);
+}
+
+void OBSBasic::EnableTBar()
+{
+	if (!previewProgramMode)
+		return;
+
+	const char *id = obs_source_get_id(GetCurrentTransition());
+
+	if (!id || strcmp(id, "cut_transition") == 0 ||
+	    strcmp(id, "obs_stinger_transition") == 0) {
+		tBar->setValue(0);
+		tBar->setEnabled(false);
+	} else {
+		tBar->setEnabled(true);
+	}
+}
+
 void OBSBasic::on_modeSwitch_clicked()
 {
 	SetPreviewProgramMode(!IsPreviewProgramMode());
@@ -1137,6 +1215,8 @@ void OBSBasic::QuickTransitionChange()
 		qt->source = GetTransitionComboItem(ui->transitions, trIdx);
 		ResetQuickTransitionText(qt);
 	}
+
+	EnableTBar();
 }
 
 void OBSBasic::QuickTransitionChangeDuration(int value)
@@ -1258,6 +1338,7 @@ void OBSBasic::SetPreviewProgramMode(bool enabled)
 
 		CreateProgramDisplay();
 		CreateProgramOptions();
+		EnableTBar();
 
 		OBSScene curScene = GetCurrentScene();
 

+ 10 - 1
UI/window-basic-main.hpp

@@ -502,6 +502,11 @@ private:
 	QIcon GetBrowserIcon() const;
 	QIcon GetDefaultIcon() const;
 
+	QSlider *tBar;
+	bool tBarActive = false;
+	bool tBarDown = false;
+	void EnableTBar();
+
 public slots:
 	void DeferSaveBegin();
 	void DeferSaveEnd();
@@ -541,7 +546,8 @@ public slots:
 	void TransitionToScene(OBSScene scene, bool force = false);
 	void TransitionToScene(OBSSource scene, bool force = false,
 			       bool quickTransition = false,
-			       int quickDuration = 0, bool black = false);
+			       int quickDuration = 0, bool black = false,
+			       bool manual = false);
 	void SetCurrentScene(OBSSource scene, bool force = false);
 
 	bool AddSceneCollection(bool create_new,
@@ -645,6 +651,9 @@ private slots:
 	void SetSceneIcon(const QIcon &icon);
 	void SetDefaultIcon(const QIcon &icon);
 
+	void TBarChanged(int value);
+	void TBarReleased();
+
 private:
 	/* OBS Callbacks */
 	static void SceneReordered(void *data, calldata_t *params);