diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index 11dc3b0c1..c9e0cea98 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -4485,7 +4485,7 @@ void OBSBasic::ClearSceneData() programScene = nullptr; prevFTBSource = nullptr; - copySources.clear(); + clipboard.clear(); copyFiltersSource = nullptr; copyFilter = nullptr; @@ -7662,11 +7662,11 @@ void OBSBasic::UpdateEditMenu() filter_count = obs_source_filter_count(source); } - for (size_t i = copySources.size(); i > 0; i--) { + for (size_t i = clipboard.size(); i > 0; i--) { const size_t idx = i - 1; - OBSWeakSource &weak = copySources[idx]; + OBSWeakSource &weak = clipboard[idx].weak_source; if (obs_weak_source_expired(weak)) - copySources.erase(copySources.begin() + idx); + clipboard.erase(clipboard.begin() + idx); } ui->actionCopySource->setEnabled(idx != -1); @@ -7675,8 +7675,8 @@ void OBSBasic::UpdateEditMenu() ui->actionCopyFilters->setEnabled(filter_count > 0); ui->actionPasteFilters->setEnabled( !obs_weak_source_expired(copyFiltersSource) && idx != -1); - ui->actionPasteRef->setEnabled(!!copySources.size()); - ui->actionPasteDup->setEnabled(!!copySources.size()); + ui->actionPasteRef->setEnabled(!!clipboard.size()); + ui->actionPasteDup->setEnabled(!!clipboard.size()); ui->actionMoveUp->setEnabled(idx != -1); ui->actionMoveDown->setEnabled(idx != -1); @@ -7720,26 +7720,8 @@ void OBSBasic::on_actionEditTransform_triggered() transformWindow->setAttribute(Qt::WA_DeleteOnClose, true); } -static obs_transform_info copiedTransformInfo; -static obs_sceneitem_crop copiedCropInfo; - void OBSBasic::on_actionCopyTransform_triggered() { - auto func = [](obs_scene_t *scene, obs_sceneitem_t *item, void *param) { - if (!obs_sceneitem_selected(item)) - return true; - - obs_sceneitem_defer_update_begin(item); - obs_sceneitem_get_info(item, &copiedTransformInfo); - obs_sceneitem_get_crop(item, &copiedCropInfo); - obs_sceneitem_defer_update_end(item); - - UNUSED_PARAMETER(scene); - UNUSED_PARAMETER(param); - return true; - }; - - obs_scene_enum_items(GetCurrentScene(), func, nullptr); ui->actionPasteTransform->setEnabled(true); } @@ -7756,40 +7738,6 @@ void undo_redo(const std::string &data) obs_scene_load_transform_states(data.c_str()); } -void OBSBasic::on_actionPasteTransform_triggered() -{ - obs_data_t *wrapper = - obs_scene_save_transform_states(GetCurrentScene(), false); - auto func = [](obs_scene_t *scene, obs_sceneitem_t *item, void *param) { - if (!obs_sceneitem_selected(item)) - return true; - - obs_sceneitem_defer_update_begin(item); - obs_sceneitem_set_info(item, &copiedTransformInfo); - obs_sceneitem_set_crop(item, &copiedCropInfo); - obs_sceneitem_defer_update_end(item); - - UNUSED_PARAMETER(scene); - UNUSED_PARAMETER(param); - return true; - }; - - obs_scene_enum_items(GetCurrentScene(), func, nullptr); - - obs_data_t *rwrapper = - obs_scene_save_transform_states(GetCurrentScene(), false); - - std::string undo_data(obs_data_get_json(wrapper)); - std::string redo_data(obs_data_get_json(rwrapper)); - undo_s.add_action( - QTStr("Undo.Transform.Paste") - .arg(obs_source_get_name(GetCurrentSceneSource())), - undo_redo, undo_redo, undo_data, redo_data); - - obs_data_release(wrapper); - obs_data_release(rwrapper); -} - static bool reset_tr(obs_scene_t *scene, obs_sceneitem_t *item, void *param) { if (obs_sceneitem_is_group(item)) @@ -9011,7 +8959,7 @@ void OBSBasic::on_actionMainRedo_triggered() void OBSBasic::on_actionCopySource_triggered() { - copySources.clear(); + clipboard.clear(); bool allowPastingDuplicate = true; for (auto &selectedSource : GetAllSelectedSourceItems()) { @@ -9023,11 +8971,15 @@ void OBSBasic::on_actionCopySource_triggered() OBSSource source = obs_sceneitem_get_source(item); - obs_weak_source *weak = obs_source_get_weak_source(source); - copySources.emplace_front(weak); - obs_weak_source_release(weak); + SourceCopyInfo copyInfo; + copyInfo.weak_source = OBSGetWeakRef(source); + copyInfo.transform = std::make_shared(); + obs_sceneitem_get_info(item, copyInfo.transform.get()); + copyInfo.crop = std::make_shared(); + obs_sceneitem_get_crop(item, copyInfo.crop.get()); + copyInfo.visible = obs_sceneitem_visible(item); - copyVisible = obs_sceneitem_visible(item); + clipboard.push_back(copyInfo); uint32_t output_flags = obs_source_get_output_flags(source); if (output_flags & OBS_SOURCE_DO_NOT_DUPLICATE) @@ -9046,20 +8998,22 @@ void OBSBasic::on_actionPasteRef_triggered() undo_s.push_disabled(); - for (auto ©Source : copySources) { - obs_source_t *source = obs_weak_source_get_source(copySource); + for (size_t i = clipboard.size(); i > 0; i--) { + SourceCopyInfo ©Info = clipboard[i - 1]; + + OBSSource source = OBSGetStrongRef(copyInfo.weak_source); if (!source) continue; const char *name = obs_source_get_name(source); - /* do not allow duplicate refs of the same group in the same scene */ - if (!!obs_scene_get_group(scene, name)) + /* do not allow duplicate refs of the same group in the same + * scene */ + if (!!obs_scene_get_group(scene, name)) { continue; + } - OBSBasicSourceSelect::SourcePaste(name, copyVisible, false); - on_actionPasteTransform_triggered(); - obs_source_release(source); + OBSBasicSourceSelect::SourcePaste(copyInfo, false); } undo_s.pop_disabled(); @@ -9079,15 +9033,9 @@ void OBSBasic::on_actionPasteDup_triggered() undo_s.push_disabled(); - for (auto ©Source : copySources) { - obs_source_t *source = obs_weak_source_get_source(copySource); - if (!source) - continue; - - const char *name = obs_source_get_name(source); - OBSBasicSourceSelect::SourcePaste(name, copyVisible, true); - on_actionPasteTransform_triggered(); - obs_source_release(source); + for (size_t i = clipboard.size(); i > 0; i--) { + SourceCopyInfo ©Info = clipboard[i - 1]; + OBSBasicSourceSelect::SourcePaste(copyInfo, true); } undo_s.pop_disabled(); diff --git a/UI/window-basic-main.hpp b/UI/window-basic-main.hpp index 683cae1f2..a2fa02ada 100644 --- a/UI/window-basic-main.hpp +++ b/UI/window-basic-main.hpp @@ -89,6 +89,13 @@ struct SavedProjectorInfo { bool alwaysOnTopOverridden; }; +struct SourceCopyInfo { + OBSWeakSource weak_source; + bool visible; + std::shared_ptr crop; + std::shared_ptr transform; +}; + struct QuickTransition { QPushButton *button = nullptr; OBSSource source; @@ -204,7 +211,7 @@ private: bool projectChanged = false; bool previewEnabled = true; - std::deque copySources; + std::deque clipboard; OBSWeakSource copyFiltersSource; bool copyVisible = true; @@ -946,7 +953,6 @@ private slots: void on_actionEditTransform_triggered(); void on_actionCopyTransform_triggered(); - void on_actionPasteTransform_triggered(); void on_actionRotate90CW_triggered(); void on_actionRotate90CCW_triggered(); void on_actionRotate180_triggered(); diff --git a/UI/window-basic-source-select.cpp b/UI/window-basic-source-select.cpp index 4d3db5d61..8229a736a 100644 --- a/UI/window-basic-source-select.cpp +++ b/UI/window-basic-source-select.cpp @@ -24,6 +24,8 @@ struct AddSourceData { obs_source_t *source; bool visible; + obs_transform_info *transform = nullptr; + obs_sceneitem_crop *crop = nullptr; }; bool OBSBasicSourceSelect::EnumSources(void *data, obs_source_t *source) @@ -116,6 +118,13 @@ static void AddSource(void *_data, obs_scene_t *scene) obs_sceneitem_t *sceneitem; sceneitem = obs_scene_add(scene, data->source); + + if (data->transform != nullptr) + obs_sceneitem_set_info(sceneitem, data->transform); + + if (data->crop != nullptr) + obs_sceneitem_set_crop(sceneitem, data->crop); + obs_sceneitem_set_visible(sceneitem, data->visible); } @@ -140,34 +149,43 @@ static char *get_new_source_name(const char *name) return new_name.array; } -static void AddExisting(const char *name, bool visible, bool duplicate) +static void AddExisting(OBSSource source, bool visible, bool duplicate, + obs_transform_info *transform, obs_sceneitem_crop *crop) { OBSBasic *main = reinterpret_cast(App()->GetMainWindow()); OBSScene scene = main->GetCurrentScene(); if (!scene) return; + if (duplicate) { + OBSSource from = source; + char *new_name = + get_new_source_name(obs_source_get_name(source)); + source = obs_source_duplicate(from, new_name, false); + obs_source_release(source); + bfree(new_name); + + if (!source) + return; + } + + AddSourceData data; + data.source = source; + data.visible = visible; + data.transform = transform; + data.crop = crop; + + 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_source_t *source = obs_get_source_by_name(name); if (source) { - if (duplicate) { - obs_source_t *from = source; - char *new_name = get_new_source_name(name); - source = obs_source_duplicate(from, new_name, false); - bfree(new_name); - obs_source_release(from); - - if (!source) - return; - } - - AddSourceData data; - data.source = source; - data.visible = visible; - - obs_enter_graphics(); - obs_scene_atomic_update(scene, AddSource, &data); - obs_leave_graphics(); - + AddExisting(source, visible, duplicate, transform, crop); obs_source_release(source); } } @@ -227,7 +245,8 @@ void OBSBasicSourceSelect::on_buttonBox_accepted() if (!item) return; - AddExisting(QT_TO_UTF8(item->text()), visible, false); + AddExisting(QT_TO_UTF8(item->text()), visible, false, nullptr, + nullptr); } else { if (ui->sourceName->text().isEmpty()) { OBSMessageBox::warning(this, @@ -378,7 +397,12 @@ OBSBasicSourceSelect::OBSBasicSourceSelect(OBSBasic *parent, const char *id_, } } -void OBSBasicSourceSelect::SourcePaste(const char *name, bool visible, bool dup) +void OBSBasicSourceSelect::SourcePaste(SourceCopyInfo &info, bool dup) { - AddExisting(name, visible, dup); + OBSSource source = OBSGetStrongRef(info.weak_source); + if (!source) + return; + + AddExisting(source, info.visible, dup, info.transform.get(), + info.crop.get()); } diff --git a/UI/window-basic-source-select.hpp b/UI/window-basic-source-select.hpp index 089dc60f3..01f024fed 100644 --- a/UI/window-basic-source-select.hpp +++ b/UI/window-basic-source-select.hpp @@ -22,6 +22,7 @@ #include "ui_OBSBasicSourceSelect.h" #include "undo-stack-obs.hpp" +#include "window-basic-main.hpp" class OBSBasic; @@ -52,5 +53,5 @@ public: OBSSource newSource; - static void SourcePaste(const char *name, bool visible, bool duplicate); + static void SourcePaste(SourceCopyInfo &info, bool duplicate); };