Add option to wait for variable changes to "Wait" action type
Some checks are pending
debian-build / build (push) Waiting to run
Check locale / ubuntu64 (push) Waiting to run
Push to master / Check Formatting 🔍 (push) Waiting to run
Push to master / Build Project 🧱 (push) Waiting to run
Push to master / Create Release 🛫 (push) Blocked by required conditions

This commit is contained in:
WarmUpTill 2026-06-12 22:43:15 +02:00 committed by WarmUpTill
parent 3a556113aa
commit ea1dea8621
11 changed files with 425 additions and 52 deletions

View File

@ -382,8 +382,8 @@ AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Warten, bis der Übergan
AdvSceneSwitcher.action.wait="Warten"
AdvSceneSwitcher.action.wait.type.fixed="fixe"
AdvSceneSwitcher.action.wait.type.random="zufällig"
AdvSceneSwitcher.action.wait.entry.fixed="Warte für {{waitType}} Dauer von {{duration}}"
AdvSceneSwitcher.action.wait.entry.random="Warte für {{waitType}} Dauer von {{duration}} bis {{duration2}}"
AdvSceneSwitcher.action.wait.layout.fixed="Warte für {{waitType}} Dauer von {{duration}}"
AdvSceneSwitcher.action.wait.layout.random="Warte für {{waitType}} Dauer von {{duration}} bis {{duration2}}"
AdvSceneSwitcher.action.audio="Audio"
AdvSceneSwitcher.action.audio.type.mute="Stummgeschaltet"
AdvSceneSwitcher.action.audio.type.unmute="Nicht stummgeschaltet"

View File

@ -899,8 +899,18 @@ AdvSceneSwitcher.action.scene.canvasNotSupported="Not supported by the currently
AdvSceneSwitcher.action.wait="Wait"
AdvSceneSwitcher.action.wait.type.fixed="fixed"
AdvSceneSwitcher.action.wait.type.random="random"
AdvSceneSwitcher.action.wait.entry.fixed="Wait for{{waitType}}duration of{{duration}}"
AdvSceneSwitcher.action.wait.entry.random="Wait for{{waitType}}duration from{{duration}}to{{duration2}}"
AdvSceneSwitcher.action.wait.type.variableCondition="variable"
AdvSceneSwitcher.action.wait.layout.fixed="Wait for{{waitType}}duration of{{duration}}"
AdvSceneSwitcher.action.wait.layout.random="Wait for{{waitType}}duration from{{duration}}to{{duration2}}"
AdvSceneSwitcher.action.wait.condition.equals="equals"
AdvSceneSwitcher.action.wait.condition.doesNotEqual="does not equal"
AdvSceneSwitcher.action.wait.condition.isEmpty="is empty"
AdvSceneSwitcher.action.wait.condition.lessThan="is less than"
AdvSceneSwitcher.action.wait.condition.greaterThan="is greater than"
AdvSceneSwitcher.action.wait.layout.variableCondition="Wait until{{waitType}}{{variable}}{{condition}}{{strValue}}{{numValue}}{{regex}}"
AdvSceneSwitcher.action.wait.layout.timeout="Timeout:{{useTimeout}}{{conditionTimeout}}"
AdvSceneSwitcher.tempVar.wait.timedOut="Timed out"
AdvSceneSwitcher.tempVar.wait.timedOut.description="True if the wait action timed out before the condition was met, false if the condition was met in time"
AdvSceneSwitcher.action.audio="Audio"
AdvSceneSwitcher.action.audio.type.mute="Mute"
AdvSceneSwitcher.action.audio.type.unmute="Unmute"

View File

@ -312,8 +312,8 @@ AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Espere hasta que se comp
AdvSceneSwitcher.action.wait="Esperar"
AdvSceneSwitcher.action.wait.type.fixed="fijo"
AdvSceneSwitcher.action.wait.type.random="aleatorio"
AdvSceneSwitcher.action.wait.entry.fixed="Espere {{waitType}} de {{duration}}"
AdvSceneSwitcher.action.wait.entry.random="Espere {{waitType}} de {{duration}} a {{duration2}}"
AdvSceneSwitcher.action.wait.layout.fixed="Espere {{waitType}} de {{duration}}"
AdvSceneSwitcher.action.wait.layout.random="Espere {{waitType}} de {{duration}} a {{duration2}}"
AdvSceneSwitcher.action.audio="Audio"
AdvSceneSwitcher.action.audio.type.mute="Silencio"
AdvSceneSwitcher.action.audio.type.unmute="Activar silencio"

View File

@ -460,8 +460,8 @@ AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Attendre que la transiti
AdvSceneSwitcher.action.wait="Attendre"
AdvSceneSwitcher.action.wait.type.fixed="fixe"
AdvSceneSwitcher.action.wait.type.random="aléatoire"
AdvSceneSwitcher.action.wait.entry.fixed="Attendre pour{{waitType}}une durée de{{duration}}"
AdvSceneSwitcher.action.wait.entry.random="Attendre pour{{waitType}}une durée de{{duration}}à{{duration2}}"
AdvSceneSwitcher.action.wait.layout.fixed="Attendre pour{{waitType}}une durée de{{duration}}"
AdvSceneSwitcher.action.wait.layout.random="Attendre pour{{waitType}}une durée de{{duration}}à{{duration2}}"
AdvSceneSwitcher.action.audio="Audio"
AdvSceneSwitcher.action.audio.type.mute="Muet"
AdvSceneSwitcher.action.audio.type.unmute="Activer le son"

View File

@ -800,8 +800,8 @@ AdvSceneSwitcher.action.scene.blockUntilTransitionDone="目的のシーンへの
; AdvSceneSwitcher.action.wait="Wait"
AdvSceneSwitcher.action.wait.type.fixed="指定"
AdvSceneSwitcher.action.wait.type.random="ランダム"
AdvSceneSwitcher.action.wait.entry.fixed="{{waitType}}期間{{duration}}待機します"
AdvSceneSwitcher.action.wait.entry.random="{{duration}}から{{duration2}}までの{{waitType}}期間待ちます"
AdvSceneSwitcher.action.wait.layout.fixed="{{waitType}}期間{{duration}}待機します"
AdvSceneSwitcher.action.wait.layout.random="{{duration}}から{{duration2}}までの{{waitType}}期間待ちます"
AdvSceneSwitcher.action.audio="音声"
AdvSceneSwitcher.action.audio.type.mute="ミュート"
AdvSceneSwitcher.action.audio.type.unmute="ミュート解除"

View File

@ -718,8 +718,8 @@ AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Aguardar até que a tran
AdvSceneSwitcher.action.wait="Aguardar"
AdvSceneSwitcher.action.wait.type.fixed="fixo"
AdvSceneSwitcher.action.wait.type.random="aleatório"
AdvSceneSwitcher.action.wait.entry.fixed="Aguardando por{{waitType}}duração de{{duration}}"
AdvSceneSwitcher.action.wait.entry.random="Aguardando por{{waitType}}duração de{{duration}}para{{duration2}}"
AdvSceneSwitcher.action.wait.layout.fixed="Aguardando por{{waitType}}duração de{{duration}}"
AdvSceneSwitcher.action.wait.layout.random="Aguardando por{{waitType}}duração de{{duration}}para{{duration2}}"
AdvSceneSwitcher.action.audio="Áudio"
AdvSceneSwitcher.action.audio.type.mute="Silenciar"
AdvSceneSwitcher.action.audio.type.unmute="Ativar som"

View File

@ -114,8 +114,8 @@ AdvSceneSwitcher.action.scene="Переключить сцену"
AdvSceneSwitcher.action.wait="Подождать"
AdvSceneSwitcher.action.wait.type.fixed="фиксированный"
AdvSceneSwitcher.action.wait.type.random="случайный"
AdvSceneSwitcher.action.wait.entry.fixed="Ожидать {{waitType}} в течении {{duration}}"
AdvSceneSwitcher.action.wait.entry.random="Ожидание {{waitType}} длительностью от {{duration}} до {{duration2}}"
AdvSceneSwitcher.action.wait.layout.fixed="Ожидать {{waitType}} в течении {{duration}}"
AdvSceneSwitcher.action.wait.layout.random="Ожидание {{waitType}} длительностью от {{duration}} до {{duration2}}"
AdvSceneSwitcher.action.audio="Аудио"
AdvSceneSwitcher.action.audio.type.mute="Замьютить"
AdvSceneSwitcher.action.audio.type.unmute="Размьютить"

View File

@ -249,8 +249,8 @@ AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Hedef sahneye geçiş ta
AdvSceneSwitcher.action.wait="Bekle"
AdvSceneSwitcher.action.wait.type.fixed="sabit"
AdvSceneSwitcher.action.wait.type.random="rastgele"
AdvSceneSwitcher.action.wait.entry.fixed="Şunu bekle {{waitType}} süre {{duration}}"
AdvSceneSwitcher.action.wait.entry.random="Şunu bekle {{waitType}} bu aralıktan {{duration}} buna {{duration2}}"
AdvSceneSwitcher.action.wait.layout.fixed="Şunu bekle {{waitType}} süre {{duration}}"
AdvSceneSwitcher.action.wait.layout.random="Şunu bekle {{waitType}} bu aralıktan {{duration}} buna {{duration2}}"
AdvSceneSwitcher.action.audio="Ses"
AdvSceneSwitcher.action.audio.type.mute="Sessiz"
AdvSceneSwitcher.action.audio.type.unmute="Ses açmak"

View File

@ -778,8 +778,8 @@ AdvSceneSwitcher.action.scene.blockUntilTransitionDone="等待转场到目标场
AdvSceneSwitcher.action.wait="等待"
AdvSceneSwitcher.action.wait.type.fixed="固定"
AdvSceneSwitcher.action.wait.type.random="随机"
AdvSceneSwitcher.action.wait.entry.fixed="等待时间{{waitType}}{{duration}}"
AdvSceneSwitcher.action.wait.entry.random="等待时间{{waitType}}{{duration}} 到 {{duration2}}"
AdvSceneSwitcher.action.wait.layout.fixed="等待时间{{waitType}}{{duration}}"
AdvSceneSwitcher.action.wait.layout.random="等待时间{{waitType}}{{duration}} 到 {{duration2}}"
AdvSceneSwitcher.action.audio="音频"
AdvSceneSwitcher.action.audio.type.mute="静音"
AdvSceneSwitcher.action.audio.type.unmute="取消静音"

View File

@ -19,6 +19,21 @@ static const std::map<MacroActionWait::Type, std::string> waitTypes = {
"AdvSceneSwitcher.action.wait.type.fixed"},
{MacroActionWait::Type::RANDOM,
"AdvSceneSwitcher.action.wait.type.random"},
{MacroActionWait::Type::VARIABLE_WAIT,
"AdvSceneSwitcher.action.wait.type.variableCondition"},
};
static const std::map<MacroActionWait::Condition, std::string> conditionTypes = {
{MacroActionWait::Condition::EQUALS,
"AdvSceneSwitcher.action.wait.condition.equals"},
{MacroActionWait::Condition::DOES_NOT_EQUAL,
"AdvSceneSwitcher.action.wait.condition.doesNotEqual"},
{MacroActionWait::Condition::IS_EMPTY,
"AdvSceneSwitcher.action.wait.condition.isEmpty"},
{MacroActionWait::Condition::LESS_THAN,
"AdvSceneSwitcher.action.wait.condition.lessThan"},
{MacroActionWait::Condition::GREATER_THAN,
"AdvSceneSwitcher.action.wait.condition.greaterThan"},
};
static std::random_device rd;
@ -35,7 +50,52 @@ static void waitHelper(std::unique_lock<std::mutex> *lock, Macro *macro,
}
}
bool MacroActionWait::PerformAction()
void MacroActionWait::SetupTempVars()
{
MacroAction::SetupTempVars();
if (_waitType != Type::VARIABLE_WAIT) {
return;
}
AddTempvar(
"timedOut",
obs_module_text("AdvSceneSwitcher.tempVar.wait.timedOut"),
obs_module_text(
"AdvSceneSwitcher.tempVar.wait.timedOut.description"));
}
bool MacroActionWait::ConditionIsMet() const
{
auto var = _variable.lock();
if (!var) {
return false;
}
switch (_condition) {
case Condition::EQUALS:
if (_regex.Enabled()) {
return _regex.Matches(var->Value(), _strValue);
}
return var->Value() == std::string(_strValue);
case Condition::DOES_NOT_EQUAL:
if (_regex.Enabled()) {
return !_regex.Matches(var->Value(), _strValue);
}
return var->Value() != std::string(_strValue);
case Condition::IS_EMPTY:
return var->Value().empty();
case Condition::LESS_THAN: {
auto val = var->DoubleValue();
return val.has_value() && *val < (double)_numValue;
}
case Condition::GREATER_THAN: {
auto val = var->DoubleValue();
return val.has_value() && *val > (double)_numValue;
}
}
return false;
}
bool MacroActionWait::PerformDurationWait()
{
double sleepDuration;
if (_waitType == Type::FIXED) {
@ -66,20 +126,71 @@ bool MacroActionWait::PerformAction()
return !MacroWaitShouldAbort();
}
bool MacroActionWait::PerformVariableWait()
{
auto var = _variable.lock();
if (!var) {
return true;
}
auto deadline =
_useTimeout
? std::chrono::high_resolution_clock::now() +
std::chrono::milliseconds((
int)(_conditionTimeout.Milliseconds()))
: std::chrono::high_resolution_clock::time_point::max();
SetMacroAbortWait(false);
SuspendLock suspendLock(*this);
auto cvLock = var->GetCVLock();
while (!MacroWaitShouldAbort() && !MacroIsStopped(GetMacro())) {
if (ConditionIsMet()) {
SetTempVarValue("timedOut", false);
return true;
}
auto now = std::chrono::high_resolution_clock::now();
if (now >= deadline) {
SetTempVarValue("timedOut", true);
return true;
}
auto wakeAt =
std::min(now + std::chrono::milliseconds(50), deadline);
var->GetCV().wait_until(cvLock, wakeAt);
}
return !MacroWaitShouldAbort();
}
bool MacroActionWait::PerformAction()
{
if (_waitType == Type::VARIABLE_WAIT) {
return PerformVariableWait();
}
return PerformDurationWait();
}
bool MacroActionWait::Save(obs_data_t *obj) const
{
MacroAction::Save(obj);
_duration.Save(obj);
_duration2.Save(obj, "duration2");
obs_data_set_int(obj, "waitType", static_cast<int>(_waitType));
obs_data_set_int(obj, "version", 1);
_duration.Save(obj);
_duration2.Save(obj, "duration2");
obs_data_set_string(obj, "variableName",
GetWeakVariableName(_variable).c_str());
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
_strValue.Save(obj, "strValue");
_numValue.Save(obj, "numValue");
_regex.Save(obj);
obs_data_set_bool(obj, "useTimeout", _useTimeout);
_conditionTimeout.Save(obj, "conditionTimeout");
return true;
}
bool MacroActionWait::Load(obs_data_t *obj)
{
MacroAction::Load(obj);
_duration.Load(obj);
_waitType = static_cast<Type>(obs_data_get_int(obj, "waitType"));
// TODO: remove this fallback
if (obs_data_get_int(obj, "version") == 1) {
_duration2.Load(obj, "duration2");
@ -88,12 +199,23 @@ bool MacroActionWait::Load(obs_data_t *obj)
_duration2.SetUnit(static_cast<Duration::Unit>(
obs_data_get_int(obj, "displayUnit2")));
}
_waitType = static_cast<Type>(obs_data_get_int(obj, "waitType"));
_duration.Load(obj);
_variable =
GetWeakVariableByName(obs_data_get_string(obj, "variableName"));
_condition = static_cast<Condition>(obs_data_get_int(obj, "condition"));
_strValue.Load(obj, "strValue");
_numValue.Load(obj, "numValue");
_regex.Load(obj);
_useTimeout = obs_data_get_bool(obj, "useTimeout");
_conditionTimeout.Load(obj, "conditionTimeout");
return true;
}
std::string MacroActionWait::GetShortDesc() const
{
if (_waitType == Type::VARIABLE_WAIT) {
return GetWeakVariableName(_variable);
}
if (_waitType == Type::FIXED) {
return _duration.ToString();
}
@ -114,12 +236,18 @@ void MacroActionWait::ResolveVariablesToFixedValues()
{
_duration.ResolveVariables();
_duration2.ResolveVariables();
_strValue.ResolveVariables();
_numValue.ResolveVariables();
_conditionTimeout.ResolveVariables();
}
static inline void populateTypeSelection(QComboBox *list)
template<typename T>
static inline void populateSelection(QComboBox *list,
const std::map<T, std::string> &options)
{
for (const auto &[_, name] : waitTypes) {
list->addItem(obs_module_text(name.c_str()));
for (const auto &[value, name] : options) {
list->addItem(obs_module_text(name.c_str()),
static_cast<int>(value));
}
}
@ -128,10 +256,21 @@ MacroActionWaitEdit::MacroActionWaitEdit(
: QWidget(parent),
_duration(new DurationSelection()),
_duration2(new DurationSelection()),
_variable(new VariableSelection(this)),
_variableCondition(new QComboBox()),
_strValue(new VariableTextEdit(this, 5, 1, 1)),
_numValue(new VariableDoubleSpinBox()),
_regex(new RegexConfigWidget(parent)),
_useTimeout(new QCheckBox()),
_conditionTimeout(new DurationSelection()),
_waitType(new QComboBox()),
_mainLayout(new QHBoxLayout())
_mainLayout(new QHBoxLayout()),
_timeoutLayout(new QHBoxLayout())
{
populateTypeSelection(_waitType);
_numValue->setMinimum(-9999999999);
_numValue->setMaximum(9999999999);
populateSelection(_waitType, waitTypes);
populateSelection(_variableCondition, conditionTypes);
QWidget::connect(_duration, SIGNAL(DurationChanged(const Duration &)),
this, SLOT(DurationChanged(const Duration &)));
@ -139,8 +278,37 @@ MacroActionWaitEdit::MacroActionWaitEdit(
this, SLOT(Duration2Changed(const Duration &)));
QWidget::connect(_waitType, SIGNAL(currentIndexChanged(int)), this,
SLOT(TypeChanged(int)));
QWidget::connect(_variable, SIGNAL(SelectionChanged(const QString &)),
this, SLOT(VariableChanged(const QString &)));
QWidget::connect(_variableCondition, SIGNAL(currentIndexChanged(int)),
this, SLOT(ConditionChanged(int)));
QWidget::connect(_strValue, SIGNAL(textChanged()), this,
SLOT(StrValueChanged()));
QWidget::connect(
_numValue,
SIGNAL(NumberVariableChanged(const NumberVariable<double> &)),
this, SLOT(NumValueChanged(const NumberVariable<double> &)));
QWidget::connect(_regex,
SIGNAL(RegexConfigChanged(const RegexConfig &)), this,
SLOT(RegexChanged(const RegexConfig &)));
QWidget::connect(_useTimeout, SIGNAL(stateChanged(int)), this,
SLOT(UseTimeoutChanged(int)));
QWidget::connect(_conditionTimeout,
SIGNAL(DurationChanged(const Duration &)), this,
SLOT(ConditionTimeoutChanged(const Duration &)));
setLayout(_mainLayout);
PlaceWidgets(
obs_module_text("AdvSceneSwitcher.action.wait.layout.timeout"),
_timeoutLayout,
{
{"{{useTimeout}}", _useTimeout},
{"{{conditionTimeout}}", _conditionTimeout},
});
auto *outerLayout = new QVBoxLayout();
outerLayout->addLayout(_mainLayout);
outerLayout->addLayout(_timeoutLayout);
setLayout(outerLayout);
_entryData = entryData;
UpdateEntryData();
@ -153,15 +321,30 @@ void MacroActionWaitEdit::UpdateEntryData()
return;
}
if (_entryData->_waitType == MacroActionWait::Type::FIXED) {
_waitType->setCurrentIndex(static_cast<int>(_entryData->_waitType));
switch (_entryData->_waitType) {
case MacroActionWait::Type::FIXED:
SetupFixedDurationEdit();
} else {
break;
case MacroActionWait::Type::RANDOM:
SetupRandomDurationEdit();
break;
case MacroActionWait::Type::VARIABLE_WAIT:
SetupVariableWaitEdit();
break;
}
_duration->SetDuration(_entryData->_duration);
_duration2->SetDuration(_entryData->_duration2);
_waitType->setCurrentIndex(static_cast<int>(_entryData->_waitType));
_variable->SetVariable(_entryData->_variable);
_variableCondition->setCurrentIndex(
static_cast<int>(_entryData->_condition));
_strValue->setPlainText(_entryData->_strValue);
_numValue->SetValue(_entryData->_numValue);
_regex->SetRegexConfig(_entryData->_regex);
_useTimeout->setChecked(_entryData->_useTimeout);
_conditionTimeout->SetDuration(_entryData->_conditionTimeout);
}
void MacroActionWaitEdit::SetupFixedDurationEdit()
@ -169,15 +352,24 @@ void MacroActionWaitEdit::SetupFixedDurationEdit()
_mainLayout->removeWidget(_duration);
_mainLayout->removeWidget(_duration2);
_mainLayout->removeWidget(_waitType);
_mainLayout->removeWidget(_variable);
_mainLayout->removeWidget(_variableCondition);
_mainLayout->removeWidget(_strValue);
_mainLayout->removeWidget(_numValue);
_mainLayout->removeWidget(_regex);
ClearLayout(_mainLayout);
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{duration}}", _duration},
{"{{waitType}}", _waitType},
};
PlaceWidgets(
obs_module_text("AdvSceneSwitcher.action.wait.entry.fixed"),
_mainLayout, widgetPlaceholders);
obs_module_text("AdvSceneSwitcher.action.wait.layout.fixed"),
_mainLayout,
{{"{{duration}}", _duration}, {"{{waitType}}", _waitType}});
_duration->show();
_duration2->hide();
_variable->hide();
_variableCondition->hide();
_strValue->hide();
_numValue->hide();
_regex->hide();
SetLayoutVisible(_timeoutLayout, false);
}
void MacroActionWaitEdit::SetupRandomDurationEdit()
@ -185,30 +377,99 @@ void MacroActionWaitEdit::SetupRandomDurationEdit()
_mainLayout->removeWidget(_duration);
_mainLayout->removeWidget(_duration2);
_mainLayout->removeWidget(_waitType);
_mainLayout->removeWidget(_variable);
_mainLayout->removeWidget(_variableCondition);
_mainLayout->removeWidget(_strValue);
_mainLayout->removeWidget(_numValue);
_mainLayout->removeWidget(_regex);
ClearLayout(_mainLayout);
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{duration}}", _duration},
{"{{duration2}}", _duration2},
{"{{waitType}}", _waitType},
};
PlaceWidgets(
obs_module_text("AdvSceneSwitcher.action.wait.entry.random"),
_mainLayout, widgetPlaceholders);
obs_module_text("AdvSceneSwitcher.action.wait.layout.random"),
_mainLayout,
{{"{{duration}}", _duration},
{"{{duration2}}", _duration2},
{"{{waitType}}", _waitType}});
_duration->show();
_duration2->show();
_variable->hide();
_variableCondition->hide();
_strValue->hide();
_numValue->hide();
_regex->hide();
SetLayoutVisible(_timeoutLayout, false);
}
void MacroActionWaitEdit::TypeChanged(int value)
void MacroActionWaitEdit::SetupVariableWaitEdit()
{
_mainLayout->removeWidget(_duration);
_mainLayout->removeWidget(_duration2);
_mainLayout->removeWidget(_waitType);
_mainLayout->removeWidget(_variable);
_mainLayout->removeWidget(_variableCondition);
_mainLayout->removeWidget(_strValue);
_mainLayout->removeWidget(_numValue);
_mainLayout->removeWidget(_regex);
ClearLayout(_mainLayout);
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{waitType}}", _waitType},
{"{{variable}}", _variable},
{"{{condition}}", _variableCondition},
{"{{strValue}}", _strValue},
{"{{numValue}}", _numValue},
{"{{regex}}", _regex},
};
PlaceWidgets(
obs_module_text(
"AdvSceneSwitcher.action.wait.layout.variableCondition"),
_mainLayout, widgetPlaceholders);
_duration->hide();
_duration2->hide();
_variable->show();
_variableCondition->show();
SetLayoutVisible(_timeoutLayout, true);
SetVariableWaitWidgetVisibility();
}
void MacroActionWaitEdit::SetVariableWaitWidgetVisibility()
{
if (!_entryData) {
return;
}
const auto cond = _entryData->_condition;
const bool isStringComparison =
cond == MacroActionWait::Condition::EQUALS ||
cond == MacroActionWait::Condition::DOES_NOT_EQUAL;
_strValue->setVisible(isStringComparison);
_regex->setVisible(isStringComparison);
_numValue->setVisible(cond == MacroActionWait::Condition::LESS_THAN ||
cond == MacroActionWait::Condition::GREATER_THAN);
_conditionTimeout->setVisible(_entryData->_useTimeout);
adjustSize();
updateGeometry();
}
void MacroActionWaitEdit::TypeChanged(int idx)
{
GUARD_LOADING_AND_LOCK();
auto type = static_cast<MacroActionWait::Type>(value);
auto type = static_cast<MacroActionWait::Type>(
_waitType->itemData(idx).toInt());
if (type == MacroActionWait::Type::FIXED) {
switch (type) {
case MacroActionWait::Type::FIXED:
SetupFixedDurationEdit();
} else {
break;
case MacroActionWait::Type::RANDOM:
SetupRandomDurationEdit();
break;
case MacroActionWait::Type::VARIABLE_WAIT:
SetupVariableWaitEdit();
break;
}
_entryData->_waitType = type;
_entryData->SetupTempVars();
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
}
@ -229,4 +490,55 @@ void MacroActionWaitEdit::Duration2Changed(const Duration &dur)
QString::fromStdString(_entryData->GetShortDesc()));
}
void MacroActionWaitEdit::VariableChanged(const QString &text)
{
GUARD_LOADING_AND_LOCK();
_entryData->_variable = GetWeakVariableByQString(text);
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
}
void MacroActionWaitEdit::ConditionChanged(int idx)
{
GUARD_LOADING_AND_LOCK();
_entryData->_condition = static_cast<MacroActionWait::Condition>(
_variableCondition->itemData(idx).toInt());
SetVariableWaitWidgetVisibility();
}
void MacroActionWaitEdit::StrValueChanged()
{
GUARD_LOADING_AND_LOCK();
_entryData->_strValue = _strValue->toPlainText().toStdString();
adjustSize();
updateGeometry();
}
void MacroActionWaitEdit::NumValueChanged(const NumberVariable<double> &val)
{
GUARD_LOADING_AND_LOCK();
_entryData->_numValue = val;
}
void MacroActionWaitEdit::RegexChanged(const RegexConfig &conf)
{
GUARD_LOADING_AND_LOCK();
_entryData->_regex = conf;
adjustSize();
updateGeometry();
}
void MacroActionWaitEdit::UseTimeoutChanged(int state)
{
GUARD_LOADING_AND_LOCK();
_entryData->_useTimeout = state != Qt::Unchecked;
SetVariableWaitWidgetVisibility();
}
void MacroActionWaitEdit::ConditionTimeoutChanged(const Duration &dur)
{
GUARD_LOADING_AND_LOCK();
_entryData->_conditionTimeout = dur;
}
} // namespace advss

View File

@ -1,8 +1,14 @@
#pragma once
#include "macro-action-edit.hpp"
#include "duration-control.hpp"
#include "regex-config.hpp"
#include "variable-spinbox.hpp"
#include "variable-text-edit.hpp"
#include "variable.hpp"
#include <QCheckBox>
#include <QHBoxLayout>
#include <QVBoxLayout>
namespace advss {
@ -17,17 +23,40 @@ public:
static std::shared_ptr<MacroAction> Create(Macro *m);
std::shared_ptr<MacroAction> Copy() const;
void ResolveVariablesToFixedValues();
Duration _duration;
Duration _duration2;
void SetupTempVars();
enum class Type {
FIXED,
RANDOM,
VARIABLE_WAIT,
};
Type _waitType = Type::FIXED;
// FIXED / RANDOM
Duration _duration;
Duration _duration2;
// VARIABLE_WAIT
enum class Condition {
EQUALS,
DOES_NOT_EQUAL,
IS_EMPTY,
LESS_THAN,
GREATER_THAN,
};
std::weak_ptr<Variable> _variable;
Condition _condition = Condition::EQUALS;
StringVariable _strValue = "";
DoubleVariable _numValue = 0.0;
RegexConfig _regex;
bool _useTimeout = false;
Duration _conditionTimeout;
private:
bool PerformDurationWait();
bool PerformVariableWait();
bool ConditionIsMet() const;
static bool _registered;
static const std::string id;
};
@ -42,6 +71,7 @@ public:
void UpdateEntryData();
void SetupFixedDurationEdit();
void SetupRandomDurationEdit();
void SetupVariableWaitEdit();
static QWidget *Create(QWidget *parent,
std::shared_ptr<MacroAction> action)
{
@ -54,15 +84,36 @@ private slots:
void DurationChanged(const Duration &value);
void Duration2Changed(const Duration &value);
void TypeChanged(int value);
void VariableChanged(const QString &);
void ConditionChanged(int);
void StrValueChanged();
void NumValueChanged(const NumberVariable<double> &);
void RegexChanged(const RegexConfig &);
void UseTimeoutChanged(int);
void ConditionTimeoutChanged(const Duration &);
signals:
void HeaderInfoChanged(const QString &);
private:
void SetVariableWaitWidgetVisibility();
// Duration widgets (FIXED / RANDOM)
DurationSelection *_duration;
DurationSelection *_duration2;
// Variable condition widgets (VARIABLE_WAIT)
VariableSelection *_variable;
QComboBox *_variableCondition;
VariableTextEdit *_strValue;
VariableDoubleSpinBox *_numValue;
RegexConfigWidget *_regex;
QCheckBox *_useTimeout;
DurationSelection *_conditionTimeout;
QComboBox *_waitType;
QHBoxLayout *_mainLayout;
QHBoxLayout *_timeoutLayout;
std::shared_ptr<MacroActionWait> _entryData;
bool _loading = true;