Add macro condition "scene item order"

This commit is contained in:
WarmUpTill 2021-06-14 10:37:04 +02:00 committed by WarmUpTill
parent efc8726054
commit 8ef798c70c
4 changed files with 347 additions and 0 deletions

View File

@ -107,6 +107,7 @@ set(advanced-scene-switcher_HEADERS
src/headers/macro-condition-process.hpp
src/headers/macro-condition-recording.hpp
src/headers/macro-condition-region.hpp
src/headers/macro-condition-scene-order.hpp
src/headers/macro-condition-scene.hpp
src/headers/macro-condition-source.hpp
src/headers/macro-condition-streaming.hpp
@ -181,6 +182,7 @@ set(advanced-scene-switcher_SOURCES
src/macro-condition-process.cpp
src/macro-condition-recording.cpp
src/macro-condition-region.cpp
src/macro-condition-scene-order.cpp
src/macro-condition-scene.cpp
src/macro-condition-source.cpp
src/macro-condition-streaming.cpp

View File

@ -162,6 +162,12 @@ AdvSceneSwitcher.condition.filter.getSettings="Get current settings"
AdvSceneSwitcher.condition.filter.entry.line1="On {{sources}} {{filters}} {{conditions}}"
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
AdvSceneSwitcher.condition.filter.entry.line3="{{regex}} {{getSettings}}"
AdvSceneSwitcher.condition.sceneOrder="Scene item order"
AdvSceneSwitcher.condition.sceneOrder.type.above="Is above"
AdvSceneSwitcher.condition.sceneOrder.type.below="Is below"
AdvSceneSwitcher.condition.sceneOrder.type.position="Is at position"
AdvSceneSwitcher.condition.sceneOrder.positionInfo="The position value starts at the bottom with 0 and increases by one for each scene item including the ones in scene groups"
AdvSceneSwitcher.condition.sceneOrder.entry="On {{scenes}} {{sources}} {{conditions}} {{sources2}} {{position}}"
; Macro Actions
AdvSceneSwitcher.action.switchScene="Switch scene"

View File

@ -0,0 +1,71 @@
#pragma once
#include "macro.hpp"
#include <QWidget>
#include <QComboBox>
enum class SceneOrderCondition {
ABOVE,
BELOW,
POSITION,
};
class MacroConditionSceneOrder : public MacroCondition {
public:
bool CheckCondition();
bool Save(obs_data_t *obj);
bool Load(obs_data_t *obj);
std::string GetId() { return id; };
static std::shared_ptr<MacroCondition> Create()
{
return std::make_shared<MacroConditionSceneOrder>();
}
OBSWeakSource _scene;
OBSWeakSource _source;
OBSWeakSource _source2;
int _position = 0;
SceneOrderCondition _condition = SceneOrderCondition::ABOVE;
private:
static bool _registered;
static const std::string id;
};
class MacroConditionSceneOrderEdit : public QWidget {
Q_OBJECT
public:
MacroConditionSceneOrderEdit(
QWidget *parent,
std::shared_ptr<MacroConditionSceneOrder> cond = nullptr);
void UpdateEntryData();
static QWidget *Create(QWidget *parent,
std::shared_ptr<MacroCondition> cond)
{
return new MacroConditionSceneOrderEdit(
parent,
std::dynamic_pointer_cast<MacroConditionSceneOrder>(
cond));
}
private slots:
void SceneChanged(const QString &text);
void SourceChanged(const QString &text);
void Source2Changed(const QString &text);
void ConditionChanged(int cond);
void PositionChanged(int cond);
protected:
QComboBox *_scenes;
QComboBox *_conditions;
QComboBox *_sources;
QComboBox *_sources2;
QSpinBox *_position;
QLabel *_posInfo;
std::shared_ptr<MacroConditionSceneOrder> _entryData;
private:
void SetWidgetVisibility(bool showPos);
bool _loading = true;
};

View File

@ -0,0 +1,268 @@
#include "headers/macro-condition-edit.hpp"
#include "headers/macro-condition-scene-order.hpp"
#include "headers/utility.hpp"
#include "headers/advanced-scene-switcher.hpp"
#include <regex>
const std::string MacroConditionSceneOrder::id = "scene_order";
bool MacroConditionSceneOrder::_registered = MacroConditionFactory::Register(
MacroConditionSceneOrder::id,
{MacroConditionSceneOrder::Create, MacroConditionSceneOrderEdit::Create,
"AdvSceneSwitcher.condition.sceneOrder"});
static std::map<SceneOrderCondition, std::string> sceneOrderConditionTypes = {
{SceneOrderCondition::ABOVE,
"AdvSceneSwitcher.condition.sceneOrder.type.above"},
{SceneOrderCondition::BELOW,
"AdvSceneSwitcher.condition.sceneOrder.type.below"},
{SceneOrderCondition::POSITION,
"AdvSceneSwitcher.condition.sceneOrder.type.position"},
};
struct PosInfo {
std::string name;
std::vector<int> pos = {};
int curPos = 0;
};
static bool getSceneItemPositions(obs_scene_t *, obs_sceneitem_t *item,
void *ptr)
{
PosInfo *posInfo = reinterpret_cast<PosInfo *>(ptr);
auto sourceName = obs_source_get_name(obs_sceneitem_get_source(item));
if (posInfo->name == sourceName) {
posInfo->pos.push_back(posInfo->curPos);
}
if (obs_sceneitem_is_group(item)) {
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
obs_scene_enum_items(scene, getSceneItemPositions, ptr);
}
posInfo->curPos += 1;
return true;
}
static bool isAbove(std::vector<int> &v1, std::vector<int> &v2)
{
for (int i : v1) {
for (int j : v2) {
if (i > j) {
return true;
}
}
}
return false;
}
static bool isBelow(std::vector<int> &v1, std::vector<int> &v2)
{
for (int i : v1) {
for (int j : v2) {
if (i < j) {
return true;
}
}
}
return false;
}
bool MacroConditionSceneOrder::CheckCondition()
{
if (!_source) {
return false;
}
bool ret = false;
auto s = obs_weak_source_get_source(_scene);
auto scene = obs_scene_from_source(s);
auto name1 = GetWeakSourceName(_source);
auto name2 = GetWeakSourceName(_source2);
PosInfo pos1 = {name1};
PosInfo pos2 = {name2};
obs_scene_enum_items(scene, getSceneItemPositions, &pos1);
obs_scene_enum_items(scene, getSceneItemPositions, &pos2);
switch (_condition) {
case SceneOrderCondition::ABOVE:
ret = isAbove(pos1.pos, pos2.pos);
break;
case SceneOrderCondition::BELOW:
ret = isBelow(pos1.pos, pos2.pos);
break;
case SceneOrderCondition::POSITION:
for (int p : pos1.pos) {
if (p == _position)
ret = true;
}
break;
default:
break;
}
obs_source_release(s);
return ret;
}
bool MacroConditionSceneOrder::Save(obs_data_t *obj)
{
MacroCondition::Save(obj);
obs_data_set_string(obj, "scene", GetWeakSourceName(_scene).c_str());
obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str());
obs_data_set_string(obj, "source2",
GetWeakSourceName(_source2).c_str());
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
obs_data_set_int(obj, "position", _position);
return true;
}
bool MacroConditionSceneOrder::Load(obs_data_t *obj)
{
MacroCondition::Load(obj);
const char *sceneName = obs_data_get_string(obj, "scene");
_scene = GetWeakSourceByName(sceneName);
const char *sourceName = obs_data_get_string(obj, "source");
_source = GetWeakSourceByName(sourceName);
const char *source2Name = obs_data_get_string(obj, "source2");
_source2 = GetWeakSourceByName(source2Name);
_condition = static_cast<SceneOrderCondition>(
obs_data_get_int(obj, "condition"));
_position = obs_data_get_int(obj, "position");
return true;
}
static inline void populateConditionSelection(QComboBox *list)
{
for (auto entry : sceneOrderConditionTypes) {
list->addItem(obs_module_text(entry.second.c_str()));
}
}
MacroConditionSceneOrderEdit::MacroConditionSceneOrderEdit(
QWidget *parent, std::shared_ptr<MacroConditionSceneOrder> entryData)
: QWidget(parent)
{
_scenes = new QComboBox();
_sources = new QComboBox();
_sources2 = new QComboBox();
_conditions = new QComboBox();
_position = new QSpinBox();
_posInfo = new QLabel(obs_module_text(
"AdvSceneSwitcher.condition.sceneOrder.positionInfo"));
populateConditionSelection(_conditions);
populateSceneSelection(_scenes);
QWidget::connect(_scenes, SIGNAL(currentTextChanged(const QString &)),
this, SLOT(SceneChanged(const QString &)));
QWidget::connect(_sources, SIGNAL(currentTextChanged(const QString &)),
this, SLOT(SourceChanged(const QString &)));
QWidget::connect(_sources2, SIGNAL(currentTextChanged(const QString &)),
this, SLOT(Source2Changed(const QString &)));
QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this,
SLOT(ConditionChanged(int)));
QWidget::connect(_position, SIGNAL(valueChanged(int)), this,
SLOT(PositionChanged(int)));
auto entryLayout = new QHBoxLayout();
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{scenes}}", _scenes}, {"{{sources}}", _sources},
{"{{sources2}}", _sources2}, {"{{conditions}}", _conditions},
{"{{position}}", _position},
};
placeWidgets(
obs_module_text("AdvSceneSwitcher.condition.sceneOrder.entry"),
entryLayout, widgetPlaceholders);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(entryLayout);
mainLayout->addWidget(_posInfo);
setLayout(mainLayout);
_entryData = entryData;
UpdateEntryData();
_loading = false;
}
void MacroConditionSceneOrderEdit::SceneChanged(const QString &text)
{
if (_loading || !_entryData) {
return;
}
{
std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_scene = GetWeakSourceByQString(text);
}
_sources->clear();
_sources2->clear();
populateSceneItemSelection(_sources, _entryData->_scene);
populateSceneItemSelection(_sources2, _entryData->_scene);
}
void MacroConditionSceneOrderEdit::SourceChanged(const QString &text)
{
if (_loading || !_entryData) {
return;
}
std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_source = GetWeakSourceByQString(text);
}
void MacroConditionSceneOrderEdit::Source2Changed(const QString &text)
{
if (_loading || !_entryData) {
return;
}
std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_source2 = GetWeakSourceByQString(text);
}
void MacroConditionSceneOrderEdit::ConditionChanged(int index)
{
if (_loading || !_entryData) {
return;
}
std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_condition = static_cast<SceneOrderCondition>(index);
SetWidgetVisibility(_entryData->_condition ==
SceneOrderCondition::POSITION);
}
void MacroConditionSceneOrderEdit::PositionChanged(int value)
{
if (_loading || !_entryData) {
return;
}
std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_position = value;
}
void MacroConditionSceneOrderEdit::SetWidgetVisibility(bool showPos)
{
_sources2->setVisible(!showPos);
_position->setVisible(showPos);
_posInfo->setVisible(showPos);
}
void MacroConditionSceneOrderEdit::UpdateEntryData()
{
if (!_entryData) {
return;
}
_scenes->setCurrentText(GetWeakSourceName(_entryData->_scene).c_str());
populateSceneItemSelection(_sources, _entryData->_scene);
populateSceneItemSelection(_sources2, _entryData->_scene);
_sources->setCurrentText(
GetWeakSourceName(_entryData->_source).c_str());
_sources2->setCurrentText(
GetWeakSourceName(_entryData->_source2).c_str());
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
SetWidgetVisibility(_entryData->_condition ==
SceneOrderCondition::POSITION);
}