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:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2018-04-30 16:57:22 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2018-05-18 14:34:24 +0300
commit17bd5c9d4b1e9377b896c13043e24eaa7e979714 (patch)
tree60ca4e4118c01d88ccc04919d4f7ed46014875c1 /source/blender/editors/object
parent70aec3732d0f03138d6477fd04c81dfd9fd21256 (diff)
Collections and groups unification
OVERVIEW * In 2.7 terminology, all layers and groups are now collection datablocks. * These collections are nestable, linkable, instanceable, overrideable, .. which opens up new ways to set up scenes and link + override data. * Viewport/render visibility and selectability are now a part of the collection and shared across all view layers and linkable. * View layers define which subset of the scene collection hierarchy is excluded for each. For many workflows one view layer can be used, these are more of an advanced feature now. OUTLINER * The outliner now has a "View Layer" display mode instead of "Collections", which can display the collections and/or objects in the view layer. * In this display mode, collections can be excluded with the right click menu. These will then be greyed out and their objects will be excluded. * To view collections not linked to any scene, the "Blender File" display mode can be used, with the new filtering option to just see Colleciton datablocks. * The outliner right click menus for collections and objects were reorganized. * Drag and drop still needs to be improved. Like before, dragging the icon or text gives different results, we'll unify this later. LINKING AND OVERRIDES * Collections can now be linked into the scene without creating an instance, with the link/append operator or from the collections view in the outliner. * Collections can get static overrides with the right click menu in the outliner, but this is rather unreliable and not clearly communicated at the moment. * We still need to improve the make override operator to turn collection instances into collections with overrides directly in the scene. PERFORMANCE * We tried to make performance not worse than before and improve it in some cases. The main thing that's still a bit slower is multiple scenes, we have to change the layer syncing to only updated affected scenes. * Collections keep a list of their parent collections for faster incremental updates in syncing and caching. * View layer bases are now in a object -> base hash to avoid quadratic time lookups internally and in API functions like visible_get(). VERSIONING * Compatibility with 2.7 files should be improved due to the new visibility controls. Of course users may not want to set up their scenes differently now to avoid having separate layers and groups. * Compatibility with 2.8 is mostly there, and was tested on Eevee demo and Hero files. There's a few things which are know to be not quite compatible, like nested layer collections inside groups. * The versioning code for 2.8 files is quite complicated, and isolated behind #ifdef so it can be removed at the end of the release cycle. KNOWN ISSUES * The G-key group operators in the 3D viewport were left mostly as is, they need to be modified still to fit better. * Same for the groups panel in the object properties. This needs to be updated still, or perhaps replaced by something better. * Collections must all have a unique name. Less restrictive namespacing is to be done later, we'll have to see how important this is as all objects within the collections must also have a unique name anyway. * Full scene copy and delete scene are exactly doing the right thing yet. Differential Revision: https://developer.blender.org/D3383 https://code.blender.org/2018/05/collections-and-groups/
Diffstat (limited to 'source/blender/editors/object')
-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
8 files changed, 411 insertions, 479 deletions
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);