Procházet zdrojové kódy

(API Change) libobs: Add 'type' to obs_scene_duplicate

(Note: This commit also modifies the UI)

Allows the ability to duplicate sources fully copied, and/or have the
scene and its duplicates be private sources
jp9000 před 9 roky
rodič
revize
a61933dd8e
3 změnil soubory, kde provedl 88 přidání a 12 odebrání
  1. 78 7
      libobs/obs-scene.c
  2. 9 4
      libobs/obs.h
  3. 1 1
      obs/window-basic-main.cpp

+ 78 - 7
libobs/obs-scene.c

@@ -751,22 +751,91 @@ obs_scene_t *obs_scene_create_private(const char *name)
 	return source->context.data;
 }
 
-obs_scene_t *obs_scene_duplicate(obs_scene_t *scene, const char *name)
+static obs_source_t *get_child_at_idx(obs_scene_t *scene, size_t idx)
 {
-	struct obs_scene *new_scene = obs_scene_create(name);
 	struct obs_scene_item *item = scene->first_item;
 
+	while (item && idx--)
+		item = item->next;
+	return item ? item->source : NULL;
+}
+
+static inline obs_source_t *dup_child(struct darray *array, size_t idx,
+		obs_scene_t *new_scene, bool private)
+{
+	DARRAY(struct obs_scene_item*) old_items;
+	obs_source_t *source;
+
+	old_items.da = *array;
+
+	source = old_items.array[idx]->source;
+
+	/* if the old item is referenced more than once in the old scene,
+	 * make sure they're referenced similarly in the new scene to reduce
+	 * load times */
+	for (size_t i = 0; i < idx; i++) {
+		struct obs_scene_item *item = old_items.array[i];
+		if (item->source == source) {
+			source = get_child_at_idx(new_scene, i);
+			obs_source_addref(source);
+			return source;
+		}
+	}
+
+	return obs_source_duplicate(source, NULL, private);
+}
+
+static inline obs_source_t *new_ref(obs_source_t *source)
+{
+	obs_source_addref(source);
+	return source;
+}
+
+obs_scene_t *obs_scene_duplicate(obs_scene_t *scene, const char *name,
+		enum obs_scene_duplicate_type type)
+{
+	bool make_unique  = ((int)type & (1<<0)) != 0;
+	bool make_private = ((int)type & (1<<1)) != 0;
+	DARRAY(struct obs_scene_item*) items;
+	struct obs_scene *new_scene;
+	struct obs_scene_item *item;
+	struct obs_source *source;
+
+	da_init(items);
+
+	if (!obs_ptr_valid(scene, "obs_scene_duplicate"))
+		return NULL;
+
+	/* --------------------------------- */
+
 	full_lock(scene);
 
+	item = scene->first_item;
 	while (item) {
-		struct obs_source *source = item->source;
+		da_push_back(items, &item);
+		obs_sceneitem_addref(item);
+		item = item->next;
+	}
+
+	full_unlock(scene);
+
+	/* --------------------------------- */
+
+	new_scene = make_private ?
+		obs_scene_create_private(name) : obs_scene_create(name);
+
+	for (size_t i = 0; i < items.num; i++) {
+		item = items.array[i];
+		source = make_unique ?
+			dup_child(&items.da, i, new_scene, make_private) :
+			new_ref(item->source);
 
 		if (source) {
 			struct obs_scene_item *new_item =
 				obs_scene_add(new_scene, source);
 
 			if (!new_item) {
-				item = item->next;
+				obs_source_release(source);
 				continue;
 			}
 
@@ -784,13 +853,15 @@ obs_scene_t *obs_scene_duplicate(obs_scene_t *scene, const char *name)
 			new_item->bounds_type = item->bounds_type;
 			new_item->bounds_align = item->bounds_align;
 			new_item->bounds = item->bounds;
-		}
 
-		item = item->next;
+			obs_source_release(source);
+		}
 	}
 
-	full_unlock(scene);
+	for (size_t i = 0; i < items.num; i++)
+		obs_sceneitem_release(items.array[i]);
 
+	da_free(items);
 	return new_scene;
 }
 

+ 9 - 4
libobs/obs.h

@@ -1084,13 +1084,18 @@ EXPORT obs_scene_t *obs_scene_create(const char *name);
 
 EXPORT obs_scene_t *obs_scene_create_private(const char *name);
 
+enum obs_scene_duplicate_type {
+	OBS_SCENE_DUP_REFS,         /**< Source refs only */
+	OBS_SCENE_DUP_COPY,         /**< Fully duplicate */
+	OBS_SCENE_DUP_PRIVATE_REFS, /**< Source refs only (as private) */
+	OBS_SCENE_DUP_PRIVATE_COPY  /**< Fully duplicate (as private) */
+};
+
 /**
  * Duplicates a scene.
- *
- *   Sources in a scene will not be recreated; it will contain references to
- * the same sources as the originating scene.
  */
-EXPORT obs_scene_t *obs_scene_duplicate(obs_scene_t *scene, const char *name);
+EXPORT obs_scene_t *obs_scene_duplicate(obs_scene_t *scene, const char *name,
+		enum obs_scene_duplicate_type type);
 
 EXPORT void        obs_scene_addref(obs_scene_t *scene);
 EXPORT void        obs_scene_release(obs_scene_t *scene);

+ 1 - 1
obs/window-basic-main.cpp

@@ -1769,7 +1769,7 @@ void OBSBasic::DuplicateSelectedScene()
 		}
 
 		obs_scene_t *scene = obs_scene_duplicate(curScene,
-				name.c_str());
+				name.c_str(), OBS_SCENE_DUP_REFS);
 		source = obs_scene_get_source(scene);
 		obs_scene_release(scene);