Просмотр исходного кода

UI: Add fullscreen projector class

This allows viewing a source, scene, or the main preview in a fullscreen
window.
jp9000 10 лет назад
Родитель
Сommit
c68283042c
3 измененных файлов с 130 добавлено и 0 удалено
  1. 2 0
      obs/CMakeLists.txt
  2. 103 0
      obs/window-projector.cpp
  3. 25 0
      obs/window-projector.hpp

+ 2 - 0
obs/CMakeLists.txt

@@ -103,6 +103,7 @@ set(obs_SOURCES
 	window-basic-preview.cpp
 	window-namedialog.cpp
 	window-log-reply.cpp
+	window-projector.cpp
 	window-remux.cpp
 	properties-view.cpp
 	focus-list.cpp
@@ -134,6 +135,7 @@ set(obs_HEADERS
 	window-basic-preview.hpp
 	window-namedialog.hpp
 	window-log-reply.hpp
+	window-projector.hpp
 	window-remux.hpp
 	properties-view.hpp
 	display-helpers.hpp

+ 103 - 0
obs/window-projector.cpp

@@ -0,0 +1,103 @@
+#include <QAction>
+#include "window-projector.hpp"
+#include "display-helpers.hpp"
+#include "qt-wrappers.hpp"
+#include "platform.hpp"
+
+OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_)
+	: OBSQTDisplay                 (widget,
+	                                Qt::Window | Qt::FramelessWindowHint),
+	  source                       (source_),
+	  removedSignal                (obs_source_get_signal_handler(source),
+	                                "removed", OBSSourceRemoved, this)
+{
+	setAttribute(Qt::WA_DeleteOnClose, true);
+}
+
+OBSProjector::~OBSProjector()
+{
+	if (source)
+		obs_source_dec_showing(source);
+}
+
+void OBSProjector::Init(int monitor)
+{
+	std::vector<MonitorInfo> monitors;
+	GetMonitors(monitors);
+	MonitorInfo &mi = monitors[monitor];
+
+	setGeometry(mi.x, mi.y, mi.cx, mi.cy);
+
+	show();
+
+	if (source)
+		obs_source_inc_showing(source);
+
+	struct gs_init_data gid = {};
+	gid.cx                  = mi.cx;
+	gid.cy                  = mi.cy;
+	gid.format              = GS_RGBA;
+	QTToGSWindow(winId(), gid.window);
+
+	display = obs_display_create(&gid);
+	obs_display_set_background_color(display, 0x000000);
+	obs_display_add_draw_callback(display, OBSRender, this);
+
+	QAction *action = new QAction(this);
+	action->setShortcut(Qt::Key_Escape);
+	addAction(action);
+
+	connect(action, SIGNAL(triggered()), this, SLOT(EscapeTriggered()));
+}
+
+void OBSProjector::OBSRender(void *data, uint32_t cx, uint32_t cy)
+{
+	OBSProjector *window = reinterpret_cast<OBSProjector*>(data);
+
+	uint32_t targetCX;
+	uint32_t targetCY;
+	int      x, y;
+	int      newCX, newCY;
+	float    scale;
+
+	if (window->source) {
+		targetCX = std::max(obs_source_get_width(window->source), 1u);
+		targetCY = std::max(obs_source_get_height(window->source), 1u);
+	} else {
+		struct obs_video_info ovi;
+		obs_get_video_info(&ovi);
+		targetCX = ovi.base_width;
+		targetCY = ovi.base_height;
+	}
+
+	GetScaleAndCenterPos(targetCX, targetCY, cx, cy, x, y, scale);
+
+	newCX = int(scale * float(targetCX));
+	newCY = int(scale * float(targetCY));
+
+	gs_viewport_push();
+	gs_projection_push();
+	gs_ortho(0.0f, float(targetCX), 0.0f, float(targetCY), -100.0f, 100.0f);
+	gs_set_viewport(x, y, newCX, newCY);
+
+	if (window->source)
+		obs_source_video_render(window->source);
+	else
+		obs_render_main_view();
+
+	gs_projection_pop();
+	gs_viewport_pop();
+}
+
+void OBSProjector::OBSSourceRemoved(void *data, calldata_t *params)
+{
+	OBSProjector *window = reinterpret_cast<OBSProjector*>(data);
+	window->deleteLater();
+
+	UNUSED_PARAMETER(params);
+}
+
+void OBSProjector::EscapeTriggered()
+{
+	deleteLater();
+}

+ 25 - 0
obs/window-projector.hpp

@@ -0,0 +1,25 @@
+#pragma once
+
+#include <obs.hpp>
+#include "qt-display.hpp"
+
+class OBSProjector : public OBSQTDisplay {
+	Q_OBJECT
+
+private:
+	OBSDisplay display;
+	OBSSource source;
+	OBSSignal removedSignal;
+
+	static void OBSRender(void *data, uint32_t cx, uint32_t cy);
+	static void OBSSourceRemoved(void *data, calldata_t *params);
+
+private slots:
+	void EscapeTriggered();
+
+public:
+	OBSProjector(QWidget *parent, obs_source_t *source);
+	~OBSProjector();
+
+	void Init(int monitor);
+};