mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-03-22 09:54:54 -05:00
404 lines
12 KiB
C++
404 lines
12 KiB
C++
#include "macro-action-transition.hpp"
|
|
#include "layout-helpers.hpp"
|
|
|
|
#include <obs-frontend-api.h>
|
|
|
|
namespace advss {
|
|
|
|
const std::string MacroActionTransition::id = "transition";
|
|
|
|
bool MacroActionTransition::_registered = MacroActionFactory::Register(
|
|
MacroActionTransition::id,
|
|
{MacroActionTransition::Create, MacroActionTransitionEdit::Create,
|
|
"AdvSceneSwitcher.action.transition"});
|
|
|
|
const static std::map<MacroActionTransition::Type, std::string> actionTypes = {
|
|
{MacroActionTransition::Type::SCENE,
|
|
"AdvSceneSwitcher.action.transition.type.scene"},
|
|
{MacroActionTransition::Type::SCENE_OVERRIDE,
|
|
"AdvSceneSwitcher.action.transition.type.sceneOverride"},
|
|
{MacroActionTransition::Type::SOURCE_SHOW,
|
|
"AdvSceneSwitcher.action.transition.type.sourceShow"},
|
|
{MacroActionTransition::Type::SOURCE_HIDE,
|
|
"AdvSceneSwitcher.action.transition.type.sourceHide"},
|
|
};
|
|
|
|
void MacroActionTransition::SetSceneTransition()
|
|
{
|
|
if (_setTransitionType) {
|
|
OBSSourceAutoRelease transition =
|
|
obs_weak_source_get_source(_transition.GetTransition());
|
|
obs_frontend_set_current_transition(transition);
|
|
}
|
|
if (_setDuration) {
|
|
obs_frontend_set_transition_duration(_duration.Seconds() *
|
|
1000);
|
|
}
|
|
}
|
|
|
|
void MacroActionTransition::SetTransitionOverride()
|
|
{
|
|
OBSSourceAutoRelease scene =
|
|
obs_weak_source_get_source(_scene.GetScene());
|
|
OBSDataAutoRelease data = obs_source_get_private_settings(scene);
|
|
if (_setTransitionType) {
|
|
obs_data_set_string(data, "transition",
|
|
_transition.ToString().c_str());
|
|
}
|
|
if (_setDuration) {
|
|
obs_data_set_int(data, "transition_duration",
|
|
_duration.Milliseconds());
|
|
}
|
|
}
|
|
|
|
#if (LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(27, 0, 0)) && \
|
|
(LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(28, 0, 0))
|
|
static void obs_sceneitem_set_transition(obs_sceneitem_t *item, bool show,
|
|
obs_source_t *transition)
|
|
{
|
|
if (show) {
|
|
obs_sceneitem_set_show_transition(item, transition);
|
|
} else {
|
|
obs_sceneitem_set_hide_transition(item, transition);
|
|
}
|
|
}
|
|
|
|
static void obs_sceneitem_set_transition_duration(obs_sceneitem_t *item,
|
|
bool show,
|
|
uint32_t duration_ms)
|
|
{
|
|
if (show) {
|
|
obs_sceneitem_set_show_transition_duration(item, duration_ms);
|
|
} else {
|
|
obs_sceneitem_set_hide_transition_duration(item, duration_ms);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static void setSceneItemTransition(const OBSSceneItem &item,
|
|
const OBSSourceAutoRelease &transition,
|
|
bool show)
|
|
{
|
|
OBSDataAutoRelease settings = obs_source_get_settings(transition);
|
|
if (!transition || !settings) {
|
|
// Set transition to "None"
|
|
obs_sceneitem_set_transition(item, show, nullptr);
|
|
return;
|
|
}
|
|
|
|
// We cannot share the transition source between
|
|
// scene items without introducing strange graphical
|
|
// artifacts so we have to create new ones here
|
|
OBSSourceAutoRelease transitionSource = obs_source_create_private(
|
|
obs_source_get_id(transition), obs_source_get_name(transition),
|
|
settings);
|
|
obs_sceneitem_set_transition(item, show, transitionSource);
|
|
}
|
|
|
|
void MacroActionTransition::SetSourceTransition(bool show)
|
|
{
|
|
#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(27, 0, 0)
|
|
OBSSourceAutoRelease transition =
|
|
obs_weak_source_get_source(_transition.GetTransition());
|
|
const auto items = _source.GetSceneItems(_scene);
|
|
for (const auto &item : items) {
|
|
if (_setTransitionType) {
|
|
setSceneItemTransition(item, transition, show);
|
|
}
|
|
if (_setDuration) {
|
|
obs_sceneitem_set_transition_duration(
|
|
item, show, _duration.Milliseconds());
|
|
}
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
bool MacroActionTransition::PerformAction()
|
|
{
|
|
switch (_type) {
|
|
case Type::SCENE:
|
|
SetSceneTransition();
|
|
break;
|
|
case Type::SCENE_OVERRIDE:
|
|
SetTransitionOverride();
|
|
break;
|
|
case Type::SOURCE_SHOW:
|
|
SetSourceTransition(true);
|
|
break;
|
|
case Type::SOURCE_HIDE:
|
|
SetSourceTransition(false);
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void MacroActionTransition::LogAction() const
|
|
{
|
|
std::string msgBegin;
|
|
switch (_type) {
|
|
case Type::SCENE:
|
|
msgBegin += "set scene transition";
|
|
break;
|
|
case Type::SCENE_OVERRIDE:
|
|
msgBegin += "set scene override transition of " +
|
|
_scene.ToString(true);
|
|
break;
|
|
case Type::SOURCE_SHOW:
|
|
msgBegin += "set source show transition of " +
|
|
_source.ToString(true) + " on scene " +
|
|
_scene.ToString(true);
|
|
break;
|
|
case Type::SOURCE_HIDE:
|
|
msgBegin += "set source hide transition of " +
|
|
_source.ToString(true) + " on scene " +
|
|
_scene.ToString(true);
|
|
break;
|
|
}
|
|
if (_setDuration) {
|
|
ablog(LOG_INFO, "%s duration to %s", msgBegin.c_str(),
|
|
_duration.ToString().c_str());
|
|
}
|
|
if (_setTransitionType) {
|
|
ablog(LOG_INFO, "%s type to \"%s\"", msgBegin.c_str(),
|
|
_transition.ToString().c_str());
|
|
}
|
|
}
|
|
|
|
bool MacroActionTransition::Save(obs_data_t *obj) const
|
|
{
|
|
MacroAction::Save(obj);
|
|
obs_data_set_int(obj, "actionType", static_cast<int>(_type));
|
|
_source.Save(obj);
|
|
_scene.Save(obj);
|
|
_duration.Save(obj);
|
|
_transition.Save(obj);
|
|
obs_data_set_bool(obj, "setDuration", _setDuration);
|
|
obs_data_set_bool(obj, "setType", _setTransitionType);
|
|
return true;
|
|
}
|
|
|
|
bool MacroActionTransition::Load(obs_data_t *obj)
|
|
{
|
|
MacroAction::Load(obj);
|
|
_type = static_cast<Type>(obs_data_get_int(obj, "actionType"));
|
|
_source.Load(obj);
|
|
_scene.Load(obj);
|
|
_duration.Load(obj);
|
|
_transition.Load(obj);
|
|
_setDuration = obs_data_get_bool(obj, "setDuration");
|
|
_setTransitionType = obs_data_get_bool(obj, "setType");
|
|
return true;
|
|
}
|
|
|
|
std::string MacroActionTransition::GetShortDesc() const
|
|
{
|
|
std::string msgBegin;
|
|
switch (_type) {
|
|
case Type::SCENE:
|
|
return _transition.ToString();
|
|
case Type::SCENE_OVERRIDE:
|
|
return _scene.ToString() + " - " + _transition.ToString();
|
|
case Type::SOURCE_SHOW:
|
|
return _scene.ToString() + " - " + _source.ToString() + " - " +
|
|
_transition.ToString();
|
|
case Type::SOURCE_HIDE:
|
|
return _scene.ToString() + " - " + _source.ToString() + " - " +
|
|
_transition.ToString();
|
|
}
|
|
return "";
|
|
}
|
|
|
|
std::shared_ptr<MacroAction> MacroActionTransition::Create(Macro *m)
|
|
{
|
|
return std::make_shared<MacroActionTransition>(m);
|
|
}
|
|
|
|
std::shared_ptr<MacroAction> MacroActionTransition::Copy() const
|
|
{
|
|
return std::make_shared<MacroActionTransition>(*this);
|
|
}
|
|
|
|
void MacroActionTransition::ResolveVariablesToFixedValues()
|
|
{
|
|
_source.ResolveVariables();
|
|
_scene.ResolveVariables();
|
|
_duration.ResolveVariables();
|
|
}
|
|
|
|
static inline void populateActionSelection(QComboBox *list)
|
|
{
|
|
for (const auto &[_, name] : actionTypes) {
|
|
list->addItem(obs_module_text(name.c_str()));
|
|
}
|
|
}
|
|
|
|
MacroActionTransitionEdit::MacroActionTransitionEdit(
|
|
QWidget *parent, std::shared_ptr<MacroActionTransition> entryData)
|
|
: QWidget(parent),
|
|
_actions(new QComboBox),
|
|
_sources(new SceneItemSelectionWidget(
|
|
parent,
|
|
{
|
|
SceneItemSelection::Type::SOURCE_NAME,
|
|
SceneItemSelection::Type::VARIABLE_NAME,
|
|
SceneItemSelection::Type::SOURCE_NAME_PATTERN,
|
|
SceneItemSelection::Type::SOURCE_GROUP,
|
|
SceneItemSelection::Type::SOURCE_TYPE,
|
|
SceneItemSelection::Type::INDEX,
|
|
SceneItemSelection::Type::INDEX_RANGE,
|
|
SceneItemSelection::Type::ALL,
|
|
},
|
|
SceneItemSelectionWidget::NameClashMode::ALL)),
|
|
_scenes(new SceneSelectionWidget(this, true, false, false, true)),
|
|
_setTransition(new QCheckBox),
|
|
_setDuration(new QCheckBox),
|
|
_transitions(new TransitionSelectionWidget(this, false)),
|
|
_duration(new DurationSelection(this, false)),
|
|
_transitionLayout(new QHBoxLayout),
|
|
_durationLayout(new QHBoxLayout)
|
|
{
|
|
populateActionSelection(_actions);
|
|
|
|
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
|
SLOT(ActionChanged(int)));
|
|
QWidget::connect(_sources,
|
|
SIGNAL(SceneItemChanged(const SceneItemSelection &)),
|
|
this, SLOT(SourceChanged(const SceneItemSelection &)));
|
|
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
|
_sources, SLOT(SceneChanged(const SceneSelection &)));
|
|
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
|
this, SLOT(SceneChanged(const SceneSelection &)));
|
|
QWidget::connect(_transitions,
|
|
SIGNAL(TransitionChanged(const TransitionSelection &)),
|
|
this,
|
|
SLOT(TransitionChanged(const TransitionSelection &)));
|
|
QWidget::connect(_duration, SIGNAL(DurationChanged(const Duration &)),
|
|
this, SLOT(DurationChanged(const Duration &)));
|
|
QWidget::connect(_setTransition, SIGNAL(stateChanged(int)), this,
|
|
SLOT(SetTransitionChanged(int)));
|
|
QWidget::connect(_setDuration, SIGNAL(stateChanged(int)), this,
|
|
SLOT(SetDurationChanged(int)));
|
|
|
|
const std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
|
{"{{type}}", _actions},
|
|
{"{{sources}}", _sources},
|
|
{"{{scenes}}", _scenes},
|
|
{"{{transitions}}", _transitions},
|
|
{"{{duration}}", _duration},
|
|
{"{{setTransition}}", _setTransition},
|
|
{"{{setDuration}}", _setDuration},
|
|
};
|
|
|
|
auto typeLayout = new QHBoxLayout;
|
|
PlaceWidgets(obs_module_text(
|
|
"AdvSceneSwitcher.action.transition.entry.line1"),
|
|
typeLayout, widgetPlaceholders);
|
|
PlaceWidgets(obs_module_text(
|
|
"AdvSceneSwitcher.action.transition.entry.line2"),
|
|
_transitionLayout, widgetPlaceholders);
|
|
PlaceWidgets(obs_module_text(
|
|
"AdvSceneSwitcher.action.transition.entry.line3"),
|
|
_durationLayout, widgetPlaceholders);
|
|
auto mainLayout = new QVBoxLayout;
|
|
mainLayout->addLayout(typeLayout);
|
|
mainLayout->addLayout(_transitionLayout);
|
|
mainLayout->addLayout(_durationLayout);
|
|
setLayout(mainLayout);
|
|
|
|
_entryData = entryData;
|
|
UpdateEntryData();
|
|
_loading = false;
|
|
}
|
|
|
|
void MacroActionTransitionEdit::UpdateEntryData()
|
|
{
|
|
if (!_entryData) {
|
|
return;
|
|
}
|
|
|
|
_actions->setCurrentIndex(static_cast<int>(_entryData->_type));
|
|
_scenes->SetScene(_entryData->_scene);
|
|
_sources->SetSceneItem((_entryData->_source));
|
|
_setDuration->setChecked(_entryData->_setDuration);
|
|
_duration->SetDuration(_entryData->_duration);
|
|
_setTransition->setChecked(_entryData->_setTransitionType);
|
|
_transitions->SetTransition(_entryData->_transition);
|
|
_transitions->setEnabled(_entryData->_setTransitionType);
|
|
_duration->setEnabled(_entryData->_setDuration);
|
|
SetWidgetVisibility();
|
|
}
|
|
|
|
void MacroActionTransitionEdit::SourceChanged(const SceneItemSelection &item)
|
|
{
|
|
GUARD_LOADING_AND_LOCK();
|
|
_entryData->_source = item;
|
|
emit HeaderInfoChanged(
|
|
QString::fromStdString(_entryData->GetShortDesc()));
|
|
adjustSize();
|
|
updateGeometry();
|
|
}
|
|
|
|
void MacroActionTransitionEdit::ActionChanged(int value)
|
|
{
|
|
GUARD_LOADING_AND_LOCK();
|
|
_entryData->_type = static_cast<MacroActionTransition::Type>(value);
|
|
SetWidgetVisibility();
|
|
emit HeaderInfoChanged(
|
|
QString::fromStdString(_entryData->GetShortDesc()));
|
|
}
|
|
|
|
void MacroActionTransitionEdit::SceneChanged(const SceneSelection &s)
|
|
{
|
|
GUARD_LOADING_AND_LOCK();
|
|
_entryData->_scene = s;
|
|
emit HeaderInfoChanged(
|
|
QString::fromStdString(_entryData->GetShortDesc()));
|
|
}
|
|
|
|
void MacroActionTransitionEdit::TransitionChanged(const TransitionSelection &t)
|
|
{
|
|
GUARD_LOADING_AND_LOCK();
|
|
_entryData->_transition = t;
|
|
emit HeaderInfoChanged(
|
|
QString::fromStdString(_entryData->GetShortDesc()));
|
|
}
|
|
|
|
void MacroActionTransitionEdit::DurationChanged(const Duration &dur)
|
|
{
|
|
GUARD_LOADING_AND_LOCK();
|
|
_entryData->_duration = dur;
|
|
}
|
|
|
|
void MacroActionTransitionEdit::SetWidgetVisibility()
|
|
{
|
|
_sources->setVisible(
|
|
_entryData->_type == MacroActionTransition::Type::SOURCE_HIDE ||
|
|
_entryData->_type == MacroActionTransition::Type::SOURCE_SHOW);
|
|
_scenes->setVisible(_entryData->_type !=
|
|
MacroActionTransition::Type::SCENE);
|
|
adjustSize();
|
|
}
|
|
|
|
void MacroActionTransitionEdit::SetTransitionChanged(int state)
|
|
{
|
|
GUARD_LOADING_AND_LOCK();
|
|
_entryData->_setTransitionType = state;
|
|
_transitions->setEnabled(state);
|
|
if (state) {
|
|
emit HeaderInfoChanged(
|
|
QString::fromStdString(_entryData->GetShortDesc()));
|
|
} else {
|
|
emit HeaderInfoChanged("");
|
|
}
|
|
}
|
|
|
|
void MacroActionTransitionEdit::SetDurationChanged(int state)
|
|
{
|
|
GUARD_LOADING_AND_LOCK();
|
|
_entryData->_setDuration = state;
|
|
_duration->setEnabled(state);
|
|
}
|
|
|
|
} // namespace advss
|