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.c696
1 files changed, 407 insertions, 289 deletions
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index f8c80f2a933..43d29b6f931 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -63,10 +63,10 @@
#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"
@@ -75,9 +75,12 @@
#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"
@@ -92,6 +95,9 @@
#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,7 +129,9 @@ static int vertex_parent_set_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);
Object *obedit = CTX_data_edit_object(C);
+ EvaluationContext eval_ctx;
BMVert *eve;
BMIter iter;
Curve *cu;
@@ -133,6 +141,8 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
Object *par;
int a, v1 = 0, v2 = 0, v3 = 0, v4 = 0, nr = 1;
+ CTX_data_eval_ctx(C, &eval_ctx);
+
/* we need 1 to 3 selected vertices */
if (obedit->type == OB_MESH) {
@@ -142,7 +152,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
EDBM_mesh_load(obedit);
EDBM_mesh_make(scene->toolsettings, obedit, true);
- DAG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, 0);
em = me->edit_btmesh;
@@ -151,7 +161,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(&eval_ctx, 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 +240,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 +249,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 +257,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(&eval_ctx, scene, ob, &workob);
invert_m4_m4(ob->parentinv, workob.obmat);
}
else {
@@ -255,7 +265,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(&eval_ctx, scene, ob, &workob);
invert_m4_m4(ob->parentinv, workob.obmat);
}
}
@@ -263,7 +273,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);
@@ -332,44 +342,41 @@ 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;
+ Base *base = BLI_findlink(&gob->dup_group->view_layer->object_bases, 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 {
@@ -388,17 +395,18 @@ static const EnumPropertyItem *proxy_group_object_itemf(bContext *C, PointerRNA
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_GROUP_OBJECT(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
RNA_enum_item_end(&item, &totitem);
*r_free = true;
@@ -524,7 +532,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 +547,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 +615,17 @@ 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);
+ EvaluationContext eval_ctx;
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);
+ CTX_data_eval_ctx(C, &eval_ctx);
+
+ DEG_id_tag_update(&par->id, OB_RECALC_OB);
/* preconditions */
if (partype == PAR_FOLLOW || partype == PAR_PATH_CONST) {
@@ -624,7 +636,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(&eval_ctx, scene, par, 0); /* force creation of path data */
}
else {
cu->flag |= CU_FOLLOW;
@@ -710,7 +722,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 +778,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(&eval_ctx, 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)
- create_vgroups_from_armature(reports, scene, ob, par, ARM_GROUPS_NAME, false);
- else if (partype == PAR_ARMATURE_ENVELOPE)
- create_vgroups_from_armature(reports, scene, ob, par, ARM_GROUPS_ENVELOPE, xmirror);
+ if (partype == PAR_ARMATURE_NAME) {
+ create_vgroups_from_armature(reports, &eval_ctx, scene, ob, par, ARM_GROUPS_NAME, false);
+ }
+ else if (partype == PAR_ARMATURE_ENVELOPE) {
+ create_vgroups_from_armature(reports, &eval_ctx, scene, ob, par, ARM_GROUPS_ENVELOPE, xmirror);
+ }
else if (partype == PAR_ARMATURE_AUTO) {
WM_cursor_wait(1);
- create_vgroups_from_armature(reports, scene, ob, par, ARM_GROUPS_AUTO, xmirror);
+ create_vgroups_from_armature(reports, &eval_ctx, 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(&eval_ctx, 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(&eval_ctx, 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 +878,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 +893,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);
@@ -996,7 +1010,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 +1025,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 +1035,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;
@@ -1048,15 +1062,18 @@ void OBJECT_OT_parent_no_inverse_set(wmOperatorType *ot)
static int object_slow_parent_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
{
if (ob->parent) {
if (ob->partype & PARSLOW) {
ob->partype -= PARSLOW;
- BKE_object_where_is_calc(scene, ob);
+ BKE_object_where_is_calc(&eval_ctx, 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 +1111,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 +1165,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 +1179,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 +1239,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 +1262,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 +1286,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 +1300,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 +1326,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,20 +1348,6 @@ 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"));
@@ -1477,9 +1367,10 @@ static int make_links_scene_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ SceneCollection *sc_to = BKE_collection_master(&scene_to->id);
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
{
- ED_object_scene_link(scene_to, base->object);
+ BKE_collection_object_add(&scene_to->id, sc_to, base->object);
}
CTX_DATA_END;
@@ -1535,7 +1426,6 @@ 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);
const int type = RNA_enum_get(op->ptr, "type");
Object *ob_src;
ID *obdata_id;
@@ -1572,7 +1462,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
/* if amount of material indices changed: */
test_object_materials(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,7 +1470,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
Material *ma = give_current_material(ob_src, a + 1);
assign_material(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);
@@ -1591,19 +1481,19 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
}
BKE_animdata_copy_id(bmain, (ID *)ob_dst->data, (ID *)ob_src->data, false);
}
- 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;
/* first clear groups */
- BKE_object_groups_clear(scene, base_dst, ob_dst);
+ BKE_object_groups_clear(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);
+ BKE_group_object_add(group_node->link, ob_dst);
}
else {
is_cycle = true;
@@ -1620,7 +1510,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
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);
+ DEG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
break;
case MAKE_LINKS_FONTS:
{
@@ -1649,7 +1539,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;
}
}
@@ -1672,7 +1562,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);
@@ -1736,69 +1626,103 @@ 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, const bool copy_groups)
{
- Base *base;
- Object *ob, *obn;
- Group *group, *groupn;
- GroupObject *go;
+ if (!ID_IS_LINKED(ob) && ob->id.us > 1) {
+ /* base gets copy of object */
+ Object *obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
- clear_sca_new_poins(); /* BGE logic */
+ if (copy_groups) {
+ if (ob->flag & OB_FROMGROUP) {
+ obn->flag |= OB_FROMGROUP;
+ }
+ }
+ else {
+ /* copy already clears */
+ }
+ /* 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;
+ }
+ }
+ }
- if ((base->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));
+ id_us_min(&ob->id);
+ return obn;
+ }
+ return NULL;
+}
- if (copy_groups) {
- if (ob->flag & OB_FROMGROUP) {
- obn->flag |= OB_FROMGROUP;
- }
- }
- else {
- /* copy already clears */
- }
- /* remap gpencil parenting */
+static void libblock_relink_scene_collection(SceneCollection *sc)
+{
+ for (LinkData *link = sc->objects.first; link; link = link->next) {
+ BKE_libblock_relink_to_newid(link->data);
+ }
- if (scene->gpd) {
- bGPdata *gpd = scene->gpd;
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if (gpl->parent == ob) {
- gpl->parent = obn;
- }
- }
- }
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ libblock_relink_scene_collection(nsc);
+ }
+}
+
+static void single_object_users_scene_collection(Main *bmain, Scene *scene, SceneCollection *sc, const int flag, const bool copy_groups)
+{
+ for (LinkData *link = sc->objects.first; link; link = link->next) {
+ Object *ob = link->data;
+ /* an object may be in more than one collection */
+ if ((ob->id.newid == NULL) && ((ob->flag & flag) == flag)) {
+ link->data = single_object_users_object(bmain, scene, link->data, copy_groups);
+ }
+ }
- base->flag = obn->flag;
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ single_object_users_scene_collection(bmain, scene, nsc, flag, copy_groups);
+ }
+}
- id_us_min(&ob->id);
- }
+/* 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)
+{
+ Group *group, *groupn;
+
+ clear_sca_new_poins(); /* BGE logic */
+
+ /* 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);
+
+ /* 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) {
+ if (copy_groups && group->view_layer->object_bases.first) {
bool all_duplicated = true;
- for (go = group->gobject.first; go; go = go->next) {
- if (!(go->ob && (go->ob->id.newid))) {
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ if (object->id.newid == NULL) {
all_duplicated = false;
break;
}
}
+ FOREACH_GROUP_OBJECT_END
if (all_duplicated) {
groupn = ID_NEW_SET(group, BKE_group_copy(bmain, group));
- for (go = groupn->gobject.first; go; go = go->next) {
- go->ob = (Object *)go->ob->id.newid;
+ FOREACH_GROUP_BASE(groupn, base)
+ {
+ base->object = (Object *)base->object->id.newid;
}
+ FOREACH_GROUP_BASE_END
}
}
}
@@ -1810,9 +1734,7 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
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);
- }
+ libblock_relink_scene_collection(msc);
set_sca_new_poins();
}
@@ -1821,16 +1743,16 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
* 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(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,25 +1777,23 @@ 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(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:
@@ -1911,16 +1831,22 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag)
BKE_animdata_copy_id_action((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 iterator to prevent memory leak. */
+ BKE_scene_objects_iterator_end(&iter_macro);
return;
}
@@ -1935,6 +1861,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 +1870,24 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag)
}
}
-static void single_object_action_users(Scene *scene, const int flag)
+static void single_object_action_users(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(scene, view_layer, flag, ob)
+ if (!ID_IS_LINKED(ob)) {
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
BKE_animdata_copy_id_action(&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, const bool do_textures)
{
- Object *ob;
- Base *base;
Material *ma, *man;
Tex *tex;
int a, b;
- for (base = FIRSTBASE; base; base = base->next) {
- ob = base->object;
- if (!ID_IS_LINKED(ob) && (flag == 0 || (base->flag & SELECT)) ) {
+ FOREACH_OBJECT_FLAG(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) {
@@ -1996,7 +1916,7 @@ static void single_mat_users(Main *bmain, Scene *scene, const int flag, const bo
}
}
}
- }
+ FOREACH_OBJECT_FLAG_END
}
static void do_single_tex_user(Main *bmain, Tex **from)
@@ -2099,8 +2019,8 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo
single_object_users(bmain, scene, NULL, 0, copy_groups);
if (full) {
- single_obdata_users(bmain, scene, 0);
- single_object_action_users(scene, 0);
+ single_obdata_users(bmain, scene, NULL, 0);
+ single_object_action_users(scene, NULL, 0);
single_mat_users_expand(bmain);
single_tex_users_expand(bmain);
}
@@ -2121,12 +2041,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(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 +2069,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 +2136,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, Scene *scene, ViewLayer *view_layer, SceneCollection *sc)
{
Object *ob;
bool changed = false;
@@ -2226,10 +2147,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(&scene->id, sc, 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;
}
@@ -2308,12 +2230,15 @@ 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);
+
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, scene, view_layer, scene_collection)) {
BKE_report(op->reports, RPT_INFO, "Orphan library objects added to the current scene to avoid loss");
}
}
@@ -2404,6 +2329,192 @@ 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 group");
+ 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)) {
+ Base *base = BLI_findlink(&obact->dup_group->view_layer->object_bases, RNA_enum_get(op->ptr, "object"));
+ Object *obgroup = obact;
+ obact = base->object;
+
+ /* First, we make a static override of the linked group itself. */
+ obgroup->dup_group->id.tag |= LIB_TAG_DOIT;
+
+ /* Then, we tag our 'main' object and its detected dependencies to be also overridden. */
+ obact->id.tag |= LIB_TAG_DOIT;
+
+ FOREACH_GROUP_OBJECT(obgroup->dup_group, ob)
+ {
+ make_override_static_tag_object(obact, ob);
+ }
+ FOREACH_GROUP_OBJECT_END;
+
+ success = BKE_override_static_create_from_tag(bmain);
+
+ /* Intantiate our 'main' newly overridden object in scene, if not yet done. */
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *new_obact = (Object *)obact->id.newid;
+ if (new_obact != NULL && (base = BKE_view_layer_base_find(view_layer, new_obact)) == NULL) {
+ BKE_collection_object_add_from(scene, obgroup, new_obact);
+ base = BKE_view_layer_base_find(view_layer, new_obact);
+ BKE_view_layer_base_select(view_layer, base);
+ }
+
+ /* Parent the group instantiating object to the new overridden one, or vice-versa, if possible. */
+ if (obgroup->parent == NULL) {
+ obgroup->parent = new_obact;
+ }
+ else if (new_obact->parent == NULL) {
+ new_obact->parent = obgroup;
+ }
+
+ /* 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);
+ }
+ /* 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 ot 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/group object to make an override from");
+ RNA_def_enum_funcs(prop, proxy_group_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,24 +2524,31 @@ 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;
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_groups);
+ }
+ else {
+ single_object_users(bmain, scene, v3d, 0, copy_groups);
+ }
/* 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, RNA_boolean_get(op->ptr, "texture"));
}
#if 0 /* can't do this separate from materials */
@@ -2438,7 +2556,7 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
single_mat_users(scene, flag, true);
#endif
if (RNA_boolean_get(op->ptr, "animation")) {
- single_object_action_users(scene, flag);
+ single_object_action_users(scene, view_layer, flag);
}
BKE_main_id_clear_newpoins(bmain);
@@ -2446,7 +2564,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;
@@ -2496,7 +2614,7 @@ static int drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent
assign_material(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));