| 
					
				 | 
			
			
				@@ -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(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 |