From 85c9aefe0fef6d9f862d34ca66beb0bb4c2bcf6c Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 1 Jul 2016 17:51:08 +0200 Subject: "Fix" crash when deleting linked object which has indirect usages. This is in fact very hairy situation here... Objects are only refcounted by scenes, any other usage is 'free', which means once all object instanciations are gone Blender considers it can delete it. There is a trap here though: indirect usages. Typically, we should never modify linked data (because it is essencially useless, changes would be ignored and ost on next reload or even undo/redo). This means indirect usages are not affected by default 'safe' remapping/unlinking. For unlinking preceeding deletion however, this is not acceptable - we are likely to end with a zero-user ID (aka deletable one) which is still actually used by other linked data. Solution choosen here is double: I) From 'user-space' (i.e. outliner, operators...), we check for cases where deleting datablocks should not be allowed (indirect data or indirectly used data), and abort (with report) if needed. II) From 'lower' level (BKE_library_remap and RNA), we also unlink from linked data, which makes actual deletion possible and safe. Note that with previous behavior (2.77 one), linked object would be deleted, including from linked data - but then, once file is saved and reloaded, indirect usage would link back the deleted object, without any instanciation in scene, which made it somehow virtual and unreachable... With new behavior, this is no more possible, but on the other hand it means that in situations of dependency cycles (two linked objects using each other), linked objects become impossible to delete (from user space). Not sure what's best here, behavior with those corner cases of library linking is very poorly defined... :( --- source/blender/editors/object/object_add.c | 29 +++++++++++++++++++++++++++- source/blender/editors/object/object_group.c | 2 +- 2 files changed, 29 insertions(+), 2 deletions(-) (limited to 'source/blender/editors/object') diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index f85c76291cd..0f1c72fcd55 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -73,6 +73,7 @@ #include "BKE_lamp.h" #include "BKE_lattice.h" #include "BKE_library.h" +#include "BKE_library_query.h" #include "BKE_key.h" #include "BKE_main.h" #include "BKE_material.h" @@ -1108,11 +1109,18 @@ static void object_delete_check_glsl_update(Object *ob) /* note: now unlinks constraints as well */ void ED_base_object_free_and_unlink(Main *bmain, Scene *scene, Base *base) { - DAG_id_type_tag(bmain, ID_OB); + if (BKE_library_ID_is_indirectly_used(bmain, base->object) && ID_REAL_USERS(base->object) <= 1) { + /* We cannot delete indirectly used object... */ + printf("WARNING, undeletable object '%s', should have been catched before reaching this function!", + base->object->id.name + 2); + return; + } + BKE_scene_base_unlink(scene, base); object_delete_check_glsl_update(base->object); BKE_libblock_free_us(bmain, base->object); MEM_freeN(base); + DAG_id_type_tag(bmain, ID_OB); } static int object_delete_exec(bContext *C, wmOperator *op) @@ -1129,6 +1137,19 @@ static int object_delete_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, base, selected_bases) { + const bool is_indirectly_used = BKE_library_ID_is_indirectly_used(bmain, base->object); + if (base->object->id.tag & LIB_TAG_INDIRECT) { + /* Can this case ever happen? */ + BKE_reportf(op->reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", base->object->id.name + 2); + continue; + } + else if (is_indirectly_used && ID_REAL_USERS(base->object) <= 1) { + BKE_reportf(op->reports, RPT_WARNING, + "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user", + base->object->id.name + 2, scene->id.name + 2); + continue; + } + /* deselect object -- it could be used in other scenes */ base->object->flag &= ~SELECT; @@ -1144,6 +1165,12 @@ static int object_delete_exec(bContext *C, wmOperator *op) if (scene_iter != scene && !(scene_iter->id.lib)) { base_other = BKE_scene_base_find(scene_iter, base->object); if (base_other) { + if (is_indirectly_used && ID_REAL_USERS(base->object) <= 1) { + BKE_reportf(op->reports, RPT_WARNING, + "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user", + base->object->id.name + 2, scene_iter->id.name + 2); + break; + } ED_base_object_free_and_unlink(bmain, scene_iter, base_other); } } diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c index 2b87a890f0f..bcdd170c53c 100644 --- a/source/blender/editors/object/object_group.c +++ b/source/blender/editors/object/object_group.c @@ -528,7 +528,7 @@ static int group_unlink_exec(bContext *C, wmOperator *UNUSED(op)) if (!group) return OPERATOR_CANCELLED; - BKE_libblock_unlink(bmain, group, false); + BKE_libblock_unlink(bmain, group, false, false); BKE_libblock_free(bmain, group); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); -- cgit v1.2.3 From 1077514896688e4f439cbd20e0f0c65c88048978 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 2 Jul 2016 10:00:30 +1000 Subject: Cleanup: style --- source/blender/editors/object/object_constraint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/editors/object') diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 9c2806f6f5a..d7b7fd7040e 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -1651,7 +1651,7 @@ static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob break; } else if (((!only_curve) || (ob->type == OB_CURVE)) && - ((!only_mesh) || (ob->type == OB_MESH))) + ((!only_mesh) || (ob->type == OB_MESH))) { /* set target */ *tar_ob = ob; -- cgit v1.2.3 From d2312602125a452e6562a76ab91779943c67396d Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 6 Jul 2016 14:11:01 +0200 Subject: Replace of (id->lib != NULL) check by meaningful macro. Idea is to replace hard-to-track (id->lib != NULL) 'is linked datablock' check everywhere in Blender by a macro doing the same thing. This will allow to easily spot those checks in future, and more importantly, to easily change it (see work done in asset-engine branch). Note: did not touch to readfile.c, since there most of the time 'id->lib' check actually concerns the pointer, and not a check whether ID is linked or not. Will have a closer look at it later. Reviewers: campbellbarton, brecht, sergey Differential Revision: https://developer.blender.org/D2082 --- source/blender/editors/object/object_add.c | 9 ++++---- source/blender/editors/object/object_constraint.c | 2 +- .../blender/editors/object/object_data_transfer.c | 6 ++--- source/blender/editors/object/object_edit.c | 12 +++++----- source/blender/editors/object/object_modifier.c | 4 ++-- source/blender/editors/object/object_relations.c | 26 +++++++++++----------- source/blender/editors/object/object_shapekey.c | 9 ++++---- source/blender/editors/object/object_transform.c | 6 ++--- source/blender/editors/object/object_vgroup.c | 23 ++++++++++--------- 9 files changed, 50 insertions(+), 47 deletions(-) (limited to 'source/blender/editors/object') diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 0f1c72fcd55..69950ccc9a9 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1162,7 +1162,7 @@ static int object_delete_exec(bContext *C, wmOperator *op) Base *base_other; for (scene_iter = bmain->scene.first; scene_iter; scene_iter = scene_iter->id.next) { - if (scene_iter != scene && !(scene_iter->id.lib)) { + if (scene_iter != scene && !ID_IS_LINKED_DATABLOCK(scene_iter)) { base_other = BKE_scene_base_find(scene_iter, base->object); if (base_other) { if (is_indirectly_used && ID_REAL_USERS(base->object) <= 1) { @@ -1515,7 +1515,8 @@ static int convert_poll(bContext *C) Object *obact = CTX_data_active_object(C); Scene *scene = CTX_data_scene(C); - return (!scene->id.lib && obact && scene->obedit != obact && (obact->flag & SELECT) && !(obact->id.lib)); + return (!ID_IS_LINKED_DATABLOCK(scene) && obact && scene->obedit != obact && + (obact->flag & SELECT) && !ID_IS_LINKED_DATABLOCK(obact)); } /* Helper for convert_exec */ @@ -2305,7 +2306,7 @@ static int join_poll(bContext *C) { Object *ob = CTX_data_active_object(C); - if (!ob || ob->id.lib) return 0; + if (!ob || ID_IS_LINKED_DATABLOCK(ob)) return 0; if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_ARMATURE)) return ED_operator_screenactive(C); @@ -2358,7 +2359,7 @@ static int join_shapes_poll(bContext *C) { Object *ob = CTX_data_active_object(C); - if (!ob || ob->id.lib) return 0; + if (!ob || ID_IS_LINKED_DATABLOCK(ob)) return 0; /* only meshes supported at the moment */ if (ob->type == OB_MESH) diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index d7b7fd7040e..db8a4c1960f 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -584,7 +584,7 @@ static int edit_constraint_poll_generic(bContext *C, StructRNA *rna_type) return 0; } - if (ob->id.lib || (ptr.id.data && ((ID *)ptr.id.data)->lib)) { + if (ID_IS_LINKED_DATABLOCK(ob) || (ptr.id.data && ID_IS_LINKED_DATABLOCK(ptr.id.data))) { CTX_wm_operator_poll_msg_set(C, "Cannot edit library data"); return 0; } diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index 47ee6752e51..acee69daab7 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -300,7 +300,7 @@ static void data_transfer_exec_preprocess_objects( } me = ob->data; - if (me->id.lib) { + if (ID_IS_LINKED_DATABLOCK(me)) { /* Do not transfer to linked data, not supported. */ BKE_reportf(op->reports, RPT_WARNING, "Skipping object '%s', linked data '%s' cannot be modified", ob->id.name + 2, me->id.name + 2); @@ -330,7 +330,7 @@ static bool data_transfer_exec_is_object_valid( me->id.tag &= ~LIB_TAG_DOIT; return true; } - else if (me->id.lib == NULL) { + else if (!ID_IS_LINKED_DATABLOCK(me)) { /* Do not transfer apply operation more than once. */ /* XXX This is not nice regarding vgroups, which are half-Object data... :/ */ BKE_reportf(op->reports, RPT_WARNING, @@ -387,7 +387,7 @@ static int data_transfer_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } - if (reverse_transfer && ((ID *)(ob_src->data))->lib) { + if (reverse_transfer && ID_IS_LINKED_DATABLOCK(ob_src->data)) { /* Do not transfer to linked data, not supported. */ return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 01a567931b3..3dc7d8ebd4b 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -470,7 +470,7 @@ void ED_object_editmode_enter(bContext *C, int flag) View3D *v3d = NULL; bool ok = false; - if (scene->id.lib) return; + if (ID_IS_LINKED_DATABLOCK(scene)) return; if (sa && sa->spacetype == SPACE_VIEW3D) v3d = sa->spacedata.first; @@ -539,7 +539,7 @@ void ED_object_editmode_enter(bContext *C, int flag) * BKE_object_obdata_is_libdata that prevent the bugfix #6614, so * i add this little hack here. */ - if (arm->id.lib) { + if (ID_IS_LINKED_DATABLOCK(arm)) { error_libdata(); return; } @@ -621,7 +621,7 @@ static int editmode_toggle_poll(bContext *C) Object *ob = CTX_data_active_object(C); /* covers proxies too */ - if (ELEM(NULL, ob, ob->data) || ((ID *)ob->data)->lib) + if (ELEM(NULL, ob, ob->data) || ID_IS_LINKED_DATABLOCK(ob->data)) return 0; /* if hidden but in edit mode, we still display */ @@ -848,7 +848,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) Nurb *nu; bool do_depgraph_update = false; - if (scene->id.lib) return; + if (ID_IS_LINKED_DATABLOCK(scene)) return; if (!(ob = OBACT)) return; @@ -1436,7 +1436,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op) { data = ob->data; - if (data && data->lib) { + if (data && ID_IS_LINKED_DATABLOCK(data)) { linked_data = true; continue; } @@ -1519,7 +1519,7 @@ static void UNUSED_FUNCTION(image_aspect) (Scene *scene, View3D *v3d) int a, b, done; if (scene->obedit) return; // XXX get from context - if (scene->id.lib) return; + if (ID_IS_LINKED_DATABLOCK(scene)) return; for (base = FIRSTBASE; base; base = base->next) { if (TESTBASELIB(v3d, base)) { diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 264945b00bf..b44ddf925a8 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -817,9 +817,9 @@ int edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type); Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C); - if (!ob || ob->id.lib) return 0; + if (!ob || ID_IS_LINKED_DATABLOCK(ob)) return 0; if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) return 0; - if (ptr.id.data && ((ID *)ptr.id.data)->lib) return 0; + if (ptr.id.data && ID_IS_LINKED_DATABLOCK(ptr.id.data)) return 0; return 1; } diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 94d1a258063..9a6fe5ae48b 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -291,17 +291,17 @@ static int make_proxy_invoke(bContext *C, wmOperator *op, const wmEvent *event) Object *ob = ED_object_active_context(C); /* sanity checks */ - if (!scene || scene->id.lib || !ob) + if (!scene || ID_IS_LINKED_DATABLOCK(scene) || !ob) return OPERATOR_CANCELLED; /* Get object to work on - use a menu if we need to... */ - if (ob->dup_group && ob->dup_group->id.lib) { + if (ob->dup_group && ID_IS_LINKED_DATABLOCK(ob->dup_group)) { /* gives menu with list of objects in group */ /* proxy_group_objects_menu(C, op, ob, ob->dup_group); */ WM_enum_search_invoke(C, op, event); return OPERATOR_CANCELLED; } - else if (ob->id.lib) { + else if (ID_IS_LINKED_DATABLOCK(ob)) { uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("OK?"), ICON_QUESTION); uiLayout *layout = UI_popup_menu_layout(pup); @@ -1466,7 +1466,7 @@ static int make_links_scene_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - if (scene_to->id.lib) { + if (ID_IS_LINKED_DATABLOCK(scene_to)) { BKE_report(op->reports, RPT_ERROR, "Cannot link objects into a linked scene"); return OPERATOR_CANCELLED; } @@ -1579,7 +1579,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op) case MAKE_LINKS_ANIMDATA: BKE_animdata_copy_id((ID *)ob_dst, (ID *)ob_src, false); if (ob_dst->data && ob_src->data) { - if (obdata_id->lib) { + if (ID_IS_LINKED_DATABLOCK(obdata_id)) { is_lib = true; break; } @@ -1621,7 +1621,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op) Curve *cu_src = ob_src->data; Curve *cu_dst = ob_dst->data; - if (obdata_id->lib) { + if (ID_IS_LINKED_DATABLOCK(obdata_id)) { is_lib = true; break; } @@ -1749,7 +1749,7 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in ob = base->object; if ((base->flag & flag) == flag) { - if (ob->id.lib == NULL && ob->id.us > 1) { + if (!ID_IS_LINKED_DATABLOCK(ob) && ob->id.us > 1) { /* base gets copy of object */ obn = BKE_object_copy(ob); base->object = obn; @@ -1828,7 +1828,7 @@ static void new_id_matar(Material **matar, const int totcol) for (a = 0; a < totcol; a++) { id = (ID *)matar[a]; - if (id && id->lib == NULL) { + if (id && !ID_IS_LINKED_DATABLOCK(id)) { if (id->newid) { matar[a] = (Material *)id->newid; id_us_plus(id->newid); @@ -1857,10 +1857,10 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag) for (base = FIRSTBASE; base; base = base->next) { ob = base->object; - if (ob->id.lib == NULL && (base->flag & flag) == flag) { + if (!ID_IS_LINKED_DATABLOCK(ob) && (base->flag & flag) == flag) { id = ob->data; - if (id && id->us > 1 && id->lib == NULL) { + if (id && id->us > 1 && !ID_IS_LINKED_DATABLOCK(id)) { DAG_id_tag_update(&ob->id, OB_RECALC_DATA); switch (ob->type) { @@ -1938,7 +1938,7 @@ static void single_object_action_users(Scene *scene, const int flag) for (base = FIRSTBASE; base; base = base->next) { ob = base->object; - if (ob->id.lib == NULL && (flag == 0 || (base->flag & SELECT)) ) { + if (!ID_IS_LINKED_DATABLOCK(ob) && (flag == 0 || (base->flag & SELECT)) ) { DAG_id_tag_update(&ob->id, OB_RECALC_DATA); BKE_animdata_copy_id_action(&ob->id); } @@ -1955,7 +1955,7 @@ static void single_mat_users(Scene *scene, const int flag, const bool do_texture for (base = FIRSTBASE; base; base = base->next) { ob = base->object; - if (ob->id.lib == NULL && (flag == 0 || (base->flag & SELECT)) ) { + if (!ID_IS_LINKED_DATABLOCK(ob) && (flag == 0 || (base->flag & SELECT)) ) { for (a = 1; a <= ob->totcol; a++) { ma = give_current_material(ob, a); if (ma) { @@ -2184,7 +2184,7 @@ static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene) bool changed = false; for (ob = bmain->object.first; ob; ob = ob->id.next) { - if (ob->id.lib && (ob->id.us == 0)) { + if (ID_IS_LINKED_DATABLOCK(ob) && (ob->id.us == 0)) { Base *base; id_us_plus(&ob->id); diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index 39bd34456be..e04114761e4 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -225,7 +225,7 @@ static int shape_key_mode_poll(bContext *C) { Object *ob = ED_object_context(C); ID *data = (ob) ? ob->data : NULL; - return (ob && !ob->id.lib && data && !data->lib && ob->mode != OB_MODE_EDIT); + return (ob && !ID_IS_LINKED_DATABLOCK(ob) && data && !ID_IS_LINKED_DATABLOCK(data) && ob->mode != OB_MODE_EDIT); } static int shape_key_mode_exists_poll(bContext *C) @@ -234,7 +234,7 @@ static int shape_key_mode_exists_poll(bContext *C) ID *data = (ob) ? ob->data : NULL; /* same as shape_key_mode_poll */ - return (ob && !ob->id.lib && data && !data->lib && ob->mode != OB_MODE_EDIT) && + return (ob && !ID_IS_LINKED_DATABLOCK(ob) && data && !ID_IS_LINKED_DATABLOCK(data) && ob->mode != OB_MODE_EDIT) && /* check a keyblock exists */ (BKE_keyblock_from_object(ob) != NULL); } @@ -246,14 +246,15 @@ static int shape_key_move_poll(bContext *C) ID *data = (ob) ? ob->data : NULL; Key *key = BKE_key_from_object(ob); - return (ob && !ob->id.lib && data && !data->lib && ob->mode != OB_MODE_EDIT && key && key->totkey > 1); + return (ob && !ID_IS_LINKED_DATABLOCK(ob) && data && !ID_IS_LINKED_DATABLOCK(data) && + ob->mode != OB_MODE_EDIT && key && key->totkey > 1); } static int shape_key_poll(bContext *C) { Object *ob = ED_object_context(C); ID *data = (ob) ? ob->data : NULL; - return (ob && !ob->id.lib && data && !data->lib); + return (ob && !ID_IS_LINKED_DATABLOCK(ob) && data && !ID_IS_LINKED_DATABLOCK(data)); } static int shape_key_add_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index d2bbb73b597..6d80c4af292 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -391,7 +391,7 @@ static int apply_objects_internal(bContext *C, ReportList *reports, bool apply_l changed = false; } - if (obdata->lib) { + if (ID_IS_LINKED_DATABLOCK(obdata)) { BKE_reportf(reports, RPT_ERROR, "Cannot apply to library data: Object \"%s\", %s \"%s\", aborting", ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2); @@ -792,7 +792,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) if (ob->data == NULL) { /* special support for dupligroups */ if ((ob->transflag & OB_DUPLIGROUP) && ob->dup_group && (ob->dup_group->id.tag & LIB_TAG_DOIT) == 0) { - if (ob->dup_group->id.lib) { + if (ID_IS_LINKED_DATABLOCK(ob->dup_group)) { tot_lib_error++; } else { @@ -817,7 +817,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) } } } - else if (((ID *)ob->data)->lib) { + else if (ID_IS_LINKED_DATABLOCK(ob->data)) { tot_lib_error++; } diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 414cc476be5..6e8aaebcccc 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -2447,8 +2447,8 @@ static int vertex_group_poll(bContext *C) Object *ob = ED_object_context(C); ID *data = (ob) ? ob->data : NULL; - return (ob && !ob->id.lib && - data && !data->lib && + return (ob && !ID_IS_LINKED_DATABLOCK(ob) && + data && !ID_IS_LINKED_DATABLOCK(data) && OB_TYPE_SUPPORT_VGROUP(ob->type) && ob->defbase.first); } @@ -2457,7 +2457,8 @@ static int vertex_group_supported_poll(bContext *C) { Object *ob = ED_object_context(C); ID *data = (ob) ? ob->data : NULL; - return (ob && !ob->id.lib && OB_TYPE_SUPPORT_VGROUP(ob->type) && data && !data->lib); + return (ob && !ID_IS_LINKED_DATABLOCK(ob) && OB_TYPE_SUPPORT_VGROUP(ob->type) && + data && !ID_IS_LINKED_DATABLOCK(data)); } static int vertex_group_mesh_poll(bContext *C) @@ -2465,8 +2466,8 @@ static int vertex_group_mesh_poll(bContext *C) Object *ob = ED_object_context(C); ID *data = (ob) ? ob->data : NULL; - return (ob && !ob->id.lib && - data && !data->lib && + return (ob && !ID_IS_LINKED_DATABLOCK(ob) && + data && !ID_IS_LINKED_DATABLOCK(data) && ob->type == OB_MESH && ob->defbase.first); } @@ -2475,7 +2476,7 @@ static int UNUSED_FUNCTION(vertex_group_mesh_supported_poll)(bContext *C) { Object *ob = ED_object_context(C); ID *data = (ob) ? ob->data : NULL; - return (ob && !ob->id.lib && ob->type == OB_MESH && data && !data->lib); + return (ob && !ID_IS_LINKED_DATABLOCK(ob) && ob->type == OB_MESH && data && !ID_IS_LINKED_DATABLOCK(data)); } @@ -2484,7 +2485,7 @@ static int UNUSED_FUNCTION(vertex_group_poll_edit) (bContext *C) Object *ob = ED_object_context(C); ID *data = (ob) ? ob->data : NULL; - if (!(ob && !ob->id.lib && data && !data->lib)) + if (!(ob && !ID_IS_LINKED_DATABLOCK(ob) && data && !ID_IS_LINKED_DATABLOCK(data))) return 0; return BKE_object_is_in_editmode_vgroup(ob); @@ -2496,7 +2497,7 @@ static int vertex_group_vert_select_poll_ex(bContext *C, const short ob_type_fla Object *ob = ED_object_context(C); ID *data = (ob) ? ob->data : NULL; - if (!(ob && !ob->id.lib && data && !data->lib)) + if (!(ob && !ID_IS_LINKED_DATABLOCK(ob) && data && !ID_IS_LINKED_DATABLOCK(data))) return false; if (ob_type_flag && (((1 << ob->type) & ob_type_flag)) == 0) { @@ -2536,7 +2537,7 @@ static int vertex_group_vert_select_unlocked_poll(bContext *C) Object *ob = ED_object_context(C); ID *data = (ob) ? ob->data : NULL; - if (!(ob && !ob->id.lib && data && !data->lib)) + if (!(ob && !ID_IS_LINKED_DATABLOCK(ob) && data && !ID_IS_LINKED_DATABLOCK(data))) return 0; if (!(BKE_object_is_in_editmode_vgroup(ob) || @@ -2559,7 +2560,7 @@ static int vertex_group_vert_select_mesh_poll(bContext *C) Object *ob = ED_object_context(C); ID *data = (ob) ? ob->data : NULL; - if (!(ob && !ob->id.lib && data && !data->lib)) + if (!(ob && !ID_IS_LINKED_DATABLOCK(ob) && data && !ID_IS_LINKED_DATABLOCK(data))) return 0; /* only difference to #vertex_group_vert_select_poll */ @@ -2748,7 +2749,7 @@ static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_object_context(C); - if (!ob || ob->id.lib) + if (!ob || ID_IS_LINKED_DATABLOCK(ob)) return OPERATOR_CANCELLED; vgroup_select_verts(ob, 1); -- cgit v1.2.3 From ab993e373cf31c1790f7283b52bbd29b4849fbe7 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 8 Jul 2016 14:36:25 +0200 Subject: Rework/split test_object_materials(). Now test_object_materials only handles one object. New test_all_objects_materials checks the whole bmain->object list for cases where it is actually needed. Should avoid some useless looping over all objects! --- source/blender/editors/object/object_relations.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/editors/object') diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 9a6fe5ae48b..af1c840b902 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1564,7 +1564,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op) ob_dst->data = obdata_id; /* if amount of material indices changed: */ - test_object_materials(bmain, ob_dst->data); + test_object_materials(ob_dst, ob_dst->data); DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA); break; -- cgit v1.2.3 From f3fe1f9c44b08de6d18cad27d8751585568b7e8e Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 8 Jul 2016 16:14:55 +0200 Subject: Refactor: pass Main to id_make_local. Totally stupid to not pass it, and then let (some) BKE_foo_make_local() use G.main! Note: unused for now, much more refactoring still to come in make_local area! --- source/blender/editors/object/object_relations.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source/blender/editors/object') diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index af1c840b902..255477b4d90 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -2104,11 +2104,11 @@ static void make_local_makelocalmaterial(Material *ma) AnimData *adt; int b; - id_make_local(&ma->id, false); + id_make_local(G.main, &ma->id, false); for (b = 0; b < MAX_MTEX; b++) if (ma->mtex[b] && ma->mtex[b]->tex) - id_make_local(&ma->mtex[b]->tex->id, false); + id_make_local(G.main, &ma->mtex[b]->tex->id, false); adt = BKE_animdata_from_id(&ma->id); if (adt) BKE_animdata_make_local(adt); @@ -2237,7 +2237,7 @@ static int make_local_exec(bContext *C, wmOperator *op) } if (ob->id.lib) - id_make_local(&ob->id, false); + id_make_local(bmain, &ob->id, false); } CTX_DATA_END; @@ -2259,7 +2259,7 @@ static int make_local_exec(bContext *C, wmOperator *op) id = ob->data; if (id && (ELEM(mode, MAKE_LOCAL_SELECT_OBDATA, MAKE_LOCAL_SELECT_OBDATA_MATERIAL))) { - id_make_local(id, false); + id_make_local(bmain, id, false); adt = BKE_animdata_from_id(id); if (adt) BKE_animdata_make_local(adt); @@ -2275,7 +2275,7 @@ static int make_local_exec(bContext *C, wmOperator *op) } for (psys = ob->particlesystem.first; psys; psys = psys->next) - id_make_local(&psys->part->id, false); + id_make_local(bmain, &psys->part->id, false); adt = BKE_animdata_from_id(&ob->id); if (adt) BKE_animdata_make_local(adt); @@ -2294,7 +2294,7 @@ static int make_local_exec(bContext *C, wmOperator *op) for (b = 0; b < MAX_MTEX; b++) if (la->mtex[b] && la->mtex[b]->tex) - id_make_local(&la->mtex[b]->tex->id, false); + id_make_local(bmain, &la->mtex[b]->tex->id, false); } else { for (a = 0; a < ob->totcol; a++) { -- cgit v1.2.3 From 245f97d7dc60f64256620383ac71c84146910300 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sat, 9 Jul 2016 11:52:09 +1200 Subject: Clear Transforms and Deltas * Alt-G, Alt-R, Alt-S --> These don't clear delta transforms by default anymore, making it possible to use these to properly store a "rest" pose * Alt-Shift-G, Alt-Shift-R, Alt-Shift-S --> These WILL clear both the normal transform and the delta, should you need to do so. --- source/blender/editors/object/object_ops.c | 18 +++- source/blender/editors/object/object_transform.c | 118 +++++++++++++++-------- 2 files changed, 94 insertions(+), 42 deletions(-) (limited to 'source/blender/editors/object') diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 534e59384ce..7e7e1ef182c 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -365,9 +365,21 @@ void ED_keymap_object(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "OBJECT_OT_constraint_add_with_targets", CKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0); WM_keymap_verify_item(keymap, "OBJECT_OT_constraints_clear", CKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); - WM_keymap_verify_item(keymap, "OBJECT_OT_location_clear", GKEY, KM_PRESS, KM_ALT, 0); - WM_keymap_verify_item(keymap, "OBJECT_OT_rotation_clear", RKEY, KM_PRESS, KM_ALT, 0); - WM_keymap_verify_item(keymap, "OBJECT_OT_scale_clear", SKEY, KM_PRESS, KM_ALT, 0); + + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_location_clear", GKEY, KM_PRESS, KM_ALT, 0); + RNA_boolean_set(kmi->ptr, "clear_delta", false); + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_rotation_clear", RKEY, KM_PRESS, KM_ALT, 0); + RNA_boolean_set(kmi->ptr, "clear_delta", false); + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_scale_clear", SKEY, KM_PRESS, KM_ALT, 0); + RNA_boolean_set(kmi->ptr, "clear_delta", false); + + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_location_clear", GKEY, KM_PRESS, KM_ALT | KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "clear_delta", true); + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_rotation_clear", RKEY, KM_PRESS, KM_ALT | KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "clear_delta", true); + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_scale_clear", SKEY, KM_PRESS, KM_ALT | KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "clear_delta", true); + WM_keymap_verify_item(keymap, "OBJECT_OT_origin_clear", OKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0); diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 6d80c4af292..c681b945788 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -76,60 +76,85 @@ /*************************** Clear Transformation ****************************/ /* clear location of object */ -static void object_clear_loc(Object *ob) +static void object_clear_loc(Object *ob, const bool clear_delta) { /* clear location if not locked */ - if ((ob->protectflag & OB_LOCK_LOCX) == 0) - ob->loc[0] = ob->dloc[0] = 0.0f; - if ((ob->protectflag & OB_LOCK_LOCY) == 0) - ob->loc[1] = ob->dloc[1] = 0.0f; - if ((ob->protectflag & OB_LOCK_LOCZ) == 0) - ob->loc[2] = ob->dloc[2] = 0.0f; + if ((ob->protectflag & OB_LOCK_LOCX) == 0) { + ob->loc[0] = 0.0f; + if (clear_delta) ob->dloc[0] = 0.0f; + } + if ((ob->protectflag & OB_LOCK_LOCY) == 0) { + ob->loc[1] = 0.0f; + if (clear_delta) ob->dloc[1] = 0.0f; + } + if ((ob->protectflag & OB_LOCK_LOCZ) == 0) { + ob->loc[2] = 0.0f; + if (clear_delta) ob->dloc[2] = 0.0f; + } } /* clear rotation of object */ -static void object_clear_rot(Object *ob) +static void object_clear_rot(Object *ob, const bool clear_delta) { /* clear rotations that aren't locked */ if (ob->protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) { if (ob->protectflag & OB_LOCK_ROT4D) { /* perform clamping on a component by component basis */ if (ob->rotmode == ROT_MODE_AXISANGLE) { - if ((ob->protectflag & OB_LOCK_ROTW) == 0) - ob->rotAngle = ob->drotAngle = 0.0f; - if ((ob->protectflag & OB_LOCK_ROTX) == 0) - ob->rotAxis[0] = ob->drotAxis[0] = 0.0f; - if ((ob->protectflag & OB_LOCK_ROTY) == 0) - ob->rotAxis[1] = ob->drotAxis[1] = 0.0f; - if ((ob->protectflag & OB_LOCK_ROTZ) == 0) - ob->rotAxis[2] = ob->drotAxis[2] = 0.0f; + if ((ob->protectflag & OB_LOCK_ROTW) == 0) { + ob->rotAngle = 0.0f; + if (clear_delta) ob->drotAngle = 0.0f; + } + if ((ob->protectflag & OB_LOCK_ROTX) == 0) { + ob->rotAxis[0] = 0.0f; + if (clear_delta) ob->drotAxis[0] = 0.0f; + } + if ((ob->protectflag & OB_LOCK_ROTY) == 0) { + ob->rotAxis[1] = 0.0f; + if (clear_delta) ob->drotAxis[1] = 0.0f; + } + if ((ob->protectflag & OB_LOCK_ROTZ) == 0) { + ob->rotAxis[2] = 0.0f; + if (clear_delta) ob->drotAxis[2] = 0.0f; + } /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */ if (IS_EQF(ob->rotAxis[0], ob->rotAxis[1]) && IS_EQF(ob->rotAxis[1], ob->rotAxis[2])) ob->rotAxis[1] = 1.0f; - if (IS_EQF(ob->drotAxis[0], ob->drotAxis[1]) && IS_EQF(ob->drotAxis[1], ob->drotAxis[2])) + if (IS_EQF(ob->drotAxis[0], ob->drotAxis[1]) && IS_EQF(ob->drotAxis[1], ob->drotAxis[2]) && clear_delta) ob->drotAxis[1] = 1.0f; } else if (ob->rotmode == ROT_MODE_QUAT) { - if ((ob->protectflag & OB_LOCK_ROTW) == 0) - ob->quat[0] = ob->dquat[0] = 1.0f; + if ((ob->protectflag & OB_LOCK_ROTW) == 0) { + ob->quat[0] = 1.0f; + if (clear_delta) ob->dquat[0] = 1.0f; + } if ((ob->protectflag & OB_LOCK_ROTX) == 0) - ob->quat[1] = ob->dquat[1] = 0.0f; + ob->quat[1] = 0.0f; + if (clear_delta) ob->dquat[1] = 0.0f; if ((ob->protectflag & OB_LOCK_ROTY) == 0) - ob->quat[2] = ob->dquat[2] = 0.0f; + ob->quat[2] = 0.0f; + if (clear_delta) ob->dquat[2] = 0.0f; if ((ob->protectflag & OB_LOCK_ROTZ) == 0) - ob->quat[3] = ob->dquat[3] = 0.0f; + ob->quat[3] = 0.0f; + if (clear_delta) ob->dquat[3] = 0.0f; /* TODO: does this quat need normalizing now? */ } else { /* the flag may have been set for the other modes, so just ignore the extra flag... */ - if ((ob->protectflag & OB_LOCK_ROTX) == 0) - ob->rot[0] = ob->drot[0] = 0.0f; - if ((ob->protectflag & OB_LOCK_ROTY) == 0) - ob->rot[1] = ob->drot[1] = 0.0f; - if ((ob->protectflag & OB_LOCK_ROTZ) == 0) - ob->rot[2] = ob->drot[2] = 0.0f; + if ((ob->protectflag & OB_LOCK_ROTX) == 0) { + ob->rot[0] = 0.0f; + if (clear_delta) ob->drot[0] = 0.0f; + } + if ((ob->protectflag & OB_LOCK_ROTY) == 0) { + ob->rot[1] = 0.0f; + if (clear_delta) ob->drot[1] = 0.0f; + } + if ((ob->protectflag & OB_LOCK_ROTZ) == 0) { + ob->rot[2] = 0.0f; + if (clear_delta) ob->drot[2] = 0.0f; + } } } else { @@ -175,34 +200,34 @@ static void object_clear_rot(Object *ob) else { if (ob->rotmode == ROT_MODE_QUAT) { unit_qt(ob->quat); - unit_qt(ob->dquat); + if (clear_delta) unit_qt(ob->dquat); } else if (ob->rotmode == ROT_MODE_AXISANGLE) { unit_axis_angle(ob->rotAxis, &ob->rotAngle); - unit_axis_angle(ob->drotAxis, &ob->drotAngle); + if (clear_delta) unit_axis_angle(ob->drotAxis, &ob->drotAngle); } else { zero_v3(ob->rot); - zero_v3(ob->drot); + if (clear_delta) zero_v3(ob->drot); } } } /* clear scale of object */ -static void object_clear_scale(Object *ob) +static void object_clear_scale(Object *ob, const bool clear_delta) { /* clear scale factors which are not locked */ if ((ob->protectflag & OB_LOCK_SCALEX) == 0) { - ob->dscale[0] = 1.0f; ob->size[0] = 1.0f; + if (clear_delta) ob->dscale[0] = 1.0f; } if ((ob->protectflag & OB_LOCK_SCALEY) == 0) { - ob->dscale[1] = 1.0f; ob->size[1] = 1.0f; + if (clear_delta) ob->dscale[1] = 1.0f; } if ((ob->protectflag & OB_LOCK_SCALEZ) == 0) { - ob->dscale[2] = 1.0f; ob->size[2] = 1.0f; + if (clear_delta) ob->dscale[2] = 1.0f; } } @@ -210,10 +235,12 @@ static void object_clear_scale(Object *ob) /* generic exec for clear-transform operators */ static int object_clear_transform_generic_exec(bContext *C, wmOperator *op, - void (*clear_func)(Object *), const char default_ksName[]) + void (*clear_func)(Object *, const bool), + const char default_ksName[]) { Scene *scene = CTX_data_scene(C); KeyingSet *ks; + const bool clear_delta = RNA_boolean_get(op->ptr, "clear_delta"); /* sanity checks */ if (ELEM(NULL, clear_func, default_ksName)) { @@ -231,10 +258,10 @@ static int object_clear_transform_generic_exec(bContext *C, wmOperator *op, { if (!(ob->mode & OB_MODE_WEIGHT_PAINT)) { /* run provided clearing function */ - clear_func(ob); - + clear_func(ob, clear_delta); + ED_autokeyframe_object(C, scene, ob, ks); - + /* tag for updates */ DAG_id_tag_update(&ob->id, OB_RECALC_OB); } @@ -268,6 +295,11 @@ void OBJECT_OT_location_clear(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + + /* properties */ + ot->prop = RNA_def_boolean(ot->srna, "clear_delta", false, "Clear Delta", + "Clear delta location in addition to clearing the normal location transform"); } static int object_rotation_clear_exec(bContext *C, wmOperator *op) @@ -288,6 +320,10 @@ void OBJECT_OT_rotation_clear(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_boolean(ot->srna, "clear_delta", false, "Clear Delta", + "Clear delta rotation in addition to clearing the normal rotation transform"); } static int object_scale_clear_exec(bContext *C, wmOperator *op) @@ -308,6 +344,10 @@ void OBJECT_OT_scale_clear(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_boolean(ot->srna, "clear_delta", false, "Clear Delta", + "Clear delta scale in addition to clearing the normal scale transform"); } /* --------------- */ -- cgit v1.2.3 From 11f64f494b715498e4cbc147ae6a9d10538dc055 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sat, 9 Jul 2016 15:08:24 +0200 Subject: Refactor/enhance BKE_curve_make_local(), and add BKE_curve_copy_ex() that takes a Main as parameter. Now using modern features from libquery/libremap areas. Provides same kind of fixes/improvements as for BKE_object_make_local() (see rBd1a4ae3f395a6). --- source/blender/editors/object/object_add.c | 10 +++++----- source/blender/editors/object/object_relations.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'source/blender/editors/object') diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 69950ccc9a9..d160a62a3f4 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1673,7 +1673,7 @@ static int convert_exec(bContext *C, wmOperator *op) id_us_min(&((Curve *)newob->data)->id); /* make a new copy of the curve */ - newob->data = BKE_curve_copy(ob->data); + newob->data = BKE_curve_copy_ex(bmain, ob->data); } else { newob = ob; @@ -1744,7 +1744,7 @@ static int convert_exec(bContext *C, wmOperator *op) id_us_min(&((Curve *)newob->data)->id); /* make a new copy of the curve */ - newob->data = BKE_curve_copy(ob->data); + newob->data = BKE_curve_copy_ex(bmain, ob->data); } else { newob = ob; @@ -1986,7 +1986,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base if (dupflag & USER_DUP_CURVE) { ID_NEW_US2(obn->data) else { - obn->data = BKE_curve_copy(obn->data); + obn->data = BKE_curve_copy_ex(bmain, obn->data); didit = 1; } id_us_min(id); @@ -1996,7 +1996,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base if (dupflag & USER_DUP_SURF) { ID_NEW_US2(obn->data) else { - obn->data = BKE_curve_copy(obn->data); + obn->data = BKE_curve_copy_ex(bmain, obn->data); didit = 1; } id_us_min(id); @@ -2006,7 +2006,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base if (dupflag & USER_DUP_FONT) { ID_NEW_US2(obn->data) else { - obn->data = BKE_curve_copy(obn->data); + obn->data = BKE_curve_copy_ex(bmain, obn->data); didit = 1; } id_us_min(id); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 255477b4d90..fff4725951c 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1886,7 +1886,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag) case OB_CURVE: case OB_SURF: case OB_FONT: - ob->data = cu = BKE_curve_copy(ob->data); + ob->data = cu = BKE_curve_copy_ex(bmain, ob->data); ID_NEW(cu->bevobj); ID_NEW(cu->taperobj); if (cu->key) -- cgit v1.2.3 From 338121e2a0d4471574f243aa36cbf93fdf495ca2 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sat, 9 Jul 2016 15:18:51 +0200 Subject: Refactor/enhance BKE_mball_make_local(), and add BKE_mball_copy_ex() that takes a Main as parameter. Now using modern features from libquery/libremap areas. Provides same kind of fixes/improvements as for BKE_object_make_local() (see rBd1a4ae3f395a6). --- source/blender/editors/object/object_add.c | 2 +- source/blender/editors/object/object_relations.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/editors/object') diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index d160a62a3f4..aac9dcfea34 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -2016,7 +2016,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base if (dupflag & USER_DUP_MBALL) { ID_NEW_US2(obn->data) else { - obn->data = BKE_mball_copy(obn->data); + obn->data = BKE_mball_copy_ex(bmain, obn->data); didit = 1; } id_us_min(id); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index fff4725951c..2e9db53edd3 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1881,7 +1881,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag) BKE_animdata_copy_id_action((ID *)me->key); break; case OB_MBALL: - ob->data = BKE_mball_copy(ob->data); + ob->data = BKE_mball_copy_ex(bmain, ob->data); break; case OB_CURVE: case OB_SURF: -- cgit v1.2.3 From 429394078bde004f608e0f9ba9937421ab35edfd Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sat, 9 Jul 2016 15:38:02 +0200 Subject: Refactor/enhance BKE_lattice_make_local(), and add BKE_lattice_copy_ex() that takes a Main as parameter. Now using modern features from libquery/libremap areas. Provides same kind of fixes/improvements as for BKE_object_make_local() (see rBd1a4ae3f395a6). --- source/blender/editors/object/object_add.c | 2 +- source/blender/editors/object/object_relations.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/editors/object') diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index aac9dcfea34..2ea39209781 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -2050,7 +2050,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base if (dupflag != 0) { ID_NEW_US2(obn->data) else { - obn->data = BKE_lattice_copy(obn->data); + obn->data = BKE_lattice_copy_ex(bmain, obn->data); didit = 1; } id_us_min(id); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 2e9db53edd3..bf2dc550067 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1893,7 +1893,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag) BKE_animdata_copy_id_action((ID *)cu->key); break; case OB_LATTICE: - ob->data = lat = BKE_lattice_copy(ob->data); + ob->data = lat = BKE_lattice_copy_ex(bmain, ob->data); if (lat->key) BKE_animdata_copy_id_action((ID *)lat->key); break; -- cgit v1.2.3 From 87b974caa1e2b780c8031d67a42488039036c489 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 10 Jul 2016 14:52:00 +0200 Subject: Cleanup/Refactor: pass Main pointer to all ID copy functions. Also allows us to get rid of a few _copy_ex() versions... --- source/blender/editors/object/object_add.c | 52 ++++++++++++------------ source/blender/editors/object/object_relations.c | 50 +++++++++++------------ 2 files changed, 51 insertions(+), 51 deletions(-) (limited to 'source/blender/editors/object') diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 2ea39209781..cc628210e20 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1299,7 +1299,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, for (dob = lb->first; dob; dob = dob->next) { Base *basen; - Object *ob = BKE_object_copy(dob->ob); + Object *ob = BKE_object_copy(bmain, dob->ob); /* font duplis can have a totcol without material, we get them from parent * should be implemented better... @@ -1520,7 +1520,7 @@ static int convert_poll(bContext *C) } /* Helper for convert_exec */ -static Base *duplibase_for_convert(Scene *scene, Base *base, Object *ob) +static Base *duplibase_for_convert(Main *bmain, Scene *scene, Base *base, Object *ob) { Object *obn; Base *basen; @@ -1529,7 +1529,7 @@ static Base *duplibase_for_convert(Scene *scene, Base *base, Object *ob) ob = base->object; } - obn = BKE_object_copy(ob); + obn = BKE_object_copy(bmain, ob); DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); basen = MEM_mallocN(sizeof(Base), "duplibase"); @@ -1609,7 +1609,7 @@ static int convert_exec(bContext *C, wmOperator *op) ob->flag |= OB_DONE; if (keep_original) { - basen = duplibase_for_convert(scene, base, NULL); + basen = duplibase_for_convert(bmain, scene, base, NULL); newob = basen->object; /* decrement original mesh's usage count */ @@ -1617,7 +1617,7 @@ static int convert_exec(bContext *C, wmOperator *op) id_us_min(&me->id); /* make a new copy of the mesh */ - newob->data = BKE_mesh_copy(me); + newob->data = BKE_mesh_copy(bmain, me); } else { newob = ob; @@ -1634,7 +1634,7 @@ static int convert_exec(bContext *C, wmOperator *op) ob->flag |= OB_DONE; if (keep_original) { - basen = duplibase_for_convert(scene, base, NULL); + basen = duplibase_for_convert(bmain, scene, base, NULL); newob = basen->object; /* decrement original mesh's usage count */ @@ -1642,7 +1642,7 @@ static int convert_exec(bContext *C, wmOperator *op) id_us_min(&me->id); /* make a new copy of the mesh */ - newob->data = BKE_mesh_copy(me); + newob->data = BKE_mesh_copy(bmain, me); } else { newob = ob; @@ -1666,14 +1666,14 @@ static int convert_exec(bContext *C, wmOperator *op) ob->flag |= OB_DONE; if (keep_original) { - basen = duplibase_for_convert(scene, base, NULL); + basen = duplibase_for_convert(bmain, scene, base, NULL); newob = basen->object; /* decrement original curve's usage count */ id_us_min(&((Curve *)newob->data)->id); /* make a new copy of the curve */ - newob->data = BKE_curve_copy_ex(bmain, ob->data); + newob->data = BKE_curve_copy(bmain, ob->data); } else { newob = ob; @@ -1737,14 +1737,14 @@ static int convert_exec(bContext *C, wmOperator *op) if (target == OB_MESH) { if (keep_original) { - basen = duplibase_for_convert(scene, base, NULL); + basen = duplibase_for_convert(bmain, scene, base, NULL); newob = basen->object; /* decrement original curve's usage count */ id_us_min(&((Curve *)newob->data)->id); /* make a new copy of the curve */ - newob->data = BKE_curve_copy_ex(bmain, ob->data); + newob->data = BKE_curve_copy(bmain, ob->data); } else { newob = ob; @@ -1772,7 +1772,7 @@ static int convert_exec(bContext *C, wmOperator *op) if (!(baseob->flag & OB_DONE)) { baseob->flag |= OB_DONE; - basen = duplibase_for_convert(scene, base, baseob); + basen = duplibase_for_convert(bmain, scene, base, baseob); newob = basen->object; mb = newob->data; @@ -1910,7 +1910,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base ; /* nothing? */ } else { - obn = BKE_object_copy(ob); + obn = BKE_object_copy(bmain, ob); DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); basen = MEM_mallocN(sizeof(Base), "duplibase"); @@ -1941,7 +1941,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base if (id) { ID_NEW_US(obn->mat[a]) else - obn->mat[a] = BKE_material_copy(obn->mat[a]); + obn->mat[a] = BKE_material_copy(bmain, obn->mat[a]); id_us_min(id); if (dupflag & USER_DUP_ACT) { @@ -1957,7 +1957,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base if (id) { ID_NEW_US(psys->part) else - psys->part = BKE_particlesettings_copy(psys->part); + psys->part = BKE_particlesettings_copy(bmain, psys->part); if (dupflag & USER_DUP_ACT) { BKE_animdata_copy_id_action(&psys->part->id); @@ -1976,7 +1976,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base if (dupflag & USER_DUP_MESH) { ID_NEW_US2(obn->data) else { - obn->data = BKE_mesh_copy(obn->data); + obn->data = BKE_mesh_copy(bmain, obn->data); didit = 1; } id_us_min(id); @@ -1986,7 +1986,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base if (dupflag & USER_DUP_CURVE) { ID_NEW_US2(obn->data) else { - obn->data = BKE_curve_copy_ex(bmain, obn->data); + obn->data = BKE_curve_copy(bmain, obn->data); didit = 1; } id_us_min(id); @@ -1996,7 +1996,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base if (dupflag & USER_DUP_SURF) { ID_NEW_US2(obn->data) else { - obn->data = BKE_curve_copy_ex(bmain, obn->data); + obn->data = BKE_curve_copy(bmain, obn->data); didit = 1; } id_us_min(id); @@ -2006,7 +2006,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base if (dupflag & USER_DUP_FONT) { ID_NEW_US2(obn->data) else { - obn->data = BKE_curve_copy_ex(bmain, obn->data); + obn->data = BKE_curve_copy(bmain, obn->data); didit = 1; } id_us_min(id); @@ -2016,7 +2016,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base if (dupflag & USER_DUP_MBALL) { ID_NEW_US2(obn->data) else { - obn->data = BKE_mball_copy_ex(bmain, obn->data); + obn->data = BKE_mball_copy(bmain, obn->data); didit = 1; } id_us_min(id); @@ -2026,7 +2026,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base if (dupflag & USER_DUP_LAMP) { ID_NEW_US2(obn->data) else { - obn->data = BKE_lamp_copy(obn->data); + obn->data = BKE_lamp_copy(bmain, obn->data); didit = 1; } id_us_min(id); @@ -2039,7 +2039,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base if (dupflag & USER_DUP_ARM) { ID_NEW_US2(obn->data) else { - obn->data = BKE_armature_copy(obn->data); + obn->data = BKE_armature_copy(bmain, obn->data); BKE_pose_rebuild(obn, obn->data); didit = 1; } @@ -2050,7 +2050,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base if (dupflag != 0) { ID_NEW_US2(obn->data) else { - obn->data = BKE_lattice_copy_ex(bmain, obn->data); + obn->data = BKE_lattice_copy(bmain, obn->data); didit = 1; } id_us_min(id); @@ -2060,7 +2060,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base if (dupflag != 0) { ID_NEW_US2(obn->data) else { - obn->data = BKE_camera_copy(obn->data); + obn->data = BKE_camera_copy(bmain, obn->data); didit = 1; } id_us_min(id); @@ -2070,7 +2070,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base if (dupflag != 0) { ID_NEW_US2(obn->data) else { - obn->data = BKE_speaker_copy(obn->data); + obn->data = BKE_speaker_copy(bmain, obn->data); didit = 1; } id_us_min(id); @@ -2109,7 +2109,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base if (id) { ID_NEW_US((*matarar)[a]) else - (*matarar)[a] = BKE_material_copy((*matarar)[a]); + (*matarar)[a] = BKE_material_copy(bmain, (*matarar)[a]); id_us_min(id); } } diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index bf2dc550067..6b16e19f790 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1751,7 +1751,7 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in if ((base->flag & flag) == flag) { if (!ID_IS_LINKED_DATABLOCK(ob) && ob->id.us > 1) { /* base gets copy of object */ - obn = BKE_object_copy(ob); + obn = BKE_object_copy(bmain, ob); base->object = obn; if (copy_groups) { @@ -1784,7 +1784,7 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in } if (all_duplicated) { - groupn = BKE_group_copy(group); + groupn = BKE_group_copy(bmain, group); for (go = groupn->gobject.first; go; go = go->next) go->ob = (Object *)go->ob->id.newid; @@ -1821,7 +1821,7 @@ void ED_object_single_user(Main *bmain, Scene *scene, Object *ob) single_object_users(bmain, scene, NULL, OB_DONE, copy_groups); } -static void new_id_matar(Material **matar, const int totcol) +static void new_id_matar(Main *bmain, Material **matar, const int totcol) { ID *id; int a; @@ -1835,7 +1835,7 @@ static void new_id_matar(Material **matar, const int totcol) id_us_min(id); } else if (id->us > 1) { - matar[a] = BKE_material_copy(matar[a]); + matar[a] = BKE_material_copy(bmain, matar[a]); id_us_min(id); id->newid = (ID *)matar[a]; } @@ -1865,7 +1865,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag) switch (ob->type) { case OB_LAMP: - ob->data = la = BKE_lamp_copy(ob->data); + ob->data = la = BKE_lamp_copy(bmain, ob->data); for (a = 0; a < MAX_MTEX; a++) { if (la->mtex[a]) { ID_NEW(la->mtex[a]->object); @@ -1873,37 +1873,37 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag) } break; case OB_CAMERA: - ob->data = BKE_camera_copy(ob->data); + ob->data = BKE_camera_copy(bmain, ob->data); break; case OB_MESH: - ob->data = me = BKE_mesh_copy(ob->data); + ob->data = me = BKE_mesh_copy(bmain, ob->data); if (me->key) BKE_animdata_copy_id_action((ID *)me->key); break; case OB_MBALL: - ob->data = BKE_mball_copy_ex(bmain, ob->data); + ob->data = BKE_mball_copy(bmain, ob->data); break; case OB_CURVE: case OB_SURF: case OB_FONT: - ob->data = cu = BKE_curve_copy_ex(bmain, ob->data); + ob->data = cu = BKE_curve_copy(bmain, ob->data); ID_NEW(cu->bevobj); ID_NEW(cu->taperobj); if (cu->key) BKE_animdata_copy_id_action((ID *)cu->key); break; case OB_LATTICE: - ob->data = lat = BKE_lattice_copy_ex(bmain, ob->data); + ob->data = lat = BKE_lattice_copy(bmain, ob->data); if (lat->key) BKE_animdata_copy_id_action((ID *)lat->key); break; case OB_ARMATURE: DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - ob->data = BKE_armature_copy(ob->data); + ob->data = BKE_armature_copy(bmain, ob->data); BKE_pose_rebuild(ob, ob->data); break; case OB_SPEAKER: - ob->data = BKE_speaker_copy(ob->data); + ob->data = BKE_speaker_copy(bmain, ob->data); break; default: if (G.debug & G_DEBUG) @@ -1945,7 +1945,7 @@ static void single_object_action_users(Scene *scene, const int flag) } } -static void single_mat_users(Scene *scene, const int flag, const bool do_textures) +static void single_mat_users(Main *bmain, Scene *scene, const int flag, const bool do_textures) { Object *ob; Base *base; @@ -1962,7 +1962,7 @@ static void single_mat_users(Scene *scene, const int flag, const bool do_texture /* do not test for LIB_TAG_NEW: this functions guaranteed delivers single_users! */ if (ma->id.us > 1) { - man = BKE_material_copy(ma); + man = BKE_material_copy(bmain, ma); BKE_animdata_copy_id_action(&man->id); man->id.us = 0; @@ -1973,7 +1973,7 @@ static void single_mat_users(Scene *scene, const int flag, const bool do_texture if (ma->mtex[b] && (tex = ma->mtex[b]->tex)) { if (tex->id.us > 1) { id_us_min(&tex->id); - tex = BKE_texture_copy(tex); + tex = BKE_texture_copy(bmain, tex); BKE_animdata_copy_id_action(&tex->id); man->mtex[b]->tex = tex; } @@ -1987,7 +1987,7 @@ static void single_mat_users(Scene *scene, const int flag, const bool do_texture } } -static void do_single_tex_user(Tex **from) +static void do_single_tex_user(Main *bmain, Tex **from) { Tex *tex, *texn; @@ -2000,7 +2000,7 @@ static void do_single_tex_user(Tex **from) id_us_min(&tex->id); } else if (tex->id.us > 1) { - texn = BKE_texture_copy(tex); + texn = BKE_texture_copy(bmain, tex); BKE_animdata_copy_id_action(&texn->id); tex->id.newid = (ID *)texn; id_us_min(&tex->id); @@ -2020,7 +2020,7 @@ static void single_tex_users_expand(Main *bmain) 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(&(ma->mtex[b]->tex)); + do_single_tex_user(bmain, &(ma->mtex[b]->tex)); } } } @@ -2030,7 +2030,7 @@ static void single_tex_users_expand(Main *bmain) 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(&(la->mtex[b]->tex)); + do_single_tex_user(bmain, &(la->mtex[b]->tex)); } } } @@ -2040,7 +2040,7 @@ static void single_tex_users_expand(Main *bmain) 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(&(wo->mtex[b]->tex)); + do_single_tex_user(bmain, &(wo->mtex[b]->tex)); } } } @@ -2059,19 +2059,19 @@ static void single_mat_users_expand(Main *bmain) for (ob = bmain->object.first; ob; ob = ob->id.next) if (ob->id.tag & LIB_TAG_NEW) - new_id_matar(ob->mat, ob->totcol); + new_id_matar(bmain, ob->mat, ob->totcol); for (me = bmain->mesh.first; me; me = me->id.next) if (me->id.tag & LIB_TAG_NEW) - new_id_matar(me->mat, me->totcol); + new_id_matar(bmain, me->mat, me->totcol); for (cu = bmain->curve.first; cu; cu = cu->id.next) if (cu->id.tag & LIB_TAG_NEW) - new_id_matar(cu->mat, cu->totcol); + new_id_matar(bmain, cu->mat, cu->totcol); for (mb = bmain->mball.first; mb; mb = mb->id.next) if (mb->id.tag & LIB_TAG_NEW) - new_id_matar(mb->mat, mb->totcol); + new_id_matar(bmain, mb->mat, mb->totcol); /* material imats */ for (ma = bmain->mat.first; ma; ma = ma->id.next) @@ -2376,7 +2376,7 @@ static int make_single_user_exec(bContext *C, wmOperator *op) } if (RNA_boolean_get(op->ptr, "material")) { - single_mat_users(scene, flag, RNA_boolean_get(op->ptr, "texture")); + single_mat_users(bmain, scene, flag, RNA_boolean_get(op->ptr, "texture")); } #if 0 /* can't do this separate from materials */ -- cgit v1.2.3 From e0c163661d339d35a518275993059136ee1e4e3e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 11 Jul 2016 08:45:00 +1000 Subject: Add missing braces --- source/blender/editors/object/object_transform.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source/blender/editors/object') diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index c681b945788..4d7d7df0d2f 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -129,16 +129,18 @@ static void object_clear_rot(Object *ob, const bool clear_delta) ob->quat[0] = 1.0f; if (clear_delta) ob->dquat[0] = 1.0f; } - if ((ob->protectflag & OB_LOCK_ROTX) == 0) + if ((ob->protectflag & OB_LOCK_ROTX) == 0) { ob->quat[1] = 0.0f; if (clear_delta) ob->dquat[1] = 0.0f; - if ((ob->protectflag & OB_LOCK_ROTY) == 0) + } + if ((ob->protectflag & OB_LOCK_ROTY) == 0) { ob->quat[2] = 0.0f; if (clear_delta) ob->dquat[2] = 0.0f; - if ((ob->protectflag & OB_LOCK_ROTZ) == 0) + } + if ((ob->protectflag & OB_LOCK_ROTZ) == 0) { ob->quat[3] = 0.0f; if (clear_delta) ob->dquat[3] = 0.0f; - + } /* TODO: does this quat need normalizing now? */ } else { -- cgit v1.2.3