diff options
Diffstat (limited to 'source/blender/editors/object')
24 files changed, 863 insertions, 423 deletions
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt index 953ef8114f9..e4991f31649 100644 --- a/source/blender/editors/object/CMakeLists.txt +++ b/source/blender/editors/object/CMakeLists.txt @@ -32,17 +32,13 @@ set(INC ../../modifiers ../../python ../../shader_fx - ../../render/extern/include + ../../render ../../windowmanager ../../../../intern/clog ../../../../intern/glew-mx ../../../../intern/guardedalloc ) -set(INC_SYS - ${GLEW_INCLUDE_PATH} -) - set(SRC object_add.c object_bake.c @@ -81,7 +77,6 @@ set(LIB bf_windowmanager ) -add_definitions(${GL_DEFINITIONS}) if(WITH_PYTHON) add_definitions(-DWITH_PYTHON) @@ -91,4 +86,10 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() +if(WITH_EXPERIMENTAL_FEATURES) + add_definitions(-DWITH_GEOMETRY_NODES) + add_definitions(-DWITH_POINT_CLOUD) + add_definitions(-DWITH_HAIR_NODES) +endif() + blender_add_lib(bf_editor_object "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 4de48fba494..e15e64a5e45 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -41,6 +41,7 @@ #include "DNA_object_fluidsim_types.h" #include "DNA_object_force_types.h" #include "DNA_object_types.h" +#include "DNA_pointcloud_types.h" #include "DNA_scene_types.h" #include "DNA_vfont_types.h" @@ -284,7 +285,7 @@ float ED_object_new_primitive_matrix( return dia; } - // return 1.0f; + /* return 1.0f; */ } /** \} */ @@ -527,14 +528,17 @@ Object *ED_object_add_type_with_obdata(bContext *C, Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob; - /* for as long scene has editmode... */ - if (CTX_data_edit_object(C)) { - ED_object_editmode_exit(C, EM_FREEDATA); + /* For as long scene has editmode... */ + { + Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + if (obedit != NULL) { + ED_object_editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA); + } } /* deselects all, sets active object */ + Object *ob; if (obdata != NULL) { BLI_assert(type == BKE_object_obdata_to_type(obdata)); ob = BKE_object_add_for_data(bmain, view_layer, type, name, obdata, true); @@ -591,18 +595,16 @@ Object *ED_object_add_type(bContext *C, /* for object add operator */ static int object_add_exec(bContext *C, wmOperator *op) { - Object *ob; - bool enter_editmode; ushort local_view_bits; + bool enter_editmode; float loc[3], rot[3], radius; - WM_operator_view3d_unit_defaults(C, op); if (!ED_object_add_generic_get_opts( C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL)) { return OPERATOR_CANCELLED; } radius = RNA_float_get(op->ptr, "radius"); - ob = ED_object_add_type( + Object *ob = ED_object_add_type( C, RNA_enum_get(op->ptr, "type"), NULL, loc, rot, enter_editmode, local_view_bits); if (ob->type == OB_LATTICE) { @@ -662,27 +664,22 @@ static const char *get_lightprobe_defname(int type) static int lightprobe_add_exec(bContext *C, wmOperator *op) { - Object *ob; - LightProbe *probe; - int type; bool enter_editmode; ushort local_view_bits; float loc[3], rot[3]; - float radius; - WM_operator_view3d_unit_defaults(C, op); if (!ED_object_add_generic_get_opts( C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL)) { return OPERATOR_CANCELLED; } - type = RNA_enum_get(op->ptr, "type"); - radius = RNA_float_get(op->ptr, "radius"); + int type = RNA_enum_get(op->ptr, "type"); + float radius = RNA_float_get(op->ptr, "radius"); - ob = ED_object_add_type( + Object *ob = ED_object_add_type( C, OB_LIGHTPROBE, get_lightprobe_defname(type), loc, rot, false, local_view_bits); copy_v3_fl(ob->scale, radius); - probe = (LightProbe *)ob->data; + LightProbe *probe = (LightProbe *)ob->data; BKE_lightprobe_type_set(probe, type); @@ -761,35 +758,35 @@ static const char *get_effector_defname(ePFieldType type) static int effector_add_exec(bContext *C, wmOperator *op) { - Object *ob; - int type; bool enter_editmode; ushort local_view_bits; float loc[3], rot[3]; - float mat[4][4]; - float dia; - WM_operator_view3d_unit_defaults(C, op); if (!ED_object_add_generic_get_opts( C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL)) { return OPERATOR_CANCELLED; } - type = RNA_enum_get(op->ptr, "type"); - dia = RNA_float_get(op->ptr, "radius"); + int type = RNA_enum_get(op->ptr, "type"); + float dia = RNA_float_get(op->ptr, "radius"); + Object *ob; if (type == PFIELD_GUIDE) { + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); Curve *cu; ob = ED_object_add_type( C, OB_CURVE, get_effector_defname(type), loc, rot, false, local_view_bits); cu = ob->data; cu->flag |= CU_PATH | CU_3D; - ED_object_editmode_enter(C, 0); + ED_object_editmode_enter_ex(bmain, scene, ob, 0); + + float mat[4][4]; ED_object_new_primitive_matrix(C, ob, loc, rot, mat); BLI_addtail(&cu->editnurb->nurbs, ED_curve_add_nurbs_primitive(C, ob, mat, CU_NURBS | CU_PRIM_PATH, dia)); if (!enter_editmode) { - ED_object_editmode_exit(C, EM_FREEDATA); + ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA); } } else { @@ -839,20 +836,18 @@ static int object_camera_add_exec(bContext *C, wmOperator *op) { View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); - Object *ob; - Camera *cam; - bool enter_editmode; - ushort local_view_bits; - float loc[3], rot[3]; /* force view align for cameras */ RNA_enum_set(op->ptr, "align", ALIGN_VIEW); + ushort local_view_bits; + bool enter_editmode; + float loc[3], rot[3]; if (!ED_object_add_generic_get_opts( C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL)) { return OPERATOR_CANCELLED; } - ob = ED_object_add_type(C, OB_CAMERA, NULL, loc, rot, false, local_view_bits); + Object *ob = ED_object_add_type(C, OB_CAMERA, NULL, loc, rot, false, local_view_bits); if (v3d) { if (v3d->camera == NULL) { @@ -863,7 +858,7 @@ static int object_camera_add_exec(bContext *C, wmOperator *op) } } - cam = ob->data; + Camera *cam = ob->data; cam->drawsize = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) : ED_scene_grid_scale(scene, NULL); return OPERATOR_FINISHED; @@ -900,19 +895,21 @@ void OBJECT_OT_camera_add(wmOperatorType *ot) static int object_metaball_add_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); - bool newob = false; - bool enter_editmode; + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + ushort local_view_bits; + bool enter_editmode; float loc[3], rot[3]; - float mat[4][4]; - float dia; - WM_operator_view3d_unit_defaults(C, op); if (!ED_object_add_generic_get_opts( C, op, 'Z', loc, rot, NULL, &enter_editmode, &local_view_bits, NULL)) { return OPERATOR_CANCELLED; } + + bool newob = false; + Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); if (obedit == NULL || obedit->type != OB_MBALL) { obedit = ED_object_add_type(C, OB_MBALL, NULL, loc, rot, true, local_view_bits); newob = true; @@ -921,17 +918,18 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); } + float mat[4][4]; ED_object_new_primitive_matrix(C, obedit, loc, rot, mat); /* Halving here is done to account for constant values from #BKE_mball_element_add. * While the default radius of the resulting meta element is 2, * we want to pass in 1 so other values such as resolution are scaled by 1.0. */ - dia = RNA_float_get(op->ptr, "radius") / 2; + float dia = RNA_float_get(op->ptr, "radius") / 2; ED_mball_add_primitive(C, obedit, newob, mat, dia, RNA_enum_get(op->ptr, "type")); /* userdef */ if (newob && !enter_editmode) { - ED_object_editmode_exit(C, EM_FREEDATA); + ED_object_editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA); } WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); @@ -1017,7 +1015,11 @@ void OBJECT_OT_text_add(wmOperatorType *ot) static int object_armature_add_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + RegionView3D *rv3d = CTX_wm_region_view3d(C); bool newob = false; bool enter_editmode; @@ -1032,7 +1034,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op) } if ((obedit == NULL) || (obedit->type != OB_ARMATURE)) { obedit = ED_object_add_type(C, OB_ARMATURE, NULL, loc, rot, true, local_view_bits); - ED_object_editmode_enter(C, 0); + ED_object_editmode_enter_ex(bmain, scene, obedit, 0); newob = true; } else { @@ -1049,7 +1051,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op) /* userdef */ if (newob && !enter_editmode) { - ED_object_editmode_exit(C, EM_FREEDATA); + ED_object_editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA); } WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); @@ -1608,15 +1610,14 @@ void OBJECT_OT_data_instance_add(wmOperatorType *ot) static int object_speaker_add_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - Object *ob; - ushort local_view_bits; - float loc[3], rot[3]; Scene *scene = CTX_data_scene(C); + ushort local_view_bits; + float loc[3], rot[3]; if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, NULL, &local_view_bits, NULL)) { return OPERATOR_CANCELLED; } - ob = ED_object_add_type(C, OB_SPEAKER, NULL, loc, rot, false, local_view_bits); + Object *ob = ED_object_add_type(C, OB_SPEAKER, NULL, loc, rot, false, local_view_bits); /* to make it easier to start using this immediately in NLA, a default sound clip is created * ready to be moved around to retime the sound and/or make new sound clips @@ -1677,10 +1678,10 @@ static int object_hair_add_exec(bContext *C, wmOperator *op) { ushort local_view_bits; float loc[3], rot[3]; - if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, NULL, &local_view_bits, NULL)) { return OPERATOR_CANCELLED; } + Object *object = ED_object_add_type(C, OB_HAIR, NULL, loc, rot, false, local_view_bits); object->dtx |= OB_DRAWBOUNDOX; /* TODO: remove once there is actual drawing. */ @@ -1712,7 +1713,7 @@ void OBJECT_OT_hair_add(wmOperatorType *ot) static bool object_pointcloud_add_poll(bContext *C) { - if (!U.experimental.use_new_particle_system) { + if (!U.experimental.use_new_point_cloud_type) { return false; } return ED_operator_objectmode(C); @@ -1722,10 +1723,10 @@ static int object_pointcloud_add_exec(bContext *C, wmOperator *op) { ushort local_view_bits; float loc[3], rot[3]; - if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, NULL, &local_view_bits, NULL)) { return OPERATOR_CANCELLED; } + Object *object = ED_object_add_type(C, OB_POINTCLOUD, NULL, loc, rot, false, local_view_bits); object->dtx |= OB_DRAWBOUNDOX; /* TODO: remove once there is actual drawing. */ @@ -1778,7 +1779,6 @@ static int object_delete_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win; const bool use_global = RNA_boolean_get(op->ptr, "use_global"); uint changed_count = 0; @@ -1871,7 +1871,7 @@ static int object_delete_exec(bContext *C, wmOperator *op) /* delete has to handle all open scenes */ BKE_main_id_tag_listbase(&bmain->scenes, LIB_TAG_DOIT, true); - for (win = wm->windows.first; win; win = win->next) { + LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { scene = WM_window_get_active_scene(win); if (scene->id.tag & LIB_TAG_DOIT) { @@ -2063,18 +2063,16 @@ static void make_object_duplilist_real(bContext *C, { Main *bmain = CTX_data_main(C); ViewLayer *view_layer = CTX_data_view_layer(C); - ListBase *lb_duplis; - DupliObject *dob; - GHash *dupli_gh, *parent_gh = NULL, *instancer_gh = NULL; + GHash *parent_gh = NULL, *instancer_gh = NULL; if (!(base->object->transflag & OB_DUPLI)) { return; } Object *object_eval = DEG_get_evaluated_object(depsgraph, base->object); - lb_duplis = object_duplilist(depsgraph, scene, object_eval); + ListBase *lb_duplis = object_duplilist(depsgraph, scene, object_eval); - dupli_gh = BLI_ghash_ptr_new(__func__); + GHash *dupli_gh = BLI_ghash_ptr_new(__func__); if (use_hierarchy) { parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__); @@ -2084,10 +2082,10 @@ static void make_object_duplilist_real(bContext *C, } } - for (dob = lb_duplis->first; dob; dob = dob->next) { + LISTBASE_FOREACH (DupliObject *, dob, lb_duplis) { Object *ob_src = DEG_get_original_object(dob->ob); - Object *ob_dst = ID_NEW_SET(ob_src, BKE_object_copy(bmain, ob_src)); - Base *base_dst; + Object *ob_dst = ID_NEW_SET(ob_src, BKE_id_copy(bmain, &ob_src->id)); + id_us_min(&ob_dst->id); /* font duplis can have a totcol without material, we get them from parent * should be implemented better... @@ -2097,7 +2095,7 @@ static void make_object_duplilist_real(bContext *C, } BKE_collection_object_add_from(bmain, scene, base->object, ob_dst); - base_dst = BKE_view_layer_base_find(view_layer, ob_dst); + Base *base_dst = BKE_view_layer_base_find(view_layer, ob_dst); BLI_assert(base_dst != NULL); ED_object_base_select(base_dst, BA_SELECT); @@ -2146,7 +2144,7 @@ static void make_object_duplilist_real(bContext *C, } } - for (dob = lb_duplis->first; dob; dob = dob->next) { + LISTBASE_FOREACH (DupliObject *, dob, lb_duplis) { Object *ob_src = dob->ob; Object *ob_dst = BLI_ghash_lookup(dupli_gh, dob); @@ -2228,7 +2226,7 @@ static void make_object_duplilist_real(bContext *C, } if (base->object->transflag & OB_DUPLICOLLECTION && base->object->instance_collection) { - for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) { + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { if (ob->proxy_group == base->object) { ob->proxy = NULL; ob->proxy_from = NULL; @@ -2315,9 +2313,28 @@ void OBJECT_OT_duplicates_make_real(wmOperatorType *ot) * \{ */ static const EnumPropertyItem convert_target_items[] = { - {OB_CURVE, "CURVE", ICON_OUTLINER_OB_CURVE, "Curve from Mesh/Text", ""}, - {OB_MESH, "MESH", ICON_OUTLINER_OB_MESH, "Mesh from Curve/Meta/Surf/Text", ""}, - {OB_GPENCIL, "GPENCIL", ICON_OUTLINER_OB_GREASEPENCIL, "Grease Pencil from Curve/Mesh", ""}, + {OB_CURVE, "CURVE", ICON_OUTLINER_OB_CURVE, "Curve", "Curve from Mesh or Text objects"}, + {OB_MESH, + "MESH", + ICON_OUTLINER_OB_MESH, + "Mesh", +#ifdef WITH_POINT_CLOUD + "Mesh from Curve, Surface, Metaball, Text, or Pointcloud objects"}, +#else + "Mesh from Curve, Surface, Metaball, or Text objects"}, +#endif + {OB_GPENCIL, + "GPENCIL", + ICON_OUTLINER_OB_GREASEPENCIL, + "Grease Pencil", + "Grease Pencil from Curve or Mesh objects"}, +#ifdef WITH_POINT_CLOUD + {OB_POINTCLOUD, + "POINTCLOUD", + ICON_OUTLINER_OB_POINTCLOUD, + "Pointcloud", + "Pointcloud from Mesh objects"}, +#endif {0, NULL, 0, NULL, NULL}, }; @@ -2331,7 +2348,7 @@ static void object_data_convert_ensure_curve_cache(Depsgraph *depsgraph, Scene * */ if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) { /* We need 'for render' ON here, to enable computing bevel dipslist if needed. - * Also makes sense anyway, we would not want e.g. to loose hidden parts etc. */ + * Also makes sense anyway, we would not want e.g. to lose hidden parts etc. */ BKE_displist_make_curveTypes(depsgraph, scene, ob, true, false); } else if (ob->type == OB_MBALL) { @@ -2392,18 +2409,16 @@ static bool object_convert_poll(bContext *C) static Base *duplibase_for_convert( Main *bmain, Depsgraph *depsgraph, Scene *scene, ViewLayer *view_layer, Base *base, Object *ob) { - Object *obn; - Base *basen; - if (ob == NULL) { ob = base->object; } - obn = BKE_object_copy(bmain, ob); + Object *obn = (Object *)BKE_id_copy(bmain, &ob->id); + id_us_min(&obn->id); DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); BKE_collection_object_add_from(bmain, scene, ob, obn); - basen = BKE_view_layer_base_find(view_layer, obn); + Base *basen = BKE_view_layer_base_find(view_layer, obn); ED_object_base_select(basen, BA_SELECT); ED_object_base_select(base, BA_DESELECT); @@ -2450,11 +2465,6 @@ static int object_convert_exec(bContext *C, wmOperator *op) View3D *v3d = CTX_wm_view3d(C); Base *basen = NULL, *basact = NULL; Object *ob1, *obact = CTX_data_active_object(C); - Curve *cu; - Nurb *nu; - MetaBall *mb; - Mesh *me; - Object *ob_gpencil = NULL; const short target = RNA_enum_get(op->ptr, "target"); bool keep_original = RNA_boolean_get(op->ptr, "keep_original"); @@ -2540,7 +2550,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) /* obdata already modified */ if (!IS_TAGGED(ob->data)) { /* When 2 objects with linked data are selected, converting both - * would keep modifiers on all but the converted object [#26003] */ + * would keep modifiers on all but the converted object T26003. */ if (ob->type == OB_MESH) { BKE_object_free_modifiers(ob, 0); /* after derivedmesh calls! */ } @@ -2558,11 +2568,11 @@ static int object_convert_exec(bContext *C, wmOperator *op) newob = basen->object; /* decrement original mesh's usage count */ - me = newob->data; + Mesh *me = newob->data; id_us_min(&me->id); /* make a new copy of the mesh */ - newob->data = BKE_mesh_copy(bmain, me); + newob->data = BKE_id_copy(bmain, &me->id); } else { newob = ob; @@ -2587,7 +2597,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) mat4_to_loc_rot_size(loc, rot, size, ob->obmat); mat3_to_eul(eul, rot); - ob_gpencil = ED_gpencil_add_object(C, loc, local_view_bits); + Object *ob_gpencil = ED_gpencil_add_object(C, loc, local_view_bits); copy_v3_v3(ob_gpencil->loc, loc); copy_v3_v3(ob_gpencil->rot, eul); copy_v3_v3(ob_gpencil->scale, size); @@ -2624,6 +2634,31 @@ static int object_convert_exec(bContext *C, wmOperator *op) } ob_gpencil->actcol = actcol; } + else if (ob->type == OB_MESH && target == OB_POINTCLOUD) { + ob->flag |= OB_DONE; + + if (keep_original) { + basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, NULL); + newob = basen->object; + + /* decrement original mesh's usage count */ + Mesh *me = newob->data; + id_us_min(&me->id); + + /* make a new copy of the mesh */ + newob->data = BKE_id_copy(bmain, &me->id); + } + else { + newob = ob; + } + + BKE_mesh_to_pointcloud(bmain, depsgraph, scene, newob); + + if (newob->type == OB_POINTCLOUD) { + BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */ + ED_rigidbody_object_remove(bmain, scene, newob); + } + } else if (ob->type == OB_MESH) { ob->flag |= OB_DONE; @@ -2632,11 +2667,11 @@ static int object_convert_exec(bContext *C, wmOperator *op) newob = basen->object; /* decrement original mesh's usage count */ - me = newob->data; + Mesh *me = newob->data; id_us_min(&me->id); /* make a new copy of the mesh */ - newob->data = BKE_mesh_copy(bmain, me); + newob->data = BKE_id_copy(bmain, &me->id); } else { newob = ob; @@ -2651,6 +2686,8 @@ static int object_convert_exec(bContext *C, wmOperator *op) Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_MESH); me_eval = BKE_mesh_copy_for_eval(me_eval, false); + /* Full (edge-angle based) draw calculation should ideally be performed. */ + BKE_mesh_edges_set_draw_render(me_eval); BKE_mesh_nomain_to_mesh(me_eval, newob->data, newob, &CD_MASK_MESH, true); BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */ } @@ -2665,13 +2702,13 @@ static int object_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(bmain, ob->data); + newob->data = BKE_id_copy(bmain, ob->data); } else { newob = ob; } - cu = newob->data; + Curve *cu = newob->data; Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); BKE_vfont_to_curve_ex(ob_eval, ob_eval->data, FO_EDIT, &cu->nurb, NULL, NULL, NULL, NULL); @@ -2709,7 +2746,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) } } - for (nu = cu->nurb.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { nu->charidx = 0; } @@ -2736,7 +2773,7 @@ static int object_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(bmain, ob->data); + newob->data = BKE_id_copy(bmain, ob->data); } else { newob = ob; @@ -2758,7 +2795,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) * Nurbs Surface are not supported. */ ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0; - ob_gpencil = ED_gpencil_add_object(C, ob->loc, local_view_bits); + Object *ob_gpencil = ED_gpencil_add_object(C, ob->loc, local_view_bits); copy_v3_v3(ob_gpencil->rot, ob->rot); copy_v3_v3(ob_gpencil->scale, ob->scale); BKE_gpencil_convert_curve(bmain, scene, ob_gpencil, ob, false, 1.0f, 0.0f); @@ -2783,13 +2820,13 @@ static int object_convert_exec(bContext *C, wmOperator *op) basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, baseob); newob = basen->object; - mb = newob->data; + MetaBall *mb = newob->data; id_us_min(&mb->id); newob->data = BKE_mesh_add(bmain, "Mesh"); newob->type = OB_MESH; - me = newob->data; + Mesh *me = newob->data; me->totcol = mb->totcol; if (newob->totcol) { me->mat = MEM_dupallocN(mb->mat); @@ -2809,6 +2846,31 @@ static int object_convert_exec(bContext *C, wmOperator *op) mballConverted = 1; } } + else if (ob->type == OB_POINTCLOUD && target == OB_MESH) { + ob->flag |= OB_DONE; + + if (keep_original) { + basen = duplibase_for_convert(bmain, depsgraph, scene, view_layer, base, NULL); + newob = basen->object; + + /* decrement original pointclouds's usage count */ + PointCloud *pointcloud = newob->data; + id_us_min(&pointcloud->id); + + /* make a new copy of the pointcloud */ + newob->data = BKE_id_copy(bmain, &pointcloud->id); + } + else { + newob = ob; + } + + BKE_pointcloud_to_mesh(bmain, depsgraph, scene, newob); + + if (newob->type == OB_MESH) { + BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */ + ED_rigidbody_object_remove(bmain, scene, newob); + } + } else { continue; } @@ -2870,7 +2932,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) /* Remove curves and meshes converted to Grease Pencil object. */ if (gpencilConverted) { FOREACH_SCENE_OBJECT_BEGIN (scene, ob_delete) { - if ((ob_delete->type == OB_CURVE) || (ob_delete->type == OB_MESH)) { + if (ELEM(ob_delete->type, OB_CURVE, OB_MESH)) { if (ob_delete->flag & OB_DONE) { ED_object_base_free_and_unlink(bmain, scene, ob_delete); } @@ -2927,7 +2989,7 @@ void OBJECT_OT_convert(wmOperatorType *ot) PropertyRNA *prop; /* identifiers */ - ot->name = "Convert to"; + ot->name = "Convert To"; ot->description = "Convert selected objects to another type"; ot->idname = "OBJECT_OT_convert"; @@ -3025,7 +3087,7 @@ static Base *object_add_duplicate_internal(Main *bmain, /* 1) duplis should end up in same collection as the original * 2) Rigid Body sim participants MUST always be part of a collection... */ - // XXX: is 2) really a good measure here? + /* XXX: is 2) really a good measure here? */ if (ob->rigidbody_object || ob->rigidbody_constraint) { Collection *collection; for (collection = bmain->collections.first; collection; collection = collection->id.next) { @@ -3057,7 +3119,7 @@ Base *ED_object_add_duplicate( ob = basen->object; - /* link own references to the newly duplicated data [#26816] */ + /* link own references to the newly duplicated data T26816. */ BKE_libblock_relink_to_newid(&ob->id); /* DAG_relations_tag_update(bmain); */ /* caller must do */ diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index ae1aae27b7f..008498a1735 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -53,7 +53,7 @@ #include "RE_multires_bake.h" #include "RE_pipeline.h" -#include "RE_shader_ext.h" +#include "RE_texture.h" #include "PIL_time.h" @@ -97,7 +97,6 @@ typedef struct MultiresBakerJobData { int len; } ob_image; DerivedMesh *lores_dm, *hires_dm; - bool simple; int lvl, tot_lvl; ListBase images; } MultiresBakerJobData; @@ -247,7 +246,7 @@ static DerivedMesh *multiresbake_create_loresdm(Scene *scene, Object *ob, int *l return dm; } -static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *lvl, bool *simple) +static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *lvl) { Mesh *me = (Mesh *)ob->data; MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0); @@ -264,7 +263,6 @@ static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *l CustomData_set_only_copy(&cddm->polyData, CD_MASK_BAREMESH.pmask); *lvl = mmd->totlvl; - *simple = mmd->simple != 0; tmp_mmd.lvl = mmd->totlvl; tmp_mmd.sculptlvl = mmd->totlvl; @@ -386,7 +384,7 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op) bkr.ob_image.array = bake_object_image_get_array(ob); bkr.ob_image.len = ob->totcol; - bkr.hires_dm = multiresbake_create_hiresdm(scene, ob, &bkr.tot_lvl, &bkr.simple); + bkr.hires_dm = multiresbake_create_hiresdm(scene, ob, &bkr.tot_lvl); bkr.lores_dm = multiresbake_create_loresdm(scene, ob, &bkr.lvl); RE_multires_bake_images(&bkr); @@ -441,7 +439,7 @@ static void init_multiresbake_job(bContext *C, MultiresBakeJob *bkj) data->ob_image.len = ob->totcol; /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */ - data->hires_dm = multiresbake_create_hiresdm(scene, ob, &data->tot_lvl, &data->simple); + data->hires_dm = multiresbake_create_hiresdm(scene, ob, &data->tot_lvl); data->lores_dm = multiresbake_create_loresdm(scene, ob, &lvl); data->lvl = lvl; @@ -491,7 +489,6 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa bkr.hires_dm = data->hires_dm; bkr.tot_lvl = data->tot_lvl; bkr.lvl = data->lvl; - bkr.simple = data->simple; /* needed for proper progress bar */ bkr.tot_obj = tot_obj; diff --git a/source/blender/editors/object/object_collection.c b/source/blender/editors/object/object_collection.c index 24f6d8c79f9..ea203468e74 100644 --- a/source/blender/editors/object/object_collection.c +++ b/source/blender/editors/object/object_collection.c @@ -50,6 +50,8 @@ #include "RNA_define.h" #include "RNA_enum_types.h" +#include "UI_interface_icons.h" + #include "object_intern.h" /********************* 3d view operators ***********************/ @@ -94,7 +96,7 @@ static const EnumPropertyItem *collection_object_active_itemf(bContext *C, collection = NULL; while ((collection = BKE_collection_object_find(bmain, scene, collection, ob))) { item_tmp.identifier = item_tmp.name = collection->id.name + 2; - /* item_tmp.icon = ICON_ARMATURE_DATA; */ + item_tmp.icon = UI_icon_color_from_collection(collection); item_tmp.value = i; RNA_enum_item_add(&item, &totitem, &item_tmp); i++; diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 85522209e29..fa8531dfb48 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -111,9 +111,9 @@ ListBase *ED_object_constraint_active_list(Object *ob) */ ListBase *ED_object_pose_constraint_list(const bContext *C) { - bPoseChannel *pose_bone = CTX_data_pointer_get(C, "active_pose_bone").data; + bPoseChannel *pose_bone = CTX_data_pointer_get(C, "pose_bone").data; if (pose_bone == NULL) { - pose_bone = CTX_data_pointer_get(C, "pose_bone").data; + pose_bone = CTX_data_pointer_get(C, "active_pose_bone").data; if (pose_bone == NULL) { return NULL; } @@ -242,7 +242,7 @@ static char *buildmenu_pyconstraints(Main *bmain, Text *con_text, int *pyconinde } #endif /* WITH_PYTHON */ -#if 0 // UNUSED, until pyconstraints are added back. +#if 0 /* UNUSED, until pyconstraints are added back. */ /* this callback gets called when the 'refresh' button of a pyconstraint gets pressed */ static void update_pyconstraint_cb(void *arg1, void *arg2) { @@ -257,7 +257,7 @@ static void update_pyconstraint_cb(void *arg1, void *arg2) } # endif } -#endif // UNUSED +#endif /* UNUSED */ /** \} */ @@ -387,6 +387,11 @@ static void test_constraint( data->act = NULL; con->flag |= CONSTRAINT_DISABLE; } + + /* Skip target checking if we're not using it */ + if (data->flag & ACTCON_USE_EVAL_TIME) { + check_targets = false; + } } else if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) { bFollowPathConstraint *data = con->data; @@ -813,7 +818,7 @@ static bConstraint *edit_constraint_property_get(bContext *C, wmOperator *op, Ob list = ED_object_pose_constraint_list(C); } else { - list = ED_object_constraint_active_list(ob); + list = &ob->constraints; } con = BKE_constraints_find_name(list, constraint_name); @@ -1421,6 +1426,49 @@ void ED_object_constraint_dependency_tag_update(Main *bmain, Object *ob, bConstr DEG_relations_tag_update(bmain); } +bool ED_object_constraint_move_to_index(Object *ob, bConstraint *con, const int index) +{ + BLI_assert(con != NULL); + BLI_assert(index >= 0); + + ListBase *conlist = ED_object_constraint_list_from_constraint(ob, con, NULL); + int current_index = BLI_findindex(conlist, con); + BLI_assert(current_index >= 0); + + BLI_listbase_link_move(conlist, con, index - current_index); + + WM_main_add_notifier(NC_OBJECT | ND_CONSTRAINT, ob); + + return true; +} + +void ED_object_constraint_link(Main *bmain, Object *ob_dst, ListBase *dst, ListBase *src) +{ + BKE_constraints_free(dst); + BKE_constraints_copy(dst, src, true); + LISTBASE_FOREACH (bConstraint *, con, dst) { + ED_object_constraint_dependency_tag_update(bmain, ob_dst, con); + } + WM_main_add_notifier(NC_OBJECT | ND_CONSTRAINT | NA_ADDED, NULL); +} + +void ED_object_constraint_copy_for_object(Main *bmain, Object *ob_dst, bConstraint *con) +{ + BKE_constraint_copy_for_object(ob_dst, con); + ED_object_constraint_dependency_tag_update(bmain, ob_dst, con); + WM_main_add_notifier(NC_OBJECT | ND_CONSTRAINT | NA_ADDED, ob_dst); +} + +void ED_object_constraint_copy_for_pose(Main *bmain, + Object *ob_dst, + bPoseChannel *pchan, + bConstraint *con) +{ + BKE_constraint_copy_for_pose(ob_dst, pchan, con); + ED_object_constraint_dependency_tag_update(bmain, ob_dst, con); + WM_main_add_notifier(NC_OBJECT | ND_CONSTRAINT | NA_ADDED, ob_dst); +} + /** \} */ /* ------------------------------------------------------------------- */ @@ -1613,13 +1661,7 @@ static int constraint_move_to_index_exec(bContext *C, wmOperator *op) } if (con) { - ListBase *conlist = ED_object_constraint_list_from_constraint(ob, con, NULL); - int current_index = BLI_findindex(conlist, con); - BLI_assert(current_index >= 0); - - BLI_listbase_link_move(conlist, con, new_index - current_index); - - WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob); + ED_object_constraint_move_to_index(ob, con, new_index); return OPERATOR_FINISHED; } @@ -1705,8 +1747,8 @@ void POSE_OT_constraints_clear(wmOperatorType *ot) /* callbacks */ ot->exec = pose_constraints_clear_exec; - ot->poll = ED_operator_posemode_exclusive; // XXX - do we want to ensure there are selected - // bones too? + ot->poll = ED_operator_posemode_exclusive; /* XXX - do we want to ensure there are selected + * bones too? */ } static int object_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op)) @@ -2177,7 +2219,7 @@ static const EnumPropertyItem *object_constraint_add_itemf(bContext *UNUSED(C), int totitem = 0; while (item->identifier) { - if ((item->value != CONSTRAINT_TYPE_KINEMATIC) && (item->value != CONSTRAINT_TYPE_SPLINEIK)) { + if (!ELEM(item->value, CONSTRAINT_TYPE_KINEMATIC, CONSTRAINT_TYPE_SPLINEIK)) { RNA_enum_item_add(&object_constraint_items, &totitem, item); } item++; @@ -2291,7 +2333,7 @@ void POSE_OT_constraint_add_with_targets(wmOperatorType *ot) * \note Only for pose-channels. * \{ */ -// TODO: should these be here, or back in editors/armature/poseobject.c again? +/* TODO: should these be here, or back in editors/armature/poseobject.c again? */ /* present menu with options + validation for targets to use */ static int pose_ik_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index 4884df1edb6..99989f86381 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -28,6 +28,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_string.h" #include "BLI_utildefines.h" #include "BKE_context.h" @@ -562,32 +563,45 @@ static bool data_transfer_poll_property(const bContext *UNUSED(C), return false; } - if (STREQ(prop_id, "use_object_transform") && use_auto_transform) { - return false; + if (STREQ(prop_id, "use_object_transform")) { + if (use_auto_transform) { + return false; + } } - if (STREQ(prop_id, "max_distance") && !use_max_distance) { - return false; + else if (STREQ(prop_id, "max_distance")) { + if (!use_max_distance) { + return false; + } } - if (STREQ(prop_id, "islands_precision") && !DT_DATATYPE_IS_LOOP(data_type)) { - return false; + else if (STREQ(prop_id, "islands_precision")) { + if (!DT_DATATYPE_IS_LOOP(data_type)) { + return false; + } } - - if (STREQ(prop_id, "vert_mapping") && !DT_DATATYPE_IS_VERT(data_type)) { - return false; + else if (STREQ(prop_id, "vert_mapping")) { + if (!DT_DATATYPE_IS_VERT(data_type)) { + return false; + } } - if (STREQ(prop_id, "edge_mapping") && !DT_DATATYPE_IS_EDGE(data_type)) { - return false; + else if (STREQ(prop_id, "edge_mapping")) { + if (!DT_DATATYPE_IS_EDGE(data_type)) { + return false; + } } - if (STREQ(prop_id, "loop_mapping") && !DT_DATATYPE_IS_LOOP(data_type)) { - return false; + else if (STREQ(prop_id, "loop_mapping")) { + if (!DT_DATATYPE_IS_LOOP(data_type)) { + return false; + } } - if (STREQ(prop_id, "poly_mapping") && !DT_DATATYPE_IS_POLY(data_type)) { - return false; + else if (STREQ(prop_id, "poly_mapping")) { + if (!DT_DATATYPE_IS_POLY(data_type)) { + return false; + } } - - if ((STREQ(prop_id, "layers_select_src") || STREQ(prop_id, "layers_select_dst")) && - !DT_DATATYPE_IS_MULTILAYERS(data_type)) { - return false; + else if (STR_ELEM(prop_id, "layers_select_src", "layers_select_dst")) { + if (!DT_DATATYPE_IS_MULTILAYERS(data_type)) { + return false; + } } /* Else, show it! */ diff --git a/source/blender/editors/object/object_data_transform.c b/source/blender/editors/object/object_data_transform.c index 8ea35c7a92c..72dde7b734b 100644 --- a/source/blender/editors/object/object_data_transform.c +++ b/source/blender/editors/object/object_data_transform.c @@ -24,7 +24,7 @@ * * This is a small API to store & apply transformations to object data, * where a transformation matrix can be continually applied ontop of the original values - * so we don't loose precision over time. + * so we don't lose precision over time. */ #include <stdlib.h> diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 966aeed75ab..70c3552e8da 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -24,7 +24,7 @@ #include <ctype.h> #include <float.h> #include <math.h> -#include <stddef.h> //for offsetof +#include <stddef.h> /* for offsetof */ #include <stdlib.h> #include <string.h> #include <time.h> @@ -100,6 +100,8 @@ #include "RNA_define.h" #include "RNA_enum_types.h" +#include "UI_interface_icons.h" + #include "CLG_log.h" /* for menu/popup icons etc etc*/ @@ -112,7 +114,7 @@ #include "WM_toolsystem.h" #include "WM_types.h" -#include "object_intern.h" // own include +#include "object_intern.h" /* own include */ static CLG_LogRef LOG = {"ed.object.edit"}; @@ -161,13 +163,32 @@ Object **ED_object_array_in_mode_or_selected(bContext *C, ScrArea *area = CTX_wm_area(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob_active = OBACT(view_layer); + ID *id_pin = NULL; + const bool use_objects_in_mode = (ob_active != NULL) && + (ob_active->mode & (OB_MODE_EDIT | OB_MODE_POSE)); + const char space_type = area ? area->spacetype : SPACE_EMPTY; Object **objects; Object *ob = NULL; bool use_ob = true; - if (area && (area->spacetype == SPACE_PROPERTIES)) { - /* May return pinned object. */ - ob = ED_object_context(C); + + if (space_type == SPACE_PROPERTIES) { + SpaceProperties *sbuts = area->spacedata.first; + id_pin = sbuts->pinid; + } + + if (id_pin && (GS(id_pin->name) == ID_OB)) { + /* Pinned data takes priority, in this case ignore selection & other objects in the mode. */ + ob = (Object *)id_pin; + } + else if ((space_type == SPACE_PROPERTIES) && (use_objects_in_mode == false)) { + /* When using the space-properties, we don't want to use the entire selection + * as the current active object may not be selected. + * + * This is not the case when we're in a mode that supports multi-mode editing, + * since the active object and all other objects in the mode will be included + * irrespective of selection. */ + ob = ob_active; } else if (ob_active && (ob_active->mode & (OB_MODE_ALL_PAINT | OB_MODE_ALL_SCULPT | OB_MODE_ALL_PAINT_GPENCIL))) { @@ -190,15 +211,17 @@ Object **ED_object_array_in_mode_or_selected(bContext *C, } } else { - const View3D *v3d = (area && area->spacetype == SPACE_VIEW3D) ? area->spacedata.first : NULL; + const View3D *v3d = (space_type == SPACE_VIEW3D) ? area->spacedata.first : NULL; /* When in a mode that supports multiple active objects, use "objects in mode" * instead of the object's selection. */ - if ((ob_active != NULL) && (ob_active->mode & (OB_MODE_EDIT | OB_MODE_POSE))) { - objects = BKE_view_layer_array_from_objects_in_mode( - view_layer, - v3d, - r_objects_len, - {.no_dup_data = true, .filter_fn = filter_fn, .filter_userdata = filter_user_data}); + if (use_objects_in_mode) { + objects = BKE_view_layer_array_from_objects_in_mode(view_layer, + v3d, + r_objects_len, + {.object_mode = ob_active->mode, + .no_dup_data = true, + .filter_fn = filter_fn, + .filter_userdata = filter_user_data}); } else { objects = BKE_view_layer_array_selected_objects( @@ -253,6 +276,7 @@ static int object_hide_view_clear_exec(bContext *C, wmOperator *op) BKE_layer_collection_sync(scene, view_layer); DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene); return OPERATOR_FINISHED; } @@ -310,6 +334,7 @@ static int object_hide_view_set_exec(bContext *C, wmOperator *op) BKE_layer_collection_sync(scene, view_layer); DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene); return OPERATOR_FINISHED; } @@ -614,7 +639,7 @@ bool ED_object_editmode_exit_ex(Main *bmain, Scene *scene, Object *obedit, int f if (ED_object_editmode_load_ex(bmain, obedit, freedata) == false) { /* in rare cases (background mode) its possible active object - * is flagged for editmode, without 'obedit' being set [#35489] */ + * is flagged for editmode, without 'obedit' being set T35489. */ if (UNLIKELY(obedit && obedit->mode & OB_MODE_EDIT)) { obedit->mode &= ~OB_MODE_EDIT; /* Also happens when mesh is shared across multiple objects. [#T69834] */ @@ -736,7 +761,7 @@ bool ED_object_editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_LATTICE, scene); } - else if (ob->type == OB_SURF || ob->type == OB_CURVE) { + else if (ELEM(ob->type, OB_SURF, OB_CURVE)) { ok = 1; ED_curve_editnurb_make(ob); @@ -769,14 +794,14 @@ bool ED_object_editmode_enter(bContext *C, int flag) static int editmode_toggle_exec(bContext *C, wmOperator *op) { - struct wmMsgBus *mbus = CTX_wm_message_bus(C); - const int mode_flag = OB_MODE_EDIT; - const bool is_mode_set = (CTX_data_edit_object(C) != NULL); 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); + ViewLayer *view_layer = CTX_data_view_layer(C); Object *obact = OBACT(view_layer); + const int mode_flag = OB_MODE_EDIT; + const bool is_mode_set = (obact->mode & mode_flag) != 0; + struct wmMsgBus *mbus = CTX_wm_message_bus(C); if (!is_mode_set) { if (!ED_object_mode_compat_set(C, obact, mode_flag, op->reports)) { @@ -785,7 +810,7 @@ static int editmode_toggle_exec(bContext *C, wmOperator *op) } if (!is_mode_set) { - ED_object_editmode_enter(C, 0); + ED_object_editmode_enter_ex(bmain, scene, obact, 0); if (obact->mode & mode_flag) { FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) { if ((ob != obact) && (ob->type == obact->type)) { @@ -796,7 +821,8 @@ static int editmode_toggle_exec(bContext *C, wmOperator *op) } } else { - ED_object_editmode_exit(C, EM_FREEDATA); + ED_object_editmode_exit_ex(bmain, scene, obact, EM_FREEDATA); + if ((obact->mode & mode_flag) == 0) { FOREACH_OBJECT_BEGIN (view_layer, ob) { if ((ob != obact) && (ob->type == obact->type)) { @@ -859,6 +885,9 @@ void OBJECT_OT_editmode_toggle(wmOperatorType *ot) static int posemode_exec(bContext *C, wmOperator *op) { struct wmMsgBus *mbus = CTX_wm_message_bus(C); + struct Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); Base *base = CTX_data_active_base(C); /* If the base is NULL it means we have an active object, but the object itself is hidden. */ @@ -880,16 +909,17 @@ static int posemode_exec(bContext *C, wmOperator *op) return OPERATOR_PASS_THROUGH; } - if (obact == CTX_data_edit_object(C)) { - ED_object_editmode_exit(C, EM_FREEDATA); - is_mode_set = false; + { + Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + if (obact == obedit) { + ED_object_editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA); + is_mode_set = false; + } } if (is_mode_set) { bool ok = ED_object_posemode_exit(C, obact); if (ok) { - struct Main *bmain = CTX_data_main(C); - ViewLayer *view_layer = CTX_data_view_layer(C); FOREACH_OBJECT_BEGIN (view_layer, ob) { if ((ob != obact) && (ob->type == OB_ARMATURE) && (ob->mode & mode_flag)) { ED_object_posemode_exit_ex(bmain, ob); @@ -901,9 +931,7 @@ static int posemode_exec(bContext *C, wmOperator *op) else { bool ok = ED_object_posemode_enter(C, obact); if (ok) { - struct Main *bmain = CTX_data_main(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); + const View3D *v3d = CTX_wm_view3d(C); FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) { if ((ob != obact) && (ob->type == OB_ARMATURE) && (ob->mode == OB_MODE_OBJECT) && (!ID_IS_LINKED(ob))) { @@ -1827,7 +1855,7 @@ static void move_to_collection_menus_free(MoveToCollectionData **menu) *menu = NULL; } -static void move_to_collection_menu_create(bContext *UNUSED(C), uiLayout *layout, void *menu_v) +static void move_to_collection_menu_create(bContext *C, uiLayout *layout, void *menu_v) { MoveToCollectionData *menu = menu_v; const char *name = BKE_collection_ui_name_get(menu->collection); @@ -1843,7 +1871,11 @@ static void move_to_collection_menu_create(bContext *UNUSED(C), uiLayout *layout uiItemS(layout); - uiItemIntO(layout, name, ICON_SCENE_DATA, menu->ot->idname, "collection_index", menu->index); + Scene *scene = CTX_data_scene(C); + const int icon = (menu->collection == scene->master_collection) ? + ICON_SCENE_DATA : + UI_icon_color_from_collection(menu->collection); + uiItemIntO(layout, name, icon, menu->ot->idname, "collection_index", menu->index); for (MoveToCollectionData *submenu = menu->submenus.first; submenu != NULL; submenu = submenu->next) { @@ -1853,17 +1885,18 @@ static void move_to_collection_menu_create(bContext *UNUSED(C), uiLayout *layout static void move_to_collection_menus_items(uiLayout *layout, MoveToCollectionData *menu) { + const int icon = UI_icon_color_from_collection(menu->collection); + if (BLI_listbase_is_empty(&menu->submenus)) { uiItemIntO(layout, menu->collection->id.name + 2, - ICON_NONE, + icon, menu->ot->idname, "collection_index", menu->index); } else { - uiItemMenuF( - layout, menu->collection->id.name + 2, ICON_NONE, move_to_collection_menu_create, menu); + uiItemMenuF(layout, menu->collection->id.name + 2, icon, move_to_collection_menu_create, menu); } } diff --git a/source/blender/editors/object/object_facemap_ops.c b/source/blender/editors/object/object_facemap_ops.c index 4e2b1eb21b6..acd04b4aabd 100644 --- a/source/blender/editors/object/object_facemap_ops.c +++ b/source/blender/editors/object/object_facemap_ops.c @@ -319,7 +319,7 @@ static int face_map_remove_from_exec(bContext *C, wmOperator *UNUSED(op)) void OBJECT_OT_face_map_remove_from(struct wmOperatorType *ot) { /* identifiers */ - ot->name = "Remove From Face Map"; + ot->name = "Remove from Face Map"; ot->idname = "OBJECT_OT_face_map_remove_from"; ot->description = "Remove faces from a face map"; diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c index 575ef38476c..eed3c7f419d 100644 --- a/source/blender/editors/object/object_gpencil_modifier.c +++ b/source/blender/editors/object/object_gpencil_modifier.c @@ -228,6 +228,9 @@ bool ED_object_gpencil_modifier_move_to_index(ReportList *reports, } } + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob); + return true; } @@ -319,6 +322,13 @@ int ED_object_gpencil_modifier_copy(ReportList *reports, Object *ob, GpencilModi return 1; } +void ED_object_gpencil_modifier_copy_to_object(Object *ob_dst, GpencilModifierData *md) +{ + BKE_object_copy_gpencil_modifier(ob_dst, md); + WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob_dst); + DEG_id_tag_update(&ob_dst->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); +} + /************************ add modifier operator *********************/ static int gpencil_modifier_add_exec(bContext *C, wmOperator *op) @@ -674,9 +684,6 @@ static int gpencil_modifier_move_to_index_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); - return OPERATOR_FINISHED; } diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 5cfe02dbc59..91c9916d227 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -238,12 +238,11 @@ static void select_editlattice_hook(Object *obedit, HookModifierData *hmd) static int return_editcurve_indexar(Object *obedit, int *r_tot, int **r_indexar, float r_cent[3]) { ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BPoint *bp; BezTriple *bezt; int *index, a, nr, totvert = 0; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -280,7 +279,7 @@ static int return_editcurve_indexar(Object *obedit, int *r_tot, int **r_indexar, nr = 0; zero_v3(r_cent); - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -377,12 +376,11 @@ static bool object_hook_index_array(Main *bmain, static void select_editcurve_hook(Object *obedit, HookModifierData *hmd) { ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BPoint *bp; BezTriple *bezt; int index = 0, a, nr = 0; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 99e139b823e..d0c6134bab5 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -63,6 +63,7 @@ void OBJECT_OT_track_set(struct wmOperatorType *ot); void OBJECT_OT_track_clear(struct wmOperatorType *ot); void OBJECT_OT_make_local(struct wmOperatorType *ot); void OBJECT_OT_make_override_library(struct wmOperatorType *ot); +void OBJECT_OT_convert_proxy_to_override(struct wmOperatorType *ot); void OBJECT_OT_make_single_user(struct wmOperatorType *ot); void OBJECT_OT_make_links_scene(struct wmOperatorType *ot); void OBJECT_OT_make_links_data(struct wmOperatorType *ot); @@ -89,6 +90,8 @@ void OBJECT_OT_forcefield_toggle(struct wmOperatorType *ot); void OBJECT_OT_move_to_collection(struct wmOperatorType *ot); void OBJECT_OT_link_to_collection(struct wmOperatorType *ot); +void OBJECT_OT_switch_object(struct wmOperatorType *ot); + /* object_select.c */ void OBJECT_OT_select_all(struct wmOperatorType *ot); void OBJECT_OT_select_random(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c index bc05a62759f..9eaa8f3d31b 100644 --- a/source/blender/editors/object/object_modes.c +++ b/source/blender/editors/object/object_modes.c @@ -26,6 +26,8 @@ #include "DNA_scene_types.h" #include "DNA_workspace_types.h" +#include "BLI_kdopbvh.h" +#include "BLI_math.h" #include "BLI_utildefines.h" #include "BKE_context.h" @@ -44,12 +46,19 @@ #include "RNA_access.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "ED_armature.h" #include "ED_gpencil.h" #include "ED_screen.h" +#include "ED_transform_snap_object_context.h" +#include "ED_undo.h" +#include "ED_view3d.h" + +#include "WM_toolsystem.h" #include "ED_object.h" /* own include */ +#include "object_intern.h" /* -------------------------------------------------------------------- */ /** \name High Level Mode Operations @@ -390,3 +399,104 @@ bool ED_object_mode_generic_has_data(struct Depsgraph *depsgraph, struct Object } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Switch Object + * + * Enters the same mode of the current active object in another object, + * leaving the mode of the current object. + * \{ */ + +static bool object_switch_object_poll(bContext *C) +{ + + if (!U.experimental.use_switch_object_operator) { + return false; + } + + if (!CTX_wm_region_view3d(C)) { + return false; + } + const Object *ob = CTX_data_active_object(C); + return ob && (ob->mode & (OB_MODE_EDIT | OB_MODE_SCULPT)); +} + +static int object_switch_object_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + ARegion *ar = CTX_wm_region(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + + Base *base_dst = ED_view3d_give_base_under_cursor(C, event->mval); + + if (base_dst == NULL) { + return OPERATOR_CANCELLED; + } + + Object *ob_dst = base_dst->object; + Object *ob_src = CTX_data_active_object(C); + + if (ob_dst == ob_src) { + return OPERATOR_CANCELLED; + } + + const eObjectMode last_mode = (eObjectMode)ob_src->mode; + if (!ED_object_mode_compat_test(ob_dst, last_mode)) { + return OPERATOR_CANCELLED; + } + + int retval = OPERATOR_CANCELLED; + + ED_undo_group_begin(C); + + if (ED_object_mode_set_ex(C, OB_MODE_OBJECT, true, op->reports)) { + Object *ob_dst_orig = DEG_get_original_object(ob_dst); + Base *base = BKE_view_layer_base_find(view_layer, ob_dst_orig); + BKE_view_layer_base_deselect_all(view_layer); + BKE_view_layer_base_select_and_set_active(view_layer, base); + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + + ED_undo_push(C, "Change Active"); + + ob_dst_orig = DEG_get_original_object(ob_dst); + ED_object_mode_set_ex(C, last_mode, true, op->reports); + + /* Update the viewport rotation origin to the mouse cursor. */ + if (last_mode & OB_MODE_ALL_PAINT) { + float global_loc[3]; + if (ED_view3d_autodist_simple(ar, event->mval, global_loc, 0, NULL)) { + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + copy_v3_v3(ups->average_stroke_accum, global_loc); + ups->average_stroke_counter = 1; + ups->last_stroke_valid = true; + } + } + + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + WM_toolsystem_update_from_context_view3d(C); + retval = OPERATOR_FINISHED; + } + + ED_undo_group_end(C); + + return retval; +} + +void OBJECT_OT_switch_object(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Switch Object"; + ot->idname = "OBJECT_OT_switch_object"; + ot->description = + "Switches the active object and assigns the same mode to a new one under the mouse cursor, " + "leaving the active mode in the current one"; + + /* api callbacks */ + ot->invoke = object_switch_object_invoke; + ot->poll = object_switch_object_poll; + + /* Undo push is handled by the operator. */ + ot->flag = OPTYPE_REGISTER; +} + +/** \} */ diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 74d6a48c4bf..ce08c5926f2 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -31,6 +31,7 @@ #include "DNA_armature_types.h" #include "DNA_curve_types.h" #include "DNA_key_types.h" +#include "DNA_lattice_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_force_types.h" @@ -46,6 +47,7 @@ #include "BKE_DerivedMesh.h" #include "BKE_animsys.h" +#include "BKE_armature.h" #include "BKE_context.h" #include "BKE_curve.h" #include "BKE_displist.h" @@ -242,9 +244,7 @@ ModifierData *ED_object_modifier_add( * the modifier pointed to be 'exclude', otherwise returns false. */ static bool object_has_modifier(const Object *ob, const ModifierData *exclude, ModifierType type) { - ModifierData *md; - - for (md = ob->modifiers.first; md; md = md->next) { + LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) { if ((md != exclude) && (md->type == type)) { return true; } @@ -308,10 +308,9 @@ static bool object_has_modifier_cb(Object *ob, void *data) * callback_data. */ bool ED_object_multires_update_totlevels_cb(Object *ob, void *totlevel_v) { - ModifierData *md; int totlevel = *((char *)totlevel_v); - for (md = ob->modifiers.first; md; md = md->next) { + LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) { if (md->type == eModifierType_Multires) { multires_set_tot_level(ob, (MultiresModifierData *)md, totlevel); DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); @@ -391,9 +390,8 @@ bool ED_object_modifier_remove( ReportList *reports, Main *bmain, Scene *scene, Object *ob, ModifierData *md) { bool sort_depsgraph = false; - bool ok; - ok = object_modifier_remove(bmain, scene, ob, md, &sort_depsgraph); + bool ok = object_modifier_remove(bmain, scene, ob, md, &sort_depsgraph); if (!ok) { BKE_reportf(reports, RPT_ERROR, "Modifier '%s' not in object '%s'", md->name, ob->id.name); @@ -416,9 +414,7 @@ void ED_object_modifier_clear(Main *bmain, Scene *scene, Object *ob) } while (md) { - ModifierData *next_md; - - next_md = md->next; + ModifierData *next_md = md->next; object_modifier_remove(bmain, scene, ob, md, &sort_depsgraph); @@ -510,9 +506,35 @@ bool ED_object_modifier_move_to_index(ReportList *reports, } } + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob); + return true; } +void ED_object_modifier_link(bContext *C, Object *ob_dst, Object *ob_src) +{ + BKE_object_link_modifiers(ob_dst, ob_src); + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob_dst); + DEG_id_tag_update(&ob_dst->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); + + Main *bmain = CTX_data_main(C); + DEG_relations_tag_update(bmain); +} + +void ED_object_modifier_copy_to_object(bContext *C, + Object *ob_dst, + Object *ob_src, + ModifierData *md) +{ + BKE_object_copy_modifier(ob_dst, ob_src, md); + WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob_dst); + DEG_id_tag_update(&ob_dst->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); + + Main *bmain = CTX_data_main(C); + DEG_relations_tag_update(bmain); +} + bool ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Depsgraph *depsgraph, @@ -520,16 +542,7 @@ bool ED_object_modifier_convert(ReportList *UNUSED(reports), Object *ob, ModifierData *md) { - Object *obn; - ParticleSystem *psys_orig, *psys_eval; - ParticleCacheKey *key, **cache; - ParticleSettings *part; - Mesh *me; - MVert *mvert; - MEdge *medge; - int a, k, kmax; - int totvert = 0, totedge = 0, cvert = 0; - int totpart = 0, totchild = 0; + int cvert = 0; if (md->type != eModifierType_ParticleSystem) { return false; @@ -538,28 +551,29 @@ bool ED_object_modifier_convert(ReportList *UNUSED(reports), return false; } - psys_orig = ((ParticleSystemModifierData *)md)->psys; - part = psys_orig->part; + ParticleSystem *psys_orig = ((ParticleSystemModifierData *)md)->psys; + ParticleSettings *part = psys_orig->part; if (part->ren_as != PART_DRAW_PATH) { return false; } - psys_eval = psys_eval_get(depsgraph, ob, psys_orig); + ParticleSystem *psys_eval = psys_eval_get(depsgraph, ob, psys_orig); if (psys_eval->pathcache == NULL) { return false; } - totpart = psys_eval->totcached; - totchild = psys_eval->totchildcache; + int totpart = psys_eval->totcached; + int totchild = psys_eval->totchildcache; if (totchild && (part->draw & PART_DRAW_PARENT) == 0) { totpart = 0; } /* count */ - cache = psys_eval->pathcache; - for (a = 0; a < totpart; a++) { - key = cache[a]; + int totvert = 0, totedge = 0; + ParticleCacheKey **cache = psys_eval->pathcache; + for (int a = 0; a < totpart; a++) { + ParticleCacheKey *key = cache[a]; if (key->segments > 0) { totvert += key->segments + 1; @@ -568,8 +582,8 @@ bool ED_object_modifier_convert(ReportList *UNUSED(reports), } cache = psys_eval->childcache; - for (a = 0; a < totchild; a++) { - key = cache[a]; + for (int a = 0; a < totchild; a++) { + ParticleCacheKey *key = cache[a]; if (key->segments > 0) { totvert += key->segments + 1; @@ -582,8 +596,8 @@ bool ED_object_modifier_convert(ReportList *UNUSED(reports), } /* add new mesh */ - obn = BKE_object_add(bmain, view_layer, OB_MESH, NULL); - me = obn->data; + Object *obn = BKE_object_add(bmain, view_layer, OB_MESH, NULL); + Mesh *me = obn->data; me->totvert = totvert; me->totedge = totedge; @@ -592,15 +606,15 @@ bool ED_object_modifier_convert(ReportList *UNUSED(reports), me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, totedge); me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0); - mvert = me->mvert; - medge = me->medge; + MVert *mvert = me->mvert; + MEdge *medge = me->medge; /* copy coordinates */ cache = psys_eval->pathcache; - for (a = 0; a < totpart; a++) { - key = cache[a]; - kmax = key->segments; - for (k = 0; k <= kmax; k++, key++, cvert++, mvert++) { + for (int a = 0; a < totpart; a++) { + ParticleCacheKey *key = cache[a]; + int kmax = key->segments; + for (int k = 0; k <= kmax; k++, key++, cvert++, mvert++) { copy_v3_v3(mvert->co, key->co); if (k) { medge->v1 = cvert - 1; @@ -616,10 +630,10 @@ bool ED_object_modifier_convert(ReportList *UNUSED(reports), } cache = psys_eval->childcache; - for (a = 0; a < totchild; a++) { - key = cache[a]; - kmax = key->segments; - for (k = 0; k <= kmax; k++, key++, cvert++, mvert++) { + for (int a = 0; a < totchild; a++) { + ParticleCacheKey *key = cache[a]; + int kmax = key->segments; + for (int k = 0; k <= kmax; k++, key++, cvert++, mvert++) { copy_v3_v3(mvert->co, key->co); if (k) { medge->v1 = cvert - 1; @@ -666,22 +680,20 @@ static int modifier_apply_shape(Main *bmain, return 0; } - /* - * It should be ridiculously easy to extract the original verts that we want - * and form the shape data. We can probably use the CD KEYINDEX layer (or - * whatever I ended up calling it, too tired to check now), though this would - * by necessity have to make some potentially ugly assumptions about the order - * of the mesh data :-/ you can probably assume in 99% of cases that the first - * element of a given index is the original, and any subsequent duplicates are - * copies/interpolates, but that's an assumption that would need to be tested - * and then predominantly stated in comments in a half dozen headers. - */ + /* We could investigate using the #CD_ORIGINDEX layer + * to support other kinds of modifiers besides deforming modifiers. + * as this is done in many other places, see: #BKE_mesh_foreach_mapped_vert_coords_get. + * + * This isn't high priority in practice since most modifiers users + * want to apply as a shape are deforming modifiers. + * + * If a compelling use-case comes up where we want to support other kinds of modifiers + * we can look into supporting them. */ if (ob->type == OB_MESH) { Mesh *mesh_applied; Mesh *me = ob->data; Key *key = me->key; - KeyBlock *kb; if (!BKE_modifier_is_same_topology(md_eval) || mti->type == eModifierTypeType_NonGeometrical) { BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to shapes"); @@ -699,17 +711,17 @@ static int modifier_apply_shape(Main *bmain, key->type = KEY_RELATIVE; /* if that was the first key block added, then it was the basis. * Initialize it with the mesh, and add another for the modifier */ - kb = BKE_keyblock_add(key, NULL); + KeyBlock *kb = BKE_keyblock_add(key, NULL); BKE_keyblock_convert_from_mesh(me, key, kb); } - kb = BKE_keyblock_add(key, md_eval->name); + KeyBlock *kb = BKE_keyblock_add(key, md_eval->name); BKE_mesh_nomain_to_meshkey(mesh_applied, me, kb); BKE_id_free(NULL, mesh_applied); } else { - /* TODO: implement for hair, pointclouds and volumes. */ + /* TODO: implement for hair, point-clouds and volumes. */ BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type"); return 0; } @@ -765,8 +777,6 @@ static int modifier_apply_obdata( Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); Curve *curve = ob->data; Curve *curve_eval = (Curve *)object_eval->data; - int numVerts; - float(*vertexCos)[3]; ModifierEvalContext mectx = {depsgraph, object_eval, 0}; if (ELEM(mti->type, eModifierTypeType_Constructive, eModifierTypeType_Nonconstructive)) { @@ -779,7 +789,8 @@ static int modifier_apply_obdata( RPT_INFO, "Applied modifier only changed CV points, not tessellated/bevel vertices"); - vertexCos = BKE_curve_nurbs_vert_coords_alloc(&curve_eval->nurb, &numVerts); + int numVerts; + float(*vertexCos)[3] = BKE_curve_nurbs_vert_coords_alloc(&curve_eval->nurb, &numVerts); mti->deformVerts(md_eval, &mectx, NULL, vertexCos, numVerts); BKE_curve_nurbs_vert_coords_apply(&curve->nurb, vertexCos, false); @@ -787,19 +798,34 @@ static int modifier_apply_obdata( DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); } + else if (ob->type == OB_LATTICE) { + Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); + Lattice *lattice = ob->data; + ModifierEvalContext mectx = {depsgraph, object_eval, 0}; + + if (ELEM(mti->type, eModifierTypeType_Constructive, eModifierTypeType_Nonconstructive)) { + BKE_report(reports, RPT_ERROR, "Constructive modifiers cannot be applied"); + return 0; + } + + int numVerts; + float(*vertexCos)[3] = BKE_lattice_vert_coords_alloc(lattice, &numVerts); + mti->deformVerts(md_eval, &mectx, NULL, vertexCos, numVerts); + BKE_lattice_vert_coords_apply(lattice, vertexCos); + + MEM_freeN(vertexCos); + + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + } else { - /* TODO: implement for hair, pointclouds and volumes. */ + /* TODO: implement for hair, point-clouds and volumes. */ BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type"); return 0; } /* lattice modifier can be applied to particle system too */ if (ob->particlesystem.first) { - - ParticleSystem *psys = ob->particlesystem.first; - - for (; psys; psys = psys->next) { - + LISTBASE_FOREACH (ParticleSystem *, psys, &ob->particlesystem) { if (psys->part->type != PART_HAIR) { continue; } @@ -820,8 +846,6 @@ bool ED_object_modifier_apply(Main *bmain, int mode, bool keep_modifier) { - int prev_mode; - if (BKE_object_is_in_editmode(ob)) { BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in edit mode"); return false; @@ -848,7 +872,7 @@ bool ED_object_modifier_apply(Main *bmain, ModifierData *md_eval = (ob_eval) ? BKE_modifiers_findby_name(ob_eval, md->name) : md; /* allow apply of a not-realtime modifier, by first re-enabling realtime. */ - prev_mode = md_eval->mode; + int prev_mode = md_eval->mode; md_eval->mode |= eModifierMode_Realtime; if (mode == MODIFIER_APPLY_SHAPE) { @@ -926,20 +950,20 @@ static const EnumPropertyItem *modifier_add_itemf(bContext *C, bool *r_free) { Object *ob = ED_object_active_context(C); - EnumPropertyItem *item = NULL; - const EnumPropertyItem *md_item, *group_item = NULL; - const ModifierTypeInfo *mti; - int totitem = 0, a; if (!ob) { return rna_enum_object_modifier_type_items; } - for (a = 0; rna_enum_object_modifier_type_items[a].identifier; a++) { - md_item = &rna_enum_object_modifier_type_items[a]; + EnumPropertyItem *items = NULL; + int totitem = 0; + + const EnumPropertyItem *group_item = NULL; + for (int a = 0; rna_enum_object_modifier_type_items[a].identifier; a++) { + const EnumPropertyItem *md_item = &rna_enum_object_modifier_type_items[a]; if (md_item->identifier[0]) { - mti = BKE_modifier_get_info(md_item->value); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md_item->value); if (mti->flags & eModifierTypeFlag_NoUserAdd) { continue; @@ -951,23 +975,21 @@ static const EnumPropertyItem *modifier_add_itemf(bContext *C, } else { group_item = md_item; - md_item = NULL; - continue; } if (group_item) { - RNA_enum_item_add(&item, &totitem, group_item); + RNA_enum_item_add(&items, &totitem, group_item); group_item = NULL; } - RNA_enum_item_add(&item, &totitem, md_item); + RNA_enum_item_add(&items, &totitem, md_item); } - RNA_enum_item_end(&item, &totitem); + RNA_enum_item_end(&items, &totitem); *r_free = true; - return item; + return items; } void OBJECT_OT_modifier_add(wmOperatorType *ot) @@ -1112,10 +1134,9 @@ bool edit_modifier_invoke_properties(bContext *C, ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type) { char modifier_name[MAX_NAME]; - ModifierData *md; RNA_string_get(op->ptr, "modifier", modifier_name); - md = BKE_modifiers_findby_name(ob, modifier_name); + ModifierData *md = BKE_modifiers_findby_name(ob, modifier_name); if (md && type != 0 && md->type != type) { md = NULL; @@ -1300,9 +1321,6 @@ static int modifier_move_to_index_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); - return OPERATOR_FINISHED; } @@ -1479,8 +1497,8 @@ static char *modifier_apply_as_shapekey_get_description(struct bContext *UNUSED( void OBJECT_OT_modifier_apply_as_shapekey(wmOperatorType *ot) { - ot->name = "Apply Modifier As Shapekey"; - ot->description = "Apply modifier as a new shapekey and remove from the stack"; + ot->name = "Apply Modifier as Shape Key"; + ot->description = "Apply modifier as a new shape key and remove from the stack"; ot->idname = "OBJECT_OT_modifier_apply_as_shapekey"; ot->invoke = modifier_apply_as_shapekey_invoke; @@ -1836,7 +1854,6 @@ static int multires_external_save_exec(bContext *C, wmOperator *op) static int multires_external_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Object *ob = ED_object_active_context(C); - MultiresModifierData *mmd; Mesh *me = ob->data; char path[FILE_MAX]; @@ -1844,7 +1861,8 @@ static int multires_external_save_invoke(bContext *C, wmOperator *op, const wmEv return OPERATOR_CANCELLED; } - mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires); + MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get( + op, ob, eModifierType_Multires); if (!mmd) { return OPERATOR_CANCELLED; @@ -1888,7 +1906,7 @@ void OBJECT_OT_multires_external_save(wmOperatorType *ot) FILE_SAVE, WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); edit_modifier_properties(ot); } @@ -2143,16 +2161,15 @@ static int skin_root_mark_exec(bContext *C, wmOperator *UNUSED(op)) Object *ob = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(ob); BMesh *bm = em->bm; - BMVert *bm_vert; - BMIter bm_iter; - GSet *visited; - visited = BLI_gset_ptr_new(__func__); + GSet *visited = BLI_gset_ptr_new(__func__); BKE_mesh_ensure_skin_customdata(ob->data); const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN); + BMVert *bm_vert; + BMIter bm_iter; BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT) && BLI_gset_add(visited, bm_vert)) { MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(bm_vert, cd_vert_skin_offset); @@ -2196,14 +2213,14 @@ static int skin_loose_mark_clear_exec(bContext *C, wmOperator *op) Object *ob = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(ob); BMesh *bm = em->bm; - BMVert *bm_vert; - BMIter bm_iter; SkinLooseAction action = RNA_enum_get(op->ptr, "action"); if (!CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) { return OPERATOR_CANCELLED; } + BMVert *bm_vert; + BMIter bm_iter; BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) { MVertSkin *vs = CustomData_bmesh_get(&bm->vdata, bm_vert->head.data, CD_MVERT_SKIN); @@ -2251,13 +2268,13 @@ static int skin_radii_equalize_exec(bContext *C, wmOperator *UNUSED(op)) Object *ob = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(ob); BMesh *bm = em->bm; - BMVert *bm_vert; - BMIter bm_iter; if (!CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) { return OPERATOR_CANCELLED; } + BMVert *bm_vert; + BMIter bm_iter; BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) { MVertSkin *vs = CustomData_bmesh_get(&bm->vdata, bm_vert->head.data, CD_MVERT_SKIN); @@ -2295,14 +2312,9 @@ static void skin_armature_bone_create(Object *skin_ob, EditBone *parent_bone, int parent_v) { - int i; - - for (i = 0; i < emap[parent_v].count; i++) { + for (int i = 0; i < emap[parent_v].count; i++) { int endx = emap[parent_v].indices[i]; const MEdge *e = &medge[endx]; - EditBone *bone; - bDeformGroup *dg; - int v; /* ignore edge if already visited */ if (BLI_BITMAP_TEST(edges_visited, endx)) { @@ -2310,9 +2322,9 @@ static void skin_armature_bone_create(Object *skin_ob, } BLI_BITMAP_ENABLE(edges_visited, endx); - v = (e->v1 == parent_v ? e->v2 : e->v1); + int v = (e->v1 == parent_v ? e->v2 : e->v1); - bone = ED_armature_ebone_add(arm, "Bone"); + EditBone *bone = ED_armature_ebone_add(arm, "Bone"); bone->parent = parent_bone; bone->flag |= BONE_CONNECTED; @@ -2323,7 +2335,8 @@ static void skin_armature_bone_create(Object *skin_ob, BLI_snprintf(bone->name, sizeof(bone->name), "Bone.%.2d", endx); /* add bDeformGroup */ - if ((dg = BKE_object_defgroup_add_name(skin_ob, bone->name))) { + bDeformGroup *dg = BKE_object_defgroup_add_name(skin_ob, bone->name); + if (dg != NULL) { ED_vgroup_vert_add(skin_ob, dg, parent_v, 1, WEIGHT_REPLACE); ED_vgroup_vert_add(skin_ob, dg, v, 1, WEIGHT_REPLACE); } @@ -2334,43 +2347,36 @@ static void skin_armature_bone_create(Object *skin_ob, static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain, Object *skin_ob) { - BLI_bitmap *edges_visited; - Mesh *me_eval_deform; - MVert *mvert; Mesh *me = skin_ob->data; - Object *arm_ob; - bArmature *arm; - MVertSkin *mvert_skin; - MeshElemMap *emap; - int *emap_mem; - int v; Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); Object *ob_eval = DEG_get_evaluated_object(depsgraph, skin_ob); - me_eval_deform = mesh_get_eval_deform(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH); - mvert = me_eval_deform->mvert; + Mesh *me_eval_deform = mesh_get_eval_deform(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH); + MVert *mvert = me_eval_deform->mvert; /* add vertex weights to original mesh */ CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert); ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph); - arm_ob = BKE_object_add(bmain, view_layer, OB_ARMATURE, NULL); + Object *arm_ob = BKE_object_add(bmain, view_layer, OB_ARMATURE, NULL); BKE_object_transform_copy(arm_ob, skin_ob); - arm = arm_ob->data; + bArmature *arm = arm_ob->data; arm->layer = 1; arm_ob->dtx |= OB_DRAW_IN_FRONT; arm->drawtype = ARM_LINE; arm->edbo = MEM_callocN(sizeof(ListBase), "edbo armature"); - mvert_skin = CustomData_get_layer(&me->vdata, CD_MVERT_SKIN); + MVertSkin *mvert_skin = CustomData_get_layer(&me->vdata, CD_MVERT_SKIN); + int *emap_mem; + MeshElemMap *emap; BKE_mesh_vert_edge_map_create(&emap, &emap_mem, me->medge, me->totvert, me->totedge); - edges_visited = BLI_BITMAP_NEW(me->totedge, "edge_visited"); + BLI_bitmap *edges_visited = BLI_BITMAP_NEW(me->totedge, "edge_visited"); /* note: we use EditBones here, easier to set them up and use * edit-armature functions to convert back to regular bones */ - for (v = 0; v < me->totvert; v++) { + for (int v = 0; v < me->totvert; v++) { if (mvert_skin[v].flag & MVERT_SKIN_ROOT) { EditBone *bone = NULL; @@ -2407,10 +2413,9 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - Object *ob = CTX_data_active_object(C), *arm_ob; + Object *ob = CTX_data_active_object(C); Mesh *me = ob->data; ModifierData *skin_md; - ArmatureModifierData *arm_md; if (!CustomData_has_layer(&me->vdata, CD_MVERT_SKIN)) { BKE_reportf(op->reports, RPT_WARNING, "Mesh '%s' has no skin vertex data", me->id.name + 2); @@ -2418,10 +2423,10 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op) } /* create new armature */ - arm_ob = modifier_skin_armature_create(depsgraph, bmain, ob); + Object *arm_ob = modifier_skin_armature_create(depsgraph, bmain, ob); /* add a modifier to connect the new armature to the mesh */ - arm_md = (ArmatureModifierData *)BKE_modifier_new(eModifierType_Armature); + ArmatureModifierData *arm_md = (ArmatureModifierData *)BKE_modifier_new(eModifierType_Armature); if (arm_md) { skin_md = edit_modifier_property_get(op, ob, eModifierType_Skin); BLI_insertlinkafter(&ob->modifiers, skin_md, arm_md); @@ -2477,7 +2482,6 @@ static int correctivesmooth_bind_exec(bContext *C, wmOperator *op) Object *ob = ED_object_active_context(C); CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)edit_modifier_property_get( op, ob, eModifierType_CorrectiveSmooth); - bool is_bind; if (!csmd) { return OPERATOR_CANCELLED; @@ -2488,7 +2492,7 @@ static int correctivesmooth_bind_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - is_bind = (csmd->bind_coords != NULL); + const bool is_bind = (csmd->bind_coords != NULL); MEM_SAFE_FREE(csmd->bind_coords); MEM_SAFE_FREE(csmd->delta_cache.deltas); @@ -2758,14 +2762,8 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) OceanModifierData *omd = (OceanModifierData *)edit_modifier_property_get( op, ob, eModifierType_Ocean); Scene *scene = CTX_data_scene(C); - OceanCache *och; - struct Ocean *ocean; - int f, cfra, i = 0; const bool free = RNA_boolean_get(op->ptr, "free"); - wmJob *wm_job; - OceanBakeJob *oj; - if (!omd) { return OPERATOR_CANCELLED; } @@ -2777,23 +2775,24 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } - och = BKE_ocean_init_cache(omd->cachepath, - BKE_modifier_path_relbase(bmain, ob), - omd->bakestart, - omd->bakeend, - omd->wave_scale, - omd->chop_amount, - omd->foam_coverage, - omd->foam_fade, - omd->resolution); + OceanCache *och = BKE_ocean_init_cache(omd->cachepath, + BKE_modifier_path_relbase(bmain, ob), + omd->bakestart, + omd->bakeend, + omd->wave_scale, + omd->chop_amount, + omd->foam_coverage, + omd->foam_fade, + omd->resolution); och->time = MEM_mallocN(och->duration * sizeof(float), "foam bake time"); - cfra = scene->r.cfra; + int cfra = scene->r.cfra; /* precalculate time variable before baking */ + int i = 0; Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); - for (f = omd->bakestart; f <= omd->bakeend; f++) { + for (int f = omd->bakestart; f <= omd->bakeend; f++) { /* For now only simple animation of time value is supported, nothing else. * No drivers or other modifier parameters. */ /* TODO(sergey): This operates on an original data, so no flush is needed. However, baking @@ -2808,7 +2807,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) } /* make a copy of ocean to use for baking - threadsafety */ - ocean = BKE_ocean_add(); + struct Ocean *ocean = BKE_ocean_add(); BKE_ocean_init_from_modifier(ocean, omd, omd->resolution); #if 0 @@ -2828,13 +2827,13 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) scene->r.cfra = cfra; /* setup job */ - wm_job = WM_jobs_get(CTX_wm_manager(C), - CTX_wm_window(C), - scene, - "Ocean Simulation", - WM_JOB_PROGRESS, - WM_JOB_TYPE_OBJECT_SIM_OCEAN); - oj = MEM_callocN(sizeof(OceanBakeJob), "ocean bake job"); + wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), + CTX_wm_window(C), + scene, + "Ocean Simulation", + WM_JOB_PROGRESS, + WM_JOB_TYPE_OBJECT_SIM_OCEAN); + OceanBakeJob *oj = MEM_callocN(sizeof(OceanBakeJob), "ocean bake job"); oj->owner = ob; oj->ocean = ocean; oj->och = och; diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 8b3837edce2..3fc29f3147b 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -71,6 +71,8 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_paths_range_update); WM_operatortype_append(OBJECT_OT_forcefield_toggle); + WM_operatortype_append(OBJECT_OT_switch_object); + WM_operatortype_append(OBJECT_OT_parent_set); WM_operatortype_append(OBJECT_OT_parent_no_inverse_set); WM_operatortype_append(OBJECT_OT_parent_clear); @@ -79,6 +81,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_track_clear); WM_operatortype_append(OBJECT_OT_make_local); WM_operatortype_append(OBJECT_OT_make_override_library); + WM_operatortype_append(OBJECT_OT_convert_proxy_to_override); WM_operatortype_append(OBJECT_OT_make_single_user); WM_operatortype_append(OBJECT_OT_make_links_scene); WM_operatortype_append(OBJECT_OT_make_links_data); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 4adf1a8d9f2..29393e8a8d1 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -696,7 +696,7 @@ bool ED_object_parent_set(ReportList *reports, /* Preconditions. */ if (ob == par) { /* Parenting an object to itself is impossible. */ - return true; + return false; } if (BKE_object_parent_loop_check(par, ob)) { @@ -756,8 +756,8 @@ bool ED_object_parent_set(ReportList *reports, /* 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 */ + /* Was removed because of bug T23577, + * but this can be handy in some cases too T32616, so make optional. */ BKE_object_apply_mat4(ob, ob->obmat, false, false); } @@ -911,7 +911,7 @@ bool ED_object_parent_set(ReportList *reports, 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)) { + else if (ELEM(partype, PAR_ARMATURE_AUTO, PAR_ARMATURE_ENVELOPE)) { WM_cursor_wait(1); ED_gpencil_add_armature_weights(C, reports, ob, par, GP_PAR_ARMATURE_AUTO); WM_cursor_wait(0); @@ -981,6 +981,12 @@ struct ParentingContext { static bool parent_set_nonvertex_parent(bContext *C, struct ParentingContext *parenting_context) { CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { + if (ob == parenting_context->par) { + /* ED_object_parent_set() will fail (and thus return false), but this case shouldn't break + * this loop. It's expected that the active object is also selected. */ + continue; + } + if (!ED_object_parent_set(parenting_context->reports, C, parenting_context->scene, @@ -1005,6 +1011,12 @@ static bool parent_set_vertex_parent_with_kdtree(bContext *C, int vert_par[3] = {0, 0, 0}; CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { + if (ob == parenting_context->par) { + /* ED_object_parent_set() will fail (and thus return false), but this case shouldn't break + * this loop. It's expected that the active object is also selected. */ + continue; + } + parent_set_vert_find(tree, ob, vert_par, parenting_context->is_vertex_tri); if (!ED_object_parent_set(parenting_context->reports, C, @@ -1244,6 +1256,7 @@ static int parent_noinv_set_exec(bContext *C, wmOperator *op) 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; } @@ -1358,7 +1371,7 @@ enum { static const EnumPropertyItem prop_make_track_types[] = { {CREATE_TRACK_DAMPTRACK, "DAMPTRACK", 0, "Damped Track Constraint", ""}, - {CREATE_TRACK_TRACKTO, "TRACKTO", 0, "Track To Constraint", ""}, + {CREATE_TRACK_TRACKTO, "TRACKTO", 0, "Track to Constraint", ""}, {CREATE_TRACK_LOCKTRACK, "LOCKTRACK", 0, "Lock Track Constraint", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -1819,8 +1832,7 @@ 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 *collection_new; - BKE_id_copy(bmain, &collection->id, (ID **)&collection_new); + Collection *collection_new = (Collection *)BKE_id_copy(bmain, &collection->id); id_us_min(&collection_new->id); collection = ID_NEW_SET(collection, collection_new); } @@ -1831,7 +1843,8 @@ static Collection *single_object_users_collection(Main *bmain, /* an object may be in more than one collection */ if ((ob->id.newid == NULL) && ((ob->flag & flag) == flag)) { if (!ID_IS_LINKED(ob) && BKE_object_scenes_users_get(bmain, ob) > 1) { - ID_NEW_SET(ob, BKE_object_copy(bmain, ob)); + ID_NEW_SET(ob, BKE_id_copy(bmain, &ob->id)); + id_us_min(ob->id.newid); } } } @@ -1923,26 +1936,26 @@ static void single_obdata_users( switch (ob->type) { case OB_LAMP: - ob->data = la = ID_NEW_SET(ob->data, BKE_light_copy(bmain, ob->data)); + ob->data = la = ID_NEW_SET(ob->data, BKE_id_copy(bmain, ob->data)); break; case OB_CAMERA: - cam = ob->data = ID_NEW_SET(ob->data, BKE_camera_copy(bmain, ob->data)); + cam = ob->data = ID_NEW_SET(ob->data, BKE_id_copy(bmain, ob->data)); ID_NEW_REMAP(cam->dof.focus_object); break; case OB_MESH: /* Needed to remap texcomesh below. */ - me = ob->data = ID_NEW_SET(ob->data, BKE_mesh_copy(bmain, ob->data)); + me = ob->data = ID_NEW_SET(ob->data, BKE_id_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); } break; case OB_MBALL: - ob->data = ID_NEW_SET(ob->data, BKE_mball_copy(bmain, ob->data)); + ob->data = ID_NEW_SET(ob->data, BKE_id_copy(bmain, ob->data)); break; case OB_CURVE: case OB_SURF: case OB_FONT: - ob->data = cu = ID_NEW_SET(ob->data, BKE_curve_copy(bmain, ob->data)); + ob->data = cu = ID_NEW_SET(ob->data, BKE_id_copy(bmain, ob->data)); ID_NEW_REMAP(cu->bevobj); ID_NEW_REMAP(cu->taperobj); if (cu->key) { /* We do not need to set cu->key->id.newid here... */ @@ -1950,33 +1963,33 @@ static void single_obdata_users( } break; case OB_LATTICE: - ob->data = lat = ID_NEW_SET(ob->data, BKE_lattice_copy(bmain, ob->data)); + ob->data = lat = ID_NEW_SET(ob->data, BKE_id_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); } break; case OB_ARMATURE: DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - ob->data = ID_NEW_SET(ob->data, BKE_armature_copy(bmain, ob->data)); + ob->data = ID_NEW_SET(ob->data, BKE_id_copy(bmain, ob->data)); BKE_pose_rebuild(bmain, ob, ob->data, true); break; case OB_SPEAKER: - ob->data = ID_NEW_SET(ob->data, BKE_speaker_copy(bmain, ob->data)); + ob->data = ID_NEW_SET(ob->data, BKE_id_copy(bmain, ob->data)); break; case OB_LIGHTPROBE: - ob->data = ID_NEW_SET(ob->data, BKE_lightprobe_copy(bmain, ob->data)); + ob->data = ID_NEW_SET(ob->data, BKE_id_copy(bmain, ob->data)); break; case OB_GPENCIL: - ob->data = ID_NEW_SET(ob->data, BKE_gpencil_copy(bmain, ob->data)); + ob->data = ID_NEW_SET(ob->data, BKE_id_copy(bmain, ob->data)); break; case OB_HAIR: - ob->data = ID_NEW_SET(ob->data, BKE_hair_copy(bmain, ob->data)); + ob->data = ID_NEW_SET(ob->data, BKE_id_copy(bmain, ob->data)); break; case OB_POINTCLOUD: - ob->data = ID_NEW_SET(ob->data, BKE_pointcloud_copy(bmain, ob->data)); + ob->data = ID_NEW_SET(ob->data, BKE_id_copy(bmain, ob->data)); break; case OB_VOLUME: - ob->data = ID_NEW_SET(ob->data, BKE_volume_copy(bmain, ob->data)); + ob->data = ID_NEW_SET(ob->data, BKE_id_copy(bmain, ob->data)); break; default: printf("ERROR %s: can't copy %s\n", __func__, id->name); @@ -2034,7 +2047,7 @@ static void single_mat_users( * this functions guaranteed delivers single_users! */ if (ma->id.us > 1) { - man = BKE_material_copy(bmain, ma); + man = (Material *)BKE_id_copy(bmain, &ma->id); BKE_animdata_copy_id_action(bmain, &man->id); man->id.us = 0; @@ -2297,7 +2310,7 @@ void OBJECT_OT_make_local(wmOperatorType *ot) /** \name Make Library Override Operator * \{ */ -static bool make_override_library_ovject_overridable_check(Main *bmain, Object *object) +static bool make_override_library_object_overridable_check(Main *bmain, Object *object) { /* An object is actually overrideable only if it is in at least one local collections. * Unfortunately 'direct link' flag is not enough here. */ @@ -2306,6 +2319,11 @@ static bool make_override_library_ovject_overridable_check(Main *bmain, Object * return true; } } + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + if (!ID_IS_LINKED(scene) && BKE_collection_has_object(scene->master_collection, object)) { + return true; + } + } return false; } @@ -2323,7 +2341,7 @@ static int make_override_library_invoke(bContext *C, wmOperator *op, const wmEve if ((!ID_IS_LINKED(obact) && obact->instance_collection != NULL && ID_IS_OVERRIDABLE_LIBRARY(obact->instance_collection)) || - make_override_library_ovject_overridable_check(bmain, obact)) { + make_override_library_object_overridable_check(bmain, obact)) { uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("OK?"), ICON_QUESTION); uiLayout *layout = UI_popup_menu_layout(pup); @@ -2374,7 +2392,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op) id_root = &obact->instance_collection->id; is_override_instancing_object = true; } - else if (!make_override_library_ovject_overridable_check(bmain, obact)) { + else if (!make_override_library_object_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) { @@ -2490,6 +2508,54 @@ void OBJECT_OT_make_override_library(wmOperatorType *ot) ot->prop = prop; } +static bool convert_proxy_to_override_poll(bContext *C) +{ + Object *obact = CTX_data_active_object(C); + + return obact != NULL && obact->proxy != NULL; +} + +static int convert_proxy_to_override_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + + BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); + + Object *ob_proxy = CTX_data_active_object(C); + Object *ob_proxy_group = ob_proxy->proxy_group; + const bool is_override_instancing_object = ob_proxy_group != NULL; + + const bool success = BKE_lib_override_library_proxy_convert(bmain, scene, view_layer, ob_proxy); + + /* 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, ob_proxy_group); + } + + 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; +} + +void OBJECT_OT_convert_proxy_to_override(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Convert Proxy To Override"; + ot->description = "Convert a proxy to a local library override"; + ot->idname = "OBJECT_OT_convert_proxy_to_override"; + + /* api callbacks */ + ot->exec = convert_proxy_to_override_exec; + ot->poll = convert_proxy_to_override_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + /** \} */ /* ------------------------------------------------------------------- */ diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c index f14c734da4e..cc3230dff7b 100644 --- a/source/blender/editors/object/object_remesh.c +++ b/source/blender/editors/object/object_remesh.c @@ -86,7 +86,7 @@ #include "BLF_api.h" -#include "object_intern.h" // own include +#include "object_intern.h" /* own include */ /* TODO(sebpa): unstable, can lead to unrecoverable errors. */ // #define USE_MESH_CURVATURE @@ -952,9 +952,10 @@ static int quadriflow_remesh_exec(bContext *C, wmOperator *op) job->smooth_normals = RNA_boolean_get(op->ptr, "smooth_normals"); /* Update the target face count if symmetry is enabled */ - Sculpt *sd = CTX_data_tool_settings(C)->sculpt; - if (sd && job->use_paint_symmetry) { - job->symmetry_axes = (eSymmetryAxes)(sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL); + Object *ob = CTX_data_active_object(C); + if (ob && job->use_paint_symmetry) { + Mesh *mesh = BKE_mesh_from_object(ob); + job->symmetry_axes = (eSymmetryAxes)mesh->symmetry; for (char i = 0; i < 3; i++) { eSymmetryAxes symm_it = (eSymmetryAxes)(1 << i); if (job->symmetry_axes & symm_it) { diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index 5dfbaf583f6..d3b9c64913d 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -661,7 +661,7 @@ static int object_select_linked_exec(bContext *C, wmOperator *op) } if (nr == OBJECT_SELECT_LINKED_IPO) { - // XXX old animation system + /* XXX old animation system */ // if (ob->ipo == 0) return OPERATOR_CANCELLED; // object_select_all_by_ipo(C, ob->ipo) return OPERATOR_CANCELLED; diff --git a/source/blender/editors/object/object_shader_fx.c b/source/blender/editors/object/object_shader_fx.c index e2a30c4ce98..c5caee5ba08 100644 --- a/source/blender/editors/object/object_shader_fx.c +++ b/source/blender/editors/object/object_shader_fx.c @@ -34,6 +34,7 @@ #include "DNA_shader_fx_types.h" #include "BLI_listbase.h" +#include "BLI_string.h" #include "BLI_string_utf8.h" #include "BLI_utildefines.h" @@ -234,9 +235,32 @@ bool ED_object_shaderfx_move_to_index(ReportList *reports, } } + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_main_add_notifier(NC_OBJECT | ND_SHADERFX, ob); + return true; } +void ED_object_shaderfx_link(Object *dst, Object *src) +{ + BLI_freelistN(&dst->shader_fx); + BKE_shaderfx_copy(&dst->shader_fx, &src->shader_fx); + + DEG_id_tag_update(&dst->id, ID_RECALC_GEOMETRY); + WM_main_add_notifier(NC_OBJECT | ND_SHADERFX, dst); +} + +void ED_object_shaderfx_copy(Object *dst, ShaderFxData *fx) +{ + ShaderFxData *nfx = BKE_shaderfx_new(fx->type); + BLI_strncpy(nfx->name, fx->name, sizeof(nfx->name)); + BKE_shaderfx_copydata(fx, nfx); + BLI_addtail(&dst->shader_fx, nfx); + + DEG_id_tag_update(&dst->id, ID_RECALC_GEOMETRY); + WM_main_add_notifier(NC_OBJECT | ND_SHADERFX, dst); +} + /************************ add effect operator *********************/ static int shaderfx_add_exec(bContext *C, wmOperator *op) @@ -586,9 +610,6 @@ static int shaderfx_move_to_index_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_OBJECT | ND_SHADERFX, ob); - return OPERATOR_FINISHED; } diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index 52e06f46149..1bb0246deb5 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -53,7 +53,7 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" -#include "BLI_sys_types.h" // for intptr_t support +#include "BLI_sys_types.h" /* for intptr_t support */ #include "ED_mesh.h" #include "ED_object.h" @@ -66,7 +66,9 @@ #include "object_intern.h" -/*********************** add shape key ***********************/ +/* -------------------------------------------------------------------- */ +/** \name Add Shape Key Function + * \{ */ static void ED_object_shape_key_add(bContext *C, Object *ob, const bool from_mix) { @@ -81,7 +83,11 @@ static void ED_object_shape_key_add(bContext *C, Object *ob, const bool from_mix } } -/*********************** remove shape key ***********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Remove Shape Key Function + * \{ */ static bool object_shapekey_remove(Main *bmain, Object *ob) { @@ -214,7 +220,11 @@ static bool object_shape_key_mirror( return 1; } -/********************** shape key operators *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Shared Poll Functions + * \{ */ static bool shape_key_poll(bContext *C) { @@ -250,6 +260,12 @@ static bool shape_key_move_poll(bContext *C) return (shape_key_mode_poll(C) && key != NULL && key->totkey > 1); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Shape Key Add Operator + * \{ */ + static int shape_key_add_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -285,6 +301,12 @@ void OBJECT_OT_shape_key_add(wmOperatorType *ot) "Create the new shape key from the existing mix of keys"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Shape Key Remove Operator + * \{ */ + static int shape_key_remove_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -326,6 +348,12 @@ void OBJECT_OT_shape_key_remove(wmOperatorType *ot) RNA_def_boolean(ot->srna, "all", 0, "All", "Remove all shape keys"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Shape Key Clear Operator + * \{ */ + static int shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_object_context(C); @@ -399,6 +427,12 @@ void OBJECT_OT_shape_key_retime(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Shape Key Mirror Operator + * \{ */ + static int shape_key_mirror_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -437,6 +471,12 @@ void OBJECT_OT_shape_key_mirror(wmOperatorType *ot) "Use topology based mirroring (for when both sides of mesh have matching, unique topology)"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Shape Key Move (Re-Order) Operator + * \{ */ + enum { KB_MOVE_TOP = -2, KB_MOVE_UP = -1, @@ -502,3 +542,5 @@ void OBJECT_OT_shape_key_move(wmOperatorType *ot) RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", ""); } + +/** \} */ diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index e2d043c3206..76d0c162f29 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -242,7 +242,7 @@ static void object_clear_rot(Object *ob, const bool clear_delta) copy_v3_v3(ob->rot, eul); } } - } // Duplicated in source/blender/editors/armature/editarmature.c + } /* Duplicated in source/blender/editors/armature/editarmature.c */ else { if (ob->rotmode == ROT_MODE_QUAT) { unit_qt(ob->quat); @@ -565,7 +565,7 @@ static void append_sorted_object_parent_hierarchy(Object *root_object, Object **sorted_objects, int *object_index) { - if (object->parent != NULL && object->parent != root_object) { + if (!ELEM(object->parent, NULL, root_object)) { append_sorted_object_parent_hierarchy( root_object, object->parent, sorted_objects, object_index); } @@ -1374,7 +1374,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) if (centermode == ORIGIN_TO_CURSOR) { copy_v3_v3(gpcenter, cursor); } - if ((centermode == ORIGIN_TO_GEOMETRY) || (centermode == ORIGIN_TO_CURSOR)) { + if (ELEM(centermode, ORIGIN_TO_GEOMETRY, ORIGIN_TO_CURSOR)) { bGPDspoint *pt; float imat[3][3], bmat[3][3]; float offset_global[3]; diff --git a/source/blender/editors/object/object_utils.c b/source/blender/editors/object/object_utils.c index fbbfde1ebef..66390f6f165 100644 --- a/source/blender/editors/object/object_utils.c +++ b/source/blender/editors/object/object_utils.c @@ -33,6 +33,7 @@ #include "BLI_utildefines.h" #include "BKE_action.h" +#include "BKE_armature.h" #include "BKE_editmesh.h" #include "BKE_lattice.h" #include "BKE_scene.h" @@ -41,7 +42,6 @@ #include "WM_types.h" -#include "ED_armature.h" #include "ED_curve.h" #include "ED_object.h" /* own include */ diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index b8811408339..3d6a6abfe0d 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -21,7 +21,6 @@ * \ingroup edobj */ -#include <assert.h> #include <math.h> #include <stddef.h> #include <string.h> @@ -578,7 +577,7 @@ void ED_vgroup_vert_active_mirror(Object *ob, int def_nr) BMEditMesh *em = me->edit_mesh; MDeformVert *dvert_act; - if (me->editflag & ME_EDIT_MIRROR_X) { + if (me->symmetry & ME_SYMMETRY_X) { if (em) { BMVert *eve_act; dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act); @@ -634,7 +633,7 @@ static bool vgroup_normalize_active_vertex(Object *ob, eVGroupSelect subset_type BKE_defvert_normalize_subset(dvert_act, vgroup_validmap, vgroup_tot); MEM_freeN((void *)vgroup_validmap); - if (me->editflag & ME_EDIT_MIRROR_X) { + if (me->symmetry & ME_SYMMETRY_X) { if (em) { const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT); ED_mesh_defvert_mirror_update_em(ob, eve_act, -1, -1, cd_dvert_offset); @@ -667,7 +666,7 @@ static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type) if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && eve != eve_act) { MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); BKE_defvert_copy_subset(dv, dvert_act, vgroup_validmap, vgroup_tot); - if (me->editflag & ME_EDIT_MIRROR_X) { + if (me->symmetry & ME_SYMMETRY_X) { ED_mesh_defvert_mirror_update_em(ob, eve, -1, i, cd_dvert_offset); } } @@ -684,7 +683,7 @@ static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type) for (i = 0; i < me->totvert; i++, dv++) { if ((me->mvert[i].flag & SELECT) && dv != dvert_act) { BKE_defvert_copy_subset(dv, dvert_act, vgroup_validmap, vgroup_tot); - if (me->editflag & ME_EDIT_MIRROR_X) { + if (me->symmetry & ME_SYMMETRY_X) { ED_mesh_defvert_mirror_update_ob(ob, -1, i); } } @@ -1592,7 +1591,7 @@ static void vgroup_levels_subset(Object *ob, const bool use_vert_sel = vertex_group_use_vert_sel(ob); const bool use_mirror = (ob->type == OB_MESH) ? - (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : + (((Mesh *)ob->data)->symmetry & ME_SYMMETRY_X) != 0 : false; ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel); @@ -1747,7 +1746,7 @@ static bool *vgroup_selected_get(Object *ob) /* Mirror the selection if X Mirror is enabled. */ Mesh *me = BKE_mesh_from_object(ob); - if (me && (me->editflag & ME_EDIT_MIRROR_X) != 0) { + if (me && (me->symmetry & ME_SYMMETRY_X) != 0) { BKE_object_defgroup_mirror_selection(ob, defbase_tot, mask, mask, &sel_count); } } @@ -1847,7 +1846,7 @@ static void vgroup_invert_subset(Object *ob, int dvert_tot = 0; const bool use_vert_sel = vertex_group_use_vert_sel(ob); const bool use_mirror = (ob->type == OB_MESH) ? - (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : + (((Mesh *)ob->data)->symmetry & ME_SYMMETRY_X) != 0 : false; ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel); @@ -1905,7 +1904,7 @@ static void vgroup_smooth_subset(Object *ob, int *vgroup_subset_map = BLI_array_alloca(vgroup_subset_map, subset_count); float *vgroup_subset_weights = BLI_array_alloca(vgroup_subset_weights, subset_count); const bool use_mirror = (ob->type == OB_MESH) ? - (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : + (((Mesh *)ob->data)->symmetry & ME_SYMMETRY_X) != 0 : false; const bool use_select = vertex_group_use_vert_sel(ob); const bool use_hide = use_select; @@ -2219,7 +2218,7 @@ static void vgroup_clean_subset(Object *ob, int dvert_tot = 0; const bool use_vert_sel = vertex_group_use_vert_sel(ob); const bool use_mirror = (ob->type == OB_MESH) ? - (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : + (((Mesh *)ob->data)->symmetry & ME_SYMMETRY_X) != 0 : false; ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel); @@ -2249,7 +2248,7 @@ static void vgroup_quantize_subset(Object *ob, int dvert_tot = 0; const bool use_vert_sel = vertex_group_use_vert_sel(ob); const bool use_mirror = (ob->type == OB_MESH) ? - (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : + (((Mesh *)ob->data)->symmetry & ME_SYMMETRY_X) != 0 : false; ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel); @@ -2665,12 +2664,23 @@ static void vgroup_assign_verts(Object *ob, const float weight) static bool vertex_group_supported_poll_ex(bContext *C, const Object *ob) { if (!ED_operator_object_active_local_editable_ex(C, ob)) { + CTX_wm_operator_poll_msg_set(C, "No active editable object"); return false; } + + if (!OB_TYPE_SUPPORT_VGROUP(ob->type)) { + CTX_wm_operator_poll_msg_set(C, "Object type does not support vertex groups"); + return false; + } + + /* Data checks. */ const ID *data = ob->data; - return (OB_TYPE_SUPPORT_VGROUP(ob->type) && - /* Data checks. */ - (data != NULL) && !ID_IS_LINKED(data) && !ID_IS_OVERRIDE_LIBRARY(data)); + if (data == NULL || ID_IS_LINKED(data) || ID_IS_OVERRIDE_LIBRARY(data)) { + CTX_wm_operator_poll_msg_set(C, "Object type \"%s\" does not have editable data"); + return false; + } + + return true; } static bool vertex_group_supported_poll(bContext *C) @@ -2679,32 +2689,61 @@ static bool vertex_group_supported_poll(bContext *C) return vertex_group_supported_poll_ex(C, ob); } -static bool vertex_group_poll(bContext *C) +static bool vertex_group_poll_ex(bContext *C, Object *ob) { - Object *ob = ED_object_context(C); + if (!vertex_group_supported_poll_ex(C, ob)) { + return false; + } + + if (BLI_listbase_is_empty(&ob->defbase)) { + CTX_wm_operator_poll_msg_set(C, "Object has no vertex groups"); + return false; + } - return (vertex_group_supported_poll(C) && ob->defbase.first); + return true; } -static bool vertex_group_mesh_poll(bContext *C) +static bool vertex_group_poll(bContext *C) { Object *ob = ED_object_context(C); + return vertex_group_poll_ex(C, ob); +} + +static bool vertex_group_mesh_poll_ex(bContext *C, Object *ob) +{ + if (!vertex_group_poll_ex(C, ob)) { + return false; + } + + if (ob->type != OB_MESH) { + CTX_wm_operator_poll_msg_set(C, "Only mesh objects are supported"); + return false; + } - return (vertex_group_poll(C) && ob->type == OB_MESH); + return true; } -static bool UNUSED_FUNCTION(vertex_group_mesh_supported_poll)(bContext *C) +static bool vertex_group_mesh_with_dvert_poll(bContext *C) { Object *ob = ED_object_context(C); + if (!vertex_group_mesh_poll_ex(C, ob)) { + return false; + } + + Mesh *me = ob->data; + if (me->dvert == NULL) { + CTX_wm_operator_poll_msg_set(C, "The active mesh object has no vertex group data"); + return false; + } - return (vertex_group_supported_poll(C) && ob->type == OB_MESH); + return true; } static bool UNUSED_FUNCTION(vertex_group_poll_edit)(bContext *C) { Object *ob = ED_object_context(C); - if (!vertex_group_supported_poll(C)) { + if (!vertex_group_supported_poll_ex(C, ob)) { return false; } @@ -2718,7 +2757,7 @@ static bool vertex_group_vert_poll_ex(bContext *C, { Object *ob = ED_object_context(C); - if (!vertex_group_supported_poll(C)) { + if (!vertex_group_supported_poll_ex(C, ob)) { return false; } @@ -2771,7 +2810,7 @@ static bool vertex_group_vert_select_unlocked_poll(bContext *C) { Object *ob = ED_object_context(C); - if (!vertex_group_supported_poll(C)) { + if (!vertex_group_supported_poll_ex(C, ob)) { return false; } @@ -2792,7 +2831,7 @@ static bool vertex_group_vert_select_mesh_poll(bContext *C) { Object *ob = ED_object_context(C); - if (!vertex_group_supported_poll(C)) { + if (!vertex_group_supported_poll_ex(C, ob)) { return false; } @@ -2880,7 +2919,7 @@ void OBJECT_OT_vertex_group_remove(wmOperatorType *ot) /* flags */ /* redo operator will fail in this case because vertex groups aren't stored * in local edit mode stack and toggling "all" property will lead to - * all groups deleted without way to restore them (see [#29527], sergey) */ + * all groups deleted without way to restore them (see T29527, sergey) */ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO; /* properties */ @@ -2923,7 +2962,7 @@ void OBJECT_OT_vertex_group_assign(wmOperatorType *ot) /* flags */ /* redo operator will fail in this case because vertex group assignment * isn't stored in local edit mode stack and toggling "new" property will - * lead to creating plenty of new vertex groups (see [#29527], sergey) */ + * lead to creating plenty of new vertex groups (see T29527, sergey) */ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO; } @@ -2958,7 +2997,7 @@ void OBJECT_OT_vertex_group_assign_new(wmOperatorType *ot) /* flags */ /* redo operator will fail in this case because vertex group assignment * isn't stored in local edit mode stack and toggling "new" property will - * lead to creating plenty of new vertex groups (see [#29527], sergey) */ + * lead to creating plenty of new vertex groups (see T29527, sergey) */ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO; } @@ -3009,7 +3048,7 @@ void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot) /* flags */ /* redo operator will fail in this case because vertex groups assignment * isn't stored in local edit mode stack and toggling "all" property will lead to - * removing vertices from all groups (see [#29527], sergey) */ + * removing vertices from all groups (see T29527, sergey) */ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO; /* properties */ @@ -3166,9 +3205,9 @@ void OBJECT_OT_vertex_group_levels(wmOperatorType *ot) vgroup_operator_subset_select_props(ot, true); RNA_def_float( - ot->srna, "offset", 0.f, -1.0, 1.0, "Offset", "Value to add to weights", -1.0f, 1.f); + ot->srna, "offset", 0.0f, -1.0, 1.0, "Offset", "Value to add to weights", -1.0f, 1.0f); RNA_def_float( - ot->srna, "gain", 1.f, 0.f, FLT_MAX, "Gain", "Value to multiply weights by", 0.0f, 10.f); + ot->srna, "gain", 1.0f, 0.0f, FLT_MAX, "Gain", "Value to multiply weights by", 0.0f, 10.0f); } /** \} */ @@ -3314,7 +3353,7 @@ void OBJECT_OT_vertex_group_fix(wmOperatorType *ot) "groups' weights (this tool may be slow for many vertices)"; /* api callbacks */ - ot->poll = vertex_group_mesh_poll; + ot->poll = vertex_group_mesh_with_dvert_poll; ot->exec = vertex_group_fix_exec; /* flags */ @@ -3330,7 +3369,7 @@ void OBJECT_OT_vertex_group_fix(wmOperatorType *ot) 10.0f); RNA_def_float(ot->srna, "strength", - 1.f, + 1.0f, -2.0f, FLT_MAX, "Strength", @@ -3346,7 +3385,7 @@ void OBJECT_OT_vertex_group_fix(wmOperatorType *ot) "Change Sensitivity", "Change the amount weights are altered with each iteration: lower values are slower", 0.05f, - 1.f); + 1.0f); } /** \} */ @@ -4286,14 +4325,14 @@ static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr) if (dw) { dw->weight = weight_act; - if (me->editflag & ME_EDIT_MIRROR_X) { + if (me->symmetry & ME_SYMMETRY_X) { ED_mesh_defvert_mirror_update_em(ob, eve, -1, i, cd_dvert_offset); } } } } - if (me->editflag & ME_EDIT_MIRROR_X) { + if (me->symmetry & ME_SYMMETRY_X) { ED_mesh_defvert_mirror_update_em(ob, eve_act, -1, -1, cd_dvert_offset); } } @@ -4313,14 +4352,14 @@ static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr) MDeformWeight *dw = BKE_defvert_find_index(dv, def_nr); if (dw) { dw->weight = weight_act; - if (me->editflag & ME_EDIT_MIRROR_X) { + if (me->symmetry & ME_SYMMETRY_X) { ED_mesh_defvert_mirror_update_ob(ob, -1, i); } } } } - if (me->editflag & ME_EDIT_MIRROR_X) { + if (me->symmetry & ME_SYMMETRY_X) { ED_mesh_defvert_mirror_update_ob(ob, -1, v_act); } } diff --git a/source/blender/editors/object/object_volume.c b/source/blender/editors/object/object_volume.c index c5dc7f9f24d..5aa61139468 100644 --- a/source/blender/editors/object/object_volume.c +++ b/source/blender/editors/object/object_volume.c @@ -184,7 +184,7 @@ void OBJECT_OT_volume_import(wmOperatorType *ot) WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILES | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); RNA_def_boolean( ot->srna, |