mirror of
https://github.com/obsproject/obs-studio.git
synced 2026-07-28 08:06:20 -04:00
UI: Optimize backup scene for undo/redo
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user