mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-09-07 17:16:00 -05:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3220809c04 | ||
|
|
72d5255c9e | ||
|
|
5995563a80 | ||
|
|
347743d93a | ||
|
|
3c067ce723 |
@@ -113,6 +113,8 @@ target_sources(
|
|||||||
src/macro-core/macro-action-plugin-state.hpp
|
src/macro-core/macro-action-plugin-state.hpp
|
||||||
src/macro-core/macro-action-profile.cpp
|
src/macro-core/macro-action-profile.cpp
|
||||||
src/macro-core/macro-action-profile.hpp
|
src/macro-core/macro-action-profile.hpp
|
||||||
|
src/macro-core/macro-action-projector.cpp
|
||||||
|
src/macro-core/macro-action-projector.hpp
|
||||||
src/macro-core/macro-action-random.cpp
|
src/macro-core/macro-action-random.cpp
|
||||||
src/macro-core/macro-action-random.hpp
|
src/macro-core/macro-action-random.hpp
|
||||||
src/macro-core/macro-action-recording.cpp
|
src/macro-core/macro-action-recording.cpp
|
||||||
|
|||||||
@@ -594,6 +594,17 @@ AdvSceneSwitcher.action.variable.currentSegmentValue="Current value:"
|
|||||||
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}"
|
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}"
|
||||||
AdvSceneSwitcher.action.variable.entry.substringIndex="Substring start:{{subStringStart}} Substring size:{{subStringSize}}"
|
AdvSceneSwitcher.action.variable.entry.substringIndex="Substring start:{{subStringStart}} Substring size:{{subStringSize}}"
|
||||||
AdvSceneSwitcher.action.variable.entry.substringRegex="Assign value of{{regexMatchIdx}}match using regular expression:"
|
AdvSceneSwitcher.action.variable.entry.substringRegex="Assign value of{{regexMatchIdx}}match using regular expression:"
|
||||||
|
AdvSceneSwitcher.action.projector="Projector"
|
||||||
|
AdvSceneSwitcher.action.projector.type.source="Source"
|
||||||
|
AdvSceneSwitcher.action.projector.type.scene="Scene"
|
||||||
|
AdvSceneSwitcher.action.projector.type.preview="Preview"
|
||||||
|
AdvSceneSwitcher.action.projector.type.program="Program"
|
||||||
|
AdvSceneSwitcher.action.projector.type.multiview="Multiview"
|
||||||
|
AdvSceneSwitcher.action.projector.display="Display"
|
||||||
|
AdvSceneSwitcher.action.projector.windowed="Windowed"
|
||||||
|
AdvSceneSwitcher.action.projector.fullscreen="Fullscreen"
|
||||||
|
AdvSceneSwitcher.action.projector.entry="Open{{windowTypes}}projector of{{types}}{{scenes}}{{sources}}"
|
||||||
|
AdvSceneSwitcher.action.projector.entry.monitor="on{{monitors}}"
|
||||||
|
|
||||||
|
|
||||||
; Transition Tab
|
; Transition Tab
|
||||||
|
|||||||
@@ -653,7 +653,7 @@ void SwitcherData::saveGeneralSettings(obs_data_t *obj)
|
|||||||
|
|
||||||
obs_data_set_int(obj, "threadPriority", threadPriority);
|
obs_data_set_int(obj, "threadPriority", threadPriority);
|
||||||
|
|
||||||
obs_data_set_bool(obj, "tansitionOverrideOverride",
|
obs_data_set_bool(obj, "transitionOverrideOverride",
|
||||||
transitionOverrideOverride);
|
transitionOverrideOverride);
|
||||||
obs_data_set_bool(obj, "adjustActiveTransitionType",
|
obs_data_set_bool(obj, "adjustActiveTransitionType",
|
||||||
adjustActiveTransitionType);
|
adjustActiveTransitionType);
|
||||||
@@ -735,8 +735,14 @@ void SwitcherData::loadGeneralSettings(obs_data_t *obj)
|
|||||||
QThread::NormalPriority);
|
QThread::NormalPriority);
|
||||||
threadPriority = obs_data_get_int(obj, "threadPriority");
|
threadPriority = obs_data_get_int(obj, "threadPriority");
|
||||||
|
|
||||||
transitionOverrideOverride =
|
// TODO: Remove this fallback in future version
|
||||||
obs_data_get_bool(obj, "tansitionOverrideOverride");
|
if (obs_data_has_user_value(obj, "tansitionOverrideOverride")) {
|
||||||
|
transitionOverrideOverride =
|
||||||
|
obs_data_get_bool(obj, "tansitionOverrideOverride");
|
||||||
|
} else {
|
||||||
|
transitionOverrideOverride =
|
||||||
|
obs_data_get_bool(obj, "transitionOverrideOverride");
|
||||||
|
}
|
||||||
adjustActiveTransitionType =
|
adjustActiveTransitionType =
|
||||||
obs_data_get_bool(obj, "adjustActiveTransitionType");
|
obs_data_get_bool(obj, "adjustActiveTransitionType");
|
||||||
|
|
||||||
|
|||||||
290
src/macro-core/macro-action-projector.cpp
Normal file
290
src/macro-core/macro-action-projector.cpp
Normal file
@@ -0,0 +1,290 @@
|
|||||||
|
#include "macro-action-projector.hpp"
|
||||||
|
#include "advanced-scene-switcher.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
#include <QScreen>
|
||||||
|
|
||||||
|
const std::string MacroActionProjector::id = "projector";
|
||||||
|
|
||||||
|
bool MacroActionProjector::_registered = MacroActionFactory::Register(
|
||||||
|
MacroActionProjector::id,
|
||||||
|
{MacroActionProjector::Create, MacroActionProjectorEdit::Create,
|
||||||
|
"AdvSceneSwitcher.action.projector"});
|
||||||
|
|
||||||
|
const static std::map<MacroActionProjector::Type, std::string> selectionTypes = {
|
||||||
|
{MacroActionProjector::Type::SOURCE,
|
||||||
|
"AdvSceneSwitcher.action.projector.type.source"},
|
||||||
|
{MacroActionProjector::Type::SCENE,
|
||||||
|
"AdvSceneSwitcher.action.projector.type.scene"},
|
||||||
|
{MacroActionProjector::Type::PREVIEW,
|
||||||
|
"AdvSceneSwitcher.action.projector.type.preview"},
|
||||||
|
{MacroActionProjector::Type::PROGRAM,
|
||||||
|
"AdvSceneSwitcher.action.projector.type.program"},
|
||||||
|
{MacroActionProjector::Type::MULTIVIEW,
|
||||||
|
"AdvSceneSwitcher.action.projector.type.multiview"},
|
||||||
|
};
|
||||||
|
|
||||||
|
bool MacroActionProjector::PerformAction()
|
||||||
|
{
|
||||||
|
std::string name = "";
|
||||||
|
const char *type = "";
|
||||||
|
|
||||||
|
switch (_type) {
|
||||||
|
case MacroActionProjector::Type::SOURCE:
|
||||||
|
type = "Source";
|
||||||
|
name = GetWeakSourceName(_source.GetSource());
|
||||||
|
if (name.empty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MacroActionProjector::Type::SCENE:
|
||||||
|
type = "Scene";
|
||||||
|
name = GetWeakSourceName(_scene.GetScene());
|
||||||
|
if (name.empty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MacroActionProjector::Type::PREVIEW:
|
||||||
|
type = "Preview";
|
||||||
|
break;
|
||||||
|
case MacroActionProjector::Type::PROGRAM:
|
||||||
|
type = "StudioProgram";
|
||||||
|
break;
|
||||||
|
case MacroActionProjector::Type::MULTIVIEW:
|
||||||
|
type = "Multiview";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
obs_frontend_open_projector(type, _fullscreen ? _monitor : -1, "",
|
||||||
|
name.c_str());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionProjector::LogAction() const
|
||||||
|
{
|
||||||
|
auto it = selectionTypes.find(_type);
|
||||||
|
if (it != selectionTypes.end()) {
|
||||||
|
vblog(LOG_INFO,
|
||||||
|
"performed projector action \"%s\" with"
|
||||||
|
"source \"%s\","
|
||||||
|
"scene \"%s\","
|
||||||
|
"monitor %d",
|
||||||
|
it->second.c_str(), _source.ToString(true).c_str(),
|
||||||
|
_scene.ToString(true).c_str(), _monitor);
|
||||||
|
} else {
|
||||||
|
blog(LOG_WARNING, "ignored unknown projector action %d",
|
||||||
|
static_cast<int>(_type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroActionProjector::Save(obs_data_t *obj) const
|
||||||
|
{
|
||||||
|
MacroAction::Save(obj);
|
||||||
|
obs_data_set_int(obj, "type", static_cast<int>(_type));
|
||||||
|
obs_data_set_int(obj, "monitor", _monitor);
|
||||||
|
obs_data_set_bool(obj, "fullscreen", _fullscreen);
|
||||||
|
_scene.Save(obj);
|
||||||
|
_source.Save(obj);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroActionProjector::Load(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
MacroAction::Load(obj);
|
||||||
|
_type = static_cast<Type>(obs_data_get_int(obj, "type"));
|
||||||
|
_monitor = obs_data_get_int(obj, "monitor");
|
||||||
|
_fullscreen = obs_data_get_bool(obj, "fullscreen");
|
||||||
|
_scene.Load(obj);
|
||||||
|
_source.Load(obj);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void populateSelectionTypes(QComboBox *list)
|
||||||
|
{
|
||||||
|
for (auto entry : selectionTypes) {
|
||||||
|
list->addItem(obs_module_text(entry.second.c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void populateWindowTypes(QComboBox *list)
|
||||||
|
{
|
||||||
|
list->addItem(
|
||||||
|
obs_module_text("AdvSceneSwitcher.action.projector.windowed"));
|
||||||
|
list->addItem(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.projector.fullscreen"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static QStringList getMonitorNames()
|
||||||
|
{
|
||||||
|
QStringList monitorNames;
|
||||||
|
QList<QScreen *> screens = QGuiApplication::screens();
|
||||||
|
for (int i = 0; i < screens.size(); i++) {
|
||||||
|
QScreen *screen = screens[i];
|
||||||
|
QRect screenGeometry = screen->geometry();
|
||||||
|
qreal ratio = screen->devicePixelRatio();
|
||||||
|
QString name = "";
|
||||||
|
#if defined(__APPLE__) || defined(_WIN32)
|
||||||
|
name = screen->name();
|
||||||
|
#else
|
||||||
|
name = screen->model().simplified();
|
||||||
|
if (name.length() > 1 && name.endsWith("-")) {
|
||||||
|
name.chop(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
name = name.simplified();
|
||||||
|
|
||||||
|
if (name.length() == 0) {
|
||||||
|
name = QString("%1 %2")
|
||||||
|
.arg(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.projector.display"))
|
||||||
|
.arg(QString::number(i + 1));
|
||||||
|
}
|
||||||
|
QString str =
|
||||||
|
QString("%1: %2x%3 @ %4,%5")
|
||||||
|
.arg(name,
|
||||||
|
QString::number(screenGeometry.width() *
|
||||||
|
ratio),
|
||||||
|
QString::number(screenGeometry.height() *
|
||||||
|
ratio),
|
||||||
|
QString::number(screenGeometry.x()),
|
||||||
|
QString::number(screenGeometry.y()));
|
||||||
|
|
||||||
|
monitorNames << str;
|
||||||
|
}
|
||||||
|
return monitorNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
MacroActionProjectorEdit::MacroActionProjectorEdit(
|
||||||
|
QWidget *parent, std::shared_ptr<MacroActionProjector> entryData)
|
||||||
|
: QWidget(parent),
|
||||||
|
_windowTypes(new QComboBox()),
|
||||||
|
_types(new QComboBox()),
|
||||||
|
_scenes(new SceneSelectionWidget(window(), true, false, true, true,
|
||||||
|
true)),
|
||||||
|
_sources(new SourceSelectionWidget(window(), QStringList(), true)),
|
||||||
|
_monitorSelection(new QHBoxLayout()),
|
||||||
|
_monitors(new QComboBox())
|
||||||
|
{
|
||||||
|
populateWindowTypes(_windowTypes);
|
||||||
|
populateSelectionTypes(_types);
|
||||||
|
auto sources = GetSourceNames();
|
||||||
|
sources.sort();
|
||||||
|
_sources->SetSourceNameList(sources);
|
||||||
|
_monitors->addItems(getMonitorNames());
|
||||||
|
|
||||||
|
QWidget::connect(_windowTypes, SIGNAL(currentIndexChanged(int)), this,
|
||||||
|
SLOT(WindowTypeChanged(int)));
|
||||||
|
QWidget::connect(_types, SIGNAL(currentIndexChanged(int)), this,
|
||||||
|
SLOT(TypeChanged(int)));
|
||||||
|
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||||
|
this, SLOT(SceneChanged(const SceneSelection &)));
|
||||||
|
QWidget::connect(_sources,
|
||||||
|
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
||||||
|
SLOT(SourceChanged(const SourceSelection &)));
|
||||||
|
QWidget::connect(_monitors, SIGNAL(currentIndexChanged(int)), this,
|
||||||
|
SLOT(MonitorChanged(int)));
|
||||||
|
|
||||||
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
|
{"{{windowTypes}}", _windowTypes}, {"{{types}}", _types},
|
||||||
|
{"{{scenes}}", _scenes}, {"{{sources}}", _sources},
|
||||||
|
{"{{monitors}}", _monitors},
|
||||||
|
};
|
||||||
|
|
||||||
|
placeWidgets(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.projector.entry.monitor"),
|
||||||
|
_monitorSelection, widgetPlaceholders);
|
||||||
|
|
||||||
|
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||||
|
placeWidgets(obs_module_text("AdvSceneSwitcher.action.projector.entry"),
|
||||||
|
mainLayout, widgetPlaceholders);
|
||||||
|
mainLayout->insertLayout(mainLayout->count() - 1, _monitorSelection);
|
||||||
|
setLayout(mainLayout);
|
||||||
|
|
||||||
|
_entryData = entryData;
|
||||||
|
UpdateEntryData();
|
||||||
|
_loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionProjectorEdit::UpdateEntryData()
|
||||||
|
{
|
||||||
|
if (!_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_windowTypes->setCurrentIndex(_entryData->_fullscreen ? 1 : 0);
|
||||||
|
_types->setCurrentIndex(static_cast<int>(_entryData->_type));
|
||||||
|
_scenes->SetScene(_entryData->_scene);
|
||||||
|
_sources->SetSource(_entryData->_source);
|
||||||
|
_monitors->setCurrentIndex(_entryData->_monitor);
|
||||||
|
SetWidgetVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionProjectorEdit::SceneChanged(const SceneSelection &s)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_scene = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionProjectorEdit::SourceChanged(const SourceSelection &source)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionProjectorEdit::MonitorChanged(int value)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_monitor = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionProjectorEdit::WindowTypeChanged(int value)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_fullscreen =
|
||||||
|
_windowTypes->currentText() ==
|
||||||
|
obs_module_text("AdvSceneSwitcher.action.projector.fullscreen");
|
||||||
|
SetWidgetVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionProjectorEdit::TypeChanged(int value)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_type = static_cast<MacroActionProjector::Type>(value);
|
||||||
|
SetWidgetVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionProjectorEdit::SetWidgetVisibility()
|
||||||
|
{
|
||||||
|
if (!_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_scenes->setVisible(_entryData->_type ==
|
||||||
|
MacroActionProjector::Type::SCENE);
|
||||||
|
_sources->setVisible(_entryData->_type ==
|
||||||
|
MacroActionProjector::Type::SOURCE);
|
||||||
|
setLayoutVisible(_monitorSelection, _entryData->_fullscreen);
|
||||||
|
|
||||||
|
adjustSize();
|
||||||
|
updateGeometry();
|
||||||
|
}
|
||||||
73
src/macro-core/macro-action-projector.hpp
Normal file
73
src/macro-core/macro-action-projector.hpp
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "macro-action-edit.hpp"
|
||||||
|
#include "scene-selection.hpp"
|
||||||
|
#include "source-selection.hpp"
|
||||||
|
|
||||||
|
class MacroActionProjector : public MacroAction {
|
||||||
|
public:
|
||||||
|
MacroActionProjector(Macro *m) : MacroAction(m) {}
|
||||||
|
bool PerformAction();
|
||||||
|
void LogAction() const;
|
||||||
|
bool Save(obs_data_t *obj) const;
|
||||||
|
bool Load(obs_data_t *obj);
|
||||||
|
std::string GetId() const { return id; };
|
||||||
|
static std::shared_ptr<MacroAction> Create(Macro *m)
|
||||||
|
{
|
||||||
|
return std::make_shared<MacroActionProjector>(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class Type {
|
||||||
|
SOURCE,
|
||||||
|
SCENE,
|
||||||
|
PREVIEW,
|
||||||
|
PROGRAM,
|
||||||
|
MULTIVIEW,
|
||||||
|
};
|
||||||
|
|
||||||
|
Type _type = Type::SCENE;
|
||||||
|
SourceSelection _source;
|
||||||
|
SceneSelection _scene;
|
||||||
|
int _monitor = 0;
|
||||||
|
bool _fullscreen = true;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool _registered;
|
||||||
|
static const std::string id;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MacroActionProjectorEdit : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MacroActionProjectorEdit(
|
||||||
|
QWidget *parent,
|
||||||
|
std::shared_ptr<MacroActionProjector> entryData = nullptr);
|
||||||
|
void UpdateEntryData();
|
||||||
|
static QWidget *Create(QWidget *parent,
|
||||||
|
std::shared_ptr<MacroAction> action)
|
||||||
|
{
|
||||||
|
return new MacroActionProjectorEdit(
|
||||||
|
parent, std::dynamic_pointer_cast<MacroActionProjector>(
|
||||||
|
action));
|
||||||
|
}
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void WindowTypeChanged(int value);
|
||||||
|
void TypeChanged(int value);
|
||||||
|
void SceneChanged(const SceneSelection &);
|
||||||
|
void SourceChanged(const SourceSelection &);
|
||||||
|
void MonitorChanged(int value);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QComboBox *_windowTypes;
|
||||||
|
QComboBox *_types;
|
||||||
|
SceneSelectionWidget *_scenes;
|
||||||
|
SourceSelectionWidget *_sources;
|
||||||
|
QHBoxLayout *_monitorSelection;
|
||||||
|
QComboBox *_monitors;
|
||||||
|
std::shared_ptr<MacroActionProjector> _entryData;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SetWidgetVisibility();
|
||||||
|
bool _loading = true;
|
||||||
|
};
|
||||||
@@ -335,7 +335,8 @@ void AdvSceneSwitcher::MacroSelectionChanged(const QItemSelection &,
|
|||||||
|
|
||||||
void AdvSceneSwitcher::HighlightOnChange()
|
void AdvSceneSwitcher::HighlightOnChange()
|
||||||
{
|
{
|
||||||
if (!switcher->macroProperties._highlightExecuted) {
|
if (!switcher->macroProperties._highlightActions &&
|
||||||
|
!switcher->macroProperties._highlightExecuted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -375,24 +375,24 @@ void MacroTreeModel::Add(std::shared_ptr<Macro> item)
|
|||||||
|
|
||||||
void MacroTreeModel::Remove(std::shared_ptr<Macro> item)
|
void MacroTreeModel::Remove(std::shared_ptr<Macro> item)
|
||||||
{
|
{
|
||||||
auto startIdx = GetItemModelIndex(item);
|
auto uiStartIdx = GetItemModelIndex(item);
|
||||||
if (startIdx == -1) {
|
if (uiStartIdx == -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto macroStartIdx = ModelIndexToMacroIndex(startIdx, _macros);
|
auto macroStartIdx = ModelIndexToMacroIndex(uiStartIdx, _macros);
|
||||||
|
|
||||||
auto endIdx = startIdx;
|
auto uiEndIdx = uiStartIdx;
|
||||||
auto macroEndIdx = macroStartIdx;
|
auto macroEndIdx = macroStartIdx;
|
||||||
|
|
||||||
bool isGroup = item->IsGroup();
|
bool isGroup = item->IsGroup();
|
||||||
if (isGroup) {
|
if (isGroup) {
|
||||||
macroEndIdx += item->GroupSize();
|
macroEndIdx += item->GroupSize();
|
||||||
if (!item->IsCollapsed()) {
|
if (!item->IsCollapsed()) {
|
||||||
endIdx = item->GroupSize();
|
uiEndIdx += item->GroupSize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
beginRemoveRows(QModelIndex(), startIdx, endIdx);
|
beginRemoveRows(QModelIndex(), uiStartIdx, uiEndIdx);
|
||||||
_macros.erase(std::next(_macros.begin(), macroStartIdx),
|
_macros.erase(std::next(_macros.begin(), macroStartIdx),
|
||||||
std::next(_macros.begin(), macroEndIdx + 1));
|
std::next(_macros.begin(), macroEndIdx + 1));
|
||||||
endRemoveRows();
|
endRemoveRows();
|
||||||
|
|||||||
@@ -342,7 +342,7 @@ MacroConditionVideoEdit::MacroConditionVideoEdit(
|
|||||||
_throttleCount(new QSpinBox()),
|
_throttleCount(new QSpinBox()),
|
||||||
_showMatch(new QPushButton(obs_module_text(
|
_showMatch(new QPushButton(obs_module_text(
|
||||||
"AdvSceneSwitcher.condition.video.showMatch"))),
|
"AdvSceneSwitcher.condition.video.showMatch"))),
|
||||||
_previewDialog(this, GetSwitcher()->interval)
|
_previewDialog(this)
|
||||||
{
|
{
|
||||||
_reduceLatency->setToolTip(obs_module_text(
|
_reduceLatency->setToolTip(obs_module_text(
|
||||||
"AdvSceneSwitcher.condition.video.reduceLatency.tooltip"));
|
"AdvSceneSwitcher.condition.video.reduceLatency.tooltip"));
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ PatternImageData createPatternData(QImage &pattern)
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void matchPattern(QImage &img, PatternImageData &patternData, double threshold,
|
void matchPattern(QImage &img, const PatternImageData &patternData,
|
||||||
cv::Mat &result, bool useAlphaAsMask)
|
double threshold, cv::Mat &result, bool useAlphaAsMask)
|
||||||
{
|
{
|
||||||
if (img.isNull() || patternData.rgbaPattern.empty()) {
|
if (img.isNull() || patternData.rgbaPattern.empty()) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -14,8 +14,9 @@ struct PatternImageData {
|
|||||||
};
|
};
|
||||||
|
|
||||||
PatternImageData createPatternData(QImage &pattern);
|
PatternImageData createPatternData(QImage &pattern);
|
||||||
void matchPattern(QImage &img, PatternImageData &patternData, double threshold,
|
void matchPattern(QImage &img, const PatternImageData &patternData,
|
||||||
cv::Mat &result, bool useAlphaAsMask = true);
|
double threshold, cv::Mat &result,
|
||||||
|
bool useAlphaAsMask = true);
|
||||||
void matchPattern(QImage &img, QImage &pattern, double threshold,
|
void matchPattern(QImage &img, QImage &pattern, double threshold,
|
||||||
cv::Mat &result, bool useAlphaAsMask);
|
cv::Mat &result, bool useAlphaAsMask);
|
||||||
std::vector<cv::Rect> matchObject(QImage &img, cv::CascadeClassifier &cascade,
|
std::vector<cv::Rect> matchObject(QImage &img, cv::CascadeClassifier &cascade,
|
||||||
|
|||||||
@@ -5,12 +5,11 @@
|
|||||||
|
|
||||||
#include <screenshot-helper.hpp>
|
#include <screenshot-helper.hpp>
|
||||||
|
|
||||||
PreviewDialog::PreviewDialog(QWidget *parent, int delay)
|
PreviewDialog::PreviewDialog(QWidget *parent)
|
||||||
: QDialog(parent),
|
: QDialog(parent),
|
||||||
_scrollArea(new QScrollArea),
|
_scrollArea(new QScrollArea),
|
||||||
_imageLabel(new QLabel(this)),
|
_imageLabel(new QLabel(this)),
|
||||||
_rubberBand(new QRubberBand(QRubberBand::Rectangle, this)),
|
_rubberBand(new QRubberBand(QRubberBand::Rectangle, this))
|
||||||
_delay(delay)
|
|
||||||
{
|
{
|
||||||
setWindowTitle("Advanced Scene Switcher");
|
setWindowTitle("Advanced Scene Switcher");
|
||||||
setWindowFlags(windowFlags() | Qt::WindowMaximizeButtonHint |
|
setWindowFlags(windowFlags() | Qt::WindowMaximizeButtonHint |
|
||||||
@@ -39,22 +38,12 @@ PreviewDialog::PreviewDialog(QWidget *parent, int delay)
|
|||||||
layout->addWidget(_statusLabel);
|
layout->addWidget(_statusLabel);
|
||||||
layout->addWidget(_scrollArea);
|
layout->addWidget(_scrollArea);
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
|
|
||||||
// This is a workaround to handle random segfaults triggered when using:
|
|
||||||
// QMetaObject::invokeMethod(this, "RedrawImage", Qt::QueuedConnection,
|
|
||||||
// Q_ARG(QImage, image));
|
|
||||||
// from within CheckForMatchLoop().
|
|
||||||
// Even using BlockingQueuedConnection causes deadlocks
|
|
||||||
_timer.setInterval(300);
|
|
||||||
QWidget::connect(&_timer, &QTimer::timeout, this,
|
|
||||||
&PreviewDialog::ResizeImageLabel);
|
|
||||||
_timer.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewDialog::mousePressEvent(QMouseEvent *event)
|
void PreviewDialog::mousePressEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
_selectingArea = true;
|
_selectingArea = true;
|
||||||
if (_type == Type::SHOW_MATCH) {
|
if (_type == PreviewType::SHOW_MATCH) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_origin = event->pos();
|
_origin = event->pos();
|
||||||
@@ -64,7 +53,7 @@ void PreviewDialog::mousePressEvent(QMouseEvent *event)
|
|||||||
|
|
||||||
void PreviewDialog::mouseMoveEvent(QMouseEvent *event)
|
void PreviewDialog::mouseMoveEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
if (_type == Type::SHOW_MATCH) {
|
if (_type == PreviewType::SHOW_MATCH) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_rubberBand->setGeometry(QRect(_origin, event->pos()).normalized());
|
_rubberBand->setGeometry(QRect(_origin, event->pos()).normalized());
|
||||||
@@ -72,7 +61,7 @@ void PreviewDialog::mouseMoveEvent(QMouseEvent *event)
|
|||||||
|
|
||||||
void PreviewDialog::mouseReleaseEvent(QMouseEvent *)
|
void PreviewDialog::mouseReleaseEvent(QMouseEvent *)
|
||||||
{
|
{
|
||||||
if (_type == Type::SHOW_MATCH) {
|
if (_type == PreviewType::SHOW_MATCH) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto selectionStart =
|
auto selectionStart =
|
||||||
@@ -102,14 +91,14 @@ void PreviewDialog::ShowMatch()
|
|||||||
{
|
{
|
||||||
Start();
|
Start();
|
||||||
_rubberBand->hide();
|
_rubberBand->hide();
|
||||||
_type = Type::SHOW_MATCH;
|
_type = PreviewType::SHOW_MATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewDialog::SelectArea()
|
void PreviewDialog::SelectArea()
|
||||||
{
|
{
|
||||||
_selectingArea = false;
|
_selectingArea = false;
|
||||||
Start();
|
Start();
|
||||||
_type = Type::SELECT_AREA;
|
_type = PreviewType::SELECT_AREA;
|
||||||
DrawFrame();
|
DrawFrame();
|
||||||
_statusLabel->setText(obs_module_text(
|
_statusLabel->setText(obs_module_text(
|
||||||
"AdvSceneSwitcher.condition.video.selectArea.status"));
|
"AdvSceneSwitcher.condition.video.selectArea.status"));
|
||||||
@@ -117,11 +106,8 @@ void PreviewDialog::SelectArea()
|
|||||||
|
|
||||||
void PreviewDialog::Stop()
|
void PreviewDialog::Stop()
|
||||||
{
|
{
|
||||||
_stop = true;
|
_thread.quit();
|
||||||
_cv.notify_all();
|
_thread.wait();
|
||||||
if (_thread.joinable()) {
|
|
||||||
_thread.join();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewDialog::closeEvent(QCloseEvent *event)
|
void PreviewDialog::closeEvent(QCloseEvent *event)
|
||||||
@@ -164,79 +150,66 @@ void PreviewDialog::ConditionChanged(int cond)
|
|||||||
_condition = static_cast<VideoCondition>(cond);
|
_condition = static_cast<VideoCondition>(cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewDialog::ResizeImageLabel()
|
void PreviewDialog::UpdateStatus(const QString &status)
|
||||||
{
|
{
|
||||||
|
_statusLabel->setText(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreviewDialog::UpdateImage(const QPixmap &image)
|
||||||
|
{
|
||||||
|
_imageLabel->setPixmap(image);
|
||||||
_imageLabel->adjustSize();
|
_imageLabel->adjustSize();
|
||||||
if (_type == Type::SELECT_AREA && !_selectingArea) {
|
if (_type == PreviewType::SELECT_AREA && !_selectingArea) {
|
||||||
DrawFrame();
|
DrawFrame();
|
||||||
}
|
}
|
||||||
|
emit NeedImage(_video, _type, _patternMatchParams, _patternImageData,
|
||||||
|
_objDetectParams, _areaParams, _condition);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewDialog::Start()
|
void PreviewDialog::Start()
|
||||||
{
|
{
|
||||||
if (_thread.joinable()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!_video.ValidSelection()) {
|
if (!_video.ValidSelection()) {
|
||||||
DisplayMessage(obs_module_text(
|
DisplayMessage(obs_module_text(
|
||||||
"AdvSceneSwitcher.condition.video.screenshotFail"));
|
"AdvSceneSwitcher.condition.video.screenshotFail"));
|
||||||
close();
|
close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_stop = false;
|
|
||||||
_thread = std::thread(&PreviewDialog::CheckForMatchLoop, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PreviewDialog::CheckForMatchLoop()
|
if (_thread.isRunning()) {
|
||||||
{
|
return;
|
||||||
while (!_stop) {
|
|
||||||
std::unique_lock<std::mutex> lock(_mtx);
|
|
||||||
auto source = obs_weak_source_get_source(_video.GetVideo());
|
|
||||||
ScreenshotHelper screenshot(source);
|
|
||||||
obs_source_release(source);
|
|
||||||
_cv.wait_for(lock, std::chrono::milliseconds(_delay));
|
|
||||||
if (_stop || isHidden()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!_video.ValidSelection()) {
|
|
||||||
_statusLabel->setText(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.condition.video.screenshotFail"));
|
|
||||||
_imageLabel->setPixmap(QPixmap());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!screenshot.done) {
|
|
||||||
_statusLabel->setText(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.condition.video.screenshotFail"));
|
|
||||||
_imageLabel->setPixmap(QPixmap());
|
|
||||||
if (_delay < 1000) {
|
|
||||||
_delay += 50;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (screenshot.image.width() == 0 ||
|
|
||||||
screenshot.image.height() == 0) {
|
|
||||||
_statusLabel->setText(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.condition.video.screenshotEmpty"));
|
|
||||||
_imageLabel->setPixmap(QPixmap());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_type == Type::SHOW_MATCH) {
|
|
||||||
if (_areaParams.enable) {
|
|
||||||
screenshot.image = screenshot.image.copy(
|
|
||||||
_areaParams.area.x, _areaParams.area.y,
|
|
||||||
_areaParams.area.width,
|
|
||||||
_areaParams.area.height);
|
|
||||||
}
|
|
||||||
MarkMatch(screenshot.image);
|
|
||||||
} else {
|
|
||||||
_statusLabel->setText("");
|
|
||||||
}
|
|
||||||
_imageLabel->setPixmap(QPixmap::fromImage(screenshot.image));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PreviewImage *worker = new PreviewImage();
|
||||||
|
worker->moveToThread(&_thread);
|
||||||
|
connect(&_thread, &QThread::finished, worker, &QObject::deleteLater);
|
||||||
|
connect(worker, &PreviewImage::ImageReady, this,
|
||||||
|
&PreviewDialog::UpdateImage);
|
||||||
|
connect(worker, &PreviewImage::StatusUpdate, this,
|
||||||
|
&PreviewDialog::UpdateStatus);
|
||||||
|
connect(this, &PreviewDialog::NeedImage, worker,
|
||||||
|
&PreviewImage::CreateImage);
|
||||||
|
_thread.start();
|
||||||
|
|
||||||
|
emit NeedImage(_video, _type, _patternMatchParams, _patternImageData,
|
||||||
|
_objDetectParams, _areaParams, _condition);
|
||||||
}
|
}
|
||||||
|
|
||||||
void markPatterns(cv::Mat &matchResult, QImage &image, cv::Mat &pattern)
|
void PreviewDialog::DrawFrame()
|
||||||
|
{
|
||||||
|
if (!_video.ValidSelection()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto imageStart =
|
||||||
|
_imageLabel->mapToGlobal(_imageLabel->rect().topLeft());
|
||||||
|
auto windowStart = mapToGlobal(rect().topLeft());
|
||||||
|
_rubberBand->resize(_areaParams.area.width, _areaParams.area.height);
|
||||||
|
_rubberBand->move(
|
||||||
|
_areaParams.area.x + (imageStart.x() - windowStart.x()),
|
||||||
|
_areaParams.area.y + (imageStart.y() - windowStart.y()));
|
||||||
|
_rubberBand->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void markPatterns(cv::Mat &matchResult, QImage &image, const cv::Mat &pattern)
|
||||||
{
|
{
|
||||||
auto matchImg = QImageToMat(image);
|
auto matchImg = QImageToMat(image);
|
||||||
for (int row = 0; row < matchResult.rows - 1; row++) {
|
for (int row = 0; row < matchResult.rows - 1; row++) {
|
||||||
@@ -262,50 +235,79 @@ void markObjects(QImage &image, std::vector<cv::Rect> &objects)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewDialog::MarkMatch(QImage &screenshot)
|
void PreviewImage::CreateImage(const VideoInput &video, PreviewType type,
|
||||||
|
const PatternMatchParameters &patternMatchParams,
|
||||||
|
const PatternImageData &patternImageData,
|
||||||
|
ObjDetectParamerts objDetectParams,
|
||||||
|
const AreaParamters &areaParams,
|
||||||
|
VideoCondition condition)
|
||||||
{
|
{
|
||||||
if (_condition == VideoCondition::PATTERN) {
|
auto source = obs_weak_source_get_source(video.GetVideo());
|
||||||
|
ScreenshotHelper screenshot(source, true);
|
||||||
|
obs_source_release(source);
|
||||||
|
|
||||||
|
if (!video.ValidSelection() || !screenshot.done) {
|
||||||
|
emit StatusUpdate(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.condition.video.screenshotFail"));
|
||||||
|
emit ImageReady(QPixmap());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (screenshot.image.width() == 0 || screenshot.image.height() == 0) {
|
||||||
|
emit StatusUpdate(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.condition.video.screenshotEmpty"));
|
||||||
|
emit ImageReady(QPixmap());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == PreviewType::SHOW_MATCH) {
|
||||||
|
if (areaParams.enable) {
|
||||||
|
screenshot.image = screenshot.image.copy(
|
||||||
|
areaParams.area.x, areaParams.area.y,
|
||||||
|
areaParams.area.width, areaParams.area.height);
|
||||||
|
}
|
||||||
|
// Will emit status label update
|
||||||
|
MarkMatch(screenshot.image, patternMatchParams,
|
||||||
|
patternImageData, objDetectParams, condition);
|
||||||
|
} else {
|
||||||
|
emit StatusUpdate("");
|
||||||
|
}
|
||||||
|
emit ImageReady(QPixmap::fromImage(screenshot.image));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreviewImage::MarkMatch(QImage &screenshot,
|
||||||
|
const PatternMatchParameters &patternMatchParams,
|
||||||
|
const PatternImageData &patternImageData,
|
||||||
|
ObjDetectParamerts &objDetectParams,
|
||||||
|
VideoCondition condition)
|
||||||
|
{
|
||||||
|
if (condition == VideoCondition::PATTERN) {
|
||||||
cv::Mat result;
|
cv::Mat result;
|
||||||
matchPattern(screenshot, _patternImageData,
|
matchPattern(screenshot, patternImageData,
|
||||||
_patternMatchParams.threshold, result,
|
patternMatchParams.threshold, result,
|
||||||
_patternMatchParams.useAlphaAsMask);
|
patternMatchParams.useAlphaAsMask);
|
||||||
if (countNonZero(result) == 0) {
|
if (countNonZero(result) == 0) {
|
||||||
_statusLabel->setText(obs_module_text(
|
emit StatusUpdate(obs_module_text(
|
||||||
"AdvSceneSwitcher.condition.video.patternMatchFail"));
|
"AdvSceneSwitcher.condition.video.patternMatchFail"));
|
||||||
} else {
|
} else {
|
||||||
_statusLabel->setText(obs_module_text(
|
emit StatusUpdate(obs_module_text(
|
||||||
"AdvSceneSwitcher.condition.video.patternMatchSuccess"));
|
"AdvSceneSwitcher.condition.video.patternMatchSuccess"));
|
||||||
markPatterns(result, screenshot,
|
markPatterns(result, screenshot,
|
||||||
_patternImageData.rgbaPattern);
|
patternImageData.rgbaPattern);
|
||||||
}
|
}
|
||||||
} else if (_condition == VideoCondition::OBJECT) {
|
} else if (condition == VideoCondition::OBJECT) {
|
||||||
auto objects = matchObject(screenshot, _objDetectParams.cascade,
|
auto objects = matchObject(screenshot, objDetectParams.cascade,
|
||||||
_objDetectParams.scaleFactor,
|
objDetectParams.scaleFactor,
|
||||||
_objDetectParams.minNeighbors,
|
objDetectParams.minNeighbors,
|
||||||
_objDetectParams.minSize.CV(),
|
objDetectParams.minSize.CV(),
|
||||||
_objDetectParams.maxSize.CV());
|
objDetectParams.maxSize.CV());
|
||||||
if (objects.empty()) {
|
if (objects.empty()) {
|
||||||
_statusLabel->setText(obs_module_text(
|
emit StatusUpdate(obs_module_text(
|
||||||
"AdvSceneSwitcher.condition.video.objectMatchFail"));
|
"AdvSceneSwitcher.condition.video.objectMatchFail"));
|
||||||
} else {
|
} else {
|
||||||
_statusLabel->setText(obs_module_text(
|
emit StatusUpdate(obs_module_text(
|
||||||
"AdvSceneSwitcher.condition.video.objectMatchSuccess"));
|
"AdvSceneSwitcher.condition.video.objectMatchSuccess"));
|
||||||
markObjects(screenshot, objects);
|
markObjects(screenshot, objects);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewDialog::DrawFrame()
|
|
||||||
{
|
|
||||||
if (!_video.ValidSelection()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto imageStart =
|
|
||||||
_imageLabel->mapToGlobal(_imageLabel->rect().topLeft());
|
|
||||||
auto windowStart = mapToGlobal(rect().topLeft());
|
|
||||||
_rubberBand->resize(_areaParams.area.width, _areaParams.area.height);
|
|
||||||
_rubberBand->move(
|
|
||||||
_areaParams.area.x + (imageStart.x() - windowStart.x()),
|
|
||||||
_areaParams.area.y + (imageStart.y() - windowStart.y()));
|
|
||||||
_rubberBand->show();
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,21 +4,40 @@
|
|||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
#include <QTimer>
|
#include <QThread>
|
||||||
|
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QRubberBand>
|
#include <QRubberBand>
|
||||||
#include <QPoint>
|
#include <QPoint>
|
||||||
|
|
||||||
#include <thread>
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <condition_variable>
|
|
||||||
|
enum class PreviewType {
|
||||||
|
SHOW_MATCH,
|
||||||
|
SELECT_AREA,
|
||||||
|
};
|
||||||
|
|
||||||
|
class PreviewImage : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void CreateImage(const VideoInput &, PreviewType,
|
||||||
|
const PatternMatchParameters &,
|
||||||
|
const PatternImageData &, ObjDetectParamerts,
|
||||||
|
const AreaParamters &, VideoCondition);
|
||||||
|
signals:
|
||||||
|
void ImageReady(const QPixmap &);
|
||||||
|
void StatusUpdate(const QString &);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void MarkMatch(QImage &screenshot, const PatternMatchParameters &,
|
||||||
|
const PatternImageData &, ObjDetectParamerts &,
|
||||||
|
VideoCondition);
|
||||||
|
};
|
||||||
|
|
||||||
class PreviewDialog : public QDialog {
|
class PreviewDialog : public QDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PreviewDialog(QWidget *parent, int delay);
|
PreviewDialog(QWidget *parent);
|
||||||
virtual ~PreviewDialog();
|
virtual ~PreviewDialog();
|
||||||
void ShowMatch();
|
void ShowMatch();
|
||||||
void SelectArea();
|
void SelectArea();
|
||||||
@@ -32,14 +51,17 @@ public slots:
|
|||||||
void AreaParamtersChanged(const AreaParamters &);
|
void AreaParamtersChanged(const AreaParamters &);
|
||||||
void ConditionChanged(int cond);
|
void ConditionChanged(int cond);
|
||||||
private slots:
|
private slots:
|
||||||
void ResizeImageLabel();
|
void UpdateImage(const QPixmap &);
|
||||||
|
void UpdateStatus(const QString &);
|
||||||
signals:
|
signals:
|
||||||
void SelectionAreaChanged(QRect area);
|
void SelectionAreaChanged(QRect area);
|
||||||
|
void NeedImage(const VideoInput &, PreviewType,
|
||||||
|
const PatternMatchParameters &, const PatternImageData &,
|
||||||
|
ObjDetectParamerts, const AreaParamters &,
|
||||||
|
VideoCondition);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Start();
|
void Start();
|
||||||
void CheckForMatchLoop();
|
|
||||||
void MarkMatch(QImage &screenshot);
|
|
||||||
void DrawFrame();
|
void DrawFrame();
|
||||||
|
|
||||||
void mousePressEvent(QMouseEvent *event);
|
void mousePressEvent(QMouseEvent *event);
|
||||||
@@ -56,21 +78,13 @@ private:
|
|||||||
QScrollArea *_scrollArea;
|
QScrollArea *_scrollArea;
|
||||||
QLabel *_statusLabel;
|
QLabel *_statusLabel;
|
||||||
QLabel *_imageLabel;
|
QLabel *_imageLabel;
|
||||||
QTimer _timer;
|
|
||||||
|
|
||||||
QPoint _origin;
|
QPoint _origin;
|
||||||
QRubberBand *_rubberBand = nullptr;
|
QRubberBand *_rubberBand = nullptr;
|
||||||
std::atomic_bool _selectingArea = {false};
|
std::atomic_bool _selectingArea = {false};
|
||||||
|
|
||||||
std::mutex _mtx;
|
PreviewType _type = PreviewType::SHOW_MATCH;
|
||||||
std::condition_variable _cv;
|
|
||||||
std::thread _thread;
|
|
||||||
std::atomic_bool _stop = {true};
|
|
||||||
|
|
||||||
enum class Type {
|
std::mutex _mtx;
|
||||||
SHOW_MATCH,
|
QThread _thread;
|
||||||
SELECT_AREA,
|
|
||||||
};
|
|
||||||
Type _type = Type::SHOW_MATCH;
|
|
||||||
int _delay = 300;
|
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user