mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-03-21 17:34:57 -05:00
Merge cc50928285 into 9301ead060
This commit is contained in:
commit
62153070a0
|
|
@ -2246,6 +2246,8 @@ AdvSceneSwitcher.tempVar.video.text="OCR text"
|
|||
AdvSceneSwitcher.tempVar.video.text.description="The text detected in a given video input frame."
|
||||
AdvSceneSwitcher.tempVar.video.color="Average color"
|
||||
AdvSceneSwitcher.tempVar.video.color.description="The average RGB color in a given video input frame in HexArgb format."
|
||||
AdvSceneSwitcher.tempVar.video.dominantColor="Dominant color"
|
||||
AdvSceneSwitcher.tempVar.video.dominantColor.description="The most dominant RGB color in a given video input frame in HexArgb format."
|
||||
|
||||
AdvSceneSwitcher.tempVar.websocket.message="Received websocket message"
|
||||
AdvSceneSwitcher.tempVar.websocket.message.description="The received websocket message, which matched the given pattern"
|
||||
|
|
|
|||
|
|
@ -17,6 +17,14 @@ namespace advss {
|
|||
|
||||
const std::string MacroActionVariable::id = "variable";
|
||||
|
||||
std::vector<TempVariableRef> MacroActionVariable::GetTempVarRefs() const
|
||||
{
|
||||
if (!_tempVar.HasValidID()) {
|
||||
return {};
|
||||
}
|
||||
return {_tempVar};
|
||||
}
|
||||
|
||||
bool MacroActionVariable::_registered = MacroActionFactory::Register(
|
||||
MacroActionVariable::id,
|
||||
{MacroActionVariable::Create, MacroActionVariableEdit::Create,
|
||||
|
|
@ -1450,6 +1458,7 @@ void MacroActionVariableEdit::SelectionChanged(const TempVariableRef &var)
|
|||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_tempVar = var;
|
||||
IncrementTempVarInUseGeneration();
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ public:
|
|||
bool PostLoad();
|
||||
std::string GetShortDesc() const;
|
||||
std::string GetId() const { return id; };
|
||||
std::vector<TempVariableRef> GetTempVarRefs() const;
|
||||
static std::shared_ptr<MacroAction> Create(Macro *m);
|
||||
std::shared_ptr<MacroAction> Copy() const;
|
||||
void SetSegmentIndexValue(int);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,14 @@ namespace advss {
|
|||
|
||||
const std::string MacroConditionTempVar::id = "temp_var";
|
||||
|
||||
std::vector<TempVariableRef> MacroConditionTempVar::GetTempVarRefs() const
|
||||
{
|
||||
if (!_tempVar.HasValidID()) {
|
||||
return {};
|
||||
}
|
||||
return {_tempVar};
|
||||
}
|
||||
|
||||
bool MacroConditionTempVar::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionTempVar::id,
|
||||
{MacroConditionTempVar::Create, MacroConditionTempVarEdit::Create,
|
||||
|
|
@ -266,6 +274,7 @@ void MacroConditionTempVarEdit::VariableChanged(const TempVariableRef &var)
|
|||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_tempVar = var;
|
||||
IncrementTempVarInUseGeneration();
|
||||
}
|
||||
|
||||
void MacroConditionTempVarEdit::Variable2Changed(const QString &text)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ public:
|
|||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc() const;
|
||||
std::string GetId() const { return id; };
|
||||
std::vector<TempVariableRef> GetTempVarRefs() const;
|
||||
static std::shared_ptr<MacroCondition> Create(Macro *m)
|
||||
{
|
||||
return std::make_shared<MacroConditionTempVar>(m);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,11 @@
|
|||
|
||||
namespace advss {
|
||||
|
||||
std::vector<TempVariableRef> MacroSegment::GetTempVarRefs() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
MacroSegment::MacroSegment(Macro *m, bool supportsVariableValue)
|
||||
: _macro(m),
|
||||
_supportsVariableValue(supportsVariableValue)
|
||||
|
|
@ -152,6 +157,16 @@ void MacroSegment::AddTempvar(const std::string &id, const std::string &name,
|
|||
NotifyUIAboutTempVarChange(this);
|
||||
}
|
||||
|
||||
bool MacroSegment::IsTempVarInUse(const std::string &id) const
|
||||
{
|
||||
for (const auto &var : _tempVariables) {
|
||||
if (var.ID() == id) {
|
||||
return var.IsInUse();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MacroSegment::SetTempVarValue(const std::string &id,
|
||||
const std::string &value)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ public:
|
|||
std::string GetCustomLabel() const { return _customLabel; }
|
||||
virtual bool Save(obs_data_t *obj) const = 0;
|
||||
virtual bool Load(obs_data_t *obj) = 0;
|
||||
virtual std::vector<TempVariableRef> GetTempVarRefs() const;
|
||||
virtual bool PostLoad();
|
||||
virtual std::string GetShortDesc() const;
|
||||
virtual std::string GetId() const = 0;
|
||||
|
|
@ -54,6 +55,7 @@ protected:
|
|||
void AddTempvar(const std::string &id, const std::string &name,
|
||||
const std::string &description = "");
|
||||
|
||||
bool IsTempVarInUse(const std::string &id) const;
|
||||
void SetTempVarValue(const std::string &id, const std::string &value);
|
||||
|
||||
template<typename T, typename = std::enable_if_t<
|
||||
|
|
@ -64,6 +66,14 @@ protected:
|
|||
: std::string("false"));
|
||||
}
|
||||
|
||||
template<typename F, typename = std::enable_if_t<std::is_invocable_v<F>>>
|
||||
void SetTempVarValue(const std::string &id, F &&valueProvider)
|
||||
{
|
||||
if (IsTempVarInUse(id)) {
|
||||
SetTempVarValue(id, valueProvider());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void ClearAvailableTempvars();
|
||||
std::optional<const TempVariable>
|
||||
|
|
|
|||
|
|
@ -10,9 +10,12 @@
|
|||
|
||||
#include <QVariant>
|
||||
#include <QAbstractItemView>
|
||||
#include <atomic>
|
||||
|
||||
Q_DECLARE_METATYPE(advss::TempVariableRef);
|
||||
|
||||
static std::atomic<uint64_t> tempVarInUseGeneration{0};
|
||||
|
||||
namespace advss {
|
||||
|
||||
TempVariable::TempVariable(const std::string &id, const std::string &name,
|
||||
|
|
@ -120,6 +123,60 @@ TempVariableRef TempVariable::GetRef() const
|
|||
return ref;
|
||||
}
|
||||
|
||||
static bool refsContain(const std::vector<TempVariableRef> &refs,
|
||||
const TempVariableRef &ref)
|
||||
{
|
||||
for (const auto &r : refs) {
|
||||
if (r == ref) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static bool segmentsReferTo(const T &segments, const TempVariableRef &ref)
|
||||
{
|
||||
for (const auto &segment : segments) {
|
||||
if (refsContain(segment->GetTempVarRefs(), ref)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TempVariable::IsInUse() const
|
||||
{
|
||||
const auto currentGen =
|
||||
tempVarInUseGeneration.load(std::memory_order_relaxed);
|
||||
if (_isInUseCacheGeneration == currentGen) {
|
||||
return _isInUseCache;
|
||||
}
|
||||
|
||||
bool inUse = false;
|
||||
const auto ref = GetRef();
|
||||
|
||||
if (ref.HasValidID()) {
|
||||
for (const auto ¯o : GetAllMacros()) {
|
||||
if (segmentsReferTo(macro->Conditions(), ref) ||
|
||||
segmentsReferTo(macro->Actions(), ref) ||
|
||||
segmentsReferTo(macro->ElseActions(), ref)) {
|
||||
inUse = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_isInUseCache = inUse;
|
||||
_isInUseCacheGeneration = currentGen;
|
||||
return inUse;
|
||||
}
|
||||
|
||||
void IncrementTempVarInUseGeneration()
|
||||
{
|
||||
tempVarInUseGeneration.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
TempVariableRef::SegmentType TempVariableRef::GetType() const
|
||||
{
|
||||
auto segment = _segment.lock();
|
||||
|
|
@ -665,6 +722,7 @@ TempVarSignalManager *TempVarSignalManager::Instance()
|
|||
|
||||
void NotifyUIAboutTempVarChange(MacroSegment *segment)
|
||||
{
|
||||
IncrementTempVarInUseGeneration();
|
||||
obs_queue_task(
|
||||
OBS_TASK_UI,
|
||||
[](void *segment) {
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ public:
|
|||
void SetValue(const std::string &val);
|
||||
void InvalidateValue();
|
||||
TempVariableRef GetRef() const;
|
||||
EXPORT bool IsInUse() const;
|
||||
|
||||
private:
|
||||
std::string _id = "";
|
||||
|
|
@ -53,6 +54,8 @@ private:
|
|||
mutable std::mutex _lastValuesMutex;
|
||||
std::vector<std::string> _lastValues;
|
||||
bool _valueIsValid = false;
|
||||
mutable bool _isInUseCache = false;
|
||||
mutable uint64_t _isInUseCacheGeneration = UINT64_MAX;
|
||||
|
||||
std::weak_ptr<MacroSegment> _segment;
|
||||
friend TempVariableSelection;
|
||||
|
|
@ -122,5 +125,6 @@ private:
|
|||
};
|
||||
|
||||
void NotifyUIAboutTempVarChange(MacroSegment *);
|
||||
EXPORT void IncrementTempVarInUseGeneration();
|
||||
|
||||
} // namespace advss
|
||||
|
|
|
|||
|
|
@ -9,6 +9,14 @@ namespace advss {
|
|||
|
||||
const std::string MacroActionFilter::id = "filter";
|
||||
|
||||
std::vector<TempVariableRef> MacroActionFilter::GetTempVarRefs() const
|
||||
{
|
||||
if (!_tempVar.HasValidID()) {
|
||||
return {};
|
||||
}
|
||||
return {_tempVar};
|
||||
}
|
||||
|
||||
bool MacroActionFilter::_registered = MacroActionFactory::Register(
|
||||
MacroActionFilter::id,
|
||||
{MacroActionFilter::Create, MacroActionFilterEdit::Create,
|
||||
|
|
@ -428,6 +436,7 @@ void MacroActionFilterEdit::SelectionChanged(const TempVariableRef &var)
|
|||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_tempVar = var;
|
||||
IncrementTempVarInUseGeneration();
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::SelectionChanged(const SourceSetting &setting)
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ public:
|
|||
SettingsInputMethod _settingsInputMethod =
|
||||
SettingsInputMethod::INDIVIDUAL_MANUAL;
|
||||
|
||||
std::vector<TempVariableRef> GetTempVarRefs() const;
|
||||
|
||||
SourceSelection _source;
|
||||
FilterSelection _filter;
|
||||
Action _action = Action::ENABLE;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,14 @@ namespace advss {
|
|||
|
||||
const std::string MacroActionSource::id = "source";
|
||||
|
||||
std::vector<TempVariableRef> MacroActionSource::GetTempVarRefs() const
|
||||
{
|
||||
if (!_tempVar.HasValidID()) {
|
||||
return {};
|
||||
}
|
||||
return {_tempVar};
|
||||
}
|
||||
|
||||
bool MacroActionSource::_registered = MacroActionFactory::Register(
|
||||
MacroActionSource::id,
|
||||
{MacroActionSource::Create, MacroActionSourceEdit::Create,
|
||||
|
|
@ -652,6 +660,7 @@ void MacroActionSourceEdit::SelectionChanged(const TempVariableRef &var)
|
|||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_tempVar = var;
|
||||
IncrementTempVarInUseGeneration();
|
||||
}
|
||||
|
||||
void MacroActionSourceEdit::SettingsInputMethodChanged(int idx)
|
||||
|
|
|
|||
|
|
@ -15,16 +15,22 @@ namespace advss {
|
|||
class MacroActionSource : public MacroAction {
|
||||
public:
|
||||
MacroActionSource(Macro *m) : MacroAction(m) {}
|
||||
bool PerformAction();
|
||||
void LogAction() const;
|
||||
bool Save(obs_data_t *obj) const;
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc() const;
|
||||
std::string GetId() const { return id; };
|
||||
|
||||
static std::shared_ptr<MacroAction> Create(Macro *m);
|
||||
std::shared_ptr<MacroAction> Copy() const;
|
||||
|
||||
bool PerformAction();
|
||||
void LogAction() const;
|
||||
|
||||
bool Save(obs_data_t *obj) const;
|
||||
bool Load(obs_data_t *obj);
|
||||
|
||||
std::string GetShortDesc() const;
|
||||
std::string GetId() const { return id; };
|
||||
|
||||
void ResolveVariablesToFixedValues();
|
||||
void SetupTempVars();
|
||||
std::vector<TempVariableRef> GetTempVarRefs() const;
|
||||
|
||||
enum class Action {
|
||||
ENABLE,
|
||||
|
|
|
|||
|
|
@ -283,10 +283,18 @@ bool MacroConditionVideo::ScreenshotContainsPattern()
|
|||
SetTempVarValue("patternCount", "0");
|
||||
return false;
|
||||
}
|
||||
const auto count = countNonZero(result);
|
||||
|
||||
SetTempVarValue("similarity", std::to_string(bestMatchValue));
|
||||
SetTempVarValue("patternCount", std::to_string(count));
|
||||
return count > 0;
|
||||
|
||||
if (IsTempVarInUse("patternCount")) {
|
||||
const auto count = CountPatternMatches(
|
||||
result, {_patternImageData.rgbaPattern.cols,
|
||||
_patternImageData.rgbaPattern.rows});
|
||||
SetTempVarValue("patternCount", std::to_string(count));
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
return countNonZero(result) > 0;
|
||||
}
|
||||
|
||||
bool MacroConditionVideo::FileInputIsUpToDate() const
|
||||
|
|
@ -369,13 +377,19 @@ bool MacroConditionVideo::CheckColor()
|
|||
_screenshotData.GetImage(), _colorParameters.color,
|
||||
_colorParameters.colorThreshold,
|
||||
_colorParameters.matchThreshold);
|
||||
// Way too slow for now
|
||||
//SetTempVarValue("dominantColor", GetDominantColor(_screenshotData.image, 3)
|
||||
// .name(QColor::HexArgb)
|
||||
// .toStdString());
|
||||
SetTempVarValue("color", GetAverageColor(_screenshotData.GetImage())
|
||||
.name(QColor::HexArgb)
|
||||
.toStdString());
|
||||
|
||||
SetTempVarValue("color", [&]() {
|
||||
return GetAverageColor(_screenshotData.GetImage())
|
||||
.name(QColor::HexArgb)
|
||||
.toStdString();
|
||||
});
|
||||
|
||||
SetTempVarValue("dominantColor", [&]() {
|
||||
return GetDominantColor(_screenshotData.GetImage(), 3)
|
||||
.name(QColor::HexArgb)
|
||||
.toStdString();
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -471,6 +485,12 @@ void MacroConditionVideo::SetupTempVars()
|
|||
obs_module_text("AdvSceneSwitcher.tempVar.video.color"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.video.color.description"));
|
||||
AddTempvar(
|
||||
"dominantColor",
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.video.dominantColor"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.video.dominantColor.description"));
|
||||
break;
|
||||
case VideoCondition::MATCH:
|
||||
case VideoCondition::DIFFER:
|
||||
|
|
|
|||
|
|
@ -97,6 +97,35 @@ double MatchPattern(QImage &img, const PatternImageData &patternData,
|
|||
return bestFitValue;
|
||||
}
|
||||
|
||||
int CountPatternMatches(const cv::Mat &result, const cv::Size &patternSize)
|
||||
{
|
||||
if (result.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
cv::Mat work = result.clone();
|
||||
int count = 0;
|
||||
|
||||
while (true) {
|
||||
double maxVal;
|
||||
cv::Point maxLoc;
|
||||
cv::minMaxLoc(work, nullptr, &maxVal, nullptr, &maxLoc);
|
||||
if (maxVal <= 0.0) {
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
// Suppress the template-sized region around this match so
|
||||
// overlapping high-scoring positions are not counted separately
|
||||
int x = std::max(0, maxLoc.x - patternSize.width / 2);
|
||||
int y = std::max(0, maxLoc.y - patternSize.height / 2);
|
||||
int w = std::min(patternSize.width, work.cols - x);
|
||||
int h = std::min(patternSize.height, work.rows - y);
|
||||
work(cv::Rect(x, y, w, h)) = 0.0f;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
double MatchPattern(QImage &img, QImage &pattern, double threshold,
|
||||
cv::Mat &result, bool useAlphaAsMask,
|
||||
cv::TemplateMatchModes matchColor)
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ double MatchPattern(QImage &img, const PatternImageData &patternData,
|
|||
double MatchPattern(QImage &img, QImage &pattern, double threshold,
|
||||
cv::Mat &result, bool useAlphaAsMask,
|
||||
cv::TemplateMatchModes matchMode);
|
||||
int CountPatternMatches(const cv::Mat &result, const cv::Size &patternSize);
|
||||
std::vector<cv::Rect> MatchObject(QImage &img, cv::CascadeClassifier &cascade,
|
||||
double scaleFactor, int minNeighbors,
|
||||
const cv::Size &minSize,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user