Skip to content

Commit

Permalink
Add option to move scene item above / below specified scene item
Browse files Browse the repository at this point in the history
  • Loading branch information
WarmUpTill committed Oct 21, 2024
1 parent ed09637 commit 39327be
Show file tree
Hide file tree
Showing 10 changed files with 194 additions and 74 deletions.
2 changes: 1 addition & 1 deletion data/locale/de-DE.ini
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ AdvSceneSwitcher.action.sceneOrder.type.moveDown="Nach unten verschieben"
AdvSceneSwitcher.action.sceneOrder.type.moveTop="An erste Stelle verschieben"
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="An letzte Stelle verschieben"
AdvSceneSwitcher.action.sceneOrder.type.movePosition="An Position verschieben"
AdvSceneSwitcher.action.sceneOrder.entry="Auf{{scenes}}{{actions}}{{sources}}{{position}}"
AdvSceneSwitcher.action.sceneOrder.entry="Auf{{scenes}}{{actions}}{{sources}}{{sources2}}{{position}}"
AdvSceneSwitcher.action.sceneTransform="Szenenelement transformieren"
AdvSceneSwitcher.action.sceneTransform.getTransform="Transformation erhalten"
AdvSceneSwitcher.action.sceneTransform.entry="Auf{{scenes}}{{action}}{{rotation}}{{sources}}{{settingSelection}}{{singleSettingValue}}"
Expand Down
4 changes: 3 additions & 1 deletion data/locale/en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -956,7 +956,9 @@ AdvSceneSwitcher.action.sceneOrder.type.moveDown="Move down"
AdvSceneSwitcher.action.sceneOrder.type.moveTop="Move to top"
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="Move to bottom"
AdvSceneSwitcher.action.sceneOrder.type.movePosition="Move to position"
AdvSceneSwitcher.action.sceneOrder.entry="On{{scenes}}{{actions}}{{sources}}{{position}}"
AdvSceneSwitcher.action.sceneOrder.type.above="Move above"
AdvSceneSwitcher.action.sceneOrder.type.below="Move below"
AdvSceneSwitcher.action.sceneOrder.entry="On{{scenes}}{{actions}}{{sources}}{{position}}{{sources2}}"
AdvSceneSwitcher.action.sceneTransform="Scene item transform"
AdvSceneSwitcher.action.sceneTransform.type.manual="Set transform string"
AdvSceneSwitcher.action.sceneTransform.type.setSingleSetting="Set transform setting"
Expand Down
2 changes: 1 addition & 1 deletion data/locale/es-ES.ini
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ AdvSceneSwitcher.action.sceneOrder.type.moveDown="Mover hacia abajo"
AdvSceneSwitcher.action.sceneOrder.type.moveTop="Mover al principio"
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="Mover al final"
AdvSceneSwitcher.action.sceneOrder.type.movePosition="Mover a la posición"
AdvSceneSwitcher.action.sceneOrder.entry="En{{scenes}}{{actions}}{{sources}}{{position}}"
AdvSceneSwitcher.action.sceneOrder.entry="En{{scenes}}{{actions}}{{sources}}{{sources2}}{{position}}"
AdvSceneSwitcher.action.sceneTransform="Transformar elemento de escena"
AdvSceneSwitcher.action.sceneTransform.getTransform="Obtener transformación"
AdvSceneSwitcher.action.sceneTransform.entry="En{{scenes}}{{action}}{{rotation}}{{sources}}{{settingSelection}}{{singleSettingValue}}"
Expand Down
2 changes: 1 addition & 1 deletion data/locale/fr-FR.ini
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ AdvSceneSwitcher.action.sceneOrder.type.moveDown="Déplacer vers le bas"
AdvSceneSwitcher.action.sceneOrder.type.moveTop="Déplacer en haut"
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="Déplacer en bas"
AdvSceneSwitcher.action.sceneOrder.type.movePosition="Déplacer à la position"
AdvSceneSwitcher.action.sceneOrder.entry="Sur{{scenes}}{{actions}}{{sources}}{{position}}"
AdvSceneSwitcher.action.sceneOrder.entry="Sur{{scenes}}{{actions}}{{sources}}{{sources2}}{{position}}"
AdvSceneSwitcher.action.sceneTransform="Transformation de l'élément de la scène"
AdvSceneSwitcher.action.sceneTransform.type.manual="Transform"
AdvSceneSwitcher.action.sceneTransform.type.reset="Réinitialiser la transformation"
Expand Down
2 changes: 1 addition & 1 deletion data/locale/ja-JP.ini
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,7 @@ AdvSceneSwitcher.action.sceneOrder.type.moveDown="下へ移動"
AdvSceneSwitcher.action.sceneOrder.type.moveTop="トップへ移動"
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="一番下へ移動"
AdvSceneSwitcher.action.sceneOrder.type.movePosition="ポジションへの移動"
AdvSceneSwitcher.action.sceneOrder.entry="オン{{scenes}}{{actions}}{{sources}}{{position}}"
AdvSceneSwitcher.action.sceneOrder.entry="オン{{scenes}}{{actions}}{{sources}}{{sources2}}{{position}}"
AdvSceneSwitcher.action.sceneTransform="シーンアイテムの変形"
AdvSceneSwitcher.action.sceneTransform.type.manual="変形"
AdvSceneSwitcher.action.sceneTransform.type.setSingleSetting="トランスフォーム設定を行う"
Expand Down
2 changes: 1 addition & 1 deletion data/locale/pt-BR.ini
Original file line number Diff line number Diff line change
Expand Up @@ -907,7 +907,7 @@ AdvSceneSwitcher.action.sceneOrder.type.moveDown="Mover para baixo"
AdvSceneSwitcher.action.sceneOrder.type.moveTop="Mover para o topo"
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="Mover para o fundo"
AdvSceneSwitcher.action.sceneOrder.type.movePosition="Mover para posição"
AdvSceneSwitcher.action.sceneOrder.entry="Em{{scenes}}{{actions}}{{sources}}{{position}}"
AdvSceneSwitcher.action.sceneOrder.entry="Em{{scenes}}{{actions}}{{sources}}{{sources2}}{{position}}"
AdvSceneSwitcher.action.sceneTransform="Transformação de item de cena"
AdvSceneSwitcher.action.sceneTransform.type.manual="Definir string de transformação"
AdvSceneSwitcher.action.sceneTransform.type.setSingleSetting="Definir configuração de transformação"
Expand Down
2 changes: 1 addition & 1 deletion data/locale/tr-TR.ini
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ AdvSceneSwitcher.action.sceneOrder.type.moveDown="Aşağı indir"
AdvSceneSwitcher.action.sceneOrder.type.moveTop="En üste taşı"
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="Aşağıya taşı"
AdvSceneSwitcher.action.sceneOrder.type.movePosition="Konuma taşı"
AdvSceneSwitcher.action.sceneOrder.entry="Açık{{scenes}}{{actions}}{{sources}}{{position}}"
AdvSceneSwitcher.action.sceneOrder.entry="Açık{{scenes}}{{actions}}{{sources}}{{sources2}}{{position}}"
AdvSceneSwitcher.action.sceneTransform="Sahne öğesi dönüşümü"
AdvSceneSwitcher.action.sceneTransform.getTransform="Dönüşümü al"
AdvSceneSwitcher.action.sceneTransform.entry="Açık{{scenes}}{{action}}{{rotation}}{{sources}}{{settingSelection}}{{singleSettingValue}}"
Expand Down
2 changes: 1 addition & 1 deletion data/locale/zh-CN.ini
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ AdvSceneSwitcher.action.sceneOrder.type.moveDown="下移"
AdvSceneSwitcher.action.sceneOrder.type.moveTop="顶部"
AdvSceneSwitcher.action.sceneOrder.type.moveBottom="底部"
AdvSceneSwitcher.action.sceneOrder.type.movePosition="移动到数值位置"
AdvSceneSwitcher.action.sceneOrder.entry=" {{scenes}} {{actions}} {{sources}} {{position}}"
AdvSceneSwitcher.action.sceneOrder.entry="在{{scenes}}{{actions}}{{sources}}{{sources2}}{{position}}"
AdvSceneSwitcher.action.sceneTransform="场景项目转换"
AdvSceneSwitcher.action.sceneTransform.getTransform="获得转换"
AdvSceneSwitcher.action.sceneTransform.entry="在{{scenes}}{{action}}{{rotation}}{{sources}}{{settingSelection}}{{singleSettingValue}}"
Expand Down
220 changes: 167 additions & 53 deletions plugins/base/macro-action-scene-order.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,21 @@ bool MacroActionSceneOrder::_registered = MacroActionFactory::Register(
{MacroActionSceneOrder::Create, MacroActionSceneOrderEdit::Create,
"AdvSceneSwitcher.action.sceneOrder"});

const static std::map<SceneOrderAction, std::string> actionTypes = {
{SceneOrderAction::MOVE_UP,
const static std::map<MacroActionSceneOrder::Action, std::string> actionTypes = {
{MacroActionSceneOrder::Action::MOVE_UP,
"AdvSceneSwitcher.action.sceneOrder.type.moveUp"},
{SceneOrderAction::MOVE_DOWN,
{MacroActionSceneOrder::Action::MOVE_DOWN,
"AdvSceneSwitcher.action.sceneOrder.type.moveDown"},
{SceneOrderAction::MOVE_TOP,
{MacroActionSceneOrder::Action::MOVE_TOP,
"AdvSceneSwitcher.action.sceneOrder.type.moveTop"},
{SceneOrderAction::MOVE_BOTTOM,
{MacroActionSceneOrder::Action::MOVE_BOTTOM,
"AdvSceneSwitcher.action.sceneOrder.type.moveBottom"},
{SceneOrderAction::POSITION,
{MacroActionSceneOrder::Action::POSITION,
"AdvSceneSwitcher.action.sceneOrder.type.movePosition"},
{MacroActionSceneOrder::Action::ABOVE,
"AdvSceneSwitcher.action.sceneOrder.type.above"},
{MacroActionSceneOrder::Action::BELOW,
"AdvSceneSwitcher.action.sceneOrder.type.below"},
};

static void moveSceneItemsUp(std::vector<OBSSceneItem> &items)
Expand Down Expand Up @@ -66,26 +70,128 @@ static void moveSceneItemsPos(std::vector<OBSSceneItem> &items, int pos)
}
}

namespace {

struct PositionData {
obs_scene_item *item = nullptr;
bool found = false;
int position = 0;
};

} // namespace

static bool getSceneItemPositionHelper(obs_scene_t *, obs_sceneitem_t *item,
void *data)
{
auto positionData = reinterpret_cast<PositionData *>(data);
if (obs_sceneitem_is_group(item)) {
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
obs_scene_enum_items(scene, getSceneItemPositionHelper, data);
}
if (positionData->item == item) {
positionData->found = true;
return false;
}

positionData->position += 1;
return true;
}

static std::optional<int> getSceneItemPosition(const OBSSceneItem &item,
const SceneSelection &scene)
{
auto sceneSource = OBSGetStrongRef(scene.GetScene());
auto obsScene = obs_scene_from_source(sceneSource);
PositionData data{item};
obs_scene_enum_items(obsScene, getSceneItemPositionHelper, &data);

if (!data.found) {
return {};
}

return data.position;
}

static void moveItemFromToHelper(MacroActionSceneOrder::Action action,
const OBSSceneItem &itemToMove,
int currentPosition, int targetPosition)
{
if (action == MacroActionSceneOrder::Action::ABOVE) {
if (currentPosition > targetPosition) {
obs_sceneitem_set_order_position(itemToMove,
targetPosition + 1);
} else {
obs_sceneitem_set_order_position(itemToMove,
targetPosition);
}
} else if (action == MacroActionSceneOrder::Action::BELOW) {
if (currentPosition > targetPosition) {
obs_sceneitem_set_order_position(itemToMove,
targetPosition);
} else {
obs_sceneitem_set_order_position(itemToMove,
targetPosition - 1);
}
}
}

static void moveItemToItemHelper(MacroActionSceneOrder::Action action,
const std::vector<OBSSceneItem> &itemsToMove,
const SceneItemSelection &target,
const SceneSelection &scene)
{
auto targetItems = target.GetSceneItems(scene);
if (targetItems.empty()) {
return;
}

auto targetItem = targetItems.at(0);

for (const auto &item : itemsToMove) {
if (item == targetItem) {
continue;
}

auto targetPosition = getSceneItemPosition(targetItem, scene);
if (!targetPosition) {
continue;
}

auto currentPosition = getSceneItemPosition(item, scene);
if (!currentPosition) {
continue;
}

moveItemFromToHelper(action, item, *currentPosition,
*targetPosition);
}
}

bool MacroActionSceneOrder::PerformAction()
{
auto items = _source.GetSceneItems(_scene);

switch (_action) {
case SceneOrderAction::MOVE_UP:
case Action::MOVE_UP:
moveSceneItemsUp(items);
break;
case SceneOrderAction::MOVE_DOWN:
case Action::MOVE_DOWN:
moveSceneItemsDown(items);
break;
case SceneOrderAction::MOVE_TOP:
case Action::MOVE_TOP:
moveSceneItemsTop(items);
break;
case SceneOrderAction::MOVE_BOTTOM:
case Action::MOVE_BOTTOM:
moveSceneItemsBottom(items);
break;
case SceneOrderAction::POSITION:
case Action::POSITION:
moveSceneItemsPos(items, _position);
break;
case Action::ABOVE:
case Action::BELOW: {
moveItemToItemHelper(_action, items, _source2, _scene);
break;
}
default:
break;
}
Expand All @@ -111,6 +217,7 @@ bool MacroActionSceneOrder::Save(obs_data_t *obj) const
MacroAction::Save(obj);
_scene.Save(obj);
_source.Save(obj);
_source2.Save(obj, "sceneItemSelection2");
obs_data_set_int(obj, "action", static_cast<int>(_action));
obs_data_set_int(obj, "position", _position);
return true;
Expand All @@ -128,8 +235,8 @@ bool MacroActionSceneOrder::Load(obs_data_t *obj)
MacroAction::Load(obj);
_scene.Load(obj);
_source.Load(obj);
_action =
static_cast<SceneOrderAction>(obs_data_get_int(obj, "action"));
_source2.Load(obj, "sceneItemSelection2");
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
_position = obs_data_get_int(obj, "position");
return true;
}
Expand Down Expand Up @@ -167,13 +274,13 @@ static inline void populateActionSelection(QComboBox *list)

MacroActionSceneOrderEdit::MacroActionSceneOrderEdit(
QWidget *parent, std::shared_ptr<MacroActionSceneOrder> entryData)
: QWidget(parent)
: QWidget(parent),
_scenes(new SceneSelectionWidget(this, true, false, false, true)),
_sources(new SceneItemSelectionWidget(this)),
_sources2(new SceneItemSelectionWidget(this)),
_actions(new QComboBox(this)),
_position(new QSpinBox(this))
{
_scenes = new SceneSelectionWidget(window(), true, false, false, true);
_sources = new SceneItemSelectionWidget(parent);
_actions = new QComboBox();
_position = new QSpinBox();

populateActionSelection(_actions);

QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
Expand All @@ -182,23 +289,28 @@ MacroActionSceneOrderEdit::MacroActionSceneOrderEdit(
this, SLOT(SceneChanged(const SceneSelection &)));
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
_sources, SLOT(SceneChanged(const SceneSelection &)));
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
_sources2, SLOT(SceneChanged(const SceneSelection &)));
QWidget::connect(_sources,
SIGNAL(SceneItemChanged(const SceneItemSelection &)),
this, SLOT(SourceChanged(const SceneItemSelection &)));
QWidget::connect(_sources2,
SIGNAL(SceneItemChanged(const SceneItemSelection &)),
this,
SLOT(Source2Changed(const SceneItemSelection &)));
QWidget::connect(_position, SIGNAL(valueChanged(int)), this,
SLOT(PositionChanged(int)));

QHBoxLayout *mainLayout = new QHBoxLayout;
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{scenes}}", _scenes},
{"{{sources}}", _sources},
{"{{actions}}", _actions},
{"{{position}}", _position},
};
auto layout = new QHBoxLayout;
PlaceWidgets(
obs_module_text("AdvSceneSwitcher.action.sceneOrder.entry"),
mainLayout, widgetPlaceholders);
setLayout(mainLayout);
layout,
{{"{{scenes}}", _scenes},
{"{{sources}}", _sources},
{"{{sources2}}", _sources2},
{"{{actions}}", _actions},
{"{{position}}", _position}});
setLayout(layout);

_entryData = entryData;
UpdateEntryData();
Expand All @@ -214,55 +326,57 @@ void MacroActionSceneOrderEdit::UpdateEntryData()
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
_scenes->SetScene(_entryData->_scene);
_sources->SetSceneItem(_entryData->_source);
_sources2->SetSceneItem(_entryData->_source2);
_position->setValue(_entryData->_position);
_position->setVisible(_entryData->_action ==
SceneOrderAction::POSITION);
SetWidgetVisibility();
}

void MacroActionSceneOrderEdit::SceneChanged(const SceneSelection &s)
{
if (_loading || !_entryData) {
return;
}

auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_scene = s;
}

void MacroActionSceneOrderEdit::SourceChanged(const SceneItemSelection &item)
{
if (_loading || !_entryData) {
return;
}

auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_source = item;
emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc()));
adjustSize();
updateGeometry();
}

void MacroActionSceneOrderEdit::ActionChanged(int value)
void MacroActionSceneOrderEdit::Source2Changed(const SceneItemSelection &item)
{
if (_loading || !_entryData) {
return;
}
GUARD_LOADING_AND_LOCK();
_entryData->_source2 = item;
adjustSize();
updateGeometry();
}

auto lock = LockContext();
_entryData->_action = static_cast<SceneOrderAction>(value);
_position->setVisible(_entryData->_action ==
SceneOrderAction::POSITION);
void MacroActionSceneOrderEdit::ActionChanged(int value)
{
GUARD_LOADING_AND_LOCK();
_entryData->_action = static_cast<MacroActionSceneOrder::Action>(value);
SetWidgetVisibility();
}

void MacroActionSceneOrderEdit::PositionChanged(int value)
{
if (_loading || !_entryData) {
return;
}

auto lock = LockContext();
GUARD_LOADING_AND_LOCK();
_entryData->_position = value;
}

void MacroActionSceneOrderEdit::SetWidgetVisibility()
{
_position->setVisible(_entryData->_action ==
MacroActionSceneOrder::Action::POSITION);
_sources2->setVisible(
_entryData->_action == MacroActionSceneOrder::Action::ABOVE ||
_entryData->_action == MacroActionSceneOrder::Action::BELOW);
adjustSize();
updateGeometry();
}

} // namespace advss
Loading

0 comments on commit 39327be

Please sign in to comment.