mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-03-21 17:34:57 -05:00
Add option to close projector windows
This commit is contained in:
parent
213f1bba36
commit
ae74f68db7
|
|
@ -1113,6 +1113,8 @@ AdvSceneSwitcher.action.variable.entry.userInput.customPrompt="{{useCustomPrompt
|
|||
AdvSceneSwitcher.action.variable.entry.userInput.placeholder="{{useInputPlaceholder}}Fill with placeholder{{inputPlaceholder}}"
|
||||
AdvSceneSwitcher.action.variable.entry.randomNumber="Generate random number in range from{{randomNumberStart}}to{{randomNumberEnd}}"
|
||||
AdvSceneSwitcher.action.projector="Projector"
|
||||
AdvSceneSwitcher.action.projector.action.open="Open"
|
||||
AdvSceneSwitcher.action.projector.action.close="Close"
|
||||
AdvSceneSwitcher.action.projector.type.source="Source"
|
||||
AdvSceneSwitcher.action.projector.type.scene="Scene"
|
||||
AdvSceneSwitcher.action.projector.type.preview="Preview"
|
||||
|
|
@ -1121,8 +1123,9 @@ AdvSceneSwitcher.action.projector.type.multiview="Multiview"
|
|||
AdvSceneSwitcher.action.projector.display="Display"
|
||||
AdvSceneSwitcher.action.projector.windowed="Windowed"
|
||||
AdvSceneSwitcher.action.projector.fullscreen="Fullscreen"
|
||||
AdvSceneSwitcher.action.projector.entry="Open{{windowTypes}}projector of{{types}}{{scenes}}{{sources}}"
|
||||
AdvSceneSwitcher.action.projector.entry.monitor="on{{monitors}}"
|
||||
AdvSceneSwitcher.action.projector.entry.close="{{actions}}projector with name{{projectorWindowName}}{{regex}}"
|
||||
AdvSceneSwitcher.action.projector.entry.open.windowed="{{actions}}{{windowTypes}}projector of{{types}}{{scenes}}{{sources}}"
|
||||
AdvSceneSwitcher.action.projector.entry.open.fullscreen="{{actions}}{{windowTypes}}projector of{{types}}{{scenes}}{{sources}}on{{monitors}}"
|
||||
AdvSceneSwitcher.action.midi="MIDI"
|
||||
AdvSceneSwitcher.action.midi.entry="Send message to{{device}}:"
|
||||
AdvSceneSwitcher.action.midi.entry.listen="Set MIDI message selection to messages incoming on{{listenDevices}}:{{listenButton}}"
|
||||
|
|
|
|||
|
|
@ -718,8 +718,6 @@ AdvSceneSwitcher.action.projector.type.multiview="Multivue"
|
|||
AdvSceneSwitcher.action.projector.display="Affichage"
|
||||
AdvSceneSwitcher.action.projector.windowed="Fenêtré"
|
||||
AdvSceneSwitcher.action.projector.fullscreen="Plein écran"
|
||||
AdvSceneSwitcher.action.projector.entry="Ouvrir le projecteur{{windowTypes}}de{{types}}{{scenes}}{{sources}}"
|
||||
AdvSceneSwitcher.action.projector.entry.monitor="sur{{monitors}}"
|
||||
AdvSceneSwitcher.action.midi="MIDI"
|
||||
AdvSceneSwitcher.action.midi.entry="Envoyer un message à{{device}}:"
|
||||
AdvSceneSwitcher.action.midi.entry.listen="Définir la sélection de messages MIDI sur les messages entrants de{{listenDevices}}:{{listenButton}}"
|
||||
|
|
|
|||
|
|
@ -1068,8 +1068,6 @@ AdvSceneSwitcher.action.projector.type.multiview="マルチビュー"
|
|||
AdvSceneSwitcher.action.projector.display="ディスプレイ"
|
||||
AdvSceneSwitcher.action.projector.windowed="ウィンドウ"
|
||||
AdvSceneSwitcher.action.projector.fullscreen="フルスクリーン"
|
||||
AdvSceneSwitcher.action.projector.entry="{{types}}{{scenes}}{{sources}}の{{windowTypes}}プロジェクターを開きます"
|
||||
AdvSceneSwitcher.action.projector.entry.monitor="{{monitors}}上で"
|
||||
; AdvSceneSwitcher.action.midi="MIDI"
|
||||
AdvSceneSwitcher.action.midi.entry="メッセージを{{device}}に送信します:"
|
||||
AdvSceneSwitcher.action.midi.entry.listen="MIDI メッセージの選択を {{listenDevices}} で受信するメッセージに設定します:{{listenButton}}"
|
||||
|
|
|
|||
|
|
@ -1049,8 +1049,6 @@ AdvSceneSwitcher.action.projector.type.multiview="Multivisão"
|
|||
AdvSceneSwitcher.action.projector.display="Exibição"
|
||||
AdvSceneSwitcher.action.projector.windowed="Janela"
|
||||
AdvSceneSwitcher.action.projector.fullscreen="Tela cheia"
|
||||
AdvSceneSwitcher.action.projector.entry="Abrir{{windowTypes}}projetor de{{types}}{{scenes}}{{sources}}"
|
||||
AdvSceneSwitcher.action.projector.entry.monitor="em{{monitors}}"
|
||||
AdvSceneSwitcher.action.midi="MIDI"
|
||||
AdvSceneSwitcher.action.midi.entry="Enviar mensagem para{{device}}:"
|
||||
AdvSceneSwitcher.action.midi.entry.listen="Definir seleção de mensagem MIDI para mensagens recebidas em{{listenDevices}}:{{listenButton}}"
|
||||
|
|
|
|||
|
|
@ -644,8 +644,6 @@ AdvSceneSwitcher.action.projector.type.multiview="多视图"
|
|||
AdvSceneSwitcher.action.projector.display="显示"
|
||||
AdvSceneSwitcher.action.projector.windowed="窗口"
|
||||
AdvSceneSwitcher.action.projector.fullscreen="全屏"
|
||||
AdvSceneSwitcher.action.projector.entry="打开为{{windowTypes}} 的 {{types}}{{scenes}}{{sources}}投影"
|
||||
AdvSceneSwitcher.action.projector.entry.monitor="在 {{monitors}} 上 (从不咕咕的阿坤说:谨慎开启!)"
|
||||
AdvSceneSwitcher.action.midi="MIDI"
|
||||
AdvSceneSwitcher.action.midi.entry="发送消息到 {{device}}:"
|
||||
AdvSceneSwitcher.action.midi.entry.listen="将MIDI消息选择设置为 {{listenDevices}} 上传入的消息: {{listenButton}}"
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
#include "source-helpers.hpp"
|
||||
|
||||
#include <obs-frontend-api.h>
|
||||
#include <QApplication>
|
||||
#include <QWindow>
|
||||
|
||||
namespace advss {
|
||||
|
||||
|
|
@ -28,8 +30,34 @@ const static std::map<MacroActionProjector::Type, std::string> selectionTypes =
|
|||
"AdvSceneSwitcher.action.projector.type.multiview"},
|
||||
};
|
||||
|
||||
static void closeOBSProjectorWindows(const std::string expectedWindowTitle,
|
||||
const RegexConfig ®ex)
|
||||
{
|
||||
for (QWindow *widget : QApplication::allWindows()) {
|
||||
if (!widget->property("isOBSProjectorWindow").toBool()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto const windowTitle = widget->title().toStdString();
|
||||
if (!regex.Enabled() && expectedWindowTitle != windowTitle) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!regex.Matches(windowTitle, expectedWindowTitle)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
widget->close();
|
||||
}
|
||||
}
|
||||
|
||||
bool MacroActionProjector::PerformAction()
|
||||
{
|
||||
if (_action == Action::CLOSE) {
|
||||
closeOBSProjectorWindows(_projectorWindowName, _regex);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string name = "";
|
||||
const char *type = "";
|
||||
|
||||
|
|
@ -78,10 +106,16 @@ bool MacroActionProjector::PerformAction()
|
|||
|
||||
void MacroActionProjector::LogAction() const
|
||||
{
|
||||
if (_action == Action::CLOSE) {
|
||||
ablog(LOG_INFO, "closing projector window \"%s\"",
|
||||
_projectorWindowName.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = selectionTypes.find(_type);
|
||||
if (it != selectionTypes.end()) {
|
||||
ablog(LOG_INFO,
|
||||
"performed projector action \"%s\" with"
|
||||
"open projector \"%s\" with"
|
||||
"source \"%s\","
|
||||
"scene \"%s\","
|
||||
"monitor %d",
|
||||
|
|
@ -96,24 +130,30 @@ void MacroActionProjector::LogAction() const
|
|||
bool MacroActionProjector::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
obs_data_set_int(obj, "type", static_cast<int>(_type));
|
||||
obs_data_set_int(obj, "monitor", _monitor);
|
||||
obs_data_set_string(obj, "monitorName", _monitorName.c_str());
|
||||
obs_data_set_bool(obj, "fullscreen", _fullscreen);
|
||||
_scene.Save(obj);
|
||||
_source.Save(obj);
|
||||
_projectorWindowName.Save(obj, "projectorWindowName");
|
||||
_regex.Save(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionProjector::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
|
||||
_type = static_cast<Type>(obs_data_get_int(obj, "type"));
|
||||
_monitor = obs_data_get_int(obj, "monitor");
|
||||
_monitorName = obs_data_get_string(obj, "monitorName");
|
||||
_fullscreen = obs_data_get_bool(obj, "fullscreen");
|
||||
_scene.Load(obj);
|
||||
_source.Load(obj);
|
||||
_projectorWindowName.Load(obj, "projectorWindowName");
|
||||
_regex.Load(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -131,6 +171,7 @@ void MacroActionProjector::ResolveVariablesToFixedValues()
|
|||
{
|
||||
_source.ResolveVariables();
|
||||
_scene.ResolveVariables();
|
||||
_projectorWindowName.ResolveVariables();
|
||||
}
|
||||
|
||||
void MacroActionProjector::SetMonitor(int idx)
|
||||
|
|
@ -166,14 +207,22 @@ bool MacroActionProjector::MonitorSetupChanged() const
|
|||
QString::fromStdString(_monitorName);
|
||||
}
|
||||
|
||||
static inline void populateSelectionTypes(QComboBox *list)
|
||||
static void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : selectionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
list->addItem(obs_module_text(
|
||||
"AdvSceneSwitcher.action.projector.action.open"));
|
||||
list->addItem(obs_module_text(
|
||||
"AdvSceneSwitcher.action.projector.action.close"));
|
||||
}
|
||||
|
||||
static void populateSelectionTypes(QComboBox *list)
|
||||
{
|
||||
for (const auto &[_, name] : selectionTypes) {
|
||||
list->addItem(obs_module_text(name.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void populateWindowTypes(QComboBox *list)
|
||||
static void populateWindowTypes(QComboBox *list)
|
||||
{
|
||||
list->addItem(
|
||||
obs_module_text("AdvSceneSwitcher.action.projector.windowed"));
|
||||
|
|
@ -184,14 +233,18 @@ static inline void populateWindowTypes(QComboBox *list)
|
|||
MacroActionProjectorEdit::MacroActionProjectorEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionProjector> entryData)
|
||||
: QWidget(parent),
|
||||
_windowTypes(new QComboBox()),
|
||||
_actions(new QComboBox()),
|
||||
_types(new QComboBox()),
|
||||
_windowTypes(new QComboBox()),
|
||||
_scenes(new SceneSelectionWidget(window(), true, false, true, true,
|
||||
true)),
|
||||
_sources(new SourceSelectionWidget(window(), QStringList(), true)),
|
||||
_monitorSelection(new QHBoxLayout()),
|
||||
_monitors(new QComboBox())
|
||||
_monitors(new QComboBox()),
|
||||
_projectorWindowName(new VariableLineEdit(this)),
|
||||
_regex(new RegexConfigWidget(this)),
|
||||
_layout(new QHBoxLayout(this))
|
||||
{
|
||||
populateActionSelection(_actions);
|
||||
populateWindowTypes(_windowTypes);
|
||||
populateSelectionTypes(_types);
|
||||
auto sources = GetSourceNames();
|
||||
|
|
@ -201,6 +254,8 @@ MacroActionProjectorEdit::MacroActionProjectorEdit(
|
|||
_monitors->setPlaceholderText(
|
||||
obs_module_text("AdvSceneSwitcher.selectDisplay"));
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
QWidget::connect(_windowTypes, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(WindowTypeChanged(int)));
|
||||
QWidget::connect(_types, SIGNAL(currentIndexChanged(int)), this,
|
||||
|
|
@ -212,24 +267,15 @@ MacroActionProjectorEdit::MacroActionProjectorEdit(
|
|||
SLOT(SourceChanged(const SourceSelection &)));
|
||||
QWidget::connect(_monitors, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(MonitorChanged(int)));
|
||||
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{windowTypes}}", _windowTypes}, {"{{types}}", _types},
|
||||
{"{{scenes}}", _scenes}, {"{{sources}}", _sources},
|
||||
{"{{monitors}}", _monitors},
|
||||
};
|
||||
|
||||
PlaceWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.action.projector.entry.monitor"),
|
||||
_monitorSelection, widgetPlaceholders);
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.projector.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
mainLayout->insertLayout(mainLayout->count() - 1, _monitorSelection);
|
||||
setLayout(mainLayout);
|
||||
QWidget::connect(_projectorWindowName, SIGNAL(editingFinished()), this,
|
||||
SLOT(ProjectorWindowNameChanged()));
|
||||
QWidget::connect(_regex,
|
||||
SIGNAL(RegexConfigChanged(const RegexConfig &)), this,
|
||||
SLOT(RegexChanged(const RegexConfig &)));
|
||||
|
||||
_entryData = entryData;
|
||||
SetWidgetLayout();
|
||||
setLayout(_layout);
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
|
@ -239,11 +285,15 @@ void MacroActionProjectorEdit::UpdateEntryData()
|
|||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_windowTypes->setCurrentIndex(_entryData->_fullscreen ? 1 : 0);
|
||||
_types->setCurrentIndex(static_cast<int>(_entryData->_type));
|
||||
_scenes->SetScene(_entryData->_scene);
|
||||
_sources->SetSource(_entryData->_source);
|
||||
_monitors->setCurrentIndex(_entryData->GetMonitor());
|
||||
_projectorWindowName->setText(_entryData->_projectorWindowName);
|
||||
_regex->SetRegexConfig(_entryData->_regex);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
|
|
@ -265,12 +315,26 @@ void MacroActionProjectorEdit::MonitorChanged(int value)
|
|||
_entryData->SetMonitor(value);
|
||||
}
|
||||
|
||||
void MacroActionProjectorEdit::ProjectorWindowNameChanged()
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_projectorWindowName =
|
||||
_projectorWindowName->text().toStdString();
|
||||
}
|
||||
|
||||
void MacroActionProjectorEdit::RegexChanged(const RegexConfig ®ex)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_regex = regex;
|
||||
}
|
||||
|
||||
void MacroActionProjectorEdit::WindowTypeChanged(int)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_fullscreen =
|
||||
_windowTypes->currentText() ==
|
||||
obs_module_text("AdvSceneSwitcher.action.projector.fullscreen");
|
||||
SetWidgetLayout();
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
|
|
@ -281,17 +345,69 @@ void MacroActionProjectorEdit::TypeChanged(int value)
|
|||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionProjectorEdit::ActionChanged(int idx)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_action = static_cast<MacroActionProjector::Action>(idx);
|
||||
SetWidgetLayout();
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionProjectorEdit::SetWidgetLayout()
|
||||
{
|
||||
const std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{actions}}", _actions},
|
||||
{"{{windowTypes}}", _windowTypes},
|
||||
{"{{types}}", _types},
|
||||
{"{{scenes}}", _scenes},
|
||||
{"{{sources}}", _sources},
|
||||
{"{{monitors}}", _monitors},
|
||||
{"{{projectorWindowName}}", _projectorWindowName},
|
||||
{"{{regex}}", _regex},
|
||||
};
|
||||
|
||||
for (const auto &[_, widget] : widgetPlaceholders) {
|
||||
_layout->removeWidget(widget);
|
||||
}
|
||||
ClearLayout(_layout);
|
||||
|
||||
const char *layoutText;
|
||||
if (_entryData->_action == MacroActionProjector::Action::CLOSE) {
|
||||
layoutText = "AdvSceneSwitcher.action.projector.entry.close";
|
||||
} else if (_entryData->_fullscreen) {
|
||||
layoutText =
|
||||
"AdvSceneSwitcher.action.projector.entry.open.fullscreen";
|
||||
} else {
|
||||
layoutText =
|
||||
"AdvSceneSwitcher.action.projector.entry.open.windowed";
|
||||
}
|
||||
|
||||
PlaceWidgets(obs_module_text(layoutText), _layout, widgetPlaceholders);
|
||||
}
|
||||
|
||||
void MacroActionProjectorEdit::SetWidgetVisibility()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_scenes->setVisible(_entryData->_type ==
|
||||
MacroActionProjector::Type::SCENE);
|
||||
_sources->setVisible(_entryData->_type ==
|
||||
MacroActionProjector::Type::SOURCE);
|
||||
SetLayoutVisible(_monitorSelection, _entryData->_fullscreen);
|
||||
_projectorWindowName->setVisible(_entryData->_action ==
|
||||
MacroActionProjector::Action::CLOSE);
|
||||
_regex->setVisible(_entryData->_action ==
|
||||
MacroActionProjector::Action::CLOSE);
|
||||
_types->setVisible(_entryData->_action ==
|
||||
MacroActionProjector::Action::OPEN);
|
||||
_windowTypes->setVisible(_entryData->_action ==
|
||||
MacroActionProjector::Action::OPEN);
|
||||
_scenes->setVisible(
|
||||
_entryData->_action == MacroActionProjector::Action::OPEN &&
|
||||
_entryData->_type == MacroActionProjector::Type::SCENE);
|
||||
_sources->setVisible(
|
||||
_entryData->_action == MacroActionProjector::Action::OPEN &&
|
||||
_entryData->_type == MacroActionProjector::Type::SOURCE);
|
||||
_monitors->setVisible(_entryData->_action ==
|
||||
MacroActionProjector::Action::OPEN &&
|
||||
_entryData->_fullscreen);
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "regex-config.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
#include "source-selection.hpp"
|
||||
#include "variable-line-edit.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
|
|
@ -19,6 +21,11 @@ public:
|
|||
void SetMonitor(int);
|
||||
int GetMonitor() const;
|
||||
|
||||
enum class Action {
|
||||
OPEN,
|
||||
CLOSE,
|
||||
};
|
||||
|
||||
enum class Type {
|
||||
SOURCE,
|
||||
SCENE,
|
||||
|
|
@ -27,10 +34,13 @@ public:
|
|||
MULTIVIEW,
|
||||
};
|
||||
|
||||
Action _action = Action::OPEN;
|
||||
Type _type = Type::SCENE;
|
||||
SourceSelection _source;
|
||||
SceneSelection _scene;
|
||||
bool _fullscreen = true;
|
||||
StringVariable _projectorWindowName = "Windowed Projector";
|
||||
RegexConfig _regex = RegexConfig::PartialMatchRegexConfig(true);
|
||||
|
||||
private:
|
||||
bool MonitorSetupChanged() const;
|
||||
|
|
@ -60,21 +70,28 @@ public:
|
|||
}
|
||||
|
||||
private slots:
|
||||
void ActionChanged(int value);
|
||||
void WindowTypeChanged(int value);
|
||||
void TypeChanged(int value);
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SourceChanged(const SourceSelection &);
|
||||
void MonitorChanged(int value);
|
||||
void ProjectorWindowNameChanged();
|
||||
void RegexChanged(const RegexConfig &);
|
||||
|
||||
private:
|
||||
void SetWidgetLayout();
|
||||
void SetWidgetVisibility();
|
||||
|
||||
QComboBox *_windowTypes;
|
||||
QComboBox *_actions;
|
||||
QComboBox *_types;
|
||||
QComboBox *_windowTypes;
|
||||
SceneSelectionWidget *_scenes;
|
||||
SourceSelectionWidget *_sources;
|
||||
QHBoxLayout *_monitorSelection;
|
||||
QComboBox *_monitors;
|
||||
VariableLineEdit *_projectorWindowName;
|
||||
RegexConfigWidget *_regex;
|
||||
QHBoxLayout *_layout;
|
||||
|
||||
std::shared_ptr<MacroActionProjector> _entryData;
|
||||
bool _loading = true;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user