Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/animation/anim_filter.c10
-rw-r--r--source/blender/editors/gpencil/gpencil_convert.c5
-rw-r--r--source/blender/editors/object/object_add.c83
-rw-r--r--source/blender/editors/object/object_edit.c107
-rw-r--r--source/blender/editors/object/object_group.c272
-rw-r--r--source/blender/editors/object/object_intern.h24
-rw-r--r--source/blender/editors/object/object_ops.c34
-rw-r--r--source/blender/editors/object/object_relations.c200
-rw-r--r--source/blender/editors/object/object_select.c166
-rw-r--r--source/blender/editors/object/object_transform.c4
-rw-r--r--source/blender/editors/physics/rigidbody_constraint.c8
-rw-r--r--source/blender/editors/physics/rigidbody_object.c8
-rw-r--r--source/blender/editors/render/render_preview.c29
-rw-r--r--source/blender/editors/space_action/space_action.c2
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c41
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c2
-rw-r--r--source/blender/editors/space_graph/space_graph.c2
-rw-r--r--source/blender/editors/space_info/info_stats.c37
-rw-r--r--source/blender/editors/space_nla/space_nla.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c1056
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c123
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c148
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h47
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c78
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c81
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c404
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c360
-rw-r--r--source/blender/editors/space_outliner/outliner_utils.c23
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c20
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c6
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c14
31 files changed, 1323 insertions, 2073 deletions
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index b7eaa1a4a5f..aad4f71fe9a 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -84,12 +84,12 @@
#include "BLI_ghash.h"
#include "BLI_string.h"
-#include "BKE_animsys.h"
#include "BKE_action.h"
-#include "BKE_fcurve.h"
+#include "BKE_animsys.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
+#include "BKE_fcurve.h"
#include "BKE_global.h"
-#include "BKE_group.h"
#include "BKE_key.h"
#include "BKE_layer.h"
#include "BKE_main.h"
@@ -1727,7 +1727,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi
* - used to ease the process of doing multiple-character choreographies
*/
if (ads->filterflag & ADS_FILTER_ONLYOBGROUP) {
- if (BKE_group_object_exists(ads->filter_grp, ob) == 0)
+ if (BKE_collection_has_object_recursive(ads->filter_grp, ob) == 0)
continue;
}
@@ -2894,7 +2894,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Base *base, int filter_m
* - used to ease the process of doing multiple-character choreographies
*/
if (ads->filterflag & ADS_FILTER_ONLYOBGROUP) {
- if (BKE_group_object_exists(ads->filter_grp, ob) == 0)
+ if (BKE_collection_has_object_recursive(ads->filter_grp, ob) == 0)
return false;
}
diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c
index 6dfe17f227a..84889033f30 100644
--- a/source/blender/editors/gpencil/gpencil_convert.c
+++ b/source/blender/editors/gpencil/gpencil_convert.c
@@ -48,6 +48,7 @@
#include "DNA_anim_types.h"
#include "DNA_curve_types.h"
+#include "DNA_group_types.h"
#include "DNA_object_types.h"
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
@@ -1128,7 +1129,7 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
struct Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- SceneCollection *sc = CTX_data_scene_collection(C);
+ Collection *collection = CTX_data_collection(C);
bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0);
bGPDstroke *gps, *prev_gps = NULL;
Object *ob;
@@ -1158,7 +1159,7 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
*/
ob = BKE_object_add_only_object(bmain, OB_CURVE, gpl->info);
cu = ob->data = BKE_curve_add(bmain, gpl->info, OB_CURVE);
- BKE_collection_object_add(&scene->id, sc, ob);
+ BKE_collection_object_add(bmain, collection, ob);
base_new = BKE_view_layer_base_find(view_layer, ob);
cu->flag |= CU_3D;
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index d9c743aaf27..8d64d8b67e9 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -71,7 +71,6 @@
#include "BKE_displist.h"
#include "BKE_effect.h"
#include "BKE_font.h"
-#include "BKE_group.h"
#include "BKE_lamp.h"
#include "BKE_lattice.h"
#include "BKE_layer.h"
@@ -1048,11 +1047,11 @@ void OBJECT_OT_lamp_add(wmOperatorType *ot)
ED_object_add_generic_props(ot, false);
}
-/********************* Add Group Instance Operator ********************/
+/********************* Add Collection Instance Operator ********************/
-static int group_instance_add_exec(bContext *C, wmOperator *op)
+static int collection_instance_add_exec(bContext *C, wmOperator *op)
{
- Group *group;
+ Collection *collection;
unsigned int layer;
float loc[3], rot[3];
@@ -1060,7 +1059,7 @@ static int group_instance_add_exec(bContext *C, wmOperator *op)
char name[MAX_ID_NAME - 2];
RNA_string_get(op->ptr, "name", name);
- group = (Group *)BKE_libblock_find_name(ID_GR, name);
+ collection = (Collection *)BKE_libblock_find_name(ID_GR, name);
if (0 == RNA_struct_property_is_set(op->ptr, "location")) {
const wmEvent *event = CTX_wm_window(C)->eventstate;
@@ -1073,22 +1072,30 @@ static int group_instance_add_exec(bContext *C, wmOperator *op)
}
}
else
- group = BLI_findlink(&CTX_data_main(C)->group, RNA_enum_get(op->ptr, "group"));
+ collection = BLI_findlink(&CTX_data_main(C)->collection, RNA_enum_get(op->ptr, "collection"));
if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &layer, NULL))
return OPERATOR_CANCELLED;
- if (group) {
+ if (collection) {
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_add_type(C, OB_EMPTY, group->id.name + 2, loc, rot, false, layer);
- ob->dup_group = group;
- ob->transflag |= OB_DUPLIGROUP;
- id_us_plus(&group->id);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ /* Avoid dependency cycles. */
+ LayerCollection *active_lc = BKE_layer_collection_get_active(view_layer);
+ while (BKE_collection_find_cycle(active_lc->collection, collection)) {
+ active_lc = BKE_layer_collection_activate_parent(view_layer, active_lc);
+ }
+
+ Object *ob = ED_object_add_type(C, OB_EMPTY, collection->id.name + 2, loc, rot, false, layer);
+ ob->dup_group = collection;
+ ob->transflag |= OB_DUPLICOLLECTION;
+ id_us_plus(&collection->id);
/* works without this except if you try render right after, see: 22027 */
DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&group->id, 0);
+ DEG_id_tag_update(&collection->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
@@ -1099,27 +1106,27 @@ static int group_instance_add_exec(bContext *C, wmOperator *op)
}
/* only used as menu */
-void OBJECT_OT_group_instance_add(wmOperatorType *ot)
+void OBJECT_OT_collection_instance_add(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
- ot->name = "Add Group Instance";
- ot->description = "Add a dupligroup instance";
- ot->idname = "OBJECT_OT_group_instance_add";
+ ot->name = "Add Collection Instance";
+ ot->description = "Add a collection instance";
+ ot->idname = "OBJECT_OT_collection_instance_add";
/* api callbacks */
ot->invoke = WM_enum_search_invoke;
- ot->exec = group_instance_add_exec;
+ ot->exec = collection_instance_add_exec;
ot->poll = ED_operator_objectmode;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- RNA_def_string(ot->srna, "name", "Group", MAX_ID_NAME - 2, "Name", "Group name to add");
- prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "");
- RNA_def_enum_funcs(prop, RNA_group_itemf);
+ RNA_def_string(ot->srna, "name", "Collection", MAX_ID_NAME - 2, "Name", "Collection name to add");
+ prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "");
+ RNA_def_enum_funcs(prop, RNA_collection_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
ED_object_add_generic_props(ot, false);
@@ -1197,7 +1204,7 @@ void ED_object_base_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
DEG_id_tag_update_ex(bmain, &ob->id, DEG_TAG_BASE_FLAGS_UPDATE);
- BKE_collections_object_remove(bmain, &scene->id, ob, true);
+ BKE_scene_collections_object_remove(bmain, scene, ob, true);
}
static int object_delete_exec(bContext *C, wmOperator *op)
@@ -1331,7 +1338,7 @@ static void copy_object_set_idnew(bContext *C)
/********************* Make Duplicates Real ************************/
/**
- * \note regarding hashing dupli-objects when using OB_DUPLIGROUP, skip the first member of #DupliObject.persistent_id
+ * \note regarding hashing dupli-objects when using OB_DUPLICOLLECTION, skip the first member of #DupliObject.persistent_id
* since its a unique index and we only want to know if the group objects are from the same dupli-group instance.
*/
static unsigned int dupliobject_group_hash(const void *ptr)
@@ -1346,7 +1353,7 @@ static unsigned int dupliobject_group_hash(const void *ptr)
}
/**
- * \note regarding hashing dupli-objects when NOT using OB_DUPLIGROUP, include the first member of #DupliObject.persistent_id
+ * \note regarding hashing dupli-objects when NOT using OB_DUPLICOLLECTION, include the first member of #DupliObject.persistent_id
* since its the index of the vertex/face the object is instantiated on and we want to identify objects on the same vertex/face.
*/
static unsigned int dupliobject_hash(const void *ptr)
@@ -1418,7 +1425,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
dupli_gh = BLI_ghash_ptr_new(__func__);
if (use_hierarchy) {
- if (base->object->transflag & OB_DUPLIGROUP) {
+ if (base->object->transflag & OB_DUPLICOLLECTION) {
parent_gh = BLI_ghash_new(dupliobject_group_hash, dupliobject_group_cmp, __func__);
}
else {
@@ -1438,7 +1445,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
ob_dst->totcol = 0;
}
- BKE_collection_object_add_from(scene, base->object, ob_dst);
+ BKE_collection_object_add_from(bmain, scene, base->object, ob_dst);
base_dst = BKE_view_layer_base_find(view_layer, ob_dst);
BLI_assert(base_dst != NULL);
@@ -1492,7 +1499,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
* they won't be read, this is simply for a hash lookup. */
DupliObject dob_key;
dob_key.ob = ob_src_par;
- if (base->object->transflag & OB_DUPLIGROUP) {
+ if (base->object->transflag & OB_DUPLICOLLECTION) {
memcpy(&dob_key.persistent_id[1],
&dob->persistent_id[1],
sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
@@ -1537,7 +1544,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
}
}
- if (base->object->transflag & OB_DUPLIGROUP && base->object->dup_group) {
+ if (base->object->transflag & OB_DUPLICOLLECTION && base->object->dup_group) {
for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
if (ob->proxy_group == base->object) {
ob->proxy = NULL;
@@ -1659,7 +1666,7 @@ static Base *duplibase_for_convert(Main *bmain, Scene *scene, ViewLayer *view_la
obn = BKE_object_copy(bmain, ob);
DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- BKE_collection_object_add_from(scene, ob, obn);
+ BKE_collection_object_add_from(bmain, scene, ob, obn);
basen = BKE_view_layer_base_find(view_layer, obn);
ED_object_base_select(basen, BA_SELECT);
@@ -2068,23 +2075,23 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer
base = BKE_view_layer_base_find(view_layer, ob);
if ((base != NULL) && (base->flag & BASE_VISIBLED)) {
- BKE_collection_object_add_from(scene, ob, obn);
+ BKE_collection_object_add_from(bmain, scene, ob, obn);
}
else {
- LayerCollection *layer_collection = BKE_layer_collection_get_active_ensure(scene, view_layer);
- BKE_collection_object_add(&scene->id, layer_collection->scene_collection, obn);
+ LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
+ BKE_collection_object_add(bmain, layer_collection->collection, obn);
}
basen = BKE_view_layer_base_find(view_layer, obn);
- /* 1) duplis should end up in same group as the original
- * 2) Rigid Body sim participants MUST always be part of a group...
+ /* 1) duplis should end up in same collection as the original
+ * 2) Rigid Body sim participants MUST always be part of a collection...
*/
// XXX: is 2) really a good measure here?
- if ((ob->flag & OB_FROMGROUP) != 0 || ob->rigidbody_object || ob->rigidbody_constraint) {
- Group *group;
- for (group = bmain->group.first; group; group = group->id.next) {
- if (BKE_group_object_exists(group, ob))
- BKE_group_object_add(group, obn);
+ if (ob->rigidbody_object || ob->rigidbody_constraint) {
+ Collection *collection;
+ for (collection = bmain->collection.first; collection; collection = collection->id.next) {
+ if (BKE_collection_has_object(collection, ob))
+ BKE_collection_object_add(bmain, collection, obn);
}
}
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index b9a7da02611..a2e91761a38 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -1506,11 +1506,12 @@ bool ED_object_editmode_calc_active_center(Object *obedit, const bool select_onl
static int move_to_collection_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "collection_index");
- const bool is_add = RNA_boolean_get(op->ptr, "is_add");
+ const bool is_link = STREQ(op->idname, "OBJECT_OT_link_to_collection");
const bool is_new = RNA_boolean_get(op->ptr, "is_new");
- SceneCollection *scene_collection;
+ Collection *collection;
if (!RNA_property_is_set(op->ptr, prop)) {
BKE_report(op->reports, RPT_ERROR, "No collection selected");
@@ -1518,8 +1519,8 @@ static int move_to_collection_exec(bContext *C, wmOperator *op)
}
int collection_index = RNA_property_int_get(op->ptr, prop);
- scene_collection = BKE_collection_from_index(CTX_data_scene(C), collection_index);
- if (scene_collection == NULL) {
+ collection = BKE_collection_from_index(CTX_data_scene(C), collection_index);
+ if (collection == NULL) {
BKE_report(op->reports, RPT_ERROR, "Unexpected error, collection not found");
return OPERATOR_CANCELLED;
}
@@ -1540,24 +1541,24 @@ static int move_to_collection_exec(bContext *C, wmOperator *op)
if (is_new) {
char new_collection_name[MAX_NAME];
RNA_string_get(op->ptr, "new_collection_name", new_collection_name);
- scene_collection = BKE_collection_add(&scene->id, scene_collection, COLLECTION_TYPE_NONE, new_collection_name);
+ collection = BKE_collection_add(bmain, collection, new_collection_name);
}
if ((single_object != NULL) &&
- is_add &&
- BLI_findptr(&scene_collection->objects, single_object, offsetof(LinkData, data)))
+ is_link &&
+ BLI_findptr(&collection->gobject, single_object, offsetof(CollectionObject, ob)))
{
- BKE_reportf(op->reports, RPT_ERROR, "%s already in %s", single_object->id.name + 2, scene_collection->name);
+ BKE_reportf(op->reports, RPT_ERROR, "%s already in %s", single_object->id.name + 2, collection->id.name + 2);
return OPERATOR_CANCELLED;
}
CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
- if (!is_add) {
- BKE_collection_object_move(&scene->id, scene_collection, NULL, ob);
+ if (!is_link) {
+ BKE_collection_object_move(bmain, scene, collection, NULL, ob);
}
else {
- BKE_collection_object_add(&scene->id, scene_collection, ob);
+ BKE_collection_object_add(bmain, collection, ob);
}
}
CTX_DATA_END;
@@ -1566,8 +1567,8 @@ static int move_to_collection_exec(bContext *C, wmOperator *op)
RPT_INFO,
"%s %s to %s",
(single_object != NULL) ? single_object->id.name + 2 : "Objects",
- is_add ? "added" : "moved",
- scene_collection->name);
+ is_link ? "linked" : "moved",
+ collection->id.name + 2);
DEG_relations_tag_update(CTX_data_main(C));
DEG_id_tag_update(&scene->id, 0);
@@ -1579,26 +1580,27 @@ static int move_to_collection_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-typedef struct MoveToCollectionData {
+struct MoveToCollectionData {
struct MoveToCollectionData *next, *prev;
int index;
- struct SceneCollection *collection;
+ struct Collection *collection;
struct ListBase submenus;
PointerRNA ptr;
struct wmOperatorType *ot;
-} MoveToCollectionData;
+};
static int move_to_collection_menus_create(wmOperator *op, MoveToCollectionData *menu)
{
int index = menu->index;
- for (SceneCollection *scene_collection = menu->collection->scene_collections.first;
- scene_collection != NULL;
- scene_collection = scene_collection->next)
+ for (CollectionChild *child = menu->collection->children.first;
+ child != NULL;
+ child = child->next)
{
+ Collection *collection = child->collection;
MoveToCollectionData *submenu = MEM_callocN(sizeof(MoveToCollectionData),
"MoveToCollectionData submenu - expected memleak");
BLI_addtail(&menu->submenus, submenu);
- submenu->collection = scene_collection;
+ submenu->collection = collection;
submenu->index = ++index;
index = move_to_collection_menus_create(op, submenu);
submenu->ot = op->type;
@@ -1631,11 +1633,19 @@ static void move_to_collection_menus_free(MoveToCollectionData **menu)
static void move_to_collection_menu_create(bContext *UNUSED(C), uiLayout *layout, void *menu_v)
{
MoveToCollectionData *menu = menu_v;
+ const char *name;
+
+ if (menu->collection->flag & COLLECTION_IS_MASTER) {
+ name = IFACE_("Scene Collection");
+ }
+ else {
+ name = menu->collection->id.name + 2;
+ }
uiItemIntO(layout,
- menu->collection->name,
+ name,
ICON_NONE,
- "OBJECT_OT_move_to_collection",
+ menu->ot->idname,
"collection_index",
menu->index);
uiItemS(layout);
@@ -1658,7 +1668,6 @@ static void move_to_collection_menu_create(bContext *UNUSED(C), uiLayout *layout
"New Collection",
ICON_ZOOMIN,
menu->ptr.data,
- /* We use invoke here so we can read ctrl from event. */
WM_OP_INVOKE_DEFAULT,
0,
NULL);
@@ -1668,15 +1677,15 @@ static void move_to_collection_menus_items(uiLayout *layout, MoveToCollectionDat
{
if (BLI_listbase_is_empty(&menu->submenus)) {
uiItemIntO(layout,
- menu->collection->name,
+ menu->collection->id.name + 2,
ICON_NONE,
- "OBJECT_OT_move_to_collection",
+ menu->ot->idname,
"collection_index",
menu->index);
}
else {
uiItemMenuF(layout,
- menu->collection->name,
+ menu->collection->id.name + 2,
ICON_NONE,
move_to_collection_menu_create,
menu);
@@ -1686,8 +1695,10 @@ static void move_to_collection_menus_items(uiLayout *layout, MoveToCollectionDat
/* This is allocated statically because we need this available for the menus creation callback. */
static MoveToCollectionData *master_collection_menu = NULL;
-static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
+ Scene *scene = CTX_data_scene(C);
+
/* Reset the menus data for the current master collection, and free previously allocated data. */
move_to_collection_menus_free(&master_collection_menu);
@@ -1695,16 +1706,15 @@ static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent
prop = RNA_struct_find_property(op->ptr, "collection_index");
if (RNA_property_is_set(op->ptr, prop)) {
int collection_index = RNA_property_int_get(op->ptr, prop);
- RNA_boolean_set(op->ptr, "is_add", event->ctrl);
if (RNA_boolean_get(op->ptr, "is_new")) {
prop = RNA_struct_find_property(op->ptr, "new_collection_name");
if (!RNA_property_is_set(op->ptr, prop)) {
char name[MAX_NAME];
- SceneCollection *scene_collection;
+ Collection *collection;
- scene_collection = BKE_collection_from_index(CTX_data_scene(C), collection_index);
- BKE_collection_new_name_get(&CTX_data_scene(C)->id, scene_collection, name);
+ collection = BKE_collection_from_index(scene, collection_index);
+ BKE_collection_new_name_get(collection, name);
RNA_property_string_set(op->ptr, prop, name);
return WM_operator_props_dialog_popup(C, op, 10 * UI_UNIT_X, 5 * UI_UNIT_Y);
@@ -1713,7 +1723,7 @@ static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent
return move_to_collection_exec(C, op);
}
- SceneCollection *master_collection = BKE_collection_master(&CTX_data_scene(C)->id);
+ Collection *master_collection = BKE_collection_master(scene);
/* We need the data to be allocated so it's available during menu drawing.
* Technically we could use wmOperator->customdata. However there is no free callback
@@ -1733,10 +1743,10 @@ static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent
uiLayout *layout;
/* Build the menus. */
- pup = UI_popup_menu_begin(C, IFACE_("Move to Collection"), ICON_NONE);
+ const char *title = CTX_IFACE_(op->type->translation_context, op->type->name);
+ pup = UI_popup_menu_begin(C, title, ICON_NONE);
layout = UI_popup_menu_layout(pup);
- /* We use invoke here so we can read ctrl from event. */
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
move_to_collection_menu_create(C, layout, master_collection_menu);
@@ -1752,7 +1762,7 @@ void OBJECT_OT_move_to_collection(wmOperatorType *ot)
/* identifiers */
ot->name = "Move to Collection";
- ot->description = "Move to a collection only (Ctrl to add)";
+ ot->description = "Move objects to a scene collection";
ot->idname = "OBJECT_OT_move_to_collection";
/* api callbacks */
@@ -1766,7 +1776,32 @@ void OBJECT_OT_move_to_collection(wmOperatorType *ot)
prop = RNA_def_int(ot->srna, "collection_index", COLLECTION_INVALID_INDEX, COLLECTION_INVALID_INDEX, INT_MAX,
"Collection Index", "Index of the collection to move to", 0, INT_MAX);
RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
- prop = RNA_def_boolean(ot->srna, "is_add", false, "Add", "Keep object in original collections as well");
+ prop = RNA_def_boolean(ot->srna, "is_new", false, "New", "Move objects to a new collection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ prop = RNA_def_string(ot->srna, "new_collection_name", NULL, MAX_NAME, "Name",
+ "Name of the newly added collection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
+void OBJECT_OT_link_to_collection(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Link to Collection";
+ ot->description = "Link objects to a collection";
+ ot->idname = "OBJECT_OT_link_to_collection";
+
+ /* api callbacks */
+ ot->exec = move_to_collection_exec;
+ ot->invoke = move_to_collection_invoke;
+ ot->poll = ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_int(ot->srna, "collection_index", COLLECTION_INVALID_INDEX, COLLECTION_INVALID_INDEX, INT_MAX,
+ "Collection Index", "Index of the collection to move to", 0, INT_MAX);
RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
prop = RNA_def_boolean(ot->srna, "is_new", false, "New", "Move objects to a new collection");
RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index cb0fbdda970..0a6a81d99da 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -39,8 +39,8 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_group.h"
#include "BKE_library.h"
#include "BKE_library_remap.h"
#include "BKE_main.h"
@@ -64,8 +64,9 @@
/********************* 3d view operators ***********************/
/* can be called with C == NULL */
-static const EnumPropertyItem *group_object_active_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *collection_object_active_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
{
+ Main *bmain = CTX_data_main(C);
Object *ob;
EnumPropertyItem *item = NULL, item_tmp = {0};
int totitem = 0;
@@ -78,25 +79,25 @@ static const EnumPropertyItem *group_object_active_itemf(bContext *C, PointerRNA
/* check that the object exists */
if (ob) {
- Group *group;
+ Collection *collection;
int i = 0, count = 0;
- /* if 2 or more groups, add option to add to all groups */
- group = NULL;
- while ((group = BKE_group_object_find(group, ob)))
+ /* if 2 or more collections, add option to add to all collections */
+ collection = NULL;
+ while ((collection = BKE_collection_object_find(bmain, collection, ob)))
count++;
if (count >= 2) {
- item_tmp.identifier = item_tmp.name = "All Groups";
+ item_tmp.identifier = item_tmp.name = "All Collections";
item_tmp.value = INT_MAX; /* this will give NULL on lookup */
RNA_enum_item_add(&item, &totitem, &item_tmp);
RNA_enum_item_add_separator(&item, &totitem);
}
- /* add groups */
- group = NULL;
- while ((group = BKE_group_object_find(group, ob))) {
- item_tmp.identifier = item_tmp.name = group->id.name + 2;
+ /* add collections */
+ collection = NULL;
+ while ((collection = BKE_collection_object_find(bmain, collection, ob))) {
+ item_tmp.identifier = item_tmp.name = collection->id.name + 2;
/* item_tmp.icon = ICON_ARMATURE_DATA; */
item_tmp.value = i;
RNA_enum_item_add(&item, &totitem, &item_tmp);
@@ -110,48 +111,48 @@ static const EnumPropertyItem *group_object_active_itemf(bContext *C, PointerRNA
return item;
}
-/* get the group back from the enum index, quite awkward and UI specific */
-static Group *group_object_active_find_index(Object *ob, const int group_object_index)
+/* get the collection back from the enum index, quite awkward and UI specific */
+static Collection *collection_object_active_find_index(Main *bmain, Object *ob, const int collection_object_index)
{
- Group *group = NULL;
+ Collection *collection = NULL;
int i = 0;
- while ((group = BKE_group_object_find(group, ob))) {
- if (i == group_object_index) {
+ while ((collection = BKE_collection_object_find(bmain, collection, ob))) {
+ if (i == collection_object_index) {
break;
}
i++;
}
- return group;
+ return collection;
}
static int objects_add_active_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
Main *bmain = CTX_data_main(C);
- int single_group_index = RNA_enum_get(op->ptr, "group");
- Group *single_group = group_object_active_find_index(ob, single_group_index);
- Group *group;
+ int single_collection_index = RNA_enum_get(op->ptr, "collection");
+ Collection *single_collection = collection_object_active_find_index(bmain, ob, single_collection_index);
+ Collection *collection;
bool is_cycle = false;
bool updated = false;
if (ob == NULL)
return OPERATOR_CANCELLED;
- /* now add all selected objects to the group(s) */
- for (group = bmain->group.first; group; group = group->id.next) {
- if (single_group && group != single_group)
+ /* now add all selected objects to the collection(s) */
+ for (collection = bmain->collection.first; collection; collection = collection->id.next) {
+ if (single_collection && collection != single_collection)
continue;
- if (!BKE_group_object_exists(group, ob))
+ if (!BKE_collection_has_object(collection, ob))
continue;
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- if (BKE_group_object_exists(group, base->object))
+ if (BKE_collection_has_object(collection, base->object))
continue;
- if (!BKE_group_object_cyclic_check(bmain, base->object, group)) {
- BKE_group_object_add(group, base->object);
+ if (!BKE_collection_object_cyclic_check(bmain, base->object, collection)) {
+ BKE_collection_object_add(bmain, collection, base->object);
updated = true;
}
else {
@@ -162,7 +163,7 @@ static int objects_add_active_exec(bContext *C, wmOperator *op)
}
if (is_cycle)
- BKE_report(op->reports, RPT_WARNING, "Skipped some groups because of cycle detected");
+ BKE_report(op->reports, RPT_WARNING, "Skipped some collections because of cycle detected");
if (!updated)
return OPERATOR_CANCELLED;
@@ -173,14 +174,14 @@ static int objects_add_active_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void GROUP_OT_objects_add_active(wmOperatorType *ot)
+void COLLECTION_OT_objects_add_active(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
- ot->name = "Add Selected To Active Group";
- ot->description = "Add the object to an object group that contains the active object";
- ot->idname = "GROUP_OT_objects_add_active";
+ ot->name = "Add Selected To Active Collection";
+ ot->description = "Add the object to an object collection that contains the active object";
+ ot->idname = "COLLECTION_OT_objects_add_active";
/* api callbacks */
ot->exec = objects_add_active_exec;
@@ -191,8 +192,8 @@ void GROUP_OT_objects_add_active(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "The group to add other selected objects to");
- RNA_def_enum_funcs(prop, group_object_active_itemf);
+ prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "The collection to add other selected objects to");
+ RNA_def_enum_funcs(prop, collection_object_active_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
}
@@ -202,26 +203,26 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = OBACT(view_layer);
- int single_group_index = RNA_enum_get(op->ptr, "group");
- Group *single_group = group_object_active_find_index(ob, single_group_index);
- Group *group;
+ int single_collection_index = RNA_enum_get(op->ptr, "collection");
+ Collection *single_collection = collection_object_active_find_index(bmain, ob, single_collection_index);
+ Collection *collection;
bool ok = false;
if (ob == NULL)
return OPERATOR_CANCELLED;
- /* linking to same group requires its own loop so we can avoid
- * looking up the active objects groups each time */
+ /* linking to same collection requires its own loop so we can avoid
+ * looking up the active objects collections each time */
- for (group = bmain->group.first; group; group = group->id.next) {
- if (single_group && group != single_group)
+ for (collection = bmain->collection.first; collection; collection = collection->id.next) {
+ if (single_collection && collection != single_collection)
continue;
- if (BKE_group_object_exists(group, ob)) {
- /* Remove groups from selected objects */
+ if (BKE_collection_has_object(collection, ob)) {
+ /* Remove collections from selected objects */
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- BKE_group_object_unlink(group, base->object);
+ BKE_collection_object_remove(bmain, collection, base->object, false);
ok = 1;
}
CTX_DATA_END;
@@ -229,7 +230,7 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op)
}
if (!ok)
- BKE_report(op->reports, RPT_ERROR, "Active object contains no groups");
+ BKE_report(op->reports, RPT_ERROR, "Active object contains no collections");
DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
@@ -237,14 +238,14 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void GROUP_OT_objects_remove_active(wmOperatorType *ot)
+void COLLECTION_OT_objects_remove_active(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
- ot->name = "Remove Selected From Active Group";
- ot->description = "Remove the object from an object group that contains the active object";
- ot->idname = "GROUP_OT_objects_remove_active";
+ ot->name = "Remove Selected From Active Collection";
+ ot->description = "Remove the object from an object collection that contains the active object";
+ ot->idname = "COLLECTION_OT_objects_remove_active";
/* api callbacks */
ot->exec = objects_remove_active_exec;
@@ -255,19 +256,19 @@ void GROUP_OT_objects_remove_active(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "The group to remove other selected objects from");
- RNA_def_enum_funcs(prop, group_object_active_itemf);
+ prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "The collection to remove other selected objects from");
+ RNA_def_enum_funcs(prop, collection_object_active_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
}
-static int group_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op))
+static int collection_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- BKE_object_groups_clear(base->object);
+ BKE_object_groups_clear(bmain, base->object);
}
CTX_DATA_END;
@@ -277,43 +278,43 @@ static int group_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-void GROUP_OT_objects_remove_all(wmOperatorType *ot)
+void COLLECTION_OT_objects_remove_all(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Remove From All Groups";
- ot->description = "Remove selected objects from all groups";
- ot->idname = "GROUP_OT_objects_remove_all";
+ ot->name = "Remove From All Unlinked Collections";
+ ot->description = "Remove selected objects from all collections not used in a scene";
+ ot->idname = "COLLECTION_OT_objects_remove_all";
/* api callbacks */
- ot->exec = group_objects_remove_all_exec;
+ ot->exec = collection_objects_remove_all_exec;
ot->poll = ED_operator_objectmode;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int group_objects_remove_exec(bContext *C, wmOperator *op)
+static int collection_objects_remove_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
Main *bmain = CTX_data_main(C);
- int single_group_index = RNA_enum_get(op->ptr, "group");
- Group *single_group = group_object_active_find_index(ob, single_group_index);
- Group *group;
+ int single_collection_index = RNA_enum_get(op->ptr, "collection");
+ Collection *single_collection = collection_object_active_find_index(bmain, ob, single_collection_index);
+ Collection *collection;
bool updated = false;
if (ob == NULL)
return OPERATOR_CANCELLED;
- for (group = bmain->group.first; group; group = group->id.next) {
- if (single_group && group != single_group)
+ for (collection = bmain->collection.first; collection; collection = collection->id.next) {
+ if (single_collection && collection != single_collection)
continue;
- if (!BKE_group_object_exists(group, ob))
+ if (!BKE_collection_has_object(collection, ob))
continue;
- /* now remove all selected objects from the group */
+ /* now remove all selected objects from the collection */
CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
{
- BKE_group_object_unlink(group, base->object);
+ BKE_collection_object_remove(bmain, collection, base->object, false);
updated = true;
}
CTX_DATA_END;
@@ -328,17 +329,17 @@ static int group_objects_remove_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void GROUP_OT_objects_remove(wmOperatorType *ot)
+void COLLECTION_OT_objects_remove(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
- ot->name = "Remove From Group";
- ot->description = "Remove selected objects from a group";
- ot->idname = "GROUP_OT_objects_remove";
+ ot->name = "Remove From Collection";
+ ot->description = "Remove selected objects from a collection";
+ ot->idname = "COLLECTION_OT_objects_remove";
/* api callbacks */
- ot->exec = group_objects_remove_exec;
+ ot->exec = collection_objects_remove_exec;
ot->invoke = WM_menu_invoke;
ot->poll = ED_operator_objectmode;
@@ -346,25 +347,24 @@ void GROUP_OT_objects_remove(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "The group to remove this object from");
- RNA_def_enum_funcs(prop, group_object_active_itemf);
+ prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "The collection to remove this object from");
+ RNA_def_enum_funcs(prop, collection_object_active_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
}
-static int group_create_exec(bContext *C, wmOperator *op)
+static int collection_create_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Group *group = NULL;
char name[MAX_ID_NAME - 2]; /* id name */
RNA_string_get(op->ptr, "name", name);
- group = BKE_group_add(bmain, name);
+ Collection *collection = BKE_collection_add(bmain, NULL, name);
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
{
- BKE_group_object_add(group, base->object);
+ BKE_collection_object_add(bmain, collection, base->object);
}
CTX_DATA_END;
@@ -374,102 +374,101 @@ static int group_create_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void GROUP_OT_create(wmOperatorType *ot)
+void COLLECTION_OT_create(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Create New Group";
- ot->description = "Create an object group from selected objects";
- ot->idname = "GROUP_OT_create";
+ ot->name = "Create New Collection";
+ ot->description = "Create an object collection from selected objects";
+ ot->idname = "COLLECTION_OT_create";
/* api callbacks */
- ot->exec = group_create_exec;
+ ot->exec = collection_create_exec;
ot->poll = ED_operator_objectmode;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_string(ot->srna, "name", "Group", MAX_ID_NAME - 2, "Name", "Name of the new group");
+ RNA_def_string(ot->srna, "name", "Collection", MAX_ID_NAME - 2, "Name", "Name of the new collection");
}
/****************** properties window operators *********************/
-static int group_add_exec(bContext *C, wmOperator *UNUSED(op))
+static int collection_add_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = ED_object_context(C);
Main *bmain = CTX_data_main(C);
- Group *group;
if (ob == NULL)
return OPERATOR_CANCELLED;
- group = BKE_group_add(bmain, "Group");
- BKE_group_object_add(group, ob);
+ Collection *collection = BKE_collection_add(bmain, NULL, "Collection");
+ BKE_collection_object_add(bmain, collection, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
}
-void OBJECT_OT_group_add(wmOperatorType *ot)
+void OBJECT_OT_collection_add(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Add to Group";
- ot->idname = "OBJECT_OT_group_add";
- ot->description = "Add an object to a new group";
+ ot->name = "Add to Collection";
+ ot->idname = "OBJECT_OT_collection_add";
+ ot->description = "Add an object to a new collection";
/* api callbacks */
- ot->exec = group_add_exec;
+ ot->exec = collection_add_exec;
ot->poll = ED_operator_objectmode;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int group_link_exec(bContext *C, wmOperator *op)
+static int collection_link_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Object *ob = ED_object_context(C);
- Group *group = BLI_findlink(&bmain->group, RNA_enum_get(op->ptr, "group"));
+ Collection *collection = BLI_findlink(&bmain->collection, RNA_enum_get(op->ptr, "collection"));
- if (ELEM(NULL, ob, group))
+ if (ELEM(NULL, ob, collection))
return OPERATOR_CANCELLED;
- /* Early return check, if the object is already in group
+ /* Early return check, if the object is already in collection
* we could skip all the dependency check and just consider
* operator is finished.
*/
- if (BKE_group_object_exists(group, ob)) {
+ if (BKE_collection_has_object(collection, ob)) {
return OPERATOR_FINISHED;
}
- /* Adding object to group which is used as dupligroup for self is bad idea.
+ /* Adding object to collection which is used as duplicollection for self is bad idea.
*
- * It is also bad idea to add object to group which is in group which
+ * It is also bad idea to add object to collection which is in collection which
* contains our current object.
*/
- if (BKE_group_object_cyclic_check(bmain, ob, group)) {
- BKE_report(op->reports, RPT_ERROR, "Could not add the group because of dependency cycle detected");
+ if (BKE_collection_object_cyclic_check(bmain, ob, collection)) {
+ BKE_report(op->reports, RPT_ERROR, "Could not add the collection because of dependency cycle detected");
return OPERATOR_CANCELLED;
}
- BKE_group_object_add(group, ob);
+ BKE_collection_object_add(bmain, collection, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
}
-void OBJECT_OT_group_link(wmOperatorType *ot)
+void OBJECT_OT_collection_link(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
- ot->name = "Link to Group";
- ot->idname = "OBJECT_OT_group_link";
- ot->description = "Add an object to an existing group";
+ ot->name = "Link to Collection";
+ ot->idname = "OBJECT_OT_collection_link";
+ ot->description = "Add an object to an existing collection";
/* api callbacks */
- ot->exec = group_link_exec;
+ ot->exec = collection_link_exec;
ot->invoke = WM_enum_search_invoke;
ot->poll = ED_operator_objectmode;
@@ -477,36 +476,37 @@ void OBJECT_OT_group_link(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "");
- RNA_def_enum_funcs(prop, RNA_group_local_itemf);
+ prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "");
+ RNA_def_enum_funcs(prop, RNA_collection_local_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
}
-static int group_remove_exec(bContext *C, wmOperator *UNUSED(op))
+static int collection_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
+ Main *bmain = CTX_data_main(C);
Object *ob = ED_object_context(C);
- Group *group = CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
+ Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
- if (!ob || !group)
+ if (!ob || !collection)
return OPERATOR_CANCELLED;
- BKE_group_object_unlink(group, ob);
+ BKE_collection_object_remove(bmain, collection, ob, false);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
}
-void OBJECT_OT_group_remove(wmOperatorType *ot)
+void OBJECT_OT_collection_remove(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Remove Group";
- ot->idname = "OBJECT_OT_group_remove";
- ot->description = "Remove the active object from this group";
+ ot->name = "Remove Collection";
+ ot->idname = "OBJECT_OT_collection_remove";
+ ot->description = "Remove the active object from this collection";
/* api callbacks */
- ot->exec = group_remove_exec;
+ ot->exec = collection_remove_exec;
ot->poll = ED_operator_objectmode;
/* flags */
@@ -514,47 +514,47 @@ void OBJECT_OT_group_remove(wmOperatorType *ot)
}
-static int group_unlink_exec(bContext *C, wmOperator *UNUSED(op))
+static int collection_unlink_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
- Group *group = CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
+ Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
- if (!group)
+ if (!collection)
return OPERATOR_CANCELLED;
- BKE_libblock_delete(bmain, group);
+ BKE_libblock_delete(bmain, collection);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
return OPERATOR_FINISHED;
}
-void OBJECT_OT_group_unlink(wmOperatorType *ot)
+void OBJECT_OT_collection_unlink(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Unlink Group";
- ot->idname = "OBJECT_OT_group_unlink";
- ot->description = "Unlink the group from all objects";
+ ot->name = "Unlink Collection";
+ ot->idname = "OBJECT_OT_collection_unlink";
+ ot->description = "Unlink the collection from all objects";
/* api callbacks */
- ot->exec = group_unlink_exec;
+ ot->exec = collection_unlink_exec;
ot->poll = ED_operator_objectmode;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op)) /* Select objects in the same group as the active */
+static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op)) /* Select objects in the same collection as the active */
{
- Group *group = CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
+ Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
- if (!group)
+ if (!collection)
return OPERATOR_CANCELLED;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
- if (BKE_group_object_exists(group, base->object)) {
+ if (BKE_collection_has_object_recursive(collection, base->object)) {
ED_object_base_select(base, BA_SELECT);
}
}
@@ -566,12 +566,12 @@ static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op)) /* Select o
return OPERATOR_FINISHED;
}
-void OBJECT_OT_grouped_select(wmOperatorType *ot)
+void OBJECT_OT_collection_objects_select(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Select Grouped";
- ot->idname = "OBJECT_OT_grouped_select";
- ot->description = "Select all objects in group";
+ ot->name = "Select Objects in Collection";
+ ot->idname = "OBJECT_OT_collection_objects_select";
+ ot->description = "Select all objects in collection";
/* api callbacks */
ot->exec = select_grouped_exec;
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index dbb81be124a..445b14982ee 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -88,6 +88,7 @@ void OBJECT_OT_paths_clear(struct wmOperatorType *ot);
void OBJECT_OT_forcefield_toggle(struct wmOperatorType *ot);
void OBJECT_OT_move_to_collection(struct wmOperatorType *ot);
+void OBJECT_OT_link_to_collection(struct wmOperatorType *ot);
/* object_select.c */
void OBJECT_OT_select_all(struct wmOperatorType *ot);
@@ -99,7 +100,6 @@ void OBJECT_OT_select_grouped(struct wmOperatorType *ot);
void OBJECT_OT_select_mirror(struct wmOperatorType *ot);
void OBJECT_OT_select_more(struct wmOperatorType *ot);
void OBJECT_OT_select_less(struct wmOperatorType *ot);
-void OBJECT_OT_select_same_group(struct wmOperatorType *ot);
void OBJECT_OT_select_same_collection(struct wmOperatorType *ot);
/* object_add.c */
@@ -115,7 +115,7 @@ void OBJECT_OT_lamp_add(struct wmOperatorType *ot);
void OBJECT_OT_effector_add(struct wmOperatorType *ot);
void OBJECT_OT_camera_add(struct wmOperatorType *ot);
void OBJECT_OT_speaker_add(struct wmOperatorType *ot);
-void OBJECT_OT_group_instance_add(struct wmOperatorType *ot);
+void OBJECT_OT_collection_instance_add(struct wmOperatorType *ot);
void OBJECT_OT_duplicates_make_real(struct wmOperatorType *ot);
void OBJECT_OT_duplicate(struct wmOperatorType *ot);
@@ -134,11 +134,11 @@ void OBJECT_OT_hook_reset(struct wmOperatorType *ot);
void OBJECT_OT_hook_recenter(struct wmOperatorType *ot);
/* object_group.c */
-void GROUP_OT_create(struct wmOperatorType *ot);
-void GROUP_OT_objects_remove_all(struct wmOperatorType *ot);
-void GROUP_OT_objects_remove(struct wmOperatorType *ot);
-void GROUP_OT_objects_add_active(struct wmOperatorType *ot);
-void GROUP_OT_objects_remove_active(struct wmOperatorType *ot);
+void COLLECTION_OT_create(struct wmOperatorType *ot);
+void COLLECTION_OT_objects_remove_all(struct wmOperatorType *ot);
+void COLLECTION_OT_objects_remove(struct wmOperatorType *ot);
+void COLLECTION_OT_objects_add_active(struct wmOperatorType *ot);
+void COLLECTION_OT_objects_remove_active(struct wmOperatorType *ot);
/* object_modifier.c */
int edit_modifier_poll_generic(struct bContext *C, struct StructRNA *rna_type, int obtype_flag);
@@ -251,11 +251,11 @@ void OBJECT_OT_shape_key_mirror(struct wmOperatorType *ot);
void OBJECT_OT_shape_key_move(struct wmOperatorType *ot);
/* object_group.c */
-void OBJECT_OT_group_add(struct wmOperatorType *ot);
-void OBJECT_OT_group_link(struct wmOperatorType *ot);
-void OBJECT_OT_group_remove(struct wmOperatorType *ot);
-void OBJECT_OT_group_unlink(struct wmOperatorType *ot);
-void OBJECT_OT_grouped_select(struct wmOperatorType *ot);
+void OBJECT_OT_collection_add(struct wmOperatorType *ot);
+void OBJECT_OT_collection_link(struct wmOperatorType *ot);
+void OBJECT_OT_collection_remove(struct wmOperatorType *ot);
+void OBJECT_OT_collection_unlink(struct wmOperatorType *ot);
+void OBJECT_OT_collection_objects_select(struct wmOperatorType *ot);
/* object_bake.c */
void OBJECT_OT_bake_image(wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index c4c86b3932d..c47d741f818 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -93,7 +93,6 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_select_random);
WM_operatortype_append(OBJECT_OT_select_all);
- WM_operatortype_append(OBJECT_OT_select_same_group);
WM_operatortype_append(OBJECT_OT_select_same_collection);
WM_operatortype_append(OBJECT_OT_select_by_type);
WM_operatortype_append(OBJECT_OT_select_linked);
@@ -102,11 +101,11 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_select_more);
WM_operatortype_append(OBJECT_OT_select_less);
- WM_operatortype_append(GROUP_OT_create);
- WM_operatortype_append(GROUP_OT_objects_remove_all);
- WM_operatortype_append(GROUP_OT_objects_remove);
- WM_operatortype_append(GROUP_OT_objects_add_active);
- WM_operatortype_append(GROUP_OT_objects_remove_active);
+ WM_operatortype_append(COLLECTION_OT_create);
+ WM_operatortype_append(COLLECTION_OT_objects_remove_all);
+ WM_operatortype_append(COLLECTION_OT_objects_remove);
+ WM_operatortype_append(COLLECTION_OT_objects_add_active);
+ WM_operatortype_append(COLLECTION_OT_objects_remove_active);
WM_operatortype_append(OBJECT_OT_delete);
WM_operatortype_append(OBJECT_OT_text_add);
@@ -120,7 +119,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_add);
WM_operatortype_append(OBJECT_OT_add_named);
WM_operatortype_append(OBJECT_OT_effector_add);
- WM_operatortype_append(OBJECT_OT_group_instance_add);
+ WM_operatortype_append(OBJECT_OT_collection_instance_add);
WM_operatortype_append(OBJECT_OT_metaball_add);
WM_operatortype_append(OBJECT_OT_duplicates_make_real);
WM_operatortype_append(OBJECT_OT_duplicate);
@@ -213,6 +212,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(TRANSFORM_OT_vertex_warp);
WM_operatortype_append(OBJECT_OT_move_to_collection);
+ WM_operatortype_append(OBJECT_OT_link_to_collection);
WM_operatortype_append(OBJECT_OT_shape_key_add);
WM_operatortype_append(OBJECT_OT_shape_key_remove);
@@ -221,11 +221,11 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_shape_key_mirror);
WM_operatortype_append(OBJECT_OT_shape_key_move);
- WM_operatortype_append(OBJECT_OT_group_add);
- WM_operatortype_append(OBJECT_OT_group_link);
- WM_operatortype_append(OBJECT_OT_group_remove);
- WM_operatortype_append(OBJECT_OT_group_unlink);
- WM_operatortype_append(OBJECT_OT_grouped_select);
+ WM_operatortype_append(OBJECT_OT_collection_add);
+ WM_operatortype_append(OBJECT_OT_collection_link);
+ WM_operatortype_append(OBJECT_OT_collection_remove);
+ WM_operatortype_append(OBJECT_OT_collection_unlink);
+ WM_operatortype_append(OBJECT_OT_collection_objects_select);
WM_operatortype_append(OBJECT_OT_hook_add_selob);
WM_operatortype_append(OBJECT_OT_hook_add_newob);
@@ -395,11 +395,11 @@ void ED_keymap_object(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "ANIM_OT_keyframe_delete_v3d", IKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_verify_item(keymap, "ANIM_OT_keying_set_active_set", IKEY, KM_PRESS, KM_CTRL | KM_SHIFT | KM_ALT, 0);
- WM_keymap_verify_item(keymap, "GROUP_OT_create", GKEY, KM_PRESS, KM_CTRL, 0);
- WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove", GKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
- WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove_all", GKEY, KM_PRESS, KM_SHIFT | KM_CTRL | KM_ALT, 0);
- WM_keymap_verify_item(keymap, "GROUP_OT_objects_add_active", GKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
- WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove_active", GKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0);
+ WM_keymap_verify_item(keymap, "COLLECTION_OT_create", GKEY, KM_PRESS, KM_CTRL, 0);
+ WM_keymap_verify_item(keymap, "COLLECTION_OT_objects_remove", GKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
+ WM_keymap_verify_item(keymap, "COLLECTION_OT_objects_remove_all", GKEY, KM_PRESS, KM_SHIFT | KM_CTRL | KM_ALT, 0);
+ WM_keymap_verify_item(keymap, "COLLECTION_OT_objects_add_active", GKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
+ WM_keymap_verify_item(keymap, "COLLECTION_OT_objects_remove_active", GKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0);
WM_keymap_add_menu(keymap, "VIEW3D_MT_object_specials", WKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index dd919aedabb..c5cf946cfb3 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -70,7 +70,6 @@
#include "BKE_DerivedMesh.h"
#include "BKE_displist.h"
#include "BKE_global.h"
-#include "BKE_group.h"
#include "BKE_fcurve.h"
#include "BKE_idprop.h"
#include "BKE_lamp.h"
@@ -329,7 +328,7 @@ static int make_proxy_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
else {
/* error.. cannot continue */
- BKE_report(op->reports, RPT_ERROR, "Can only make proxy for a referenced object or group");
+ BKE_report(op->reports, RPT_ERROR, "Can only make proxy for a referenced object or collection");
return OPERATOR_CANCELLED;
}
@@ -343,7 +342,8 @@ static int make_proxy_exec(bContext *C, wmOperator *op)
ViewLayer *view_layer = CTX_data_view_layer(C);
if (gob->dup_group != NULL) {
- Base *base = BLI_findlink(&gob->dup_group->view_layer->object_bases, RNA_enum_get(op->ptr, "object"));
+ const ListBase dup_group_objects = BKE_collection_object_cache_get(gob->dup_group);
+ Base *base = BLI_findlink(&dup_group_objects, RNA_enum_get(op->ptr, "object"));
ob = base->object;
}
else {
@@ -385,8 +385,8 @@ static int make_proxy_exec(bContext *C, wmOperator *op)
}
/* Generic itemf's for operators that take library args */
-static const EnumPropertyItem *proxy_group_object_itemf(bContext *C, PointerRNA *UNUSED(ptr),
- PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *proxy_collection_object_itemf(bContext *C, PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop), bool *r_free)
{
EnumPropertyItem item_tmp = {0}, *item = NULL;
int totitem = 0;
@@ -397,13 +397,13 @@ static const EnumPropertyItem *proxy_group_object_itemf(bContext *C, PointerRNA
return DummyRNA_DEFAULT_items;
/* find the object to affect */
- FOREACH_GROUP_OBJECT_BEGIN(ob->dup_group, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(ob->dup_group, object)
{
item_tmp.identifier = item_tmp.name = object->id.name + 2;
item_tmp.value = i++;
RNA_enum_item_add(&item, &totitem, &item_tmp);
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
RNA_enum_item_end(&item, &totitem);
*r_free = true;
@@ -431,8 +431,8 @@ void OBJECT_OT_proxy_make(wmOperatorType *ot)
/* properties */
/* XXX, relies on hard coded ID at the moment */
prop = RNA_def_enum(ot->srna, "object", DummyRNA_DEFAULT_items, 0, "Proxy Object",
- "Name of lib-linked/grouped object to make a proxy for");
- RNA_def_enum_funcs(prop, proxy_group_object_itemf);
+ "Name of lib-linked/collection object to make a proxy for");
+ RNA_def_enum_funcs(prop, proxy_collection_object_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
}
@@ -1343,7 +1343,8 @@ static void link_to_scene(Main *UNUSED(bmain), unsigned short UNUSED(nr))
static int make_links_scene_exec(bContext *C, wmOperator *op)
{
- Scene *scene_to = BLI_findlink(&CTX_data_main(C)->scene, RNA_enum_get(op->ptr, "scene"));
+ Main *bmain = CTX_data_main(C);
+ Scene *scene_to = BLI_findlink(&bmain->scene, RNA_enum_get(op->ptr, "scene"));
if (scene_to == NULL) {
BKE_report(op->reports, RPT_ERROR, "Could not find scene");
@@ -1360,10 +1361,10 @@ static int make_links_scene_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- SceneCollection *sc_to = BKE_collection_master(&scene_to->id);
+ Collection *collection_to = BKE_collection_master(scene_to);
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
{
- BKE_collection_object_add(&scene_to->id, sc_to, base->object);
+ BKE_collection_object_add(bmain, collection_to, base->object);
}
CTX_DATA_END;
@@ -1379,7 +1380,7 @@ enum {
MAKE_LINKS_MATERIALS = 2,
MAKE_LINKS_ANIMDATA = 3,
MAKE_LINKS_GROUP = 4,
- MAKE_LINKS_DUPLIGROUP = 5,
+ MAKE_LINKS_DUPLICOLLECTION = 5,
MAKE_LINKS_MODIFIERS = 6,
MAKE_LINKS_FONTS = 7,
};
@@ -1400,7 +1401,7 @@ static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst
break;
case MAKE_LINKS_ANIMDATA:
case MAKE_LINKS_GROUP:
- case MAKE_LINKS_DUPLIGROUP:
+ case MAKE_LINKS_DUPLICOLLECTION:
return true;
case MAKE_LINKS_MODIFIERS:
if (!ELEM(OB_EMPTY, ob_src->type, ob_dst->type)) {
@@ -1424,16 +1425,16 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
ID *obdata_id;
int a;
- /* group */
- LinkNode *ob_groups = NULL;
+ /* collection */
+ LinkNode *ob_collections = NULL;
bool is_cycle = false;
bool is_lib = false;
ob_src = ED_object_active_context(C);
- /* avoid searching all groups in source object each time */
+ /* avoid searching all collections in source object each time */
if (type == MAKE_LINKS_GROUP) {
- ob_groups = BKE_object_groups(ob_src);
+ ob_collections = BKE_object_groups(bmain, ob_src);
}
CTX_DATA_BEGIN (C, Base *, base_dst, selected_editable_bases)
@@ -1478,15 +1479,15 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
break;
case MAKE_LINKS_GROUP:
{
- LinkNode *group_node;
+ LinkNode *collection_node;
- /* first clear groups */
- BKE_object_groups_clear(ob_dst);
+ /* first clear collections */
+ BKE_object_groups_clear(bmain, ob_dst);
- /* now add in the groups from the link nodes */
- for (group_node = ob_groups; group_node; group_node = group_node->next) {
- if (ob_dst->dup_group != group_node->link) {
- BKE_group_object_add(group_node->link, ob_dst);
+ /* now add in the collections from the link nodes */
+ for (collection_node = ob_collections; collection_node; collection_node = collection_node->next) {
+ if (ob_dst->dup_group != collection_node->link) {
+ BKE_collection_object_add(bmain, collection_node->link, ob_dst);
}
else {
is_cycle = true;
@@ -1494,11 +1495,11 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
}
break;
}
- case MAKE_LINKS_DUPLIGROUP:
+ case MAKE_LINKS_DUPLICOLLECTION:
ob_dst->dup_group = ob_src->dup_group;
if (ob_dst->dup_group) {
id_us_plus(&ob_dst->dup_group->id);
- ob_dst->transflag |= OB_DUPLIGROUP;
+ ob_dst->transflag |= OB_DUPLICOLLECTION;
}
break;
case MAKE_LINKS_MODIFIERS:
@@ -1542,12 +1543,12 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
if (type == MAKE_LINKS_GROUP) {
- if (ob_groups) {
- BLI_linklist_free(ob_groups, NULL);
+ if (ob_collections) {
+ BLI_linklist_free(ob_collections, NULL);
}
if (is_cycle) {
- BKE_report(op->reports, RPT_WARNING, "Skipped some groups because of cycle detected");
+ BKE_report(op->reports, RPT_WARNING, "Skipped some collections because of cycle detected");
}
}
@@ -1595,7 +1596,7 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
{MAKE_LINKS_MATERIALS, "MATERIAL", 0, "Materials", ""},
{MAKE_LINKS_ANIMDATA, "ANIMATION", 0, "Animation Data", ""},
{MAKE_LINKS_GROUP, "GROUPS", 0, "Group", ""},
- {MAKE_LINKS_DUPLIGROUP, "DUPLIGROUP", 0, "DupliGroup", ""},
+ {MAKE_LINKS_DUPLICOLLECTION, "DUPLICOLLECTION", 0, "DupliGroup", ""},
{MAKE_LINKS_MODIFIERS, "MODIFIERS", 0, "Modifiers", ""},
{MAKE_LINKS_FONTS, "FONTS", 0, "Fonts", ""},
{0, NULL, 0, NULL, NULL}};
@@ -1619,19 +1620,11 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
/**************************** Make Single User ********************************/
-static Object *single_object_users_object(Main *bmain, Scene *scene, Object *ob, const bool copy_groups)
+static Object *single_object_users_object(Main *bmain, Scene *scene, Object *ob)
{
/* base gets copy of object */
Object *obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
- if (copy_groups) {
- if (ob->flag & OB_FROMGROUP) {
- obn->flag |= OB_FROMGROUP;
- }
- }
- else {
- /* copy already clears */
- }
/* remap gpencil parenting */
if (scene->gpd) {
@@ -1647,42 +1640,42 @@ static Object *single_object_users_object(Main *bmain, Scene *scene, Object *ob,
return obn;
}
-static void libblock_relink_scene_collection(SceneCollection *sc)
+static void libblock_relink_collection(Collection *collection)
{
- for (LinkData *link = sc->objects.first; link; link = link->next) {
- BKE_libblock_relink_to_newid(link->data);
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ BKE_libblock_relink_to_newid(&cob->ob->id);
}
- for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
- libblock_relink_scene_collection(nsc);
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ libblock_relink_collection(child->collection);
}
}
-static void single_object_users_scene_collection(Main *bmain, Scene *scene, SceneCollection *sc, const int flag, const bool copy_groups)
+static void single_object_users_collection(Main *bmain, Scene *scene, Collection *collection, const int flag, const bool copy_collections)
{
- for (LinkData *link = sc->objects.first; link; link = link->next) {
- Object *ob = link->data;
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ Object *ob = cob->ob;
/* an object may be in more than one collection */
if ((ob->id.newid == NULL) && ((ob->flag & flag) == flag)) {
if (!ID_IS_LINKED(ob) && ob->id.us > 1) {
- link->data = single_object_users_object(bmain, scene, link->data, copy_groups);
+ cob->ob = single_object_users_object(bmain, scene, cob->ob);
}
}
}
- for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
- single_object_users_scene_collection(bmain, scene, nsc, flag, copy_groups);
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ single_object_users_collection(bmain, scene, child->collection, flag, copy_collections);
}
}
-/* Warning, sets ID->newid pointers of objects and groups, but does not clear them. */
-static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_groups)
+/* Warning, sets ID->newid pointers of objects and collections, but does not clear them. */
+static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_collections)
{
- Group *group, *groupn;
+ Collection *collection, *collectionn;
/* duplicate all the objects of the scene */
- SceneCollection *msc = BKE_collection_master(&scene->id);
- single_object_users_scene_collection(bmain, scene, msc, flag, copy_groups);
+ Collection *master_collection = BKE_collection_master(scene);
+ single_object_users_collection(bmain, scene, master_collection, flag, copy_collections);
/* loop over ViewLayers and assign the pointers accordingly */
for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
@@ -1691,40 +1684,39 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
}
}
- /* duplicate groups that consist entirely of duplicated objects */
- for (group = bmain->group.first; group; group = group->id.next) {
- if (copy_groups && group->view_layer->object_bases.first) {
+ /* duplicate collections that consist entirely of duplicated objects */
+ for (collection = bmain->collection.first; collection; collection = collection->id.next) {
+ if (copy_collections) {
bool all_duplicated = true;
+ bool any_duplicated = false;
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
- {
- if (object->id.newid == NULL) {
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ any_duplicated = true;
+ if (cob->ob->id.newid == NULL) {
all_duplicated = false;
break;
}
}
- FOREACH_GROUP_OBJECT_END;
- if (all_duplicated) {
- groupn = ID_NEW_SET(group, BKE_group_copy(bmain, group));
+ if (any_duplicated && all_duplicated) {
+ // TODO: test if this works, with child collections ..
+ collectionn = ID_NEW_SET(collection, BKE_collection_copy(bmain, NULL, collection));
- FOREACH_GROUP_BASE_BEGIN(groupn, base)
- {
- base->object = (Object *)base->object->id.newid;
+ for (CollectionObject *cob = collectionn->gobject.first; cob; cob = cob->next) {
+ cob->ob = (Object *)cob->ob->id.newid;
}
- FOREACH_GROUP_BASE_END
}
}
}
- /* group pointers in scene */
+ /* collection pointers in scene */
BKE_scene_groups_relink(scene);
ID_NEW_REMAP(scene->camera);
if (v3d) ID_NEW_REMAP(v3d->camera);
- /* object and group pointers */
- libblock_relink_scene_collection(msc);
+ /* object and collection pointers */
+ libblock_relink_collection(master_collection);
}
/* not an especially efficient function, only added so the single user
@@ -1917,9 +1909,9 @@ static void single_mat_users_expand(Main *bmain)
}
/* used for copying scenes */
-void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bool copy_groups)
+void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bool copy_collections)
{
- single_object_users(bmain, scene, NULL, 0, copy_groups);
+ single_object_users(bmain, scene, NULL, 0, copy_collections);
if (full) {
single_obdata_users(bmain, scene, NULL, 0);
@@ -2038,7 +2030,7 @@ static void tag_localizable_objects(bContext *C, const int mode)
* Instance indirectly referenced zero user objects,
* otherwise they're lost on reload, see T40595.
*/
-static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene, ViewLayer *view_layer, SceneCollection *sc)
+static bool make_local_all__instance_indirect_unused(Main *bmain, ViewLayer *view_layer, Collection *collection)
{
Object *ob;
bool changed = false;
@@ -2049,7 +2041,7 @@ static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene,
id_us_plus(&ob->id);
- BKE_collection_object_add(&scene->id, sc, ob);
+ BKE_collection_object_add(bmain, collection, ob);
base = BKE_view_layer_base_find(view_layer, ob);
base->flag |= BASE_SELECTED;
BKE_scene_object_base_flag_sync_from_base(base);
@@ -2117,7 +2109,6 @@ static void make_local_material_tag(Material *ma)
static int make_local_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
ParticleSystem *psys;
Material *ma, ***matarar;
const int mode = RNA_enum_get(op->ptr, "type");
@@ -2126,14 +2117,14 @@ static int make_local_exec(bContext *C, wmOperator *op)
/* Note: we (ab)use LIB_TAG_PRE_EXISTING to cherry pick which ID to make local... */
if (mode == MAKE_LOCAL_ALL) {
ViewLayer *view_layer = CTX_data_view_layer(C);
- SceneCollection *scene_collection = CTX_data_scene_collection(C);
+ Collection *collection = CTX_data_collection(C);
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
/* De-select so the user can differentiate newly instanced from existing objects. */
BKE_view_layer_base_deselect_all(view_layer);
- if (make_local_all__instance_indirect_unused(bmain, scene, view_layer, scene_collection)) {
+ if (make_local_all__instance_indirect_unused(bmain, view_layer, collection)) {
BKE_report(op->reports, RPT_INFO, "Orphan library objects added to the current scene to avoid loss");
}
}
@@ -2282,7 +2273,7 @@ static int make_override_static_invoke(bContext *C, wmOperator *op, const wmEven
}
else {
/* Error.. cannot continue. */
- BKE_report(op->reports, RPT_ERROR, "Can only make static override for a referenced object or group");
+ BKE_report(op->reports, RPT_ERROR, "Can only make static override for a referenced object or collection");
return OPERATOR_CANCELLED;
}
@@ -2296,23 +2287,24 @@ static int make_override_static_exec(bContext *C, wmOperator *op)
bool success = false;
if (!ID_IS_LINKED(obact) && obact->dup_group != NULL && ID_IS_LINKED(obact->dup_group)) {
- Base *base = BLI_findlink(&obact->dup_group->view_layer->object_bases, RNA_enum_get(op->ptr, "object"));
- Object *obgroup = obact;
+ const ListBase dup_collection_objects = BKE_collection_object_cache_get(obact->dup_group);
+ Base *base = BLI_findlink(&dup_collection_objects, RNA_enum_get(op->ptr, "object"));
+ Object *obcollection = obact;
obact = base->object;
- Group *group = obgroup->dup_group;
+ Collection *collection = obcollection->dup_group;
- /* First, we make a static override of the linked group itself. */
- group->id.tag |= LIB_TAG_DOIT;
+ /* First, we make a static override of the linked collection itself. */
+ collection->id.tag |= LIB_TAG_DOIT;
- /* Then, we make static override of the whole set of objects in the group. */
- FOREACH_GROUP_OBJECT_BEGIN(group, ob)
+ /* Then, we make static override of the whole set of objects in the Collection. */
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, ob)
{
ob->id.tag |= LIB_TAG_DOIT;
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- /* Then, we make static override of the whole set of objects in the group. */
- FOREACH_GROUP_OBJECT_BEGIN(group, ob)
+ /* Then, we make static override of the whole set of objects in the collection. */
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, ob)
{
if (ob->type == OB_ARMATURE && ob->pose != NULL) {
for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
@@ -2322,25 +2314,25 @@ static int make_override_static_exec(bContext *C, wmOperator *op)
}
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
success = BKE_override_static_create_from_tag(bmain);
/* Intantiate our newly overridden objects in scene, if not yet done. */
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- Group *new_group = (Group *)group->id.newid;
- FOREACH_GROUP_OBJECT_BEGIN(new_group, new_ob)
+ Collection *new_collection = (Collection *)collection->id.newid;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(new_collection, new_ob)
{
if (new_ob != NULL &&
new_ob->id.override_static != NULL &&
(base = BKE_view_layer_base_find(view_layer, new_ob)) == NULL)
{
- BKE_collection_object_add_from(scene, obgroup, new_ob);
+ BKE_collection_object_add_from(bmain, scene, obcollection, new_ob);
DEG_id_tag_update_ex(bmain, &new_ob->id, OB_RECALC_OB | DEG_TAG_BASE_FLAGS_UPDATE);
- /* parent to 'group' empty */
+ /* parent to 'collection' empty */
if (new_ob->parent == NULL) {
- new_ob->parent = obgroup;
+ new_ob->parent = obcollection;
}
if (new_ob == (Object *)obact->id.newid) {
base = BKE_view_layer_base_find(view_layer, new_ob);
@@ -2354,10 +2346,10 @@ static int make_override_static_exec(bContext *C, wmOperator *op)
BKE_override_static_operations_create(&new_ob->id, true);
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- /* obgroup is no more dupligroup-ing, it merely parents whole group of overriding instantiated objects. */
- obgroup->dup_group = NULL;
+ /* obcollection is no more duplicollection-ing, it merely parents whole collection of overriding instantiated objects. */
+ obcollection->dup_group = NULL;
/* Also, we'd likely want to lock by default things like transformations of implicitly overriden objects? */
@@ -2423,8 +2415,8 @@ void OBJECT_OT_make_override_static(wmOperatorType *ot)
/* properties */
PropertyRNA *prop;
prop = RNA_def_enum(ot->srna, "object", DummyRNA_DEFAULT_items, 0, "Override Object",
- "Name of lib-linked/group object to make an override from");
- RNA_def_enum_funcs(prop, proxy_group_object_itemf);
+ "Name of lib-linked/collection object to make an override from");
+ RNA_def_enum_funcs(prop, proxy_collection_object_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
}
@@ -2441,16 +2433,16 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
ViewLayer *view_layer = CTX_data_view_layer(C);
View3D *v3d = CTX_wm_view3d(C); /* ok if this is NULL */
const int flag = (RNA_enum_get(op->ptr, "type") == MAKE_SINGLE_USER_SELECTED) ? SELECT : 0;
- const bool copy_groups = false;
+ const bool copy_collections = false;
bool update_deps = false;
if (RNA_boolean_get(op->ptr, "object")) {
if (flag == SELECT) {
BKE_view_layer_selected_objects_tag(view_layer, OB_DONE);
- single_object_users(bmain, scene, v3d, OB_DONE, copy_groups);
+ single_object_users(bmain, scene, v3d, OB_DONE, copy_collections);
}
else {
- single_object_users(bmain, scene, v3d, 0, copy_groups);
+ single_object_users(bmain, scene, v3d, 0, copy_collections);
}
/* needed since object relationships may have changed */
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index d0d0418c861..d5e6f08352f 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -50,8 +50,8 @@
#include "BLT_translation.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_group.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -267,12 +267,12 @@ static bool object_select_all_by_material(bContext *C, Material *mat)
static bool object_select_all_by_dup_group(bContext *C, Object *ob)
{
bool changed = false;
- Group *dup_group = (ob->transflag & OB_DUPLIGROUP) ? ob->dup_group : NULL;
+ Collection *dup_group = (ob->transflag & OB_DUPLICOLLECTION) ? ob->dup_group : NULL;
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
- Group *dup_group_other = (base->object->transflag & OB_DUPLIGROUP) ? base->object->dup_group : NULL;
+ Collection *dup_group_other = (base->object->transflag & OB_DUPLICOLLECTION) ? base->object->dup_group : NULL;
if (dup_group == dup_group_other) {
ED_object_base_select(base, BA_SELECT);
changed = true;
@@ -475,7 +475,6 @@ enum {
OBJECT_GRPSEL_SIBLINGS = 3,
OBJECT_GRPSEL_TYPE = 4,
OBJECT_GRPSEL_COLLECTION = 5,
- OBJECT_GRPSEL_GROUP = 6,
OBJECT_GRPSEL_HOOK = 7,
OBJECT_GRPSEL_PASS = 8,
OBJECT_GRPSEL_COLOR = 9,
@@ -490,7 +489,6 @@ static const EnumPropertyItem prop_select_grouped_types[] = {
{OBJECT_GRPSEL_SIBLINGS, "SIBLINGS", 0, "Siblings", "Shared Parent"},
{OBJECT_GRPSEL_TYPE, "TYPE", 0, "Type", "Shared object type"},
{OBJECT_GRPSEL_COLLECTION, "COLLECTION", 0, "Collection", "Shared collection"},
- {OBJECT_GRPSEL_GROUP, "GROUP", 0, "Group", "Shared group"},
{OBJECT_GRPSEL_HOOK, "HOOK", 0, "Hook", ""},
{OBJECT_GRPSEL_PASS, "PASS", 0, "Pass", "Render pass Index"},
{OBJECT_GRPSEL_COLOR, "COLOR", 0, "Color", "Object Color"},
@@ -542,30 +540,30 @@ static bool select_grouped_parent(bContext *C) /* Makes parent active and de-sel
}
-#define GROUP_MENU_MAX 24
-static bool select_grouped_group(bContext *C, Object *ob) /* Select objects in the same group as the active */
+#define COLLECTION_MENU_MAX 24
+static bool select_grouped_collection(bContext *C, Object *ob) /* Select objects in the same group as the active */
{
bool changed = false;
- Group *group, *ob_groups[GROUP_MENU_MAX];
- int group_count = 0, i;
+ Collection *collection, *ob_collections[COLLECTION_MENU_MAX];
+ int collection_count = 0, i;
uiPopupMenu *pup;
uiLayout *layout;
- for (group = CTX_data_main(C)->group.first; group && group_count < GROUP_MENU_MAX; group = group->id.next) {
- if (BKE_group_object_exists(group, ob)) {
- ob_groups[group_count] = group;
- group_count++;
+ for (collection = CTX_data_main(C)->collection.first; collection && collection_count < COLLECTION_MENU_MAX; collection = collection->id.next) {
+ if (BKE_collection_has_object(collection, ob)) {
+ ob_collections[collection_count] = collection;
+ collection_count++;
}
}
- if (!group_count)
+ if (!collection_count)
return 0;
- else if (group_count == 1) {
- group = ob_groups[0];
+ else if (collection_count == 1) {
+ collection = ob_collections[0];
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
- if (BKE_group_object_exists(group, base->object)) {
+ if (BKE_collection_has_object(collection, base->object)) {
ED_object_base_select(base, BA_SELECT);
changed = true;
}
@@ -576,12 +574,12 @@ static bool select_grouped_group(bContext *C, Object *ob) /* Select objects in
}
/* build the menu. */
- pup = UI_popup_menu_begin(C, IFACE_("Select Group"), ICON_NONE);
+ pup = UI_popup_menu_begin(C, IFACE_("Select Collection"), ICON_NONE);
layout = UI_popup_menu_layout(pup);
- for (i = 0; i < group_count; i++) {
- group = ob_groups[i];
- uiItemStringO(layout, group->id.name + 2, 0, "OBJECT_OT_select_same_group", "group", group->id.name + 2);
+ for (i = 0; i < collection_count; i++) {
+ collection = ob_collections[i];
+ uiItemStringO(layout, collection->id.name + 2, 0, "OBJECT_OT_select_same_collection", "collection", collection->id.name + 2);
}
UI_popup_menu_end(C, pup);
@@ -662,60 +660,6 @@ static bool select_grouped_type(bContext *C, Object *ob)
return changed;
}
-#define COLLECTION_MENU_MAX 24
-static bool select_grouped_collection(bContext *C, Object *ob) /* Select objects in the same collection as the active */
-{
- typedef struct EnumeratedCollection {
- struct SceneCollection *collection;
- int index;
- } EnumeratedCollection;
-
- bool changed = false;
- SceneCollection *collection;
- EnumeratedCollection ob_collections[COLLECTION_MENU_MAX];
- int collection_count = 0, i;
- uiPopupMenu *pup;
- uiLayout *layout;
-
- i = 0;
- FOREACH_SCENE_COLLECTION_BEGIN(CTX_data_scene(C), scene_collection)
- {
- if (BKE_collection_object_exists(scene_collection, ob)) {
- ob_collections[collection_count].index = i;
- ob_collections[collection_count].collection = scene_collection;
- if (++collection_count >= COLLECTION_MENU_MAX) {
- break;
- }
- }
- i++;
- }
- FOREACH_SCENE_COLLECTION_END;
-
- if (!collection_count) {
- return 0;
- }
- else if (collection_count == 1) {
- collection = ob_collections[0].collection;
- return BKE_collection_objects_select(CTX_data_view_layer(C), collection);
- }
-
- /* build the menu. */
- pup = UI_popup_menu_begin(C, IFACE_("Select Collection"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
-
- for (i = 0; i < collection_count; i++) {
- uiItemIntO(layout,
- ob_collections[i].collection->name,
- ICON_NONE,
- "OBJECT_OT_select_same_collection",
- "collection_index",
- ob_collections[i].index);
- }
-
- UI_popup_menu_end(C, pup);
- return changed; /* The operator already handle this! */
-}
-
static bool select_grouped_index_object(bContext *C, Object *ob)
{
bool changed = false;
@@ -841,9 +785,6 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
case OBJECT_GRPSEL_COLLECTION:
changed |= select_grouped_collection(C, ob);
break;
- case OBJECT_GRPSEL_GROUP:
- changed |= select_grouped_group(C, ob);
- break;
case OBJECT_GRPSEL_HOOK:
changed |= select_grouped_object_hooks(C, ob);
break;
@@ -960,28 +901,28 @@ void OBJECT_OT_select_all(wmOperatorType *ot)
WM_operator_properties_select_all(ot);
}
-/**************************** Select In The Same Group ****************************/
+/**************************** Select In The Same Collection ****************************/
-static int object_select_same_group_exec(bContext *C, wmOperator *op)
+static int object_select_same_collection_exec(bContext *C, wmOperator *op)
{
- Group *group;
- char group_name[MAX_ID_NAME];
+ Collection *collection;
+ char collection_name[MAX_ID_NAME];
/* passthrough if no objects are visible */
if (CTX_DATA_COUNT(C, visible_bases) == 0) return OPERATOR_PASS_THROUGH;
- RNA_string_get(op->ptr, "group", group_name);
+ RNA_string_get(op->ptr, "collection", collection_name);
- group = (Group *)BKE_libblock_find_name(ID_GR, group_name);
+ collection = (Collection *)BKE_libblock_find_name(ID_GR, collection_name);
- if (!group) {
+ if (!collection) {
return OPERATOR_PASS_THROUGH;
}
CTX_DATA_BEGIN (C, Base *, base, visible_bases)
{
if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
- if (BKE_group_object_exists(group, base->object)) {
+ if (BKE_collection_has_object(collection, base->object)) {
ED_object_base_select(base, BA_SELECT);
}
}
@@ -993,67 +934,24 @@ static int object_select_same_group_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void OBJECT_OT_select_same_group(wmOperatorType *ot)
-{
-
- /* identifiers */
- ot->name = "Select Same Group";
- ot->description = "Select object in the same group";
- ot->idname = "OBJECT_OT_select_same_group";
-
- /* api callbacks */
- ot->exec = object_select_same_group_exec;
- ot->poll = objects_selectable_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_string(ot->srna, "group", NULL, MAX_ID_NAME, "Group", "Name of the group to select");
-}
-
-/**************************** Select In The Same Collection ****************************/
-
-static int object_select_same_collection_exec(bContext *C, wmOperator *op)
-{
- SceneCollection *collection;
-
- /* passthrough if no objects are visible */
- if (CTX_DATA_COUNT(C, visible_bases) == 0) return OPERATOR_PASS_THROUGH;
-
- int collection_index = RNA_int_get(op->ptr, "collection_index");
- collection = BKE_collection_from_index(CTX_data_scene(C), collection_index);
-
- if (!collection) {
- return OPERATOR_PASS_THROUGH;
- }
-
- if (BKE_collection_objects_select(CTX_data_view_layer(C), collection)) {
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
- }
-
- return OPERATOR_FINISHED;
-}
-
void OBJECT_OT_select_same_collection(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
+
/* identifiers */
ot->name = "Select Same Collection";
ot->description = "Select object in the same collection";
ot->idname = "OBJECT_OT_select_same_collection";
-
+
/* api callbacks */
ot->exec = object_select_same_collection_exec;
ot->poll = objects_selectable_poll;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_int(ot->srna, "collection_index", -1, -1, INT_MAX,
- "Collection Index", "Index of the collection to select", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_string(ot->srna, "collection", NULL, MAX_ID_NAME, "Collection", "Name of the collection to select");
}
+
/**************************** Select Mirror ****************************/
static int object_select_mirror_exec(bContext *C, wmOperator *op)
{
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index a862ef718d2..6b22521eedd 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -879,7 +879,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
if (ob->data == NULL) {
/* special support for dupligroups */
- if ((ob->transflag & OB_DUPLIGROUP) && ob->dup_group && (ob->dup_group->id.tag & LIB_TAG_DOIT) == 0) {
+ if ((ob->transflag & OB_DUPLICOLLECTION) && ob->dup_group && (ob->dup_group->id.tag & LIB_TAG_DOIT) == 0) {
if (ID_IS_LINKED(ob->dup_group)) {
tot_lib_error++;
}
@@ -1088,7 +1088,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
if ((ob_other->flag & OB_DONE) == 0 &&
((ob->data && (ob->data == ob_other->data)) ||
(ob->dup_group == ob_other->dup_group &&
- (ob->transflag | ob_other->transflag) & OB_DUPLIGROUP)))
+ (ob->transflag | ob_other->transflag) & OB_DUPLICOLLECTION)))
{
ob_other->flag |= OB_DONE;
DEG_id_tag_update(&ob_other->id, OB_RECALC_OB | OB_RECALC_DATA);
diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c
index 3bcc047bf5b..f62b72679d0 100644
--- a/source/blender/editors/physics/rigidbody_constraint.c
+++ b/source/blender/editors/physics/rigidbody_constraint.c
@@ -37,8 +37,8 @@
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_group.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_rigidbody.h"
@@ -83,14 +83,14 @@ bool ED_rigidbody_constraint_add(Main *bmain, Scene *scene, Object *ob, int type
}
/* create constraint group if it doesn't already exits */
if (rbw->constraints == NULL) {
- rbw->constraints = BKE_group_add(bmain, "RigidBodyConstraints");
+ rbw->constraints = BKE_collection_add(bmain, NULL, "RigidBodyConstraints");
}
/* make rigidbody constraint settings */
ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, type);
ob->rigidbody_constraint->flag |= RBC_FLAG_NEEDS_VALIDATE;
/* add constraint to rigid body constraint group */
- BKE_group_object_add(rbw->constraints, ob);
+ BKE_collection_object_add(bmain, rbw->constraints, ob);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
@@ -103,7 +103,7 @@ void ED_rigidbody_constraint_remove(Main *bmain, Scene *scene, Object *ob)
BKE_rigidbody_remove_constraint(scene, ob);
if (rbw)
- BKE_group_object_unlink(rbw->constraints, ob);
+ BKE_collection_object_remove(bmain, rbw->constraints, ob, false);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
index 3553ffa5033..99976898ac1 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -42,8 +42,8 @@
#include "BLT_translation.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_group.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_rigidbody.h"
@@ -109,7 +109,7 @@ bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, Re
scene->rigidbody_world = rbw;
}
if (rbw->group == NULL) {
- rbw->group = BKE_group_add(bmain, "RigidBodyWorld");
+ rbw->group = BKE_collection_add(bmain, NULL, "RigidBodyWorld");
}
/* make rigidbody object settings */
@@ -120,7 +120,7 @@ bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, Re
ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_VALIDATE;
/* add object to rigid body group */
- BKE_group_object_add(rbw->group, ob);
+ BKE_collection_object_add(bmain, rbw->group, ob);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
@@ -134,7 +134,7 @@ void ED_rigidbody_object_remove(Main *bmain, Scene *scene, Object *ob)
BKE_rigidbody_remove_object(scene, ob);
if (rbw)
- BKE_group_object_unlink(rbw->group, ob);
+ BKE_collection_object_remove(bmain, rbw->group, ob, false);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index d0390985181..946da6f1ed8 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -51,6 +51,7 @@
#include "DNA_world_types.h"
#include "DNA_camera_types.h"
+#include "DNA_group_types.h"
#include "DNA_material_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
@@ -252,7 +253,7 @@ static Scene *preview_get_scene(Main *pr_main)
return pr_main->scene.first;
}
-static const char *preview_layer_name(const char pr_type)
+static const char *preview_collection_name(const char pr_type)
{
switch (pr_type) {
case MA_FLAT:
@@ -281,19 +282,21 @@ static const char *preview_layer_name(const char pr_type)
}
}
-static void set_preview_layer(ViewLayer *view_layer, char pr_type)
+static void set_preview_collection(Scene *scene, ViewLayer *view_layer, char pr_type)
{
- LayerCollection *lc;
- const char *collection_name = preview_layer_name(pr_type);
+ LayerCollection *lc = view_layer->layer_collections.first;
+ const char *collection_name = preview_collection_name(pr_type);
- for (lc = view_layer->layer_collections.first; lc; lc = lc->next) {
- if (STREQ(lc->scene_collection->name, collection_name)) {
- lc->flag = COLLECTION_VIEWPORT | COLLECTION_RENDER;
+ for (lc = lc->layer_collections.first; lc; lc = lc->next) {
+ if (STREQ(lc->collection->id.name + 2, collection_name)) {
+ lc->collection->flag &= ~COLLECTION_RESTRICT_RENDER;
}
else {
- lc->flag = COLLECTION_DISABLED;
+ lc->collection->flag |= COLLECTION_RESTRICT_RENDER;
}
}
+
+ BKE_layer_collection_sync(scene, view_layer);
}
static World *preview_get_localized_world(ShaderPreview *sp, World *world)
@@ -389,10 +392,10 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
}
if (sp->pr_method == PR_ICON_RENDER) {
- set_preview_layer(view_layer, MA_SPHERE_A);
+ set_preview_collection(sce, view_layer, MA_SPHERE_A);
}
else {
- set_preview_layer(view_layer, mat->pr_type);
+ set_preview_collection(sce, view_layer, mat->pr_type);
if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
@@ -433,7 +436,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
sp->texcopy = tex;
BLI_addtail(&pr_main->tex, tex);
}
- set_preview_layer(view_layer, MA_TEXTURE);
+ set_preview_collection(sce, view_layer, MA_TEXTURE);
if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
@@ -451,7 +454,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
BLI_addtail(&pr_main->lamp, la);
}
- set_preview_layer(view_layer, MA_LAMP);
+ set_preview_collection(sce, view_layer, MA_LAMP);
if (sce->world) {
/* Only use lighting from the lamp. */
@@ -483,7 +486,7 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
BLI_addtail(&pr_main->world, wrld);
}
- set_preview_layer(view_layer, MA_SKY);
+ set_preview_collection(sce, view_layer, MA_SKY);
sce->world = wrld;
if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {
diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c
index 5353c250d1e..2a0be4eaf0d 100644
--- a/source/blender/editors/space_action/space_action.c
+++ b/source/blender/editors/space_action/space_action.c
@@ -776,7 +776,7 @@ static void action_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, I
}
if ((ID *)sact->ads.filter_grp == old_id) {
- sact->ads.filter_grp = (Group *)new_id;
+ sact->ads.filter_grp = (Collection *)new_id;
}
if ((ID *)sact->ads.source == old_id) {
sact->ads.source = new_id;
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 6793f0a0195..207e08c9a44 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -191,40 +191,6 @@ static int buttons_context_path_workspace(ButsContextPath *path)
return RNA_struct_is_a(ptr->type, &RNA_WorkSpace);
}
-static int buttons_context_path_collection(ButsContextPath *path, eSpaceButtons_Collection_Context collection_context)
-{
- PointerRNA *ptr = &path->ptr[path->len - 1];
-
- /* if we already have a (pinned) Collection, we're done */
- if (RNA_struct_is_a(ptr->type, &RNA_LayerCollection)) {
- return 1;
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_ViewLayer)) {
- ViewLayer *view_layer = ptr->data;
-
- if (collection_context == SB_COLLECTION_CTX_GROUP) {
- Object *ob = OBACT(view_layer);
- if (ob && ob->dup_group) {
- view_layer = ob->dup_group->view_layer;
-
- /* Replace the view layer by the group in the context path. */
- RNA_pointer_create(NULL, &RNA_Group, ob->dup_group, &path->ptr[path->len - 1]);
- }
- }
-
- LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
-
- if (layer_collection) {
- RNA_pointer_create(NULL, &RNA_LayerCollection, layer_collection, &path->ptr[path->len]);
- path->len++;
- return 1;
- }
- }
-
- /* no path to a collection possible */
- return 0;
-}
-
static int buttons_context_path_object(ButsContextPath *path)
{
PointerRNA *ptr = &path->ptr[path->len - 1];
@@ -562,9 +528,6 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma
case BCONTEXT_WORKSPACE:
found = buttons_context_path_workspace(path);
break;
- case BCONTEXT_COLLECTION:
- found = buttons_context_path_collection(path, sbuts->collection_context);
- break;
case BCONTEXT_OBJECT:
case BCONTEXT_PHYSICS:
case BCONTEXT_CONSTRAINT:
@@ -982,10 +945,6 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
set_pointer_type(path, result, &RNA_FreestyleLineStyle);
return 1;
}
- else if (CTX_data_equals(member, "collection")) {
- set_pointer_type(path, result, &RNA_LayerCollection);
- return 1;
- }
else {
return 0; /* not found */
}
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index 6ad5ed40f74..05304ecbf94 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -156,8 +156,6 @@ static void buttons_main_region_draw(const bContext *C, ARegion *ar)
ED_region_panels(C, ar, "world", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_WORKSPACE)
ED_region_panels(C, ar, "workspace", sbuts->mainb, vertical);
- else if (sbuts->mainb == BCONTEXT_COLLECTION)
- ED_region_panels(C, ar, "collection", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_OBJECT)
ED_region_panels(C, ar, "object", sbuts->mainb, vertical);
else if (sbuts->mainb == BCONTEXT_DATA)
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index ff144fec778..8d3647def9e 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -755,7 +755,7 @@ static void graph_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID
if (sgraph->ads) {
if ((ID *)sgraph->ads->filter_grp == old_id) {
- sgraph->ads->filter_grp = (Group *)new_id;
+ sgraph->ads->filter_grp = (Collection *)new_id;
}
if ((ID *)sgraph->ads->source == old_id) {
sgraph->ads->source = new_id;
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index c7d4fa1465b..dfcf5fd5d8d 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -37,6 +37,7 @@
#include "DNA_meta_types.h"
#include "DNA_scene_types.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
@@ -271,36 +272,26 @@ static void stats_object_sculpt_dynamic_topology(Object *ob, SceneStats *stats)
stats->tottri = ob->sculpt->bm->totface;
}
-static void stats_dupli_object_group_count(SceneCollection *scene_collection, int *count)
+static void stats_dupli_object_group_count(Collection *collection, int *count)
{
- for (LinkData *link = scene_collection->objects.first; link; link = link->next) {
- (*count)++;
- }
+ *count += BLI_listbase_count(&collection->gobject);
- SceneCollection *scene_collection_nested;
- for (scene_collection_nested = scene_collection->scene_collections.first;
- scene_collection_nested;
- scene_collection_nested = scene_collection_nested->next)
- {
- stats_dupli_object_group_count(scene_collection_nested, count);
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ stats_dupli_object_group_count(child->collection, count);
}
}
-static void stats_dupli_object_group_doit(SceneCollection *scene_collection, SceneStats *stats, ParticleSystem *psys,
+static void stats_dupli_object_group_doit(Collection *collection, SceneStats *stats, ParticleSystem *psys,
const int totgroup, int *cur)
{
- for (LinkData *link = scene_collection->objects.first; link; link = link->next) {
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
int tot = count_particles_mod(psys, totgroup, *cur);
- stats_object(link->data, 0, tot, stats);
+ stats_object(cob->ob, 0, tot, stats);
(*cur)++;
}
- SceneCollection *scene_collection_nested;
- for (scene_collection_nested = scene_collection->scene_collections.first;
- scene_collection_nested;
- scene_collection_nested = scene_collection_nested->next)
- {
- stats_dupli_object_group_doit(scene_collection_nested, stats, psys, totgroup, cur);
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ stats_dupli_object_group_doit(child->collection, stats, psys, totgroup, cur);
}
}
@@ -323,9 +314,9 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
else if (part->draw_as == PART_DRAW_GR && part->dup_group) {
int totgroup = 0, cur = 0;
- SceneCollection *scene_collection = part->dup_group->collection;
- stats_dupli_object_group_count(scene_collection, &totgroup);
- stats_dupli_object_group_doit(scene_collection, stats, psys, totgroup, &cur);
+ Collection *collection = part->dup_group;
+ stats_dupli_object_group_count(collection, &totgroup);
+ stats_dupli_object_group_doit(collection, stats, psys, totgroup, &cur);
}
}
@@ -353,7 +344,7 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
stats->totobj += tot;
stats_object(ob, base->flag & BASE_SELECTED, tot, stats);
}
- else if ((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) {
+ else if ((ob->transflag & OB_DUPLICOLLECTION) && ob->dup_group) {
/* Dupli Group */
int tot = count_duplilist(ob);
stats->totobj += tot;
diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c
index 222fb6d8fbd..7245fd9c17f 100644
--- a/source/blender/editors/space_nla/space_nla.c
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -571,7 +571,7 @@ static void nla_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *
if (snla->ads) {
if ((ID *)snla->ads->filter_grp == old_id) {
- snla->ads->filter_grp = (Group *)new_id;
+ snla->ads->filter_grp = (Collection *)new_id;
}
if ((ID *)snla->ads->source == old_id) {
snla->ads->source = new_id;
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index 4ea2c243365..9bb3871c247 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -24,9 +24,14 @@
* \ingroup spoutliner
*/
+#include <string.h>
+
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
+#include "DNA_group_types.h"
+#include "DNA_object_types.h"
+
#include "BKE_context.h"
#include "BKE_collection.h"
#include "BKE_layer.h"
@@ -36,9 +41,7 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
-#include "DNA_group_types.h"
-#include "DNA_object_types.h"
-
+#include "ED_object.h"
#include "ED_screen.h"
#include "WM_api.h"
@@ -52,26 +55,44 @@
#include "outliner_intern.h" /* own include */
-/* Prototypes. */
-static int collection_delete_exec(struct bContext *C, struct wmOperator *op);
-
/* -------------------------------------------------------------------- */
-static LayerCollection *outliner_collection_active(bContext *C)
+bool outliner_is_collection_tree_element(const TreeElement *te)
{
- return CTX_data_layer_collection(C);
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (!tselem) {
+ return false;
+ }
+
+ if (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
+ return true;
+ }
+ else if (tselem->type == 0 && te->idcode == ID_GR) {
+ return true;
+ }
+
+ return false;
}
-SceneCollection *outliner_scene_collection_from_tree_element(TreeElement *te)
+Collection *outliner_collection_from_tree_element(const TreeElement *te)
{
TreeStoreElem *tselem = TREESTORE(te);
- if (tselem->type == TSE_SCENE_COLLECTION) {
- return te->directdata;
+ if (!tselem) {
+ return false;
}
- else if (tselem->type == TSE_LAYER_COLLECTION) {
+
+ if (tselem->type == TSE_LAYER_COLLECTION) {
LayerCollection *lc = te->directdata;
- return lc->scene_collection;
+ return lc->collection;
+ }
+ else if (ELEM(tselem->type, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
+ Scene *scene = (Scene*)tselem->id;
+ return BKE_collection_master(scene);
+ }
+ else if (tselem->type == 0 && te->idcode == ID_GR) {
+ return (Collection*)tselem->id;
}
return NULL;
@@ -83,956 +104,593 @@ SceneCollection *outliner_scene_collection_from_tree_element(TreeElement *te)
static int collections_editor_poll(bContext *C)
{
SpaceOops *so = CTX_wm_space_outliner(C);
- return (so != NULL) && (so->outlinevis == SO_COLLECTIONS);
+ return (so != NULL) && ELEM(so->outlinevis, SO_VIEW_LAYER, SO_SCENES);
}
-static int outliner_objects_collection_poll(bContext *C)
-{
- SpaceOops *so = CTX_wm_space_outliner(C);
- if (so == NULL) {
- return 0;
- }
-
- /* Groups don't support filtering. */
- if ((so->outlinevis != SO_GROUPS) && (so->filter & SO_FILTER_NO_COLLECTION)) {
- return 0;
- }
+/********************************* New Collection ****************************/
- return ELEM(so->outlinevis, SO_COLLECTIONS, SO_GROUPS);
-}
-
-/* -------------------------------------------------------------------- */
-/* collection manager operators */
-
-/**
- * Recursively get the collection for a given index
- */
-static SceneCollection *scene_collection_from_index(ListBase *lb, const int number, int *i)
+struct CollectionNewData
{
- for (SceneCollection *sc = lb->first; sc; sc = sc->next) {
- if (*i == number) {
- return sc;
- }
+ bool error;
+ Collection *collection;
+};
- (*i)++;
+static TreeTraversalAction collection_find_selected_to_add(TreeElement *te, void *customdata)
+{
+ struct CollectionNewData *data = customdata;
+ Collection *collection = outliner_collection_from_tree_element(te);
- SceneCollection *sc_nested = scene_collection_from_index(&sc->scene_collections, number, i);
- if (sc_nested) {
- return sc_nested;
- }
+ if (!collection) {
+ return TRAVERSE_SKIP_CHILDS;
}
- return NULL;
-}
-typedef struct TreeElementFindData {
- SceneCollection *collection;
- TreeElement *r_result_te;
-} TreeElementFindData;
-
-static TreeTraversalAction tree_element_find_by_scene_collection_cb(TreeElement *te, void *customdata)
-{
- TreeElementFindData *data = customdata;
- const SceneCollection *current_element_sc = outliner_scene_collection_from_tree_element(te);
-
- if (current_element_sc == data->collection) {
- data->r_result_te = te;
+ if (data->collection != NULL) {
+ data->error = true;
return TRAVERSE_BREAK;
}
+ data->collection = collection;
return TRAVERSE_CONTINUE;
}
-static TreeElement *outliner_tree_element_from_layer_collection_index(
- SpaceOops *soops, ViewLayer *view_layer,
- const int index)
+static int collection_new_exec(bContext *C, wmOperator *op)
{
- LayerCollection *lc = BKE_layer_collection_from_index(view_layer, index);
-
- if (lc == NULL) {
- return NULL;
- }
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
- /* Find the tree element containing the LayerCollection's scene_collection. */
- TreeElementFindData data = {
- .collection = lc->scene_collection,
- .r_result_te = NULL,
+ struct CollectionNewData data = {
+ .error = false,
+ .collection = NULL,
};
- outliner_tree_traverse(soops, &soops->tree, 0, 0, tree_element_find_by_scene_collection_cb, &data);
-
- return data.r_result_te;
-}
-static int collection_link_exec(bContext *C, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- SceneCollection *sc_master = BKE_collection_master(&scene->id);
- SceneCollection *sc;
+ if (RNA_boolean_get(op->ptr, "nested")) {
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_selected_to_add, &data);
- int scene_collection_index = RNA_enum_get(op->ptr, "scene_collection");
- if (scene_collection_index == 0) {
- sc = sc_master;
- }
- else {
- int index = 1;
- sc = scene_collection_from_index(&sc_master->scene_collections, scene_collection_index, &index);
- BLI_assert(sc);
+ if (data.error) {
+ BKE_report(op->reports, RPT_ERROR, "More than one collection is selected");
+ return OPERATOR_CANCELLED;
+ }
}
- BKE_collection_link(view_layer, sc);
-
- DEG_relations_tag_update(CTX_data_main(C));
+ if (!data.collection && (soops->outlinevis == SO_VIEW_LAYER)) {
+ data.collection = BKE_collection_master(scene);
+ }
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&scene->id, 0);
+ BKE_collection_add(
+ bmain,
+ data.collection,
+ NULL);
+ outliner_cleanup_tree(soops);
+ DEG_relations_tag_update(bmain);
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
return OPERATOR_FINISHED;
}
-static int collection_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- Scene *scene = CTX_data_scene(C);
- SceneCollection *master_collection = BKE_collection_master(&scene->id);
- if (master_collection->scene_collections.first == NULL) {
- RNA_enum_set(op->ptr, "scene_collection", 0);
- return collection_link_exec(C, op);
- }
- else {
- return WM_enum_search_invoke(C, op, event);
- }
-}
-
-static void collection_scene_collection_itemf_recursive(
- EnumPropertyItem *tmp, EnumPropertyItem **item, int *totitem, int *value, SceneCollection *sc)
-{
- tmp->value = *value;
- tmp->icon = ICON_COLLAPSEMENU;
- tmp->identifier = sc->name;
- tmp->name = sc->name;
- RNA_enum_item_add(item, totitem, tmp);
-
- (*value)++;
-
- for (SceneCollection *ncs = sc->scene_collections.first; ncs; ncs = ncs->next) {
- collection_scene_collection_itemf_recursive(tmp, item, totitem, value, ncs);
- }
-}
-
-static const EnumPropertyItem *collection_scene_collection_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
-{
- EnumPropertyItem tmp = {0, "", 0, "", ""};
- EnumPropertyItem *item = NULL;
- int value = 0, totitem = 0;
-
- Scene *scene = CTX_data_scene(C);
- SceneCollection *sc = BKE_collection_master(&scene->id);
-
- collection_scene_collection_itemf_recursive(&tmp, &item, &totitem, &value, sc);
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
-}
-
-void OUTLINER_OT_collection_link(wmOperatorType *ot)
+void OUTLINER_OT_collection_new(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
/* identifiers */
- ot->name = "Link Collection";
- ot->idname = "OUTLINER_OT_collection_link";
- ot->description = "Link a new collection to the active layer";
+ ot->name = "New Collection";
+ ot->idname = "OUTLINER_OT_collection_new";
+ ot->description = "Add a new collection inside selected collection";
/* api callbacks */
- ot->exec = collection_link_exec;
- ot->invoke = collection_link_invoke;
+ ot->exec = collection_new_exec;
+ ot->poll = collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- prop = RNA_def_enum(ot->srna, "scene_collection", DummyRNA_NULL_items, 0, "Scene Collection", "");
- RNA_def_enum_funcs(prop, collection_scene_collection_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ /* properties */
+ PropertyRNA *prop = RNA_def_boolean(ot->srna, "nested", true, "Nested", "Add as child of selected collection");;
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/**
- * Returns true if selected element is a collection directly
- * linked to the active ViewLayer (not a nested collection)
- */
-static int collection_unlink_poll(bContext *C)
+/**************************** Delete Collection ******************************/
+
+struct CollectionEditData {
+ Scene *scene;
+ SpaceOops *soops;
+ GSet *collections_to_edit;
+};
+
+static TreeTraversalAction collection_find_data_to_edit(TreeElement *te, void *customdata)
{
- if (collections_editor_poll(C) == 0) {
- return 0;
- }
+ struct CollectionEditData *data = customdata;
+ Collection *collection = outliner_collection_from_tree_element(te);
- LayerCollection *lc = outliner_collection_active(C);
+ if (!collection) {
+ return TRAVERSE_SKIP_CHILDS;
+ }
- if (lc == NULL) {
- return 0;
+ if (collection == BKE_collection_master(data->scene)) {
+ /* skip - showing warning/error message might be missleading
+ * when deleting multiple collections, so just do nothing */
+ }
+ else {
+ /* Delete, duplicate and link don't edit children, those will come along
+ * with the parents. */
+ BLI_gset_add(data->collections_to_edit, collection);
+ return TRAVERSE_SKIP_CHILDS;
}
- ViewLayer *view_layer = CTX_data_view_layer(C);
- return BLI_findindex(&view_layer->layer_collections, lc) != -1 ? 1 : 0;
+ return TRAVERSE_CONTINUE;
}
-static int collection_unlink_exec(bContext *C, wmOperator *op)
+static int collection_delete_exec(bContext *C, wmOperator *op)
{
- LayerCollection *lc = outliner_collection_active(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
+ struct CollectionEditData data = {.scene = scene, .soops = soops};
+ bool hierarchy = RNA_boolean_get(op->ptr, "hierarchy");
- if (lc == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Active element is not a collection");
- return OPERATOR_CANCELLED;
- }
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- BKE_collection_unlink(view_layer, lc);
+ /* We first walk over and find the Collections we actually want to delete (ignoring duplicates). */
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_edit, &data);
- if (soops) {
- outliner_cleanup_tree(soops);
+ /* Effectively delete the collections. */
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
+ /* TODO: what if collection was child and got deleted in the meantime? */
+ Collection *collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+ BKE_collection_delete(bmain, collection, hierarchy);
}
- DEG_relations_tag_update(CTX_data_main(C));
+ BLI_gset_free(data.collections_to_edit, NULL);
+
+ DEG_relations_tag_update(bmain);
/* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&CTX_data_scene(C)->id, 0);
+ DEG_id_tag_update(&scene->id, 0);
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- return OPERATOR_FINISHED;
-}
-
-void OUTLINER_OT_collection_unlink(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Unlink Collection";
- ot->idname = "OUTLINER_OT_collection_unlink";
- ot->description = "Unlink collection from the active layer";
-
- /* api callbacks */
- ot->exec = collection_unlink_exec;
- ot->poll = collection_unlink_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/**********************************************************************************/
-/* Add new collection. */
-static int collection_new_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- SceneCollection *scene_collection_parent = BKE_collection_master(&scene->id);
- SceneCollection *scene_collection = BKE_collection_add(&scene->id, scene_collection_parent, COLLECTION_TYPE_NONE, NULL);
- BKE_collection_link(view_layer, scene_collection);
-
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
return OPERATOR_FINISHED;
}
-void OUTLINER_OT_collection_new(wmOperatorType *ot)
+void OUTLINER_OT_collection_delete(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "New Collection";
- ot->idname = "OUTLINER_OT_collection_new";
- ot->description = "Add a new collection to the scene";
+ ot->name = "Delete Collection";
+ ot->idname = "OUTLINER_OT_collection_delete";
+ ot->description = "Delete selected collections";
/* api callbacks */
- ot->exec = collection_new_exec;
+ ot->exec = collection_delete_exec;
+ ot->poll = collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ PropertyRNA *prop = RNA_def_boolean(ot->srna, "hierarchy", false, "Hierarchy", "Delete child objects and collections");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/**********************************************************************************/
-/* Add new nested collection. */
+/****************************** Select Objects *******************************/
-struct CollectionNewData
-{
+struct CollectionObjectsSelectData {
bool error;
- SceneCollection *scene_collection;
+ LayerCollection *layer_collection;
};
-static TreeTraversalAction collection_find_selected_to_add(TreeElement *te, void *customdata)
+static TreeTraversalAction outliner_find_first_selected_layer_collection(TreeElement *te, void *customdata)
{
- struct CollectionNewData *data = customdata;
- SceneCollection *scene_collection = outliner_scene_collection_from_tree_element(te);
-
- if (!scene_collection) {
- return TRAVERSE_SKIP_CHILDS;
- }
+ struct CollectionObjectsSelectData *data = customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
- if (data->scene_collection != NULL) {
- data->error = true;
- return TRAVERSE_BREAK;
+ switch (tselem->type) {
+ case TSE_LAYER_COLLECTION:
+ data->layer_collection = te->directdata;
+ return TRAVERSE_BREAK;
+ case TSE_R_LAYER:
+ case TSE_SCENE_COLLECTION_BASE:
+ case TSE_VIEW_COLLECTION_BASE:
+ return TRAVERSE_CONTINUE;
+ default:
+ return TRAVERSE_SKIP_CHILDS;
}
-
- data->scene_collection = scene_collection;
- return TRAVERSE_CONTINUE;
}
-static int collection_nested_new_exec(bContext *C, wmOperator *op)
+static LayerCollection *outliner_active_layer_collection(bContext *C)
{
SpaceOops *soops = CTX_wm_space_outliner(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- struct CollectionNewData data = {
- .error = false,
- .scene_collection = NULL,
+ struct CollectionObjectsSelectData data = {
+ .layer_collection = NULL,
};
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_selected_to_add, &data);
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_first_selected_layer_collection, &data);
+ return data.layer_collection;
+}
+
+static int collection_objects_select_exec(bContext *C, wmOperator *op)
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ LayerCollection *layer_collection = outliner_active_layer_collection(C);
+ bool deselect = STREQ(op->idname, "OUTLINER_OT_collection_objects_deselect");
- if (data.error) {
- BKE_report(op->reports, RPT_ERROR, "More than one collection is selected");
+ if (layer_collection == NULL) {
return OPERATOR_CANCELLED;
}
- BKE_collection_add(
- &scene->id,
- data.scene_collection,
- COLLECTION_TYPE_NONE,
- NULL);
+ BKE_layer_collection_objects_select(view_layer, layer_collection, deselect);
+ WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
- outliner_cleanup_tree(soops);
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
return OPERATOR_FINISHED;
}
-void OUTLINER_OT_collection_nested_new(wmOperatorType *ot)
+void OUTLINER_OT_collection_objects_select(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "New Nested Collection";
- ot->idname = "OUTLINER_OT_collection_nested_new";
- ot->description = "Add a new collection inside selected collection";
+ ot->name = "Select Objects";
+ ot->idname = "OUTLINER_OT_collection_objects_select";
+ ot->description = "Select objects in collection";
/* api callbacks */
- ot->exec = collection_nested_new_exec;
+ ot->exec = collection_objects_select_exec;
ot->poll = collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/**********************************************************************************/
-/* Delete selected collection. */
-
-void OUTLINER_OT_collection_delete_selected(wmOperatorType *ot)
+void OUTLINER_OT_collection_objects_deselect(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Delete Selected Collections";
- ot->idname = "OUTLINER_OT_collection_delete_selected";
- ot->description = "Delete all the selected collections";
+ ot->name = "Deselect Objects";
+ ot->idname = "OUTLINER_OT_collection_objects_deselect";
+ ot->description = "Deselect objects in collection";
/* api callbacks */
- ot->exec = collection_delete_exec;
+ ot->exec = collection_objects_select_exec;
ot->poll = collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/**********************************************************************************/
-/* Add new selected objects. */
+/************************** Duplicate Collection *****************************/
-struct SceneCollectionSelectedData {
- ListBase scene_collections_array;
+struct CollectionDuplicateData {
+ TreeElement *te;
};
-static TreeTraversalAction collection_find_selected_scene_collections(TreeElement *te, void *customdata)
+static TreeTraversalAction outliner_find_first_selected_collection(TreeElement *te, void *customdata)
{
- struct SceneCollectionSelectedData *data = customdata;
- SceneCollection *scene_collection = outliner_scene_collection_from_tree_element(te);
+ struct CollectionDuplicateData *data = customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
- if (!scene_collection) {
- return TRAVERSE_SKIP_CHILDS;
+ switch (tselem->type) {
+ case TSE_LAYER_COLLECTION:
+ data->te = te;
+ return TRAVERSE_BREAK;
+ case TSE_R_LAYER:
+ case TSE_SCENE_COLLECTION_BASE:
+ case TSE_VIEW_COLLECTION_BASE:
+ default:
+ return TRAVERSE_CONTINUE;
}
-
- BLI_addtail(&data->scene_collections_array, BLI_genericNodeN(scene_collection));
- return TRAVERSE_CONTINUE;
}
-static int collection_objects_add_exec(bContext *C, wmOperator *op)
+static TreeElement *outliner_active_collection(bContext *C)
{
SpaceOops *soops = CTX_wm_space_outliner(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- struct SceneCollectionSelectedData data = {
- .scene_collections_array = {NULL, NULL},
+ struct CollectionDuplicateData data = {
+ .te = NULL,
};
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_selected_scene_collections, &data);
-
- if (BLI_listbase_is_empty(&data.scene_collections_array)) {
- BKE_report(op->reports, RPT_ERROR, "No collection is selected");
- return OPERATOR_CANCELLED;
- }
-
- CTX_DATA_BEGIN (C, struct Object *, ob, selected_objects)
- {
- LISTBASE_FOREACH (LinkData *, link, &data.scene_collections_array) {
- SceneCollection *scene_collection = link->data;
- BKE_collection_object_add(
- &scene->id,
- scene_collection,
- ob);
- }
- }
- CTX_DATA_END;
- BLI_freelistN(&data.scene_collections_array);
-
- outliner_cleanup_tree(soops);
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- return OPERATOR_FINISHED;
-}
-
-void OUTLINER_OT_collection_objects_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Objects";
- ot->idname = "OUTLINER_OT_collection_objects_add";
- ot->description = "Add selected objects to collection";
-
- /* api callbacks */
- ot->exec = collection_objects_add_exec;
- ot->poll = collections_editor_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_first_selected_collection, &data);
+ return data.te;
}
-/**********************************************************************************/
-/* Remove selected objects. */
-
-
-static int collection_objects_remove_exec(bContext *C, wmOperator *op)
+static int collection_duplicate_exec(bContext *C, wmOperator *op)
{
- SpaceOops *soops = CTX_wm_space_outliner(C);
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
-
- struct SceneCollectionSelectedData data = {
- .scene_collections_array = {NULL, NULL},
- };
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ TreeElement *te = outliner_active_collection(C);
+ BLI_assert(te != NULL);
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_selected_scene_collections, &data);
+ Collection *collection = outliner_collection_from_tree_element(te);
+ Collection *parent = (te->parent) ? outliner_collection_from_tree_element(te->parent) : NULL;
- if (BLI_listbase_is_empty(&data.scene_collections_array)) {
- BKE_report(op->reports, RPT_ERROR, "No collection is selected");
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ BKE_report(op->reports, RPT_ERROR, "Can't duplicate the master collection");
return OPERATOR_CANCELLED;
}
- CTX_DATA_BEGIN (C, struct Object *, ob, selected_objects)
- {
- LISTBASE_FOREACH (LinkData *, link, &data.scene_collections_array) {
- SceneCollection *scene_collection = link->data;
- BKE_collection_object_remove(
- bmain,
- &scene->id,
- scene_collection,
- ob,
- true);
- }
+ switch (soops->outlinevis) {
+ case SO_SCENES:
+ case SO_VIEW_LAYER:
+ case SO_LIBRARIES:
+ BKE_collection_copy(bmain, parent, collection);
+ break;
}
- CTX_DATA_END;
- BLI_freelistN(&data.scene_collections_array);
- outliner_cleanup_tree(soops);
DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, CTX_data_scene(C));
+
return OPERATOR_FINISHED;
}
-void OUTLINER_OT_collection_objects_remove(wmOperatorType *ot)
+void OUTLINER_OT_collection_duplicate(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Remove Objects";
- ot->idname = "OUTLINER_OT_collection_objects_remove";
- ot->description = "Remove selected objects from collection";
+ ot->name = "Duplicate Collection";
+ ot->idname = "OUTLINER_OT_collection_duplicate";
+ ot->description = "Duplicate selected collections";
/* api callbacks */
- ot->exec = collection_objects_remove_exec;
+ ot->exec = collection_duplicate_exec;
ot->poll = collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static TreeElement *outliner_collection_parent_element_get(TreeElement *te)
-{
- TreeElement *te_parent = te;
- while ((te_parent = te_parent->parent)) {
- if (outliner_scene_collection_from_tree_element(te->parent)) {
- return te_parent;
- }
- }
- return NULL;
-}
+/**************************** Link Collection ******************************/
-static int object_collection_remove_exec(bContext *C, wmOperator *UNUSED(op))
+static int collection_link_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceOops *soops = CTX_wm_space_outliner(C);
Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Collection *active_collection = CTX_data_layer_collection(C)->collection;
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ struct CollectionEditData data = {.scene = scene, .soops = soops};
- struct ObjectsSelectedData data = {
- .objects_selected_array = {NULL, NULL},
- };
-
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &data);
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
- LISTBASE_FOREACH (LinkData *, link, &data.objects_selected_array) {
- TreeElement *te = (TreeElement *)link->data;
- Object *ob = (Object *)TREESTORE(te)->id;
- SceneCollection *scene_collection = NULL;
+ /* We first walk over and find the Collections we actually want to link (ignoring duplicates). */
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_edit, &data);
- TreeElement *te_parent = outliner_collection_parent_element_get(te);
- if (te_parent != NULL) {
- scene_collection = outliner_scene_collection_from_tree_element(te_parent);
- ID *owner_id = TREESTORE(te_parent)->id;
- BKE_collection_object_remove(bmain, owner_id, scene_collection, ob, true);
- DEG_id_tag_update(owner_id, DEG_TAG_BASE_FLAGS_UPDATE);
- }
+ /* Effectively link the collections. */
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
+ Collection *collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+ BKE_collection_child_add(bmain, active_collection, collection);
+ id_fake_user_clear(&collection->id);
}
- BLI_freelistN(&data.objects_selected_array);
+ BLI_gset_free(data.collections_to_edit, NULL);
- outliner_cleanup_tree(soops);
DEG_relations_tag_update(bmain);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(&scene->id, 0);
+
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- WM_main_add_notifier(NC_SCENE | ND_OB_ACTIVE, NULL);
- WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, NULL);
return OPERATOR_FINISHED;
}
-void OUTLINER_OT_object_remove_from_collection(wmOperatorType *ot)
+void OUTLINER_OT_collection_link(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Remove Object from Collection";
- ot->idname = "OUTLINER_OT_object_remove_from_collection";
- ot->description = "Remove selected objects from their respective collection";
+ ot->name = "Link Collection";
+ ot->idname = "OUTLINER_OT_collection_link";
+ ot->description = "Link selected collections to active scene";
/* api callbacks */
- ot->exec = object_collection_remove_exec;
- ot->poll = outliner_objects_collection_poll;
+ ot->exec = collection_link_exec;
+ ot->poll = collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static int object_add_to_new_collection_exec(bContext *C, wmOperator *op)
-{
- int operator_result = OPERATOR_CANCELLED;
+/************************** Instance Collection ******************************/
- SpaceOops *soops = CTX_wm_space_outliner(C);
+static int collection_instance_exec(bContext *C, wmOperator *UNUSED(op))
+{
Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ struct CollectionEditData data = {.scene = scene, .soops = soops};
- SceneCollection *scene_collection_parent, *scene_collection_new;
- TreeElement *te_active, *te_parent;
-
- struct ObjectsSelectedData data = {{NULL}}, active = {{NULL}};
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_HIGHLIGHTED, outliner_find_selected_objects, &active);
- if (BLI_listbase_is_empty(&active.objects_selected_array)) {
- BKE_report(op->reports, RPT_ERROR, "No object is selected");
- goto cleanup;
- }
+ /* We first walk over and find the Collections we actually want to instance (ignoring duplicates). */
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_edit, &data);
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &data);
- if (BLI_listbase_is_empty(&data.objects_selected_array)) {
- BKE_report(op->reports, RPT_ERROR, "No objects are selected");
- goto cleanup;
- }
+ /* Find an active collection to add to, that doesn't give dependency cycles. */
+ LayerCollection *active_lc = BKE_layer_collection_get_active(view_layer);
- /* Heuristic to get the "active" / "last object" */
- te_active = ((LinkData *)active.objects_selected_array.first)->data;
- te_parent = outliner_collection_parent_element_get(te_active);
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
+ Collection *collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
- if (te_parent == NULL) {
- BKE_reportf(op->reports, RPT_ERROR, "Couldn't find collection of \"%s\" object", te_active->name);
- goto cleanup;
+ while (BKE_collection_find_cycle(active_lc->collection, collection)) {
+ active_lc = BKE_layer_collection_activate_parent(view_layer, active_lc);
+ }
}
- ID *owner_id = TREESTORE(te_parent)->id;
- scene_collection_parent = outliner_scene_collection_from_tree_element(te_parent);
- scene_collection_new = BKE_collection_add(owner_id, scene_collection_parent, scene_collection_parent->type, NULL);
-
- LISTBASE_FOREACH (LinkData *, link, &data.objects_selected_array) {
- TreeElement *te = (TreeElement *)link->data;
- Object *ob = (Object *)TREESTORE(te)->id;
- BKE_collection_object_add(owner_id, scene_collection_new, ob);
+ /* Effectively instance the collections. */
+ GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
+ Collection *collection = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+ Object *ob = ED_object_add_type(C, OB_EMPTY, collection->id.name + 2, scene->cursor.location, NULL, false, scene->layact);
+ ob->dup_group = collection;
+ ob->transflag |= OB_DUPLICOLLECTION;
+ id_lib_extern(&collection->id);
}
- outliner_cleanup_tree(soops);
+ BLI_gset_free(data.collections_to_edit, NULL);
+
DEG_relations_tag_update(bmain);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(&scene->id, 0);
+
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- operator_result = OPERATOR_FINISHED;
-cleanup:
- BLI_freelistN(&active.objects_selected_array);
- BLI_freelistN(&data.objects_selected_array);
- return operator_result;
+ return OPERATOR_FINISHED;
}
-void OUTLINER_OT_object_add_to_new_collection(wmOperatorType *ot)
+void OUTLINER_OT_collection_instance(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Add Objects to New Collection";
- ot->idname = "OUTLINER_OT_object_add_to_new_collection";
- ot->description = "Add objects to a new collection";
+ ot->name = "Instance Collection";
+ ot->idname = "OUTLINER_OT_collection_instance";
+ ot->description = "Instance selected collections to active scene";
/* api callbacks */
- ot->exec = object_add_to_new_collection_exec;
- ot->poll = outliner_objects_collection_poll;
+ ot->exec = collection_instance_exec;
+ ot->poll = collections_editor_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-struct CollectionDeleteData {
- Scene *scene;
- SpaceOops *soops;
- GSet *collections_to_delete;
-};
+/************************** Exclude Collection ******************************/
-static TreeTraversalAction collection_find_data_to_delete(TreeElement *te, void *customdata)
+static TreeTraversalAction layer_collection_find_data_to_edit(TreeElement *te, void *customdata)
{
- struct CollectionDeleteData *data = customdata;
- SceneCollection *scene_collection = outliner_scene_collection_from_tree_element(te);
+ struct CollectionEditData *data = customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
- if (!scene_collection) {
- return TRAVERSE_SKIP_CHILDS;
+ if (!(tselem && tselem->type == TSE_LAYER_COLLECTION)) {
+ return TRAVERSE_CONTINUE;
}
- if (scene_collection == BKE_collection_master(&data->scene->id)) {
+ LayerCollection *lc = te->directdata;
+
+ if (lc->collection->flag & COLLECTION_IS_MASTER) {
/* skip - showing warning/error message might be missleading
* when deleting multiple collections, so just do nothing */
}
else {
- BLI_gset_add(data->collections_to_delete, scene_collection);
- return TRAVERSE_SKIP_CHILDS; /* Childs will be gone anyway, no need to recurse deeper. */
+ /* Delete, duplicate and link don't edit children, those will come along
+ * with the parents. */
+ BLI_gset_add(data->collections_to_edit, lc);
}
return TRAVERSE_CONTINUE;
}
-static TreeTraversalAction collection_delete_elements_from_collection(TreeElement *te, void *customdata)
+static int collections_view_layer_poll(bContext *C, bool include)
{
- struct CollectionDeleteData *data = customdata;
- SceneCollection *scene_collection = outliner_scene_collection_from_tree_element(te);
-
- if (!scene_collection) {
- return TRAVERSE_SKIP_CHILDS;
- }
-
- const bool will_be_deleted = BLI_gset_haskey(data->collections_to_delete, scene_collection);
- if (will_be_deleted) {
- outliner_free_tree_element(te, te->parent ? &te->parent->subtree : &data->soops->tree);
- /* Childs are freed now, so don't recurse into them. */
- return TRAVERSE_SKIP_CHILDS;
+ /* Poll function so the right click menu show current state of selected collections. */
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ if (!(soops && soops->outlinevis == SO_VIEW_LAYER)) {
+ return false;
}
- return TRAVERSE_CONTINUE;
-}
-
-static int collection_delete_exec(bContext *C, wmOperator *UNUSED(op))
-{
Scene *scene = CTX_data_scene(C);
- SpaceOops *soops = CTX_wm_space_outliner(C);
- struct CollectionDeleteData data = {.scene = scene, .soops = soops};
-
- data.collections_to_delete = BLI_gset_ptr_new(__func__);
-
- /* We first walk over and find the SceneCollections we actually want to delete (ignoring duplicates). */
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_delete, &data);
-
- /* Now, delete all tree elements representing a collection that will be deleted. We'll look for a
- * new element to select in a few lines, so we can't wait until the tree is recreated on redraw. */
- outliner_tree_traverse(soops, &soops->tree, 0, 0, collection_delete_elements_from_collection, &data);
+ struct CollectionEditData data = {.scene = scene, .soops = soops};
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
+ bool result = false;
- /* Effectively delete the collections. */
- GSetIterator collections_to_delete_iter;
- GSET_ITER(collections_to_delete_iter, data.collections_to_delete) {
- SceneCollection *sc = BLI_gsetIterator_getKey(&collections_to_delete_iter);
- BKE_collection_remove(&data.scene->id, sc);
- }
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, layer_collection_find_data_to_edit, &data);
- BLI_gset_free(data.collections_to_delete, NULL);
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
+ LayerCollection *lc = BLI_gsetIterator_getKey(&collections_to_edit_iter);
- TreeElement *select_te = outliner_tree_element_from_layer_collection_index(soops, CTX_data_view_layer(C), 0);
- if (select_te) {
- outliner_item_select(soops, select_te, false, false);
+ if (include && (lc->flag & LAYER_COLLECTION_EXCLUDE)) {
+ result = true;
+ }
+ else if (!include && !(lc->flag & LAYER_COLLECTION_EXCLUDE)) {
+ result = true;
+ }
}
- DEG_relations_tag_update(CTX_data_main(C));
-
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&scene->id, 0);
-
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
-
- return OPERATOR_FINISHED;
+ BLI_gset_free(data.collections_to_edit, NULL);
+ return result;
}
-void OUTLINER_OT_collections_delete(wmOperatorType *ot)
+static int collections_exclude_poll(bContext *C)
{
- /* identifiers */
- ot->name = "Delete";
- ot->idname = "OUTLINER_OT_collections_delete";
- ot->description = "Delete selected overrides or collections";
-
- /* api callbacks */
- ot->exec = collection_delete_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ return collections_view_layer_poll(C, false);
}
-static int collection_select_exec(bContext *C, wmOperator *op)
+static int collections_include_poll(bContext *C)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const int collection_index = RNA_int_get(op->ptr, "collection_index");
- view_layer->active_collection = collection_index;
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- return OPERATOR_FINISHED;
-}
-
-void OUTLINER_OT_collection_select(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select";
- ot->idname = "OUTLINER_OT_collection_select";
- ot->description = "Change active collection or override";
-
- /* api callbacks */
- ot->exec = collection_select_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_int(ot->srna, "collection_index", 0, 0, INT_MAX, "Index",
- "Index of collection to select", 0, INT_MAX);
+ return collections_view_layer_poll(C, true);
}
-#define ACTION_DISABLE 0
-#define ACTION_ENABLE 1
-#define ACTION_TOGGLE 2
-
-static int collection_toggle_exec(bContext *C, wmOperator *op)
+static void layer_collection_exclude_recursive_set(LayerCollection *lc)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- int action = RNA_enum_get(op->ptr, "action");
- LayerCollection *layer_collection = CTX_data_layer_collection(C);
-
- if (layer_collection->flag & COLLECTION_DISABLED) {
- if (ELEM(action, ACTION_TOGGLE, ACTION_ENABLE)) {
- layer_collection->flag &= ~COLLECTION_DISABLED;
- }
- else { /* ACTION_DISABLE */
- BKE_reportf(op->reports, RPT_ERROR, "Layer collection %s already disabled",
- layer_collection->scene_collection->name);
- return OPERATOR_CANCELLED;
+ for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+ if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
+ nlc->flag |= LAYER_COLLECTION_EXCLUDE;
}
- }
- else {
- if (ELEM(action, ACTION_TOGGLE, ACTION_DISABLE)) {
- layer_collection->flag |= COLLECTION_DISABLED;
- }
- else { /* ACTION_ENABLE */
- BKE_reportf(op->reports, RPT_ERROR, "Layer collection %s already enabled",
- layer_collection->scene_collection->name);
- return OPERATOR_CANCELLED;
+ else {
+ nlc->flag &= ~LAYER_COLLECTION_EXCLUDE;
}
- }
-
- DEG_relations_tag_update(bmain);
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&scene->id, 0);
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
- return OPERATOR_FINISHED;
+ layer_collection_exclude_recursive_set(nlc);
+ }
}
-void OUTLINER_OT_collection_toggle(wmOperatorType *ot)
+static int collection_view_layer_exec(bContext *C, wmOperator *op)
{
- PropertyRNA *prop;
-
- static EnumPropertyItem actions_items[] = {
- {ACTION_DISABLE, "DISABLE", 0, "Disable", "Disable selected markers"},
- {ACTION_ENABLE, "ENABLE", 0, "Enable", "Enable selected markers"},
- {ACTION_TOGGLE, "TOGGLE", 0, "Toggle", "Toggle disabled flag for selected markers"},
- {0, NULL, 0, NULL, NULL}
- };
-
- /* identifiers */
- ot->name = "Toggle Collection";
- ot->idname = "OUTLINER_OT_collection_toggle";
- ot->description = "Deselect collection objects";
-
- /* api callbacks */
- ot->exec = collection_toggle_exec;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ struct CollectionEditData data = {.scene = scene, .soops = soops};
+ bool include = STREQ(op->idname, "OUTLINER_OT_collection_include_set");
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
- /* properties */
- prop = RNA_def_int(ot->srna, "collection_index", -1, -1, INT_MAX, "Collection Index", "Index of collection to toggle", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_enum(ot->srna, "action", actions_items, ACTION_TOGGLE, "Action", "Selection action to execute");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-}
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, layer_collection_find_data_to_edit, &data);
-#undef ACTION_TOGGLE
-#undef ACTION_ENABLE
-#undef ACTION_DISABLE
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
+ LayerCollection *lc = BLI_gsetIterator_getKey(&collections_to_edit_iter);
-struct CollectionObjectsSelectData {
- bool error;
- LayerCollection *layer_collection;
-};
+ if (!(lc->collection->flag & COLLECTION_IS_MASTER)) {
+ if (include) {
+ lc->flag &= ~LAYER_COLLECTION_EXCLUDE;
+ }
+ else {
+ lc->flag |= LAYER_COLLECTION_EXCLUDE;
+ }
-static TreeTraversalAction outliner_find_first_selected_layer_collection(TreeElement *te, void *customdata)
-{
- struct CollectionObjectsSelectData *data = customdata;
- TreeStoreElem *tselem = TREESTORE(te);
-
- switch (tselem->type) {
- case TSE_LAYER_COLLECTION:
- data->layer_collection = te->directdata;
- return TRAVERSE_BREAK;
- case TSE_LAYER_COLLECTION_BASE:
- return TRAVERSE_CONTINUE;
- default:
- return TRAVERSE_SKIP_CHILDS;
+ layer_collection_exclude_recursive_set(lc);
+ }
}
-}
-
-static LayerCollection *outliner_active_layer_collection(bContext *C)
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
- struct CollectionObjectsSelectData data = {
- .layer_collection = NULL,
- };
-
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_first_selected_layer_collection, &data);
- return data.layer_collection;
-}
+ BLI_gset_free(data.collections_to_edit, NULL);
-static int collection_objects_select_exec(bContext *C, wmOperator *UNUSED(op))
-{
- LayerCollection *layer_collection = outliner_active_layer_collection(C);
-
- if (layer_collection == NULL) {
- return OPERATOR_CANCELLED;
- }
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_relations_tag_update(bmain);
- BKE_layer_collection_objects_select(layer_collection);
- WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
return OPERATOR_FINISHED;
}
-void OUTLINER_OT_collection_objects_select(wmOperatorType *ot)
+void OUTLINER_OT_collection_exclude_set(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Select Objects";
- ot->idname = "OUTLINER_OT_collection_objects_select";
- ot->description = "Select all the collection objects";
+ ot->name = "Exclude from View Layer";
+ ot->idname = "OUTLINER_OT_collection_exclude_set";
+ ot->description = "Exclude collection from the active view layer";
/* api callbacks */
- ot->exec = collection_objects_select_exec;
- ot->poll = collections_editor_poll;
+ ot->exec = collection_view_layer_exec;
+ ot->poll = collections_exclude_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-struct CollectionDuplicateData {
- TreeElement *te;
-};
-
-static TreeTraversalAction outliner_find_first_selected_collection(TreeElement *te, void *customdata)
-{
- struct CollectionDuplicateData *data = customdata;
- TreeStoreElem *tselem = TREESTORE(te);
-
- switch (tselem->type) {
- case TSE_LAYER_COLLECTION:
- case TSE_SCENE_COLLECTION:
- data->te = te;
- return TRAVERSE_BREAK;
- case TSE_LAYER_COLLECTION_BASE:
- default:
- return TRAVERSE_CONTINUE;
- }
-}
-
-static TreeElement *outliner_active_collection(bContext *C)
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
-
- struct CollectionDuplicateData data = {
- .te = NULL,
- };
-
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_first_selected_collection, &data);
- return data.te;
-}
-
-static int collection_duplicate_exec(bContext *C, wmOperator *op)
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
- TreeElement *te = outliner_active_collection(C);
-
- BLI_assert(te != NULL);
- if (BKE_collection_master(TREESTORE(te)->id) == outliner_scene_collection_from_tree_element(te)) {
- BKE_report(op->reports, RPT_ERROR, "You can't duplicate the master collection");
- return OPERATOR_CANCELLED;
- }
-
- switch (soops->outlinevis) {
- case SO_SCENES:
- BKE_collection_duplicate(TREESTORE(te)->id, (SceneCollection *)te->directdata);
- break;
- case SO_COLLECTIONS:
- case SO_GROUPS:
- BKE_layer_collection_duplicate(TREESTORE(te)->id, (LayerCollection *)te->directdata);
- break;
- }
-
- DEG_relations_tag_update(CTX_data_main(C));
- WM_main_add_notifier(NC_SCENE | ND_LAYER, CTX_data_scene(C));
-
- return OPERATOR_FINISHED;
-}
-
-void OUTLINER_OT_collection_duplicate(wmOperatorType *ot)
+void OUTLINER_OT_collection_include_set(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Duplicate Collection";
- ot->idname = "OUTLINER_OT_collection_duplicate";
- ot->description = "Duplicate collection";
+ ot->name = "Include in View Layer";
+ ot->idname = "OUTLINER_OT_collection_include_set";
+ ot->description = "Include collection in the active view layer";
/* api callbacks */
- ot->exec = collection_duplicate_exec;
- ot->poll = collections_editor_poll;
+ ot->exec = collection_view_layer_exec;
+ ot->poll = collections_include_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index d3e70da80c8..90b137bcd7d 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -248,19 +248,6 @@ static void restrictbutton_gp_layer_flag_cb(bContext *C, void *UNUSED(poin), voi
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
-static void restrictbutton_collection_flag_cb(bContext *C, void *poin, void *UNUSED(poin2))
-{
- ID *id = (ID *)poin;
-
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(id, 0);
-
- if (GS(id->name) == ID_SCE) {
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, id);
- }
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, NULL);
-}
-
static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void *UNUSED(poin2))
{
ID *id = (ID *)poin;
@@ -275,9 +262,9 @@ static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void
}
}
-
static void namebutton_cb(bContext *C, void *tsep, char *oldname)
{
+ Main *bmain = CTX_data_main(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -289,7 +276,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
TreeElement *te = outliner_find_tree_element(&soops->tree, tselem);
if (tselem->type == 0) {
- BLI_libblock_ensure_unique_name(G.main, tselem->id->name);
+ BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
switch (GS(tselem->id->name)) {
case ID_MA:
@@ -311,7 +298,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
BKE_library_filepath_set(lib, lib->name);
BLI_strncpy(expanded, lib->name, sizeof(expanded));
- BLI_path_abs(expanded, G.main->name);
+ BLI_path_abs(expanded, bmain->name);
if (!BLI_exists(expanded)) {
BKE_reportf(CTX_wm_reports(C), RPT_ERROR,
"Library path '%s' does not exist, correct this before saving", expanded);
@@ -329,7 +316,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
defgroup_unique_name(te->directdata, (Object *)tselem->id); // id = object
break;
case TSE_NLA_ACTION:
- BLI_libblock_ensure_unique_name(G.main, tselem->id->name);
+ BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
break;
case TSE_EBONE:
{
@@ -404,14 +391,10 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, gpd);
break;
}
- case TSE_R_LAYER:
- break;
- case TSE_SCENE_COLLECTION:
case TSE_LAYER_COLLECTION:
{
- SceneCollection *sc = outliner_scene_collection_from_tree_element(te);
- BKE_collection_rename(tselem->id, sc, te->name);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
+ WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL); break;
break;
}
}
@@ -427,16 +410,16 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
TreeStoreElem *tselem;
Object *ob = NULL;
-#if 0
- PropertyRNA *object_prop_hide, *object_prop_hide_select, *object_prop_hide_render;
-
- /* get RNA properties (once) */
- object_prop_hide = RNA_struct_type_find_property(&RNA_Object, "hide");
- object_prop_hide_select = RNA_struct_type_find_property(&RNA_Object, "hide_select");
- object_prop_hide_render = RNA_struct_type_find_property(&RNA_Object, "hide_render");
- BLI_assert(object_prop_hide && object_prop_hide_select && object_prop_hide_render);
-#endif
-
+ /* get RNA properties (once for speed) */
+ PropertyRNA *collection_prop_hide_viewport;
+ PropertyRNA *collection_prop_hide_select;
+ PropertyRNA *collection_prop_hide_render;
+ collection_prop_hide_select = RNA_struct_type_find_property(&RNA_Collection, "hide_select");
+ collection_prop_hide_viewport = RNA_struct_type_find_property(&RNA_Collection, "hide_viewport");
+ collection_prop_hide_render = RNA_struct_type_find_property(&RNA_Collection, "hide_render");
+ BLI_assert(collection_prop_hide_viewport &&
+ collection_prop_hide_select &&
+ collection_prop_hide_render);
for (te = lb->first; te; te = te->next) {
tselem = TREESTORE(te);
@@ -540,46 +523,33 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
UI_block_emboss_set(block, UI_EMBOSS);
}
- else if (tselem->type == TSE_LAYER_COLLECTION) {
- LayerCollection *collection = te->directdata;
-
- const bool is_enabled = (collection->flag & COLLECTION_DISABLED) == 0;
+ else if (outliner_is_collection_tree_element(te)) {
+ LayerCollection *lc = (tselem->type == TSE_LAYER_COLLECTION) ? te->directdata : NULL;
+ Collection *collection = outliner_collection_from_tree_element(te);
UI_block_emboss_set(block, UI_EMBOSS_NONE);
- if (collection->scene_collection->type == COLLECTION_TYPE_NONE) {
- bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, COLLECTION_SELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &collection->flag, 0, 0, 0, 0,
- TIP_("Restrict/Allow 3D View selection of objects in the collection"));
- UI_but_func_set(bt, restrictbutton_collection_flag_cb, scene, collection);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- }
- else if ((soops->outlinevis == SO_GROUPS) &&
- (collection->scene_collection->type == COLLECTION_TYPE_GROUP_INTERNAL))
+ if ((!lc || !(lc->flag & LAYER_COLLECTION_EXCLUDE)) &&
+ !(collection->flag & COLLECTION_IS_MASTER))
{
- bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, COLLECTION_VIEWPORT, 0, ICON_RESTRICT_VIEW_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &collection->flag, 0, 0, 0, 0,
- TIP_("Restrict/Allow 3D View selection of objects in the collection"));
- UI_but_func_set(bt, restrictbutton_collection_flag_cb, tselem->id, collection);
+ PointerRNA collection_ptr;
+ RNA_id_pointer_create(&collection->id, &collection_ptr);
+
+ bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_VIEW_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &collection_ptr, collection_prop_hide_viewport, -1, 0, 0, 0, 0, NULL);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, COLLECTION_RENDER, 0, ICON_RESTRICT_RENDER_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &collection->flag, 0, 0, 0, 0,
- TIP_("Restrict/Allow 3D View selection of objects in the collection"));
- UI_but_func_set(bt, restrictbutton_collection_flag_cb, tselem->id, collection);
+ bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_RENDER_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &collection_ptr, collection_prop_hide_render, -1, 0, 0, 0, 0, NULL);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- }
- bt = uiDefIconButBitS(block, UI_BTYPE_BUT_TOGGLE, COLLECTION_DISABLED, 0,
- is_enabled ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &collection->flag, 0, 0, 0, 0,
- TIP_("Enable/Disable collection"));
- UI_but_func_set(bt, restrictbutton_collection_flag_cb, tselem->id, collection);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_SELECT_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &collection_ptr, collection_prop_hide_select, -1, 0, 0, 0, 0, NULL);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
UI_block_emboss_set(block, UI_EMBOSS);
}
@@ -1090,8 +1060,9 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
}
break;
case TSE_LAYER_COLLECTION:
- case TSE_SCENE_COLLECTION:
- ICON_DRAW(ICON_COLLAPSEMENU);
+ case TSE_SCENE_COLLECTION_BASE:
+ case TSE_VIEW_COLLECTION_BASE:
+ ICON_DRAW(ICON_GROUP);
break;
/* Removed the icons from outliner. Need a better structure with Layers, Palettes and Colors */
#if 0
@@ -1131,7 +1102,13 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
case OB_LIGHTPROBE:
tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LIGHTPROBE); break;
case OB_EMPTY:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_EMPTY); break;
+ if (ob->dup_group) {
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_GROUP_INSTANCE);
+ }
+ else {
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_EMPTY);
+ }
+ break;
}
}
else {
@@ -1339,7 +1316,7 @@ static void outliner_draw_tree_element(
tselem = TREESTORE(te);
if (*starty + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && *starty <= ar->v2d.cur.ymax) {
- const float alpha_fac = draw_grayed_out ? 0.5f : 1.0f;
+ const float alpha_fac = ((te->flag & TE_DISABLED) || draw_grayed_out) ? 0.5f : 1.0f;
const float alpha = 0.5f * alpha_fac;
int xmax = ar->v2d.cur.xmax;
@@ -1422,8 +1399,8 @@ static void outliner_draw_tree_element(
te->flag |= TE_ACTIVE; // for lookup in display hierarchies
}
- if ((soops->outlinevis == SO_COLLECTIONS) && (tselem->type == TSE_R_LAYER)) {
- /* View layer in collections can't expand/collapse. */
+ if (tselem->type == TSE_VIEW_COLLECTION_BASE) {
+ /* Scene collection in view layer can't expand/collapse. */
}
else if (te->subtree.first || (tselem->type == 0 && te->idcode == ID_SCE) || (te->flag & TE_LAZY_CLOSED)) {
/* open/close icon, only when sublevels, except for scene */
@@ -1448,7 +1425,7 @@ static void outliner_draw_tree_element(
else
offsx += 2 * ufac;
- if (tselem->type == 0 && ID_IS_LINKED(tselem->id)) {
+ if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION) && ID_IS_LINKED(tselem->id)) {
if (tselem->id->tag & LIB_TAG_MISSING) {
UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_BROKEN,
alpha_fac);
@@ -1463,7 +1440,7 @@ static void outliner_draw_tree_element(
}
offsx += UI_UNIT_X + 2 * ufac;
}
- else if (tselem->type == 0 && ID_IS_STATIC_OVERRIDE(tselem->id)) {
+ else if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION) && ID_IS_STATIC_OVERRIDE(tselem->id)) {
UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_OVERRIDE,
alpha_fac);
offsx += UI_UNIT_X + 2 * ufac;
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 5187de00cff..5922e208f36 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -50,6 +50,7 @@
#include "BLT_translation.h"
#include "BKE_animsys.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_idcode.h"
#include "BKE_layer.h"
@@ -61,7 +62,6 @@
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_material.h"
-#include "BKE_group.h"
#include "DEG_depsgraph_build.h"
@@ -254,7 +254,7 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot)
/* Rename --------------------------------------------------- */
-static void do_item_rename(const Scene *scene, ARegion *ar, TreeElement *te, TreeStoreElem *tselem,
+static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem,
ReportList *reports)
{
bool add_textbut = false;
@@ -264,19 +264,18 @@ static void do_item_rename(const Scene *scene, ARegion *ar, TreeElement *te, Tre
/* do nothing */;
}
else if (ELEM(tselem->type, TSE_ANIM_DATA, TSE_NLA, TSE_DEFGROUP_BASE, TSE_CONSTRAINT_BASE, TSE_MODIFIER_BASE,
- TSE_DRIVER_BASE, TSE_POSE_BASE, TSE_POSEGRP_BASE, TSE_R_LAYER_BASE))
+ TSE_DRIVER_BASE, TSE_POSE_BASE, TSE_POSEGRP_BASE, TSE_R_LAYER_BASE, TSE_SCENE_COLLECTION_BASE,
+ TSE_VIEW_COLLECTION_BASE))
{
BKE_report(reports, RPT_WARNING, "Cannot edit builtin name");
}
else if (ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) {
BKE_report(reports, RPT_WARNING, "Cannot edit sequence name");
}
- else if (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
- SceneCollection *master = BKE_collection_master(&scene->id);
+ else if (outliner_is_collection_tree_element(te)) {
+ Collection *collection = outliner_collection_from_tree_element(te);
- if ((tselem->type == TSE_SCENE_COLLECTION && te->directdata == master) ||
- (((LayerCollection *)te->directdata)->scene_collection == master))
- {
+ if (collection->flag & COLLECTION_IS_MASTER) {
BKE_report(reports, RPT_WARNING, "Cannot edit name of master collection");
}
else {
@@ -300,14 +299,14 @@ static void do_item_rename(const Scene *scene, ARegion *ar, TreeElement *te, Tre
}
void item_rename_cb(
- bContext *C, ReportList *reports, Scene *scene, TreeElement *te,
+ bContext *C, ReportList *reports, Scene *UNUSED(scene), TreeElement *te,
TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
{
ARegion *ar = CTX_wm_region(C);
- do_item_rename(scene, ar, te, tselem, reports);
+ do_item_rename(ar, te, tselem, reports);
}
-static int do_outliner_item_rename(const Scene *scene, ReportList *reports, ARegion *ar, TreeElement *te,
+static int do_outliner_item_rename(ReportList *reports, ARegion *ar, TreeElement *te,
const float mval[2])
{
if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
@@ -315,14 +314,14 @@ static int do_outliner_item_rename(const Scene *scene, ReportList *reports, AReg
/* click on name */
if (mval[0] > te->xs + UI_UNIT_X * 2 && mval[0] < te->xend) {
- do_item_rename(scene, ar, te, tselem, reports);
+ do_item_rename(ar, te, tselem, reports);
return 1;
}
return 0;
}
for (te = te->subtree.first; te; te = te->next) {
- if (do_outliner_item_rename(scene, reports, ar, te, mval)) return 1;
+ if (do_outliner_item_rename(reports, ar, te, mval)) return 1;
}
return 0;
}
@@ -338,7 +337,7 @@ static int outliner_item_rename(bContext *C, wmOperator *op, const wmEvent *even
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
for (te = soops->tree.first; te; te = te->next) {
- if (do_outliner_item_rename(CTX_data_scene(C), op->reports, ar, te, fmval)) {
+ if (do_outliner_item_rename(op->reports, ar, te, fmval)) {
changed = true;
break;
}
@@ -1915,7 +1914,6 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Main *bmain = CTX_data_main(C);
Scene *scene = NULL;
TreeElement *te = NULL;
- TreeStoreElem *tselem;
char childname[MAX_ID_NAME];
char parname[MAX_ID_NAME];
int partype = 0;
@@ -1925,21 +1923,8 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* Find object hovered over */
te = outliner_dropzone_find(soops, fmval, true);
- tselem = te ? TREESTORE(te) : NULL;
-
- if (tselem && ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
- SceneCollection *sc = outliner_scene_collection_from_tree_element(te);
-
- scene = BKE_scene_find_from_collection(bmain, sc);
- BLI_assert(scene);
- RNA_string_get(op->ptr, "child", childname);
- ob = (Object *)BKE_libblock_find_name(ID_OB, childname);
- BKE_collection_object_add(&scene->id, sc, ob);
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- }
- else if (te) {
+ if (te) {
RNA_string_set(op->ptr, "parent", te->name);
/* Identify parent and child */
RNA_string_get(op->ptr, "child", childname);
@@ -2082,9 +2067,10 @@ static int outliner_parenting_poll(bContext *C)
if (soops->outlinevis == SO_SCENES) {
return true;
}
-
- if (soops->outlinevis == SO_COLLECTIONS) {
- return (soops->filter & SO_FILTER_NO_COLLECTION);
+ else if ((soops->outlinevis == SO_VIEW_LAYER) &&
+ (soops->filter & SO_FILTER_NO_COLLECTION))
+ {
+ return true;
}
}
@@ -2163,16 +2149,16 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
}
- SceneCollection *sc;
+ Collection *collection;
if (scene != CTX_data_scene(C)) {
/* when linking to an inactive scene link to the master collection */
- sc = BKE_collection_master(&scene->id);
+ collection = BKE_collection_master(scene);
}
else {
- sc = CTX_data_scene_collection(C);
+ collection = CTX_data_collection(C);
}
- BKE_collection_object_add(&scene->id, sc, ob);
+ BKE_collection_object_add(bmain, collection, ob);
for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
Base *base = BKE_view_layer_base_find(view_layer, ob);
@@ -2268,58 +2254,81 @@ void OUTLINER_OT_material_drop(wmOperatorType *ot)
RNA_def_string(ot->srna, "material", "Material", MAX_ID_NAME, "Material", "Target Material");
}
-static int group_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+/* ******************** Collection Drop Operator *********************** */
+
+static int collection_drop_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
{
+ /* TODO: implement */
+#if 0
+ Object *par = NULL, *ob = NULL;
Main *bmain = CTX_data_main(C);
- Group *group = NULL;
- Object *ob = NULL;
+ Scene *scene = CTX_data_scene(C);
+ int partype = -1;
+ char parname[MAX_ID_NAME], childname[MAX_ID_NAME];
+
+ RNA_string_get(op->ptr, "parent", parname);
+ par = (Object *)BKE_libblock_find_name(ID_OB, parname);
+ RNA_string_get(op->ptr, "child", childname);
+ ob = (Object *)BKE_libblock_find_name(ID_OB, childname);
+
+ if (ID_IS_LINKED(ob)) {
+ BKE_report(op->reports, RPT_INFO, "Can't edit library linked object");
+ return OPERATOR_CANCELLED;
+ }
+
+ ED_object_parent_set(op->reports, C, scene, ob, par, partype, false, false, NULL);
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
+#endif
+
+ return OPERATOR_FINISHED;
+}
+
+static int collection_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
SpaceOops *soops = CTX_wm_space_outliner(C);
ARegion *ar = CTX_wm_region(C);
- TreeElement *te = NULL;
- char ob_name[MAX_ID_NAME - 2];
+ Main *bmain = CTX_data_main(C);
+ char childname[MAX_ID_NAME];
float fmval[2];
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
/* Find object hovered over */
- te = outliner_dropzone_find(soops, fmval, true);
-
- if (te) {
- group = (Group *)BKE_libblock_find_name(ID_GR, te->name);
-
- RNA_string_get(op->ptr, "object", ob_name);
- ob = (Object *)BKE_libblock_find_name(ID_OB, ob_name);
+ TreeElement *te = outliner_dropzone_find(soops, fmval, true);
- if (ELEM(NULL, group, ob)) {
- return OPERATOR_CANCELLED;
- }
- if (BKE_group_object_exists(group, ob)) {
- return OPERATOR_FINISHED;
- }
+ if (!te || !outliner_is_collection_tree_element(te)) {
+ return OPERATOR_CANCELLED;
+ }
- if (BKE_group_object_cyclic_check(bmain, ob, group)) {
- BKE_report(op->reports, RPT_ERROR, "Could not add the group because of dependency cycle detected");
- return OPERATOR_CANCELLED;
- }
+ Collection *collection = outliner_collection_from_tree_element(te);
- BKE_group_object_add(group, ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ // TODO: don't use scene, makes no sense anymore
+ // TODO: move rather than link, change hover text
+ Scene *scene = BKE_scene_find_from_collection(bmain, collection);
+ BLI_assert(scene);
+ RNA_string_get(op->ptr, "child", childname);
+ Object *ob = (Object *)BKE_libblock_find_name(ID_OB, childname);
+ BKE_collection_object_add(bmain, collection, ob);
- return OPERATOR_FINISHED;
- }
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- return OPERATOR_CANCELLED;
+ return OPERATOR_FINISHED;
}
-void OUTLINER_OT_group_link(wmOperatorType *ot)
+void OUTLINER_OT_collection_drop(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Link Object to Group";
- ot->description = "Link Object to Group in Outliner";
- ot->idname = "OUTLINER_OT_group_link";
+ ot->name = "Link to Collection"; // TODO: rename to move?
+ ot->description = "Drag to move to collection in Outliner";
+ ot->idname = "OUTLINER_OT_collection_drop";
/* api callbacks */
- ot->invoke = group_link_invoke;
+ ot->invoke = collection_drop_invoke;
+ ot->exec = collection_drop_exec;
ot->poll = ED_operator_outliner_active;
@@ -2327,5 +2336,6 @@ void OUTLINER_OT_group_link(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
/* properties */
- RNA_def_string(ot->srna, "object", "Object", MAX_ID_NAME, "Object", "Target Object");
+ RNA_def_string(ot->srna, "child", "Object", MAX_ID_NAME, "Child", "Child Object");
+ RNA_def_string(ot->srna, "parent", "Collection", MAX_ID_NAME, "Parent", "Parent Collection");
}
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index a0de3a06556..73494b890ed 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -71,6 +71,7 @@ typedef enum TreeTraversalAction {
* Callback type for reinserting elements at a different position, used to allow user customizable element order.
*/
typedef void (*TreeElementReinsertFunc)(struct Main *bmain,
+ struct Scene *scene,
struct SpaceOops *soops,
struct TreeElement *insert_element,
struct TreeElement *insert_handle,
@@ -124,6 +125,7 @@ enum {
TE_ICONROW = (1 << 1),
TE_LAZY_CLOSED = (1 << 2),
TE_FREE_NAME = (1 << 3),
+ TE_DISABLED = (1 << 4),
};
/* button events */
@@ -149,11 +151,11 @@ typedef enum {
/* size constants */
#define OL_Y_OFFSET 2
-#define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 3.0f)
-#define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 2.0f)
+#define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 3.0f)
+#define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 2.0f)
#define OL_TOG_RESTRICT_RENDERX UI_UNIT_X
-#define OL_TOGW OL_TOG_RESTRICT_VIEWX
+#define OL_TOGW OL_TOG_RESTRICT_SELECTX
#define OL_RNA_COLX (UI_UNIT_X * 15)
#define OL_RNA_COL_SIZEX (UI_UNIT_X * 7.5f)
@@ -161,7 +163,7 @@ typedef enum {
/* The outliner display modes that support the filter system.
* Note: keep it synced with space_outliner.py */
-#define SUPPORT_FILTER_OUTLINER(soops_) ((soops_)->outlinevis == SO_COLLECTIONS)
+#define SUPPORT_FILTER_OUTLINER(soops_) (ELEM((soops_)->outlinevis, SO_VIEW_LAYER))
/* Outliner Searching --
*
@@ -253,16 +255,6 @@ void object_toggle_renderability_cb(
TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
-void group_toggle_visibility_cb(
- struct bContext *C, struct ReportList *reports, struct Scene *scene,
- TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
-void group_toggle_selectability_cb(
- struct bContext *C, struct ReportList *reports, struct Scene *scene,
- TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
-void group_toggle_renderability_cb(
- struct bContext *C, struct ReportList *reports, struct Scene *scene,
- TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
-
void item_rename_cb(
struct bContext *C, struct ReportList *reports, struct Scene *scene,
TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
@@ -319,14 +311,13 @@ void OUTLINER_OT_parent_drop(struct wmOperatorType *ot);
void OUTLINER_OT_parent_clear(struct wmOperatorType *ot);
void OUTLINER_OT_scene_drop(struct wmOperatorType *ot);
void OUTLINER_OT_material_drop(struct wmOperatorType *ot);
-void OUTLINER_OT_group_link(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_drop(struct wmOperatorType *ot);
/* outliner_tools.c ---------------------------------------------- */
void OUTLINER_OT_operation(struct wmOperatorType *ot);
void OUTLINER_OT_scene_operation(struct wmOperatorType *ot);
void OUTLINER_OT_object_operation(struct wmOperatorType *ot);
-void OUTLINER_OT_group_operation(struct wmOperatorType *ot);
void OUTLINER_OT_lib_operation(struct wmOperatorType *ot);
void OUTLINER_OT_id_operation(struct wmOperatorType *ot);
void OUTLINER_OT_id_remap(struct wmOperatorType *ot);
@@ -335,7 +326,7 @@ void OUTLINER_OT_animdata_operation(struct wmOperatorType *ot);
void OUTLINER_OT_action_set(struct wmOperatorType *ot);
void OUTLINER_OT_constraint_operation(struct wmOperatorType *ot);
void OUTLINER_OT_modifier_operation(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_operation(struct wmOperatorType *ot);
+
/* ---------------------------------------------------------------- */
/* outliner_ops.c */
@@ -344,23 +335,18 @@ void outliner_keymap(struct wmKeyConfig *keyconf);
/* outliner_collections.c */
-struct SceneCollection *outliner_scene_collection_from_tree_element(TreeElement *te);
+bool outliner_is_collection_tree_element(const TreeElement *te);
+struct Collection *outliner_collection_from_tree_element(const TreeElement *te);
-void OUTLINER_OT_collections_delete(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_select(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_toggle(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_link(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_unlink(struct wmOperatorType *ot);
void OUTLINER_OT_collection_new(struct wmOperatorType *ot);
void OUTLINER_OT_collection_duplicate(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_objects_remove(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_delete(struct wmOperatorType *ot);
void OUTLINER_OT_collection_objects_select(struct wmOperatorType *ot);
-void OUTLINER_OT_object_add_to_new_collection(struct wmOperatorType *ot);
-void OUTLINER_OT_object_remove_from_collection(struct wmOperatorType *ot);
-
-void OUTLINER_OT_collection_objects_add(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_nested_new(struct wmOperatorType *ot);
-void OUTLINER_OT_collection_delete_selected(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_objects_deselect(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_link(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_instance(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_exclude_set(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_include_set(struct wmOperatorType *ot);
/* outliner_utils.c ---------------------------------------------- */
@@ -368,6 +354,7 @@ TreeElement *outliner_find_item_at_y(const SpaceOops *soops, const ListBase *tre
TreeElement *outliner_find_item_at_x_in_row(const SpaceOops *soops, const TreeElement *parent_te, float view_co_x);
TreeElement *outliner_find_tse(struct SpaceOops *soops, const TreeStoreElem *tse);
TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem);
+TreeElement *outliner_find_parent_element(ListBase *lb, TreeElement *parent_te, const TreeElement *child_te);
TreeElement *outliner_find_id(struct SpaceOops *soops, ListBase *lb, const struct ID *id);
TreeElement *outliner_find_posechannel(ListBase *lb, const struct bPoseChannel *pchan);
TreeElement *outliner_find_editbone(ListBase *lb, const struct EditBone *ebone);
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index 9f466d331f3..9c1b9bf2630 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -33,6 +33,8 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "DNA_group_types.h"
+
#include "BLT_translation.h"
#include "BKE_context.h"
@@ -67,7 +69,7 @@ static int outliner_item_drag_drop_poll(bContext *C)
SpaceOops *soops = CTX_wm_space_outliner(C);
return ED_operator_outliner_active(C) &&
/* Only collection display modes supported for now. Others need more design work */
- ELEM(soops->outlinevis, SO_COLLECTIONS, SO_GROUPS);
+ ELEM(soops->outlinevis, SO_VIEW_LAYER, SO_LIBRARIES);
}
static TreeElement *outliner_item_drag_element_find(SpaceOops *soops, ARegion *ar, const wmEvent *event)
@@ -184,25 +186,19 @@ static void outliner_item_drag_handle(
*/
static bool is_empty_collection(TreeElement *te)
{
- if (!ELEM(TREESTORE(te)->type, TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION)) {
- return false;
- }
+ Collection *collection = outliner_collection_from_tree_element(te);
- SceneCollection *scene_collection;
- if (TREESTORE(te)->type == TSE_SCENE_COLLECTION) {
- scene_collection = (SceneCollection *)te->directdata;
- }
- else {
- BLI_assert(TREESTORE(te)->type == TSE_LAYER_COLLECTION);
- scene_collection = ((LayerCollection *)te->directdata)->scene_collection;
+ if (!collection) {
+ return false;
}
- return BLI_listbase_is_empty(&scene_collection->objects) &&
- BLI_listbase_is_empty(&scene_collection->scene_collections);
+ return BLI_listbase_is_empty(&collection->gobject) &&
+ BLI_listbase_is_empty(&collection->children);
}
static bool outliner_item_drag_drop_apply(
Main *bmain,
+ Scene *scene,
SpaceOops *soops,
OutlinerDragDropTooltip *data,
const wmEvent *event)
@@ -225,7 +221,7 @@ static bool outliner_item_drag_drop_apply(
* it is strange to have it closed and we not see the newly dragged elements. */
const bool should_open_collection = (insert_type == TE_INSERT_INTO) && is_empty_collection(insert_handle);
- dragged_te->reinsert(bmain, soops, dragged_te, insert_handle, insert_type, event);
+ dragged_te->reinsert(bmain, scene, soops, dragged_te, insert_handle, insert_type, event);
if (should_open_collection && !is_empty_collection(insert_handle)) {
TREESTORE(insert_handle)->flag &= ~TSE_CLOSED;
@@ -239,6 +235,7 @@ static bool outliner_item_drag_drop_apply(
static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
OutlinerDragDropTooltip *data = op->customdata;
@@ -250,7 +247,7 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv
switch (event->type) {
case EVT_MODAL_MAP:
if (event->val == OUTLINER_ITEM_DRAG_CONFIRM) {
- if (outliner_item_drag_drop_apply(bmain, soops, data, event)) {
+ if (outliner_item_drag_drop_apply(bmain, scene, soops, data, event)) {
skip_rebuild = false;
}
retval = OPERATOR_FINISHED;
@@ -283,37 +280,20 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv
return retval;
}
-/**
- * Check if the given TreeElement is a collection
- *
- * This test is mainly used to see if next/prev TreeElement is a collection.
- * It will fail when there is no next/prev TreeElement, or when the
- * element is an Override or something else in the future.
- */
-static bool tree_element_is_collection_get(const TreeElement *te)
-{
- if (te == NULL) {
- return false;
- }
-
- TreeStoreElem *tselem = TREESTORE(te);
- return ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION);
-}
-
static const char *outliner_drag_drop_tooltip_get(
const TreeElement *te_float)
{
const char *name = NULL;
const TreeElement *te_insert = te_float->drag_data->insert_handle;
- if (tree_element_is_collection_get(te_float)) {
+ if (te_float && outliner_is_collection_tree_element(te_float)) {
if (te_insert == NULL) {
name = TIP_("Move collection");
}
else {
switch (te_float->drag_data->insert_type) {
case TE_INSERT_BEFORE:
- if (tree_element_is_collection_get(te_insert->prev)) {
+ if (te_insert->prev && outliner_is_collection_tree_element(te_insert->prev)) {
name = TIP_("Move between collections");
}
else {
@@ -321,7 +301,7 @@ static const char *outliner_drag_drop_tooltip_get(
}
break;
case TE_INSERT_AFTER:
- if (tree_element_is_collection_get(te_insert->next)) {
+ if (te_insert->next && outliner_is_collection_tree_element(te_insert->next)) {
name = TIP_("Move between collections");
}
else {
@@ -335,7 +315,7 @@ static const char *outliner_drag_drop_tooltip_get(
}
}
else if ((TREESTORE(te_float)->type == 0) && (te_float->idcode == ID_OB)) {
- name = TIP_("Move to collection (Ctrl to add)");
+ name = TIP_("Move to collection (Ctrl to link)");
}
return name;
@@ -434,7 +414,6 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_operation);
WM_operatortype_append(OUTLINER_OT_scene_operation);
WM_operatortype_append(OUTLINER_OT_object_operation);
- WM_operatortype_append(OUTLINER_OT_group_operation);
WM_operatortype_append(OUTLINER_OT_lib_operation);
WM_operatortype_append(OUTLINER_OT_lib_relocate);
WM_operatortype_append(OUTLINER_OT_id_operation);
@@ -445,7 +424,6 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_action_set);
WM_operatortype_append(OUTLINER_OT_constraint_operation);
WM_operatortype_append(OUTLINER_OT_modifier_operation);
- WM_operatortype_append(OUTLINER_OT_collection_operation);
WM_operatortype_append(OUTLINER_OT_show_one_level);
WM_operatortype_append(OUTLINER_OT_show_active);
@@ -467,24 +445,18 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_parent_clear);
WM_operatortype_append(OUTLINER_OT_scene_drop);
WM_operatortype_append(OUTLINER_OT_material_drop);
- WM_operatortype_append(OUTLINER_OT_group_link);
+ WM_operatortype_append(OUTLINER_OT_collection_drop);
/* collections */
- WM_operatortype_append(OUTLINER_OT_collections_delete);
- WM_operatortype_append(OUTLINER_OT_collection_select);
- WM_operatortype_append(OUTLINER_OT_collection_toggle);
- WM_operatortype_append(OUTLINER_OT_collection_link);
- WM_operatortype_append(OUTLINER_OT_collection_unlink);
WM_operatortype_append(OUTLINER_OT_collection_new);
WM_operatortype_append(OUTLINER_OT_collection_duplicate);
-
- WM_operatortype_append(OUTLINER_OT_collection_nested_new);
- WM_operatortype_append(OUTLINER_OT_collection_delete_selected);
- WM_operatortype_append(OUTLINER_OT_collection_objects_add);
- WM_operatortype_append(OUTLINER_OT_collection_objects_remove);
+ WM_operatortype_append(OUTLINER_OT_collection_delete);
WM_operatortype_append(OUTLINER_OT_collection_objects_select);
- WM_operatortype_append(OUTLINER_OT_object_add_to_new_collection);
- WM_operatortype_append(OUTLINER_OT_object_remove_from_collection);
+ WM_operatortype_append(OUTLINER_OT_collection_objects_deselect);
+ WM_operatortype_append(OUTLINER_OT_collection_link);
+ WM_operatortype_append(OUTLINER_OT_collection_instance);
+ WM_operatortype_append(OUTLINER_OT_collection_exclude_set);
+ WM_operatortype_append(OUTLINER_OT_collection_include_set);
}
static wmKeyMap *outliner_item_drag_drop_modal_keymap(wmKeyConfig *keyconf)
@@ -582,8 +554,8 @@ void outliner_keymap(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "OUTLINER_OT_drivers_add_selected", DKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "OUTLINER_OT_drivers_delete_selected", DKEY, KM_PRESS, KM_ALT, 0);
- WM_keymap_verify_item(keymap, "OUTLINER_OT_collection_nested_new", CKEY, KM_PRESS, 0, 0);
- WM_keymap_verify_item(keymap, "OUTLINER_OT_collection_delete_selected", XKEY, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "OUTLINER_OT_collection_new", CKEY, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "OUTLINER_OT_collection_delete", XKEY, KM_PRESS, 0, 0);
outliner_item_drag_drop_modal_keymap(keyconf);
}
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index d62f542e1d1..42fe70be527 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -44,8 +44,8 @@
#include "BLI_listbase.h"
#include "BKE_armature.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_group.h"
#include "BKE_layer.h"
#include "BKE_object.h"
#include "BKE_scene.h"
@@ -681,43 +681,42 @@ static eOLDrawState tree_element_active_keymap_item(
return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_collection(
- bContext *C, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
+static eOLDrawState tree_element_active_master_collection(
+ bContext *C, TreeElement *UNUSED(te), const eOLSetState set)
{
if (set == OL_SETSEL_NONE) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
LayerCollection *active = CTX_data_layer_collection(C);
- /* sometimes the renderlayer has no LayerCollection at all */
- if (active == NULL) {
- return OL_DRAWSEL_NONE;
- }
-
- if ((tselem->type == TSE_SCENE_COLLECTION && active->scene_collection == te->directdata) ||
- (tselem->type == TSE_LAYER_COLLECTION && active == te->directdata))
- {
+ if (active == view_layer->layer_collections.first) {
return OL_DRAWSEL_NORMAL;
}
}
- /* don't allow selecting a scene collection, it can have multiple layer collection
- * instances (which one would the user want to be selected then?) */
- else if (tselem->type == TSE_LAYER_COLLECTION) {
- LayerCollection *layer_collection = te->directdata;
+ else {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ LayerCollection *layer_collection = view_layer->layer_collections.first;
+ BKE_layer_collection_activate(view_layer, layer_collection);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ }
- switch (layer_collection->scene_collection->type) {
- case COLLECTION_TYPE_NONE:
- case COLLECTION_TYPE_GROUP_INTERNAL:
- {
- ViewLayer *view_layer = BKE_view_layer_find_from_collection(tselem->id, layer_collection);
- const int collection_index = BKE_layer_collection_findindex(view_layer, layer_collection);
+ return OL_DRAWSEL_NONE;
+}
- if (collection_index > -1) {
- view_layer->active_collection = collection_index;
- }
- break;
- }
- default:
- BLI_assert(!"Collection type not fully implemented");
+static eOLDrawState tree_element_active_layer_collection(
+ bContext *C, TreeElement *te, const eOLSetState set)
+{
+ if (set == OL_SETSEL_NONE) {
+ LayerCollection *active = CTX_data_layer_collection(C);
+
+ if (active == te->directdata) {
+ return OL_DRAWSEL_NORMAL;
}
+ }
+ else {
+ Scene *scene = CTX_data_scene(C);
+ LayerCollection *layer_collection = te->directdata;
+ ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, layer_collection);
+ BKE_layer_collection_activate(view_layer, layer_collection);
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
}
@@ -785,12 +784,7 @@ eOLDrawState tree_element_type_active(
case TSE_CONSTRAINT:
return tree_element_active_constraint(C, scene, view_layer, te, tselem, set);
case TSE_R_LAYER:
- if (soops->outlinevis == SO_SCENES) {
- return active_viewlayer(C, scene, view_layer, te, tselem, set);
- }
- else {
- return OL_DRAWSEL_NONE;
- }
+ return active_viewlayer(C, scene, view_layer, te, tselem, set);
case TSE_POSEGRP:
return tree_element_active_posegroup(C, scene, view_layer, te, tselem, set);
case TSE_SEQUENCE:
@@ -802,9 +796,10 @@ eOLDrawState tree_element_type_active(
case TSE_GP_LAYER:
//return tree_element_active_gplayer(C, scene, s, te, tselem, set);
break;
- case TSE_SCENE_COLLECTION:
+ case TSE_VIEW_COLLECTION_BASE:
+ return tree_element_active_master_collection(C, te, set);
case TSE_LAYER_COLLECTION:
- return tree_element_active_collection(C, te, tselem, set);
+ return tree_element_active_layer_collection(C, te, set);
}
return OL_DRAWSEL_NONE;
}
@@ -840,29 +835,29 @@ static void do_outliner_item_activate_tree_element(
}
}
else if (te->idcode == ID_GR) {
- Group *gr = (Group *)tselem->id;
+ Collection *gr = (Collection *)tselem->id;
if (extend) {
int sel = BA_SELECT;
- FOREACH_GROUP_BASE_BEGIN(gr, base)
+ FOREACH_COLLECTION_BASE_RECURSIVE_BEGIN(gr, base)
{
if (base->flag & BASE_SELECTED) {
sel = BA_DESELECT;
break;
}
}
- FOREACH_GROUP_BASE_END
+ FOREACH_COLLECTION_BASE_RECURSIVE_END
- FOREACH_GROUP_OBJECT_BEGIN(gr, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(gr, object)
{
ED_object_base_select(BKE_view_layer_base_find(view_layer, object), sel);
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
else {
BKE_view_layer_base_deselect_all(view_layer);
- FOREACH_GROUP_OBJECT_BEGIN(gr, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(gr, object)
{
Base *base = BKE_view_layer_base_find(view_layer, object);
/* Object may not be in this scene */
@@ -872,7 +867,7 @@ static void do_outliner_item_activate_tree_element(
}
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index fd5f29aec39..5ae6cec84ba 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -51,10 +51,10 @@
#include "BLI_utildefines.h"
#include "BKE_animsys.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_constraint.h"
#include "BKE_fcurve.h"
-#include "BKE_group.h"
#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_override.h"
@@ -105,7 +105,8 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb,
for (te = lb->first; te; te = te->next) {
tselem = TREESTORE(te);
if (tselem->flag & TSE_SELECTED) {
- if (tselem->type) {
+ /* Layer collection points to collection ID. */
+ if (!ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) {
if (*datalevel == 0)
*datalevel = tselem->type;
else if (*datalevel != tselem->type)
@@ -129,6 +130,9 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb,
case ID_LI:
if (*idlevel == 0) *idlevel = idcode;
else if (*idlevel != idcode) *idlevel = -1;
+ if (ELEM(*datalevel, TSE_VIEW_COLLECTION_BASE, TSE_SCENE_COLLECTION_BASE)) {
+ *datalevel = 0;
+ }
break;
}
}
@@ -214,21 +218,52 @@ static void unlink_texture_cb(
}
}
-static void unlink_group_cb(
+static void unlink_collection_cb(
bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
TreeStoreElem *tsep, TreeStoreElem *tselem, void *UNUSED(user_data))
{
- Group *group = (Group *)tselem->id;
-
+ Main *bmain = CTX_data_main(C);
+ Collection *collection = (Collection *)tselem->id;
+
if (tsep) {
if (GS(tsep->id->name) == ID_OB) {
Object *ob = (Object *)tsep->id;
ob->dup_group = NULL;
+ DEG_relations_tag_update(bmain);
+ }
+ else if (GS(tsep->id->name) == ID_GR) {
+ Collection *parent = (Collection *)tsep->id;
+ id_fake_user_set(&collection->id);
+ BKE_collection_child_remove(bmain, parent, collection);
+ DEG_relations_tag_update(bmain);
+ }
+ else if (GS(tsep->id->name) == ID_SCE) {
+ Collection *parent = BKE_collection_master((Scene *)tsep->id);
+ id_fake_user_set(&collection->id);
+ BKE_collection_child_remove(bmain, parent, collection);
+ DEG_relations_tag_update(bmain);
}
}
- else {
- Main *bmain = CTX_data_main(C);
- BKE_libblock_delete(bmain, group);
+}
+
+static void unlink_object_cb(
+ bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
+ TreeStoreElem *tsep, TreeStoreElem *tselem, void *UNUSED(user_data))
+{
+ Main *bmain = CTX_data_main(C);
+ Object *ob = (Object *)tselem->id;
+
+ if (tsep) {
+ if (GS(tsep->id->name) == ID_GR) {
+ Collection *parent = (Collection *)tsep->id;
+ BKE_collection_object_remove(bmain, parent, ob, true);
+ DEG_relations_tag_update(bmain);
+ }
+ else if (GS(tsep->id->name) == ID_SCE) {
+ Collection *parent = BKE_collection_master((Scene *)tsep->id);
+ BKE_collection_object_remove(bmain, parent, ob, true);
+ DEG_relations_tag_update(bmain);
+ }
}
}
@@ -255,7 +290,7 @@ static void outliner_do_libdata_operation(
for (te = lb->first; te; te = te->next) {
tselem = TREESTORE(te);
if (tselem->flag & TSE_SELECTED) {
- if (tselem->type == 0) {
+ if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) {
TreeStoreElem *tsep = te->parent ? TREESTORE(te->parent) : NULL;
operation_cb(C, reports, scene, te, tsep, tselem, user_data);
}
@@ -520,42 +555,6 @@ static void singleuser_world_cb(
}
}
-static void group_linkobs2scene_cb(
- bContext *C, ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- SceneCollection *sc = CTX_data_scene_collection(C);
- Group *group = (Group *)tselem->id;
- Base *base;
-
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
- {
- base = BKE_view_layer_base_find(view_layer, object);
- if (!base) {
- /* link to scene */
- BKE_collection_object_add(&scene->id, sc, object);
- base = BKE_view_layer_base_find(view_layer, object);
- id_us_plus(&object->id);
- }
-
- base->flag |= BASE_SELECTED;
- }
- FOREACH_GROUP_OBJECT_END;
-}
-
-static void group_instance_cb(
- bContext *C, ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- Group *group = (Group *)tselem->id;
-
- Object *ob = ED_object_add_type(C, OB_EMPTY, group->id.name + 2, scene->cursor.location, NULL, false, scene->layact);
- ob->dup_group = group;
- ob->transflag |= OB_DUPLIGROUP;
- id_lib_extern(&group->id);
-}
-
/**
* \param select_recurse: Set to false for operations which are already recursively operating on their children.
*/
@@ -660,17 +659,6 @@ typedef enum eOutliner_PropModifierOps {
OL_MODIFIER_OP_DELETE
} eOutliner_PropModifierOps;
-typedef enum eOutliner_PropCollectionOps {
- OL_COLLECTION_OP_OBJECTS_ADD = 1,
- OL_COLLECTION_OP_OBJECTS_REMOVE,
- OL_COLLECTION_OP_OBJECTS_SELECT,
- OL_COLLECTION_OP_COLLECTION_NEW,
- OL_COLLECTION_OP_COLLECTION_COPY,
- OL_COLLECTION_OP_COLLECTION_DEL,
- OL_COLLECTION_OP_COLLECTION_UNLINK,
- OL_COLLECTION_OP_GROUP_CREATE,
-} eOutliner_PropCollectionOps;
-
static void pchan_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *UNUSED(arg))
{
bPoseChannel *pchan = (bPoseChannel *)te->directdata;
@@ -821,90 +809,6 @@ static void modifier_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem
}
}
-static void collection_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *Carg)
-{
- bContext *C = (bContext *)Carg;
- Scene *scene = CTX_data_scene(C);
- LayerCollection *lc = te->directdata;
- ID *id = te->store_elem->id;
- SceneCollection *sc = lc->scene_collection;
-
- if (event == OL_COLLECTION_OP_OBJECTS_ADD) {
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- BKE_collection_object_add(id, sc, ob);
- }
- CTX_DATA_END;
-
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- }
- else if (event == OL_COLLECTION_OP_OBJECTS_REMOVE) {
- Main *bmain = CTX_data_main(C);
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- BKE_collection_object_remove(bmain, id, sc, ob, true);
- }
- CTX_DATA_END;
-
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- te->store_elem->flag &= ~TSE_SELECTED;
- }
- else if (event == OL_COLLECTION_OP_OBJECTS_SELECT) {
- BKE_layer_collection_objects_select(lc);
- WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
- }
- else if (event == OL_COLLECTION_OP_COLLECTION_NEW) {
- if (GS(id->name) == ID_GR) {
- BKE_collection_add(id, sc, COLLECTION_TYPE_GROUP_INTERNAL, NULL);
- }
- else {
- BLI_assert(GS(id->name) == ID_SCE);
- BKE_collection_add(id, sc, COLLECTION_TYPE_NONE, NULL);
- }
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- }
- else if (event == OL_COLLECTION_OP_COLLECTION_COPY) {
- BKE_layer_collection_duplicate(id, lc);
- DEG_relations_tag_update(CTX_data_main(C));
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- }
- else if (event == OL_COLLECTION_OP_COLLECTION_UNLINK) {
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- if (BLI_findindex(&view_layer->layer_collections, lc) == -1) {
- /* we can't unlink if the layer collection wasn't directly linked */
- TODO_LAYER_OPERATORS; /* this shouldn't be in the menu in those cases */
- }
- else {
- BKE_collection_unlink(view_layer, lc);
- DEG_relations_tag_update(CTX_data_main(C));
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- }
- }
- else if (event == OL_COLLECTION_OP_COLLECTION_DEL) {
- if (BKE_collection_remove(id, sc)) {
- DEG_relations_tag_update(CTX_data_main(C));
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- }
- else {
- /* we can't remove the master collection */
- TODO_LAYER_OPERATORS; /* this shouldn't be in the menu in those cases */
- }
- }
- else if (event == OL_COLLECTION_OP_GROUP_CREATE) {
- Main *bmain = CTX_data_main(C);
- BKE_collection_group_create(bmain, scene, lc);
- DEG_relations_tag_update(bmain);
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&scene->id, 0);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- }
- else {
- BLI_assert(!"Collection operation not fully implemented!");
- }
-}
-
static void outliner_do_data_operation(SpaceOops *soops, int type, int event, ListBase *lb,
void (*operation_cb)(int, TreeElement *, TreeStoreElem *, void *),
void *arg)
@@ -1124,106 +1028,6 @@ void OUTLINER_OT_object_operation(wmOperatorType *ot)
/* **************************************** */
-typedef enum eOutliner_PropGroupOps {
- OL_GROUPOP_UNLINK = 1,
- OL_GROUPOP_LOCAL,
- OL_GROUPOP_STATIC_OVERRIDE,
- OL_GROUPOP_LINK,
- OL_GROUPOP_DELETE,
- OL_GROUPOP_REMAP,
- OL_GROUPOP_INSTANCE,
- OL_GROUPOP_TOGVIS,
- OL_GROUPOP_TOGSEL,
- OL_GROUPOP_TOGREN,
- OL_GROUPOP_RENAME,
-} eOutliner_PropGroupOps;
-
-static const EnumPropertyItem prop_group_op_types[] = {
- {OL_GROUPOP_UNLINK, "UNLINK", 0, "Unlink Group", ""},
- {OL_GROUPOP_LOCAL, "LOCAL", 0, "Make Local Group", ""},
- {OL_GROUPOP_STATIC_OVERRIDE, "STATIC_OVERRIDE",
- 0, "Add Static Override", "Add a local static override of that group"},
- {OL_GROUPOP_LINK, "LINK", 0, "Link Group Objects to Scene", ""},
- {OL_GROUPOP_DELETE, "DELETE", 0, "Delete Group", ""},
- {OL_GROUPOP_REMAP, "REMAP", 0, "Remap Users",
- "Make all users of selected data-blocks to use instead current (clicked) one"},
- {OL_GROUPOP_INSTANCE, "INSTANCE", 0, "Instance Groups in Scene", ""},
- {OL_GROUPOP_TOGVIS, "TOGVIS", 0, "Toggle Visible Group", ""},
- {OL_GROUPOP_TOGSEL, "TOGSEL", 0, "Toggle Selectable", ""},
- {OL_GROUPOP_TOGREN, "TOGREN", 0, "Toggle Renderable", ""},
- {OL_GROUPOP_RENAME, "RENAME", 0, "Rename", ""},
- {0, NULL, 0, NULL, NULL}
-};
-
-static int outliner_group_operation_exec(bContext *C, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
- SpaceOops *soops = CTX_wm_space_outliner(C);
- int event;
-
- /* check for invalid states */
- if (soops == NULL)
- return OPERATOR_CANCELLED;
-
- event = RNA_enum_get(op->ptr, "type");
-
- switch (event) {
- case OL_GROUPOP_UNLINK:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, unlink_group_cb, NULL);
- break;
- case OL_GROUPOP_LOCAL:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_local_cb, NULL);
- break;
- case OL_GROUPOP_STATIC_OVERRIDE:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_static_override_cb, NULL);
- break;
- case OL_GROUPOP_LINK:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_linkobs2scene_cb, NULL);
- break;
- case OL_GROUPOP_INSTANCE:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_instance_cb, NULL);
- /* works without this except if you try render right after, see: 22027 */
- DEG_relations_tag_update(CTX_data_main(C));
- break;
- case OL_GROUPOP_DELETE:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_delete_cb, NULL);
- break;
- case OL_GROUPOP_REMAP:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL);
- break;
- case OL_GROUPOP_RENAME:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb, NULL);
- break;
- default:
- BLI_assert(0);
- }
-
- ED_undo_push(C, prop_group_op_types[event - 1].name);
- WM_event_add_notifier(C, NC_GROUP, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-
-void OUTLINER_OT_group_operation(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Outliner Group Operation";
- ot->idname = "OUTLINER_OT_group_operation";
- ot->description = "";
-
- /* callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = outliner_group_operation_exec;
- ot->poll = ED_operator_outliner_active;
-
- ot->flag = 0;
-
- ot->prop = RNA_def_enum(ot->srna, "type", prop_group_op_types, 0, "Group Operation", "");
-}
-
-/* **************************************** */
-
typedef enum eOutlinerIdOpTypes {
OUTLINER_IDOP_INVALID = 0,
@@ -1278,6 +1082,14 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
case OUTLINER_IDOP_UNLINK:
{
/* unlink datablock from its parent */
+ if (objectlevel) {
+ outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, unlink_object_cb, NULL);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, NULL);
+ ED_undo_push(C, "Unlink Object");
+ break;
+ }
+
switch (idlevel) {
case ID_AC:
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, unlink_action_cb, NULL);
@@ -1303,6 +1115,12 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_SCENE | ND_WORLD, NULL);
ED_undo_push(C, "Unlink world");
break;
+ case ID_GR:
+ outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, unlink_collection_cb, NULL);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, NULL);
+ ED_undo_push(C, "Unlink Collection");
+ break;
default:
BKE_report(op->reports, RPT_WARNING, "Not yet implemented");
break;
@@ -1840,84 +1658,6 @@ void OUTLINER_OT_modifier_operation(wmOperatorType *ot)
/* ******************** */
-static EnumPropertyItem prop_collection_op_types[] = {
- {OL_COLLECTION_OP_OBJECTS_ADD, "OBJECTS_ADD", ICON_ZOOMIN, "Add Selected", "Add selected objects to collection"},
- {OL_COLLECTION_OP_OBJECTS_REMOVE, "OBJECTS_REMOVE", ICON_X, "Remove Selected", "Remove selected objects from collection"},
- {OL_COLLECTION_OP_OBJECTS_SELECT, "OBJECTS_SELECT", ICON_RESTRICT_SELECT_OFF, "Select Objects", "Select collection objects"},
- {OL_COLLECTION_OP_COLLECTION_NEW, "COLLECTION_NEW", ICON_NEW, "New Collection", "Add a new nested collection"},
- {OL_COLLECTION_OP_COLLECTION_COPY, "COLLECTION_DUPLI", ICON_NONE, "Duplicate Collection", "Duplicate the collection"},
- {OL_COLLECTION_OP_COLLECTION_UNLINK, "COLLECTION_UNLINK", ICON_UNLINKED, "Unlink", "Unlink collection"},
- {OL_COLLECTION_OP_COLLECTION_DEL, "COLLECTION_DEL", ICON_X, "Delete Collection", "Delete the collection"},
- {OL_COLLECTION_OP_GROUP_CREATE, "GROUP_CREATE", ICON_GROUP, "Create Group", "Turn the collection into a group collection"},
- {0, NULL, 0, NULL, NULL}
-};
-
-static int outliner_collection_operation_exec(bContext *C, wmOperator *op)
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
- int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
- eOutliner_PropCollectionOps event;
-
- event = RNA_enum_get(op->ptr, "type");
- set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
-
- outliner_do_data_operation(soops, datalevel, event, &soops->tree, collection_cb, C);
-
- outliner_cleanup_tree(soops);
-
- ED_undo_push(C, "Collection operation");
-
- return OPERATOR_FINISHED;
-}
-
-static int outliner_collection_operation_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
- wmOperatorType *ot = op->type;
- EnumPropertyItem *prop = &prop_collection_op_types[0];
-
- uiPopupMenu *pup = UI_popup_menu_begin(C, "Collection", ICON_NONE);
- uiLayout *layout = UI_popup_menu_layout(pup);
-
- for (int i = 0; i < (ARRAY_SIZE(prop_collection_op_types) - 1); i++, prop++) {
- if (soops->outlinevis != SO_GROUPS ||
- !ELEM(prop->value,
- OL_COLLECTION_OP_OBJECTS_SELECT,
- OL_COLLECTION_OP_COLLECTION_UNLINK,
- OL_COLLECTION_OP_GROUP_CREATE))
- {
- uiItemEnumO_ptr(layout, ot, NULL, prop->icon, "type", prop->value);
- }
- }
-
- UI_popup_menu_end(C, pup);
-
- return OPERATOR_INTERFACE;
-}
-
-void OUTLINER_OT_collection_operation(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Outliner Collection Operation";
- ot->idname = "OUTLINER_OT_collection_operation";
- ot->description = "";
-
- /* callbacks */
- ot->invoke = outliner_collection_operation_invoke;
- ot->exec = outliner_collection_operation_exec;
- ot->poll = ED_operator_outliner_active;
-
- ot->flag = 0;
-
- prop = RNA_def_enum(ot->srna, "type", prop_collection_op_types, OL_COLLECTION_OP_OBJECTS_ADD, "Collection Operation", "");
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
-}
-
-/* ******************** */
-
// XXX: select linked is for RNA structs only
static const EnumPropertyItem prop_data_op_types[] = {
{OL_DOP_SELECT, "SELECT", 0, "Select", ""},
@@ -2041,7 +1781,7 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop
}
set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
-
+
if (scenelevel) {
if (objectlevel || datalevel || idlevel) {
BKE_report(reports, RPT_WARNING, "Mixed selection");
@@ -2051,7 +1791,7 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop
}
}
else if (objectlevel) {
- WM_menu_name_call(C, "OUTLINER_MT_context_object", WM_OP_INVOKE_REGION_WIN);
+ WM_menu_name_call(C, "OUTLINER_MT_object", WM_OP_INVOKE_REGION_WIN);
}
else if (idlevel) {
if (idlevel == -1 || datalevel) {
@@ -2060,7 +1800,7 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop
else {
switch (idlevel) {
case ID_GR:
- WM_operator_name_call(C, "OUTLINER_OT_group_operation", WM_OP_INVOKE_REGION_WIN, NULL);
+ WM_menu_name_call(C, "OUTLINER_MT_collection", WM_OP_INVOKE_REGION_WIN);
break;
case ID_LI:
WM_operator_name_call(C, "OUTLINER_OT_lib_operation", WM_OP_INVOKE_REGION_WIN, NULL);
@@ -2081,8 +1821,11 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop
else if (datalevel == TSE_DRIVER_BASE) {
/* do nothing... no special ops needed yet */
}
- else if (ELEM(datalevel, TSE_R_LAYER_BASE, TSE_R_LAYER)) {
- /*WM_operator_name_call(C, "OUTLINER_OT_renderdata_operation", WM_OP_INVOKE_REGION_WIN, NULL)*/
+ else if (datalevel == TSE_LAYER_COLLECTION) {
+ WM_menu_name_call(C, "OUTLINER_MT_collection", WM_OP_INVOKE_REGION_WIN);
+ }
+ else if (ELEM(datalevel, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
+ WM_menu_name_call(C, "OUTLINER_MT_collection_new", WM_OP_INVOKE_REGION_WIN);
}
else if (datalevel == TSE_ID_BASE) {
/* do nothing... there are no ops needed here yet */
@@ -2093,12 +1836,6 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop
else if (datalevel == TSE_MODIFIER) {
WM_operator_name_call(C, "OUTLINER_OT_modifier_operation", WM_OP_INVOKE_REGION_WIN, NULL);
}
- else if (datalevel == TSE_LAYER_COLLECTION) {
- WM_operator_name_call(C, "OUTLINER_OT_collection_operation", WM_OP_INVOKE_REGION_WIN, NULL);
- }
- else if (datalevel == TSE_SCENE_COLLECTION) {
- WM_menu_name_call(C, "OUTLINER_MT_context_scene_collection", WM_OP_INVOKE_REGION_WIN);
- }
else {
WM_operator_name_call(C, "OUTLINER_OT_data_operation", WM_OP_INVOKE_REGION_WIN, NULL);
}
@@ -2123,6 +1860,7 @@ static int outliner_operation(bContext *C, wmOperator *UNUSED(op), const wmEvent
uiBut *but = UI_context_active_but_get(C);
TreeElement *te;
float fmval[2];
+ bool found = false;
if (but) {
UI_but_tooltip_timer_remove(C, but);
@@ -2132,9 +1870,17 @@ static int outliner_operation(bContext *C, wmOperator *UNUSED(op), const wmEvent
for (te = soops->tree.first; te; te = te->next) {
if (do_outliner_operation_event(C, ar, soops, te, fmval)) {
+ found = true;
break;
}
}
+
+ if (!found) {
+ /* Menus for clicking in empty space. */
+ if (soops->outlinevis == SO_VIEW_LAYER) {
+ WM_menu_name_call(C, "OUTLINER_MT_collection_new", WM_OP_INVOKE_REGION_WIN);
+ }
+ }
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index ed809062a29..58ab8f3735e 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -91,14 +91,8 @@
#endif
/* prototypes */
-static void outliner_add_layer_collections_recursive(
- SpaceOops *soops, ListBase *tree, ID *id, ListBase *layer_collections, TreeElement *parent_ten,
- const bool show_objects);
-static TreeElement *outliner_add_scene_collection_recursive(
- SpaceOops *soops, ListBase *tree, Scene *scene, SceneCollection *scene_collection, TreeElement *parent_ten);
-static void outliner_add_view_layer(
- SpaceOops *soops, ListBase *tree, TreeElement *parent,
- Scene *scene, ViewLayer *layer, const bool show_objects);
+static TreeElement *outliner_add_collection_recursive(
+ SpaceOops *soops, Collection *collection, TreeElement *ten);
static void outliner_make_object_parent_hierarchy(ListBase *lb);
/* ********************************************************* */
@@ -293,28 +287,30 @@ static void outliner_add_line_styles(SpaceOops *soops, ListBase *lb, Scene *sce,
static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *sce, TreeElement *te)
{
/* View layers */
- TreeElement *tenla = outliner_add_element(soops, lb, sce, te, TSE_R_LAYER_BASE, 0);
- tenla->name = IFACE_("View Layers");
+ TreeElement *ten = outliner_add_element(soops, lb, sce, te, TSE_R_LAYER_BASE, 0);
+ ten->name = IFACE_("View Layers");
ViewLayer *view_layer;
for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
- TreeElement *tenlay = outliner_add_element(soops, &tenla->subtree, sce, te, TSE_R_LAYER, 0);
+ TreeElement *tenlay = outliner_add_element(soops, &ten->subtree, sce, te, TSE_R_LAYER, 0);
tenlay->name = view_layer->name;
tenlay->directdata = view_layer;
}
/* Collections */
- outliner_add_scene_collection_recursive(soops, lb, sce, sce->collection, NULL);
+ ten = outliner_add_element(soops, lb, &sce->id, te, TSE_SCENE_COLLECTION_BASE, 0);
+ ten->name = IFACE_("Scene Collection");
+ outliner_add_collection_recursive(soops, sce->master_collection, ten);
/* Objects */
- tenla = outliner_add_element(soops, lb, sce, te, TSE_SCENE_OBJECTS_BASE, 0);
- tenla->name = IFACE_("Objects");
+ ten = outliner_add_element(soops, lb, sce, te, TSE_SCENE_OBJECTS_BASE, 0);
+ ten->name = IFACE_("Objects");
FOREACH_SCENE_OBJECT_BEGIN(sce, ob)
{
- outliner_add_element(soops, &tenla->subtree, ob, NULL, 0, 0);
+ outliner_add_element(soops, &ten->subtree, ob, NULL, 0, 0);
}
FOREACH_SCENE_OBJECT_END;
- outliner_make_object_parent_hierarchy(&tenla->subtree);
+ outliner_make_object_parent_hierarchy(&ten->subtree);
/* Animation Data */
if (outliner_animdata_test(sce->adt))
@@ -329,7 +325,7 @@ TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void *custom
struct ObjectsSelectedData *data = customdata;
TreeStoreElem *tselem = TREESTORE(te);
- if (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
+ if (outliner_is_collection_tree_element(te)) {
return TRAVERSE_CONTINUE;
}
@@ -348,13 +344,14 @@ TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void *custom
* Instead we move all the selected objects around.
*/
static void outliner_object_reorder(
- Main *bmain, SpaceOops *soops,
+ Main *bmain, Scene *scene,
+ SpaceOops *soops,
TreeElement *insert_element,
TreeElement *insert_handle, TreeElementInsertType action,
const wmEvent *event)
{
- SceneCollection *sc = outliner_scene_collection_from_tree_element(insert_handle);
- SceneCollection *sc_ob_parent = NULL;
+ Collection *collection = outliner_collection_from_tree_element(insert_handle);
+ Collection *collection_ob_parent = NULL;
ID *id = insert_handle->store_elem->id;
BLI_assert(action == TE_INSERT_INTO);
@@ -375,24 +372,24 @@ static void outliner_object_reorder(
Object *ob = (Object *)TREESTORE(ten_selected)->id;
if (is_append) {
- BKE_collection_object_add(id, sc, ob);
+ BKE_collection_object_add(bmain, collection, ob);
continue;
}
- /* Find parent scene-collection of object. */
+ /* Find parent collection of object. */
if (ten_selected->parent) {
for (TreeElement *te_ob_parent = ten_selected->parent; te_ob_parent; te_ob_parent = te_ob_parent->parent) {
- if (ELEM(TREESTORE(te_ob_parent)->type, TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION)) {
- sc_ob_parent = outliner_scene_collection_from_tree_element(te_ob_parent);
+ if (outliner_is_collection_tree_element(te_ob_parent)) {
+ collection_ob_parent = outliner_collection_from_tree_element(te_ob_parent);
break;
}
}
}
else {
- sc_ob_parent = BKE_collection_master(id);
+ collection_ob_parent = BKE_collection_master(scene);
}
- BKE_collection_object_move(id, sc, sc_ob_parent, ob);
+ BKE_collection_object_move(bmain, scene, collection, collection_ob_parent, ob);
}
BLI_freelistN(&data.objects_selected_array);
@@ -409,8 +406,7 @@ static bool outliner_object_reorder_poll(
const TreeElement *insert_element,
TreeElement **io_insert_handle, TreeElementInsertType *io_action)
{
- TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle);
- if (ELEM(tselem_handle->type, TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION) &&
+ if (outliner_is_collection_tree_element(*io_insert_handle) &&
(insert_element->parent != *io_insert_handle))
{
*io_action = TE_INSERT_INTO;
@@ -815,6 +811,11 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
}
break;
}
+ case ID_GR:
+ {
+ Collection *collection = (Collection *)id;
+ outliner_add_collection_recursive(soops, collection, te);
+ }
default:
break;
}
@@ -876,7 +877,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
else if (type == TSE_GP_LAYER) {
/* pass */
}
- else if (ELEM(type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
+ else if (ELEM(type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
/* pass */
}
else if (type == TSE_ID_BASE) {
@@ -895,8 +896,9 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
TreeStoreElem *tsepar = parent ? TREESTORE(parent) : NULL;
/* ID datablock */
- if (tsepar == NULL || tsepar->type != TSE_ID_BASE)
+ if (tsepar == NULL || tsepar->type != TSE_ID_BASE || soops->filter_id_type) {
outliner_add_id_contents(soops, te, tselem, id);
+ }
}
else if (type == TSE_ANIM_DATA) {
IdAdtTemplate *iat = (IdAdtTemplate *)idv;
@@ -1177,11 +1179,6 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
te->flag |= TE_LAZY_CLOSED;
}
- if ((type != TSE_LAYER_COLLECTION) && (te->idcode == ID_GR)) {
- Group *group = (Group *)id;
- outliner_add_layer_collections_recursive(soops, &te->subtree, id, &group->view_layer->layer_collections, NULL, true);
- }
-
return te;
}
@@ -1263,6 +1260,32 @@ static const char *outliner_idcode_to_plural(short idcode)
return (prop) ? RNA_property_ui_name(prop) : "UNKNOWN";
}
+static bool outliner_library_id_show(Library *lib, ID *id, short filter_id_type)
+{
+ if (id->lib != lib) {
+ return false;
+ }
+
+ if (filter_id_type == ID_GR) {
+ /* Don't show child collections of non-scene master collection,
+ * they are already shown as children. */
+ Collection *collection = (Collection *)id;
+ bool has_non_scene_parent = false;
+
+ for (CollectionParent *cparent = collection->parents.first; cparent; cparent = cparent->next) {
+ if (!(cparent->collection->flag & COLLECTION_IS_MASTER)) {
+ has_non_scene_parent = true;
+ }
+ }
+
+ if (has_non_scene_parent) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
static void outliner_add_library_contents(Main *mainvar, SpaceOops *soops, TreeElement *te, Library *lib)
{
TreeElement *ten;
@@ -1298,13 +1321,13 @@ static void outliner_add_library_contents(Main *mainvar, SpaceOops *soops, TreeE
}
for (id = lbarray[a]->first; id; id = id->next) {
- if (id->lib == lib)
+ if (outliner_library_id_show(lib, id, filter_id_type)) {
outliner_add_element(soops, &ten->subtree, id, ten, 0, 0);
+ }
}
}
}
}
-
}
static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
@@ -1353,170 +1376,165 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
}
}
-static void outliner_layer_collections_reorder(
+static void outliner_collections_reorder(
Main *bmain,
- SpaceOops *UNUSED(soops),
- TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action,
+ Scene *UNUSED(scene),
+ SpaceOops *soops,
+ TreeElement *insert_element,
+ TreeElement *insert_handle,
+ TreeElementInsertType action,
const wmEvent *UNUSED(event))
{
- LayerCollection *lc_insert = insert_element->directdata;
- LayerCollection *lc_handle = insert_handle->directdata;
- ID *id = insert_element->store_elem->id;
+ TreeElement *from_parent_te, *to_parent_te;
+ Collection *from_parent, *to_parent;
- if (action == TE_INSERT_BEFORE) {
- BKE_layer_collection_move_above(id, lc_handle, lc_insert);
- }
- else if (action == TE_INSERT_AFTER) {
- BKE_layer_collection_move_below(id, lc_handle, lc_insert);
+ Collection *collection = outliner_collection_from_tree_element(insert_element);
+ Collection *relative = NULL;
+ bool relative_after = false;
+
+ from_parent_te = outliner_find_parent_element(&soops->tree, NULL, insert_element);
+ from_parent = (from_parent_te) ? outliner_collection_from_tree_element(from_parent_te) : NULL;
+
+ if (ELEM(action, TE_INSERT_BEFORE, TE_INSERT_AFTER)) {
+ to_parent_te = outliner_find_parent_element(&soops->tree, NULL, insert_handle);
+ to_parent = (to_parent_te) ? outliner_collection_from_tree_element(to_parent_te) : NULL;
+
+ relative = outliner_collection_from_tree_element(insert_handle);
+ relative_after = (action == TE_INSERT_AFTER);
}
else if (action == TE_INSERT_INTO) {
- BKE_layer_collection_move_into(id, lc_handle, lc_insert);
+ to_parent = outliner_collection_from_tree_element(insert_handle);
}
else {
BLI_assert(0);
+ return;
}
+ if (!to_parent) {
+ return;
+ }
+
+ BKE_collection_move(bmain, to_parent, from_parent, relative, relative_after, collection);
+
DEG_relations_tag_update(bmain);
}
-static bool outliner_layer_collections_reorder_poll(
+
+static bool outliner_collections_reorder_poll(
const TreeElement *insert_element,
- TreeElement **io_insert_handle, TreeElementInsertType *UNUSED(io_action))
+ TreeElement **io_insert_handle,
+ TreeElementInsertType *io_action)
{
- const TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle);
+ /* Can't move master collection. */
+ Collection *collection = outliner_collection_from_tree_element(insert_element);
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ return false;
+ }
+
+ /* Can only move into collections. */
+ Collection *collection_handle = outliner_collection_from_tree_element(*io_insert_handle);
+ if (collection_handle == NULL) {
+ return false;
+ }
- if (tselem_handle->id != insert_element->store_elem->id) {
- return false;
+ /* We can't insert/before after master collection. */
+ if (collection_handle->flag & COLLECTION_IS_MASTER) {
+ if (*io_action == TE_INSERT_BEFORE) {
+ /* can't go higher than master collection, insert into it */
+ *io_action = TE_INSERT_INTO;
+ }
+ else if (*io_action == TE_INSERT_AFTER) {
+ *io_insert_handle = (*io_insert_handle)->subtree.last;
+ }
}
- return ELEM(tselem_handle->type, TSE_LAYER_COLLECTION);
+ return true;
+}
+
+static void outliner_add_layer_collection_objects(
+ SpaceOops *soops, ListBase *tree, ViewLayer *layer,
+ LayerCollection *lc, TreeElement *ten)
+{
+ for (CollectionObject *cob = lc->collection->gobject.first; cob; cob = cob->next) {
+ Base *base = BKE_view_layer_base_find(layer, cob->ob);
+ TreeElement *te_object = outliner_add_element(soops, tree, base->object, ten, 0, 0);
+ te_object->directdata = base;
+ }
}
static void outliner_add_layer_collections_recursive(
- SpaceOops *soops, ListBase *tree, ID *id, ListBase *layer_collections, TreeElement *parent_ten,
+ SpaceOops *soops, ListBase *tree, ViewLayer *layer,
+ ListBase *layer_collections, TreeElement *parent_ten,
const bool show_objects)
{
- for (LayerCollection *collection = layer_collections->first; collection; collection = collection->next) {
+ for (LayerCollection *lc = layer_collections->first; lc; lc = lc->next) {
+ ID *id = &lc->collection->id;
TreeElement *ten = outliner_add_element(soops, tree, id, parent_ten, TSE_LAYER_COLLECTION, 0);
- ten->name = collection->scene_collection->name;
- ten->directdata = collection;
- ten->reinsert = outliner_layer_collections_reorder;
- ten->reinsert_poll = outliner_layer_collections_reorder_poll;
+ ten->name = id->name + 2;
+ ten->directdata = lc;
+ ten->reinsert = outliner_collections_reorder;
+ ten->reinsert_poll = outliner_collections_reorder_poll;
- outliner_add_layer_collections_recursive(soops, &ten->subtree, id, &collection->layer_collections, ten, show_objects);
- if (show_objects) {
- for (LinkData *link = collection->object_bases.first; link; link = link->next) {
- Base *base = (Base *)link->data;
- TreeElement *te_object = outliner_add_element(soops, &ten->subtree, base->object, ten, 0, 0);
- te_object->directdata = base;
- }
+ const bool exclude = (lc->flag & LAYER_COLLECTION_EXCLUDE) != 0;
+ if (exclude) {
+ ten->flag |= TE_DISABLED;
+ }
+
+ outliner_add_layer_collections_recursive(soops, &ten->subtree, layer, &lc->layer_collections, ten, show_objects);
+ if (!exclude && show_objects) {
+ outliner_add_layer_collection_objects(soops, &ten->subtree, layer, lc, ten);
}
}
}
static void outliner_add_view_layer(SpaceOops *soops, ListBase *tree, TreeElement *parent,
- Scene *scene, ViewLayer *layer, const bool show_objects)
-{
- outliner_add_layer_collections_recursive(soops, tree, &scene->id, &layer->layer_collections, parent, show_objects);
-}
-
-static void outliner_scene_collections_reorder(
- Main *bmain,
- SpaceOops *UNUSED(soops),
- TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action,
- const wmEvent *UNUSED(event))
-{
- SceneCollection *sc_insert = insert_element->directdata;
- SceneCollection *sc_handle = insert_handle->directdata;
- ID *id = insert_handle->store_elem->id;
- BLI_assert(id == insert_element->store_elem->id);
-
- BLI_assert((action == TE_INSERT_INTO) || (sc_handle != BKE_collection_master(id)));
- if (action == TE_INSERT_BEFORE) {
- BKE_collection_move_above(id, sc_handle, sc_insert);
- }
- else if (action == TE_INSERT_AFTER) {
- BKE_collection_move_below(id, sc_handle, sc_insert);
- }
- else if (action == TE_INSERT_INTO) {
- BKE_collection_move_into(id, sc_handle, sc_insert);
- }
- else {
- BLI_assert(0);
- }
-
- DEG_relations_tag_update(bmain);
-}
-static bool outliner_scene_collections_reorder_poll(
- const TreeElement *insert_element,
- TreeElement **io_insert_handle, TreeElementInsertType *io_action)
+ ViewLayer *layer, const bool show_objects)
{
- const TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle);
- ID *id = tselem_handle->id;
-
- if (id != insert_element->store_elem->id) {
- return false;
- }
-
- if (!ELEM(tselem_handle->type, TSE_SCENE_COLLECTION)) {
- return false;
+ /* First layer collection is for master collection, don't show it. */
+ LayerCollection *lc = layer->layer_collections.first;
+ if (lc == NULL) {
+ return;
}
- SceneCollection *sc_master = BKE_collection_master(id);
- SceneCollection *sc_handle = (*io_insert_handle)->directdata;
-
- if (sc_handle == sc_master) {
- /* exception: Can't insert before/after master selection, has to be one of its childs */
- TreeElement *te_master = *io_insert_handle;
- if (*io_action == TE_INSERT_BEFORE) {
- /* can't go higher than master collection, insert into it */
- *io_action = TE_INSERT_INTO;
- }
- else if (*io_action == TE_INSERT_AFTER) {
- *io_insert_handle = te_master->subtree.last;
- }
+ outliner_add_layer_collections_recursive(soops, tree, layer, &lc->layer_collections, parent, show_objects);
+ if (show_objects) {
+ outliner_add_layer_collection_objects(soops, tree, layer, lc, parent);
}
- return true;
}
-BLI_INLINE void outliner_add_scene_collection_init(TreeElement *te, Scene *scene, SceneCollection *collection)
+BLI_INLINE void outliner_add_collection_init(TreeElement *te, Collection *collection)
{
- if (collection == scene->collection) {
- // Don't display name of master collection
- te->name = IFACE_("Collections");
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ te->name = IFACE_("Scene Collection");
}
else {
- te->name = collection->name;
+ te->name = collection->id.name + 2;
}
te->directdata = collection;
- te->reinsert = outliner_scene_collections_reorder;
- te->reinsert_poll = outliner_scene_collections_reorder_poll;
+ te->reinsert = outliner_collections_reorder;
+ te->reinsert_poll = outliner_collections_reorder_poll;
}
-BLI_INLINE void outliner_add_scene_collection_objects(
- SpaceOops *soops, ListBase *tree, SceneCollection *collection, TreeElement *parent)
+BLI_INLINE void outliner_add_collection_objects(
+ SpaceOops *soops, ListBase *tree, Collection *collection, TreeElement *parent)
{
- for (LinkData *link = collection->objects.first; link; link = link->next) {
- outliner_add_element(soops, tree, link->data, parent, 0, 0);
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ outliner_add_element(soops, tree, cob->ob, parent, 0, 0);
}
}
-static TreeElement *outliner_add_scene_collection_recursive(
- SpaceOops *soops, ListBase *tree, Scene *scene, SceneCollection *scene_collection, TreeElement *parent_ten)
+static TreeElement *outliner_add_collection_recursive(
+ SpaceOops *soops, Collection *collection, TreeElement *ten)
{
- TreeElement *ten = outliner_add_element(soops, tree, &scene->id, parent_ten, TSE_SCENE_COLLECTION, 0);
- outliner_add_scene_collection_init(ten, scene, scene_collection);
+ outliner_add_collection_init(ten, collection);
- if (soops->outlinevis != SO_SCENES) {
- outliner_add_scene_collection_objects(soops, &ten->subtree, scene_collection, ten);
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ outliner_add_element(soops, &ten->subtree, &child->collection->id, ten, 0, 0);
}
- for (SceneCollection *scene_collection_nested = scene_collection->scene_collections.first;
- scene_collection_nested != NULL;
- scene_collection_nested = scene_collection_nested->next)
- {
- outliner_add_scene_collection_recursive(soops, &ten->subtree, scene, scene_collection_nested, ten);
+ if (soops->outlinevis != SO_SCENES) {
+ outliner_add_collection_objects(soops, &ten->subtree, collection, ten);
}
return ten;
@@ -1732,8 +1750,7 @@ static void outliner_restore_scrolling_position(SpaceOops *soops, ARegion *ar, O
static bool test_collection_callback(TreeElement *te)
{
- TreeStoreElem *tselem = TREESTORE(te);
- return ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION);
+ return outliner_is_collection_tree_element(te);
}
static bool test_object_callback(TreeElement *te)
@@ -1787,7 +1804,8 @@ static TreeElement *outliner_find_first_desired_element_at_y(
te = outliner_find_item_at_y(soops, &soops->tree, view_co);
bool (*callback_test)(TreeElement *);
- if (soops->filter & SO_FILTER_NO_COLLECTION) {
+ if ((soops->outlinevis == SO_VIEW_LAYER) &&
+ (soops->filter & SO_FILTER_NO_COLLECTION)) {
callback_test = test_object_callback;
}
else {
@@ -1866,10 +1884,11 @@ static int outliner_exclude_filter_get(SpaceOops *soops)
return (exclude_filter & SO_FILTER_SEARCH);
}
+ if (soops->filter & SO_FILTER_NO_OBJECT) {
+ exclude_filter |= SO_FILTER_OB_TYPE;
+ }
+
switch (soops->filter_state) {
- case SO_FILTER_OB_NONE:
- exclude_filter |= SO_FILTER_OB_TYPE;
- break;
case SO_FILTER_OB_VISIBLE:
exclude_filter |= SO_FILTER_OB_STATE_VISIBLE;
break;
@@ -2163,12 +2182,6 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
outliner_make_object_parent_hierarchy(&te->subtree);
}
}
- else if (soops->outlinevis == SO_GROUPS) {
- Group *group;
- for (group = mainvar->group.first; group; group = group->id.next) {
- te = outliner_add_element(soops, &soops->tree, group, NULL, 0, 0);
- }
- }
else if (soops->outlinevis == SO_SEQUENCE) {
Sequence *seq;
Editing *ed = BKE_sequencer_editing_get(scene, false);
@@ -2208,27 +2221,24 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
else if (soops->outlinevis == SO_ID_ORPHANS) {
outliner_add_orphaned_datablocks(mainvar, soops);
}
- else if (soops->outlinevis == SO_COLLECTIONS) {
- TreeElement *tenlay = outliner_add_element(soops, &soops->tree, scene, te, TSE_R_LAYER, 0);
- tenlay->name = view_layer->name;
- tenlay->directdata = view_layer;
- TREESTORE(tenlay)->flag &= ~TSE_CLOSED;
-
+ else if (soops->outlinevis == SO_VIEW_LAYER) {
if (soops->filter & SO_FILTER_NO_COLLECTION) {
+ /* Show objects in the view layer. */
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- TreeElement *te_object = outliner_add_element(soops, &tenlay->subtree, base->object, NULL, 0, 0);
+ TreeElement *te_object = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
te_object->directdata = base;
}
- outliner_make_object_parent_hierarchy(&tenlay->subtree);
+
+ outliner_make_object_parent_hierarchy(&soops->tree);
}
else {
- outliner_add_view_layer(soops, &tenlay->subtree, NULL, scene, view_layer, true);
- }
- }
- else {
- if (BASACT(view_layer)) {
- ten = outliner_add_element(soops, &soops->tree, OBACT(view_layer), NULL, 0, 0);
- ten->directdata = BASACT(view_layer);
+ /* Show collections in the view layer. */
+ ten = outliner_add_element(soops, &soops->tree, scene, NULL, TSE_VIEW_COLLECTION_BASE, 0);
+ ten->name = IFACE_("Scene Collection");
+ TREESTORE(ten)->flag &= ~TSE_CLOSED;
+
+ bool show_objects = !(soops->filter & SO_FILTER_NO_OBJECT);
+ outliner_add_view_layer(soops, &ten->subtree, ten, view_layer, show_objects);
}
}
diff --git a/source/blender/editors/space_outliner/outliner_utils.c b/source/blender/editors/space_outliner/outliner_utils.c
index d3f7fd7055e..896f6c016d0 100644
--- a/source/blender/editors/space_outliner/outliner_utils.c
+++ b/source/blender/editors/space_outliner/outliner_utils.c
@@ -101,6 +101,23 @@ TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store
return NULL;
}
+/* Find parent element of te */
+TreeElement *outliner_find_parent_element(ListBase *lb, TreeElement *parent_te, const TreeElement *child_te)
+{
+ TreeElement *te;
+ for (te = lb->first; te; te = te->next) {
+ if (te == child_te) {
+ return parent_te;
+ }
+
+ TreeElement *find_te = outliner_find_parent_element(&te->subtree, te, child_te);
+ if (find_te) {
+ return find_te;
+ }
+ }
+ return NULL;
+}
+
/* tse is not in the treestore, we use its contents to find a match */
TreeElement *outliner_find_tse(SpaceOops *soops, const TreeStoreElem *tse)
{
@@ -125,10 +142,8 @@ TreeElement *outliner_find_id(SpaceOops *soops, ListBase *lb, const ID *id)
if (tselem->id == id) {
return te;
}
- /* only deeper on scene or object */
- if (ELEM(te->idcode, ID_OB, ID_SCE) ||
- ((soops->outlinevis == SO_GROUPS) && (te->idcode == ID_GR)))
- {
+ /* only deeper on scene collection or object */
+ if (ELEM(te->idcode, ID_OB, ID_SCE, ID_GR)) {
TreeElement *tes = outliner_find_id(soops, &te->subtree, id);
if (tes) {
return tes;
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index b762dd31f58..72ce24aaff5 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -138,10 +138,6 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e
}
}
}
- else if (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
- /* support adding object from different scene to collection */
- return 1;
- }
}
}
return 0;
@@ -163,7 +159,7 @@ static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
- if (!ELEM(soops->outlinevis, SO_SCENES, SO_GROUPS, SO_COLLECTIONS)) {
+ if (!ELEM(soops->outlinevis, SO_VIEW_LAYER)) {
return false;
}
@@ -250,7 +246,7 @@ static void outliner_material_drop_copy(wmDrag *drag, wmDropBox *drop)
RNA_string_set(drop->ptr, "material", id->name + 2);
}
-static int outliner_group_link_poll(bContext *C, wmDrag *drag, const wmEvent *event)
+static int outliner_collection_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
@@ -259,19 +255,19 @@ static int outliner_group_link_poll(bContext *C, wmDrag *drag, const wmEvent *ev
if (drag->type == WM_DRAG_ID) {
ID *id = drag->poin;
- if (GS(id->name) == ID_OB) {
+ if (ELEM(GS(id->name), ID_OB, ID_GR)) {
/* Ensure item under cursor is valid drop target */
TreeElement *te = outliner_dropzone_find(soops, fmval, true);
- return (te && te->idcode == ID_GR && TREESTORE(te)->type == 0);
+ return (te && outliner_is_collection_tree_element(te));
}
}
return 0;
}
-static void outliner_group_link_copy(wmDrag *drag, wmDropBox *drop)
+static void outliner_collection_drop_copy(wmDrag *drag, wmDropBox *drop)
{
ID *id = drag->poin;
- RNA_string_set(drop->ptr, "object", id->name + 2);
+ RNA_string_set(drop->ptr, "child", id->name + 2);
}
/* region dropbox definition */
@@ -283,7 +279,7 @@ static void outliner_dropboxes(void)
WM_dropbox_add(lb, "OUTLINER_OT_parent_clear", outliner_parent_clear_poll, outliner_parent_clear_copy);
WM_dropbox_add(lb, "OUTLINER_OT_scene_drop", outliner_scene_drop_poll, outliner_scene_drop_copy);
WM_dropbox_add(lb, "OUTLINER_OT_material_drop", outliner_material_drop_poll, outliner_material_drop_copy);
- WM_dropbox_add(lb, "OUTLINER_OT_group_link", outliner_group_link_poll, outliner_group_link_copy);
+ WM_dropbox_add(lb, "OUTLINER_OT_collection_drop", outliner_collection_drop_poll, outliner_collection_drop_copy);
}
static void outliner_main_region_draw(const bContext *C, ARegion *ar)
@@ -438,7 +434,7 @@ static void outliner_main_region_message_subscribe(
.notify = ED_region_do_msg_notify_tag_redraw,
};
- if (soops->outlinevis == SO_COLLECTIONS) {
+ if (ELEM(soops->outlinevis, SO_VIEW_LAYER, SO_SCENES)) {
WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_region_tag_redraw);
}
}
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index df9d8dad6ee..f26da3ad07e 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -549,7 +549,7 @@ static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent
return 0;
}
-static int view3d_group_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
+static int view3d_collection_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_ID) {
ID *id = drag->poin;
@@ -624,7 +624,7 @@ static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
RNA_string_set(drop->ptr, "name", id->name + 2);
}
-static void view3d_group_drop_copy(wmDrag *drag, wmDropBox *drop)
+static void view3d_collection_drop_copy(wmDrag *drag, wmDropBox *drop)
{
ID *id = drag->poin;
@@ -664,7 +664,7 @@ static void view3d_dropboxes(void)
WM_dropbox_add(lb, "MESH_OT_drop_named_image", view3d_ima_mesh_drop_poll, view3d_id_path_drop_copy);
WM_dropbox_add(lb, "OBJECT_OT_drop_named_image", view3d_ima_empty_drop_poll, view3d_id_path_drop_copy);
WM_dropbox_add(lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy);
- WM_dropbox_add(lb, "OBJECT_OT_group_instance_add", view3d_group_drop_poll, view3d_group_drop_copy);
+ WM_dropbox_add(lb, "OBJECT_OT_collection_instance_add", view3d_collection_drop_poll, view3d_collection_drop_copy);
}
static void view3d_widgets(void)
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 7fc582a1511..43ff8af42fb 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -45,8 +45,8 @@
#include "BKE_appdir.h"
#include "BKE_blender_copybuffer.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
-#include "BKE_group.h"
#include "BKE_main.h"
#include "BKE_report.h"
@@ -81,17 +81,17 @@ static int view3d_copybuffer_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- for (Group *group = bmain->group.first; group; group = group->id.next) {
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
- {
+ for (Collection *collection = bmain->collection.first; collection; collection = collection->id.next) {
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ Object *object = cob->ob;
+
if (object && (object->id.tag & LIB_TAG_DOIT)) {
- BKE_copybuffer_tag_ID(&group->id);
+ BKE_copybuffer_tag_ID(&collection->id);
/* don't expand out to all other objects */
- group->id.tag &= ~LIB_TAG_NEED_EXPAND;
+ collection->id.tag &= ~LIB_TAG_NEED_EXPAND;
break;
}
}
- FOREACH_GROUP_OBJECT_END;
}
BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");