diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini
index 9ba1a37e..1c58b335 100644
--- a/data/locale/en-US.ini
+++ b/data/locale/en-US.ini
@@ -1795,6 +1795,10 @@ AdvSceneSwitcher.script.file.layout="Script file:{{path}}{{open}}"
AdvSceneSwitcher.tempVar.select="--select value--"
AdvSceneSwitcher.tempVar.selectionInfo.lastValues="Last values:"
+AdvSceneSwitcher.tempVar.outputMappings="Save outputs to variables:"
+AdvSceneSwitcher.tempVar.outputMappings.add="+ Add output mapping"
+AdvSceneSwitcher.tempVar.outputMappings.toggle="Assign outputs to variables"
+AdvSceneSwitcher.tempVar.outputMappings.remove="Remove output mapping"
AdvSceneSwitcher.tempVar.twitch.broadcaster_user_id="Twitch broadcaster user ID"
AdvSceneSwitcher.tempVar.twitch.broadcaster_user_id.description="The numerical Twitch user ID of the broadcaster."
diff --git a/data/res/images/DarkVariable.svg b/data/res/images/DarkVariable.svg
new file mode 100644
index 00000000..02c1091e
--- /dev/null
+++ b/data/res/images/DarkVariable.svg
@@ -0,0 +1,10 @@
+
+
\ No newline at end of file
diff --git a/data/res/images/LightVariable.svg b/data/res/images/LightVariable.svg
new file mode 100644
index 00000000..8544425c
--- /dev/null
+++ b/data/res/images/LightVariable.svg
@@ -0,0 +1,10 @@
+
+
\ No newline at end of file
diff --git a/lib/macro/macro-action-edit.cpp b/lib/macro/macro-action-edit.cpp
index 3156ff7b..5b5a239a 100644
--- a/lib/macro/macro-action-edit.cpp
+++ b/lib/macro/macro-action-edit.cpp
@@ -49,10 +49,12 @@ MacroActionEdit::MacroActionEdit(QWidget *parent,
_section->AddHeaderWidget(_enable);
_section->AddHeaderWidget(_actionSelection);
_section->AddHeaderWidget(_headerInfo);
+ _section->AddHeaderWidget(_varMappingToggle);
auto actionLayout = new QVBoxLayout;
actionLayout->setContentsMargins({7, 7, 7, 7});
actionLayout->addWidget(_section);
+ actionLayout->addWidget(_outputMappings);
_contentLayout->addLayout(actionLayout);
auto mainLayout = new QHBoxLayout;
@@ -61,7 +63,6 @@ MacroActionEdit::MacroActionEdit(QWidget *parent,
mainLayout->addWidget(_frame);
setLayout(mainLayout);
- _entryData = entryData;
SetupWidgets(true);
actionStateTimer->start(300);
@@ -90,7 +91,10 @@ void MacroActionEdit::SetupWidgets(bool basicSetup)
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
this, SLOT(HeaderInfoChanged(const QString &)));
+ QWidget::connect(widget, SIGNAL(ShowVariableMappings(bool)), this,
+ SLOT(ShowVariableMappings(bool)));
_section->SetContent(widget, (*_entryData)->GetCollapsed());
+ SetupVarMappings((*_entryData).get());
SetFocusPolicyOfWidgets();
_allWidgetsAreSetup = true;
@@ -121,7 +125,10 @@ void MacroActionEdit::ActionSelectionChanged(const QString &text)
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
this, SLOT(HeaderInfoChanged(const QString &)));
+ QWidget::connect(widget, SIGNAL(ShowVariableMappings(bool)), this,
+ SLOT(ShowVariableMappings(bool)));
_section->SetContent(widget);
+ SetupVarMappings((*_entryData).get());
SetFocusPolicyOfWidgets();
}
diff --git a/lib/macro/macro-action-variable.cpp b/lib/macro/macro-action-variable.cpp
index e92329dc..57bb3495 100644
--- a/lib/macro/macro-action-variable.cpp
+++ b/lib/macro/macro-action-variable.cpp
@@ -19,10 +19,11 @@ const std::string MacroActionVariable::id = "variable";
std::vector MacroActionVariable::GetTempVarRefs() const
{
- if (!_tempVar.HasValidID()) {
- return {};
+ auto refs = MacroSegment::GetTempVarRefs();
+ if (_tempVar.HasValidID()) {
+ refs.push_back(_tempVar);
}
- return {_tempVar};
+ return refs;
}
bool MacroActionVariable::_registered = MacroActionFactory::Register(
diff --git a/lib/macro/macro-condition-edit.cpp b/lib/macro/macro-condition-edit.cpp
index 4ccc098b..85edcf62 100644
--- a/lib/macro/macro-condition-edit.cpp
+++ b/lib/macro/macro-condition-edit.cpp
@@ -126,10 +126,12 @@ MacroConditionEdit::MacroConditionEdit(
_section->AddHeaderWidget(_conditionSelection);
_section->AddHeaderWidget(_headerInfo);
_section->AddHeaderWidget(_dur);
+ _section->AddHeaderWidget(_varMappingToggle);
QVBoxLayout *conditionLayout = new QVBoxLayout;
conditionLayout->setContentsMargins({7, 7, 7, 7});
conditionLayout->addWidget(_section);
+ conditionLayout->addWidget(_outputMappings);
_contentLayout->addLayout(conditionLayout);
QHBoxLayout *mainLayout = new QHBoxLayout;
@@ -204,7 +206,10 @@ void MacroConditionEdit::SetupWidgets(bool basicSetup)
MacroConditionFactory::CreateWidget(id, this, *_entryData);
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
this, SLOT(HeaderInfoChanged(const QString &)));
+ QWidget::connect(widget, SIGNAL(ShowVariableMappings(bool)), this,
+ SLOT(ShowVariableMappings(bool)));
_section->SetContent(widget, (*_entryData)->GetCollapsed());
+ SetupVarMappings((*_entryData).get());
SetFocusPolicyOfWidgets();
_allWidgetsAreSetup = true;
@@ -245,7 +250,10 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
MacroConditionFactory::CreateWidget(id, this, *_entryData);
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
this, SLOT(HeaderInfoChanged(const QString &)));
+ QWidget::connect(widget, SIGNAL(ShowVariableMappings(bool)), this,
+ SLOT(ShowVariableMappings(bool)));
_section->SetContent(widget);
+ SetupVarMappings((*_entryData).get());
_dur->setVisible(MacroConditionFactory::UsesDurationModifier(id));
SetFocusPolicyOfWidgets();
}
diff --git a/lib/macro/macro-condition-tempvar.cpp b/lib/macro/macro-condition-tempvar.cpp
index db7ed2b3..fd6caca5 100644
--- a/lib/macro/macro-condition-tempvar.cpp
+++ b/lib/macro/macro-condition-tempvar.cpp
@@ -8,10 +8,11 @@ const std::string MacroConditionTempVar::id = "temp_var";
std::vector MacroConditionTempVar::GetTempVarRefs() const
{
- if (!_tempVar.HasValidID()) {
- return {};
+ auto refs = MacroSegment::GetTempVarRefs();
+ if (_tempVar.HasValidID()) {
+ refs.push_back(_tempVar);
}
- return {_tempVar};
+ return refs;
}
bool MacroConditionTempVar::_registered = MacroConditionFactory::Register(
diff --git a/lib/macro/macro-segment.cpp b/lib/macro/macro-segment.cpp
index f10907a8..2103bc6e 100644
--- a/lib/macro/macro-segment.cpp
+++ b/lib/macro/macro-segment.cpp
@@ -1,8 +1,10 @@
#include "macro-segment.hpp"
#include "macro.hpp"
#include "mouse-wheel-guard.hpp"
+#include "path-helpers.hpp"
#include "section.hpp"
#include "ui-helpers.hpp"
+#include "variable.hpp"
#include
#include
@@ -15,7 +17,48 @@ namespace advss {
std::vector MacroSegment::GetTempVarRefs() const
{
- return {};
+ std::vector refs;
+ for (const auto &mapping : _varMappings) {
+ if (mapping.tempVar.HasValidID()) {
+ refs.push_back(mapping.tempVar);
+ }
+ }
+ return refs;
+}
+
+void MacroSegment::ApplyVarMappings()
+{
+ auto macro = GetMacro();
+ for (const auto &mapping : _varMappings) {
+ auto var = mapping.variable.lock();
+ if (!var) {
+ continue;
+ }
+ const auto tempVar = mapping.tempVar.GetTempVariable(macro);
+ if (!tempVar) {
+ continue;
+ }
+ const auto value = tempVar->Value();
+ if (!value) {
+ continue;
+ }
+ var->SetValue(*value);
+ }
+}
+
+const std::vector &MacroSegment::GetVarMappings() const
+{
+ return _varMappings;
+}
+
+void MacroSegment::SetVarMappings(const std::vector &mappings)
+{
+ _varMappings = mappings;
+}
+
+std::vector MacroSegment::GetOwnTempVars() const
+{
+ return _tempVariables;
}
MacroSegment::MacroSegment(Macro *m, bool supportsVariableValue)
@@ -24,14 +67,32 @@ MacroSegment::MacroSegment(Macro *m, bool supportsVariableValue)
{
}
+void MacroSegment::SetVarMappingExpanded(bool expanded)
+{
+ _varMappingExpanded = expanded;
+}
+
bool MacroSegment::Save(obs_data_t *obj) const
{
OBSDataAutoRelease data = obs_data_create();
obs_data_set_bool(data, "collapsed", _collapsed);
+ obs_data_set_bool(data, "varMappingExpanded", _varMappingExpanded);
obs_data_set_bool(data, "useCustomLabel", _useCustomLabel);
obs_data_set_string(data, "customLabel", _customLabel.c_str());
obs_data_set_bool(data, "enabled", _enabled);
obs_data_set_int(data, "version", 1);
+
+ OBSDataArrayAutoRelease mappingsArray = obs_data_array_create();
+ for (const auto &mapping : _varMappings) {
+ OBSDataAutoRelease item = obs_data_create();
+ mapping.tempVar.Save(item, GetMacro(), "tempVar");
+ obs_data_set_string(
+ item, "variable",
+ GetWeakVariableName(mapping.variable).c_str());
+ obs_data_array_push_back(mappingsArray, item);
+ }
+ obs_data_set_array(data, "varMappings", mappingsArray);
+
obs_data_set_obj(obj, "segmentSettings", data);
return true;
}
@@ -40,6 +101,7 @@ bool MacroSegment::Load(obs_data_t *obj)
{
OBSDataAutoRelease data = obs_data_get_obj(obj, "segmentSettings");
_collapsed = obs_data_get_bool(data, "collapsed");
+ _varMappingExpanded = obs_data_get_bool(data, "varMappingExpanded");
_useCustomLabel = obs_data_get_bool(data, "useCustomLabel");
_customLabel = obs_data_get_string(data, "customLabel");
obs_data_set_default_bool(data, "enabled", true);
@@ -50,6 +112,20 @@ bool MacroSegment::Load(obs_data_t *obj)
_enabled = obs_data_get_bool(obj, "enabled");
}
+ _varMappings.clear();
+ OBSDataArrayAutoRelease mappingsArray =
+ obs_data_get_array(data, "varMappings");
+ const size_t count = obs_data_array_count(mappingsArray);
+ _varMappings.reserve(count);
+ for (size_t i = 0; i < count; i++) {
+ OBSDataAutoRelease item = obs_data_array_item(mappingsArray, i);
+ VarMapping mapping;
+ mapping.variable = GetWeakVariableByName(
+ obs_data_get_string(item, "variable"));
+ _varMappings.push_back(std::move(mapping));
+ _varMappings.back().tempVar.Load(item, GetMacro(), "tempVar");
+ }
+
ClearAvailableTempvars();
return true;
}
@@ -226,11 +302,38 @@ MacroSegmentEdit::MacroSegmentEdit(QWidget *parent)
_headerInfo(new QLabel()),
_frame(new QWidget),
_contentLayout(new QVBoxLayout),
+ _outputMappings(new TempVarOutputMappingsWidget(this)),
+ _varMappingToggle(new QPushButton(this)),
_noBorderframe(new QFrame),
_borderFrame(new QFrame),
_dropLineAbove(new QFrame),
_dropLineBelow(new QFrame)
{
+ const auto iconPath = QString::fromStdString(GetDataFilePath(
+ "res/images/" + GetThemeTypeName() + "Variable.svg"));
+ _varMappingToggle->setIcon(QIcon(iconPath));
+ _varMappingToggle->setMaximumWidth(22);
+ _varMappingToggle->setFlat(true);
+ _varMappingToggle->setCheckable(true);
+ _varMappingToggle->setVisible(false);
+ _varMappingToggle->setToolTip(obs_module_text(
+ "AdvSceneSwitcher.tempVar.outputMappings.toggle"));
+
+ QWidget::connect(_varMappingToggle, &QPushButton::toggled,
+ _outputMappings,
+ &TempVarOutputMappingsWidget::SetPanelExpanded);
+ QWidget::connect(_varMappingToggle, &QPushButton::toggled, this,
+ [this](bool checked) {
+ if (Data()) {
+ Data()->SetVarMappingExpanded(checked);
+ }
+ });
+ QWidget::connect(_outputMappings,
+ &TempVarOutputMappingsWidget::ExpandableChanged,
+ _varMappingToggle, &QPushButton::setVisible);
+ QWidget::connect(_section, &Section::Collapsed, _outputMappings,
+ &TempVarOutputMappingsWidget::SetSectionCollapsed);
+
_dropLineAbove->setLineWidth(3);
_dropLineAbove->setFixedHeight(11);
_dropLineBelow->setLineWidth(3);
@@ -292,6 +395,21 @@ MacroSegmentEdit::MacroSegmentEdit(QWidget *parent)
_headerInfo->installEventFilter(this);
}
+void MacroSegmentEdit::SetupVarMappings(MacroSegment *segment)
+{
+ _outputMappings->SetSegment(segment);
+ _varMappingToggle->setChecked(segment &&
+ segment->GetVarMappingExpanded());
+}
+
+void MacroSegmentEdit::ShowVariableMappings(bool show)
+{
+ _varMappingToggle->setChecked(show);
+ if (Data()) {
+ Data()->SetVarMappingExpanded(show);
+ }
+}
+
bool MacroSegmentEdit::eventFilter(QObject *obj, QEvent *ev)
{
if (obj == _headerInfo && ev->type() == QEvent::MouseMove) {
diff --git a/lib/macro/macro-segment.hpp b/lib/macro/macro-segment.hpp
index 803379d2..64508951 100644
--- a/lib/macro/macro-segment.hpp
+++ b/lib/macro/macro-segment.hpp
@@ -9,15 +9,23 @@
#include
#include
+#include
#include
#include
#include
+#include
class QLabel;
namespace advss {
class Macro;
+class Variable;
+
+struct VarMapping {
+ TempVariableRef tempVar;
+ std::weak_ptr variable;
+};
class EXPORT MacroSegment : public Lockable {
public:
@@ -28,6 +36,8 @@ public:
int GetIndex() const { return _idx; }
void SetCollapsed(bool collapsed) { _collapsed = collapsed; }
bool GetCollapsed() const { return _collapsed; }
+ void SetVarMappingExpanded(bool expanded);
+ bool GetVarMappingExpanded() const { return _varMappingExpanded; }
void SetUseCustomLabel(bool enable) { _useCustomLabel = enable; }
bool GetUseCustomLabel() const { return _useCustomLabel; }
void SetCustomLabel(const std::string &label) { _customLabel = label; }
@@ -43,6 +53,10 @@ public:
void SetEnabled(bool);
bool Enabled() const;
virtual std::string GetVariableValue() const;
+ void ApplyVarMappings();
+ const std::vector &GetVarMappings() const;
+ void SetVarMappings(const std::vector &mappings);
+ std::vector GetOwnTempVars() const;
protected:
friend bool SupportsVariableValue(MacroSegment *);
@@ -87,6 +101,7 @@ private:
// UI helper
bool _highlight = false;
bool _collapsed = false;
+ bool _varMappingExpanded = false;
bool _enabled = true;
// Custom header labels
@@ -99,6 +114,7 @@ private:
int _variableRefs = 0;
std::string _variableValue;
std::vector _tempVariables;
+ std::vector _varMappings;
friend class Macro;
};
@@ -118,8 +134,11 @@ public:
virtual std::shared_ptr Data() const = 0;
virtual void SetupWidgets(bool basicSetup = false) = 0;
+ void SetupVarMappings(MacroSegment *segment);
+
public slots:
void HeaderInfoChanged(const QString &);
+ void ShowVariableMappings(bool show);
protected slots:
void Collapsed(bool) const;
@@ -134,6 +153,8 @@ protected:
QLabel *_headerInfo;
QWidget *_frame;
QVBoxLayout *_contentLayout;
+ TempVarOutputMappingsWidget *_outputMappings;
+ QPushButton *_varMappingToggle;
bool _allWidgetsAreSetup = false;
private:
diff --git a/lib/macro/macro.cpp b/lib/macro/macro.cpp
index 0e00ab17..2ae9a5c5 100644
--- a/lib/macro/macro.cpp
+++ b/lib/macro/macro.cpp
@@ -113,6 +113,7 @@ static bool checkCondition(const std::shared_ptr &condition)
condition->WithLock([&condition, &conditionMatched]() {
conditionMatched = condition->EvaluateCondition();
});
+ condition->ApplyVarMappings();
const auto endTime = std::chrono::high_resolution_clock::now();
const auto timeSpent = endTime - startTime;
@@ -432,6 +433,7 @@ bool Macro::RunActionsHelper(
action->WithLock([&action, &actionResult]() {
actionResult = action->PerformAction();
});
+ action->ApplyVarMappings();
actionsExecutedSuccessfully =
actionsExecutedSuccessfully && actionResult;
} else {
diff --git a/lib/utils/temp-variable.cpp b/lib/utils/temp-variable.cpp
index f429fa73..afe63255 100644
--- a/lib/utils/temp-variable.cpp
+++ b/lib/utils/temp-variable.cpp
@@ -5,11 +5,20 @@
#include "macro-edit.hpp"
#include "macro-segment.hpp"
#include "plugin-state-helpers.hpp"
+#include "sync-helpers.hpp"
#include "ui-helpers.hpp"
#include "utility.hpp"
+#include "variable.hpp"
-#include
#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
#include
Q_DECLARE_METATYPE(advss::TempVariableRef);
@@ -731,4 +740,293 @@ void NotifyUIAboutTempVarChange(MacroSegment *segment)
segment);
}
+TempVarOutputMappingsWidget::TempVarOutputMappingsWidget(QWidget *parent)
+ : QWidget(parent),
+ _rowsLayout(new QVBoxLayout()),
+ _addButton(new QPushButton(
+ obs_module_text("AdvSceneSwitcher.tempVar.outputMappings.add"),
+ this)),
+ _animation(new QPropertyAnimation(this, "maximumHeight", this))
+{
+ _rowsLayout->setContentsMargins(0, 0, 0, 0);
+ _rowsLayout->setSpacing(2);
+ auto rowsContainer = new QWidget(this);
+ rowsContainer->setLayout(_rowsLayout);
+
+ auto label = new QLabel(
+ obs_module_text("AdvSceneSwitcher.tempVar.outputMappings"),
+ this);
+
+ auto mainLayout = new QVBoxLayout();
+ mainLayout->addWidget(label);
+ mainLayout->addWidget(rowsContainer);
+ mainLayout->addWidget(_addButton);
+ setLayout(mainLayout);
+
+ _animation->setDuration(300);
+ _animation->setEasingCurve(QEasingCurve::InOutQuad);
+ connect(_animation, &QPropertyAnimation::finished, this,
+ &TempVarOutputMappingsWidget::AnimationFinished);
+
+ hide();
+
+ connect(_addButton, &QPushButton::clicked, this,
+ &TempVarOutputMappingsWidget::Add);
+ connect(TempVarSignalManager::Instance(),
+ SIGNAL(SegmentTempVarsChanged(MacroSegment *)), this,
+ SLOT(SegmentTempVarsChanged(MacroSegment *)));
+}
+
+void TempVarOutputMappingsWidget::SetSegment(MacroSegment *segment)
+{
+ _segment = segment;
+ _panelExpanded = false;
+ Rebuild();
+}
+
+void TempVarOutputMappingsWidget::Add()
+{
+ if (!_segment) {
+ return;
+ }
+ auto mappings = _segment->GetVarMappings();
+ mappings.push_back(VarMapping{});
+ {
+ auto lock = LockContext();
+ _segment->SetVarMappings(mappings);
+ }
+ Rebuild();
+}
+
+void TempVarOutputMappingsWidget::Remove(int rowIdx)
+{
+ if (!_segment) {
+ return;
+ }
+ auto mappings = _segment->GetVarMappings();
+ if (rowIdx < 0 || rowIdx >= (int)mappings.size()) {
+ return;
+ }
+ mappings.erase(mappings.begin() + rowIdx);
+ {
+ auto lock = LockContext();
+ _segment->SetVarMappings(mappings);
+ }
+ Rebuild();
+}
+
+void TempVarOutputMappingsWidget::SegmentTempVarsChanged(MacroSegment *segment)
+{
+ if (segment != _segment) {
+ return;
+ }
+ // Re-populate each temp var combobox in case temp vars were added/removed
+ _loading = true;
+ const auto &mappings = _segment->GetVarMappings();
+ for (int i = 0; i < (int)_rows.size(); i++) {
+ auto combo = _rows[i].tempVarCombo;
+ const QSignalBlocker blocker(combo);
+ combo->clear();
+ PopulateTempVarCombo(combo);
+ if (i < (int)mappings.size() &&
+ mappings[i].tempVar.HasValidID()) {
+ QVariant v;
+ v.setValue(mappings[i].tempVar);
+ combo->setCurrentIndex(combo->findData(v));
+ }
+ }
+ _loading = false;
+ UpdateVisibility();
+}
+
+void TempVarOutputMappingsWidget::WriteBackMappings()
+{
+ if (_loading || !_segment) {
+ return;
+ }
+ std::vector mappings;
+ for (const auto &row : _rows) {
+ VarMapping m;
+ const int idx = row.tempVarCombo->currentIndex();
+ if (idx >= 0) {
+ m.tempVar = row.tempVarCombo->itemData(idx)
+ .value();
+ }
+
+ auto item = row.varSelection->GetCurrentItem();
+ if (!item) {
+ continue;
+ }
+
+ m.variable = GetWeakVariableByName(item->Name());
+ mappings.push_back(std::move(m));
+ }
+ auto lock = LockContext();
+ _segment->SetVarMappings(mappings);
+}
+
+void TempVarOutputMappingsWidget::Rebuild()
+{
+ _loading = true;
+
+ // Remove all existing row widgets from layout and delete them
+ for (auto &row : _rows) {
+ _rowsLayout->removeWidget(row.container);
+ delete row.container;
+ }
+ _rows.clear();
+
+ if (!_segment) {
+ _loading = false;
+ UpdateVisibility();
+ return;
+ }
+
+ const auto &mappings = _segment->GetVarMappings();
+ for (int i = 0; i < (int)mappings.size(); i++) {
+ const auto &mapping = mappings[i];
+
+ auto container = new QWidget(this);
+ auto rowLayout = new QHBoxLayout();
+ rowLayout->setContentsMargins(0, 0, 0, 0);
+
+ auto tempVarCombo = new FilterComboBox(
+ container,
+ obs_module_text("AdvSceneSwitcher.tempVar.select"));
+ tempVarCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents);
+ tempVarCombo->setMaximumWidth(350);
+ tempVarCombo->setDuplicatesEnabled(true);
+ PopulateTempVarCombo(tempVarCombo);
+ if (mapping.tempVar.HasValidID()) {
+ QVariant v;
+ v.setValue(mapping.tempVar);
+ tempVarCombo->setCurrentIndex(
+ tempVarCombo->findData(v));
+ }
+
+ auto arrowLabel = new QLabel(container);
+ {
+ QIcon icon;
+ const auto path = (GetThemeTypeName() == "Light")
+ ? "theme:Light/right.svg"
+ : "theme:Dark/right.svg";
+ icon.addFile(QString::fromUtf8(path), QSize(),
+ QIcon::Normal, QIcon::Off);
+ arrowLabel->setPixmap(icon.pixmap(16, 16));
+ }
+
+ auto varSel = new VariableSelection(container);
+ varSel->SetVariable(mapping.variable);
+
+ auto removeBtn = new QToolButton(container);
+ removeBtn->setProperty("themeID", QVariant(QString::fromUtf8(
+ "removeIconSmall")));
+ removeBtn->setProperty(
+ "class", QVariant(QString::fromUtf8("icon-trash")));
+ removeBtn->setToolTip(obs_module_text(
+ "AdvSceneSwitcher.tempVar.outputMappings.remove"));
+
+ rowLayout->addWidget(tempVarCombo, 1);
+ rowLayout->addWidget(arrowLabel);
+ rowLayout->addWidget(varSel, 1);
+ rowLayout->addWidget(removeBtn);
+ container->setLayout(rowLayout);
+
+ _rowsLayout->addWidget(container);
+ _rows.push_back({container, tempVarCombo, varSel});
+
+ const int capturedIdx = i;
+ connect(removeBtn, &QPushButton::clicked, this,
+ [this, capturedIdx]() { Remove(capturedIdx); });
+ connect(tempVarCombo,
+ QOverload::of(&QComboBox::currentIndexChanged),
+ this, &TempVarOutputMappingsWidget::WriteBackMappings);
+ connect(varSel, &VariableSelection::SelectionChanged, this,
+ [this](const QString &) { WriteBackMappings(); });
+ }
+
+ _loading = false;
+ UpdateVisibility();
+}
+
+bool TempVarOutputMappingsWidget::IsExpandable() const
+{
+ return _segment && !_segment->GetOwnTempVars().empty();
+}
+
+void TempVarOutputMappingsWidget::SetPanelExpanded(bool expanded)
+{
+ _panelExpanded = expanded;
+ UpdateHeight();
+}
+
+void TempVarOutputMappingsWidget::SetSectionCollapsed(bool collapsed)
+{
+ _sectionCollapsed = collapsed;
+ UpdateHeight();
+}
+
+void TempVarOutputMappingsWidget::AnimateTo(int targetHeight)
+{
+ if (_animation->state() == QAbstractAnimation::Running) {
+ _animation->stop();
+ }
+
+ if (targetHeight > 0 && !isVisible()) {
+ setMinimumHeight(0);
+ setMaximumHeight(0);
+ show();
+ }
+
+ const int currentMax = maximumHeight();
+ const int currentHeight = (currentMax >= QWIDGETSIZE_MAX) ? height()
+ : currentMax;
+
+ _animationTargetHeight = targetHeight;
+ _animation->setStartValue(currentHeight);
+ _animation->setEndValue(targetHeight);
+ _animation->start();
+}
+
+void TempVarOutputMappingsWidget::AnimationFinished()
+{
+ if (_animationTargetHeight > 0) {
+ setMaximumHeight(QWIDGETSIZE_MAX);
+ } else {
+ hide();
+ setMaximumHeight(QWIDGETSIZE_MAX);
+ }
+}
+
+void TempVarOutputMappingsWidget::UpdateHeight()
+{
+ const bool shouldShow = _panelExpanded && !_sectionCollapsed &&
+ IsExpandable();
+ if (shouldShow) {
+ AnimateTo(sizeHint().height());
+ } else {
+ AnimateTo(0);
+ }
+}
+
+void TempVarOutputMappingsWidget::UpdateVisibility()
+{
+ const bool expandable = IsExpandable();
+ emit ExpandableChanged(expandable);
+ UpdateHeight();
+}
+
+void TempVarOutputMappingsWidget::PopulateTempVarCombo(
+ FilterComboBox *combo) const
+{
+ if (!_segment) {
+ return;
+ }
+ for (const auto &var : _segment->GetOwnTempVars()) {
+ QVariant v;
+ v.setValue(var.GetRef());
+ combo->addItem(QString::fromStdString(var.Name()), v);
+ }
+}
+
} // namespace advss
diff --git a/lib/utils/temp-variable.hpp b/lib/utils/temp-variable.hpp
index 92c1edb2..ab0cc54b 100644
--- a/lib/utils/temp-variable.hpp
+++ b/lib/utils/temp-variable.hpp
@@ -5,11 +5,12 @@
#include
#include
#include
-#include
-#include
-#include
#include
+class QPropertyAnimation;
+class QPushButton;
+class QVBoxLayout;
+
namespace advss {
class Macro;
@@ -17,6 +18,9 @@ class MacroEdit;
class MacroSegment;
class TempVariableRef;
class TempVariableSelection;
+class TempVarOutputMappingsWidget;
+class VariableSelection;
+struct VarMapping;
// TempVariables are variables that are local to a given macro.
// They can be created and used by macro segments.
@@ -127,4 +131,48 @@ private:
void NotifyUIAboutTempVarChange(MacroSegment *);
EXPORT void IncrementTempVarInUseGeneration();
+class ADVSS_EXPORT TempVarOutputMappingsWidget : public QWidget {
+ Q_OBJECT
+
+public:
+ TempVarOutputMappingsWidget(QWidget *parent);
+ void SetSegment(MacroSegment *segment);
+ void SetPanelExpanded(bool expanded);
+ void SetSectionCollapsed(bool collapsed);
+ bool IsExpandable() const;
+
+signals:
+ void ExpandableChanged(bool);
+
+private slots:
+ void Add();
+ void Remove(int rowIdx);
+ void SegmentTempVarsChanged(MacroSegment *segment);
+ void WriteBackMappings();
+ void AnimationFinished();
+
+private:
+ void Rebuild();
+ void UpdateVisibility();
+ void UpdateHeight();
+ void AnimateTo(int targetHeight);
+ void PopulateTempVarCombo(FilterComboBox *combo) const;
+
+ struct MappingRow {
+ QWidget *container;
+ FilterComboBox *tempVarCombo;
+ VariableSelection *varSelection;
+ };
+
+ MacroSegment *_segment = nullptr;
+ QVBoxLayout *_rowsLayout;
+ QPushButton *_addButton;
+ std::vector _rows;
+ bool _loading = false;
+ bool _panelExpanded = false;
+ bool _sectionCollapsed = false;
+ int _animationTargetHeight = 0;
+ QPropertyAnimation *_animation;
+};
+
} // namespace advss
diff --git a/plugins/base/macro-action-filter.cpp b/plugins/base/macro-action-filter.cpp
index 2fd6b66c..4f18f29f 100644
--- a/plugins/base/macro-action-filter.cpp
+++ b/plugins/base/macro-action-filter.cpp
@@ -11,10 +11,11 @@ const std::string MacroActionFilter::id = "filter";
std::vector MacroActionFilter::GetTempVarRefs() const
{
- if (!_tempVar.HasValidID()) {
- return {};
+ auto refs = MacroSegment::GetTempVarRefs();
+ if (_tempVar.HasValidID()) {
+ refs.push_back(_tempVar);
}
- return {_tempVar};
+ return refs;
}
bool MacroActionFilter::_registered = MacroActionFactory::Register(
diff --git a/plugins/base/macro-action-source.cpp b/plugins/base/macro-action-source.cpp
index 1c4c13f0..25fb4943 100644
--- a/plugins/base/macro-action-source.cpp
+++ b/plugins/base/macro-action-source.cpp
@@ -15,10 +15,11 @@ const std::string MacroActionSource::id = "source";
std::vector MacroActionSource::GetTempVarRefs() const
{
- if (!_tempVar.HasValidID()) {
- return {};
+ auto refs = MacroSegment::GetTempVarRefs();
+ if (_tempVar.HasValidID()) {
+ refs.push_back(_tempVar);
}
- return {_tempVar};
+ return refs;
}
bool MacroActionSource::_registered = MacroActionFactory::Register(