Browse Source

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 years ago
parent
commit
b4d2d5d9c4
1 changed files with 106 additions and 105 deletions
  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;
 
 	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;
 	float        fX, fY, halfCX, halfCY, sourceX, sourceY, labelX, labelY,
 		     quarterCX, quarterCY, scale, targetCXF, targetCYF,
 		     hiCX, hiCY, qiX, qiY, qiCX, qiCY, hiScaleX, hiScaleY,
 		     qiScaleX, qiScaleY;
-	uint32_t     offset;
 
 	gs_effect_t  *solid = obs_get_base_effect(OBS_EFFECT_SOLID);
 	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);
 	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 programSrc = main->GetProgramSource();
@@ -356,7 +356,7 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
 			sourceX = halfCX;
 			sourceY = (i / 2 ) * quarterCY;
 			if (i % 2 != 0)
-				sourceX = halfCX + quarterCX;
+				sourceX += quarterCX;
 			break;
 		case MultiviewLayout::VERTICAL_RIGHT_8_SCENES:
 			sourceX = 0;
@@ -382,53 +382,64 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
 				sourceY = halfCY + quarterCY;
 			}
 		}
+		qiX = sourceX + thickness;
+		qiY = sourceY + thickness;
 	};
 
 	auto calcPreviewProgram = [&](bool program)
 	{
 		switch (multiviewLayout) {
 		case MultiviewLayout::VERTICAL_LEFT_8_SCENES:
-			sourceX = 2.0f;
-			sourceY = halfCY + 2.0f;
+			sourceX = thickness;
+			sourceY = halfCY + thickness;
 			labelX = offset;
 			labelY = halfCY * 1.8f;
 			if (program) {
-				sourceY = 2.0f;
+				sourceY = thickness;
 				labelY = halfCY * 0.8f;
 			}
 			break;
 		case MultiviewLayout::VERTICAL_RIGHT_8_SCENES:
-			sourceX = halfCX + 2.0f;
-			sourceY = halfCY + 2.0f;
+			sourceX = halfCX + thickness;
+			sourceY = halfCY + thickness;
 			labelX = halfCX + offset;
 			labelY = halfCY * 1.8f;
 			if (program) {
-				sourceY = 2.0f;
+				sourceY = thickness;
 				labelY = halfCY * 0.8f;
 			}
 			break;
 		case MultiviewLayout::HORIZONTAL_BOTTOM_8_SCENES:
-			sourceX = 2.0f;
-			sourceY = halfCY + 2.0f;
+			sourceX = thickness;
+			sourceY = halfCY + thickness;
 			labelX = offset;
 			labelY = halfCY * 1.8f;
 			if (program) {
-				sourceX = halfCX + 2.0f;
-				labelX = halfCX + offset;
+				sourceX += halfCX;
+				labelX += halfCX;
 			}
 			break;
 		default: // MultiviewLayout::HORIZONTAL_TOP_8_SCENES:
-			sourceX = 2.0f;
-			sourceY = 2.0f;
+			sourceX = thickness;
+			sourceY = thickness;
 			labelX = offset;
 			labelY = halfCY * 0.8f;
 			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
 	startRegion(x, y, targetCX * scale, targetCY * scale, 0.0f, targetCXF,
 			0.0f, targetCYF);
@@ -443,63 +454,58 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
 		OBSSource src = OBSGetStrongRef(window->multiviewScenes[i]);
 		obs_source *label = window->multiviewLabels[i + 2];
 
-		if (!src)
-			continue;
-		if (!label)
-			continue;
-
+		// Handle all the offsets
 		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);
 	calcPreviewProgram(false);
 
+	// Paint the background
+	paintAreaWithColor(sourceX, sourceY, hiCX, hiCY, backgroundColor);
+
+	// Scale and Draw the preview
 	gs_matrix_push();
 	gs_matrix_translate3f(sourceX, sourceY, 0.0f);
 	gs_matrix_scale3f(hiScaleX, hiScaleY, 1.0f);
-
 	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);
-	} else {
+	else
 		obs_render_main_texture();
-	}
-	endRegion();
-
 	renderVB(window->innerBox, targetCX, targetCY, outerColor);
 	renderVB(window->leftVLine, targetCX, targetCY, outerColor);
 	renderVB(window->rightVLine, targetCX, targetCY, outerColor);
 	renderVB(window->leftLine, targetCX, targetCY, outerColor);
 	renderVB(window->topLine, targetCX, targetCY, outerColor);
 	renderVB(window->rightLine, targetCX, targetCY, outerColor);
-
+	endRegion();
 	gs_matrix_pop();
 
 	/* ----------- */
 
-	cx = obs_source_get_width(previewLabel);
-	cy = obs_source_get_height(previewLabel);
-
+	// Draw the Label
 	gs_matrix_push();
 	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);
-
 	gs_matrix_pop();
 
 	/* ----------------------------- */
@@ -552,24 +554,23 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
 	offset = labelOffset(programLabel, halfCX);
 	calcPreviewProgram(true);
 
+	// Scale and Draw the program
 	gs_matrix_push();
 	gs_matrix_translate3f(sourceX, sourceY, 0.0f);
 	gs_matrix_scale3f(hiScaleX, hiScaleY, 1.0f);
-
 	setRegion(sourceX, sourceY, hiCX, hiCY);
 	obs_render_main_texture();
 	endRegion();
-
 	gs_matrix_pop();
 
 	/* ----------- */
 
-	cx = obs_source_get_width(programLabel);
-	cy = obs_source_get_height(programLabel);
-
+	// Draw the Label
 	gs_matrix_push();
 	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);
 	gs_matrix_pop();
 	endRegion();