mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-03-21 17:34:57 -05:00
1353 lines
35 KiB
C++
1353 lines
35 KiB
C++
#include "advanced-scene-switcher.hpp"
|
|
#include "action-queue.hpp"
|
|
#include "macro-action-edit.hpp"
|
|
#include "macro-condition-edit.hpp"
|
|
#include "macro-export-import-dialog.hpp"
|
|
#include "macro-properties.hpp"
|
|
#include "macro-tree.hpp"
|
|
#include "macro.hpp"
|
|
#include "math-helpers.hpp"
|
|
#include "name-dialog.hpp"
|
|
#include "path-helpers.hpp"
|
|
#include "switcher-data.hpp"
|
|
#include "ui-helpers.hpp"
|
|
#include "utility.hpp"
|
|
#include "version.h"
|
|
|
|
#include <obs-frontend-api.h>
|
|
#include <QColor>
|
|
#include <QGraphicsOpacityEffect>
|
|
#include <QMenu>
|
|
#include <QPropertyAnimation>
|
|
|
|
namespace advss {
|
|
|
|
static QMetaObject::Connection addPulse;
|
|
static QTimer onChangeHighlightTimer;
|
|
|
|
static bool macroNameExists(const std::string &name)
|
|
{
|
|
return !!GetMacroByName(name.c_str());
|
|
}
|
|
|
|
bool AdvSceneSwitcher::AddNewMacro(std::shared_ptr<Macro> &res,
|
|
std::string &name, std::string format)
|
|
{
|
|
QString fmt;
|
|
int i = 1;
|
|
if (format.empty()) {
|
|
fmt = QString(obs_module_text(
|
|
"AdvSceneSwitcher.macroTab.defaultname"));
|
|
} else {
|
|
fmt = QString::fromStdString(format);
|
|
i = 2;
|
|
}
|
|
|
|
QString placeHolderText = fmt.arg(i);
|
|
while ((macroNameExists(placeHolderText.toUtf8().constData()))) {
|
|
placeHolderText = fmt.arg(++i);
|
|
}
|
|
|
|
bool accepted = AdvSSNameDialog::AskForName(
|
|
this, obs_module_text("AdvSceneSwitcher.macroTab.add"),
|
|
obs_module_text("AdvSceneSwitcher.macroTab.name"), name,
|
|
placeHolderText);
|
|
|
|
if (!accepted) {
|
|
return false;
|
|
}
|
|
|
|
if (name.empty()) {
|
|
return false;
|
|
}
|
|
|
|
if (macroNameExists(name)) {
|
|
DisplayMessage(
|
|
obs_module_text("AdvSceneSwitcher.macroTab.exists"));
|
|
return false;
|
|
}
|
|
|
|
res = std::make_shared<Macro>(
|
|
name, GetGlobalMacroProperties()._newMacroRegisterHotkeys);
|
|
return true;
|
|
}
|
|
|
|
void AdvSceneSwitcher::on_macroAdd_clicked()
|
|
{
|
|
std::string name;
|
|
std::shared_ptr<Macro> newMacro;
|
|
if (!AddNewMacro(newMacro, name)) {
|
|
return;
|
|
}
|
|
|
|
ui->macros->Add(newMacro);
|
|
ui->macroAdd->disconnect(addPulse);
|
|
emit MacroAdded(QString::fromStdString(name));
|
|
}
|
|
|
|
void AdvSceneSwitcher::RemoveMacro(std::shared_ptr<Macro> ¯o)
|
|
{
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
|
|
auto name = QString::fromStdString(macro->Name());
|
|
if (macro->IsGroup() && macro->GroupSize() > 0) {
|
|
QString deleteWarning = obs_module_text(
|
|
"AdvSceneSwitcher.macroTab.removeGroupPopup.text");
|
|
if (!DisplayMessage(deleteWarning.arg(name), true)) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
ui->macros->Remove(macro);
|
|
emit MacroRemoved(name);
|
|
}
|
|
|
|
void AdvSceneSwitcher::RemoveSelectedMacros()
|
|
{
|
|
auto macros = GetSelectedMacros();
|
|
if (macros.empty()) {
|
|
return;
|
|
}
|
|
|
|
int macroCount = macros.size();
|
|
if (macroCount == 1) {
|
|
QString deleteWarning = obs_module_text(
|
|
"AdvSceneSwitcher.macroTab.removeSingleMacroPopup.text");
|
|
auto macro = macros.at(0);
|
|
deleteWarning = deleteWarning.arg(
|
|
QString::fromStdString(macro->Name()));
|
|
|
|
if ((!macro->IsGroup() || macro->GroupSize() == 0) &&
|
|
!DisplayMessage(deleteWarning, true)) {
|
|
return;
|
|
}
|
|
|
|
RemoveMacro(macro);
|
|
return;
|
|
}
|
|
|
|
QString deleteWarning = obs_module_text(
|
|
"AdvSceneSwitcher.macroTab.removeMultipleMacrosPopup.text");
|
|
if (!DisplayMessage(deleteWarning.arg(macroCount), true)) {
|
|
return;
|
|
}
|
|
|
|
for (auto ¯o : macros) {
|
|
RemoveMacro(macro);
|
|
}
|
|
}
|
|
|
|
void AdvSceneSwitcher::RenameMacro(std::shared_ptr<Macro> ¯o,
|
|
const QString &name)
|
|
{
|
|
auto oldName = QString::fromStdString(macro->Name());
|
|
{
|
|
auto lock = LockContext();
|
|
macro->SetName(name.toStdString());
|
|
}
|
|
emit MacroRenamed(oldName, name);
|
|
}
|
|
|
|
void AdvSceneSwitcher::on_macroRemove_clicked()
|
|
{
|
|
RemoveSelectedMacros();
|
|
}
|
|
|
|
void AdvSceneSwitcher::on_macroUp_clicked()
|
|
{
|
|
auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
ui->macros->Up(macro);
|
|
}
|
|
|
|
void AdvSceneSwitcher::on_macroDown_clicked()
|
|
{
|
|
auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
ui->macros->Down(macro);
|
|
}
|
|
|
|
static bool newMacroNameValid(const std::string &name)
|
|
{
|
|
if (!macroNameExists(name)) {
|
|
return true;
|
|
}
|
|
DisplayMessage(obs_module_text("AdvSceneSwitcher.macroTab.exists"));
|
|
return false;
|
|
}
|
|
|
|
void AdvSceneSwitcher::RenameSelectedMacro()
|
|
{
|
|
auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
|
|
std::string oldName = macro->Name();
|
|
std::string name;
|
|
if (!AdvSSNameDialog::AskForName(
|
|
this, obs_module_text("AdvSceneSwitcher.windowTitle"),
|
|
obs_module_text("AdvSceneSwitcher.item.newName"), name,
|
|
QString::fromStdString(oldName))) {
|
|
return;
|
|
}
|
|
|
|
if (name.empty() || name == oldName || !newMacroNameValid(name)) {
|
|
return;
|
|
}
|
|
|
|
RenameMacro(macro, QString::fromStdString(name));
|
|
|
|
const QSignalBlocker b(ui->macroName);
|
|
ui->macroName->setText(QString::fromStdString(name));
|
|
}
|
|
|
|
static void addGroupSubitems(std::vector<std::shared_ptr<Macro>> ¯os,
|
|
const std::shared_ptr<Macro> &group)
|
|
{
|
|
std::vector<std::shared_ptr<Macro>> subitems;
|
|
subitems.reserve(group->GroupSize());
|
|
|
|
// Find all subitems
|
|
auto allMacros = GetMacros();
|
|
for (auto it = allMacros.begin(); it < allMacros.end(); it++) {
|
|
if ((*it)->Name() == group->Name()) {
|
|
for (uint32_t i = 1; i <= group->GroupSize(); i++) {
|
|
subitems.emplace_back(*std::next(it, i));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Remove subitems which were already selected to avoid duplicates
|
|
for (const auto &subitem : subitems) {
|
|
auto it = std::find(macros.begin(), macros.end(), subitem);
|
|
if (it == macros.end()) {
|
|
continue;
|
|
}
|
|
macros.erase(it);
|
|
}
|
|
|
|
// Add group subitems
|
|
auto it = std::find(macros.begin(), macros.end(), group);
|
|
if (it == macros.end()) {
|
|
return;
|
|
}
|
|
it = std::next(it);
|
|
macros.insert(it, subitems.begin(), subitems.end());
|
|
}
|
|
|
|
void AdvSceneSwitcher::ExportMacros()
|
|
{
|
|
auto selectedMacros = GetSelectedMacros();
|
|
auto macros = selectedMacros;
|
|
for (const auto ¯o : selectedMacros) {
|
|
if (macro->IsGroup() && macro->GroupSize() > 0) {
|
|
addGroupSubitems(macros, macro);
|
|
}
|
|
}
|
|
|
|
OBSDataAutoRelease data = obs_data_create();
|
|
OBSDataArrayAutoRelease macroArray = obs_data_array_create();
|
|
for (const auto ¯o : macros) {
|
|
OBSDataAutoRelease obj = obs_data_create();
|
|
macro->Save(obj);
|
|
obs_data_array_push_back(macroArray, obj);
|
|
}
|
|
obs_data_set_array(data, "macros", macroArray);
|
|
SaveVariables(data);
|
|
SaveActionQueues(data);
|
|
obs_data_set_string(data, "version", g_GIT_TAG);
|
|
auto json = obs_data_get_json(data);
|
|
QString exportString(json);
|
|
|
|
MacroExportImportDialog::ExportMacros(exportString);
|
|
}
|
|
|
|
static bool
|
|
isValidMacroSegmentIdx(const std::deque<std::shared_ptr<MacroSegment>> &list,
|
|
int idx)
|
|
{
|
|
return (idx > 0 || (unsigned)idx < list.size());
|
|
}
|
|
|
|
void AdvSceneSwitcher::SetupMacroSegmentSelection(MacroSection type, int idx)
|
|
{
|
|
auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
|
|
MacroSegmentList *setList = nullptr, *resetList1 = nullptr,
|
|
*resetList2 = nullptr;
|
|
int *setIdx = nullptr, *resetIdx1 = nullptr, *resetIdx2 = nullptr;
|
|
std::deque<std::shared_ptr<MacroSegment>> segements;
|
|
|
|
switch (type) {
|
|
case AdvSceneSwitcher::MacroSection::CONDITIONS:
|
|
setList = ui->conditionsList;
|
|
setIdx = ¤tConditionIdx;
|
|
segements = {macro->Conditions().begin(),
|
|
macro->Conditions().end()};
|
|
|
|
resetList1 = ui->actionsList;
|
|
resetList2 = ui->elseActionsList;
|
|
resetIdx1 = ¤tActionIdx;
|
|
resetIdx2 = ¤tElseActionIdx;
|
|
break;
|
|
case AdvSceneSwitcher::MacroSection::ACTIONS:
|
|
setList = ui->actionsList;
|
|
setIdx = ¤tActionIdx;
|
|
segements = {macro->Actions().begin(), macro->Actions().end()};
|
|
|
|
resetList1 = ui->conditionsList;
|
|
resetList2 = ui->elseActionsList;
|
|
resetIdx1 = ¤tConditionIdx;
|
|
resetIdx2 = ¤tElseActionIdx;
|
|
break;
|
|
case AdvSceneSwitcher::MacroSection::ELSE_ACTIONS:
|
|
setList = ui->elseActionsList;
|
|
setIdx = ¤tElseActionIdx;
|
|
segements = {macro->ElseActions().begin(),
|
|
macro->ElseActions().end()};
|
|
|
|
resetList1 = ui->actionsList;
|
|
resetList2 = ui->conditionsList;
|
|
resetIdx1 = ¤tActionIdx;
|
|
resetIdx2 = ¤tConditionIdx;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
setList->SetSelection(idx);
|
|
resetList1->SetSelection(-1);
|
|
resetList2->SetSelection(-1);
|
|
if (isValidMacroSegmentIdx(segements, idx)) {
|
|
*setIdx = idx;
|
|
} else {
|
|
*setIdx = -1;
|
|
}
|
|
*resetIdx1 = -1;
|
|
*resetIdx2 = -1;
|
|
|
|
lastInteracted = type;
|
|
HighlightControls();
|
|
}
|
|
|
|
bool AdvSceneSwitcher::ResolveMacroImportNameConflict(
|
|
std::shared_ptr<Macro> ¯o)
|
|
{
|
|
QString errorMesg = obs_module_text(
|
|
"AdvSceneSwitcher.macroTab.import.nameConflict");
|
|
errorMesg = errorMesg.arg(QString::fromStdString(macro->Name()),
|
|
QString::fromStdString(macro->Name()));
|
|
bool continueResolve = DisplayMessage(errorMesg, true);
|
|
if (!continueResolve) {
|
|
return false;
|
|
}
|
|
|
|
QString format = QString::fromStdString(macro->Name()) + " %1";
|
|
int i = 2;
|
|
|
|
QString placeHolderText = format.arg(i);
|
|
while ((macroNameExists(placeHolderText.toUtf8().constData()))) {
|
|
placeHolderText = format.arg(++i);
|
|
}
|
|
|
|
std::string newName;
|
|
bool accepted = AdvSSNameDialog::AskForName(
|
|
this, obs_module_text("AdvSceneSwitcher.macroTab.add"),
|
|
obs_module_text("AdvSceneSwitcher.macroTab.name"), newName,
|
|
placeHolderText);
|
|
|
|
if (!accepted) {
|
|
return false;
|
|
}
|
|
|
|
if (newName.empty()) {
|
|
return false;
|
|
}
|
|
|
|
if (macroNameExists(newName)) {
|
|
DisplayMessage(
|
|
obs_module_text("AdvSceneSwitcher.macroTab.exists"));
|
|
return ResolveMacroImportNameConflict(macro);
|
|
}
|
|
|
|
macro->SetName(newName);
|
|
return true;
|
|
}
|
|
|
|
void AdvSceneSwitcher::ImportMacros()
|
|
{
|
|
QString json;
|
|
if (!MacroExportImportDialog::ImportMacros(json)) {
|
|
return;
|
|
}
|
|
OBSDataAutoRelease data =
|
|
obs_data_create_from_json(json.toStdString().c_str());
|
|
if (!data) {
|
|
DisplayMessage(obs_module_text(
|
|
"AdvSceneSwitcher.macroTab.import.invalid"));
|
|
ImportMacros();
|
|
return;
|
|
}
|
|
ImportVariables(data);
|
|
ImportQueues(data);
|
|
|
|
auto version = obs_data_get_string(data, "version");
|
|
if (strcmp(version, g_GIT_TAG) != 0) {
|
|
blog(LOG_WARNING,
|
|
"importing macros from non matching plugin version \"%s\"",
|
|
version);
|
|
}
|
|
|
|
OBSDataArrayAutoRelease array = obs_data_get_array(data, "macros");
|
|
size_t count = obs_data_array_count(array);
|
|
|
|
int groupSize = 0;
|
|
std::shared_ptr<Macro> group;
|
|
std::vector<std::shared_ptr<Macro>> importedMacros;
|
|
|
|
auto lock = LockContext();
|
|
for (size_t i = 0; i < count; i++) {
|
|
OBSDataAutoRelease array_obj = obs_data_array_item(array, i);
|
|
auto macro = std::make_shared<Macro>();
|
|
macro->Load(array_obj);
|
|
RunPostLoadSteps();
|
|
|
|
if (macroNameExists(macro->Name()) &&
|
|
!ResolveMacroImportNameConflict(macro)) {
|
|
groupSize--;
|
|
continue;
|
|
}
|
|
|
|
importedMacros.emplace_back(macro);
|
|
GetMacros().emplace_back(macro);
|
|
if (groupSize > 0 && !macro->IsGroup()) {
|
|
Macro::PrepareMoveToGroup(group, macro);
|
|
groupSize--;
|
|
}
|
|
|
|
if (macro->IsGroup()) {
|
|
group = macro;
|
|
groupSize = macro->GroupSize();
|
|
// We are not sure if all elements will be added so we
|
|
// have to reset the group size to zero and add elements
|
|
// to the group as they come up.
|
|
macro->ResetGroupSize();
|
|
}
|
|
}
|
|
|
|
for (const auto ¯o : importedMacros) {
|
|
macro->PostLoad();
|
|
}
|
|
RunPostLoadSteps();
|
|
|
|
ui->macros->Reset(GetMacros(),
|
|
GetGlobalMacroProperties()._highlightExecuted);
|
|
}
|
|
|
|
void AdvSceneSwitcher::on_macroName_editingFinished()
|
|
{
|
|
auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
|
|
QString newName = ui->macroName->text();
|
|
QString oldName = QString::fromStdString(macro->Name());
|
|
|
|
if (newName.isEmpty() || newName == oldName ||
|
|
!newMacroNameValid(newName.toStdString())) {
|
|
ui->macroName->setText(oldName);
|
|
return;
|
|
}
|
|
RenameMacro(macro, newName);
|
|
}
|
|
|
|
void AdvSceneSwitcher::on_runMacroInParallel_stateChanged(int value)
|
|
{
|
|
auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
auto lock = LockContext();
|
|
macro->SetRunInParallel(value);
|
|
}
|
|
|
|
void AdvSceneSwitcher::on_runMacroOnChange_stateChanged(int value)
|
|
{
|
|
auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
auto lock = LockContext();
|
|
macro->SetMatchOnChange(value);
|
|
}
|
|
|
|
void AdvSceneSwitcher::PopulateMacroActions(Macro &m, uint32_t afterIdx)
|
|
{
|
|
auto &actions = m.Actions();
|
|
for (; afterIdx < actions.size(); afterIdx++) {
|
|
auto newEntry = new MacroActionEdit(this, &actions[afterIdx],
|
|
actions[afterIdx]->GetId());
|
|
ui->actionsList->Add(newEntry);
|
|
}
|
|
ui->actionsList->SetHelpMsgVisible(actions.size() == 0);
|
|
}
|
|
|
|
void AdvSceneSwitcher::PopulateMacroElseActions(Macro &m, uint32_t afterIdx)
|
|
{
|
|
auto &actions = m.ElseActions();
|
|
for (; afterIdx < actions.size(); afterIdx++) {
|
|
auto newEntry = new MacroActionEdit(this, &actions[afterIdx],
|
|
actions[afterIdx]->GetId());
|
|
ui->elseActionsList->Add(newEntry);
|
|
}
|
|
ui->elseActionsList->SetHelpMsgVisible(actions.size() == 0);
|
|
}
|
|
|
|
void AdvSceneSwitcher::PopulateMacroConditions(Macro &m, uint32_t afterIdx)
|
|
{
|
|
bool root = afterIdx == 0;
|
|
auto &conditions = m.Conditions();
|
|
for (; afterIdx < conditions.size(); afterIdx++) {
|
|
auto newEntry = new MacroConditionEdit(
|
|
this, &conditions[afterIdx],
|
|
conditions[afterIdx]->GetId(), root);
|
|
ui->conditionsList->Add(newEntry);
|
|
root = false;
|
|
}
|
|
ui->conditionsList->SetHelpMsgVisible(conditions.size() == 0);
|
|
}
|
|
|
|
void AdvSceneSwitcher::SetActionData(Macro &m)
|
|
{
|
|
auto &actions = m.Actions();
|
|
for (int idx = 0; idx < ui->actionsList->ContentLayout()->count();
|
|
idx++) {
|
|
auto item = ui->actionsList->ContentLayout()->itemAt(idx);
|
|
if (!item) {
|
|
continue;
|
|
}
|
|
auto widget = static_cast<MacroActionEdit *>(item->widget());
|
|
if (!widget) {
|
|
continue;
|
|
}
|
|
widget->SetEntryData(&*(actions.begin() + idx));
|
|
}
|
|
}
|
|
|
|
void AdvSceneSwitcher::SetElseActionData(Macro &m)
|
|
{
|
|
auto &actions = m.ElseActions();
|
|
for (int idx = 0; idx < ui->elseActionsList->ContentLayout()->count();
|
|
idx++) {
|
|
auto item = ui->elseActionsList->ContentLayout()->itemAt(idx);
|
|
if (!item) {
|
|
continue;
|
|
}
|
|
auto widget = static_cast<MacroActionEdit *>(item->widget());
|
|
if (!widget) {
|
|
continue;
|
|
}
|
|
widget->SetEntryData(&*(actions.begin() + idx));
|
|
}
|
|
}
|
|
|
|
void AdvSceneSwitcher::SetConditionData(Macro &m)
|
|
{
|
|
auto &conditions = m.Conditions();
|
|
for (int idx = 0; idx < ui->conditionsList->ContentLayout()->count();
|
|
idx++) {
|
|
auto item = ui->conditionsList->ContentLayout()->itemAt(idx);
|
|
if (!item) {
|
|
continue;
|
|
}
|
|
auto widget = static_cast<MacroConditionEdit *>(item->widget());
|
|
if (!widget) {
|
|
continue;
|
|
}
|
|
widget->SetEntryData(&*(conditions.begin() + idx));
|
|
}
|
|
}
|
|
|
|
static void maximizeFirstSplitterEntry(QSplitter *splitter)
|
|
{
|
|
QList<int> newSizes;
|
|
newSizes << 999999;
|
|
for (int i = 0; i < splitter->sizes().size() - 1; i++) {
|
|
newSizes << 0;
|
|
}
|
|
splitter->setSizes(newSizes);
|
|
}
|
|
|
|
static void centerSplitterPosition(QSplitter *splitter)
|
|
{
|
|
splitter->setSizes(QList<int>() << 999999 << 999999);
|
|
}
|
|
|
|
void AdvSceneSwitcher::SetEditMacro(Macro &m)
|
|
{
|
|
{
|
|
const QSignalBlocker b1(ui->macroName);
|
|
const QSignalBlocker b2(ui->runMacroInParallel);
|
|
const QSignalBlocker b3(ui->runMacroOnChange);
|
|
ui->macroName->setText(m.Name().c_str());
|
|
ui->runMacroInParallel->setChecked(m.RunInParallel());
|
|
ui->runMacroOnChange->setChecked(m.MatchOnChange());
|
|
}
|
|
ui->conditionsList->Clear();
|
|
ui->actionsList->Clear();
|
|
ui->elseActionsList->Clear();
|
|
|
|
m.ResetUIHelpers();
|
|
|
|
PopulateMacroConditions(m);
|
|
PopulateMacroActions(m);
|
|
PopulateMacroElseActions(m);
|
|
SetMacroEditAreaDisabled(false);
|
|
|
|
currentActionIdx = -1;
|
|
currentElseActionIdx = -1;
|
|
currentConditionIdx = -1;
|
|
HighlightControls();
|
|
|
|
if (m.IsGroup()) {
|
|
SetMacroEditAreaDisabled(true);
|
|
ui->macroName->setEnabled(true);
|
|
centerSplitterPosition(ui->macroActionConditionSplitter);
|
|
maximizeFirstSplitterEntry(ui->macroElseActionSplitter);
|
|
return;
|
|
}
|
|
|
|
if (!m.HasValidSplitterPositions()) {
|
|
centerSplitterPosition(ui->macroActionConditionSplitter);
|
|
maximizeFirstSplitterEntry(ui->macroElseActionSplitter);
|
|
return;
|
|
}
|
|
|
|
ui->macroActionConditionSplitter->setSizes(
|
|
m.GetActionConditionSplitterPosition());
|
|
ui->macroElseActionSplitter->setSizes(
|
|
m.GetElseActionSplitterPosition());
|
|
}
|
|
|
|
void AdvSceneSwitcher::SetMacroEditAreaDisabled(bool disable)
|
|
{
|
|
ui->macroName->setDisabled(disable);
|
|
ui->runMacro->setDisabled(disable);
|
|
ui->runMacroInParallel->setDisabled(disable);
|
|
ui->runMacroOnChange->setDisabled(disable);
|
|
ui->macroActions->setDisabled(disable);
|
|
ui->macroConditions->setDisabled(disable);
|
|
ui->macroActionConditionSplitter->setDisabled(disable);
|
|
}
|
|
|
|
void AdvSceneSwitcher::HighlightAction(int idx, QColor color)
|
|
{
|
|
ui->actionsList->Highlight(idx, color);
|
|
}
|
|
|
|
void AdvSceneSwitcher::HighlightElseAction(int idx, QColor color)
|
|
{
|
|
ui->elseActionsList->Highlight(idx, color);
|
|
}
|
|
|
|
void AdvSceneSwitcher::HighlightCondition(int idx, QColor color)
|
|
{
|
|
ui->conditionsList->Highlight(idx, color);
|
|
}
|
|
|
|
std::shared_ptr<Macro> AdvSceneSwitcher::GetSelectedMacro()
|
|
{
|
|
return ui->macros->GetCurrentMacro();
|
|
}
|
|
|
|
std::vector<std::shared_ptr<Macro>> AdvSceneSwitcher::GetSelectedMacros()
|
|
{
|
|
return ui->macros->GetCurrentMacros();
|
|
}
|
|
|
|
void AdvSceneSwitcher::MacroSelectionAboutToChange()
|
|
{
|
|
if (loading) {
|
|
return;
|
|
}
|
|
|
|
if (!ui->macroName->isEnabled()) { // No macro is selected
|
|
return;
|
|
}
|
|
|
|
auto macro = GetMacroByQString(ui->macroName->text());
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
|
|
macro->SetActionConditionSplitterPosition(
|
|
ui->macroActionConditionSplitter->sizes());
|
|
|
|
auto elsePos = ui->macroElseActionSplitter->sizes();
|
|
// If only conditions are visible maximize the actions to avoid neither
|
|
// actions nor elseActions being visible when the condition <-> action
|
|
// splitter is moved
|
|
if (elsePos[0] == 0 && elsePos[1] == 0) {
|
|
maximizeFirstSplitterEntry(ui->macroElseActionSplitter);
|
|
return;
|
|
}
|
|
macro->SetElseActionSplitterPosition(
|
|
ui->macroElseActionSplitter->sizes());
|
|
}
|
|
|
|
void AdvSceneSwitcher::MacroSelectionChanged()
|
|
{
|
|
if (loading) {
|
|
return;
|
|
}
|
|
|
|
auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
SetMacroEditAreaDisabled(true);
|
|
ui->conditionsList->Clear();
|
|
ui->actionsList->Clear();
|
|
ui->elseActionsList->Clear();
|
|
ui->conditionsList->SetHelpMsgVisible(true);
|
|
ui->actionsList->SetHelpMsgVisible(true);
|
|
ui->elseActionsList->SetHelpMsgVisible(true);
|
|
centerSplitterPosition(ui->macroActionConditionSplitter);
|
|
maximizeFirstSplitterEntry(ui->macroElseActionSplitter);
|
|
return;
|
|
}
|
|
SetEditMacro(*macro);
|
|
obs_frontend_save();
|
|
}
|
|
|
|
void AdvSceneSwitcher::HighlightOnChange()
|
|
{
|
|
if (!GetGlobalMacroProperties()._highlightActions &&
|
|
!GetGlobalMacroProperties()._highlightExecuted) {
|
|
return;
|
|
}
|
|
|
|
auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
|
|
if (macro->OnChangePreventedActionsRecently()) {
|
|
PulseWidget(ui->runMacroOnChange, Qt::yellow, Qt::transparent,
|
|
true);
|
|
}
|
|
}
|
|
|
|
void AdvSceneSwitcher::on_macroProperties_clicked()
|
|
{
|
|
MacroProperties prop = GetGlobalMacroProperties();
|
|
bool accepted = MacroPropertiesDialog::AskForSettings(
|
|
this, prop, GetSelectedMacro().get());
|
|
if (!accepted) {
|
|
return;
|
|
}
|
|
GetGlobalMacroProperties() = prop;
|
|
emit HighlightMacrosChanged(prop._highlightExecuted);
|
|
emit HighlightActionsChanged(prop._highlightActions);
|
|
emit HighlightConditionsChanged(prop._highlightConditions);
|
|
}
|
|
|
|
static void moveControlsToSplitter(QSplitter *splitter, int idx,
|
|
QLayoutItem *item)
|
|
{
|
|
static int splitterHandleWidth = 38;
|
|
auto handle = splitter->handle(idx);
|
|
auto layout = item->layout();
|
|
layout->setContentsMargins(7, 7, 7, 7);
|
|
handle->setLayout(layout);
|
|
splitter->setHandleWidth(splitterHandleWidth);
|
|
splitter->setStyleSheet("QSplitter::handle {background: transparent;}");
|
|
}
|
|
|
|
bool shouldRestoreSplitter(const QList<int> &pos)
|
|
{
|
|
if (pos.size() == 0) {
|
|
return false;
|
|
}
|
|
|
|
for (int i = 0; i < pos.size(); ++i) {
|
|
if (pos[i] == 0) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void AdvSceneSwitcher::SetupMacroTab()
|
|
{
|
|
ui->macroElseActions->installEventFilter(this);
|
|
ui->macros->installEventFilter(this);
|
|
|
|
if (GetMacros().size() == 0 && !switcher->disableHints) {
|
|
addPulse = PulseWidget(ui->macroAdd, QColor(Qt::green));
|
|
}
|
|
ui->macros->Reset(GetMacros(),
|
|
GetGlobalMacroProperties()._highlightExecuted);
|
|
connect(ui->macros, SIGNAL(MacroSelectionAboutToChange()), this,
|
|
SLOT(MacroSelectionAboutToChange()));
|
|
connect(ui->macros, SIGNAL(MacroSelectionChanged()), this,
|
|
SLOT(MacroSelectionChanged()));
|
|
ui->runMacro->SetMacroTree(ui->macros);
|
|
|
|
ui->conditionsList->SetHelpMsg(
|
|
obs_module_text("AdvSceneSwitcher.macroTab.editConditionHelp"));
|
|
connect(ui->conditionsList, &MacroSegmentList::SelectionChanged, this,
|
|
&AdvSceneSwitcher::MacroConditionSelectionChanged);
|
|
connect(ui->conditionsList, &MacroSegmentList::Reorder, this,
|
|
&AdvSceneSwitcher::MacroConditionReorder);
|
|
|
|
ui->actionsList->SetHelpMsg(
|
|
obs_module_text("AdvSceneSwitcher.macroTab.editActionHelp"));
|
|
connect(ui->actionsList, &MacroSegmentList::SelectionChanged, this,
|
|
&AdvSceneSwitcher::MacroActionSelectionChanged);
|
|
connect(ui->actionsList, &MacroSegmentList::Reorder, this,
|
|
&AdvSceneSwitcher::MacroActionReorder);
|
|
|
|
ui->elseActionsList->SetHelpMsg(obs_module_text(
|
|
"AdvSceneSwitcher.macroTab.editElseActionHelp"));
|
|
connect(ui->elseActionsList, &MacroSegmentList::SelectionChanged, this,
|
|
&AdvSceneSwitcher::MacroElseActionSelectionChanged);
|
|
connect(ui->elseActionsList, &MacroSegmentList::Reorder, this,
|
|
&AdvSceneSwitcher::MacroElseActionReorder);
|
|
|
|
ui->macros->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
connect(ui->macros, &QWidget::customContextMenuRequested, this,
|
|
&AdvSceneSwitcher::ShowMacroContextMenu);
|
|
ui->actionsList->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
connect(ui->actionsList, &QWidget::customContextMenuRequested, this,
|
|
&AdvSceneSwitcher::ShowMacroActionsContextMenu);
|
|
ui->elseActionsList->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
connect(ui->elseActionsList, &QWidget::customContextMenuRequested, this,
|
|
&AdvSceneSwitcher::ShowMacroElseActionsContextMenu);
|
|
ui->conditionsList->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
connect(ui->conditionsList, &QWidget::customContextMenuRequested, this,
|
|
&AdvSceneSwitcher::ShowMacroConditionsContextMenu);
|
|
|
|
SetMacroEditAreaDisabled(true);
|
|
ui->macroPriorityWarning->setVisible(
|
|
switcher->functionNamesByPriority[0] != macro_func);
|
|
|
|
onChangeHighlightTimer.setInterval(1500);
|
|
connect(&onChangeHighlightTimer, SIGNAL(timeout()), this,
|
|
SLOT(HighlightOnChange()));
|
|
onChangeHighlightTimer.start();
|
|
|
|
// Move condition controls into splitter handle layout
|
|
moveControlsToSplitter(ui->macroActionConditionSplitter, 1,
|
|
ui->macroConditionsLayout->takeAt(1));
|
|
moveControlsToSplitter(ui->macroElseActionSplitter, 1,
|
|
ui->macroActionsLayout->takeAt(1));
|
|
|
|
// Set action and condition control icons
|
|
const std::string pathPrefix =
|
|
GetDataFilePath("res/images/" + GetThemeTypeName());
|
|
SetButtonIcon(ui->actionTop, (pathPrefix + "DoubleUp.svg").c_str());
|
|
SetButtonIcon(ui->actionBottom,
|
|
(pathPrefix + "DoubleDown.svg").c_str());
|
|
SetButtonIcon(ui->elseActionTop, (pathPrefix + "DoubleUp.svg").c_str());
|
|
SetButtonIcon(ui->elseActionBottom,
|
|
(pathPrefix + "DoubleDown.svg").c_str());
|
|
SetButtonIcon(ui->conditionTop, (pathPrefix + "DoubleUp.svg").c_str());
|
|
SetButtonIcon(ui->conditionBottom,
|
|
(pathPrefix + "DoubleDown.svg").c_str());
|
|
SetButtonIcon(ui->toggleElseActions,
|
|
(pathPrefix + "NotEqual.svg").c_str());
|
|
|
|
// Reserve more space for macro edit area than for the macro list
|
|
ui->macroListMacroEditSplitter->setStretchFactor(0, 1);
|
|
ui->macroListMacroEditSplitter->setStretchFactor(1, 4);
|
|
|
|
centerSplitterPosition(ui->macroActionConditionSplitter);
|
|
maximizeFirstSplitterEntry(ui->macroElseActionSplitter);
|
|
|
|
if (switcher->saveWindowGeo) {
|
|
if (shouldRestoreSplitter(
|
|
switcher->macroListMacroEditSplitterPosition)) {
|
|
ui->macroListMacroEditSplitter->setSizes(
|
|
switcher->macroListMacroEditSplitterPosition);
|
|
}
|
|
}
|
|
}
|
|
|
|
void AdvSceneSwitcher::ShowMacroContextMenu(const QPoint &pos)
|
|
{
|
|
QPoint globalPos = ui->macros->mapToGlobal(pos);
|
|
QMenu menu;
|
|
|
|
menu.addAction(
|
|
obs_module_text("AdvSceneSwitcher.macroTab.contextMenuAdd"),
|
|
this, &AdvSceneSwitcher::on_macroAdd_clicked);
|
|
|
|
auto copy = menu.addAction(
|
|
obs_module_text("AdvSceneSwitcher.macroTab.copy"), this,
|
|
&AdvSceneSwitcher::CopyMacro);
|
|
copy->setEnabled(ui->macros->SingleItemSelected() &&
|
|
!ui->macros->GroupsSelected());
|
|
menu.addSeparator();
|
|
|
|
auto group = menu.addAction(
|
|
obs_module_text("AdvSceneSwitcher.macroTab.group"), ui->macros,
|
|
&MacroTree::GroupSelectedItems);
|
|
group->setDisabled(ui->macros->GroupedItemsSelected() ||
|
|
ui->macros->GroupsSelected() ||
|
|
ui->macros->SelectionEmpty());
|
|
|
|
auto ungroup = menu.addAction(
|
|
obs_module_text("AdvSceneSwitcher.macroTab.ungroup"),
|
|
ui->macros, &MacroTree::UngroupSelectedGroups);
|
|
ungroup->setEnabled(ui->macros->GroupsSelected());
|
|
menu.addSeparator();
|
|
|
|
auto rename = menu.addAction(
|
|
obs_module_text("AdvSceneSwitcher.macroTab.rename"), this,
|
|
&AdvSceneSwitcher::RenameSelectedMacro);
|
|
rename->setEnabled(ui->macros->SingleItemSelected());
|
|
|
|
auto remove = menu.addAction(
|
|
obs_module_text("AdvSceneSwitcher.macroTab.remove"), this,
|
|
&AdvSceneSwitcher::on_macroRemove_clicked);
|
|
remove->setDisabled(ui->macros->SelectionEmpty());
|
|
menu.addSeparator();
|
|
|
|
auto exportAction = menu.addAction(
|
|
obs_module_text("AdvSceneSwitcher.macroTab.export"), this,
|
|
&AdvSceneSwitcher::ExportMacros);
|
|
exportAction->setDisabled(ui->macros->SelectionEmpty());
|
|
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.import"),
|
|
this, &AdvSceneSwitcher::ImportMacros);
|
|
|
|
menu.exec(globalPos);
|
|
}
|
|
|
|
static void setupConextMenu(AdvSceneSwitcher *ss, const QPoint &pos,
|
|
std::function<void(AdvSceneSwitcher *)> expand,
|
|
std::function<void(AdvSceneSwitcher *)> collapse,
|
|
std::function<void(AdvSceneSwitcher *)> maximize,
|
|
std::function<void(AdvSceneSwitcher *)> minimize)
|
|
{
|
|
QMenu menu;
|
|
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.expandAll"),
|
|
ss, [ss, expand]() { expand(ss); });
|
|
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.collapseAll"),
|
|
ss, [ss, collapse]() { collapse(ss); });
|
|
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.maximize"),
|
|
ss, [ss, maximize]() { maximize(ss); });
|
|
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.minimize"),
|
|
ss, [ss, minimize]() { minimize(ss); });
|
|
menu.exec(pos);
|
|
}
|
|
|
|
void AdvSceneSwitcher::ShowMacroActionsContextMenu(const QPoint &pos)
|
|
{
|
|
setupConextMenu(this, ui->actionsList->mapToGlobal(pos),
|
|
&AdvSceneSwitcher::ExpandAllActions,
|
|
&AdvSceneSwitcher::CollapseAllActions,
|
|
&AdvSceneSwitcher::MaximizeActions,
|
|
&AdvSceneSwitcher::MinimizeActions);
|
|
}
|
|
|
|
void AdvSceneSwitcher::ShowMacroElseActionsContextMenu(const QPoint &pos)
|
|
{
|
|
setupConextMenu(this, ui->elseActionsList->mapToGlobal(pos),
|
|
&AdvSceneSwitcher::ExpandAllElseActions,
|
|
&AdvSceneSwitcher::CollapseAllElseActions,
|
|
&AdvSceneSwitcher::MaximizeElseActions,
|
|
&AdvSceneSwitcher::MinimizeElseActions);
|
|
}
|
|
|
|
void AdvSceneSwitcher::ShowMacroConditionsContextMenu(const QPoint &pos)
|
|
{
|
|
setupConextMenu(this, ui->conditionsList->mapToGlobal(pos),
|
|
&AdvSceneSwitcher::ExpandAllConditions,
|
|
&AdvSceneSwitcher::CollapseAllConditions,
|
|
&AdvSceneSwitcher::MaximizeConditions,
|
|
&AdvSceneSwitcher::MinimizeConditions);
|
|
}
|
|
|
|
void AdvSceneSwitcher::CopyMacro()
|
|
{
|
|
const auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
|
|
std::string format = macro->Name() + " %1";
|
|
std::string name;
|
|
std::shared_ptr<Macro> newMacro;
|
|
if (!AddNewMacro(newMacro, name, format)) {
|
|
return;
|
|
}
|
|
|
|
OBSDataAutoRelease data = obs_data_create();
|
|
macro->Save(data);
|
|
newMacro->Load(data);
|
|
newMacro->PostLoad();
|
|
newMacro->SetName(name);
|
|
RunPostLoadSteps();
|
|
Macro::PrepareMoveToGroup(macro->Parent(), newMacro);
|
|
|
|
ui->macros->Add(newMacro, macro);
|
|
ui->macroAdd->disconnect(addPulse);
|
|
emit MacroAdded(QString::fromStdString(name));
|
|
}
|
|
|
|
void setCollapsedHelper(const std::shared_ptr<Macro> &m, MacroSegmentList *list,
|
|
bool collapsed)
|
|
{
|
|
if (!m) {
|
|
return;
|
|
}
|
|
list->SetCollapsed(collapsed);
|
|
}
|
|
|
|
void AdvSceneSwitcher::ExpandAllActions()
|
|
{
|
|
setCollapsedHelper(GetSelectedMacro(), ui->actionsList, false);
|
|
}
|
|
|
|
void AdvSceneSwitcher::ExpandAllElseActions()
|
|
{
|
|
setCollapsedHelper(GetSelectedMacro(), ui->elseActionsList, false);
|
|
}
|
|
|
|
void AdvSceneSwitcher::ExpandAllConditions()
|
|
{
|
|
setCollapsedHelper(GetSelectedMacro(), ui->conditionsList, false);
|
|
}
|
|
|
|
void AdvSceneSwitcher::CollapseAllActions()
|
|
{
|
|
setCollapsedHelper(GetSelectedMacro(), ui->actionsList, true);
|
|
}
|
|
|
|
void AdvSceneSwitcher::CollapseAllElseActions()
|
|
{
|
|
setCollapsedHelper(GetSelectedMacro(), ui->elseActionsList, true);
|
|
}
|
|
|
|
void AdvSceneSwitcher::CollapseAllConditions()
|
|
{
|
|
setCollapsedHelper(GetSelectedMacro(), ui->conditionsList, true);
|
|
}
|
|
|
|
static void reduceSizeOfSplitterIdx(QSplitter *splitter, int idx)
|
|
{
|
|
auto sizes = splitter->sizes();
|
|
int sum = sizes[0] + sizes[1];
|
|
int reducedSize = sum / 10;
|
|
sizes[idx] = reducedSize;
|
|
sizes[(idx + 1) % 2] = sum - reducedSize;
|
|
splitter->setSizes(sizes);
|
|
}
|
|
|
|
void AdvSceneSwitcher::MinimizeActions()
|
|
{
|
|
auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
if (macro->ElseActions().size() == 0) {
|
|
reduceSizeOfSplitterIdx(ui->macroActionConditionSplitter, 1);
|
|
} else {
|
|
maximizeFirstSplitterEntry(ui->macroElseActionSplitter);
|
|
reduceSizeOfSplitterIdx(ui->macroActionConditionSplitter, 1);
|
|
}
|
|
}
|
|
|
|
void AdvSceneSwitcher::MaximizeActions()
|
|
{
|
|
MinimizeElseActions();
|
|
MinimizeConditions();
|
|
}
|
|
|
|
void AdvSceneSwitcher::MinimizeElseActions()
|
|
{
|
|
auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
if (macro->ElseActions().size() == 0) {
|
|
maximizeFirstSplitterEntry(ui->macroElseActionSplitter);
|
|
} else {
|
|
reduceSizeOfSplitterIdx(ui->macroElseActionSplitter, 1);
|
|
}
|
|
}
|
|
|
|
void AdvSceneSwitcher::MaximizeElseActions()
|
|
{
|
|
MinimizeConditions();
|
|
reduceSizeOfSplitterIdx(ui->macroElseActionSplitter, 0);
|
|
}
|
|
|
|
void AdvSceneSwitcher::MinimizeConditions()
|
|
{
|
|
reduceSizeOfSplitterIdx(ui->macroActionConditionSplitter, 0);
|
|
}
|
|
|
|
void AdvSceneSwitcher::MaximizeConditions()
|
|
{
|
|
MinimizeElseActions();
|
|
MinimizeActions();
|
|
}
|
|
|
|
void AdvSceneSwitcher::on_toggleElseActions_clicked()
|
|
{
|
|
auto elsePosition = ui->macroElseActionSplitter->sizes();
|
|
if (elsePosition[1] == 0) {
|
|
centerSplitterPosition(ui->macroElseActionSplitter);
|
|
return;
|
|
}
|
|
|
|
maximizeFirstSplitterEntry(ui->macroElseActionSplitter);
|
|
}
|
|
|
|
void AdvSceneSwitcher::SetElseActionsStateToHidden()
|
|
{
|
|
ui->toggleElseActions->setToolTip(obs_module_text(
|
|
"AdvSceneSwitcher.macroTab.toggleElseActions.show.tooltip"));
|
|
ui->toggleElseActions->setChecked(false);
|
|
}
|
|
|
|
void AdvSceneSwitcher::SetElseActionsStateToVisible()
|
|
{
|
|
ui->toggleElseActions->setToolTip(obs_module_text(
|
|
"AdvSceneSwitcher.macroTab.toggleElseActions.hide.tooltip"));
|
|
ui->toggleElseActions->setChecked(true);
|
|
}
|
|
|
|
bool AdvSceneSwitcher::MacroTabIsInFocus()
|
|
{
|
|
return isActiveWindow() && isAncestorOf(focusWidget()) &&
|
|
(ui->tabWidget->currentWidget()->objectName() == "macroTab");
|
|
}
|
|
|
|
void AdvSceneSwitcher::UpMacroSegementHotkey()
|
|
{
|
|
if (!MacroTabIsInFocus()) {
|
|
return;
|
|
}
|
|
|
|
auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
int actionSize = macro->Actions().size();
|
|
int conditionSize = macro->Conditions().size();
|
|
|
|
if (currentActionIdx == -1 && currentConditionIdx == -1) {
|
|
if (lastInteracted == MacroSection::CONDITIONS) {
|
|
if (conditionSize == 0) {
|
|
MacroActionSelectionChanged(0);
|
|
} else {
|
|
MacroConditionSelectionChanged(0);
|
|
}
|
|
} else {
|
|
if (actionSize == 0) {
|
|
MacroConditionSelectionChanged(0);
|
|
} else {
|
|
MacroActionSelectionChanged(0);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (currentActionIdx > 0) {
|
|
MacroActionSelectionChanged(currentActionIdx - 1);
|
|
return;
|
|
}
|
|
if (currentConditionIdx > 0) {
|
|
MacroConditionSelectionChanged(currentConditionIdx - 1);
|
|
return;
|
|
}
|
|
if (currentActionIdx == 0) {
|
|
if (conditionSize == 0) {
|
|
MacroActionSelectionChanged(actionSize - 1);
|
|
} else {
|
|
MacroConditionSelectionChanged(conditionSize - 1);
|
|
}
|
|
return;
|
|
}
|
|
if (currentConditionIdx == 0) {
|
|
if (actionSize == 0) {
|
|
MacroConditionSelectionChanged(conditionSize - 1);
|
|
} else {
|
|
MacroActionSelectionChanged(actionSize - 1);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
void AdvSceneSwitcher::DownMacroSegementHotkey()
|
|
{
|
|
if (!MacroTabIsInFocus()) {
|
|
return;
|
|
}
|
|
|
|
auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
int actionSize = macro->Actions().size();
|
|
int conditionSize = macro->Conditions().size();
|
|
|
|
if (currentActionIdx == -1 && currentConditionIdx == -1) {
|
|
if (lastInteracted == MacroSection::CONDITIONS) {
|
|
if (conditionSize == 0) {
|
|
MacroActionSelectionChanged(0);
|
|
} else {
|
|
MacroConditionSelectionChanged(0);
|
|
}
|
|
} else {
|
|
if (actionSize == 0) {
|
|
MacroConditionSelectionChanged(0);
|
|
} else {
|
|
MacroActionSelectionChanged(0);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (currentActionIdx < actionSize - 1) {
|
|
MacroActionSelectionChanged(currentActionIdx + 1);
|
|
return;
|
|
}
|
|
if (currentConditionIdx < conditionSize - 1) {
|
|
MacroConditionSelectionChanged(currentConditionIdx + 1);
|
|
return;
|
|
}
|
|
if (currentActionIdx == actionSize - 1) {
|
|
if (conditionSize == 0) {
|
|
MacroActionSelectionChanged(0);
|
|
} else {
|
|
MacroConditionSelectionChanged(0);
|
|
}
|
|
return;
|
|
}
|
|
if (currentConditionIdx == conditionSize - 1) {
|
|
if (actionSize == 0) {
|
|
MacroConditionSelectionChanged(0);
|
|
} else {
|
|
MacroActionSelectionChanged(0);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
void AdvSceneSwitcher::DeleteMacroSegementHotkey()
|
|
{
|
|
if (!MacroTabIsInFocus()) {
|
|
return;
|
|
}
|
|
|
|
if (currentActionIdx != -1) {
|
|
RemoveMacroAction(currentActionIdx);
|
|
} else if (currentConditionIdx != -1) {
|
|
RemoveMacroCondition(currentConditionIdx);
|
|
}
|
|
}
|
|
|
|
static void fade(QWidget *widget, bool fadeOut)
|
|
{
|
|
const double fadeOutOpacity = 0.3;
|
|
// Don't use exactly 1.0 as for some reason this causes buttons in
|
|
// macroSplitter handle layout to not be redrawn unless mousing over
|
|
// them
|
|
const double fadeInOpacity = 0.99;
|
|
auto curEffect = widget->graphicsEffect();
|
|
if (curEffect) {
|
|
auto curOpacity =
|
|
dynamic_cast<QGraphicsOpacityEffect *>(curEffect);
|
|
if (curOpacity &&
|
|
((fadeOut && DoubleEquals(curOpacity->opacity(),
|
|
fadeOutOpacity, 0.0001)) ||
|
|
(!fadeOut && DoubleEquals(curOpacity->opacity(),
|
|
fadeInOpacity, 0.0001)))) {
|
|
return;
|
|
}
|
|
} else if (!fadeOut) {
|
|
return;
|
|
}
|
|
delete curEffect;
|
|
QGraphicsOpacityEffect *opacityEffect = new QGraphicsOpacityEffect();
|
|
widget->setGraphicsEffect(opacityEffect);
|
|
QPropertyAnimation *animation =
|
|
new QPropertyAnimation(opacityEffect, "opacity");
|
|
animation->setDuration(350);
|
|
animation->setStartValue(fadeOut ? fadeInOpacity : fadeOutOpacity);
|
|
animation->setEndValue(fadeOut ? fadeOutOpacity : fadeInOpacity);
|
|
animation->setEasingCurve(QEasingCurve::OutQuint);
|
|
animation->start(QPropertyAnimation::DeleteWhenStopped);
|
|
}
|
|
|
|
void AdvSceneSwitcher::FadeOutActionControls()
|
|
{
|
|
fade(ui->actionAdd, true);
|
|
fade(ui->actionRemove, true);
|
|
fade(ui->actionTop, true);
|
|
fade(ui->actionUp, true);
|
|
fade(ui->actionDown, true);
|
|
fade(ui->actionBottom, true);
|
|
}
|
|
|
|
void AdvSceneSwitcher::FadeOutConditionControls()
|
|
{
|
|
fade(ui->conditionAdd, true);
|
|
fade(ui->conditionRemove, true);
|
|
fade(ui->conditionTop, true);
|
|
fade(ui->conditionUp, true);
|
|
fade(ui->conditionDown, true);
|
|
fade(ui->conditionBottom, true);
|
|
}
|
|
|
|
void AdvSceneSwitcher::ResetOpacityActionControls()
|
|
{
|
|
fade(ui->actionAdd, false);
|
|
fade(ui->actionRemove, false);
|
|
fade(ui->actionTop, false);
|
|
fade(ui->actionUp, false);
|
|
fade(ui->actionDown, false);
|
|
fade(ui->actionBottom, false);
|
|
}
|
|
|
|
void AdvSceneSwitcher::ResetOpacityConditionControls()
|
|
{
|
|
fade(ui->conditionAdd, false);
|
|
fade(ui->conditionRemove, false);
|
|
fade(ui->conditionTop, false);
|
|
fade(ui->conditionUp, false);
|
|
fade(ui->conditionDown, false);
|
|
fade(ui->conditionBottom, false);
|
|
}
|
|
|
|
void AdvSceneSwitcher::HighlightControls()
|
|
{
|
|
if ((currentActionIdx == -1 && currentConditionIdx == -1) ||
|
|
(currentActionIdx != -1 && currentConditionIdx != -1)) {
|
|
ResetOpacityActionControls();
|
|
ResetOpacityConditionControls();
|
|
} else if (currentActionIdx != -1) {
|
|
FadeOutConditionControls();
|
|
ResetOpacityActionControls();
|
|
} else {
|
|
FadeOutActionControls();
|
|
ResetOpacityConditionControls();
|
|
}
|
|
}
|
|
|
|
} // namespace advss
|