diff --git a/data/locale/de-DE.ini b/data/locale/de-DE.ini index a31c0867..3812d4a9 100644 --- a/data/locale/de-DE.ini +++ b/data/locale/de-DE.ini @@ -99,7 +99,6 @@ AdvSceneSwitcher.macroList.deleted="gelöscht" AdvSceneSwitcher.macroList.duplicate="\"%1\" ist bereits ausgewählt!" ; Macro Logic -AdvSceneSwitcher.logic.none="Eintrag ignorieren" AdvSceneSwitcher.logic.and="Und" AdvSceneSwitcher.logic.or="Oder" AdvSceneSwitcher.logic.andNot="Und nicht" diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 1c58b335..96b8b4ab 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -306,7 +306,6 @@ AdvSceneSwitcher.macroList.deleted="deleted" AdvSceneSwitcher.macroList.duplicate="\"%1\" is alreay selected!" # Macro Logic -AdvSceneSwitcher.logic.none="Ignore entry" AdvSceneSwitcher.logic.and="And" AdvSceneSwitcher.logic.or="Or" AdvSceneSwitcher.logic.andNot="And not" @@ -1076,8 +1075,8 @@ AdvSceneSwitcher.action.macro.type.runActions="Run macro actions" AdvSceneSwitcher.action.macro.type.run.conditions.ignore="Do not consider condition state" AdvSceneSwitcher.action.macro.type.run.conditions.true="Only if conditions evaluate to true" AdvSceneSwitcher.action.macro.type.run.conditions.false="Only if conditions evaluate to false" -AdvSceneSwitcher.action.macro.type.run.updateConditionMatchState="Reevaluate the condition state before executing this action" -AdvSceneSwitcher.action.macro.type.run.updateConditionMatchState.help="The plugin operates in phases:\n * The phase evaluating the macro conditions\n * The phase running macro actions\nMacros executed before this particular action might have side effects on the condition state of macros.\nCheck this option if you want those side effects to be taken into account when evaluating the condition state." +AdvSceneSwitcher.action.macro.type.run.updateConditionMatchState="Check conditions now, even if macro is paused" +AdvSceneSwitcher.action.macro.type.run.updateConditionMatchState.help="The plugin operates in phases:\n * The phase evaluating the macro conditions\n * The phase running macro actions\nMacros executed before this particular action might have side effects on the condition state of macros.\nAdditionally, paused macros are assumed to not match their conditions.\nCheck this option to force a fresh condition evaluation before running this action, regardless of whether the macro is paused." AdvSceneSwitcher.action.macro.type.run.actionType.regular="actions" AdvSceneSwitcher.action.macro.type.run.actionType.else="else-actions" AdvSceneSwitcher.action.macro.type.run.skipWhenPaused="Skip execution when macro is paused" diff --git a/data/locale/es-ES.ini b/data/locale/es-ES.ini index c1516c19..d7d7a49f 100644 --- a/data/locale/es-ES.ini +++ b/data/locale/es-ES.ini @@ -83,7 +83,6 @@ AdvSceneSwitcher.macroTab.highlightTrueConditions="Resaltar condiciones de la ma AdvSceneSwitcher.macroTab.highlightPerformedActions="Resaltar acciones realizadas recientemente de la macro seleccionada actualmente" ; Lógica de macros -AdvSceneSwitcher.logic.none="Omitir entrada" AdvSceneSwitcher.logic.and="Y" AdvSceneSwitcher.logic.or="O" AdvSceneSwitcher.logic.andNot="Y no" diff --git a/data/locale/fr-FR.ini b/data/locale/fr-FR.ini index 21173201..9973533b 100644 --- a/data/locale/fr-FR.ini +++ b/data/locale/fr-FR.ini @@ -131,7 +131,6 @@ AdvSceneSwitcher.macroList.deleted="supprimé" AdvSceneSwitcher.macroList.duplicate="\"%1\" est déjà sélectionné !" ; Macro Logic -AdvSceneSwitcher.logic.none="Ignorer l'entrée" AdvSceneSwitcher.logic.and="Et" AdvSceneSwitcher.logic.or="Ou" AdvSceneSwitcher.logic.andNot="Et pas" diff --git a/data/locale/ja-JP.ini b/data/locale/ja-JP.ini index 23444e06..5fc8c5eb 100644 --- a/data/locale/ja-JP.ini +++ b/data/locale/ja-JP.ini @@ -275,7 +275,6 @@ AdvSceneSwitcher.macroList.deleted="削除" AdvSceneSwitcher.macroList.duplicate="\"%1\" はすでに選択されています!" # Macro Logic -AdvSceneSwitcher.logic.none="入力無視" ; AdvSceneSwitcher.logic.and="And" ; AdvSceneSwitcher.logic.or="Or" ; AdvSceneSwitcher.logic.andNot="And not" diff --git a/data/locale/pt-BR.ini b/data/locale/pt-BR.ini index 38fe61b3..21476e55 100644 --- a/data/locale/pt-BR.ini +++ b/data/locale/pt-BR.ini @@ -239,7 +239,6 @@ AdvSceneSwitcher.macroList.deleted="excluída" AdvSceneSwitcher.macroList.duplicate="\"%1\" já está selecionada!" ; Macro Logic -AdvSceneSwitcher.logic.none="Ignorar entrada" AdvSceneSwitcher.logic.and="E" AdvSceneSwitcher.logic.or="Ou" AdvSceneSwitcher.logic.andNot="E não" diff --git a/data/locale/ru-RU.ini b/data/locale/ru-RU.ini index d1425056..18ace96f 100644 --- a/data/locale/ru-RU.ini +++ b/data/locale/ru-RU.ini @@ -70,7 +70,6 @@ AdvSceneSwitcher.macroTab.name="Имя:" AdvSceneSwitcher.macroTab.defaultname="Макрос %1" AdvSceneSwitcher.macroTab.copy="Создать копию" ; Macro Logic -AdvSceneSwitcher.logic.none="Игнорировать вход" AdvSceneSwitcher.logic.and="И" AdvSceneSwitcher.logic.or="Или" AdvSceneSwitcher.logic.andNot="И не" diff --git a/data/locale/tr-TR.ini b/data/locale/tr-TR.ini index 9d7a3743..fd1310ea 100644 --- a/data/locale/tr-TR.ini +++ b/data/locale/tr-TR.ini @@ -78,7 +78,6 @@ AdvSceneSwitcher.macroTab.expandAll="Hepsini Genişlet" AdvSceneSwitcher.macroTab.collapseAll="Hepsini Küçült" ; Macro Logic -AdvSceneSwitcher.logic.none="Girişi yoksay" AdvSceneSwitcher.logic.and="Ve" AdvSceneSwitcher.logic.or="Ya da" AdvSceneSwitcher.logic.andNot="ve değil" diff --git a/data/locale/zh-CN.ini b/data/locale/zh-CN.ini index ee2b7183..83fc970c 100644 --- a/data/locale/zh-CN.ini +++ b/data/locale/zh-CN.ini @@ -259,7 +259,6 @@ AdvSceneSwitcher.macroList.deleted="删除" AdvSceneSwitcher.macroList.duplicate="\"%1\" 已选择!" ; Macro Logic -AdvSceneSwitcher.logic.none="忽略条件" AdvSceneSwitcher.logic.and="且" AdvSceneSwitcher.logic.or="或" AdvSceneSwitcher.logic.andNot="且不" diff --git a/lib/advanced-scene-switcher.cpp b/lib/advanced-scene-switcher.cpp index f800406d..5279d020 100644 --- a/lib/advanced-scene-switcher.cpp +++ b/lib/advanced-scene-switcher.cpp @@ -506,6 +506,8 @@ bool SwitcherData::AnySceneTransitionStarted() ******************************************************************************/ extern "C" EXPORT void FreeSceneSwitcher() { + switcher->Stop(); + PlatformCleanup(); RunPluginCleanupSteps(); diff --git a/lib/macro/macro-action-macro.cpp b/lib/macro/macro-action-macro.cpp index 725921db..164e897f 100644 --- a/lib/macro/macro-action-macro.cpp +++ b/lib/macro/macro-action-macro.cpp @@ -871,6 +871,8 @@ void MacroActionMacroEdit::SetWidgetVisibility() } else { _noConditionsWarning->setVisible(false); } + _runMacroHelp->setVisible(action == + MacroActionMacro::Action::RUN_MACRO); _nestedMacro->setVisible(action == MacroActionMacro::Action::NESTED_MACRO); diff --git a/lib/macro/macro-condition-edit.cpp b/lib/macro/macro-condition-edit.cpp index 85edcf62..fef70ad6 100644 --- a/lib/macro/macro-condition-edit.cpp +++ b/lib/macro/macro-condition-edit.cpp @@ -5,6 +5,7 @@ #include "path-helpers.hpp" #include "plugin-state-helpers.hpp" #include "section.hpp" +#include "switch-button.hpp" #include "ui-helpers.hpp" #include "utility.hpp" @@ -102,12 +103,15 @@ MacroConditionEdit::MacroConditionEdit( QWidget *parent, std::shared_ptr *entryData, bool isRootCondition) : MacroSegmentEdit(parent), + _enable(new SwitchButton()), _logicSelection(new QComboBox()), _conditionSelection(new FilterComboBox()), _dur(new DurationModifierEdit()), _entryData(entryData), _isRoot(isRootCondition) { + QWidget::connect(_enable, SIGNAL(checked(bool)), this, + SLOT(ConditionEnableChanged(bool))); QWidget::connect(_logicSelection, SIGNAL(currentIndexChanged(int)), this, SLOT(LogicSelectionChanged(int))); QWidget::connect(_conditionSelection, @@ -122,6 +126,7 @@ MacroConditionEdit::MacroConditionEdit( Logic::PopulateLogicTypeSelection(_logicSelection, isRootCondition); populateConditionSelection(_conditionSelection); + _section->AddHeaderWidget(_enable); _section->AddHeaderWidget(_logicSelection); _section->AddHeaderWidget(_conditionSelection); _section->AddHeaderWidget(_headerInfo); @@ -154,8 +159,17 @@ void MacroConditionEdit::LogicSelectionChanged(int idx) const auto logic = static_cast( _logicSelection->itemData(idx).toInt()); (*_entryData)->SetLogicType(logic); +} - SetEnableAppearance(logic != Logic::Type::NONE); +void MacroConditionEdit::ConditionEnableChanged(bool value) +{ + if (_loading || !_entryData) { + return; + } + + auto lock = LockContext(); + (*_entryData)->SetEnabled(value); + SetDisableEffect(!value); } bool MacroConditionEdit::IsRootNode() const @@ -168,7 +182,9 @@ void MacroConditionEdit::SetLogicSelection() const auto logic = (*_entryData)->GetLogicType(); _logicSelection->setCurrentIndex( _logicSelection->findData(static_cast(logic))); - SetEnableAppearance(logic != Logic::Type::NONE); + const bool enabled = (*_entryData)->Enabled(); + _enable->setChecked(enabled); + SetEnableAppearance(enabled); } void MacroConditionEdit::SetRootNode(bool root) @@ -239,10 +255,12 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text) { auto lock = LockContext(); auto logic = (*_entryData)->GetLogicType(); + const bool enabled = (*_entryData)->Enabled(); _entryData->reset(); *_entryData = MacroConditionFactory::Create(id, macro); (*_entryData)->SetIndex(idx); (*_entryData)->SetLogicType(logic); + (*_entryData)->SetEnabled(enabled); (*_entryData)->PostLoad(); RunAndClearPostLoadSteps(); } diff --git a/lib/macro/macro-condition-edit.hpp b/lib/macro/macro-condition-edit.hpp index b3450518..7c50b885 100644 --- a/lib/macro/macro-condition-edit.hpp +++ b/lib/macro/macro-condition-edit.hpp @@ -8,6 +8,8 @@ namespace advss { +class SwitchButton; + class DurationModifierEdit : public QWidget { Q_OBJECT public: @@ -47,11 +49,13 @@ private slots: void ConditionSelectionChanged(const QString &text); void DurationChanged(const Duration &value); void DurationModifierChanged(DurationModifier::Type m); + void ConditionEnableChanged(bool); private: void SetLogicSelection(); std::shared_ptr Data() const; + SwitchButton *_enable; QComboBox *_logicSelection; FilterComboBox *_conditionSelection; DurationModifierEdit *_dur; diff --git a/lib/macro/macro-condition.cpp b/lib/macro/macro-condition.cpp index f855f405..dc26f9dc 100644 --- a/lib/macro/macro-condition.cpp +++ b/lib/macro/macro-condition.cpp @@ -31,6 +31,10 @@ bool MacroCondition::Load(obs_data_t *obj) { MacroSegment::Load(obj); _logic.Load(obj, "logic"); + if (_logic.GetType() == Logic::Type::NONE) { + SetEnabled(false); + _logic.SetType(Logic::Type::AND); + } _durationModifier.Load(obj); return true; } @@ -50,7 +54,8 @@ void MacroCondition::ValidateLogicSelection(bool isRootCondition, return; } - _logic.SetType(Logic::Type::NONE); + _logic.SetType(Logic::Type::AND); + SetEnabled(false); blog(LOG_WARNING, "setting invalid logic selection to 'ignore' for macro %s", context); diff --git a/lib/macro/macro-segment.cpp b/lib/macro/macro-segment.cpp index 2103bc6e..64d8d89a 100644 --- a/lib/macro/macro-segment.cpp +++ b/lib/macro/macro-segment.cpp @@ -80,7 +80,7 @@ bool MacroSegment::Save(obs_data_t *obj) const 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); + obs_data_set_int(data, "version", 2); OBSDataArrayAutoRelease mappingsArray = obs_data_array_create(); for (const auto &mapping : _varMappings) { @@ -112,6 +112,12 @@ bool MacroSegment::Load(obs_data_t *obj) _enabled = obs_data_get_bool(obj, "enabled"); } + // Reset the previously unused "enabled" value for conditions to "true" + if (obs_data_get_int(data, "version") < 2 && + obs_data_has_user_value(obj, "logic")) { + _enabled = true; + } + _varMappings.clear(); OBSDataArrayAutoRelease mappingsArray = obs_data_get_array(data, "varMappings"); diff --git a/lib/macro/macro-tab.cpp b/lib/macro/macro-tab.cpp index d5aba05b..3a8bfd80 100644 --- a/lib/macro/macro-tab.cpp +++ b/lib/macro/macro-tab.cpp @@ -557,6 +557,10 @@ void AdvSceneSwitcher::HighlightOnChange() const return; } + if (macro->Paused()) { + return; + } + if (macro->ActionTriggerModePreventedActionsSince( lastOnChangeHighlightCheckTime)) { HighlightWidget(ui->actionTriggerMode, Qt::yellow, diff --git a/lib/macro/macro.cpp b/lib/macro/macro.cpp index 55e68c9b..51a0f151 100644 --- a/lib/macro/macro.cpp +++ b/lib/macro/macro.cpp @@ -157,6 +157,15 @@ bool Macro::CheckConditionHelper( return conditionMatched; }; + if (!condition->Enabled()) { + vblog(LOG_INFO, "ignoring condition '%s' for '%s'", + condition->GetId().c_str(), _name.c_str()); + if (!_useShortCircuitEvaluation) { + (void)evaluateCondition(); + } + return _matched; + } + const auto logicType = condition->GetLogicType(); if (logicType == Logic::Type::NONE) { vblog(LOG_INFO, "ignoring condition '%s' for '%s'", @@ -281,7 +290,7 @@ bool Macro::CheckConditions(bool ignorePause) const bool hasActionsToExecute = _matched ? (_actions.size() > 0) : (_elseActions.size() > 0); - if (!_actionModeMatch && hasActionsToExecute) { + if (!_actionModeMatch && hasActionsToExecute && !_paused) { _lastActionRunModePreventTime = std::chrono::high_resolution_clock::now(); } @@ -380,7 +389,7 @@ bool Macro::ShouldRunActions() const !_paused && (_matched || _elseActions.size() > 0) && _actionModeMatch; - if (VerboseLoggingEnabled() && !_actionModeMatch) { + if (VerboseLoggingEnabled() && !_actionModeMatch && !_paused) { if (_matched && _actions.size() > 0) { blog(LOG_INFO, "skip actions for Macro %s (on change)", _name.c_str()); diff --git a/lib/utils/condition-logic.cpp b/lib/utils/condition-logic.cpp index 67deac74..efa915da 100644 --- a/lib/utils/condition-logic.cpp +++ b/lib/utils/condition-logic.cpp @@ -8,7 +8,6 @@ namespace advss { const std::map Logic::localeMap = { - {Logic::Type::NONE, {"AdvSceneSwitcher.logic.none"}}, {Logic::Type::AND, {"AdvSceneSwitcher.logic.and"}}, {Logic::Type::OR, {"AdvSceneSwitcher.logic.or"}}, {Logic::Type::AND_NOT, {"AdvSceneSwitcher.logic.andNot"}}, @@ -67,7 +66,7 @@ void Logic::PopulateLogicTypeSelection(QComboBox *list, bool isRootCondition) return typeValue < rootOffset; }} : std::function{[](int typeValue) { - return typeValue >= rootOffset; + return typeValue > rootOffset; }}; for (const auto &[type, name] : localeMap) { const int typeValue = static_cast(type); diff --git a/lib/utils/plugin-state-helpers.cpp b/lib/utils/plugin-state-helpers.cpp index fa4fce75..75ca49b7 100644 --- a/lib/utils/plugin-state-helpers.cpp +++ b/lib/utils/plugin-state-helpers.cpp @@ -75,6 +75,18 @@ static std::vector> &getStopSteps() return steps; } +static std::vector> &getEarlySaveSteps() +{ + static std::vector> steps; + return steps; +} + +static std::vector> &getEarlyLoadSteps() +{ + static std::vector> steps; + return steps; +} + static std::vector> &getSaveSteps() { static std::vector> steps; @@ -109,6 +121,18 @@ void LoadPluginSettings(obs_data_t *obj) GetSwitcher()->LoadSettings(obj); } +void AddEarlySaveStep(std::function step) +{ + std::lock_guard lock(mutex); + getEarlySaveSteps().emplace_back(step); +} + +void AddEarlyLoadStep(std::function step) +{ + std::lock_guard lock(mutex); + getEarlyLoadSteps().emplace_back(step); +} + void AddSaveStep(std::function step) { std::lock_guard lock(mutex); @@ -136,6 +160,9 @@ void AddIntervalResetStep(std::function step) void RunSaveSteps(obs_data_t *obj) { std::lock_guard lock(mutex); + for (const auto &func : getEarlySaveSteps()) { + func(obj); + } for (const auto &func : getSaveSteps()) { func(obj); } @@ -144,6 +171,9 @@ void RunSaveSteps(obs_data_t *obj) void RunLoadSteps(obs_data_t *obj) { std::lock_guard lock(mutex); + for (const auto &func : getEarlyLoadSteps()) { + func(obj); + } for (const auto &func : getLoadSteps()) { func(obj); } diff --git a/lib/utils/plugin-state-helpers.hpp b/lib/utils/plugin-state-helpers.hpp index 1df274d3..0ee36edc 100644 --- a/lib/utils/plugin-state-helpers.hpp +++ b/lib/utils/plugin-state-helpers.hpp @@ -8,6 +8,8 @@ namespace advss { void SavePluginSettings(obs_data_t *); EXPORT void LoadPluginSettings(obs_data_t *); +void AddEarlySaveStep(std::function); +void AddEarlyLoadStep(std::function); EXPORT void AddSaveStep(std::function); EXPORT void AddLoadStep(std::function); EXPORT void AddPostLoadStep(std::function); diff --git a/lib/variables/variable-tab.cpp b/lib/variables/variable-tab.cpp index 3a4ed292..84f3d534 100644 --- a/lib/variables/variable-tab.cpp +++ b/lib/variables/variable-tab.cpp @@ -63,7 +63,6 @@ static void load(obs_data_t *data) { tabSettings.Load(data, "tabSettings"); dockSettings.Load(data, "dockSettings"); - enableDock(obs_data_get_bool(data, "addVariablesDock")); } diff --git a/lib/variables/variable.cpp b/lib/variables/variable.cpp index 61b3ec8d..9ae25c07 100644 --- a/lib/variables/variable.cpp +++ b/lib/variables/variable.cpp @@ -20,8 +20,8 @@ static std::chrono::high_resolution_clock::time_point lastVariableChange{}; static bool setup() { - AddSaveStep(SaveVariables); - AddLoadStep(LoadVariables); + AddEarlySaveStep(SaveVariables); + AddEarlyLoadStep(LoadVariables); AddPluginCleanupStep([]() { variables.clear(); }); return true; } diff --git a/lib/win/advanced-scene-switcher-win.cpp b/lib/win/advanced-scene-switcher-win.cpp index 2ba00294..530a3c05 100644 --- a/lib/win/advanced-scene-switcher-win.cpp +++ b/lib/win/advanced-scene-switcher-win.cpp @@ -1,10 +1,12 @@ #include "platform-funcs.hpp" +#include "plugin-state-helpers.hpp" #include #include #include #include #include +#include #include #include #include @@ -16,6 +18,9 @@ #include #include +#define ADVSS_WIDEN_(x) L##x +#define ADVSS_WIDEN(x) ADVSS_WIDEN_(x) + namespace advss { #define MAX_SEARCH 1000 @@ -500,9 +505,86 @@ int SecondsSinceLastInput() return (getTime() - getLastInputTime()) / 1000; } +static void addPluginFolderToSymbolPath() +{ + // This runs after OBS_FRONTEND_EVENT_FINISHED_LOADING, which fires after + // obs_load_all_modules() completes. By that point OBS has already called + // reset_win32_symbol_paths() -> SymInitializeW(), so DbgHelp is + // initialized and we can append our plugins subfolder (where the PDB + // files live) to the existing search path. + HMODULE dbghelp = LoadLibraryW(L"DbgHelp"); + if (!dbghelp) { + return; + } + + typedef BOOL(WINAPI * SymGetSearchPathW_t)(HANDLE, PWSTR, DWORD); + typedef BOOL(WINAPI * SymSetSearchPathW_t)(HANDLE, PCWSTR); + typedef BOOL(WINAPI * SymRefreshModuleList_t)(HANDLE); + + auto symGetSearchPathW = reinterpret_cast( + GetProcAddress(dbghelp, "SymGetSearchPathW")); + auto symSetSearchPathW = reinterpret_cast( + GetProcAddress(dbghelp, "SymSetSearchPathW")); + auto symRefreshModuleList = reinterpret_cast( + GetProcAddress(dbghelp, "SymRefreshModuleList")); + + if (!symGetSearchPathW || !symSetSearchPathW || !symRefreshModuleList) { + FreeLibrary(dbghelp); + return; + } + + HMODULE hModule = NULL; + if (!GetModuleHandleExW( + GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + reinterpret_cast(addPluginFolderToSymbolPath), + &hModule)) { + FreeLibrary(dbghelp); + return; + } + + wchar_t dllDir[MAX_PATH]; + if (!GetModuleFileNameW(hModule, dllDir, MAX_PATH)) { + FreeLibrary(dbghelp); + return; + } + + wchar_t *lastSep = wcsrchr(dllDir, L'\\'); + if (!lastSep) { + FreeLibrary(dbghelp); + return; + } + *lastSep = L'\0'; + + wchar_t pluginsPath[MAX_PATH]; + wcsncpy_s(pluginsPath, MAX_PATH, dllDir, _TRUNCATE); + wcsncat_s(pluginsPath, MAX_PATH, L"\\" ADVSS_WIDEN(ADVSS_PLUGIN_FOLDER), + _TRUNCATE); + + constexpr DWORD currentPathLen = 4096; + constexpr DWORD newPathLen = 8192; + auto currentPath = std::make_unique(currentPathLen); + auto newPath = std::make_unique(newPathLen); + + symGetSearchPathW(GetCurrentProcess(), currentPath.get(), + currentPathLen); + + if (currentPath[0] != L'\0') { + _snwprintf_s(newPath.get(), newPathLen, _TRUNCATE, L"%s;%s", + currentPath.get(), pluginsPath); + } else { + wcsncpy_s(newPath.get(), newPathLen, pluginsPath, _TRUNCATE); + } + + symSetSearchPathW(GetCurrentProcess(), newPath.get()); + symRefreshModuleList(GetCurrentProcess()); + FreeLibrary(dbghelp); +} + void PlatformInit() { CoInitialize(NULL); + AddFinishedLoadingStep(addPluginFolderToSymbolPath); } void PlatformCleanup() diff --git a/tests/stubs/plugin-state-helpers.cpp b/tests/stubs/plugin-state-helpers.cpp index eb94fb8b..b037ba56 100644 --- a/tests/stubs/plugin-state-helpers.cpp +++ b/tests/stubs/plugin-state-helpers.cpp @@ -4,6 +4,8 @@ namespace advss { void SavePluginSettings(obs_data_t *) {} void LoadPluginSettings(obs_data_t *) {} +void AddEarlySaveStep(std::function) {} +void AddEarlyLoadStep(std::function) {} void AddSaveStep(std::function) {} void AddLoadStep(std::function) {} void AddPostLoadStep(std::function) {}