浏览代码

UI: Add Studio Preview Projector

This commit allows a user to create projectors for the preview scene
instead of the program/live scene.

Close jp9000/obs-studio#1071
Ryan Foster 8 年之前
父节点
当前提交
9fce162137

+ 2 - 0
UI/data/locale/en-US.ini

@@ -33,9 +33,11 @@ Browse="Browse"
 Mono="Mono"
 Stereo="Stereo"
 DroppedFrames="Dropped Frames %1 (%2%)"
+StudioProgramProjector="Fullscreen Projector (Program)"
 PreviewProjector="Fullscreen Projector (Preview)"
 SceneProjector="Fullscreen Projector (Scene)"
 SourceProjector="Fullscreen Projector (Source)"
+StudioProgramWindow="Windowed Projector (Program)"
 PreviewWindow="Windowed Projector (Preview)"
 SceneWindow="Windowed Projector (Scene)"
 SourceWindow="Windowed Projector (Source)"

+ 3 - 0
UI/window-basic-main-transitions.cpp

@@ -604,6 +604,9 @@ void OBSBasic::SetCurrentScene(OBSSource scene, bool force, bool direct)
 void OBSBasic::CreateProgramDisplay()
 {
 	program = new OBSQTDisplay();
+	program->setContextMenuPolicy(Qt::CustomContextMenu);
+	connect(program.data(), &QWidget::customContextMenuRequested,
+			this, &OBSBasic::on_program_customContextMenuRequested);
 
 	auto displayResize = [this]() {
 		struct obs_video_info ovi;

+ 127 - 9
UI/window-basic-main.cpp

@@ -139,6 +139,7 @@ OBSBasic::OBSBasic(QWidget *parent)
 
 	projectorArray.resize(10, "");
 	previewProjectorArray.resize(10, 0);
+	studioProgramProjectorArray.resize(10, "");
 
 	setAcceptDrops(true);
 
@@ -318,7 +319,8 @@ static obs_data_t *GenerateSaveData(obs_data_array_t *sceneOrder,
 		obs_data_array_t *transitions,
 		OBSScene &scene, OBSSource &curProgramScene,
 		obs_data_array_t *savedProjectorList,
-		obs_data_array_t *savedPreviewProjectorList)
+		obs_data_array_t *savedPreviewProjectorList,
+		obs_data_array_t *savedStudioProgramProjectorList)
 {
 	obs_data_t *saveData = obs_data_create();
 
@@ -362,6 +364,8 @@ static obs_data_t *GenerateSaveData(obs_data_array_t *sceneOrder,
 	obs_data_set_array(saveData, "saved_projectors", savedProjectorList);
 	obs_data_set_array(saveData, "saved_preview_projectors",
 			savedPreviewProjectorList);
+	obs_data_set_array(saveData, "saved_studio_preview_projectors",
+			savedStudioProgramProjectorList);
 	obs_data_array_release(sourcesArray);
 
 	obs_data_set_string(saveData, "current_transition",
@@ -449,6 +453,21 @@ obs_data_array_t *OBSBasic::SavePreviewProjectors()
 	return saveProjector;
 }
 
+obs_data_array_t *OBSBasic::SaveStudioProgramProjectors()
+{
+	obs_data_array_t *saveProjector = obs_data_array_create();
+
+	for (size_t i = 0; i < studioProgramProjectorArray.size(); i++) {
+		obs_data_t *data = obs_data_create();
+		obs_data_set_string(data, "saved_studio_preview_projectors",
+			studioProgramProjectorArray.at(i).c_str());
+		obs_data_array_push_back(saveProjector, data);
+		obs_data_release(data);
+	}
+
+	return saveProjector;
+}
+
 void OBSBasic::Save(const char *file)
 {
 	OBSScene scene = GetCurrentScene();
@@ -461,10 +480,13 @@ void OBSBasic::Save(const char *file)
 	obs_data_array_t *quickTrData = SaveQuickTransitions();
 	obs_data_array_t *savedProjectorList = SaveProjectors();
 	obs_data_array_t *savedPreviewProjectorList = SavePreviewProjectors();
-	obs_data_t *saveData  = GenerateSaveData(sceneOrder, quickTrData,
+	obs_data_array_t *savedStudioProgramProjectorList =
+			SaveStudioProgramProjectors();
+	obs_data_t *saveData = GenerateSaveData(sceneOrder, quickTrData,
 			ui->transitionDuration->value(), transitions,
 			scene, curProgramScene, savedProjectorList,
-			savedPreviewProjectorList);
+			savedPreviewProjectorList,
+			savedStudioProgramProjectorList);
 
 	obs_data_set_bool(saveData, "preview_locked", ui->preview->Locked());
 	obs_data_set_bool(saveData, "scaling_enabled",
@@ -492,6 +514,7 @@ void OBSBasic::Save(const char *file)
 	obs_data_array_release(transitions);
 	obs_data_array_release(savedProjectorList);
 	obs_data_array_release(savedPreviewProjectorList);
+	obs_data_array_release(savedStudioProgramProjectorList);
 }
 
 static void LoadAudioDevice(const char *name, int channel, obs_data_t *parent)
@@ -617,6 +640,19 @@ void OBSBasic::LoadSavedPreviewProjectors(obs_data_array_t *array)
 	}
 }
 
+void OBSBasic::LoadSavedStudioProgramProjectors(obs_data_array_t *array)
+{
+	size_t num = obs_data_array_count(array);
+
+	for (size_t i = 0; i < num; i++) {
+		obs_data_t *data = obs_data_array_item(array, i);
+		studioProgramProjectorArray.at(i) = obs_data_get_string(data,
+				"saved_studio_preview_projectors");
+
+		obs_data_release(data);
+	}
+}
+
 static void LogFilter(obs_source_t*, obs_source_t *filter, void *v_val)
 {
 	const char *name = obs_source_get_name(filter);
@@ -764,6 +800,14 @@ void OBSBasic::Load(const char *file)
 
 	obs_data_array_release(savedPreviewProjectors);
 
+	obs_data_array_t *savedStudioProgramProjectors = obs_data_get_array(data,
+			"saved_studio_preview_projectors");
+
+	if (savedStudioProgramProjectors)
+		LoadSavedStudioProgramProjectors(savedStudioProgramProjectors);
+
+	obs_data_array_release(savedStudioProgramProjectors);
+
 
 retryScene:
 	curScene = obs_get_source_by_name(sceneName);
@@ -3673,15 +3717,23 @@ void OBSBasic::CreateSourcePopupMenu(QListWidgetItem *item, bool preview)
 		popup.addAction(ui->actionLockPreview);
 		popup.addMenu(ui->scalingMenu);
 
+		const char *slot = IsPreviewProgramMode()
+			? SLOT(OpenStudioProgramProjector())
+			: SLOT(OpenPreviewProjector());
+
 		previewProjector = new QMenu(QTStr("PreviewProjector"));
 		AddProjectorMenuMonitors(previewProjector, this,
-				SLOT(OpenPreviewProjector()));
+				slot);
 
 		popup.addMenu(previewProjector);
 
+		slot = IsPreviewProgramMode()
+			? SLOT(OpenStudioProgramWindow())
+			: SLOT(OpenPreviewWindow());
+
 		QAction *previewWindow = popup.addAction(
 				QTStr("PreviewWindow"),
-				this, SLOT(OpenPreviewWindow()));
+				this, slot);
 
 		popup.addAction(previewWindow);
 
@@ -4875,6 +4927,27 @@ void OBSBasic::on_preview_customContextMenuRequested(const QPoint &pos)
 	UNUSED_PARAMETER(pos);
 }
 
+void OBSBasic::on_program_customContextMenuRequested(const QPoint&)
+{
+	QMenu popup(this);
+	QPointer<QMenu> studioProgramProjector;
+
+	studioProgramProjector = new QMenu(
+			QTStr("StudioProgramProjector"));
+	AddProjectorMenuMonitors(studioProgramProjector, this,
+			SLOT(OpenPreviewProjector()));
+
+	popup.addMenu(studioProgramProjector);
+
+	QAction *studioProgramWindow = popup.addAction(
+			QTStr("StudioProgramWindow"),
+			this, SLOT(OpenPreviewWindow()));
+
+	popup.addAction(studioProgramWindow);
+
+	popup.exec(QCursor::pos());
+}
+
 void OBSBasic::on_previewDisabledLabel_customContextMenuRequested(
 		const QPoint &pos)
 {
@@ -5336,7 +5409,7 @@ void OBSBasic::NudgeLeft()     {Nudge(1,  MoveDir::Left);}
 void OBSBasic::NudgeRight()    {Nudge(1,  MoveDir::Right);}
 
 void OBSBasic::OpenProjector(obs_source_t *source, int monitor, bool window,
-		QString title)
+		QString title, bool studioProgram)
 {
 	/* seriously?  10 monitors? */
 	if (monitor > 9 || monitor > QGuiApplication::screens().size() - 1)
@@ -5357,7 +5430,9 @@ void OBSBasic::OpenProjector(obs_source_t *source, int monitor, bool window,
 	const char *name = obs_source_get_name(source);
 
 	if (!window) {
-		if (isPreview) {
+		if (studioProgram) {
+			studioProgramProjectorArray.at((size_t)monitor) = name;
+		} else if (isPreview) {
 			previewProjectorArray.at((size_t)monitor) = 1;
 		} else {
 			projectorArray.at((size_t)monitor) = name;
@@ -5365,10 +5440,10 @@ void OBSBasic::OpenProjector(obs_source_t *source, int monitor, bool window,
 	}
 
 	if (!window) {
-		projector->Init(monitor, false, nullptr);
+		projector->Init(monitor, false, nullptr, studioProgram);
 		projectors[monitor] = projector;
 	} else {
-		projector->Init(monitor, true, title);
+		projector->Init(monitor, true, title, studioProgram);
 
 		for (auto &projPtr : windowProjectors) {
 			if (!projPtr) {
@@ -5382,6 +5457,16 @@ void OBSBasic::OpenProjector(obs_source_t *source, int monitor, bool window,
 	}
 }
 
+void OBSBasic::OpenStudioProgramProjector()
+{
+	int monitor = sender()->property("monitor").toInt();
+	obs_source_t *source = GetCurrentSceneSource();
+	if (!source)
+		return;
+
+	OpenProjector(source, monitor, false, nullptr, true);
+}
+
 void OBSBasic::OpenPreviewProjector()
 {
 	int monitor = sender()->property("monitor").toInt();
@@ -5408,6 +5493,17 @@ void OBSBasic::OpenSceneProjector()
 	OpenProjector(obs_scene_get_source(scene), monitor, false);
 }
 
+void OBSBasic::OpenStudioProgramWindow()
+{
+	int monitor = sender()->property("monitor").toInt();
+	QString title = QTStr("StudioProgramWindow");
+	obs_source_t *source = GetCurrentSceneSource();
+	if (!source)
+		return;
+
+	OpenProjector(source, monitor, true, title, true);
+}
+
 void OBSBasic::OpenPreviewWindow()
 {
 	int monitor = sender()->property("monitor").toInt();
@@ -5467,6 +5563,22 @@ void OBSBasic::OpenSavedProjectors()
 			}
 		}
 
+		for (size_t i = 0; i < studioProgramProjectorArray.size(); i++) {
+			if (studioProgramProjectorArray.at(i).empty() == false) {
+				OBSSource source = obs_get_source_by_name(
+					studioProgramProjectorArray.at(i).c_str());
+
+				if (!source) {
+					RemoveSavedProjectors((int)i);
+					obs_source_release(source);
+					continue;
+				}
+
+				OpenProjector(source, (int)i, false, nullptr, true);
+				obs_source_release(source);
+			}
+		}
+
 		for (size_t i = 0; i < previewProjectorArray.size(); i++) {
 			if (previewProjectorArray.at(i) == 1) {
 				OpenProjector(nullptr, (int)i, false);
@@ -5477,6 +5589,7 @@ void OBSBasic::OpenSavedProjectors()
 
 void OBSBasic::RemoveSavedProjectors(int monitor)
 {
+	studioProgramProjectorArray.at((size_t)monitor) = "";
 	previewProjectorArray.at((size_t)monitor) = 0;
 	projectorArray.at((size_t)monitor) = "";
 }
@@ -5771,10 +5884,15 @@ void OBSBasic::SystemTrayInit()
 	QMenu *previewProjector = new QMenu(QTStr("PreviewProjector"));
 	AddProjectorMenuMonitors(previewProjector, this,
 			SLOT(OpenPreviewProjector()));
+	QMenu *studioProgramProjector = new QMenu(
+			QTStr("StudioProgramProjector"));
+	AddProjectorMenuMonitors(studioProgramProjector, this,
+			SLOT(OpenStudioProgramProjector()));
 
 	trayMenu = new QMenu;
 	trayMenu->addAction(showHide);
 	trayMenu->addMenu(previewProjector);
+	trayMenu->addMenu(studioProgramProjector);
 	trayMenu->addAction(sysTrayStream);
 	trayMenu->addAction(sysTrayRecord);
 	trayMenu->addAction(sysTrayReplayBuffer);

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

@@ -114,6 +114,7 @@ private:
 	std::vector<OBSSignal> signalHandlers;
 
 	std::vector<std::string> projectorArray;
+	std::vector<std::string> studioProgramProjectorArray;
 	std::vector<int> previewProjectorArray;
 
 	bool loaded = false;
@@ -240,7 +241,7 @@ private:
 
 	void Nudge(int dist, MoveDir dir);
 	void OpenProjector(obs_source_t *source, int monitor, bool window,
-			QString title = nullptr);
+			QString title = nullptr, bool studioProgram = false);
 
 	void GetAudioSourceFilters();
 	void GetAudioSourceProperties();
@@ -358,6 +359,10 @@ private:
 	void LoadSavedPreviewProjectors(
 		obs_data_array_t *savedPreviewProjectors);
 
+	obs_data_array_t *SaveStudioProgramProjectors();
+	void LoadSavedStudioProgramProjectors(
+		obs_data_array_t *savedStudioProgramProjectors);
+
 public slots:
 	void StartStreaming();
 	void StopStreaming();
@@ -609,6 +614,7 @@ private slots:
 	void on_actionWebsite_triggered();
 
 	void on_preview_customContextMenuRequested(const QPoint &pos);
+	void on_program_customContextMenuRequested(const QPoint &pos);
 	void on_previewDisabledLabel_customContextMenuRequested(
 			const QPoint &pos);
 
@@ -675,10 +681,12 @@ private slots:
 	void NudgeLeft();
 	void NudgeRight();
 
+	void OpenStudioProgramProjector();
 	void OpenPreviewProjector();
 	void OpenSourceProjector();
 	void OpenSceneProjector();
 
+	void OpenStudioProgramWindow();
 	void OpenPreviewWindow();
 	void OpenSourceWindow();
 	void OpenSceneWindow();

+ 26 - 3
UI/window-projector.cpp

@@ -55,7 +55,8 @@ OBSProjector::~OBSProjector()
 	App()->DecrementSleepInhibition();
 }
 
-void OBSProjector::Init(int monitor, bool window, QString title)
+void OBSProjector::Init(int monitor, bool window, QString title,
+		bool studioProgram)
 {
 	QScreen *screen = QGuiApplication::screens()[monitor];
 
@@ -72,6 +73,12 @@ void OBSProjector::Init(int monitor, bool window, QString title)
 
 	show();
 
+	if (studioProgram && !source) {
+		OBSBasic *main =
+			reinterpret_cast<OBSBasic*>(App()->GetMainWindow());
+		source = main->GetCurrentSceneSource();
+	}
+
 	if (source)
 		obs_source_inc_showing(source);
 
@@ -86,6 +93,7 @@ void OBSProjector::Init(int monitor, bool window, QString title)
 
 	savedMonitor = monitor;
 	isWindow = window;
+	useStudioProgram = studioProgram;
 }
 
 void OBSProjector::OBSRender(void *data, uint32_t cx, uint32_t cy)
@@ -118,10 +126,25 @@ void OBSProjector::OBSRender(void *data, uint32_t cx, uint32_t cy)
 	gs_ortho(0.0f, float(targetCX), 0.0f, float(targetCY), -100.0f, 100.0f);
 	gs_set_viewport(x, y, newCX, newCY);
 
-	if (window->source)
+	if (window->useStudioProgram) {
+		OBSBasic *main =
+			reinterpret_cast<OBSBasic*>(App()->GetMainWindow());
+		OBSSource curSource = main->GetCurrentSceneSource();
+
+		if (window->source != curSource) {
+			blog(LOG_INFO, "new scene for studio preview projector: '%s'",
+					obs_source_get_name(curSource));
+			obs_source_dec_showing(window->source);
+			obs_source_inc_showing(curSource);
+			window->source = curSource;
+		}
+	}
+
+	if (window->source) {
 		obs_source_video_render(window->source);
-	else
+	} else {
 		obs_render_main_view();
+	}
 
 	gs_projection_pop();
 	gs_viewport_pop();

+ 3 - 1
UI/window-projector.hpp

@@ -20,6 +20,7 @@ private:
 
 	int savedMonitor = 0;
 	bool isWindow = false;
+	bool useStudioProgram = false;
 
 private slots:
 	void EscapeTriggered();
@@ -28,5 +29,6 @@ public:
 	OBSProjector(QWidget *parent, obs_source_t *source, bool window);
 	~OBSProjector();
 
-	void Init(int monitor, bool window, QString title);
+	void Init(int monitor, bool window, QString title,
+			bool studioProgram = false);
 };