UI: Optimize backup scene for undo/redo

master
Exeldro 2021-06-05 09:40:05 +02:00 committed by Jim
parent ba3eb46bf9
commit 5998f4cc4d
3 changed files with 86 additions and 23 deletions

View File

@ -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 */

View File

@ -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);
}

View File

@ -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,