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.c653
1 files changed, 293 insertions, 360 deletions
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index eed3f2ea90c..9520b03f3a6 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -33,6 +33,7 @@
#include "DNA_collection_types.h"
#include "DNA_constraint_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
#include "DNA_light_types.h"
#include "DNA_material_types.h"
@@ -68,6 +69,7 @@
#include "BKE_gpencil.h"
#include "BKE_hair.h"
#include "BKE_idprop.h"
+#include "BKE_idtype.h"
#include "BKE_lattice.h"
#include "BKE_layer.h"
#include "BKE_lib_id.h"
@@ -357,7 +359,7 @@ static int make_proxy_invoke(bContext *C, wmOperator *op, const wmEvent *event)
WM_enum_search_invoke(C, op, event);
return OPERATOR_CANCELLED;
}
- else if (ID_IS_LINKED(ob)) {
+ if (ID_IS_LINKED(ob)) {
uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("OK?"), ICON_QUESTION);
uiLayout *layout = UI_popup_menu_layout(pup);
@@ -372,12 +374,10 @@ static int make_proxy_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* 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 proxy for a referenced object or collection");
- return OPERATOR_CANCELLED;
- }
+
+ /* error.. cannot continue */
+ BKE_report(op->reports, RPT_ERROR, "Can only make proxy for a referenced object or collection");
+ return OPERATOR_CANCELLED;
}
static int make_proxy_exec(bContext *C, wmOperator *op)
@@ -706,36 +706,34 @@ bool ED_object_parent_set(ReportList *reports,
if (par->type != OB_CURVE) {
return 0;
}
+ Curve *cu = par->data;
+ Curve *cu_eval = parent_eval->data;
+ if ((cu->flag & CU_PATH) == 0) {
+ cu->flag |= CU_PATH | CU_FOLLOW;
+ cu_eval->flag |= CU_PATH | CU_FOLLOW;
+ /* force creation of path data */
+ BKE_displist_make_curveTypes(depsgraph, scene, par, false, false);
+ }
else {
- Curve *cu = par->data;
- Curve *cu_eval = parent_eval->data;
- if ((cu->flag & CU_PATH) == 0) {
- cu->flag |= CU_PATH | CU_FOLLOW;
- cu_eval->flag |= CU_PATH | CU_FOLLOW;
- /* force creation of path data */
- BKE_displist_make_curveTypes(depsgraph, scene, par, false, false);
- }
- else {
- cu->flag |= CU_FOLLOW;
- cu_eval->flag |= CU_FOLLOW;
- }
+ cu->flag |= CU_FOLLOW;
+ cu_eval->flag |= CU_FOLLOW;
+ }
- /* if follow, add F-Curve for ctime (i.e. "eval_time") so that path-follow works */
- if (partype == PAR_FOLLOW) {
- /* get or create F-Curve */
- bAction *act = ED_id_action_ensure(bmain, &cu->id);
- FCurve *fcu = ED_action_fcurve_ensure(bmain, act, NULL, NULL, "eval_time", 0);
+ /* if follow, add F-Curve for ctime (i.e. "eval_time") so that path-follow works */
+ if (partype == PAR_FOLLOW) {
+ /* get or create F-Curve */
+ bAction *act = ED_id_action_ensure(bmain, &cu->id);
+ FCurve *fcu = ED_action_fcurve_ensure(bmain, act, NULL, NULL, "eval_time", 0);
- /* setup dummy 'generator' modifier here to get 1-1 correspondence still working */
- if (!fcu->bezt && !fcu->fpt && !fcu->modifiers.first) {
- add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR, fcu);
- }
+ /* setup dummy 'generator' modifier here to get 1-1 correspondence still working */
+ if (!fcu->bezt && !fcu->fpt && !fcu->modifiers.first) {
+ add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR, fcu);
}
+ }
- /* fall back on regular parenting now (for follow only) */
- if (partype == PAR_FOLLOW) {
- partype = PAR_OBJECT;
- }
+ /* fall back on regular parenting now (for follow only) */
+ if (partype == PAR_FOLLOW) {
+ partype = PAR_OBJECT;
}
}
else if (ELEM(partype, PAR_BONE, PAR_BONE_RELATIVE)) {
@@ -753,188 +751,185 @@ bool ED_object_parent_set(ReportList *reports,
BKE_report(reports, RPT_ERROR, "Loop in parents");
return false;
}
- else {
- Object workob;
- /* apply transformation of previous parenting */
- if (keep_transform) {
- /* was removed because of bug [#23577],
- * but this can be handy in some cases too [#32616], so make optional */
- BKE_object_apply_mat4(ob, ob->obmat, false, false);
- }
+ Object workob;
- /* set the parent (except for follow-path constraint option) */
- if (partype != PAR_PATH_CONST) {
- ob->parent = par;
- /* Always clear parentinv matrix for sake of consistency, see T41950. */
- unit_m4(ob->parentinv);
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- }
+ /* apply transformation of previous parenting */
+ if (keep_transform) {
+ /* was removed because of bug [#23577],
+ * but this can be handy in some cases too [#32616], so make optional */
+ BKE_object_apply_mat4(ob, ob->obmat, false, false);
+ }
- /* handle types */
- if (pchan) {
- BLI_strncpy(ob->parsubstr, pchan->name, sizeof(ob->parsubstr));
- }
- else {
- ob->parsubstr[0] = 0;
- }
+ /* set the parent (except for follow-path constraint option) */
+ if (partype != PAR_PATH_CONST) {
+ ob->parent = par;
+ /* Always clear parentinv matrix for sake of consistency, see T41950. */
+ unit_m4(ob->parentinv);
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ }
- if (partype == PAR_PATH_CONST) {
- /* don't do anything here, since this is not technically "parenting" */
- }
- else if (ELEM(partype, PAR_CURVE, PAR_LATTICE) || (pararm)) {
- /* partype is now set to PAROBJECT so that invisible 'virtual'
- * modifiers don't need to be created.
- * NOTE: the old (2.4x) method was to set ob->partype = PARSKEL,
- * creating the virtual modifiers.
- */
- ob->partype = PAROBJECT; /* note, dna define, not operator property */
- /* ob->partype = PARSKEL; */ /* note, dna define, not operator property */
+ /* handle types */
+ if (pchan) {
+ BLI_strncpy(ob->parsubstr, pchan->name, sizeof(ob->parsubstr));
+ }
+ else {
+ ob->parsubstr[0] = 0;
+ }
- /* BUT, to keep the deforms, we need a modifier,
- * and then we need to set the object that it uses
- * - We need to ensure that the modifier we're adding doesn't already exist,
- * so we check this by assuming that the parent is selected too.
- */
- /* XXX currently this should only happen for meshes, curves, surfaces,
- * and lattices - this stuff isn't available for metas yet */
- if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
- ModifierData *md;
-
- switch (partype) {
- case PAR_CURVE: /* curve deform */
- if (BKE_modifiers_is_deformed_by_curve(ob) != par) {
- md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Curve);
- if (md) {
- ((CurveModifierData *)md)->object = par;
- }
- if (par->runtime.curve_cache && par->runtime.curve_cache->path == NULL) {
- DEG_id_tag_update(&par->id, ID_RECALC_GEOMETRY);
- }
+ if (partype == PAR_PATH_CONST) {
+ /* don't do anything here, since this is not technically "parenting" */
+ }
+ else if (ELEM(partype, PAR_CURVE, PAR_LATTICE) || (pararm)) {
+ /* partype is now set to PAROBJECT so that invisible 'virtual'
+ * modifiers don't need to be created.
+ * NOTE: the old (2.4x) method was to set ob->partype = PARSKEL,
+ * creating the virtual modifiers.
+ */
+ ob->partype = PAROBJECT; /* note, dna define, not operator property */
+ /* ob->partype = PARSKEL; */ /* note, dna define, not operator property */
+
+ /* BUT, to keep the deforms, we need a modifier,
+ * and then we need to set the object that it uses
+ * - We need to ensure that the modifier we're adding doesn't already exist,
+ * so we check this by assuming that the parent is selected too.
+ */
+ /* XXX currently this should only happen for meshes, curves, surfaces,
+ * and lattices - this stuff isn't available for metas yet */
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
+ ModifierData *md;
+
+ switch (partype) {
+ case PAR_CURVE: /* curve deform */
+ if (BKE_modifiers_is_deformed_by_curve(ob) != par) {
+ md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Curve);
+ if (md) {
+ ((CurveModifierData *)md)->object = par;
}
- break;
- case PAR_LATTICE: /* lattice deform */
- if (BKE_modifiers_is_deformed_by_lattice(ob) != par) {
- md = ED_object_modifier_add(
- reports, bmain, scene, ob, NULL, eModifierType_Lattice);
- if (md) {
- ((LatticeModifierData *)md)->object = par;
- }
+ if (par->runtime.curve_cache && par->runtime.curve_cache->path == NULL) {
+ DEG_id_tag_update(&par->id, ID_RECALC_GEOMETRY);
}
- break;
- default: /* armature deform */
- if (BKE_modifiers_is_deformed_by_armature(ob) != par) {
- md = ED_object_modifier_add(
- reports, bmain, scene, ob, NULL, eModifierType_Armature);
- if (md) {
- ((ArmatureModifierData *)md)->object = par;
- }
+ }
+ break;
+ case PAR_LATTICE: /* lattice deform */
+ if (BKE_modifiers_is_deformed_by_lattice(ob) != par) {
+ md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Lattice);
+ if (md) {
+ ((LatticeModifierData *)md)->object = par;
}
- break;
- }
- }
- }
- else if (partype == PAR_BONE) {
- ob->partype = PARBONE; /* note, dna define, not operator property */
- if (pchan->bone) {
- pchan->bone->flag &= ~BONE_RELATIVE_PARENTING;
- pchan_eval->bone->flag &= ~BONE_RELATIVE_PARENTING;
- }
- }
- else if (partype == PAR_BONE_RELATIVE) {
- ob->partype = PARBONE; /* note, dna define, not operator property */
- if (pchan->bone) {
- pchan->bone->flag |= BONE_RELATIVE_PARENTING;
- pchan_eval->bone->flag |= BONE_RELATIVE_PARENTING;
+ }
+ break;
+ default: /* armature deform */
+ if (BKE_modifiers_is_deformed_by_armature(ob) != par) {
+ md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Armature);
+ if (md) {
+ ((ArmatureModifierData *)md)->object = par;
+ }
+ }
+ break;
}
}
- else if (partype == PAR_VERTEX) {
- ob->partype = PARVERT1;
- ob->par1 = vert_par[0];
- }
- else if (partype == PAR_VERTEX_TRI) {
- ob->partype = PARVERT3;
- copy_v3_v3_int(&ob->par1, vert_par);
+ }
+ else if (partype == PAR_BONE) {
+ ob->partype = PARBONE; /* note, dna define, not operator property */
+ if (pchan->bone) {
+ pchan->bone->flag &= ~BONE_RELATIVE_PARENTING;
+ pchan_eval->bone->flag &= ~BONE_RELATIVE_PARENTING;
}
- else {
- ob->partype = PAROBJECT; /* note, dna define, not operator property */
+ }
+ else if (partype == PAR_BONE_RELATIVE) {
+ ob->partype = PARBONE; /* note, dna define, not operator property */
+ if (pchan->bone) {
+ pchan->bone->flag |= BONE_RELATIVE_PARENTING;
+ pchan_eval->bone->flag |= BONE_RELATIVE_PARENTING;
}
+ }
+ else if (partype == PAR_VERTEX) {
+ ob->partype = PARVERT1;
+ ob->par1 = vert_par[0];
+ }
+ else if (partype == PAR_VERTEX_TRI) {
+ ob->partype = PARVERT3;
+ copy_v3_v3_int(&ob->par1, vert_par);
+ }
+ else {
+ ob->partype = PAROBJECT; /* note, dna define, not operator property */
+ }
- /* constraint */
- if (partype == PAR_PATH_CONST) {
- bConstraint *con;
- bFollowPathConstraint *data;
- float cmat[4][4], vec[3];
+ /* constraint */
+ if (partype == PAR_PATH_CONST) {
+ bConstraint *con;
+ bFollowPathConstraint *data;
+ float cmat[4][4], vec[3];
- con = BKE_constraint_add_for_object(ob, "AutoPath", CONSTRAINT_TYPE_FOLLOWPATH);
+ con = BKE_constraint_add_for_object(ob, "AutoPath", CONSTRAINT_TYPE_FOLLOWPATH);
- data = con->data;
- data->tar = par;
+ data = con->data;
+ data->tar = par;
- 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]);
+ 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);
+ 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, depsgraph, scene, ob, par, ARM_GROUPS_NAME, false);
}
- else if (pararm && (ob->type == OB_MESH) && (par->type == OB_ARMATURE)) {
- 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, depsgraph, scene, ob, par, ARM_GROUPS_AUTO, xmirror);
- WM_cursor_wait(0);
- }
- /* get corrected inverse */
- ob->partype = PAROBJECT;
- BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
-
- invert_m4_m4(ob->parentinv, workob.obmat);
+ else if (partype == PAR_ARMATURE_ENVELOPE) {
+ ED_object_vgroup_calc_from_armature(
+ reports, depsgraph, scene, ob, par, ARM_GROUPS_ENVELOPE, xmirror);
}
- else if (pararm && (ob->type == OB_GPENCIL) && (par->type == OB_ARMATURE)) {
- if (partype == PAR_ARMATURE) {
- ED_gpencil_add_armature(C, reports, ob, par);
- }
- else if (partype == PAR_ARMATURE_NAME) {
- ED_gpencil_add_armature_weights(C, reports, ob, par, GP_PAR_ARMATURE_NAME);
- }
- else if ((partype == PAR_ARMATURE_AUTO) || (partype == PAR_ARMATURE_ENVELOPE)) {
- WM_cursor_wait(1);
- ED_gpencil_add_armature_weights(C, reports, ob, par, GP_PAR_ARMATURE_AUTO);
- WM_cursor_wait(0);
- }
- /* get corrected inverse */
- ob->partype = PAROBJECT;
- BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
-
- invert_m4_m4(ob->parentinv, workob.obmat);
+ else if (partype == PAR_ARMATURE_AUTO) {
+ WM_cursor_wait(1);
+ ED_object_vgroup_calc_from_armature(
+ reports, depsgraph, scene, ob, par, ARM_GROUPS_AUTO, xmirror);
+ WM_cursor_wait(0);
}
- else if ((ob->type == OB_GPENCIL) && (par->type == OB_LATTICE)) {
- /* Add Lattice modifier */
- if (partype == PAR_LATTICE) {
- ED_gpencil_add_lattice_modifier(C, reports, ob, par);
- }
- /* get corrected inverse */
- ob->partype = PAROBJECT;
- BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
+ /* get corrected inverse */
+ ob->partype = PAROBJECT;
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- invert_m4_m4(ob->parentinv, workob.obmat);
+ invert_m4_m4(ob->parentinv, workob.obmat);
+ }
+ else if (pararm && (ob->type == OB_GPENCIL) && (par->type == OB_ARMATURE)) {
+ if (partype == PAR_ARMATURE) {
+ ED_gpencil_add_armature(C, reports, ob, par);
}
- else {
- /* calculate inverse parent matrix */
- BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- invert_m4_m4(ob->parentinv, workob.obmat);
+ else if (partype == PAR_ARMATURE_NAME) {
+ ED_gpencil_add_armature_weights(C, reports, ob, par, GP_PAR_ARMATURE_NAME);
+ }
+ else if ((partype == PAR_ARMATURE_AUTO) || (partype == PAR_ARMATURE_ENVELOPE)) {
+ WM_cursor_wait(1);
+ ED_gpencil_add_armature_weights(C, reports, ob, par, GP_PAR_ARMATURE_AUTO);
+ WM_cursor_wait(0);
+ }
+ /* get corrected inverse */
+ ob->partype = PAROBJECT;
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
+
+ invert_m4_m4(ob->parentinv, workob.obmat);
+ }
+ else if ((ob->type == OB_GPENCIL) && (par->type == OB_LATTICE)) {
+ /* Add Lattice modifier */
+ if (partype == PAR_LATTICE) {
+ ED_gpencil_add_lattice_modifier(C, reports, ob, par);
}
+ /* get corrected inverse */
+ ob->partype = PAROBJECT;
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ invert_m4_m4(ob->parentinv, workob.obmat);
}
+ else {
+ /* calculate inverse parent matrix */
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
+ invert_m4_m4(ob->parentinv, workob.obmat);
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
}
return true;
@@ -1122,9 +1117,7 @@ static bool parent_set_poll_property(const bContext *UNUSED(C),
if (ELEM(type, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO)) {
return true;
}
- else {
- return false;
- }
+ return false;
}
return true;
@@ -1771,7 +1764,10 @@ static Collection *single_object_users_collection(Main *bmain,
/* Generate new copies for objects in given collection and all its children,
* and optionally also copy collections themselves. */
if (copy_collections && !is_master_collection) {
- collection = ID_NEW_SET(collection, BKE_collection_copy(bmain, NULL, collection));
+ Collection *collection_new;
+ BKE_id_copy(bmain, &collection->id, (ID **)&collection_new);
+ id_us_min(&collection_new->id);
+ collection = ID_NEW_SET(collection, collection_new);
}
/* We do not remap to new objects here, this is done in separate step. */
@@ -1882,7 +1878,7 @@ static void single_obdata_users(
/* Needed to remap texcomesh below. */
me = ob->data = ID_NEW_SET(ob->data, BKE_mesh_copy(bmain, ob->data));
if (me->key) { /* We do not need to set me->key->id.newid here... */
- BKE_animdata_copy_id_action(bmain, (ID *)me->key, false);
+ BKE_animdata_copy_id_action(bmain, (ID *)me->key);
}
break;
case OB_MBALL:
@@ -1895,13 +1891,13 @@ static void single_obdata_users(
ID_NEW_REMAP(cu->bevobj);
ID_NEW_REMAP(cu->taperobj);
if (cu->key) { /* We do not need to set cu->key->id.newid here... */
- BKE_animdata_copy_id_action(bmain, (ID *)cu->key, false);
+ BKE_animdata_copy_id_action(bmain, (ID *)cu->key);
}
break;
case OB_LATTICE:
ob->data = lat = ID_NEW_SET(ob->data, BKE_lattice_copy(bmain, ob->data));
if (lat->key) { /* We do not need to set lat->key->id.newid here... */
- BKE_animdata_copy_id_action(bmain, (ID *)lat->key, false);
+ BKE_animdata_copy_id_action(bmain, (ID *)lat->key);
}
break;
case OB_ARMATURE:
@@ -1941,7 +1937,7 @@ static void single_obdata_users(
* AnimData structure, which is not what we want.
* (sergey)
*/
- BKE_animdata_copy_id_action(bmain, (ID *)ob->data, false);
+ BKE_animdata_copy_id_action(bmain, (ID *)ob->data);
id_us_min(id);
}
@@ -1962,7 +1958,7 @@ static void single_object_action_users(
FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
if (!ID_IS_LINKED(ob)) {
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- BKE_animdata_copy_id_action(bmain, &ob->id, false);
+ BKE_animdata_copy_id_action(bmain, &ob->id);
}
}
FOREACH_OBJECT_FLAG_END;
@@ -1984,7 +1980,7 @@ static void single_mat_users(
if (ma->id.us > 1) {
man = BKE_material_copy(bmain, ma);
- BKE_animdata_copy_id_action(bmain, &man->id, false);
+ BKE_animdata_copy_id_action(bmain, &man->id);
man->id.us = 0;
BKE_object_material_assign(bmain, ob, man, a, BKE_MAT_ASSIGN_USERPREF);
@@ -2246,52 +2242,22 @@ void OBJECT_OT_make_local(wmOperatorType *ot)
/** \name Make Library Override Operator
* \{ */
-static void make_override_library_tag_object(Object *obact, Object *ob)
+static bool make_override_library_ovject_overridable_check(Main *bmain, Object *object)
{
- 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;
- }
- }
+ /* An object is actually overrideable only if it is in at least one local collections.
+ * Unfortunately 'direct link' flag is not enough here. */
+ LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
+ if (!ID_IS_LINKED(collection) && BKE_collection_has_object(collection, object)) {
+ return true;
}
}
- 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);
- }
-}
-
-static void make_override_library_tag_collections(Collection *collection)
-{
- collection->id.tag |= LIB_TAG_DOIT;
- for (CollectionChild *coll_child = collection->children.first; coll_child != NULL;
- coll_child = coll_child->next) {
- make_override_library_tag_collections(coll_child->collection);
- }
+ return false;
}
/* Set the object to override. */
static int make_override_library_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Object *obact = ED_object_active_context(C);
@@ -2300,14 +2266,9 @@ static int make_override_library_invoke(bContext *C, wmOperator *op, const wmEve
return OPERATOR_CANCELLED;
}
- /* Get object to work on - use a menu if we need to... */
- if (!ID_IS_LINKED(obact) && obact->instance_collection != NULL &&
- ID_IS_LINKED(obact->instance_collection)) {
- /* Gives menu with list of objects in group. */
- WM_enum_search_invoke(C, op, event);
- return OPERATOR_CANCELLED;
- }
- else if (ID_IS_LINKED(obact)) {
+ if ((!ID_IS_LINKED(obact) && obact->instance_collection != NULL &&
+ ID_IS_OVERRIDABLE_LIBRARY(obact->instance_collection)) ||
+ make_override_library_ovject_overridable_check(bmain, obact)) {
uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("OK?"), ICON_QUESTION);
uiLayout *layout = UI_popup_menu_layout(pup);
@@ -2322,21 +2283,27 @@ static int make_override_library_invoke(bContext *C, wmOperator *op, const wmEve
/* 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 library override for a referenced object or collection");
+ else if (ID_IS_LINKED(obact)) {
+ /* Show menu with list of directly linked collections containing the active object. */
+ WM_enum_search_invoke(C, op, event);
return OPERATOR_CANCELLED;
}
+
+ /* Error.. cannot continue. */
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Can only make library override for a referenced object or collection");
+ return OPERATOR_CANCELLED;
}
static int make_override_library_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 *obact = CTX_data_active_object(C);
-
- bool success = false;
+ ID *id_root = NULL;
+ bool is_override_instancing_object = false;
if (!ID_IS_LINKED(obact) && obact->instance_collection != NULL &&
ID_IS_LINKED(obact->instance_collection)) {
@@ -2348,115 +2315,50 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
-
- Object *obcollection = obact;
- Collection *collection = obcollection->instance_collection;
-
- const ListBase dup_collection_objects = BKE_collection_object_cache_get(collection);
- Base *base = BLI_findlink(&dup_collection_objects, RNA_enum_get(op->ptr, "object"));
- obact = base->object;
-
- /* First, we make a library override of the linked collection itself, and all its children. */
- make_override_library_tag_collections(collection);
-
- /* Then, we make library 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;
- }
- }
- }
+ id_root = &obact->instance_collection->id;
+ is_override_instancing_object = true;
+ }
+ else if (!make_override_library_ovject_overridable_check(bmain, obact)) {
+ const int i = RNA_property_enum_get(op->ptr, op->type->prop);
+ const uint collection_session_uuid = *((uint *)&i);
+ if (collection_session_uuid == MAIN_ID_SESSION_UUID_UNSET) {
+ BKE_reportf(op->reports,
+ RPT_ERROR_INVALID_INPUT,
+ "Active object '%s' is not overridable",
+ obact->id.name + 2);
+ return OPERATOR_CANCELLED;
}
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
-
- success = BKE_lib_override_library_create_from_tag(bmain);
- /* Instantiate 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;
-
- BKE_collection_add_from_object(bmain, scene, obcollection, new_collection);
-
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (new_collection, new_ob) {
- if (new_ob != NULL && new_ob->id.override_library != NULL) {
- if ((base = BKE_view_layer_base_find(view_layer, new_ob)) == NULL) {
- BKE_collection_object_add_from(bmain, scene, obcollection, new_ob);
- base = BKE_view_layer_base_find(view_layer, new_ob);
- DEG_id_tag_update_ex(bmain, &new_ob->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS);
- }
-
- if (new_ob == (Object *)obact->id.newid) {
- /* TODO: is setting active needed? */
- BKE_view_layer_base_select_and_set_active(view_layer, base);
- }
- else {
- /* Disable auto-override tags for non-active objects, will help with performaces... */
- new_ob->id.override_library->flag &= ~OVERRIDE_LIBRARY_AUTO;
- }
- /* We still want to store all objects' current override status (i.e. change of parent). */
- BKE_lib_override_library_operations_create(bmain, &new_ob->id, true);
- }
+ Collection *collection = BLI_listbase_bytes_find(&bmain->collections,
+ &collection_session_uuid,
+ sizeof(collection_session_uuid),
+ offsetof(ID, session_uuid));
+ if (!ID_IS_OVERRIDABLE_LIBRARY(collection)) {
+ BKE_reportf(op->reports,
+ RPT_ERROR_INVALID_INPUT,
+ "Could not find an overridable collection containing object '%s'",
+ obact->id.name + 2);
+ return OPERATOR_CANCELLED;
}
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
-
- /* Remove the instance empty from this scene, the items now have an overridden collection
- * instead. */
- ED_object_base_free_and_unlink(bmain, scene, obcollection);
-
- /* Also, we'd likely want to lock by default things like
- * transformations of implicitly overridden objects? */
-
- DEG_id_tag_update(&scene->id, 0);
-
- /* Cleanup. */
- BKE_main_id_clear_newpoins(bmain);
- BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
- }
- else if (!ID_IS_OVERRIDABLE_LIBRARY(obact)) {
- BKE_reportf(op->reports,
- RPT_ERROR_INVALID_INPUT,
- "Active object '%s' is not overridable",
- obact->id.name + 2);
- return OPERATOR_CANCELLED;
+ id_root = &collection->id;
}
/* 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->objects.first; ob != NULL; ob = ob->id.next) {
- make_override_library_tag_object(obact, ob);
- }
+ else {
+ id_root = &obact->id;
+ }
- success = BKE_lib_override_library_create_from_tag(bmain);
+ BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
- /* Also, we'd likely want to lock by default things like
- * transformations of implicitly overridden objects? */
+ const bool success = BKE_lib_override_library_create(
+ bmain, scene, view_layer, id_root, &obact->id);
- /* Cleanup. */
- BKE_main_id_clear_newpoins(bmain);
- BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
- }
- /* TODO: probably more cases where we want to do automated smart things in the future! */
- else {
- /* For now, remapp all local usages of linked ID to local override one here. */
- BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, true);
- success = (BKE_lib_override_library_create_from_id(bmain, &obact->id, true) != NULL);
- BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
+ /* Remove the instance empty from this scene, the items now have an overridden collection
+ * instead. */
+ if (success && is_override_instancing_object) {
+ ED_object_base_free_and_unlink(bmain, scene, obact);
}
+ DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_BASE_FLAGS | ID_RECALC_COPY_ON_WRITE);
WM_event_add_notifier(C, NC_WINDOW, NULL);
return success ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
@@ -2467,10 +2369,40 @@ static bool make_override_library_poll(bContext *C)
Object *obact = CTX_data_active_object(C);
/* Object must be directly linked to be overridable. */
- return (BKE_lib_override_library_is_enabled() && ED_operator_objectmode(C) && obact != NULL &&
- ((ID_IS_LINKED(obact) && obact->id.tag & LIB_TAG_EXTERN) ||
- (!ID_IS_LINKED(obact) && obact->instance_collection != NULL &&
- ID_IS_LINKED(obact->instance_collection))));
+ return (ED_operator_objectmode(C) && obact != NULL &&
+ (ID_IS_LINKED(obact) || (obact->instance_collection != NULL &&
+ ID_IS_OVERRIDABLE_LIBRARY(obact->instance_collection))));
+}
+
+static const EnumPropertyItem *make_override_collections_of_linked_object_itemf(
+ bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ EnumPropertyItem item_tmp = {0}, *item = NULL;
+ int totitem = 0;
+
+ Object *object = ED_object_active_context(C);
+ Main *bmain = CTX_data_main(C);
+
+ if (!object || !ID_IS_LINKED(object)) {
+ return DummyRNA_DEFAULT_items;
+ }
+
+ LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
+ /* Only check for directly linked collections. */
+ if (!ID_IS_LINKED(&collection->id) || (collection->id.tag & LIB_TAG_INDIRECT) != 0) {
+ continue;
+ }
+ if (BKE_collection_has_object_recursive(collection, object)) {
+ item_tmp.identifier = item_tmp.name = collection->id.name + 2;
+ item_tmp.value = *((int *)&collection->id.session_uuid);
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ }
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
void OBJECT_OT_make_override_library(wmOperatorType *ot)
@@ -2491,12 +2423,13 @@ void OBJECT_OT_make_override_library(wmOperatorType *ot)
/* properties */
PropertyRNA *prop;
prop = RNA_def_enum(ot->srna,
- "object",
+ "collection",
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);
+ MAIN_ID_SESSION_UUID_UNSET,
+ "Override Collection",
+ "Name of directly linked collection containing the selected object, to make "
+ "an override from");
+ RNA_def_enum_funcs(prop, make_override_collections_of_linked_object_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
}