Ver código fonte

UI: Optimize backup scene for undo/redo

Exeldro 4 anos atrás
pai
commit
5998f4cc4d
3 arquivos alterados com 86 adições e 23 exclusões
  1. 11 3
      UI/source-tree.cpp
  2. 67 16
      UI/window-basic-main.cpp
  3. 8 4
      UI/window-basic-main.hpp

+ 11 - 3
UI/source-tree.cpp

@@ -1286,8 +1286,16 @@ void SourceTree::dropEvent(QDropEvent *event)
 
 	/* --------------------------------------- */
 	/* save undo data                          */
-
-	OBSData undo_data = main->BackupScene(scenesource);
+	std::vector<obs_source_t *> sources;
+	for (int i = 0; i < indices.size(); i++) {
+		obs_sceneitem_t *item = items[indices[i].row()];
+		if (obs_sceneitem_get_scene(item) != scene)
+			sources.push_back(obs_scene_get_source(
+				obs_sceneitem_get_scene(item)));
+	}
+	if (dropGroup)
+		sources.push_back(obs_sceneitem_get_source(dropGroup));
+	OBSData undo_data = main->BackupScene(scene, &sources);
 
 	/* --------------------------------------- */
 	/* if selection includes base group items, */
@@ -1455,7 +1463,7 @@ void SourceTree::dropEvent(QDropEvent *event)
 	/* --------------------------------------- */
 	/* save redo data                          */
 
-	OBSData redo_data = main->BackupScene(scenesource);
+	OBSData redo_data = main->BackupScene(scene, &sources);
 
 	/* --------------------------------------- */
 	/* add undo/redo action                    */

+ 67 - 16
UI/window-basic-main.cpp

@@ -3677,15 +3677,36 @@ void OBSBasic::DuplicateSelectedScene()
 	}
 }
 
-static void save_undo_source_enum(obs_source_t *, obs_source_t *source, void *p)
+static bool save_undo_source_enum(obs_scene_t *scene, obs_sceneitem_t *item,
+				  void *p)
 {
+	obs_source_t *source = obs_sceneitem_get_source(item);
 	if (obs_obj_is_private(source) && !obs_source_removed(source))
-		return;
+		return true;
 
 	obs_data_array_t *array = (obs_data_array_t *)p;
+
+	/* check if the source is already stored in the array */
+	const char *name = obs_source_get_name(source);
+	const size_t count = obs_data_array_count(array);
+	for (size_t i = 0; i < count; i++) {
+		obs_data_t *sourceData = obs_data_array_item(array, i);
+		if (strcmp(name, obs_data_get_string(sourceData, "name")) ==
+		    0) {
+			obs_data_release(sourceData);
+			return true;
+		}
+		obs_data_release(sourceData);
+	}
+
+	if (obs_source_is_group(source))
+		obs_scene_enum_items(obs_group_from_source(source),
+				     save_undo_source_enum, p);
+
 	obs_data_t *source_data = obs_save_source(source);
 	obs_data_array_push_back(array, source_data);
 	obs_data_release(source_data);
+	return true;
 }
 
 void OBSBasic::RemoveSelectedScene()
@@ -3700,11 +3721,11 @@ void OBSBasic::RemoveSelectedScene()
 	}
 
 	/* ------------------------------ */
-	/* save all sources in scene tree */
+	/* save all sources in scene      */
 
 	obs_data_array_t *array = obs_data_array_create();
 
-	obs_source_enum_full_tree(source, save_undo_source_enum, array);
+	obs_scene_enum_items(scene, save_undo_source_enum, array);
 
 	obs_data_t *scene_data = obs_save_source(source);
 	obs_data_array_push_back(array, scene_data);
@@ -5459,14 +5480,22 @@ static bool remove_items(obs_scene_t *, obs_sceneitem_t *item, void *param)
 	return true;
 };
 
-OBSData OBSBasic::BackupScene(obs_source_t *scene_source)
+OBSData OBSBasic::BackupScene(obs_scene_t *scene,
+			      std::vector<obs_source_t *> *sources)
 {
 	obs_data_array_t *undo_array = obs_data_array_create();
 
-	obs_source_enum_full_tree(scene_source, save_undo_source_enum,
-				  undo_array);
+	if (!sources) {
+		obs_scene_enum_items(scene, save_undo_source_enum, undo_array);
+	} else {
+		for (obs_source_t *source : *sources) {
+			obs_data_t *source_data = obs_save_source(source);
+			obs_data_array_push_back(undo_array, source_data);
+			obs_data_release(source_data);
+		}
+	}
 
-	obs_data_t *scene_data = obs_save_source(scene_source);
+	obs_data_t *scene_data = obs_save_source(obs_scene_get_source(scene));
 	obs_data_array_push_back(undo_array, scene_data);
 	obs_data_release(scene_data);
 
@@ -5479,6 +5508,13 @@ OBSData OBSBasic::BackupScene(obs_source_t *scene_source)
 	return data;
 }
 
+static bool add_source_enum(obs_scene_t *, obs_sceneitem_t *item, void *p)
+{
+	auto sources = static_cast<std::vector<obs_source_t *> *>(p);
+	sources->push_back(obs_sceneitem_get_source(item));
+	return true;
+}
+
 void OBSBasic::CreateSceneUndoRedoAction(const QString &action_name,
 					 OBSData undo_data, OBSData redo_data)
 {
@@ -5486,9 +5522,10 @@ void OBSBasic::CreateSceneUndoRedoAction(const QString &action_name,
 		obs_data_t *base = obs_data_create_from_json(json.c_str());
 		obs_data_array_t *array = obs_data_get_array(base, "array");
 		std::vector<obs_source_t *> sources;
+		std::vector<obs_source_t *> old_sources;
 
 		/* create missing sources */
-		size_t count = obs_data_array_count(array);
+		const size_t count = obs_data_array_count(array);
 		sources.reserve(count);
 
 		for (size_t i = 0; i < count; i++) {
@@ -5498,12 +5535,16 @@ void OBSBasic::CreateSceneUndoRedoAction(const QString &action_name,
 			obs_source_t *source = obs_get_source_by_name(name);
 			if (!source)
 				source = obs_load_source(data);
+
 			sources.push_back(source);
 
 			/* update scene/group settings to restore their
-			 * contents to their saved settings */
-			if (obs_source_is_group(source) ||
-			    obs_source_is_scene(source)) {
+			* contents to their saved settings */
+			obs_scene_t *scene =
+				obs_group_or_scene_from_source(source);
+			if (scene) {
+				obs_scene_enum_items(scene, add_source_enum,
+						     &old_sources);
 				obs_data_t *scene_settings =
 					obs_data_get_obj(data, "settings");
 				obs_source_update(source, scene_settings);
@@ -5512,6 +5553,8 @@ void OBSBasic::CreateSceneUndoRedoAction(const QString &action_name,
 
 			obs_data_release(data);
 		}
+		for (obs_source_t *source : old_sources)
+			obs_source_addref(source);
 
 		/* actually load sources now */
 		for (obs_source_t *source : sources)
@@ -5520,6 +5563,8 @@ void OBSBasic::CreateSceneUndoRedoAction(const QString &action_name,
 		/* release sources */
 		for (obs_source_t *source : sources)
 			obs_source_release(source);
+		for (obs_source_t *source : old_sources)
+			obs_source_release(source);
 
 		obs_data_array_release(array);
 		obs_data_release(base);
@@ -5633,15 +5678,21 @@ void OBSBasic::MoveSceneItem(enum obs_order_movement movement,
 	if (!source)
 		return;
 
-	OBSSource scene_source = GetCurrentSceneSource();
-	OBSData undo_data = BackupScene(scene_source);
+	OBSScene scene = GetCurrentScene();
+	std::vector<obs_source_t *> sources;
+	if (scene != obs_sceneitem_get_scene(item))
+		sources.push_back(
+			obs_scene_get_source(obs_sceneitem_get_scene(item)));
+
+	OBSData undo_data = BackupScene(scene, &sources);
 
 	obs_sceneitem_set_order(item, movement);
 
 	const char *source_name = obs_source_get_name(source);
-	const char *scene_name = obs_source_get_name(scene_source);
+	const char *scene_name =
+		obs_source_get_name(obs_scene_get_source(scene));
 
-	OBSData redo_data = BackupScene(scene_source);
+	OBSData redo_data = BackupScene(scene, &sources);
 	CreateSceneUndoRedoAction(action_name.arg(source_name, scene_name),
 				  undo_data, redo_data);
 }

+ 8 - 4
UI/window-basic-main.hpp

@@ -860,14 +860,18 @@ public:
 
 	void ShowStatusBarMessage(const QString &message);
 
-	static OBSData BackupScene(obs_source_t *scene_source);
+	static OBSData
+	BackupScene(obs_scene_t *scene,
+		    std::vector<obs_source_t *> *sources = nullptr);
 	void CreateSceneUndoRedoAction(const QString &action_name,
 				       OBSData undo_data, OBSData redo_data);
 
-	static inline OBSData BackupScene(obs_scene_t *scene)
+	static inline OBSData
+	BackupScene(obs_source_t *scene_source,
+		    std::vector<obs_source_t *> *sources = nullptr)
 	{
-		obs_source_t *source = obs_scene_get_source(scene);
-		return BackupScene(source);
+		obs_scene_t *scene = obs_scene_from_source(scene_source);
+		return BackupScene(scene, sources);
 	}
 
 	void CreateFilterPasteUndoRedoAction(const QString &text,