Add macro action "random" (#353)

This should be expanded upon by adding the ability to add weights to each macro.
This commit is contained in:
WarmUpTill 2021-11-20 03:52:12 -08:00 committed by GitHub
parent cce6e240c2
commit a1cae263c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 355 additions and 2 deletions

View File

@ -215,6 +215,7 @@ set(advanced-scene-switcher_HEADERS
src/headers/macro-action-media.hpp
src/headers/macro-action-plugin-state.hpp
src/headers/macro-action-preview-scene.hpp
src/headers/macro-action-random.hpp
src/headers/macro-action-recording.hpp
src/headers/macro-action-replay-buffer.hpp
src/headers/macro-action-run.hpp
@ -307,6 +308,7 @@ set(advanced-scene-switcher_SOURCES
src/macro-action-media.cpp
src/macro-action-plugin-state.cpp
src/macro-action-preview-scene.cpp
src/macro-action-random.cpp
src/macro-action-recording.cpp
src/macro-action-replay-buffer.cpp
src/macro-action-run.cpp

View File

@ -353,6 +353,10 @@ AdvSceneSwitcher.action.timer.type.continue="Continue"
AdvSceneSwitcher.action.timer.type.reset="Reset"
AdvSceneSwitcher.action.timer.type.setTimeRemaining="Set time remaining of"
AdvSceneSwitcher.action.timer.entry="{{timerAction}} timers on {{macros}} {{duration}}"
AdvSceneSwitcher.action.random="Random"
AdvSceneSwitcher.action.random.arguments="Macros:"
AdvSceneSwitcher.action.random.addArgument="Add Macro"
AdvSceneSwitcher.action.random.entry="Run {{macroSelection}}"
; Transition Tab
AdvSceneSwitcher.transitionTab.title="Transition"

View File

@ -0,0 +1,63 @@
#pragma once
#include "macro-action-edit.hpp"
#include "macro-selection.hpp"
#include <QPushButton>
#include <QListWidget>
#include <unordered_map>
class MacroActionRandom : public MultiMacroRefAction {
public:
bool PerformAction();
void LogAction();
bool Save(obs_data_t *obj);
bool Load(obs_data_t *obj);
std::string GetId() { return id; };
static std::shared_ptr<MacroAction> Create()
{
return std::make_shared<MacroActionRandom>();
}
// TODO: add weights to each macro ...
// std::unordered_map<MacroRef, int> _weights;
private:
MacroRef lastRandomMacro;
static bool _registered;
static const std::string id;
};
class MacroActionRandomEdit : public QWidget {
Q_OBJECT
public:
MacroActionRandomEdit(
QWidget *parent,
std::shared_ptr<MacroActionRandom> entryData = nullptr);
void UpdateEntryData();
static QWidget *Create(QWidget *parent,
std::shared_ptr<MacroAction> action)
{
return new MacroActionRandomEdit(
parent,
std::dynamic_pointer_cast<MacroActionRandom>(action));
}
private slots:
void MacroRemove(const QString &name);
void MacroRename(const QString &oldName, const QString &newName);
void AddMacro();
void RemoveMacro();
int FindEntry(const std::string &macro);
void MacroSelectionChanged(int idx);
protected:
std::shared_ptr<MacroActionRandom> _entryData;
private:
MacroSelection *_macroSelection;
QListWidget *_macroList;
QPushButton *_add;
QPushButton *_remove;
bool _loading = true;
};

View File

@ -145,3 +145,9 @@ public:
void ResolveMacroRef();
MacroRef _macro;
};
class MultiMacroRefAction : public MacroAction {
public:
void ResolveMacroRef();
std::vector<MacroRef> _macros;
};

263
src/macro-action-random.cpp Normal file
View File

@ -0,0 +1,263 @@
#include "headers/macro-action-random.hpp"
#include "headers/advanced-scene-switcher.hpp"
#include "headers/name-dialog.hpp"
#include "headers/utility.hpp"
#include <cstdlib>
const std::string MacroActionRandom::id = "random";
bool MacroActionRandom::_registered = MacroActionFactory::Register(
MacroActionRandom::id,
{MacroActionRandom::Create, MacroActionRandomEdit::Create,
"AdvSceneSwitcher.action.random"});
std::vector<MacroRef> getPossibleMacros(std::vector<MacroRef> &macros,
MacroRef &lastRandomMacro)
{
std::vector<MacroRef> res;
if (macros.size() == 1) {
if (macros[0]->Paused()) {
return res;
} else {
return macros;
}
}
for (auto &m : macros) {
if (m.get() && !m->Paused() &&
!(lastRandomMacro.get() == m.get())) {
res.push_back(m);
}
}
return res;
}
bool MacroActionRandom::PerformAction()
{
if (_macros.size() == 0) {
return true;
}
auto macros = getPossibleMacros(_macros, lastRandomMacro);
if (macros.size() == 0) {
return true;
}
if (macros.size() == 1) {
lastRandomMacro = macros[0];
return macros[0]->PerformAction();
}
size_t idx = std::rand() % (macros.size());
lastRandomMacro = macros[idx];
return macros[idx]->PerformAction();
}
void MacroActionRandom::LogAction()
{
vblog(LOG_INFO, "running random macro");
}
bool MacroActionRandom::Save(obs_data_t *obj)
{
MacroAction::Save(obj);
obs_data_array_t *args = obs_data_array_create();
for (auto &m : _macros) {
obs_data_t *array_obj = obs_data_create();
m.Save(array_obj);
obs_data_array_push_back(args, array_obj);
obs_data_release(array_obj);
}
obs_data_set_array(obj, "macros", args);
obs_data_array_release(args);
return true;
}
bool MacroActionRandom::Load(obs_data_t *obj)
{
MacroAction::Load(obj);
obs_data_array_t *args = obs_data_get_array(obj, "macros");
size_t count = obs_data_array_count(args);
for (size_t i = 0; i < count; i++) {
obs_data_t *array_obj = obs_data_array_item(args, i);
MacroRef ref;
ref.Load(array_obj);
_macros.push_back(ref);
obs_data_release(array_obj);
}
obs_data_array_release(args);
return true;
}
MacroActionRandomEdit::MacroActionRandomEdit(
QWidget *parent, std::shared_ptr<MacroActionRandom> entryData)
: QWidget(parent)
{
_macroSelection = new MacroSelection(window());
_macroList = new QListWidget();
_macroList->setSortingEnabled(true);
_add = new QPushButton();
_add->setMaximumSize(QSize(22, 22));
_add->setProperty("themeID",
QVariant(QString::fromUtf8("addIconSmall")));
_add->setFlat(true);
_remove = new QPushButton();
_remove->setMaximumSize(QSize(22, 22));
_remove->setProperty("themeID",
QVariant(QString::fromUtf8("removeIconSmall")));
_remove->setFlat(true);
QWidget::connect(_add, SIGNAL(clicked()), this, SLOT(AddMacro()));
QWidget::connect(_remove, SIGNAL(clicked()), this, SLOT(RemoveMacro()));
QWidget::connect(_macroList, SIGNAL(currentRowChanged(int)), this,
SLOT(MacroSelectionChanged(int)));
QWidget::connect(window(),
SIGNAL(MacroRenamed(const QString &, const QString &)),
this,
SLOT(MacroRename(const QString &, const QString &)));
auto *entryLayout = new QHBoxLayout;
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{macroSelection}}", _macroSelection},
};
placeWidgets(obs_module_text("AdvSceneSwitcher.action.random.entry"),
entryLayout, widgetPlaceholders);
auto *argButtonLayout = new QHBoxLayout;
argButtonLayout->addWidget(_add);
argButtonLayout->addWidget(_remove);
argButtonLayout->addStretch();
auto *mainLayout = new QVBoxLayout;
mainLayout->addLayout(entryLayout);
mainLayout->addWidget(new QLabel(
obs_module_text("AdvSceneSwitcher.action.random.arguments")));
mainLayout->addWidget(_macroList);
mainLayout->addLayout(argButtonLayout);
setLayout(mainLayout);
_entryData = entryData;
UpdateEntryData();
_loading = false;
}
void MacroActionRandomEdit::UpdateEntryData()
{
if (!_entryData) {
return;
}
for (auto &m : _entryData->_macros) {
if (!m.get()) {
continue;
}
auto name = QString::fromStdString(m->Name());
QListWidgetItem *item = new QListWidgetItem(name, _macroList);
item->setData(Qt::UserRole, name);
}
}
void MacroActionRandomEdit::MacroRemove(const QString &name)
{
if (_entryData) {
auto it = _entryData->_macros.begin();
while (it != _entryData->_macros.end()) {
if (it->get()->Name() == name.toStdString()) {
it = _entryData->_macros.erase(it);
} else {
++it;
}
}
}
}
void MacroActionRandomEdit::MacroRename(const QString &oldName,
const QString &newName)
{
auto count = _macroList->count();
for (int idx = 0; idx < count; ++idx) {
QListWidgetItem *item = _macroList->item(idx);
QString itemString = item->data(Qt::UserRole).toString();
if (oldName == itemString) {
item->setData(Qt::UserRole, newName);
item->setText(newName);
break;
}
}
}
void MacroActionRandomEdit::AddMacro()
{
if (_loading || !_entryData) {
return;
}
auto macroName = _macroSelection->currentText();
MacroRef macro(macroName.toStdString());
if (!macro.get()) {
return;
}
if (FindEntry(macro->Name()) != -1) {
return;
}
QVariant v = QVariant::fromValue(macroName);
QListWidgetItem *item = new QListWidgetItem(macroName, _macroList);
item->setData(Qt::UserRole, macroName);
std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_macros.push_back(macro);
}
void MacroActionRandomEdit::RemoveMacro()
{
if (_loading || !_entryData) {
return;
}
std::lock_guard<std::mutex> lock(switcher->m);
auto item = _macroList->currentItem();
if (!item) {
return;
}
std::string name = item->data(Qt::UserRole).toString().toStdString();
for (auto it = _entryData->_macros.begin();
it != _entryData->_macros.end(); ++it) {
auto m = *it;
if (m.get() && m->Name() == name) {
_entryData->_macros.erase(it);
break;
}
}
delete item;
}
int MacroActionRandomEdit::FindEntry(const std::string &macro)
{
int count = _macroList->count();
int idx = -1;
for (int i = 0; i < count; i++) {
QListWidgetItem *item = _macroList->item(i);
QString itemString = item->data(Qt::UserRole).toString();
if (QString::fromStdString(macro) == itemString) {
idx = i;
break;
}
}
return idx;
}
void MacroActionRandomEdit::MacroSelectionChanged(int idx)
{
if (_loading || !_entryData || idx == -1) {
return;
}
QListWidgetItem *item = _macroList->item(idx);
QString name = item->text();
_macroSelection->SetCurrentMacro(GetMacroByName(name.toUtf8().data()));
}

View File

@ -86,6 +86,9 @@ void AdvSceneSwitcher::on_macroRemove_clicked()
int idx = ui->macros->currentRow();
QString::fromStdString(switcher->macros[idx]->Name());
switcher->macros.erase(switcher->macros.begin() + idx);
for (auto &m : switcher->macros) {
m->ResolveMacroRef();
}
}
delete item;

View File

@ -303,13 +303,18 @@ void Macro::ResolveMacroRef()
MacroRefCondition *ref =
dynamic_cast<MacroRefCondition *>(c.get());
if (ref) {
ref->_macro.UpdateRef();
ref->ResolveMacroRef();
}
}
for (auto &a : _actions) {
MacroRefAction *ref = dynamic_cast<MacroRefAction *>(a.get());
if (ref) {
ref->_macro.UpdateRef();
ref->ResolveMacroRef();
}
MultiMacroRefAction *ref2 =
dynamic_cast<MultiMacroRefAction *>(a.get());
if (ref2) {
ref2->ResolveMacroRef();
}
}
}
@ -586,3 +591,10 @@ void MacroRefAction::ResolveMacroRef()
{
_macro.UpdateRef();
}
void MultiMacroRefAction::ResolveMacroRef()
{
for (auto &m : _macros) {
m.UpdateRef();
}
}