Rework scene switch action

* Support "next scene" and "previous scene"
* Support "scene at index"
* Add canvas support
* Rework layout
This commit is contained in:
WarmUpTill 2025-10-10 20:13:54 +02:00 committed by WarmUpTill
parent 02d5051974
commit 16136b8741
11 changed files with 381 additions and 110 deletions

View File

@ -383,8 +383,6 @@ AdvSceneSwitcher.condition.variable.type.greaterThanVariable="ist größer als d
; Macro Actions
AdvSceneSwitcher.action.scene="Szene wechseln"
AdvSceneSwitcher.action.scene.entry="Wechsle{{sceneTypes}}Szene zu{{scenes}}mittels{{transitions}}mit einer Dauer von{{duration}}Sekunden"
AdvSceneSwitcher.action.scene.entry.noDuration="Wechsle{{sceneTypes}}Szene zu{{scenes}}mittels{{transitions}}"
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Warten, bis der Übergang zur Zielszene abgeschlossen ist"
AdvSceneSwitcher.action.wait="Warten"
AdvSceneSwitcher.action.wait.type.fixed="fixe"

View File

@ -822,12 +822,21 @@ AdvSceneSwitcher.condition.script="Script"
# Macro Actions
AdvSceneSwitcher.action.unknown="Unknown action"
AdvSceneSwitcher.action.scene="Switch scene"
AdvSceneSwitcher.action.scene.action.fixed="Scene with name"
AdvSceneSwitcher.action.scene.action.sceneListNext="Next scene in scene list"
AdvSceneSwitcher.action.scene.action.sceneListPrevious="Previous scene in scene list"
AdvSceneSwitcher.action.scene.action.sceneListIndex="Scene in scene list at position"
AdvSceneSwitcher.action.scene.type.program="Program"
AdvSceneSwitcher.action.scene.type.preview="Preview"
AdvSceneSwitcher.action.scene.entry="Switch{{sceneTypes}}scene to{{scenes}}using{{transitions}}with a duration of{{duration}}seconds"
AdvSceneSwitcher.action.scene.entry.noDuration="Switch{{sceneTypes}}scene to{{scenes}}using{{transitions}}"
AdvSceneSwitcher.action.scene.entry.preview="Switch{{sceneTypes}}scene to{{scenes}}"
AdvSceneSwitcher.action.scene.layout.action.fixed="Switch{{sceneTypes}}to{{actions}}{{scenes}}"
AdvSceneSwitcher.action.scene.layout.action.list="Switch{{sceneTypes}}to{{actions}}on{{canvas}}"
AdvSceneSwitcher.action.scene.layout.action.list.noCanvasSelection="Switch{{sceneTypes}}to{{actions}}"
AdvSceneSwitcher.action.scene.layout.action.listIndex="Switch{{sceneTypes}}to{{actions}}{{index}}on{{canvas}}{{sceneNameAtIndex}}"
AdvSceneSwitcher.action.scene.layout.action.listIndex.noCanvasSelection="Switch{{sceneTypes}}to{{actions}}{{index}}{{sceneNameAtIndex}}"
AdvSceneSwitcher.action.scene.layout.transition="Use transition{{transitions}}"
AdvSceneSwitcher.action.scene.layout.transitionWithDuration="Use transition{{transitions}}with a duration of{{duration}}seconds"
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Wait until transition to target scene is complete"
AdvSceneSwitcher.action.scene.canvasNotSupported="Not supported by the currently selected canvas \"%1\""
AdvSceneSwitcher.action.wait="Wait"
AdvSceneSwitcher.action.wait.type.fixed="fixed"
AdvSceneSwitcher.action.wait.type.random="random"

View File

@ -311,7 +311,6 @@ AdvSceneSwitcher.condition.stats.entry="{{stats}} esta {{condition}} {{value}}"
; Macro Actions
AdvSceneSwitcher.action.scene="Cambiar escena"
AdvSceneSwitcher.action.scene.entry="Cambiar a la{{sceneTypes}}escena{{scenes}}usando{{transitions}}con una duración de{{duration}} segundos"
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Espere hasta que se complete la transición a la escena de destino"
AdvSceneSwitcher.action.wait="Esperar"
AdvSceneSwitcher.action.wait.type.fixed="fijo"

View File

@ -459,8 +459,6 @@ AdvSceneSwitcher.condition.slideshow.updateInterval.tooltip="Les informations su
AdvSceneSwitcher.action.scene="Changer de scène"
AdvSceneSwitcher.action.scene.type.program="Programme"
AdvSceneSwitcher.action.scene.type.preview="Aperçu"
AdvSceneSwitcher.action.scene.entry="Changer la scène{{sceneTypes}}{{scenes}}en utilisant{{transitions}}avec une durée de{{duration}}secondes"
AdvSceneSwitcher.action.scene.entry.noDuration="Changer la scène{{sceneTypes}}{{scenes}}en utilisant{{transitions}}"
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Attendre que la transition vers la scène cible soit terminée"
AdvSceneSwitcher.action.wait="Attendre"
AdvSceneSwitcher.action.wait.type.fixed="fixe"

View File

@ -810,9 +810,6 @@ AdvSceneSwitcher.action.unknown="不明なアクション"
AdvSceneSwitcher.action.scene="シーン切り替え"
AdvSceneSwitcher.action.scene.type.program="プログラム"
AdvSceneSwitcher.action.scene.type.preview="プレビュー"
AdvSceneSwitcher.action.scene.entry="{{duration}}秒間の{{transitions}}を使用して、{{sceneTypes}}シーンを{{scenes}}に切り替えます"
AdvSceneSwitcher.action.scene.entry.noDuration="{{transitions}}を使用して{{sceneTypes}}シーンを{{scenes}}に切り替える"
AdvSceneSwitcher.action.scene.entry.preview="{{sceneTypes}}シーンを{{scenes}}に切り替えます"
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="目的のシーンへの遷移が完了するまで待ちます"
; AdvSceneSwitcher.action.wait="Wait"
AdvSceneSwitcher.action.wait.type.fixed="指定"

View File

@ -720,9 +720,6 @@ AdvSceneSwitcher.condition.noDevicesFoundWarning="Nenhum dispositivo USB detecta
AdvSceneSwitcher.action.scene="Trocar cena"
AdvSceneSwitcher.action.scene.type.program="Programa"
AdvSceneSwitcher.action.scene.type.preview="Pré-visualização"
AdvSceneSwitcher.action.scene.entry="Trocar{{sceneTypes}}cena para{{scenes}}usando{{transitions}}com duração de{{duration}}segundos"
AdvSceneSwitcher.action.scene.entry.noDuration="Trocar{{sceneTypes}}cena para{{scenes}}usando{{transitions}}"
AdvSceneSwitcher.action.scene.entry.preview="Trocar{{sceneTypes}}cena para{{scenes}}"
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Aguardar até que a transição para a cena de destino seja concluída"
AdvSceneSwitcher.action.wait="Aguardar"
AdvSceneSwitcher.action.wait.type.fixed="fixo"

View File

@ -114,7 +114,6 @@ AdvSceneSwitcher.condition.pluginState.entry="{{condition}}"
; Macro Actions
AdvSceneSwitcher.action.scene="Переключить сцену"
AdvSceneSwitcher.action.scene.entry="Перейти к сцене{{sceneTypes}}{{scenes}}используя{{transitions}}с продолжительностью{{duration}}секунд"
AdvSceneSwitcher.action.wait="Подождать"
AdvSceneSwitcher.action.wait.type.fixed="фиксированный"
AdvSceneSwitcher.action.wait.type.random="случайный"

View File

@ -249,7 +249,6 @@ AdvSceneSwitcher.condition.openvr.entry.line3="HMD mevcut {{xPos}} x {{yPos}} x
; Macro Actions
AdvSceneSwitcher.action.scene="Sahne Degistirici"
AdvSceneSwitcher.action.scene.entry="Sahneyi{{sceneTypes}}{{scenes}}kullanarak{{transitions}}süresi olan{{duration}}saniye"
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Hedef sahneye geçiş tamamlanana kadar bekleyin"
AdvSceneSwitcher.action.wait="Bekle"
AdvSceneSwitcher.action.wait.type.fixed="sabit"

View File

@ -698,7 +698,7 @@ AdvSceneSwitcher.condition.twitch.type.event.channel.user.moderator.deletion="
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online.live="开始直播"
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online.playlist="开始播放列表"
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online.watchParty="开始观看派对"
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online.premiere="开始首播
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online.premiere="开始首播"
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online.rerun="开始重播"
AdvSceneSwitcher.condition.twitch.type.polling.channel.live="当前正在直播"
AdvSceneSwitcher.condition.twitch.type.polling.channel.title="当前为头衔赛"
@ -779,9 +779,6 @@ AdvSceneSwitcher.action.unknown="未知操作"
AdvSceneSwitcher.action.scene="切换场景"
AdvSceneSwitcher.action.scene.type.program="程序"
AdvSceneSwitcher.action.scene.type.preview="预览"
AdvSceneSwitcher.action.scene.entry="切换到场景{{sceneTypes}}{{scenes}}使用{{transitions}}时长{{duration}}秒"
AdvSceneSwitcher.action.scene.entry.noDuration="切换到场景{{sceneTypes}}{{scenes}}使用{{transitions}}"
AdvSceneSwitcher.action.scene.entry.preview="将{{sceneTypes}}场景切换到{{scenes}}"
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="等待转场到目标场景的动画完成"
AdvSceneSwitcher.action.wait="等待"
AdvSceneSwitcher.action.wait.type.fixed="固定"

View File

@ -19,14 +19,6 @@ bool MacroActionSwitchScene::_registered = MacroActionFactory::Register(
{MacroActionSwitchScene::Create, MacroActionSwitchSceneEdit::Create,
"AdvSceneSwitcher.action.scene"});
const static std::map<MacroActionSwitchScene::SceneType, std::string>
sceneTypes = {
{MacroActionSwitchScene::SceneType::PROGRAM,
"AdvSceneSwitcher.action.scene.type.program"},
{MacroActionSwitchScene::SceneType::PREVIEW,
"AdvSceneSwitcher.action.scene.type.preview"},
};
static void waitForTransitionChange(OBSWeakSource &transition,
std::unique_lock<std::mutex> *lock,
Macro *macro)
@ -144,34 +136,92 @@ bool MacroActionSwitchScene::WaitForTransition(OBSWeakSource &scene,
bool MacroActionSwitchScene::PerformAction()
{
auto scene = _scene.GetScene();
OBSWeakSource sceneToSwitchTo;
OBSWeakCanvas canvas;
switch (_action) {
case Action::SCENE_NAME:
sceneToSwitchTo = _scene.GetScene();
canvas = _scene.GetCanvas();
break;
case Action::SCENE_LIST_NEXT: {
const auto activeScene = GetActiveCanvasScene(_canvas);
const int currentIndex = GetIndexOfScene(_canvas, activeScene);
sceneToSwitchTo = GetSceneAtIndex(_canvas, currentIndex + 1);
canvas = _canvas;
break;
}
case Action::SCENE_LIST_PREVIOUS: {
const auto activeScene = GetActiveCanvasScene(_canvas);
const int currentIndex = GetIndexOfScene(_canvas, activeScene);
sceneToSwitchTo = GetSceneAtIndex(_canvas, currentIndex - 1);
canvas = _canvas;
break;
}
case Action::SCENE_LIST_INDEX: {
sceneToSwitchTo =
GetSceneAtIndex(_canvas, _index.GetValue() - 1);
canvas = _canvas;
break;
}
default:
break;
}
if (_sceneType == SceneType::PREVIEW) {
OBSSourceAutoRelease previewScneSource =
obs_weak_source_get_source(scene);
obs_frontend_set_current_preview_scene(previewScneSource);
OBSSourceAutoRelease previewSceneSource =
obs_weak_source_get_source(sceneToSwitchTo);
obs_frontend_set_current_preview_scene(previewSceneSource);
return true;
}
auto transition = _transition.GetTransition();
SwitchScene({scene, transition, (int)(_duration.Milliseconds())},
obs_frontend_preview_program_mode_active());
if (_blockUntilTransitionDone && scene && scene != GetCurrentScene()) {
return WaitForTransition(scene, transition);
SwitchScene({sceneToSwitchTo, transition,
(int)(_duration.Milliseconds())},
obs_frontend_preview_program_mode_active(), canvas);
if (_blockUntilTransitionDone && sceneToSwitchTo &&
sceneToSwitchTo != GetCurrentScene() && IsMainCanvas(canvas)) {
return WaitForTransition(sceneToSwitchTo, transition);
}
return true;
}
void MacroActionSwitchScene::LogAction() const
{
ablog(LOG_INFO, "switch%s scene to '%s'",
_sceneType == SceneType::PREVIEW ? " preview" : "",
_scene.ToString(true).c_str());
if (!ActionLoggingEnabled()) {
return;
}
switch (_action) {
case Action::SCENE_NAME:
blog(LOG_INFO, "switch %s scene to '%s'",
_sceneType == SceneType::PREVIEW ? " preview" : "program",
_scene.ToString(true).c_str());
break;
case Action::SCENE_LIST_NEXT:
blog(LOG_INFO, "switch %s to next scene in scene list",
_sceneType == SceneType::PREVIEW ? " preview" : "program");
break;
case Action::SCENE_LIST_PREVIOUS:
blog(LOG_INFO, "switch %s to previous scene in scene list",
_sceneType == SceneType::PREVIEW ? " preview" : "program");
break;
case Action::SCENE_LIST_INDEX:
blog(LOG_INFO, "switch %s to scene at index %d in scene list",
_sceneType == SceneType::PREVIEW ? " preview" : "program",
_index.GetValue());
break;
default:
break;
}
}
bool MacroActionSwitchScene::Save(obs_data_t *obj) const
{
MacroAction::Save(obj);
obs_data_set_int(obj, "action", static_cast<int>(_action));
obs_data_set_string(obj, "canvas", GetWeakCanvasName(_canvas).c_str());
_index.Save(obj, "index");
_scene.Save(obj);
_transition.Save(obj);
_duration.Save(obj);
@ -184,6 +234,16 @@ bool MacroActionSwitchScene::Save(obs_data_t *obj) const
bool MacroActionSwitchScene::Load(obs_data_t *obj)
{
MacroAction::Load(obj);
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
if (obs_data_has_user_value(obj, "canvas")) {
_canvas =
GetWeakCanvasByName(obs_data_get_string(obj, "canvas"));
} else {
OBSCanvasAutoRelease main = obs_get_main_canvas();
_canvas = OBSGetWeakRef(main);
}
_index.Save(obj, "index");
_scene.Load(obj);
_transition.Load(obj);
_duration.Load(obj);
@ -195,7 +255,7 @@ bool MacroActionSwitchScene::Load(obs_data_t *obj)
std::string MacroActionSwitchScene::GetShortDesc() const
{
return _scene.ToString();
return _action == Action::SCENE_NAME ? _scene.ToString() : "";
}
std::shared_ptr<MacroAction> MacroActionSwitchScene::Create(Macro *m)
@ -214,61 +274,128 @@ void MacroActionSwitchScene::ResolveVariablesToFixedValues()
_duration.ResolveVariables();
}
template<typename T>
static void populate(QComboBox *list, const std::map<T, std::string> &data)
{
for (const auto &[value, name] : data) {
list->addItem(obs_module_text(name.c_str()),
static_cast<int>(value));
}
}
static inline void populateTypeSelection(QComboBox *list)
{
for (const auto &[_, name] : sceneTypes) {
list->addItem(obs_module_text(name.c_str()));
}
static const std::map<MacroActionSwitchScene::SceneType, std::string>
types = {
{MacroActionSwitchScene::SceneType::PROGRAM,
"AdvSceneSwitcher.action.scene.type.program"},
{MacroActionSwitchScene::SceneType::PREVIEW,
"AdvSceneSwitcher.action.scene.type.preview"},
};
populate(list, types);
}
static inline void populateActionSelection(QComboBox *list)
{
static const std::map<MacroActionSwitchScene::Action, std::string>
actions = {
{MacroActionSwitchScene::Action::SCENE_NAME,
"AdvSceneSwitcher.action.scene.action.fixed"},
{MacroActionSwitchScene::Action::SCENE_LIST_NEXT,
"AdvSceneSwitcher.action.scene.action.sceneListNext"},
{MacroActionSwitchScene::Action::SCENE_LIST_PREVIOUS,
"AdvSceneSwitcher.action.scene.action.sceneListPrevious"},
{MacroActionSwitchScene::Action::SCENE_LIST_INDEX,
"AdvSceneSwitcher.action.scene.action.sceneListIndex"},
};
populate(list, actions);
}
MacroActionSwitchSceneEdit::MacroActionSwitchSceneEdit(
QWidget *parent, std::shared_ptr<MacroActionSwitchScene> entryData)
: QWidget(parent),
_actions(new QComboBox(this)),
_index(new VariableSpinBox(this)),
_scenes(new SceneSelectionWidget(this, true, true, true)),
_transitions(new TransitionSelectionWidget(this)),
_duration(new DurationSelection(parent, false)),
_duration(new DurationSelection(this, false)),
_blockUntilTransitionDone(new QCheckBox(obs_module_text(
"AdvSceneSwitcher.action.scene.blockUntilTransitionDone"))),
_sceneTypes(new QComboBox()),
_entryLayout(new QHBoxLayout())
_sceneTypes(new QComboBox(this)),
_canvas(new CanvasSelection(this)),
_sceneNameAtIndex(new QLabel(this)),
_updateSceneNameTimer(new QTimer(this)),
_actionLayout(new QHBoxLayout()),
_transitionLayout(new QHBoxLayout()),
_notSupportedWarning(new QLabel(this))
{
_index->setMinimum(1);
_index->setMaximum(999);
_duration->SpinBox()->setSpecialValueText("-");
populateTypeSelection(_sceneTypes);
populateActionSelection(_actions);
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
this, SLOT(SceneChanged(const SceneSelection &)));
QWidget::connect(_transitions,
SIGNAL(TransitionChanged(const TransitionSelection &)),
this,
SLOT(TransitionChanged(const TransitionSelection &)));
QWidget::connect(_duration, SIGNAL(DurationChanged(const Duration &)),
this, SLOT(DurationChanged(const Duration &)));
QWidget::connect(_blockUntilTransitionDone, SIGNAL(stateChanged(int)),
this, SLOT(BlockUntilTransitionDoneChanged(int)));
QWidget::connect(_sceneTypes, SIGNAL(currentIndexChanged(int)), this,
SLOT(SceneTypeChanged(int)));
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.scene.entry"),
_entryLayout,
{{"{{scenes}}", _scenes},
{"{{transitions}}", _transitions},
{"{{duration}}", _duration},
{"{{sceneTypes}}", _sceneTypes}});
SetupWidgetConnections();
auto mainLayout = new QVBoxLayout;
mainLayout->addLayout(_entryLayout);
mainLayout->addLayout(_actionLayout);
mainLayout->addLayout(_transitionLayout);
mainLayout->addWidget(_blockUntilTransitionDone);
mainLayout->addWidget(_notSupportedWarning);
setLayout(mainLayout);
_entryData = entryData;
_sceneTypes->setCurrentIndex(static_cast<int>(_entryData->_sceneType));
SetWidgetData();
SetWidgetVisibility();
_loading = false;
}
void MacroActionSwitchSceneEdit::SetupWidgetConnections() const
{
connect(_actions, SIGNAL(currentIndexChanged(int)), this,
SLOT(ActionChanged(int)));
connect(_sceneTypes, SIGNAL(currentIndexChanged(int)), this,
SLOT(SceneTypeChanged(int)));
connect(_canvas, SIGNAL(CanvasChanged(const OBSWeakCanvas &)), this,
SLOT(CanvasChanged(const OBSWeakCanvas &)));
connect(_index,
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
this, SLOT(IndexChanged(const NumberVariable<int> &)));
connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)), this,
SLOT(SceneChanged(const SceneSelection &)));
connect(_scenes, SIGNAL(CanvasChanged(const OBSWeakCanvas &)), this,
SLOT(SceneSelectionCanvasChanged(const OBSWeakCanvas &)));
connect(_transitions,
SIGNAL(TransitionChanged(const TransitionSelection &)), this,
SLOT(TransitionChanged(const TransitionSelection &)));
connect(_duration, SIGNAL(DurationChanged(const Duration &)), this,
SLOT(DurationChanged(const Duration &)));
connect(_blockUntilTransitionDone, SIGNAL(stateChanged(int)), this,
SLOT(BlockUntilTransitionDoneChanged(int)));
connect(_updateSceneNameTimer, SIGNAL(timeout()), this,
SLOT(UpdateSceneNameAtIndex()));
_updateSceneNameTimer->setInterval(300);
_updateSceneNameTimer->start();
}
void MacroActionSwitchSceneEdit::SetWidgetData() const
{
_actions->setCurrentIndex(
_actions->findData(static_cast<int>(_entryData->_action)));
_index->SetValue(_entryData->_index);
_sceneTypes->setCurrentIndex(_sceneTypes->findData(
static_cast<int>(_entryData->_sceneType)));
_scenes->SetScene(_entryData->_scene);
_transitions->SetTransition(_entryData->_transition);
_duration->SetDuration(_entryData->_duration);
_blockUntilTransitionDone->setChecked(
_entryData->_blockUntilTransitionDone);
SetWidgetVisibility();
_loading = false;
}
void MacroActionSwitchSceneEdit::DurationChanged(const Duration &dur)
@ -283,58 +410,182 @@ void MacroActionSwitchSceneEdit::BlockUntilTransitionDoneChanged(int state)
_entryData->_blockUntilTransitionDone = state;
}
void MacroActionSwitchSceneEdit::SceneTypeChanged(int value)
void MacroActionSwitchSceneEdit::SceneTypeChanged(int)
{
GUARD_LOADING_AND_LOCK();
_entryData->_sceneType =
static_cast<MacroActionSwitchScene::SceneType>(value);
_entryData->_sceneType = static_cast<MacroActionSwitchScene::SceneType>(
_sceneTypes->currentData().toInt());
SetWidgetVisibility();
}
void MacroActionSwitchSceneEdit::CanvasChanged(const OBSWeakCanvas &canvas)
{
GUARD_LOADING_AND_LOCK();
_entryData->_canvas = canvas;
SetWidgetVisibility();
}
void MacroActionSwitchSceneEdit::SceneSelectionCanvasChanged(
const OBSWeakCanvas &)
{
SetWidgetVisibility();
}
void MacroActionSwitchSceneEdit::ActionChanged(int value)
{
GUARD_LOADING_AND_LOCK();
_entryData->_action = static_cast<MacroActionSwitchScene::Action>(
_actions->currentData().toInt());
SetWidgetVisibility();
}
void MacroActionSwitchSceneEdit::IndexChanged(const NumberVariable<int> &value)
{
GUARD_LOADING_AND_LOCK();
_entryData->_index = value;
}
void MacroActionSwitchSceneEdit::UpdateSceneNameAtIndex()
{
if (!_entryData) {
return;
}
auto weakSource =
GetSceneAtIndex(_entryData->_canvas, _entryData->_index - 1);
if (!weakSource) {
_sceneNameAtIndex->setText("");
return;
}
OBSSourceAutoRelease source = OBSGetStrongRef(weakSource);
auto name = obs_source_get_name(source);
if (!name) {
_sceneNameAtIndex->setText("");
return;
}
const QString text = QString("(") + name + ")";
_sceneNameAtIndex->setText(text);
}
static bool
shouldShowDurationInTransitionLayout(MacroActionSwitchScene::SceneType type,
const TransitionSelection &transition)
{
if (type == MacroActionSwitchScene::SceneType::PREVIEW) {
return false;
}
if (transition.GetType() != TransitionSelection::Type::TRANSITION) {
return true;
}
if (isUsingFixedLengthTransition(transition.GetTransition())) {
return false;
}
return true;
}
void MacroActionSwitchSceneEdit::SetWidgetVisibility()
{
_entryLayout->removeWidget(_scenes);
_entryLayout->removeWidget(_transitions);
_entryLayout->removeWidget(_duration);
_entryLayout->removeWidget(_sceneTypes);
ClearLayout(_entryLayout);
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{scenes}}", _scenes},
{"{{transitions}}", _transitions},
{"{{duration}}", _duration},
_actionLayout->removeWidget(_sceneTypes);
_actionLayout->removeWidget(_actions);
_actionLayout->removeWidget(_scenes);
_actionLayout->removeWidget(_canvas);
_actionLayout->removeWidget(_index);
_actionLayout->removeWidget(_sceneNameAtIndex);
ClearLayout(_actionLayout);
const int canvasCount = GetCanvasCount();
const auto &action = _entryData->_action;
_scenes->setVisible(action ==
MacroActionSwitchScene::Action::SCENE_NAME);
_canvas->setVisible(
action != MacroActionSwitchScene::Action::SCENE_NAME &&
canvasCount > 1);
_index->setVisible(action ==
MacroActionSwitchScene::Action::SCENE_LIST_INDEX);
_sceneNameAtIndex->setVisible(
action == MacroActionSwitchScene::Action::SCENE_LIST_INDEX);
const std::unordered_map<std::string, QWidget *> actionWidgets = {
{"{{actions}}", _actions},
{"{{sceneTypes}}", _sceneTypes},
};
{"{{scenes}}", _scenes},
{"{{canvas}}", _canvas},
{"{{index}}", _index},
{"{{sceneNameAtIndex}}", _sceneNameAtIndex}};
if (_entryData->_sceneType ==
MacroActionSwitchScene::SceneType::PREVIEW) {
_transitions->hide();
_duration->hide();
PlaceWidgets(
obs_module_text(
"AdvSceneSwitcher.action.scene.entry.preview"),
_entryLayout, widgetPlaceholders);
return;
const char *layoutString = "";
switch (action) {
case MacroActionSwitchScene::Action::SCENE_NAME:
layoutString =
"AdvSceneSwitcher.action.scene.layout.action.fixed";
break;
case MacroActionSwitchScene::Action::SCENE_LIST_NEXT:
case MacroActionSwitchScene::Action::SCENE_LIST_PREVIOUS:
layoutString =
(canvasCount > 1)
? "AdvSceneSwitcher.action.scene.layout.action.list"
: "AdvSceneSwitcher.action.scene.layout.action.list.noCanvasSelection";
break;
case MacroActionSwitchScene::Action::SCENE_LIST_INDEX:
layoutString =
(canvasCount > 1)
? "AdvSceneSwitcher.action.scene.layout.action.listIndex"
: "AdvSceneSwitcher.action.scene.layout.action.listIndex.noCanvasSelection";
break;
default:
break;
}
_transitions->show();
if (_entryData->_transition.GetType() !=
TransitionSelection::Type::TRANSITION) {
_duration->show();
}
const bool fixedDuration = isUsingFixedLengthTransition(
_entryData->_transition.GetTransition());
_duration->setVisible(!fixedDuration);
PlaceWidgets(obs_module_text(layoutString), _actionLayout,
actionWidgets);
if (fixedDuration) {
PlaceWidgets(
obs_module_text(
"AdvSceneSwitcher.action.scene.entry.noDuration"),
_entryLayout, widgetPlaceholders);
} else {
PlaceWidgets(
obs_module_text("AdvSceneSwitcher.action.scene.entry"),
_entryLayout, widgetPlaceholders);
}
_transitionLayout->removeWidget(_transitions);
_transitionLayout->removeWidget(_duration);
ClearLayout(_transitionLayout);
const bool shouldShowDuration = shouldShowDurationInTransitionLayout(
_entryData->_sceneType, _entryData->_transition);
_duration->setVisible(shouldShowDuration);
layoutString =
shouldShowDuration
? "AdvSceneSwitcher.action.scene.layout.transitionWithDuration"
: "AdvSceneSwitcher.action.scene.layout.transition";
PlaceWidgets(obs_module_text(layoutString), _transitionLayout,
{{"{{transitions}}", _transitions},
{"{{duration}}", _duration}});
const auto canvas = action == MacroActionSwitchScene::Action::SCENE_NAME
? _entryData->_scene.GetCanvas()
: _entryData->_canvas;
const bool isMainCanvas = IsMainCanvas(canvas);
SetLayoutVisible(_transitionLayout, isMainCanvas);
_blockUntilTransitionDone->setVisible(isMainCanvas);
_scenes->setVisible(action ==
MacroActionSwitchScene::Action::SCENE_NAME);
_index->setVisible(action ==
MacroActionSwitchScene::Action::SCENE_LIST_INDEX);
_sceneNameAtIndex->setVisible(
action == MacroActionSwitchScene::Action::SCENE_LIST_INDEX);
const QString fmt = obs_module_text(
"AdvSceneSwitcher.action.scene.canvasNotSupported");
_notSupportedWarning->setText(
fmt.arg(QString::fromStdString(GetWeakCanvasName(canvas))));
_notSupportedWarning->setVisible(
!IsMainCanvas(canvas) &&
_entryData->_sceneType ==
MacroActionSwitchScene::SceneType::PREVIEW);
adjustSize();
updateGeometry();
}
void MacroActionSwitchSceneEdit::SceneChanged(const SceneSelection &s)

View File

@ -6,6 +6,8 @@
#include <QCheckBox>
#include <obs.hpp>
namespace advss {
class MacroActionSwitchScene : public MacroAction {
@ -21,8 +23,19 @@ public:
std::shared_ptr<MacroAction> Copy() const;
void ResolveVariablesToFixedValues();
enum class Action {
SCENE_NAME,
SCENE_LIST_NEXT,
SCENE_LIST_PREVIOUS,
SCENE_LIST_INDEX,
};
Action _action = Action::SCENE_NAME;
enum class SceneType { PROGRAM, PREVIEW };
SceneType _sceneType = SceneType::PROGRAM;
OBSWeakCanvas _canvas;
IntVariable _index = 1;
SceneSelection _scene;
TransitionSelection _transition;
Duration _duration;
@ -57,18 +70,32 @@ private slots:
void DurationChanged(const Duration &seconds);
void BlockUntilTransitionDoneChanged(int state);
void SceneTypeChanged(int);
void CanvasChanged(const OBSWeakCanvas &);
void SceneSelectionCanvasChanged(const OBSWeakCanvas &);
void ActionChanged(int);
void IndexChanged(const NumberVariable<int> &);
void UpdateSceneNameAtIndex();
signals:
void HeaderInfoChanged(const QString &);
private:
void SetupWidgetConnections() const;
void SetWidgetData() const;
void SetWidgetVisibility();
QComboBox *_actions;
VariableSpinBox *_index;
SceneSelectionWidget *_scenes;
TransitionSelectionWidget *_transitions;
DurationSelection *_duration;
QCheckBox *_blockUntilTransitionDone;
QComboBox *_sceneTypes;
QHBoxLayout *_entryLayout;
CanvasSelection *_canvas;
QLabel *_sceneNameAtIndex;
QTimer *_updateSceneNameTimer;
QHBoxLayout *_actionLayout;
QHBoxLayout *_transitionLayout;
QLabel *_notSupportedWarning;
std::shared_ptr<MacroActionSwitchScene> _entryData;
bool _loading = true;