From 8c946e792abcb9525655e97780360a133cb05b21 Mon Sep 17 00:00:00 2001 From: cg2121 Date: Fri, 12 Sep 2025 03:17:56 -0500 Subject: [PATCH] frontend: Make sure all scene item properties are copied Scale filtering, show/hide transitions and private settings were not copied when copying scene items. --- frontend/dialogs/OBSBasicSourceSelect.cpp | 67 +++++++++++++++++++---- frontend/widgets/OBSBasic.hpp | 8 +++ frontend/widgets/OBSBasic_Clipboard.cpp | 23 ++++++++ 3 files changed, 86 insertions(+), 12 deletions(-) diff --git a/frontend/dialogs/OBSBasicSourceSelect.cpp b/frontend/dialogs/OBSBasicSourceSelect.cpp index 3e5056180..44c4ee766 100644 --- a/frontend/dialogs/OBSBasicSourceSelect.cpp +++ b/frontend/dialogs/OBSBasicSourceSelect.cpp @@ -29,6 +29,14 @@ struct AddSourceData { obs_sceneitem_crop *crop = nullptr; obs_blending_method *blend_method = nullptr; obs_blending_type *blend_mode = nullptr; + obs_scale_type *scale_type = nullptr; + const char *show_transition_id = nullptr; + const char *hide_transition_id = nullptr; + OBSData show_transition_settings; + OBSData hide_transition_settings; + uint32_t show_transition_duration = 300; + uint32_t hide_transition_duration = 300; + OBSData private_settings; /* Return data */ obs_sceneitem_t *scene_item = nullptr; @@ -125,9 +133,35 @@ static void AddSource(void *_data, obs_scene_t *scene) obs_sceneitem_set_blending_method(sceneitem, *data->blend_method); if (data->blend_mode != nullptr) obs_sceneitem_set_blending_mode(sceneitem, *data->blend_mode); + if (data->scale_type != nullptr) + obs_sceneitem_set_scale_filter(sceneitem, *data->scale_type); + + if (data->show_transition_id && *data->show_transition_id) { + OBSSourceAutoRelease source = obs_source_create(data->show_transition_id, data->show_transition_id, + data->show_transition_settings, nullptr); + + if (source) + obs_sceneitem_set_transition(sceneitem, true, source); + } + + if (data->hide_transition_id && *data->hide_transition_id) { + OBSSourceAutoRelease source = obs_source_create(data->hide_transition_id, data->hide_transition_id, + data->hide_transition_settings, nullptr); + + if (source) + obs_sceneitem_set_transition(sceneitem, false, source); + } + + obs_sceneitem_set_transition_duration(sceneitem, true, data->show_transition_duration); + obs_sceneitem_set_transition_duration(sceneitem, false, data->hide_transition_duration); obs_sceneitem_set_visible(sceneitem, data->visible); + if (data->private_settings) { + OBSDataAutoRelease newPrivateSettings = obs_sceneitem_get_private_settings(sceneitem); + obs_data_apply(newPrivateSettings, data->private_settings); + } + data->scene_item = sceneitem; } @@ -149,8 +183,7 @@ char *get_new_source_name(const char *name, const char *format) return new_name.array; } -static void AddExisting(OBSSource source, bool visible, bool duplicate, obs_transform_info *transform, - obs_sceneitem_crop *crop, obs_blending_method *blend_method, obs_blending_type *blend_mode) +static void AddExisting(OBSSource source, bool visible, bool duplicate, SourceCopyInfo *info = nullptr) { OBSBasic *main = OBSBasic::Get(); OBSScene scene = main->GetCurrentScene(); @@ -171,22 +204,32 @@ static void AddExisting(OBSSource source, bool visible, bool duplicate, obs_tran AddSourceData data; data.source = source; data.visible = visible; - data.transform = transform; - data.crop = crop; - data.blend_method = blend_method; - data.blend_mode = blend_mode; + + if (info) { + data.transform = &info->transform; + data.crop = &info->crop; + data.blend_method = &info->blend_method; + data.blend_mode = &info->blend_mode; + data.scale_type = &info->scale_type; + data.show_transition_id = info->show_transition_id; + data.hide_transition_id = info->hide_transition_id; + data.show_transition_settings = std::move(info->show_transition_settings); + data.hide_transition_settings = std::move(info->hide_transition_settings); + data.show_transition_duration = info->show_transition_duration; + data.hide_transition_duration = info->hide_transition_duration; + data.private_settings = std::move(info->private_settings); + } obs_enter_graphics(); obs_scene_atomic_update(scene, AddSource, &data); obs_leave_graphics(); } -static void AddExisting(const char *name, bool visible, bool duplicate, obs_transform_info *transform, - obs_sceneitem_crop *crop, obs_blending_method *blend_method, obs_blending_type *blend_mode) +static void AddExisting(const char *name, bool visible, bool duplicate) { OBSSourceAutoRelease source = obs_get_source_by_name(name); if (source) { - AddExisting(source.Get(), visible, duplicate, transform, crop, blend_method, blend_mode); + AddExisting(source.Get(), visible, duplicate); } } @@ -243,7 +286,7 @@ void OBSBasicSourceSelect::on_buttonBox_accepted() return; QString source_name = item->text(); - AddExisting(QT_TO_UTF8(source_name), visible, false, nullptr, nullptr, nullptr, nullptr); + AddExisting(QT_TO_UTF8(source_name), visible, false); OBSBasic *main = OBSBasic::Get(); const char *scene_name = obs_source_get_name(main->GetCurrentSceneSource()); @@ -270,7 +313,7 @@ void OBSBasicSourceSelect::on_buttonBox_accepted() obs_source_t *scene_source = obs_get_source_by_name(scene_name); main->SetCurrentScene(scene_source, true); obs_source_release(scene_source); - AddExisting(QT_TO_UTF8(source_name), visible, false, nullptr, nullptr, nullptr, nullptr); + AddExisting(QT_TO_UTF8(source_name), visible, false); }; undo_s.add_action(QTStr("Undo.Add").arg(source_name), undo, redo, "", ""); @@ -411,5 +454,5 @@ void OBSBasicSourceSelect::SourcePaste(SourceCopyInfo &info, bool dup) if (!source) return; - AddExisting(source, info.visible, dup, &info.transform, &info.crop, &info.blend_method, &info.blend_mode); + AddExisting(source, info.visible, dup, &info); } diff --git a/frontend/widgets/OBSBasic.hpp b/frontend/widgets/OBSBasic.hpp index 4cb0fc544..8f6222dba 100644 --- a/frontend/widgets/OBSBasic.hpp +++ b/frontend/widgets/OBSBasic.hpp @@ -106,6 +106,14 @@ struct SourceCopyInfo { obs_transform_info transform; obs_blending_method blend_method; obs_blending_type blend_mode; + obs_scale_type scale_type; + const char *show_transition_id; + const char *hide_transition_id; + OBSData show_transition_settings; + OBSData hide_transition_settings; + uint32_t show_transition_duration; + uint32_t hide_transition_duration; + OBSData private_settings; }; struct OBSProfile { diff --git a/frontend/widgets/OBSBasic_Clipboard.cpp b/frontend/widgets/OBSBasic_Clipboard.cpp index f42ff23af..a4bcc1682 100644 --- a/frontend/widgets/OBSBasic_Clipboard.cpp +++ b/frontend/widgets/OBSBasic_Clipboard.cpp @@ -83,6 +83,27 @@ void OBSBasic::on_actionCopySource_triggered() copyInfo.blend_method = obs_sceneitem_get_blending_method(item); copyInfo.blend_mode = obs_sceneitem_get_blending_mode(item); copyInfo.visible = obs_sceneitem_visible(item); + copyInfo.scale_type = obs_sceneitem_get_scale_filter(item); + copyInfo.show_transition_id = obs_source_get_id(obs_sceneitem_get_transition(item, true)); + copyInfo.hide_transition_id = obs_source_get_id(obs_sceneitem_get_transition(item, false)); + + OBSDataAutoRelease newShowData = obs_data_create(); + OBSDataAutoRelease oldShowData = obs_source_get_settings(obs_sceneitem_get_transition(item, true)); + obs_data_apply(newShowData, oldShowData); + copyInfo.show_transition_settings = newShowData.Get(); + + OBSDataAutoRelease newHideData = obs_data_create(); + OBSDataAutoRelease oldHideData = obs_source_get_settings(obs_sceneitem_get_transition(item, false)); + obs_data_apply(newHideData, oldHideData); + copyInfo.hide_transition_settings = newHideData.Get(); + + copyInfo.show_transition_duration = obs_sceneitem_get_transition_duration(item, true); + copyInfo.hide_transition_duration = obs_sceneitem_get_transition_duration(item, false); + + OBSDataAutoRelease newPrivData = obs_data_create(); + OBSDataAutoRelease oldPrivData = obs_sceneitem_get_private_settings(item); + obs_data_apply(newPrivData, oldPrivData); + copyInfo.private_settings = newPrivData.Get(); clipboard.push_back(copyInfo); } @@ -114,6 +135,7 @@ void OBSBasic::on_actionPasteRef_triggered() } OBSBasicSourceSelect::SourcePaste(copyInfo, false); + RefreshSources(scene); } undo_s.pop_disabled(); @@ -135,6 +157,7 @@ void OBSBasic::on_actionPasteDup_triggered() for (size_t i = clipboard.size(); i > 0; i--) { SourceCopyInfo ©Info = clipboard[i - 1]; OBSBasicSourceSelect::SourcePaste(copyInfo, true); + RefreshSources(GetCurrentScene()); } undo_s.pop_disabled();