Add canvas and position variable support to scene condition

This commit is contained in:
WarmUpTill 2025-10-12 18:19:30 +02:00 committed by WarmUpTill
parent 16136b8741
commit 8f54e71e61
3 changed files with 130 additions and 35 deletions

View File

@ -325,6 +325,7 @@ AdvSceneSwitcher.condition.scene.type.previousPattern="Previous scene matches"
AdvSceneSwitcher.condition.scene.type.previewPattern="Preview scene matches" AdvSceneSwitcher.condition.scene.type.previewPattern="Preview scene matches"
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="During transition check for transition target scene" AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="During transition check for transition target scene"
AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="During transition check for transition source scene" AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="During transition check for transition source scene"
AdvSceneSwitcher.condition.scene.canvasNotSupported="This check is not supported for the currently selected canvas \"%1\""
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}{{regex}}" AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}{{regex}}"
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}" AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
AdvSceneSwitcher.condition.window="Window" AdvSceneSwitcher.condition.window="Window"
@ -2103,6 +2104,7 @@ AdvSceneSwitcher.tempVar.clipboard.mimeType.all.description="All MIME types of t
AdvSceneSwitcher.tempVar.scene.current="Current scene" AdvSceneSwitcher.tempVar.scene.current="Current scene"
AdvSceneSwitcher.tempVar.scene.previous="Previous scene" AdvSceneSwitcher.tempVar.scene.previous="Previous scene"
AdvSceneSwitcher.tempVar.scene.preview="Preview scene" AdvSceneSwitcher.tempVar.scene.preview="Preview scene"
AdvSceneSwitcher.tempVar.scene.position="Position in scenes list"
AdvSceneSwitcher.tempVar.window.window="Window title" AdvSceneSwitcher.tempVar.window.window="Window title"
AdvSceneSwitcher.tempVar.window.window.description="The window title of the matching window." AdvSceneSwitcher.tempVar.window.window.description="The window title of the matching window."

View File

@ -41,8 +41,17 @@ static bool sceneNameMatchesRegex(const OBSWeakSource &scene,
return regex.Matches(GetWeakSourceName(scene), pattern); return regex.Matches(GetWeakSourceName(scene), pattern);
} }
static OBSWeakSource getCurrentSceneHelper(bool useTransitionTargetScene) static OBSWeakSource getCurrentSceneHelper(bool useTransitionTargetScene,
obs_weak_canvas_t *canvas)
{ {
if (!IsMainCanvas(canvas)) {
// An "active" scene doesn't necessarily have to be the current
// scene, but this is still the best guess for now without
// having more information about each canvas' specific frontend
// implementation
return GetActiveCanvasScene(canvas);
}
if (useTransitionTargetScene) { if (useTransitionTargetScene) {
auto current = obs_frontend_get_current_scene(); auto current = obs_frontend_get_current_scene();
auto weak = obs_source_get_weak_source(current); auto weak = obs_source_get_weak_source(current);
@ -68,62 +77,119 @@ bool MacroConditionScene::CheckCondition()
_lastSceneChangeTime = GetLastSceneChangeTime(); _lastSceneChangeTime = GetLastSceneChangeTime();
} }
const auto canvas = _scene.GetCanvas();
switch (_type) { switch (_type) {
case Type::CURRENT: { case Type::CURRENT: {
auto scene = getCurrentSceneHelper(_useTransitionTargetScene); auto scene = getCurrentSceneHelper(_useTransitionTargetScene,
canvas);
SetVariableValue(GetWeakSourceName(scene)); SetVariableValue(GetWeakSourceName(scene));
SetTempVarValue("current", GetWeakSourceName(scene)); SetTempVarValue("current", GetWeakSourceName(scene));
return scene == _scene.GetScene(false); SetTempVarValue("position",
std::to_string(GetIndexOfScene(canvas, scene)));
return scene && scene == _scene.GetScene(false);
} }
case Type::PREVIOUS: { case Type::PREVIOUS: {
if (!IsMainCanvas(canvas)) {
return false;
}
auto scene = getPreviousSceneHelper(_useTransitionTargetScene); auto scene = getPreviousSceneHelper(_useTransitionTargetScene);
if (!scene) {
// Scene was never switched
return false;
}
SetVariableValue(GetWeakSourceName(scene)); SetVariableValue(GetWeakSourceName(scene));
SetTempVarValue("position",
std::to_string(GetIndexOfScene(canvas, scene)));
SetTempVarValue("previous", GetWeakSourceName(scene)); SetTempVarValue("previous", GetWeakSourceName(scene));
return scene == _scene.GetScene(false); return scene == _scene.GetScene(false);
} }
case Type::PREVIEW: { case Type::PREVIEW: {
if (!IsMainCanvas(canvas)) {
return false;
}
OBSSourceAutoRelease source = OBSSourceAutoRelease source =
obs_frontend_get_current_preview_scene(); obs_frontend_get_current_preview_scene();
OBSWeakSourceAutoRelease scene = OBSWeakSourceAutoRelease scene =
obs_source_get_weak_source(source); obs_source_get_weak_source(source);
SetVariableValue(GetWeakSourceName(scene)); SetVariableValue(GetWeakSourceName(scene));
SetTempVarValue("preview", GetWeakSourceName(scene)); SetTempVarValue("preview", GetWeakSourceName(scene));
return scene == _scene.GetScene(false); SetTempVarValue("position", std::to_string(GetIndexOfScene(
canvas, scene.Get())));
return scene && scene == _scene.GetScene(false);
} }
case Type::CHANGED: case Type::CHANGED:
if (!IsMainCanvas(canvas)) {
return false;
}
SetVariableValue(GetWeakSourceName(GetCurrentScene())); SetVariableValue(GetWeakSourceName(GetCurrentScene()));
SetTempVarValue("current", SetTempVarValue("current",
GetWeakSourceName(GetCurrentScene())); GetWeakSourceName(GetCurrentScene()));
SetTempVarValue("previous", SetTempVarValue("previous",
GetWeakSourceName(GetPreviousScene())); GetWeakSourceName(GetPreviousScene()));
SetTempVarValue("position",
std::to_string(GetIndexOfScene(
canvas, GetCurrentScene())));
return sceneChanged; return sceneChanged;
case Type::NOT_CHANGED: case Type::NOT_CHANGED:
if (!IsMainCanvas(canvas)) {
return false;
}
SetVariableValue(GetWeakSourceName(GetCurrentScene())); SetVariableValue(GetWeakSourceName(GetCurrentScene()));
SetTempVarValue("current", SetTempVarValue("current",
GetWeakSourceName(GetCurrentScene())); GetWeakSourceName(GetCurrentScene()));
SetTempVarValue("previous", SetTempVarValue("previous",
GetWeakSourceName(GetPreviousScene())); GetWeakSourceName(GetPreviousScene()));
SetTempVarValue("position",
std::to_string(GetIndexOfScene(
canvas, GetCurrentScene())));
return !sceneChanged; return !sceneChanged;
case Type::CURRENT_PATTERN: { case Type::CURRENT_PATTERN: {
auto scene = getCurrentSceneHelper(_useTransitionTargetScene); auto scene = getCurrentSceneHelper(_useTransitionTargetScene,
canvas);
SetVariableValue(GetWeakSourceName(scene)); SetVariableValue(GetWeakSourceName(scene));
SetTempVarValue("current", GetWeakSourceName(scene)); SetTempVarValue("current", GetWeakSourceName(scene));
return sceneNameMatchesRegex(scene, _regex, _pattern); SetTempVarValue("position",
std::to_string(GetIndexOfScene(canvas, scene)));
return scene && sceneNameMatchesRegex(scene, _regex, _pattern);
} }
case Type::PREVIOUS_PATTERN: { case Type::PREVIOUS_PATTERN: {
if (!IsMainCanvas(canvas)) {
return false;
}
auto scene = getPreviousSceneHelper(_useTransitionTargetScene); auto scene = getPreviousSceneHelper(_useTransitionTargetScene);
if (!scene) {
// Scene was never switched
return false;
}
SetVariableValue(GetWeakSourceName(scene)); SetVariableValue(GetWeakSourceName(scene));
SetTempVarValue("previous", GetWeakSourceName(scene)); SetTempVarValue("previous", GetWeakSourceName(scene));
SetTempVarValue("position",
std::to_string(GetIndexOfScene(canvas, scene)));
return sceneNameMatchesRegex(scene, _regex, _pattern); return sceneNameMatchesRegex(scene, _regex, _pattern);
} }
case Type::PREVIEW_PATTERN: { case Type::PREVIEW_PATTERN: {
if (!IsMainCanvas(canvas)) {
return false;
}
OBSSourceAutoRelease source = OBSSourceAutoRelease source =
obs_frontend_get_current_preview_scene(); obs_frontend_get_current_preview_scene();
OBSWeakSourceAutoRelease scene = OBSWeakSourceAutoRelease scene =
obs_source_get_weak_source(source); obs_source_get_weak_source(source);
SetVariableValue(GetWeakSourceName(scene)); SetVariableValue(GetWeakSourceName(scene));
SetTempVarValue("preview", GetWeakSourceName(scene)); SetTempVarValue("preview", GetWeakSourceName(scene));
return sceneNameMatchesRegex(scene.Get(), _regex, _pattern); SetTempVarValue("position", std::to_string(GetIndexOfScene(
canvas, scene.Get())));
return scene &&
sceneNameMatchesRegex(scene.Get(), _regex, _pattern);
} }
} }
@ -214,6 +280,7 @@ std::string MacroConditionScene::GetShortDesc() const
void MacroConditionScene::SetupTempVars() void MacroConditionScene::SetupTempVars()
{ {
MacroCondition::SetupTempVars(); MacroCondition::SetupTempVars();
switch (_type) { switch (_type) {
case Type::CURRENT: case Type::CURRENT:
case Type::CURRENT_PATTERN: case Type::CURRENT_PATTERN:
@ -245,6 +312,9 @@ void MacroConditionScene::SetupTempVars()
default: default:
break; break;
} }
AddTempvar("position",
obs_module_text("AdvSceneSwitcher.tempVar.scene.position"));
} }
void MacroConditionScene::SetType(const Type &type) void MacroConditionScene::SetType(const Type &type)
@ -269,10 +339,13 @@ MacroConditionSceneEdit::MacroConditionSceneEdit(
_pattern(new QLineEdit()), _pattern(new QLineEdit()),
_useTransitionTargetScene(new QCheckBox(obs_module_text( _useTransitionTargetScene(new QCheckBox(obs_module_text(
"AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour"))), "AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour"))),
_regex(new RegexConfigWidget(this, false)) _regex(new RegexConfigWidget(this, false)),
_canvasWarning(new QLabel(this))
{ {
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)), QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
this, SLOT(SceneChanged(const SceneSelection &))); this, SLOT(SceneChanged(const SceneSelection &)));
QWidget::connect(_scenes, SIGNAL(CanvasChanged(const OBSWeakCanvas &)),
this, SLOT(CanvasChanged(const OBSWeakCanvas &)));
QWidget::connect(_sceneType, SIGNAL(currentIndexChanged(int)), this, QWidget::connect(_sceneType, SIGNAL(currentIndexChanged(int)), this,
SLOT(TypeChanged(int))); SLOT(TypeChanged(int)));
QWidget::connect(_pattern, SIGNAL(editingFinished()), this, QWidget::connect(_pattern, SIGNAL(editingFinished()), this,
@ -285,7 +358,7 @@ MacroConditionSceneEdit::MacroConditionSceneEdit(
populateTypeSelection(_sceneType); populateTypeSelection(_sceneType);
std::unordered_map<std::string, QWidget *> widgetPlaceholders = { const std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{scenes}}", _scenes}, {"{{scenes}}", _scenes},
{"{{sceneType}}", _sceneType}, {"{{sceneType}}", _sceneType},
{"{{pattern}}", _pattern}, {"{{pattern}}", _pattern},
@ -303,6 +376,7 @@ MacroConditionSceneEdit::MacroConditionSceneEdit(
auto mainLayout = new QVBoxLayout; auto mainLayout = new QVBoxLayout;
mainLayout->addLayout(line1Layout); mainLayout->addLayout(line1Layout);
mainLayout->addLayout(line2Layout); mainLayout->addLayout(line2Layout);
mainLayout->addWidget(_canvasWarning);
setLayout(mainLayout); setLayout(mainLayout);
_entryData = entryData; _entryData = entryData;
@ -344,41 +418,58 @@ void MacroConditionSceneEdit::RegexChanged(const RegexConfig &regex)
_entryData->_regex = regex; _entryData->_regex = regex;
} }
void MacroConditionSceneEdit::CanvasChanged(const OBSWeakCanvas &)
{
SetWidgetVisibility();
}
void MacroConditionSceneEdit::SetWidgetVisibility() void MacroConditionSceneEdit::SetWidgetVisibility()
{ {
_scenes->setVisible( const auto type = _entryData->GetType();
_entryData->GetType() == MacroConditionScene::Type::CURRENT ||
_entryData->GetType() == MacroConditionScene::Type::PREVIOUS || _scenes->setVisible(type == MacroConditionScene::Type::CURRENT ||
_entryData->GetType() == MacroConditionScene::Type::PREVIEW); type == MacroConditionScene::Type::PREVIOUS ||
type == MacroConditionScene::Type::PREVIEW);
_useTransitionTargetScene->setVisible( _useTransitionTargetScene->setVisible(
_entryData->GetType() == MacroConditionScene::Type::CURRENT || type == MacroConditionScene::Type::CURRENT ||
_entryData->GetType() == MacroConditionScene::Type::PREVIOUS || type == MacroConditionScene::Type::PREVIOUS ||
_entryData->GetType() == type == MacroConditionScene::Type::CURRENT_PATTERN ||
MacroConditionScene::Type::CURRENT_PATTERN || type == MacroConditionScene::Type::PREVIOUS_PATTERN);
_entryData->GetType() ==
MacroConditionScene::Type::PREVIOUS_PATTERN);
const bool isUsingPattern = const bool isUsingPattern =
_entryData->GetType() == type == MacroConditionScene::Type::CURRENT_PATTERN ||
MacroConditionScene::Type::CURRENT_PATTERN || type == MacroConditionScene::Type::PREVIOUS_PATTERN ||
_entryData->GetType() == type == MacroConditionScene::Type::PREVIEW_PATTERN;
MacroConditionScene::Type::PREVIOUS_PATTERN ||
_entryData->GetType() ==
MacroConditionScene::Type::PREVIEW_PATTERN;
_pattern->setVisible(isUsingPattern); _pattern->setVisible(isUsingPattern);
_regex->setVisible(isUsingPattern); _regex->setVisible(isUsingPattern);
if (_entryData->GetType() == MacroConditionScene::Type::PREVIOUS || if (type == MacroConditionScene::Type::PREVIOUS ||
_entryData->GetType() == type == MacroConditionScene::Type::PREVIOUS_PATTERN) {
MacroConditionScene::Type::PREVIOUS_PATTERN) {
_useTransitionTargetScene->setText(obs_module_text( _useTransitionTargetScene->setText(obs_module_text(
"AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour")); "AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour"));
} }
if (_entryData->GetType() == MacroConditionScene::Type::CURRENT || if (type == MacroConditionScene::Type::CURRENT ||
_entryData->GetType() == type == MacroConditionScene::Type::CURRENT_PATTERN) {
MacroConditionScene::Type::CURRENT_PATTERN) {
_useTransitionTargetScene->setText(obs_module_text( _useTransitionTargetScene->setText(obs_module_text(
"AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour")); "AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour"));
} }
const auto canvas = _entryData->_scene.GetCanvas();
const bool isUsingMainCanvas = IsMainCanvas(canvas);
_useTransitionTargetScene->setVisible(isUsingMainCanvas);
const QString fmt = obs_module_text(
"AdvSceneSwitcher.condition.scene.canvasNotSupported");
_canvasWarning->setText(
fmt.arg(QString::fromStdString(GetWeakCanvasName(canvas))));
_canvasWarning->setVisible(
canvas && !isUsingMainCanvas &&
(type == MacroConditionScene::Type::PREVIOUS ||
type == MacroConditionScene::Type::PREVIEW ||
type == MacroConditionScene::Type::CHANGED ||
type == MacroConditionScene::Type::NOT_CHANGED ||
type == MacroConditionScene::Type::PREVIOUS_PATTERN ||
type == MacroConditionScene::Type::PREVIEW_PATTERN));
adjustSize(); adjustSize();
updateGeometry(); updateGeometry();
} }

View File

@ -75,19 +75,21 @@ private slots:
void PatternChanged(); void PatternChanged();
void UseTransitionTargetSceneChanged(int state); void UseTransitionTargetSceneChanged(int state);
void RegexChanged(const RegexConfig &); void RegexChanged(const RegexConfig &);
void CanvasChanged(const OBSWeakCanvas &);
signals: signals:
void HeaderInfoChanged(const QString &); void HeaderInfoChanged(const QString &);
protected: private:
void SetWidgetVisibility();
SceneSelectionWidget *_scenes; SceneSelectionWidget *_scenes;
QComboBox *_sceneType; QComboBox *_sceneType;
QLineEdit *_pattern; QLineEdit *_pattern;
QCheckBox *_useTransitionTargetScene; QCheckBox *_useTransitionTargetScene;
RegexConfigWidget *_regex; RegexConfigWidget *_regex;
std::shared_ptr<MacroConditionScene> _entryData; QLabel *_canvasWarning;
private: std::shared_ptr<MacroConditionScene> _entryData;
void SetWidgetVisibility();
bool _loading = true; bool _loading = true;
}; };