Draft source interaction action

This commit is contained in:
WarmUpTill 2022-11-16 14:06:27 +01:00
parent 17c72b772d
commit e683fd82f4
6 changed files with 1295 additions and 1 deletions

View File

@ -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.openInteractionDialog="Open interaction dialog"
AdvSceneSwitcher.action.source.type.openFilterDialog="Open filter dialog" AdvSceneSwitcher.action.source.type.openFilterDialog="Open filter dialog"
AdvSceneSwitcher.action.source.type.openPropertiesDialog="Open properties 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="{{actions}}{{sources}}{{settingsButtons}}{{deinterlaceMode}}{{deinterlaceOrder}}{{refresh}}"
AdvSceneSwitcher.action.source.entry.settings="{{settings}}{{settingsInputMethod}}{{settingValue}}{{tempVar}}" 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\"" 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.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 :) ; Legacy tabs below - please don't waste your time adding translations for these :)
; Transition Tab ; Transition Tab
AdvSceneSwitcher.transitionTab.title="Transition" AdvSceneSwitcher.transitionTab.title="Transition"

View File

@ -166,6 +166,8 @@ target_sources(
utils/source-properties-button.hpp utils/source-properties-button.hpp
utils/source-settings-helpers.cpp utils/source-settings-helpers.cpp
utils/source-settings-helpers.hpp utils/source-settings-helpers.hpp
utils/source-interact.cpp
utils/source-interact.hpp
utils/source-setting.cpp utils/source-setting.cpp
utils/source-setting.hpp utils/source-setting.hpp
utils/striped-frame.cpp utils/striped-frame.cpp

View File

@ -36,6 +36,8 @@ const static std::map<MacroActionSource::Action, std::string> actionTypes = {
"AdvSceneSwitcher.action.source.type.openFilterDialog"}, "AdvSceneSwitcher.action.source.type.openFilterDialog"},
{MacroActionSource::Action::OPEN_PROPERTIES_DIALOG, {MacroActionSource::Action::OPEN_PROPERTIES_DIALOG,
"AdvSceneSwitcher.action.source.type.openPropertiesDialog"}, "AdvSceneSwitcher.action.source.type.openPropertiesDialog"},
{MacroActionSource::Action::INTERACT,
"AdvSceneSwitcher.action.source.type.interact"},
}; };
const static std::map<obs_deinterlace_mode, std::string> deinterlaceModes = { const static std::map<obs_deinterlace_mode, std::string> deinterlaceModes = {
@ -142,6 +144,9 @@ bool MacroActionSource::PerformAction()
case Action::SETTINGS_BUTTON: case Action::SETTINGS_BUTTON:
PressSourceButton(_button, s); PressSourceButton(_button, s);
break; break;
case Action::INTERACT:
_interaction.SendToSource(s);
break;
case Action::DEINTERLACE_MODE: case Action::DEINTERLACE_MODE:
obs_source_set_deinterlace_mode(s, _deinterlaceMode); obs_source_set_deinterlace_mode(s, _deinterlaceMode);
break; break;
@ -199,6 +204,7 @@ bool MacroActionSource::Save(obs_data_t *obj) const
static_cast<int>(_deinterlaceMode)); static_cast<int>(_deinterlaceMode));
obs_data_set_int(obj, "deinterlaceOrder", obs_data_set_int(obj, "deinterlaceOrder",
static_cast<int>(_deinterlaceOrder)); static_cast<int>(_deinterlaceOrder));
_interaction.Save(obj);
return true; return true;
} }
@ -223,6 +229,7 @@ bool MacroActionSource::Load(obs_data_t *obj)
obs_data_get_int(obj, "deinterlaceMode")); obs_data_get_int(obj, "deinterlaceMode"));
_deinterlaceOrder = static_cast<obs_deinterlace_field_order>( _deinterlaceOrder = static_cast<obs_deinterlace_field_order>(
obs_data_get_int(obj, "deinterlaceOrder")); obs_data_get_int(obj, "deinterlaceOrder"));
_interaction.Load(obj);
return true; return true;
} }
@ -309,7 +316,8 @@ MacroActionSourceEdit::MacroActionSourceEdit(
_warning(new QLabel( _warning(new QLabel(
obs_module_text("AdvSceneSwitcher.action.source.warning"))), obs_module_text("AdvSceneSwitcher.action.source.warning"))),
_refreshSettingSelection(new QPushButton( _refreshSettingSelection(new QPushButton(
obs_module_text("AdvSceneSwitcher.action.source.refresh"))) obs_module_text("AdvSceneSwitcher.action.source.refresh"))),
_interaction(new SourceInteractionWidget())
{ {
populateActionSelection(_actions); populateActionSelection(_actions);
auto sources = GetSourceNames(); auto sources = GetSourceNames();
@ -349,6 +357,13 @@ MacroActionSourceEdit::MacroActionSourceEdit(
SLOT(SelectionChanged(const SourceSetting &))); SLOT(SelectionChanged(const SourceSetting &)));
QWidget::connect(_refreshSettingSelection, SIGNAL(clicked()), this, QWidget::connect(_refreshSettingSelection, SIGNAL(clicked()), this,
SLOT(RefreshVariableSourceSelectionValue())); 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; auto entryLayout = new QHBoxLayout;
entryLayout->setContentsMargins(0, 0, 0, 0); entryLayout->setContentsMargins(0, 0, 0, 0);
@ -381,6 +396,7 @@ MacroActionSourceEdit::MacroActionSourceEdit(
buttonLayout->addWidget(_getSettings); buttonLayout->addWidget(_getSettings);
buttonLayout->addStretch(); buttonLayout->addStretch();
mainLayout->addLayout(buttonLayout); mainLayout->addLayout(buttonLayout);
mainLayout->addWidget(_interaction);
setLayout(mainLayout); setLayout(mainLayout);
_entryData = entryData; _entryData = entryData;
@ -411,6 +427,7 @@ void MacroActionSourceEdit::UpdateEntryData()
static_cast<int>(_entryData->_settingsInputMethod))); static_cast<int>(_entryData->_settingsInputMethod)));
_tempVars->SetVariable(_entryData->_tempVar); _tempVars->SetVariable(_entryData->_tempVar);
_manualSettingValue->setPlainText(_entryData->_manualSettingValue); _manualSettingValue->setPlainText(_entryData->_manualSettingValue);
_interaction->SetSourceInteractionSelection(_entryData->_interaction);
SetWidgetVisibility(); SetWidgetVisibility();
} }
@ -561,6 +578,29 @@ void MacroActionSourceEdit::ManualSettingsValueChanged()
updateGeometry(); 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() void MacroActionSourceEdit::RefreshVariableSourceSelectionValue()
{ {
_sourceSettings->SetSource(_entryData->_source.GetSource()); _sourceSettings->SetSource(_entryData->_source.GetSource());
@ -617,6 +657,8 @@ void MacroActionSourceEdit::SetWidgetVisibility()
_entryData->_source.GetType() == _entryData->_source.GetType() ==
SourceSelection::Type::VARIABLE); SourceSelection::Type::VARIABLE);
_interaction->setVisible(_entryData->_action ==
MacroActionSource::Action::INTERACT);
adjustSize(); adjustSize();
updateGeometry(); updateGeometry();
} }

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "macro-action-edit.hpp" #include "macro-action-edit.hpp"
#include "variable-text-edit.hpp" #include "variable-text-edit.hpp"
#include "source-interact.hpp"
#include "source-properties-button.hpp" #include "source-properties-button.hpp"
#include "source-selection.hpp" #include "source-selection.hpp"
#include "source-setting.hpp" #include "source-setting.hpp"
@ -34,6 +35,7 @@ public:
OBS_DEINTERLACE_FIELD_ORDER_TOP; OBS_DEINTERLACE_FIELD_ORDER_TOP;
TempVariableRef _tempVar; TempVariableRef _tempVar;
SourceSetting _setting; SourceSetting _setting;
SourceInteraction _interaction;
enum class Action { enum class Action {
ENABLE, ENABLE,
@ -46,6 +48,7 @@ public:
OPEN_INTERACTION_DIALOG, OPEN_INTERACTION_DIALOG,
OPEN_FILTER_DIALOG, OPEN_FILTER_DIALOG,
OPEN_PROPERTIES_DIALOG, OPEN_PROPERTIES_DIALOG,
INTERACT,
}; };
Action _action = Action::SETTINGS; Action _action = Action::SETTINGS;
@ -92,6 +95,8 @@ private slots:
void ManualSettingsValueChanged(); void ManualSettingsValueChanged();
void RefreshVariableSourceSelectionValue(); void RefreshVariableSourceSelectionValue();
void InteractionTypeChanged(SourceInteraction::Type value);
void InteractionSettingsChanged(SourceInteractionInstance *value);
signals: signals:
void HeaderInfoChanged(const QString &); void HeaderInfoChanged(const QString &);
@ -112,6 +117,7 @@ private:
QComboBox *_deinterlaceOrder; QComboBox *_deinterlaceOrder;
QLabel *_warning; QLabel *_warning;
QPushButton *_refreshSettingSelection; QPushButton *_refreshSettingSelection;
SourceInteractionWidget *_interaction;
std::shared_ptr<MacroActionSource> _entryData; std::shared_ptr<MacroActionSource> _entryData;
bool _loading = true; bool _loading = true;

View File

@ -0,0 +1,882 @@
#include "source-interact.hpp"
#include "obs-module-helper.hpp"
#include "layout-helpers.hpp"
#include <QLayout>
#include <QLabel>
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<MouseClick>();
}
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<int>(_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<Type>(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<int>(_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<Button>(obs_data_get_int(data, "button"));
_up = obs_data_get_bool(data, "up");
_pos.Load(data);
_count.Load(data, "count");
_modifier.Load(data);
}
void MouseClick::SendToSource(obs_source_t *source) const
{
obs_mouse_event ev = {_modifier.GetModifiers(), _pos.x, _pos.y};
obs_source_send_mouse_click(source, &ev, static_cast<int32_t>(_button),
_up, _count);
}
void MouseMove::Save(obs_data_t *obj, const char *name) const
{
OBSDataAutoRelease data = obs_data_create();
_pos.Save(data);
_modifier.Save(data);
obs_data_set_obj(obj, name, data);
}
void MouseMove::Load(obs_data_t *obj, const char *name)
{
OBSDataAutoRelease data = obs_data_get_obj(obj, name);
_pos.Load(data);
_modifier.Load(data);
}
void MouseMove::SendToSource(obs_source_t *source) const
{
obs_mouse_event ev = {_modifier.GetModifiers(), _pos.x, _pos.y};
obs_source_send_mouse_move(source, &ev, _leaveSource);
}
void MouseWheel::Save(obs_data_t *obj, const char *name) const
{
OBSDataAutoRelease data = obs_data_create();
_pos.Save(data);
_amount.Save(data, "amount");
_pos.Save(data);
_modifier.Save(data);
obs_data_set_obj(obj, name, data);
}
void MouseWheel::Load(obs_data_t *obj, const char *name)
{
OBSDataAutoRelease data = obs_data_get_obj(obj, name);
_pos.Load(data);
_amount.Load(data, "amount");
_modifier.Load(data);
}
void MouseWheel::SendToSource(obs_source_t *source) const
{
obs_mouse_event ev = {_modifier.GetModifiers(), _pos.x, _pos.y};
obs_source_send_mouse_wheel(source, &ev, _amount.x, _amount.y);
}
void KeyPress::Save(obs_data_t *obj, const char *name) const
{
OBSDataAutoRelease data = obs_data_create();
obs_data_set_bool(data, "up", _up);
_modifier.Save(data);
obs_data_set_obj(obj, name, data);
}
void KeyPress::Load(obs_data_t *obj, const char *name)
{
OBSDataAutoRelease data = obs_data_get_obj(obj, name);
_up = obs_data_get_bool(data, "up");
_modifier.Load(data);
}
void KeyPress::SendToSource(obs_source_t *source) const
{
char text = _text;
obs_key_event ev = {_modifier.GetModifiers(), &text, 0, 0, 0};
obs_source_send_key_click(source, &ev, _up);
}
PositionSelection::PositionSelection(int min, int max, QWidget *parent)
: QWidget(parent),
_x(new VariableSpinBox),
_y(new VariableSpinBox)
{
_x->setMinimum(min);
_y->setMinimum(min);
_x->setMaximum(max);
_y->setMaximum(max);
connect(_x, SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
this, SLOT(XChanged(const NumberVariable<int> &)));
connect(_y, SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
this, SLOT(YChanged(const NumberVariable<int> &)));
auto layout = new QHBoxLayout();
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(_x);
layout->setStretch(0, 3);
auto label = new QLabel("x");
label->setAlignment(Qt::AlignCenter);
layout->addWidget(label);
layout->addWidget(_y);
layout->setStretch(2, 3);
setLayout(layout);
}
void PositionSelection::SetPosition(const Position &pos)
{
_x->SetValue(pos.x);
_y->SetValue(pos.y);
}
Position PositionSelection::GetPosition() const
{
return Position{_x->Value(), _y->Value()};
}
void PositionSelection::XChanged(const NumberVariable<int> &value)
{
emit PositionChanged(Position{value, _y->Value()});
}
void PositionSelection::YChanged(const NumberVariable<int> &value)
{
emit PositionChanged(Position{_x->Value(), value});
}
ModifierSelection::ModifierSelection(QWidget *parent)
: QWidget(parent),
_shift(new QCheckBox(
obs_module_text("AdvSceneSwitcher.modifierKey.shift"))),
_ctrl(new QCheckBox(
obs_module_text("AdvSceneSwitcher.modifierKey.ctrl"))),
_alt(new QCheckBox(
obs_module_text("AdvSceneSwitcher.modifierKey.alt"))),
_meta(new QCheckBox(
obs_module_text("AdvSceneSwitcher.modifierKey.meta")))
{
connect(_shift, SIGNAL(stateChanged(int)), this,
SLOT(ShiftChanged(int)));
connect(_ctrl, SIGNAL(stateChanged(int)), this, SLOT(CtrlChanged(int)));
connect(_alt, SIGNAL(stateChanged(int)), this, SLOT(AltChanged(int)));
connect(_meta, SIGNAL(stateChanged(int)), this, SLOT(MetaChanged(int)));
auto layout = new QHBoxLayout();
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(_shift);
layout->addWidget(_ctrl);
layout->addWidget(_alt);
layout->addWidget(_meta);
setLayout(layout);
}
void ModifierSelection::SetModifier(const Modifier &modifier)
{
_shift->setChecked(modifier._shift);
_ctrl->setChecked(modifier._ctrl);
_alt->setChecked(modifier._alt);
_meta->setChecked(modifier._meta);
}
Modifier ModifierSelection::GetCurrentModifier() const
{
Modifier modifier;
modifier.EnableShift(_shift->isChecked());
modifier.EnableCtrl(_ctrl->isChecked());
modifier.EnableAlt(_alt->isChecked());
modifier.EnableMeta(_meta->isChecked());
return modifier;
}
void ModifierSelection::ShiftChanged(int value)
{
auto modifier = GetCurrentModifier();
modifier.EnableShift(value);
emit ModifierChanged(modifier);
}
void ModifierSelection::CtrlChanged(int value)
{
auto modifier = GetCurrentModifier();
modifier.EnableCtrl(value);
emit ModifierChanged(modifier);
}
void ModifierSelection::AltChanged(int value)
{
auto modifier = GetCurrentModifier();
modifier.EnableAlt(value);
emit ModifierChanged(modifier);
}
void ModifierSelection::MetaChanged(int value)
{
auto modifier = GetCurrentModifier();
modifier.EnableMeta(value);
emit ModifierChanged(modifier);
}
static inline void populateInteractionTypeSelection(QComboBox *list)
{
list->addItem(
obs_module_text(
"AdvSceneSwitcher.action.source.type.interact.mouseClick"),
(int)SourceInteraction::Type::CLICK);
list->addItem(
obs_module_text(
"AdvSceneSwitcher.action.source.type.interact.mouseMove"),
(int)SourceInteraction::Type::MOVE);
list->addItem(
obs_module_text(
"AdvSceneSwitcher.action.source.type.interact.mouseWheel"),
(int)SourceInteraction::Type::WHEEL);
list->addItem(
obs_module_text(
"AdvSceneSwitcher.action.source.type.interact.keyPress"),
(int)SourceInteraction::Type::KEY);
}
SourceInteractionWidget::SourceInteractionWidget(QWidget *parent)
: QWidget(parent),
_type(new QComboBox),
_settingsLayout(new QHBoxLayout)
{
populateInteractionTypeSelection(_type);
connect(_type, SIGNAL(currentIndexChanged(int)), this,
SLOT(TypeChange(int)));
auto typeLayout = new QHBoxLayout();
PlaceWidgets(
obs_module_text(
"AdvSceneSwitcher.action.source.type.interact.selectType"),
typeLayout, {{"{{type}}", _type}});
SetupSettingsWidget(SourceInteraction::Type::CLICK);
auto layout = new QVBoxLayout();
layout->setContentsMargins(0, 0, 0, 0);
layout->addLayout(typeLayout);
layout->addLayout(_settingsLayout);
setLayout(layout);
}
void SourceInteractionWidget::SetupSettingsWidget(SourceInteraction::Type type)
{
_type->setCurrentIndex(_type->findData(static_cast<int>(type)));
ClearLayout(_settingsLayout);
switch (type) {
case SourceInteraction::Type::CLICK:
SetupMouseClick();
break;
case SourceInteraction::Type::MOVE:
SetupMouseMove();
break;
case SourceInteraction::Type::WHEEL:
SetupMouseWheel();
break;
case SourceInteraction::Type::KEY:
SetupKeyPress();
break;
}
_settingsLayout->update();
adjustSize();
updateGeometry();
}
void SourceInteractionWidget::SetupMouseClick()
{
auto widget = new MouseClickSettings();
connect(widget, SIGNAL(MouseClickSettingsChanged(const MouseClick &)),
this, SLOT(MouseClickSettingsChanged(const MouseClick &)));
_settingsLayout->addWidget(widget);
}
void SourceInteractionWidget::SetupMouseMove()
{
auto widget = new MouseMoveSettings();
connect(widget, SIGNAL(MouseMoveSettingsChanged(const MouseMove &)),
this, SLOT(MouseMoveSettingsChanged(const MouseMove &)));
_settingsLayout->addWidget(widget);
}
void SourceInteractionWidget::SetupMouseWheel()
{
auto widget = new MouseWheelSettings();
connect(widget, SIGNAL(MouseWheelSettingsChanged(const MouseWheel &)),
this, SLOT(MouseWheelSettingsChanged(const MouseWheel &)));
_settingsLayout->addWidget(widget);
}
void SourceInteractionWidget::SetupKeyPress()
{
auto widget = new KeyPressSettings();
connect(widget, SIGNAL(KeyPressSettingsChanged(const KeyPress &)), this,
SLOT(KeyPressSettingsChanged(const KeyPress &)));
_settingsLayout->addWidget(widget);
}
void SourceInteractionWidget::TypeChange(int idx)
{
auto type = static_cast<SourceInteraction::Type>(
_type->itemData(idx).toInt());
SetupSettingsWidget(type);
emit TypeChanged(type);
}
void SourceInteractionWidget::SetSourceInteractionSelection(
const SourceInteraction &interaction)
{
SetupSettingsWidget(interaction._type);
auto item = _settingsLayout->itemAt(0);
if (!item) {
return;
}
auto widget = item->widget();
if (!widget) {
return;
}
switch (interaction._type) {
case SourceInteraction::Type::CLICK: {
auto mouseClickWidget =
dynamic_cast<MouseClickSettings *>(widget);
if (!mouseClickWidget) {
return;
}
auto mouseClickSettings = dynamic_cast<MouseClick *>(
interaction._interaction.get());
if (!mouseClickSettings) {
return;
}
mouseClickWidget->SetMouseClickSettings(*mouseClickSettings);
}
return;
case SourceInteraction::Type::MOVE: {
auto mouseMoveWidget =
dynamic_cast<MouseMoveSettings *>(widget);
if (!mouseMoveWidget) {
return;
}
auto mouseMoveSettings = dynamic_cast<MouseMove *>(
interaction._interaction.get());
if (!mouseMoveSettings) {
return;
}
mouseMoveWidget->SetMouseMoveSettings(*mouseMoveSettings);
}
return;
case SourceInteraction::Type::WHEEL: {
auto mouseWheelWidget =
dynamic_cast<MouseWheelSettings *>(widget);
if (!mouseWheelWidget) {
return;
}
auto mouseWheelSettings = dynamic_cast<MouseWheel *>(
interaction._interaction.get());
if (!mouseWheelSettings) {
return;
}
mouseWheelWidget->SetMouseWheelSettings(*mouseWheelSettings);
}
return;
case SourceInteraction::Type::KEY: {
auto KeyPressWidget = dynamic_cast<KeyPressSettings *>(widget);
if (!KeyPressWidget) {
return;
}
auto KeyPressSettings = dynamic_cast<KeyPress *>(
interaction._interaction.get());
if (!KeyPressSettings) {
return;
}
KeyPressWidget->SetKeyPressSettings(*KeyPressSettings);
}
return;
}
adjustSize();
updateGeometry();
}
void SourceInteractionWidget::MouseClickSettingsChanged(const MouseClick &value)
{
auto click = new MouseClick();
*click = value;
emit SettingsChanged(click);
}
void SourceInteractionWidget::MouseMoveSettingsChanged(const MouseMove &value)
{
auto move = new MouseMove();
*move = value;
emit SettingsChanged(move);
}
void SourceInteractionWidget::MouseWheelSettingsChanged(const MouseWheel &value)
{
auto wheel = new MouseWheel();
*wheel = value;
emit SettingsChanged(wheel);
}
void SourceInteractionWidget::KeyPressSettingsChanged(const KeyPress &value)
{
auto key = new KeyPress();
*key = value;
emit SettingsChanged(key);
}
static inline void populateMouseButtonSelection(QComboBox *list)
{
list->addItem(obs_module_text("AdvSceneSwitcher.mouse.button.left"));
list->addItem(obs_module_text("AdvSceneSwitcher.mouse.button.middle"));
list->addItem(obs_module_text("AdvSceneSwitcher.mouse.button.right"));
}
MouseClickSettings::MouseClickSettings(QWidget *parent)
: QWidget(parent),
_button(new QComboBox),
_position(new PositionSelection(0, 999999)),
_up(new QCheckBox),
_count(new VariableSpinBox),
_modifier(new ModifierSelection)
{
_count->setMinimum(1);
_count->setMaximum(99);
populateMouseButtonSelection(_button);
connect(_button, SIGNAL(currentIndexChanged(int)), this,
SLOT(ButtonChanged(int)));
connect(_position, SIGNAL(PositionChanged(const Position &)), this,
SLOT(PositionChanged(const Position &)));
connect(_up, SIGNAL(stateChanged(int)), this, SLOT(UpChanged(int)));
connect(_count,
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
this, SLOT(CountChanged(const NumberVariable<int> &)));
connect(_modifier, SIGNAL(ModifierChanged(const Modifier &)), this,
SLOT(ModifierChanged(const Modifier &)));
auto layout = new QGridLayout();
layout->setColumnStretch(1, 3);
layout->setContentsMargins(0, 0, 0, 0);
int row = 0;
layout->addWidget(
new QLabel(obs_module_text("AdvSceneSwitcher.mouse.button")),
row, 0);
layout->addWidget(_button, row, 1);
++row;
layout->addWidget(
new QLabel(obs_module_text("AdvSceneSwitcher.mouse.position")),
row, 0);
layout->addWidget(_position, row, 1);
++row;
layout->addWidget(
new QLabel(obs_module_text("AdvSceneSwitcher.mouse.up")), row,
0);
layout->addWidget(_up, row, 1);
++row;
layout->addWidget(
new QLabel(obs_module_text("AdvSceneSwitcher.mouse.count")),
row, 0);
layout->addWidget(_count, row, 1);
++row;
layout->addWidget(
new QLabel(obs_module_text("AdvSceneSwitcher.modifierKey")),
row, 0);
layout->addWidget(_modifier, row, 1);
++row;
setLayout(layout);
}
void MouseClickSettings::SetMouseClickSettings(const MouseClick &click)
{
_button->setCurrentIndex(static_cast<int>(click._button));
_position->SetPosition(click._pos);
_up->setChecked(click._up);
_count->SetValue(click._count);
_modifier->SetModifier(click._modifier);
}
void MouseClickSettings::ButtonChanged(int button)
{
auto click = GetCurrentMouseClick();
click.SetButton(static_cast<MouseClick::Button>(button));
emit MouseClickSettingsChanged(click);
}
void MouseClickSettings::PositionChanged(const Position &pos)
{
auto click = GetCurrentMouseClick();
click.SetPosition(pos);
emit MouseClickSettingsChanged(click);
}
void MouseClickSettings::UpChanged(int value)
{
auto click = GetCurrentMouseClick();
click.SetDirection(value);
emit MouseClickSettingsChanged(click);
}
void MouseClickSettings::CountChanged(const IntVariable &value)
{
auto click = GetCurrentMouseClick();
click.SetCount(value);
emit MouseClickSettingsChanged(click);
}
void MouseClickSettings::ModifierChanged(const Modifier &modifier)
{
auto click = GetCurrentMouseClick();
click.SetModifier(modifier);
emit MouseClickSettingsChanged(click);
}
MouseClick MouseClickSettings::GetCurrentMouseClick() const
{
MouseClick click;
click.SetButton(
static_cast<MouseClick::Button>(_button->currentIndex()));
click.SetPosition(_position->GetPosition());
click.SetDirection(_up->isChecked());
click.SetCount(_count->Value());
click.SetModifier(_modifier->GetModifier());
return click;
}
MouseMoveSettings::MouseMoveSettings(QWidget *parent)
: QWidget(parent),
_position(new PositionSelection(0, 999999)),
_leaveEvent(new QCheckBox),
_modifier(new ModifierSelection)
{
connect(_position, SIGNAL(PositionChanged(const Position &)), this,
SLOT(PositionChanged(const Position &)));
connect(_leaveEvent, SIGNAL(stateChanged(int)), this,
SLOT(LeaveChanged(int)));
connect(_modifier, SIGNAL(ModifierChanged(const Modifier &)), this,
SLOT(ModifierChanged(const Modifier &)));
auto layout = new QGridLayout();
layout->setColumnStretch(1, 3);
layout->setContentsMargins(0, 0, 0, 0);
int row = 0;
layout->addWidget(
new QLabel(obs_module_text("AdvSceneSwitcher.mouse.position")),
row, 0);
layout->addWidget(_position, row, 1);
++row;
layout->addWidget(
new QLabel(obs_module_text("AdvSceneSwitcher.mouse.leave")),
row, 0);
layout->addWidget(_leaveEvent, row, 1);
++row;
layout->addWidget(
new QLabel(obs_module_text("AdvSceneSwitcher.modifierKey")),
row, 0);
layout->addWidget(_modifier, row, 1);
++row;
setLayout(layout);
}
void MouseMoveSettings::SetMouseMoveSettings(const MouseMove &move)
{
_position->SetPosition(move._pos);
_leaveEvent->setChecked(move._leaveSource);
_modifier->SetModifier(move._modifier);
}
void MouseMoveSettings::PositionChanged(const Position &pos)
{
auto move = GetCurrentMouseMove();
move.SetPosition(pos);
emit MouseMoveSettingsChanged(move);
}
void MouseMoveSettings::LeaveChanged(int value)
{
auto move = GetCurrentMouseMove();
move.SetLeave(value);
emit MouseMoveSettingsChanged(move);
}
void MouseMoveSettings::ModifierChanged(const Modifier &modifier)
{
auto move = GetCurrentMouseMove();
move.SetModifier(modifier);
emit MouseMoveSettingsChanged(move);
}
MouseMove MouseMoveSettings::GetCurrentMouseMove() const
{
MouseMove move;
move.SetPosition(_position->GetPosition());
move.SetLeave(_leaveEvent->isChecked());
move.SetModifier(_modifier->GetModifier());
return move;
}
MouseWheelSettings::MouseWheelSettings(QWidget *parent)
: QWidget(parent),
_position(new PositionSelection(0, 999999)),
_amount(new PositionSelection(-999999, 999999)),
_modifier(new ModifierSelection)
{
connect(_position, SIGNAL(PositionChanged(const Position &)), this,
SLOT(PositionChanged(const Position &)));
connect(_amount, SIGNAL(PositionChanged(const Position &)), this,
SLOT(AmountChanged(const Position &)));
connect(_modifier, SIGNAL(ModifierChanged(const Modifier &)), this,
SLOT(ModifierChanged(const Modifier &)));
auto layout = new QGridLayout();
layout->setColumnStretch(1, 3);
layout->setContentsMargins(0, 0, 0, 0);
int row = 0;
layout->addWidget(
new QLabel(obs_module_text("AdvSceneSwitcher.mouse.position")),
row, 0);
layout->addWidget(_position, row, 1);
++row;
layout->addWidget(new QLabel(obs_module_text(
"AdvSceneSwitcher.mouse.scrollAmount")),
row, 0);
layout->addWidget(_amount, row, 1);
++row;
layout->addWidget(
new QLabel(obs_module_text("AdvSceneSwitcher.modifierKey")),
row, 0);
layout->addWidget(_modifier, row, 1);
++row;
setLayout(layout);
}
void MouseWheelSettings::SetMouseWheelSettings(const MouseWheel &wheel)
{
_position->SetPosition(wheel._pos);
_position->SetPosition(wheel._amount);
_modifier->SetModifier(wheel._modifier);
}
void MouseWheelSettings::PositionChanged(const Position &pos)
{
auto wheel = GetCurrentMouseWheel();
wheel.SetPosition(pos);
emit MouseWheelSettingsChanged(wheel);
}
void MouseWheelSettings::AmountChanged(const Position &amount)
{
auto wheel = GetCurrentMouseWheel();
wheel.SetAmount(amount);
emit MouseWheelSettingsChanged(wheel);
}
void MouseWheelSettings::ModifierChanged(const Modifier &modifier)
{
auto move = GetCurrentMouseWheel();
move.SetModifier(modifier);
emit MouseWheelSettingsChanged(move);
}
MouseWheel MouseWheelSettings::GetCurrentMouseWheel() const
{
MouseWheel wheel;
wheel.SetPosition(_position->GetPosition());
wheel.SetAmount(_amount->GetPosition());
wheel.SetModifier(_modifier->GetModifier());
return wheel;
}
KeyPressSettings::KeyPressSettings(QWidget *parent)
: QWidget(parent),
_text(new QLineEdit()),
_up(new QCheckBox()),
_modifier(new ModifierSelection)
{
_text->setMaxLength(1);
connect(_text, SIGNAL(editingFinished()), this, SLOT(TextChanged()));
connect(_up, SIGNAL(stateChanged(int)), this, SLOT(UpChanged(int)));
connect(_modifier, SIGNAL(ModifierChanged(const Modifier &)), this,
SLOT(ModifierChanged(const Modifier &)));
auto layout = new QGridLayout();
layout->setColumnStretch(1, 3);
layout->setContentsMargins(0, 0, 0, 0);
int row = 0;
layout->addWidget(new QLabel(obs_module_text("AdvSceneSwitcher.key")),
row, 0);
layout->addWidget(_text, row, 1);
++row;
layout->addWidget(
new QLabel(obs_module_text("AdvSceneSwitcher.key.up")), row, 0);
layout->addWidget(_up, row, 1);
++row;
layout->addWidget(
new QLabel(obs_module_text("AdvSceneSwitcher.modifierKey")),
row, 0);
layout->addWidget(_modifier, row, 1);
++row;
setLayout(layout);
}
void KeyPressSettings::SetKeyPressSettings(const KeyPress &key)
{
_text->setText(QString(key._text));
_up->setChecked(key._up);
_modifier->SetModifier(key._modifier);
}
void KeyPressSettings::TextChanged()
{
auto key = GetCurrentKeyPress();
key.SetKey(_text->text().at(0).toLatin1());
emit KeyPressSettingsChanged(key);
}
void KeyPressSettings::UpChanged(int value)
{
auto key = GetCurrentKeyPress();
key.SetDirection(value);
emit KeyPressSettingsChanged(key);
}
void KeyPressSettings::ModifierChanged(const Modifier &modifier)
{
auto move = GetCurrentKeyPress();
move.SetModifier(modifier);
emit KeyPressSettingsChanged(move);
}
KeyPress KeyPressSettings::GetCurrentKeyPress() const
{
KeyPress key;
key.SetDirection(_up->isChecked());
key.SetModifier(_modifier->GetModifier());
return key;
}
} // namespace advss

View File

@ -0,0 +1,337 @@
#pragma once
#include "variable-number.hpp"
#include "variable-spinbox.hpp"
#include <chrono>
#include <memory>
#include <obs.hpp>
#include <QWidget>
#include <QSpinBox>
#include <QComboBox>
#include <QCheckBox>
#include <QLineEdit>
#include <QLayout>
namespace advss {
struct Position {
void Save(obs_data_t *obj, const char *name = "position") const;
void Load(obs_data_t *obj, const char *name = "position");
IntVariable x = 0;
IntVariable y = 0;
};
class Modifier {
public:
void Save(obs_data_t *obj, const char *name = "modifier") const;
void Load(obs_data_t *obj, const char *name = "modifier");
void EnableShift(bool value) { _shift = value; }
void EnableCtrl(bool value) { _ctrl = value; }
void EnableAlt(bool value) { _alt = value; }
void EnableMeta(bool value) { _meta = value; }
uint32_t GetModifiers() const;
private:
bool _shift = false;
bool _ctrl = false;
bool _alt = false;
bool _meta = false;
friend class ModifierSelection;
};
class SourceInteractionInstance;
class SourceInteraction {
public:
SourceInteraction();
SourceInteraction(const SourceInteraction &);
void Save(obs_data_t *obj, const char *name = "interaction") const;
void Load(obs_data_t *obj, const char *name = "interaction");
enum class Type {
CLICK,
MOVE,
WHEEL,
KEY,
};
void SetType(Type);
void SetSettings(SourceInteractionInstance *);
void SendToSource(obs_source_t *source) const;
private:
void UpdateType();
Type _type = Type::CLICK;
std::unique_ptr<SourceInteractionInstance> _interaction;
friend class SourceInteractionWidget;
};
class SourceInteractionInstance {
public:
virtual void Save(obs_data_t *obj, const char *name) const = 0;
virtual void Load(obs_data_t *obj, const char *name) = 0;
void SetModifier(Modifier modifier) { _modifier = modifier; }
virtual void SendToSource(obs_source_t *source) const = 0;
virtual ~SourceInteractionInstance(){};
protected:
Modifier _modifier;
};
/* Interaction types below */
class MouseClick : public SourceInteractionInstance {
public:
void Save(obs_data_t *obj,
const char *name = "mouseClick") const override;
void Load(obs_data_t *obj, const char *name = "mouseClick") override;
enum class Button {
LEFT,
MIDDLE,
RIGHT,
};
void SetButton(Button button) { _button = button; }
void SetDirection(bool up) { _up = up; }
void SetCount(const IntVariable &count) { _count = count; }
void SetPosition(const Position &pos) { _pos = pos; }
void SendToSource(obs_source_t *source) const override;
private:
Button _button = Button::LEFT;
Position _pos;
bool _up = false;
IntVariable _count = 1;
friend class MouseClickSettings;
};
class MouseMove : public SourceInteractionInstance {
public:
void Save(obs_data_t *obj,
const char *name = "mouseMove") const override;
void Load(obs_data_t *obj, const char *name = "mouseMove") override;
void SetLeave(bool leave) { _leaveSource = leave; }
void SetPosition(const Position &pos) { _pos = pos; }
void SendToSource(obs_source_t *source) const override;
private:
Position _pos;
bool _leaveSource = false;
friend class MouseMoveSettings;
};
class MouseWheel : public SourceInteractionInstance {
public:
void Save(obs_data_t *obj,
const char *name = "mouseWheel") const override;
void Load(obs_data_t *obj, const char *name = "mouseWheel") override;
void SetPosition(const Position &pos) { _pos = pos; }
void SetAmount(const Position &amount) { _amount = amount; }
void SendToSource(obs_source_t *source) const override;
private:
Position _pos;
Position _amount;
friend class MouseWheelSettings;
};
class KeyPress : public SourceInteractionInstance {
public:
void Save(obs_data_t *obj,
const char *name = "keyPress") const override;
void Load(obs_data_t *obj, const char *name = "keyPress") override;
void SetDirection(bool up) { _up = up; }
void SetKey(char value) { _text = value; }
void SendToSource(obs_source_t *source) const override;
private:
char _text;
bool _up = false;
friend class KeyPressSettings;
};
/* Helper widgets below */
class PositionSelection : public QWidget {
Q_OBJECT
public:
PositionSelection(int min, int max, QWidget *parent = 0);
void SetPosition(const Position &);
Position GetPosition() const;
private slots:
void XChanged(const NumberVariable<int> &);
void YChanged(const NumberVariable<int> &);
signals:
void PositionChanged(const Position &value);
private:
VariableSpinBox *_x;
VariableSpinBox *_y;
};
class ModifierSelection : public QWidget {
Q_OBJECT
public:
ModifierSelection(QWidget *parent = 0);
void SetModifier(const Modifier &);
Modifier GetModifier() const { return GetCurrentModifier(); }
private slots:
void ShiftChanged(int);
void CtrlChanged(int);
void AltChanged(int);
void MetaChanged(int);
signals:
void ModifierChanged(const Modifier &value);
private:
Modifier GetCurrentModifier() const;
QCheckBox *_shift;
QCheckBox *_ctrl;
QCheckBox *_alt;
QCheckBox *_meta;
};
/* Settings widgets below */
class SourceInteractionWidget : public QWidget {
Q_OBJECT
public:
SourceInteractionWidget(QWidget *parent = 0);
void SetSourceInteractionSelection(const SourceInteraction &);
private slots:
void TypeChange(int);
void MouseClickSettingsChanged(const MouseClick &);
void MouseMoveSettingsChanged(const MouseMove &);
void MouseWheelSettingsChanged(const MouseWheel &);
void KeyPressSettingsChanged(const KeyPress &);
signals:
void TypeChanged(SourceInteraction::Type value);
void SettingsChanged(SourceInteractionInstance *value);
private:
void SetupSettingsWidget(SourceInteraction::Type);
void SetupMouseClick();
void SetupMouseMove();
void SetupMouseWheel();
void SetupKeyPress();
QComboBox *_type;
QHBoxLayout *_settingsLayout;
};
class MouseClickSettings : public QWidget {
Q_OBJECT
public:
MouseClickSettings(QWidget *parent = 0);
void SetMouseClickSettings(const MouseClick &);
private slots:
void ButtonChanged(int);
void PositionChanged(const Position &);
void UpChanged(int);
void CountChanged(const NumberVariable<int> &);
void ModifierChanged(const Modifier &);
signals:
void MouseClickSettingsChanged(const MouseClick &value);
private:
MouseClick GetCurrentMouseClick() const;
QComboBox *_button;
PositionSelection *_position;
QCheckBox *_up;
VariableSpinBox *_count;
ModifierSelection *_modifier;
};
class MouseMoveSettings : public QWidget {
Q_OBJECT
public:
MouseMoveSettings(QWidget *parent = 0);
void SetMouseMoveSettings(const MouseMove &);
private slots:
void PositionChanged(const Position &);
void LeaveChanged(int);
void ModifierChanged(const Modifier &);
signals:
void MouseMoveSettingsChanged(const MouseMove &value);
private:
MouseMove GetCurrentMouseMove() const;
PositionSelection *_position;
QCheckBox *_leaveEvent;
ModifierSelection *_modifier;
};
class MouseWheelSettings : public QWidget {
Q_OBJECT
public:
MouseWheelSettings(QWidget *parent = 0);
void SetMouseWheelSettings(const MouseWheel &);
private slots:
void PositionChanged(const Position &);
void AmountChanged(const Position &);
void ModifierChanged(const Modifier &);
signals:
void MouseWheelSettingsChanged(const MouseWheel &value);
private:
MouseWheel GetCurrentMouseWheel() const;
PositionSelection *_position;
PositionSelection *_amount;
ModifierSelection *_modifier;
};
class KeyPressSettings : public QWidget {
Q_OBJECT
public:
KeyPressSettings(QWidget *parent = 0);
void SetKeyPressSettings(const KeyPress &);
private slots:
void TextChanged();
void UpChanged(int);
void ModifierChanged(const Modifier &);
signals:
void KeyPressSettingsChanged(const KeyPress &value);
private:
KeyPress GetCurrentKeyPress() const;
QLineEdit *_text;
QCheckBox *_up;
ModifierSelection *_modifier;
};
} // namespace advss