mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-09-07 00:56:00 -05:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68c6492c3f | ||
|
|
0ba7ba77d8 | ||
|
|
04b2b3474d | ||
|
|
ecbb5ebbd7 | ||
|
|
b62757b65d | ||
|
|
b1a3ab5493 | ||
|
|
abc3357180 | ||
|
|
29f9cba236 | ||
|
|
9a62522140 |
1
.github/ISSUE_TEMPLATE/bug_report.md
vendored
1
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -22,6 +22,7 @@ A clear and concise description of what you expected to happen.
|
|||||||
|
|
||||||
**Logs**
|
**Logs**
|
||||||
Please provide a log of your issue with verbose logging enabled (See General tab of the plugin).
|
Please provide a log of your issue with verbose logging enabled (See General tab of the plugin).
|
||||||
|
In case of a crash, please also include the corresponding crash log.
|
||||||
See [here](https://obsproject.com/forum/threads/please-post-a-log-with-your-issue-heres-how.23074/) for a description where to find the log files and how to share them.
|
See [here](https://obsproject.com/forum/threads/please-post-a-log-with-your-issue-heres-how.23074/) for a description where to find the log files and how to share them.
|
||||||
Please share the currently used plugin settings by exporting them them to a file (See General tab of the plugin).
|
Please share the currently used plugin settings by exporting them them to a file (See General tab of the plugin).
|
||||||
If applicable, add screenshots to help explain your problem.
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|||||||
@@ -104,12 +104,14 @@ AdvSceneSwitcher.macroTab.maximize="Maximize"
|
|||||||
AdvSceneSwitcher.macroTab.minimize="Minimize"
|
AdvSceneSwitcher.macroTab.minimize="Minimize"
|
||||||
AdvSceneSwitcher.macroTab.highlightSettings="Visual settings"
|
AdvSceneSwitcher.macroTab.highlightSettings="Visual settings"
|
||||||
AdvSceneSwitcher.macroTab.hotkeySettings="Hotkey settings"
|
AdvSceneSwitcher.macroTab.hotkeySettings="Hotkey settings"
|
||||||
|
AdvSceneSwitcher.macroTab.generalSettings="General settings"
|
||||||
AdvSceneSwitcher.macroTab.dockSettings="Dock settings"
|
AdvSceneSwitcher.macroTab.dockSettings="Dock settings"
|
||||||
AdvSceneSwitcher.macroTab.highlightExecutedMacros="Highlight recently executed macros"
|
AdvSceneSwitcher.macroTab.highlightExecutedMacros="Highlight recently executed macros"
|
||||||
AdvSceneSwitcher.macroTab.highlightTrueConditions="Highlight conditions of currently selected macro that evaluated to true recently"
|
AdvSceneSwitcher.macroTab.highlightTrueConditions="Highlight conditions of currently selected macro that evaluated to true recently"
|
||||||
AdvSceneSwitcher.macroTab.highlightPerformedActions="Highlight recently performed actions of currently selected macro"
|
AdvSceneSwitcher.macroTab.highlightPerformedActions="Highlight recently performed actions of currently selected macro"
|
||||||
AdvSceneSwitcher.macroTab.newMacroRegisterHotkey="Register hotkeys to control the pause state of new macros"
|
AdvSceneSwitcher.macroTab.newMacroRegisterHotkey="Register hotkeys to control the pause state of new macros"
|
||||||
AdvSceneSwitcher.macroTab.currentDisableHotkeys="Register hotkeys to control the pause state of selected macro"
|
AdvSceneSwitcher.macroTab.currentDisableHotkeys="Register hotkeys to control the pause state of selected macro"
|
||||||
|
AdvSceneSwitcher.macroTab.currentSkipExecutionOnStartup="Skip execution of actions of current macro on startup"
|
||||||
AdvSceneSwitcher.macroTab.currentRegisterDock="Register dock widget to control the pause state of selected macro or run it manually"
|
AdvSceneSwitcher.macroTab.currentRegisterDock="Register dock widget to control the pause state of selected macro or run it manually"
|
||||||
AdvSceneSwitcher.macroTab.currentDockAddRunButton="Add button to run the macro"
|
AdvSceneSwitcher.macroTab.currentDockAddRunButton="Add button to run the macro"
|
||||||
AdvSceneSwitcher.macroTab.currentDockAddPauseButton="Add button to pause or unpause the macro"
|
AdvSceneSwitcher.macroTab.currentDockAddPauseButton="Add button to pause or unpause the macro"
|
||||||
|
|||||||
@@ -40,7 +40,8 @@ static bool windowContainsText(const std::string &window,
|
|||||||
return text == matchText;
|
return text == matchText;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroConditionWindow::WindowMatches(const std::string &window)
|
bool MacroConditionWindow::WindowMatchesRequirements(
|
||||||
|
const std::string &window) const
|
||||||
{
|
{
|
||||||
const bool focusCheckOK = (!_focus || window == switcher->currentTitle);
|
const bool focusCheckOK = (!_focus || window == switcher->currentTitle);
|
||||||
if (!focusCheckOK) {
|
if (!focusCheckOK) {
|
||||||
@@ -60,26 +61,52 @@ bool MacroConditionWindow::WindowMatches(const std::string &window)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_checkText) {
|
|
||||||
auto text = GetTextInWindow(window);
|
|
||||||
SetVariableValue(text.value_or(""));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MacroConditionWindow::WindowMatches(
|
||||||
|
const std::vector<std::string> &windowList)
|
||||||
|
{
|
||||||
|
bool match = !_checkTitle ||
|
||||||
|
std::find(windowList.begin(), windowList.end(),
|
||||||
|
std::string(_window)) != windowList.end();
|
||||||
|
match = match && WindowMatchesRequirements(_window);
|
||||||
|
SetVariableValueBasedOnMatch(_window);
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
bool MacroConditionWindow::WindowRegexMatches(
|
bool MacroConditionWindow::WindowRegexMatches(
|
||||||
const std::vector<std::string> &windowList)
|
const std::vector<std::string> &windowList)
|
||||||
{
|
{
|
||||||
|
// No need to test if checking for window title is required as if the
|
||||||
|
// user has disabled window title matching the option will always be
|
||||||
|
// enabled in the backend and use the regular expression ".*".
|
||||||
|
|
||||||
for (const auto &window : windowList) {
|
for (const auto &window : windowList) {
|
||||||
if (matchRegex(_windowRegex, window, _window) &&
|
if (matchRegex(_windowRegex, window, _window) &&
|
||||||
WindowMatches(window)) {
|
WindowMatchesRequirements(window)) {
|
||||||
|
SetVariableValueBasedOnMatch(window);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SetVariableValueBasedOnMatch("");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroConditionWindow::SetVariableValueBasedOnMatch(
|
||||||
|
const std::string &matchWindow)
|
||||||
|
{
|
||||||
|
if (!IsReferencedInVars()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_checkText) {
|
||||||
|
auto text = GetTextInWindow(matchWindow);
|
||||||
|
SetVariableValue(text.value_or(""));
|
||||||
|
} else {
|
||||||
|
SetVariableValue(switcher->currentTitle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool foregroundWindowChanged()
|
static bool foregroundWindowChanged()
|
||||||
{
|
{
|
||||||
return switcher->currentTitle != switcher->lastTitle;
|
return switcher->currentTitle != switcher->lastTitle;
|
||||||
@@ -87,19 +114,13 @@ static bool foregroundWindowChanged()
|
|||||||
|
|
||||||
bool MacroConditionWindow::CheckCondition()
|
bool MacroConditionWindow::CheckCondition()
|
||||||
{
|
{
|
||||||
SetVariableValue("");
|
|
||||||
if (!_checkText) {
|
|
||||||
SetVariableValue(switcher->currentTitle);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> windowList;
|
std::vector<std::string> windowList;
|
||||||
GetWindowList(windowList);
|
GetWindowList(windowList);
|
||||||
|
|
||||||
bool match = false;
|
bool match = false;
|
||||||
if (_windowRegex.Enabled()) {
|
if (_windowRegex.Enabled()) {
|
||||||
match = WindowRegexMatches(windowList);
|
match = WindowRegexMatches(windowList);
|
||||||
} else {
|
} else {
|
||||||
match = WindowMatches(_window);
|
match = WindowMatches(windowList);
|
||||||
}
|
}
|
||||||
match = match && (!_windowFocusChanged || foregroundWindowChanged());
|
match = match && (!_windowFocusChanged || foregroundWindowChanged());
|
||||||
return match;
|
return match;
|
||||||
|
|||||||
@@ -21,10 +21,6 @@ public:
|
|||||||
return std::make_shared<MacroConditionWindow>(m);
|
return std::make_shared<MacroConditionWindow>(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
bool WindowMatches(const std::string &window);
|
|
||||||
bool WindowRegexMatches(const std::vector<std::string> &windowList);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StringVariable _window;
|
StringVariable _window;
|
||||||
RegexConfig _windowRegex;
|
RegexConfig _windowRegex;
|
||||||
@@ -40,6 +36,11 @@ public:
|
|||||||
RegexConfig _textRegex = RegexConfig::PartialMatchRegexConfig();
|
RegexConfig _textRegex = RegexConfig::PartialMatchRegexConfig();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool WindowMatchesRequirements(const std::string &window) const;
|
||||||
|
bool WindowMatches(const std::vector<std::string> &windowList);
|
||||||
|
bool WindowRegexMatches(const std::vector<std::string> &windowList);
|
||||||
|
void SetVariableValueBasedOnMatch(const std::string &matchWindow);
|
||||||
|
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
static const std::string id;
|
static const std::string id;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
|
#include <QScrollArea>
|
||||||
|
#include <QScrollBar>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
@@ -44,6 +46,8 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
|
|||||||
"AdvSceneSwitcher.macroTab.newMacroRegisterHotkey"))),
|
"AdvSceneSwitcher.macroTab.newMacroRegisterHotkey"))),
|
||||||
_currentMacroRegisterHotkeys(new QCheckBox(obs_module_text(
|
_currentMacroRegisterHotkeys(new QCheckBox(obs_module_text(
|
||||||
"AdvSceneSwitcher.macroTab.currentDisableHotkeys"))),
|
"AdvSceneSwitcher.macroTab.currentDisableHotkeys"))),
|
||||||
|
_currentSkipOnStartup(new QCheckBox(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.macroTab.currentSkipExecutionOnStartup"))),
|
||||||
_currentMacroRegisterDock(new QCheckBox(obs_module_text(
|
_currentMacroRegisterDock(new QCheckBox(obs_module_text(
|
||||||
"AdvSceneSwitcher.macroTab.currentRegisterDock"))),
|
"AdvSceneSwitcher.macroTab.currentRegisterDock"))),
|
||||||
_currentMacroDockAddRunButton(new QCheckBox(obs_module_text(
|
_currentMacroDockAddRunButton(new QCheckBox(obs_module_text(
|
||||||
@@ -82,6 +86,12 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
|
|||||||
hotkeyLayout->addWidget(_currentMacroRegisterHotkeys);
|
hotkeyLayout->addWidget(_currentMacroRegisterHotkeys);
|
||||||
hotkeyOptions->setLayout(hotkeyLayout);
|
hotkeyOptions->setLayout(hotkeyLayout);
|
||||||
|
|
||||||
|
auto generalOptions = new QGroupBox(
|
||||||
|
obs_module_text("AdvSceneSwitcher.macroTab.generalSettings"));
|
||||||
|
auto generalLayout = new QVBoxLayout;
|
||||||
|
generalLayout->addWidget(_currentSkipOnStartup);
|
||||||
|
generalOptions->setLayout(generalLayout);
|
||||||
|
|
||||||
int row = 0;
|
int row = 0;
|
||||||
_dockLayout->addWidget(_currentMacroRegisterDock, row, 1, 1, 2);
|
_dockLayout->addWidget(_currentMacroRegisterDock, row, 1, 1, 2);
|
||||||
row++;
|
row++;
|
||||||
@@ -146,12 +156,23 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
|
|||||||
connect(_currentMacroDockAddStatusLabel, &QCheckBox::stateChanged, this,
|
connect(_currentMacroDockAddStatusLabel, &QCheckBox::stateChanged, this,
|
||||||
&MacroPropertiesDialog::StatusLabelEnableChanged);
|
&MacroPropertiesDialog::StatusLabelEnableChanged);
|
||||||
|
|
||||||
auto layout = new QVBoxLayout;
|
auto scrollArea = new QScrollArea(this);
|
||||||
|
scrollArea->setWidgetResizable(true);
|
||||||
|
scrollArea->setFrameShape(QFrame::NoFrame);
|
||||||
|
|
||||||
|
auto contentWidget = new QWidget(scrollArea);
|
||||||
|
auto layout = new QVBoxLayout(contentWidget);
|
||||||
layout->addWidget(highlightOptions);
|
layout->addWidget(highlightOptions);
|
||||||
layout->addWidget(hotkeyOptions);
|
layout->addWidget(hotkeyOptions);
|
||||||
|
layout->addWidget(generalOptions);
|
||||||
layout->addWidget(_dockOptions);
|
layout->addWidget(_dockOptions);
|
||||||
layout->addWidget(buttonbox);
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
setLayout(layout);
|
scrollArea->setWidget(contentWidget);
|
||||||
|
|
||||||
|
auto dialogLayout = new QVBoxLayout();
|
||||||
|
dialogLayout->addWidget(scrollArea);
|
||||||
|
dialogLayout->addWidget(buttonbox);
|
||||||
|
setLayout(dialogLayout);
|
||||||
|
|
||||||
_executed->setChecked(prop._highlightExecuted);
|
_executed->setChecked(prop._highlightExecuted);
|
||||||
_conditions->setChecked(prop._highlightConditions);
|
_conditions->setChecked(prop._highlightConditions);
|
||||||
@@ -159,10 +180,12 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
|
|||||||
_newMacroRegisterHotkeys->setChecked(prop._newMacroRegisterHotkeys);
|
_newMacroRegisterHotkeys->setChecked(prop._newMacroRegisterHotkeys);
|
||||||
if (!macro || macro->IsGroup()) {
|
if (!macro || macro->IsGroup()) {
|
||||||
hotkeyOptions->hide();
|
hotkeyOptions->hide();
|
||||||
|
generalOptions->hide();
|
||||||
_dockOptions->hide();
|
_dockOptions->hide();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_currentMacroRegisterHotkeys->setChecked(macro->PauseHotkeysEnabled());
|
_currentMacroRegisterHotkeys->setChecked(macro->PauseHotkeysEnabled());
|
||||||
|
_currentSkipOnStartup->setChecked(macro->SkipExecOnStart());
|
||||||
const bool dockEnabled = macro->DockEnabled();
|
const bool dockEnabled = macro->DockEnabled();
|
||||||
_currentMacroRegisterDock->setChecked(dockEnabled);
|
_currentMacroRegisterDock->setChecked(dockEnabled);
|
||||||
_currentMacroDockAddRunButton->setChecked(macro->DockHasRunButton());
|
_currentMacroDockAddRunButton->setChecked(macro->DockHasRunButton());
|
||||||
@@ -194,6 +217,20 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
|
|||||||
dockEnabled && macro->DockHasStatusLabel());
|
dockEnabled && macro->DockHasStatusLabel());
|
||||||
MinimizeSizeOfColumn(_dockLayout, 0);
|
MinimizeSizeOfColumn(_dockLayout, 0);
|
||||||
Resize();
|
Resize();
|
||||||
|
|
||||||
|
// Try to set sensible initial size for the dialog window
|
||||||
|
QSize contentSize = contentWidget->sizeHint();
|
||||||
|
resize(contentSize.width() + layout->contentsMargins().left() +
|
||||||
|
layout->contentsMargins().right() +
|
||||||
|
dialogLayout->contentsMargins().left() +
|
||||||
|
dialogLayout->contentsMargins().right() +
|
||||||
|
scrollArea->verticalScrollBar()->sizeHint().width() + 20,
|
||||||
|
contentSize.height() + dialogLayout->spacing() +
|
||||||
|
buttonbox->sizeHint().height() +
|
||||||
|
dialogLayout->contentsMargins().top() +
|
||||||
|
dialogLayout->contentsMargins().bottom() +
|
||||||
|
scrollArea->horizontalScrollBar()->sizeHint().height() +
|
||||||
|
20);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroPropertiesDialog::DockEnableChanged(int enabled)
|
void MacroPropertiesDialog::DockEnableChanged(int enabled)
|
||||||
@@ -244,8 +281,6 @@ void MacroPropertiesDialog::Resize()
|
|||||||
{
|
{
|
||||||
_dockOptions->adjustSize();
|
_dockOptions->adjustSize();
|
||||||
_dockOptions->updateGeometry();
|
_dockOptions->updateGeometry();
|
||||||
adjustSize();
|
|
||||||
updateGeometry();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroPropertiesDialog::AskForSettings(QWidget *parent,
|
bool MacroPropertiesDialog::AskForSettings(QWidget *parent,
|
||||||
@@ -268,6 +303,7 @@ bool MacroPropertiesDialog::AskForSettings(QWidget *parent,
|
|||||||
|
|
||||||
macro->EnablePauseHotkeys(
|
macro->EnablePauseHotkeys(
|
||||||
dialog._currentMacroRegisterHotkeys->isChecked());
|
dialog._currentMacroRegisterHotkeys->isChecked());
|
||||||
|
macro->SetSkipExecOnStart(dialog._currentSkipOnStartup->isChecked());
|
||||||
macro->EnableDock(dialog._currentMacroRegisterDock->isChecked());
|
macro->EnableDock(dialog._currentMacroRegisterDock->isChecked());
|
||||||
macro->SetDockHasRunButton(
|
macro->SetDockHasRunButton(
|
||||||
dialog._currentMacroDockAddRunButton->isChecked());
|
dialog._currentMacroDockAddRunButton->isChecked());
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ private:
|
|||||||
QCheckBox *_newMacroRegisterHotkeys;
|
QCheckBox *_newMacroRegisterHotkeys;
|
||||||
// Current macro specific settings
|
// Current macro specific settings
|
||||||
QCheckBox *_currentMacroRegisterHotkeys;
|
QCheckBox *_currentMacroRegisterHotkeys;
|
||||||
|
QCheckBox *_currentSkipOnStartup;
|
||||||
QCheckBox *_currentMacroRegisterDock;
|
QCheckBox *_currentMacroRegisterDock;
|
||||||
QCheckBox *_currentMacroDockAddRunButton;
|
QCheckBox *_currentMacroDockAddRunButton;
|
||||||
QCheckBox *_currentMacroDockAddPauseButton;
|
QCheckBox *_currentMacroDockAddPauseButton;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ Macro::~Macro()
|
|||||||
Stop();
|
Stop();
|
||||||
ClearHotkeys();
|
ClearHotkeys();
|
||||||
|
|
||||||
// Keep the dock widgets in case of shutdown so they can be rostored by
|
// Keep the dock widgets in case of shutdown so they can be restored by
|
||||||
// OBS on startup
|
// OBS on startup
|
||||||
if (!switcher->obsIsShuttingDown) {
|
if (!switcher->obsIsShuttingDown) {
|
||||||
RemoveDock();
|
RemoveDock();
|
||||||
@@ -361,6 +361,7 @@ bool Macro::Save(obs_data_t *obj) const
|
|||||||
obs_data_set_bool(obj, "pause", _paused);
|
obs_data_set_bool(obj, "pause", _paused);
|
||||||
obs_data_set_bool(obj, "parallel", _runInParallel);
|
obs_data_set_bool(obj, "parallel", _runInParallel);
|
||||||
obs_data_set_bool(obj, "onChange", _matchOnChange);
|
obs_data_set_bool(obj, "onChange", _matchOnChange);
|
||||||
|
obs_data_set_bool(obj, "skipExecOnStart", _skipExecOnStart);
|
||||||
|
|
||||||
obs_data_set_bool(obj, "group", _isGroup);
|
obs_data_set_bool(obj, "group", _isGroup);
|
||||||
if (_isGroup) {
|
if (_isGroup) {
|
||||||
@@ -453,6 +454,7 @@ bool Macro::Load(obs_data_t *obj)
|
|||||||
_paused = obs_data_get_bool(obj, "pause");
|
_paused = obs_data_get_bool(obj, "pause");
|
||||||
_runInParallel = obs_data_get_bool(obj, "parallel");
|
_runInParallel = obs_data_get_bool(obj, "parallel");
|
||||||
_matchOnChange = obs_data_get_bool(obj, "onChange");
|
_matchOnChange = obs_data_get_bool(obj, "onChange");
|
||||||
|
_skipExecOnStart = obs_data_get_bool(obj, "skipExecOnStart");
|
||||||
|
|
||||||
_isGroup = obs_data_get_bool(obj, "group");
|
_isGroup = obs_data_get_bool(obj, "group");
|
||||||
if (_isGroup) {
|
if (_isGroup) {
|
||||||
@@ -1026,7 +1028,7 @@ bool SwitcherData::CheckMacros()
|
|||||||
|
|
||||||
bool SwitcherData::RunMacros()
|
bool SwitcherData::RunMacros()
|
||||||
{
|
{
|
||||||
// Create copy of macor list as elements might be removed, inserted, or
|
// Create copy of macro list as elements might be removed, inserted, or
|
||||||
// reordered while macros are currently being executed.
|
// reordered while macros are currently being executed.
|
||||||
// For example, this can happen if a macro is performing a wait action,
|
// For example, this can happen if a macro is performing a wait action,
|
||||||
// as the main lock will be unlocked during this time.
|
// as the main lock will be unlocked during this time.
|
||||||
@@ -1047,12 +1049,18 @@ bool SwitcherData::RunMacros()
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto &m : runPhaseMacros) {
|
for (auto &m : runPhaseMacros) {
|
||||||
if (m && m->Matched()) {
|
if (!m || !m->Matched()) {
|
||||||
vblog(LOG_INFO, "running macro: %s", m->Name().c_str());
|
continue;
|
||||||
if (!m->PerformActions()) {
|
}
|
||||||
blog(LOG_WARNING, "abort macro: %s",
|
if (firstInterval && m->SkipExecOnStart()) {
|
||||||
m->Name().c_str());
|
blog(LOG_INFO,
|
||||||
}
|
"skip execution of macro \"%s\" at startup",
|
||||||
|
m->Name().c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
vblog(LOG_INFO, "running macro: %s", m->Name().c_str());
|
||||||
|
if (!m->PerformActions()) {
|
||||||
|
blog(LOG_WARNING, "abort macro: %s", m->Name().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (GetLock()) {
|
if (GetLock()) {
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ public:
|
|||||||
bool Paused() const { return _paused; }
|
bool Paused() const { return _paused; }
|
||||||
void SetMatchOnChange(bool onChange) { _matchOnChange = onChange; }
|
void SetMatchOnChange(bool onChange) { _matchOnChange = onChange; }
|
||||||
bool MatchOnChange() const { return _matchOnChange; }
|
bool MatchOnChange() const { return _matchOnChange; }
|
||||||
|
void SetSkipExecOnStart(bool skip) { _skipExecOnStart = skip; }
|
||||||
|
bool SkipExecOnStart() const { return _skipExecOnStart; }
|
||||||
int RunCount() const { return _runCount; };
|
int RunCount() const { return _runCount; };
|
||||||
void ResetRunCount() { _runCount = 0; };
|
void ResetRunCount() { _runCount = 0; };
|
||||||
void ResetTimers();
|
void ResetTimers();
|
||||||
@@ -141,6 +143,7 @@ private:
|
|||||||
bool _matched = false;
|
bool _matched = false;
|
||||||
bool _lastMatched = false;
|
bool _lastMatched = false;
|
||||||
bool _matchOnChange = true;
|
bool _matchOnChange = true;
|
||||||
|
bool _skipExecOnStart = false;
|
||||||
bool _paused = false;
|
bool _paused = false;
|
||||||
int _runCount = 0;
|
int _runCount = 0;
|
||||||
bool _registerHotkeys = true;
|
bool _registerHotkeys = true;
|
||||||
|
|||||||
@@ -83,11 +83,6 @@ const static std::map<tesseract::PageSegMode, std::string> pageSegModes = {
|
|||||||
"AdvSceneSwitcher.condition.video.ocrMode.sparseTextOSD"},
|
"AdvSceneSwitcher.condition.video.ocrMode.sparseTextOSD"},
|
||||||
};
|
};
|
||||||
|
|
||||||
MacroConditionVideo::MacroConditionVideo(Macro *m) : MacroCondition(m, true)
|
|
||||||
{
|
|
||||||
SetupOpenCL();
|
|
||||||
}
|
|
||||||
|
|
||||||
cv::CascadeClassifier initObjectCascade(std::string &path)
|
cv::CascadeClassifier initObjectCascade(std::string &path)
|
||||||
{
|
{
|
||||||
cv::CascadeClassifier cascade;
|
cv::CascadeClassifier cascade;
|
||||||
@@ -266,7 +261,7 @@ bool MacroConditionVideo::SetLanguage(const std::string &language)
|
|||||||
|
|
||||||
bool MacroConditionVideo::ScreenshotContainsPattern()
|
bool MacroConditionVideo::ScreenshotContainsPattern()
|
||||||
{
|
{
|
||||||
cv::UMat result;
|
cv::Mat result;
|
||||||
MatchPattern(_screenshotData.image, _patternImageData,
|
MatchPattern(_screenshotData.image, _patternImageData,
|
||||||
_patternMatchParameters.threshold, result,
|
_patternMatchParameters.threshold, result,
|
||||||
_patternMatchParameters.useAlphaAsMask,
|
_patternMatchParameters.useAlphaAsMask,
|
||||||
@@ -279,16 +274,20 @@ bool MacroConditionVideo::ScreenshotContainsPattern()
|
|||||||
|
|
||||||
bool MacroConditionVideo::OutputChanged()
|
bool MacroConditionVideo::OutputChanged()
|
||||||
{
|
{
|
||||||
if (_patternMatchParameters.useForChangedCheck) {
|
if (!_patternMatchParameters.useForChangedCheck) {
|
||||||
cv::UMat result;
|
return _screenshotData.image != _matchImage;
|
||||||
_patternImageData = CreatePatternData(_matchImage);
|
|
||||||
MatchPattern(_screenshotData.image, _patternImageData,
|
|
||||||
_patternMatchParameters.threshold, result,
|
|
||||||
_patternMatchParameters.useAlphaAsMask,
|
|
||||||
_patternMatchParameters.matchMode);
|
|
||||||
return countNonZero(result) == 0;
|
|
||||||
}
|
}
|
||||||
return _screenshotData.image != _matchImage;
|
|
||||||
|
cv::Mat result;
|
||||||
|
_patternImageData = CreatePatternData(_matchImage);
|
||||||
|
MatchPattern(_screenshotData.image, _patternImageData,
|
||||||
|
_patternMatchParameters.threshold, result,
|
||||||
|
_patternMatchParameters.useAlphaAsMask,
|
||||||
|
_patternMatchParameters.matchMode);
|
||||||
|
if (result.total() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return countNonZero(result) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroConditionVideo::ScreenshotContainsObject()
|
bool MacroConditionVideo::ScreenshotContainsObject()
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class PreviewDialog;
|
|||||||
|
|
||||||
class MacroConditionVideo : public MacroCondition {
|
class MacroConditionVideo : public MacroCondition {
|
||||||
public:
|
public:
|
||||||
MacroConditionVideo(Macro *m);
|
MacroConditionVideo(Macro *m) : MacroCondition(m, true){};
|
||||||
bool CheckCondition();
|
bool CheckCondition();
|
||||||
bool Save(obs_data_t *obj) const;
|
bool Save(obs_data_t *obj) const;
|
||||||
bool Load(obs_data_t *obj);
|
bool Load(obs_data_t *obj);
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
#include "opencv-helpers.hpp"
|
#include "opencv-helpers.hpp"
|
||||||
#include "log-helper.hpp"
|
|
||||||
|
|
||||||
#include <opencv2/core/ocl.hpp>
|
#include <log-helper.hpp>
|
||||||
#include <opencv2/core/mat.hpp>
|
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
@@ -24,19 +22,17 @@ PatternImageData CreatePatternData(const QImage &pattern)
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void invertPatternMatchResult(cv::UMat &umat)
|
static void invertPatternMatchResult(cv::Mat &mat)
|
||||||
{
|
{
|
||||||
auto mat = umat.getMat(cv::ACCESS_RW);
|
|
||||||
for (int r = 0; r < mat.rows; r++) {
|
for (int r = 0; r < mat.rows; r++) {
|
||||||
for (int c = 0; c < mat.cols; c++) {
|
for (int c = 0; c < mat.cols; c++) {
|
||||||
mat.at<float>(r, c) = 1.0 - mat.at<float>(r, c);
|
mat.at<float>(r, c) = 1.0 - mat.at<float>(r, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
umat = mat.getUMat(cv::ACCESS_RW);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MatchPattern(QImage &img, const PatternImageData &patternData,
|
void MatchPattern(QImage &img, const PatternImageData &patternData,
|
||||||
double threshold, cv::UMat &result, bool useAlphaAsMask,
|
double threshold, cv::Mat &result, bool useAlphaAsMask,
|
||||||
cv::TemplateMatchModes matchMode)
|
cv::TemplateMatchModes matchMode)
|
||||||
{
|
{
|
||||||
if (img.isNull() || patternData.rgbaPattern.empty()) {
|
if (img.isNull() || patternData.rgbaPattern.empty()) {
|
||||||
@@ -55,12 +51,13 @@ void MatchPattern(QImage &img, const PatternImageData &patternData,
|
|||||||
// thus should not be used while matching the pattern as well
|
// thus should not be used while matching the pattern as well
|
||||||
//
|
//
|
||||||
// Input format is Format_RGBA8888 so discard the 4th channel
|
// Input format is Format_RGBA8888 so discard the 4th channel
|
||||||
std::vector<cv::UMat> inputChannels;
|
std::vector<cv::Mat1b> inputChannels;
|
||||||
cv::split(input, inputChannels);
|
cv::split(input, inputChannels);
|
||||||
std::vector<cv::UMat> rgbChanlesImage(
|
std::vector<cv::Mat1b> rgbChanlesImage(
|
||||||
inputChannels.begin(), inputChannels.begin() + 3);
|
inputChannels.begin(), inputChannels.begin() + 3);
|
||||||
cv::UMat rgbInput;
|
cv::Mat3b rgbInput;
|
||||||
cv::merge(rgbChanlesImage, rgbInput);
|
cv::merge(rgbChanlesImage, rgbInput);
|
||||||
|
|
||||||
cv::matchTemplate(rgbInput, patternData.rgbPattern, result,
|
cv::matchTemplate(rgbInput, patternData.rgbPattern, result,
|
||||||
matchMode, patternData.mask);
|
matchMode, patternData.mask);
|
||||||
} else {
|
} else {
|
||||||
@@ -79,7 +76,7 @@ void MatchPattern(QImage &img, const PatternImageData &patternData,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MatchPattern(QImage &img, QImage &pattern, double threshold,
|
void MatchPattern(QImage &img, QImage &pattern, double threshold,
|
||||||
cv::UMat &result, bool useAlphaAsMask,
|
cv::Mat &result, bool useAlphaAsMask,
|
||||||
cv::TemplateMatchModes matchColor)
|
cv::TemplateMatchModes matchColor)
|
||||||
{
|
{
|
||||||
auto data = CreatePatternData(pattern);
|
auto data = CreatePatternData(pattern);
|
||||||
@@ -96,12 +93,16 @@ std::vector<cv::Rect> MatchObject(QImage &img, cv::CascadeClassifier &cascade,
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto image = QImageToMat(img);
|
auto image = QImageToMat(img);
|
||||||
cv::UMat frameGray;
|
cv::Mat frameGray;
|
||||||
cv::cvtColor(image, frameGray, cv::COLOR_RGBA2GRAY);
|
cv::cvtColor(image, frameGray, cv::COLOR_RGBA2GRAY);
|
||||||
cv::equalizeHist(frameGray, frameGray);
|
cv::equalizeHist(frameGray, frameGray);
|
||||||
std::vector<cv::Rect> objects;
|
std::vector<cv::Rect> objects;
|
||||||
cascade.detectMultiScale(frameGray, objects, scaleFactor, minNeighbors,
|
try {
|
||||||
0, minSize, maxSize);
|
cascade.detectMultiScale(frameGray, objects, scaleFactor,
|
||||||
|
minNeighbors, 0, minSize, maxSize);
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
vblog(LOG_INFO, "detectMultiScale failed: %s", e.what());
|
||||||
|
}
|
||||||
return objects;
|
return objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,9 +112,9 @@ uchar GetAvgBrightness(QImage &img)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto i = QImageToMat(img);
|
auto image = QImageToMat(img);
|
||||||
cv::Mat hsvImage, rgbImage;
|
cv::Mat hsvImage, rgbImage;
|
||||||
cv::cvtColor(i, rgbImage, cv::COLOR_RGBA2RGB);
|
cv::cvtColor(image, rgbImage, cv::COLOR_RGBA2RGB);
|
||||||
cv::cvtColor(rgbImage, hsvImage, cv::COLOR_RGB2HSV);
|
cv::cvtColor(rgbImage, hsvImage, cv::COLOR_RGB2HSV);
|
||||||
long long brightnessSum = 0;
|
long long brightnessSum = 0;
|
||||||
for (int i = 0; i < hsvImage.rows; ++i) {
|
for (int i = 0; i < hsvImage.rows; ++i) {
|
||||||
@@ -138,8 +139,7 @@ static bool colorIsSimilar(const QColor &color1, const QColor &color2,
|
|||||||
cv::Mat PreprocessForOCR(const QImage &image, const QColor &textColor,
|
cv::Mat PreprocessForOCR(const QImage &image, const QColor &textColor,
|
||||||
double colorDiff)
|
double colorDiff)
|
||||||
{
|
{
|
||||||
auto umat = QImageToMat(image);
|
auto mat = QImageToMat(image);
|
||||||
auto mat = umat.getMat(cv::ACCESS_RW);
|
|
||||||
|
|
||||||
// Tesseract works best when matching black text on a white background,
|
// Tesseract works best when matching black text on a white background,
|
||||||
// so everything that matches the text color will be displayed black
|
// so everything that matches the text color will be displayed black
|
||||||
@@ -224,14 +224,13 @@ bool ContainsPixelsInColorRange(const QImage &image, const QColor &color,
|
|||||||
|
|
||||||
// Assumption is that QImage uses Format_RGBA8888.
|
// Assumption is that QImage uses Format_RGBA8888.
|
||||||
// Conversion from: https://github.com/dbzhang800/QtOpenCV
|
// Conversion from: https://github.com/dbzhang800/QtOpenCV
|
||||||
cv::UMat QImageToMat(const QImage &img)
|
cv::Mat QImageToMat(const QImage &img)
|
||||||
{
|
{
|
||||||
if (img.isNull()) {
|
if (img.isNull()) {
|
||||||
return cv::UMat();
|
return cv::Mat();
|
||||||
}
|
}
|
||||||
auto temp = cv::Mat(img.height(), img.width(), CV_8UC(img.depth() / 8),
|
return cv::Mat(img.height(), img.width(), CV_8UC(img.depth() / 8),
|
||||||
(uchar *)img.bits(), img.bytesPerLine());
|
(uchar *)img.bits(), img.bytesPerLine());
|
||||||
return temp.getUMat(cv::ACCESS_RW);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage MatToQImage(const cv::Mat &mat)
|
QImage MatToQImage(const cv::Mat &mat)
|
||||||
@@ -243,12 +242,4 @@ QImage MatToQImage(const cv::Mat &mat)
|
|||||||
QImage::Format::Format_RGBA8888);
|
QImage::Format::Format_RGBA8888);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupOpenCL()
|
|
||||||
{
|
|
||||||
if (cv::ocl::haveOpenCL() && !cv::ocl::useOpenCL()) {
|
|
||||||
blog(LOG_INFO, "enabled OpenCL support for OpenCV");
|
|
||||||
cv::ocl::setUseOpenCL(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -42,17 +42,17 @@ constexpr int maxMinNeighbors = 6;
|
|||||||
constexpr double defaultScaleFactor = 1.1;
|
constexpr double defaultScaleFactor = 1.1;
|
||||||
|
|
||||||
struct PatternImageData {
|
struct PatternImageData {
|
||||||
cv::UMat rgbaPattern;
|
cv::Mat4b rgbaPattern;
|
||||||
cv::UMat rgbPattern;
|
cv::Mat3b rgbPattern;
|
||||||
cv::UMat mask;
|
cv::Mat1b mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
PatternImageData CreatePatternData(const QImage &pattern);
|
PatternImageData CreatePatternData(const QImage &pattern);
|
||||||
void MatchPattern(QImage &img, const PatternImageData &patternData,
|
void MatchPattern(QImage &img, const PatternImageData &patternData,
|
||||||
double threshold, cv::UMat &result, bool useAlphaAsMask,
|
double threshold, cv::Mat &result, bool useAlphaAsMask,
|
||||||
cv::TemplateMatchModes matchMode);
|
cv::TemplateMatchModes matchMode);
|
||||||
void MatchPattern(QImage &img, QImage &pattern, double threshold,
|
void MatchPattern(QImage &img, QImage &pattern, double threshold,
|
||||||
cv::UMat &result, bool useAlphaAsMask,
|
cv::Mat &result, bool useAlphaAsMask,
|
||||||
cv::TemplateMatchModes matchMode);
|
cv::TemplateMatchModes matchMode);
|
||||||
std::vector<cv::Rect> MatchObject(QImage &img, cv::CascadeClassifier &cascade,
|
std::vector<cv::Rect> MatchObject(QImage &img, cv::CascadeClassifier &cascade,
|
||||||
double scaleFactor, int minNeighbors,
|
double scaleFactor, int minNeighbors,
|
||||||
@@ -66,8 +66,7 @@ std::string RunOCR(tesseract::TessBaseAPI *, const QImage &, const QColor &,
|
|||||||
bool ContainsPixelsInColorRange(const QImage &image, const QColor &color,
|
bool ContainsPixelsInColorRange(const QImage &image, const QColor &color,
|
||||||
double colorDeviationThreshold,
|
double colorDeviationThreshold,
|
||||||
double totalPixelMatchThreshold);
|
double totalPixelMatchThreshold);
|
||||||
cv::UMat QImageToMat(const QImage &img);
|
cv::Mat QImageToMat(const QImage &img);
|
||||||
QImage MatToQImage(const cv::Mat &mat);
|
QImage MatToQImage(const cv::Mat &mat);
|
||||||
void SetupOpenCL();
|
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -252,7 +252,9 @@ OCRParameters::OCRParameters(const OCRParameters &other)
|
|||||||
colorThreshold(other.colorThreshold),
|
colorThreshold(other.colorThreshold),
|
||||||
pageSegMode(other.pageSegMode)
|
pageSegMode(other.pageSegMode)
|
||||||
{
|
{
|
||||||
Setup();
|
if (!initDone) {
|
||||||
|
Setup();
|
||||||
|
}
|
||||||
if (initDone) {
|
if (initDone) {
|
||||||
ocr->SetPageSegMode(pageSegMode);
|
ocr->SetPageSegMode(pageSegMode);
|
||||||
}
|
}
|
||||||
@@ -265,7 +267,12 @@ OCRParameters &OCRParameters::operator=(const OCRParameters &other)
|
|||||||
color = other.color;
|
color = other.color;
|
||||||
colorThreshold = other.colorThreshold;
|
colorThreshold = other.colorThreshold;
|
||||||
pageSegMode = other.pageSegMode;
|
pageSegMode = other.pageSegMode;
|
||||||
ocr->SetPageSegMode(pageSegMode);
|
if (!initDone) {
|
||||||
|
Setup();
|
||||||
|
}
|
||||||
|
if (initDone) {
|
||||||
|
ocr->SetPageSegMode(pageSegMode);
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ void PreviewDialog::PatternMatchParametersChanged(
|
|||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(_mtx);
|
std::unique_lock<std::mutex> lock(_mtx);
|
||||||
_patternMatchParams = params;
|
_patternMatchParams = params;
|
||||||
|
_patternImageData = CreatePatternData(_patternMatchParams.image);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewDialog::ObjDetectParametersChanged(const ObjDetectParameters ¶ms)
|
void PreviewDialog::ObjDetectParametersChanged(const ObjDetectParameters ¶ms)
|
||||||
@@ -169,8 +170,8 @@ void PreviewDialog::UpdateImage(const QPixmap &image)
|
|||||||
if (_type == PreviewType::SELECT_AREA && !_selectingArea) {
|
if (_type == PreviewType::SELECT_AREA && !_selectingArea) {
|
||||||
DrawFrame();
|
DrawFrame();
|
||||||
}
|
}
|
||||||
emit NeedImage(_video, _type, _patternMatchParams, _objDetectParams,
|
emit NeedImage(_video, _type, _patternMatchParams, _patternImageData,
|
||||||
_ocrParams, _areaParams, _condition);
|
_objDetectParams, _ocrParams, _areaParams, _condition);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewDialog::Start()
|
void PreviewDialog::Start()
|
||||||
@@ -186,7 +187,7 @@ void PreviewDialog::Start()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PreviewImage *worker = new PreviewImage(_mtx);
|
auto worker = new PreviewImage(_mtx);
|
||||||
worker->moveToThread(&_thread);
|
worker->moveToThread(&_thread);
|
||||||
connect(&_thread, &QThread::finished, worker, &QObject::deleteLater);
|
connect(&_thread, &QThread::finished, worker, &QObject::deleteLater);
|
||||||
connect(worker, &PreviewImage::ImageReady, this,
|
connect(worker, &PreviewImage::ImageReady, this,
|
||||||
@@ -197,8 +198,8 @@ void PreviewDialog::Start()
|
|||||||
&PreviewImage::CreateImage);
|
&PreviewImage::CreateImage);
|
||||||
_thread.start();
|
_thread.start();
|
||||||
|
|
||||||
emit NeedImage(_video, _type, _patternMatchParams, _objDetectParams,
|
emit NeedImage(_video, _type, _patternMatchParams, _patternImageData,
|
||||||
_ocrParams, _areaParams, _condition);
|
_objDetectParams, _ocrParams, _areaParams, _condition);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewDialog::DrawFrame()
|
void PreviewDialog::DrawFrame()
|
||||||
@@ -216,14 +217,13 @@ void PreviewDialog::DrawFrame()
|
|||||||
_rubberBand->show();
|
_rubberBand->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void markPatterns(cv::UMat &matchResult, QImage &image,
|
static void markPatterns(cv::Mat &matchResult, QImage &image,
|
||||||
const cv::UMat &pattern)
|
const cv::Mat &pattern)
|
||||||
{
|
{
|
||||||
auto temp = matchResult.getMat(cv::ACCESS_RW);
|
|
||||||
auto matchImg = QImageToMat(image);
|
auto matchImg = QImageToMat(image);
|
||||||
for (int row = 0; row < temp.rows - 1; row++) {
|
for (int row = 0; row < matchResult.rows - 1; row++) {
|
||||||
for (int col = 0; col < temp.cols - 1; col++) {
|
for (int col = 0; col < matchResult.cols - 1; col++) {
|
||||||
if (temp.at<float>(row, col) != 0.0) {
|
if (matchResult.at<float>(row, col) != 0.0) {
|
||||||
rectangle(matchImg, {col, row},
|
rectangle(matchImg, {col, row},
|
||||||
cv::Point(col + pattern.cols,
|
cv::Point(col + pattern.cols,
|
||||||
row + pattern.rows),
|
row + pattern.rows),
|
||||||
@@ -231,7 +231,6 @@ static void markPatterns(cv::UMat &matchResult, QImage &image,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
matchResult = temp.getUMat(cv::ACCESS_RW);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void markObjects(QImage &image, std::vector<cv::Rect> &objects)
|
static void markObjects(QImage &image, std::vector<cv::Rect> &objects)
|
||||||
@@ -249,6 +248,7 @@ PreviewImage::PreviewImage(std::mutex &mtx) : _mtx(mtx) {}
|
|||||||
|
|
||||||
void PreviewImage::CreateImage(const VideoInput &video, PreviewType type,
|
void PreviewImage::CreateImage(const VideoInput &video, PreviewType type,
|
||||||
const PatternMatchParameters &patternMatchParams,
|
const PatternMatchParameters &patternMatchParams,
|
||||||
|
const PatternImageData &patternImageData,
|
||||||
ObjDetectParameters objDetectParams,
|
ObjDetectParameters objDetectParams,
|
||||||
OCRParameters ocrParams,
|
OCRParameters ocrParams,
|
||||||
const AreaParameters &areaParams,
|
const AreaParameters &areaParams,
|
||||||
@@ -279,8 +279,6 @@ void PreviewImage::CreateImage(const VideoInput &video, PreviewType type,
|
|||||||
areaParams.area.x, areaParams.area.y,
|
areaParams.area.x, areaParams.area.y,
|
||||||
areaParams.area.width, areaParams.area.height);
|
areaParams.area.width, areaParams.area.height);
|
||||||
}
|
}
|
||||||
const auto patternImageData =
|
|
||||||
CreatePatternData(patternMatchParams.image);
|
|
||||||
// Will emit status label update
|
// Will emit status label update
|
||||||
MarkMatch(screenshot.image, patternMatchParams,
|
MarkMatch(screenshot.image, patternMatchParams,
|
||||||
patternImageData, objDetectParams, ocrParams,
|
patternImageData, objDetectParams, ocrParams,
|
||||||
@@ -299,7 +297,7 @@ void PreviewImage::MarkMatch(QImage &screenshot,
|
|||||||
VideoCondition condition)
|
VideoCondition condition)
|
||||||
{
|
{
|
||||||
if (condition == VideoCondition::PATTERN) {
|
if (condition == VideoCondition::PATTERN) {
|
||||||
cv::UMat result;
|
cv::Mat result;
|
||||||
MatchPattern(screenshot, patternImageData,
|
MatchPattern(screenshot, patternImageData,
|
||||||
patternMatchParams.threshold, result,
|
patternMatchParams.threshold, result,
|
||||||
patternMatchParams.useAlphaAsMask,
|
patternMatchParams.useAlphaAsMask,
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ public:
|
|||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void CreateImage(const VideoInput &, PreviewType,
|
void CreateImage(const VideoInput &, PreviewType,
|
||||||
const PatternMatchParameters &, ObjDetectParameters,
|
const PatternMatchParameters &,
|
||||||
|
const PatternImageData &, ObjDetectParameters,
|
||||||
OCRParameters, const AreaParameters &, VideoCondition);
|
OCRParameters, const AreaParameters &, VideoCondition);
|
||||||
signals:
|
signals:
|
||||||
void ImageReady(const QPixmap &);
|
void ImageReady(const QPixmap &);
|
||||||
@@ -63,8 +64,9 @@ private slots:
|
|||||||
signals:
|
signals:
|
||||||
void SelectionAreaChanged(QRect area);
|
void SelectionAreaChanged(QRect area);
|
||||||
void NeedImage(const VideoInput &, PreviewType,
|
void NeedImage(const VideoInput &, PreviewType,
|
||||||
const PatternMatchParameters &, ObjDetectParameters,
|
const PatternMatchParameters &, const PatternImageData &,
|
||||||
OCRParameters, const AreaParameters &, VideoCondition);
|
ObjDetectParameters, OCRParameters,
|
||||||
|
const AreaParameters &, VideoCondition);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Start();
|
void Start();
|
||||||
@@ -76,6 +78,7 @@ private:
|
|||||||
|
|
||||||
VideoInput _video;
|
VideoInput _video;
|
||||||
PatternMatchParameters _patternMatchParams;
|
PatternMatchParameters _patternMatchParams;
|
||||||
|
PatternImageData _patternImageData;
|
||||||
ObjDetectParameters _objDetectParams;
|
ObjDetectParameters _objDetectParams;
|
||||||
OCRParameters _ocrParams;
|
OCRParameters _ocrParams;
|
||||||
AreaParameters _areaParams;
|
AreaParameters _areaParams;
|
||||||
|
|||||||
@@ -510,7 +510,8 @@ bool DisplayMessage(const QString &msg, bool question, bool modal)
|
|||||||
return (answer == QMessageBox::Yes);
|
return (answer == QMessageBox::Yes);
|
||||||
} else if (question && modal) {
|
} else if (question && modal) {
|
||||||
auto answer = QMessageBox::question(
|
auto answer = QMessageBox::question(
|
||||||
nullptr,
|
static_cast<QMainWindow *>(
|
||||||
|
obs_frontend_get_main_window()),
|
||||||
obs_module_text("AdvSceneSwitcher.windowTitle"), msg,
|
obs_module_text("AdvSceneSwitcher.windowTitle"), msg,
|
||||||
QMessageBox::Yes | QMessageBox::No);
|
QMessageBox::Yes | QMessageBox::No);
|
||||||
return answer == QMessageBox::Yes;
|
return answer == QMessageBox::Yes;
|
||||||
@@ -842,11 +843,9 @@ QStringList GetMediaSourceNames()
|
|||||||
auto sourceEnum = [](void *param, obs_source_t *source) -> bool /* -- */
|
auto sourceEnum = [](void *param, obs_source_t *source) -> bool /* -- */
|
||||||
{
|
{
|
||||||
QStringList *list = reinterpret_cast<QStringList *>(param);
|
QStringList *list = reinterpret_cast<QStringList *>(param);
|
||||||
std::string sourceId = obs_source_get_id(source);
|
uint32_t flags = obs_source_get_output_flags(source);
|
||||||
if (sourceId.compare("ffmpeg_source") == 0 ||
|
|
||||||
sourceId.compare("vlc_source") == 0 ||
|
if ((flags & OBS_SOURCE_CONTROLLABLE_MEDIA) != 0) {
|
||||||
sourceId.compare("slideshow") == 0 ||
|
|
||||||
sourceId.compare("media_playlist_source_codeyan") == 0) {
|
|
||||||
*list << obs_source_get_name(source);
|
*list << obs_source_get_name(source);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user