mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-23 17:55:43 -05:00
Add SceneItemSelection and SceneItemSelectionWidget
Allows selecting individual scene items if there are duplicate entries for the same source.
This commit is contained in:
@@ -248,6 +248,7 @@ set(advanced-scene-switcher_HEADERS
|
||||
src/headers/macro-selection.hpp
|
||||
src/headers/curl-helper.hpp
|
||||
src/headers/hotkey.hpp
|
||||
src/headers/scene-item-selection.hpp
|
||||
src/headers/scene-selection.hpp
|
||||
src/headers/screenshot-helper.hpp
|
||||
src/headers/transition-selection.hpp
|
||||
@@ -346,6 +347,7 @@ set(advanced-scene-switcher_SOURCES
|
||||
src/macro-selection.cpp
|
||||
src/macro-tab.cpp
|
||||
src/curl-helper.cpp
|
||||
src/scene-item-selection.cpp
|
||||
src/scene-selection.cpp
|
||||
src/screenshot-helper.cpp
|
||||
src/transition-selection.cpp
|
||||
|
||||
@@ -662,6 +662,8 @@ AdvSceneSwitcher.enterPath="--enter path--"
|
||||
AdvSceneSwitcher.enterText="--enter text--"
|
||||
AdvSceneSwitcher.invaildEntriesWillNotBeSaved="invalid entries will not be saved"
|
||||
AdvSceneSwitcher.selectWindowTip="Use \"OBS\" to specify OBS window\nUse \"Task Switching\"to specify ALT + TAB"
|
||||
AdvSceneSwitcher.sceneItemSelection.all="All"
|
||||
AdvSceneSwitcher.sceneItemSelection.any="Any"
|
||||
|
||||
AdvSceneSwitcher.status.active="Active"
|
||||
AdvSceneSwitcher.status.inactive="Inactive"
|
||||
|
||||
59
src/headers/scene-item-selection.hpp
Normal file
59
src/headers/scene-item-selection.hpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
#include <QComboBox>
|
||||
#include <obs-data.h>
|
||||
|
||||
#include "scene-selection.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
class SceneItemSelection {
|
||||
public:
|
||||
void Save(obs_data_t *obj, const char *name = "sceneItem",
|
||||
const char *targetName = "sceneItemTarget",
|
||||
const char *idxName = "sceneItemIdx");
|
||||
void Load(obs_data_t *obj, const char *name = "sceneItem",
|
||||
const char *targetName = "sceneItemTarget",
|
||||
const char *idxName = "sceneItemIdx");
|
||||
|
||||
enum class Target { ALL, ANY, INDIVIDUAL };
|
||||
Target GetType() { return _target; }
|
||||
std::vector<obs_scene_item *> GetSceneItems(SceneSelection &s);
|
||||
std::string ToString();
|
||||
|
||||
private:
|
||||
OBSWeakSource _sceneItem;
|
||||
Target _target = Target::ALL;
|
||||
int _idx = 0;
|
||||
friend class SceneItemSelectionWidget;
|
||||
};
|
||||
|
||||
class SceneItemSelectionWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum class AllSelectionType { ALL, ANY };
|
||||
SceneItemSelectionWidget(
|
||||
QWidget *parent, bool allSelection = true,
|
||||
AllSelectionType allType = AllSelectionType::ALL);
|
||||
void SetSceneItem(const SceneItemSelection &);
|
||||
void SetScene(const SceneSelection &);
|
||||
void SetShowAll(bool);
|
||||
void SetShowAllSelectionType(AllSelectionType t);
|
||||
signals:
|
||||
void SceneItemChanged(const SceneItemSelection &);
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SelectionChanged(const QString &name);
|
||||
void IdxChanged(int);
|
||||
|
||||
private:
|
||||
void SetupIdxSelection(int);
|
||||
|
||||
QComboBox *_sceneItems;
|
||||
QComboBox *_idx;
|
||||
|
||||
SceneSelection _scene;
|
||||
OBSWeakSource _sceneItem;
|
||||
bool _showAll = false;
|
||||
AllSelectionType _allType = AllSelectionType::ALL;
|
||||
};
|
||||
240
src/scene-item-selection.cpp
Normal file
240
src/scene-item-selection.cpp
Normal file
@@ -0,0 +1,240 @@
|
||||
#include "headers/scene-item-selection.hpp"
|
||||
|
||||
#include <obs-module.h>
|
||||
|
||||
void SceneItemSelection::Save(obs_data_t *obj, const char *name,
|
||||
const char *targetName, const char *idxName)
|
||||
{
|
||||
obs_data_set_int(obj, targetName, static_cast<int>(_target));
|
||||
if (_target == SceneItemSelection::Target::INDIVIDUAL) {
|
||||
obs_data_set_int(obj, idxName, _idx);
|
||||
} else {
|
||||
obs_data_set_int(obj, idxName, 0);
|
||||
}
|
||||
obs_data_set_string(obj, name, GetWeakSourceName(_sceneItem).c_str());
|
||||
}
|
||||
|
||||
void SceneItemSelection::Load(obs_data_t *obj, const char *name,
|
||||
const char *targetName, const char *idxName)
|
||||
{
|
||||
_target = static_cast<SceneItemSelection::Target>(
|
||||
obs_data_get_int(obj, targetName));
|
||||
_idx = obs_data_get_int(obj, idxName);
|
||||
auto sceneItemName = obs_data_get_string(obj, name);
|
||||
_sceneItem = GetWeakSourceByName(sceneItemName);
|
||||
}
|
||||
|
||||
struct ItemCountData {
|
||||
std::string name;
|
||||
int count = 0;
|
||||
};
|
||||
|
||||
static bool countSceneItem(obs_scene_t *, obs_sceneitem_t *item, void *ptr)
|
||||
{
|
||||
auto data = reinterpret_cast<ItemCountData *>(ptr);
|
||||
|
||||
if (obs_sceneitem_is_group(item)) {
|
||||
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
|
||||
obs_scene_enum_items(scene, countSceneItem, ptr);
|
||||
}
|
||||
auto name = obs_source_get_name(obs_sceneitem_get_source(item));
|
||||
if (name == data->name) {
|
||||
data->count++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int getCountOfSceneItemOccurance(SceneSelection &s, std::string &name,
|
||||
bool enumAllScenes = true)
|
||||
{
|
||||
ItemCountData data{name};
|
||||
if (enumAllScenes && (s.GetType() == SceneSelectionType::CURRENT ||
|
||||
s.GetType() == SceneSelectionType::PREVIOUS)) {
|
||||
auto enumScenes = [](void *param, obs_source_t *source) {
|
||||
if (!source) {
|
||||
return true;
|
||||
}
|
||||
auto data = reinterpret_cast<ItemCountData *>(param);
|
||||
auto scene = obs_scene_from_source(source);
|
||||
obs_scene_enum_items(scene, countSceneItem, data);
|
||||
return true;
|
||||
};
|
||||
obs_enum_scenes(enumScenes, &data);
|
||||
} else {
|
||||
auto source = obs_weak_source_get_source(s.GetScene(false));
|
||||
auto scene = obs_scene_from_source(source);
|
||||
obs_scene_enum_items(scene, countSceneItem, &data);
|
||||
obs_source_release(source);
|
||||
}
|
||||
return data.count;
|
||||
}
|
||||
|
||||
std::vector<obs_scene_item *>
|
||||
SceneItemSelection::GetSceneItems(SceneSelection &sceneSelection)
|
||||
{
|
||||
auto s = obs_weak_source_get_source(sceneSelection.GetScene(false));
|
||||
auto scene = obs_scene_from_source(s);
|
||||
auto name = GetWeakSourceName(_sceneItem);
|
||||
int count = getCountOfSceneItemOccurance(sceneSelection, name, false);
|
||||
auto items = getSceneItemsWithName(scene, name);
|
||||
obs_source_release(s);
|
||||
|
||||
std::vector<obs_scene_item *> ret;
|
||||
|
||||
if (_target == SceneItemSelection::Target::ALL ||
|
||||
_target == SceneItemSelection::Target::ANY) {
|
||||
ret = items;
|
||||
} else {
|
||||
// Index order starts at the bottom and increases to the top
|
||||
// As this might be confusing reverse that order internally
|
||||
int idx = count - 1 - _idx;
|
||||
|
||||
if (idx >= 0 && idx < items.size()) {
|
||||
obs_sceneitem_addref(items[idx]);
|
||||
ret.emplace_back(items[idx]);
|
||||
}
|
||||
|
||||
for (auto item : items) {
|
||||
obs_sceneitem_release(item);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string SceneItemSelection::ToString()
|
||||
{
|
||||
return GetWeakSourceName(_sceneItem);
|
||||
}
|
||||
|
||||
SceneItemSelectionWidget::SceneItemSelectionWidget(QWidget *parent,
|
||||
bool showAll,
|
||||
AllSelectionType type)
|
||||
: QWidget(parent), _showAll(showAll), _allType(type)
|
||||
{
|
||||
_sceneItems = new QComboBox();
|
||||
_idx = new QComboBox();
|
||||
|
||||
_sceneItems->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||
_idx->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||
|
||||
populateSceneItemSelection(_sceneItems);
|
||||
|
||||
QWidget::connect(_sceneItems,
|
||||
SIGNAL(currentTextChanged(const QString &)), this,
|
||||
SLOT(SelectionChanged(const QString &)));
|
||||
QWidget::connect(_idx, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(IdxChanged(int)));
|
||||
auto layout = new QHBoxLayout;
|
||||
layout->addWidget(_idx);
|
||||
layout->addWidget(_sceneItems);
|
||||
setLayout(layout);
|
||||
_idx->hide();
|
||||
}
|
||||
|
||||
void SceneItemSelectionWidget::SetSceneItem(const SceneItemSelection &item)
|
||||
{
|
||||
_sceneItems->setCurrentText(
|
||||
QString::fromStdString(GetWeakSourceName(item._sceneItem)));
|
||||
if (item._target == SceneItemSelection::Target::ALL) {
|
||||
_allType = AllSelectionType::ALL;
|
||||
_idx->setCurrentIndex(0);
|
||||
} else if (item._target == SceneItemSelection::Target::ANY) {
|
||||
_allType = AllSelectionType::ANY;
|
||||
_idx->setCurrentIndex(0);
|
||||
} else {
|
||||
int idx = item._idx;
|
||||
if (_showAll) {
|
||||
idx += 1;
|
||||
}
|
||||
_idx->setCurrentIndex(idx);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneItemSelectionWidget::SetScene(const SceneSelection &s)
|
||||
{
|
||||
_scene = s;
|
||||
_sceneItems->clear();
|
||||
_idx->hide();
|
||||
populateSceneItemSelection(_sceneItems, _scene);
|
||||
}
|
||||
|
||||
void SceneItemSelectionWidget::SetShowAll(bool value)
|
||||
{
|
||||
_showAll = value;
|
||||
}
|
||||
|
||||
void SceneItemSelectionWidget::SetShowAllSelectionType(AllSelectionType t)
|
||||
{
|
||||
_allType = t;
|
||||
_sceneItems->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
void SceneItemSelectionWidget::SceneChanged(const SceneSelection &s)
|
||||
{
|
||||
SetScene(s);
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
void SceneItemSelectionWidget::SelectionChanged(const QString &name)
|
||||
{
|
||||
SceneItemSelection s;
|
||||
_sceneItem = GetWeakSourceByQString(name);
|
||||
s._sceneItem = _sceneItem;
|
||||
if (_allType == AllSelectionType::ALL) {
|
||||
s._target = SceneItemSelection::Target::ALL;
|
||||
} else {
|
||||
s._target = SceneItemSelection::Target::ANY;
|
||||
}
|
||||
auto stdName = name.toStdString();
|
||||
int sceneItemCount = getCountOfSceneItemOccurance(_scene, stdName);
|
||||
if (sceneItemCount > 1) {
|
||||
_idx->show();
|
||||
SetupIdxSelection(sceneItemCount);
|
||||
} else {
|
||||
_idx->hide();
|
||||
}
|
||||
emit SceneItemChanged(s);
|
||||
}
|
||||
|
||||
void SceneItemSelectionWidget::IdxChanged(int idx)
|
||||
{
|
||||
if (idx < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
SceneItemSelection s;
|
||||
s._sceneItem = _sceneItem;
|
||||
if (_showAll && idx == 0) {
|
||||
if (_allType == AllSelectionType::ALL) {
|
||||
s._target = SceneItemSelection::Target::ALL;
|
||||
} else {
|
||||
s._target = SceneItemSelection::Target::ANY;
|
||||
}
|
||||
s._idx = 0;
|
||||
} else {
|
||||
s._target = SceneItemSelection::Target::INDIVIDUAL;
|
||||
if (_showAll) {
|
||||
idx -= 1;
|
||||
}
|
||||
s._idx = idx;
|
||||
}
|
||||
emit SceneItemChanged(s);
|
||||
}
|
||||
|
||||
void SceneItemSelectionWidget::SetupIdxSelection(int sceneItemCount)
|
||||
{
|
||||
_idx->clear();
|
||||
if (_showAll) {
|
||||
if (_allType == AllSelectionType::ALL) {
|
||||
_idx->addItem(obs_module_text(
|
||||
"AdvSceneSwitcher.sceneItemSelection.all"));
|
||||
} else {
|
||||
_idx->addItem(obs_module_text(
|
||||
"AdvSceneSwitcher.sceneItemSelection.any"));
|
||||
}
|
||||
}
|
||||
for (int i = 1; i <= sceneItemCount; ++i) {
|
||||
_idx->addItem(QString::number(i) + ".");
|
||||
}
|
||||
adjustSize();
|
||||
}
|
||||
Reference in New Issue
Block a user