diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index a70f3020..3f78c5a7 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -1614,139 +1614,6 @@ Region - - - - - - If cursor is in - - - - - - - Min X: - - - -1000000 - - - 1000000 - - - - - - - Min Y: - - - -1000000 - - - 1000000 - - - - - - - x - - - - - - - Max X: - - - -1000000 - - - 1000000 - - - - - - - Max Y: - - - -1000000 - - - 1000000 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - switch to - - - - - - - - 0 - 0 - - - - - 100 - 0 - - - - - - - - using - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - @@ -1789,6 +1656,20 @@ + + + + Qt::Vertical + + + + + + + Show guide frames + + + @@ -1805,7 +1686,7 @@ - + 0 diff --git a/src/headers/advanced-scene-switcher.hpp b/src/headers/advanced-scene-switcher.hpp index c900bece..6c27109d 100644 --- a/src/headers/advanced-scene-switcher.hpp +++ b/src/headers/advanced-scene-switcher.hpp @@ -33,7 +33,6 @@ public: void SetStarted(); void SetStopped(); - int ScreenRegionFindByData(const QString ®ion); int PauseScenesFindByData(const QString &scene); int PauseWindowsFindByData(const QString &window); int IgnoreWindowsFindByData(const QString &window); @@ -99,7 +98,8 @@ public slots: void on_toggleStartButton_clicked(); void on_tabMoved(int from, int to); - void on_screenRegions_currentRowChanged(int idx); + void on_screenRegionSwitches_currentRowChanged(int idx); + void on_showFrame_clicked(); void on_screenRegionAdd_clicked(); void on_screenRegionRemove_clicked(); void on_screenRegionUp_clicked(); diff --git a/src/headers/switch-screen-region.hpp b/src/headers/switch-screen-region.hpp index 717f2c58..783eac2c 100644 --- a/src/headers/switch-screen-region.hpp +++ b/src/headers/switch-screen-region.hpp @@ -1,5 +1,4 @@ #pragma once -#include #include "utility.hpp" #include "switch-generic.hpp" @@ -7,26 +6,57 @@ constexpr auto screen_region_func = 4; constexpr auto default_priority_4 = screen_region_func; struct ScreenRegionSwitch : SceneSwitcherEntry { - int minX, minY, maxX, maxY; - std::string regionStr; + int minX = 0, minY = 0, maxX = 0, maxY = 0; const char *getType() { return "region"; } + inline ScreenRegionSwitch(){}; inline ScreenRegionSwitch(OBSWeakSource scene_, OBSWeakSource transition_, int minX_, - int minY_, int maxX_, int maxY_, - std::string regionStr_) + int minY_, int maxX_, int maxY_) : SceneSwitcherEntry(scene_, transition_), minX(minX_), minY(minY_), maxX(maxX_), - maxY(maxY_), - regionStr(regionStr_) + maxY(maxY_) { } }; -static inline QString MakeScreenRegionSwitchName(const QString &scene, - const QString &transition, - int minX, int minY, int maxX, - int maxY); +class ScreenRegionWidget : public SwitchWidget { + Q_OBJECT + +public: + ScreenRegionWidget(ScreenRegionSwitch *s); + ScreenRegionSwitch *getSwitchData(); + void setSwitchData(ScreenRegionSwitch *s); + + static void swapSwitchData(ScreenRegionWidget *s1, + ScreenRegionWidget *s2); + + void showFrame(); + void hideFrame(); + +private slots: + void MinXChanged(int pos); + void MinYChanged(int pos); + void MaxXChanged(int pos); + void MaxYChanged(int pos); + +private: + QSpinBox *minX; + QSpinBox *minY; + QSpinBox *maxX; + QSpinBox *maxY; + + QFrame helperFrame; + + QLabel *cursorLabel; + QLabel *xLabel; + QLabel *switchLabel; + QLabel *usingLabel; + + ScreenRegionSwitch *switchData; + + void drawFrame(); +}; diff --git a/src/headers/switcher-data-structs.hpp b/src/headers/switcher-data-structs.hpp index 25c56b87..1b2dd712 100644 --- a/src/headers/switcher-data-structs.hpp +++ b/src/headers/switcher-data-structs.hpp @@ -47,6 +47,7 @@ struct SwitcherData { bool stop = false; bool verbose = false; bool disableHints = false; + bool showFrame = false; bool tansitionOverrideOverride = false; int interval = default_interval; @@ -63,7 +64,7 @@ struct SwitcherData { std::vector ignoreIdleWindows; std::string lastTitle; - std::vector screenRegionSwitches; + std::deque screenRegionSwitches; std::vector pauseScenesSwitches; diff --git a/src/switch-screen-region.cpp b/src/switch-screen-region.cpp index 558675e6..f262f71a 100644 --- a/src/switch-screen-region.cpp +++ b/src/switch-screen-region.cpp @@ -2,6 +2,125 @@ #include "headers/advanced-scene-switcher.hpp" +static QMetaObject::Connection addPulse; + +void clearFrames(QListWidget *list) +{ + for (int i = 0; i < list->count(); ++i) { + ScreenRegionWidget *sw = + (ScreenRegionWidget *)list->itemWidget(list->item(i)); + sw->hideFrame(); + } +} + +void showCurrentFrame(QListWidget *list) +{ + QListWidgetItem *item = list->currentItem(); + + if (!item) + return; + + ScreenRegionWidget *sw = (ScreenRegionWidget *)list->itemWidget(item); + sw->showFrame(); +} + +void SceneSwitcher::on_showFrame_clicked() +{ + switcher->showFrame = !switcher->showFrame; + + if (switcher->showFrame) { + ui->showFrame->setText("Hide guide frames"); + showCurrentFrame(ui->screenRegionSwitches); + } else { + ui->showFrame->setText("Show guide frames"); + clearFrames(ui->screenRegionSwitches); + } +} + +void SceneSwitcher::on_screenRegionSwitches_currentRowChanged(int idx) +{ + if (loading) + return; + + if (switcher->showFrame) { + clearFrames(ui->screenRegionSwitches); + showCurrentFrame(ui->screenRegionSwitches); + } +} + +void SceneSwitcher::on_screenRegionAdd_clicked() +{ + ui->screenRegionAdd->disconnect(addPulse); + + std::lock_guard lock(switcher->m); + switcher->screenRegionSwitches.emplace_back(); + + QListWidgetItem *item; + item = new QListWidgetItem(ui->screenRegionSwitches); + ui->screenRegionSwitches->addItem(item); + ScreenRegionWidget *sw = + new ScreenRegionWidget(&switcher->screenRegionSwitches.back()); + item->setSizeHint(sw->minimumSizeHint()); + ui->screenRegionSwitches->setItemWidget(item, sw); +} + +void SceneSwitcher::on_screenRegionRemove_clicked() +{ + QListWidgetItem *item = ui->screenRegionSwitches->currentItem(); + if (!item) + return; + + { + std::lock_guard lock(switcher->m); + int idx = ui->screenRegionSwitches->currentRow(); + auto &switches = switcher->screenRegionSwitches; + switches.erase(switches.begin() + idx); + } + + delete item; +} + +void SceneSwitcher::on_screenRegionUp_clicked() +{ + int index = ui->screenRegionSwitches->currentRow(); + if (!listMoveUp(ui->screenRegionSwitches)) + return; + + ScreenRegionWidget *s1 = + (ScreenRegionWidget *)ui->screenRegionSwitches->itemWidget( + ui->screenRegionSwitches->item(index)); + ScreenRegionWidget *s2 = + (ScreenRegionWidget *)ui->screenRegionSwitches->itemWidget( + ui->screenRegionSwitches->item(index - 1)); + ScreenRegionWidget::swapSwitchData(s1, s2); + + std::lock_guard lock(switcher->m); + + std::swap(switcher->screenRegionSwitches[index], + switcher->screenRegionSwitches[index - 1]); +} + +void SceneSwitcher::on_screenRegionDown_clicked() +{ + int index = ui->screenRegionSwitches->currentRow(); + + if (!listMoveDown(ui->screenRegionSwitches)) + return; + + ScreenRegionWidget *s1 = + (ScreenRegionWidget *)ui->screenRegionSwitches->itemWidget( + ui->screenRegionSwitches->item(index)); + ScreenRegionWidget *s2 = + (ScreenRegionWidget *)ui->screenRegionSwitches->itemWidget( + ui->screenRegionSwitches->item(index + 1)); + ScreenRegionWidget::swapSwitchData(s1, s2); + + std::lock_guard lock(switcher->m); + + std::swap(switcher->screenRegionSwitches[index], + switcher->screenRegionSwitches[index + 1]); +} + void SwitcherData::checkScreenRegionSwitch(bool &match, OBSWeakSource &scene, OBSWeakSource &transition) { @@ -33,163 +152,6 @@ void SceneSwitcher::updateScreenRegionCursorPos() ui->cursorYPosition->setText(QString::number(position.second)); } -void SceneSwitcher::on_screenRegionAdd_clicked() -{ - QString sceneName = ui->screenRegionScenes->currentText(); - QString transitionName = ui->screenRegionsTransitions->currentText(); - - if (sceneName.isEmpty()) - return; - - int minX = ui->screenRegionMinX->value(); - int minY = ui->screenRegionMinY->value(); - int maxX = ui->screenRegionMaxX->value(); - int maxY = ui->screenRegionMaxY->value(); - - std::string regionStr = - std::to_string(minX) + ", " + std::to_string(minY) + " x " + - std::to_string(maxX) + ", " + std::to_string(maxY); - QString region = QString::fromStdString(regionStr); - - OBSWeakSource source = GetWeakSourceByQString(sceneName); - OBSWeakSource transition = GetWeakTransitionByQString(transitionName); - QVariant v = QVariant::fromValue(region); - - QString text = MakeScreenRegionSwitchName(sceneName, transitionName, - minX, minY, maxX, maxY); - - int idx = ScreenRegionFindByData(region); - - if (idx == -1) { - QListWidgetItem *item = - new QListWidgetItem(text, ui->screenRegions); - item->setData(Qt::UserRole, v); - - std::lock_guard lock(switcher->m); - switcher->screenRegionSwitches.emplace_back( - source, transition, minX, minY, maxX, maxY, regionStr); - } else { - QListWidgetItem *item = ui->screenRegions->item(idx); - item->setText(text); - - std::string curRegion = region.toUtf8().constData(); - - { - std::lock_guard lock(switcher->m); - for (auto &s : switcher->screenRegionSwitches) { - if (s.regionStr == curRegion) { - s.scene = source; - s.transition = transition; - break; - } - } - } - } -} - -void SceneSwitcher::on_screenRegionRemove_clicked() -{ - QListWidgetItem *item = ui->screenRegions->currentItem(); - if (!item) - return; - - std::string region = - item->data(Qt::UserRole).toString().toUtf8().constData(); - - { - std::lock_guard lock(switcher->m); - auto &switches = switcher->screenRegionSwitches; - - for (auto it = switches.begin(); it != switches.end(); ++it) { - auto &s = *it; - - if (s.regionStr == region) { - switches.erase(it); - break; - } - } - } - - delete item; -} - -void SceneSwitcher::on_screenRegions_currentRowChanged(int idx) -{ - if (loading) - return; - if (idx == -1) - return; - - QListWidgetItem *item = ui->screenRegions->item(idx); - - QString region = item->data(Qt::UserRole).toString(); - - std::lock_guard lock(switcher->m); - for (auto &s : switcher->screenRegionSwitches) { - if (region.compare(s.regionStr.c_str()) == 0) { - std::string name = GetWeakSourceName(s.scene); - std::string transitionName = - GetWeakSourceName(s.transition); - ui->screenRegionScenes->setCurrentText(name.c_str()); - ui->screenRegionsTransitions->setCurrentText( - transitionName.c_str()); - ui->screenRegionMinX->setValue(s.minX); - ui->screenRegionMinY->setValue(s.minY); - ui->screenRegionMaxX->setValue(s.maxX); - ui->screenRegionMaxY->setValue(s.maxY); - break; - } - } -} - -int SceneSwitcher::ScreenRegionFindByData(const QString ®ion) -{ - int count = ui->screenRegions->count(); - int idx = -1; - - for (int i = 0; i < count; i++) { - QListWidgetItem *item = ui->screenRegions->item(i); - QString itemRegion = item->data(Qt::UserRole).toString(); - - if (itemRegion == region) { - idx = i; - break; - } - } - - return idx; -} - -void SceneSwitcher::on_screenRegionUp_clicked() -{ - int index = ui->screenRegions->currentRow(); - if (index != -1 && index != 0) { - ui->screenRegions->insertItem( - index - 1, ui->screenRegions->takeItem(index)); - ui->screenRegions->setCurrentRow(index - 1); - - std::lock_guard lock(switcher->m); - - iter_swap(switcher->screenRegionSwitches.begin() + index, - switcher->screenRegionSwitches.begin() + index - 1); - } -} - -void SceneSwitcher::on_screenRegionDown_clicked() -{ - int index = ui->screenRegions->currentRow(); - if (index != -1 && index != ui->screenRegions->count() - 1) { - ui->screenRegions->insertItem( - index + 1, ui->screenRegions->takeItem(index)); - ui->screenRegions->setCurrentRow(index + 1); - - std::lock_guard lock(switcher->m); - - iter_swap(switcher->screenRegionSwitches.begin() + index, - switcher->screenRegionSwitches.begin() + index + 1); - } -} - void SwitcherData::saveScreenRegionSwitches(obs_data_t *obj) { obs_data_array_t *screenRegionArray = obs_data_array_create(); @@ -243,16 +205,10 @@ void SwitcherData::loadScreenRegionSwitches(obs_data_t *obj) int maxX = obs_data_get_int(array_obj, "maxX"); int maxY = obs_data_get_int(array_obj, "maxY"); - std::string regionStr = - MakeScreenRegionSwitchName(scene, transition, minX, - minY, maxX, maxY) - .toUtf8() - .constData(); - switcher->screenRegionSwitches.emplace_back( GetWeakSourceByName(scene), GetWeakTransitionByName(transition), minX, minY, maxX, - maxY, regionStr); + maxY); obs_data_release(array_obj); } @@ -261,21 +217,18 @@ void SwitcherData::loadScreenRegionSwitches(obs_data_t *obj) void SceneSwitcher::setupRegionTab() { - populateSceneSelection(ui->screenRegionScenes, false); - populateTransitionSelection(ui->screenRegionsTransitions); - for (auto &s : switcher->screenRegionSwitches) { - std::string sceneName = GetWeakSourceName(s.scene); - std::string transitionName = GetWeakSourceName(s.transition); - QString text = MakeScreenRegionSwitchName( - sceneName.c_str(), transitionName.c_str(), s.minX, - s.minY, s.maxX, s.maxY); - - QListWidgetItem *item = - new QListWidgetItem(text, ui->screenRegions); - item->setData(Qt::UserRole, s.regionStr.c_str()); + QListWidgetItem *item; + item = new QListWidgetItem(ui->screenRegionSwitches); + ui->screenRegionSwitches->addItem(item); + ScreenRegionWidget *sw = new ScreenRegionWidget(&s); + item->setSizeHint(sw->minimumSizeHint()); + ui->screenRegionSwitches->setItemWidget(item, sw); } + if (switcher->screenRegionSwitches.size() == 0) + addPulse = PulseWidget(ui->screenRegionAdd, QColor(Qt::green)); + // screen region cursor position QTimer *screenRegionTimer = new QTimer(this); connect(screenRegionTimer, SIGNAL(timeout()), this, @@ -283,14 +236,155 @@ void SceneSwitcher::setupRegionTab() screenRegionTimer->start(1000); } -static inline QString MakeScreenRegionSwitchName(const QString &scene, - const QString &transition, - int minX, int minY, int maxX, - int maxY) +ScreenRegionWidget::ScreenRegionWidget(ScreenRegionSwitch *s) + : SwitchWidget(s, false) { - return QStringLiteral("[") + scene + QStringLiteral(", ") + transition + - QStringLiteral("]: ") + QString::number(minX) + - QStringLiteral(", ") + QString::number(minY) + - QStringLiteral(" x ") + QString::number(maxX) + - QStringLiteral(", ") + QString::number(maxY); + minX = new QSpinBox(); + minY = new QSpinBox(); + maxX = new QSpinBox(); + maxY = new QSpinBox(); + + cursorLabel = new QLabel("If cursor is in"); + xLabel = new QLabel("x"); + switchLabel = new QLabel("switch to"); + usingLabel = new QLabel("using"); + + minX->setPrefix("Min X: "); + minY->setPrefix("Min Y: "); + maxX->setPrefix("Max X: "); + maxY->setPrefix("Max Y: "); + + minX->setMinimum(-1000000); + minY->setMinimum(-1000000); + maxX->setMinimum(-1000000); + maxY->setMinimum(-1000000); + + minX->setMaximum(1000000); + minY->setMaximum(1000000); + maxX->setMaximum(1000000); + maxY->setMaximum(1000000); + + QWidget::connect(minX, SIGNAL(valueChanged(int)), this, + SLOT(MinXChanged(int))); + QWidget::connect(minY, SIGNAL(valueChanged(int)), this, + SLOT(MinYChanged(int))); + QWidget::connect(maxX, SIGNAL(valueChanged(int)), this, + SLOT(MaxXChanged(int))); + QWidget::connect(maxY, SIGNAL(valueChanged(int)), this, + SLOT(MaxYChanged(int))); + + if (s) { + minX->setValue(s->minX); + minY->setValue(s->minY); + maxX->setValue(s->maxX); + maxY->setValue(s->maxY); + } + + setStyleSheet("* { background-color: transparent; }"); + + QHBoxLayout *mainLayout = new QHBoxLayout; + + mainLayout->addWidget(cursorLabel); + mainLayout->addWidget(minX); + mainLayout->addWidget(minY); + mainLayout->addWidget(xLabel); + mainLayout->addWidget(maxX); + mainLayout->addWidget(maxY); + mainLayout->addWidget(switchLabel); + mainLayout->addWidget(scenes); + mainLayout->addWidget(usingLabel); + mainLayout->addWidget(transitions); + mainLayout->addStretch(); + + setLayout(mainLayout); + + switchData = s; + + loading = false; +} + +ScreenRegionSwitch *ScreenRegionWidget::getSwitchData() +{ + return switchData; +} + +void ScreenRegionWidget::setSwitchData(ScreenRegionSwitch *s) +{ + switchData = s; +} + +void ScreenRegionWidget::swapSwitchData(ScreenRegionWidget *s1, + ScreenRegionWidget *s2) +{ + SwitchWidget::swapSwitchData(s1, s2); + + ScreenRegionSwitch *t = s1->getSwitchData(); + s1->setSwitchData(s2->getSwitchData()); + s2->setSwitchData(t); +} + +void ScreenRegionWidget::showFrame() +{ + drawFrame(); + helperFrame.show(); +} + +void ScreenRegionWidget::hideFrame() +{ + helperFrame.hide(); +} + +void ScreenRegionWidget::MinXChanged(int pos) +{ + if (loading || !switchData) + return; + std::lock_guard lock(switcher->m); + switchData->minX = pos; + + drawFrame(); +} + +void ScreenRegionWidget::MinYChanged(int pos) +{ + if (loading || !switchData) + return; + std::lock_guard lock(switcher->m); + switchData->minY = pos; + + drawFrame(); +} + +void ScreenRegionWidget::MaxXChanged(int pos) +{ + if (loading || !switchData) + return; + std::lock_guard lock(switcher->m); + switchData->maxX = pos; + + drawFrame(); +} + +void ScreenRegionWidget::MaxYChanged(int pos) +{ + if (loading || !switchData) + return; + std::lock_guard lock(switcher->m); + switchData->maxY = pos; + + drawFrame(); +} + +void ScreenRegionWidget::drawFrame() +{ + helperFrame.setFrameStyle(QFrame::Box | QFrame::Plain); + helperFrame.setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | + Qt::WindowTransparentForInput | + Qt::WindowDoesNotAcceptFocus | + Qt::WindowStaysOnTopHint); + helperFrame.setAttribute(Qt::WA_TranslucentBackground, true); + + if (switchData) + helperFrame.setGeometry(switchData->minX, switchData->minY, + switchData->maxX - switchData->minX, + switchData->maxY - switchData->minY); }