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/object/object_relations.c')
-rw-r--r--source/blender/editors/object/object_relations.c900
1 files changed, 459 insertions, 441 deletions
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 8abbb535981..f2e996237cf 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -63,21 +63,23 @@
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_camera.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_constraint.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#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"
#include "BKE_lattice.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
+#include "BKE_library_override.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
+#include "BKE_lightprobe.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mball.h"
@@ -86,12 +88,14 @@
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_report.h"
-#include "BKE_sca.h"
#include "BKE_scene.h"
#include "BKE_speaker.h"
#include "BKE_texture.h"
#include "BKE_editmesh.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -123,6 +127,8 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Object *obedit = CTX_data_edit_object(C);
BMVert *eve;
BMIter iter;
@@ -142,7 +148,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
EDBM_mesh_load(bmain, obedit);
EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
em = me->edit_btmesh;
@@ -151,7 +157,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
/* derivedMesh might be needed for solving parenting,
* so re-create it here */
- makeDerivedMesh(scene, obedit, em, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX, false);
+ makeDerivedMesh(depsgraph, scene, obedit, em, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX, false);
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
@@ -230,7 +236,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
if (ob != obedit) {
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
par = obedit->parent;
if (BKE_object_parent_loop_check(par, ob)) {
@@ -239,7 +245,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
else {
Object workob;
- ob->parent = BASACT->object;
+ ob->parent = BASACT(view_layer)->object;
if (v3) {
ob->partype = PARVERT3;
ob->par1 = v1 - 1;
@@ -247,7 +253,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
ob->par3 = v3 - 1;
/* inverse parent matrix */
- BKE_object_workob_calc_parent(scene, ob, &workob);
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
invert_m4_m4(ob->parentinv, workob.obmat);
}
else {
@@ -255,7 +261,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
ob->par1 = v1 - 1;
/* inverse parent matrix */
- BKE_object_workob_calc_parent(scene, ob, &workob);
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
invert_m4_m4(ob->parentinv, workob.obmat);
}
}
@@ -263,7 +269,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT, NULL);
@@ -322,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;
}
@@ -332,44 +338,42 @@ static int make_proxy_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Object *ob, *gob = ED_object_active_context(C);
- GroupObject *go;
Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
if (gob->dup_group != NULL) {
- go = BLI_findlink(&gob->dup_group->gobject, RNA_enum_get(op->ptr, "object"));
- ob = go->ob;
+ 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 {
ob = gob;
- gob = NULL;
}
if (ob) {
Object *newob;
- Base *newbase, *oldbase = BASACT;
char name[MAX_ID_NAME + 4];
BLI_snprintf(name, sizeof(name), "%s_proxy", ((ID *)(gob ? gob : ob))->name + 2);
/* Add new object for the proxy */
- newob = BKE_object_add(bmain, scene, OB_EMPTY, name);
+ newob = BKE_object_add_from(bmain, scene, view_layer, OB_EMPTY, name, gob ? gob : ob);
/* set layers OK */
- newbase = BASACT; /* BKE_object_add sets active... */
- newbase->lay = oldbase->lay;
- newob->lay = newbase->lay;
-
- /* remove base, leave user count of object, it gets linked in BKE_object_make_proxy */
- if (gob == NULL) {
- BKE_scene_base_unlink(scene, oldbase);
- MEM_freeN(oldbase);
- }
-
BKE_object_make_proxy(newob, ob, gob);
+ /* Set back pointer immediately so dependency graph knows that this is
+ * is a proxy and will act accordingly. Otherwise correctness of graph
+ * will depend on order of bases.
+ *
+ * TODO(sergey): We really need to get rid of this bi-directional links
+ * in proxies with something like static overrides.
+ */
+ newob->proxy->proxy_from = newob;
+
/* depsgraph flushes are needed for the new data */
- DAG_relations_tag_update(bmain);
- DAG_id_tag_update(&newob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&newob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, newob);
}
else {
@@ -381,24 +385,25 @@ 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;
int i = 0;
Object *ob = ED_object_active_context(C);
- GroupObject *go;
if (!ob || !ob->dup_group)
return DummyRNA_DEFAULT_items;
/* find the object to affect */
- for (go = ob->dup_group->gobject.first; go; go = go->next) {
- item_tmp.identifier = item_tmp.name = go->ob->id.name + 2;
+ 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_COLLECTION_OBJECT_RECURSIVE_END;
RNA_enum_item_end(&item, &totitem);
*r_free = true;
@@ -426,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;
}
@@ -524,7 +529,7 @@ void ED_object_parent_clear(Object *ob, const int type)
/* Always clear parentinv matrix for sake of consistency, see T41950. */
unit_m4(ob->parentinv);
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
/* note, poll should check for editable scene */
@@ -539,7 +544,7 @@ static int parent_clear_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- DAG_relations_tag_update(bmain);
+ 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);
return OPERATOR_FINISHED;
@@ -607,13 +612,15 @@ EnumPropertyItem prop_make_parent_types[] = {
{0, NULL, 0, NULL, NULL}
};
-bool ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object *ob, Object *par,
+bool ED_object_parent_set(ReportList *reports, const bContext *C, Scene *scene, Object *ob, Object *par,
int partype, const bool xmirror, const bool keep_transform, const int vert_par[3])
{
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
bPoseChannel *pchan = NULL;
const bool pararm = ELEM(partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO);
- DAG_id_tag_update(&par->id, OB_RECALC_OB);
+ DEG_id_tag_update(&par->id, OB_RECALC_OB);
/* preconditions */
if (partype == PAR_FOLLOW || partype == PAR_PATH_CONST) {
@@ -624,7 +631,7 @@ bool ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
if ((cu->flag & CU_PATH) == 0) {
cu->flag |= CU_PATH | CU_FOLLOW;
- BKE_displist_make_curveTypes(scene, par, 0); /* force creation of path data */
+ BKE_displist_make_curveTypes(depsgraph, scene, par, 0); /* force creation of path data */
}
else {
cu->flag |= CU_FOLLOW;
@@ -710,7 +717,7 @@ bool ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
((CurveModifierData *)md)->object = par;
}
if (par->curve_cache && par->curve_cache->path == NULL) {
- DAG_id_tag_update(&par->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&par->id, OB_RECALC_DATA);
}
}
break;
@@ -766,34 +773,36 @@ bool ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object
data = con->data;
data->tar = par;
- BKE_constraint_target_matrix_get(scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra);
+ BKE_constraint_target_matrix_get(depsgraph, scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra);
sub_v3_v3v3(vec, ob->obmat[3], cmat[3]);
copy_v3_v3(ob->loc, vec);
}
else if (pararm && (ob->type == OB_MESH) && (par->type == OB_ARMATURE)) {
- if (partype == PAR_ARMATURE_NAME)
- ED_object_vgroup_calc_from_armature(reports, scene, ob, par, ARM_GROUPS_NAME, false);
- else if (partype == PAR_ARMATURE_ENVELOPE)
- ED_object_vgroup_calc_from_armature(reports, scene, ob, par, ARM_GROUPS_ENVELOPE, xmirror);
+ if (partype == PAR_ARMATURE_NAME) {
+ ED_object_vgroup_calc_from_armature(reports, depsgraph, scene, ob, par, ARM_GROUPS_NAME, false);
+ }
+ else if (partype == PAR_ARMATURE_ENVELOPE) {
+ ED_object_vgroup_calc_from_armature(reports, depsgraph, scene, ob, par, ARM_GROUPS_ENVELOPE, xmirror);
+ }
else if (partype == PAR_ARMATURE_AUTO) {
WM_cursor_wait(1);
- ED_object_vgroup_calc_from_armature(reports, scene, ob, par, ARM_GROUPS_AUTO, xmirror);
+ ED_object_vgroup_calc_from_armature(reports, depsgraph, scene, ob, par, ARM_GROUPS_AUTO, xmirror);
WM_cursor_wait(0);
}
/* get corrected inverse */
ob->partype = PAROBJECT;
- BKE_object_workob_calc_parent(scene, ob, &workob);
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
invert_m4_m4(ob->parentinv, workob.obmat);
}
else {
/* calculate inverse parent matrix */
- BKE_object_workob_calc_parent(scene, ob, &workob);
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
invert_m4_m4(ob->parentinv, workob.obmat);
}
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
}
}
@@ -864,7 +873,7 @@ static int parent_set_exec(bContext *C, wmOperator *op)
parent_set_vert_find(tree, ob, vert_par, is_tri);
}
- if (!ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, xmirror, keep_transform, vert_par_p)) {
+ if (!ED_object_parent_set(op->reports, C, scene, ob, par, partype, xmirror, keep_transform, vert_par_p)) {
ok = false;
break;
}
@@ -879,7 +888,7 @@ static int parent_set_exec(bContext *C, wmOperator *op)
if (!ok)
return OPERATOR_CANCELLED;
- DAG_relations_tag_update(bmain);
+ 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);
@@ -963,7 +972,7 @@ static void parent_set_ui(bContext *C, wmOperator *op)
RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
/* Main auto-draw call. */
- uiDefAutoButsRNA(layout, &ptr, parent_set_draw_check_prop, '\0');
+ uiDefAutoButsRNA(layout, &ptr, parent_set_draw_check_prop, UI_BUT_LABEL_ALIGN_NONE, false);
}
void OBJECT_OT_parent_set(wmOperatorType *ot)
@@ -996,7 +1005,7 @@ static int parent_noinv_set_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
Object *par = ED_object_active_context(C);
- DAG_id_tag_update(&par->id, OB_RECALC_OB);
+ DEG_id_tag_update(&par->id, OB_RECALC_OB);
/* context iterator */
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
@@ -1011,7 +1020,7 @@ static int parent_noinv_set_exec(bContext *C, wmOperator *op)
memset(ob->loc, 0, 3 * sizeof(float));
/* set recalc flags */
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
/* set parenting type for object - object only... */
ob->parent = par;
@@ -1021,7 +1030,7 @@ static int parent_noinv_set_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
return OPERATOR_FINISHED;
@@ -1047,6 +1056,7 @@ void OBJECT_OT_parent_no_inverse_set(wmOperatorType *ot)
static int object_slow_parent_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *scene = CTX_data_scene(C);
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
@@ -1054,9 +1064,9 @@ static int object_slow_parent_clear_exec(bContext *C, wmOperator *UNUSED(op))
if (ob->parent) {
if (ob->partype & PARSLOW) {
ob->partype -= PARSLOW;
- BKE_object_where_is_calc(scene, ob);
+ BKE_object_where_is_calc(depsgraph, scene, ob);
ob->partype |= PARSLOW;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
}
}
}
@@ -1094,7 +1104,7 @@ static int object_slow_parent_set_exec(bContext *C, wmOperator *UNUSED(op))
if (ob->parent)
ob->partype |= PARSLOW;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB);
}
CTX_DATA_END;
@@ -1148,7 +1158,7 @@ static int object_track_clear_exec(bContext *C, wmOperator *op)
/* remove track-object for old track */
ob->track = NULL;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* also remove all tracking constraints */
for (con = ob->constraints.last; con; con = pcon) {
@@ -1162,7 +1172,7 @@ static int object_track_clear_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
return OPERATOR_FINISHED;
@@ -1222,7 +1232,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
data = con->data;
data->tar = obact;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* Lamp, Camera and Speaker track differently by default */
if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
@@ -1245,7 +1255,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
data = con->data;
data->tar = obact;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* Lamp, Camera and Speaker track differently by default */
if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
@@ -1269,7 +1279,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
data = con->data;
data->tar = obact;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* Lamp, Camera and Speaker track differently by default */
if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
@@ -1283,7 +1293,7 @@ static int track_set_exec(bContext *C, wmOperator *op)
}
}
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
return OPERATOR_FINISHED;
@@ -1309,119 +1319,6 @@ void OBJECT_OT_track_set(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_make_track_types, 0, "Type", "");
}
-/************************** Move to Layer Operator *****************************/
-
-static unsigned int move_to_layer_init(bContext *C, wmOperator *op)
-{
- int values[20], a;
- unsigned int lay = 0;
-
- if (!RNA_struct_property_is_set(op->ptr, "layers")) {
- /* note: layers are set in bases, library objects work for this */
- CTX_DATA_BEGIN (C, Base *, base, selected_bases)
- {
- lay |= base->lay;
- }
- CTX_DATA_END;
-
- for (a = 0; a < 20; a++)
- values[a] = (lay & (1 << a)) != 0;
-
- RNA_boolean_set_array(op->ptr, "layers", values);
- }
- else {
- RNA_boolean_get_array(op->ptr, "layers", values);
-
- for (a = 0; a < 20; a++)
- if (values[a])
- lay |= (1 << a);
- }
-
- return lay;
-}
-
-static int move_to_layer_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d && v3d->localvd) {
- return WM_operator_confirm_message(C, op, "Move out of Local View");
- }
- else {
- move_to_layer_init(C, op);
- return WM_operator_props_popup(C, op, event);
- }
-}
-
-static int move_to_layer_exec(bContext *C, wmOperator *op)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- unsigned int lay, local;
- /* bool is_lamp = false; */ /* UNUSED */
-
- lay = move_to_layer_init(C, op);
- lay &= 0xFFFFFF;
-
- if (lay == 0) return OPERATOR_CANCELLED;
-
- if (v3d && v3d->localvd) {
- /* now we can move out of localview. */
- /* note: layers are set in bases, library objects work for this */
- CTX_DATA_BEGIN (C, Base *, base, selected_bases)
- {
- lay = base->lay & ~v3d->lay;
- base->lay = lay;
- base->object->lay = lay;
- base->object->flag &= ~SELECT;
- base->flag &= ~SELECT;
- /* if (base->object->type == OB_LAMP) is_lamp = true; */
- }
- CTX_DATA_END;
- }
- else {
- /* normal non localview operation */
- /* note: layers are set in bases, library objects work for this */
- CTX_DATA_BEGIN (C, Base *, base, selected_bases)
- {
- /* upper byte is used for local view */
- local = base->lay & 0xFF000000;
- base->lay = lay + local;
- base->object->lay = base->lay;
- /* if (base->object->type == OB_LAMP) is_lamp = true; */
- }
- CTX_DATA_END;
- }
-
- /* warning, active object may be hidden now */
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
-
- DAG_relations_tag_update(bmain);
-
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_move_to_layer(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Move to Layer";
- ot->description = "Move the object to different layers";
- ot->idname = "OBJECT_OT_move_to_layer";
-
- /* api callbacks */
- ot->invoke = move_to_layer_invoke;
- ot->exec = move_to_layer_exec;
- ot->poll = ED_operator_objectmode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean_layer_member(ot->srna, "layers", 20, NULL, "Layer", "");
-}
-
/************************** Link to Scene Operator *****************************/
#if 0
@@ -1444,23 +1341,10 @@ static void link_to_scene(Main *UNUSED(bmain), unsigned short UNUSED(nr))
}
#endif
-Base *ED_object_scene_link(Scene *scene, Object *ob)
-{
- Base *base;
-
- if (BKE_scene_base_find(scene, ob)) {
- return NULL;
- }
-
- base = BKE_scene_base_add(scene, ob);
- id_us_plus(&ob->id);
-
- return base;
-}
-
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");
@@ -1477,9 +1361,10 @@ static int make_links_scene_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ Collection *collection_to = BKE_collection_master(scene_to);
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
{
- ED_object_scene_link(scene_to, base->object);
+ BKE_collection_object_add(bmain, collection_to, base->object);
}
CTX_DATA_END;
@@ -1495,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,
};
@@ -1516,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)) {
@@ -1534,23 +1419,23 @@ static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst
static int make_links_data_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ Main *bmain = CTX_data_main(C);
const int type = RNA_enum_get(op->ptr, "type");
Object *ob_src;
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(bmain, ob_src);
+ ob_collections = BKE_object_groups(bmain, ob_src);
}
CTX_DATA_BEGIN (C, Base *, base_dst, selected_editable_bases)
@@ -1572,7 +1457,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
/* if amount of material indices changed: */
test_object_materials(bmain, ob_dst, ob_dst->data);
- DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
break;
case MAKE_LINKS_MATERIALS:
/* new approach, using functions from kernel */
@@ -1580,30 +1465,30 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
Material *ma = give_current_material(ob_src, a + 1);
assign_material(bmain, ob_dst, ma, a + 1, BKE_MAT_ASSIGN_USERPREF); /* also works with ma==NULL */
}
- DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
break;
case MAKE_LINKS_ANIMDATA:
- BKE_animdata_copy_id(bmain, (ID *)ob_dst, (ID *)ob_src, false);
+ BKE_animdata_copy_id(bmain, (ID *)ob_dst, (ID *)ob_src, false, true);
if (ob_dst->data && ob_src->data) {
if (ID_IS_LINKED(obdata_id)) {
is_lib = true;
break;
}
- BKE_animdata_copy_id(bmain, (ID *)ob_dst->data, (ID *)ob_src->data, false);
+ BKE_animdata_copy_id(bmain, (ID *)ob_dst->data, (ID *)ob_src->data, false, true);
}
- DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
break;
case MAKE_LINKS_GROUP:
{
- LinkNode *group_node;
+ LinkNode *collection_node;
- /* first clear groups */
- BKE_object_groups_clear(bmain, scene, base_dst, 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, scene, base_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;
@@ -1611,16 +1496,16 @@ 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:
- BKE_object_link_modifiers(ob_dst, ob_src);
- DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ BKE_object_link_modifiers(scene, ob_dst, ob_src);
+ DEG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
break;
case MAKE_LINKS_FONTS:
{
@@ -1649,7 +1534,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
cu_dst->vfontbi = cu_src->vfontbi;
id_us_plus((ID *)cu_dst->vfontbi);
- DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
break;
}
}
@@ -1659,12 +1544,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");
}
}
@@ -1672,7 +1557,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_WARNING, "Skipped editing library object data");
}
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C));
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, CTX_wm_view3d(C));
WM_event_add_notifier(C, NC_OBJECT, NULL);
@@ -1712,7 +1597,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}};
@@ -1736,101 +1621,120 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
/**************************** Make Single User ********************************/
-/* 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)
+static Object *single_object_users_object(Main *bmain, Scene *scene, Object *ob)
{
- Base *base;
- Object *ob, *obn;
- Group *group, *groupn;
- GroupObject *go;
+ /* base gets copy of object */
+ Object *obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
- clear_sca_new_poins(); /* BGE logic */
+ /* remap gpencil parenting */
- /* duplicate (must set newid) */
- for (base = FIRSTBASE; base; base = base->next) {
- ob = base->object;
+ if (scene->gpd) {
+ bGPdata *gpd = scene->gpd;
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if (gpl->parent == ob) {
+ gpl->parent = obn;
+ }
+ }
+ }
+
+ id_us_plus(&obn->id);
+ id_us_min(&ob->id);
+ return obn;
+}
- if ((base->flag & flag) == flag) {
+static void libblock_relink_collection(Collection *collection)
+{
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ BKE_libblock_relink_to_newid(&cob->ob->id);
+ }
+
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ libblock_relink_collection(child->collection);
+ }
+}
+
+static void single_object_users_collection(Main *bmain, Scene *scene, Collection *collection, const int flag, const bool copy_collections)
+{
+ 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) {
- /* base gets copy of object */
- base->object = obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
+ cob->ob = single_object_users_object(bmain, scene, cob->ob);
+ }
+ }
+ }
- if (copy_groups) {
- if (ob->flag & OB_FROMGROUP) {
- obn->flag |= OB_FROMGROUP;
- }
- }
- else {
- /* copy already clears */
- }
- /* remap gpencil parenting */
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ single_object_users_collection(bmain, scene, child->collection, flag, copy_collections);
+ }
+}
- if (scene->gpd) {
- bGPdata *gpd = scene->gpd;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if (gpl->parent == ob) {
- gpl->parent = obn;
- }
- }
- }
+/* 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)
+{
+ Collection *collection, *collectionn;
- base->flag = obn->flag;
+ /* duplicate all the objects of the scene */
+ Collection *master_collection = BKE_collection_master(scene);
+ single_object_users_collection(bmain, scene, master_collection, flag, copy_collections);
- id_us_min(&ob->id);
- }
+ /* loop over ViewLayers and assign the pointers accordingly */
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ ID_NEW_REMAP(base->object);
}
}
- /* duplicate groups that consist entirely of duplicated objects */
- for (group = bmain->group.first; group; group = group->id.next) {
- if (copy_groups && group->gobject.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;
- for (go = group->gobject.first; go; go = go->next) {
- if (!(go->ob && (go->ob->id.newid))) {
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ any_duplicated = true;
+ if (cob->ob->id.newid == NULL) {
all_duplicated = false;
break;
}
}
- 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));
- for (go = groupn->gobject.first; go; go = go->next) {
- go->ob = (Object *)go->ob->id.newid;
+ for (CollectionObject *cob = collectionn->gobject.first; cob; cob = cob->next) {
+ cob->ob = (Object *)cob->ob->id.newid;
}
}
}
}
- /* 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 */
- for (base = FIRSTBASE; base; base = base->next) {
- BKE_libblock_relink_to_newid(&base->object->id);
- }
-
- set_sca_new_poins();
+ /* object and collection pointers */
+ libblock_relink_collection(master_collection);
}
/* not an especially efficient function, only added so the single user
* button can be functional.*/
void ED_object_single_user(Main *bmain, Scene *scene, Object *ob)
{
- Base *base;
- const bool copy_groups = false;
-
- for (base = FIRSTBASE; base; base = base->next) {
- if (base->object == ob) base->flag |= OB_DONE;
- else base->flag &= ~OB_DONE;
+ FOREACH_SCENE_OBJECT_BEGIN(scene, ob_iter)
+ {
+ ob_iter->flag &= ~OB_DONE;
}
+ FOREACH_SCENE_OBJECT_END;
- single_object_users(bmain, scene, NULL, OB_DONE, copy_groups);
+ /* tag only the one object */
+ ob->flag |= OB_DONE;
+ single_object_users(bmain, scene, NULL, OB_DONE, false);
BKE_main_id_clear_newpoins(bmain);
}
@@ -1855,34 +1759,26 @@ static void new_id_matar(Main *bmain, Material **matar, const int totcol)
}
}
-static void single_obdata_users(Main *bmain, Scene *scene, const int flag)
+static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer, const int flag)
{
- Object *ob;
Lamp *la;
Curve *cu;
/* Camera *cam; */
- Base *base;
Mesh *me;
Lattice *lat;
ID *id;
- int a;
- for (base = FIRSTBASE; base; base = base->next) {
- ob = base->object;
- if (!ID_IS_LINKED(ob) && (base->flag & flag) == flag) {
+ FOREACH_OBJECT_FLAG_BEGIN(scene, view_layer, flag, ob)
+ {
+ if (!ID_IS_LINKED(ob)) {
id = ob->data;
if (id && id->us > 1 && !ID_IS_LINKED(id)) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
switch (ob->type) {
case OB_LAMP:
ob->data = la = ID_NEW_SET(ob->data, BKE_lamp_copy(bmain, ob->data));
- for (a = 0; a < MAX_MTEX; a++) {
- if (la->mtex[a]) {
- ID_NEW_REMAP(la->mtex[a]->object);
- }
- }
break;
case OB_CAMERA:
ob->data = ID_NEW_SET(ob->data, BKE_camera_copy(bmain, ob->data));
@@ -1911,16 +1807,22 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag)
BKE_animdata_copy_id_action(bmain, (ID *)lat->key, false);
break;
case OB_ARMATURE:
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
ob->data = ID_NEW_SET(ob->data, BKE_armature_copy(bmain, ob->data));
BKE_pose_rebuild(ob, ob->data);
break;
case OB_SPEAKER:
ob->data = ID_NEW_SET(ob->data, BKE_speaker_copy(bmain, ob->data));
break;
+ case OB_LIGHTPROBE:
+ ob->data = ID_NEW_SET(ob->data, BKE_lightprobe_copy(bmain, ob->data));
+ break;
default:
- if (G.debug & G_DEBUG)
- printf("ERROR %s: can't copy %s\n", __func__, id->name);
+ printf("ERROR %s: can't copy %s\n", __func__, id->name);
+ BLI_assert(!"This should never happen.");
+
+ /* We need to end the FOREACH_OBJECT_FLAG_BEGIN iterator to prevent memory leak. */
+ BKE_scene_objects_iterator_end(&iter_macro);
return;
}
@@ -1935,6 +1837,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag)
}
}
}
+ FOREACH_OBJECT_FLAG_END;
me = bmain->mesh.first;
while (me) {
@@ -1943,31 +1846,26 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag)
}
}
-static void single_object_action_users(Main *bmain, Scene *scene, const int flag)
+static void single_object_action_users(Main *bmain, Scene *scene, ViewLayer *view_layer, const int flag)
{
- Object *ob;
- Base *base;
-
- for (base = FIRSTBASE; base; base = base->next) {
- ob = base->object;
- if (!ID_IS_LINKED(ob) && (flag == 0 || (base->flag & SELECT)) ) {
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ FOREACH_OBJECT_FLAG_BEGIN(scene, view_layer, flag, ob)
+ {
+ if (!ID_IS_LINKED(ob)) {
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
BKE_animdata_copy_id_action(bmain, &ob->id, false);
}
}
+ FOREACH_OBJECT_FLAG_END;
}
-static void single_mat_users(Main *bmain, Scene *scene, const int flag, const bool do_textures)
+static void single_mat_users(Main *bmain, Scene *scene, ViewLayer *view_layer, const int flag)
{
- Object *ob;
- Base *base;
Material *ma, *man;
- Tex *tex;
- int a, b;
+ int a;
- for (base = FIRSTBASE; base; base = base->next) {
- ob = base->object;
- if (!ID_IS_LINKED(ob) && (flag == 0 || (base->flag & SELECT)) ) {
+ FOREACH_OBJECT_FLAG_BEGIN(scene, view_layer, flag, ob)
+ {
+ if (!ID_IS_LINKED(ob)) {
for (a = 1; a <= ob->totcol; a++) {
ma = give_current_material(ob, a);
if (ma) {
@@ -1979,84 +1877,12 @@ static void single_mat_users(Main *bmain, Scene *scene, const int flag, const bo
man->id.us = 0;
assign_material(bmain, ob, man, a, BKE_MAT_ASSIGN_USERPREF);
-
- if (do_textures) {
- for (b = 0; b < MAX_MTEX; b++) {
- if (ma->mtex[b] && (tex = ma->mtex[b]->tex)) {
- if (tex->id.us > 1) {
- id_us_min(&tex->id);
- tex = BKE_texture_copy(bmain, tex);
- BKE_animdata_copy_id_action(bmain, &tex->id, false);
- man->mtex[b]->tex = tex;
- }
- }
- }
- }
}
}
}
}
}
-}
-
-static void do_single_tex_user(Main *bmain, Tex **from)
-{
- Tex *tex, *texn;
-
- tex = *from;
- if (tex == NULL) return;
-
- if (tex->id.newid) {
- *from = (Tex *)tex->id.newid;
- id_us_plus(tex->id.newid);
- id_us_min(&tex->id);
- }
- else if (tex->id.us > 1) {
- texn = ID_NEW_SET(tex, BKE_texture_copy(bmain, tex));
- BKE_animdata_copy_id_action(bmain, &texn->id, false);
- tex->id.newid = (ID *)texn;
- id_us_min(&tex->id);
- *from = texn;
- }
-}
-
-static void single_tex_users_expand(Main *bmain)
-{
- /* only when 'parent' blocks are LIB_TAG_NEW */
- Material *ma;
- Lamp *la;
- World *wo;
- int b;
-
- for (ma = bmain->mat.first; ma; ma = ma->id.next) {
- if (ma->id.tag & LIB_TAG_NEW) {
- for (b = 0; b < MAX_MTEX; b++) {
- if (ma->mtex[b] && ma->mtex[b]->tex) {
- do_single_tex_user(bmain, &(ma->mtex[b]->tex));
- }
- }
- }
- }
-
- for (la = bmain->lamp.first; la; la = la->id.next) {
- if (la->id.tag & LIB_TAG_NEW) {
- for (b = 0; b < MAX_MTEX; b++) {
- if (la->mtex[b] && la->mtex[b]->tex) {
- do_single_tex_user(bmain, &(la->mtex[b]->tex));
- }
- }
- }
- }
-
- for (wo = bmain->world.first; wo; wo = wo->id.next) {
- if (wo->id.tag & LIB_TAG_NEW) {
- for (b = 0; b < MAX_MTEX; b++) {
- if (wo->mtex[b] && wo->mtex[b]->tex) {
- do_single_tex_user(bmain, &(wo->mtex[b]->tex));
- }
- }
- }
- }
+ FOREACH_OBJECT_FLAG_END;
}
static void single_mat_users_expand(Main *bmain)
@@ -2066,8 +1892,6 @@ static void single_mat_users_expand(Main *bmain)
Mesh *me;
Curve *cu;
MetaBall *mb;
- Material *ma;
- int a;
for (ob = bmain->object.first; ob; ob = ob->id.next)
if (ob->id.tag & LIB_TAG_NEW)
@@ -2084,25 +1908,17 @@ static void single_mat_users_expand(Main *bmain)
for (mb = bmain->mball.first; mb; mb = mb->id.next)
if (mb->id.tag & LIB_TAG_NEW)
new_id_matar(bmain, mb->mat, mb->totcol);
-
- /* material imats */
- for (ma = bmain->mat.first; ma; ma = ma->id.next)
- if (ma->id.tag & LIB_TAG_NEW)
- for (a = 0; a < MAX_MTEX; a++)
- if (ma->mtex[a])
- ID_NEW_REMAP(ma->mtex[a]->object);
}
/* 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, 0);
- single_object_action_users(bmain, scene, 0);
+ single_obdata_users(bmain, scene, NULL, 0);
+ single_object_action_users(bmain, scene, NULL, 0);
single_mat_users_expand(bmain);
- single_tex_users_expand(bmain);
}
/* Relink nodetrees' pointers that have been duplicated. */
@@ -2121,12 +1937,13 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo
{
IDP_RelinkProperty(scene->id.properties);
- for (Base *base = scene->base.first; base; base = base->next) {
- Object *ob = base->object;
+ FOREACH_SCENE_OBJECT_BEGIN(scene, ob)
+ {
if (!ID_IS_LINKED(ob)) {
IDP_RelinkProperty(ob->id.properties);
}
}
+ FOREACH_SCENE_OBJECT_END;
if (scene->nodetree) {
IDP_RelinkProperty(scene->nodetree->id.properties);
@@ -2148,7 +1965,7 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo
}
}
BKE_main_id_clear_newpoins(bmain);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
/******************************* Make Local ***********************************/
@@ -2215,7 +2032,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)
+static bool make_local_all__instance_indirect_unused(Main *bmain, ViewLayer *view_layer, Collection *collection)
{
Object *ob;
bool changed = false;
@@ -2226,10 +2043,11 @@ static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene)
id_us_plus(&ob->id);
- base = BKE_scene_base_add(scene, ob);
- base->flag |= SELECT;
- base->object->flag = base->flag;
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ 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);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
changed = true;
}
@@ -2287,33 +2105,28 @@ static void make_local_material_tag(Material *ma)
make_local_animdata_tag(BKE_animdata_from_id(&ma->id));
/* About nodetrees: root one is made local together with material, others we keep linked for now... */
-
- for (int a = 0; a < MAX_MTEX; a++) {
- if (ma->mtex[a] && ma->mtex[a]->tex) {
- ma->mtex[a]->tex->id.tag &= ~LIB_TAG_PRE_EXISTING;
- }
- }
}
}
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;
- Lamp *la;
const int mode = RNA_enum_get(op->ptr, "type");
int a;
/* 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);
+ 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_scene_base_deselect_all(scene);
+ /* 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)) {
+ 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");
}
}
@@ -2350,16 +2163,6 @@ static int make_local_exec(bContext *C, wmOperator *op)
}
}
}
-
- if (ob->type == OB_LAMP) {
- BLI_assert(ob->data != NULL);
- la = ob->data;
- for (a = 0; a < MAX_MTEX; a++) {
- if (la->mtex[a] && la->mtex[a]->tex) {
- la->id.tag &= ~LIB_TAG_PRE_EXISTING;
- }
- }
- }
}
if (ELEM(mode, MAKE_LOCAL_SELECT_OBDATA, MAKE_LOCAL_SELECT_OBDATA_MATERIAL) && ob->data != NULL) {
@@ -2404,6 +2207,220 @@ void OBJECT_OT_make_local(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
}
+
+static void make_override_static_tag_object(Object *obact, Object *ob)
+{
+ if (ob == obact) {
+ return;
+ }
+
+ if (!ID_IS_LINKED(ob)) {
+ return;
+ }
+
+ /* Note: all this is very case-by-case bad handling, ultimately we'll want a real full 'automatic', generic
+ * handling of all this, will probably require adding some override-aware stuff to library_query code... */
+
+ if (obact->type == OB_ARMATURE && ob->modifiers.first != NULL) {
+ for (ModifierData *md = ob->modifiers.first; md != NULL; md = md->next) {
+ if (md->type == eModifierType_Armature) {
+ ArmatureModifierData *amd = (ArmatureModifierData *)md;
+ if (amd->object == obact) {
+ ob->id.tag |= LIB_TAG_DOIT;
+ break;
+ }
+ }
+ }
+ }
+ else if (ob->parent == obact) {
+ ob->id.tag |= LIB_TAG_DOIT;
+ }
+
+ if (ob->id.tag & LIB_TAG_DOIT) {
+ printf("Indirectly overriding %s for %s\n", ob->id.name, obact->id.name);
+ }
+}
+
+/* Set the object to override. */
+static int make_override_static_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Scene *scene = CTX_data_scene(C);
+ Object *obact = ED_object_active_context(C);
+
+ /* Sanity checks. */
+ if (!scene || ID_IS_LINKED(scene) || !obact) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Get object to work on - use a menu if we need to... */
+ if (!ID_IS_LINKED(obact) && obact->dup_group != NULL && ID_IS_LINKED(obact->dup_group)) {
+ /* Gives menu with list of objects in group. */
+ WM_enum_search_invoke(C, op, event);
+ return OPERATOR_CANCELLED;
+ }
+ else if (ID_IS_LINKED(obact)) {
+ uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("OK?"), ICON_QUESTION);
+ uiLayout *layout = UI_popup_menu_layout(pup);
+
+ /* Create operator menu item with relevant properties filled in. */
+ PointerRNA opptr_dummy;
+ uiItemFullO_ptr(layout, op->type, op->type->name, ICON_NONE, NULL,
+ WM_OP_EXEC_REGION_WIN, 0, &opptr_dummy);
+
+ /* Present the menu and be done... */
+ UI_popup_menu_end(C, pup);
+
+ /* This invoke just calls another instance of this operator... */
+ return OPERATOR_INTERFACE;
+ }
+ else {
+ /* Error.. cannot continue. */
+ BKE_report(op->reports, RPT_ERROR, "Can only make static override for a referenced object or collection");
+ return OPERATOR_CANCELLED;
+ }
+
+}
+
+static int make_override_static_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Object *obact = CTX_data_active_object(C);
+
+ bool success = false;
+
+ if (!ID_IS_LINKED(obact) && obact->dup_group != NULL && ID_IS_LINKED(obact->dup_group)) {
+ 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;
+ Collection *collection = obcollection->dup_group;
+
+ /* 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 Collection. */
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, ob)
+ {
+ ob->id.tag |= LIB_TAG_DOIT;
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+
+ /* Then, we remove (untag) bone shape objects, you shall never want to override those (hopefully)... */
+ 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) {
+ if (pchan->custom != NULL) {
+ pchan->custom->id.tag &= ~ LIB_TAG_DOIT;
+ }
+ }
+ }
+ }
+ 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);
+ 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) {
+ if ((base = BKE_view_layer_base_find(view_layer, new_ob)) == NULL) {
+ BKE_collection_object_add_from(bmain, scene, obcollection, new_ob);
+ DEG_id_tag_update_ex(bmain, &new_ob->id, DEG_TAG_TRANSFORM | DEG_TAG_BASE_FLAGS_UPDATE);
+ }
+ /* parent to 'collection' empty */
+ if (new_ob->parent == NULL) {
+ new_ob->parent = obcollection;
+ }
+ if (new_ob == (Object *)obact->id.newid) {
+ BKE_view_layer_base_select(view_layer, base);
+ }
+ else {
+ /* Disable auto-override tags for non-active objects, will help with performaces... */
+ new_ob->id.override_static->flag &= ~STATICOVERRIDE_AUTO;
+ }
+ /* We still want to store all objects' current override status (i.e. change of parent). */
+ BKE_override_static_operations_create(&new_ob->id, true);
+ }
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+
+ /* 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? */
+
+ DEG_id_tag_update(&scene->id, 0);
+
+ /* Cleanup. */
+ BKE_main_id_clear_newpoins(bmain);
+ BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, false);
+ }
+ /* Else, poll func ensures us that ID_IS_LINKED(obact) is true. */
+ else if (obact->type == OB_ARMATURE) {
+ BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
+
+ obact->id.tag |= LIB_TAG_DOIT;
+
+ for (Object *ob = bmain->object.first; ob != NULL; ob = ob->id.next) {
+ make_override_static_tag_object(obact, ob);
+ }
+
+ success = BKE_override_static_create_from_tag(bmain);
+
+ /* Also, we'd likely want to lock by default things like transformations of implicitly overriden objects? */
+
+ /* Cleanup. */
+ BKE_main_id_clear_newpoins(bmain);
+ BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, false);
+ }
+ /* TODO: probably more cases where we want to do automated smart things in the future! */
+ else {
+ success = (BKE_override_static_create_from_id(bmain, &obact->id) != NULL);
+ }
+
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+
+ return success ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+}
+
+static int make_override_static_poll(bContext *C)
+{
+ Object *obact = CTX_data_active_object(C);
+
+ /* Object must be directly linked to be overridable. */
+ return (ED_operator_objectmode(C) && obact != NULL &&
+ ((ID_IS_LINKED(obact) && obact->id.tag & LIB_TAG_EXTERN) ||
+ (!ID_IS_LINKED(obact) && obact->dup_group != NULL && ID_IS_LINKED(obact->dup_group))));
+}
+
+void OBJECT_OT_make_override_static(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Make Static Override";
+ ot->description = "Make local override of this library linked data-block";
+ ot->idname = "OBJECT_OT_make_override_static";
+
+ /* api callbacks */
+ ot->invoke = make_override_static_invoke;
+ ot->exec = make_override_static_exec;
+ ot->poll = make_override_static_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ PropertyRNA *prop;
+ prop = RNA_def_enum(ot->srna, "object", DummyRNA_DEFAULT_items, 0, "Override Object",
+ "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;
+}
+
enum {
MAKE_SINGLE_USER_ALL = 1,
MAKE_SINGLE_USER_SELECTED = 2,
@@ -2413,32 +2430,35 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ 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")) {
- single_object_users(bmain, scene, v3d, flag, copy_groups);
+ if (flag == SELECT) {
+ BKE_view_layer_selected_objects_tag(view_layer, OB_DONE);
+ single_object_users(bmain, scene, v3d, OB_DONE, copy_collections);
+ }
+ else {
+ single_object_users(bmain, scene, v3d, 0, copy_collections);
+ }
/* needed since object relationships may have changed */
update_deps = true;
}
if (RNA_boolean_get(op->ptr, "obdata")) {
- single_obdata_users(bmain, scene, flag);
+ single_obdata_users(bmain, scene, view_layer, flag);
}
if (RNA_boolean_get(op->ptr, "material")) {
- single_mat_users(bmain, scene, flag, RNA_boolean_get(op->ptr, "texture"));
+ single_mat_users(bmain, scene, view_layer, flag);
}
-#if 0 /* can't do this separate from materials */
- if (RNA_boolean_get(op->ptr, "texture"))
- single_mat_users(scene, flag, true);
-#endif
if (RNA_boolean_get(op->ptr, "animation")) {
- single_object_action_users(bmain, scene, flag);
+ single_object_action_users(bmain, scene, view_layer, flag);
}
BKE_main_id_clear_newpoins(bmain);
@@ -2446,7 +2466,7 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_WINDOW, NULL);
if (update_deps) {
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
return OPERATOR_FINISHED;
@@ -2478,8 +2498,6 @@ void OBJECT_OT_make_single_user(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "object", 0, "Object", "Make single user objects");
RNA_def_boolean(ot->srna, "obdata", 0, "Object Data", "Make single user object data");
RNA_def_boolean(ot->srna, "material", 0, "Materials", "Make materials local to each data-block");
- RNA_def_boolean(ot->srna, "texture", 0, "Textures",
- "Make textures local to each material (needs 'Materials' to be set too)");
RNA_def_boolean(ot->srna, "animation", 0, "Object Animation", "Make animation data local to each object");
}
@@ -2497,7 +2515,7 @@ static int drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent
assign_material(CTX_data_main(C), base->object, ma, 1, BKE_MAT_ASSIGN_USERPREF);
- DAG_id_tag_update(&base->object->id, OB_RECALC_OB);
+ DEG_id_tag_update(&base->object->id, OB_RECALC_OB);
WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, base->object);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C));