Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/object')
-rw-r--r--source/blender/editors/object/CMakeLists.txt4
-rw-r--r--source/blender/editors/object/object_add.c237
-rw-r--r--source/blender/editors/object/object_constraint.c71
-rw-r--r--source/blender/editors/object/object_data_transfer.c12
-rw-r--r--source/blender/editors/object/object_edit.c33
-rw-r--r--source/blender/editors/object/object_facemap_ops.c7
-rw-r--r--source/blender/editors/object/object_gpencil_modifier.c230
-rw-r--r--source/blender/editors/object/object_intern.h8
-rw-r--r--source/blender/editors/object/object_modes.c2
-rw-r--r--source/blender/editors/object/object_modifier.c166
-rw-r--r--source/blender/editors/object/object_ops.c5
-rw-r--r--source/blender/editors/object/object_relations.c292
-rw-r--r--source/blender/editors/object/object_remesh.c20
-rw-r--r--source/blender/editors/object/object_shader_fx.c98
-rw-r--r--source/blender/editors/object/object_shapekey.c32
-rw-r--r--source/blender/editors/object/object_transform.c50
-rw-r--r--source/blender/editors/object/object_vgroup.c255
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;
}
+
+/** \} */