mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-03-22 01:44:49 -05:00
The "core" macro conditions and actions have been extracted out to the "base" plugin. The library now mostly contains functionality which is required across all plugins and (e.g. definitions for macro segments). The goal is to reduce the complexity and cross-dependencies and group the source files in a better way. This should relsove the "library limit of 65535 objects exceeded" build issue occuring in some Windows build environments.
458 lines
10 KiB
C++
458 lines
10 KiB
C++
#include "scene-selection.hpp"
|
|
#include "obs-module-helper.hpp"
|
|
#include "scene-group.hpp"
|
|
#include "scene-switch-helpers.hpp"
|
|
#include "utility.hpp"
|
|
|
|
namespace advss {
|
|
|
|
constexpr std::string_view typeSaveName = "type";
|
|
constexpr std::string_view nameSaveName = "name";
|
|
constexpr std::string_view selectionSaveName = "sceneSelection";
|
|
|
|
void SceneSelection::Save(obs_data_t *obj) const
|
|
{
|
|
auto data = obs_data_create();
|
|
obs_data_set_int(data, typeSaveName.data(), static_cast<int>(_type));
|
|
switch (_type) {
|
|
case Type::SCENE:
|
|
obs_data_set_string(data, nameSaveName.data(),
|
|
GetWeakSourceName(_scene).c_str());
|
|
break;
|
|
case Type::GROUP:
|
|
obs_data_set_string(data, nameSaveName.data(),
|
|
_group->name.c_str());
|
|
break;
|
|
case Type::VARIABLE: {
|
|
auto var = _variable.lock();
|
|
if (!var) {
|
|
break;
|
|
}
|
|
obs_data_set_string(data, nameSaveName.data(),
|
|
var->Name().c_str());
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
obs_data_set_obj(obj, selectionSaveName.data(), data);
|
|
obs_data_release(data);
|
|
}
|
|
|
|
void SceneSelection::Load(obs_data_t *obj, const char *name,
|
|
const char *typeName)
|
|
{
|
|
// TODO: Remove in future version
|
|
if (!obs_data_has_user_value(obj, selectionSaveName.data())) {
|
|
_type = static_cast<Type>(obs_data_get_int(obj, typeName));
|
|
auto targetName = obs_data_get_string(obj, name);
|
|
switch (_type) {
|
|
case Type::SCENE:
|
|
_scene = GetWeakSourceByName(targetName);
|
|
break;
|
|
case Type::GROUP:
|
|
_group = GetSceneGroupByName(targetName);
|
|
break;
|
|
case Type::PREVIOUS:
|
|
break;
|
|
case Type::CURRENT:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
auto data = obs_data_get_obj(obj, selectionSaveName.data());
|
|
_type = static_cast<Type>(obs_data_get_int(data, typeSaveName.data()));
|
|
auto targetName = obs_data_get_string(data, nameSaveName.data());
|
|
switch (_type) {
|
|
case Type::SCENE:
|
|
_scene = GetWeakSourceByName(targetName);
|
|
break;
|
|
case Type::GROUP:
|
|
_group = GetSceneGroupByName(targetName);
|
|
break;
|
|
case Type::PREVIOUS:
|
|
break;
|
|
case Type::CURRENT:
|
|
break;
|
|
case Type::PREVIEW:
|
|
break;
|
|
case Type::VARIABLE:
|
|
_variable = GetWeakVariableByName(targetName);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
obs_data_release(data);
|
|
}
|
|
|
|
static bool IsScene(const OBSWeakSource &source)
|
|
{
|
|
auto s = obs_weak_source_get_source(source);
|
|
bool ret = !!obs_scene_from_source(s);
|
|
obs_source_release(s);
|
|
return ret;
|
|
}
|
|
|
|
OBSWeakSource SceneSelection::GetScene(bool advance) const
|
|
{
|
|
switch (_type) {
|
|
case Type::SCENE:
|
|
return _scene;
|
|
case Type::GROUP:
|
|
if (!_group) {
|
|
return nullptr;
|
|
}
|
|
if (advance) {
|
|
return _group->getNextScene();
|
|
}
|
|
return _group->getCurrentScene();
|
|
case Type::PREVIOUS:
|
|
return GetPreviousScene();
|
|
case Type::CURRENT:
|
|
return GetCurrentScene();
|
|
case Type::PREVIEW: {
|
|
auto s = obs_frontend_get_current_preview_scene();
|
|
auto scene = obs_source_get_weak_source(s);
|
|
obs_weak_source_release(scene);
|
|
obs_source_release(s);
|
|
return scene;
|
|
}
|
|
case Type::VARIABLE: {
|
|
auto var = _variable.lock();
|
|
if (!var) {
|
|
return nullptr;
|
|
}
|
|
auto scene = GetWeakSourceByName(var->Value().c_str());
|
|
if (IsScene(scene)) {
|
|
return scene;
|
|
}
|
|
return nullptr;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
std::string SceneSelection::ToString(bool resolve) const
|
|
{
|
|
switch (_type) {
|
|
case Type::SCENE:
|
|
return GetWeakSourceName(_scene);
|
|
case Type::GROUP:
|
|
if (_group) {
|
|
if (resolve) {
|
|
return _group->name + "[" +
|
|
GetWeakSourceName(
|
|
_group->getCurrentScene()) +
|
|
"]";
|
|
}
|
|
return _group->name;
|
|
}
|
|
break;
|
|
case Type::PREVIOUS:
|
|
return obs_module_text("AdvSceneSwitcher.selectPreviousScene");
|
|
case Type::CURRENT:
|
|
return obs_module_text("AdvSceneSwitcher.selectCurrentScene");
|
|
case Type::PREVIEW:
|
|
return obs_module_text("AdvSceneSwitcher.selectPreviewScene");
|
|
case Type::VARIABLE: {
|
|
auto var = _variable.lock();
|
|
if (!var) {
|
|
return "";
|
|
}
|
|
if (resolve) {
|
|
return var->Name() + "[" + var->Value() + "]";
|
|
}
|
|
return var->Name();
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
SceneSelection SceneSelectionWidget::CurrentSelection()
|
|
{
|
|
SceneSelection s;
|
|
const int idx = currentIndex();
|
|
const auto name = currentText();
|
|
if (idx == -1 || name.isEmpty()) {
|
|
return s;
|
|
}
|
|
|
|
if (idx < _placeholderEndIdx) {
|
|
if (IsCurrentSceneSelected(name)) {
|
|
s._type = SceneSelection::Type::CURRENT;
|
|
}
|
|
if (IsPreviousSceneSelected(name)) {
|
|
s._type = SceneSelection::Type::PREVIOUS;
|
|
}
|
|
if (IsPreviewSceneSelected(name)) {
|
|
s._type = SceneSelection::Type::PREVIEW;
|
|
}
|
|
} else if (idx < _variablesEndIdx) {
|
|
s._type = SceneSelection::Type::VARIABLE;
|
|
s._variable = GetWeakVariableByQString(name);
|
|
} else if (idx < _groupsEndIdx) {
|
|
s._type = SceneSelection::Type::GROUP;
|
|
s._group = GetSceneGroupByQString(name);
|
|
} else if (idx < _scenesEndIdx) {
|
|
s._type = SceneSelection::Type::SCENE;
|
|
s._scene = GetWeakSourceByQString(name);
|
|
}
|
|
return s;
|
|
}
|
|
|
|
static QStringList getOrderList(bool current, bool previous, bool preview)
|
|
{
|
|
QStringList list;
|
|
if (current) {
|
|
list << obs_module_text("AdvSceneSwitcher.selectCurrentScene");
|
|
}
|
|
if (previous) {
|
|
list << obs_module_text("AdvSceneSwitcher.selectPreviousScene");
|
|
}
|
|
if (preview) {
|
|
list << obs_module_text("AdvSceneSwitcher.selectPreviewScene");
|
|
}
|
|
return list;
|
|
}
|
|
|
|
static QStringList getScenesList()
|
|
{
|
|
QStringList list;
|
|
char **scenes = obs_frontend_get_scene_names();
|
|
char **temp = scenes;
|
|
while (*temp) {
|
|
const char *name = *temp;
|
|
list << name;
|
|
temp++;
|
|
}
|
|
bfree(scenes);
|
|
return list;
|
|
}
|
|
|
|
static QStringList getSceneGroupsList()
|
|
{
|
|
QStringList list;
|
|
for (const auto &sg : GetSceneGroups()) {
|
|
list << QString::fromStdString(sg.name);
|
|
}
|
|
list.sort();
|
|
return list;
|
|
}
|
|
|
|
void SceneSelectionWidget::Reset()
|
|
{
|
|
auto previousSel = _currentSelection;
|
|
PopulateSelection();
|
|
SetScene(previousSel);
|
|
}
|
|
|
|
void SceneSelectionWidget::PopulateSelection()
|
|
{
|
|
clear();
|
|
if (_current || _previous) {
|
|
const QStringList order =
|
|
getOrderList(_current, _previous, _preview);
|
|
AddSelectionGroup(this, order);
|
|
}
|
|
_placeholderEndIdx = count();
|
|
|
|
if (_variables) {
|
|
const QStringList variables = GetVariablesNameList();
|
|
AddSelectionGroup(this, variables);
|
|
}
|
|
_variablesEndIdx = count();
|
|
|
|
if (_sceneGroups) {
|
|
const QStringList sceneGroups = getSceneGroupsList();
|
|
AddSelectionGroup(this, sceneGroups);
|
|
}
|
|
_groupsEndIdx = count();
|
|
|
|
const QStringList scenes = getScenesList();
|
|
AddSelectionGroup(this, scenes);
|
|
_scenesEndIdx = count();
|
|
|
|
// Remove last separator
|
|
removeItem(count() - 1);
|
|
setCurrentIndex(-1);
|
|
}
|
|
|
|
SceneSelectionWidget::SceneSelectionWidget(QWidget *parent, bool variables,
|
|
bool sceneGroups, bool previous,
|
|
bool current, bool preview)
|
|
: FilterComboBox(parent,
|
|
obs_module_text("AdvSceneSwitcher.selectScene")),
|
|
_current(current),
|
|
_previous(previous),
|
|
_preview(preview),
|
|
_variables(variables),
|
|
_sceneGroups(sceneGroups)
|
|
{
|
|
setDuplicatesEnabled(true);
|
|
PopulateSelection();
|
|
|
|
QWidget::connect(this, SIGNAL(currentIndexChanged(int)), this,
|
|
SLOT(SelectionChanged(int)));
|
|
|
|
// Scene groups
|
|
QWidget::connect(window(), SIGNAL(SceneGroupAdded(const QString &)),
|
|
this, SLOT(ItemAdd(const QString &)));
|
|
QWidget::connect(window(), SIGNAL(SceneGroupRemoved(const QString &)),
|
|
this, SLOT(ItemRemove(const QString &)));
|
|
QWidget::connect(
|
|
window(),
|
|
SIGNAL(SceneGroupRenamed(const QString &, const QString &)),
|
|
this, SLOT(ItemRename(const QString &, const QString &)));
|
|
|
|
// Variables
|
|
QWidget::connect(window(), SIGNAL(VariableAdded(const QString &)), this,
|
|
SLOT(ItemAdd(const QString &)));
|
|
QWidget::connect(window(), SIGNAL(VariableRemoved(const QString &)),
|
|
this, SLOT(ItemRemove(const QString &)));
|
|
QWidget::connect(
|
|
window(),
|
|
SIGNAL(VariableRenamed(const QString &, const QString &)), this,
|
|
SLOT(ItemRename(const QString &, const QString &)));
|
|
}
|
|
|
|
void SceneSelectionWidget::SetScene(const SceneSelection &s)
|
|
{
|
|
int idx = -1;
|
|
|
|
switch (s.GetType()) {
|
|
case SceneSelection::Type::SCENE: {
|
|
if (_scenesEndIdx == -1) {
|
|
idx = -1;
|
|
break;
|
|
}
|
|
idx = FindIdxInRagne(this, _groupsEndIdx, _scenesEndIdx,
|
|
s.ToString());
|
|
break;
|
|
}
|
|
case SceneSelection::Type::GROUP: {
|
|
if (_groupsEndIdx == -1) {
|
|
idx = -1;
|
|
break;
|
|
}
|
|
idx = FindIdxInRagne(this, _variablesEndIdx, _groupsEndIdx,
|
|
s.ToString());
|
|
break;
|
|
}
|
|
case SceneSelection::Type::PREVIOUS: {
|
|
if (_placeholderEndIdx == -1) {
|
|
idx = -1;
|
|
break;
|
|
}
|
|
|
|
idx = FindIdxInRagne(
|
|
this, _selectIdx, _placeholderEndIdx,
|
|
obs_module_text(
|
|
"AdvSceneSwitcher.selectPreviousScene"));
|
|
break;
|
|
}
|
|
case SceneSelection::Type::CURRENT: {
|
|
if (_placeholderEndIdx == -1) {
|
|
idx = -1;
|
|
break;
|
|
}
|
|
|
|
idx = FindIdxInRagne(
|
|
this, _selectIdx, _placeholderEndIdx,
|
|
obs_module_text("AdvSceneSwitcher.selectCurrentScene"));
|
|
break;
|
|
}
|
|
case SceneSelection::Type::PREVIEW: {
|
|
if (_placeholderEndIdx == -1) {
|
|
idx = -1;
|
|
break;
|
|
}
|
|
|
|
idx = FindIdxInRagne(
|
|
this, _selectIdx, _placeholderEndIdx,
|
|
obs_module_text("AdvSceneSwitcher.selectPreviewScene"));
|
|
break;
|
|
}
|
|
case SceneSelection::Type::VARIABLE: {
|
|
if (_variablesEndIdx == -1) {
|
|
idx = -1;
|
|
break;
|
|
}
|
|
idx = FindIdxInRagne(this, _placeholderEndIdx, _variablesEndIdx,
|
|
s.ToString());
|
|
break;
|
|
default:
|
|
idx = -1;
|
|
break;
|
|
}
|
|
}
|
|
setCurrentIndex(idx);
|
|
_currentSelection = s;
|
|
}
|
|
|
|
bool SceneSelectionWidget::IsCurrentSceneSelected(const QString &name)
|
|
{
|
|
return name == QString::fromStdString((obs_module_text(
|
|
"AdvSceneSwitcher.selectCurrentScene")));
|
|
}
|
|
|
|
bool SceneSelectionWidget::IsPreviousSceneSelected(const QString &name)
|
|
{
|
|
return name == QString::fromStdString((obs_module_text(
|
|
"AdvSceneSwitcher.selectPreviousScene")));
|
|
}
|
|
|
|
bool SceneSelectionWidget::IsPreviewSceneSelected(const QString &name)
|
|
{
|
|
return name == QString::fromStdString((obs_module_text(
|
|
"AdvSceneSwitcher.selectPreviewScene")));
|
|
}
|
|
|
|
void SceneSelectionWidget::SelectionChanged(int)
|
|
{
|
|
_currentSelection = CurrentSelection();
|
|
emit SceneChanged(_currentSelection);
|
|
}
|
|
|
|
void SceneSelectionWidget::ItemAdd(const QString &)
|
|
{
|
|
blockSignals(true);
|
|
Reset();
|
|
blockSignals(false);
|
|
}
|
|
|
|
bool SceneSelectionWidget::NameUsed(const QString &name)
|
|
{
|
|
if (_currentSelection._type == SceneSelection::Type::GROUP &&
|
|
_currentSelection._group &&
|
|
_currentSelection._group->name == name.toStdString()) {
|
|
return true;
|
|
}
|
|
return _currentSelection._type == SceneSelection::Type::VARIABLE &&
|
|
currentText() == name;
|
|
}
|
|
|
|
void SceneSelectionWidget::ItemRemove(const QString &name)
|
|
{
|
|
if (!NameUsed(name)) {
|
|
blockSignals(true);
|
|
}
|
|
Reset();
|
|
blockSignals(false);
|
|
}
|
|
|
|
void SceneSelectionWidget::ItemRename(const QString &, const QString &)
|
|
{
|
|
blockSignals(true);
|
|
Reset();
|
|
blockSignals(false);
|
|
}
|
|
|
|
} // namespace advss
|