UI: Add option to draw safe areas in preview
parent
1b29bfc884
commit
afd58a78e5
|
@ -17,6 +17,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <graphics/vec4.h>
|
||||
#include <graphics/matrix4.h>
|
||||
|
||||
static inline void GetScaleAndCenterPos(int baseCX, int baseCY, int windowCX,
|
||||
int windowCY, int &x, int &y,
|
||||
float &scale)
|
||||
|
@ -53,3 +56,90 @@ static inline QSize GetPixelSize(QWidget *widget)
|
|||
{
|
||||
return widget->size() * widget->devicePixelRatioF();
|
||||
}
|
||||
|
||||
#define OUTLINE_COLOR 0xFFD0D0D0
|
||||
#define LINE_LENGTH 0.1f
|
||||
|
||||
// Rec. ITU-R BT.1848-1 / EBU R 95
|
||||
#define ACTION_SAFE_PERCENT 0.035f // 3.5%
|
||||
#define GRAPHICS_SAFE_PERCENT 0.05f // 5.0%
|
||||
#define FOURBYTHREE_SAFE_PERCENT 0.1625f // 16.25%
|
||||
|
||||
static inline void InitSafeAreas(gs_vertbuffer_t **actionSafeMargin,
|
||||
gs_vertbuffer_t **graphicsSafeMargin,
|
||||
gs_vertbuffer_t **fourByThreeSafeMargin,
|
||||
gs_vertbuffer_t **leftLine,
|
||||
gs_vertbuffer_t **topLine,
|
||||
gs_vertbuffer_t **rightLine)
|
||||
{
|
||||
obs_enter_graphics();
|
||||
|
||||
// All essential action should be placed inside this area
|
||||
gs_render_start(true);
|
||||
gs_vertex2f(ACTION_SAFE_PERCENT, ACTION_SAFE_PERCENT);
|
||||
gs_vertex2f(ACTION_SAFE_PERCENT, 1 - ACTION_SAFE_PERCENT);
|
||||
gs_vertex2f(1 - ACTION_SAFE_PERCENT, 1 - ACTION_SAFE_PERCENT);
|
||||
gs_vertex2f(1 - ACTION_SAFE_PERCENT, ACTION_SAFE_PERCENT);
|
||||
gs_vertex2f(ACTION_SAFE_PERCENT, ACTION_SAFE_PERCENT);
|
||||
*actionSafeMargin = gs_render_save();
|
||||
|
||||
// All graphics should be placed inside this area
|
||||
gs_render_start(true);
|
||||
gs_vertex2f(GRAPHICS_SAFE_PERCENT, GRAPHICS_SAFE_PERCENT);
|
||||
gs_vertex2f(GRAPHICS_SAFE_PERCENT, 1 - GRAPHICS_SAFE_PERCENT);
|
||||
gs_vertex2f(1 - GRAPHICS_SAFE_PERCENT, 1 - GRAPHICS_SAFE_PERCENT);
|
||||
gs_vertex2f(1 - GRAPHICS_SAFE_PERCENT, GRAPHICS_SAFE_PERCENT);
|
||||
gs_vertex2f(GRAPHICS_SAFE_PERCENT, GRAPHICS_SAFE_PERCENT);
|
||||
*graphicsSafeMargin = gs_render_save();
|
||||
|
||||
// 4:3 safe area for widescreen
|
||||
gs_render_start(true);
|
||||
gs_vertex2f(FOURBYTHREE_SAFE_PERCENT, GRAPHICS_SAFE_PERCENT);
|
||||
gs_vertex2f(1 - FOURBYTHREE_SAFE_PERCENT, GRAPHICS_SAFE_PERCENT);
|
||||
gs_vertex2f(1 - FOURBYTHREE_SAFE_PERCENT, 1 - GRAPHICS_SAFE_PERCENT);
|
||||
gs_vertex2f(FOURBYTHREE_SAFE_PERCENT, 1 - GRAPHICS_SAFE_PERCENT);
|
||||
gs_vertex2f(FOURBYTHREE_SAFE_PERCENT, GRAPHICS_SAFE_PERCENT);
|
||||
*fourByThreeSafeMargin = gs_render_save();
|
||||
|
||||
gs_render_start(true);
|
||||
gs_vertex2f(0.0f, 0.5f);
|
||||
gs_vertex2f(LINE_LENGTH, 0.5f);
|
||||
*leftLine = gs_render_save();
|
||||
|
||||
gs_render_start(true);
|
||||
gs_vertex2f(0.5f, 0.0f);
|
||||
gs_vertex2f(0.5f, LINE_LENGTH);
|
||||
*topLine = gs_render_save();
|
||||
|
||||
gs_render_start(true);
|
||||
gs_vertex2f(1.0f, 0.5f);
|
||||
gs_vertex2f(1 - LINE_LENGTH, 0.5f);
|
||||
*rightLine = gs_render_save();
|
||||
|
||||
obs_leave_graphics();
|
||||
}
|
||||
|
||||
static inline void RenderSafeAreas(gs_vertbuffer_t *vb, int cx, int cy)
|
||||
{
|
||||
if (!vb)
|
||||
return;
|
||||
|
||||
matrix4 transform;
|
||||
matrix4_identity(&transform);
|
||||
transform.x.x = cx;
|
||||
transform.y.y = cy;
|
||||
|
||||
gs_load_vertexbuffer(vb);
|
||||
|
||||
gs_matrix_push();
|
||||
gs_matrix_mul(&transform);
|
||||
|
||||
gs_effect_t *solid = obs_get_base_effect(OBS_EFFECT_SOLID);
|
||||
gs_eparam_t *color = gs_effect_get_param_by_name(solid, "color");
|
||||
|
||||
gs_effect_set_color(color, OUTLINE_COLOR);
|
||||
while (gs_effect_loop(solid, "Solid"))
|
||||
gs_draw(GS_LINESTRIP, 0, 0);
|
||||
|
||||
gs_matrix_pop();
|
||||
}
|
||||
|
|
|
@ -595,6 +595,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="previewSafeAreas">
|
||||
<property name="text">
|
||||
<string>Basic.Settings.General.Multiview.DrawSafeAreas</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="overflowHide">
|
||||
<property name="text">
|
||||
|
|
|
@ -458,6 +458,8 @@ OBSBasic::OBSBasic(QWidget *parent)
|
|||
|
||||
connect(ui->broadcastButton, &QPushButton::clicked, this,
|
||||
&OBSBasic::BroadcastButtonClicked);
|
||||
|
||||
UpdatePreviewSafeAreas();
|
||||
}
|
||||
|
||||
static void SaveAudioDevice(const char *name, int channel, obs_data_t *parent,
|
||||
|
@ -1642,6 +1644,8 @@ void OBSBasic::InitPrimitives()
|
|||
}
|
||||
circle = gs_render_save();
|
||||
|
||||
InitSafeAreas(&actionSafeMargin, &graphicsSafeMargin,
|
||||
&fourByThreeSafeMargin, &leftLine, &topLine, &rightLine);
|
||||
obs_leave_graphics();
|
||||
}
|
||||
|
||||
|
@ -2643,6 +2647,12 @@ OBSBasic::~OBSBasic()
|
|||
gs_vertexbuffer_destroy(boxRight);
|
||||
gs_vertexbuffer_destroy(boxBottom);
|
||||
gs_vertexbuffer_destroy(circle);
|
||||
gs_vertexbuffer_destroy(actionSafeMargin);
|
||||
gs_vertexbuffer_destroy(graphicsSafeMargin);
|
||||
gs_vertexbuffer_destroy(fourByThreeSafeMargin);
|
||||
gs_vertexbuffer_destroy(leftLine);
|
||||
gs_vertexbuffer_destroy(topLine);
|
||||
gs_vertexbuffer_destroy(rightLine);
|
||||
obs_leave_graphics();
|
||||
|
||||
/* When shutting down, sometimes source references can get in to the
|
||||
|
@ -4081,6 +4091,19 @@ void OBSBasic::RenderMain(void *data, uint32_t cx, uint32_t cy)
|
|||
|
||||
window->ui->preview->DrawSceneEditing();
|
||||
|
||||
uint32_t targetCX = window->previewCX;
|
||||
uint32_t targetCY = window->previewCY;
|
||||
|
||||
if (window->drawSafeAreas) {
|
||||
RenderSafeAreas(window->actionSafeMargin, targetCX, targetCY);
|
||||
RenderSafeAreas(window->graphicsSafeMargin, targetCX, targetCY);
|
||||
RenderSafeAreas(window->fourByThreeSafeMargin, targetCX,
|
||||
targetCY);
|
||||
RenderSafeAreas(window->leftLine, targetCX, targetCY);
|
||||
RenderSafeAreas(window->topLine, targetCX, targetCY);
|
||||
RenderSafeAreas(window->rightLine, targetCX, targetCY);
|
||||
}
|
||||
|
||||
/* --------------------------------------- */
|
||||
|
||||
gs_projection_pop();
|
||||
|
@ -9650,3 +9673,9 @@ void OBSBasic::ShowStatusBarMessage(const QString &message)
|
|||
ui->statusbar->clearMessage();
|
||||
ui->statusbar->showMessage(message, 10000);
|
||||
}
|
||||
|
||||
void OBSBasic::UpdatePreviewSafeAreas()
|
||||
{
|
||||
drawSafeAreas = config_get_bool(App()->GlobalConfig(), "BasicWindow",
|
||||
"ShowSafeAreas");
|
||||
}
|
||||
|
|
|
@ -243,6 +243,13 @@ private:
|
|||
gs_vertbuffer_t *boxBottom = nullptr;
|
||||
gs_vertbuffer_t *circle = nullptr;
|
||||
|
||||
gs_vertbuffer_t *actionSafeMargin = nullptr;
|
||||
gs_vertbuffer_t *graphicsSafeMargin = nullptr;
|
||||
gs_vertbuffer_t *fourByThreeSafeMargin = nullptr;
|
||||
gs_vertbuffer_t *leftLine = nullptr;
|
||||
gs_vertbuffer_t *topLine = nullptr;
|
||||
gs_vertbuffer_t *rightLine = nullptr;
|
||||
|
||||
int previewX = 0, previewY = 0;
|
||||
int previewCX = 0, previewCY = 0;
|
||||
float previewScale = 0.0f;
|
||||
|
@ -570,6 +577,9 @@ private:
|
|||
#endif
|
||||
void BroadcastButtonClicked();
|
||||
|
||||
void UpdatePreviewSafeAreas();
|
||||
bool drawSafeAreas = false;
|
||||
|
||||
public slots:
|
||||
void DeferSaveBegin();
|
||||
void DeferSaveEnd();
|
||||
|
|
|
@ -408,6 +408,7 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent)
|
|||
HookWidget(ui->overflowHide, CHECK_CHANGED, GENERAL_CHANGED);
|
||||
HookWidget(ui->overflowAlwaysVisible,CHECK_CHANGED, GENERAL_CHANGED);
|
||||
HookWidget(ui->overflowSelectionHide,CHECK_CHANGED, GENERAL_CHANGED);
|
||||
HookWidget(ui->previewSafeAreas, CHECK_CHANGED, GENERAL_CHANGED);
|
||||
HookWidget(ui->automaticSearch, CHECK_CHANGED, GENERAL_CHANGED);
|
||||
HookWidget(ui->doubleClickSwitch, CHECK_CHANGED, GENERAL_CHANGED);
|
||||
HookWidget(ui->studioPortraitLayout, CHECK_CHANGED, GENERAL_CHANGED);
|
||||
|
@ -1313,6 +1314,10 @@ void OBSBasicSettings::LoadGeneralSettings()
|
|||
GetGlobalConfig(), "BasicWindow", "OverflowSelectionHidden");
|
||||
ui->overflowSelectionHide->setChecked(overflowSelectionHide);
|
||||
|
||||
bool safeAreas = config_get_bool(GetGlobalConfig(), "BasicWindow",
|
||||
"ShowSafeAreas");
|
||||
ui->previewSafeAreas->setChecked(safeAreas);
|
||||
|
||||
bool automaticSearch = config_get_bool(GetGlobalConfig(), "General",
|
||||
"AutomaticCollectionSearch");
|
||||
ui->automaticSearch->setChecked(automaticSearch);
|
||||
|
@ -3021,6 +3026,12 @@ void OBSBasicSettings::SaveGeneralSettings()
|
|||
config_set_bool(GetGlobalConfig(), "BasicWindow",
|
||||
"OverflowSelectionHidden",
|
||||
ui->overflowSelectionHide->isChecked());
|
||||
if (WidgetChanged(ui->previewSafeAreas)) {
|
||||
config_set_bool(GetGlobalConfig(), "BasicWindow",
|
||||
"ShowSafeAreas",
|
||||
ui->previewSafeAreas->isChecked());
|
||||
main->UpdatePreviewSafeAreas();
|
||||
}
|
||||
if (WidgetChanged(ui->doubleClickSwitch))
|
||||
config_set_bool(GetGlobalConfig(), "BasicWindow",
|
||||
"TransitionOnDoubleClick",
|
||||
|
|
|
@ -70,58 +70,9 @@ OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_, int monitor,
|
|||
&OBSProjector::ScreenRemoved);
|
||||
|
||||
if (type == ProjectorType::Multiview) {
|
||||
obs_enter_graphics();
|
||||
|
||||
// All essential action should be placed inside this area
|
||||
gs_render_start(true);
|
||||
gs_vertex2f(actionSafePercentage, actionSafePercentage);
|
||||
gs_vertex2f(actionSafePercentage, 1 - actionSafePercentage);
|
||||
gs_vertex2f(1 - actionSafePercentage, 1 - actionSafePercentage);
|
||||
gs_vertex2f(1 - actionSafePercentage, actionSafePercentage);
|
||||
gs_vertex2f(actionSafePercentage, actionSafePercentage);
|
||||
actionSafeMargin = gs_render_save();
|
||||
|
||||
// All graphics should be placed inside this area
|
||||
gs_render_start(true);
|
||||
gs_vertex2f(graphicsSafePercentage, graphicsSafePercentage);
|
||||
gs_vertex2f(graphicsSafePercentage, 1 - graphicsSafePercentage);
|
||||
gs_vertex2f(1 - graphicsSafePercentage,
|
||||
1 - graphicsSafePercentage);
|
||||
gs_vertex2f(1 - graphicsSafePercentage, graphicsSafePercentage);
|
||||
gs_vertex2f(graphicsSafePercentage, graphicsSafePercentage);
|
||||
graphicsSafeMargin = gs_render_save();
|
||||
|
||||
// 4:3 safe area for widescreen
|
||||
gs_render_start(true);
|
||||
gs_vertex2f(fourByThreeSafePercentage, graphicsSafePercentage);
|
||||
gs_vertex2f(1 - fourByThreeSafePercentage,
|
||||
graphicsSafePercentage);
|
||||
gs_vertex2f(1 - fourByThreeSafePercentage,
|
||||
1 - graphicsSafePercentage);
|
||||
gs_vertex2f(fourByThreeSafePercentage,
|
||||
1 - graphicsSafePercentage);
|
||||
gs_vertex2f(fourByThreeSafePercentage, graphicsSafePercentage);
|
||||
fourByThreeSafeMargin = gs_render_save();
|
||||
|
||||
gs_render_start(true);
|
||||
gs_vertex2f(0.0f, 0.5f);
|
||||
gs_vertex2f(lineLength, 0.5f);
|
||||
leftLine = gs_render_save();
|
||||
|
||||
gs_render_start(true);
|
||||
gs_vertex2f(0.5f, 0.0f);
|
||||
gs_vertex2f(0.5f, lineLength);
|
||||
topLine = gs_render_save();
|
||||
|
||||
gs_render_start(true);
|
||||
gs_vertex2f(1.0f, 0.5f);
|
||||
gs_vertex2f(1 - lineLength, 0.5f);
|
||||
rightLine = gs_render_save();
|
||||
obs_leave_graphics();
|
||||
|
||||
solid = obs_get_base_effect(OBS_EFFECT_SOLID);
|
||||
color = gs_effect_get_param_by_name(solid, "color");
|
||||
|
||||
InitSafeAreas(&actionSafeMargin, &graphicsSafeMargin,
|
||||
&fourByThreeSafeMargin, &leftLine, &topLine,
|
||||
&rightLine);
|
||||
UpdateMultiview();
|
||||
|
||||
multiviewProjectors.push_back(this);
|
||||
|
@ -297,31 +248,13 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
|
|||
OBSSource programSrc = main->GetProgramSource();
|
||||
bool studioMode = main->IsPreviewProgramMode();
|
||||
|
||||
auto renderVB = [&](gs_vertbuffer_t *vb, int cx, int cy,
|
||||
uint32_t colorVal) {
|
||||
if (!vb)
|
||||
return;
|
||||
|
||||
matrix4 transform;
|
||||
matrix4_identity(&transform);
|
||||
transform.x.x = cx;
|
||||
transform.y.y = cy;
|
||||
|
||||
gs_load_vertexbuffer(vb);
|
||||
|
||||
gs_matrix_push();
|
||||
gs_matrix_mul(&transform);
|
||||
|
||||
gs_effect_set_color(window->color, colorVal);
|
||||
while (gs_effect_loop(window->solid, "Solid"))
|
||||
gs_draw(GS_LINESTRIP, 0, 0);
|
||||
|
||||
gs_matrix_pop();
|
||||
};
|
||||
|
||||
auto drawBox = [&](float cx, float cy, uint32_t colorVal) {
|
||||
gs_effect_set_color(window->color, colorVal);
|
||||
while (gs_effect_loop(window->solid, "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_effect_set_color(color, colorVal);
|
||||
while (gs_effect_loop(solid, "Solid"))
|
||||
gs_draw_sprite(nullptr, 0, (uint32_t)cx, (uint32_t)cy);
|
||||
};
|
||||
|
||||
|
@ -549,17 +482,17 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
|
|||
obs_source_video_render(previewSrc);
|
||||
else
|
||||
obs_render_main_texture();
|
||||
|
||||
if (drawSafeArea) {
|
||||
renderVB(window->actionSafeMargin, targetCX, targetCY,
|
||||
outerColor);
|
||||
renderVB(window->graphicsSafeMargin, targetCX, targetCY,
|
||||
outerColor);
|
||||
renderVB(window->fourByThreeSafeMargin, targetCX, targetCY,
|
||||
outerColor);
|
||||
renderVB(window->leftLine, targetCX, targetCY, outerColor);
|
||||
renderVB(window->topLine, targetCX, targetCY, outerColor);
|
||||
renderVB(window->rightLine, targetCX, targetCY, outerColor);
|
||||
RenderSafeAreas(window->actionSafeMargin, targetCX, targetCY);
|
||||
RenderSafeAreas(window->graphicsSafeMargin, targetCX, targetCY);
|
||||
RenderSafeAreas(window->fourByThreeSafeMargin, targetCX,
|
||||
targetCY);
|
||||
RenderSafeAreas(window->leftLine, targetCX, targetCY);
|
||||
RenderSafeAreas(window->topLine, targetCX, targetCY);
|
||||
RenderSafeAreas(window->rightLine, targetCX, targetCY);
|
||||
}
|
||||
|
||||
endRegion();
|
||||
gs_matrix_pop();
|
||||
|
||||
|
|
|
@ -49,8 +49,6 @@ private:
|
|||
gs_vertbuffer_t *leftLine = nullptr;
|
||||
gs_vertbuffer_t *topLine = nullptr;
|
||||
gs_vertbuffer_t *rightLine = nullptr;
|
||||
gs_effect_t *solid = nullptr;
|
||||
gs_eparam_t *color = nullptr;
|
||||
// Multiview position helpers
|
||||
float thickness = 4;
|
||||
float offset, thicknessx2 = thickness * 2, pvwprgCX, pvwprgCY, sourceX,
|
||||
|
@ -58,11 +56,6 @@ private:
|
|||
siX, siY, siCX, siCY, ppiScaleX, ppiScaleY, siScaleX,
|
||||
siScaleY, fw, fh, ratio;
|
||||
|
||||
float lineLength = 0.1f;
|
||||
// Rec. ITU-R BT.1848-1 / EBU R 95
|
||||
float actionSafePercentage = 0.035f; // 3.5%
|
||||
float graphicsSafePercentage = 0.05f; // 5.0%
|
||||
float fourByThreeSafePercentage = 0.1625f; // 16.25%
|
||||
bool ready = false;
|
||||
|
||||
// argb colors
|
||||
|
|
Loading…
Reference in New Issue