浏览代码

UI: Add proper source markers to multiview

This ensures the pixel correctness of the sources selection highlight
boxes when on a fullscreen projector.

When on a windowed projector due to the nature of int<->float
conversions and also due to the limited space, some source boxes
might be like 'off-by-one' and barely noticeable.
Shaolin 7 年之前
父节点
当前提交
b4d2d5d9c4
共有 1 个文件被更改,包括 106 次插入105 次删除
  1. 106 105
      UI/window-projector.cpp

+ 106 - 105
UI/window-projector.cpp

@@ -262,13 +262,13 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
 		return;
 		return;
 
 
 	OBSBasic     *main   = (OBSBasic *)obs_frontend_get_main_window();
 	OBSBasic     *main   = (OBSBasic *)obs_frontend_get_main_window();
-	uint32_t     targetCX, targetCY;
+	uint32_t     thickness = 4;
+	uint32_t     targetCX, targetCY, offset, thicknessx2 = thickness * 2;
 	int          x, y;
 	int          x, y;
 	float        fX, fY, halfCX, halfCY, sourceX, sourceY, labelX, labelY,
 	float        fX, fY, halfCX, halfCY, sourceX, sourceY, labelX, labelY,
 		     quarterCX, quarterCY, scale, targetCXF, targetCYF,
 		     quarterCX, quarterCY, scale, targetCXF, targetCYF,
 		     hiCX, hiCY, qiX, qiY, qiCX, qiCY, hiScaleX, hiScaleY,
 		     hiCX, hiCY, qiX, qiY, qiCX, qiCY, hiScaleX, hiScaleY,
 		     qiScaleX, qiScaleY;
 		     qiScaleX, qiScaleY;
-	uint32_t     offset;
 
 
 	gs_effect_t  *solid = obs_get_base_effect(OBS_EFFECT_SOLID);
 	gs_effect_t  *solid = obs_get_base_effect(OBS_EFFECT_SOLID);
 	gs_eparam_t  *color = gs_effect_get_param_by_name(solid, "color");
 	gs_eparam_t  *color = gs_effect_get_param_by_name(solid, "color");
@@ -285,19 +285,19 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
 	fX        = float(x);
 	fX        = float(x);
 	fY        = float(y);
 	fY        = float(y);
 
 
-	halfCX    = (targetCXF + 1) / 2;
-	halfCY    = (targetCYF + 1) / 2;
-	hiCX      = (halfCX - 4.0);
-	hiCY      = (halfCY - 4.0);
-	hiScaleX  = hiCX / targetCXF;
-	hiScaleY  = hiCY / targetCYF;
+	halfCX    = targetCXF / 2;
+	halfCY    = targetCYF / 2;
+	hiCX      = halfCX - thicknessx2;
+	hiCY      = halfCY - thicknessx2;
+	hiScaleX  = (halfCX - thicknessx2) / targetCXF;
+	hiScaleY  = (halfCY - thicknessx2) / targetCYF;
 
 
-	quarterCX = (halfCX + 1) / 2;
-	quarterCY = (halfCY + 1) / 2;
-	qiCX      = (quarterCX - 8.0);
-	qiCY      = (quarterCY - 8.0);
-	qiScaleX  = qiCX / targetCXF;
-	qiScaleY  = qiCY / targetCYF;
+	quarterCX = halfCX / 2;
+	quarterCY = halfCY / 2;
+	qiCX      = quarterCX - thicknessx2;
+	qiCY      = quarterCY - thicknessx2;
+	qiScaleX  = (quarterCX - thicknessx2) / targetCXF;
+	qiScaleY  = (quarterCY - thicknessx2) / targetCYF;
 
 
 	OBSSource previewSrc = main->GetCurrentSceneSource();
 	OBSSource previewSrc = main->GetCurrentSceneSource();
 	OBSSource programSrc = main->GetProgramSource();
 	OBSSource programSrc = main->GetProgramSource();
@@ -356,7 +356,7 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
 			sourceX = halfCX;
 			sourceX = halfCX;
 			sourceY = (i / 2 ) * quarterCY;
 			sourceY = (i / 2 ) * quarterCY;
 			if (i % 2 != 0)
 			if (i % 2 != 0)
-				sourceX = halfCX + quarterCX;
+				sourceX += quarterCX;
 			break;
 			break;
 		case MultiviewLayout::VERTICAL_RIGHT_8_SCENES:
 		case MultiviewLayout::VERTICAL_RIGHT_8_SCENES:
 			sourceX = 0;
 			sourceX = 0;
@@ -382,53 +382,64 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
 				sourceY = halfCY + quarterCY;
 				sourceY = halfCY + quarterCY;
 			}
 			}
 		}
 		}
+		qiX = sourceX + thickness;
+		qiY = sourceY + thickness;
 	};
 	};
 
 
 	auto calcPreviewProgram = [&](bool program)
 	auto calcPreviewProgram = [&](bool program)
 	{
 	{
 		switch (multiviewLayout) {
 		switch (multiviewLayout) {
 		case MultiviewLayout::VERTICAL_LEFT_8_SCENES:
 		case MultiviewLayout::VERTICAL_LEFT_8_SCENES:
-			sourceX = 2.0f;
-			sourceY = halfCY + 2.0f;
+			sourceX = thickness;
+			sourceY = halfCY + thickness;
 			labelX = offset;
 			labelX = offset;
 			labelY = halfCY * 1.8f;
 			labelY = halfCY * 1.8f;
 			if (program) {
 			if (program) {
-				sourceY = 2.0f;
+				sourceY = thickness;
 				labelY = halfCY * 0.8f;
 				labelY = halfCY * 0.8f;
 			}
 			}
 			break;
 			break;
 		case MultiviewLayout::VERTICAL_RIGHT_8_SCENES:
 		case MultiviewLayout::VERTICAL_RIGHT_8_SCENES:
-			sourceX = halfCX + 2.0f;
-			sourceY = halfCY + 2.0f;
+			sourceX = halfCX + thickness;
+			sourceY = halfCY + thickness;
 			labelX = halfCX + offset;
 			labelX = halfCX + offset;
 			labelY = halfCY * 1.8f;
 			labelY = halfCY * 1.8f;
 			if (program) {
 			if (program) {
-				sourceY = 2.0f;
+				sourceY = thickness;
 				labelY = halfCY * 0.8f;
 				labelY = halfCY * 0.8f;
 			}
 			}
 			break;
 			break;
 		case MultiviewLayout::HORIZONTAL_BOTTOM_8_SCENES:
 		case MultiviewLayout::HORIZONTAL_BOTTOM_8_SCENES:
-			sourceX = 2.0f;
-			sourceY = halfCY + 2.0f;
+			sourceX = thickness;
+			sourceY = halfCY + thickness;
 			labelX = offset;
 			labelX = offset;
 			labelY = halfCY * 1.8f;
 			labelY = halfCY * 1.8f;
 			if (program) {
 			if (program) {
-				sourceX = halfCX + 2.0f;
-				labelX = halfCX + offset;
+				sourceX += halfCX;
+				labelX += halfCX;
 			}
 			}
 			break;
 			break;
 		default: // MultiviewLayout::HORIZONTAL_TOP_8_SCENES:
 		default: // MultiviewLayout::HORIZONTAL_TOP_8_SCENES:
-			sourceX = 2.0f;
-			sourceY = 2.0f;
+			sourceX = thickness;
+			sourceY = thickness;
 			labelX = offset;
 			labelX = offset;
 			labelY = halfCY * 0.8f;
 			labelY = halfCY * 0.8f;
 			if (program) {
 			if (program) {
-				sourceX = halfCX + 2.0f;
-				labelX = halfCX + offset;
+				sourceX += halfCX;
+				labelX += halfCX;
 			}
 			}
 		}
 		}
 	};
 	};
 
 
+	auto paintAreaWithColor = [&](float tx, float ty, float cx, float cy,
+			uint32_t color)
+	{
+		gs_matrix_push();
+		gs_matrix_translate3f(tx, ty, 0.0f);
+		drawBox(cx, cy, color);
+		gs_matrix_pop();
+	};
+
 	// Define the whole usable region for the multiview
 	// Define the whole usable region for the multiview
 	startRegion(x, y, targetCX * scale, targetCY * scale, 0.0f, targetCXF,
 	startRegion(x, y, targetCX * scale, targetCY * scale, 0.0f, targetCXF,
 			0.0f, targetCYF);
 			0.0f, targetCYF);
@@ -443,63 +454,58 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
 		OBSSource src = OBSGetStrongRef(window->multiviewScenes[i]);
 		OBSSource src = OBSGetStrongRef(window->multiviewScenes[i]);
 		obs_source *label = window->multiviewLabels[i + 2];
 		obs_source *label = window->multiviewLabels[i + 2];
 
 
-		if (!src)
-			continue;
-		if (!label)
-			continue;
-
+		// Handle all the offsets
 		calcBaseSource(i);
 		calcBaseSource(i);
 
 
-		qiX = sourceX + 4.0f;
-		qiY = sourceY + 4.0f;
-
-		/* ----------- */
-
-		uint32_t colorVal = outerColor;
-		if (src == programSrc)
-			colorVal = programColor;
-		else if (src == previewSrc)
-			colorVal = studioMode ? previewColor : programColor;
-
-		// Highlight preview/program sources with a proper color
-		gs_matrix_push();
-		gs_matrix_translate3f(sourceX, sourceY, 0.0f);
-		drawBox(quarterCX, quarterCY, colorVal);
-		gs_matrix_pop();
-
-		// Change the background back of the source region
-		gs_matrix_push();
-		gs_matrix_translate3f(qiX, qiY, 0.0f);
-		drawBox(qiCX, qiCY, backgroundColor);
-		gs_matrix_pop();
-
-		/* ----------- */
-
-		// Draw the actual source
-		gs_matrix_push();
-		gs_matrix_translate3f(qiX, qiY, 0.0f);
-		gs_matrix_scale3f(qiScaleX, qiScaleY, 1.0f);
-
-		setRegion(qiX, qiY, qiCX, qiCY);
-		obs_source_video_render(src);
-		endRegion();
-
-		gs_matrix_pop();
-
-		/* ----------- */
-
-		offset = labelOffset(label, quarterCX);
-		cx = obs_source_get_width(label);
-		cy = obs_source_get_height(label);
-
-		gs_matrix_push();
-		gs_matrix_translate3f(sourceX + offset,
-				(quarterCY * 0.8f) + sourceY, 0.0f);
-
-		drawBox(cx, cy + int(quarterCX * 0.015f), labelColor);
-		obs_source_video_render(label);
-
-		gs_matrix_pop();
+		if (src) {
+			// Chose the proper highlight color
+			uint32_t colorVal = outerColor;
+			if (src == programSrc)
+				colorVal = programColor;
+			else if (src == previewSrc)
+				colorVal = studioMode ? previewColor
+						: programColor;
+
+			// Paint the background
+			paintAreaWithColor(sourceX, sourceY, quarterCX,
+					quarterCY, colorVal);
+			paintAreaWithColor(qiX, qiY, qiCX, qiCY,
+					backgroundColor);
+
+			/* ----------- */
+
+			// Render the source
+			gs_matrix_push();
+			gs_matrix_translate3f(qiX, qiY, 0.0f);
+			gs_matrix_scale3f(qiScaleX, qiScaleY, 1.0f);
+			setRegion(qiX, qiY, qiCX, qiCY);
+			obs_source_video_render(src);
+			endRegion();
+			gs_matrix_pop();
+
+			/* ----------- */
+
+			// Render the label
+			if (!label)
+				continue;
+
+			offset = labelOffset(label, quarterCX);
+			cx = obs_source_get_width(label);
+			cy = obs_source_get_height(label);
+
+			gs_matrix_push();
+			gs_matrix_translate3f(sourceX + offset,
+					(quarterCY * 0.8f) + sourceY, 0.0f);
+			drawBox(cx, cy + int(quarterCX * 0.015f), labelColor);
+			obs_source_video_render(label);
+			gs_matrix_pop();
+		} else {
+			// Paint the background
+			paintAreaWithColor(sourceX, sourceY, quarterCX,
+					quarterCY, outerColor);
+			paintAreaWithColor(qiX, qiY, qiCX, qiCY,
+					backgroundColor);
+		}
 	}
 	}
 
 
 	/* ----------------------------- */
 	/* ----------------------------- */
@@ -509,40 +515,36 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
 	offset = labelOffset(previewLabel, halfCX);
 	offset = labelOffset(previewLabel, halfCX);
 	calcPreviewProgram(false);
 	calcPreviewProgram(false);
 
 
+	// Paint the background
+	paintAreaWithColor(sourceX, sourceY, hiCX, hiCY, backgroundColor);
+
+	// Scale and Draw the preview
 	gs_matrix_push();
 	gs_matrix_push();
 	gs_matrix_translate3f(sourceX, sourceY, 0.0f);
 	gs_matrix_translate3f(sourceX, sourceY, 0.0f);
 	gs_matrix_scale3f(hiScaleX, hiScaleY, 1.0f);
 	gs_matrix_scale3f(hiScaleX, hiScaleY, 1.0f);
-
 	setRegion(sourceX, sourceY, hiCX, hiCY);
 	setRegion(sourceX, sourceY, hiCX, hiCY);
-	if (studioMode) {
-		// Change the background back of the source region
-		drawBox(targetCXF, targetCYF, backgroundColor);
+	if (studioMode)
 		obs_source_video_render(previewSrc);
 		obs_source_video_render(previewSrc);
-	} else {
+	else
 		obs_render_main_texture();
 		obs_render_main_texture();
-	}
-	endRegion();
-
 	renderVB(window->innerBox, targetCX, targetCY, outerColor);
 	renderVB(window->innerBox, targetCX, targetCY, outerColor);
 	renderVB(window->leftVLine, targetCX, targetCY, outerColor);
 	renderVB(window->leftVLine, targetCX, targetCY, outerColor);
 	renderVB(window->rightVLine, targetCX, targetCY, outerColor);
 	renderVB(window->rightVLine, targetCX, targetCY, outerColor);
 	renderVB(window->leftLine, targetCX, targetCY, outerColor);
 	renderVB(window->leftLine, targetCX, targetCY, outerColor);
 	renderVB(window->topLine, targetCX, targetCY, outerColor);
 	renderVB(window->topLine, targetCX, targetCY, outerColor);
 	renderVB(window->rightLine, targetCX, targetCY, outerColor);
 	renderVB(window->rightLine, targetCX, targetCY, outerColor);
-
+	endRegion();
 	gs_matrix_pop();
 	gs_matrix_pop();
 
 
 	/* ----------- */
 	/* ----------- */
 
 
-	cx = obs_source_get_width(previewLabel);
-	cy = obs_source_get_height(previewLabel);
-
+	// Draw the Label
 	gs_matrix_push();
 	gs_matrix_push();
 	gs_matrix_translate3f(labelX, labelY, 0.0f);
 	gs_matrix_translate3f(labelX, labelY, 0.0f);
-
-	drawBox(cx, cy + int(halfCX * 0.015f), labelColor);
+	drawBox(obs_source_get_width(previewLabel),
+			obs_source_get_height(previewLabel) +
+					int(halfCX * 0.015f), labelColor);
 	obs_source_video_render(previewLabel);
 	obs_source_video_render(previewLabel);
-
 	gs_matrix_pop();
 	gs_matrix_pop();
 
 
 	/* ----------------------------- */
 	/* ----------------------------- */
@@ -552,24 +554,23 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
 	offset = labelOffset(programLabel, halfCX);
 	offset = labelOffset(programLabel, halfCX);
 	calcPreviewProgram(true);
 	calcPreviewProgram(true);
 
 
+	// Scale and Draw the program
 	gs_matrix_push();
 	gs_matrix_push();
 	gs_matrix_translate3f(sourceX, sourceY, 0.0f);
 	gs_matrix_translate3f(sourceX, sourceY, 0.0f);
 	gs_matrix_scale3f(hiScaleX, hiScaleY, 1.0f);
 	gs_matrix_scale3f(hiScaleX, hiScaleY, 1.0f);
-
 	setRegion(sourceX, sourceY, hiCX, hiCY);
 	setRegion(sourceX, sourceY, hiCX, hiCY);
 	obs_render_main_texture();
 	obs_render_main_texture();
 	endRegion();
 	endRegion();
-
 	gs_matrix_pop();
 	gs_matrix_pop();
 
 
 	/* ----------- */
 	/* ----------- */
 
 
-	cx = obs_source_get_width(programLabel);
-	cy = obs_source_get_height(programLabel);
-
+	// Draw the Label
 	gs_matrix_push();
 	gs_matrix_push();
 	gs_matrix_translate3f(labelX, labelY, 0.0f);
 	gs_matrix_translate3f(labelX, labelY, 0.0f);
-	drawBox(cx, cy + int(halfCX * 0.015f), labelColor);
+	drawBox(obs_source_get_width(programLabel),
+			obs_source_get_height(programLabel) +
+					int(halfCX * 0.015f), labelColor);
 	obs_source_video_render(programLabel);
 	obs_source_video_render(programLabel);
 	gs_matrix_pop();
 	gs_matrix_pop();
 	endRegion();
 	endRegion();