From e683fd82f42778ee9b1ea005a1a3bd123a5c4688 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Wed, 16 Nov 2022 14:06:27 +0100 Subject: [PATCH] Draft source interaction action --- data/locale/en-US.ini | 25 + plugins/base/CMakeLists.txt | 2 + plugins/base/macro-action-source.cpp | 44 +- plugins/base/macro-action-source.hpp | 6 + plugins/base/utils/source-interact.cpp | 882 +++++++++++++++++++++++++ plugins/base/utils/source-interact.hpp | 337 ++++++++++ 6 files changed, 1295 insertions(+), 1 deletion(-) create mode 100644 plugins/base/utils/source-interact.cpp create mode 100644 plugins/base/utils/source-interact.hpp diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 31308724..d54930ed 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -809,6 +809,12 @@ AdvSceneSwitcher.action.source.type.deinterlaceOrder="Set deinterlace field orde AdvSceneSwitcher.action.source.type.openInteractionDialog="Open interaction dialog" AdvSceneSwitcher.action.source.type.openFilterDialog="Open filter dialog" AdvSceneSwitcher.action.source.type.openPropertiesDialog="Open properties dialog" +AdvSceneSwitcher.action.source.type.interact="Interact" +AdvSceneSwitcher.action.source.type.interact.selectType="Interaction type:{{type}}" +AdvSceneSwitcher.action.source.type.interact.mouseClick="Send mouse click" +AdvSceneSwitcher.action.source.type.interact.mouseMove="Send mouse move" +AdvSceneSwitcher.action.source.type.interact.mouseWheel="Send mouse wheel" +AdvSceneSwitcher.action.source.type.interact.keyPress="Send key press" AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}{{deinterlaceMode}}{{deinterlaceOrder}}{{refresh}}" AdvSceneSwitcher.action.source.entry.settings="{{settings}}{{settingsInputMethod}}{{settingValue}}{{tempVar}}" AdvSceneSwitcher.action.source.warning="Warning: Enabling and disabling sources globally cannot be controlled by the OBS UI\nYou might be looking for \"Scene item visibility\"" @@ -1889,6 +1895,25 @@ AdvSceneSwitcher.noSettingsButtons="No buttons found!" AdvSceneSwitcher.clearBufferOnMatch="Clear message buffer when matching message was found" +AdvSceneSwitcher.key="Key:" +AdvSceneSwitcher.key.up="Key up:" + +AdvSceneSwitcher.modifierKey="Modifier keys:" +AdvSceneSwitcher.modifierKey.shift="Shift" +AdvSceneSwitcher.modifierKey.ctrl="Ctrl" +AdvSceneSwitcher.modifierKey.alt="Alt" +AdvSceneSwitcher.modifierKey.meta="Meta" + +AdvSceneSwitcher.mouse.button="Mouse button:" +AdvSceneSwitcher.mouse.button.left="Left" +AdvSceneSwitcher.mouse.button.middle="Middle" +AdvSceneSwitcher.mouse.button.right="Right" +AdvSceneSwitcher.mouse.position="Mouse position:" +AdvSceneSwitcher.mouse.up="Mouse up event:" +AdvSceneSwitcher.mouse.count="Mouse click count:" +AdvSceneSwitcher.mouse.leave="Mouse leave event:" +AdvSceneSwitcher.mouse.scrollAmount="Mouse scroll amount:" + ; Legacy tabs below - please don't waste your time adding translations for these :) ; Transition Tab AdvSceneSwitcher.transitionTab.title="Transition" diff --git a/plugins/base/CMakeLists.txt b/plugins/base/CMakeLists.txt index 7617fe29..d6f03f50 100644 --- a/plugins/base/CMakeLists.txt +++ b/plugins/base/CMakeLists.txt @@ -166,6 +166,8 @@ target_sources( utils/source-properties-button.hpp utils/source-settings-helpers.cpp utils/source-settings-helpers.hpp + utils/source-interact.cpp + utils/source-interact.hpp utils/source-setting.cpp utils/source-setting.hpp utils/striped-frame.cpp diff --git a/plugins/base/macro-action-source.cpp b/plugins/base/macro-action-source.cpp index b1cda0dd..5b4d1c23 100644 --- a/plugins/base/macro-action-source.cpp +++ b/plugins/base/macro-action-source.cpp @@ -36,6 +36,8 @@ const static std::map actionTypes = { "AdvSceneSwitcher.action.source.type.openFilterDialog"}, {MacroActionSource::Action::OPEN_PROPERTIES_DIALOG, "AdvSceneSwitcher.action.source.type.openPropertiesDialog"}, + {MacroActionSource::Action::INTERACT, + "AdvSceneSwitcher.action.source.type.interact"}, }; const static std::map deinterlaceModes = { @@ -142,6 +144,9 @@ bool MacroActionSource::PerformAction() case Action::SETTINGS_BUTTON: PressSourceButton(_button, s); break; + case Action::INTERACT: + _interaction.SendToSource(s); + break; case Action::DEINTERLACE_MODE: obs_source_set_deinterlace_mode(s, _deinterlaceMode); break; @@ -199,6 +204,7 @@ bool MacroActionSource::Save(obs_data_t *obj) const static_cast(_deinterlaceMode)); obs_data_set_int(obj, "deinterlaceOrder", static_cast(_deinterlaceOrder)); + _interaction.Save(obj); return true; } @@ -223,6 +229,7 @@ bool MacroActionSource::Load(obs_data_t *obj) obs_data_get_int(obj, "deinterlaceMode")); _deinterlaceOrder = static_cast( obs_data_get_int(obj, "deinterlaceOrder")); + _interaction.Load(obj); return true; } @@ -309,7 +316,8 @@ MacroActionSourceEdit::MacroActionSourceEdit( _warning(new QLabel( obs_module_text("AdvSceneSwitcher.action.source.warning"))), _refreshSettingSelection(new QPushButton( - obs_module_text("AdvSceneSwitcher.action.source.refresh"))) + obs_module_text("AdvSceneSwitcher.action.source.refresh"))), + _interaction(new SourceInteractionWidget()) { populateActionSelection(_actions); auto sources = GetSourceNames(); @@ -349,6 +357,13 @@ MacroActionSourceEdit::MacroActionSourceEdit( SLOT(SelectionChanged(const SourceSetting &))); QWidget::connect(_refreshSettingSelection, SIGNAL(clicked()), this, SLOT(RefreshVariableSourceSelectionValue())); + QWidget::connect( + _interaction, + SIGNAL(SettingsChanged(SourceInteractionInstance *)), this, + SLOT(InteractionSettingsChanged(SourceInteractionInstance *))); + QWidget::connect(_interaction, + SIGNAL(TypeChanged(SourceInteraction::Type)), this, + SLOT(InteractionTypeChanged(SourceInteraction::Type))); auto entryLayout = new QHBoxLayout; entryLayout->setContentsMargins(0, 0, 0, 0); @@ -381,6 +396,7 @@ MacroActionSourceEdit::MacroActionSourceEdit( buttonLayout->addWidget(_getSettings); buttonLayout->addStretch(); mainLayout->addLayout(buttonLayout); + mainLayout->addWidget(_interaction); setLayout(mainLayout); _entryData = entryData; @@ -411,6 +427,7 @@ void MacroActionSourceEdit::UpdateEntryData() static_cast(_entryData->_settingsInputMethod))); _tempVars->SetVariable(_entryData->_tempVar); _manualSettingValue->setPlainText(_entryData->_manualSettingValue); + _interaction->SetSourceInteractionSelection(_entryData->_interaction); SetWidgetVisibility(); } @@ -561,6 +578,29 @@ void MacroActionSourceEdit::ManualSettingsValueChanged() updateGeometry(); } +void MacroActionSourceEdit::InteractionTypeChanged(SourceInteraction::Type value) +{ + if (_loading || !_entryData) { + return; + } + + auto lock = LockContext(); + _entryData->_interaction.SetType(value); + + adjustSize(); + updateGeometry(); +} + +void MacroActionSourceEdit::InteractionSettingsChanged( + SourceInteractionInstance *value) +{ + if (_loading || !_entryData) { + return; + } + auto lock = LockContext(); + _entryData->_interaction.SetSettings(value); +} + void MacroActionSourceEdit::RefreshVariableSourceSelectionValue() { _sourceSettings->SetSource(_entryData->_source.GetSource()); @@ -617,6 +657,8 @@ void MacroActionSourceEdit::SetWidgetVisibility() _entryData->_source.GetType() == SourceSelection::Type::VARIABLE); + _interaction->setVisible(_entryData->_action == + MacroActionSource::Action::INTERACT); adjustSize(); updateGeometry(); } diff --git a/plugins/base/macro-action-source.hpp b/plugins/base/macro-action-source.hpp index 53f79ada..9145330b 100644 --- a/plugins/base/macro-action-source.hpp +++ b/plugins/base/macro-action-source.hpp @@ -1,6 +1,7 @@ #pragma once #include "macro-action-edit.hpp" #include "variable-text-edit.hpp" +#include "source-interact.hpp" #include "source-properties-button.hpp" #include "source-selection.hpp" #include "source-setting.hpp" @@ -34,6 +35,7 @@ public: OBS_DEINTERLACE_FIELD_ORDER_TOP; TempVariableRef _tempVar; SourceSetting _setting; + SourceInteraction _interaction; enum class Action { ENABLE, @@ -46,6 +48,7 @@ public: OPEN_INTERACTION_DIALOG, OPEN_FILTER_DIALOG, OPEN_PROPERTIES_DIALOG, + INTERACT, }; Action _action = Action::SETTINGS; @@ -92,6 +95,8 @@ private slots: void ManualSettingsValueChanged(); void RefreshVariableSourceSelectionValue(); + void InteractionTypeChanged(SourceInteraction::Type value); + void InteractionSettingsChanged(SourceInteractionInstance *value); signals: void HeaderInfoChanged(const QString &); @@ -112,6 +117,7 @@ private: QComboBox *_deinterlaceOrder; QLabel *_warning; QPushButton *_refreshSettingSelection; + SourceInteractionWidget *_interaction; std::shared_ptr _entryData; bool _loading = true; diff --git a/plugins/base/utils/source-interact.cpp b/plugins/base/utils/source-interact.cpp new file mode 100644 index 00000000..de03ac52 --- /dev/null +++ b/plugins/base/utils/source-interact.cpp @@ -0,0 +1,882 @@ +#include "source-interact.hpp" +#include "obs-module-helper.hpp" +#include "layout-helpers.hpp" + +#include +#include + +namespace advss { + +void Position::Save(obs_data_t *obj, const char *name) const +{ + OBSDataAutoRelease data = obs_data_create(); + x.Save(data, "x"); + y.Save(data, "y"); + obs_data_set_obj(obj, name, data); +} + +void Position::Load(obs_data_t *obj, const char *name) +{ + OBSDataAutoRelease data = obs_data_get_obj(obj, name); + x.Load(data, "x"); + y.Load(data, "y"); +} + +void Modifier::Save(obs_data_t *obj, const char *name) const +{ + OBSDataAutoRelease data = obs_data_create(); + obs_data_set_bool(data, "shift", _shift); + obs_data_set_bool(data, "ctrl", _ctrl); + obs_data_set_bool(data, "alt", _alt); + obs_data_set_bool(data, "meta", _meta); + obs_data_set_obj(obj, name, data); +} + +void Modifier::Load(obs_data_t *obj, const char *name) +{ + OBSDataAutoRelease data = obs_data_get_obj(obj, name); + _shift = obs_data_get_bool(data, "shift"); + _ctrl = obs_data_get_bool(data, "ctrl"); + _alt = obs_data_get_bool(data, "alt"); + _meta = obs_data_get_bool(data, "meta"); +} + +uint32_t Modifier::GetModifiers() const +{ + uint32_t modifiers = INTERACT_NONE; + if (_shift) { + modifiers |= INTERACT_SHIFT_KEY; + } + if (_ctrl) { + modifiers |= INTERACT_CONTROL_KEY; + } + if (_alt) { + modifiers |= INTERACT_ALT_KEY; + } + if (_alt) { + modifiers |= INTERACT_COMMAND_KEY; + } + return modifiers; +} + +SourceInteraction::SourceInteraction() +{ + _interaction = std::make_unique(); +} + +SourceInteraction::SourceInteraction(const SourceInteraction &other) +{ + OBSDataAutoRelease data = obs_data_create(); + other.Save(data); + Load(data); +} + +void SourceInteraction::Save(obs_data_t *obj, const char *name) const +{ + OBSDataAutoRelease data = obs_data_create(); + obs_data_set_int(data, "type", static_cast(_type)); + _interaction->Save(data, "settings"); + obs_data_set_obj(obj, name, data); +} + +void SourceInteraction::Load(obs_data_t *obj, const char *name) +{ + OBSDataAutoRelease data = obs_data_get_obj(obj, name); + _type = static_cast(obs_data_get_int(data, "type")); + UpdateType(); + _interaction->Load(data, "settings"); +} + +void SourceInteraction::SetSettings(SourceInteractionInstance *value) +{ + _interaction.reset(value); +} + +void SourceInteraction::SetType(Type t) +{ + _type = t; + UpdateType(); +} + +void SourceInteraction::SendToSource(obs_source_t *source) const +{ + _interaction->SendToSource(source); +} + +void SourceInteraction::UpdateType() +{ + switch (_type) { + case SourceInteraction::Type::CLICK: + _interaction.reset(new MouseClick); + break; + case SourceInteraction::Type::MOVE: + _interaction.reset(new MouseMove); + break; + case SourceInteraction::Type::WHEEL: + _interaction.reset(new MouseWheel); + break; + case SourceInteraction::Type::KEY: + _interaction.reset(new KeyPress); + break; + } +} + +void MouseClick::Save(obs_data_t *obj, const char *name) const +{ + OBSDataAutoRelease data = obs_data_create(); + obs_data_set_int(data, "button", static_cast(_button)); + obs_data_set_bool(data, "up", _up); + _pos.Save(data); + _count.Save(data, "count"); + _modifier.Save(data); + obs_data_set_obj(obj, name, data); +} + +void MouseClick::Load(obs_data_t *obj, const char *name) +{ + OBSDataAutoRelease data = obs_data_get_obj(obj, name); + _button = static_cast