#include "headers/macro-action-scene-visibility.hpp" #include "headers/advanced-scene-switcher.hpp" #include "headers/utility.hpp" const std::string MacroActionSceneVisibility::id = "scene_visibility"; bool MacroActionSceneVisibility::_registered = MacroActionFactory::Register( MacroActionSceneVisibility::id, {MacroActionSceneVisibility::Create, MacroActionSceneVisibilityEdit::Create, "AdvSceneSwitcher.action.sceneVisibility"}); const static std::map actionTypes = { {SceneVisibilityAction::SHOW, "AdvSceneSwitcher.action.sceneVisibility.type.show"}, {SceneVisibilityAction::HIDE, "AdvSceneSwitcher.action.sceneVisibility.type.hide"}, }; const static std::map sourceItemSourceTypes = { {SceneItemSourceType::SOURCE, "AdvSceneSwitcher.action.sceneVisibility.type.source"}, {SceneItemSourceType::SOURCE_GROUP, "AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup"}, }; struct VisibilityData { std::string name; bool visible; }; static bool visibilitySourceTypeEnum(obs_scene_t *, obs_sceneitem_t *item, void *ptr) { VisibilityData *vInfo = reinterpret_cast(ptr); auto sourceTypeName = obs_source_get_display_name( obs_source_get_id(obs_sceneitem_get_source(item))); if (vInfo->name == sourceTypeName) { obs_sceneitem_set_visible(item, vInfo->visible); } if (obs_sceneitem_is_group(item)) { obs_scene_t *scene = obs_sceneitem_group_get_scene(item); obs_scene_enum_items(scene, visibilitySourceTypeEnum, ptr); } return true; } bool MacroActionSceneVisibility::PerformAction() { switch (_sourceType) { case SceneItemSourceType::SOURCE: { auto items = _source.GetSceneItems(_scene); for (auto item : items) { obs_sceneitem_set_visible( item, _action == SceneVisibilityAction::SHOW); obs_sceneitem_release(item); } break; } case SceneItemSourceType::SOURCE_GROUP: { auto s = obs_weak_source_get_source(_scene.GetScene()); auto scene = obs_scene_from_source(s); VisibilityData vInfo = {_sourceGroup, _action == SceneVisibilityAction::SHOW}; obs_scene_enum_items(scene, visibilitySourceTypeEnum, &vInfo); obs_source_release(s); break; } default: break; } return true; } void MacroActionSceneVisibility::LogAction() { auto it = actionTypes.find(_action); if (it != actionTypes.end()) { if (_sourceType == SceneItemSourceType::SOURCE) { vblog(LOG_INFO, "performed visibility action \"%s\" for source \"%s\" on scene \"%s\"", it->second.c_str(), _source.ToString().c_str(), _scene.ToString().c_str()); } else { vblog(LOG_INFO, "performed visibility action \"%s\" for any source type \"%s\" on scene \"%s\"", it->second.c_str(), _sourceGroup.c_str(), _scene.ToString().c_str()); } } else { blog(LOG_WARNING, "ignored unknown SceneVisibility action %d", static_cast(_action)); } } bool MacroActionSceneVisibility::Save(obs_data_t *obj) { MacroAction::Save(obj); _scene.Save(obj); if (_sourceType == SceneItemSourceType::SOURCE) { _source.Save(obj); } else { obs_data_set_string(obj, "sourceGroup", _sourceGroup.c_str()); } obs_data_set_int(obj, "action", static_cast(_action)); obs_data_set_int(obj, "sourceType", static_cast(_sourceType)); return true; } bool MacroActionSceneVisibility::Load(obs_data_t *obj) { // Convert old data format // TODO: Remove in future version if (obs_data_has_user_value(obj, "source")) { auto sourceName = obs_data_get_string(obj, "source"); obs_data_set_string(obj, "sceneItem", sourceName); obs_data_set_string(obj, "sourceGroup", sourceName); } MacroAction::Load(obj); _scene.Load(obj); _source.Load(obj); _sourceType = static_cast( obs_data_get_int(obj, "sourceType")); _sourceGroup = obs_data_get_string(obj, "sourceGroup"); _action = static_cast( obs_data_get_int(obj, "action")); return true; } std::string MacroActionSceneVisibility::GetShortDesc() { if (_sourceType == SceneItemSourceType::SOURCE && !_source.ToString().empty()) { return _scene.ToString() + " - " + _source.ToString(); } if (_sourceType == SceneItemSourceType::SOURCE_GROUP && !_sourceGroup.empty()) { return _scene.ToString() + " - " + obs_module_text( "AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup") + " " + _sourceGroup; } return ""; } static inline void populateActionSelection(QComboBox *list) { for (auto entry : actionTypes) { list->addItem(obs_module_text(entry.second.c_str())); } } static inline void populateSourceItemTypeSelection(QComboBox *list) { for (auto entry : sourceItemSourceTypes) { list->addItem(obs_module_text(entry.second.c_str())); } } MacroActionSceneVisibilityEdit::MacroActionSceneVisibilityEdit( QWidget *parent, std::shared_ptr entryData) : QWidget(parent) { _scenes = new SceneSelectionWidget(window(), false, true, true); _sourceTypes = new QComboBox(); _sources = new SceneItemSelectionWidget(parent); _sourceGroups = new QComboBox(); _actions = new QComboBox(); populateSourceItemTypeSelection(_sourceTypes); populateSourceGroupSelection(_sourceGroups); populateActionSelection(_actions); QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this, SLOT(ActionChanged(int))); QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)), this, SLOT(SceneChanged(const SceneSelection &))); QWidget::connect(_sourceTypes, SIGNAL(currentIndexChanged(int)), this, SLOT(SourceTypeChanged(int))); QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)), _sources, SLOT(SceneChanged(const SceneSelection &))); QWidget::connect(_sources, SIGNAL(SceneItemChanged(const SceneItemSelection &)), this, SLOT(SourceChanged(const SceneItemSelection &))); QWidget::connect(_sourceGroups, SIGNAL(currentTextChanged(const QString &)), this, SLOT(SourceGroupChanged(const QString &))); QHBoxLayout *mainLayout = new QHBoxLayout; std::unordered_map widgetPlaceholders = { {"{{scenes}}", _scenes}, {"{{sourceTypes}}", _sourceTypes}, {"{{sources}}", _sources}, {"{{sourceGroups}}", _sourceGroups}, {"{{actions}}", _actions}, }; placeWidgets(obs_module_text( "AdvSceneSwitcher.action.sceneVisibility.entry"), mainLayout, widgetPlaceholders); setLayout(mainLayout); _entryData = entryData; UpdateEntryData(); _loading = false; } void MacroActionSceneVisibilityEdit::UpdateEntryData() { if (!_entryData) { return; } _actions->setCurrentIndex(static_cast(_entryData->_action)); _sourceTypes->setCurrentIndex( static_cast(_entryData->_sourceType)); _scenes->SetScene(_entryData->_scene); _sources->SetSceneItem((_entryData->_source)); _sourceGroups->setCurrentText( QString::fromStdString(_entryData->_sourceGroup)); SetWidgetVisibility(); } void MacroActionSceneVisibilityEdit::SceneChanged(const SceneSelection &s) { if (_loading || !_entryData) { return; } std::lock_guard lock(switcher->m); _entryData->_scene = s; } void MacroActionSceneVisibilityEdit::SourceTypeChanged(int value) { if (_loading || !_entryData) { return; } std::lock_guard lock(switcher->m); _entryData->_sourceType = static_cast(value); SetWidgetVisibility(); } void MacroActionSceneVisibilityEdit::SourceChanged( const SceneItemSelection &item) { if (_loading || !_entryData) { return; } std::lock_guard lock(switcher->m); _entryData->_source = item; emit HeaderInfoChanged( QString::fromStdString(_entryData->GetShortDesc())); } void MacroActionSceneVisibilityEdit::SourceGroupChanged(const QString &text) { if (_loading || !_entryData) { return; } std::lock_guard lock(switcher->m); if (text == obs_module_text("AdvSceneSwitcher.selectItem")) { _entryData->_sourceGroup = ""; } else { _entryData->_sourceGroup = text.toStdString(); } emit HeaderInfoChanged( QString::fromStdString(_entryData->GetShortDesc())); } void MacroActionSceneVisibilityEdit::ActionChanged(int value) { if (_loading || !_entryData) { return; } std::lock_guard lock(switcher->m); _entryData->_action = static_cast(value); } void MacroActionSceneVisibilityEdit::SetWidgetVisibility() { if (!_entryData) { return; } _sources->setVisible(_entryData->_sourceType == SceneItemSourceType::SOURCE); _sourceGroups->setVisible(_entryData->_sourceType == SceneItemSourceType::SOURCE_GROUP); adjustSize(); }