|
|
|
|
@@ -35,6 +35,7 @@
|
|
|
|
|
#include <QLayout>
|
|
|
|
|
#include <QLineEdit>
|
|
|
|
|
#include <QPushButton>
|
|
|
|
|
#include <QSpinBox>
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
std::array<std::string, 4> MonitorNames = {
|
|
|
|
|
@@ -91,20 +92,21 @@ WindowControl::WindowControl(int monitorIndex, int windowIndex,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WindowControl::createWidgets(const QColor& windowColor) {
|
|
|
|
|
// Column 0 Column 1 Column 2 Column 3 Column 4 Column 5 * Column 6 *
|
|
|
|
|
// *----------*----------*----------*----------*----------*----------*----------*
|
|
|
|
|
// | Window {n} | R0
|
|
|
|
|
// | Name * [ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo] | R1
|
|
|
|
|
// | Monitor * DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD> | R2
|
|
|
|
|
// | Size * [xxxxxx] * x * [yyyyyyy] * px * <lock> * | R3
|
|
|
|
|
// | Offset * [xxxxxx] * , * [yyyyyyy] * px * * | R4
|
|
|
|
|
// | <Set to Fullscreen > | R5
|
|
|
|
|
// | [] Window Decoration | R6
|
|
|
|
|
// | [] UI only in this window | R7
|
|
|
|
|
// | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~Detail components~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | R8
|
|
|
|
|
// *----------*----------*----------*----------*----------*----------*----------*
|
|
|
|
|
// Col 0 Col 1 Col 2 Col 3 Col 4 Col 5 Col 6 Col 7
|
|
|
|
|
// *----------*----------*-------*----------*-------*--------*-------*-------*
|
|
|
|
|
// | Window {n} | R0
|
|
|
|
|
// | Name * [oooooooooooooooooooooooooooooooooooooooooooooooooooooooooo] | R1
|
|
|
|
|
// | Monitor * DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD> | R2
|
|
|
|
|
// | Size * [xxxxxx] * x * [yyyyyy] * px * <lock> * < Set to | R3
|
|
|
|
|
// | Offset * [xxxxxx] * , * [yyyyyy] * px * * Fullscreen> | R4
|
|
|
|
|
// | [] Window Decoration | R5
|
|
|
|
|
// | [] UI only in this window | R6
|
|
|
|
|
// | ~~~~~~~~~~~~~~~~~~~~~~~~~Projection components~~~~~~~~~~~~~~~~~~~~~~~~~ | R7
|
|
|
|
|
// *----------*----------*-------*----------*-------*--------*-------*-------*
|
|
|
|
|
|
|
|
|
|
QGridLayout* layout = new QGridLayout(this);
|
|
|
|
|
QMargins margins = layout->contentsMargins();
|
|
|
|
|
layout->setContentsMargins(margins.left(), 0, margins.right(), 0);
|
|
|
|
|
layout->setColumnStretch(6, 1);
|
|
|
|
|
layout->setRowStretch(8, 1);
|
|
|
|
|
|
|
|
|
|
@@ -113,7 +115,7 @@ void WindowControl::createWidgets(const QColor& windowColor) {
|
|
|
|
|
"QLabel {{ color : #{:02x}{:02x}{:02x}; }}",
|
|
|
|
|
windowColor.red(), windowColor.green(), windowColor.blue()
|
|
|
|
|
)));
|
|
|
|
|
layout->addWidget(_windowNumber, 0, 0, 1, 7, Qt::AlignCenter);
|
|
|
|
|
layout->addWidget(_windowNumber, 0, 0, 1, 8, Qt::AlignCenter);
|
|
|
|
|
{
|
|
|
|
|
QString tip = "The name for the window (displayed in title bar).";
|
|
|
|
|
|
|
|
|
|
@@ -123,7 +125,7 @@ void WindowControl::createWidgets(const QColor& windowColor) {
|
|
|
|
|
|
|
|
|
|
_windowName = new QLineEdit;
|
|
|
|
|
_windowName->setToolTip(tip);
|
|
|
|
|
layout->addWidget(_windowName, 1, 1, 1, 6);
|
|
|
|
|
layout->addWidget(_windowName, 1, 1, 1, 7);
|
|
|
|
|
}
|
|
|
|
|
if (_monitorResolutions.size() > 1) {
|
|
|
|
|
QString tip = "The monitor where this window is located.";
|
|
|
|
|
@@ -136,7 +138,7 @@ void WindowControl::createWidgets(const QColor& windowColor) {
|
|
|
|
|
_monitor->addItems(monitorNames(_monitorResolutions));
|
|
|
|
|
_monitor->setCurrentIndex(_monitorIndexDefault);
|
|
|
|
|
_monitor->setToolTip(tip);
|
|
|
|
|
layout->addWidget(_monitor, 2, 1, 1, 6);
|
|
|
|
|
layout->addWidget(_monitor, 2, 1, 1, 7);
|
|
|
|
|
connect(
|
|
|
|
|
_monitor, qOverload<int>(&QComboBox::currentIndexChanged),
|
|
|
|
|
[this]() {
|
|
|
|
|
@@ -150,27 +152,35 @@ void WindowControl::createWidgets(const QColor& windowColor) {
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
QLabel* size = new QLabel("Size");
|
|
|
|
|
size->setToolTip("The window's width & height in pixels.");
|
|
|
|
|
size->setToolTip("The window's width & height in pixels");
|
|
|
|
|
size->setFixedWidth(55);
|
|
|
|
|
layout->addWidget(size, 3, 0);
|
|
|
|
|
|
|
|
|
|
_sizeX = new QLineEdit;
|
|
|
|
|
_sizeX->setValidator(new QIntValidator(10, MaxWindowSizePixels, this));
|
|
|
|
|
_sizeX = new QSpinBox;
|
|
|
|
|
_sizeX->setMinimum(0);
|
|
|
|
|
_sizeX->setMaximum(MaxWindowSizePixels);
|
|
|
|
|
_sizeX->setFixedWidth(LineEditWidthFixedWindowSize);
|
|
|
|
|
_sizeX->setToolTip("The window's width (pixels)");
|
|
|
|
|
layout->addWidget(_sizeX, 3, 1);
|
|
|
|
|
connect(_sizeX, &QLineEdit::textChanged, this, &WindowControl::onSizeXChanged);
|
|
|
|
|
connect(
|
|
|
|
|
_sizeX, QOverload<int>::of(&QSpinBox::valueChanged),
|
|
|
|
|
this, &WindowControl::onSizeXChanged
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
QLabel* delim = new QLabel("x");
|
|
|
|
|
delim->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum));
|
|
|
|
|
layout->addWidget(delim, 3, 2);
|
|
|
|
|
|
|
|
|
|
_sizeY = new QLineEdit;
|
|
|
|
|
_sizeY->setValidator(new QIntValidator(10, MaxWindowSizePixels, this));
|
|
|
|
|
_sizeY = new QSpinBox;
|
|
|
|
|
_sizeY->setMinimum(0);
|
|
|
|
|
_sizeY->setMaximum(MaxWindowSizePixels);
|
|
|
|
|
_sizeY->setFixedWidth(LineEditWidthFixedWindowSize);
|
|
|
|
|
_sizeY->setToolTip("The window's height (pixels).");
|
|
|
|
|
_sizeY->setToolTip("The window's height (pixels)");
|
|
|
|
|
layout->addWidget(_sizeY, 3, 3, Qt::AlignLeft);
|
|
|
|
|
connect(_sizeY, &QLineEdit::textChanged, this, &WindowControl::onSizeYChanged);
|
|
|
|
|
connect(
|
|
|
|
|
_sizeY, QOverload<int>::of(&QSpinBox::valueChanged),
|
|
|
|
|
this, &WindowControl::onSizeYChanged
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
QLabel* unit = new QLabel("px");
|
|
|
|
|
unit->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum));
|
|
|
|
|
@@ -179,7 +189,7 @@ void WindowControl::createWidgets(const QColor& windowColor) {
|
|
|
|
|
QPushButton* lockAspectRatio = new QPushButton;
|
|
|
|
|
lockAspectRatio->setIcon(_unlockIcon);
|
|
|
|
|
lockAspectRatio->setFocusPolicy(Qt::NoFocus);
|
|
|
|
|
lockAspectRatio->setToolTip("Locks/Unlocks size aspect ratio.");
|
|
|
|
|
lockAspectRatio->setToolTip("Locks/Unlocks the aspect ratio of the window size");
|
|
|
|
|
layout->addWidget(lockAspectRatio, 3, 5, Qt::AlignLeft);
|
|
|
|
|
connect(
|
|
|
|
|
lockAspectRatio, &QPushButton::released,
|
|
|
|
|
@@ -201,18 +211,17 @@ void WindowControl::createWidgets(const QColor& windowColor) {
|
|
|
|
|
offset->setFixedWidth(55);
|
|
|
|
|
layout->addWidget(offset, 4, 0);
|
|
|
|
|
|
|
|
|
|
_offsetX = new QLineEdit;
|
|
|
|
|
_offsetX->setValidator(
|
|
|
|
|
new QIntValidator(-MaxWindowSizePixels, MaxWindowSizePixels, this)
|
|
|
|
|
);
|
|
|
|
|
_offsetX = new QSpinBox;
|
|
|
|
|
_offsetX->setMinimum(0);
|
|
|
|
|
_offsetX->setMaximum(MaxWindowSizePixels);
|
|
|
|
|
_offsetX->setToolTip(
|
|
|
|
|
"The x location of the window's upper left corner from monitor's left side "
|
|
|
|
|
"(pixels)."
|
|
|
|
|
"(pixels)"
|
|
|
|
|
);
|
|
|
|
|
_offsetX->setFixedWidth(LineEditWidthFixedWindowSize);
|
|
|
|
|
layout->addWidget(_offsetX, 4, 1);
|
|
|
|
|
connect(
|
|
|
|
|
_offsetX, &QLineEdit::textChanged,
|
|
|
|
|
_offsetX, QOverload<int>::of(&QSpinBox::valueChanged),
|
|
|
|
|
this, &WindowControl::onOffsetXChanged
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
@@ -220,18 +229,17 @@ void WindowControl::createWidgets(const QColor& windowColor) {
|
|
|
|
|
comma->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum));
|
|
|
|
|
layout->addWidget(comma, 4, 2);
|
|
|
|
|
|
|
|
|
|
_offsetY = new QLineEdit;
|
|
|
|
|
_offsetY->setValidator(
|
|
|
|
|
new QIntValidator(-MaxWindowSizePixels, MaxWindowSizePixels, this)
|
|
|
|
|
);
|
|
|
|
|
_offsetY = new QSpinBox;
|
|
|
|
|
_offsetY->setMinimum(0);
|
|
|
|
|
_offsetY->setMaximum(MaxWindowSizePixels);
|
|
|
|
|
_offsetY->setToolTip(
|
|
|
|
|
"The y location of the window's upper left corner from monitor's top edge "
|
|
|
|
|
"(pixels)."
|
|
|
|
|
"(pixels)"
|
|
|
|
|
);
|
|
|
|
|
_offsetY->setFixedWidth(LineEditWidthFixedWindowSize);
|
|
|
|
|
layout->addWidget(_offsetY, 4, 3, Qt::AlignLeft);
|
|
|
|
|
connect(
|
|
|
|
|
_offsetY, &QLineEdit::textChanged,
|
|
|
|
|
_offsetY, QOverload<int>::of(&QSpinBox::valueChanged),
|
|
|
|
|
this, &WindowControl::onOffsetYChanged
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
@@ -240,14 +248,23 @@ void WindowControl::createWidgets(const QColor& windowColor) {
|
|
|
|
|
layout->addWidget(unit, 4, 4, Qt::AlignLeft);
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
QPushButton* setFullscreen = new QPushButton("Set to Fullscreen");
|
|
|
|
|
QBoxLayout* holderLayout = new QHBoxLayout;
|
|
|
|
|
|
|
|
|
|
QPushButton* setFullscreen = new QPushButton("Set Window\nto Fullscreen");
|
|
|
|
|
setFullscreen->setToolTip(
|
|
|
|
|
"If enabled, the window will be created in an exclusive fullscreen mode. The "
|
|
|
|
|
"size of this\nwindow will be set to the screen resolution, and the window "
|
|
|
|
|
"decoration automatically disabled."
|
|
|
|
|
"decoration automatically disabled"
|
|
|
|
|
);
|
|
|
|
|
setFullscreen->setFocusPolicy(Qt::NoFocus);
|
|
|
|
|
layout->addWidget(setFullscreen, 5, 0, 1, 7);
|
|
|
|
|
setFullscreen->setSizePolicy(
|
|
|
|
|
QSizePolicy::MinimumExpanding,
|
|
|
|
|
QSizePolicy::MinimumExpanding
|
|
|
|
|
);
|
|
|
|
|
holderLayout->addStretch();
|
|
|
|
|
holderLayout->addWidget(setFullscreen);
|
|
|
|
|
holderLayout->addStretch();
|
|
|
|
|
layout->addLayout(holderLayout, 3, 6, 2, 2);
|
|
|
|
|
connect(
|
|
|
|
|
setFullscreen, &QPushButton::released,
|
|
|
|
|
this, &WindowControl::onFullscreenClicked
|
|
|
|
|
@@ -257,17 +274,17 @@ void WindowControl::createWidgets(const QColor& windowColor) {
|
|
|
|
|
_windowDecoration->setChecked(true);
|
|
|
|
|
_windowDecoration->setToolTip(
|
|
|
|
|
"If disabled, the window will not have a border frame or title bar, and no\n "
|
|
|
|
|
"controls for minimizing/maximizing, resizing, or closing the window."
|
|
|
|
|
"controls for minimizing/maximizing, resizing, or closing the window"
|
|
|
|
|
);
|
|
|
|
|
layout->addWidget(_windowDecoration, 6, 0, 1, 7);
|
|
|
|
|
layout->addWidget(_windowDecoration, 5, 0, 1, 8);
|
|
|
|
|
|
|
|
|
|
_webGui = new QCheckBox("UI only in this window");
|
|
|
|
|
_webGui = new QCheckBox("Show user interface only in this window");
|
|
|
|
|
_webGui->setToolTip(
|
|
|
|
|
"If enabled, the window will be dedicated solely to displaying the GUI "
|
|
|
|
|
"controls, and will not\nrender any other content. All other window(s) will "
|
|
|
|
|
"render normally but will not have GUI controls."
|
|
|
|
|
"render normally but will not have GUI controls"
|
|
|
|
|
);
|
|
|
|
|
layout->addWidget(_webGui, 7, 0, 1, 7);
|
|
|
|
|
layout->addWidget(_webGui, 6, 0, 1, 8);
|
|
|
|
|
connect(
|
|
|
|
|
_webGui, &QCheckBox::stateChanged,
|
|
|
|
|
[this]() {
|
|
|
|
|
@@ -285,12 +302,18 @@ void WindowControl::createWidgets(const QColor& windowColor) {
|
|
|
|
|
//
|
|
|
|
|
// Projection combobox
|
|
|
|
|
QBoxLayout* projectionLayout = new QVBoxLayout(projectionGroup);
|
|
|
|
|
projectionLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
projectionLayout->setSpacing(0);
|
|
|
|
|
|
|
|
|
|
_projectionType = new QComboBox;
|
|
|
|
|
_projectionType->addItems({
|
|
|
|
|
"Planar", "Fisheye", "Spherical Mirror", "Cylindrical", "Equirectangular"
|
|
|
|
|
"Planar Projection",
|
|
|
|
|
"Fisheye",
|
|
|
|
|
"Spherical Mirror Projection",
|
|
|
|
|
"Cylindrical Projection",
|
|
|
|
|
"Equirectangular Projection"
|
|
|
|
|
});
|
|
|
|
|
_projectionType->setToolTip("Select from the supported window projection types.");
|
|
|
|
|
_projectionType->setToolTip("Select from the supported window projection types");
|
|
|
|
|
_projectionType->setCurrentIndex(0);
|
|
|
|
|
projectionLayout->addWidget(_projectionType);
|
|
|
|
|
connect(
|
|
|
|
|
@@ -316,51 +339,75 @@ void WindowControl::createWidgets(const QColor& windowColor) {
|
|
|
|
|
// We need to trigger this once to ensure that all of the defaults are correct
|
|
|
|
|
onProjectionChanged(0);
|
|
|
|
|
|
|
|
|
|
layout->addWidget(projectionGroup, 8, 0, 1, 7);
|
|
|
|
|
layout->addWidget(projectionGroup, 7, 0, 1, 8);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QWidget* WindowControl::createPlanarWidget() {
|
|
|
|
|
// Column 0 Column 1 Column 2
|
|
|
|
|
// *----------*----------*----------*
|
|
|
|
|
// | HFOV * [oooooo] * Lock * Row 0
|
|
|
|
|
// | VFOV * [oooooo] * Button * Row 1
|
|
|
|
|
// | { Informational text } | Row 0
|
|
|
|
|
// | HFOV * [oooooo] * Lock | Row 1
|
|
|
|
|
// | VFOV * [oooooo] * Button | Row 2
|
|
|
|
|
// *----------*----------*----------*
|
|
|
|
|
|
|
|
|
|
QWidget* widget = new QWidget;
|
|
|
|
|
QGridLayout* layout = new QGridLayout(widget);
|
|
|
|
|
layout->setColumnStretch(1, 1);
|
|
|
|
|
|
|
|
|
|
QLabel* info = new QLabel(
|
|
|
|
|
"This projection type is the 'regular' projection with a horizontal and a "
|
|
|
|
|
"vertical field of view, given in degrees. The wider the field of view, the "
|
|
|
|
|
"more content is shown at the same time, but everything becomes smaller. Very "
|
|
|
|
|
"large values will introduce distorions on the corners"
|
|
|
|
|
);
|
|
|
|
|
info->setObjectName("info");
|
|
|
|
|
info->setWordWrap(true);
|
|
|
|
|
layout->addWidget(info, 0, 0, 1, 3);
|
|
|
|
|
|
|
|
|
|
QLabel* fovH = new QLabel("Horizontal FOV");
|
|
|
|
|
QString hfovTip = "The total horizontal field of view of the viewport (degrees).";
|
|
|
|
|
QString hfovTip = "The total horizontal field of view of the viewport (degrees)";
|
|
|
|
|
fovH->setToolTip(hfovTip);
|
|
|
|
|
layout->addWidget(fovH, 0, 0);
|
|
|
|
|
layout->addWidget(fovH, 1, 0);
|
|
|
|
|
|
|
|
|
|
_planar.fovH = new QLineEdit(QString::number(DefaultFovH));
|
|
|
|
|
_planar.fovH = new QDoubleSpinBox;
|
|
|
|
|
_planar.fovH->setMinimum(0.0);
|
|
|
|
|
_planar.fovH->setMaximum(180.0);
|
|
|
|
|
_planar.fovH->setValue(DefaultFovH);
|
|
|
|
|
_planar.fovH->setEnabled(false);
|
|
|
|
|
_planar.fovH->setValidator(new QDoubleValidator(-180.0, 180.0, 10, this));
|
|
|
|
|
_planar.fovH->setToolTip(hfovTip);
|
|
|
|
|
layout->addWidget(_planar.fovH, 0, 1);
|
|
|
|
|
_planar.fovH->setSizePolicy(
|
|
|
|
|
QSizePolicy::MinimumExpanding,
|
|
|
|
|
QSizePolicy::MinimumExpanding
|
|
|
|
|
);
|
|
|
|
|
layout->addWidget(_planar.fovH, 1, 1);
|
|
|
|
|
|
|
|
|
|
QLabel* fovV = new QLabel("Vertical FOV");
|
|
|
|
|
QString vfovTip = "The total vertical field of view of the viewport (degrees). "
|
|
|
|
|
"Internally,\nthe values for 'up' & 'down' will each be half this value.";
|
|
|
|
|
"Internally,\nthe values for 'up' & 'down' will each be half this value";
|
|
|
|
|
fovV->setToolTip(vfovTip);
|
|
|
|
|
layout->addWidget(fovV, 1, 0);
|
|
|
|
|
layout->addWidget(fovV, 2, 0);
|
|
|
|
|
|
|
|
|
|
_planar.fovV = new QLineEdit(QString::number(DefaultFovV));
|
|
|
|
|
_planar.fovV = new QDoubleSpinBox;
|
|
|
|
|
_planar.fovH->setMinimum(0.0);
|
|
|
|
|
_planar.fovH->setMaximum(90.0);
|
|
|
|
|
_planar.fovH->setValue(DefaultFovV);
|
|
|
|
|
_planar.fovV->setEnabled(false);
|
|
|
|
|
_planar.fovV->setValidator(new QDoubleValidator(-90.0, 90.0, 10, this));
|
|
|
|
|
_planar.fovV->setToolTip(vfovTip);
|
|
|
|
|
layout->addWidget(_planar.fovV, 1, 1);
|
|
|
|
|
_planar.fovH->setSizePolicy(
|
|
|
|
|
QSizePolicy::MinimumExpanding,
|
|
|
|
|
QSizePolicy::MinimumExpanding
|
|
|
|
|
);
|
|
|
|
|
layout->addWidget(_planar.fovV, 2, 1);
|
|
|
|
|
|
|
|
|
|
QPushButton* lockFov = new QPushButton;
|
|
|
|
|
lockFov->setIcon(_lockIcon);
|
|
|
|
|
lockFov->setToolTip(
|
|
|
|
|
"Locks and scales the Horizontal & Vertical field-of-view to the ideal settings "
|
|
|
|
|
"based on the provided aspect ratio."
|
|
|
|
|
"based on the provided aspect ratio"
|
|
|
|
|
);
|
|
|
|
|
lockFov->setFocusPolicy(Qt::NoFocus);
|
|
|
|
|
layout->addWidget(lockFov, 0, 2, 2, 1);
|
|
|
|
|
layout->addWidget(lockFov, 1, 2, 2, 1);
|
|
|
|
|
connect(
|
|
|
|
|
lockFov, &QPushButton::released,
|
|
|
|
|
[this, lockFov]() {
|
|
|
|
|
@@ -368,134 +415,189 @@ QWidget* WindowControl::createPlanarWidget() {
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
connect(lockFov, &QPushButton::released, this, &WindowControl::onFovLockClicked);
|
|
|
|
|
|
|
|
|
|
return widget;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QWidget* WindowControl::createFisheyeWidget() {
|
|
|
|
|
// Column 0 Column 1
|
|
|
|
|
// *----------*----------*
|
|
|
|
|
// | Quality * [DDDDD>] * Row 0
|
|
|
|
|
// | [] Spout Output * Row 1
|
|
|
|
|
// *----------*----------*
|
|
|
|
|
// *------------*-----------*
|
|
|
|
|
// | { Informational text } | Row 0
|
|
|
|
|
// | Quality * [DDDDD>] | Row 1
|
|
|
|
|
// | [] Spout Output | Row 2
|
|
|
|
|
// *------------*-----------*
|
|
|
|
|
|
|
|
|
|
QWidget* widget = new QWidget;
|
|
|
|
|
QGridLayout* layout = new QGridLayout(widget);
|
|
|
|
|
layout->setColumnStretch(1, 1);
|
|
|
|
|
|
|
|
|
|
QLabel* info = new QLabel(
|
|
|
|
|
"This projection provides a rendering in a format that is suitable for "
|
|
|
|
|
"planetariums and other immersive environments. A field-of-view of 180 degrees "
|
|
|
|
|
"is presented as a circular image in the center of the screen. For this "
|
|
|
|
|
"projection a square window is suggested, but not necessary."
|
|
|
|
|
);
|
|
|
|
|
info->setObjectName("info");
|
|
|
|
|
info->setWordWrap(true);
|
|
|
|
|
layout->addWidget(info, 0, 0, 1, 2);
|
|
|
|
|
|
|
|
|
|
QLabel* qualityFisheye = new QLabel("Quality");
|
|
|
|
|
QString qualityTip = "Determines the pixel resolution of the projection rendering. "
|
|
|
|
|
"The higher resolution,\nthe better the rendering quality, but at the expense of "
|
|
|
|
|
"increased rendering times.";
|
|
|
|
|
"increased rendering times";
|
|
|
|
|
qualityFisheye->setToolTip(qualityTip);
|
|
|
|
|
layout->addWidget(qualityFisheye, 0, 0);
|
|
|
|
|
layout->addWidget(qualityFisheye, 1, 0);
|
|
|
|
|
|
|
|
|
|
_fisheye.quality = new QComboBox;
|
|
|
|
|
_fisheye.quality->addItems(QualityTypes);
|
|
|
|
|
_fisheye.quality->setToolTip(qualityTip);
|
|
|
|
|
_fisheye.quality->setCurrentIndex(2);
|
|
|
|
|
layout->addWidget(_fisheye.quality, 0, 1);
|
|
|
|
|
layout->addWidget(_fisheye.quality, 1, 1);
|
|
|
|
|
|
|
|
|
|
_fisheye.spoutOutput = new QCheckBox("Spout Output");
|
|
|
|
|
_fisheye.spoutOutput->setToolTip(
|
|
|
|
|
"This projection method provides the ability to share the reprojected image "
|
|
|
|
|
"using the Spout library.\nThis library only supports the Windows operating "
|
|
|
|
|
"system. Spout makes it possible to make the rendered\nimages available to other "
|
|
|
|
|
"real-time applications on the same machine for further processing."
|
|
|
|
|
"real-time applications on the same machine for further processing"
|
|
|
|
|
);
|
|
|
|
|
layout->addWidget(_fisheye.spoutOutput, 1, 0, 1, 2);
|
|
|
|
|
layout->addWidget(_fisheye.spoutOutput, 2, 0, 1, 2);
|
|
|
|
|
|
|
|
|
|
return widget;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QWidget* WindowControl::createSphericalMirrorWidget() {
|
|
|
|
|
// Column 0 Column 1
|
|
|
|
|
// *----------*----------*
|
|
|
|
|
// | Quality * [DDDDD>] * Row 0
|
|
|
|
|
// *----------*----------*
|
|
|
|
|
// *------------*-----------*
|
|
|
|
|
// | { Informational text } | Row 0
|
|
|
|
|
// | Quality * [DDDDD>] | Row 1
|
|
|
|
|
// *------------*-----------*
|
|
|
|
|
QWidget* widget = new QWidget;
|
|
|
|
|
QGridLayout* layout = new QGridLayout(widget);
|
|
|
|
|
layout->setColumnStretch(1, 1);
|
|
|
|
|
|
|
|
|
|
QLabel* info = new QLabel(
|
|
|
|
|
"This projection is rendering a image suite for use with a spherical mirror "
|
|
|
|
|
"projection as described by Paul Bourke (http://paulbourke.net/dome/mirrordome/) "
|
|
|
|
|
"and which is a low-cost yet effective way to provide content for a sphericalal "
|
|
|
|
|
"display surface using a regular projector."
|
|
|
|
|
);
|
|
|
|
|
info->setObjectName("info");
|
|
|
|
|
info->setWordWrap(true);
|
|
|
|
|
layout->addWidget(info, 0, 0, 1, 2);
|
|
|
|
|
|
|
|
|
|
QLabel* qualitySphericalMirror = new QLabel("Quality");
|
|
|
|
|
QString qualityTip = "Determines the pixel resolution of the projection rendering. "
|
|
|
|
|
"The higher resolution,\nthe better the rendering quality, but at the expense of "
|
|
|
|
|
"increased rendering times.";
|
|
|
|
|
"increased rendering times";
|
|
|
|
|
qualitySphericalMirror->setToolTip(qualityTip);
|
|
|
|
|
layout->addWidget(qualitySphericalMirror, 0, 0);
|
|
|
|
|
layout->addWidget(qualitySphericalMirror, 1, 0);
|
|
|
|
|
|
|
|
|
|
_sphericalMirror.quality = new QComboBox;
|
|
|
|
|
_sphericalMirror.quality->addItems(QualityTypes);
|
|
|
|
|
_sphericalMirror.quality->setToolTip(qualityTip);
|
|
|
|
|
_sphericalMirror.quality->setCurrentIndex(2);
|
|
|
|
|
layout->addWidget(_sphericalMirror.quality, 0, 1);
|
|
|
|
|
layout->addWidget(_sphericalMirror.quality, 1, 1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return widget;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QWidget* WindowControl::createCylindricalWidget() {
|
|
|
|
|
// Column 0 Column 1
|
|
|
|
|
// *----------*----------*
|
|
|
|
|
// | Quality * [DDDDD>] * Row 0
|
|
|
|
|
// | HOffset * [oooooo] * Row 1
|
|
|
|
|
// *----------*----------*
|
|
|
|
|
// *------------*-----------*
|
|
|
|
|
// | { Informational text } | Row 0
|
|
|
|
|
// | Quality * [DDDDD>] | Row 1
|
|
|
|
|
// | HOffset * [oooooo] | Row 2
|
|
|
|
|
// *------------*-----------*
|
|
|
|
|
QWidget* widget = new QWidget;
|
|
|
|
|
QGridLayout* layout = new QGridLayout(widget);
|
|
|
|
|
layout->setColumnStretch(1, 1);
|
|
|
|
|
|
|
|
|
|
QLabel* info = new QLabel(
|
|
|
|
|
"This projection type provides a cylindrical rendering that covers 360 degrees "
|
|
|
|
|
"around the camera, which can be useful in immersive environments that are not "
|
|
|
|
|
"spherical, but where, for example, all walls of a room are covered with "
|
|
|
|
|
"projectors."
|
|
|
|
|
);
|
|
|
|
|
info->setObjectName("info");
|
|
|
|
|
info->setWordWrap(true);
|
|
|
|
|
layout->addWidget(info, 0, 0, 1, 2);
|
|
|
|
|
|
|
|
|
|
QLabel* qualityCylindrical = new QLabel("Quality");
|
|
|
|
|
QString qualityTip = "Determines the pixel resolution of the projection rendering. "
|
|
|
|
|
"The higher resolution,\nthe better the rendering quality, but at the expense of "
|
|
|
|
|
"increased rendering times.";
|
|
|
|
|
"increased rendering times";
|
|
|
|
|
qualityCylindrical->setToolTip(qualityTip);
|
|
|
|
|
layout->addWidget(qualityCylindrical, 0, 0);
|
|
|
|
|
layout->addWidget(qualityCylindrical, 1, 0);
|
|
|
|
|
|
|
|
|
|
_cylindrical.quality = new QComboBox;
|
|
|
|
|
_cylindrical.quality->addItems(QualityTypes);
|
|
|
|
|
_cylindrical.quality->setToolTip(qualityTip);
|
|
|
|
|
_cylindrical.quality->setCurrentIndex(2);
|
|
|
|
|
layout->addWidget(_cylindrical.quality, 0, 1);
|
|
|
|
|
layout->addWidget(_cylindrical.quality, 1, 1);
|
|
|
|
|
|
|
|
|
|
QLabel* heightOffset = new QLabel("Height Offset");
|
|
|
|
|
QString heightTip = "Offsets the height from which the cylindrical projection is "
|
|
|
|
|
"generated.\nThis is, in general, only necessary if the user position is offset "
|
|
|
|
|
"and\ncountering that offset is desired in order to continue producing\na "
|
|
|
|
|
"'standard' cylindrical projection.";
|
|
|
|
|
"'standard' cylindrical projection";
|
|
|
|
|
heightOffset->setToolTip(heightTip);
|
|
|
|
|
layout->addWidget(heightOffset);
|
|
|
|
|
layout->addWidget(heightOffset, 2, 0);
|
|
|
|
|
|
|
|
|
|
_cylindrical.heightOffset = new QLineEdit(QString::number(DefaultHeightOffset));
|
|
|
|
|
_cylindrical.heightOffset->setValidator(
|
|
|
|
|
new QDoubleValidator(-1000000.0, 1000000.0, 12, this)
|
|
|
|
|
);
|
|
|
|
|
_cylindrical.heightOffset = new QDoubleSpinBox;
|
|
|
|
|
_cylindrical.heightOffset->setMinimum(-1000000.0);
|
|
|
|
|
_cylindrical.heightOffset->setMaximum(1000000.0);
|
|
|
|
|
_cylindrical.heightOffset->setValue(DefaultHeightOffset);
|
|
|
|
|
_cylindrical.heightOffset->setToolTip(heightTip);
|
|
|
|
|
layout->addWidget(_cylindrical.heightOffset);
|
|
|
|
|
layout->addWidget(_cylindrical.heightOffset, 2, 1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return widget;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QWidget* WindowControl::createEquirectangularWidget() {
|
|
|
|
|
// Column 0 Column 1
|
|
|
|
|
// *----------*----------*
|
|
|
|
|
// | Quality * [DDDDD>] * Row 0
|
|
|
|
|
// | [] Spout Output * Row 1
|
|
|
|
|
// *----------*----------*
|
|
|
|
|
// *------------*-----------*
|
|
|
|
|
// | { Informational text } | Row 0
|
|
|
|
|
// | Quality * [DDDDD>] | Row 1
|
|
|
|
|
// | [] Spout Output | Row 2
|
|
|
|
|
// *------------*-----------*
|
|
|
|
|
QWidget* widget = new QWidget;
|
|
|
|
|
QGridLayout* layout = new QGridLayout(widget);
|
|
|
|
|
layout->setColumnStretch(1, 1);
|
|
|
|
|
|
|
|
|
|
QLabel* info = new QLabel(
|
|
|
|
|
"This projection provides the rendering as an image in equirectangular "
|
|
|
|
|
"projection, which is a common display type for 360 surround video. When "
|
|
|
|
|
"uploading a video in equirectangular projection to YouTube, for example, it "
|
|
|
|
|
"will use it as a 360 video."
|
|
|
|
|
);
|
|
|
|
|
info->setObjectName("info");
|
|
|
|
|
info->setWordWrap(true);
|
|
|
|
|
layout->addWidget(info, 0, 0, 1, 2);
|
|
|
|
|
|
|
|
|
|
QLabel* qualityEquirectangular = new QLabel("Quality");
|
|
|
|
|
QString qualityTip = "Determines the pixel resolution of the projection rendering. "
|
|
|
|
|
"The higher resolution,\nthe better the rendering quality, but at the expense of "
|
|
|
|
|
"increased rendering times.";
|
|
|
|
|
"increased rendering times";
|
|
|
|
|
qualityEquirectangular->setToolTip(qualityTip);
|
|
|
|
|
layout->addWidget(qualityEquirectangular, 0, 0);
|
|
|
|
|
layout->addWidget(qualityEquirectangular, 1, 0);
|
|
|
|
|
|
|
|
|
|
_equirectangular.quality = new QComboBox;
|
|
|
|
|
_equirectangular.quality->addItems(QualityTypes);
|
|
|
|
|
_equirectangular.quality->setToolTip(qualityTip);
|
|
|
|
|
_equirectangular.quality->setCurrentIndex(2);
|
|
|
|
|
layout->addWidget(_equirectangular.quality, 0, 1);
|
|
|
|
|
layout->addWidget(_equirectangular.quality, 1, 1);
|
|
|
|
|
|
|
|
|
|
_equirectangular.spoutOutput = new QCheckBox("Spout Output");
|
|
|
|
|
_equirectangular.spoutOutput->setToolTip(
|
|
|
|
|
"This projection method provides the ability to share the reprojected image "
|
|
|
|
|
"using the Spout library.\nThis library only supports the Windows operating "
|
|
|
|
|
"system. Spout makes it possible to make the rendered\nimages available to other "
|
|
|
|
|
"real-time applications on the same machine for further processing."
|
|
|
|
|
"real-time applications on the same machine for further processing"
|
|
|
|
|
);
|
|
|
|
|
layout->addWidget(_equirectangular.spoutOutput, 1, 0, 1, 2);
|
|
|
|
|
layout->addWidget(_equirectangular.spoutOutput, 2, 0, 1, 2);
|
|
|
|
|
|
|
|
|
|
return widget;
|
|
|
|
|
}
|
|
|
|
|
@@ -507,15 +609,15 @@ void WindowControl::resetToDefaults() {
|
|
|
|
|
constexpr int PrimaryMonitorIdx = 0;
|
|
|
|
|
|
|
|
|
|
_windowDimensions = DefaultWindowSizes[_windowIndex];
|
|
|
|
|
_offsetX->setText(QString::number(_windowDimensions.x()));
|
|
|
|
|
_offsetY->setText(QString::number(_windowDimensions.y()));
|
|
|
|
|
_offsetX->setValue(_windowDimensions.x());
|
|
|
|
|
_offsetY->setValue(_windowDimensions.y());
|
|
|
|
|
float newHeight =
|
|
|
|
|
_monitorResolutions[PrimaryMonitorIdx].height() * IdealScaleVerticalLines;
|
|
|
|
|
float newWidth = newHeight * IdealAspectRatio;
|
|
|
|
|
_windowDimensions.setHeight(newHeight);
|
|
|
|
|
_windowDimensions.setWidth(newWidth);
|
|
|
|
|
_sizeX->setText(QString::number(static_cast<int>(newWidth)));
|
|
|
|
|
_sizeY->setText(QString::number(static_cast<int>(newHeight)));
|
|
|
|
|
_sizeX->setValue(static_cast<int>(newWidth));
|
|
|
|
|
_sizeY->setValue(static_cast<int>(newHeight));
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Reset widgets
|
|
|
|
|
@@ -528,9 +630,9 @@ void WindowControl::resetToDefaults() {
|
|
|
|
|
_fisheye.spoutOutput->setChecked(false);
|
|
|
|
|
_equirectangular.spoutOutput->setChecked(false);
|
|
|
|
|
_projectionType->setCurrentIndex(static_cast<int>(ProjectionIndices::Planar));
|
|
|
|
|
_planar.fovV->setText(QString::number(DefaultFovH));
|
|
|
|
|
_planar.fovV->setText(QString::number(DefaultFovV));
|
|
|
|
|
_cylindrical.heightOffset->setText(QString::number(DefaultHeightOffset));
|
|
|
|
|
_planar.fovV->setValue(DefaultFovH);
|
|
|
|
|
_planar.fovV->setValue(DefaultFovV);
|
|
|
|
|
_cylindrical.heightOffset->setValue(DefaultHeightOffset);
|
|
|
|
|
_fisheye.quality->setCurrentIndex(2);
|
|
|
|
|
_sphericalMirror.quality->setCurrentIndex(2);
|
|
|
|
|
_cylindrical.quality->setCurrentIndex(2);
|
|
|
|
|
@@ -640,12 +742,12 @@ sgct::config::Window WindowControl::generateWindowInformation() const {
|
|
|
|
|
return window;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WindowControl::onSizeXChanged(const QString& newText) {
|
|
|
|
|
_windowDimensions.setWidth(newText.toInt());
|
|
|
|
|
void WindowControl::onSizeXChanged(int newValue) {
|
|
|
|
|
_windowDimensions.setWidth(newValue);
|
|
|
|
|
if (_aspectRatioLocked) {
|
|
|
|
|
int updatedHeight = _windowDimensions.width() / _aspectRatioSize;
|
|
|
|
|
_sizeY->blockSignals(true);
|
|
|
|
|
_sizeY->setText(QString::number(updatedHeight));
|
|
|
|
|
_sizeY->setValue(updatedHeight);
|
|
|
|
|
_sizeY->blockSignals(false);
|
|
|
|
|
_windowDimensions.setHeight(updatedHeight);
|
|
|
|
|
}
|
|
|
|
|
@@ -655,12 +757,12 @@ void WindowControl::onSizeXChanged(const QString& newText) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WindowControl::onSizeYChanged(const QString& newText) {
|
|
|
|
|
_windowDimensions.setHeight(newText.toInt());
|
|
|
|
|
void WindowControl::onSizeYChanged(int newValue) {
|
|
|
|
|
_windowDimensions.setHeight(newValue);
|
|
|
|
|
if (_aspectRatioLocked) {
|
|
|
|
|
int updatedWidth = _windowDimensions.height() * _aspectRatioSize;
|
|
|
|
|
_sizeX->blockSignals(true);
|
|
|
|
|
_sizeX->setText(QString::number(updatedWidth));
|
|
|
|
|
_sizeX->setValue(updatedWidth);
|
|
|
|
|
_sizeX->blockSignals(false);
|
|
|
|
|
_windowDimensions.setWidth(updatedWidth);
|
|
|
|
|
}
|
|
|
|
|
@@ -670,39 +772,27 @@ void WindowControl::onSizeYChanged(const QString& newText) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WindowControl::onOffsetXChanged(const QString& newText) {
|
|
|
|
|
void WindowControl::onOffsetXChanged(int newValue) {
|
|
|
|
|
float prevWidth = _windowDimensions.width();
|
|
|
|
|
try {
|
|
|
|
|
_windowDimensions.setX(newText.toInt());
|
|
|
|
|
_windowDimensions.setWidth(prevWidth);
|
|
|
|
|
emit windowChanged(_monitor->currentIndex(), _windowIndex, _windowDimensions);
|
|
|
|
|
}
|
|
|
|
|
catch (const std::exception&) {
|
|
|
|
|
// The QIntValidator ensures that the range is a +/- integer. However, it's
|
|
|
|
|
// possible to enter only a - character causing an exception, which is ignored
|
|
|
|
|
// here (when user enters an integer after the - then the value will be updated)
|
|
|
|
|
}
|
|
|
|
|
_windowDimensions.setX(newValue);
|
|
|
|
|
_windowDimensions.setWidth(prevWidth);
|
|
|
|
|
emit windowChanged(_monitor->currentIndex(), _windowIndex, _windowDimensions);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WindowControl::onOffsetYChanged(const QString& newText) {
|
|
|
|
|
void WindowControl::onOffsetYChanged(int newValue) {
|
|
|
|
|
float prevHeight = _windowDimensions.height();
|
|
|
|
|
try {
|
|
|
|
|
_windowDimensions.setY(newText.toInt());
|
|
|
|
|
_windowDimensions.setHeight(prevHeight);
|
|
|
|
|
emit windowChanged(_monitor->currentIndex(), _windowIndex, _windowDimensions);
|
|
|
|
|
}
|
|
|
|
|
catch (const std::exception&) {
|
|
|
|
|
// See comment in onOffsetXChanged
|
|
|
|
|
}
|
|
|
|
|
_windowDimensions.setY(newValue);
|
|
|
|
|
_windowDimensions.setHeight(prevHeight);
|
|
|
|
|
emit windowChanged(_monitor->currentIndex(), _windowIndex, _windowDimensions);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WindowControl::onFullscreenClicked() {
|
|
|
|
|
QRect resolution = _monitorResolutions[_monitor->currentIndex()];
|
|
|
|
|
|
|
|
|
|
_offsetX->setText("0");
|
|
|
|
|
_offsetY->setText("0");
|
|
|
|
|
_sizeX->setText(QString::number(resolution.width()));
|
|
|
|
|
_sizeY->setText(QString::number(resolution.height()));
|
|
|
|
|
_offsetX->setValue(0);
|
|
|
|
|
_offsetY->setValue(0);
|
|
|
|
|
_sizeX->setValue(resolution.width());
|
|
|
|
|
_sizeY->setValue(resolution.height());
|
|
|
|
|
_windowDecoration->setChecked(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -739,12 +829,12 @@ void WindowControl::updatePlanarLockedFov() {
|
|
|
|
|
const float aspectRatio = _windowDimensions.width() / _windowDimensions.height();
|
|
|
|
|
const float ratio = aspectRatio / IdealAspectRatio;
|
|
|
|
|
if (ratio >= 1.f) {
|
|
|
|
|
_planar.fovH->setText(QString::number(std::min(DefaultFovH * ratio, 180.f)));
|
|
|
|
|
_planar.fovV->setText(QString::number(DefaultFovV));
|
|
|
|
|
_planar.fovH->setValue(std::min(DefaultFovH * ratio, 180.f));
|
|
|
|
|
_planar.fovV->setValue(DefaultFovV);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
_planar.fovH->setText(QString::number(DefaultFovH));
|
|
|
|
|
_planar.fovV->setText(QString::number(std::min(DefaultFovV / ratio, 180.f)));
|
|
|
|
|
_planar.fovH->setValue(DefaultFovH);
|
|
|
|
|
_planar.fovV->setValue(std::min(DefaultFovV / ratio, 180.f));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|