diff options
author | Julian Eisel <julian@blender.org> | 2020-07-01 18:25:04 +0300 |
---|---|---|
committer | Julian Eisel <julian@blender.org> | 2020-07-01 18:25:04 +0300 |
commit | 889c4ca9c26d770af02cedef972d65eb173bdb5e (patch) | |
tree | 6f46156146db1b3f09d92c6eaa1f44ba8a584ed4 /source/blender/editors/object | |
parent | 87df15190210eb84ef52e5dccc2932918f912da5 (diff) | |
parent | 0829cebeb024095c268f190c34daa8ae9a5a224c (diff) |
Merge branch 'asset-uuid--archived' into asset-engine--archivedasset-engine--archived
Diffstat (limited to 'source/blender/editors/object')
17 files changed, 1150 insertions, 372 deletions
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt index fb273cf49a8..953ef8114f9 100644 --- a/source/blender/editors/object/CMakeLists.txt +++ b/source/blender/editors/object/CMakeLists.txt @@ -91,8 +91,4 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -if(WITH_NEW_OBJECT_TYPES) - add_definitions(-DWITH_NEW_OBJECT_TYPES) -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 8289f52b0c8..8073d87080f 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -65,6 +65,7 @@ #include "BKE_effect.h" #include "BKE_font.h" #include "BKE_gpencil_curve.h" +#include "BKE_gpencil_geom.h" #include "BKE_hair.h" #include "BKE_key.h" #include "BKE_lattice.h" @@ -96,6 +97,8 @@ #include "RNA_define.h" #include "RNA_enum_types.h" +#include "UI_interface.h" + #include "WM_api.h" #include "WM_types.h" @@ -857,7 +860,7 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op) * 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; - ED_mball_add_primitive(C, obedit, mat, dia, RNA_enum_get(op->ptr, "type")); + ED_mball_add_primitive(C, obedit, newob, mat, dia, RNA_enum_get(op->ptr, "type")); /* userdef */ if (newob && !enter_editmode) { @@ -1508,6 +1511,14 @@ void OBJECT_OT_speaker_add(wmOperatorType *ot) /** \name Add Hair Operator * \{ */ +static bool object_hair_add_poll(bContext *C) +{ + if (!U.experimental.use_new_hair_type) { + return false; + } + return ED_operator_objectmode(C); +} + static int object_hair_add_exec(bContext *C, wmOperator *op) { ushort local_view_bits; @@ -1531,7 +1542,7 @@ void OBJECT_OT_hair_add(wmOperatorType *ot) /* api callbacks */ ot->exec = object_hair_add_exec; - ot->poll = ED_operator_objectmode; + ot->poll = object_hair_add_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1545,6 +1556,14 @@ void OBJECT_OT_hair_add(wmOperatorType *ot) /** \name Add Point Cloud Operator * \{ */ +static bool object_pointcloud_add_poll(bContext *C) +{ + if (!U.experimental.use_new_particle_system) { + return false; + } + return ED_operator_objectmode(C); +} + static int object_pointcloud_add_exec(bContext *C, wmOperator *op) { ushort local_view_bits; @@ -1568,7 +1587,7 @@ void OBJECT_OT_pointcloud_add(wmOperatorType *ot) /* api callbacks */ ot->exec = object_pointcloud_add_exec; - ot->poll = ED_operator_objectmode; + ot->poll = object_pointcloud_add_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -2129,11 +2148,11 @@ 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", ""}, + {OB_GPENCIL, "GPENCIL", ICON_OUTLINER_OB_GREASEPENCIL, "Grease Pencil from Curve/Mesh", ""}, {0, NULL, 0, NULL, NULL}, }; -static void convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Object *ob) +static void object_data_convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Object *ob) { if (ob->runtime.curve_cache == NULL) { /* Force creation. This is normally not needed but on operator @@ -2152,7 +2171,7 @@ static void convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Objec } } -static void curvetomesh(Main *bmain, Depsgraph *depsgraph, Object *ob) +static void object_data_convert_curve_to_mesh(Main *bmain, Depsgraph *depsgraph, Object *ob) { Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); Curve *curve = ob->data; @@ -2185,17 +2204,22 @@ static void curvetomesh(Main *bmain, Depsgraph *depsgraph, Object *ob) } } -static bool convert_poll(bContext *C) +static bool object_convert_poll(bContext *C) { Scene *scene = CTX_data_scene(C); Base *base_act = CTX_data_active_base(C); Object *obact = base_act ? base_act->object : NULL; - return (!ID_IS_LINKED(scene) && obact && (BKE_object_is_in_editmode(obact) == false) && - (base_act->flag & BASE_SELECTED) && !ID_IS_LINKED(obact)); + if (obact == NULL || obact->data == NULL || ID_IS_LINKED(obact) || + ID_IS_OVERRIDE_LIBRARY(obact) || ID_IS_OVERRIDE_LIBRARY(obact->data)) { + return false; + } + + return (!ID_IS_LINKED(scene) && (BKE_object_is_in_editmode(obact) == false) && + (base_act->flag & BASE_SELECTED)); } -/* Helper for convert_exec */ +/* Helper for object_convert_exec */ static Base *duplibase_for_convert( Main *bmain, Depsgraph *depsgraph, Scene *scene, ViewLayer *view_layer, Base *base, Object *ob) { @@ -2230,7 +2254,7 @@ static Base *duplibase_for_convert( * time we need to duplicate an object to convert it. Even worse, this is not 100% correct, since * we do not yet have duplicated obdata. * However, that is a safe solution for now. Proper, longer-term solution is to refactor - * convert_exec to: + * object_convert_exec to: * - duplicate all data it needs to in a first loop. * - do a single update. * - convert data in a second loop. */ @@ -2248,7 +2272,7 @@ static Base *duplibase_for_convert( return basen; } -static int convert_exec(bContext *C, wmOperator *op) +static int object_convert_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); @@ -2261,9 +2285,16 @@ static int convert_exec(bContext *C, wmOperator *op) Nurb *nu; MetaBall *mb; Mesh *me; - Object *gpencil_ob = NULL; + Object *ob_gpencil = NULL; const short target = RNA_enum_get(op->ptr, "target"); bool keep_original = RNA_boolean_get(op->ptr, "keep_original"); + + const float angle = RNA_float_get(op->ptr, "angle"); + const int thickness = RNA_int_get(op->ptr, "thickness"); + const bool use_seams = RNA_boolean_get(op->ptr, "seams"); + const bool use_faces = RNA_boolean_get(op->ptr, "faces"); + const float offset = RNA_float_get(op->ptr, "offset"); + int a, mballConverted = 0; bool gpencilConverted = false; @@ -2375,6 +2406,54 @@ static int convert_exec(bContext *C, wmOperator *op) ED_rigidbody_object_remove(bmain, scene, newob); } } + else if (ob->type == OB_MESH && target == OB_GPENCIL) { + ob->flag |= OB_DONE; + + /* Create a new grease pencil object and copy transformations. */ + ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0; + float loc[3], size[3], rot[3][3], eul[3]; + float matrix[4][4]; + 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); + copy_v3_v3(ob_gpencil->loc, loc); + copy_v3_v3(ob_gpencil->rot, eul); + copy_v3_v3(ob_gpencil->scale, size); + unit_m4(matrix); + /* Set object in 3D mode. */ + bGPdata *gpd = (bGPdata *)ob_gpencil->data; + gpd->draw_mode = GP_DRAWMODE_3D; + + BKE_gpencil_convert_mesh(bmain, + depsgraph, + scene, + ob_gpencil, + ob, + angle, + thickness, + offset, + matrix, + 0, + use_seams, + use_faces); + gpencilConverted = true; + + /* Remove unused materials. */ + int actcol = ob_gpencil->actcol; + for (int slot = 1; slot <= ob_gpencil->totcol; slot++) { + while (slot <= ob_gpencil->totcol && + !BKE_object_material_slot_used(ob_gpencil->data, slot)) { + ob_gpencil->actcol = slot; + BKE_object_material_slot_remove(CTX_data_main(C), ob_gpencil); + + if (actcol >= slot) { + actcol--; + } + } + } + ob_gpencil->actcol = actcol; + } else if (ob->type == OB_MESH) { ob->flag |= OB_DONE; @@ -2470,7 +2549,7 @@ static int convert_exec(bContext *C, wmOperator *op) if (target == OB_MESH) { /* No assumption should be made that the resulting objects is a mesh, as conversion can * fail. */ - curvetomesh(bmain, depsgraph, newob); + object_data_convert_curve_to_mesh(bmain, depsgraph, newob); /* meshes doesn't use displist */ BKE_object_free_curve_cache(newob); } @@ -2495,7 +2574,7 @@ static int convert_exec(bContext *C, wmOperator *op) /* No assumption should be made that the resulting objects is a mesh, as conversion can * fail. */ - curvetomesh(bmain, depsgraph, newob); + object_data_convert_curve_to_mesh(bmain, depsgraph, newob); /* meshes doesn't use displist */ BKE_object_free_curve_cache(newob); } @@ -2509,10 +2588,10 @@ static int convert_exec(bContext *C, wmOperator *op) * Nurbs Surface are not supported. */ ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0; - gpencil_ob = ED_gpencil_add_object(C, ob->loc, local_view_bits); - copy_v3_v3(gpencil_ob->rot, ob->rot); - copy_v3_v3(gpencil_ob->scale, ob->scale); - BKE_gpencil_convert_curve(bmain, scene, gpencil_ob, ob, false, false, true); + 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, false, true); gpencilConverted = true; } } @@ -2549,7 +2628,7 @@ static int convert_exec(bContext *C, wmOperator *op) } } - convert_ensure_curve_cache(depsgraph, scene, baseob); + object_data_convert_ensure_curve_cache(depsgraph, scene, baseob); BKE_mesh_from_metaball(&baseob->runtime.curve_cache->disp, newob->data); if (obact->type == OB_MBALL) { @@ -2618,12 +2697,12 @@ static int convert_exec(bContext *C, wmOperator *op) } FOREACH_SCENE_OBJECT_END; } - /* Remove curves converted to Grease Pencil object. */ + /* Remove curves and meshes converted to Grease Pencil object. */ if (gpencilConverted) { - FOREACH_SCENE_OBJECT_BEGIN (scene, ob_curve) { - if (ob_curve->type == OB_CURVE) { - if (ob_curve->flag & OB_DONE) { - ED_object_base_free_and_unlink(bmain, scene, ob_curve); + FOREACH_SCENE_OBJECT_BEGIN (scene, ob_delete) { + if ((ob_delete->type == OB_CURVE) || (ob_delete->type == OB_MESH)) { + if (ob_delete->flag & OB_DONE) { + ED_object_base_free_and_unlink(bmain, scene, ob_delete); } } } @@ -2652,8 +2731,28 @@ static int convert_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static void object_convert_ui(bContext *UNUSED(C), wmOperator *op) +{ + uiLayout *layout = op->layout; + PointerRNA ptr; + + RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); + uiItemR(layout, &ptr, "target", 0, NULL, ICON_NONE); + uiItemR(layout, &ptr, "keep_original", 0, NULL, ICON_NONE); + + if (RNA_enum_get(&ptr, "target") == OB_GPENCIL) { + uiItemR(layout, &ptr, "thickness", 0, NULL, ICON_NONE); + uiItemR(layout, &ptr, "angle", 0, NULL, ICON_NONE); + uiItemR(layout, &ptr, "offset", 0, NULL, ICON_NONE); + uiItemR(layout, &ptr, "seams", 0, NULL, ICON_NONE); + uiItemR(layout, &ptr, "faces", 0, NULL, ICON_NONE); + } +} + void OBJECT_OT_convert(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Convert to"; ot->description = "Convert selected objects to another type"; @@ -2661,8 +2760,9 @@ void OBJECT_OT_convert(wmOperatorType *ot) /* api callbacks */ ot->invoke = WM_menu_invoke; - ot->exec = convert_exec; - ot->poll = convert_poll; + ot->exec = object_convert_exec; + ot->poll = object_convert_poll; + ot->ui = object_convert_ui; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -2675,6 +2775,31 @@ void OBJECT_OT_convert(wmOperatorType *ot) 0, "Keep Original", "Keep original objects instead of replacing them"); + + prop = RNA_def_float_rotation(ot->srna, + "angle", + 0, + NULL, + DEG2RADF(0.0f), + DEG2RADF(180.0f), + "Threshold Angle", + "Threshold to determine ends of the strokes", + DEG2RADF(0.0f), + DEG2RADF(180.0f)); + RNA_def_property_float_default(prop, DEG2RADF(70.0f)); + + RNA_def_int(ot->srna, "thickness", 5, 1, 100, "Thickness", "", 1, 100); + RNA_def_boolean(ot->srna, "seams", 0, "Only Seam Edges", "Convert only seam edges"); + RNA_def_boolean(ot->srna, "faces", 1, "Export Faces", "Export faces as filled strokes"); + RNA_def_float_distance(ot->srna, + "offset", + 0.01f, + 0.0, + OBJECT_ADD_SIZE_MAXF, + "Stroke Offset", + "Offset strokes from fill", + 0.0, + 100.00); } /** \} */ @@ -2693,8 +2818,12 @@ void OBJECT_OT_convert(wmOperatorType *ot) /* used below, assumes id.new is correct */ /* leaves selection of base/object unaltered */ /* Does set ID->newid pointers. */ -static Base *object_add_duplicate_internal( - Main *bmain, Scene *scene, ViewLayer *view_layer, Object *ob, int dupflag) +static Base *object_add_duplicate_internal(Main *bmain, + Scene *scene, + ViewLayer *view_layer, + Object *ob, + const eDupli_ID_Flags dupflag, + const eLibIDDuplicateFlags duplicate_options) { Base *base, *basen = NULL; Object *obn; @@ -2703,7 +2832,7 @@ static Base *object_add_duplicate_internal( /* nothing? */ } else { - obn = ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag)); + obn = ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag, duplicate_options)); DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); base = BKE_view_layer_base_find(view_layer, ob); @@ -2742,12 +2871,13 @@ static Base *object_add_duplicate_internal( * note: caller must do DAG_relations_tag_update(bmain); * this is not done automatic since we may duplicate many objects in a batch */ Base *ED_object_add_duplicate( - Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, int dupflag) + Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, const eDupli_ID_Flags dupflag) { Base *basen; Object *ob; - basen = object_add_duplicate_internal(bmain, scene, view_layer, base->object, dupflag); + basen = object_add_duplicate_internal( + bmain, scene, view_layer, base->object, dupflag, LIB_ID_DUPLICATE_IS_SUBPROCESS); if (basen == NULL) { return NULL; } @@ -2775,10 +2905,11 @@ static int duplicate_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); const bool linked = RNA_boolean_get(op->ptr, "linked"); - int dupflag = (linked) ? 0 : U.dupflag; + const eDupli_ID_Flags dupflag = (linked) ? 0 : (eDupli_ID_Flags)U.dupflag; CTX_DATA_BEGIN (C, Base *, base, selected_bases) { - Base *basen = object_add_duplicate_internal(bmain, scene, view_layer, base->object, dupflag); + Base *basen = object_add_duplicate_internal( + bmain, scene, view_layer, base->object, dupflag, 0); /* note that this is safe to do with this context iterator, * the list is made in advance */ @@ -2849,7 +2980,7 @@ void OBJECT_OT_duplicate(wmOperatorType *ot) * Use for drag & drop. * \{ */ -static int add_named_exec(bContext *C, wmOperator *op) +static int object_add_named_exec(bContext *C, wmOperator *op) { wmWindow *win = CTX_wm_window(C); const wmEvent *event = win ? win->eventstate : NULL; @@ -2859,7 +2990,7 @@ static int add_named_exec(bContext *C, wmOperator *op) Base *basen; Object *ob; const bool linked = RNA_boolean_get(op->ptr, "linked"); - int dupflag = (linked) ? 0 : U.dupflag; + const eDupli_ID_Flags dupflag = (linked) ? 0 : (eDupli_ID_Flags)U.dupflag; char name[MAX_ID_NAME - 2]; /* find object, create fake base */ @@ -2872,7 +3003,7 @@ static int add_named_exec(bContext *C, wmOperator *op) } /* prepare dupli */ - basen = object_add_duplicate_internal(bmain, scene, view_layer, ob, dupflag); + basen = object_add_duplicate_internal(bmain, scene, view_layer, ob, dupflag, 0); if (basen == NULL) { BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated"); @@ -2912,7 +3043,7 @@ void OBJECT_OT_add_named(wmOperatorType *ot) ot->idname = "OBJECT_OT_add_named"; /* api callbacks */ - ot->exec = add_named_exec; + ot->exec = object_add_named_exec; ot->poll = ED_operator_objectmode; /* flags */ @@ -2933,23 +3064,24 @@ void OBJECT_OT_add_named(wmOperatorType *ot) * * \{ */ -static bool join_poll(bContext *C) +static bool object_join_poll(bContext *C) { Object *ob = CTX_data_active_object(C); - if (!ob || ID_IS_LINKED(ob)) { - return 0; + if (ob == NULL || ob->data == NULL || ID_IS_LINKED(ob) || ID_IS_OVERRIDE_LIBRARY(ob) || + ID_IS_OVERRIDE_LIBRARY(ob->data)) { + return false; } if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_ARMATURE, OB_GPENCIL)) { return ED_operator_screenactive(C); } else { - return 0; + return false; } } -static int join_exec(bContext *C, wmOperator *op) +static int object_join_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); @@ -2970,13 +3102,13 @@ static int join_exec(bContext *C, wmOperator *op) } if (ob->type == OB_MESH) { - return join_mesh_exec(C, op); + return ED_mesh_join_objects_exec(C, op); } else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { - return join_curve_exec(C, op); + return ED_curve_join_objects_exec(C, op); } else if (ob->type == OB_ARMATURE) { - return join_armature_exec(C, op); + return ED_armature_join_objects_exec(C, op); } else if (ob->type == OB_GPENCIL) { return ED_gpencil_join_objects_exec(C, op); @@ -2993,8 +3125,8 @@ void OBJECT_OT_join(wmOperatorType *ot) ot->idname = "OBJECT_OT_join"; /* api callbacks */ - ot->exec = join_exec; - ot->poll = join_poll; + ot->exec = object_join_exec; + ot->poll = object_join_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -3010,8 +3142,9 @@ static bool join_shapes_poll(bContext *C) { Object *ob = CTX_data_active_object(C); - if (!ob || ID_IS_LINKED(ob)) { - return 0; + if (ob == NULL || ob->data == NULL || ID_IS_LINKED(ob) || ID_IS_OVERRIDE_LIBRARY(ob) || + ID_IS_OVERRIDE_LIBRARY(ob->data)) { + return false; } /* only meshes supported at the moment */ @@ -3019,7 +3152,7 @@ static bool join_shapes_poll(bContext *C) return ED_operator_screenactive(C); } else { - return 0; + return false; } } @@ -3037,7 +3170,7 @@ static int join_shapes_exec(bContext *C, wmOperator *op) } if (ob->type == OB_MESH) { - return join_mesh_shapes_exec(C, op); + return ED_mesh_shapes_join_objects_exec(C, op); } return OPERATOR_CANCELLED; diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index a2d33ffe413..5746480e3f8 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -1557,6 +1557,77 @@ void CONSTRAINT_OT_move_up(wmOperatorType *ot) /** \} */ /* ------------------------------------------------------------------- */ +/** \name Move Constraint To Index Operator + * \{ */ + +static int constraint_move_to_index_exec(bContext *C, wmOperator *op) +{ + Object *ob = ED_object_active_context(C); + bConstraint *con = edit_constraint_property_get(op, ob, 0); + + int new_index = RNA_int_get(op->ptr, "index"); + if (new_index < 0) { + new_index = 0; + } + + 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); + + return OPERATOR_FINISHED; + } + + return OPERATOR_CANCELLED; +} + +static int constraint_move_to_index_invoke(bContext *C, + wmOperator *op, + const wmEvent *UNUSED(event)) +{ + if (edit_constraint_invoke_properties(C, op)) { + return constraint_move_to_index_exec(C, op); + } + else { + return OPERATOR_CANCELLED; + } +} + +void CONSTRAINT_OT_move_to_index(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Move Constraint To Index"; + ot->idname = "CONSTRAINT_OT_move_to_index"; + ot->description = + "Change the constraint's position in the list so it evaluates after the set number of " + "others"; + + /* callbacks */ + ot->exec = constraint_move_to_index_exec; + ot->invoke = constraint_move_to_index_invoke; + ot->poll = edit_constraint_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + edit_constraint_properties(ot); + RNA_def_int(ot->srna, + "index", + 0, + 0, + INT_MAX, + "Index", + "The index to move the constraint to", + 0, + INT_MAX); +} + +/** \} */ + +/* ------------------------------------------------------------------- */ /** \name Clear Pose Constraints Operator * \{ */ diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index 274cd31406c..0df33255c34 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -381,7 +381,7 @@ static bool data_transfer_exec_is_object_valid(wmOperator *op, me->id.tag &= ~LIB_TAG_DOIT; return true; } - else if (!ID_IS_LINKED(me)) { + else if (!ID_IS_LINKED(me) && !ID_IS_OVERRIDE_LIBRARY(me)) { /* Do not apply transfer operation more than once. */ /* XXX This is not nice regarding vgroups, which are half-Object data... :/ */ BKE_reportf( @@ -446,8 +446,8 @@ static int data_transfer_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } - if (reverse_transfer && ID_IS_LINKED(ob_src->data)) { - /* Do not transfer to linked data, not supported. */ + if (reverse_transfer && (ID_IS_LINKED(ob_src->data) || ID_IS_OVERRIDE_LIBRARY(ob_src->data))) { + /* Do not transfer to linked or override data, not supported. */ return OPERATOR_CANCELLED; } @@ -530,7 +530,7 @@ static bool data_transfer_poll(bContext *C) { Object *ob = ED_object_active_context(C); ID *data = (ob) ? ob->data : NULL; - return (ob && ob->type == OB_MESH && data); + return (ob != NULL && ob->type == OB_MESH && data != NULL); } /* Used by both OBJECT_OT_data_transfer and OBJECT_OT_datalayout_transfer */ @@ -786,7 +786,7 @@ static int datalayout_transfer_exec(bContext *C, wmOperator *op) const bool use_delete = false; /* Never when used from modifier, for now. */ - if (!ob_src) { + if (!ob_src || ID_IS_LINKED(ob_dst) || ID_IS_OVERRIDE_LIBRARY(ob_dst)) { return OPERATOR_CANCELLED; } @@ -854,7 +854,7 @@ static int datalayout_transfer_exec(bContext *C, wmOperator *op) static int datalayout_transfer_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return datalayout_transfer_exec(C, op); } else { diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index d522dcabae3..283aaec85ef 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -600,7 +600,8 @@ bool ED_object_editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag { bool ok = false; - if (ELEM(NULL, ob, ob->data) || ID_IS_LINKED(ob)) { + if (ELEM(NULL, ob, ob->data) || ID_IS_LINKED(ob) || ID_IS_OVERRIDE_LIBRARY(ob) || + ID_IS_OVERRIDE_LIBRARY(ob->data)) { return false; } @@ -695,14 +696,10 @@ bool ED_object_editmode_enter(bContext *C, int flag) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Object *ob; /* Active layer checked here for view3d, * callers that don't want view context can call the extended version. */ - ob = CTX_data_active_object(C); - if ((ob == NULL) || ID_IS_LINKED(ob)) { - return false; - } + Object *ob = CTX_data_active_object(C); return ED_object_editmode_enter_ex(bmain, scene, ob, flag); } @@ -760,7 +757,8 @@ static bool editmode_toggle_poll(bContext *C) Object *ob = CTX_data_active_object(C); /* covers proxies too */ - if (ELEM(NULL, ob, ob->data) || ID_IS_LINKED(ob->data)) { + if (ELEM(NULL, ob, ob->data) || ID_IS_LINKED(ob->data) || ID_IS_OVERRIDE_LIBRARY(ob) || + ID_IS_OVERRIDE_LIBRARY(ob->data)) { return 0; } @@ -1368,7 +1366,8 @@ static bool shade_poll(bContext *C) Object *obact = OBACT(view_layer); if (obact != NULL) { /* Doesn't handle edit-data, sculpt dynamic-topology, or their undo systems. */ - if (obact->mode & (OB_MODE_EDIT | OB_MODE_SCULPT)) { + if (obact->mode & (OB_MODE_EDIT | OB_MODE_SCULPT) || obact->data == NULL || + ID_IS_OVERRIDE_LIBRARY(obact) || ID_IS_OVERRIDE_LIBRARY(obact->data)) { return false; } } @@ -1771,15 +1770,6 @@ static void move_to_collection_menu_create(bContext *UNUSED(C), uiLayout *layout const char *name = BKE_collection_ui_name_get(menu->collection); UI_block_flag_enable(uiLayoutGetBlock(layout), UI_BLOCK_IS_FLIP); - uiItemIntO(layout, name, ICON_NONE, menu->ot->idname, "collection_index", menu->index); - uiItemS(layout); - - for (MoveToCollectionData *submenu = menu->submenus.first; submenu != NULL; - submenu = submenu->next) { - move_to_collection_menus_items(layout, submenu); - } - - uiItemS(layout); WM_operator_properties_create_ptr(&menu->ptr, menu->ot); RNA_int_set(&menu->ptr, "collection_index", menu->index); @@ -1787,6 +1777,15 @@ static void move_to_collection_menu_create(bContext *UNUSED(C), uiLayout *layout uiItemFullO_ptr( layout, menu->ot, "New Collection", ICON_ADD, menu->ptr.data, WM_OP_INVOKE_DEFAULT, 0, NULL); + + uiItemS(layout); + + uiItemIntO(layout, name, ICON_SCENE_DATA, menu->ot->idname, "collection_index", menu->index); + + for (MoveToCollectionData *submenu = menu->submenus.first; submenu != NULL; + submenu = submenu->next) { + move_to_collection_menus_items(layout, submenu); + } } static void move_to_collection_menus_items(uiLayout *layout, MoveToCollectionData *menu) diff --git a/source/blender/editors/object/object_facemap_ops.c b/source/blender/editors/object/object_facemap_ops.c index 147bd3d7871..6e0376358bb 100644 --- a/source/blender/editors/object/object_facemap_ops.c +++ b/source/blender/editors/object/object_facemap_ops.c @@ -171,14 +171,15 @@ static bool face_map_supported_poll(bContext *C) { Object *ob = ED_object_context(C); ID *data = (ob) ? ob->data : NULL; - return (ob && !ob->id.lib && ob->type == OB_MESH && data && !data->lib); + return (ob && !ID_IS_LINKED(ob) && !ID_IS_OVERRIDE_LIBRARY(ob) && ob->type == OB_MESH && data && + !ID_IS_LINKED(data) && !ID_IS_OVERRIDE_LIBRARY(data)); } static bool face_map_supported_edit_mode_poll(bContext *C) { Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - if (ob && !ob->id.lib && ob->type == OB_MESH && data && !data->lib) { + + if (face_map_supported_poll(C)) { if (ob->mode == OB_MODE_EDIT) { return true; } diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c index 6d0f53cfa1e..cfdb6fea52d 100644 --- a/source/blender/editors/object/object_gpencil_modifier.c +++ b/source/blender/editors/object/object_gpencil_modifier.c @@ -24,6 +24,7 @@ #include <math.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "MEM_guardedalloc.h" @@ -54,6 +55,8 @@ #include "ED_object.h" #include "ED_screen.h" +#include "UI_interface.h" + #include "WM_api.h" #include "WM_types.h" @@ -105,23 +108,6 @@ GpencilModifierData *ED_object_gpencil_modifier_add( return new_md; } -/* Return true if the object has a modifier of type 'type' other than - * the modifier pointed to be 'exclude', otherwise returns false. */ -static bool UNUSED_FUNCTION(gpencil_object_has_modifier)(const Object *ob, - const GpencilModifierData *exclude, - GpencilModifierType type) -{ - GpencilModifierData *md; - - for (md = ob->greasepencil_modifiers.first; md; md = md->next) { - if ((md != exclude) && (md->type == type)) { - return true; - } - } - - return false; -} - static bool gpencil_object_modifier_remove(Main *bmain, Object *ob, GpencilModifierData *md, @@ -211,6 +197,40 @@ int ED_object_gpencil_modifier_move_down(ReportList *UNUSED(reports), return 1; } +bool ED_object_gpencil_modifier_move_to_index(ReportList *reports, + Object *ob, + GpencilModifierData *md, + const int index) +{ + BLI_assert(md != NULL); + BLI_assert(index >= 0); + if (index >= BLI_listbase_count(&ob->greasepencil_modifiers)) { + BKE_report(reports, RPT_WARNING, "Cannot move modifier beyond the end of the stack"); + return false; + } + + int md_index = BLI_findindex(&ob->greasepencil_modifiers, md); + BLI_assert(md_index != -1); + if (md_index < index) { + /* Move modifier down in list. */ + for (; md_index < index; md_index++) { + if (!ED_object_gpencil_modifier_move_down(reports, ob, md)) { + break; + } + } + } + else { + /* Move modifier up in list. */ + for (; md_index > index; md_index--) { + if (!ED_object_gpencil_modifier_move_up(reports, ob, md)) { + break; + } + } + } + + return true; +} + static int gpencil_modifier_apply_obdata( ReportList *reports, Main *bmain, Depsgraph *depsgraph, Object *ob, GpencilModifierData *md) { @@ -428,22 +448,58 @@ static void gpencil_edit_modifier_properties(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN); } -static int gpencil_edit_modifier_invoke_properties(bContext *C, wmOperator *op) +static void gpencil_edit_modifier_report_property(wmOperatorType *ot) { - GpencilModifierData *md; + PropertyRNA *prop = RNA_def_boolean( + ot->srna, "report", false, "Report", "Create a notification after the operation"); + RNA_def_property_flag(prop, PROP_HIDDEN); +} +/** + * \param event: If this isn't NULL, the operator will also look for panels underneath + * the cursor with customdata set to a modifier. + * \param r_retval: This should be used if #event is used in order to to return + * #OPERATOR_PASS_THROUGH to check other operators with the same key set. + */ +static bool gpencil_edit_modifier_invoke_properties(bContext *C, + wmOperator *op, + const wmEvent *event, + int *r_retval) +{ if (RNA_struct_property_is_set(op->ptr, "modifier")) { return true; } - else { - PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_GpencilModifier); - if (ptr.data) { - md = ptr.data; - RNA_string_set(op->ptr, "modifier", md->name); - return true; + + PointerRNA ctx_ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_GpencilModifier); + if (ctx_ptr.data != NULL) { + GpencilModifierData *md = ctx_ptr.data; + RNA_string_set(op->ptr, "modifier", md->name); + return true; + } + + /* Check the custom data of panels under the mouse for a modifier. */ + if (event != NULL) { + PointerRNA *panel_ptr = UI_region_panel_custom_data_under_cursor(C, event); + + if (!(panel_ptr == NULL || RNA_pointer_is_null(panel_ptr))) { + if (RNA_struct_is_a(panel_ptr->type, &RNA_GpencilModifier)) { + GpencilModifierData *md = panel_ptr->data; + RNA_string_set(op->ptr, "modifier", md->name); + return true; + } + else { + BLI_assert(r_retval != NULL); /* We need the return value in this case. */ + if (r_retval != NULL) { + *r_retval = (OPERATOR_PASS_THROUGH | OPERATOR_CANCELLED); + } + return false; + } } } + if (r_retval != NULL) { + *r_retval = OPERATOR_CANCELLED; + } return false; } @@ -472,24 +528,35 @@ static int gpencil_modifier_remove_exec(bContext *C, wmOperator *op) Object *ob = ED_object_active_context(C); GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0); - if (!md || !ED_object_gpencil_modifier_remove(op->reports, bmain, ob, md)) { + if (md == NULL) { + return OPERATOR_CANCELLED; + } + + /* Store name temporarily for report. */ + char name[MAX_NAME]; + strcpy(name, md->name); + + if (!ED_object_gpencil_modifier_remove(op->reports, bmain, ob, md)) { return OPERATOR_CANCELLED; } WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); + if (RNA_boolean_get(op->ptr, "report")) { + BKE_reportf(op->reports, RPT_INFO, "Removed modifier: %s", name); + } + return OPERATOR_FINISHED; } -static int gpencil_modifier_remove_invoke(bContext *C, - wmOperator *op, - const wmEvent *UNUSED(event)) +static int gpencil_modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (gpencil_edit_modifier_invoke_properties(C, op)) { + int retval; + if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) { return gpencil_modifier_remove_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } @@ -506,6 +573,7 @@ void OBJECT_OT_gpencil_modifier_remove(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; gpencil_edit_modifier_properties(ot); + gpencil_edit_modifier_report_property(ot); } /************************ move up modifier operator *********************/ @@ -525,15 +593,14 @@ static int gpencil_modifier_move_up_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int gpencil_modifier_move_up_invoke(bContext *C, - wmOperator *op, - const wmEvent *UNUSED(event)) +static int gpencil_modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (gpencil_edit_modifier_invoke_properties(C, op)) { + int retval; + if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) { return gpencil_modifier_move_up_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } @@ -569,15 +636,14 @@ static int gpencil_modifier_move_down_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int gpencil_modifier_move_down_invoke(bContext *C, - wmOperator *op, - const wmEvent *UNUSED(event)) +static int gpencil_modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (gpencil_edit_modifier_invoke_properties(C, op)) { + int retval; + if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) { return gpencil_modifier_move_down_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } @@ -596,6 +662,59 @@ void OBJECT_OT_gpencil_modifier_move_down(wmOperatorType *ot) gpencil_edit_modifier_properties(ot); } +/* ************************* Move to Index Gpencil Modifier Operator ************************* */ + +static bool gpencil_modifier_move_to_index_poll(bContext *C) +{ + return gpencil_edit_modifier_poll(C); +} + +static int gpencil_modifier_move_to_index_exec(bContext *C, wmOperator *op) +{ + Object *ob = ED_object_active_context(C); + GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0); + int index = RNA_int_get(op->ptr, "index"); + + if (!ED_object_gpencil_modifier_move_to_index(op->reports, ob, md, index)) { + 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; +} + +static int gpencil_modifier_move_to_index_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + int retval; + if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) { + return gpencil_modifier_move_to_index_exec(C, op); + } + else { + return retval; + } +} + +void OBJECT_OT_gpencil_modifier_move_to_index(wmOperatorType *ot) +{ + ot->name = "Move Active Modifier to Index"; + ot->idname = "OBJECT_OT_gpencil_modifier_move_to_index"; + ot->description = + "Change the modifier's position in the list so it evaluates after the set number of " + "others"; + + ot->invoke = gpencil_modifier_move_to_index_invoke; + ot->exec = gpencil_modifier_move_to_index_exec; + ot->poll = gpencil_modifier_move_to_index_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + edit_modifier_properties(ot); + RNA_def_int( + ot->srna, "index", 0, 0, INT_MAX, "Index", "The index to move the modifier to", 0, INT_MAX); +} + /************************ apply modifier operator *********************/ static int gpencil_modifier_apply_exec(bContext *C, wmOperator *op) @@ -606,23 +725,36 @@ static int gpencil_modifier_apply_exec(bContext *C, wmOperator *op) GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0); int apply_as = RNA_enum_get(op->ptr, "apply_as"); - if (!md || !ED_object_gpencil_modifier_apply(bmain, op->reports, depsgraph, ob, md, apply_as)) { + if (md == NULL) { + return OPERATOR_CANCELLED; + } + + /* Store name temporarily for report. */ + char name[MAX_NAME]; + strcpy(name, md->name); + + if (!ED_object_gpencil_modifier_apply(bmain, op->reports, depsgraph, ob, md, apply_as)) { return OPERATOR_CANCELLED; } DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); + if (RNA_boolean_get(op->ptr, "report")) { + BKE_reportf(op->reports, RPT_INFO, "Applied modifier: %s", name); + } + return OPERATOR_FINISHED; } -static int gpencil_modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int gpencil_modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (gpencil_edit_modifier_invoke_properties(C, op)) { + int retval; + if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) { return gpencil_modifier_apply_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } @@ -656,6 +788,7 @@ void OBJECT_OT_gpencil_modifier_apply(wmOperatorType *ot) "Apply as", "How to apply the modifier to the geometry"); gpencil_edit_modifier_properties(ot); + gpencil_edit_modifier_report_property(ot); } /************************ copy modifier operator *********************/ @@ -675,13 +808,14 @@ static int gpencil_modifier_copy_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int gpencil_modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int gpencil_modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (gpencil_edit_modifier_invoke_properties(C, op)) { + int retval; + if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) { return gpencil_modifier_copy_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index c5a6e38fbcb..afc87c0caba 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -153,7 +153,10 @@ bool edit_modifier_poll_generic(struct bContext *C, const bool is_editmode_allowed); bool edit_modifier_poll(struct bContext *C); void edit_modifier_properties(struct wmOperatorType *ot); -int edit_modifier_invoke_properties(struct bContext *C, struct wmOperator *op); +bool edit_modifier_invoke_properties(struct bContext *C, + struct wmOperator *op, + const struct wmEvent *event, + int *r_retval); struct ModifierData *edit_modifier_property_get(struct wmOperator *op, struct Object *ob, int type); @@ -190,6 +193,7 @@ void OBJECT_OT_gpencil_modifier_add(struct wmOperatorType *ot); void OBJECT_OT_gpencil_modifier_remove(struct wmOperatorType *ot); void OBJECT_OT_gpencil_modifier_move_up(struct wmOperatorType *ot); void OBJECT_OT_gpencil_modifier_move_down(struct wmOperatorType *ot); +void OBJECT_OT_gpencil_modifier_move_to_index(struct wmOperatorType *ot); void OBJECT_OT_gpencil_modifier_apply(struct wmOperatorType *ot); void OBJECT_OT_gpencil_modifier_copy(struct wmOperatorType *ot); @@ -198,6 +202,7 @@ void OBJECT_OT_shaderfx_add(struct wmOperatorType *ot); void OBJECT_OT_shaderfx_remove(struct wmOperatorType *ot); void OBJECT_OT_shaderfx_move_up(struct wmOperatorType *ot); void OBJECT_OT_shaderfx_move_down(struct wmOperatorType *ot); +void OBJECT_OT_shaderfx_move_to_index(struct wmOperatorType *ot); /* object_constraint.c */ void OBJECT_OT_constraint_add(struct wmOperatorType *ot); @@ -217,6 +222,7 @@ void POSE_OT_ik_clear(struct wmOperatorType *ot); void CONSTRAINT_OT_delete(struct wmOperatorType *ot); void CONSTRAINT_OT_move_up(struct wmOperatorType *ot); +void CONSTRAINT_OT_move_to_index(struct wmOperatorType *ot); void CONSTRAINT_OT_move_down(struct wmOperatorType *ot); void CONSTRAINT_OT_stretchto_reset(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c index c518fd32c7f..5d4476ecb8c 100644 --- a/source/blender/editors/object/object_modes.c +++ b/source/blender/editors/object/object_modes.c @@ -116,7 +116,7 @@ bool ED_object_mode_compat_test(const Object *ob, eObjectMode mode) case OB_SURF: case OB_FONT: case OB_MBALL: - if (mode & (OB_MODE_EDIT)) { + if (mode & OB_MODE_EDIT) { return true; } break; diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index a6c5814e88a..6b0eff5b6e5 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -88,6 +88,8 @@ #include "ED_screen.h" #include "ED_sculpt.h" +#include "UI_interface.h" + #include "WM_api.h" #include "WM_types.h" @@ -1037,22 +1039,58 @@ void edit_modifier_properties(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN); } -int edit_modifier_invoke_properties(bContext *C, wmOperator *op) +static void edit_modifier_report_property(wmOperatorType *ot) { - ModifierData *md; + PropertyRNA *prop = RNA_def_boolean( + ot->srna, "report", false, "Report", "Create a notification after the operation"); + RNA_def_property_flag(prop, PROP_HIDDEN); +} +/** + * \param event: If this isn't NULL, the operator will also look for panels underneath + * the cursor with customdata set to a modifier. + * \param r_retval: This should be used if #event is used in order to to return + * #OPERATOR_PASS_THROUGH to check other operators with the same key set. + */ +bool edit_modifier_invoke_properties(bContext *C, + wmOperator *op, + const wmEvent *event, + int *r_retval) +{ if (RNA_struct_property_is_set(op->ptr, "modifier")) { return true; } - else { - PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier); - if (ptr.data) { - md = ptr.data; - RNA_string_set(op->ptr, "modifier", md->name); - return true; + + PointerRNA ctx_ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier); + if (ctx_ptr.data != NULL) { + ModifierData *md = ctx_ptr.data; + RNA_string_set(op->ptr, "modifier", md->name); + return true; + } + + /* Check the custom data of panels under the mouse for a modifier. */ + if (event != NULL) { + PointerRNA *panel_ptr = UI_region_panel_custom_data_under_cursor(C, event); + + if (!(panel_ptr == NULL || RNA_pointer_is_null(panel_ptr))) { + if (RNA_struct_is_a(panel_ptr->type, &RNA_Modifier)) { + ModifierData *md = panel_ptr->data; + RNA_string_set(op->ptr, "modifier", md->name); + return true; + } + else { + BLI_assert(r_retval != NULL); /* We need the return value in this case. */ + if (r_retval != NULL) { + *r_retval = (OPERATOR_PASS_THROUGH | OPERATOR_CANCELLED); + } + return false; + } } } + if (r_retval != NULL) { + *r_retval = OPERATOR_CANCELLED; + } return false; } @@ -1085,7 +1123,15 @@ static int modifier_remove_exec(bContext *C, wmOperator *op) ModifierData *md = edit_modifier_property_get(op, ob, 0); int mode_orig = ob->mode; - if (!md || !ED_object_modifier_remove(op->reports, bmain, ob, md)) { + if (md == NULL) { + return OPERATOR_CANCELLED; + } + + /* Store name temporarily for report. */ + char name[MAX_NAME]; + strcpy(name, md->name); + + if (!ED_object_modifier_remove(op->reports, bmain, ob, md)) { return OPERATOR_CANCELLED; } @@ -1099,16 +1145,22 @@ static int modifier_remove_exec(bContext *C, wmOperator *op) } } } + + if (RNA_boolean_get(op->ptr, "report")) { + BKE_reportf(op->reports, RPT_INFO, "Removed modifier: %s", name); + } + return OPERATOR_FINISHED; } -static int modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + int retval; + if (edit_modifier_invoke_properties(C, op, event, &retval)) { return modifier_remove_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } @@ -1125,6 +1177,7 @@ void OBJECT_OT_modifier_remove(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; edit_modifier_properties(ot); + edit_modifier_report_property(ot); } /** \} */ @@ -1148,13 +1201,14 @@ static int modifier_move_up_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + int retval; + if (edit_modifier_invoke_properties(C, op, event, &retval)) { return modifier_move_up_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } @@ -1194,13 +1248,14 @@ static int modifier_move_down_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + int retval; + if (edit_modifier_invoke_properties(C, op, event, &retval)) { return modifier_move_down_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } @@ -1246,13 +1301,14 @@ static int modifier_move_to_index_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int modifier_move_to_index_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int modifier_move_to_index_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + int retval; + if (edit_modifier_invoke_properties(C, op, event, &retval)) { return modifier_move_to_index_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } @@ -1291,6 +1347,10 @@ static bool modifier_apply_poll(bContext *C) Object *ob = (ptr.owner_id != NULL) ? (Object *)ptr.owner_id : ED_object_active_context(C); ModifierData *md = ptr.data; /* May be NULL. */ + if (ID_IS_OVERRIDE_LIBRARY(ob) || ID_IS_OVERRIDE_LIBRARY(ob->data)) { + CTX_wm_operator_poll_msg_set(C, "Modifiers cannot be applied on override data"); + return false; + } if ((ob->data != NULL) && ID_REAL_USERS(ob->data) > 1) { CTX_wm_operator_poll_msg_set(C, "Modifiers cannot be applied to multi-user data"); return false; @@ -1315,7 +1375,15 @@ static int modifier_apply_exec(bContext *C, wmOperator *op) ModifierData *md = edit_modifier_property_get(op, ob, 0); int apply_as = RNA_enum_get(op->ptr, "apply_as"); - if (!md || !ED_object_modifier_apply(bmain, op->reports, depsgraph, scene, ob, md, apply_as)) { + if (md == NULL) { + return OPERATOR_CANCELLED; + } + + /* Store name temporarily for report. */ + char name[MAX_NAME]; + strcpy(name, md->name); + + if (!ED_object_modifier_apply(bmain, op->reports, depsgraph, scene, ob, md, apply_as)) { return OPERATOR_CANCELLED; } @@ -1323,16 +1391,21 @@ static int modifier_apply_exec(bContext *C, wmOperator *op) DEG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); + if (RNA_boolean_get(op->ptr, "report")) { + BKE_reportf(op->reports, RPT_INFO, "Applied modifier: %s", name); + } + return OPERATOR_FINISHED; } -static int modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + int retval; + if (edit_modifier_invoke_properties(C, op, event, &retval)) { return modifier_apply_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } @@ -1366,6 +1439,7 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot) "Apply as", "How to apply the modifier to the geometry"); edit_modifier_properties(ot); + edit_modifier_report_property(ot); } /** \} */ @@ -1396,7 +1470,7 @@ static int modifier_convert_exec(bContext *C, wmOperator *op) static int modifier_convert_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return modifier_convert_exec(C, op); } else { @@ -1440,13 +1514,14 @@ static int modifier_copy_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (edit_modifier_invoke_properties(C, op)) { + int retval; + if (edit_modifier_invoke_properties(C, op, event, &retval)) { return modifier_copy_exec(C, op); } else { - return OPERATOR_CANCELLED; + return retval; } } @@ -1501,7 +1576,7 @@ static int multires_higher_levels_delete_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return multires_higher_levels_delete_exec(C, op); } else { @@ -1579,7 +1654,7 @@ static int multires_subdivide_exec(bContext *C, wmOperator *op) static int multires_subdivide_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return multires_subdivide_exec(C, op); } else { @@ -1656,7 +1731,7 @@ static int multires_reshape_exec(bContext *C, wmOperator *op) static int multires_reshape_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return multires_reshape_exec(C, op); } else { @@ -1720,7 +1795,7 @@ static int multires_external_save_invoke(bContext *C, wmOperator *op, const wmEv Mesh *me = ob->data; char path[FILE_MAX]; - if (!edit_modifier_invoke_properties(C, op)) { + if (!edit_modifier_invoke_properties(C, op, NULL, NULL)) { return OPERATOR_CANCELLED; } @@ -1837,7 +1912,7 @@ static int multires_base_apply_exec(bContext *C, wmOperator *op) static int multires_base_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return multires_base_apply_exec(C, op); } else { @@ -1891,7 +1966,7 @@ static int multires_unsubdivide_exec(bContext *C, wmOperator *op) static int multires_unsubdivide_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return multires_unsubdivide_exec(C, op); } else { @@ -1949,7 +2024,7 @@ static int multires_rebuild_subdiv_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return multires_rebuild_subdiv_exec(C, op); } else { @@ -1999,8 +2074,9 @@ static bool skin_poll(bContext *C) static bool skin_edit_poll(bContext *C) { - return (CTX_data_edit_object(C) && - edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH), true)); + Object *ob = CTX_data_edit_object(C); + return (ob != NULL && edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH), true) && + !ID_IS_OVERRIDE_LIBRARY(ob) && !ID_IS_OVERRIDE_LIBRARY(ob->data)); } static void skin_root_clear(BMVert *bm_vert, GSet *visited, const int cd_vert_skin_offset) @@ -2327,7 +2403,7 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op) static int skin_armature_create_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return skin_armature_create_exec(C, op); } else { @@ -2406,7 +2482,7 @@ static int correctivesmooth_bind_exec(bContext *C, wmOperator *op) static int correctivesmooth_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return correctivesmooth_bind_exec(C, op); } else { @@ -2483,7 +2559,7 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op) static int meshdeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return meshdeform_bind_exec(C, op); } else { @@ -2539,7 +2615,7 @@ static int explode_refresh_exec(bContext *C, wmOperator *op) static int explode_refresh_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return explode_refresh_exec(C, op); } else { @@ -2743,7 +2819,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) static int ocean_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return ocean_bake_exec(C, op); } else { @@ -2822,7 +2898,7 @@ static int laplaciandeform_bind_exec(bContext *C, wmOperator *op) static int laplaciandeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return laplaciandeform_bind_exec(C, op); } else { @@ -2891,7 +2967,7 @@ static int surfacedeform_bind_exec(bContext *C, wmOperator *op) static int surfacedeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (edit_modifier_invoke_properties(C, op)) { + if (edit_modifier_invoke_properties(C, op, NULL, NULL)) { return surfacedeform_bind_exec(C, op); } else { diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 05f1ced8615..e28bbb3fb1c 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -109,10 +109,8 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_light_add); WM_operatortype_append(OBJECT_OT_camera_add); WM_operatortype_append(OBJECT_OT_speaker_add); -#ifdef WITH_NEW_OBJECT_TYPES WM_operatortype_append(OBJECT_OT_hair_add); WM_operatortype_append(OBJECT_OT_pointcloud_add); -#endif WM_operatortype_append(OBJECT_OT_volume_add); WM_operatortype_append(OBJECT_OT_volume_import); WM_operatortype_append(OBJECT_OT_add); @@ -152,6 +150,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_gpencil_modifier_remove); WM_operatortype_append(OBJECT_OT_gpencil_modifier_move_up); WM_operatortype_append(OBJECT_OT_gpencil_modifier_move_down); + WM_operatortype_append(OBJECT_OT_gpencil_modifier_move_to_index); WM_operatortype_append(OBJECT_OT_gpencil_modifier_apply); WM_operatortype_append(OBJECT_OT_gpencil_modifier_copy); @@ -160,6 +159,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_shaderfx_remove); WM_operatortype_append(OBJECT_OT_shaderfx_move_up); WM_operatortype_append(OBJECT_OT_shaderfx_move_down); + WM_operatortype_append(OBJECT_OT_shaderfx_move_to_index); WM_operatortype_append(OBJECT_OT_correctivesmooth_bind); WM_operatortype_append(OBJECT_OT_meshdeform_bind); @@ -179,6 +179,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(CONSTRAINT_OT_delete); WM_operatortype_append(CONSTRAINT_OT_move_up); WM_operatortype_append(CONSTRAINT_OT_move_down); + WM_operatortype_append(CONSTRAINT_OT_move_to_index); WM_operatortype_append(CONSTRAINT_OT_stretchto_reset); WM_operatortype_append(CONSTRAINT_OT_limitdistance_reset); WM_operatortype_append(CONSTRAINT_OT_childof_set_inverse); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index fd2fcb11635..509b70f849e 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -33,6 +33,7 @@ #include "DNA_collection_types.h" #include "DNA_constraint_types.h" #include "DNA_gpencil_types.h" +#include "DNA_key_types.h" #include "DNA_lattice_types.h" #include "DNA_light_types.h" #include "DNA_material_types.h" @@ -68,6 +69,7 @@ #include "BKE_gpencil.h" #include "BKE_hair.h" #include "BKE_idprop.h" +#include "BKE_idtype.h" #include "BKE_lattice.h" #include "BKE_layer.h" #include "BKE_lib_id.h" @@ -1771,7 +1773,10 @@ static Collection *single_object_users_collection(Main *bmain, /* Generate new copies for objects in given collection and all its children, * and optionally also copy collections themselves. */ if (copy_collections && !is_master_collection) { - collection = ID_NEW_SET(collection, BKE_collection_copy(bmain, NULL, collection)); + Collection *collection_new; + BKE_id_copy(bmain, &collection->id, (ID **)&collection_new); + id_us_min(&collection_new->id); + collection = ID_NEW_SET(collection, collection_new); } /* We do not remap to new objects here, this is done in separate step. */ @@ -2246,47 +2251,66 @@ void OBJECT_OT_make_local(wmOperatorType *ot) /** \name Make Library Override Operator * \{ */ -static void make_override_library_tag_object(Object *obact, Object *ob) +static bool make_override_hierarchy_recursive_tag(Main *bmain, ID *id) { - if (ob == obact) { - return; + MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->id_user_to_used, id); + + /* This way we won't process again that ID should we encounter it again through another + * relationship hierarchy. + * Note that this does not free any memory from relations, so we can still use the entries. + */ + BKE_main_relations_ID_remove(bmain, id); + + for (; entry != NULL; entry = entry->next) { + /* We only consider IDs from the same library. */ + if (entry->id_pointer != NULL && (*entry->id_pointer)->lib == id->lib) { + if (make_override_hierarchy_recursive_tag(bmain, *entry->id_pointer)) { + id->tag |= LIB_TAG_DOIT; + } + } } - if (!ID_IS_LINKED(ob)) { - return; + return (id->tag & LIB_TAG_DOIT) != 0; +} + +static int make_override_tag_ids_cb(LibraryIDLinkCallbackData *cb_data) +{ + if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_LOOPBACK)) { + return IDWALK_RET_STOP_RECURSION; } - /* Note: all this is very case-by-case bad handling, ultimately we'll want a real full - * 'automatic', generic handling of all this, - * will probably require adding some override-aware stuff to library_query code... */ + ID *id_root = cb_data->user_data; + Library *library_root = id_root->lib; + ID *id = *cb_data->id_pointer; + ID *id_owner = cb_data->id_owner; - if (obact->type == OB_ARMATURE && ob->modifiers.first != NULL) { - for (ModifierData *md = ob->modifiers.first; md != NULL; md = md->next) { - if (md->type == eModifierType_Armature) { - ArmatureModifierData *amd = (ArmatureModifierData *)md; - if (amd->object == obact) { - ob->id.tag |= LIB_TAG_DOIT; - break; - } - } - } + BLI_assert(id_owner == cb_data->id_self); + + if (ELEM(id, NULL, id_owner)) { + return IDWALK_RET_NOP; } - else if (ob->parent == obact) { - ob->id.tag |= LIB_TAG_DOIT; + + BLI_assert(id->lib != NULL); + BLI_assert(id_owner->lib == library_root); + + if (id->tag & LIB_TAG_DOIT) { + /* Already processed, but maybe not with the same chain of dependency, so we need to check that + * one nonetheless. */ + return IDWALK_RET_STOP_RECURSION; } - if (ob->id.tag & LIB_TAG_DOIT) { - printf("Indirectly overriding %s for %s\n", ob->id.name, obact->id.name); + if (id->lib != library_root) { + /* We do not override data-blocks from other libraries, nor do we process them. */ + return IDWALK_RET_STOP_RECURSION; } -} -static void make_override_library_tag_collections(Collection *collection) -{ - collection->id.tag |= LIB_TAG_DOIT; - for (CollectionChild *coll_child = collection->children.first; coll_child != NULL; - coll_child = coll_child->next) { - make_override_library_tag_collections(coll_child->collection); + /* We tag all collections and objects for override. And we also tag all other data-blocks which + * would user one of those. */ + if (ELEM(GS(id->name), ID_OB, ID_GR)) { + id->tag |= LIB_TAG_DOIT; } + + return IDWALK_RET_NOP; } /* Set the object to override. */ @@ -2335,6 +2359,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Object *obact = CTX_data_active_object(C); + ID *id_root = NULL; bool success = false; @@ -2348,111 +2373,156 @@ static int make_override_library_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); + id_root = &obact->instance_collection->id; + } + else if (!ID_IS_OVERRIDABLE_LIBRARY(obact)) { + BKE_reportf(op->reports, + RPT_ERROR_INVALID_INPUT, + "Active object '%s' is not overridable", + obact->id.name + 2); + return OPERATOR_CANCELLED; + } + /* Else, poll func ensures us that ID_IS_LINKED(obact) is true. */ + else { + id_root = &obact->id; + } - Object *obcollection = obact; - Collection *collection = obcollection->instance_collection; + BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); - const ListBase dup_collection_objects = BKE_collection_object_cache_get(collection); - Base *base = BLI_findlink(&dup_collection_objects, RNA_enum_get(op->ptr, "object")); - obact = base->object; + /* Tag all collections and objects, as well as other IDs using them. */ + id_root->tag |= LIB_TAG_DOIT; - /* First, we make a library override of the linked collection itself, and all its children. */ - make_override_library_tag_collections(collection); + BKE_main_relations_create(bmain, 0); - /* Then, we make library override of the whole set of objects in the Collection. */ - FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection, ob) { - ob->id.tag |= LIB_TAG_DOIT; - } - FOREACH_COLLECTION_OBJECT_RECURSIVE_END; - - /* Then, we remove (untag) bone shape objects, you shall never want to override those - * (hopefully)... */ - FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection, ob) { - if (ob->type == OB_ARMATURE && ob->pose != NULL) { - for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan != NULL; pchan = pchan->next) { - if (pchan->custom != NULL) { - pchan->custom->id.tag &= ~LIB_TAG_DOIT; - } + BKE_library_foreach_ID_link( + bmain, id_root, make_override_tag_ids_cb, id_root, IDWALK_READONLY | IDWALK_RECURSE); + + /* Then, we remove (untag) bone shape objects, you shall never want to override those + * (hopefully)... */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + if (ob->type == OB_ARMATURE && ob->pose != NULL && (ob->id.tag & LIB_TAG_DOIT)) { + for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan != NULL; pchan = pchan->next) { + if (pchan->custom != NULL) { + pchan->custom->id.tag &= ~LIB_TAG_DOIT; } } } - FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + } - success = BKE_lib_override_library_create_from_tag(bmain); + /* The we tag all intermediary data-blocks in-between to overridden ones (e.g. if a shapekey has + * a driver using an armature object's bone, we need to override the shapekey/obdata, the objects + * using them, etc.) */ + make_override_hierarchy_recursive_tag(bmain, id_root); + + BKE_main_relations_free(bmain); + + ID *id; + FOREACH_MAIN_ID_BEGIN (bmain, id) { + if (id->tag & LIB_TAG_DOIT && id->lib != NULL) { + printf("ID %s tagged for override\n", id->name); + } + } + FOREACH_MAIN_ID_END; - /* Instantiate our newly overridden objects in scene, if not yet done. */ + success = BKE_lib_override_library_create_from_tag(bmain); + + if (success) { Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - Collection *new_collection = (Collection *)collection->id.newid; - BKE_collection_add_from_object(bmain, scene, obcollection, new_collection); + BKE_main_collection_sync(bmain); + + switch (GS(id_root->name)) { + case ID_GR: { + Collection *collection_new = ((Collection *)id_root->newid); + BKE_collection_add_from_object(bmain, scene, obact, collection_new); + + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection_new, ob_new) { + if (ob_new != NULL && ob_new->id.override_library != NULL) { + Base *base; + if ((base = BKE_view_layer_base_find(view_layer, ob_new)) == NULL) { + BKE_collection_object_add_from(bmain, scene, obact, ob_new); + base = BKE_view_layer_base_find(view_layer, ob_new); + DEG_id_tag_update_ex(bmain, &ob_new->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); + } - FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (new_collection, new_ob) { - if (new_ob != NULL && new_ob->id.override_library != NULL) { - if ((base = BKE_view_layer_base_find(view_layer, new_ob)) == NULL) { - BKE_collection_object_add_from(bmain, scene, obcollection, new_ob); - base = BKE_view_layer_base_find(view_layer, new_ob); - DEG_id_tag_update_ex(bmain, &new_ob->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); + if (ob_new == (Object *)obact->id.newid) { + /* TODO: is setting active needed? */ + BKE_view_layer_base_select_and_set_active(view_layer, base); + } + } } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + break; + } + case ID_OB: { + BKE_collection_object_add_from(bmain, scene, obact, ((Object *)id_root->newid)); + break; + } + default: + BLI_assert(0); + } - if (new_ob == (Object *)obact->id.newid) { - /* TODO: is setting active needed? */ - BKE_view_layer_base_select_and_set_active(view_layer, base); + /* We need to ensure all new overrides of objects are properly instantiated. */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + Object *ob_new = (Object *)ob->id.newid; + if (ob_new != NULL) { + BLI_assert(ob_new->id.override_library != NULL && + ob_new->id.override_library->reference == &ob->id); + + Collection *default_instantiating_collection = NULL; + Base *base; + if ((base = BKE_view_layer_base_find(view_layer, ob_new)) == NULL) { + if (default_instantiating_collection == NULL) { + switch (GS(id_root->name)) { + case ID_GR: { + default_instantiating_collection = BKE_collection_add( + bmain, (Collection *)id_root, "OVERRIDE_HIDDEN"); + break; + } + case ID_OB: { + /* Add the new container collection to one of the collections instantiating the + * root object, or scene's master collection if none found. */ + Object *ob_root = (Object *)id_root; + LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { + if (BKE_collection_has_object(collection, ob_root) && + BKE_view_layer_has_collection(view_layer, collection)) { + default_instantiating_collection = BKE_collection_add( + bmain, collection, "OVERRIDE_HIDDEN"); + } + } + if (default_instantiating_collection == NULL) { + default_instantiating_collection = BKE_collection_add( + bmain, scene->master_collection, "OVERRIDE_HIDDEN"); + } + break; + } + default: + BLI_assert(0); + } + /* Hide the collection from viewport and render. */ + default_instantiating_collection->flag |= COLLECTION_RESTRICT_VIEWPORT | + COLLECTION_RESTRICT_RENDER; + } + + BKE_collection_object_add(bmain, default_instantiating_collection, ob_new); + DEG_id_tag_update_ex(bmain, &ob_new->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); } - /* We still want to store all objects' current override status (i.e. change of parent). */ - BKE_lib_override_library_operations_create(bmain, &new_ob->id, true); } } - FOREACH_COLLECTION_OBJECT_RECURSIVE_END; /* Remove the instance empty from this scene, the items now have an overridden collection * instead. */ - ED_object_base_free_and_unlink(bmain, scene, obcollection); - - /* Also, we'd likely want to lock by default things like - * transformations of implicitly overridden objects? */ - - DEG_id_tag_update(&scene->id, 0); - - /* Cleanup. */ - BKE_main_id_clear_newpoins(bmain); - BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); - } - else if (!ID_IS_OVERRIDABLE_LIBRARY(obact)) { - BKE_reportf(op->reports, - RPT_ERROR_INVALID_INPUT, - "Active object '%s' is not overridable", - obact->id.name + 2); - return OPERATOR_CANCELLED; - } - /* Else, poll func ensures us that ID_IS_LINKED(obact) is true. */ - else if (obact->type == OB_ARMATURE) { - BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); - - obact->id.tag |= LIB_TAG_DOIT; - - for (Object *ob = bmain->objects.first; ob != NULL; ob = ob->id.next) { - make_override_library_tag_object(obact, ob); + if (id_root != &obact->id) { + ED_object_base_free_and_unlink(bmain, scene, obact); } - - success = BKE_lib_override_library_create_from_tag(bmain); - - /* Also, we'd likely want to lock by default things like - * transformations of implicitly overridden objects? */ - - /* Cleanup. */ - BKE_main_id_clear_newpoins(bmain); - BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); - } - /* TODO: probably more cases where we want to do automated smart things in the future! */ - else { - /* For now, remapp all local usages of linked ID to local override one here. */ - BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, true); - success = (BKE_lib_override_library_create_from_id(bmain, &obact->id, true) != NULL); - BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); } + /* Cleanup. */ + BKE_main_id_clear_newpoins(bmain); + BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); + + 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; diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c index 1d7920b9991..664d4219686 100644 --- a/source/blender/editors/object/object_remesh.c +++ b/source/blender/editors/object/object_remesh.c @@ -100,7 +100,12 @@ static bool object_remesh_poll(bContext *C) { Object *ob = CTX_data_active_object(C); - if (ob == NULL) { + if (ob == NULL || ob->data == NULL) { + return false; + } + + if (ID_IS_LINKED(ob) || ID_IS_LINKED(ob->data) || ID_IS_OVERRIDE_LIBRARY(ob->data)) { + CTX_wm_operator_poll_msg_set(C, "The remesher cannot worked on linked or override data"); return false; } @@ -174,6 +179,11 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op) BKE_remesh_reproject_sculpt_face_sets(new_mesh, mesh); } + if (mesh->flag & ME_REMESH_REPROJECT_VERTEX_COLORS) { + BKE_mesh_runtime_clear_geometry(mesh); + BKE_remesh_reproject_vertex_paint(new_mesh, mesh); + } + BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob, &CD_MASK_MESH, true); if (mesh->flag & ME_REMESH_SMOOTH_NORMALS) { @@ -521,7 +531,9 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev /* Project the selected face in the previous step of the Bounding Box. */ for (int i = 0; i < 4; i++) { - ED_view3d_project(ar, cd->preview_plane[i], preview_plane_proj[i]); + float preview_plane_world_space[3]; + mul_v3_m4v3(preview_plane_world_space, active_object->obmat, cd->preview_plane[i]); + ED_view3d_project(ar, preview_plane_world_space, preview_plane_proj[i]); } /* Get the initial X and Y axis of the basis from the edges of the Bounding Box face. */ @@ -569,7 +581,9 @@ static int voxel_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *ev copy_v3_v3(cd->text_mat[3], text_pos); /* Scale the text. */ - const float pixelsize = ED_view3d_pixel_size(rv3d, text_pos); + float text_pos_word_space[3]; + mul_v3_m4v3(text_pos_word_space, active_object->obmat, text_pos); + const float pixelsize = ED_view3d_pixel_size(rv3d, text_pos_word_space); scale_m4_fl(scale_mat, pixelsize * 0.5f); mul_m4_m4_post(cd->text_mat, scale_mat); diff --git a/source/blender/editors/object/object_shader_fx.c b/source/blender/editors/object/object_shader_fx.c index 5db4a5a4f57..d9f37b8e38b 100644 --- a/source/blender/editors/object/object_shader_fx.c +++ b/source/blender/editors/object/object_shader_fx.c @@ -200,6 +200,40 @@ int ED_object_shaderfx_move_down(ReportList *UNUSED(reports), Object *ob, Shader return 1; } +bool ED_object_shaderfx_move_to_index(ReportList *reports, + Object *ob, + ShaderFxData *fx, + const int index) +{ + BLI_assert(fx != NULL); + BLI_assert(index >= 0); + if (index >= BLI_listbase_count(&ob->shader_fx)) { + BKE_report(reports, RPT_WARNING, "Cannot move effect beyond the end of the stack"); + return false; + } + + int fx_index = BLI_findindex(&ob->shader_fx, fx); + BLI_assert(fx_index != -1); + if (fx_index < index) { + /* Move shaderfx down in list. */ + for (; fx_index < index; fx_index++) { + if (!ED_object_shaderfx_move_down(reports, ob, fx)) { + break; + } + } + } + else { + /* Move shaderfx up in list. */ + for (; fx_index > index; fx_index--) { + if (!ED_object_shaderfx_move_up(reports, ob, fx)) { + break; + } + } + } + + return true; +} + /************************ add effect operator *********************/ static int shaderfx_add_exec(bContext *C, wmOperator *op) @@ -391,8 +425,8 @@ static int shaderfx_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UN void OBJECT_OT_shaderfx_remove(wmOperatorType *ot) { - ot->name = "Remove Grease Pencil Modifier"; - ot->description = "Remove a shaderfx from the active grease pencil object"; + ot->name = "Remove Grease Pencil Effect"; + ot->description = "Remove a effect from the active grease pencil object"; ot->idname = "OBJECT_OT_shaderfx_remove"; ot->invoke = shaderfx_remove_invoke; @@ -433,8 +467,8 @@ static int shaderfx_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *U void OBJECT_OT_shaderfx_move_up(wmOperatorType *ot) { - ot->name = "Move Up Modifier"; - ot->description = "Move shaderfx up in the stack"; + ot->name = "Move Up Effect"; + ot->description = "Move effect up in the stack"; ot->idname = "OBJECT_OT_shaderfx_move_up"; ot->invoke = shaderfx_move_up_invoke; @@ -475,8 +509,8 @@ static int shaderfx_move_down_invoke(bContext *C, wmOperator *op, const wmEvent void OBJECT_OT_shaderfx_move_down(wmOperatorType *ot) { - ot->name = "Move Down Modifier"; - ot->description = "Move shaderfx down in the stack"; + ot->name = "Move Down Effect"; + ot->description = "Move effect down in the stack"; ot->idname = "OBJECT_OT_shaderfx_move_down"; ot->invoke = shaderfx_move_down_invoke; @@ -487,3 +521,55 @@ void OBJECT_OT_shaderfx_move_down(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; edit_shaderfx_properties(ot); } + +/************************ move shaderfx to index operator *********************/ + +static bool shaderfx_move_to_index_poll(bContext *C) +{ + return edit_shaderfx_poll_generic(C, &RNA_ShaderFx, 0); +} + +static int shaderfx_move_to_index_exec(bContext *C, wmOperator *op) +{ + Object *ob = ED_object_active_context(C); + ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0); + int index = RNA_int_get(op->ptr, "index"); + + if (!fx || !ED_object_shaderfx_move_to_index(op->reports, ob, fx, index)) { + 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; +} + +static int shaderfx_move_to_index_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + if (edit_shaderfx_invoke_properties(C, op)) { + return shaderfx_move_to_index_exec(C, op); + } + else { + return OPERATOR_CANCELLED; + } +} + +void OBJECT_OT_shaderfx_move_to_index(wmOperatorType *ot) +{ + ot->name = "Move Effect to Index"; + ot->idname = "OBJECT_OT_shaderfx_move_to_index"; + ot->description = + "Change the effect's position in the list so it evaluates after the set number of " + "others"; + + ot->invoke = shaderfx_move_to_index_invoke; + ot->exec = shaderfx_move_to_index_exec; + ot->poll = shaderfx_move_to_index_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + edit_shaderfx_properties(ot); + RNA_def_int( + ot->srna, "index", 0, 0, INT_MAX, "Index", "The index to move the effect to", 0, INT_MAX); +} diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index 26d33bbc375..71778f92349 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -216,40 +216,38 @@ static bool object_shape_key_mirror( /********************** shape key operators *********************/ -static bool shape_key_mode_poll(bContext *C) +static bool shape_key_poll(bContext *C) { Object *ob = ED_object_context(C); ID *data = (ob) ? ob->data : NULL; - return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data) && ob->mode != OB_MODE_EDIT); + + return (ob != NULL && !ID_IS_LINKED(ob) && !ID_IS_OVERRIDE_LIBRARY(ob) && data != NULL && + !ID_IS_LINKED(data) && !ID_IS_OVERRIDE_LIBRARY(data)); } -static bool shape_key_mode_exists_poll(bContext *C) +static bool shape_key_mode_poll(bContext *C) { Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - /* same as shape_key_mode_poll */ - return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data) && ob->mode != OB_MODE_EDIT) && - /* check a keyblock exists */ - (BKE_keyblock_from_object(ob) != NULL); + return (shape_key_poll(C) && ob->mode != OB_MODE_EDIT); } -static bool shape_key_move_poll(bContext *C) +static bool shape_key_mode_exists_poll(bContext *C) { - /* Same as shape_key_mode_exists_poll above, but ensure we have at least two shapes! */ Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - Key *key = BKE_key_from_object(ob); - return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data) && ob->mode != OB_MODE_EDIT && - key && key->totkey > 1); + return (shape_key_mode_poll(C) && + /* check a keyblock exists */ + (BKE_keyblock_from_object(ob) != NULL)); } -static bool shape_key_poll(bContext *C) +static bool shape_key_move_poll(bContext *C) { + /* Same as shape_key_mode_exists_poll above, but ensure we have at least two shapes! */ Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data)); + Key *key = BKE_key_from_object(ob); + + return (shape_key_mode_poll(C) && key != NULL && key->totkey > 1); } static int shape_key_add_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 132b530455e..161611d59c9 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -1098,15 +1098,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) mul_m4_v3(obedit->imat, cent); } else { - if (around == V3D_AROUND_CENTER_MEDIAN) { - if (em->bm->totvert) { - const float total_div = 1.0f / (float)em->bm->totvert; - BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { - madd_v3_v3fl(cent, eve->co, total_div); - } - } - } - else { + if (around == V3D_AROUND_CENTER_BOUNDS) { float min[3], max[3]; INIT_MINMAX(min, max); BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { @@ -1114,6 +1106,14 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) } mid_v3_v3v3(cent, min, max); } + else { /* #V3D_AROUND_CENTER_MEDIAN. */ + if (em->bm->totvert) { + const float total_div = 1.0f / (float)em->bm->totvert; + BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { + madd_v3_v3fl(cent, eve->co, total_div); + } + } + } } BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { @@ -1211,12 +1211,12 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) else if (centermode == ORIGIN_TO_CENTER_OF_MASS_VOLUME) { BKE_mesh_center_of_volume(me, cent); } - else if (around == V3D_AROUND_CENTER_MEDIAN) { - BKE_mesh_center_median(me, cent); - } - else { + else if (around == V3D_AROUND_CENTER_BOUNDS) { BKE_mesh_center_bounds(me, cent); } + else { /* #V3D_AROUND_CENTER_MEDIAN. */ + BKE_mesh_center_median(me, cent); + } negate_v3_v3(cent_neg, cent); BKE_mesh_translate(me, cent_neg, 1); @@ -1231,12 +1231,12 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) if (centermode == ORIGIN_TO_CURSOR) { /* done */ } - else if (around == V3D_AROUND_CENTER_MEDIAN) { - BKE_curve_center_median(cu, cent); - } - else { + else if (around == V3D_AROUND_CENTER_BOUNDS) { BKE_curve_center_bounds(cu, cent); } + else { /* #V3D_AROUND_CENTER_MEDIAN. */ + BKE_curve_center_median(cu, cent); + } /* don't allow Z change if curve is 2D */ if ((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) { @@ -1324,12 +1324,12 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) if (centermode == ORIGIN_TO_CURSOR) { /* done */ } - else if (around == V3D_AROUND_CENTER_MEDIAN) { - BKE_mball_center_median(mb, cent); - } - else { + else if (around == V3D_AROUND_CENTER_BOUNDS) { BKE_mball_center_bounds(mb, cent); } + else { /* #V3D_AROUND_CENTER_MEDIAN. */ + BKE_mball_center_median(mb, cent); + } negate_v3_v3(cent_neg, cent); BKE_mball_translate(mb, cent_neg); @@ -1351,12 +1351,12 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) if (centermode == ORIGIN_TO_CURSOR) { /* done */ } - else if (around == V3D_AROUND_CENTER_MEDIAN) { - BKE_lattice_center_median(lt, cent); - } - else { + else if (around == V3D_AROUND_CENTER_BOUNDS) { BKE_lattice_center_bounds(lt, cent); } + else { /* #V3D_AROUND_CENTER_MEDIAN. */ + BKE_lattice_center_median(lt, cent); + } negate_v3_v3(cent_neg, cent); BKE_lattice_translate(lt, cent_neg, 1); diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index fb79cfb910e..7ca2a89f61d 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -77,7 +77,10 @@ #include "object_intern.h" -/************************ Exported Functions **********************/ +/* -------------------------------------------------------------------- */ +/** \name Public Utility Functions + * \{ */ + static bool vertex_group_use_vert_sel(Object *ob) { if (ob->mode == OB_MODE_EDIT) { @@ -682,7 +685,11 @@ static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type) MEM_freeN((void *)vgroup_validmap); } -/***********************Start weight transfer (WT)*********************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Shared Weight Transfer Operator Properties + * \{ */ static const EnumPropertyItem WT_vertex_group_select_item[] = { {WT_VGROUP_ACTIVE, "ACTIVE", 0, "Active Group", "The active Vertex Group"}, @@ -779,7 +786,15 @@ static void vgroup_operator_subset_select_props(wmOperatorType *ot, bool use_act ot->prop = prop; } -/***********************End weight transfer (WT)***********************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name High Level Vertex Group Add/Remove + * + * Wrap lower level `BKE` functions. + * + * \note that operations on many vertices should use #ED_vgroup_parray_alloc. + * \{ */ /* for Mesh in Object mode */ /* allows editmode for Lattice */ @@ -976,7 +991,11 @@ void ED_vgroup_select_by_name(Object *ob, const char *name) ob->actdef = BKE_object_defgroup_name_index(ob, name) + 1; } -/********************** Operator Implementations *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Operator Function Implementations + * \{ */ /* only in editmode */ static void vgroup_select_verts(Object *ob, int select) @@ -2634,48 +2653,49 @@ static void vgroup_assign_verts(Object *ob, const float weight) } } -/********************** vertex group operators *********************/ +/** \} */ -static bool vertex_group_poll(bContext *C) +/* -------------------------------------------------------------------- */ +/** \name Shared Operator Poll Functions + * \{ */ + +static bool vertex_group_supported_poll(bContext *C) { Object *ob = ED_object_context(C); ID *data = (ob) ? ob->data : NULL; - return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data) && - OB_TYPE_SUPPORT_VGROUP(ob->type) && ob->defbase.first); + return (ob && !ID_IS_LINKED(ob) && OB_TYPE_SUPPORT_VGROUP(ob->type) && + !ID_IS_OVERRIDE_LIBRARY(ob) && data && !ID_IS_LINKED(data) && + !ID_IS_OVERRIDE_LIBRARY(data)); } -static bool vertex_group_supported_poll(bContext *C) +static bool vertex_group_poll(bContext *C) { Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - return (ob && !ID_IS_LINKED(ob) && OB_TYPE_SUPPORT_VGROUP(ob->type) && data && - !ID_IS_LINKED(data)); + + return (vertex_group_supported_poll(C) && ob->defbase.first); } static bool vertex_group_mesh_poll(bContext *C) { Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data) && ob->type == OB_MESH && - ob->defbase.first); + return (vertex_group_poll(C) && ob->type == OB_MESH); } static bool UNUSED_FUNCTION(vertex_group_mesh_supported_poll)(bContext *C) { Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - return (ob && !ID_IS_LINKED(ob) && ob->type == OB_MESH && data && !ID_IS_LINKED(data)); + + return (vertex_group_supported_poll(C) && ob->type == OB_MESH); } static bool UNUSED_FUNCTION(vertex_group_poll_edit)(bContext *C) { Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - if (!(ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data))) { - return 0; + if (!vertex_group_supported_poll(C)) { + return false; } return BKE_object_is_in_editmode_vgroup(ob); @@ -2687,9 +2707,8 @@ static bool vertex_group_vert_poll_ex(bContext *C, const short ob_type_flag) { Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - if (!(ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data))) { + if (!vertex_group_supported_poll(C)) { return false; } @@ -2747,14 +2766,13 @@ static bool vertex_group_mesh_vert_select_poll(bContext *C) static bool vertex_group_vert_select_unlocked_poll(bContext *C) { Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - if (!(ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data))) { - return 0; + if (!vertex_group_supported_poll(C)) { + return false; } if (!(BKE_object_is_in_editmode_vgroup(ob) || BKE_object_is_in_wpaint_select_vert(ob))) { - return 0; + return false; } if (ob->actdef != 0) { @@ -2763,26 +2781,31 @@ static bool vertex_group_vert_select_unlocked_poll(bContext *C) return !(dg->flag & DG_LOCK_WEIGHT); } } - return 1; + return true; } static bool vertex_group_vert_select_mesh_poll(bContext *C) { Object *ob = ED_object_context(C); - ID *data = (ob) ? ob->data : NULL; - if (!(ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data))) { - return 0; + if (!vertex_group_supported_poll(C)) { + return false; } /* only difference to #vertex_group_vert_select_poll */ if (ob->type != OB_MESH) { - return 0; + return false; } return (BKE_object_is_in_editmode_vgroup(ob) || BKE_object_is_in_wpaint_select_vert(ob)); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Add Operator + * \{ */ + static int vertex_group_add_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_object_context(C); @@ -2811,6 +2834,12 @@ void OBJECT_OT_vertex_group_add(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Remove Operator + * \{ */ + static int vertex_group_remove_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -2858,6 +2887,12 @@ void OBJECT_OT_vertex_group_remove(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Assign Operator + * \{ */ + static int vertex_group_assign_exec(bContext *C, wmOperator *UNUSED(op)) { ToolSettings *ts = CTX_data_tool_settings(C); @@ -2888,6 +2923,12 @@ void OBJECT_OT_vertex_group_assign(wmOperatorType *ot) ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Assign New Operator + * \{ */ + /* NOTE: just a wrapper around vertex_group_assign_exec(), except we add these to a new group */ static int vertex_group_assign_new_exec(bContext *C, wmOperator *op) { @@ -2917,6 +2958,12 @@ void OBJECT_OT_vertex_group_assign_new(wmOperatorType *ot) ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Remove From Operator + * \{ */ + static int vertex_group_remove_from_exec(bContext *C, wmOperator *op) { const bool use_all_groups = RNA_boolean_get(op->ptr, "use_all_groups"); @@ -2968,6 +3015,12 @@ void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Select Operator + * \{ */ + static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_object_context(C); @@ -2998,6 +3051,12 @@ void OBJECT_OT_vertex_group_select(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Deselect Operator + * \{ */ + static int vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_object_context(C); @@ -3037,6 +3096,12 @@ static int vertex_group_copy_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Copy Operator + * \{ */ + void OBJECT_OT_vertex_group_copy(wmOperatorType *ot) { /* identifiers */ @@ -3074,6 +3139,12 @@ static int vertex_group_levels_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Levels Operator + * \{ */ + void OBJECT_OT_vertex_group_levels(wmOperatorType *ot) { /* identifiers */ @@ -3115,6 +3186,12 @@ static int vertex_group_normalize_exec(bContext *C, wmOperator *UNUSED(op)) } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Normalize Operator + * \{ */ + void OBJECT_OT_vertex_group_normalize(wmOperatorType *ot) { /* identifiers */ @@ -3158,6 +3235,12 @@ static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op) } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Normalize All Operator + * \{ */ + void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot) { /* identifiers */ @@ -3182,6 +3265,12 @@ void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot) "Keep the values of the active group while normalizing others"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Fix Position Operator + * \{ */ + static int vertex_group_fix_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); @@ -3259,6 +3348,12 @@ void OBJECT_OT_vertex_group_fix(wmOperatorType *ot) 1.f); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Lock Operator + * \{ */ + static int vertex_group_lock_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); @@ -3361,6 +3456,12 @@ void OBJECT_OT_vertex_group_lock(wmOperatorType *ot) "Apply the action based on vertex group selection"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Invert Operator + * \{ */ + static int vertex_group_invert_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -3410,6 +3511,12 @@ void OBJECT_OT_vertex_group_invert(wmOperatorType *ot) "Remove verts from groups that have zero weight after inverting"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Invert Operator + * \{ */ + static int vertex_group_smooth_exec(bContext *C, wmOperator *op) { const float fac = RNA_float_get(op->ptr, "factor"); @@ -3482,6 +3589,12 @@ void OBJECT_OT_vertex_group_smooth(wmOperatorType *ot) 1.0f); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Clean Operator + * \{ */ + static int vertex_group_clean_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -3535,6 +3648,12 @@ void OBJECT_OT_vertex_group_clean(wmOperatorType *ot) "Keep verts assigned to at least one group when cleaning"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Quantize Operator + * \{ */ + static int vertex_group_quantize_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -3574,6 +3693,12 @@ void OBJECT_OT_vertex_group_quantize(wmOperatorType *ot) RNA_def_int(ot->srna, "steps", 4, 1, 1000, "Steps", "Number of steps between 0 and 1", 1, 100); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Limit Total Operator + * \{ */ + static int vertex_group_limit_total_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -3625,6 +3750,12 @@ void OBJECT_OT_vertex_group_limit_total(wmOperatorType *ot) RNA_def_int(ot->srna, "limit", 4, 1, 32, "Limit", "Maximum number of deform weights", 1, 32); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Mirror Operator + * \{ */ + static int vertex_group_mirror_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -3677,6 +3808,12 @@ void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot) "Use topology based mirroring (for when both sides of mesh have matching, unique topology)"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Copy to Linked Operator + * \{ */ + static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); @@ -3720,6 +3857,12 @@ void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Copy to Selected Operator + * \{ */ + static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op) { Object *obact = ED_object_context(C); @@ -3768,6 +3911,12 @@ void OBJECT_OT_vertex_group_copy_to_selected(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Set Active Operator + * \{ */ + static int set_active_group_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -3836,6 +3985,12 @@ void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot) ot->prop = prop; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Sort Operator + * \{ */ + /* creates the name_array parameter for vgroup_do_remap, call this before fiddling * with the order of vgroups then call vgroup_do_remap after */ static char *vgroup_init_remap(Object *ob) @@ -4030,6 +4185,12 @@ void OBJECT_OT_vertex_group_sort(wmOperatorType *ot) RNA_def_enum(ot->srna, "sort_type", vgroup_sort_type, SORT_TYPE_NAME, "Sort type", "Sort type"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Move Operator + * \{ */ + static int vgroup_move_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -4089,6 +4250,12 @@ void OBJECT_OT_vertex_group_move(wmOperatorType *ot) "Direction to move the active vertex group towards"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Weight Paste Operator + * \{ */ + static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr) { MDeformVert *dvert_act; @@ -4218,6 +4385,12 @@ void OBJECT_OT_vertex_weight_paste(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Weight Delete Operator + * \{ */ + static int vertex_weight_delete_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -4262,6 +4435,12 @@ void OBJECT_OT_vertex_weight_delete(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Set Active by Weight Operator + * \{ */ + static int vertex_weight_set_active_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); @@ -4303,6 +4482,12 @@ void OBJECT_OT_vertex_weight_set_active(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Normalize Active Vertex Operator + * \{ */ + static int vertex_weight_normalize_active_vertex_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_object_context(C); @@ -4338,6 +4523,12 @@ void OBJECT_OT_vertex_weight_normalize_active_vertex(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex Group Copy Weights from Active Operator + * \{ */ + static int vertex_weight_copy_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_object_context(C); @@ -4366,3 +4557,5 @@ void OBJECT_OT_vertex_weight_copy(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } + +/** \} */ |