libobs: Remove group_sceneitem from obs_scene struct

(This commit also modifies UI)

Removes obs_scene::group_sceneitem and replaces it with
obs_scene::is_group.  Changes a number of other functions related to
groups so that a group is not inherently tied to a specific scene, and
helps allow a single group to be referenced in multiple scenes if
desired.
This commit is contained in:
jp9000 2018-07-15 18:18:25 -07:00
parent 2329c6f6ea
commit 35704c4c04
6 changed files with 95 additions and 73 deletions

View file

@ -917,7 +917,7 @@ void SourceTree::dropEvent(QDropEvent *event)
obs_sceneitem_t *dropGroup = itemIsGroup
? dropItem
: obs_sceneitem_get_group(dropItem);
: obs_sceneitem_get_group(scene, dropItem);
/* not a group if moving above the group */
if (indicator == QAbstractItemView::AboveItem && itemIsGroup)
@ -966,7 +966,7 @@ void SourceTree::dropEvent(QDropEvent *event)
: stm->items[row];
if (hasGroups) {
if (!itemBelow ||
obs_sceneitem_get_group(itemBelow) != dropGroup) {
obs_sceneitem_get_group(scene, itemBelow) != dropGroup) {
indicator = QAbstractItemView::BelowItem;
dropGroup = nullptr;
dropOnCollapsed = false;
@ -1006,7 +1006,8 @@ void SourceTree::dropEvent(QDropEvent *event)
for (int j = items.size() - 1; j >= 0; j--) {
obs_sceneitem_t *subitem = items[j];
obs_sceneitem_t *subitemGroup =
obs_sceneitem_get_group(subitem);
obs_sceneitem_get_group(scene,
subitem);
if (subitemGroup == item) {
QModelIndex idx =
@ -1117,7 +1118,7 @@ void SourceTree::dropEvent(QDropEvent *event)
if (!hasGroups && i >= firstIdx && i <= lastIdx)
group = dropGroup;
else
group = obs_sceneitem_get_group(item);
group = obs_sceneitem_get_group(scene, item);
if (lastGroup && lastGroup != group) {
insertLastGroup();

View file

@ -2627,7 +2627,7 @@ void OBSBasic::DeactivateAudioSource(OBSSource source)
bool OBSBasic::QueryRemoveSource(obs_source_t *source)
{
if (obs_source_get_type(source) == OBS_SOURCE_TYPE_SCENE &&
!obs_sceneitem_group_from_source(source)) {
!obs_source_is_group(source)) {
int count = ui->scenes->count();
if (count == 1) {

View file

@ -420,7 +420,7 @@ void OBSBasicPreview::GetStretchHandleData(const vec2 &pos)
cropSize.y = float(obs_source_get_height(source) -
startCrop.top - startCrop.bottom);
stretchGroup = obs_sceneitem_get_group(stretchItem);
stretchGroup = obs_sceneitem_get_group(scene, stretchItem);
if (stretchGroup) {
obs_sceneitem_get_draw_transform(stretchGroup,
&invGroupTransform);
@ -1135,8 +1135,11 @@ void OBSBasicPreview::mouseMoveEvent(QMouseEvent *event)
pos.y = std::round(pos.y);
if (stretchHandle != ItemHandle::None) {
OBSBasic *main = reinterpret_cast<OBSBasic*>(
App()->GetMainWindow());
OBSScene scene = main->GetCurrentScene();
obs_sceneitem_t *group = obs_sceneitem_get_group(
stretchItem);
scene, stretchItem);
if (group) {
vec3 group_pos;
vec3_set(&group_pos, pos.x, pos.y, 0.0f);

View file

@ -530,9 +530,8 @@ static void scene_video_tick(void *data, float seconds)
/* assumes video lock */
static void update_transforms_and_prune_sources(obs_scene_t *scene,
struct darray *remove_items)
struct darray *remove_items, obs_sceneitem_t *group_sceneitem)
{
obs_sceneitem_t *group_sceneitem = scene->group_sceneitem;
struct obs_scene_item *item = scene->first_item;
bool rebuild_group = group_sceneitem &&
os_atomic_load_bool(&group_sceneitem->update_group_resize);
@ -554,7 +553,7 @@ static void update_transforms_and_prune_sources(obs_scene_t *scene,
video_lock(group_scene);
update_transforms_and_prune_sources(group_scene,
remove_items);
remove_items, item);
video_unlock(group_scene);
}
@ -568,8 +567,8 @@ static void update_transforms_and_prune_sources(obs_scene_t *scene,
item = item->next;
}
if (rebuild_group && scene->group_sceneitem)
resize_group(scene->group_sceneitem);
if (rebuild_group && group_sceneitem)
resize_group(group_sceneitem);
}
static void scene_video_render(void *data, gs_effect_t *effect)
@ -582,8 +581,9 @@ static void scene_video_render(void *data, gs_effect_t *effect)
video_lock(scene);
if (!scene->group_sceneitem) {
update_transforms_and_prune_sources(scene, &remove_items.da);
if (!scene->is_group) {
update_transforms_and_prune_sources(scene, &remove_items.da,
NULL);
}
gs_blend_state_push();
@ -671,7 +671,7 @@ static void scene_load_item(struct obs_scene *scene, obs_data_t *item_data)
if (is_group) {
item->is_group = true;
((obs_scene_t *)source->context.data)->group_sceneitem = item;
((obs_scene_t *)source->context.data)->is_group = true;
}
obs_data_set_default_int(item_data, "align",
@ -779,7 +779,8 @@ static void scene_load(void *data, obs_data_t *settings)
static void scene_save(void *data, obs_data_t *settings);
static void scene_save_item(obs_data_array_t *array,
struct obs_scene_item *item, bool group_item_backup)
struct obs_scene_item *item,
struct obs_scene_item *backup_group)
{
obs_data_t *item_data = obs_data_create();
const char *name = obs_source_get_name(item->source);
@ -788,9 +789,8 @@ static void scene_save_item(obs_data_array_t *array,
struct vec2 scale = item->scale;
float rot = item->rot;
if (group_item_backup) {
obs_sceneitem_t *group = item->parent->group_sceneitem;
get_ungrouped_transform(group, &pos, &scale, &rot);
if (backup_group) {
get_ungrouped_transform(backup_group, &pos, &scale, &rot);
}
obs_data_set_string(item_data, "name", name);
@ -809,7 +809,7 @@ static void scene_save_item(obs_data_array_t *array,
obs_data_set_int (item_data, "crop_bottom", (int)item->crop.bottom);
obs_data_set_int (item_data, "id", item->id);
obs_data_set_bool (item_data, "is_group", item->is_group);
obs_data_set_bool (item_data, "group_item_backup", group_item_backup);
obs_data_set_bool (item_data, "group_item_backup", !!backup_group);
if (item->is_group) {
obs_data_t *group_data = obs_data_create();
@ -825,7 +825,7 @@ static void scene_save_item(obs_data_array_t *array,
group_item = group_scene->first_item;
while (group_item) {
scene_save_item(array, group_item, true);
scene_save_item(array, group_item, item);
group_item = group_item->next;
}
@ -865,7 +865,7 @@ static void scene_save(void *data, obs_data_t *settings)
item = scene->first_item;
while (item) {
scene_save_item(array, item, false);
scene_save_item(array, item, NULL);
item = item->next;
}
@ -1687,16 +1687,6 @@ static void signal_parent(obs_scene_t *parent, const char *command,
{
calldata_set_ptr(params, "scene", parent);
signal_handler_signal(parent->source->context.signals, command, params);
if (parent->group_sceneitem) {
parent = parent->group_sceneitem->parent;
if (!parent)
return;
calldata_set_ptr(params, "scene", parent);
signal_handler_signal(parent->source->context.signals, command,
params);
}
}
void obs_sceneitem_select(obs_sceneitem_t *item, bool select)
@ -2271,13 +2261,13 @@ static void get_ungrouped_transform(obs_sceneitem_t *group,
*rot += group->rot;
}
static void remove_group_transform(obs_sceneitem_t *item)
static void remove_group_transform(obs_sceneitem_t *group,
obs_sceneitem_t *item)
{
obs_scene_t *parent = item->parent;
if (!parent || !parent->group_sceneitem)
if (!parent || !group)
return;
obs_sceneitem_t *group = parent->group_sceneitem;
get_ungrouped_transform(group, &item->pos, &item->scale, &item->rot);
update_item_transform(item);
@ -2411,7 +2401,6 @@ obs_sceneitem_t *obs_scene_insert_group(obs_scene_t *scene,
obs_sceneitem_t *item = obs_scene_add_internal(
scene, sub_scene->source, last_item, true);
sub_scene->group_sceneitem = item;
sub_scene->custom_size = true;
obs_scene_release(sub_scene);
@ -2427,7 +2416,7 @@ obs_sceneitem_t *obs_scene_insert_group(obs_scene_t *scene,
for (size_t i = count; i > 0; i--) {
size_t idx = i - 1;
remove_group_transform(items[idx]);
remove_group_transform(item, items[idx]);
detach_sceneitem(items[idx]);
}
for (size_t i = 0; i < count; i++) {
@ -2480,17 +2469,6 @@ obs_sceneitem_t *obs_scene_get_group(obs_scene_t *scene, const char *name)
return group;
}
obs_sceneitem_t *obs_sceneitem_group_from_scene(obs_scene_t *scene)
{
return scene ? scene->group_sceneitem : NULL;
}
obs_sceneitem_t *obs_sceneitem_group_from_source(obs_source_t *source)
{
obs_scene_t *scene = obs_scene_from_source(source);
return obs_sceneitem_group_from_scene(scene);
}
bool obs_sceneitem_is_group(obs_sceneitem_t *item)
{
return item && item->is_group;
@ -2517,7 +2495,7 @@ void obs_sceneitem_group_ungroup(obs_sceneitem_t *item)
first = subscene->first_item;
last = first;
while (last) {
remove_group_transform(last);
remove_group_transform(item, last);
last->parent = scene;
if (!last->next)
break;
@ -2567,7 +2545,7 @@ void obs_sceneitem_group_add_item(obs_sceneitem_t *group, obs_sceneitem_t *item)
/* ------------------------- */
full_lock(scene);
remove_group_transform(item);
remove_group_transform(group, item);
detach_sceneitem(item);
/* ------------------------- */
@ -2596,41 +2574,38 @@ void obs_sceneitem_group_add_item(obs_sceneitem_t *group, obs_sceneitem_t *item)
full_unlock(scene);
}
void obs_sceneitem_group_remove_item(obs_sceneitem_t *item)
void obs_sceneitem_group_remove_item(obs_sceneitem_t *group,
obs_sceneitem_t *item)
{
if (!item)
if (!item || !group || !group->is_group)
return;
obs_scene_t *groupscene = item->parent;
obs_sceneitem_t *groupitem = groupscene->group_sceneitem;
if (!groupitem)
return;
obs_scene_t *scene = groupitem->parent;
obs_scene_t *scene = group->parent;
/* ------------------------- */
full_lock(scene);
full_lock(groupscene);
remove_group_transform(item);
remove_group_transform(group, item);
detach_sceneitem(item);
/* ------------------------- */
if (groupitem->prev) {
groupitem->prev->next = item;
item->prev = groupitem->prev;
if (group->prev) {
group->prev->next = item;
item->prev = group->prev;
} else {
scene->first_item = item;
item->prev = NULL;
}
groupitem->prev = item;
item->next = groupitem;
group->prev = item;
item->next = group;
item->parent = scene;
/* ------------------------- */
resize_group(groupitem);
resize_group(group);
full_unlock(groupscene);
full_unlock(scene);
}
@ -2695,6 +2670,23 @@ static bool sceneitems_match2(obs_scene_t *scene,
return true;
}
static obs_sceneitem_t *get_sceneitem_parent_group(obs_scene_t *scene,
obs_sceneitem_t *group_subitem)
{
if (group_subitem->is_group)
return NULL;
obs_sceneitem_t *item = scene->first_item;
while (item) {
if (item->is_group &&
item->source->context.data == group_subitem->parent)
return item;
item = item->next;
}
return NULL;
}
bool obs_scene_reorder_items2(obs_scene_t *scene,
struct obs_sceneitem_order_info *item_order,
size_t item_order_size)
@ -2714,7 +2706,9 @@ bool obs_scene_reorder_items2(obs_scene_t *scene,
for (size_t i = 0; i < item_order_size; i++) {
struct obs_sceneitem_order_info *info = &item_order[i];
if (!info->item->is_group) {
remove_group_transform(info->item);
obs_sceneitem_t *group =
get_sceneitem_parent_group(scene, info->item);
remove_group_transform(group, info->item);
}
}
@ -2783,16 +2777,38 @@ bool obs_scene_reorder_items2(obs_scene_t *scene,
return true;
}
obs_sceneitem_t *obs_sceneitem_get_group(obs_sceneitem_t *item)
obs_sceneitem_t *obs_sceneitem_get_group(obs_scene_t *scene,
obs_sceneitem_t *group_subitem)
{
return item && item->parent ? item->parent->group_sceneitem : NULL;
if (!scene || !group_subitem || group_subitem->is_group)
return NULL;
full_lock(scene);
obs_sceneitem_t *group = get_sceneitem_parent_group(scene,
group_subitem);
full_unlock(scene);
return group;
}
bool obs_source_is_group(const obs_source_t *source)
{
if (!source || source->info.id != scene_info.id)
return false;
return ((obs_scene_t *)source->context.data)->is_group;
}
bool obs_scene_is_group(const obs_scene_t *scene)
{
return scene ? scene->is_group : false;
}
void obs_sceneitem_group_enum_items(obs_sceneitem_t *group,
bool (*callback)(obs_scene_t*, obs_sceneitem_t*, void*),
void *param)
{
if (!group)
if (!group || !group->is_group)
return;
obs_scene_t *scene = obs_scene_from_source(group->source);

View file

@ -85,8 +85,8 @@ struct obs_scene_item {
struct obs_scene {
struct obs_source *source;
struct obs_scene_item *group_sceneitem;
bool is_group;
bool custom_size;
uint32_t cx;
uint32_t cy;

View file

@ -1447,12 +1447,14 @@ EXPORT void obs_sceneitem_group_ungroup(obs_sceneitem_t *group);
EXPORT void obs_sceneitem_group_add_item(obs_sceneitem_t *group,
obs_sceneitem_t *item);
EXPORT void obs_sceneitem_group_remove_item(obs_sceneitem_t *item);
EXPORT void obs_sceneitem_group_remove_item(obs_sceneitem_t *group,
obs_sceneitem_t *item);
EXPORT obs_sceneitem_t *obs_sceneitem_get_group(obs_sceneitem_t *item);
EXPORT obs_sceneitem_t *obs_sceneitem_get_group(obs_scene_t *scene,
obs_sceneitem_t *item);
EXPORT obs_sceneitem_t *obs_sceneitem_group_from_scene(obs_scene_t *scene);
EXPORT obs_sceneitem_t *obs_sceneitem_group_from_source(obs_source_t *source);
EXPORT bool obs_source_is_group(const obs_source_t *source);
EXPORT bool obs_scene_is_group(const obs_scene_t *scene);
EXPORT void obs_sceneitem_group_enum_items(obs_sceneitem_t *group,
bool (*callback)(obs_scene_t*, obs_sceneitem_t*, void*),