This commit is contained in:
Exeldro 2024-06-27 12:25:52 +02:00 committed by GitHub
commit 5364855d0b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 131 additions and 57 deletions

View file

@ -774,6 +774,24 @@ struct OBSStudioAPI : obs_frontend_callbacks {
undo_data, redo_data, repeatable);
}
void obs_frontend_copy_sceneitem(obs_sceneitem_t *item) override
{
main->clipboard.clear();
main->CopySceneItem(item);
main->UpdateEditMenu();
}
bool obs_frontend_can_paste_sceneitem(bool duplicate) override
{
return main->CanPasteSceneItem(duplicate);
}
void obs_frontend_paste_sceneitem(obs_scene_t *scene,
bool duplicate) override
{
main->PasteSceneItem(scene, duplicate);
}
void on_load(obs_data_t *settings) override
{
for (size_t i = saveCallbacks.size(); i > 0; i--) {

View file

@ -637,3 +637,22 @@ void obs_frontend_add_undo_redo_action(const char *name,
c->obs_frontend_add_undo_redo_action(
name, undo, redo, undo_data, redo_data, repeatable);
}
void obs_frontend_copy_sceneitem(obs_sceneitem_t *item)
{
if (callbacks_valid())
return c->obs_frontend_copy_sceneitem(item);
}
bool obs_frontend_can_paste_sceneitem(bool duplicate)
{
if (!callbacks_valid())
return false;
return c->obs_frontend_can_paste_sceneitem(duplicate);
}
void obs_frontend_paste_sceneitem(obs_scene_t *scene, bool duplicate)
{
if (callbacks_valid())
return c->obs_frontend_paste_sceneitem(scene, duplicate);
}

View file

@ -253,6 +253,10 @@ EXPORT void obs_frontend_add_undo_redo_action(
const char *name, const undo_redo_cb undo, const undo_redo_cb redo,
const char *undo_data, const char *redo_data, bool repeatable);
EXPORT void obs_frontend_copy_sceneitem(obs_sceneitem_t *item);
EXPORT bool obs_frontend_can_paste_sceneitem(bool duplicate);
EXPORT void obs_frontend_paste_sceneitem(obs_scene_t *scene, bool duplicate);
/* ------------------------------------------------------------------------- */
#ifdef __cplusplus

View file

@ -168,6 +168,11 @@ struct obs_frontend_callbacks {
const char *undo_data,
const char *redo_data,
bool repeatable) = 0;
virtual void obs_frontend_copy_sceneitem(obs_sceneitem_t *item) = 0;
virtual bool obs_frontend_can_paste_sceneitem(bool duplicate) = 0;
virtual void obs_frontend_paste_sceneitem(obs_scene_t *scene,
bool duplicate) = 0;
};
EXPORT void

View file

@ -8594,22 +8594,6 @@ void OBSBasic::UpdateEditMenu()
filter_count = obs_source_filter_count(source);
}
bool allowPastingDuplicate = !!clipboard.size();
for (size_t i = clipboard.size(); i > 0; i--) {
const size_t idx = i - 1;
OBSWeakSource &weak = clipboard[idx].weak_source;
if (obs_weak_source_expired(weak)) {
clipboard.erase(clipboard.begin() + idx);
continue;
}
OBSSourceAutoRelease strong =
obs_weak_source_get_source(weak.Get());
if (allowPastingDuplicate &&
obs_source_get_output_flags(strong) &
OBS_SOURCE_DO_NOT_DUPLICATE)
allowPastingDuplicate = false;
}
int videoCount = 0;
bool canTransformMultiple = false;
for (int i = 0; i < totalCount; i++) {
@ -8636,8 +8620,8 @@ void OBSBasic::UpdateEditMenu()
ui->actionCopyFilters->setEnabled(filter_count > 0);
ui->actionPasteFilters->setEnabled(
!obs_weak_source_expired(copyFiltersSource) && totalCount > 0);
ui->actionPasteRef->setEnabled(!!clipboard.size());
ui->actionPasteDup->setEnabled(allowPastingDuplicate);
ui->actionPasteRef->setEnabled(CanPasteSceneItem(false));
ui->actionPasteDup->setEnabled(CanPasteSceneItem(true));
ui->actionMoveUp->setEnabled(totalCount > 0);
ui->actionMoveDown->setEnabled(totalCount > 0);
@ -8657,6 +8641,29 @@ void OBSBasic::UpdateEditMenu()
ui->actionHorizontalCenter->setEnabled(canTransformMultiple);
}
bool OBSBasic::CanPasteSceneItem(bool duplicate)
{
if (!duplicate)
return !!clipboard.size();
bool allowPastingDuplicate = !!clipboard.size();
for (size_t i = clipboard.size(); i > 0; i--) {
const size_t idx = i - 1;
OBSWeakSource &weak = clipboard[idx].weak_source;
if (obs_weak_source_expired(weak)) {
clipboard.erase(clipboard.begin() + idx);
continue;
}
OBSSourceAutoRelease strong =
obs_weak_source_get_source(weak.Get());
if (allowPastingDuplicate &&
obs_source_get_output_flags(strong) &
OBS_SOURCE_DO_NOT_DUPLICATE)
allowPastingDuplicate = false;
}
return allowPastingDuplicate;
}
void OBSBasic::on_actionEditTransform_triggered()
{
const auto item = GetCurrentSceneItem();
@ -10032,31 +10039,39 @@ void OBSBasic::on_actionCopySource_triggered()
clipboard.clear();
for (auto &selectedSource : GetAllSelectedSourceItems()) {
OBSSceneItem item = ui->sources->Get(selectedSource.row());
if (!item)
continue;
OBSSource source = obs_sceneitem_get_source(item);
SourceCopyInfo copyInfo;
copyInfo.weak_source = OBSGetWeakRef(source);
obs_sceneitem_get_info2(item, &copyInfo.transform);
obs_sceneitem_get_crop(item, &copyInfo.crop);
copyInfo.blend_method = obs_sceneitem_get_blending_method(item);
copyInfo.blend_mode = obs_sceneitem_get_blending_mode(item);
copyInfo.visible = obs_sceneitem_visible(item);
clipboard.push_back(copyInfo);
CopySceneItem(ui->sources->Get(selectedSource.row()));
}
UpdateEditMenu();
}
void OBSBasic::CopySceneItem(OBSSceneItem item)
{
if (!item)
return;
OBSSource source = obs_sceneitem_get_source(item);
SourceCopyInfo copyInfo;
copyInfo.weak_source = OBSGetWeakRef(source);
obs_sceneitem_get_info2(item, &copyInfo.transform);
obs_sceneitem_get_crop(item, &copyInfo.crop);
copyInfo.blend_method = obs_sceneitem_get_blending_method(item);
copyInfo.blend_mode = obs_sceneitem_get_blending_mode(item);
copyInfo.visible = obs_sceneitem_visible(item);
clipboard.push_back(copyInfo);
}
void OBSBasic::on_actionPasteRef_triggered()
{
OBSSource scene_source = GetCurrentSceneSource();
PasteSceneItem(GetCurrentScene(), false);
}
void OBSBasic::PasteSceneItem(OBSScene scene, bool duplicate)
{
if (!scene || !clipboard.size())
return;
OBSSource scene_source = obs_scene_get_source(scene);
OBSData undo_data = BackupScene(scene_source);
OBSScene scene = GetCurrentScene();
undo_s.push_disabled();
@ -10071,16 +10086,17 @@ void OBSBasic::on_actionPasteRef_triggered()
/* do not allow duplicate refs of the same group in the same
* scene */
if (!!obs_scene_get_group(scene, name)) {
if (!duplicate && !!obs_scene_get_group(scene, name)) {
continue;
}
OBSBasicSourceSelect::SourcePaste(copyInfo, false);
OBSBasicSourceSelect::SourcePaste(copyInfo, duplicate);
}
undo_s.pop_disabled();
QString action_name = QTStr("Undo.PasteSourceRef");
QString action_name =
QTStr(duplicate ? "Undo.PasteSource" : "Undo.PasteSourceRef");
const char *scene_name = obs_source_get_name(scene_source);
OBSData redo_data = BackupScene(scene_source);
@ -10090,24 +10106,7 @@ void OBSBasic::on_actionPasteRef_triggered()
void OBSBasic::on_actionPasteDup_triggered()
{
OBSSource scene_source = GetCurrentSceneSource();
OBSData undo_data = BackupScene(scene_source);
undo_s.push_disabled();
for (size_t i = clipboard.size(); i > 0; i--) {
SourceCopyInfo &copyInfo = clipboard[i - 1];
OBSBasicSourceSelect::SourcePaste(copyInfo, true);
}
undo_s.pop_disabled();
QString action_name = QTStr("Undo.PasteSource");
const char *scene_name = obs_source_get_name(scene_source);
OBSData redo_data = BackupScene(scene_source);
CreateSceneUndoRedoAction(action_name.arg(scene_name), undo_data,
redo_data);
PasteSceneItem(GetCurrentScene(), true);
}
void OBSBasic::SourcePasteFilters(OBSSource source, OBSSource dstSource)

View file

@ -1039,6 +1039,9 @@ public:
obs_data_array_t *redo_array);
void UpdateEditMenu();
void CopySceneItem(OBSSceneItem item);
bool CanPasteSceneItem(bool duplicate);
void PasteSceneItem(OBSScene scene, bool duplicate);
void SetDisplayAffinity(QWindow *window);

View file

@ -949,3 +949,29 @@ Functions
This uses the undo action from the first and the redo action from the last action.
.. versionadded:: 29.1
---------------------------------------
.. function:: void obs_frontend_copy_sceneitem(obs_sceneitem_t *item)
:param item: The scene item to copy
.. versionadded:: 31.0
---------------------------------------
.. function:: bool obs_frontend_can_paste_sceneitem(bool duplicate)
:param duplicate: Check if the copied source allows duplication.
:return: Whether there is a scene item copied and can be pasted
.. versionadded:: 31.0
---------------------------------------
.. function:: void obs_frontend_paste_sceneitem(obs_scene_t *scene, bool duplicate)
:param scene: The scene to paste on
:param duplicate: *true* for paste duplicate, *false* for paste reference
.. versionadded:: 31.0