mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-03-29 21:35:35 -05:00
This required the following adjustments: Instead of having a dedicated entry indicating the empty selection the setPlaceholderText() mechanism is used. Thus the locations where the 1st entry was assumed to be the empty selection would have to be adjusted. Additional checks for the empty string / index -1 have been added. FindIdxInRagne() was adjusted to return -1 instead of 0 in case the given string was not found. Switched to index based singal instead of text based signal to be notified about selection changes.
456 lines
10 KiB
C++
456 lines
10 KiB
C++
#include "scene-selection.hpp"
|
|
#include "switcher-data.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 switcher->previousScene;
|
|
case Type::CURRENT:
|
|
return switcher->currentScene;
|
|
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 : switcher->sceneGroups) {
|
|
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
|