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:
authorCampbell Barton <ideasman42@gmail.com>2019-04-17 07:17:24 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-04-17 07:21:24 +0300
commite12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch)
tree8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/editors/object
parentb3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff)
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/editors/object')
-rw-r--r--source/blender/editors/object/CMakeLists.txt96
-rw-r--r--source/blender/editors/object/object_add.c3846
-rw-r--r--source/blender/editors/object/object_bake.c870
-rw-r--r--source/blender/editors/object/object_bake_api.c2807
-rw-r--r--source/blender/editors/object/object_collection.c857
-rw-r--r--source/blender/editors/object/object_constraint.c3109
-rw-r--r--source/blender/editors/object/object_data_transfer.c1340
-rw-r--r--source/blender/editors/object/object_edit.c2541
-rw-r--r--source/blender/editors/object/object_facemap_ops.c645
-rw-r--r--source/blender/editors/object/object_gpencil_modifier.c754
-rw-r--r--source/blender/editors/object/object_hook.c1475
-rw-r--r--source/blender/editors/object/object_intern.h10
-rw-r--r--source/blender/editors/object/object_modes.c363
-rw-r--r--source/blender/editors/object/object_modifier.c3329
-rw-r--r--source/blender/editors/object/object_ops.c482
-rw-r--r--source/blender/editors/object/object_random.c218
-rw-r--r--source/blender/editors/object/object_relations.c4314
-rw-r--r--source/blender/editors/object/object_select.c2060
-rw-r--r--source/blender/editors/object/object_shader_fx.c505
-rw-r--r--source/blender/editors/object/object_shapekey.c652
-rw-r--r--source/blender/editors/object/object_transform.c2947
-rw-r--r--source/blender/editors/object/object_utils.c181
-rw-r--r--source/blender/editors/object/object_vgroup.c6626
-rw-r--r--source/blender/editors/object/object_warp.c441
24 files changed, 20784 insertions, 19684 deletions
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt
index 75d2fada7f3..8ef0d85bcfd 100644
--- a/source/blender/editors/object/CMakeLists.txt
+++ b/source/blender/editors/object/CMakeLists.txt
@@ -16,72 +16,72 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../bmesh
- ../../depsgraph
- ../../gpu
- ../../ikplugin
- ../../imbuf
- ../../makesdna
- ../../makesrna
- ../../modifiers
- ../../gpencil_modifiers
- ../../shader_fx
- ../../python
- ../../render/extern/include
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
+ ../include
+ ../../blenkernel
+ ../../blenlib
+ ../../blentranslation
+ ../../bmesh
+ ../../depsgraph
+ ../../gpu
+ ../../ikplugin
+ ../../imbuf
+ ../../makesdna
+ ../../makesrna
+ ../../modifiers
+ ../../gpencil_modifiers
+ ../../shader_fx
+ ../../python
+ ../../render/extern/include
+ ../../windowmanager
+ ../../../../intern/guardedalloc
+ ../../../../intern/glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_PATH}
+ ${GLEW_INCLUDE_PATH}
)
set(SRC
- object_add.c
- object_bake.c
- object_bake_api.c
- object_collection.c
- object_constraint.c
- object_data_transfer.c
- object_edit.c
- object_facemap_ops.c
- object_gpencil_modifier.c
- object_hook.c
- object_modes.c
- object_modifier.c
- object_ops.c
- object_random.c
- object_relations.c
- object_select.c
- object_shader_fx.c
- object_shapekey.c
- object_transform.c
- object_utils.c
- object_vgroup.c
- object_warp.c
+ object_add.c
+ object_bake.c
+ object_bake_api.c
+ object_collection.c
+ object_constraint.c
+ object_data_transfer.c
+ object_edit.c
+ object_facemap_ops.c
+ object_gpencil_modifier.c
+ object_hook.c
+ object_modes.c
+ object_modifier.c
+ object_ops.c
+ object_random.c
+ object_relations.c
+ object_select.c
+ object_shader_fx.c
+ object_shapekey.c
+ object_transform.c
+ object_utils.c
+ object_vgroup.c
+ object_warp.c
- object_intern.h
+ object_intern.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
- bf_render
+ bf_blenkernel
+ bf_blenlib
+ bf_render
)
add_definitions(${GL_DEFINITIONS})
if(WITH_PYTHON)
- add_definitions(-DWITH_PYTHON)
+ add_definitions(-DWITH_PYTHON)
endif()
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
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 9269c25f54b..c050b579aa6 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
@@ -118,357 +117,392 @@
* kept here because of linking order.
* Icons are only defined here */
const EnumPropertyItem rna_enum_light_type_items[] = {
- {LA_LOCAL, "POINT", ICON_LIGHT_POINT, "Point", "Omnidirectional point light source"},
- {LA_SUN, "SUN", ICON_LIGHT_SUN, "Sun", "Constant direction parallel ray light source"},
- {LA_SPOT, "SPOT", ICON_LIGHT_SPOT, "Spot", "Directional cone light source"},
- {LA_AREA, "AREA", ICON_LIGHT_AREA, "Area", "Directional area light source"},
- {0, NULL, 0, NULL, NULL},
+ {LA_LOCAL, "POINT", ICON_LIGHT_POINT, "Point", "Omnidirectional point light source"},
+ {LA_SUN, "SUN", ICON_LIGHT_SUN, "Sun", "Constant direction parallel ray light source"},
+ {LA_SPOT, "SPOT", ICON_LIGHT_SPOT, "Spot", "Directional cone light source"},
+ {LA_AREA, "AREA", ICON_LIGHT_AREA, "Area", "Directional area light source"},
+ {0, NULL, 0, NULL, NULL},
};
/* copy from rna_object_force.c */
static const EnumPropertyItem field_type_items[] = {
- {PFIELD_FORCE, "FORCE", ICON_FORCE_FORCE, "Force", ""},
- {PFIELD_WIND, "WIND", ICON_FORCE_WIND, "Wind", ""},
- {PFIELD_VORTEX, "VORTEX", ICON_FORCE_VORTEX, "Vortex", ""},
- {PFIELD_MAGNET, "MAGNET", ICON_FORCE_MAGNETIC, "Magnetic", ""},
- {PFIELD_HARMONIC, "HARMONIC", ICON_FORCE_HARMONIC, "Harmonic", ""},
- {PFIELD_CHARGE, "CHARGE", ICON_FORCE_CHARGE, "Charge", ""},
- {PFIELD_LENNARDJ, "LENNARDJ", ICON_FORCE_LENNARDJONES, "Lennard-Jones", ""},
- {PFIELD_TEXTURE, "TEXTURE", ICON_FORCE_TEXTURE, "Texture", ""},
- {PFIELD_GUIDE, "GUIDE", ICON_FORCE_CURVE, "Curve Guide", ""},
- {PFIELD_BOID, "BOID", ICON_FORCE_BOID, "Boid", ""},
- {PFIELD_TURBULENCE, "TURBULENCE", ICON_FORCE_TURBULENCE, "Turbulence", ""},
- {PFIELD_DRAG, "DRAG", ICON_FORCE_DRAG, "Drag", ""},
- {PFIELD_SMOKEFLOW, "SMOKE", ICON_FORCE_SMOKEFLOW, "Smoke Flow", ""},
- {0, NULL, 0, NULL, NULL},
+ {PFIELD_FORCE, "FORCE", ICON_FORCE_FORCE, "Force", ""},
+ {PFIELD_WIND, "WIND", ICON_FORCE_WIND, "Wind", ""},
+ {PFIELD_VORTEX, "VORTEX", ICON_FORCE_VORTEX, "Vortex", ""},
+ {PFIELD_MAGNET, "MAGNET", ICON_FORCE_MAGNETIC, "Magnetic", ""},
+ {PFIELD_HARMONIC, "HARMONIC", ICON_FORCE_HARMONIC, "Harmonic", ""},
+ {PFIELD_CHARGE, "CHARGE", ICON_FORCE_CHARGE, "Charge", ""},
+ {PFIELD_LENNARDJ, "LENNARDJ", ICON_FORCE_LENNARDJONES, "Lennard-Jones", ""},
+ {PFIELD_TEXTURE, "TEXTURE", ICON_FORCE_TEXTURE, "Texture", ""},
+ {PFIELD_GUIDE, "GUIDE", ICON_FORCE_CURVE, "Curve Guide", ""},
+ {PFIELD_BOID, "BOID", ICON_FORCE_BOID, "Boid", ""},
+ {PFIELD_TURBULENCE, "TURBULENCE", ICON_FORCE_TURBULENCE, "Turbulence", ""},
+ {PFIELD_DRAG, "DRAG", ICON_FORCE_DRAG, "Drag", ""},
+ {PFIELD_SMOKEFLOW, "SMOKE", ICON_FORCE_SMOKEFLOW, "Smoke Flow", ""},
+ {0, NULL, 0, NULL, NULL},
};
static EnumPropertyItem lightprobe_type_items[] = {
- {LIGHTPROBE_TYPE_CUBE, "CUBEMAP", ICON_LIGHTPROBE_CUBEMAP, "Reflection Cubemap",
+ {LIGHTPROBE_TYPE_CUBE,
+ "CUBEMAP",
+ ICON_LIGHTPROBE_CUBEMAP,
+ "Reflection Cubemap",
"Reflection probe with spherical or cubic attenuation"},
- {LIGHTPROBE_TYPE_PLANAR, "PLANAR", ICON_LIGHTPROBE_PLANAR, "Reflection Plane",
+ {LIGHTPROBE_TYPE_PLANAR,
+ "PLANAR",
+ ICON_LIGHTPROBE_PLANAR,
+ "Reflection Plane",
"Planar reflection probe"},
- {LIGHTPROBE_TYPE_GRID, "GRID", ICON_LIGHTPROBE_GRID, "Irradiance Volume",
+ {LIGHTPROBE_TYPE_GRID,
+ "GRID",
+ ICON_LIGHTPROBE_GRID,
+ "Irradiance Volume",
"Irradiance probe to capture diffuse indirect lighting"},
- {0, NULL, 0, NULL, NULL},
+ {0, NULL, 0, NULL, NULL},
};
/************************** Exported *****************************/
void ED_object_location_from_view(bContext *C, float loc[3])
{
- const Scene *scene = CTX_data_scene(C);
- copy_v3_v3(loc, scene->cursor.location);
+ const Scene *scene = CTX_data_scene(C);
+ copy_v3_v3(loc, scene->cursor.location);
}
void ED_object_rotation_from_quat(float rot[3], const float viewquat[4], const char align_axis)
{
- BLI_assert(align_axis >= 'X' && align_axis <= 'Z');
-
- switch (align_axis) {
- case 'X':
- {
- /* Same as 'rv3d->viewinv[1]' */
- float axis_y[4] = {0.0f, 1.0f, 0.0f};
- float quat_y[4], quat[4];
- axis_angle_to_quat(quat_y, axis_y, M_PI_2);
- mul_qt_qtqt(quat, viewquat, quat_y);
- quat_to_eul(rot, quat);
- break;
- }
- case 'Y':
- {
- quat_to_eul(rot, viewquat);
- rot[0] -= (float)M_PI_2;
- break;
- }
- case 'Z':
- {
- quat_to_eul(rot, viewquat);
- break;
- }
- }
+ BLI_assert(align_axis >= 'X' && align_axis <= 'Z');
+
+ switch (align_axis) {
+ case 'X': {
+ /* Same as 'rv3d->viewinv[1]' */
+ float axis_y[4] = {0.0f, 1.0f, 0.0f};
+ float quat_y[4], quat[4];
+ axis_angle_to_quat(quat_y, axis_y, M_PI_2);
+ mul_qt_qtqt(quat, viewquat, quat_y);
+ quat_to_eul(rot, quat);
+ break;
+ }
+ case 'Y': {
+ quat_to_eul(rot, viewquat);
+ rot[0] -= (float)M_PI_2;
+ break;
+ }
+ case 'Z': {
+ quat_to_eul(rot, viewquat);
+ break;
+ }
+ }
}
void ED_object_rotation_from_view(bContext *C, float rot[3], const char align_axis)
{
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- BLI_assert(align_axis >= 'X' && align_axis <= 'Z');
- if (rv3d) {
- float viewquat[4];
- copy_qt_qt(viewquat, rv3d->viewquat);
- viewquat[0] *= -1.0f;
- ED_object_rotation_from_quat(rot, viewquat, align_axis);
- }
- else {
- zero_v3(rot);
- }
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ BLI_assert(align_axis >= 'X' && align_axis <= 'Z');
+ if (rv3d) {
+ float viewquat[4];
+ copy_qt_qt(viewquat, rv3d->viewquat);
+ viewquat[0] *= -1.0f;
+ ED_object_rotation_from_quat(rot, viewquat, align_axis);
+ }
+ else {
+ zero_v3(rot);
+ }
}
void ED_object_base_init_transform(bContext *C, Base *base, const float loc[3], const float rot[3])
{
- Object *ob = base->object;
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob = base->object;
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
- if (!scene) return;
+ if (!scene)
+ return;
- if (loc)
- copy_v3_v3(ob->loc, loc);
+ if (loc)
+ copy_v3_v3(ob->loc, loc);
- if (rot)
- copy_v3_v3(ob->rot, rot);
+ if (rot)
+ copy_v3_v3(ob->rot, rot);
- BKE_object_where_is_calc(depsgraph, scene, ob);
+ BKE_object_where_is_calc(depsgraph, scene, ob);
}
/* Uses context to figure out transform for primitive.
* Returns standard diameter. */
float ED_object_new_primitive_matrix(
- bContext *C, Object *obedit,
- const float loc[3], const float rot[3], float primmat[4][4])
+ bContext *C, Object *obedit, const float loc[3], const float rot[3], float primmat[4][4])
{
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- float mat[3][3], rmat[3][3], cmat[3][3], imat[3][3];
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ float mat[3][3], rmat[3][3], cmat[3][3], imat[3][3];
- unit_m4(primmat);
+ unit_m4(primmat);
- eul_to_mat3(rmat, rot);
- invert_m3(rmat);
+ eul_to_mat3(rmat, rot);
+ invert_m3(rmat);
- /* inverse transform for initial rotation and object */
- copy_m3_m4(mat, obedit->obmat);
- mul_m3_m3m3(cmat, rmat, mat);
- invert_m3_m3(imat, cmat);
- copy_m4_m3(primmat, imat);
+ /* inverse transform for initial rotation and object */
+ copy_m3_m4(mat, obedit->obmat);
+ mul_m3_m3m3(cmat, rmat, mat);
+ invert_m3_m3(imat, cmat);
+ copy_m4_m3(primmat, imat);
- /* center */
- copy_v3_v3(primmat[3], loc);
- sub_v3_v3v3(primmat[3], primmat[3], obedit->obmat[3]);
- invert_m3_m3(imat, mat);
- mul_m3_v3(imat, primmat[3]);
+ /* center */
+ copy_v3_v3(primmat[3], loc);
+ sub_v3_v3v3(primmat[3], primmat[3], obedit->obmat[3]);
+ invert_m3_m3(imat, mat);
+ mul_m3_v3(imat, primmat[3]);
- {
- const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) : ED_scene_grid_scale(scene, NULL);
- return dia;
- }
+ {
+ const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) :
+ ED_scene_grid_scale(scene, NULL);
+ return dia;
+ }
- // return 1.0f;
+ // return 1.0f;
}
/********************* Add Object Operator ********************/
-static void view_align_update(struct Main *UNUSED(main), struct Scene *UNUSED(scene), struct PointerRNA *ptr)
+static void view_align_update(struct Main *UNUSED(main),
+ struct Scene *UNUSED(scene),
+ struct PointerRNA *ptr)
{
- RNA_struct_idprops_unset(ptr, "rotation");
+ RNA_struct_idprops_unset(ptr, "rotation");
}
void ED_object_add_unit_props_size(wmOperatorType *ot)
{
- RNA_def_float_distance(ot->srna, "size", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Size", "", 0.001, 100.00);
+ RNA_def_float_distance(
+ ot->srna, "size", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Size", "", 0.001, 100.00);
}
void ED_object_add_unit_props_radius(wmOperatorType *ot)
{
- RNA_def_float_distance(ot->srna, "radius", 1.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius", "", 0.001, 100.00);
+ RNA_def_float_distance(
+ ot->srna, "radius", 1.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius", "", 0.001, 100.00);
}
void ED_object_add_generic_props(wmOperatorType *ot, bool do_editmode)
{
- PropertyRNA *prop;
-
- /* note: this property gets hidden for add-camera operator */
- prop = RNA_def_boolean(ot->srna, "view_align", 0, "Align to View", "Align the new object to the view");
- RNA_def_property_update_runtime(prop, view_align_update);
-
- if (do_editmode) {
- prop = RNA_def_boolean(ot->srna, "enter_editmode", 0, "Enter Editmode",
- "Enter editmode when adding this object");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- }
-
- prop = RNA_def_float_vector_xyz(ot->srna, "location", 3, NULL, -OBJECT_ADD_SIZE_MAXF, OBJECT_ADD_SIZE_MAXF,
- "Location", "Location for the newly added object", -1000.0f, 1000.0f);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_float_rotation(ot->srna, "rotation", 3, NULL, -OBJECT_ADD_SIZE_MAXF, OBJECT_ADD_SIZE_MAXF,
- "Rotation", "Rotation for the newly added object",
- DEG2RADF(-360.0f), DEG2RADF(360.0f));
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* note: this property gets hidden for add-camera operator */
+ prop = RNA_def_boolean(
+ ot->srna, "view_align", 0, "Align to View", "Align the new object to the view");
+ RNA_def_property_update_runtime(prop, view_align_update);
+
+ if (do_editmode) {
+ prop = RNA_def_boolean(
+ ot->srna, "enter_editmode", 0, "Enter Editmode", "Enter editmode when adding this object");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ }
+
+ prop = RNA_def_float_vector_xyz(ot->srna,
+ "location",
+ 3,
+ NULL,
+ -OBJECT_ADD_SIZE_MAXF,
+ OBJECT_ADD_SIZE_MAXF,
+ "Location",
+ "Location for the newly added object",
+ -1000.0f,
+ 1000.0f);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_float_rotation(ot->srna,
+ "rotation",
+ 3,
+ NULL,
+ -OBJECT_ADD_SIZE_MAXF,
+ OBJECT_ADD_SIZE_MAXF,
+ "Rotation",
+ "Rotation for the newly added object",
+ DEG2RADF(-360.0f),
+ DEG2RADF(360.0f));
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
void ED_object_add_mesh_props(wmOperatorType *ot)
{
- RNA_def_boolean(ot->srna, "calc_uvs", true, "Generate UVs", "Generate a default UV map");
-}
-
-bool ED_object_add_generic_get_opts(
- bContext *C, wmOperator *op, const char view_align_axis,
- float loc[3], float rot[3],
- bool *enter_editmode, ushort *local_view_bits, bool *is_view_aligned)
-{
- PropertyRNA *prop;
-
- /* Switch to Edit mode? optional prop */
- if ((prop = RNA_struct_find_property(op->ptr, "enter_editmode"))) {
- bool _enter_editmode;
- if (!enter_editmode)
- enter_editmode = &_enter_editmode;
-
- if (RNA_property_is_set(op->ptr, prop) && enter_editmode)
- *enter_editmode = RNA_property_boolean_get(op->ptr, prop);
- else {
- *enter_editmode = (U.flag & USER_ADD_EDITMODE) != 0;
- RNA_property_boolean_set(op->ptr, prop, *enter_editmode);
- }
- }
-
- if (local_view_bits) {
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d && v3d->localvd) {
- *local_view_bits = v3d->local_view_uuid;
- }
- }
-
- /* Location! */
- {
- float _loc[3];
- if (!loc)
- loc = _loc;
-
- if (RNA_struct_property_is_set(op->ptr, "location")) {
- RNA_float_get_array(op->ptr, "location", loc);
- }
- else {
- ED_object_location_from_view(C, loc);
- RNA_float_set_array(op->ptr, "location", loc);
- }
- }
-
- /* Rotation! */
- {
- bool _is_view_aligned;
- float _rot[3];
- if (!is_view_aligned)
- is_view_aligned = &_is_view_aligned;
- if (!rot)
- rot = _rot;
-
- if (RNA_struct_property_is_set(op->ptr, "rotation"))
- *is_view_aligned = false;
- else if (RNA_struct_property_is_set(op->ptr, "view_align"))
- *is_view_aligned = RNA_boolean_get(op->ptr, "view_align");
- else {
- *is_view_aligned = (U.flag & USER_ADD_VIEWALIGNED) != 0;
- RNA_boolean_set(op->ptr, "view_align", *is_view_aligned);
- }
-
- if (*is_view_aligned) {
- ED_object_rotation_from_view(C, rot, view_align_axis);
- RNA_float_set_array(op->ptr, "rotation", rot);
- }
- else
- RNA_float_get_array(op->ptr, "rotation", rot);
- }
-
- return true;
+ RNA_def_boolean(ot->srna, "calc_uvs", true, "Generate UVs", "Generate a default UV map");
+}
+
+bool ED_object_add_generic_get_opts(bContext *C,
+ wmOperator *op,
+ const char view_align_axis,
+ float loc[3],
+ float rot[3],
+ bool *enter_editmode,
+ ushort *local_view_bits,
+ bool *is_view_aligned)
+{
+ PropertyRNA *prop;
+
+ /* Switch to Edit mode? optional prop */
+ if ((prop = RNA_struct_find_property(op->ptr, "enter_editmode"))) {
+ bool _enter_editmode;
+ if (!enter_editmode)
+ enter_editmode = &_enter_editmode;
+
+ if (RNA_property_is_set(op->ptr, prop) && enter_editmode)
+ *enter_editmode = RNA_property_boolean_get(op->ptr, prop);
+ else {
+ *enter_editmode = (U.flag & USER_ADD_EDITMODE) != 0;
+ RNA_property_boolean_set(op->ptr, prop, *enter_editmode);
+ }
+ }
+
+ if (local_view_bits) {
+ View3D *v3d = CTX_wm_view3d(C);
+ if (v3d && v3d->localvd) {
+ *local_view_bits = v3d->local_view_uuid;
+ }
+ }
+
+ /* Location! */
+ {
+ float _loc[3];
+ if (!loc)
+ loc = _loc;
+
+ if (RNA_struct_property_is_set(op->ptr, "location")) {
+ RNA_float_get_array(op->ptr, "location", loc);
+ }
+ else {
+ ED_object_location_from_view(C, loc);
+ RNA_float_set_array(op->ptr, "location", loc);
+ }
+ }
+
+ /* Rotation! */
+ {
+ bool _is_view_aligned;
+ float _rot[3];
+ if (!is_view_aligned)
+ is_view_aligned = &_is_view_aligned;
+ if (!rot)
+ rot = _rot;
+
+ if (RNA_struct_property_is_set(op->ptr, "rotation"))
+ *is_view_aligned = false;
+ else if (RNA_struct_property_is_set(op->ptr, "view_align"))
+ *is_view_aligned = RNA_boolean_get(op->ptr, "view_align");
+ else {
+ *is_view_aligned = (U.flag & USER_ADD_VIEWALIGNED) != 0;
+ RNA_boolean_set(op->ptr, "view_align", *is_view_aligned);
+ }
+
+ if (*is_view_aligned) {
+ ED_object_rotation_from_view(C, rot, view_align_axis);
+ RNA_float_set_array(op->ptr, "rotation", rot);
+ }
+ else
+ RNA_float_get_array(op->ptr, "rotation", rot);
+ }
+
+ return true;
}
/* For object add primitive operators.
* Do not call undo push in this function (users of this function have to). */
-Object *ED_object_add_type(
- bContext *C,
- int type, const char *name,
- const float loc[3], const float rot[3],
- bool enter_editmode, ushort local_view_bits)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob;
-
- /* for as long scene has editmode... */
- if (CTX_data_edit_object(C)) {
- ED_object_editmode_exit(C, EM_FREEDATA);
- }
-
- /* deselects all, sets active object */
- ob = BKE_object_add(bmain, scene, view_layer, type, name);
- BASACT(view_layer)->local_view_bits = local_view_bits;
- /* editor level activate, notifiers */
- ED_object_base_activate(C, view_layer->basact);
-
- /* more editor stuff */
- ED_object_base_init_transform(C, view_layer->basact, loc, rot);
-
- /* TODO(sergey): This is weird to manually tag objects for update, better to
- * use DEG_id_tag_update here perhaps.
- */
- DEG_id_type_tag(bmain, ID_OB);
- DEG_relations_tag_update(bmain);
- if (ob->data != NULL) {
- DEG_id_tag_update_ex(bmain, (ID *)ob->data, ID_RECALC_EDITORS);
- }
-
- if (enter_editmode) {
- ED_object_editmode_enter_ex(bmain, scene, ob, 0);
- }
-
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
-
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&scene->id, 0);
-
- return ob;
+Object *ED_object_add_type(bContext *C,
+ int type,
+ const char *name,
+ const float loc[3],
+ const float rot[3],
+ bool enter_editmode,
+ ushort local_view_bits)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob;
+
+ /* for as long scene has editmode... */
+ if (CTX_data_edit_object(C)) {
+ ED_object_editmode_exit(C, EM_FREEDATA);
+ }
+
+ /* deselects all, sets active object */
+ ob = BKE_object_add(bmain, scene, view_layer, type, name);
+ BASACT(view_layer)->local_view_bits = local_view_bits;
+ /* editor level activate, notifiers */
+ ED_object_base_activate(C, view_layer->basact);
+
+ /* more editor stuff */
+ ED_object_base_init_transform(C, view_layer->basact, loc, rot);
+
+ /* TODO(sergey): This is weird to manually tag objects for update, better to
+ * use DEG_id_tag_update here perhaps.
+ */
+ DEG_id_type_tag(bmain, ID_OB);
+ DEG_relations_tag_update(bmain);
+ if (ob->data != NULL) {
+ DEG_id_tag_update_ex(bmain, (ID *)ob->data, ID_RECALC_EDITORS);
+ }
+
+ if (enter_editmode) {
+ ED_object_editmode_enter_ex(bmain, scene, ob, 0);
+ }
+
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
+
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(&scene->id, 0);
+
+ return ob;
}
/* for object add operator */
static int object_add_exec(bContext *C, wmOperator *op)
{
- Object *ob;
- bool enter_editmode;
- ushort local_view_bits;
- float loc[3], rot[3], radius;
+ Object *ob;
+ bool enter_editmode;
+ ushort local_view_bits;
+ float loc[3], rot[3], radius;
- WM_operator_view3d_unit_defaults(C, op);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- radius = RNA_float_get(op->ptr, "radius");
- ob = ED_object_add_type(C, RNA_enum_get(op->ptr, "type"), NULL, loc, rot, enter_editmode, local_view_bits);
+ WM_operator_view3d_unit_defaults(C, op);
+ if (!ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ radius = RNA_float_get(op->ptr, "radius");
+ ob = ED_object_add_type(
+ C, RNA_enum_get(op->ptr, "type"), NULL, loc, rot, enter_editmode, local_view_bits);
- if (ob->type == OB_LATTICE) {
- /* lattice is a special case!
- * we never want to scale the obdata since that is the rest-state */
- copy_v3_fl(ob->scale, radius);
- }
- else {
- BKE_object_obdata_size_init(ob, radius);
- }
+ if (ob->type == OB_LATTICE) {
+ /* lattice is a special case!
+ * we never want to scale the obdata since that is the rest-state */
+ copy_v3_fl(ob->scale, radius);
+ }
+ else {
+ BKE_object_obdata_size_init(ob, radius);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Object";
- ot->description = "Add an object to the scene";
- ot->idname = "OBJECT_OT_add";
+ /* identifiers */
+ ot->name = "Add Object";
+ ot->description = "Add an object to the scene";
+ ot->idname = "OBJECT_OT_add";
- /* api callbacks */
- ot->exec = object_add_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = object_add_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ED_object_add_unit_props_radius(ot);
- PropertyRNA *prop = RNA_def_enum(ot->srna, "type", rna_enum_object_type_items, 0, "Type", "");
- RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);
+ /* properties */
+ ED_object_add_unit_props_radius(ot);
+ PropertyRNA *prop = RNA_def_enum(ot->srna, "type", rna_enum_object_type_items, 0, "Type", "");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_generic_props(ot, true);
}
/********************** Add Probe Operator **********************/
@@ -476,82 +510,87 @@ void OBJECT_OT_add(wmOperatorType *ot)
/* for object add operator */
static const char *get_lightprobe_defname(int type)
{
- switch (type) {
- case LIGHTPROBE_TYPE_GRID: return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "IrradianceVolume");
- case LIGHTPROBE_TYPE_PLANAR: return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "ReflectionPlane");
- case LIGHTPROBE_TYPE_CUBE: return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "ReflectionCubemap");
- default:
- return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "LightProbe");
- }
+ switch (type) {
+ case LIGHTPROBE_TYPE_GRID:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "IrradianceVolume");
+ case LIGHTPROBE_TYPE_PLANAR:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "ReflectionPlane");
+ case LIGHTPROBE_TYPE_CUBE:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "ReflectionCubemap");
+ default:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "LightProbe");
+ }
}
static int lightprobe_add_exec(bContext *C, wmOperator *op)
{
- Object *ob;
- LightProbe *probe;
- int type;
- bool enter_editmode;
- ushort local_view_bits;
- float loc[3], rot[3];
- float radius;
-
- WM_operator_view3d_unit_defaults(C, op);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- type = RNA_enum_get(op->ptr, "type");
- radius = RNA_float_get(op->ptr, "radius");
-
- ob = ED_object_add_type(C, OB_LIGHTPROBE, get_lightprobe_defname(type), loc, rot, false, local_view_bits);
- copy_v3_fl(ob->scale, radius);
-
- probe = (LightProbe *)ob->data;
- probe->type = type;
-
- switch (type) {
- case LIGHTPROBE_TYPE_GRID:
- probe->distinf = 0.3f;
- probe->falloff = 1.0f;
- probe->clipsta = 0.01f;
- break;
- case LIGHTPROBE_TYPE_PLANAR:
- probe->distinf = 0.1f;
- probe->falloff = 0.5f;
- probe->clipsta = 0.001f;
- ob->empty_drawsize = 0.5f;
- break;
- case LIGHTPROBE_TYPE_CUBE:
- probe->attenuation_type = LIGHTPROBE_SHAPE_ELIPSOID;
- break;
- default:
- BLI_assert(!"LightProbe type not configured.");
- break;
- }
-
- DEG_relations_tag_update(CTX_data_main(C));
-
- return OPERATOR_FINISHED;
+ Object *ob;
+ LightProbe *probe;
+ int type;
+ bool enter_editmode;
+ ushort local_view_bits;
+ float loc[3], rot[3];
+ float radius;
+
+ WM_operator_view3d_unit_defaults(C, op);
+ if (!ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ type = RNA_enum_get(op->ptr, "type");
+ radius = RNA_float_get(op->ptr, "radius");
+
+ ob = ED_object_add_type(
+ C, OB_LIGHTPROBE, get_lightprobe_defname(type), loc, rot, false, local_view_bits);
+ copy_v3_fl(ob->scale, radius);
+
+ probe = (LightProbe *)ob->data;
+ probe->type = type;
+
+ switch (type) {
+ case LIGHTPROBE_TYPE_GRID:
+ probe->distinf = 0.3f;
+ probe->falloff = 1.0f;
+ probe->clipsta = 0.01f;
+ break;
+ case LIGHTPROBE_TYPE_PLANAR:
+ probe->distinf = 0.1f;
+ probe->falloff = 0.5f;
+ probe->clipsta = 0.001f;
+ ob->empty_drawsize = 0.5f;
+ break;
+ case LIGHTPROBE_TYPE_CUBE:
+ probe->attenuation_type = LIGHTPROBE_SHAPE_ELIPSOID;
+ break;
+ default:
+ BLI_assert(!"LightProbe type not configured.");
+ break;
+ }
+
+ DEG_relations_tag_update(CTX_data_main(C));
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_lightprobe_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Light Probe";
- ot->description = "Add a light probe object";
- ot->idname = "OBJECT_OT_lightprobe_add";
+ /* identifiers */
+ ot->name = "Add Light Probe";
+ ot->description = "Add a light probe object";
+ ot->idname = "OBJECT_OT_lightprobe_add";
- /* api callbacks */
- ot->exec = lightprobe_add_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = lightprobe_add_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", lightprobe_type_items, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", lightprobe_type_items, 0, "Type", "");
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, true);
}
/********************* Add Effector Operator ********************/
@@ -559,759 +598,768 @@ void OBJECT_OT_lightprobe_add(wmOperatorType *ot)
/* for object add operator */
static int effector_add_exec(bContext *C, wmOperator *op)
{
- Object *ob;
- int type;
- bool enter_editmode;
- ushort local_view_bits;
- float loc[3], rot[3];
- float mat[4][4];
- float dia;
-
- WM_operator_view3d_unit_defaults(C, op);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- type = RNA_enum_get(op->ptr, "type");
- dia = RNA_float_get(op->ptr, "radius");
-
- if (type == PFIELD_GUIDE) {
- Curve *cu;
- const char *name = CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "CurveGuide");
- ob = ED_object_add_type(C, OB_CURVE, name, loc, rot, false, local_view_bits);
-
- cu = ob->data;
- cu->flag |= CU_PATH | CU_3D;
- ED_object_editmode_enter(C, 0);
- ED_object_new_primitive_matrix(C, ob, loc, rot, mat);
- BLI_addtail(&cu->editnurb->nurbs, ED_curve_add_nurbs_primitive(C, ob, mat, CU_NURBS | CU_PRIM_PATH, dia));
- if (!enter_editmode)
- ED_object_editmode_exit(C, EM_FREEDATA);
- }
- else {
- const char *name = CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Field");
- ob = ED_object_add_type(C, OB_EMPTY, name, loc, rot, false, local_view_bits);
- BKE_object_obdata_size_init(ob, dia);
- if (ELEM(type, PFIELD_WIND, PFIELD_VORTEX))
- ob->empty_drawtype = OB_SINGLE_ARROW;
- }
-
- ob->pd = BKE_partdeflect_new(type);
-
- DEG_relations_tag_update(CTX_data_main(C));
-
- return OPERATOR_FINISHED;
+ Object *ob;
+ int type;
+ bool enter_editmode;
+ ushort local_view_bits;
+ float loc[3], rot[3];
+ float mat[4][4];
+ float dia;
+
+ WM_operator_view3d_unit_defaults(C, op);
+ if (!ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ type = RNA_enum_get(op->ptr, "type");
+ dia = RNA_float_get(op->ptr, "radius");
+
+ if (type == PFIELD_GUIDE) {
+ Curve *cu;
+ const char *name = CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "CurveGuide");
+ ob = ED_object_add_type(C, OB_CURVE, name, loc, rot, false, local_view_bits);
+
+ cu = ob->data;
+ cu->flag |= CU_PATH | CU_3D;
+ ED_object_editmode_enter(C, 0);
+ ED_object_new_primitive_matrix(C, ob, loc, rot, mat);
+ BLI_addtail(&cu->editnurb->nurbs,
+ ED_curve_add_nurbs_primitive(C, ob, mat, CU_NURBS | CU_PRIM_PATH, dia));
+ if (!enter_editmode)
+ ED_object_editmode_exit(C, EM_FREEDATA);
+ }
+ else {
+ const char *name = CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Field");
+ ob = ED_object_add_type(C, OB_EMPTY, name, loc, rot, false, local_view_bits);
+ BKE_object_obdata_size_init(ob, dia);
+ if (ELEM(type, PFIELD_WIND, PFIELD_VORTEX))
+ ob->empty_drawtype = OB_SINGLE_ARROW;
+ }
+
+ ob->pd = BKE_partdeflect_new(type);
+
+ DEG_relations_tag_update(CTX_data_main(C));
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_effector_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Effector";
- ot->description = "Add an empty object with a physics effector to the scene";
- ot->idname = "OBJECT_OT_effector_add";
+ /* identifiers */
+ ot->name = "Add Effector";
+ ot->description = "Add an empty object with a physics effector to the scene";
+ ot->idname = "OBJECT_OT_effector_add";
- /* api callbacks */
- ot->exec = effector_add_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = effector_add_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", field_type_items, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", field_type_items, 0, "Type", "");
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, true);
}
/********************* Add Camera Operator ********************/
static int object_camera_add_exec(bContext *C, wmOperator *op)
{
- View3D *v3d = CTX_wm_view3d(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob;
- Camera *cam;
- bool enter_editmode;
- ushort local_view_bits;
- float loc[3], rot[3];
+ View3D *v3d = CTX_wm_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob;
+ Camera *cam;
+ bool enter_editmode;
+ ushort local_view_bits;
+ float loc[3], rot[3];
- /* force view align for cameras */
- RNA_boolean_set(op->ptr, "view_align", true);
+ /* force view align for cameras */
+ RNA_boolean_set(op->ptr, "view_align", true);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- ob = ED_object_add_type(C, OB_CAMERA, NULL, loc, rot, false, local_view_bits);
+ if (!ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ ob = ED_object_add_type(C, OB_CAMERA, NULL, loc, rot, false, local_view_bits);
- if (v3d) {
- if (v3d->camera == NULL)
- v3d->camera = ob;
- if (v3d->scenelock && scene->camera == NULL) {
- scene->camera = ob;
- }
- }
+ if (v3d) {
+ if (v3d->camera == NULL)
+ v3d->camera = ob;
+ if (v3d->scenelock && scene->camera == NULL) {
+ scene->camera = ob;
+ }
+ }
- cam = ob->data;
- cam->drawsize = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) : ED_scene_grid_scale(scene, NULL);
+ cam = ob->data;
+ cam->drawsize = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) : ED_scene_grid_scale(scene, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_camera_add(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Add Camera";
- ot->description = "Add a camera object to the scene";
- ot->idname = "OBJECT_OT_camera_add";
+ /* identifiers */
+ ot->name = "Add Camera";
+ ot->description = "Add a camera object to the scene";
+ ot->idname = "OBJECT_OT_camera_add";
- /* api callbacks */
- ot->exec = object_camera_add_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = object_camera_add_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ED_object_add_generic_props(ot, true);
+ ED_object_add_generic_props(ot, true);
- /* hide this for cameras, default */
- prop = RNA_struct_type_find_property(ot->srna, "view_align");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ /* hide this for cameras, default */
+ prop = RNA_struct_type_find_property(ot->srna, "view_align");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
-
/********************* Add Metaball Operator ********************/
static int object_metaball_add_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- bool newob = false;
- bool enter_editmode;
- ushort local_view_bits;
- float loc[3], rot[3];
- float mat[4][4];
- float dia;
+ Object *obedit = CTX_data_edit_object(C);
+ bool newob = false;
+ bool enter_editmode;
+ ushort local_view_bits;
+ float loc[3], rot[3];
+ float mat[4][4];
+ float dia;
- WM_operator_view3d_unit_defaults(C, op);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- if (obedit == NULL || obedit->type != OB_MBALL) {
- obedit = ED_object_add_type(C, OB_MBALL, NULL, loc, rot, true, local_view_bits);
- newob = true;
- }
- else {
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
- }
+ WM_operator_view3d_unit_defaults(C, op);
+ if (!ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ if (obedit == NULL || obedit->type != OB_MBALL) {
+ obedit = ED_object_add_type(C, OB_MBALL, NULL, loc, rot, true, local_view_bits);
+ newob = true;
+ }
+ else {
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ }
- ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
- dia = RNA_float_get(op->ptr, "radius");
+ ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
+ dia = RNA_float_get(op->ptr, "radius");
- ED_mball_add_primitive(C, obedit, mat, dia, RNA_enum_get(op->ptr, "type"));
+ ED_mball_add_primitive(C, obedit, mat, dia, RNA_enum_get(op->ptr, "type"));
- /* userdef */
- if (newob && !enter_editmode) {
- ED_object_editmode_exit(C, EM_FREEDATA);
- }
+ /* userdef */
+ if (newob && !enter_editmode) {
+ ED_object_editmode_exit(C, EM_FREEDATA);
+ }
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_metaball_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Metaball";
- ot->description = "Add an metaball object to the scene";
- ot->idname = "OBJECT_OT_metaball_add";
+ /* identifiers */
+ ot->name = "Add Metaball";
+ ot->description = "Add an metaball object to the scene";
+ ot->idname = "OBJECT_OT_metaball_add";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_metaball_add_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_metaball_add_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_metaelem_type_items, 0, "Primitive", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_metaelem_type_items, 0, "Primitive", "");
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, true);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, true);
}
/********************* Add Text Operator ********************/
static int object_add_text_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- bool enter_editmode;
- ushort local_view_bits;
- float loc[3], rot[3];
+ Object *obedit = CTX_data_edit_object(C);
+ bool enter_editmode;
+ ushort local_view_bits;
+ float loc[3], rot[3];
- WM_operator_view3d_unit_defaults(C, op);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- if (obedit && obedit->type == OB_FONT)
- return OPERATOR_CANCELLED;
+ WM_operator_view3d_unit_defaults(C, op);
+ if (!ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ if (obedit && obedit->type == OB_FONT)
+ return OPERATOR_CANCELLED;
- obedit = ED_object_add_type(C, OB_FONT, NULL, loc, rot, enter_editmode, local_view_bits);
- BKE_object_obdata_size_init(obedit, RNA_float_get(op->ptr, "radius"));
+ obedit = ED_object_add_type(C, OB_FONT, NULL, loc, rot, enter_editmode, local_view_bits);
+ BKE_object_obdata_size_init(obedit, RNA_float_get(op->ptr, "radius"));
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_text_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Text";
- ot->description = "Add a text object to the scene";
- ot->idname = "OBJECT_OT_text_add";
+ /* identifiers */
+ ot->name = "Add Text";
+ ot->description = "Add a text object to the scene";
+ ot->idname = "OBJECT_OT_text_add";
- /* api callbacks */
- ot->exec = object_add_text_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = object_add_text_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, true);
+ /* properties */
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, true);
}
/********************* Add Armature Operator ********************/
static int object_armature_add_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- bool newob = false;
- bool enter_editmode;
- ushort local_view_bits;
- float loc[3], rot[3], dia;
- bool view_aligned = rv3d && (U.flag & USER_ADD_VIEWALIGNED);
-
- WM_operator_view3d_unit_defaults(C, op);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- if ((obedit == NULL) || (obedit->type != OB_ARMATURE)) {
- obedit = ED_object_add_type(C, OB_ARMATURE, NULL, loc, rot, true, local_view_bits);
- ED_object_editmode_enter(C, 0);
- newob = true;
- }
- else {
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
- }
-
- if (obedit == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Cannot create editmode armature");
- return OPERATOR_CANCELLED;
- }
-
- dia = RNA_float_get(op->ptr, "radius");
- ED_armature_ebone_add_primitive(obedit, dia, view_aligned);
-
- /* userdef */
- if (newob && !enter_editmode)
- ED_object_editmode_exit(C, EM_FREEDATA);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
-
- return OPERATOR_FINISHED;
+ Object *obedit = CTX_data_edit_object(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ bool newob = false;
+ bool enter_editmode;
+ ushort local_view_bits;
+ float loc[3], rot[3], dia;
+ bool view_aligned = rv3d && (U.flag & USER_ADD_VIEWALIGNED);
+
+ WM_operator_view3d_unit_defaults(C, op);
+ if (!ED_object_add_generic_get_opts(
+ C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ if ((obedit == NULL) || (obedit->type != OB_ARMATURE)) {
+ obedit = ED_object_add_type(C, OB_ARMATURE, NULL, loc, rot, true, local_view_bits);
+ ED_object_editmode_enter(C, 0);
+ newob = true;
+ }
+ else {
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ }
+
+ if (obedit == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot create editmode armature");
+ return OPERATOR_CANCELLED;
+ }
+
+ dia = RNA_float_get(op->ptr, "radius");
+ ED_armature_ebone_add_primitive(obedit, dia, view_aligned);
+
+ /* userdef */
+ if (newob && !enter_editmode)
+ ED_object_editmode_exit(C, EM_FREEDATA);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_armature_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Armature";
- ot->description = "Add an armature object to the scene";
- ot->idname = "OBJECT_OT_armature_add";
+ /* identifiers */
+ ot->name = "Add Armature";
+ ot->description = "Add an armature object to the scene";
+ ot->idname = "OBJECT_OT_armature_add";
- /* api callbacks */
- ot->exec = object_armature_add_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = object_armature_add_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, true);
+ /* properties */
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, true);
}
/********************* Add Empty Operator ********************/
static int object_empty_add_exec(bContext *C, wmOperator *op)
{
- Object *ob;
- int type = RNA_enum_get(op->ptr, "type");
- ushort local_view_bits;
- float loc[3], rot[3];
+ Object *ob;
+ int type = RNA_enum_get(op->ptr, "type");
+ ushort local_view_bits;
+ float loc[3], rot[3];
- WM_operator_view3d_unit_defaults(C, op);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- ob = ED_object_add_type(C, OB_EMPTY, NULL, loc, rot, false, local_view_bits);
+ WM_operator_view3d_unit_defaults(C, op);
+ if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ ob = ED_object_add_type(C, OB_EMPTY, NULL, loc, rot, false, local_view_bits);
- BKE_object_empty_draw_type_set(ob, type);
- BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius"));
+ BKE_object_empty_draw_type_set(ob, type);
+ BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius"));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_empty_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Empty";
- ot->description = "Add an empty object to the scene";
- ot->idname = "OBJECT_OT_empty_add";
+ /* identifiers */
+ ot->name = "Add Empty";
+ ot->description = "Add an empty object to the scene";
+ ot->idname = "OBJECT_OT_empty_add";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_empty_add_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_empty_add_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_empty_drawtype_items, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_empty_drawtype_items, 0, "Type", "");
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, false);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, false);
}
static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- Image *ima = NULL;
+ Image *ima = NULL;
- ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
- if (!ima) {
- return OPERATOR_CANCELLED;
- }
- /* handled below */
- id_us_min((ID *)ima);
+ ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
+ if (!ima) {
+ return OPERATOR_CANCELLED;
+ }
+ /* handled below */
+ id_us_min((ID *)ima);
- Object *ob = NULL;
- Object *ob_cursor = ED_view3d_give_object_under_cursor(C, event->mval);
+ Object *ob = NULL;
+ Object *ob_cursor = ED_view3d_give_object_under_cursor(C, event->mval);
- /* either change empty under cursor or create a new empty */
- if (ob_cursor && ob_cursor->type == OB_EMPTY) {
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
- DEG_id_tag_update((ID *)ob_cursor, ID_RECALC_TRANSFORM);
- ob = ob_cursor;
- }
- else {
- /* add new empty */
- ushort local_view_bits;
- float rot[3];
+ /* either change empty under cursor or create a new empty */
+ if (ob_cursor && ob_cursor->type == OB_EMPTY) {
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+ DEG_id_tag_update((ID *)ob_cursor, ID_RECALC_TRANSFORM);
+ ob = ob_cursor;
+ }
+ else {
+ /* add new empty */
+ ushort local_view_bits;
+ float rot[3];
- if (!ED_object_add_generic_get_opts(C, op, 'Z', NULL, rot, NULL, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- ob = ED_object_add_type(C, OB_EMPTY, NULL, NULL, rot, false, local_view_bits);
+ if (!ED_object_add_generic_get_opts(C, op, 'Z', NULL, rot, NULL, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ ob = ED_object_add_type(C, OB_EMPTY, NULL, NULL, rot, false, local_view_bits);
- ED_object_location_from_view(C, ob->loc);
- ED_view3d_cursor3d_position(C, event->mval, false, ob->loc);
- ED_object_rotation_from_view(C, ob->rot, 'Z');
- ob->empty_drawsize = 5.0f;
- }
+ ED_object_location_from_view(C, ob->loc);
+ ED_view3d_cursor3d_position(C, event->mval, false, ob->loc);
+ ED_object_rotation_from_view(C, ob->rot, 'Z');
+ ob->empty_drawsize = 5.0f;
+ }
- BKE_object_empty_draw_type_set(ob, OB_EMPTY_IMAGE);
+ BKE_object_empty_draw_type_set(ob, OB_EMPTY_IMAGE);
- id_us_min(ob->data);
- ob->data = ima;
- id_us_plus(ob->data);
+ id_us_min(ob->data);
+ ob->data = ima;
+ id_us_plus(ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_drop_named_image(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Add Empty Image/Drop Image To Empty";
- ot->description = "Add an empty image type to scene with data";
- ot->idname = "OBJECT_OT_drop_named_image";
+ /* identifiers */
+ ot->name = "Add Empty Image/Drop Image To Empty";
+ ot->description = "Add an empty image type to scene with data";
+ ot->idname = "OBJECT_OT_drop_named_image";
- /* api callbacks */
- ot->invoke = empty_drop_named_image_invoke;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->invoke = empty_drop_named_image_invoke;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- prop = RNA_def_string(ot->srna, "filepath", NULL, FILE_MAX, "Filepath", "Path to image file");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- RNA_def_boolean(ot->srna, "relative_path", true, "Relative Path", "Select the file relative to the blend file");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Image name to assign");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- ED_object_add_generic_props(ot, false);
+ /* properties */
+ prop = RNA_def_string(ot->srna, "filepath", NULL, FILE_MAX, "Filepath", "Path to image file");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ RNA_def_boolean(ot->srna,
+ "relative_path",
+ true,
+ "Relative Path",
+ "Select the file relative to the blend file");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Image name to assign");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ ED_object_add_generic_props(ot, false);
}
/********************* Add Gpencil Operator ********************/
static bool object_gpencil_add_poll(bContext *C)
{
- Scene *scene = CTX_data_scene(C);
- Object *obact = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *obact = CTX_data_active_object(C);
- if ((scene == NULL) || (ID_IS_LINKED(scene))) {
- return false;
- }
+ if ((scene == NULL) || (ID_IS_LINKED(scene))) {
+ return false;
+ }
- if (obact && obact->type == OB_GPENCIL) {
- if (obact->mode != OB_MODE_OBJECT) {
- return false;
- }
- }
+ if (obact && obact->type == OB_GPENCIL) {
+ if (obact->mode != OB_MODE_OBJECT) {
+ return false;
+ }
+ }
- return true;
+ return true;
}
static int object_gpencil_add_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
- bGPdata *gpd = (ob && (ob->type == OB_GPENCIL)) ? ob->data : NULL;
-
- const int type = RNA_enum_get(op->ptr, "type");
-
- ushort local_view_bits;
- float loc[3], rot[3];
- bool newob = false;
-
- /* Note: We use 'Y' here (not 'Z'), as */
- WM_operator_view3d_unit_defaults(C, op);
- if (!ED_object_add_generic_get_opts(C, op, 'Y', loc, rot, NULL, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- /* add new object if not currently editing a GP object,
- * or if "empty" was chosen (i.e. user wants a blank GP canvas)
- */
- if ((gpd == NULL) || (GPENCIL_ANY_MODE(gpd) == false) || (type == GP_EMPTY)) {
- const char *ob_name = NULL;
- switch (type) {
- case GP_MONKEY:
- {
- ob_name = "Suzanne";
- break;
- }
- case GP_STROKE:
- {
- ob_name = "Stroke";
- break;
- }
- default:
- {
- break;
- }
- }
-
- ob = ED_object_add_type(C, OB_GPENCIL, ob_name, loc, rot, true, local_view_bits);
- gpd = ob->data;
- newob = true;
- }
- else {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_ADDED, NULL);
- }
-
- /* create relevant geometry */
- switch (type) {
- case GP_STROKE:
- {
- float radius = RNA_float_get(op->ptr, "radius");
- float mat[4][4];
-
- ED_object_new_primitive_matrix(C, ob, loc, rot, mat);
- mul_v3_fl(mat[0], radius);
- mul_v3_fl(mat[1], radius);
- mul_v3_fl(mat[2], radius);
-
- ED_gpencil_create_stroke(C, ob, mat);
- break;
- }
- case GP_MONKEY:
- {
- float radius = RNA_float_get(op->ptr, "radius");
- float mat[4][4];
-
- ED_object_new_primitive_matrix(C, ob, loc, rot, mat);
- mul_v3_fl(mat[0], radius);
- mul_v3_fl(mat[1], radius);
- mul_v3_fl(mat[2], radius);
-
- ED_gpencil_create_monkey(C, ob, mat);
- break;
- }
- case GP_EMPTY:
- /* do nothing */
- break;
-
- default:
- BKE_report(op->reports, RPT_WARNING, "Not implemented");
- break;
- }
-
- /* if this is a new object, initialise default stuff (colors, etc.) */
- if (newob) {
- /* set default viewport color to black */
- copy_v3_fl(ob->color, 0.0f);
-
- ED_gpencil_add_defaults(C, ob);
- }
-
- return OPERATOR_FINISHED;
+ Object *ob = CTX_data_active_object(C);
+ bGPdata *gpd = (ob && (ob->type == OB_GPENCIL)) ? ob->data : NULL;
+
+ const int type = RNA_enum_get(op->ptr, "type");
+
+ ushort local_view_bits;
+ float loc[3], rot[3];
+ bool newob = false;
+
+ /* Note: We use 'Y' here (not 'Z'), as */
+ WM_operator_view3d_unit_defaults(C, op);
+ if (!ED_object_add_generic_get_opts(C, op, 'Y', loc, rot, NULL, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ /* add new object if not currently editing a GP object,
+ * or if "empty" was chosen (i.e. user wants a blank GP canvas)
+ */
+ if ((gpd == NULL) || (GPENCIL_ANY_MODE(gpd) == false) || (type == GP_EMPTY)) {
+ const char *ob_name = NULL;
+ switch (type) {
+ case GP_MONKEY: {
+ ob_name = "Suzanne";
+ break;
+ }
+ case GP_STROKE: {
+ ob_name = "Stroke";
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+
+ ob = ED_object_add_type(C, OB_GPENCIL, ob_name, loc, rot, true, local_view_bits);
+ gpd = ob->data;
+ newob = true;
+ }
+ else {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_ADDED, NULL);
+ }
+
+ /* create relevant geometry */
+ switch (type) {
+ case GP_STROKE: {
+ float radius = RNA_float_get(op->ptr, "radius");
+ float mat[4][4];
+
+ ED_object_new_primitive_matrix(C, ob, loc, rot, mat);
+ mul_v3_fl(mat[0], radius);
+ mul_v3_fl(mat[1], radius);
+ mul_v3_fl(mat[2], radius);
+
+ ED_gpencil_create_stroke(C, ob, mat);
+ break;
+ }
+ case GP_MONKEY: {
+ float radius = RNA_float_get(op->ptr, "radius");
+ float mat[4][4];
+
+ ED_object_new_primitive_matrix(C, ob, loc, rot, mat);
+ mul_v3_fl(mat[0], radius);
+ mul_v3_fl(mat[1], radius);
+ mul_v3_fl(mat[2], radius);
+
+ ED_gpencil_create_monkey(C, ob, mat);
+ break;
+ }
+ case GP_EMPTY:
+ /* do nothing */
+ break;
+
+ default:
+ BKE_report(op->reports, RPT_WARNING, "Not implemented");
+ break;
+ }
+
+ /* if this is a new object, initialise default stuff (colors, etc.) */
+ if (newob) {
+ /* set default viewport color to black */
+ copy_v3_fl(ob->color, 0.0f);
+
+ ED_gpencil_add_defaults(C, ob);
+ }
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_gpencil_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Grease Pencil";
- ot->description = "Add a Grease Pencil object to the scene";
- ot->idname = "OBJECT_OT_gpencil_add";
+ /* identifiers */
+ ot->name = "Add Grease Pencil";
+ ot->description = "Add a Grease Pencil object to the scene";
+ ot->idname = "OBJECT_OT_gpencil_add";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_gpencil_add_exec;
- ot->poll = object_gpencil_add_poll;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_gpencil_add_exec;
+ ot->poll = object_gpencil_add_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, false);
+ /* properties */
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, false);
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_gpencil_type_items, 0, "Type", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_gpencil_type_items, 0, "Type", "");
}
/********************* Add Light Operator ********************/
static const char *get_light_defname(int type)
{
- switch (type) {
- case LA_LOCAL: return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Point");
- case LA_SUN: return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Sun");
- case LA_SPOT: return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Spot");
- case LA_AREA: return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Area");
- default:
- return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Light");
- }
+ switch (type) {
+ case LA_LOCAL:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Point");
+ case LA_SUN:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Sun");
+ case LA_SPOT:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Spot");
+ case LA_AREA:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Area");
+ default:
+ return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Light");
+ }
}
static int object_light_add_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob;
- Light *la;
- int type = RNA_enum_get(op->ptr, "type");
- ushort local_view_bits;
- float loc[3], rot[3];
-
- WM_operator_view3d_unit_defaults(C, op);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- ob = ED_object_add_type(C, OB_LAMP, get_light_defname(type), loc, rot, false, local_view_bits);
-
- float size = RNA_float_get(op->ptr, "radius");
- /* Better defaults for light size. */
- switch (type) {
- case LA_LOCAL:
- case LA_SPOT:
- break;
- case LA_AREA:
- size *= 4.0f;
- break;
- default:
- size *= 0.5f;
- break;
- }
- BKE_object_obdata_size_init(ob, size);
-
- la = (Light *)ob->data;
- la->type = type;
-
- if (BKE_scene_uses_cycles(scene)) {
- ED_node_shader_default(C, &la->id);
- la->use_nodes = true;
- }
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Object *ob;
+ Light *la;
+ int type = RNA_enum_get(op->ptr, "type");
+ ushort local_view_bits;
+ float loc[3], rot[3];
+
+ WM_operator_view3d_unit_defaults(C, op);
+ if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ ob = ED_object_add_type(C, OB_LAMP, get_light_defname(type), loc, rot, false, local_view_bits);
+
+ float size = RNA_float_get(op->ptr, "radius");
+ /* Better defaults for light size. */
+ switch (type) {
+ case LA_LOCAL:
+ case LA_SPOT:
+ break;
+ case LA_AREA:
+ size *= 4.0f;
+ break;
+ default:
+ size *= 0.5f;
+ break;
+ }
+ BKE_object_obdata_size_init(ob, size);
+
+ la = (Light *)ob->data;
+ la->type = type;
+
+ if (BKE_scene_uses_cycles(scene)) {
+ ED_node_shader_default(C, &la->id);
+ la->use_nodes = true;
+ }
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_light_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Light";
- ot->description = "Add a light object to the scene";
- ot->idname = "OBJECT_OT_light_add";
+ /* identifiers */
+ ot->name = "Add Light";
+ ot->description = "Add a light object to the scene";
+ ot->idname = "OBJECT_OT_light_add";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_light_add_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_light_add_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_light_type_items, 0, "Type", "");
- RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_LIGHT);
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_light_type_items, 0, "Type", "");
+ RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_LIGHT);
- ED_object_add_unit_props_radius(ot);
- ED_object_add_generic_props(ot, false);
+ ED_object_add_unit_props_radius(ot);
+ ED_object_add_generic_props(ot, false);
}
/********************* Add Collection Instance Operator ********************/
static int collection_instance_add_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Collection *collection;
- ushort local_view_bits;
- float loc[3], rot[3];
-
- if (RNA_struct_property_is_set(op->ptr, "name")) {
- char name[MAX_ID_NAME - 2];
-
- RNA_string_get(op->ptr, "name", name);
- collection = (Collection *)BKE_libblock_find_name(bmain, ID_GR, name);
-
- if (0 == RNA_struct_property_is_set(op->ptr, "location")) {
- const wmEvent *event = CTX_wm_window(C)->eventstate;
- ARegion *ar = CTX_wm_region(C);
- const int mval[2] = {event->x - ar->winrct.xmin,
- event->y - ar->winrct.ymin};
- ED_object_location_from_view(C, loc);
- ED_view3d_cursor3d_position(C, mval, false, loc);
- RNA_float_set_array(op->ptr, "location", loc);
- }
- }
- else
- collection = BLI_findlink(&CTX_data_main(C)->collections, RNA_enum_get(op->ptr, "collection"));
-
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- if (collection) {
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- /* Avoid dependency cycles. */
- LayerCollection *active_lc = BKE_layer_collection_get_active(view_layer);
- while (BKE_collection_find_cycle(active_lc->collection, collection)) {
- active_lc = BKE_layer_collection_activate_parent(view_layer, active_lc);
- }
-
- Object *ob = ED_object_add_type(C, OB_EMPTY, collection->id.name + 2, loc, rot, false, local_view_bits);
- ob->instance_collection = collection;
- ob->transflag |= OB_DUPLICOLLECTION;
- id_us_plus(&collection->id);
-
- /* works without this except if you try render right after, see: 22027 */
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
-
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_CANCELLED;
+ Main *bmain = CTX_data_main(C);
+ Collection *collection;
+ ushort local_view_bits;
+ float loc[3], rot[3];
+
+ if (RNA_struct_property_is_set(op->ptr, "name")) {
+ char name[MAX_ID_NAME - 2];
+
+ RNA_string_get(op->ptr, "name", name);
+ collection = (Collection *)BKE_libblock_find_name(bmain, ID_GR, name);
+
+ if (0 == RNA_struct_property_is_set(op->ptr, "location")) {
+ const wmEvent *event = CTX_wm_window(C)->eventstate;
+ ARegion *ar = CTX_wm_region(C);
+ const int mval[2] = {event->x - ar->winrct.xmin, event->y - ar->winrct.ymin};
+ ED_object_location_from_view(C, loc);
+ ED_view3d_cursor3d_position(C, mval, false, loc);
+ RNA_float_set_array(op->ptr, "location", loc);
+ }
+ }
+ else
+ collection = BLI_findlink(&CTX_data_main(C)->collections, RNA_enum_get(op->ptr, "collection"));
+
+ if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ if (collection) {
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ /* Avoid dependency cycles. */
+ LayerCollection *active_lc = BKE_layer_collection_get_active(view_layer);
+ while (BKE_collection_find_cycle(active_lc->collection, collection)) {
+ active_lc = BKE_layer_collection_activate_parent(view_layer, active_lc);
+ }
+
+ Object *ob = ED_object_add_type(
+ C, OB_EMPTY, collection->id.name + 2, loc, rot, false, local_view_bits);
+ ob->instance_collection = collection;
+ ob->transflag |= OB_DUPLICOLLECTION;
+ id_us_plus(&collection->id);
+
+ /* works without this except if you try render right after, see: 22027 */
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
}
/* only used as menu */
void OBJECT_OT_collection_instance_add(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Add Collection Instance";
- ot->description = "Add a collection instance";
- ot->idname = "OBJECT_OT_collection_instance_add";
+ /* identifiers */
+ ot->name = "Add Collection Instance";
+ ot->description = "Add a collection instance";
+ ot->idname = "OBJECT_OT_collection_instance_add";
- /* api callbacks */
- ot->invoke = WM_enum_search_invoke;
- ot->exec = collection_instance_add_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->invoke = WM_enum_search_invoke;
+ ot->exec = collection_instance_add_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_string(ot->srna, "name", "Collection", MAX_ID_NAME - 2, "Name", "Collection name to add");
- prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "");
- RNA_def_enum_funcs(prop, RNA_collection_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
- ED_object_add_generic_props(ot, false);
+ /* properties */
+ RNA_def_string(
+ ot->srna, "name", "Collection", MAX_ID_NAME - 2, "Name", "Collection name to add");
+ prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "");
+ RNA_def_enum_funcs(prop, RNA_collection_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
+ ED_object_add_generic_props(ot, false);
}
/********************* Add Speaker Operator ********************/
static int object_speaker_add_exec(bContext *C, wmOperator *op)
{
- Object *ob;
- ushort local_view_bits;
- float loc[3], rot[3];
- Scene *scene = CTX_data_scene(C);
+ Object *ob;
+ ushort local_view_bits;
+ float loc[3], rot[3];
+ Scene *scene = CTX_data_scene(C);
- if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
- return OPERATOR_CANCELLED;
- }
- ob = ED_object_add_type(C, OB_SPEAKER, NULL, loc, rot, false, local_view_bits);
+ if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ ob = ED_object_add_type(C, OB_SPEAKER, NULL, loc, rot, false, local_view_bits);
- /* to make it easier to start using this immediately in NLA, a default sound clip is created
- * ready to be moved around to retime the sound and/or make new sound clips
- */
- {
- /* create new data for NLA hierarchy */
- AnimData *adt = BKE_animdata_add_id(&ob->id);
- NlaTrack *nlt = BKE_nlatrack_add(adt, NULL);
- NlaStrip *strip = BKE_nla_add_soundstrip(scene, ob->data);
- strip->start = CFRA;
- strip->end += strip->start;
+ /* to make it easier to start using this immediately in NLA, a default sound clip is created
+ * ready to be moved around to retime the sound and/or make new sound clips
+ */
+ {
+ /* create new data for NLA hierarchy */
+ AnimData *adt = BKE_animdata_add_id(&ob->id);
+ NlaTrack *nlt = BKE_nlatrack_add(adt, NULL);
+ NlaStrip *strip = BKE_nla_add_soundstrip(scene, ob->data);
+ strip->start = CFRA;
+ strip->end += strip->start;
- /* hook them up */
- BKE_nlatrack_add_strip(nlt, strip);
+ /* hook them up */
+ BKE_nlatrack_add_strip(nlt, strip);
- /* auto-name the strip, and give the track an interesting name */
- BLI_strncpy(nlt->name, DATA_("SoundTrack"), sizeof(nlt->name));
- BKE_nlastrip_validate_name(adt, strip);
+ /* auto-name the strip, and give the track an interesting name */
+ BLI_strncpy(nlt->name, DATA_("SoundTrack"), sizeof(nlt->name));
+ BKE_nlastrip_validate_name(adt, strip);
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
- }
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_speaker_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Speaker";
- ot->description = "Add a speaker object to the scene";
- ot->idname = "OBJECT_OT_speaker_add";
+ /* identifiers */
+ ot->name = "Add Speaker";
+ ot->description = "Add a speaker object to the scene";
+ ot->idname = "OBJECT_OT_speaker_add";
- /* api callbacks */
- ot->exec = object_speaker_add_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = object_speaker_add_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ED_object_add_generic_props(ot, true);
+ ED_object_add_generic_props(ot, true);
}
/**************************** Delete Object *************************/
@@ -1320,143 +1368,153 @@ void OBJECT_OT_speaker_add(wmOperatorType *ot)
/* note: now unlinks constraints as well */
void ED_object_base_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
{
- if (BKE_library_ID_is_indirectly_used(bmain, ob) &&
- ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0)
- {
- /* We cannot delete indirectly used object... */
- printf("WARNING, undeletable object '%s', should have been catched before reaching this function!",
- ob->id.name + 2);
- return;
- }
+ if (BKE_library_ID_is_indirectly_used(bmain, ob) && ID_REAL_USERS(ob) <= 1 &&
+ ID_EXTRA_USERS(ob) == 0) {
+ /* We cannot delete indirectly used object... */
+ printf(
+ "WARNING, undeletable object '%s', should have been catched before reaching this "
+ "function!",
+ ob->id.name + 2);
+ return;
+ }
- DEG_id_tag_update_ex(bmain, &ob->id, ID_RECALC_BASE_FLAGS);
+ DEG_id_tag_update_ex(bmain, &ob->id, ID_RECALC_BASE_FLAGS);
- BKE_scene_collections_object_remove(bmain, scene, ob, true);
+ BKE_scene_collections_object_remove(bmain, scene, ob, true);
}
static int object_delete_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- wmWindowManager *wm = CTX_wm_manager(C);
- wmWindow *win;
- const bool use_global = RNA_boolean_get(op->ptr, "use_global");
- uint changed_count = 0;
-
- if (CTX_data_edit_object(C))
- return OPERATOR_CANCELLED;
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- const bool is_indirectly_used = BKE_library_ID_is_indirectly_used(bmain, ob);
- if (ob->id.tag & LIB_TAG_INDIRECT) {
- /* Can this case ever happen? */
- BKE_reportf(op->reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", ob->id.name + 2);
- continue;
- }
- else if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) {
- BKE_reportf(op->reports, RPT_WARNING,
- "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
- ob->id.name + 2, scene->id.name + 2);
- continue;
- }
-
- /* if grease pencil object, set cache as dirty */
- if (ob->type == OB_GPENCIL) {
- bGPdata *gpd = (bGPdata *)ob->data;
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- }
-
- /* This is sort of a quick hack to address T51243 - Proper thing to do here would be to nuke most of all this
- * custom scene/object/base handling, and use generic lib remap/query for that.
- * But this is for later (aka 2.8, once layers & co are settled and working).
- */
- if (use_global && ob->id.lib == NULL) {
- /* We want to nuke the object, let's nuke it the easy way (not for linked data though)... */
- BKE_id_delete(bmain, &ob->id);
- changed_count += 1;
- continue;
- }
-
- /* remove from Grease Pencil parent */
- /* XXX This is likely not correct? Will also remove parent from grease pencil from other scenes,
- * even when use_global is false... */
- for (bGPdata *gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- if (gpl->parent != NULL) {
- if (gpl->parent == ob) {
- gpl->parent = NULL;
- }
- }
- }
- }
-
- /* remove from current scene only */
- ED_object_base_free_and_unlink(bmain, scene, ob);
- changed_count += 1;
-
- if (use_global) {
- Scene *scene_iter;
- for (scene_iter = bmain->scenes.first; scene_iter; scene_iter = scene_iter->id.next) {
- if (scene_iter != scene && !ID_IS_LINKED(scene_iter)) {
- if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) {
- BKE_reportf(op->reports, RPT_WARNING,
- "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
- ob->id.name + 2, scene_iter->id.name + 2);
- break;
- }
- ED_object_base_free_and_unlink(bmain, scene_iter, ob);
- }
- }
- }
- /* end global */
- }
- CTX_DATA_END;
-
- BKE_reportf(op->reports, RPT_INFO, "Deleted %u object(s)", changed_count);
-
- if (changed_count == 0) {
- return OPERATOR_CANCELLED;
- }
-
- /* delete has to handle all open scenes */
- BKE_main_id_tag_listbase(&bmain->scenes, LIB_TAG_DOIT, true);
- for (win = wm->windows.first; win; win = win->next) {
- scene = WM_window_get_active_scene(win);
-
- if (scene->id.tag & LIB_TAG_DOIT) {
- scene->id.tag &= ~LIB_TAG_DOIT;
-
- DEG_relations_tag_update(bmain);
-
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
- }
- }
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win;
+ const bool use_global = RNA_boolean_get(op->ptr, "use_global");
+ uint changed_count = 0;
+
+ if (CTX_data_edit_object(C))
+ return OPERATOR_CANCELLED;
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ const bool is_indirectly_used = BKE_library_ID_is_indirectly_used(bmain, ob);
+ if (ob->id.tag & LIB_TAG_INDIRECT) {
+ /* Can this case ever happen? */
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "Cannot delete indirectly linked object '%s'",
+ ob->id.name + 2);
+ continue;
+ }
+ else if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) {
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "Cannot delete object '%s' from scene '%s', indirectly used objects need at "
+ "least one user",
+ ob->id.name + 2,
+ scene->id.name + 2);
+ continue;
+ }
+
+ /* if grease pencil object, set cache as dirty */
+ if (ob->type == OB_GPENCIL) {
+ bGPdata *gpd = (bGPdata *)ob->data;
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ }
+
+ /* This is sort of a quick hack to address T51243 - Proper thing to do here would be to nuke most of all this
+ * custom scene/object/base handling, and use generic lib remap/query for that.
+ * But this is for later (aka 2.8, once layers & co are settled and working).
+ */
+ if (use_global && ob->id.lib == NULL) {
+ /* We want to nuke the object, let's nuke it the easy way (not for linked data though)... */
+ BKE_id_delete(bmain, &ob->id);
+ changed_count += 1;
+ continue;
+ }
+
+ /* remove from Grease Pencil parent */
+ /* XXX This is likely not correct? Will also remove parent from grease pencil from other scenes,
+ * even when use_global is false... */
+ for (bGPdata *gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next) {
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if (gpl->parent != NULL) {
+ if (gpl->parent == ob) {
+ gpl->parent = NULL;
+ }
+ }
+ }
+ }
+
+ /* remove from current scene only */
+ ED_object_base_free_and_unlink(bmain, scene, ob);
+ changed_count += 1;
+
+ if (use_global) {
+ Scene *scene_iter;
+ for (scene_iter = bmain->scenes.first; scene_iter; scene_iter = scene_iter->id.next) {
+ if (scene_iter != scene && !ID_IS_LINKED(scene_iter)) {
+ if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) {
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "Cannot delete object '%s' from scene '%s', indirectly used objects need "
+ "at least one user",
+ ob->id.name + 2,
+ scene_iter->id.name + 2);
+ break;
+ }
+ ED_object_base_free_and_unlink(bmain, scene_iter, ob);
+ }
+ }
+ }
+ /* end global */
+ }
+ CTX_DATA_END;
+
+ BKE_reportf(op->reports, RPT_INFO, "Deleted %u object(s)", changed_count);
+
+ if (changed_count == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* delete has to handle all open scenes */
+ BKE_main_id_tag_listbase(&bmain->scenes, LIB_TAG_DOIT, true);
+ for (win = wm->windows.first; win; win = win->next) {
+ scene = WM_window_get_active_scene(win);
+
+ if (scene->id.tag & LIB_TAG_DOIT) {
+ scene->id.tag &= ~LIB_TAG_DOIT;
+
+ DEG_relations_tag_update(bmain);
+
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete";
- ot->description = "Delete selected objects";
- ot->idname = "OBJECT_OT_delete";
+ /* identifiers */
+ ot->name = "Delete";
+ ot->description = "Delete selected objects";
+ ot->idname = "OBJECT_OT_delete";
- /* api callbacks */
- ot->invoke = WM_operator_confirm_or_exec;
- ot->exec = object_delete_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm_or_exec;
+ ot->exec = object_delete_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- PropertyRNA *prop;
- prop = RNA_def_boolean(ot->srna, "use_global", 0, "Delete Globally", "Remove object from all scenes");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- WM_operator_properties_confirm_or_exec(ot);
+ PropertyRNA *prop;
+ prop = RNA_def_boolean(
+ ot->srna, "use_global", 0, "Delete Globally", "Remove object from all scenes");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ WM_operator_properties_confirm_or_exec(ot);
}
/**************************** Copy Utilities ******************************/
@@ -1464,15 +1522,14 @@ void OBJECT_OT_delete(wmOperatorType *ot)
/* after copying objects, copied data should get new pointers */
static void copy_object_set_idnew(bContext *C)
{
- Main *bmain = CTX_data_main(C);
+ Main *bmain = CTX_data_main(C);
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- BKE_libblock_relink_to_newid(&ob->id);
- }
- CTX_DATA_END;
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ BKE_libblock_relink_to_newid(&ob->id);
+ }
+ CTX_DATA_END;
- BKE_main_id_clear_newpoins(bmain);
+ BKE_main_id_clear_newpoins(bmain);
}
/********************* Make Duplicates Real ************************/
@@ -1483,13 +1540,13 @@ static void copy_object_set_idnew(bContext *C)
*/
static unsigned int dupliobject_group_hash(const void *ptr)
{
- const DupliObject *dob = ptr;
- unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
- unsigned int i;
- for (i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) {
- hash ^= (dob->persistent_id[i] ^ i);
- }
- return hash;
+ const DupliObject *dob = ptr;
+ unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
+ unsigned int i;
+ for (i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) {
+ hash ^= (dob->persistent_id[i] ^ i);
+ }
+ return hash;
}
/**
@@ -1498,704 +1555,714 @@ static unsigned int dupliobject_group_hash(const void *ptr)
*/
static unsigned int dupliobject_hash(const void *ptr)
{
- const DupliObject *dob = ptr;
- unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
- hash ^= (dob->persistent_id[0] ^ 0);
- return hash;
+ const DupliObject *dob = ptr;
+ unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
+ hash ^= (dob->persistent_id[0] ^ 0);
+ return hash;
}
/* Compare function that matches dupliobject_group_hash */
static bool dupliobject_group_cmp(const void *a_, const void *b_)
{
- const DupliObject *a = a_;
- const DupliObject *b = b_;
- unsigned int i;
+ const DupliObject *a = a_;
+ const DupliObject *b = b_;
+ unsigned int i;
- if (a->ob != b->ob) {
- return true;
- }
+ if (a->ob != b->ob) {
+ return true;
+ }
- for (i = 1; (i < MAX_DUPLI_RECUR); i++) {
- if (a->persistent_id[i] != b->persistent_id[i]) {
- return true;
- }
- else if (a->persistent_id[i] == INT_MAX) {
- break;
- }
- }
+ for (i = 1; (i < MAX_DUPLI_RECUR); i++) {
+ if (a->persistent_id[i] != b->persistent_id[i]) {
+ return true;
+ }
+ else if (a->persistent_id[i] == INT_MAX) {
+ break;
+ }
+ }
- /* matching */
- return false;
+ /* matching */
+ return false;
}
/* Compare function that matches dupliobject_hash */
static bool dupliobject_cmp(const void *a_, const void *b_)
{
- const DupliObject *a = a_;
- const DupliObject *b = b_;
-
- if (a->ob != b->ob) {
- return true;
- }
-
- if (a->persistent_id[0] != b->persistent_id[0]) {
- return true;
- }
-
- /* matching */
- return false;
-}
-
-static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
- const bool use_base_parent,
- const bool use_hierarchy)
-{
- Main *bmain = CTX_data_main(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ListBase *lb_duplis;
- DupliObject *dob;
- GHash *dupli_gh, *parent_gh = NULL;
-
- if (!(base->object->transflag & OB_DUPLI)) {
- return;
- }
-
- Object *object_eval = DEG_get_evaluated_object(depsgraph, base->object);
- lb_duplis = object_duplilist(depsgraph, scene, object_eval);
-
- dupli_gh = BLI_ghash_ptr_new(__func__);
- if (use_hierarchy) {
- if (base->object->transflag & OB_DUPLICOLLECTION) {
- parent_gh = BLI_ghash_new(dupliobject_group_hash, dupliobject_group_cmp, __func__);
- }
- else {
- parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
- }
- }
-
- for (dob = lb_duplis->first; dob; dob = dob->next) {
- Object *ob_src = DEG_get_original_object(dob->ob);
- Object *ob_dst = ID_NEW_SET(dob->ob, BKE_object_copy(bmain, ob_src));
- Base *base_dst;
-
- /* font duplis can have a totcol without material, we get them from parent
- * should be implemented better...
- */
- if (ob_dst->mat == NULL) {
- ob_dst->totcol = 0;
- }
-
- BKE_collection_object_add_from(bmain, scene, base->object, ob_dst);
- base_dst = BKE_view_layer_base_find(view_layer, ob_dst);
- BLI_assert(base_dst != NULL);
-
- BKE_scene_object_base_flag_sync_from_base(base_dst);
-
- /* make sure apply works */
- BKE_animdata_free(&ob_dst->id, true);
- ob_dst->adt = NULL;
-
- /* Proxies are not to be copied. */
- ob_dst->proxy_from = NULL;
- ob_dst->proxy_group = NULL;
- ob_dst->proxy = NULL;
-
- ob_dst->parent = NULL;
- BKE_constraints_free(&ob_dst->constraints);
- ob_dst->runtime.curve_cache = NULL;
- ob_dst->transflag &= ~OB_DUPLI;
-
- copy_m4_m4(ob_dst->obmat, dob->mat);
- BKE_object_apply_mat4(ob_dst, ob_dst->obmat, false, false);
-
- BLI_ghash_insert(dupli_gh, dob, ob_dst);
- if (parent_gh) {
- void **val;
- /* Due to nature of hash/comparison of this ghash, a lot of duplis may be considered as
- * 'the same', this avoids trying to insert same key several time and
- * raise asserts in debug builds... */
- if (!BLI_ghash_ensure_p(parent_gh, dob, &val)) {
- *val = ob_dst;
- }
- }
- }
-
- for (dob = lb_duplis->first; dob; dob = dob->next) {
- Object *ob_src = dob->ob;
- Object *ob_dst = BLI_ghash_lookup(dupli_gh, dob);
-
- /* Remap new object to itself, and clear again newid pointer of orig object. */
- BKE_libblock_relink_to_newid(&ob_dst->id);
-
- DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
-
- if (use_hierarchy) {
- /* original parents */
- Object *ob_src_par = ob_src->parent;
- Object *ob_dst_par = NULL;
-
- /* find parent that was also made real */
- if (ob_src_par) {
- /* OK to keep most of the members uninitialized,
- * they won't be read, this is simply for a hash lookup. */
- DupliObject dob_key;
- dob_key.ob = ob_src_par;
- if (base->object->transflag & OB_DUPLICOLLECTION) {
- memcpy(&dob_key.persistent_id[1],
- &dob->persistent_id[1],
- sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
- }
- else {
- dob_key.persistent_id[0] = dob->persistent_id[0];
- }
- ob_dst_par = BLI_ghash_lookup(parent_gh, &dob_key);
- }
-
- if (ob_dst_par) {
- /* allow for all possible parent types */
- ob_dst->partype = ob_src->partype;
- BLI_strncpy(ob_dst->parsubstr, ob_src->parsubstr, sizeof(ob_dst->parsubstr));
- ob_dst->par1 = ob_src->par1;
- ob_dst->par2 = ob_src->par2;
- ob_dst->par3 = ob_src->par3;
-
- copy_m4_m4(ob_dst->parentinv, ob_src->parentinv);
-
- ob_dst->parent = ob_dst_par;
- }
- else if (use_base_parent) {
- ob_dst->parent = base->object;
- ob_dst->partype = PAROBJECT;
- }
- }
- else if (use_base_parent) {
- /* since we are ignoring the internal hierarchy - parent all to the
- * base object */
- ob_dst->parent = base->object;
- ob_dst->partype = PAROBJECT;
- }
-
- if (ob_dst->parent) {
- /* note, this may be the parent of other objects, but it should
- * still work out ok */
- BKE_object_apply_mat4(ob_dst, dob->mat, false, true);
-
- /* to set ob_dst->orig and in case there's any other discrepancies */
- DEG_id_tag_update(&ob_dst->id, ID_RECALC_TRANSFORM);
- }
- }
-
- if (base->object->transflag & OB_DUPLICOLLECTION && base->object->instance_collection) {
- for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- if (ob->proxy_group == base->object) {
- ob->proxy = NULL;
- ob->proxy_from = NULL;
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- }
- }
- }
-
- BLI_ghash_free(dupli_gh, NULL, NULL);
- if (parent_gh) {
- BLI_ghash_free(parent_gh, NULL, NULL);
- }
-
- free_object_duplilist(lb_duplis);
-
- BKE_main_id_clear_newpoins(bmain);
-
- base->object->transflag &= ~OB_DUPLI;
- DEG_id_tag_update(&base->object->id, ID_RECALC_COPY_ON_WRITE);
+ const DupliObject *a = a_;
+ const DupliObject *b = b_;
+
+ if (a->ob != b->ob) {
+ return true;
+ }
+
+ if (a->persistent_id[0] != b->persistent_id[0]) {
+ return true;
+ }
+
+ /* matching */
+ return false;
+}
+
+static void make_object_duplilist_real(
+ bContext *C, Scene *scene, Base *base, const bool use_base_parent, const bool use_hierarchy)
+{
+ Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ListBase *lb_duplis;
+ DupliObject *dob;
+ GHash *dupli_gh, *parent_gh = NULL;
+
+ if (!(base->object->transflag & OB_DUPLI)) {
+ return;
+ }
+
+ Object *object_eval = DEG_get_evaluated_object(depsgraph, base->object);
+ lb_duplis = object_duplilist(depsgraph, scene, object_eval);
+
+ dupli_gh = BLI_ghash_ptr_new(__func__);
+ if (use_hierarchy) {
+ if (base->object->transflag & OB_DUPLICOLLECTION) {
+ parent_gh = BLI_ghash_new(dupliobject_group_hash, dupliobject_group_cmp, __func__);
+ }
+ else {
+ parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
+ }
+ }
+
+ for (dob = lb_duplis->first; dob; dob = dob->next) {
+ Object *ob_src = DEG_get_original_object(dob->ob);
+ Object *ob_dst = ID_NEW_SET(dob->ob, BKE_object_copy(bmain, ob_src));
+ Base *base_dst;
+
+ /* font duplis can have a totcol without material, we get them from parent
+ * should be implemented better...
+ */
+ if (ob_dst->mat == NULL) {
+ ob_dst->totcol = 0;
+ }
+
+ BKE_collection_object_add_from(bmain, scene, base->object, ob_dst);
+ base_dst = BKE_view_layer_base_find(view_layer, ob_dst);
+ BLI_assert(base_dst != NULL);
+
+ BKE_scene_object_base_flag_sync_from_base(base_dst);
+
+ /* make sure apply works */
+ BKE_animdata_free(&ob_dst->id, true);
+ ob_dst->adt = NULL;
+
+ /* Proxies are not to be copied. */
+ ob_dst->proxy_from = NULL;
+ ob_dst->proxy_group = NULL;
+ ob_dst->proxy = NULL;
+
+ ob_dst->parent = NULL;
+ BKE_constraints_free(&ob_dst->constraints);
+ ob_dst->runtime.curve_cache = NULL;
+ ob_dst->transflag &= ~OB_DUPLI;
+
+ copy_m4_m4(ob_dst->obmat, dob->mat);
+ BKE_object_apply_mat4(ob_dst, ob_dst->obmat, false, false);
+
+ BLI_ghash_insert(dupli_gh, dob, ob_dst);
+ if (parent_gh) {
+ void **val;
+ /* Due to nature of hash/comparison of this ghash, a lot of duplis may be considered as
+ * 'the same', this avoids trying to insert same key several time and
+ * raise asserts in debug builds... */
+ if (!BLI_ghash_ensure_p(parent_gh, dob, &val)) {
+ *val = ob_dst;
+ }
+ }
+ }
+
+ for (dob = lb_duplis->first; dob; dob = dob->next) {
+ Object *ob_src = dob->ob;
+ Object *ob_dst = BLI_ghash_lookup(dupli_gh, dob);
+
+ /* Remap new object to itself, and clear again newid pointer of orig object. */
+ BKE_libblock_relink_to_newid(&ob_dst->id);
+
+ DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
+
+ if (use_hierarchy) {
+ /* original parents */
+ Object *ob_src_par = ob_src->parent;
+ Object *ob_dst_par = NULL;
+
+ /* find parent that was also made real */
+ if (ob_src_par) {
+ /* OK to keep most of the members uninitialized,
+ * they won't be read, this is simply for a hash lookup. */
+ DupliObject dob_key;
+ dob_key.ob = ob_src_par;
+ if (base->object->transflag & OB_DUPLICOLLECTION) {
+ memcpy(&dob_key.persistent_id[1],
+ &dob->persistent_id[1],
+ sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
+ }
+ else {
+ dob_key.persistent_id[0] = dob->persistent_id[0];
+ }
+ ob_dst_par = BLI_ghash_lookup(parent_gh, &dob_key);
+ }
+
+ if (ob_dst_par) {
+ /* allow for all possible parent types */
+ ob_dst->partype = ob_src->partype;
+ BLI_strncpy(ob_dst->parsubstr, ob_src->parsubstr, sizeof(ob_dst->parsubstr));
+ ob_dst->par1 = ob_src->par1;
+ ob_dst->par2 = ob_src->par2;
+ ob_dst->par3 = ob_src->par3;
+
+ copy_m4_m4(ob_dst->parentinv, ob_src->parentinv);
+
+ ob_dst->parent = ob_dst_par;
+ }
+ else if (use_base_parent) {
+ ob_dst->parent = base->object;
+ ob_dst->partype = PAROBJECT;
+ }
+ }
+ else if (use_base_parent) {
+ /* since we are ignoring the internal hierarchy - parent all to the
+ * base object */
+ ob_dst->parent = base->object;
+ ob_dst->partype = PAROBJECT;
+ }
+
+ if (ob_dst->parent) {
+ /* note, this may be the parent of other objects, but it should
+ * still work out ok */
+ BKE_object_apply_mat4(ob_dst, dob->mat, false, true);
+
+ /* to set ob_dst->orig and in case there's any other discrepancies */
+ DEG_id_tag_update(&ob_dst->id, ID_RECALC_TRANSFORM);
+ }
+ }
+
+ if (base->object->transflag & OB_DUPLICOLLECTION && base->object->instance_collection) {
+ for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
+ if (ob->proxy_group == base->object) {
+ ob->proxy = NULL;
+ ob->proxy_from = NULL;
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ }
+ }
+ }
+
+ BLI_ghash_free(dupli_gh, NULL, NULL);
+ if (parent_gh) {
+ BLI_ghash_free(parent_gh, NULL, NULL);
+ }
+
+ free_object_duplilist(lb_duplis);
+
+ BKE_main_id_clear_newpoins(bmain);
+
+ base->object->transflag &= ~OB_DUPLI;
+ DEG_id_tag_update(&base->object->id, ID_RECALC_COPY_ON_WRITE);
}
static int object_duplicates_make_real_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
- const bool use_base_parent = RNA_boolean_get(op->ptr, "use_base_parent");
- const bool use_hierarchy = RNA_boolean_get(op->ptr, "use_hierarchy");
+ const bool use_base_parent = RNA_boolean_get(op->ptr, "use_base_parent");
+ const bool use_hierarchy = RNA_boolean_get(op->ptr, "use_hierarchy");
- BKE_main_id_clear_newpoins(bmain);
+ BKE_main_id_clear_newpoins(bmain);
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
- {
- make_object_duplilist_real(C, scene, base, use_base_parent, use_hierarchy);
+ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
+ make_object_duplilist_real(C, scene, base, use_base_parent, use_hierarchy);
- /* dependencies were changed */
- WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, base->object);
- }
- CTX_DATA_END;
+ /* dependencies were changed */
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, base->object);
+ }
+ CTX_DATA_END;
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_SCENE, scene);
- WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_SCENE, scene);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_duplicates_make_real(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Duplicates Real";
- ot->description = "Make dupli objects attached to this object real";
- ot->idname = "OBJECT_OT_duplicates_make_real";
+ /* identifiers */
+ ot->name = "Make Duplicates Real";
+ ot->description = "Make dupli objects attached to this object real";
+ ot->idname = "OBJECT_OT_duplicates_make_real";
- /* api callbacks */
- ot->exec = object_duplicates_make_real_exec;
+ /* api callbacks */
+ ot->exec = object_duplicates_make_real_exec;
- ot->poll = ED_operator_objectmode;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
- RNA_def_boolean(ot->srna, "use_base_parent", 0, "Parent", "Parent newly created objects to the original duplicator");
- RNA_def_boolean(ot->srna, "use_hierarchy", 0, "Keep Hierarchy", "Maintain parent child relationships");
+ RNA_def_boolean(ot->srna,
+ "use_base_parent",
+ 0,
+ "Parent",
+ "Parent newly created objects to the original duplicator");
+ RNA_def_boolean(
+ ot->srna, "use_hierarchy", 0, "Keep Hierarchy", "Maintain parent child relationships");
}
/**************************** Convert **************************/
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", ""},
- {0, NULL, 0, NULL, NULL},
+ {OB_CURVE, "CURVE", ICON_OUTLINER_OB_CURVE, "Curve from Mesh/Text", ""},
+ {OB_MESH, "MESH", ICON_OUTLINER_OB_MESH, "Mesh from Curve/Meta/Surf/Text", ""},
+ {0, NULL, 0, NULL, NULL},
};
static void 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
- * redo we might end up with an object which isn't evaluated yet.
- * Also happens in case we are working on a copy of the object (all its caches have been nuked then).
- */
- if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
- /* We need 'for render' ON here, to enable computing bevel dipslist if needed.
- * Also makes sense anyway, we would not want e.g. to loose hidden parts etc. */
- BKE_displist_make_curveTypes(depsgraph, scene, ob, true, false, NULL);
- }
- else if (ob->type == OB_MBALL) {
- BKE_displist_make_mball(depsgraph, scene, ob);
- }
- }
+ if (ob->runtime.curve_cache == NULL) {
+ /* Force creation. This is normally not needed but on operator
+ * redo we might end up with an object which isn't evaluated yet.
+ * Also happens in case we are working on a copy of the object (all its caches have been nuked then).
+ */
+ if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
+ /* We need 'for render' ON here, to enable computing bevel dipslist if needed.
+ * Also makes sense anyway, we would not want e.g. to loose hidden parts etc. */
+ BKE_displist_make_curveTypes(depsgraph, scene, ob, true, false, NULL);
+ }
+ else if (ob->type == OB_MBALL) {
+ BKE_displist_make_mball(depsgraph, scene, ob);
+ }
+ }
}
static void curvetomesh(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
{
- convert_ensure_curve_cache(depsgraph, scene, ob);
- BKE_mesh_from_nurbs(bmain, ob); /* also does users */
+ convert_ensure_curve_cache(depsgraph, scene, ob);
+ BKE_mesh_from_nurbs(bmain, ob); /* also does users */
- if (ob->type == OB_MESH) {
- BKE_object_free_modifiers(ob, 0);
- }
+ if (ob->type == OB_MESH) {
+ BKE_object_free_modifiers(ob, 0);
+ }
}
static bool 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;
+ 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));
+ return (!ID_IS_LINKED(scene) && obact && (BKE_object_is_in_editmode(obact) == false) &&
+ (base_act->flag & BASE_SELECTED) && !ID_IS_LINKED(obact));
}
/* Helper for convert_exec */
-static Base *duplibase_for_convert(Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, Object *ob)
+static Base *duplibase_for_convert(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, Object *ob)
{
- Object *obn;
- Base *basen;
+ Object *obn;
+ Base *basen;
- if (ob == NULL) {
- ob = base->object;
- }
+ if (ob == NULL) {
+ ob = base->object;
+ }
- obn = BKE_object_copy(bmain, ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- BKE_collection_object_add_from(bmain, scene, ob, obn);
+ obn = BKE_object_copy(bmain, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ BKE_collection_object_add_from(bmain, scene, ob, obn);
- basen = BKE_view_layer_base_find(view_layer, obn);
- ED_object_base_select(basen, BA_SELECT);
- ED_object_base_select(basen, BA_DESELECT);
- return basen;
+ basen = BKE_view_layer_base_find(view_layer, obn);
+ ED_object_base_select(basen, BA_SELECT);
+ ED_object_base_select(basen, BA_DESELECT);
+ return basen;
}
static int convert_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *basen = NULL, *basact = NULL;
- Object *ob1, *obact = CTX_data_active_object(C);
- Curve *cu;
- Nurb *nu;
- MetaBall *mb;
- Mesh *me;
- const short target = RNA_enum_get(op->ptr, "target");
- bool keep_original = RNA_boolean_get(op->ptr, "keep_original");
- int a, mballConverted = 0;
-
- /* don't forget multiple users! */
-
- {
- FOREACH_SCENE_OBJECT_BEGIN(scene, ob)
- {
- ob->flag &= ~OB_DONE;
-
- /* flag data that's not been edited (only needed for !keep_original) */
- if (ob->data) {
- ((ID *)ob->data)->tag |= LIB_TAG_DOIT;
- }
-
- /* possible metaball basis is not in this scene */
- if (ob->type == OB_MBALL && target == OB_MESH) {
- if (BKE_mball_is_basis(ob) == false) {
- Object *ob_basis;
- ob_basis = BKE_mball_basis_find(scene, ob);
- if (ob_basis) {
- ob_basis->flag &= ~OB_DONE;
- }
- }
- }
- }
- FOREACH_SCENE_OBJECT_END;
- }
-
- ListBase selected_editable_bases = CTX_data_collection_get(C, "selected_editable_bases");
-
- /* Ensure we get all meshes calculated with a sufficient data-mask,
- * needed since re-evaluating single modifiers causes bugs if they depend
- * on other objects data masks too, see: T50950. */
- {
- for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) {
- Base *base = link->ptr.data;
- Object *ob = base->object;
-
- /* The way object type conversion works currently (enforcing conversion of *all* objects using converted
- * object-data, even some un-selected/hidden/another scene ones, sounds totally bad to me.
- * However, changing this is more design than bug-fix, not to mention convoluted code below,
- * so that will be for later.
- * But at the very least, do not do that with linked IDs! */
- if ((ID_IS_LINKED(ob) || (ob->data && ID_IS_LINKED(ob->data))) && !keep_original) {
- keep_original = true;
- BKE_report(op->reports, RPT_INFO,
- "Converting some linked object/object data, enforcing 'Keep Original' option to True");
- }
-
- DEG_id_tag_update(&base->object->id, ID_RECALC_GEOMETRY);
- }
-
- CustomData_MeshMasks customdata_mask_prev = scene->customdata_mask;
- CustomData_MeshMasks_update(&scene->customdata_mask, &CD_MASK_MESH);
- BKE_scene_graph_update_tagged(depsgraph, bmain);
- scene->customdata_mask = customdata_mask_prev;
- }
-
- for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) {
- Object *newob = NULL;
- Base *base = link->ptr.data;
- Object *ob = base->object;
-
- if (ob->flag & OB_DONE || !IS_TAGGED(ob->data)) {
- if (ob->type != target) {
- base->flag &= ~SELECT;
- ob->flag &= ~SELECT;
- }
-
- /* obdata already modified */
- if (!IS_TAGGED(ob->data)) {
- /* When 2 objects with linked data are selected, converting both
- * would keep modifiers on all but the converted object [#26003] */
- if (ob->type == OB_MESH) {
- BKE_object_free_modifiers(ob, 0); /* after derivedmesh calls! */
- }
- if (ob->type == OB_GPENCIL) {
- BKE_object_free_modifiers(ob, 0); /* after derivedmesh calls! */
- BKE_object_free_shaderfx(ob, 0);
- }
- }
- }
- else if (ob->type == OB_MESH && target == OB_CURVE) {
- ob->flag |= OB_DONE;
-
- if (keep_original) {
- basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL);
- newob = basen->object;
-
- /* decrement original mesh's usage count */
- me = newob->data;
- id_us_min(&me->id);
-
- /* make a new copy of the mesh */
- newob->data = BKE_mesh_copy(bmain, me);
- }
- else {
- newob = ob;
- }
-
- BKE_mesh_to_curve(bmain, depsgraph, scene, newob);
-
- if (newob->type == OB_CURVE) {
- BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
- ED_rigidbody_object_remove(bmain, scene, newob);
- }
- }
- else if (ob->type == OB_MESH) {
- ob->flag |= OB_DONE;
-
- if (keep_original) {
- basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL);
- newob = basen->object;
-
- /* decrement original mesh's usage count */
- me = newob->data;
- id_us_min(&me->id);
-
- /* make a new copy of the mesh */
- newob->data = BKE_mesh_copy(bmain, me);
- }
- else {
- newob = ob;
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- }
-
- /* make new mesh data from the original copy */
- /* note: get the mesh from the original, not from the copy in some
- * cases this doesn't give correct results (when MDEF is used for eg)
- */
- Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_MESH);
- me_eval = BKE_mesh_copy_for_eval(me_eval, false);
- BKE_mesh_nomain_to_mesh(me_eval, newob->data, newob, &CD_MASK_MESH, true);
- BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
- }
- else if (ob->type == OB_FONT) {
- ob->flag |= OB_DONE;
-
- if (keep_original) {
- basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL);
- newob = basen->object;
-
- /* decrement original curve's usage count */
- id_us_min(&((Curve *)newob->data)->id);
-
- /* make a new copy of the curve */
- newob->data = BKE_curve_copy(bmain, ob->data);
- }
- else {
- newob = ob;
- }
-
- cu = newob->data;
-
- /* TODO(sergey): Ideally DAG will create nurbs list for a curve data
- * datablock, but for until we've got granular update
- * lets take care by selves.
- */
- /* XXX This may fail/crash, since BKE_vfont_to_curve()
- * accesses evaluated data in some cases (bastien). */
- BKE_vfont_to_curve(newob, FO_EDIT);
-
- newob->type = OB_CURVE;
- cu->type = OB_CURVE;
-
- if (cu->vfont) {
- id_us_min(&cu->vfont->id);
- cu->vfont = NULL;
- }
- if (cu->vfontb) {
- id_us_min(&cu->vfontb->id);
- cu->vfontb = NULL;
- }
- if (cu->vfonti) {
- id_us_min(&cu->vfonti->id);
- cu->vfonti = NULL;
- }
- if (cu->vfontbi) {
- id_us_min(&cu->vfontbi->id);
- cu->vfontbi = NULL;
- }
-
- if (!keep_original) {
- /* other users */
- if (cu->id.us > 1) {
- for (ob1 = bmain->objects.first; ob1; ob1 = ob1->id.next) {
- if (ob1->data == ob->data) {
- ob1->type = OB_CURVE;
- DEG_id_tag_update(&ob1->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- }
- }
- }
- }
-
- for (nu = cu->nurb.first; nu; nu = nu->next)
- nu->charidx = 0;
-
- cu->flag &= ~CU_3D;
- BKE_curve_curve_dimension_update(cu);
-
- if (target == OB_MESH) {
- curvetomesh(bmain, depsgraph, scene, newob);
-
- /* meshes doesn't use displist */
- BKE_object_free_curve_cache(newob);
- }
- }
- else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
- ob->flag |= OB_DONE;
-
- if (target == OB_MESH) {
- if (keep_original) {
- basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL);
- newob = basen->object;
-
- /* decrement original curve's usage count */
- id_us_min(&((Curve *)newob->data)->id);
-
- /* make a new copy of the curve */
- newob->data = BKE_curve_copy(bmain, ob->data);
- }
- else {
- newob = ob;
- }
-
- curvetomesh(bmain, depsgraph, scene, newob);
-
- /* meshes doesn't use displist */
- BKE_object_free_curve_cache(newob);
- }
- }
- else if (ob->type == OB_MBALL && target == OB_MESH) {
- Object *baseob;
-
- base->flag &= ~BASE_SELECTED;
- ob->base_flag &= ~BASE_SELECTED;
-
- baseob = BKE_mball_basis_find(scene, ob);
-
- if (ob != baseob) {
- /* if motherball is converting it would be marked as done later */
- ob->flag |= OB_DONE;
- }
-
- if (!(baseob->flag & OB_DONE)) {
- baseob->flag |= OB_DONE;
-
- basen = duplibase_for_convert(bmain, scene, view_layer, base, baseob);
- newob = basen->object;
-
- mb = newob->data;
- id_us_min(&mb->id);
-
- newob->data = BKE_mesh_add(bmain, "Mesh");
- newob->type = OB_MESH;
-
- me = newob->data;
- me->totcol = mb->totcol;
- if (newob->totcol) {
- me->mat = MEM_dupallocN(mb->mat);
- for (a = 0; a < newob->totcol; a++) id_us_plus((ID *)me->mat[a]);
- }
-
- convert_ensure_curve_cache(depsgraph, scene, baseob);
- BKE_mesh_from_metaball(&baseob->runtime.curve_cache->disp, newob->data);
-
- if (obact->type == OB_MBALL) {
- basact = basen;
- }
-
- mballConverted = 1;
- }
- }
- else {
- continue;
- }
-
- /* Ensure new object has consistent material data with its new obdata. */
- if (newob) {
- test_object_materials(bmain, newob, newob->data);
- }
-
- /* tag obdata if it was been changed */
-
- /* If the original object is active then make this object active */
- if (basen) {
- if (ob == obact) {
- /* store new active base to update BASACT */
- basact = basen;
- }
-
- basen = NULL;
- }
-
- if (!keep_original && (ob->flag & OB_DONE)) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- ((ID *)ob->data)->tag &= ~LIB_TAG_DOIT; /* flag not to convert this datablock again */
- }
- }
- BLI_freelistN(&selected_editable_bases);
-
- if (!keep_original) {
- if (mballConverted) {
- FOREACH_SCENE_OBJECT_BEGIN(scene, ob_mball)
- {
- if (ob_mball->type == OB_MBALL) {
- if (ob_mball->flag & OB_DONE) {
- Object *ob_basis = NULL;
- if (BKE_mball_is_basis(ob_mball) ||
- ((ob_basis = BKE_mball_basis_find(scene, ob_mball)) && (ob_basis->flag & OB_DONE)))
- {
- ED_object_base_free_and_unlink(bmain, scene, ob_mball);
- }
- }
- }
- }
- FOREACH_SCENE_OBJECT_END;
- }
- }
-
-// XXX ED_object_editmode_enter(C, 0);
-// XXX exit_editmode(C, EM_FREEDATA|); /* freedata, but no undo */
-
- if (basact) {
- /* active base was changed */
- ED_object_base_activate(C, basact);
- BASACT(view_layer) = basact;
- }
- else if (BASACT(view_layer)->object->flag & OB_DONE) {
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, BASACT(view_layer)->object);
- WM_event_add_notifier(C, NC_OBJECT | ND_DATA, BASACT(view_layer)->object);
- }
-
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *basen = NULL, *basact = NULL;
+ Object *ob1, *obact = CTX_data_active_object(C);
+ Curve *cu;
+ Nurb *nu;
+ MetaBall *mb;
+ Mesh *me;
+ const short target = RNA_enum_get(op->ptr, "target");
+ bool keep_original = RNA_boolean_get(op->ptr, "keep_original");
+ int a, mballConverted = 0;
+
+ /* don't forget multiple users! */
+
+ {
+ FOREACH_SCENE_OBJECT_BEGIN (scene, ob) {
+ ob->flag &= ~OB_DONE;
+
+ /* flag data that's not been edited (only needed for !keep_original) */
+ if (ob->data) {
+ ((ID *)ob->data)->tag |= LIB_TAG_DOIT;
+ }
+
+ /* possible metaball basis is not in this scene */
+ if (ob->type == OB_MBALL && target == OB_MESH) {
+ if (BKE_mball_is_basis(ob) == false) {
+ Object *ob_basis;
+ ob_basis = BKE_mball_basis_find(scene, ob);
+ if (ob_basis) {
+ ob_basis->flag &= ~OB_DONE;
+ }
+ }
+ }
+ }
+ FOREACH_SCENE_OBJECT_END;
+ }
+
+ ListBase selected_editable_bases = CTX_data_collection_get(C, "selected_editable_bases");
+
+ /* Ensure we get all meshes calculated with a sufficient data-mask,
+ * needed since re-evaluating single modifiers causes bugs if they depend
+ * on other objects data masks too, see: T50950. */
+ {
+ for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) {
+ Base *base = link->ptr.data;
+ Object *ob = base->object;
+
+ /* The way object type conversion works currently (enforcing conversion of *all* objects using converted
+ * object-data, even some un-selected/hidden/another scene ones, sounds totally bad to me.
+ * However, changing this is more design than bug-fix, not to mention convoluted code below,
+ * so that will be for later.
+ * But at the very least, do not do that with linked IDs! */
+ if ((ID_IS_LINKED(ob) || (ob->data && ID_IS_LINKED(ob->data))) && !keep_original) {
+ keep_original = true;
+ BKE_report(
+ op->reports,
+ RPT_INFO,
+ "Converting some linked object/object data, enforcing 'Keep Original' option to True");
+ }
+
+ DEG_id_tag_update(&base->object->id, ID_RECALC_GEOMETRY);
+ }
+
+ CustomData_MeshMasks customdata_mask_prev = scene->customdata_mask;
+ CustomData_MeshMasks_update(&scene->customdata_mask, &CD_MASK_MESH);
+ BKE_scene_graph_update_tagged(depsgraph, bmain);
+ scene->customdata_mask = customdata_mask_prev;
+ }
+
+ for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) {
+ Object *newob = NULL;
+ Base *base = link->ptr.data;
+ Object *ob = base->object;
+
+ if (ob->flag & OB_DONE || !IS_TAGGED(ob->data)) {
+ if (ob->type != target) {
+ base->flag &= ~SELECT;
+ ob->flag &= ~SELECT;
+ }
+
+ /* obdata already modified */
+ if (!IS_TAGGED(ob->data)) {
+ /* When 2 objects with linked data are selected, converting both
+ * would keep modifiers on all but the converted object [#26003] */
+ if (ob->type == OB_MESH) {
+ BKE_object_free_modifiers(ob, 0); /* after derivedmesh calls! */
+ }
+ if (ob->type == OB_GPENCIL) {
+ BKE_object_free_modifiers(ob, 0); /* after derivedmesh calls! */
+ BKE_object_free_shaderfx(ob, 0);
+ }
+ }
+ }
+ else if (ob->type == OB_MESH && target == OB_CURVE) {
+ ob->flag |= OB_DONE;
+
+ if (keep_original) {
+ basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL);
+ newob = basen->object;
+
+ /* decrement original mesh's usage count */
+ me = newob->data;
+ id_us_min(&me->id);
+
+ /* make a new copy of the mesh */
+ newob->data = BKE_mesh_copy(bmain, me);
+ }
+ else {
+ newob = ob;
+ }
+
+ BKE_mesh_to_curve(bmain, depsgraph, scene, newob);
+
+ if (newob->type == OB_CURVE) {
+ BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
+ ED_rigidbody_object_remove(bmain, scene, newob);
+ }
+ }
+ else if (ob->type == OB_MESH) {
+ ob->flag |= OB_DONE;
+
+ if (keep_original) {
+ basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL);
+ newob = basen->object;
+
+ /* decrement original mesh's usage count */
+ me = newob->data;
+ id_us_min(&me->id);
+
+ /* make a new copy of the mesh */
+ newob->data = BKE_mesh_copy(bmain, me);
+ }
+ else {
+ newob = ob;
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ }
+
+ /* make new mesh data from the original copy */
+ /* note: get the mesh from the original, not from the copy in some
+ * cases this doesn't give correct results (when MDEF is used for eg)
+ */
+ Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &CD_MASK_MESH);
+ me_eval = BKE_mesh_copy_for_eval(me_eval, false);
+ BKE_mesh_nomain_to_mesh(me_eval, newob->data, newob, &CD_MASK_MESH, true);
+ BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
+ }
+ else if (ob->type == OB_FONT) {
+ ob->flag |= OB_DONE;
+
+ if (keep_original) {
+ basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL);
+ newob = basen->object;
+
+ /* decrement original curve's usage count */
+ id_us_min(&((Curve *)newob->data)->id);
+
+ /* make a new copy of the curve */
+ newob->data = BKE_curve_copy(bmain, ob->data);
+ }
+ else {
+ newob = ob;
+ }
+
+ cu = newob->data;
+
+ /* TODO(sergey): Ideally DAG will create nurbs list for a curve data
+ * datablock, but for until we've got granular update
+ * lets take care by selves.
+ */
+ /* XXX This may fail/crash, since BKE_vfont_to_curve()
+ * accesses evaluated data in some cases (bastien). */
+ BKE_vfont_to_curve(newob, FO_EDIT);
+
+ newob->type = OB_CURVE;
+ cu->type = OB_CURVE;
+
+ if (cu->vfont) {
+ id_us_min(&cu->vfont->id);
+ cu->vfont = NULL;
+ }
+ if (cu->vfontb) {
+ id_us_min(&cu->vfontb->id);
+ cu->vfontb = NULL;
+ }
+ if (cu->vfonti) {
+ id_us_min(&cu->vfonti->id);
+ cu->vfonti = NULL;
+ }
+ if (cu->vfontbi) {
+ id_us_min(&cu->vfontbi->id);
+ cu->vfontbi = NULL;
+ }
+
+ if (!keep_original) {
+ /* other users */
+ if (cu->id.us > 1) {
+ for (ob1 = bmain->objects.first; ob1; ob1 = ob1->id.next) {
+ if (ob1->data == ob->data) {
+ ob1->type = OB_CURVE;
+ DEG_id_tag_update(&ob1->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ }
+ }
+ }
+ }
+
+ for (nu = cu->nurb.first; nu; nu = nu->next)
+ nu->charidx = 0;
+
+ cu->flag &= ~CU_3D;
+ BKE_curve_curve_dimension_update(cu);
+
+ if (target == OB_MESH) {
+ curvetomesh(bmain, depsgraph, scene, newob);
+
+ /* meshes doesn't use displist */
+ BKE_object_free_curve_cache(newob);
+ }
+ }
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
+ ob->flag |= OB_DONE;
+
+ if (target == OB_MESH) {
+ if (keep_original) {
+ basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL);
+ newob = basen->object;
+
+ /* decrement original curve's usage count */
+ id_us_min(&((Curve *)newob->data)->id);
+
+ /* make a new copy of the curve */
+ newob->data = BKE_curve_copy(bmain, ob->data);
+ }
+ else {
+ newob = ob;
+ }
+
+ curvetomesh(bmain, depsgraph, scene, newob);
+
+ /* meshes doesn't use displist */
+ BKE_object_free_curve_cache(newob);
+ }
+ }
+ else if (ob->type == OB_MBALL && target == OB_MESH) {
+ Object *baseob;
+
+ base->flag &= ~BASE_SELECTED;
+ ob->base_flag &= ~BASE_SELECTED;
+
+ baseob = BKE_mball_basis_find(scene, ob);
+
+ if (ob != baseob) {
+ /* if motherball is converting it would be marked as done later */
+ ob->flag |= OB_DONE;
+ }
+
+ if (!(baseob->flag & OB_DONE)) {
+ baseob->flag |= OB_DONE;
+
+ basen = duplibase_for_convert(bmain, scene, view_layer, base, baseob);
+ newob = basen->object;
+
+ mb = newob->data;
+ id_us_min(&mb->id);
+
+ newob->data = BKE_mesh_add(bmain, "Mesh");
+ newob->type = OB_MESH;
+
+ me = newob->data;
+ me->totcol = mb->totcol;
+ if (newob->totcol) {
+ me->mat = MEM_dupallocN(mb->mat);
+ for (a = 0; a < newob->totcol; a++)
+ id_us_plus((ID *)me->mat[a]);
+ }
+
+ convert_ensure_curve_cache(depsgraph, scene, baseob);
+ BKE_mesh_from_metaball(&baseob->runtime.curve_cache->disp, newob->data);
+
+ if (obact->type == OB_MBALL) {
+ basact = basen;
+ }
+
+ mballConverted = 1;
+ }
+ }
+ else {
+ continue;
+ }
+
+ /* Ensure new object has consistent material data with its new obdata. */
+ if (newob) {
+ test_object_materials(bmain, newob, newob->data);
+ }
+
+ /* tag obdata if it was been changed */
+
+ /* If the original object is active then make this object active */
+ if (basen) {
+ if (ob == obact) {
+ /* store new active base to update BASACT */
+ basact = basen;
+ }
+
+ basen = NULL;
+ }
+
+ if (!keep_original && (ob->flag & OB_DONE)) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ ((ID *)ob->data)->tag &= ~LIB_TAG_DOIT; /* flag not to convert this datablock again */
+ }
+ }
+ BLI_freelistN(&selected_editable_bases);
+
+ if (!keep_original) {
+ if (mballConverted) {
+ FOREACH_SCENE_OBJECT_BEGIN (scene, ob_mball) {
+ if (ob_mball->type == OB_MBALL) {
+ if (ob_mball->flag & OB_DONE) {
+ Object *ob_basis = NULL;
+ if (BKE_mball_is_basis(ob_mball) ||
+ ((ob_basis = BKE_mball_basis_find(scene, ob_mball)) &&
+ (ob_basis->flag & OB_DONE))) {
+ ED_object_base_free_and_unlink(bmain, scene, ob_mball);
+ }
+ }
+ }
+ }
+ FOREACH_SCENE_OBJECT_END;
+ }
+ }
+
+ // XXX ED_object_editmode_enter(C, 0);
+ // XXX exit_editmode(C, EM_FREEDATA|); /* freedata, but no undo */
+
+ if (basact) {
+ /* active base was changed */
+ ED_object_base_activate(C, basact);
+ BASACT(view_layer) = basact;
+ }
+ else if (BASACT(view_layer)->object->flag & OB_DONE) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, BASACT(view_layer)->object);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DATA, BASACT(view_layer)->object);
+ }
+
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
+ return OPERATOR_FINISHED;
}
-
void OBJECT_OT_convert(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Convert to";
- ot->description = "Convert selected objects to another type";
- ot->idname = "OBJECT_OT_convert";
+ /* identifiers */
+ ot->name = "Convert to";
+ ot->description = "Convert selected objects to another type";
+ ot->idname = "OBJECT_OT_convert";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = convert_exec;
- ot->poll = convert_poll;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = convert_exec;
+ ot->poll = convert_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "target", convert_target_items, OB_MESH, "Target", "Type of object to convert to");
- RNA_def_boolean(ot->srna, "keep_original", 0, "Keep Original", "Keep original objects instead of replacing them");
+ /* properties */
+ ot->prop = RNA_def_enum(
+ ot->srna, "target", convert_target_items, OB_MESH, "Target", "Type of object to convert to");
+ RNA_def_boolean(ot->srna,
+ "keep_original",
+ 0,
+ "Keep Original",
+ "Keep original objects instead of replacing them");
}
/**************************** Duplicate ************************/
@@ -2209,45 +2276,46 @@ 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)
-{
- Base *base, *basen = NULL;
- Object *obn;
-
- if (ob->mode & OB_MODE_POSE) {
- /* nothing? */
- }
- else {
- obn = ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag));
- DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
-
- base = BKE_view_layer_base_find(view_layer, ob);
- if ((base != NULL) && (base->flag & BASE_VISIBLE)) {
- BKE_collection_object_add_from(bmain, scene, ob, obn);
- }
- else {
- LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
- BKE_collection_object_add(bmain, layer_collection->collection, obn);
- }
-
- basen = BKE_view_layer_base_find(view_layer, obn);
- if (base != NULL) {
- basen->local_view_bits = base->local_view_bits;
- }
-
- /* 1) duplis should end up in same collection as the original
- * 2) Rigid Body sim participants MUST always be part of a collection...
- */
- // XXX: is 2) really a good measure here?
- if (ob->rigidbody_object || ob->rigidbody_constraint) {
- Collection *collection;
- for (collection = bmain->collections.first; collection; collection = collection->id.next) {
- if (BKE_collection_has_object(collection, ob))
- BKE_collection_object_add(bmain, collection, obn);
- }
- }
- }
- return basen;
+static Base *object_add_duplicate_internal(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, Object *ob, int dupflag)
+{
+ Base *base, *basen = NULL;
+ Object *obn;
+
+ if (ob->mode & OB_MODE_POSE) {
+ /* nothing? */
+ }
+ else {
+ obn = ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag));
+ DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+
+ base = BKE_view_layer_base_find(view_layer, ob);
+ if ((base != NULL) && (base->flag & BASE_VISIBLE)) {
+ BKE_collection_object_add_from(bmain, scene, ob, obn);
+ }
+ else {
+ LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
+ BKE_collection_object_add(bmain, layer_collection->collection, obn);
+ }
+
+ basen = BKE_view_layer_base_find(view_layer, obn);
+ if (base != NULL) {
+ basen->local_view_bits = base->local_view_bits;
+ }
+
+ /* 1) duplis should end up in same collection as the original
+ * 2) Rigid Body sim participants MUST always be part of a collection...
+ */
+ // XXX: is 2) really a good measure here?
+ if (ob->rigidbody_object || ob->rigidbody_constraint) {
+ Collection *collection;
+ for (collection = bmain->collections.first; collection; collection = collection->id.next) {
+ if (BKE_collection_has_object(collection, ob))
+ BKE_collection_object_add(bmain, collection, obn);
+ }
+ }
+ }
+ return basen;
}
/* single object duplicate, if dupflag==0, fully linked, else it uses the flags given */
@@ -2255,278 +2323,288 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer
* note: don't call this within a loop since clear_* funcs loop over the entire database.
* 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)
+Base *ED_object_add_duplicate(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, int dupflag)
{
- Base *basen;
- Object *ob;
+ Base *basen;
+ Object *ob;
- basen = object_add_duplicate_internal(bmain, scene, view_layer, base->object, dupflag);
- if (basen == NULL) {
- return NULL;
- }
+ basen = object_add_duplicate_internal(bmain, scene, view_layer, base->object, dupflag);
+ if (basen == NULL) {
+ return NULL;
+ }
- ob = basen->object;
+ ob = basen->object;
- /* link own references to the newly duplicated data [#26816] */
- BKE_libblock_relink_to_newid(&ob->id);
+ /* link own references to the newly duplicated data [#26816] */
+ BKE_libblock_relink_to_newid(&ob->id);
- /* DAG_relations_tag_update(bmain); */ /* caller must do */
+ /* DAG_relations_tag_update(bmain); */ /* caller must do */
- if (ob->data != NULL) {
- DEG_id_tag_update_ex(bmain, (ID *)ob->data, ID_RECALC_EDITORS);
- }
+ if (ob->data != NULL) {
+ DEG_id_tag_update_ex(bmain, (ID *)ob->data, ID_RECALC_EDITORS);
+ }
- BKE_main_id_clear_newpoins(bmain);
+ BKE_main_id_clear_newpoins(bmain);
- return basen;
+ return basen;
}
/* contextual operator dupli */
static int duplicate_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const bool linked = RNA_boolean_get(op->ptr, "linked");
- int dupflag = (linked) ? 0 : U.dupflag;
+ Main *bmain = CTX_data_main(C);
+ 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;
- CTX_DATA_BEGIN (C, Base *, base, selected_bases)
- {
- Base *basen = object_add_duplicate_internal(bmain, scene, view_layer, base->object, dupflag);
+ CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
+ Base *basen = object_add_duplicate_internal(bmain, scene, view_layer, base->object, dupflag);
- /* note that this is safe to do with this context iterator,
- * the list is made in advance */
- ED_object_base_select(base, BA_DESELECT);
- ED_object_base_select(basen, BA_SELECT);
+ /* note that this is safe to do with this context iterator,
+ * the list is made in advance */
+ ED_object_base_select(base, BA_DESELECT);
+ ED_object_base_select(basen, BA_SELECT);
- if (basen == NULL) {
- continue;
- }
+ if (basen == NULL) {
+ continue;
+ }
- /* new object becomes active */
- if (BASACT(view_layer) == base)
- ED_object_base_activate(C, basen);
+ /* new object becomes active */
+ if (BASACT(view_layer) == base)
+ ED_object_base_activate(C, basen);
- if (basen->object->data) {
- DEG_id_tag_update(basen->object->data, 0);
- }
- }
- CTX_DATA_END;
+ if (basen->object->data) {
+ DEG_id_tag_update(basen->object->data, 0);
+ }
+ }
+ CTX_DATA_END;
- copy_object_set_idnew(C);
+ copy_object_set_idnew(C);
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_duplicate(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Duplicate Objects";
- ot->description = "Duplicate selected objects";
- ot->idname = "OBJECT_OT_duplicate";
+ /* identifiers */
+ ot->name = "Duplicate Objects";
+ ot->description = "Duplicate selected objects";
+ ot->idname = "OBJECT_OT_duplicate";
- /* api callbacks */
- ot->exec = duplicate_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = duplicate_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* to give to transform */
- RNA_def_boolean(ot->srna, "linked", 0, "Linked", "Duplicate object but not object data, linking to the original data");
- prop = RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ /* to give to transform */
+ RNA_def_boolean(ot->srna,
+ "linked",
+ 0,
+ "Linked",
+ "Duplicate object but not object data, linking to the original data");
+ prop = RNA_def_enum(
+ ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
/* **************** add named object, for dragdrop ************* */
static int add_named_exec(bContext *C, wmOperator *op)
{
- wmWindow *win = CTX_wm_window(C);
- const wmEvent *event = win ? win->eventstate : NULL;
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *basen;
- Object *ob;
- const bool linked = RNA_boolean_get(op->ptr, "linked");
- int dupflag = (linked) ? 0 : U.dupflag;
- char name[MAX_ID_NAME - 2];
+ wmWindow *win = CTX_wm_window(C);
+ const wmEvent *event = win ? win->eventstate : NULL;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *basen;
+ Object *ob;
+ const bool linked = RNA_boolean_get(op->ptr, "linked");
+ int dupflag = (linked) ? 0 : U.dupflag;
+ char name[MAX_ID_NAME - 2];
- /* find object, create fake base */
- RNA_string_get(op->ptr, "name", name);
- ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, name);
+ /* find object, create fake base */
+ RNA_string_get(op->ptr, "name", name);
+ ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, name);
- if (ob == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Object not found");
- return OPERATOR_CANCELLED;
- }
+ if (ob == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Object not found");
+ return OPERATOR_CANCELLED;
+ }
- /* prepare dupli */
- basen = object_add_duplicate_internal(bmain, scene, view_layer, ob, dupflag);
+ /* prepare dupli */
+ basen = object_add_duplicate_internal(bmain, scene, view_layer, ob, dupflag);
- if (basen == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated");
- return OPERATOR_CANCELLED;
- }
+ if (basen == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated");
+ return OPERATOR_CANCELLED;
+ }
- BKE_scene_object_base_flag_sync_from_object(basen);
- basen->object->restrictflag &= ~OB_RESTRICT_VIEW;
+ BKE_scene_object_base_flag_sync_from_object(basen);
+ basen->object->restrictflag &= ~OB_RESTRICT_VIEW;
- if (event) {
- ARegion *ar = CTX_wm_region(C);
- const int mval[2] = {event->x - ar->winrct.xmin,
- event->y - ar->winrct.ymin};
- ED_object_location_from_view(C, basen->object->loc);
- ED_view3d_cursor3d_position(C, mval, false, basen->object->loc);
- }
+ if (event) {
+ ARegion *ar = CTX_wm_region(C);
+ const int mval[2] = {event->x - ar->winrct.xmin, event->y - ar->winrct.ymin};
+ ED_object_location_from_view(C, basen->object->loc);
+ ED_view3d_cursor3d_position(C, mval, false, basen->object->loc);
+ }
- ED_object_base_select(basen, BA_SELECT);
- ED_object_base_activate(C, basen);
+ ED_object_base_select(basen, BA_SELECT);
+ ED_object_base_activate(C, basen);
- copy_object_set_idnew(C);
+ copy_object_set_idnew(C);
- /* TODO(sergey): Only update relations for the current scene. */
- DEG_relations_tag_update(bmain);
+ /* TODO(sergey): Only update relations for the current scene. */
+ DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_add_named(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Named Object";
- ot->description = "Add named object";
- ot->idname = "OBJECT_OT_add_named";
+ /* identifiers */
+ ot->name = "Add Named Object";
+ ot->description = "Add named object";
+ ot->idname = "OBJECT_OT_add_named";
- /* api callbacks */
- ot->exec = add_named_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = add_named_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "linked", 0, "Linked", "Duplicate object but not object data, linking to the original data");
- RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Object name to add");
+ RNA_def_boolean(ot->srna,
+ "linked",
+ 0,
+ "Linked",
+ "Duplicate object but not object data, linking to the original data");
+ RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Object name to add");
}
/**************************** Join *************************/
static bool join_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- if (!ob || ID_IS_LINKED(ob)) return 0;
+ if (!ob || ID_IS_LINKED(ob))
+ return 0;
- if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_ARMATURE, OB_GPENCIL))
- return ED_operator_screenactive(C);
- else
- return 0;
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_ARMATURE, OB_GPENCIL))
+ return ED_operator_screenactive(C);
+ else
+ return 0;
}
static int join_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
-
- if (ob->mode & OB_MODE_EDIT) {
- BKE_report(op->reports, RPT_ERROR, "This data does not support joining in edit mode");
- return OPERATOR_CANCELLED;
- }
- else if (BKE_object_obdata_is_libdata(ob)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data");
- return OPERATOR_CANCELLED;
- }
- else if (ob->type == OB_GPENCIL) {
- bGPdata *gpd = (bGPdata *)ob->data;
- if ((!gpd) || GPENCIL_ANY_MODE(gpd)) {
- BKE_report(op->reports, RPT_ERROR, "This data does not support joining in this mode");
- return OPERATOR_CANCELLED;
- }
- }
-
- if (ob->type == OB_MESH)
- return join_mesh_exec(C, op);
- else if (ELEM(ob->type, OB_CURVE, OB_SURF))
- return join_curve_exec(C, op);
- else if (ob->type == OB_ARMATURE)
- return join_armature_exec(C, op);
- else if (ob->type == OB_GPENCIL)
- return ED_gpencil_join_objects_exec(C, op);
-
- return OPERATOR_CANCELLED;
+ Object *ob = CTX_data_active_object(C);
+
+ if (ob->mode & OB_MODE_EDIT) {
+ BKE_report(op->reports, RPT_ERROR, "This data does not support joining in edit mode");
+ return OPERATOR_CANCELLED;
+ }
+ else if (BKE_object_obdata_is_libdata(ob)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data");
+ return OPERATOR_CANCELLED;
+ }
+ else if (ob->type == OB_GPENCIL) {
+ bGPdata *gpd = (bGPdata *)ob->data;
+ if ((!gpd) || GPENCIL_ANY_MODE(gpd)) {
+ BKE_report(op->reports, RPT_ERROR, "This data does not support joining in this mode");
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ if (ob->type == OB_MESH)
+ return join_mesh_exec(C, op);
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF))
+ return join_curve_exec(C, op);
+ else if (ob->type == OB_ARMATURE)
+ return join_armature_exec(C, op);
+ else if (ob->type == OB_GPENCIL)
+ return ED_gpencil_join_objects_exec(C, op);
+
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_join(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Join";
- ot->description = "Join selected objects into active object";
- ot->idname = "OBJECT_OT_join";
+ /* identifiers */
+ ot->name = "Join";
+ ot->description = "Join selected objects into active object";
+ ot->idname = "OBJECT_OT_join";
- /* api callbacks */
- ot->exec = join_exec;
- ot->poll = join_poll;
+ /* api callbacks */
+ ot->exec = join_exec;
+ ot->poll = join_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/**************************** Join as Shape Key*************************/
static bool join_shapes_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- if (!ob || ID_IS_LINKED(ob)) return 0;
+ if (!ob || ID_IS_LINKED(ob))
+ return 0;
- /* only meshes supported at the moment */
- if (ob->type == OB_MESH)
- return ED_operator_screenactive(C);
- else
- return 0;
+ /* only meshes supported at the moment */
+ if (ob->type == OB_MESH)
+ return ED_operator_screenactive(C);
+ else
+ return 0;
}
static int join_shapes_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- if (ob->mode & OB_MODE_EDIT) {
- BKE_report(op->reports, RPT_ERROR, "This data does not support joining in edit mode");
- return OPERATOR_CANCELLED;
- }
- else if (BKE_object_obdata_is_libdata(ob)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data");
- return OPERATOR_CANCELLED;
- }
+ if (ob->mode & OB_MODE_EDIT) {
+ BKE_report(op->reports, RPT_ERROR, "This data does not support joining in edit mode");
+ return OPERATOR_CANCELLED;
+ }
+ else if (BKE_object_obdata_is_libdata(ob)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot edit external library data");
+ return OPERATOR_CANCELLED;
+ }
- if (ob->type == OB_MESH)
- return join_mesh_shapes_exec(C, op);
+ if (ob->type == OB_MESH)
+ return join_mesh_shapes_exec(C, op);
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_join_shapes(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Join as Shapes";
- ot->description = "Merge selected objects to shapes of active object";
- ot->idname = "OBJECT_OT_join_shapes";
+ /* identifiers */
+ ot->name = "Join as Shapes";
+ ot->description = "Merge selected objects to shapes of active object";
+ ot->idname = "OBJECT_OT_join_shapes";
- /* api callbacks */
- ot->exec = join_shapes_exec;
- ot->poll = join_shapes_poll;
+ /* api callbacks */
+ ot->exec = join_shapes_exec;
+ ot->poll = join_shapes_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index ac1f31d0b48..f3138c5afec 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -73,18 +73,18 @@
static Image *bake_object_image_get(Object *ob, int mat_nr)
{
- Image *image = NULL;
- ED_object_get_active_image(ob, mat_nr + 1, &image, NULL, NULL, NULL);
- return image;
+ Image *image = NULL;
+ ED_object_get_active_image(ob, mat_nr + 1, &image, NULL, NULL, NULL);
+ return image;
}
static Image **bake_object_image_get_array(Object *ob)
{
- Image **image_array = MEM_mallocN(sizeof(Material *) * ob->totcol, __func__);
- for (int i = 0; i < ob->totcol; i++) {
- image_array[i] = bake_object_image_get(ob, i);
- }
- return image_array;
+ Image **image_array = MEM_mallocN(sizeof(Material *) * ob->totcol, __func__);
+ for (int i = 0; i < ob->totcol; i++) {
+ image_array[i] = bake_object_image_get(ob, i);
+ }
+ return image_array;
}
/* ****************** multires BAKING ********************** */
@@ -92,485 +92,486 @@ static Image **bake_object_image_get_array(Object *ob)
/* holder of per-object data needed for bake job
* needed to make job totally thread-safe */
typedef struct MultiresBakerJobData {
- struct MultiresBakerJobData *next, *prev;
- /* material aligned image array (for per-face bake image) */
- struct {
- Image **array;
- int len;
- } ob_image;
- DerivedMesh *lores_dm, *hires_dm;
- bool simple;
- int lvl, tot_lvl;
- ListBase images;
+ struct MultiresBakerJobData *next, *prev;
+ /* material aligned image array (for per-face bake image) */
+ struct {
+ Image **array;
+ int len;
+ } ob_image;
+ DerivedMesh *lores_dm, *hires_dm;
+ bool simple;
+ int lvl, tot_lvl;
+ ListBase images;
} MultiresBakerJobData;
/* data passing to multires-baker job */
typedef struct {
- Scene *scene;
- ListBase data;
- /** Clear the images before baking */
- bool bake_clear;
- /** Bake-filter, aka margin */
- int bake_filter;
- /** mode of baking (displacement, normals, AO) */
- short mode;
- /** Use low-resolution mesh when baking displacement maps */
- bool use_lores_mesh;
- /** Number of rays to be cast when doing AO baking */
- int number_of_rays;
- /** Bias between object and start ray point when doing AO baking */
- float bias;
- /** Number of threads to be used for baking */
- int threads;
- /** User scale used to scale displacement when baking derivative map. */
- float user_scale;
+ Scene *scene;
+ ListBase data;
+ /** Clear the images before baking */
+ bool bake_clear;
+ /** Bake-filter, aka margin */
+ int bake_filter;
+ /** mode of baking (displacement, normals, AO) */
+ short mode;
+ /** Use low-resolution mesh when baking displacement maps */
+ bool use_lores_mesh;
+ /** Number of rays to be cast when doing AO baking */
+ int number_of_rays;
+ /** Bias between object and start ray point when doing AO baking */
+ float bias;
+ /** Number of threads to be used for baking */
+ int threads;
+ /** User scale used to scale displacement when baking derivative map. */
+ float user_scale;
} MultiresBakeJob;
static bool multiresbake_check(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob;
- Mesh *me;
- MultiresModifierData *mmd;
- bool ok = true;
- int a;
-
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
- {
- ob = base->object;
-
- if (ob->type != OB_MESH) {
- BKE_report(op->reports, RPT_ERROR, "Baking of multires data only works with an active mesh object");
-
- ok = false;
- break;
- }
-
- me = (Mesh *)ob->data;
- mmd = get_multires_modifier(scene, ob, 0);
-
- /* Multi-resolution should be and be last in the stack */
- if (ok && mmd) {
- ModifierData *md;
-
- ok = mmd->totlvl > 0;
-
- for (md = (ModifierData *)mmd->modifier.next; md && ok; md = md->next) {
- if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) {
- ok = false;
- }
- }
- }
- else {
- ok = false;
- }
-
- if (!ok) {
- BKE_report(op->reports, RPT_ERROR, "Multires data baking requires multi-resolution object");
-
- break;
- }
-
- if (!me->mloopuv) {
- BKE_report(op->reports, RPT_ERROR, "Mesh should be unwrapped before multires data baking");
-
- ok = false;
- }
- else {
- a = me->totpoly;
- while (ok && a--) {
- Image *ima = bake_object_image_get(ob, me->mpoly[a].mat_nr);
-
- if (!ima) {
- BKE_report(op->reports, RPT_ERROR, "You should have active texture to use multires baker");
-
- ok = false;
- }
- else {
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
-
- if (!ibuf) {
- BKE_report(op->reports, RPT_ERROR, "Baking should happen to image with image buffer");
-
- ok = false;
- }
- else {
- if (ibuf->rect == NULL && ibuf->rect_float == NULL)
- ok = false;
-
- if (ibuf->rect_float && !(ibuf->channels == 0 || ibuf->channels == 4))
- ok = false;
-
- if (!ok)
- BKE_report(op->reports, RPT_ERROR, "Baking to unsupported image type");
- }
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
- }
- }
- }
-
- if (!ok)
- break;
- }
- CTX_DATA_END;
-
- return ok;
+ Scene *scene = CTX_data_scene(C);
+ Object *ob;
+ Mesh *me;
+ MultiresModifierData *mmd;
+ bool ok = true;
+ int a;
+
+ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
+ ob = base->object;
+
+ if (ob->type != OB_MESH) {
+ BKE_report(
+ op->reports, RPT_ERROR, "Baking of multires data only works with an active mesh object");
+
+ ok = false;
+ break;
+ }
+
+ me = (Mesh *)ob->data;
+ mmd = get_multires_modifier(scene, ob, 0);
+
+ /* Multi-resolution should be and be last in the stack */
+ if (ok && mmd) {
+ ModifierData *md;
+
+ ok = mmd->totlvl > 0;
+
+ for (md = (ModifierData *)mmd->modifier.next; md && ok; md = md->next) {
+ if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) {
+ ok = false;
+ }
+ }
+ }
+ else {
+ ok = false;
+ }
+
+ if (!ok) {
+ BKE_report(op->reports, RPT_ERROR, "Multires data baking requires multi-resolution object");
+
+ break;
+ }
+
+ if (!me->mloopuv) {
+ BKE_report(op->reports, RPT_ERROR, "Mesh should be unwrapped before multires data baking");
+
+ ok = false;
+ }
+ else {
+ a = me->totpoly;
+ while (ok && a--) {
+ Image *ima = bake_object_image_get(ob, me->mpoly[a].mat_nr);
+
+ if (!ima) {
+ BKE_report(
+ op->reports, RPT_ERROR, "You should have active texture to use multires baker");
+
+ ok = false;
+ }
+ else {
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+
+ if (!ibuf) {
+ BKE_report(op->reports, RPT_ERROR, "Baking should happen to image with image buffer");
+
+ ok = false;
+ }
+ else {
+ if (ibuf->rect == NULL && ibuf->rect_float == NULL)
+ ok = false;
+
+ if (ibuf->rect_float && !(ibuf->channels == 0 || ibuf->channels == 4))
+ ok = false;
+
+ if (!ok)
+ BKE_report(op->reports, RPT_ERROR, "Baking to unsupported image type");
+ }
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+ }
+ }
+
+ if (!ok)
+ break;
+ }
+ CTX_DATA_END;
+
+ return ok;
}
static DerivedMesh *multiresbake_create_loresdm(Scene *scene, Object *ob, int *lvl)
{
- DerivedMesh *dm;
- MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
- Mesh *me = (Mesh *)ob->data;
- MultiresModifierData tmp_mmd = *mmd;
- DerivedMesh *cddm = CDDM_from_mesh(me);
+ DerivedMesh *dm;
+ MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
+ Mesh *me = (Mesh *)ob->data;
+ MultiresModifierData tmp_mmd = *mmd;
+ DerivedMesh *cddm = CDDM_from_mesh(me);
- DM_set_only_copy(cddm, &CD_MASK_BAREMESH);
+ DM_set_only_copy(cddm, &CD_MASK_BAREMESH);
- if (mmd->lvl == 0) {
- dm = CDDM_copy(cddm);
- }
- else {
- tmp_mmd.lvl = mmd->lvl;
- tmp_mmd.sculptlvl = mmd->lvl;
- dm = multires_make_derived_from_derived(cddm, &tmp_mmd, scene, ob, 0);
- }
+ if (mmd->lvl == 0) {
+ dm = CDDM_copy(cddm);
+ }
+ else {
+ tmp_mmd.lvl = mmd->lvl;
+ tmp_mmd.sculptlvl = mmd->lvl;
+ dm = multires_make_derived_from_derived(cddm, &tmp_mmd, scene, ob, 0);
+ }
- cddm->release(cddm);
+ cddm->release(cddm);
- *lvl = mmd->lvl;
+ *lvl = mmd->lvl;
- return dm;
+ return dm;
}
static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *lvl, bool *simple)
{
- Mesh *me = (Mesh *)ob->data;
- MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
- MultiresModifierData tmp_mmd = *mmd;
- DerivedMesh *cddm = CDDM_from_mesh(me);
- DerivedMesh *dm;
+ Mesh *me = (Mesh *)ob->data;
+ MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
+ MultiresModifierData tmp_mmd = *mmd;
+ DerivedMesh *cddm = CDDM_from_mesh(me);
+ DerivedMesh *dm;
- DM_set_only_copy(cddm, &CD_MASK_BAREMESH);
+ DM_set_only_copy(cddm, &CD_MASK_BAREMESH);
- /* TODO: DM_set_only_copy wouldn't set mask for loop and poly data,
- * but we really need BAREMESH only to save lots of memory
- */
- CustomData_set_only_copy(&cddm->loopData, CD_MASK_BAREMESH.lmask);
- CustomData_set_only_copy(&cddm->polyData, CD_MASK_BAREMESH.pmask);
+ /* TODO: DM_set_only_copy wouldn't set mask for loop and poly data,
+ * but we really need BAREMESH only to save lots of memory
+ */
+ CustomData_set_only_copy(&cddm->loopData, CD_MASK_BAREMESH.lmask);
+ CustomData_set_only_copy(&cddm->polyData, CD_MASK_BAREMESH.pmask);
- *lvl = mmd->totlvl;
- *simple = mmd->simple != 0;
+ *lvl = mmd->totlvl;
+ *simple = mmd->simple != 0;
- tmp_mmd.lvl = mmd->totlvl;
- tmp_mmd.sculptlvl = mmd->totlvl;
- dm = multires_make_derived_from_derived(cddm, &tmp_mmd, scene, ob, 0);
- cddm->release(cddm);
+ tmp_mmd.lvl = mmd->totlvl;
+ tmp_mmd.sculptlvl = mmd->totlvl;
+ dm = multires_make_derived_from_derived(cddm, &tmp_mmd, scene, ob, 0);
+ cddm->release(cddm);
- return dm;
+ return dm;
}
typedef enum ClearFlag {
- CLEAR_TANGENT_NORMAL = 1,
- CLEAR_DISPLACEMENT = 2,
+ CLEAR_TANGENT_NORMAL = 1,
+ CLEAR_DISPLACEMENT = 2,
} ClearFlag;
-
static void clear_single_image(Image *image, ClearFlag flag)
{
- const float vec_alpha[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- const float vec_solid[4] = {0.0f, 0.0f, 0.0f, 1.0f};
- const float nor_alpha[4] = {0.5f, 0.5f, 1.0f, 0.0f};
- const float nor_solid[4] = {0.5f, 0.5f, 1.0f, 1.0f};
- const float disp_alpha[4] = {0.5f, 0.5f, 0.5f, 0.0f};
- const float disp_solid[4] = {0.5f, 0.5f, 0.5f, 1.0f};
-
- if ((image->id.tag & LIB_TAG_DOIT) == 0) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
-
- if (flag == CLEAR_TANGENT_NORMAL)
- IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid);
- else if (flag == CLEAR_DISPLACEMENT)
- IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? disp_alpha : disp_solid);
- else
- IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
-
- image->id.tag |= LIB_TAG_DOIT;
-
- BKE_image_release_ibuf(image, ibuf, NULL);
- }
+ const float vec_alpha[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ const float vec_solid[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ const float nor_alpha[4] = {0.5f, 0.5f, 1.0f, 0.0f};
+ const float nor_solid[4] = {0.5f, 0.5f, 1.0f, 1.0f};
+ const float disp_alpha[4] = {0.5f, 0.5f, 0.5f, 0.0f};
+ const float disp_solid[4] = {0.5f, 0.5f, 0.5f, 1.0f};
+
+ if ((image->id.tag & LIB_TAG_DOIT) == 0) {
+ ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
+
+ if (flag == CLEAR_TANGENT_NORMAL)
+ IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid);
+ else if (flag == CLEAR_DISPLACEMENT)
+ IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? disp_alpha : disp_solid);
+ else
+ IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
+
+ image->id.tag |= LIB_TAG_DOIT;
+
+ BKE_image_release_ibuf(image, ibuf, NULL);
+ }
}
static void clear_images_poly(Image **ob_image_array, int ob_image_array_len, ClearFlag flag)
{
- for (int i = 0; i < ob_image_array_len; i++) {
- Image *image = ob_image_array[i];
- if (image) {
- image->id.tag &= ~LIB_TAG_DOIT;
- }
- }
-
- for (int i = 0; i < ob_image_array_len; i++) {
- Image *image = ob_image_array[i];
- if (image) {
- clear_single_image(image, flag);
- }
- }
-
- for (int i = 0; i < ob_image_array_len; i++) {
- Image *image = ob_image_array[i];
- if (image) {
- image->id.tag &= ~LIB_TAG_DOIT;
- }
- }
+ for (int i = 0; i < ob_image_array_len; i++) {
+ Image *image = ob_image_array[i];
+ if (image) {
+ image->id.tag &= ~LIB_TAG_DOIT;
+ }
+ }
+
+ for (int i = 0; i < ob_image_array_len; i++) {
+ Image *image = ob_image_array[i];
+ if (image) {
+ clear_single_image(image, flag);
+ }
+ }
+
+ for (int i = 0; i < ob_image_array_len; i++) {
+ Image *image = ob_image_array[i];
+ if (image) {
+ image->id.tag &= ~LIB_TAG_DOIT;
+ }
+ }
}
static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
{
- Object *ob;
- Scene *scene = CTX_data_scene(C);
- int objects_baked = 0;
+ Object *ob;
+ Scene *scene = CTX_data_scene(C);
+ int objects_baked = 0;
- if (!multiresbake_check(C, op))
- return OPERATOR_CANCELLED;
+ if (!multiresbake_check(C, op))
+ return OPERATOR_CANCELLED;
- if (scene->r.bake_flag & R_BAKE_CLEAR) { /* clear images */
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
- {
- ClearFlag clear_flag = 0;
+ if (scene->r.bake_flag & R_BAKE_CLEAR) { /* clear images */
+ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
+ ClearFlag clear_flag = 0;
- ob = base->object;
- // me = (Mesh *)ob->data;
+ ob = base->object;
+ // me = (Mesh *)ob->data;
- if (scene->r.bake_mode == RE_BAKE_NORMALS) {
- clear_flag = CLEAR_TANGENT_NORMAL;
- }
- else if (scene->r.bake_mode == RE_BAKE_DISPLACEMENT) {
- clear_flag = CLEAR_DISPLACEMENT;
- }
+ if (scene->r.bake_mode == RE_BAKE_NORMALS) {
+ clear_flag = CLEAR_TANGENT_NORMAL;
+ }
+ else if (scene->r.bake_mode == RE_BAKE_DISPLACEMENT) {
+ clear_flag = CLEAR_DISPLACEMENT;
+ }
- {
- Image **ob_image_array = bake_object_image_get_array(ob);
- clear_images_poly(ob_image_array, ob->totcol, clear_flag);
- MEM_freeN(ob_image_array);
- }
- }
- CTX_DATA_END;
- }
+ {
+ Image **ob_image_array = bake_object_image_get_array(ob);
+ clear_images_poly(ob_image_array, ob->totcol, clear_flag);
+ MEM_freeN(ob_image_array);
+ }
+ }
+ CTX_DATA_END;
+ }
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
- {
- MultiresBakeRender bkr = {NULL};
+ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
+ MultiresBakeRender bkr = {NULL};
- ob = base->object;
+ ob = base->object;
- multires_force_update(ob);
+ multires_force_update(ob);
- /* copy data stored in job descriptor */
- bkr.scene = scene;
- bkr.bake_filter = scene->r.bake_filter;
- bkr.mode = scene->r.bake_mode;
- bkr.use_lores_mesh = scene->r.bake_flag & R_BAKE_LORES_MESH;
- bkr.bias = scene->r.bake_biasdist;
- bkr.number_of_rays = scene->r.bake_samples;
- bkr.threads = BKE_scene_num_threads(scene);
- bkr.user_scale = (scene->r.bake_flag & R_BAKE_USERSCALE) ? scene->r.bake_user_scale : -1.0f;
- //bkr.reports= op->reports;
+ /* copy data stored in job descriptor */
+ bkr.scene = scene;
+ bkr.bake_filter = scene->r.bake_filter;
+ bkr.mode = scene->r.bake_mode;
+ bkr.use_lores_mesh = scene->r.bake_flag & R_BAKE_LORES_MESH;
+ bkr.bias = scene->r.bake_biasdist;
+ bkr.number_of_rays = scene->r.bake_samples;
+ bkr.threads = BKE_scene_num_threads(scene);
+ bkr.user_scale = (scene->r.bake_flag & R_BAKE_USERSCALE) ? scene->r.bake_user_scale : -1.0f;
+ //bkr.reports= op->reports;
- /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
- bkr.ob_image.array = bake_object_image_get_array(ob);
- bkr.ob_image.len = ob->totcol;
+ /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
+ bkr.ob_image.array = bake_object_image_get_array(ob);
+ bkr.ob_image.len = ob->totcol;
- bkr.hires_dm = multiresbake_create_hiresdm(scene, ob, &bkr.tot_lvl, &bkr.simple);
- bkr.lores_dm = multiresbake_create_loresdm(scene, ob, &bkr.lvl);
+ bkr.hires_dm = multiresbake_create_hiresdm(scene, ob, &bkr.tot_lvl, &bkr.simple);
+ bkr.lores_dm = multiresbake_create_loresdm(scene, ob, &bkr.lvl);
- RE_multires_bake_images(&bkr);
+ RE_multires_bake_images(&bkr);
- MEM_freeN(bkr.ob_image.array);
+ MEM_freeN(bkr.ob_image.array);
- BLI_freelistN(&bkr.image);
+ BLI_freelistN(&bkr.image);
- bkr.lores_dm->release(bkr.lores_dm);
- bkr.hires_dm->release(bkr.hires_dm);
+ bkr.lores_dm->release(bkr.lores_dm);
+ bkr.hires_dm->release(bkr.hires_dm);
- objects_baked++;
- }
- CTX_DATA_END;
+ objects_baked++;
+ }
+ CTX_DATA_END;
- if (!objects_baked)
- BKE_report(op->reports, RPT_ERROR, "No objects found to bake from");
+ if (!objects_baked)
+ BKE_report(op->reports, RPT_ERROR, "No objects found to bake from");
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/* Multiresbake adopted for job-system executing */
static void init_multiresbake_job(bContext *C, MultiresBakeJob *bkj)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob;
-
- /* backup scene settings, so their changing in UI would take no effect on baker */
- bkj->scene = scene;
- bkj->bake_filter = scene->r.bake_filter;
- bkj->mode = scene->r.bake_mode;
- bkj->use_lores_mesh = scene->r.bake_flag & R_BAKE_LORES_MESH;
- bkj->bake_clear = scene->r.bake_flag & R_BAKE_CLEAR;
- bkj->bias = scene->r.bake_biasdist;
- bkj->number_of_rays = scene->r.bake_samples;
- bkj->threads = BKE_scene_num_threads(scene);
- bkj->user_scale = (scene->r.bake_flag & R_BAKE_USERSCALE) ? scene->r.bake_user_scale : -1.0f;
- //bkj->reports = op->reports;
-
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
- {
- MultiresBakerJobData *data;
- int lvl;
-
- ob = base->object;
-
- multires_force_update(ob);
-
- data = MEM_callocN(sizeof(MultiresBakerJobData), "multiresBaker derivedMesh_data");
-
- data->ob_image.array = bake_object_image_get_array(ob);
- data->ob_image.len = ob->totcol;
-
- /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
- data->hires_dm = multiresbake_create_hiresdm(scene, ob, &data->tot_lvl, &data->simple);
- data->lores_dm = multiresbake_create_loresdm(scene, ob, &lvl);
- data->lvl = lvl;
-
- BLI_addtail(&bkj->data, data);
- }
- CTX_DATA_END;
+ Scene *scene = CTX_data_scene(C);
+ Object *ob;
+
+ /* backup scene settings, so their changing in UI would take no effect on baker */
+ bkj->scene = scene;
+ bkj->bake_filter = scene->r.bake_filter;
+ bkj->mode = scene->r.bake_mode;
+ bkj->use_lores_mesh = scene->r.bake_flag & R_BAKE_LORES_MESH;
+ bkj->bake_clear = scene->r.bake_flag & R_BAKE_CLEAR;
+ bkj->bias = scene->r.bake_biasdist;
+ bkj->number_of_rays = scene->r.bake_samples;
+ bkj->threads = BKE_scene_num_threads(scene);
+ bkj->user_scale = (scene->r.bake_flag & R_BAKE_USERSCALE) ? scene->r.bake_user_scale : -1.0f;
+ //bkj->reports = op->reports;
+
+ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
+ MultiresBakerJobData *data;
+ int lvl;
+
+ ob = base->object;
+
+ multires_force_update(ob);
+
+ data = MEM_callocN(sizeof(MultiresBakerJobData), "multiresBaker derivedMesh_data");
+
+ data->ob_image.array = bake_object_image_get_array(ob);
+ data->ob_image.len = ob->totcol;
+
+ /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
+ data->hires_dm = multiresbake_create_hiresdm(scene, ob, &data->tot_lvl, &data->simple);
+ data->lores_dm = multiresbake_create_loresdm(scene, ob, &lvl);
+ data->lvl = lvl;
+
+ BLI_addtail(&bkj->data, data);
+ }
+ CTX_DATA_END;
}
static void multiresbake_startjob(void *bkv, short *stop, short *do_update, float *progress)
{
- MultiresBakerJobData *data;
- MultiresBakeJob *bkj = bkv;
- int baked_objects = 0, tot_obj;
-
- tot_obj = BLI_listbase_count(&bkj->data);
-
- if (bkj->bake_clear) { /* clear images */
- for (data = bkj->data.first; data; data = data->next) {
- ClearFlag clear_flag = 0;
-
- if (bkj->mode == RE_BAKE_NORMALS) {
- clear_flag = CLEAR_TANGENT_NORMAL;
- }
- else if (bkj->mode == RE_BAKE_DISPLACEMENT) {
- clear_flag = CLEAR_DISPLACEMENT;
- }
-
- clear_images_poly(data->ob_image.array, data->ob_image.len, clear_flag);
- }
- }
-
- for (data = bkj->data.first; data; data = data->next) {
- MultiresBakeRender bkr = {NULL};
-
- /* copy data stored in job descriptor */
- bkr.scene = bkj->scene;
- bkr.bake_filter = bkj->bake_filter;
- bkr.mode = bkj->mode;
- bkr.use_lores_mesh = bkj->use_lores_mesh;
- bkr.user_scale = bkj->user_scale;
- //bkr.reports = bkj->reports;
- bkr.ob_image.array = data->ob_image.array;
- bkr.ob_image.len = data->ob_image.len;
-
- /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
- bkr.lores_dm = data->lores_dm;
- bkr.hires_dm = data->hires_dm;
- bkr.tot_lvl = data->tot_lvl;
- bkr.lvl = data->lvl;
- bkr.simple = data->simple;
-
- /* needed for proper progress bar */
- bkr.tot_obj = tot_obj;
- bkr.baked_objects = baked_objects;
-
- bkr.stop = stop;
- bkr.do_update = do_update;
- bkr.progress = progress;
-
- bkr.bias = bkj->bias;
- bkr.number_of_rays = bkj->number_of_rays;
- bkr.threads = bkj->threads;
-
- RE_multires_bake_images(&bkr);
-
- data->images = bkr.image;
-
- baked_objects++;
- }
+ MultiresBakerJobData *data;
+ MultiresBakeJob *bkj = bkv;
+ int baked_objects = 0, tot_obj;
+
+ tot_obj = BLI_listbase_count(&bkj->data);
+
+ if (bkj->bake_clear) { /* clear images */
+ for (data = bkj->data.first; data; data = data->next) {
+ ClearFlag clear_flag = 0;
+
+ if (bkj->mode == RE_BAKE_NORMALS) {
+ clear_flag = CLEAR_TANGENT_NORMAL;
+ }
+ else if (bkj->mode == RE_BAKE_DISPLACEMENT) {
+ clear_flag = CLEAR_DISPLACEMENT;
+ }
+
+ clear_images_poly(data->ob_image.array, data->ob_image.len, clear_flag);
+ }
+ }
+
+ for (data = bkj->data.first; data; data = data->next) {
+ MultiresBakeRender bkr = {NULL};
+
+ /* copy data stored in job descriptor */
+ bkr.scene = bkj->scene;
+ bkr.bake_filter = bkj->bake_filter;
+ bkr.mode = bkj->mode;
+ bkr.use_lores_mesh = bkj->use_lores_mesh;
+ bkr.user_scale = bkj->user_scale;
+ //bkr.reports = bkj->reports;
+ bkr.ob_image.array = data->ob_image.array;
+ bkr.ob_image.len = data->ob_image.len;
+
+ /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
+ bkr.lores_dm = data->lores_dm;
+ bkr.hires_dm = data->hires_dm;
+ bkr.tot_lvl = data->tot_lvl;
+ bkr.lvl = data->lvl;
+ bkr.simple = data->simple;
+
+ /* needed for proper progress bar */
+ bkr.tot_obj = tot_obj;
+ bkr.baked_objects = baked_objects;
+
+ bkr.stop = stop;
+ bkr.do_update = do_update;
+ bkr.progress = progress;
+
+ bkr.bias = bkj->bias;
+ bkr.number_of_rays = bkj->number_of_rays;
+ bkr.threads = bkj->threads;
+
+ RE_multires_bake_images(&bkr);
+
+ data->images = bkr.image;
+
+ baked_objects++;
+ }
}
static void multiresbake_freejob(void *bkv)
{
- MultiresBakeJob *bkj = bkv;
- MultiresBakerJobData *data, *next;
- LinkData *link;
+ MultiresBakeJob *bkj = bkv;
+ MultiresBakerJobData *data, *next;
+ LinkData *link;
- data = bkj->data.first;
- while (data) {
- next = data->next;
- data->lores_dm->release(data->lores_dm);
- data->hires_dm->release(data->hires_dm);
+ data = bkj->data.first;
+ while (data) {
+ next = data->next;
+ data->lores_dm->release(data->lores_dm);
+ data->hires_dm->release(data->hires_dm);
- /* delete here, since this delete will be called from main thread */
- for (link = data->images.first; link; link = link->next) {
- Image *ima = (Image *)link->data;
- GPU_free_image(ima);
- }
+ /* delete here, since this delete will be called from main thread */
+ for (link = data->images.first; link; link = link->next) {
+ Image *ima = (Image *)link->data;
+ GPU_free_image(ima);
+ }
- MEM_freeN(data->ob_image.array);
+ MEM_freeN(data->ob_image.array);
- BLI_freelistN(&data->images);
+ BLI_freelistN(&data->images);
- MEM_freeN(data);
- data = next;
- }
+ MEM_freeN(data);
+ data = next;
+ }
- MEM_freeN(bkj);
+ MEM_freeN(bkj);
}
static int multiresbake_image_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- MultiresBakeJob *bkr;
- wmJob *wm_job;
+ Scene *scene = CTX_data_scene(C);
+ MultiresBakeJob *bkr;
+ wmJob *wm_job;
- if (!multiresbake_check(C, op))
- return OPERATOR_CANCELLED;
+ if (!multiresbake_check(C, op))
+ return OPERATOR_CANCELLED;
- bkr = MEM_callocN(sizeof(MultiresBakeJob), "MultiresBakeJob data");
- init_multiresbake_job(C, bkr);
+ bkr = MEM_callocN(sizeof(MultiresBakeJob), "MultiresBakeJob data");
+ init_multiresbake_job(C, bkr);
- if (!bkr->data.first) {
- BKE_report(op->reports, RPT_ERROR, "No objects found to bake from");
- return OPERATOR_CANCELLED;
- }
+ if (!bkr->data.first) {
+ BKE_report(op->reports, RPT_ERROR, "No objects found to bake from");
+ return OPERATOR_CANCELLED;
+ }
- /* setup job */
- wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Multires Bake",
- WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_BAKE_TEXTURE);
- WM_jobs_customdata_set(wm_job, bkr, multiresbake_freejob);
- WM_jobs_timer(wm_job, 0.5, NC_IMAGE, 0); /* TODO - only draw bake image, can we enforce this */
- WM_jobs_callbacks(wm_job, multiresbake_startjob, NULL, NULL, NULL);
+ /* setup job */
+ wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ scene,
+ "Multires Bake",
+ WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS,
+ WM_JOB_TYPE_OBJECT_BAKE_TEXTURE);
+ WM_jobs_customdata_set(wm_job, bkr, multiresbake_freejob);
+ WM_jobs_timer(wm_job, 0.5, NC_IMAGE, 0); /* TODO - only draw bake image, can we enforce this */
+ WM_jobs_callbacks(wm_job, multiresbake_startjob, NULL, NULL, NULL);
- G.is_break = false;
+ G.is_break = false;
- WM_jobs_start(CTX_wm_manager(C), wm_job);
- WM_cursor_wait(0);
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+ WM_cursor_wait(0);
- /* add modal handler for ESC */
- WM_event_add_modal_handler(C, op);
+ /* add modal handler for ESC */
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
/* ****************** render BAKING ********************** */
@@ -578,66 +579,65 @@ static int multiresbake_image_exec(bContext *C, wmOperator *op)
/* catch esc */
static int objects_bake_render_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- /* no running blender, remove handler and pass through */
- if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_OBJECT_BAKE_TEXTURE))
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
-
- /* running render */
- switch (event->type) {
- case ESCKEY:
- return OPERATOR_RUNNING_MODAL;
- }
- return OPERATOR_PASS_THROUGH;
+ /* no running blender, remove handler and pass through */
+ if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_OBJECT_BAKE_TEXTURE))
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+
+ /* running render */
+ switch (event->type) {
+ case ESCKEY:
+ return OPERATOR_RUNNING_MODAL;
+ }
+ return OPERATOR_PASS_THROUGH;
}
static bool is_multires_bake(Scene *scene)
{
- if (ELEM(scene->r.bake_mode, RE_BAKE_NORMALS, RE_BAKE_DISPLACEMENT, RE_BAKE_AO))
- return scene->r.bake_flag & R_BAKE_MULTIRES;
+ if (ELEM(scene->r.bake_mode, RE_BAKE_NORMALS, RE_BAKE_DISPLACEMENT, RE_BAKE_AO))
+ return scene->r.bake_flag & R_BAKE_MULTIRES;
- return 0;
+ return 0;
}
static int objects_bake_render_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(_event))
{
- Scene *scene = CTX_data_scene(C);
- int result = OPERATOR_CANCELLED;
+ Scene *scene = CTX_data_scene(C);
+ int result = OPERATOR_CANCELLED;
- result = multiresbake_image_exec(C, op);
+ result = multiresbake_image_exec(C, op);
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);
- return result;
+ return result;
}
-
static int bake_image_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- int result = OPERATOR_CANCELLED;
+ Scene *scene = CTX_data_scene(C);
+ int result = OPERATOR_CANCELLED;
- if (!is_multires_bake(scene)) {
- BLI_assert(0);
- return result;
- }
+ if (!is_multires_bake(scene)) {
+ BLI_assert(0);
+ return result;
+ }
- result = multiresbake_image_exec_locked(C, op);
+ result = multiresbake_image_exec_locked(C, op);
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);
- return result;
+ return result;
}
void OBJECT_OT_bake_image(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Bake";
- ot->description = "Bake image textures of selected objects";
- ot->idname = "OBJECT_OT_bake_image";
-
- /* api callbacks */
- ot->exec = bake_image_exec;
- ot->invoke = objects_bake_render_invoke;
- ot->modal = objects_bake_render_modal;
- ot->poll = ED_operator_object_active;
+ /* identifiers */
+ ot->name = "Bake";
+ ot->description = "Bake image textures of selected objects";
+ ot->idname = "OBJECT_OT_bake_image";
+
+ /* api callbacks */
+ ot->exec = bake_image_exec;
+ ot->invoke = objects_bake_render_invoke;
+ ot->modal = objects_bake_render_modal;
+ ot->poll = ED_operator_object_active;
}
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index e3e3f3d10ef..fba5a4e281e 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include "MEM_guardedalloc.h"
#include "DNA_object_types.h"
@@ -77,517 +76,584 @@
static void bake_set_props(wmOperator *op, Scene *scene);
typedef struct BakeAPIRender {
- Object *ob;
- Main *main;
- Scene *scene;
- ViewLayer *view_layer;
- ReportList *reports;
- ListBase selected_objects;
-
- eScenePassType pass_type;
- int pass_filter;
- int margin;
-
- int save_mode;
-
- bool is_clear;
- bool is_split_materials;
- bool is_automatic_name;
- bool is_selected_to_active;
- bool is_cage;
-
- float cage_extrusion;
- int normal_space;
- eBakeNormalSwizzle normal_swizzle[3];
-
- char uv_layer[MAX_CUSTOMDATA_LAYER_NAME];
- char custom_cage[MAX_NAME];
- char filepath[FILE_MAX];
-
- int width;
- int height;
- const char *identifier;
-
- int result;
- bool ready;
-
- /* callbacks */
- Render *render;
- float *progress;
- short *do_update;
-
- /* for redrawing */
- ScrArea *sa;
+ Object *ob;
+ Main *main;
+ Scene *scene;
+ ViewLayer *view_layer;
+ ReportList *reports;
+ ListBase selected_objects;
+
+ eScenePassType pass_type;
+ int pass_filter;
+ int margin;
+
+ int save_mode;
+
+ bool is_clear;
+ bool is_split_materials;
+ bool is_automatic_name;
+ bool is_selected_to_active;
+ bool is_cage;
+
+ float cage_extrusion;
+ int normal_space;
+ eBakeNormalSwizzle normal_swizzle[3];
+
+ char uv_layer[MAX_CUSTOMDATA_LAYER_NAME];
+ char custom_cage[MAX_NAME];
+ char filepath[FILE_MAX];
+
+ int width;
+ int height;
+ const char *identifier;
+
+ int result;
+ bool ready;
+
+ /* callbacks */
+ Render *render;
+ float *progress;
+ short *do_update;
+
+ /* for redrawing */
+ ScrArea *sa;
} BakeAPIRender;
/* callbacks */
static void bake_progress_update(void *bjv, float progress)
{
- BakeAPIRender *bj = bjv;
+ BakeAPIRender *bj = bjv;
- if (bj->progress && *bj->progress != progress) {
- *bj->progress = progress;
+ if (bj->progress && *bj->progress != progress) {
+ *bj->progress = progress;
- /* make jobs timer to send notifier */
- *(bj->do_update) = true;
- }
+ /* make jobs timer to send notifier */
+ *(bj->do_update) = true;
+ }
}
/* catch esc */
static int bake_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
- /* no running blender, remove handler and pass through */
- if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_OBJECT_BAKE))
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
-
- /* running render */
- switch (event->type) {
- case ESCKEY:
- {
- G.is_break = true;
- return OPERATOR_RUNNING_MODAL;
- }
- }
- return OPERATOR_PASS_THROUGH;
+ /* no running blender, remove handler and pass through */
+ if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_OBJECT_BAKE))
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+
+ /* running render */
+ switch (event->type) {
+ case ESCKEY: {
+ G.is_break = true;
+ return OPERATOR_RUNNING_MODAL;
+ }
+ }
+ return OPERATOR_PASS_THROUGH;
}
/* for exec() when there is no render job
* note: this wont check for the escape key being pressed, but doing so isnt threadsafe */
static int bake_break(void *UNUSED(rjv))
{
- if (G.is_break)
- return 1;
- return 0;
+ if (G.is_break)
+ return 1;
+ return 0;
}
-
static void bake_update_image(ScrArea *sa, Image *image)
{
- if (sa && sa->spacetype == SPACE_IMAGE) { /* in case the user changed while baking */
- SpaceImage *sima = sa->spacedata.first;
- if (sima)
- sima->image = image;
- }
+ if (sa && sa->spacetype == SPACE_IMAGE) { /* in case the user changed while baking */
+ SpaceImage *sima = sa->spacedata.first;
+ if (sima)
+ sima->image = image;
+ }
}
-static bool write_internal_bake_pixels(
- Image *image, BakePixel pixel_array[], float *buffer,
- const int width, const int height, const int margin,
- const bool is_clear, const bool is_noncolor)
+static bool write_internal_bake_pixels(Image *image,
+ BakePixel pixel_array[],
+ float *buffer,
+ const int width,
+ const int height,
+ const int margin,
+ const bool is_clear,
+ const bool is_noncolor)
{
- ImBuf *ibuf;
- void *lock;
- bool is_float;
- char *mask_buffer = NULL;
- const size_t num_pixels = (size_t)width * (size_t)height;
-
- ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
-
- if (!ibuf)
- return false;
-
- if (margin > 0 || !is_clear) {
- mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask");
- RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer);
- }
-
- is_float = (ibuf->rect_float != NULL);
-
- /* colormanagement conversions */
- if (!is_noncolor) {
- const char *from_colorspace;
- const char *to_colorspace;
-
- from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
-
- if (is_float)
- to_colorspace = IMB_colormanagement_get_float_colorspace(ibuf);
- else
- to_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf);
-
- if (from_colorspace != to_colorspace)
- IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, false);
- }
-
- /* populates the ImBuf */
- if (is_clear) {
- if (is_float) {
- IMB_buffer_float_from_float(
- ibuf->rect_float, buffer, ibuf->channels,
- IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false,
- ibuf->x, ibuf->y, ibuf->x, ibuf->x);
- }
- else {
- IMB_buffer_byte_from_float(
- (unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither,
- IB_PROFILE_SRGB, IB_PROFILE_SRGB,
- false, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
- }
- }
- else {
- if (is_float) {
- IMB_buffer_float_from_float_mask(
- ibuf->rect_float, buffer, ibuf->channels,
- ibuf->x, ibuf->y, ibuf->x, ibuf->x, mask_buffer);
- }
- else {
- IMB_buffer_byte_from_float_mask(
- (unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither,
- false, ibuf->x, ibuf->y, ibuf->x, ibuf->x, mask_buffer);
- }
- }
-
- /* margins */
- if (margin > 0)
- RE_bake_margin(ibuf, mask_buffer, margin);
-
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID | IB_BITMAPDIRTY;
-
- if (ibuf->rect_float)
- ibuf->userflags |= IB_RECT_INVALID;
-
- /* force mipmap recalc */
- if (ibuf->mipmap[0]) {
- ibuf->userflags |= IB_MIPMAP_INVALID;
- imb_freemipmapImBuf(ibuf);
- }
-
- BKE_image_release_ibuf(image, ibuf, NULL);
-
- if (mask_buffer)
- MEM_freeN(mask_buffer);
-
- return true;
+ ImBuf *ibuf;
+ void *lock;
+ bool is_float;
+ char *mask_buffer = NULL;
+ const size_t num_pixels = (size_t)width * (size_t)height;
+
+ ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
+
+ if (!ibuf)
+ return false;
+
+ if (margin > 0 || !is_clear) {
+ mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask");
+ RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer);
+ }
+
+ is_float = (ibuf->rect_float != NULL);
+
+ /* colormanagement conversions */
+ if (!is_noncolor) {
+ const char *from_colorspace;
+ const char *to_colorspace;
+
+ from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
+
+ if (is_float)
+ to_colorspace = IMB_colormanagement_get_float_colorspace(ibuf);
+ else
+ to_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf);
+
+ if (from_colorspace != to_colorspace)
+ IMB_colormanagement_transform(
+ buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, false);
+ }
+
+ /* populates the ImBuf */
+ if (is_clear) {
+ if (is_float) {
+ IMB_buffer_float_from_float(ibuf->rect_float,
+ buffer,
+ ibuf->channels,
+ IB_PROFILE_LINEAR_RGB,
+ IB_PROFILE_LINEAR_RGB,
+ false,
+ ibuf->x,
+ ibuf->y,
+ ibuf->x,
+ ibuf->x);
+ }
+ else {
+ IMB_buffer_byte_from_float((unsigned char *)ibuf->rect,
+ buffer,
+ ibuf->channels,
+ ibuf->dither,
+ IB_PROFILE_SRGB,
+ IB_PROFILE_SRGB,
+ false,
+ ibuf->x,
+ ibuf->y,
+ ibuf->x,
+ ibuf->x);
+ }
+ }
+ else {
+ if (is_float) {
+ IMB_buffer_float_from_float_mask(ibuf->rect_float,
+ buffer,
+ ibuf->channels,
+ ibuf->x,
+ ibuf->y,
+ ibuf->x,
+ ibuf->x,
+ mask_buffer);
+ }
+ else {
+ IMB_buffer_byte_from_float_mask((unsigned char *)ibuf->rect,
+ buffer,
+ ibuf->channels,
+ ibuf->dither,
+ false,
+ ibuf->x,
+ ibuf->y,
+ ibuf->x,
+ ibuf->x,
+ mask_buffer);
+ }
+ }
+
+ /* margins */
+ if (margin > 0)
+ RE_bake_margin(ibuf, mask_buffer, margin);
+
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID | IB_BITMAPDIRTY;
+
+ if (ibuf->rect_float)
+ ibuf->userflags |= IB_RECT_INVALID;
+
+ /* force mipmap recalc */
+ if (ibuf->mipmap[0]) {
+ ibuf->userflags |= IB_MIPMAP_INVALID;
+ imb_freemipmapImBuf(ibuf);
+ }
+
+ BKE_image_release_ibuf(image, ibuf, NULL);
+
+ if (mask_buffer)
+ MEM_freeN(mask_buffer);
+
+ return true;
}
/* force OpenGL reload */
static void refresh_images(BakeImages *bake_images)
{
- int i;
- for (i = 0; i < bake_images->size; i++) {
- Image *ima = bake_images->data[i].image;
- if (ima->ok == IMA_OK_LOADED) {
- GPU_free_image(ima);
- DEG_id_tag_update(&ima->id, 0);
- }
- }
+ int i;
+ for (i = 0; i < bake_images->size; i++) {
+ Image *ima = bake_images->data[i].image;
+ if (ima->ok == IMA_OK_LOADED) {
+ GPU_free_image(ima);
+ DEG_id_tag_update(&ima->id, 0);
+ }
+ }
}
-static bool write_external_bake_pixels(
- const char *filepath, BakePixel pixel_array[], float *buffer,
- const int width, const int height, const int margin,
- ImageFormatData *im_format, const bool is_noncolor)
+static bool write_external_bake_pixels(const char *filepath,
+ BakePixel pixel_array[],
+ float *buffer,
+ const int width,
+ const int height,
+ const int margin,
+ ImageFormatData *im_format,
+ const bool is_noncolor)
{
- ImBuf *ibuf = NULL;
- bool ok = false;
- bool is_float;
-
- is_float = im_format->depth > 8;
-
- /* create a new ImBuf */
- ibuf = IMB_allocImBuf(width, height, im_format->planes, (is_float ? IB_rectfloat : IB_rect));
-
- if (!ibuf)
- return false;
-
- /* populates the ImBuf */
- if (is_float) {
- IMB_buffer_float_from_float(
- ibuf->rect_float, buffer, ibuf->channels,
- IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, false,
- ibuf->x, ibuf->y, ibuf->x, ibuf->x);
- }
- else {
- if (!is_noncolor) {
- const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
- const char *to_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf);
- IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, false);
- }
-
- IMB_buffer_byte_from_float(
- (unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither,
- IB_PROFILE_SRGB, IB_PROFILE_SRGB,
- false, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
- }
-
- /* margins */
- if (margin > 0) {
- char *mask_buffer = NULL;
- const size_t num_pixels = (size_t)width * (size_t)height;
-
- mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask");
- RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer);
- RE_bake_margin(ibuf, mask_buffer, margin);
-
- if (mask_buffer)
- MEM_freeN(mask_buffer);
- }
-
- if ((ok = BKE_imbuf_write(ibuf, filepath, im_format))) {
+ ImBuf *ibuf = NULL;
+ bool ok = false;
+ bool is_float;
+
+ is_float = im_format->depth > 8;
+
+ /* create a new ImBuf */
+ ibuf = IMB_allocImBuf(width, height, im_format->planes, (is_float ? IB_rectfloat : IB_rect));
+
+ if (!ibuf)
+ return false;
+
+ /* populates the ImBuf */
+ if (is_float) {
+ IMB_buffer_float_from_float(ibuf->rect_float,
+ buffer,
+ ibuf->channels,
+ IB_PROFILE_LINEAR_RGB,
+ IB_PROFILE_LINEAR_RGB,
+ false,
+ ibuf->x,
+ ibuf->y,
+ ibuf->x,
+ ibuf->x);
+ }
+ else {
+ if (!is_noncolor) {
+ const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(
+ COLOR_ROLE_SCENE_LINEAR);
+ const char *to_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf);
+ IMB_colormanagement_transform(
+ buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, false);
+ }
+
+ IMB_buffer_byte_from_float((unsigned char *)ibuf->rect,
+ buffer,
+ ibuf->channels,
+ ibuf->dither,
+ IB_PROFILE_SRGB,
+ IB_PROFILE_SRGB,
+ false,
+ ibuf->x,
+ ibuf->y,
+ ibuf->x,
+ ibuf->x);
+ }
+
+ /* margins */
+ if (margin > 0) {
+ char *mask_buffer = NULL;
+ const size_t num_pixels = (size_t)width * (size_t)height;
+
+ mask_buffer = MEM_callocN(sizeof(char) * num_pixels, "Bake Mask");
+ RE_bake_mask_fill(pixel_array, num_pixels, mask_buffer);
+ RE_bake_margin(ibuf, mask_buffer, margin);
+
+ if (mask_buffer)
+ MEM_freeN(mask_buffer);
+ }
+
+ if ((ok = BKE_imbuf_write(ibuf, filepath, im_format))) {
#ifndef WIN32
- chmod(filepath, S_IRUSR | S_IWUSR);
+ chmod(filepath, S_IRUSR | S_IWUSR);
#endif
- //printf("%s saving bake map: '%s'\n", __func__, filepath);
- }
+ //printf("%s saving bake map: '%s'\n", __func__, filepath);
+ }
- /* garbage collection */
- IMB_freeImBuf(ibuf);
+ /* garbage collection */
+ IMB_freeImBuf(ibuf);
- return ok;
+ return ok;
}
static bool is_noncolor_pass(eScenePassType pass_type)
{
- return ELEM(pass_type,
- SCE_PASS_Z,
- SCE_PASS_NORMAL,
- SCE_PASS_VECTOR,
- SCE_PASS_INDEXOB,
- SCE_PASS_UV,
- SCE_PASS_RAYHITS,
- SCE_PASS_INDEXMA);
+ return ELEM(pass_type,
+ SCE_PASS_Z,
+ SCE_PASS_NORMAL,
+ SCE_PASS_VECTOR,
+ SCE_PASS_INDEXOB,
+ SCE_PASS_UV,
+ SCE_PASS_RAYHITS,
+ SCE_PASS_INDEXMA);
}
/* if all is good tag image and return true */
static bool bake_object_check(ViewLayer *view_layer, Object *ob, ReportList *reports)
{
- Image *image;
- Base *base = BKE_view_layer_base_find(view_layer, ob);
- void *lock;
- int i;
-
- if (base == NULL) {
- BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not in view layer", ob->id.name + 2);
- return false;
- }
-
- if (!(base->flag & BASE_ENABLED_RENDER)) {
- BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not enabled for rendering", ob->id.name + 2);
- return false;
- }
-
-
- if (ob->type != OB_MESH) {
- BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not a mesh", ob->id.name + 2);
- return false;
- }
- else {
- Mesh *me = (Mesh *)ob->data;
-
- if (CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV) == -1) {
- BKE_reportf(reports, RPT_ERROR,
- "No active UV layer found in the object \"%s\"", ob->id.name + 2);
- return false;
- }
- }
-
- for (i = 0; i < ob->totcol; i++) {
- bNodeTree *ntree = NULL;
- bNode *node = NULL;
- ED_object_get_active_image(ob, i + 1, &image, NULL, &node, &ntree);
-
- if (image) {
- ImBuf *ibuf;
-
- if (node) {
- if (BKE_node_is_connected_to_output(ntree, node)) {
- /* we don't return false since this may be a false positive
- * this can't be RPT_ERROR though, otherwise it prevents
- * multiple highpoly objects to be baked at once */
- BKE_reportf(reports, RPT_INFO,
- "Circular dependency for image \"%s\" from object \"%s\"",
- image->id.name + 2, ob->id.name + 2);
- }
- }
-
- ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
-
- if (ibuf) {
- BKE_image_release_ibuf(image, ibuf, lock);
- }
- else {
- BKE_reportf(reports, RPT_ERROR,
- "Uninitialized image \"%s\" from object \"%s\"",
- image->id.name + 2, ob->id.name + 2);
-
- BKE_image_release_ibuf(image, ibuf, lock);
- return false;
- }
- }
- else {
- Material *mat = give_current_material(ob, i);
- if (mat != NULL) {
- BKE_reportf(reports, RPT_INFO,
- "No active image found in material \"%s\" (%d) for object \"%s\"",
- mat->id.name + 2, i, ob->id.name + 2);
- }
- else {
- BKE_reportf(reports, RPT_INFO,
- "No active image found in material slot (%d) for object \"%s\"",
- i, ob->id.name + 2);
- }
- continue;
- }
-
- image->id.tag |= LIB_TAG_DOIT;
- }
- return true;
+ Image *image;
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+ void *lock;
+ int i;
+
+ if (base == NULL) {
+ BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not in view layer", ob->id.name + 2);
+ return false;
+ }
+
+ if (!(base->flag & BASE_ENABLED_RENDER)) {
+ BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not enabled for rendering", ob->id.name + 2);
+ return false;
+ }
+
+ if (ob->type != OB_MESH) {
+ BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not a mesh", ob->id.name + 2);
+ return false;
+ }
+ else {
+ Mesh *me = (Mesh *)ob->data;
+
+ if (CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV) == -1) {
+ BKE_reportf(
+ reports, RPT_ERROR, "No active UV layer found in the object \"%s\"", ob->id.name + 2);
+ return false;
+ }
+ }
+
+ for (i = 0; i < ob->totcol; i++) {
+ bNodeTree *ntree = NULL;
+ bNode *node = NULL;
+ ED_object_get_active_image(ob, i + 1, &image, NULL, &node, &ntree);
+
+ if (image) {
+ ImBuf *ibuf;
+
+ if (node) {
+ if (BKE_node_is_connected_to_output(ntree, node)) {
+ /* we don't return false since this may be a false positive
+ * this can't be RPT_ERROR though, otherwise it prevents
+ * multiple highpoly objects to be baked at once */
+ BKE_reportf(reports,
+ RPT_INFO,
+ "Circular dependency for image \"%s\" from object \"%s\"",
+ image->id.name + 2,
+ ob->id.name + 2);
+ }
+ }
+
+ ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
+
+ if (ibuf) {
+ BKE_image_release_ibuf(image, ibuf, lock);
+ }
+ else {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Uninitialized image \"%s\" from object \"%s\"",
+ image->id.name + 2,
+ ob->id.name + 2);
+
+ BKE_image_release_ibuf(image, ibuf, lock);
+ return false;
+ }
+ }
+ else {
+ Material *mat = give_current_material(ob, i);
+ if (mat != NULL) {
+ BKE_reportf(reports,
+ RPT_INFO,
+ "No active image found in material \"%s\" (%d) for object \"%s\"",
+ mat->id.name + 2,
+ i,
+ ob->id.name + 2);
+ }
+ else {
+ BKE_reportf(reports,
+ RPT_INFO,
+ "No active image found in material slot (%d) for object \"%s\"",
+ i,
+ ob->id.name + 2);
+ }
+ continue;
+ }
+
+ image->id.tag |= LIB_TAG_DOIT;
+ }
+ return true;
}
-static bool bake_pass_filter_check(eScenePassType pass_type, const int pass_filter, ReportList *reports)
+static bool bake_pass_filter_check(eScenePassType pass_type,
+ const int pass_filter,
+ ReportList *reports)
{
- switch (pass_type) {
- case SCE_PASS_COMBINED:
- if ((pass_filter & R_BAKE_PASS_FILTER_EMIT) != 0) {
- return true;
- }
-
- if (((pass_filter & R_BAKE_PASS_FILTER_DIRECT) != 0) ||
- ((pass_filter & R_BAKE_PASS_FILTER_INDIRECT) != 0))
- {
- if (((pass_filter & R_BAKE_PASS_FILTER_DIFFUSE) != 0) ||
- ((pass_filter & R_BAKE_PASS_FILTER_GLOSSY) != 0) ||
- ((pass_filter & R_BAKE_PASS_FILTER_TRANSM) != 0) ||
- ((pass_filter & R_BAKE_PASS_FILTER_SUBSURFACE) != 0))
- {
- return true;
- }
-
- if ((pass_filter & R_BAKE_PASS_FILTER_AO) != 0) {
- BKE_report(reports, RPT_ERROR,
- "Combined bake pass Ambient Occlusion contribution requires an enabled light pass "
- "(bake the Ambient Occlusion pass type instead)");
- }
- else {
- BKE_report(reports, RPT_ERROR,
- "Combined bake pass requires Emit, or a light pass with "
- "Direct or Indirect contributions enabled");
- }
-
- return false;
- }
- else {
- BKE_report(reports, RPT_ERROR,
- "Combined bake pass requires Emit, or a light pass with "
- "Direct or Indirect contributions enabled");
- return false;
- }
- break;
- case SCE_PASS_DIFFUSE_COLOR:
- case SCE_PASS_GLOSSY_COLOR:
- case SCE_PASS_TRANSM_COLOR:
- case SCE_PASS_SUBSURFACE_COLOR:
- if (((pass_filter & R_BAKE_PASS_FILTER_COLOR) != 0) ||
- ((pass_filter & R_BAKE_PASS_FILTER_DIRECT) != 0) ||
- ((pass_filter & R_BAKE_PASS_FILTER_INDIRECT) != 0))
- {
- return true;
- }
- else {
- BKE_report(reports, RPT_ERROR,
- "Bake pass requires Direct, Indirect, or Color contributions to be enabled");
- return false;
- }
- break;
- default:
- return true;
- break;
- }
+ switch (pass_type) {
+ case SCE_PASS_COMBINED:
+ if ((pass_filter & R_BAKE_PASS_FILTER_EMIT) != 0) {
+ return true;
+ }
+
+ if (((pass_filter & R_BAKE_PASS_FILTER_DIRECT) != 0) ||
+ ((pass_filter & R_BAKE_PASS_FILTER_INDIRECT) != 0)) {
+ if (((pass_filter & R_BAKE_PASS_FILTER_DIFFUSE) != 0) ||
+ ((pass_filter & R_BAKE_PASS_FILTER_GLOSSY) != 0) ||
+ ((pass_filter & R_BAKE_PASS_FILTER_TRANSM) != 0) ||
+ ((pass_filter & R_BAKE_PASS_FILTER_SUBSURFACE) != 0)) {
+ return true;
+ }
+
+ if ((pass_filter & R_BAKE_PASS_FILTER_AO) != 0) {
+ BKE_report(
+ reports,
+ RPT_ERROR,
+ "Combined bake pass Ambient Occlusion contribution requires an enabled light pass "
+ "(bake the Ambient Occlusion pass type instead)");
+ }
+ else {
+ BKE_report(reports,
+ RPT_ERROR,
+ "Combined bake pass requires Emit, or a light pass with "
+ "Direct or Indirect contributions enabled");
+ }
+
+ return false;
+ }
+ else {
+ BKE_report(reports,
+ RPT_ERROR,
+ "Combined bake pass requires Emit, or a light pass with "
+ "Direct or Indirect contributions enabled");
+ return false;
+ }
+ break;
+ case SCE_PASS_DIFFUSE_COLOR:
+ case SCE_PASS_GLOSSY_COLOR:
+ case SCE_PASS_TRANSM_COLOR:
+ case SCE_PASS_SUBSURFACE_COLOR:
+ if (((pass_filter & R_BAKE_PASS_FILTER_COLOR) != 0) ||
+ ((pass_filter & R_BAKE_PASS_FILTER_DIRECT) != 0) ||
+ ((pass_filter & R_BAKE_PASS_FILTER_INDIRECT) != 0)) {
+ return true;
+ }
+ else {
+ BKE_report(reports,
+ RPT_ERROR,
+ "Bake pass requires Direct, Indirect, or Color contributions to be enabled");
+ return false;
+ }
+ break;
+ default:
+ return true;
+ break;
+ }
}
/* before even getting in the bake function we check for some basic errors */
-static bool bake_objects_check(Main *bmain, ViewLayer *view_layer, Object *ob, ListBase *selected_objects,
- ReportList *reports, const bool is_selected_to_active)
+static bool bake_objects_check(Main *bmain,
+ ViewLayer *view_layer,
+ Object *ob,
+ ListBase *selected_objects,
+ ReportList *reports,
+ const bool is_selected_to_active)
{
- CollectionPointerLink *link;
-
- /* error handling and tag (in case multiple materials share the same image) */
- BKE_main_id_tag_idcode(bmain, ID_IM, LIB_TAG_DOIT, false);
-
- if (is_selected_to_active) {
- int tot_objects = 0;
-
- if (!bake_object_check(view_layer, ob, reports))
- return false;
-
- for (link = selected_objects->first; link; link = link->next) {
- Object *ob_iter = (Object *)link->ptr.data;
-
- if (ob_iter == ob)
- continue;
-
- if (ELEM(ob_iter->type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL) == false) {
- BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not a mesh or can't be converted to a mesh (Curve, Text, Surface or Metaball)", ob_iter->id.name + 2);
- return false;
- }
- tot_objects += 1;
- }
-
- if (tot_objects == 0) {
- BKE_report(reports, RPT_ERROR, "No valid selected objects");
- return false;
- }
- }
- else {
- if (BLI_listbase_is_empty(selected_objects)) {
- BKE_report(reports, RPT_ERROR, "No valid selected objects");
- return false;
- }
-
- for (link = selected_objects->first; link; link = link->next) {
- if (!bake_object_check(view_layer, link->ptr.data, reports))
- return false;
- }
- }
- return true;
+ CollectionPointerLink *link;
+
+ /* error handling and tag (in case multiple materials share the same image) */
+ BKE_main_id_tag_idcode(bmain, ID_IM, LIB_TAG_DOIT, false);
+
+ if (is_selected_to_active) {
+ int tot_objects = 0;
+
+ if (!bake_object_check(view_layer, ob, reports))
+ return false;
+
+ for (link = selected_objects->first; link; link = link->next) {
+ Object *ob_iter = (Object *)link->ptr.data;
+
+ if (ob_iter == ob)
+ continue;
+
+ if (ELEM(ob_iter->type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL) == false) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Object \"%s\" is not a mesh or can't be converted to a mesh (Curve, Text, "
+ "Surface or Metaball)",
+ ob_iter->id.name + 2);
+ return false;
+ }
+ tot_objects += 1;
+ }
+
+ if (tot_objects == 0) {
+ BKE_report(reports, RPT_ERROR, "No valid selected objects");
+ return false;
+ }
+ }
+ else {
+ if (BLI_listbase_is_empty(selected_objects)) {
+ BKE_report(reports, RPT_ERROR, "No valid selected objects");
+ return false;
+ }
+
+ for (link = selected_objects->first; link; link = link->next) {
+ if (!bake_object_check(view_layer, link->ptr.data, reports))
+ return false;
+ }
+ }
+ return true;
}
/* it needs to be called after bake_objects_check since the image tagging happens there */
static void bake_images_clear(Main *bmain, const bool is_tangent)
{
- Image *image;
- for (image = bmain->images.first; image; image = image->id.next) {
- if ((image->id.tag & LIB_TAG_DOIT) != 0) {
- RE_bake_ibuf_clear(image, is_tangent);
- }
- }
+ Image *image;
+ for (image = bmain->images.first; image; image = image->id.next) {
+ if ((image->id.tag & LIB_TAG_DOIT) != 0) {
+ RE_bake_ibuf_clear(image, is_tangent);
+ }
+ }
}
static void build_image_lookup(Main *bmain, Object *ob, BakeImages *bake_images)
{
- const int tot_mat = ob->totcol;
- int i, j;
- int tot_images = 0;
-
- /* error handling and tag (in case multiple materials share the same image) */
- BKE_main_id_tag_idcode(bmain, ID_IM, LIB_TAG_DOIT, false);
-
- for (i = 0; i < tot_mat; i++) {
- Image *image;
- ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
-
- /* Some materials have no image, we just ignore those cases. */
- if (image == NULL) {
- bake_images->lookup[i] = -1;
- }
- else if (image->id.tag & LIB_TAG_DOIT) {
- for (j = 0; j < i; j++) {
- if (bake_images->data[j].image == image) {
- bake_images->lookup[i] = j;
- break;
- }
- }
- }
- else {
- bake_images->lookup[i] = tot_images;
- bake_images->data[tot_images].image = image;
- image->id.tag |= LIB_TAG_DOIT;
- tot_images++;
- }
- }
-
- bake_images->size = tot_images;
+ const int tot_mat = ob->totcol;
+ int i, j;
+ int tot_images = 0;
+
+ /* error handling and tag (in case multiple materials share the same image) */
+ BKE_main_id_tag_idcode(bmain, ID_IM, LIB_TAG_DOIT, false);
+
+ for (i = 0; i < tot_mat; i++) {
+ Image *image;
+ ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
+
+ /* Some materials have no image, we just ignore those cases. */
+ if (image == NULL) {
+ bake_images->lookup[i] = -1;
+ }
+ else if (image->id.tag & LIB_TAG_DOIT) {
+ for (j = 0; j < i; j++) {
+ if (bake_images->data[j].image == image) {
+ bake_images->lookup[i] = j;
+ break;
+ }
+ }
+ }
+ else {
+ bake_images->lookup[i] = tot_images;
+ bake_images->data[tot_images].image = image;
+ image->id.tag |= LIB_TAG_DOIT;
+ tot_images++;
+ }
+ }
+
+ bake_images->size = tot_images;
}
/*
@@ -595,881 +661,1130 @@ static void build_image_lookup(Main *bmain, Object *ob, BakeImages *bake_images)
*/
static size_t initialize_internal_images(BakeImages *bake_images, ReportList *reports)
{
- int i;
- size_t tot_size = 0;
-
- for (i = 0; i < bake_images->size; i++) {
- ImBuf *ibuf;
- void *lock;
-
- BakeImage *bk_image = &bake_images->data[i];
- ibuf = BKE_image_acquire_ibuf(bk_image->image, NULL, &lock);
-
- if (ibuf) {
- bk_image->width = ibuf->x;
- bk_image->height = ibuf->y;
- bk_image->offset = tot_size;
-
- tot_size += (size_t)ibuf->x * (size_t)ibuf->y;
- }
- else {
- BKE_image_release_ibuf(bk_image->image, ibuf, lock);
- BKE_reportf(reports, RPT_ERROR, "Uninitialized image %s", bk_image->image->id.name + 2);
- return 0;
- }
- BKE_image_release_ibuf(bk_image->image, ibuf, lock);
- }
- return tot_size;
+ int i;
+ size_t tot_size = 0;
+
+ for (i = 0; i < bake_images->size; i++) {
+ ImBuf *ibuf;
+ void *lock;
+
+ BakeImage *bk_image = &bake_images->data[i];
+ ibuf = BKE_image_acquire_ibuf(bk_image->image, NULL, &lock);
+
+ if (ibuf) {
+ bk_image->width = ibuf->x;
+ bk_image->height = ibuf->y;
+ bk_image->offset = tot_size;
+
+ tot_size += (size_t)ibuf->x * (size_t)ibuf->y;
+ }
+ else {
+ BKE_image_release_ibuf(bk_image->image, ibuf, lock);
+ BKE_reportf(reports, RPT_ERROR, "Uninitialized image %s", bk_image->image->id.name + 2);
+ return 0;
+ }
+ BKE_image_release_ibuf(bk_image->image, ibuf, lock);
+ }
+ return tot_size;
}
/* create new mesh with edit mode changes and modifiers applied */
static Mesh *bake_mesh_new_from_object(Depsgraph *depsgraph, Main *bmain, Scene *scene, Object *ob)
{
- bool apply_modifiers = (ob->type != OB_MESH);
- Mesh *me = BKE_mesh_new_from_object(depsgraph, bmain, scene, ob, apply_modifiers, false);
+ bool apply_modifiers = (ob->type != OB_MESH);
+ Mesh *me = BKE_mesh_new_from_object(depsgraph, bmain, scene, ob, apply_modifiers, false);
- if (me->flag & ME_AUTOSMOOTH) {
- BKE_mesh_split_faces(me, true);
- }
+ if (me->flag & ME_AUTOSMOOTH) {
+ BKE_mesh_split_faces(me, true);
+ }
- return me;
+ return me;
}
-static int bake(
- Render *re, Main *bmain, Scene *scene, ViewLayer *view_layer, Object *ob_low, ListBase *selected_objects,
- ReportList *reports,
- const eScenePassType pass_type, const int pass_filter, const int margin,
- const eBakeSaveMode save_mode, const bool is_clear, const bool is_split_materials,
- const bool is_automatic_name, const bool is_selected_to_active, const bool is_cage,
- const float cage_extrusion, const int normal_space, const eBakeNormalSwizzle normal_swizzle[],
- const char *custom_cage, const char *filepath, const int width, const int height,
- const char *identifier, ScrArea *sa, const char *uv_layer)
+static int bake(Render *re,
+ Main *bmain,
+ Scene *scene,
+ ViewLayer *view_layer,
+ Object *ob_low,
+ ListBase *selected_objects,
+ ReportList *reports,
+ const eScenePassType pass_type,
+ const int pass_filter,
+ const int margin,
+ const eBakeSaveMode save_mode,
+ const bool is_clear,
+ const bool is_split_materials,
+ const bool is_automatic_name,
+ const bool is_selected_to_active,
+ const bool is_cage,
+ const float cage_extrusion,
+ const int normal_space,
+ const eBakeNormalSwizzle normal_swizzle[],
+ const char *custom_cage,
+ const char *filepath,
+ const int width,
+ const int height,
+ const char *identifier,
+ ScrArea *sa,
+ const char *uv_layer)
{
- /* We build a depsgraph for the baking,
- * so we don't need to change the original data to adjust visibility and modifiers. */
- Depsgraph *depsgraph = DEG_graph_new(scene, view_layer, DAG_EVAL_RENDER);
- DEG_graph_build_from_view_layer(depsgraph, bmain, scene, view_layer);
-
- int op_result = OPERATOR_CANCELLED;
- bool ok = false;
-
- Object *ob_cage = NULL;
- Object *ob_cage_eval = NULL;
- Object *ob_low_eval = NULL;
-
- BakeHighPolyData *highpoly = NULL;
- int tot_highpoly = 0;
-
- Mesh *me_low = NULL;
- Mesh *me_cage = NULL;
-
- MultiresModifierData *mmd_low = NULL;
- int mmd_flags_low = 0;
-
- float *result = NULL;
-
- BakePixel *pixel_array_low = NULL;
- BakePixel *pixel_array_high = NULL;
-
- const bool is_save_internal = (save_mode == R_BAKE_SAVE_INTERNAL);
- const bool is_noncolor = is_noncolor_pass(pass_type);
- const int depth = RE_pass_depth(pass_type);
-
- BakeImages bake_images = {NULL};
-
- size_t num_pixels;
- int tot_materials;
-
- RE_bake_engine_set_engine_parameters(re, bmain, scene);
-
- if (!RE_bake_has_engine(re)) {
- BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
- goto cleanup;
- }
-
- tot_materials = ob_low->totcol;
-
- if (uv_layer && uv_layer[0] != '\0') {
- Mesh *me = (Mesh *)ob_low->data;
- if (CustomData_get_named_layer(&me->ldata, CD_MLOOPUV, uv_layer) == -1) {
- BKE_reportf(reports, RPT_ERROR,
- "No UV layer named \"%s\" found in the object \"%s\"", uv_layer, ob_low->id.name + 2);
- goto cleanup;
- }
- }
-
- if (tot_materials == 0) {
- if (is_save_internal) {
- BKE_report(reports, RPT_ERROR,
- "No active image found, add a material or bake to an external file");
-
- goto cleanup;
- }
- else if (is_split_materials) {
- BKE_report(reports, RPT_ERROR,
- "No active image found, add a material or bake without the Split Materials option");
-
- goto cleanup;
- }
- else {
- /* baking externally without splitting materials */
- tot_materials = 1;
- }
- }
-
- /* we overallocate in case there is more materials than images */
- bake_images.data = MEM_mallocN(sizeof(BakeImage) * tot_materials, "bake images dimensions (width, height, offset)");
- bake_images.lookup = MEM_mallocN(sizeof(int) * tot_materials, "bake images lookup (from material to BakeImage)");
-
- build_image_lookup(bmain, ob_low, &bake_images);
-
- if (is_save_internal) {
- num_pixels = initialize_internal_images(&bake_images, reports);
-
- if (num_pixels == 0) {
- goto cleanup;
- }
- }
- else {
- /* when saving externally always use the size specified in the UI */
-
- num_pixels = (size_t)width * (size_t)height * bake_images.size;
-
- for (int i = 0; i < bake_images.size; i++) {
- bake_images.data[i].width = width;
- bake_images.data[i].height = height;
- bake_images.data[i].offset = (is_split_materials ? num_pixels : 0);
- bake_images.data[i].image = NULL;
- }
-
- if (!is_split_materials) {
- /* saving a single image */
- for (int i = 0; i < tot_materials; i++) {
- bake_images.lookup[i] = 0;
- }
- }
- }
-
- if (is_selected_to_active) {
- CollectionPointerLink *link;
- tot_highpoly = 0;
-
- for (link = selected_objects->first; link; link = link->next) {
- Object *ob_iter = link->ptr.data;
-
- if (ob_iter == ob_low)
- continue;
-
- tot_highpoly ++;
- }
-
- if (is_cage && custom_cage[0] != '\0') {
- ob_cage = BLI_findstring(&bmain->objects, custom_cage, offsetof(ID, name) + 2);
-
- if (ob_cage == NULL || ob_cage->type != OB_MESH) {
- BKE_report(reports, RPT_ERROR, "No valid cage object");
- goto cleanup;
- }
- else {
- ob_cage_eval = DEG_get_evaluated_object(depsgraph, ob_cage);
- ob_cage_eval->restrictflag |= OB_RESTRICT_RENDER;
- ob_cage_eval->base_flag &= ~(BASE_VISIBLE | BASE_ENABLED_RENDER);
- }
- }
- }
-
- pixel_array_low = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels low poly");
- pixel_array_high = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels high poly");
- result = MEM_callocN(sizeof(float) * depth * num_pixels, "bake return pixels");
-
- /* for multires bake, use linear UV subdivision to match low res UVs */
- if (pass_type == SCE_PASS_NORMAL && normal_space == R_BAKE_SPACE_TANGENT && !is_selected_to_active) {
- mmd_low = (MultiresModifierData *) modifiers_findByType(ob_low, eModifierType_Multires);
- if (mmd_low) {
- mmd_flags_low = mmd_low->flags;
- mmd_low->uv_smooth = SUBSURF_UV_SMOOTH_NONE;
- }
- }
-
- /* Make sure depsgraph is up to date. */
- BKE_scene_graph_update_tagged(depsgraph, bmain);
- ob_low_eval = DEG_get_evaluated_object(depsgraph, ob_low);
-
- /* get the mesh as it arrives in the renderer */
- me_low = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_low_eval);
-
- /* populate the pixel array with the face data */
- if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false)
- RE_bake_pixels_populate(me_low, pixel_array_low, num_pixels, &bake_images, uv_layer);
- /* else populate the pixel array with the 'cage' mesh (the smooth version of the mesh) */
-
- if (is_selected_to_active) {
- CollectionPointerLink *link;
- int i = 0;
-
- /* prepare cage mesh */
- if (ob_cage) {
- me_cage = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_cage_eval);
- if ((me_low->totpoly != me_cage->totpoly) || (me_low->totloop != me_cage->totloop)) {
- BKE_report(reports, RPT_ERROR,
- "Invalid cage object, the cage mesh must have the same number "
- "of faces as the active object");
- goto cleanup;
- }
- }
- else if (is_cage) {
- BKE_object_eval_reset(ob_low_eval);
-
- ModifierData *md = ob_low_eval->modifiers.first;
- while (md) {
- ModifierData *md_next = md->next;
-
- /* Edge Split cannot be applied in the cage,
- * the cage is supposed to have interpolated normals
- * between the faces unless the geometry is physically
- * split. So we create a copy of the low poly mesh without
- * the eventual edge split.*/
-
- if (md->type == eModifierType_EdgeSplit) {
- BLI_remlink(&ob_low_eval->modifiers, md);
- modifier_free(md);
- }
- md = md_next;
- }
-
- me_cage = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_low_eval);
- RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer);
- }
-
- highpoly = MEM_callocN(sizeof(BakeHighPolyData) * tot_highpoly, "bake high poly objects");
-
- /* populate highpoly array */
- for (link = selected_objects->first; link; link = link->next) {
- Object *ob_iter = link->ptr.data;
-
- if (ob_iter == ob_low)
- continue;
-
- /* initialize highpoly_data */
- highpoly[i].ob = ob_iter;
- highpoly[i].ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter);
- highpoly[i].ob_eval->restrictflag &= ~OB_RESTRICT_RENDER;
- highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE | BASE_ENABLED_RENDER);
- highpoly[i].me = bake_mesh_new_from_object(depsgraph, bmain, scene, highpoly[i].ob_eval);
-
- /* lowpoly to highpoly transformation matrix */
- copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat);
- invert_m4_m4(highpoly[i].imat, highpoly[i].obmat);
-
- highpoly[i].is_flip_object = is_negative_m4(highpoly[i].ob->obmat);
-
- i++;
- }
-
- BLI_assert(i == tot_highpoly);
-
-
- if (ob_cage != NULL) {
- ob_cage_eval->restrictflag |= OB_RESTRICT_RENDER;
- ob_cage_eval->base_flag &= ~(BASE_VISIBLE | BASE_ENABLED_RENDER);
- }
- ob_low_eval->restrictflag |= OB_RESTRICT_RENDER;
- ob_low_eval->base_flag &= ~(BASE_VISIBLE | BASE_ENABLED_RENDER);
-
- /* populate the pixel arrays with the corresponding face data for each high poly object */
- if (!RE_bake_pixels_populate_from_objects(
- me_low, pixel_array_low, pixel_array_high, highpoly, tot_highpoly, num_pixels, ob_cage != NULL,
- cage_extrusion, ob_low_eval->obmat, (ob_cage ? ob_cage->obmat : ob_low_eval->obmat), me_cage))
- {
- BKE_report(reports, RPT_ERROR, "Error handling selected objects");
- goto cleanup;
- }
-
- /* the baking itself */
- for (i = 0; i < tot_highpoly; i++) {
- ok = RE_bake_engine(re, depsgraph, highpoly[i].ob, i, pixel_array_high,
- num_pixels, depth, pass_type, pass_filter, result);
- if (!ok) {
- BKE_reportf(reports, RPT_ERROR, "Error baking from object \"%s\"", highpoly[i].ob->id.name + 2);
- goto cleanup;
- }
- }
- }
- else {
- /* If low poly is not renderable it should have failed long ago. */
- BLI_assert((ob_low_eval->restrictflag & OB_RESTRICT_RENDER) == 0);
-
- if (RE_bake_has_engine(re)) {
- ok = RE_bake_engine(re, depsgraph, ob_low_eval, 0, pixel_array_low, num_pixels, depth, pass_type, pass_filter, result);
- }
- else {
- BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
- goto cleanup;
- }
- }
-
- /* normal space conversion
- * the normals are expected to be in world space, +X +Y +Z */
- if (ok && pass_type == SCE_PASS_NORMAL) {
- switch (normal_space) {
- case R_BAKE_SPACE_WORLD:
- {
- /* Cycles internal format */
- if ((normal_swizzle[0] == R_BAKE_POSX) &&
- (normal_swizzle[1] == R_BAKE_POSY) &&
- (normal_swizzle[2] == R_BAKE_POSZ))
- {
- break;
- }
- else {
- RE_bake_normal_world_to_world(pixel_array_low, num_pixels, depth, result, normal_swizzle);
- }
- break;
- }
- case R_BAKE_SPACE_OBJECT:
- {
- RE_bake_normal_world_to_object(pixel_array_low, num_pixels, depth, result, ob_low_eval, normal_swizzle);
- break;
- }
- case R_BAKE_SPACE_TANGENT:
- {
- if (is_selected_to_active) {
- RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_low, normal_swizzle, ob_low_eval->obmat);
- }
- else {
- /* from multiresolution */
- Mesh *me_nores = NULL;
- ModifierData *md = NULL;
- int mode;
-
- BKE_object_eval_reset(ob_low_eval);
- md = modifiers_findByType(ob_low_eval, eModifierType_Multires);
-
- if (md) {
- mode = md->mode;
- md->mode &= ~eModifierMode_Render;
- }
-
- /* Evaluate modifiers again. */
- me_nores = BKE_mesh_new_from_object(depsgraph, bmain, scene, ob_low_eval, true, false);
- RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer);
-
- RE_bake_normal_world_to_tangent(pixel_array_low, num_pixels, depth, result, me_nores, normal_swizzle, ob_low_eval->obmat);
- BKE_id_free(bmain, me_nores);
-
- if (md)
- md->mode = mode;
- }
- break;
- }
- default:
- break;
- }
- }
-
- if (!ok) {
- BKE_reportf(reports, RPT_ERROR, "Problem baking object \"%s\"", ob_low->id.name + 2);
- op_result = OPERATOR_CANCELLED;
- }
- else {
- /* save the results */
- for (int i = 0; i < bake_images.size; i++) {
- BakeImage *bk_image = &bake_images.data[i];
-
- if (is_save_internal) {
- ok = write_internal_bake_pixels(
- bk_image->image,
- pixel_array_low + bk_image->offset,
- result + bk_image->offset * depth,
- bk_image->width, bk_image->height,
- margin, is_clear, is_noncolor);
-
- /* might be read by UI to set active image for display */
- bake_update_image(sa, bk_image->image);
-
- if (!ok) {
- BKE_reportf(reports, RPT_ERROR,
- "Problem saving the bake map internally for object \"%s\"", ob_low->id.name + 2);
- op_result = OPERATOR_CANCELLED;
- }
- else {
- BKE_report(reports, RPT_INFO,
- "Baking map saved to internal image, save it externally or pack it");
- op_result = OPERATOR_FINISHED;
- }
- }
- /* save externally */
- else {
- BakeData *bake = &scene->r.bake;
- char name[FILE_MAX];
-
- BKE_image_path_from_imtype(name, filepath, BKE_main_blendfile_path(bmain),
- 0, bake->im_format.imtype, true, false, NULL);
-
- if (is_automatic_name) {
- BLI_path_suffix(name, FILE_MAX, ob_low->id.name + 2, "_");
- BLI_path_suffix(name, FILE_MAX, identifier, "_");
- }
-
- if (is_split_materials) {
- if (bk_image->image) {
- BLI_path_suffix(name, FILE_MAX, bk_image->image->id.name + 2, "_");
- }
- else {
- if (ob_low_eval->mat[i]) {
- BLI_path_suffix(name, FILE_MAX, ob_low_eval->mat[i]->id.name + 2, "_");
- }
- else if (me_low->mat[i]) {
- BLI_path_suffix(name, FILE_MAX, me_low->mat[i]->id.name + 2, "_");
- }
- else {
- /* if everything else fails, use the material index */
- char tmp[5];
- sprintf(tmp, "%d", i % 1000);
- BLI_path_suffix(name, FILE_MAX, tmp, "_");
- }
- }
- }
-
- /* save it externally */
- ok = write_external_bake_pixels(
- name,
- pixel_array_low + bk_image->offset,
- result + bk_image->offset * depth,
- bk_image->width, bk_image->height,
- margin, &bake->im_format, is_noncolor);
-
- if (!ok) {
- BKE_reportf(reports, RPT_ERROR, "Problem saving baked map in \"%s\"", name);
- op_result = OPERATOR_CANCELLED;
- }
- else {
- BKE_reportf(reports, RPT_INFO, "Baking map written to \"%s\"", name);
- op_result = OPERATOR_FINISHED;
- }
-
- if (!is_split_materials) {
- break;
- }
- }
- }
- }
-
- if (is_save_internal)
- refresh_images(&bake_images);
+ /* We build a depsgraph for the baking,
+ * so we don't need to change the original data to adjust visibility and modifiers. */
+ Depsgraph *depsgraph = DEG_graph_new(scene, view_layer, DAG_EVAL_RENDER);
+ DEG_graph_build_from_view_layer(depsgraph, bmain, scene, view_layer);
+
+ int op_result = OPERATOR_CANCELLED;
+ bool ok = false;
+
+ Object *ob_cage = NULL;
+ Object *ob_cage_eval = NULL;
+ Object *ob_low_eval = NULL;
+
+ BakeHighPolyData *highpoly = NULL;
+ int tot_highpoly = 0;
+
+ Mesh *me_low = NULL;
+ Mesh *me_cage = NULL;
+
+ MultiresModifierData *mmd_low = NULL;
+ int mmd_flags_low = 0;
+
+ float *result = NULL;
+
+ BakePixel *pixel_array_low = NULL;
+ BakePixel *pixel_array_high = NULL;
+
+ const bool is_save_internal = (save_mode == R_BAKE_SAVE_INTERNAL);
+ const bool is_noncolor = is_noncolor_pass(pass_type);
+ const int depth = RE_pass_depth(pass_type);
+
+ BakeImages bake_images = {NULL};
+
+ size_t num_pixels;
+ int tot_materials;
+
+ RE_bake_engine_set_engine_parameters(re, bmain, scene);
+
+ if (!RE_bake_has_engine(re)) {
+ BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
+ goto cleanup;
+ }
+
+ tot_materials = ob_low->totcol;
+
+ if (uv_layer && uv_layer[0] != '\0') {
+ Mesh *me = (Mesh *)ob_low->data;
+ if (CustomData_get_named_layer(&me->ldata, CD_MLOOPUV, uv_layer) == -1) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "No UV layer named \"%s\" found in the object \"%s\"",
+ uv_layer,
+ ob_low->id.name + 2);
+ goto cleanup;
+ }
+ }
+
+ if (tot_materials == 0) {
+ if (is_save_internal) {
+ BKE_report(
+ reports, RPT_ERROR, "No active image found, add a material or bake to an external file");
+
+ goto cleanup;
+ }
+ else if (is_split_materials) {
+ BKE_report(
+ reports,
+ RPT_ERROR,
+ "No active image found, add a material or bake without the Split Materials option");
+
+ goto cleanup;
+ }
+ else {
+ /* baking externally without splitting materials */
+ tot_materials = 1;
+ }
+ }
+
+ /* we overallocate in case there is more materials than images */
+ bake_images.data = MEM_mallocN(sizeof(BakeImage) * tot_materials,
+ "bake images dimensions (width, height, offset)");
+ bake_images.lookup = MEM_mallocN(sizeof(int) * tot_materials,
+ "bake images lookup (from material to BakeImage)");
+
+ build_image_lookup(bmain, ob_low, &bake_images);
+
+ if (is_save_internal) {
+ num_pixels = initialize_internal_images(&bake_images, reports);
+
+ if (num_pixels == 0) {
+ goto cleanup;
+ }
+ }
+ else {
+ /* when saving externally always use the size specified in the UI */
+
+ num_pixels = (size_t)width * (size_t)height * bake_images.size;
+
+ for (int i = 0; i < bake_images.size; i++) {
+ bake_images.data[i].width = width;
+ bake_images.data[i].height = height;
+ bake_images.data[i].offset = (is_split_materials ? num_pixels : 0);
+ bake_images.data[i].image = NULL;
+ }
+
+ if (!is_split_materials) {
+ /* saving a single image */
+ for (int i = 0; i < tot_materials; i++) {
+ bake_images.lookup[i] = 0;
+ }
+ }
+ }
+
+ if (is_selected_to_active) {
+ CollectionPointerLink *link;
+ tot_highpoly = 0;
+
+ for (link = selected_objects->first; link; link = link->next) {
+ Object *ob_iter = link->ptr.data;
+
+ if (ob_iter == ob_low)
+ continue;
+
+ tot_highpoly++;
+ }
+
+ if (is_cage && custom_cage[0] != '\0') {
+ ob_cage = BLI_findstring(&bmain->objects, custom_cage, offsetof(ID, name) + 2);
+
+ if (ob_cage == NULL || ob_cage->type != OB_MESH) {
+ BKE_report(reports, RPT_ERROR, "No valid cage object");
+ goto cleanup;
+ }
+ else {
+ ob_cage_eval = DEG_get_evaluated_object(depsgraph, ob_cage);
+ ob_cage_eval->restrictflag |= OB_RESTRICT_RENDER;
+ ob_cage_eval->base_flag &= ~(BASE_VISIBLE | BASE_ENABLED_RENDER);
+ }
+ }
+ }
+
+ pixel_array_low = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels low poly");
+ pixel_array_high = MEM_mallocN(sizeof(BakePixel) * num_pixels, "bake pixels high poly");
+ result = MEM_callocN(sizeof(float) * depth * num_pixels, "bake return pixels");
+
+ /* for multires bake, use linear UV subdivision to match low res UVs */
+ if (pass_type == SCE_PASS_NORMAL && normal_space == R_BAKE_SPACE_TANGENT &&
+ !is_selected_to_active) {
+ mmd_low = (MultiresModifierData *)modifiers_findByType(ob_low, eModifierType_Multires);
+ if (mmd_low) {
+ mmd_flags_low = mmd_low->flags;
+ mmd_low->uv_smooth = SUBSURF_UV_SMOOTH_NONE;
+ }
+ }
+
+ /* Make sure depsgraph is up to date. */
+ BKE_scene_graph_update_tagged(depsgraph, bmain);
+ ob_low_eval = DEG_get_evaluated_object(depsgraph, ob_low);
+
+ /* get the mesh as it arrives in the renderer */
+ me_low = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_low_eval);
+
+ /* populate the pixel array with the face data */
+ if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false)
+ RE_bake_pixels_populate(me_low, pixel_array_low, num_pixels, &bake_images, uv_layer);
+ /* else populate the pixel array with the 'cage' mesh (the smooth version of the mesh) */
+
+ if (is_selected_to_active) {
+ CollectionPointerLink *link;
+ int i = 0;
+
+ /* prepare cage mesh */
+ if (ob_cage) {
+ me_cage = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_cage_eval);
+ if ((me_low->totpoly != me_cage->totpoly) || (me_low->totloop != me_cage->totloop)) {
+ BKE_report(reports,
+ RPT_ERROR,
+ "Invalid cage object, the cage mesh must have the same number "
+ "of faces as the active object");
+ goto cleanup;
+ }
+ }
+ else if (is_cage) {
+ BKE_object_eval_reset(ob_low_eval);
+
+ ModifierData *md = ob_low_eval->modifiers.first;
+ while (md) {
+ ModifierData *md_next = md->next;
+
+ /* Edge Split cannot be applied in the cage,
+ * the cage is supposed to have interpolated normals
+ * between the faces unless the geometry is physically
+ * split. So we create a copy of the low poly mesh without
+ * the eventual edge split.*/
+
+ if (md->type == eModifierType_EdgeSplit) {
+ BLI_remlink(&ob_low_eval->modifiers, md);
+ modifier_free(md);
+ }
+ md = md_next;
+ }
+
+ me_cage = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_low_eval);
+ RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer);
+ }
+
+ highpoly = MEM_callocN(sizeof(BakeHighPolyData) * tot_highpoly, "bake high poly objects");
+
+ /* populate highpoly array */
+ for (link = selected_objects->first; link; link = link->next) {
+ Object *ob_iter = link->ptr.data;
+
+ if (ob_iter == ob_low)
+ continue;
+
+ /* initialize highpoly_data */
+ highpoly[i].ob = ob_iter;
+ highpoly[i].ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter);
+ highpoly[i].ob_eval->restrictflag &= ~OB_RESTRICT_RENDER;
+ highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE | BASE_ENABLED_RENDER);
+ highpoly[i].me = bake_mesh_new_from_object(depsgraph, bmain, scene, highpoly[i].ob_eval);
+
+ /* lowpoly to highpoly transformation matrix */
+ copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat);
+ invert_m4_m4(highpoly[i].imat, highpoly[i].obmat);
+
+ highpoly[i].is_flip_object = is_negative_m4(highpoly[i].ob->obmat);
+
+ i++;
+ }
+
+ BLI_assert(i == tot_highpoly);
+
+ if (ob_cage != NULL) {
+ ob_cage_eval->restrictflag |= OB_RESTRICT_RENDER;
+ ob_cage_eval->base_flag &= ~(BASE_VISIBLE | BASE_ENABLED_RENDER);
+ }
+ ob_low_eval->restrictflag |= OB_RESTRICT_RENDER;
+ ob_low_eval->base_flag &= ~(BASE_VISIBLE | BASE_ENABLED_RENDER);
+
+ /* populate the pixel arrays with the corresponding face data for each high poly object */
+ if (!RE_bake_pixels_populate_from_objects(me_low,
+ pixel_array_low,
+ pixel_array_high,
+ highpoly,
+ tot_highpoly,
+ num_pixels,
+ ob_cage != NULL,
+ cage_extrusion,
+ ob_low_eval->obmat,
+ (ob_cage ? ob_cage->obmat : ob_low_eval->obmat),
+ me_cage)) {
+ BKE_report(reports, RPT_ERROR, "Error handling selected objects");
+ goto cleanup;
+ }
+
+ /* the baking itself */
+ for (i = 0; i < tot_highpoly; i++) {
+ ok = RE_bake_engine(re,
+ depsgraph,
+ highpoly[i].ob,
+ i,
+ pixel_array_high,
+ num_pixels,
+ depth,
+ pass_type,
+ pass_filter,
+ result);
+ if (!ok) {
+ BKE_reportf(
+ reports, RPT_ERROR, "Error baking from object \"%s\"", highpoly[i].ob->id.name + 2);
+ goto cleanup;
+ }
+ }
+ }
+ else {
+ /* If low poly is not renderable it should have failed long ago. */
+ BLI_assert((ob_low_eval->restrictflag & OB_RESTRICT_RENDER) == 0);
+
+ if (RE_bake_has_engine(re)) {
+ ok = RE_bake_engine(re,
+ depsgraph,
+ ob_low_eval,
+ 0,
+ pixel_array_low,
+ num_pixels,
+ depth,
+ pass_type,
+ pass_filter,
+ result);
+ }
+ else {
+ BKE_report(reports, RPT_ERROR, "Current render engine does not support baking");
+ goto cleanup;
+ }
+ }
+
+ /* normal space conversion
+ * the normals are expected to be in world space, +X +Y +Z */
+ if (ok && pass_type == SCE_PASS_NORMAL) {
+ switch (normal_space) {
+ case R_BAKE_SPACE_WORLD: {
+ /* Cycles internal format */
+ if ((normal_swizzle[0] == R_BAKE_POSX) && (normal_swizzle[1] == R_BAKE_POSY) &&
+ (normal_swizzle[2] == R_BAKE_POSZ)) {
+ break;
+ }
+ else {
+ RE_bake_normal_world_to_world(
+ pixel_array_low, num_pixels, depth, result, normal_swizzle);
+ }
+ break;
+ }
+ case R_BAKE_SPACE_OBJECT: {
+ RE_bake_normal_world_to_object(
+ pixel_array_low, num_pixels, depth, result, ob_low_eval, normal_swizzle);
+ break;
+ }
+ case R_BAKE_SPACE_TANGENT: {
+ if (is_selected_to_active) {
+ RE_bake_normal_world_to_tangent(pixel_array_low,
+ num_pixels,
+ depth,
+ result,
+ me_low,
+ normal_swizzle,
+ ob_low_eval->obmat);
+ }
+ else {
+ /* from multiresolution */
+ Mesh *me_nores = NULL;
+ ModifierData *md = NULL;
+ int mode;
+
+ BKE_object_eval_reset(ob_low_eval);
+ md = modifiers_findByType(ob_low_eval, eModifierType_Multires);
+
+ if (md) {
+ mode = md->mode;
+ md->mode &= ~eModifierMode_Render;
+ }
+
+ /* Evaluate modifiers again. */
+ me_nores = BKE_mesh_new_from_object(depsgraph, bmain, scene, ob_low_eval, true, false);
+ RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer);
+
+ RE_bake_normal_world_to_tangent(pixel_array_low,
+ num_pixels,
+ depth,
+ result,
+ me_nores,
+ normal_swizzle,
+ ob_low_eval->obmat);
+ BKE_id_free(bmain, me_nores);
+
+ if (md)
+ md->mode = mode;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ if (!ok) {
+ BKE_reportf(reports, RPT_ERROR, "Problem baking object \"%s\"", ob_low->id.name + 2);
+ op_result = OPERATOR_CANCELLED;
+ }
+ else {
+ /* save the results */
+ for (int i = 0; i < bake_images.size; i++) {
+ BakeImage *bk_image = &bake_images.data[i];
+
+ if (is_save_internal) {
+ ok = write_internal_bake_pixels(bk_image->image,
+ pixel_array_low + bk_image->offset,
+ result + bk_image->offset * depth,
+ bk_image->width,
+ bk_image->height,
+ margin,
+ is_clear,
+ is_noncolor);
+
+ /* might be read by UI to set active image for display */
+ bake_update_image(sa, bk_image->image);
+
+ if (!ok) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Problem saving the bake map internally for object \"%s\"",
+ ob_low->id.name + 2);
+ op_result = OPERATOR_CANCELLED;
+ }
+ else {
+ BKE_report(reports,
+ RPT_INFO,
+ "Baking map saved to internal image, save it externally or pack it");
+ op_result = OPERATOR_FINISHED;
+ }
+ }
+ /* save externally */
+ else {
+ BakeData *bake = &scene->r.bake;
+ char name[FILE_MAX];
+
+ BKE_image_path_from_imtype(name,
+ filepath,
+ BKE_main_blendfile_path(bmain),
+ 0,
+ bake->im_format.imtype,
+ true,
+ false,
+ NULL);
+
+ if (is_automatic_name) {
+ BLI_path_suffix(name, FILE_MAX, ob_low->id.name + 2, "_");
+ BLI_path_suffix(name, FILE_MAX, identifier, "_");
+ }
+
+ if (is_split_materials) {
+ if (bk_image->image) {
+ BLI_path_suffix(name, FILE_MAX, bk_image->image->id.name + 2, "_");
+ }
+ else {
+ if (ob_low_eval->mat[i]) {
+ BLI_path_suffix(name, FILE_MAX, ob_low_eval->mat[i]->id.name + 2, "_");
+ }
+ else if (me_low->mat[i]) {
+ BLI_path_suffix(name, FILE_MAX, me_low->mat[i]->id.name + 2, "_");
+ }
+ else {
+ /* if everything else fails, use the material index */
+ char tmp[5];
+ sprintf(tmp, "%d", i % 1000);
+ BLI_path_suffix(name, FILE_MAX, tmp, "_");
+ }
+ }
+ }
+
+ /* save it externally */
+ ok = write_external_bake_pixels(name,
+ pixel_array_low + bk_image->offset,
+ result + bk_image->offset * depth,
+ bk_image->width,
+ bk_image->height,
+ margin,
+ &bake->im_format,
+ is_noncolor);
+
+ if (!ok) {
+ BKE_reportf(reports, RPT_ERROR, "Problem saving baked map in \"%s\"", name);
+ op_result = OPERATOR_CANCELLED;
+ }
+ else {
+ BKE_reportf(reports, RPT_INFO, "Baking map written to \"%s\"", name);
+ op_result = OPERATOR_FINISHED;
+ }
+
+ if (!is_split_materials) {
+ break;
+ }
+ }
+ }
+ }
+
+ if (is_save_internal)
+ refresh_images(&bake_images);
cleanup:
- if (highpoly) {
- int i;
- for (i = 0; i < tot_highpoly; i++) {
- if (highpoly[i].me)
- BKE_id_free(bmain, highpoly[i].me);
- }
- MEM_freeN(highpoly);
- }
+ if (highpoly) {
+ int i;
+ for (i = 0; i < tot_highpoly; i++) {
+ if (highpoly[i].me)
+ BKE_id_free(bmain, highpoly[i].me);
+ }
+ MEM_freeN(highpoly);
+ }
- if (mmd_low)
- mmd_low->flags = mmd_flags_low;
+ if (mmd_low)
+ mmd_low->flags = mmd_flags_low;
- if (pixel_array_low)
- MEM_freeN(pixel_array_low);
+ if (pixel_array_low)
+ MEM_freeN(pixel_array_low);
- if (pixel_array_high)
- MEM_freeN(pixel_array_high);
+ if (pixel_array_high)
+ MEM_freeN(pixel_array_high);
- if (bake_images.data)
- MEM_freeN(bake_images.data);
+ if (bake_images.data)
+ MEM_freeN(bake_images.data);
- if (bake_images.lookup)
- MEM_freeN(bake_images.lookup);
+ if (bake_images.lookup)
+ MEM_freeN(bake_images.lookup);
- if (result)
- MEM_freeN(result);
+ if (result)
+ MEM_freeN(result);
- if (me_low)
- BKE_id_free(bmain, me_low);
+ if (me_low)
+ BKE_id_free(bmain, me_low);
- if (me_cage)
- BKE_id_free(bmain, me_cage);
+ if (me_cage)
+ BKE_id_free(bmain, me_cage);
- DEG_graph_free(depsgraph);
+ DEG_graph_free(depsgraph);
- return op_result;
+ return op_result;
}
static void bake_init_api_data(wmOperator *op, bContext *C, BakeAPIRender *bkr)
{
- bool is_save_internal;
- bScreen *sc = CTX_wm_screen(C);
+ bool is_save_internal;
+ bScreen *sc = CTX_wm_screen(C);
- bkr->ob = CTX_data_active_object(C);
- bkr->main = CTX_data_main(C);
- bkr->view_layer = CTX_data_view_layer(C);
- bkr->scene = CTX_data_scene(C);
- bkr->sa = sc ? BKE_screen_find_big_area(sc, SPACE_IMAGE, 10) : NULL;
+ bkr->ob = CTX_data_active_object(C);
+ bkr->main = CTX_data_main(C);
+ bkr->view_layer = CTX_data_view_layer(C);
+ bkr->scene = CTX_data_scene(C);
+ bkr->sa = sc ? BKE_screen_find_big_area(sc, SPACE_IMAGE, 10) : NULL;
- bkr->pass_type = RNA_enum_get(op->ptr, "type");
- bkr->pass_filter = RNA_enum_get(op->ptr, "pass_filter");
- bkr->margin = RNA_int_get(op->ptr, "margin");
+ bkr->pass_type = RNA_enum_get(op->ptr, "type");
+ bkr->pass_filter = RNA_enum_get(op->ptr, "pass_filter");
+ bkr->margin = RNA_int_get(op->ptr, "margin");
- bkr->save_mode = RNA_enum_get(op->ptr, "save_mode");
- is_save_internal = (bkr->save_mode == R_BAKE_SAVE_INTERNAL);
+ bkr->save_mode = RNA_enum_get(op->ptr, "save_mode");
+ is_save_internal = (bkr->save_mode == R_BAKE_SAVE_INTERNAL);
- bkr->is_clear = RNA_boolean_get(op->ptr, "use_clear");
- bkr->is_split_materials = (!is_save_internal) && RNA_boolean_get(op->ptr, "use_split_materials");
- bkr->is_automatic_name = RNA_boolean_get(op->ptr, "use_automatic_name");
- bkr->is_selected_to_active = RNA_boolean_get(op->ptr, "use_selected_to_active");
- bkr->is_cage = RNA_boolean_get(op->ptr, "use_cage");
- bkr->cage_extrusion = RNA_float_get(op->ptr, "cage_extrusion");
+ bkr->is_clear = RNA_boolean_get(op->ptr, "use_clear");
+ bkr->is_split_materials = (!is_save_internal) && RNA_boolean_get(op->ptr, "use_split_materials");
+ bkr->is_automatic_name = RNA_boolean_get(op->ptr, "use_automatic_name");
+ bkr->is_selected_to_active = RNA_boolean_get(op->ptr, "use_selected_to_active");
+ bkr->is_cage = RNA_boolean_get(op->ptr, "use_cage");
+ bkr->cage_extrusion = RNA_float_get(op->ptr, "cage_extrusion");
- bkr->normal_space = RNA_enum_get(op->ptr, "normal_space");
- bkr->normal_swizzle[0] = RNA_enum_get(op->ptr, "normal_r");
- bkr->normal_swizzle[1] = RNA_enum_get(op->ptr, "normal_g");
- bkr->normal_swizzle[2] = RNA_enum_get(op->ptr, "normal_b");
+ bkr->normal_space = RNA_enum_get(op->ptr, "normal_space");
+ bkr->normal_swizzle[0] = RNA_enum_get(op->ptr, "normal_r");
+ bkr->normal_swizzle[1] = RNA_enum_get(op->ptr, "normal_g");
+ bkr->normal_swizzle[2] = RNA_enum_get(op->ptr, "normal_b");
- bkr->width = RNA_int_get(op->ptr, "width");
- bkr->height = RNA_int_get(op->ptr, "height");
- bkr->identifier = "";
+ bkr->width = RNA_int_get(op->ptr, "width");
+ bkr->height = RNA_int_get(op->ptr, "height");
+ bkr->identifier = "";
- RNA_string_get(op->ptr, "uv_layer", bkr->uv_layer);
+ RNA_string_get(op->ptr, "uv_layer", bkr->uv_layer);
- RNA_string_get(op->ptr, "cage_object", bkr->custom_cage);
+ RNA_string_get(op->ptr, "cage_object", bkr->custom_cage);
- if ((!is_save_internal) && bkr->is_automatic_name) {
- PropertyRNA *prop = RNA_struct_find_property(op->ptr, "type");
- RNA_property_enum_identifier(C, op->ptr, prop, bkr->pass_type, &bkr->identifier);
- }
+ if ((!is_save_internal) && bkr->is_automatic_name) {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "type");
+ RNA_property_enum_identifier(C, op->ptr, prop, bkr->pass_type, &bkr->identifier);
+ }
- CTX_data_selected_objects(C, &bkr->selected_objects);
+ CTX_data_selected_objects(C, &bkr->selected_objects);
- bkr->reports = op->reports;
+ bkr->reports = op->reports;
- bkr->result = OPERATOR_CANCELLED;
+ bkr->result = OPERATOR_CANCELLED;
- bkr->render = RE_NewSceneRender(bkr->scene);
+ bkr->render = RE_NewSceneRender(bkr->scene);
- /* XXX hack to force saving to always be internal. Whether (and how) to support
- * external saving will be addressed later */
- bkr->save_mode = R_BAKE_SAVE_INTERNAL;
+ /* XXX hack to force saving to always be internal. Whether (and how) to support
+ * external saving will be addressed later */
+ bkr->save_mode = R_BAKE_SAVE_INTERNAL;
}
static int bake_exec(bContext *C, wmOperator *op)
{
- Render *re;
- int result = OPERATOR_CANCELLED;
- BakeAPIRender bkr = {NULL};
- Scene *scene = CTX_data_scene(C);
-
- G.is_break = false;
- G.is_rendering = true;
-
- bake_set_props(op, scene);
-
- bake_init_api_data(op, C, &bkr);
- re = bkr.render;
-
- /* setup new render */
- RE_test_break_cb(re, NULL, bake_break);
-
- if (!bake_pass_filter_check(bkr.pass_type, bkr.pass_filter, bkr.reports)) {
- goto finally;
- }
-
- if (!bake_objects_check(bkr.main, bkr.view_layer, bkr.ob, &bkr.selected_objects, bkr.reports, bkr.is_selected_to_active)) {
- goto finally;
- }
-
- if (bkr.is_clear) {
- const bool is_tangent = ((bkr.pass_type == SCE_PASS_NORMAL) && (bkr.normal_space == R_BAKE_SPACE_TANGENT));
- bake_images_clear(bkr.main, is_tangent);
- }
-
- RE_SetReports(re, bkr.reports);
-
- if (bkr.is_selected_to_active) {
- result = bake(
- bkr.render, bkr.main, bkr.scene, bkr.view_layer, bkr.ob, &bkr.selected_objects, bkr.reports,
- bkr.pass_type, bkr.pass_filter, bkr.margin, bkr.save_mode,
- bkr.is_clear, bkr.is_split_materials, bkr.is_automatic_name, true, bkr.is_cage,
- bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle,
- bkr.custom_cage, bkr.filepath, bkr.width, bkr.height, bkr.identifier, bkr.sa,
- bkr.uv_layer);
- }
- else {
- CollectionPointerLink *link;
- const bool is_clear = bkr.is_clear && BLI_listbase_is_single(&bkr.selected_objects);
- for (link = bkr.selected_objects.first; link; link = link->next) {
- Object *ob_iter = link->ptr.data;
- result = bake(
- bkr.render, bkr.main, bkr.scene, bkr.view_layer, ob_iter, NULL, bkr.reports,
- bkr.pass_type, bkr.pass_filter, bkr.margin, bkr.save_mode,
- is_clear, bkr.is_split_materials, bkr.is_automatic_name, false, bkr.is_cage,
- bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle,
- bkr.custom_cage, bkr.filepath, bkr.width, bkr.height, bkr.identifier, bkr.sa,
- bkr.uv_layer);
- }
- }
-
- RE_SetReports(re, NULL);
-
+ Render *re;
+ int result = OPERATOR_CANCELLED;
+ BakeAPIRender bkr = {NULL};
+ Scene *scene = CTX_data_scene(C);
+
+ G.is_break = false;
+ G.is_rendering = true;
+
+ bake_set_props(op, scene);
+
+ bake_init_api_data(op, C, &bkr);
+ re = bkr.render;
+
+ /* setup new render */
+ RE_test_break_cb(re, NULL, bake_break);
+
+ if (!bake_pass_filter_check(bkr.pass_type, bkr.pass_filter, bkr.reports)) {
+ goto finally;
+ }
+
+ if (!bake_objects_check(bkr.main,
+ bkr.view_layer,
+ bkr.ob,
+ &bkr.selected_objects,
+ bkr.reports,
+ bkr.is_selected_to_active)) {
+ goto finally;
+ }
+
+ if (bkr.is_clear) {
+ const bool is_tangent = ((bkr.pass_type == SCE_PASS_NORMAL) &&
+ (bkr.normal_space == R_BAKE_SPACE_TANGENT));
+ bake_images_clear(bkr.main, is_tangent);
+ }
+
+ RE_SetReports(re, bkr.reports);
+
+ if (bkr.is_selected_to_active) {
+ result = bake(bkr.render,
+ bkr.main,
+ bkr.scene,
+ bkr.view_layer,
+ bkr.ob,
+ &bkr.selected_objects,
+ bkr.reports,
+ bkr.pass_type,
+ bkr.pass_filter,
+ bkr.margin,
+ bkr.save_mode,
+ bkr.is_clear,
+ bkr.is_split_materials,
+ bkr.is_automatic_name,
+ true,
+ bkr.is_cage,
+ bkr.cage_extrusion,
+ bkr.normal_space,
+ bkr.normal_swizzle,
+ bkr.custom_cage,
+ bkr.filepath,
+ bkr.width,
+ bkr.height,
+ bkr.identifier,
+ bkr.sa,
+ bkr.uv_layer);
+ }
+ else {
+ CollectionPointerLink *link;
+ const bool is_clear = bkr.is_clear && BLI_listbase_is_single(&bkr.selected_objects);
+ for (link = bkr.selected_objects.first; link; link = link->next) {
+ Object *ob_iter = link->ptr.data;
+ result = bake(bkr.render,
+ bkr.main,
+ bkr.scene,
+ bkr.view_layer,
+ ob_iter,
+ NULL,
+ bkr.reports,
+ bkr.pass_type,
+ bkr.pass_filter,
+ bkr.margin,
+ bkr.save_mode,
+ is_clear,
+ bkr.is_split_materials,
+ bkr.is_automatic_name,
+ false,
+ bkr.is_cage,
+ bkr.cage_extrusion,
+ bkr.normal_space,
+ bkr.normal_swizzle,
+ bkr.custom_cage,
+ bkr.filepath,
+ bkr.width,
+ bkr.height,
+ bkr.identifier,
+ bkr.sa,
+ bkr.uv_layer);
+ }
+ }
+
+ RE_SetReports(re, NULL);
finally:
- G.is_rendering = false;
- BLI_freelistN(&bkr.selected_objects);
- return result;
+ G.is_rendering = false;
+ BLI_freelistN(&bkr.selected_objects);
+ return result;
}
static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, float *progress)
{
- BakeAPIRender *bkr = (BakeAPIRender *)bkv;
-
- /* setup new render */
- bkr->do_update = do_update;
- bkr->progress = progress;
-
- RE_SetReports(bkr->render, bkr->reports);
-
- if (!bake_pass_filter_check(bkr->pass_type, bkr->pass_filter, bkr->reports)) {
- bkr->result = OPERATOR_CANCELLED;
- return;
- }
-
- if (!bake_objects_check(bkr->main, bkr->view_layer, bkr->ob, &bkr->selected_objects, bkr->reports, bkr->is_selected_to_active)) {
- bkr->result = OPERATOR_CANCELLED;
- return;
- }
-
- if (bkr->is_clear) {
- const bool is_tangent = ((bkr->pass_type == SCE_PASS_NORMAL) && (bkr->normal_space == R_BAKE_SPACE_TANGENT));
- bake_images_clear(bkr->main, is_tangent);
- }
-
- if (bkr->is_selected_to_active) {
- bkr->result = bake(
- bkr->render, bkr->main, bkr->scene, bkr->view_layer, bkr->ob, &bkr->selected_objects, bkr->reports,
- bkr->pass_type, bkr->pass_filter, bkr->margin, bkr->save_mode,
- bkr->is_clear, bkr->is_split_materials, bkr->is_automatic_name, true, bkr->is_cage,
- bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle,
- bkr->custom_cage, bkr->filepath, bkr->width, bkr->height, bkr->identifier, bkr->sa,
- bkr->uv_layer);
- }
- else {
- CollectionPointerLink *link;
- const bool is_clear = bkr->is_clear && BLI_listbase_is_single(&bkr->selected_objects);
- for (link = bkr->selected_objects.first; link; link = link->next) {
- Object *ob_iter = link->ptr.data;
- bkr->result = bake(
- bkr->render, bkr->main, bkr->scene, bkr->view_layer, ob_iter, NULL, bkr->reports,
- bkr->pass_type, bkr->pass_filter, bkr->margin, bkr->save_mode,
- is_clear, bkr->is_split_materials, bkr->is_automatic_name, false, bkr->is_cage,
- bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle,
- bkr->custom_cage, bkr->filepath, bkr->width, bkr->height, bkr->identifier, bkr->sa,
- bkr->uv_layer);
-
- if (bkr->result == OPERATOR_CANCELLED)
- return;
- }
- }
-
- RE_SetReports(bkr->render, NULL);
+ BakeAPIRender *bkr = (BakeAPIRender *)bkv;
+
+ /* setup new render */
+ bkr->do_update = do_update;
+ bkr->progress = progress;
+
+ RE_SetReports(bkr->render, bkr->reports);
+
+ if (!bake_pass_filter_check(bkr->pass_type, bkr->pass_filter, bkr->reports)) {
+ bkr->result = OPERATOR_CANCELLED;
+ return;
+ }
+
+ if (!bake_objects_check(bkr->main,
+ bkr->view_layer,
+ bkr->ob,
+ &bkr->selected_objects,
+ bkr->reports,
+ bkr->is_selected_to_active)) {
+ bkr->result = OPERATOR_CANCELLED;
+ return;
+ }
+
+ if (bkr->is_clear) {
+ const bool is_tangent = ((bkr->pass_type == SCE_PASS_NORMAL) &&
+ (bkr->normal_space == R_BAKE_SPACE_TANGENT));
+ bake_images_clear(bkr->main, is_tangent);
+ }
+
+ if (bkr->is_selected_to_active) {
+ bkr->result = bake(bkr->render,
+ bkr->main,
+ bkr->scene,
+ bkr->view_layer,
+ bkr->ob,
+ &bkr->selected_objects,
+ bkr->reports,
+ bkr->pass_type,
+ bkr->pass_filter,
+ bkr->margin,
+ bkr->save_mode,
+ bkr->is_clear,
+ bkr->is_split_materials,
+ bkr->is_automatic_name,
+ true,
+ bkr->is_cage,
+ bkr->cage_extrusion,
+ bkr->normal_space,
+ bkr->normal_swizzle,
+ bkr->custom_cage,
+ bkr->filepath,
+ bkr->width,
+ bkr->height,
+ bkr->identifier,
+ bkr->sa,
+ bkr->uv_layer);
+ }
+ else {
+ CollectionPointerLink *link;
+ const bool is_clear = bkr->is_clear && BLI_listbase_is_single(&bkr->selected_objects);
+ for (link = bkr->selected_objects.first; link; link = link->next) {
+ Object *ob_iter = link->ptr.data;
+ bkr->result = bake(bkr->render,
+ bkr->main,
+ bkr->scene,
+ bkr->view_layer,
+ ob_iter,
+ NULL,
+ bkr->reports,
+ bkr->pass_type,
+ bkr->pass_filter,
+ bkr->margin,
+ bkr->save_mode,
+ is_clear,
+ bkr->is_split_materials,
+ bkr->is_automatic_name,
+ false,
+ bkr->is_cage,
+ bkr->cage_extrusion,
+ bkr->normal_space,
+ bkr->normal_swizzle,
+ bkr->custom_cage,
+ bkr->filepath,
+ bkr->width,
+ bkr->height,
+ bkr->identifier,
+ bkr->sa,
+ bkr->uv_layer);
+
+ if (bkr->result == OPERATOR_CANCELLED)
+ return;
+ }
+ }
+
+ RE_SetReports(bkr->render, NULL);
}
static void bake_freejob(void *bkv)
{
- BakeAPIRender *bkr = (BakeAPIRender *)bkv;
+ BakeAPIRender *bkr = (BakeAPIRender *)bkv;
- BLI_freelistN(&bkr->selected_objects);
- MEM_freeN(bkr);
+ BLI_freelistN(&bkr->selected_objects);
+ MEM_freeN(bkr);
- G.is_rendering = false;
+ G.is_rendering = false;
}
static void bake_set_props(wmOperator *op, Scene *scene)
{
- PropertyRNA *prop;
- BakeData *bake = &scene->r.bake;
-
- prop = RNA_struct_find_property(op->ptr, "filepath");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_string_set(op->ptr, prop, bake->filepath);
- }
-
- prop = RNA_struct_find_property(op->ptr, "width");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_int_set(op->ptr, prop, bake->width);
- }
-
- prop = RNA_struct_find_property(op->ptr, "height");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_int_set(op->ptr, prop, bake->width);
- }
-
- prop = RNA_struct_find_property(op->ptr, "margin");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_int_set(op->ptr, prop, bake->margin);
- }
-
- prop = RNA_struct_find_property(op->ptr, "use_selected_to_active");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_TO_ACTIVE) != 0);
- }
-
- prop = RNA_struct_find_property(op->ptr, "cage_extrusion");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_float_set(op->ptr, prop, bake->cage_extrusion);
- }
-
- prop = RNA_struct_find_property(op->ptr, "cage_object");
- if (!RNA_property_is_set(op->ptr, prop)) {
- if (bake->cage_object) {
- RNA_property_string_set(op->ptr, prop, bake->cage_object->id.name + 2);
- }
- }
-
- prop = RNA_struct_find_property(op->ptr, "normal_space");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_enum_set(op->ptr, prop, bake->normal_space);
- }
-
- prop = RNA_struct_find_property(op->ptr, "normal_r");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_enum_set(op->ptr, prop, bake->normal_swizzle[0]);
- }
-
- prop = RNA_struct_find_property(op->ptr, "normal_g");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_enum_set(op->ptr, prop, bake->normal_swizzle[1]);
- }
-
- prop = RNA_struct_find_property(op->ptr, "normal_b");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_enum_set(op->ptr, prop, bake->normal_swizzle[2]);
- }
-
- prop = RNA_struct_find_property(op->ptr, "save_mode");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_enum_set(op->ptr, prop, bake->save_mode);
- }
-
- prop = RNA_struct_find_property(op->ptr, "use_clear");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_CLEAR) != 0);
- }
-
- prop = RNA_struct_find_property(op->ptr, "use_cage");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_CAGE) != 0);
- }
-
- prop = RNA_struct_find_property(op->ptr, "use_split_materials");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_SPLIT_MAT) != 0);
- }
-
- prop = RNA_struct_find_property(op->ptr, "use_automatic_name");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_AUTO_NAME) != 0);
- }
-
- prop = RNA_struct_find_property(op->ptr, "pass_filter");
- if (!RNA_property_is_set(op->ptr, prop)) {
- RNA_property_enum_set(op->ptr, prop, bake->pass_filter);
- }
+ PropertyRNA *prop;
+ BakeData *bake = &scene->r.bake;
+
+ prop = RNA_struct_find_property(op->ptr, "filepath");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_string_set(op->ptr, prop, bake->filepath);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "width");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_int_set(op->ptr, prop, bake->width);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "height");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_int_set(op->ptr, prop, bake->width);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "margin");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_int_set(op->ptr, prop, bake->margin);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "use_selected_to_active");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_TO_ACTIVE) != 0);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "cage_extrusion");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_float_set(op->ptr, prop, bake->cage_extrusion);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "cage_object");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ if (bake->cage_object) {
+ RNA_property_string_set(op->ptr, prop, bake->cage_object->id.name + 2);
+ }
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "normal_space");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_enum_set(op->ptr, prop, bake->normal_space);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "normal_r");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_enum_set(op->ptr, prop, bake->normal_swizzle[0]);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "normal_g");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_enum_set(op->ptr, prop, bake->normal_swizzle[1]);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "normal_b");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_enum_set(op->ptr, prop, bake->normal_swizzle[2]);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "save_mode");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_enum_set(op->ptr, prop, bake->save_mode);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "use_clear");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_CLEAR) != 0);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "use_cage");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_CAGE) != 0);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "use_split_materials");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_SPLIT_MAT) != 0);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "use_automatic_name");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_AUTO_NAME) != 0);
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "pass_filter");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ RNA_property_enum_set(op->ptr, prop, bake->pass_filter);
+ }
}
static int bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- wmJob *wm_job;
- BakeAPIRender *bkr;
- Render *re;
- Scene *scene = CTX_data_scene(C);
+ wmJob *wm_job;
+ BakeAPIRender *bkr;
+ Render *re;
+ Scene *scene = CTX_data_scene(C);
- bake_set_props(op, scene);
+ bake_set_props(op, scene);
- /* only one render job at a time */
- if (WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_OBJECT_BAKE))
- return OPERATOR_CANCELLED;
+ /* only one render job at a time */
+ if (WM_jobs_test(CTX_wm_manager(C), scene, WM_JOB_TYPE_OBJECT_BAKE))
+ return OPERATOR_CANCELLED;
- bkr = MEM_mallocN(sizeof(BakeAPIRender), "render bake");
+ bkr = MEM_mallocN(sizeof(BakeAPIRender), "render bake");
- /* init bake render */
- bake_init_api_data(op, C, bkr);
- re = bkr->render;
+ /* init bake render */
+ bake_init_api_data(op, C, bkr);
+ re = bkr->render;
- /* setup new render */
- RE_test_break_cb(re, NULL, bake_break);
- RE_progress_cb(re, bkr, bake_progress_update);
+ /* setup new render */
+ RE_test_break_cb(re, NULL, bake_break);
+ RE_progress_cb(re, bkr, bake_progress_update);
- /* setup job */
- wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Texture Bake",
- WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_BAKE);
- WM_jobs_customdata_set(wm_job, bkr, bake_freejob);
- WM_jobs_timer(wm_job, 0.5, NC_IMAGE, 0); /* TODO - only draw bake image, can we enforce this */
- WM_jobs_callbacks(wm_job, bake_startjob, NULL, NULL, NULL);
+ /* setup job */
+ wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ scene,
+ "Texture Bake",
+ WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS,
+ WM_JOB_TYPE_OBJECT_BAKE);
+ WM_jobs_customdata_set(wm_job, bkr, bake_freejob);
+ WM_jobs_timer(wm_job, 0.5, NC_IMAGE, 0); /* TODO - only draw bake image, can we enforce this */
+ WM_jobs_callbacks(wm_job, bake_startjob, NULL, NULL, NULL);
- G.is_break = false;
- G.is_rendering = true;
+ G.is_break = false;
+ G.is_rendering = true;
- WM_jobs_start(CTX_wm_manager(C), wm_job);
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
- WM_cursor_wait(0);
+ WM_cursor_wait(0);
- /* add modal handler for ESC */
- WM_event_add_modal_handler(C, op);
+ /* add modal handler for ESC */
+ WM_event_add_modal_handler(C, op);
- WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);
- return OPERATOR_RUNNING_MODAL;
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, scene);
+ return OPERATOR_RUNNING_MODAL;
}
void OBJECT_OT_bake(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Bake";
- ot->description = "Bake image textures of selected objects";
- ot->idname = "OBJECT_OT_bake";
-
- /* api callbacks */
- ot->exec = bake_exec;
- ot->modal = bake_modal;
- ot->invoke = bake_invoke;
- ot->poll = ED_operator_object_active_editable_mesh;
-
- RNA_def_enum(ot->srna, "type", rna_enum_bake_pass_type_items, SCE_PASS_COMBINED, "Type",
- "Type of pass to bake, some of them may not be supported by the current render engine");
- prop = RNA_def_enum(ot->srna, "pass_filter", rna_enum_bake_pass_filter_type_items, R_BAKE_PASS_FILTER_NONE, "Pass Filter",
- "Filter to combined, diffuse, glossy, transmission and subsurface passes");
- RNA_def_property_flag(prop, PROP_ENUM_FLAG);
- RNA_def_string_file_path(ot->srna, "filepath", NULL, FILE_MAX, "File Path",
- "Image filepath to use when saving externally");
- RNA_def_int(ot->srna, "width", 512, 1, INT_MAX, "Width",
- "Horizontal dimension of the baking map (external only)", 64, 4096);
- RNA_def_int(ot->srna, "height", 512, 1, INT_MAX, "Height",
- "Vertical dimension of the baking map (external only)", 64, 4096);
- RNA_def_int(ot->srna, "margin", 16, 0, INT_MAX, "Margin",
- "Extends the baked result as a post process filter", 0, 64);
- RNA_def_boolean(ot->srna, "use_selected_to_active", false, "Selected to Active",
- "Bake shading on the surface of selected objects to the active object");
- RNA_def_float(ot->srna, "cage_extrusion", 0.0f, 0.0f, FLT_MAX, "Cage Extrusion",
- "Distance to use for the inward ray cast when using selected to active", 0.0f, 1.0f);
- RNA_def_string(ot->srna, "cage_object", NULL, MAX_NAME, "Cage Object",
- "Object to use as cage, instead of calculating the cage from the active object with cage extrusion");
- RNA_def_enum(ot->srna, "normal_space", rna_enum_normal_space_items, R_BAKE_SPACE_TANGENT, "Normal Space",
- "Choose normal space for baking");
- RNA_def_enum(ot->srna, "normal_r", rna_enum_normal_swizzle_items, R_BAKE_POSX, "R", "Axis to bake in red channel");
- RNA_def_enum(ot->srna, "normal_g", rna_enum_normal_swizzle_items, R_BAKE_POSY, "G", "Axis to bake in green channel");
- RNA_def_enum(ot->srna, "normal_b", rna_enum_normal_swizzle_items, R_BAKE_POSZ, "B", "Axis to bake in blue channel");
- RNA_def_enum(ot->srna, "save_mode", rna_enum_bake_save_mode_items, R_BAKE_SAVE_INTERNAL, "Save Mode",
- "Choose how to save the baking map");
- RNA_def_boolean(ot->srna, "use_clear", false, "Clear",
- "Clear Images before baking (only for internal saving)");
- RNA_def_boolean(ot->srna, "use_cage", false, "Cage",
- "Cast rays to active object from a cage");
- RNA_def_boolean(ot->srna, "use_split_materials", false, "Split Materials",
- "Split baked maps per material, using material name in output file (external only)");
- RNA_def_boolean(ot->srna, "use_automatic_name", false, "Automatic Name",
- "Automatically name the output file with the pass type");
- RNA_def_string(ot->srna, "uv_layer", NULL, MAX_CUSTOMDATA_LAYER_NAME, "UV Layer", "UV layer to override active");
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Bake";
+ ot->description = "Bake image textures of selected objects";
+ ot->idname = "OBJECT_OT_bake";
+
+ /* api callbacks */
+ ot->exec = bake_exec;
+ ot->modal = bake_modal;
+ ot->invoke = bake_invoke;
+ ot->poll = ED_operator_object_active_editable_mesh;
+
+ RNA_def_enum(
+ ot->srna,
+ "type",
+ rna_enum_bake_pass_type_items,
+ SCE_PASS_COMBINED,
+ "Type",
+ "Type of pass to bake, some of them may not be supported by the current render engine");
+ prop = RNA_def_enum(ot->srna,
+ "pass_filter",
+ rna_enum_bake_pass_filter_type_items,
+ R_BAKE_PASS_FILTER_NONE,
+ "Pass Filter",
+ "Filter to combined, diffuse, glossy, transmission and subsurface passes");
+ RNA_def_property_flag(prop, PROP_ENUM_FLAG);
+ RNA_def_string_file_path(ot->srna,
+ "filepath",
+ NULL,
+ FILE_MAX,
+ "File Path",
+ "Image filepath to use when saving externally");
+ RNA_def_int(ot->srna,
+ "width",
+ 512,
+ 1,
+ INT_MAX,
+ "Width",
+ "Horizontal dimension of the baking map (external only)",
+ 64,
+ 4096);
+ RNA_def_int(ot->srna,
+ "height",
+ 512,
+ 1,
+ INT_MAX,
+ "Height",
+ "Vertical dimension of the baking map (external only)",
+ 64,
+ 4096);
+ RNA_def_int(ot->srna,
+ "margin",
+ 16,
+ 0,
+ INT_MAX,
+ "Margin",
+ "Extends the baked result as a post process filter",
+ 0,
+ 64);
+ RNA_def_boolean(ot->srna,
+ "use_selected_to_active",
+ false,
+ "Selected to Active",
+ "Bake shading on the surface of selected objects to the active object");
+ RNA_def_float(ot->srna,
+ "cage_extrusion",
+ 0.0f,
+ 0.0f,
+ FLT_MAX,
+ "Cage Extrusion",
+ "Distance to use for the inward ray cast when using selected to active",
+ 0.0f,
+ 1.0f);
+ RNA_def_string(ot->srna,
+ "cage_object",
+ NULL,
+ MAX_NAME,
+ "Cage Object",
+ "Object to use as cage, instead of calculating the cage from the active object "
+ "with cage extrusion");
+ RNA_def_enum(ot->srna,
+ "normal_space",
+ rna_enum_normal_space_items,
+ R_BAKE_SPACE_TANGENT,
+ "Normal Space",
+ "Choose normal space for baking");
+ RNA_def_enum(ot->srna,
+ "normal_r",
+ rna_enum_normal_swizzle_items,
+ R_BAKE_POSX,
+ "R",
+ "Axis to bake in red channel");
+ RNA_def_enum(ot->srna,
+ "normal_g",
+ rna_enum_normal_swizzle_items,
+ R_BAKE_POSY,
+ "G",
+ "Axis to bake in green channel");
+ RNA_def_enum(ot->srna,
+ "normal_b",
+ rna_enum_normal_swizzle_items,
+ R_BAKE_POSZ,
+ "B",
+ "Axis to bake in blue channel");
+ RNA_def_enum(ot->srna,
+ "save_mode",
+ rna_enum_bake_save_mode_items,
+ R_BAKE_SAVE_INTERNAL,
+ "Save Mode",
+ "Choose how to save the baking map");
+ RNA_def_boolean(ot->srna,
+ "use_clear",
+ false,
+ "Clear",
+ "Clear Images before baking (only for internal saving)");
+ RNA_def_boolean(ot->srna, "use_cage", false, "Cage", "Cast rays to active object from a cage");
+ RNA_def_boolean(
+ ot->srna,
+ "use_split_materials",
+ false,
+ "Split Materials",
+ "Split baked maps per material, using material name in output file (external only)");
+ RNA_def_boolean(ot->srna,
+ "use_automatic_name",
+ false,
+ "Automatic Name",
+ "Automatically name the output file with the pass type");
+ RNA_def_string(ot->srna,
+ "uv_layer",
+ NULL,
+ MAX_CUSTOMDATA_LAYER_NAME,
+ "UV Layer",
+ "UV layer to override active");
}
diff --git a/source/blender/editors/object/object_collection.c b/source/blender/editors/object/object_collection.c
index e8552c823bf..0b22dec99c7 100644
--- a/source/blender/editors/object/object_collection.c
+++ b/source/blender/editors/object/object_collection.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include <string.h>
#include "BLI_blenlib.h"
@@ -56,546 +55,566 @@
/********************* 3d view operators ***********************/
/* can be called with C == NULL */
-static const EnumPropertyItem *collection_object_active_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *collection_object_active_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob;
- EnumPropertyItem *item = NULL, item_tmp = {0};
- int totitem = 0;
-
- if (C == NULL) {
- return DummyRNA_NULL_items;
- }
-
- ob = ED_object_context(C);
-
- /* check that the object exists */
- if (ob) {
- Collection *collection;
- int i = 0, count = 0;
-
- /* if 2 or more collections, add option to add to all collections */
- collection = NULL;
- while ((collection = BKE_collection_object_find(bmain, scene, collection, ob)))
- count++;
-
- if (count >= 2) {
- item_tmp.identifier = item_tmp.name = "All Collections";
- item_tmp.value = INT_MAX; /* this will give NULL on lookup */
- RNA_enum_item_add(&item, &totitem, &item_tmp);
- RNA_enum_item_add_separator(&item, &totitem);
- }
-
- /* add collections */
- collection = NULL;
- while ((collection = BKE_collection_object_find(bmain, scene, collection, ob))) {
- item_tmp.identifier = item_tmp.name = collection->id.name + 2;
- /* item_tmp.icon = ICON_ARMATURE_DATA; */
- item_tmp.value = i;
- RNA_enum_item_add(&item, &totitem, &item_tmp);
- i++;
- }
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob;
+ EnumPropertyItem *item = NULL, item_tmp = {0};
+ int totitem = 0;
+
+ if (C == NULL) {
+ return DummyRNA_NULL_items;
+ }
+
+ ob = ED_object_context(C);
+
+ /* check that the object exists */
+ if (ob) {
+ Collection *collection;
+ int i = 0, count = 0;
+
+ /* if 2 or more collections, add option to add to all collections */
+ collection = NULL;
+ while ((collection = BKE_collection_object_find(bmain, scene, collection, ob)))
+ count++;
+
+ if (count >= 2) {
+ item_tmp.identifier = item_tmp.name = "All Collections";
+ item_tmp.value = INT_MAX; /* this will give NULL on lookup */
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ RNA_enum_item_add_separator(&item, &totitem);
+ }
+
+ /* add collections */
+ collection = NULL;
+ while ((collection = BKE_collection_object_find(bmain, scene, collection, ob))) {
+ item_tmp.identifier = item_tmp.name = collection->id.name + 2;
+ /* item_tmp.icon = ICON_ARMATURE_DATA; */
+ item_tmp.value = i;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ i++;
+ }
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
/* get the collection back from the enum index, quite awkward and UI specific */
-static Collection *collection_object_active_find_index(Main *bmain, Scene *scene, Object *ob, const int collection_object_index)
+static Collection *collection_object_active_find_index(Main *bmain,
+ Scene *scene,
+ Object *ob,
+ const int collection_object_index)
{
- Collection *collection = NULL;
- int i = 0;
- while ((collection = BKE_collection_object_find(bmain, scene, collection, ob))) {
- if (i == collection_object_index) {
- break;
- }
- i++;
- }
-
- return collection;
+ Collection *collection = NULL;
+ int i = 0;
+ while ((collection = BKE_collection_object_find(bmain, scene, collection, ob))) {
+ if (i == collection_object_index) {
+ break;
+ }
+ i++;
+ }
+
+ return collection;
}
static int objects_add_active_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- int single_collection_index = RNA_enum_get(op->ptr, "collection");
- Collection *single_collection = collection_object_active_find_index(bmain, scene, ob, single_collection_index);
- bool is_cycle = false;
- bool updated = false;
-
- if (ob == NULL)
- return OPERATOR_CANCELLED;
-
- /* now add all selected objects to the collection(s) */
- FOREACH_COLLECTION_BEGIN(bmain, scene, Collection *, collection)
- {
- if (single_collection && collection != single_collection)
- continue;
- if (!BKE_collection_has_object(collection, ob))
- continue;
-
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
- {
- if (BKE_collection_has_object(collection, base->object))
- continue;
-
- if (!BKE_collection_object_cyclic_check(bmain, base->object, collection)) {
- BKE_collection_object_add(bmain, collection, base->object);
- DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
- updated = true;
- }
- else {
- is_cycle = true;
- }
- }
- CTX_DATA_END;
- }
- FOREACH_COLLECTION_END;
-
- if (is_cycle)
- BKE_report(op->reports, RPT_WARNING, "Skipped some collections because of cycle detected");
-
- if (!updated)
- return OPERATOR_CANCELLED;
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
+ Object *ob = ED_object_context(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ int single_collection_index = RNA_enum_get(op->ptr, "collection");
+ Collection *single_collection = collection_object_active_find_index(
+ bmain, scene, ob, single_collection_index);
+ bool is_cycle = false;
+ bool updated = false;
+
+ if (ob == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* now add all selected objects to the collection(s) */
+ FOREACH_COLLECTION_BEGIN(bmain, scene, Collection *, collection)
+ {
+ if (single_collection && collection != single_collection)
+ continue;
+ if (!BKE_collection_has_object(collection, ob))
+ continue;
+
+ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
+ if (BKE_collection_has_object(collection, base->object))
+ continue;
+
+ if (!BKE_collection_object_cyclic_check(bmain, base->object, collection)) {
+ BKE_collection_object_add(bmain, collection, base->object);
+ DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
+ updated = true;
+ }
+ else {
+ is_cycle = true;
+ }
+ }
+ CTX_DATA_END;
+ }
+ FOREACH_COLLECTION_END;
+
+ if (is_cycle)
+ BKE_report(op->reports, RPT_WARNING, "Skipped some collections because of cycle detected");
+
+ if (!updated)
+ return OPERATOR_CANCELLED;
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
}
void COLLECTION_OT_objects_add_active(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Add Selected To Active Collection";
- ot->description = "Add the object to an object collection that contains the active object";
- ot->idname = "COLLECTION_OT_objects_add_active";
-
- /* api callbacks */
- ot->exec = objects_add_active_exec;
- ot->invoke = WM_menu_invoke;
- ot->poll = ED_operator_objectmode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "The collection to add other selected objects to");
- RNA_def_enum_funcs(prop, collection_object_active_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Add Selected To Active Collection";
+ ot->description = "Add the object to an object collection that contains the active object";
+ ot->idname = "COLLECTION_OT_objects_add_active";
+
+ /* api callbacks */
+ ot->exec = objects_add_active_exec;
+ ot->invoke = WM_menu_invoke;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna,
+ "collection",
+ DummyRNA_NULL_items,
+ 0,
+ "Collection",
+ "The collection to add other selected objects to");
+ RNA_def_enum_funcs(prop, collection_object_active_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
static int objects_remove_active_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- int single_collection_index = RNA_enum_get(op->ptr, "collection");
- Collection *single_collection = collection_object_active_find_index(bmain, scene, ob, single_collection_index);
- bool ok = false;
-
- if (ob == NULL)
- return OPERATOR_CANCELLED;
-
- /* Linking to same collection requires its own loop so we can avoid
- * looking up the active objects collections each time. */
- FOREACH_COLLECTION_BEGIN(bmain, scene, Collection *, collection)
- {
- if (single_collection && collection != single_collection)
- continue;
-
- if (BKE_collection_has_object(collection, ob)) {
- /* Remove collections from selected objects */
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
- {
- BKE_collection_object_remove(bmain, collection, base->object, false);
- DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
- ok = 1;
- }
- CTX_DATA_END;
- }
- }
- FOREACH_COLLECTION_END;
-
- if (!ok)
- BKE_report(op->reports, RPT_ERROR, "Active object contains no collections");
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ int single_collection_index = RNA_enum_get(op->ptr, "collection");
+ Collection *single_collection = collection_object_active_find_index(
+ bmain, scene, ob, single_collection_index);
+ bool ok = false;
+
+ if (ob == NULL)
+ return OPERATOR_CANCELLED;
+
+ /* Linking to same collection requires its own loop so we can avoid
+ * looking up the active objects collections each time. */
+ FOREACH_COLLECTION_BEGIN(bmain, scene, Collection *, collection)
+ {
+ if (single_collection && collection != single_collection)
+ continue;
+
+ if (BKE_collection_has_object(collection, ob)) {
+ /* Remove collections from selected objects */
+ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
+ BKE_collection_object_remove(bmain, collection, base->object, false);
+ DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
+ ok = 1;
+ }
+ CTX_DATA_END;
+ }
+ }
+ FOREACH_COLLECTION_END;
+
+ if (!ok)
+ BKE_report(op->reports, RPT_ERROR, "Active object contains no collections");
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
}
void COLLECTION_OT_objects_remove_active(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Remove Selected From Active Collection";
- ot->description = "Remove the object from an object collection that contains the active object";
- ot->idname = "COLLECTION_OT_objects_remove_active";
-
- /* api callbacks */
- ot->exec = objects_remove_active_exec;
- ot->invoke = WM_menu_invoke;
- ot->poll = ED_operator_objectmode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "The collection to remove other selected objects from");
- RNA_def_enum_funcs(prop, collection_object_active_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Remove Selected From Active Collection";
+ ot->description = "Remove the object from an object collection that contains the active object";
+ ot->idname = "COLLECTION_OT_objects_remove_active";
+
+ /* api callbacks */
+ ot->exec = objects_remove_active_exec;
+ ot->invoke = WM_menu_invoke;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna,
+ "collection",
+ DummyRNA_NULL_items,
+ 0,
+ "Collection",
+ "The collection to remove other selected objects from");
+ RNA_def_enum_funcs(prop, collection_object_active_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
static int collection_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
- {
- BKE_object_groups_clear(bmain, scene, base->object);
- }
- CTX_DATA_END;
+ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
+ BKE_object_groups_clear(bmain, scene, base->object);
+ }
+ CTX_DATA_END;
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void COLLECTION_OT_objects_remove_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove From All Unlinked Collections";
- ot->description = "Remove selected objects from all collections not used in a scene";
- ot->idname = "COLLECTION_OT_objects_remove_all";
+ /* identifiers */
+ ot->name = "Remove From All Unlinked Collections";
+ ot->description = "Remove selected objects from all collections not used in a scene";
+ ot->idname = "COLLECTION_OT_objects_remove_all";
- /* api callbacks */
- ot->exec = collection_objects_remove_all_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = collection_objects_remove_all_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int collection_objects_remove_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- int single_collection_index = RNA_enum_get(op->ptr, "collection");
- Collection *single_collection = collection_object_active_find_index(bmain, scene, ob, single_collection_index);
- bool updated = false;
-
- if (ob == NULL)
- return OPERATOR_CANCELLED;
-
- FOREACH_COLLECTION_BEGIN(bmain, scene, Collection *, collection)
- {
- if (single_collection && collection != single_collection)
- continue;
- if (!BKE_collection_has_object(collection, ob))
- continue;
-
- /* now remove all selected objects from the collection */
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
- {
- BKE_collection_object_remove(bmain, collection, base->object, false);
- DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
- updated = true;
- }
- CTX_DATA_END;
- }
- FOREACH_COLLECTION_END;
-
- if (!updated)
- return OPERATOR_CANCELLED;
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
+ Object *ob = ED_object_context(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ int single_collection_index = RNA_enum_get(op->ptr, "collection");
+ Collection *single_collection = collection_object_active_find_index(
+ bmain, scene, ob, single_collection_index);
+ bool updated = false;
+
+ if (ob == NULL)
+ return OPERATOR_CANCELLED;
+
+ FOREACH_COLLECTION_BEGIN(bmain, scene, Collection *, collection)
+ {
+ if (single_collection && collection != single_collection)
+ continue;
+ if (!BKE_collection_has_object(collection, ob))
+ continue;
+
+ /* now remove all selected objects from the collection */
+ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
+ BKE_collection_object_remove(bmain, collection, base->object, false);
+ DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
+ updated = true;
+ }
+ CTX_DATA_END;
+ }
+ FOREACH_COLLECTION_END;
+
+ if (!updated)
+ return OPERATOR_CANCELLED;
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
}
void COLLECTION_OT_objects_remove(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Remove From Collection";
- ot->description = "Remove selected objects from a collection";
- ot->idname = "COLLECTION_OT_objects_remove";
-
- /* api callbacks */
- ot->exec = collection_objects_remove_exec;
- ot->invoke = WM_menu_invoke;
- ot->poll = ED_operator_objectmode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "The collection to remove this object from");
- RNA_def_enum_funcs(prop, collection_object_active_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Remove From Collection";
+ ot->description = "Remove selected objects from a collection";
+ ot->idname = "COLLECTION_OT_objects_remove";
+
+ /* api callbacks */
+ ot->exec = collection_objects_remove_exec;
+ ot->invoke = WM_menu_invoke;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna,
+ "collection",
+ DummyRNA_NULL_items,
+ 0,
+ "Collection",
+ "The collection to remove this object from");
+ RNA_def_enum_funcs(prop, collection_object_active_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
static int collection_create_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- char name[MAX_ID_NAME - 2]; /* id name */
+ Main *bmain = CTX_data_main(C);
+ char name[MAX_ID_NAME - 2]; /* id name */
- RNA_string_get(op->ptr, "name", name);
+ RNA_string_get(op->ptr, "name", name);
- Collection *collection = BKE_collection_add(bmain, NULL, name);
- id_fake_user_set(&collection->id);
+ Collection *collection = BKE_collection_add(bmain, NULL, name);
+ id_fake_user_set(&collection->id);
- CTX_DATA_BEGIN (C, Base *, base, selected_bases)
- {
- BKE_collection_object_add(bmain, collection, base->object);
- DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
- }
- CTX_DATA_END;
+ CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
+ BKE_collection_object_add(bmain, collection, base->object);
+ DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ CTX_DATA_END;
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void COLLECTION_OT_create(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Create New Collection";
- ot->description = "Create an object collection from selected objects";
- ot->idname = "COLLECTION_OT_create";
+ /* identifiers */
+ ot->name = "Create New Collection";
+ ot->description = "Create an object collection from selected objects";
+ ot->idname = "COLLECTION_OT_create";
- /* api callbacks */
- ot->exec = collection_create_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = collection_create_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_string(ot->srna, "name", "Collection", MAX_ID_NAME - 2, "Name", "Name of the new collection");
+ RNA_def_string(
+ ot->srna, "name", "Collection", MAX_ID_NAME - 2, "Name", "Name of the new collection");
}
/****************** properties window operators *********************/
static int collection_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_context(C);
+ Main *bmain = CTX_data_main(C);
- if (ob == NULL)
- return OPERATOR_CANCELLED;
+ if (ob == NULL)
+ return OPERATOR_CANCELLED;
- Collection *collection = BKE_collection_add(bmain, NULL, "Collection");
- id_fake_user_set(&collection->id);
- BKE_collection_object_add(bmain, collection, ob);
+ Collection *collection = BKE_collection_add(bmain, NULL, "Collection");
+ id_fake_user_set(&collection->id);
+ BKE_collection_object_add(bmain, collection, ob);
- DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_collection_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add to Collection";
- ot->idname = "OBJECT_OT_collection_add";
- ot->description = "Add an object to a new collection";
+ /* identifiers */
+ ot->name = "Add to Collection";
+ ot->idname = "OBJECT_OT_collection_add";
+ ot->description = "Add an object to a new collection";
- /* api callbacks */
- ot->exec = collection_add_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = collection_add_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int collection_link_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_context(C);
- Collection *collection = BLI_findlink(&bmain->collections, RNA_enum_get(op->ptr, "collection"));
-
- if (ELEM(NULL, ob, collection))
- return OPERATOR_CANCELLED;
-
- /* Early return check, if the object is already in collection
- * we could skip all the dependency check and just consider
- * operator is finished.
- */
- if (BKE_collection_has_object(collection, ob)) {
- return OPERATOR_FINISHED;
- }
-
- /* Adding object to collection which is used as duplicollection for self is bad idea.
- *
- * It is also bad idea to add object to collection which is in collection which
- * contains our current object.
- */
- if (BKE_collection_object_cyclic_check(bmain, ob, collection)) {
- BKE_report(op->reports, RPT_ERROR, "Could not add the collection because of dependency cycle detected");
- return OPERATOR_CANCELLED;
- }
-
- BKE_collection_object_add(bmain, collection, ob);
-
- DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_context(C);
+ Collection *collection = BLI_findlink(&bmain->collections, RNA_enum_get(op->ptr, "collection"));
+
+ if (ELEM(NULL, ob, collection))
+ return OPERATOR_CANCELLED;
+
+ /* Early return check, if the object is already in collection
+ * we could skip all the dependency check and just consider
+ * operator is finished.
+ */
+ if (BKE_collection_has_object(collection, ob)) {
+ return OPERATOR_FINISHED;
+ }
+
+ /* Adding object to collection which is used as duplicollection for self is bad idea.
+ *
+ * It is also bad idea to add object to collection which is in collection which
+ * contains our current object.
+ */
+ if (BKE_collection_object_cyclic_check(bmain, ob, collection)) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Could not add the collection because of dependency cycle detected");
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_collection_object_add(bmain, collection, ob);
+
+ DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_collection_link(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Link to Collection";
- ot->idname = "OBJECT_OT_collection_link";
- ot->description = "Add an object to an existing collection";
-
- /* api callbacks */
- ot->exec = collection_link_exec;
- ot->invoke = WM_enum_search_invoke;
- ot->poll = ED_operator_objectmode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "");
- RNA_def_enum_funcs(prop, RNA_collection_local_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Link to Collection";
+ ot->idname = "OBJECT_OT_collection_link";
+ ot->description = "Add an object to an existing collection";
+
+ /* api callbacks */
+ ot->exec = collection_link_exec;
+ ot->invoke = WM_enum_search_invoke;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "");
+ RNA_def_enum_funcs(prop, RNA_collection_local_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
static int collection_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_context(C);
- Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_context(C);
+ Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
- if (!ob || !collection)
- return OPERATOR_CANCELLED;
+ if (!ob || !collection)
+ return OPERATOR_CANCELLED;
- BKE_collection_object_remove(bmain, collection, ob, false);
+ BKE_collection_object_remove(bmain, collection, ob, false);
- DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_collection_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Collection";
- ot->idname = "OBJECT_OT_collection_remove";
- ot->description = "Remove the active object from this collection";
+ /* identifiers */
+ ot->name = "Remove Collection";
+ ot->idname = "OBJECT_OT_collection_remove";
+ ot->description = "Remove the active object from this collection";
- /* api callbacks */
- ot->exec = collection_remove_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = collection_remove_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
static int collection_unlink_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
+ Main *bmain = CTX_data_main(C);
+ Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
- if (!collection)
- return OPERATOR_CANCELLED;
+ if (!collection)
+ return OPERATOR_CANCELLED;
- BKE_id_delete(bmain, collection);
+ BKE_id_delete(bmain, collection);
- DEG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_collection_unlink(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Unlink Collection";
- ot->idname = "OBJECT_OT_collection_unlink";
- ot->description = "Unlink the collection from all objects";
+ /* identifiers */
+ ot->name = "Unlink Collection";
+ ot->idname = "OBJECT_OT_collection_unlink";
+ ot->description = "Unlink the collection from all objects";
- /* api callbacks */
- ot->exec = collection_unlink_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = collection_unlink_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* Select objects in the same collection as the active */
static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
-
- if (!collection)
- return OPERATOR_CANCELLED;
-
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
- if (BKE_collection_has_object_recursive(collection, base->object)) {
- ED_object_base_select(base, BA_SELECT);
- }
- }
- }
- CTX_DATA_END;
-
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
+
+ if (!collection)
+ return OPERATOR_CANCELLED;
+
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
+ if (BKE_collection_has_object_recursive(collection, base->object)) {
+ ED_object_base_select(base, BA_SELECT);
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_collection_objects_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Objects in Collection";
- ot->idname = "OBJECT_OT_collection_objects_select";
- ot->description = "Select all objects in collection";
+ /* identifiers */
+ ot->name = "Select Objects in Collection";
+ ot->idname = "OBJECT_OT_collection_objects_select";
+ ot->description = "Select all objects in collection";
- /* api callbacks */
- ot->exec = select_grouped_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = select_grouped_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 988d9373766..c571fc6821e 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include <stdio.h>
#include <string.h>
@@ -56,7 +55,7 @@
#include "DEG_depsgraph_build.h"
#ifdef WITH_PYTHON
-#include "BPY_extern.h"
+# include "BPY_extern.h"
#endif
#include "WM_api.h"
@@ -80,63 +79,63 @@
/* if object in posemode, active bone constraints, else object constraints */
ListBase *get_active_constraints(Object *ob)
{
- if (ob == NULL)
- return NULL;
+ if (ob == NULL)
+ return NULL;
- if (ob->mode & OB_MODE_POSE) {
- bPoseChannel *pchan;
+ if (ob->mode & OB_MODE_POSE) {
+ bPoseChannel *pchan;
- pchan = BKE_pose_channel_active(ob);
- if (pchan)
- return &pchan->constraints;
- }
- else
- return &ob->constraints;
+ pchan = BKE_pose_channel_active(ob);
+ if (pchan)
+ return &pchan->constraints;
+ }
+ else
+ return &ob->constraints;
- return NULL;
+ return NULL;
}
/* Find the list that a given constraint belongs to,
* and/or also get the posechannel this is from (if applicable) */
ListBase *get_constraint_lb(Object *ob, bConstraint *con, bPoseChannel **r_pchan)
{
- if (r_pchan)
- *r_pchan = NULL;
+ if (r_pchan)
+ *r_pchan = NULL;
- if (ELEM(NULL, ob, con))
- return NULL;
+ if (ELEM(NULL, ob, con))
+ return NULL;
- /* try object constraints first */
- if ((BLI_findindex(&ob->constraints, con) != -1)) {
- return &ob->constraints;
- }
+ /* try object constraints first */
+ if ((BLI_findindex(&ob->constraints, con) != -1)) {
+ return &ob->constraints;
+ }
- /* if armature, try pose bones too */
- if (ob->pose) {
- bPoseChannel *pchan;
+ /* if armature, try pose bones too */
+ if (ob->pose) {
+ bPoseChannel *pchan;
- /* try each bone in order
- * NOTE: it's not possible to directly look up the active bone yet, so this will have to do
- */
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if ((BLI_findindex(&pchan->constraints, con) != -1)) {
+ /* try each bone in order
+ * NOTE: it's not possible to directly look up the active bone yet, so this will have to do
+ */
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if ((BLI_findindex(&pchan->constraints, con) != -1)) {
- if (r_pchan)
- *r_pchan = pchan;
+ if (r_pchan)
+ *r_pchan = pchan;
- return &pchan->constraints;
- }
- }
- }
+ return &pchan->constraints;
+ }
+ }
+ }
- /* done */
- return NULL;
+ /* done */
+ return NULL;
}
/* single constraint */
bConstraint *get_active_constraint(Object *ob)
{
- return BKE_constraints_active_get(get_active_constraints(ob));
+ return BKE_constraints_active_get(get_active_constraints(ob));
}
/* -------------- Constraint Management (Add New, Remove, Rename) -------------------- */
@@ -146,367 +145,377 @@ bConstraint *get_active_constraint(Object *ob)
/* this callback sets the text-file to be used for selected menu item */
static void validate_pyconstraint_cb(Main *bmain, void *arg1, void *arg2)
{
- bPythonConstraint *data = arg1;
- Text *text = NULL;
- int index = *((int *)arg2);
- int i;
+ bPythonConstraint *data = arg1;
+ Text *text = NULL;
+ int index = *((int *)arg2);
+ int i;
- /* exception for no script */
- if (index) {
- /* innovative use of a for...loop to search */
- for (text = bmain->texts.first, i = 1; text && index != i; i++, text = text->id.next) ;
- }
- data->text = text;
+ /* exception for no script */
+ if (index) {
+ /* innovative use of a for...loop to search */
+ for (text = bmain->texts.first, i = 1; text && index != i; i++, text = text->id.next)
+ ;
+ }
+ data->text = text;
}
/* this returns a string for the list of usable pyconstraint script names */
static char *buildmenu_pyconstraints(Main *bmain, Text *con_text, int *pyconindex)
{
- DynStr *pupds = BLI_dynstr_new();
- Text *text;
- char *str;
- char buf[64];
- int i;
+ DynStr *pupds = BLI_dynstr_new();
+ Text *text;
+ char *str;
+ char buf[64];
+ int i;
- /* add title first */
- sprintf(buf, "Scripts: %%t|[None]%%x0|");
- BLI_dynstr_append(pupds, buf);
+ /* add title first */
+ sprintf(buf, "Scripts: %%t|[None]%%x0|");
+ BLI_dynstr_append(pupds, buf);
- /* init active-index first */
- if (con_text == NULL)
- *pyconindex = 0;
+ /* init active-index first */
+ if (con_text == NULL)
+ *pyconindex = 0;
- /* loop through markers, adding them */
- for (text = bmain->texts.first, i = 1; text; i++, text = text->id.next) {
- /* this is important to ensure that right script is shown as active */
- if (text == con_text) *pyconindex = i;
+ /* loop through markers, adding them */
+ for (text = bmain->texts.first, i = 1; text; i++, text = text->id.next) {
+ /* this is important to ensure that right script is shown as active */
+ if (text == con_text)
+ *pyconindex = i;
- /* only include valid pyconstraint scripts */
- if (BPY_is_pyconstraint(text)) {
- BLI_dynstr_append(pupds, text->id.name + 2);
+ /* only include valid pyconstraint scripts */
+ if (BPY_is_pyconstraint(text)) {
+ BLI_dynstr_append(pupds, text->id.name + 2);
- sprintf(buf, "%%x%d", i);
- BLI_dynstr_append(pupds, buf);
+ sprintf(buf, "%%x%d", i);
+ BLI_dynstr_append(pupds, buf);
- if (text->id.next)
- BLI_dynstr_append(pupds, "|");
- }
- }
+ if (text->id.next)
+ BLI_dynstr_append(pupds, "|");
+ }
+ }
- /* convert to normal MEM_malloc'd string */
- str = BLI_dynstr_get_cstring(pupds);
- BLI_dynstr_free(pupds);
+ /* convert to normal MEM_malloc'd string */
+ str = BLI_dynstr_get_cstring(pupds);
+ BLI_dynstr_free(pupds);
- return str;
+ return str;
}
#endif /* WITH_PYTHON */
-#if 0 // UNUSED, until pyconstraints are added back.
+#if 0 // UNUSED, until pyconstraints are added back.
/* this callback gets called when the 'refresh' button of a pyconstraint gets pressed */
static void update_pyconstraint_cb(void *arg1, void *arg2)
{
-#ifndef WITH_PYTHON
- (void)arg1; /* unused */
- (void)arg2; /* unused */
-#else
- Object *owner = (Object *)arg1;
- bConstraint *con = (bConstraint *)arg2;
- if (owner && con)
- BPY_pyconstraint_update(owner, con);
-#endif
+# ifndef WITH_PYTHON
+ (void)arg1; /* unused */
+ (void)arg2; /* unused */
+# else
+ Object *owner = (Object *)arg1;
+ bConstraint *con = (bConstraint *)arg2;
+ if (owner && con)
+ BPY_pyconstraint_update(owner, con);
+# endif
}
-#endif // UNUSED
+#endif // UNUSED
/* helper function for add_constriant - sets the last target for the active constraint */
-static void set_constraint_nth_target(bConstraint *con, Object *target, const char subtarget[], int index)
-{
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
- int num_targets, i;
-
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
- num_targets = BLI_listbase_count(&targets);
-
- if (index < 0) {
- if (abs(index) < num_targets)
- index = num_targets - abs(index);
- else
- index = num_targets - 1;
- }
- else if (index >= num_targets) {
- index = num_targets - 1;
- }
-
- for (ct = targets.first, i = 0; ct; ct = ct->next, i++) {
- if (i == index) {
- ct->tar = target;
- BLI_strncpy(ct->subtarget, subtarget, sizeof(ct->subtarget));
- break;
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 0);
- }
+static void set_constraint_nth_target(bConstraint *con,
+ Object *target,
+ const char subtarget[],
+ int index)
+{
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+ int num_targets, i;
+
+ if (cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+ num_targets = BLI_listbase_count(&targets);
+
+ if (index < 0) {
+ if (abs(index) < num_targets)
+ index = num_targets - abs(index);
+ else
+ index = num_targets - 1;
+ }
+ else if (index >= num_targets) {
+ index = num_targets - 1;
+ }
+
+ for (ct = targets.first, i = 0; ct; ct = ct->next, i++) {
+ if (i == index) {
+ ct->tar = target;
+ BLI_strncpy(ct->subtarget, subtarget, sizeof(ct->subtarget));
+ break;
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
}
/* ------------- Constraint Sanity Testing ------------------- */
-static void test_constraint(Main *bmain, Object *owner, bPoseChannel *pchan, bConstraint *con, int type)
-{
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
- bool check_targets = true;
-
- /* clear disabled-flag first */
- con->flag &= ~CONSTRAINT_DISABLE;
-
- if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
- bKinematicConstraint *data = con->data;
-
- /* bad: we need a separate set of checks here as poletarget is
- * optional... otherwise poletarget must exist too or else
- * the constraint is deemed invalid
- */
- /* default IK check ... */
- if (BKE_object_exists_check(bmain, data->tar) == 0) {
- data->tar = NULL;
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (data->tar == owner) {
- if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->subtarget)) {
- con->flag |= CONSTRAINT_DISABLE;
- }
- }
-
- if (data->poletar) {
- if (BKE_object_exists_check(bmain, data->poletar) == 0) {
- data->poletar = NULL;
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (data->poletar == owner) {
- if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->polesubtarget)) {
- con->flag |= CONSTRAINT_DISABLE;
- }
- }
- }
- /* ... can be overwritten here */
- BIK_test_constraint(owner, con);
- /* targets have already been checked for this */
- check_targets = false;
- }
- else if (con->type == CONSTRAINT_TYPE_PIVOT) {
- bPivotConstraint *data = con->data;
-
- /* target doesn't have to exist, but if it is non-null, it must exist! */
- if (data->tar && BKE_object_exists_check(bmain, data->tar) == 0) {
- data->tar = NULL;
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (data->tar == owner) {
- if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->subtarget)) {
- con->flag |= CONSTRAINT_DISABLE;
- }
- }
-
- /* targets have already been checked for this */
- check_targets = false;
- }
- else if (con->type == CONSTRAINT_TYPE_ACTION) {
- bActionConstraint *data = con->data;
-
- /* validate action */
- if (data->act == NULL) {
- /* must have action */
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (data->act->idroot != ID_OB) {
- /* only object-rooted actions can be used */
- data->act = NULL;
- con->flag |= CONSTRAINT_DISABLE;
- }
- }
- else if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) {
- bFollowPathConstraint *data = con->data;
-
- /* don't allow track/up axes to be the same */
- if (data->upflag == data->trackflag)
- con->flag |= CONSTRAINT_DISABLE;
- if (data->upflag + 3 == data->trackflag)
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (con->type == CONSTRAINT_TYPE_TRACKTO) {
- bTrackToConstraint *data = con->data;
-
- /* don't allow track/up axes to be the same */
- if (data->reserved2 == data->reserved1)
- con->flag |= CONSTRAINT_DISABLE;
- if (data->reserved2 + 3 == data->reserved1)
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (con->type == CONSTRAINT_TYPE_LOCKTRACK) {
- bLockTrackConstraint *data = con->data;
-
- if (data->lockflag == data->trackflag)
- con->flag |= CONSTRAINT_DISABLE;
- if (data->lockflag + 3 == data->trackflag)
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (con->type == CONSTRAINT_TYPE_SPLINEIK) {
- bSplineIKConstraint *data = con->data;
-
- /* if the number of points does not match the amount required by the chain length,
- * free the points array and request a rebind...
- */
- if ((data->points == NULL) || (data->numpoints != data->chainlen + 1)) {
- /* free the points array */
- if (data->points) {
- MEM_freeN(data->points);
- data->points = NULL;
- }
-
- /* clear the bound flag, forcing a rebind next time this is evaluated */
- data->flag &= ~CONSTRAINT_SPLINEIK_BOUND;
- }
- }
- else if (con->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
- bFollowTrackConstraint *data = con->data;
-
- if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0) {
- if (data->clip != NULL && data->track[0]) {
- MovieTracking *tracking = &data->clip->tracking;
- MovieTrackingObject *tracking_object;
-
- if (data->object[0])
- tracking_object = BKE_tracking_object_get_named(tracking, data->object);
- else
- tracking_object = BKE_tracking_object_get_camera(tracking);
-
- if (!tracking_object) {
- con->flag |= CONSTRAINT_DISABLE;
- }
- else {
- if (!BKE_tracking_track_get_named(tracking, tracking_object, data->track))
- con->flag |= CONSTRAINT_DISABLE;
- }
- }
- else {
- con->flag |= CONSTRAINT_DISABLE;
- }
- }
- }
- else if (con->type == CONSTRAINT_TYPE_CAMERASOLVER) {
- bCameraSolverConstraint *data = con->data;
-
- if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL))
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (con->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
- bObjectSolverConstraint *data = con->data;
-
- if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL))
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (con->type == CONSTRAINT_TYPE_TRANSFORM_CACHE) {
- bTransformCacheConstraint *data = con->data;
-
- if ((data->cache_file == NULL) || (data->object_path[0] == '\0')) {
- con->flag |= CONSTRAINT_DISABLE;
- }
- }
-
- /* Check targets for constraints */
- if (check_targets && cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- /* constraints with empty target list that actually require targets */
- if (!targets.first && ELEM(con->type, CONSTRAINT_TYPE_ARMATURE)) {
- con->flag |= CONSTRAINT_DISABLE;
- }
-
- /* disable and clear constraints targets that are incorrect */
- for (ct = targets.first; ct; ct = ct->next) {
- /* general validity checks (for those constraints that need this) */
- if (BKE_object_exists_check(bmain, ct->tar) == 0) {
- /* object doesn't exist, but constraint requires target */
- ct->tar = NULL;
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (ct->tar == owner) {
- if (type == CONSTRAINT_OBTYPE_BONE) {
- if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), ct->subtarget)) {
- /* bone must exist in armature... */
- /* TODO: clear subtarget? */
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (STREQ(pchan->name, ct->subtarget)) {
- /* cannot target self */
- ct->subtarget[0] = '\0';
- con->flag |= CONSTRAINT_DISABLE;
- }
- }
- else {
- /* cannot use self as target */
- ct->tar = NULL;
- con->flag |= CONSTRAINT_DISABLE;
- }
- }
-
- /* target checks for specific constraints */
- if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK)) {
- if (ct->tar) {
- if (ct->tar->type != OB_CURVE) {
- ct->tar = NULL;
- con->flag |= CONSTRAINT_DISABLE;
- }
- else {
- Curve *cu = ct->tar->data;
-
- /* auto-set 'Path' setting on curve so this works */
- cu->flag |= CU_PATH;
- }
- }
- }
- else if (con->type == CONSTRAINT_TYPE_ARMATURE) {
- if (ct->tar) {
- if (ct->tar->type != OB_ARMATURE) {
- ct->tar = NULL;
- con->flag |= CONSTRAINT_DISABLE;
- }
- else if (!BKE_armature_find_bone_name(BKE_armature_from_object(ct->tar), ct->subtarget)) {
- /* bone must exist in armature... */
- con->flag |= CONSTRAINT_DISABLE;
- }
- }
- }
- }
-
- /* free any temporary targets */
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 0);
- }
+static void test_constraint(
+ Main *bmain, Object *owner, bPoseChannel *pchan, bConstraint *con, int type)
+{
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ ListBase targets = {NULL, NULL};
+ bConstraintTarget *ct;
+ bool check_targets = true;
+
+ /* clear disabled-flag first */
+ con->flag &= ~CONSTRAINT_DISABLE;
+
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
+ bKinematicConstraint *data = con->data;
+
+ /* bad: we need a separate set of checks here as poletarget is
+ * optional... otherwise poletarget must exist too or else
+ * the constraint is deemed invalid
+ */
+ /* default IK check ... */
+ if (BKE_object_exists_check(bmain, data->tar) == 0) {
+ data->tar = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (data->tar == owner) {
+ if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->subtarget)) {
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+
+ if (data->poletar) {
+ if (BKE_object_exists_check(bmain, data->poletar) == 0) {
+ data->poletar = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (data->poletar == owner) {
+ if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->polesubtarget)) {
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+ }
+ /* ... can be overwritten here */
+ BIK_test_constraint(owner, con);
+ /* targets have already been checked for this */
+ check_targets = false;
+ }
+ else if (con->type == CONSTRAINT_TYPE_PIVOT) {
+ bPivotConstraint *data = con->data;
+
+ /* target doesn't have to exist, but if it is non-null, it must exist! */
+ if (data->tar && BKE_object_exists_check(bmain, data->tar) == 0) {
+ data->tar = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (data->tar == owner) {
+ if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), data->subtarget)) {
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+
+ /* targets have already been checked for this */
+ check_targets = false;
+ }
+ else if (con->type == CONSTRAINT_TYPE_ACTION) {
+ bActionConstraint *data = con->data;
+
+ /* validate action */
+ if (data->act == NULL) {
+ /* must have action */
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (data->act->idroot != ID_OB) {
+ /* only object-rooted actions can be used */
+ data->act = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+ else if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) {
+ bFollowPathConstraint *data = con->data;
+
+ /* don't allow track/up axes to be the same */
+ if (data->upflag == data->trackflag)
+ con->flag |= CONSTRAINT_DISABLE;
+ if (data->upflag + 3 == data->trackflag)
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (con->type == CONSTRAINT_TYPE_TRACKTO) {
+ bTrackToConstraint *data = con->data;
+
+ /* don't allow track/up axes to be the same */
+ if (data->reserved2 == data->reserved1)
+ con->flag |= CONSTRAINT_DISABLE;
+ if (data->reserved2 + 3 == data->reserved1)
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (con->type == CONSTRAINT_TYPE_LOCKTRACK) {
+ bLockTrackConstraint *data = con->data;
+
+ if (data->lockflag == data->trackflag)
+ con->flag |= CONSTRAINT_DISABLE;
+ if (data->lockflag + 3 == data->trackflag)
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (con->type == CONSTRAINT_TYPE_SPLINEIK) {
+ bSplineIKConstraint *data = con->data;
+
+ /* if the number of points does not match the amount required by the chain length,
+ * free the points array and request a rebind...
+ */
+ if ((data->points == NULL) || (data->numpoints != data->chainlen + 1)) {
+ /* free the points array */
+ if (data->points) {
+ MEM_freeN(data->points);
+ data->points = NULL;
+ }
+
+ /* clear the bound flag, forcing a rebind next time this is evaluated */
+ data->flag &= ~CONSTRAINT_SPLINEIK_BOUND;
+ }
+ }
+ else if (con->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
+ bFollowTrackConstraint *data = con->data;
+
+ if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0) {
+ if (data->clip != NULL && data->track[0]) {
+ MovieTracking *tracking = &data->clip->tracking;
+ MovieTrackingObject *tracking_object;
+
+ if (data->object[0])
+ tracking_object = BKE_tracking_object_get_named(tracking, data->object);
+ else
+ tracking_object = BKE_tracking_object_get_camera(tracking);
+
+ if (!tracking_object) {
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else {
+ if (!BKE_tracking_track_get_named(tracking, tracking_object, data->track))
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+ else {
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+ }
+ else if (con->type == CONSTRAINT_TYPE_CAMERASOLVER) {
+ bCameraSolverConstraint *data = con->data;
+
+ if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL))
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (con->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
+ bObjectSolverConstraint *data = con->data;
+
+ if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL))
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (con->type == CONSTRAINT_TYPE_TRANSFORM_CACHE) {
+ bTransformCacheConstraint *data = con->data;
+
+ if ((data->cache_file == NULL) || (data->object_path[0] == '\0')) {
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+
+ /* Check targets for constraints */
+ if (check_targets && cti && cti->get_constraint_targets) {
+ cti->get_constraint_targets(con, &targets);
+
+ /* constraints with empty target list that actually require targets */
+ if (!targets.first && ELEM(con->type, CONSTRAINT_TYPE_ARMATURE)) {
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+
+ /* disable and clear constraints targets that are incorrect */
+ for (ct = targets.first; ct; ct = ct->next) {
+ /* general validity checks (for those constraints that need this) */
+ if (BKE_object_exists_check(bmain, ct->tar) == 0) {
+ /* object doesn't exist, but constraint requires target */
+ ct->tar = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (ct->tar == owner) {
+ if (type == CONSTRAINT_OBTYPE_BONE) {
+ if (!BKE_armature_find_bone_name(BKE_armature_from_object(owner), ct->subtarget)) {
+ /* bone must exist in armature... */
+ /* TODO: clear subtarget? */
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (STREQ(pchan->name, ct->subtarget)) {
+ /* cannot target self */
+ ct->subtarget[0] = '\0';
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+ else {
+ /* cannot use self as target */
+ ct->tar = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+
+ /* target checks for specific constraints */
+ if (ELEM(con->type,
+ CONSTRAINT_TYPE_FOLLOWPATH,
+ CONSTRAINT_TYPE_CLAMPTO,
+ CONSTRAINT_TYPE_SPLINEIK)) {
+ if (ct->tar) {
+ if (ct->tar->type != OB_CURVE) {
+ ct->tar = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else {
+ Curve *cu = ct->tar->data;
+
+ /* auto-set 'Path' setting on curve so this works */
+ cu->flag |= CU_PATH;
+ }
+ }
+ }
+ else if (con->type == CONSTRAINT_TYPE_ARMATURE) {
+ if (ct->tar) {
+ if (ct->tar->type != OB_ARMATURE) {
+ ct->tar = NULL;
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ else if (!BKE_armature_find_bone_name(BKE_armature_from_object(ct->tar),
+ ct->subtarget)) {
+ /* bone must exist in armature... */
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
+ }
+ }
+
+ /* free any temporary targets */
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 0);
+ }
}
static int constraint_type_get(Object *owner, bPoseChannel *pchan)
{
- int type;
- /* Check parents */
- if (pchan) {
- switch (owner->type) {
- case OB_ARMATURE:
- type = CONSTRAINT_OBTYPE_BONE;
- break;
- default:
- type = CONSTRAINT_OBTYPE_OBJECT;
- break;
- }
- }
- else
- type = CONSTRAINT_OBTYPE_OBJECT;
- return type;
+ int type;
+ /* Check parents */
+ if (pchan) {
+ switch (owner->type) {
+ case OB_ARMATURE:
+ type = CONSTRAINT_OBTYPE_BONE;
+ break;
+ default:
+ type = CONSTRAINT_OBTYPE_OBJECT;
+ break;
+ }
+ }
+ else
+ type = CONSTRAINT_OBTYPE_OBJECT;
+ return type;
}
/* checks validity of object pointers, and NULLs,
@@ -514,185 +523,192 @@ static int constraint_type_get(Object *owner, bPoseChannel *pchan)
*/
static void test_constraints(Main *bmain, Object *owner, bPoseChannel *pchan)
{
- bConstraint *curcon;
- ListBase *conlist = NULL;
- int type;
+ bConstraint *curcon;
+ ListBase *conlist = NULL;
+ int type;
- if (owner == NULL) return;
+ if (owner == NULL)
+ return;
- type = constraint_type_get(owner, pchan);
+ type = constraint_type_get(owner, pchan);
- /* Get the constraint list for this object */
- switch (type) {
- case CONSTRAINT_OBTYPE_OBJECT:
- conlist = &owner->constraints;
- break;
- case CONSTRAINT_OBTYPE_BONE:
- conlist = &pchan->constraints;
- break;
- }
+ /* Get the constraint list for this object */
+ switch (type) {
+ case CONSTRAINT_OBTYPE_OBJECT:
+ conlist = &owner->constraints;
+ break;
+ case CONSTRAINT_OBTYPE_BONE:
+ conlist = &pchan->constraints;
+ break;
+ }
- /* Check all constraints - is constraint valid? */
- if (conlist) {
- for (curcon = conlist->first; curcon; curcon = curcon->next) {
- test_constraint(bmain, owner, pchan, curcon, type);
- }
- }
+ /* Check all constraints - is constraint valid? */
+ if (conlist) {
+ for (curcon = conlist->first; curcon; curcon = curcon->next) {
+ test_constraint(bmain, owner, pchan, curcon, type);
+ }
+ }
}
void object_test_constraints(Main *bmain, Object *owner)
{
- if (owner->constraints.first)
- test_constraints(bmain, owner, NULL);
+ if (owner->constraints.first)
+ test_constraints(bmain, owner, NULL);
- if (owner->type == OB_ARMATURE && owner->pose) {
- bPoseChannel *pchan;
+ if (owner->type == OB_ARMATURE && owner->pose) {
+ bPoseChannel *pchan;
- for (pchan = owner->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->constraints.first)
- test_constraints(bmain, owner, pchan);
- }
- }
+ for (pchan = owner->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->constraints.first)
+ test_constraints(bmain, owner, pchan);
+ }
+ }
}
static void object_test_constraint(Main *bmain, Object *owner, bConstraint *con)
{
- if (owner->type == OB_ARMATURE && owner->pose) {
- if (BLI_findindex(&owner->constraints, con) != -1) {
- test_constraint(bmain, owner, NULL, con, CONSTRAINT_OBTYPE_OBJECT);
- }
- else {
- bPoseChannel *pchan;
- for (pchan = owner->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (BLI_findindex(&pchan->constraints, con) != -1) {
- test_constraint(bmain, owner, pchan, con, CONSTRAINT_OBTYPE_BONE);
- break;
- }
- }
- }
- }
- else {
- test_constraint(bmain, owner, NULL, con, CONSTRAINT_OBTYPE_OBJECT);
- }
+ if (owner->type == OB_ARMATURE && owner->pose) {
+ if (BLI_findindex(&owner->constraints, con) != -1) {
+ test_constraint(bmain, owner, NULL, con, CONSTRAINT_OBTYPE_OBJECT);
+ }
+ else {
+ bPoseChannel *pchan;
+ for (pchan = owner->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (BLI_findindex(&pchan->constraints, con) != -1) {
+ test_constraint(bmain, owner, pchan, con, CONSTRAINT_OBTYPE_BONE);
+ break;
+ }
+ }
+ }
+ }
+ else {
+ test_constraint(bmain, owner, NULL, con, CONSTRAINT_OBTYPE_OBJECT);
+ }
}
/************************ generic functions for operators using constraint names and data context *********************/
-#define EDIT_CONSTRAINT_OWNER_OBJECT 0
-#define EDIT_CONSTRAINT_OWNER_BONE 1
+#define EDIT_CONSTRAINT_OWNER_OBJECT 0
+#define EDIT_CONSTRAINT_OWNER_BONE 1
static const EnumPropertyItem constraint_owner_items[] = {
- {EDIT_CONSTRAINT_OWNER_OBJECT, "OBJECT", 0, "Object", "Edit a constraint on the active object"},
- {EDIT_CONSTRAINT_OWNER_BONE, "BONE", 0, "Bone", "Edit a constraint on the active bone"},
- {0, NULL, 0, NULL, NULL},
+ {EDIT_CONSTRAINT_OWNER_OBJECT,
+ "OBJECT",
+ 0,
+ "Object",
+ "Edit a constraint on the active object"},
+ {EDIT_CONSTRAINT_OWNER_BONE, "BONE", 0, "Bone", "Edit a constraint on the active bone"},
+ {0, NULL, 0, NULL, NULL},
};
-
static bool edit_constraint_poll_generic(bContext *C, StructRNA *rna_type)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", rna_type);
- Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", rna_type);
+ Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
- if (!ptr.data) {
- CTX_wm_operator_poll_msg_set(C, "Context missing 'constraint'");
- return 0;
- }
+ if (!ptr.data) {
+ CTX_wm_operator_poll_msg_set(C, "Context missing 'constraint'");
+ return 0;
+ }
- if (!ob) {
- CTX_wm_operator_poll_msg_set(C, "Context missing active object");
- return 0;
- }
+ if (!ob) {
+ CTX_wm_operator_poll_msg_set(C, "Context missing active object");
+ return 0;
+ }
- if (ID_IS_LINKED(ob) || (ptr.id.data && ID_IS_LINKED(ptr.id.data))) {
- CTX_wm_operator_poll_msg_set(C, "Cannot edit library data");
- return 0;
- }
+ if (ID_IS_LINKED(ob) || (ptr.id.data && ID_IS_LINKED(ptr.id.data))) {
+ CTX_wm_operator_poll_msg_set(C, "Cannot edit library data");
+ return 0;
+ }
- if (ID_IS_STATIC_OVERRIDE(ob)) {
- CTX_wm_operator_poll_msg_set(C, "Cannot edit constraints coming from static override");
- return (((bConstraint *)ptr.data)->flag & CONSTRAINT_STATICOVERRIDE_LOCAL) != 0;
- }
+ if (ID_IS_STATIC_OVERRIDE(ob)) {
+ CTX_wm_operator_poll_msg_set(C, "Cannot edit constraints coming from static override");
+ return (((bConstraint *)ptr.data)->flag & CONSTRAINT_STATICOVERRIDE_LOCAL) != 0;
+ }
- return 1;
+ return 1;
}
static bool edit_constraint_poll(bContext *C)
{
- return edit_constraint_poll_generic(C, &RNA_Constraint);
+ return edit_constraint_poll_generic(C, &RNA_Constraint);
}
static void edit_constraint_properties(wmOperatorType *ot)
{
- PropertyRNA *prop;
- prop = RNA_def_string(ot->srna, "constraint", NULL, MAX_NAME, "Constraint", "Name of the constraint to edit");
- RNA_def_property_flag(prop, PROP_HIDDEN);
- prop = RNA_def_enum(ot->srna, "owner", constraint_owner_items, 0, "Owner", "The owner of this constraint");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ PropertyRNA *prop;
+ prop = RNA_def_string(
+ ot->srna, "constraint", NULL, MAX_NAME, "Constraint", "Name of the constraint to edit");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_enum(
+ ot->srna, "owner", constraint_owner_items, 0, "Owner", "The owner of this constraint");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
static int edit_constraint_invoke_properties(bContext *C, wmOperator *op)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
- Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
- bConstraint *con;
- ListBase *list;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
+ Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
+ bConstraint *con;
+ ListBase *list;
- if (RNA_struct_property_is_set(op->ptr, "constraint") && RNA_struct_property_is_set(op->ptr, "owner"))
- return 1;
+ if (RNA_struct_property_is_set(op->ptr, "constraint") &&
+ RNA_struct_property_is_set(op->ptr, "owner"))
+ return 1;
- if (ptr.data) {
- con = ptr.data;
- RNA_string_set(op->ptr, "constraint", con->name);
+ if (ptr.data) {
+ con = ptr.data;
+ RNA_string_set(op->ptr, "constraint", con->name);
- list = get_constraint_lb(ob, con, NULL);
+ list = get_constraint_lb(ob, con, NULL);
- if (&ob->constraints == list)
- RNA_enum_set(op->ptr, "owner", EDIT_CONSTRAINT_OWNER_OBJECT);
- else
- RNA_enum_set(op->ptr, "owner", EDIT_CONSTRAINT_OWNER_BONE);
+ if (&ob->constraints == list)
+ RNA_enum_set(op->ptr, "owner", EDIT_CONSTRAINT_OWNER_OBJECT);
+ else
+ RNA_enum_set(op->ptr, "owner", EDIT_CONSTRAINT_OWNER_BONE);
- return 1;
- }
+ return 1;
+ }
- return 0;
+ return 0;
}
static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int type)
{
- char constraint_name[MAX_NAME];
- int owner = RNA_enum_get(op->ptr, "owner");
- bConstraint *con;
- ListBase *list = NULL;
-
- RNA_string_get(op->ptr, "constraint", constraint_name);
-
- if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
- list = &ob->constraints;
- }
- else if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
- bPoseChannel *pchan = BKE_pose_channel_active(ob);
- if (pchan)
- list = &pchan->constraints;
- else {
- //if (G.debug & G_DEBUG)
- //printf("edit_constraint_property_get: No active bone for object '%s'\n", (ob) ? ob->id.name + 2 : "<None>");
- return NULL;
- }
- }
- else {
- //if (G.debug & G_DEBUG)
- //printf("edit_constraint_property_get: defaulting to getting list in the standard way\n");
- list = get_active_constraints(ob);
- }
-
- con = BKE_constraints_find_name(list, constraint_name);
- //if (G.debug & G_DEBUG)
- //printf("constraint found = %p, %s\n", (void *)con, (con) ? con->name : "<Not found>");
-
- if (con && (type != 0) && (con->type != type))
- con = NULL;
-
- return con;
+ char constraint_name[MAX_NAME];
+ int owner = RNA_enum_get(op->ptr, "owner");
+ bConstraint *con;
+ ListBase *list = NULL;
+
+ RNA_string_get(op->ptr, "constraint", constraint_name);
+
+ if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
+ list = &ob->constraints;
+ }
+ else if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
+ bPoseChannel *pchan = BKE_pose_channel_active(ob);
+ if (pchan)
+ list = &pchan->constraints;
+ else {
+ //if (G.debug & G_DEBUG)
+ //printf("edit_constraint_property_get: No active bone for object '%s'\n", (ob) ? ob->id.name + 2 : "<None>");
+ return NULL;
+ }
+ }
+ else {
+ //if (G.debug & G_DEBUG)
+ //printf("edit_constraint_property_get: defaulting to getting list in the standard way\n");
+ list = get_active_constraints(ob);
+ }
+
+ con = BKE_constraints_find_name(list, constraint_name);
+ //if (G.debug & G_DEBUG)
+ //printf("constraint found = %p, %s\n", (void *)con, (con) ? con->name : "<Not found>");
+
+ if (con && (type != 0) && (con->type != type))
+ con = NULL;
+
+ return con;
}
/* ********************** CONSTRAINT-SPECIFIC STUFF ********************* */
@@ -702,733 +718,755 @@ static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int
static int stretchto_reset_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_active_context(C);
- bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_STRETCHTO);
- bStretchToConstraint *data = (con) ? (bStretchToConstraint *)con->data : NULL;
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_active_context(C);
+ bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_STRETCHTO);
+ bStretchToConstraint *data = (con) ? (bStretchToConstraint *)con->data : NULL;
- /* despite 3 layers of checks, we may still not be able to find a constraint */
- if (data == NULL)
- return OPERATOR_CANCELLED;
+ /* despite 3 layers of checks, we may still not be able to find a constraint */
+ if (data == NULL)
+ return OPERATOR_CANCELLED;
- /* just set original length to 0.0, which will cause a reset on next recalc */
- data->orglength = 0.0f;
- ED_object_constraint_update(bmain, ob);
+ /* just set original length to 0.0, which will cause a reset on next recalc */
+ data->orglength = 0.0f;
+ ED_object_constraint_update(bmain, ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, NULL);
- return OPERATOR_FINISHED;
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, NULL);
+ return OPERATOR_FINISHED;
}
static int stretchto_reset_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op))
- return stretchto_reset_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_constraint_invoke_properties(C, op))
+ return stretchto_reset_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void CONSTRAINT_OT_stretchto_reset(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reset Original Length";
- ot->idname = "CONSTRAINT_OT_stretchto_reset";
- ot->description = "Reset original length of bone for Stretch To Constraint";
+ /* identifiers */
+ ot->name = "Reset Original Length";
+ ot->idname = "CONSTRAINT_OT_stretchto_reset";
+ ot->description = "Reset original length of bone for Stretch To Constraint";
- /* callbacks */
- ot->invoke = stretchto_reset_invoke;
- ot->exec = stretchto_reset_exec;
- ot->poll = edit_constraint_poll;
+ /* callbacks */
+ ot->invoke = stretchto_reset_invoke;
+ ot->exec = stretchto_reset_exec;
+ ot->poll = edit_constraint_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- edit_constraint_properties(ot);
+ /* properties */
+ edit_constraint_properties(ot);
}
-
static int limitdistance_reset_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_active_context(C);
- bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_DISTLIMIT);
- bDistLimitConstraint *data = (con) ? (bDistLimitConstraint *)con->data : NULL;
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_active_context(C);
+ bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_DISTLIMIT);
+ bDistLimitConstraint *data = (con) ? (bDistLimitConstraint *)con->data : NULL;
- /* despite 3 layers of checks, we may still not be able to find a constraint */
- if (data == NULL)
- return OPERATOR_CANCELLED;
+ /* despite 3 layers of checks, we may still not be able to find a constraint */
+ if (data == NULL)
+ return OPERATOR_CANCELLED;
- /* just set original length to 0.0, which will cause a reset on next recalc */
- data->dist = 0.0f;
- ED_object_constraint_update(bmain, ob);
+ /* just set original length to 0.0, which will cause a reset on next recalc */
+ data->dist = 0.0f;
+ ED_object_constraint_update(bmain, ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, NULL);
- return OPERATOR_FINISHED;
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, NULL);
+ return OPERATOR_FINISHED;
}
static int limitdistance_reset_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op))
- return limitdistance_reset_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_constraint_invoke_properties(C, op))
+ return limitdistance_reset_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void CONSTRAINT_OT_limitdistance_reset(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Reset Distance";
- ot->idname = "CONSTRAINT_OT_limitdistance_reset";
- ot->description = "Reset limiting distance for Limit Distance Constraint";
+ /* identifiers */
+ ot->name = "Reset Distance";
+ ot->idname = "CONSTRAINT_OT_limitdistance_reset";
+ ot->description = "Reset limiting distance for Limit Distance Constraint";
- /* callbacks */
- ot->invoke = limitdistance_reset_invoke;
- ot->exec = limitdistance_reset_exec;
- ot->poll = edit_constraint_poll;
+ /* callbacks */
+ ot->invoke = limitdistance_reset_invoke;
+ ot->exec = limitdistance_reset_exec;
+ ot->poll = edit_constraint_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- edit_constraint_properties(ot);
+ /* properties */
+ edit_constraint_properties(ot);
}
/* ------------- Child-Of Constraint ------------------ */
-static void child_get_inverse_matrix(const bContext *C, Scene *scene, Object *ob, bConstraint *con, float invmat[4][4], const int owner)
-{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
-
- /* nullify inverse matrix first */
- unit_m4(invmat);
-
- if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
- bPoseChannel *pchan;
- /* try to find a pose channel - assume that this is the constraint owner */
- /* TODO: get from context instead? */
- if (ob && ob->pose && (pchan = BKE_pose_channel_active(ob))) {
- bConstraint *con_last;
- /* calculate/set inverse matrix:
- * We just calculate all transform-stack eval up to but not including this constraint.
- * This is because inverse should just inverse correct for just the constraint's influence
- * when it gets applied; that is, at the time of application, we don't know anything about
- * what follows.
- */
- float imat[4][4], tmat[4][4];
- float pmat[4][4];
-
- /* make sure we passed the correct constraint */
- BLI_assert(BLI_findindex(&pchan->constraints, con) != -1);
-
- /* 1. calculate posemat where inverse doesn't exist yet (inverse was cleared above),
- * to use as baseline ("pmat") to derive delta from. This extra calc saves users
- * from having pressing "Clear Inverse" first
- */
- BKE_pose_where_is(depsgraph, scene, ob);
- copy_m4_m4(pmat, pchan->pose_mat);
-
- /* 2. knock out constraints starting from this one */
- con_last = pchan->constraints.last;
- pchan->constraints.last = con->prev;
-
- if (con->prev) {
- /* new end must not point to this one, else this chain cutting is useless */
- con->prev->next = NULL;
- }
- else {
- /* constraint was first */
- pchan->constraints.first = NULL;
- }
-
- /* 3. solve pose without disabled constraints */
- BKE_pose_where_is(depsgraph, scene, ob);
-
- /* 4. determine effect of constraint by removing the newly calculated
- * pchan->pose_mat from the original pchan->pose_mat, thus determining
- * the effect of the constraint
- */
- invert_m4_m4(imat, pchan->pose_mat);
- mul_m4_m4m4(tmat, pmat, imat);
- invert_m4_m4(invmat, tmat);
-
- /* 5. restore constraints */
- pchan->constraints.last = con_last;
-
- if (con->prev) {
- /* hook up prev to this one again */
- con->prev->next = con;
- }
- else {
- /* set as first again */
- pchan->constraints.first = con;
- }
-
- /* 6. recalculate pose with new inv-mat applied */
- BKE_pose_where_is(depsgraph, scene, ob);
- }
- }
- if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
- if (ob) {
- Object workob;
-
- /* make sure we passed the correct constraint */
- BLI_assert(BLI_findindex(&ob->constraints, con) != -1);
-
- /* use BKE_object_workob_calc_parent to find inverse - just like for normal parenting */
- BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- invert_m4_m4(invmat, workob.obmat);
- }
- }
+static void child_get_inverse_matrix(const bContext *C,
+ Scene *scene,
+ Object *ob,
+ bConstraint *con,
+ float invmat[4][4],
+ const int owner)
+{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+
+ /* nullify inverse matrix first */
+ unit_m4(invmat);
+
+ if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
+ bPoseChannel *pchan;
+ /* try to find a pose channel - assume that this is the constraint owner */
+ /* TODO: get from context instead? */
+ if (ob && ob->pose && (pchan = BKE_pose_channel_active(ob))) {
+ bConstraint *con_last;
+ /* calculate/set inverse matrix:
+ * We just calculate all transform-stack eval up to but not including this constraint.
+ * This is because inverse should just inverse correct for just the constraint's influence
+ * when it gets applied; that is, at the time of application, we don't know anything about
+ * what follows.
+ */
+ float imat[4][4], tmat[4][4];
+ float pmat[4][4];
+
+ /* make sure we passed the correct constraint */
+ BLI_assert(BLI_findindex(&pchan->constraints, con) != -1);
+
+ /* 1. calculate posemat where inverse doesn't exist yet (inverse was cleared above),
+ * to use as baseline ("pmat") to derive delta from. This extra calc saves users
+ * from having pressing "Clear Inverse" first
+ */
+ BKE_pose_where_is(depsgraph, scene, ob);
+ copy_m4_m4(pmat, pchan->pose_mat);
+
+ /* 2. knock out constraints starting from this one */
+ con_last = pchan->constraints.last;
+ pchan->constraints.last = con->prev;
+
+ if (con->prev) {
+ /* new end must not point to this one, else this chain cutting is useless */
+ con->prev->next = NULL;
+ }
+ else {
+ /* constraint was first */
+ pchan->constraints.first = NULL;
+ }
+
+ /* 3. solve pose without disabled constraints */
+ BKE_pose_where_is(depsgraph, scene, ob);
+
+ /* 4. determine effect of constraint by removing the newly calculated
+ * pchan->pose_mat from the original pchan->pose_mat, thus determining
+ * the effect of the constraint
+ */
+ invert_m4_m4(imat, pchan->pose_mat);
+ mul_m4_m4m4(tmat, pmat, imat);
+ invert_m4_m4(invmat, tmat);
+
+ /* 5. restore constraints */
+ pchan->constraints.last = con_last;
+
+ if (con->prev) {
+ /* hook up prev to this one again */
+ con->prev->next = con;
+ }
+ else {
+ /* set as first again */
+ pchan->constraints.first = con;
+ }
+
+ /* 6. recalculate pose with new inv-mat applied */
+ BKE_pose_where_is(depsgraph, scene, ob);
+ }
+ }
+ if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
+ if (ob) {
+ Object workob;
+
+ /* make sure we passed the correct constraint */
+ BLI_assert(BLI_findindex(&ob->constraints, con) != -1);
+
+ /* use BKE_object_workob_calc_parent to find inverse - just like for normal parenting */
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
+ invert_m4_m4(invmat, workob.obmat);
+ }
+ }
}
/* ChildOf Constraint - set inverse callback */
static int childof_set_inverse_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF);
- bChildOfConstraint *data = (con) ? (bChildOfConstraint *)con->data : NULL;
- const int owner = RNA_enum_get(op->ptr, "owner");
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF);
+ bChildOfConstraint *data = (con) ? (bChildOfConstraint *)con->data : NULL;
+ const int owner = RNA_enum_get(op->ptr, "owner");
- /* despite 3 layers of checks, we may still not be able to find a constraint */
- if (data == NULL) {
- printf("DEBUG: Child-Of Set Inverse - object = '%s'\n", (ob) ? ob->id.name + 2 : "<None>");
- BKE_report(op->reports, RPT_ERROR, "Could not find constraint data for Child-Of Set Inverse");
- return OPERATOR_CANCELLED;
- }
+ /* despite 3 layers of checks, we may still not be able to find a constraint */
+ if (data == NULL) {
+ printf("DEBUG: Child-Of Set Inverse - object = '%s'\n", (ob) ? ob->id.name + 2 : "<None>");
+ BKE_report(op->reports, RPT_ERROR, "Could not find constraint data for Child-Of Set Inverse");
+ return OPERATOR_CANCELLED;
+ }
- child_get_inverse_matrix(C, scene, ob, con, data->invmat, owner);
+ child_get_inverse_matrix(C, scene, ob, con, data->invmat, owner);
- ED_object_constraint_update(bmain, ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
+ ED_object_constraint_update(bmain, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int childof_set_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op))
- return childof_set_inverse_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_constraint_invoke_properties(C, op))
+ return childof_set_inverse_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void CONSTRAINT_OT_childof_set_inverse(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Inverse";
- ot->idname = "CONSTRAINT_OT_childof_set_inverse";
- ot->description = "Set inverse correction for ChildOf constraint";
+ /* identifiers */
+ ot->name = "Set Inverse";
+ ot->idname = "CONSTRAINT_OT_childof_set_inverse";
+ ot->description = "Set inverse correction for ChildOf constraint";
- /* callbacks */
- ot->invoke = childof_set_inverse_invoke;
- ot->exec = childof_set_inverse_exec;
- ot->poll = edit_constraint_poll;
+ /* callbacks */
+ ot->invoke = childof_set_inverse_invoke;
+ ot->exec = childof_set_inverse_exec;
+ ot->poll = edit_constraint_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- edit_constraint_properties(ot);
+ /* properties */
+ edit_constraint_properties(ot);
}
/* ChildOf Constraint - clear inverse callback */
static int childof_clear_inverse_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_active_context(C);
- bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF);
- bChildOfConstraint *data = (con) ? (bChildOfConstraint *)con->data : NULL;
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_active_context(C);
+ bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF);
+ bChildOfConstraint *data = (con) ? (bChildOfConstraint *)con->data : NULL;
- if (data == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Child Of constraint not found");
- return OPERATOR_CANCELLED;
- }
+ if (data == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Child Of constraint not found");
+ return OPERATOR_CANCELLED;
+ }
- /* simply clear the matrix */
- unit_m4(data->invmat);
+ /* simply clear the matrix */
+ unit_m4(data->invmat);
- ED_object_constraint_update(bmain, ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
+ ED_object_constraint_update(bmain, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int childof_clear_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op))
- return childof_clear_inverse_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_constraint_invoke_properties(C, op))
+ return childof_clear_inverse_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void CONSTRAINT_OT_childof_clear_inverse(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Inverse";
- ot->idname = "CONSTRAINT_OT_childof_clear_inverse";
- ot->description = "Clear inverse correction for ChildOf constraint";
+ /* identifiers */
+ ot->name = "Clear Inverse";
+ ot->idname = "CONSTRAINT_OT_childof_clear_inverse";
+ ot->description = "Clear inverse correction for ChildOf constraint";
- /* callbacks */
- ot->invoke = childof_clear_inverse_invoke;
- ot->exec = childof_clear_inverse_exec;
- ot->poll = edit_constraint_poll;
+ /* callbacks */
+ ot->invoke = childof_clear_inverse_invoke;
+ ot->exec = childof_clear_inverse_exec;
+ ot->poll = edit_constraint_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- edit_constraint_properties(ot);
+ /* properties */
+ edit_constraint_properties(ot);
}
/* --------------- Follow Path Constraint ------------------ */
static int followpath_path_animate_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_active_context(C);
- bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_FOLLOWPATH);
- bFollowPathConstraint *data = (con) ? (bFollowPathConstraint *)con->data : NULL;
-
- bAction *act = NULL;
- FCurve *fcu = NULL;
- int sfra = RNA_int_get(op->ptr, "frame_start");
- int len = RNA_int_get(op->ptr, "length");
- float standardRange = 1.0;
-
- /* nearly impossible sanity check */
- if (data == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Follow Path constraint not found");
- return OPERATOR_CANCELLED;
- }
-
- /* add F-Curve as appropriate */
- if (data->tar) {
- Curve *cu = (Curve *)data->tar->data;
-
- if (ELEM(NULL, cu->adt, cu->adt->action) ||
- (list_find_fcurve(&cu->adt->action->curves, "eval_time", 0) == NULL))
- {
- /* create F-Curve for path animation */
- act = verify_adt_action(bmain, &cu->id, 1);
- fcu = verify_fcurve(bmain, act, NULL, NULL, "eval_time", 0, 1);
-
- /* standard vertical range - 1:1 = 100 frames */
- standardRange = 100.0f;
- }
- else {
- /* path anim exists already - abort for now as this may well be what was intended */
- BKE_report(op->reports, RPT_WARNING, "Path is already animated");
- return OPERATOR_CANCELLED;
- }
- }
- else {
- /* animate constraint's "fixed offset" */
- PointerRNA ptr;
- PropertyRNA *prop;
- char *path;
-
- /* get RNA pointer to constraint's "offset_factor" property - to build RNA path */
- RNA_pointer_create(&ob->id, &RNA_FollowPathConstraint, con, &ptr);
- prop = RNA_struct_find_property(&ptr, "offset_factor");
-
- path = RNA_path_from_ID_to_property(&ptr, prop);
-
- /* create F-Curve for constraint */
- act = verify_adt_action(bmain, &ob->id, 1);
- fcu = verify_fcurve(bmain, act, NULL, NULL, path, 0, 1);
-
- /* standard vertical range - 0.0 to 1.0 */
- standardRange = 1.0f;
-
- /* enable "Use Fixed Position" so that animating this has effect */
- data->followflag |= FOLLOWPATH_STATIC;
-
- /* path needs to be freed */
- if (path)
- MEM_freeN(path);
- }
-
- /* setup dummy 'generator' modifier here to get 1-1 correspondence still working
- * and define basic slope of this curve based on the properties
- */
- if (!fcu->bezt && !fcu->fpt && !fcu->modifiers.first) {
- FModifier *fcm = add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR, fcu);
- FMod_Generator *gen = fcm->data;
-
- /* Assume that we have the following equation:
- * y = Ax + B
- * 1 0 <-- coefficients array indices
- */
- float A = standardRange / (float)(len);
- float B = (float)(-sfra) * A;
-
- gen->coefficients[1] = A;
- gen->coefficients[0] = B;
- }
-
- /* updates... */
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
- return OPERATOR_FINISHED;
-}
-
-static int followpath_path_animate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- /* hook up invoke properties for figuring out which constraint we're dealing with */
- if (edit_constraint_invoke_properties(C, op)) {
- return followpath_path_animate_exec(C, op);
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_active_context(C);
+ bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_FOLLOWPATH);
+ bFollowPathConstraint *data = (con) ? (bFollowPathConstraint *)con->data : NULL;
+
+ bAction *act = NULL;
+ FCurve *fcu = NULL;
+ int sfra = RNA_int_get(op->ptr, "frame_start");
+ int len = RNA_int_get(op->ptr, "length");
+ float standardRange = 1.0;
+
+ /* nearly impossible sanity check */
+ if (data == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Follow Path constraint not found");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* add F-Curve as appropriate */
+ if (data->tar) {
+ Curve *cu = (Curve *)data->tar->data;
+
+ if (ELEM(NULL, cu->adt, cu->adt->action) ||
+ (list_find_fcurve(&cu->adt->action->curves, "eval_time", 0) == NULL)) {
+ /* create F-Curve for path animation */
+ act = verify_adt_action(bmain, &cu->id, 1);
+ fcu = verify_fcurve(bmain, act, NULL, NULL, "eval_time", 0, 1);
+
+ /* standard vertical range - 1:1 = 100 frames */
+ standardRange = 100.0f;
+ }
+ else {
+ /* path anim exists already - abort for now as this may well be what was intended */
+ BKE_report(op->reports, RPT_WARNING, "Path is already animated");
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ /* animate constraint's "fixed offset" */
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ char *path;
+
+ /* get RNA pointer to constraint's "offset_factor" property - to build RNA path */
+ RNA_pointer_create(&ob->id, &RNA_FollowPathConstraint, con, &ptr);
+ prop = RNA_struct_find_property(&ptr, "offset_factor");
+
+ path = RNA_path_from_ID_to_property(&ptr, prop);
+
+ /* create F-Curve for constraint */
+ act = verify_adt_action(bmain, &ob->id, 1);
+ fcu = verify_fcurve(bmain, act, NULL, NULL, path, 0, 1);
+
+ /* standard vertical range - 0.0 to 1.0 */
+ standardRange = 1.0f;
+
+ /* enable "Use Fixed Position" so that animating this has effect */
+ data->followflag |= FOLLOWPATH_STATIC;
+
+ /* path needs to be freed */
+ if (path)
+ MEM_freeN(path);
+ }
+
+ /* setup dummy 'generator' modifier here to get 1-1 correspondence still working
+ * and define basic slope of this curve based on the properties
+ */
+ if (!fcu->bezt && !fcu->fpt && !fcu->modifiers.first) {
+ FModifier *fcm = add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR, fcu);
+ FMod_Generator *gen = fcm->data;
+
+ /* Assume that we have the following equation:
+ * y = Ax + B
+ * 1 0 <-- coefficients array indices
+ */
+ float A = standardRange / (float)(len);
+ float B = (float)(-sfra) * A;
+
+ gen->coefficients[1] = A;
+ gen->coefficients[0] = B;
+ }
+
+ /* updates... */
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
+ return OPERATOR_FINISHED;
+}
+
+static int followpath_path_animate_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
+{
+ /* hook up invoke properties for figuring out which constraint we're dealing with */
+ if (edit_constraint_invoke_properties(C, op)) {
+ return followpath_path_animate_exec(C, op);
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void CONSTRAINT_OT_followpath_path_animate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Auto Animate Path";
- ot->idname = "CONSTRAINT_OT_followpath_path_animate";
- ot->description = "Add default animation for path used by constraint if it isn't animated already";
-
- /* callbacks */
- ot->invoke = followpath_path_animate_invoke;
- ot->exec = followpath_path_animate_exec;
- ot->poll = edit_constraint_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- edit_constraint_properties(ot);
- RNA_def_int(ot->srna, "frame_start", 1, MINAFRAME, MAXFRAME, "Start Frame",
- "First frame of path animation", MINAFRAME, MAXFRAME);
- RNA_def_int(ot->srna, "length", 100, 0, MAXFRAME, "Length",
- "Number of frames that path animation should take", 0, MAXFRAME);
+ /* identifiers */
+ ot->name = "Auto Animate Path";
+ ot->idname = "CONSTRAINT_OT_followpath_path_animate";
+ ot->description =
+ "Add default animation for path used by constraint if it isn't animated already";
+
+ /* callbacks */
+ ot->invoke = followpath_path_animate_invoke;
+ ot->exec = followpath_path_animate_exec;
+ ot->poll = edit_constraint_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ edit_constraint_properties(ot);
+ RNA_def_int(ot->srna,
+ "frame_start",
+ 1,
+ MINAFRAME,
+ MAXFRAME,
+ "Start Frame",
+ "First frame of path animation",
+ MINAFRAME,
+ MAXFRAME);
+ RNA_def_int(ot->srna,
+ "length",
+ 100,
+ 0,
+ MAXFRAME,
+ "Length",
+ "Number of frames that path animation should take",
+ 0,
+ MAXFRAME);
}
/* ------------- Object Solver Constraint ------------------ */
static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
- bObjectSolverConstraint *data = (con) ? (bObjectSolverConstraint *)con->data : NULL;
- const int owner = RNA_enum_get(op->ptr, "owner");
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
+ bObjectSolverConstraint *data = (con) ? (bObjectSolverConstraint *)con->data : NULL;
+ const int owner = RNA_enum_get(op->ptr, "owner");
- /* despite 3 layers of checks, we may still not be able to find a constraint */
- if (data == NULL) {
- printf("DEBUG: Child-Of Set Inverse - object = '%s'\n", (ob) ? ob->id.name + 2 : "<None>");
- BKE_report(op->reports, RPT_ERROR, "Could not find constraint data for Child-Of Set Inverse");
- return OPERATOR_CANCELLED;
- }
+ /* despite 3 layers of checks, we may still not be able to find a constraint */
+ if (data == NULL) {
+ printf("DEBUG: Child-Of Set Inverse - object = '%s'\n", (ob) ? ob->id.name + 2 : "<None>");
+ BKE_report(op->reports, RPT_ERROR, "Could not find constraint data for Child-Of Set Inverse");
+ return OPERATOR_CANCELLED;
+ }
- child_get_inverse_matrix(C, scene, ob, con, data->invmat, owner);
+ child_get_inverse_matrix(C, scene, ob, con, data->invmat, owner);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static int objectsolver_set_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int objectsolver_set_inverse_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op))
- return objectsolver_set_inverse_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_constraint_invoke_properties(C, op))
+ return objectsolver_set_inverse_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void CONSTRAINT_OT_objectsolver_set_inverse(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Set Inverse";
- ot->idname = "CONSTRAINT_OT_objectsolver_set_inverse";
- ot->description = "Set inverse correction for ObjectSolver constraint";
+ /* identifiers */
+ ot->name = "Set Inverse";
+ ot->idname = "CONSTRAINT_OT_objectsolver_set_inverse";
+ ot->description = "Set inverse correction for ObjectSolver constraint";
- /* callbacks */
- ot->invoke = objectsolver_set_inverse_invoke;
- ot->exec = objectsolver_set_inverse_exec;
- ot->poll = edit_constraint_poll;
+ /* callbacks */
+ ot->invoke = objectsolver_set_inverse_invoke;
+ ot->exec = objectsolver_set_inverse_exec;
+ ot->poll = edit_constraint_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- edit_constraint_properties(ot);
+ /* properties */
+ edit_constraint_properties(ot);
}
static int objectsolver_clear_inverse_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
- bObjectSolverConstraint *data = (con) ? (bObjectSolverConstraint *)con->data : NULL;
+ Object *ob = ED_object_active_context(C);
+ bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
+ bObjectSolverConstraint *data = (con) ? (bObjectSolverConstraint *)con->data : NULL;
- if (data == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Child Of constraint not found");
- return OPERATOR_CANCELLED;
- }
+ if (data == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Child Of constraint not found");
+ return OPERATOR_CANCELLED;
+ }
- /* simply clear the matrix */
- unit_m4(data->invmat);
+ /* simply clear the matrix */
+ unit_m4(data->invmat);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static int objectsolver_clear_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int objectsolver_clear_inverse_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op))
- return objectsolver_clear_inverse_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_constraint_invoke_properties(C, op))
+ return objectsolver_clear_inverse_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void CONSTRAINT_OT_objectsolver_clear_inverse(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Inverse";
- ot->idname = "CONSTRAINT_OT_objectsolver_clear_inverse";
- ot->description = "Clear inverse correction for ObjectSolver constraint";
+ /* identifiers */
+ ot->name = "Clear Inverse";
+ ot->idname = "CONSTRAINT_OT_objectsolver_clear_inverse";
+ ot->description = "Clear inverse correction for ObjectSolver constraint";
- /* callbacks */
- ot->invoke = objectsolver_clear_inverse_invoke;
- ot->exec = objectsolver_clear_inverse_exec;
- ot->poll = edit_constraint_poll;
+ /* callbacks */
+ ot->invoke = objectsolver_clear_inverse_invoke;
+ ot->exec = objectsolver_clear_inverse_exec;
+ ot->poll = edit_constraint_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- edit_constraint_properties(ot);
+ /* properties */
+ edit_constraint_properties(ot);
}
/***************************** BUTTONS ****************************/
void ED_object_constraint_set_active(Object *ob, bConstraint *con)
{
- ListBase *lb = get_constraint_lb(ob, con, NULL);
+ ListBase *lb = get_constraint_lb(ob, con, NULL);
- /* lets be nice and escape if its active already */
- /* NOTE: this assumes that the stack doesn't have other active ones set... */
- if ((lb && con) && (con->flag & CONSTRAINT_ACTIVE))
- return;
+ /* lets be nice and escape if its active already */
+ /* NOTE: this assumes that the stack doesn't have other active ones set... */
+ if ((lb && con) && (con->flag & CONSTRAINT_ACTIVE))
+ return;
- BKE_constraints_active_set(lb, con);
+ BKE_constraints_active_set(lb, con);
}
void ED_object_constraint_update(Main *bmain, Object *ob)
{
- if (ob->pose) BKE_pose_update_constraint_flags(ob->pose);
+ if (ob->pose)
+ BKE_pose_update_constraint_flags(ob->pose);
- object_test_constraints(bmain, ob);
+ object_test_constraints(bmain, ob);
- if (ob->type == OB_ARMATURE)
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_TRANSFORM);
- else
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ if (ob->type == OB_ARMATURE)
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_TRANSFORM);
+ else
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
}
static void object_pose_tag_update(Main *bmain, Object *ob)
{
- BKE_pose_tag_recalc(bmain, ob->pose); /* Checks & sort pose channels. */
- if (ob->proxy && ob->adt) {
- /* We need to make use of ugly POSE_ANIMATION_WORKAROUND here too, else anim data are not reloaded
- * after calling `BKE_pose_rebuild()`, which causes T43872.
- * Note that this is a bit wide here, since we cannot be sure whether there are some locked proxy bones
- * or not...
- * XXX Temp hack until new depsgraph hopefully solves this. */
- DEG_id_tag_update(&ob->id, ID_RECALC_ANIMATION);
- }
+ BKE_pose_tag_recalc(bmain, ob->pose); /* Checks & sort pose channels. */
+ if (ob->proxy && ob->adt) {
+ /* We need to make use of ugly POSE_ANIMATION_WORKAROUND here too, else anim data are not reloaded
+ * after calling `BKE_pose_rebuild()`, which causes T43872.
+ * Note that this is a bit wide here, since we cannot be sure whether there are some locked proxy bones
+ * or not...
+ * XXX Temp hack until new depsgraph hopefully solves this. */
+ DEG_id_tag_update(&ob->id, ID_RECALC_ANIMATION);
+ }
}
void ED_object_constraint_dependency_update(Main *bmain, Object *ob)
{
- ED_object_constraint_update(bmain, ob);
+ ED_object_constraint_update(bmain, ob);
- if (ob->pose) {
- object_pose_tag_update(bmain, ob);
- }
- DEG_relations_tag_update(bmain);
+ if (ob->pose) {
+ object_pose_tag_update(bmain, ob);
+ }
+ DEG_relations_tag_update(bmain);
}
void ED_object_constraint_tag_update(Main *bmain, Object *ob, bConstraint *con)
{
- if (ob->pose) {
- BKE_pose_tag_update_constraint_flags(ob->pose);
- }
+ if (ob->pose) {
+ BKE_pose_tag_update_constraint_flags(ob->pose);
+ }
- if (con) {
- object_test_constraint(bmain, ob, con);
- }
+ if (con) {
+ object_test_constraint(bmain, ob, con);
+ }
- if (ob->type == OB_ARMATURE)
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_TRANSFORM);
- else
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ if (ob->type == OB_ARMATURE)
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_TRANSFORM);
+ else
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- /* Do Copy-on-Write tag here too, otherwise constraint
- * influence/mute buttons in UI have no effect
- */
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+ /* Do Copy-on-Write tag here too, otherwise constraint
+ * influence/mute buttons in UI have no effect
+ */
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
}
void ED_object_constraint_dependency_tag_update(Main *bmain, Object *ob, bConstraint *con)
{
- ED_object_constraint_tag_update(bmain, ob, con);
+ ED_object_constraint_tag_update(bmain, ob, con);
- if (ob->pose) {
- object_pose_tag_update(bmain, ob);
- }
- DEG_relations_tag_update(bmain);
+ if (ob->pose) {
+ object_pose_tag_update(bmain, ob);
+ }
+ DEG_relations_tag_update(bmain);
}
static bool constraint_poll(bContext *C)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
- return (ptr.id.data && ptr.data);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
+ return (ptr.id.data && ptr.data);
}
-
static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
- Object *ob = ptr.id.data;
- bConstraint *con = ptr.data;
- ListBase *lb = get_constraint_lb(ob, con, NULL);
+ Main *bmain = CTX_data_main(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
+ Object *ob = ptr.id.data;
+ bConstraint *con = ptr.data;
+ ListBase *lb = get_constraint_lb(ob, con, NULL);
- /* free the constraint */
- if (BKE_constraint_remove_ex(lb, ob, con, true)) {
- /* there's no active constraint now, so make sure this is the case */
- BKE_constraints_active_set(&ob->constraints, NULL);
- /* needed to set the flags on posebones correctly */
- ED_object_constraint_update(bmain, ob);
+ /* free the constraint */
+ if (BKE_constraint_remove_ex(lb, ob, con, true)) {
+ /* there's no active constraint now, so make sure this is the case */
+ BKE_constraints_active_set(&ob->constraints, NULL);
+ /* needed to set the flags on posebones correctly */
+ ED_object_constraint_update(bmain, ob);
- /* relations */
- DEG_relations_tag_update(CTX_data_main(C));
+ /* relations */
+ DEG_relations_tag_update(CTX_data_main(C));
- /* notifiers */
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
+ /* notifiers */
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
- return OPERATOR_FINISHED;
- }
- else {
- /* couldn't remove due to some invalid data */
- return OPERATOR_CANCELLED;
- }
+ return OPERATOR_FINISHED;
+ }
+ else {
+ /* couldn't remove due to some invalid data */
+ return OPERATOR_CANCELLED;
+ }
}
void CONSTRAINT_OT_delete(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Delete Constraint";
- ot->idname = "CONSTRAINT_OT_delete";
- ot->description = "Remove constraint from constraint stack";
+ /* identifiers */
+ ot->name = "Delete Constraint";
+ ot->idname = "CONSTRAINT_OT_delete";
+ ot->description = "Remove constraint from constraint stack";
- /* callbacks */
- ot->exec = constraint_delete_exec;
- ot->poll = constraint_poll;
+ /* callbacks */
+ ot->exec = constraint_delete_exec;
+ ot->poll = constraint_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
static int constraint_move_down_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- bConstraint *con = edit_constraint_property_get(op, ob, 0);
+ Object *ob = ED_object_active_context(C);
+ bConstraint *con = edit_constraint_property_get(op, ob, 0);
- if (con && con->next) {
- ListBase *conlist = get_constraint_lb(ob, con, NULL);
- bConstraint *nextCon = con->next;
+ if (con && con->next) {
+ ListBase *conlist = get_constraint_lb(ob, con, NULL);
+ bConstraint *nextCon = con->next;
- /* insert the nominated constraint after the one that used to be after it */
- BLI_remlink(conlist, con);
- BLI_insertlinkafter(conlist, nextCon, con);
+ /* insert the nominated constraint after the one that used to be after it */
+ BLI_remlink(conlist, con);
+ BLI_insertlinkafter(conlist, nextCon, con);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
- return OPERATOR_FINISHED;
- }
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
static int constraint_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op))
- return constraint_move_down_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_constraint_invoke_properties(C, op))
+ return constraint_move_down_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void CONSTRAINT_OT_move_down(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Move Constraint Down";
- ot->idname = "CONSTRAINT_OT_move_down";
- ot->description = "Move constraint down in constraint stack";
+ /* identifiers */
+ ot->name = "Move Constraint Down";
+ ot->idname = "CONSTRAINT_OT_move_down";
+ ot->description = "Move constraint down in constraint stack";
- /* callbacks */
- ot->invoke = constraint_move_down_invoke;
- ot->exec = constraint_move_down_exec;
- ot->poll = edit_constraint_poll;
+ /* callbacks */
+ ot->invoke = constraint_move_down_invoke;
+ ot->exec = constraint_move_down_exec;
+ ot->poll = edit_constraint_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- edit_constraint_properties(ot);
+ /* properties */
+ edit_constraint_properties(ot);
}
-
static int constraint_move_up_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- bConstraint *con = edit_constraint_property_get(op, ob, 0);
+ Object *ob = ED_object_active_context(C);
+ bConstraint *con = edit_constraint_property_get(op, ob, 0);
- if (con && con->prev) {
- ListBase *conlist = get_constraint_lb(ob, con, NULL);
- bConstraint *prevCon = con->prev;
+ if (con && con->prev) {
+ ListBase *conlist = get_constraint_lb(ob, con, NULL);
+ bConstraint *prevCon = con->prev;
- /* insert the nominated constraint before the one that used to be before it */
- BLI_remlink(conlist, con);
- BLI_insertlinkbefore(conlist, prevCon, con);
+ /* insert the nominated constraint before the one that used to be before it */
+ BLI_remlink(conlist, con);
+ BLI_insertlinkbefore(conlist, prevCon, con);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
- return OPERATOR_FINISHED;
- }
+ return OPERATOR_FINISHED;
+ }
- return OPERATOR_CANCELLED;
+ return OPERATOR_CANCELLED;
}
static int constraint_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op))
- return constraint_move_up_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_constraint_invoke_properties(C, op))
+ return constraint_move_up_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void CONSTRAINT_OT_move_up(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Move Constraint Up";
- ot->idname = "CONSTRAINT_OT_move_up";
- ot->description = "Move constraint up in constraint stack";
+ /* identifiers */
+ ot->name = "Move Constraint Up";
+ ot->idname = "CONSTRAINT_OT_move_up";
+ ot->description = "Move constraint up in constraint stack";
- /* callbacks */
- ot->exec = constraint_move_up_exec;
- ot->invoke = constraint_move_up_invoke;
- ot->poll = edit_constraint_poll;
+ /* callbacks */
+ ot->exec = constraint_move_up_exec;
+ ot->invoke = constraint_move_up_invoke;
+ ot->poll = edit_constraint_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- edit_constraint_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ edit_constraint_properties(ot);
}
/***************************** OPERATORS ****************************/
@@ -1437,433 +1475,428 @@ void CONSTRAINT_OT_move_up(wmOperatorType *ot)
static int pose_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Object *prev_ob = NULL;
+ Main *bmain = CTX_data_main(C);
+ Object *prev_ob = NULL;
- /* free constraints for all selected bones */
- CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, selected_pose_bones, Object *, ob)
- {
- BKE_constraints_free(&pchan->constraints);
- pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_SPLINEIK | PCHAN_HAS_CONST);
+ /* free constraints for all selected bones */
+ CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, pchan, selected_pose_bones, Object *, ob)
+ {
+ BKE_constraints_free(&pchan->constraints);
+ pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_SPLINEIK | PCHAN_HAS_CONST);
- if (prev_ob != ob) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
- prev_ob = ob;
- }
- }
- CTX_DATA_END;
+ if (prev_ob != ob) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
+ prev_ob = ob;
+ }
+ }
+ CTX_DATA_END;
- /* force depsgraph to get recalculated since relationships removed */
- DEG_relations_tag_update(bmain);
+ /* force depsgraph to get recalculated since relationships removed */
+ DEG_relations_tag_update(bmain);
- /* note, calling BIK_clear_data() isn't needed here */
+ /* note, calling BIK_clear_data() isn't needed here */
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void POSE_OT_constraints_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Pose Constraints";
- ot->idname = "POSE_OT_constraints_clear";
- ot->description = "Clear all the constraints for the selected bones";
+ /* identifiers */
+ ot->name = "Clear Pose Constraints";
+ ot->idname = "POSE_OT_constraints_clear";
+ ot->description = "Clear all the constraints for the selected bones";
- /* callbacks */
- ot->exec = pose_constraints_clear_exec;
- ot->poll = ED_operator_posemode_exclusive; // XXX - do we want to ensure there are selected bones too?
+ /* callbacks */
+ ot->exec = pose_constraints_clear_exec;
+ ot->poll =
+ ED_operator_posemode_exclusive; // XXX - do we want to ensure there are selected bones too?
}
-
static int object_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
+ Main *bmain = CTX_data_main(C);
- /* do freeing */
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- BKE_constraints_free(&ob->constraints);
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- }
- CTX_DATA_END;
+ /* do freeing */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ BKE_constraints_free(&ob->constraints);
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ }
+ CTX_DATA_END;
- /* force depsgraph to get recalculated since relationships removed */
- DEG_relations_tag_update(bmain);
+ /* force depsgraph to get recalculated since relationships removed */
+ DEG_relations_tag_update(bmain);
- /* do updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, NULL);
+ /* do updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_constraints_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Object Constraints";
- ot->idname = "OBJECT_OT_constraints_clear";
- ot->description = "Clear all the constraints for the active Object only";
+ /* identifiers */
+ ot->name = "Clear Object Constraints";
+ ot->idname = "OBJECT_OT_constraints_clear";
+ ot->description = "Clear all the constraints for the active Object only";
- /* callbacks */
- ot->exec = object_constraints_clear_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* callbacks */
+ ot->exec = object_constraints_clear_exec;
+ ot->poll = ED_operator_object_active_editable;
}
/************************ copy all constraints operators *********************/
static int pose_constraint_copy_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- bPoseChannel *pchan = CTX_data_active_pose_bone(C);
+ Main *bmain = CTX_data_main(C);
+ bPoseChannel *pchan = CTX_data_active_pose_bone(C);
- /* don't do anything if bone doesn't exist or doesn't have any constraints */
- if (ELEM(NULL, pchan, pchan->constraints.first)) {
- BKE_report(op->reports, RPT_ERROR, "No active bone with constraints for copying");
- return OPERATOR_CANCELLED;
- }
+ /* don't do anything if bone doesn't exist or doesn't have any constraints */
+ if (ELEM(NULL, pchan, pchan->constraints.first)) {
+ BKE_report(op->reports, RPT_ERROR, "No active bone with constraints for copying");
+ return OPERATOR_CANCELLED;
+ }
- Object *prev_ob = NULL;
+ Object *prev_ob = NULL;
- /* copy all constraints from active posebone to all selected posebones */
- CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, chan, selected_pose_bones, Object *, ob)
- {
- /* if we're not handling the object we're copying from, copy all constraints over */
- if (pchan != chan) {
- BKE_constraints_copy(&chan->constraints, &pchan->constraints, true);
- /* update flags (need to add here, not just copy) */
- chan->constflag |= pchan->constflag;
+ /* copy all constraints from active posebone to all selected posebones */
+ CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, chan, selected_pose_bones, Object *, ob)
+ {
+ /* if we're not handling the object we're copying from, copy all constraints over */
+ if (pchan != chan) {
+ BKE_constraints_copy(&chan->constraints, &pchan->constraints, true);
+ /* update flags (need to add here, not just copy) */
+ chan->constflag |= pchan->constflag;
- if (prev_ob != ob) {
- BKE_pose_tag_recalc(bmain, ob->pose);
- DEG_id_tag_update((ID *)ob, ID_RECALC_GEOMETRY);
- prev_ob = ob;
- }
- }
- }
- CTX_DATA_END;
+ if (prev_ob != ob) {
+ BKE_pose_tag_recalc(bmain, ob->pose);
+ DEG_id_tag_update((ID *)ob, ID_RECALC_GEOMETRY);
+ prev_ob = ob;
+ }
+ }
+ }
+ CTX_DATA_END;
- /* force depsgraph to get recalculated since new relationships added */
- DEG_relations_tag_update(bmain);
+ /* force depsgraph to get recalculated since new relationships added */
+ DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void POSE_OT_constraints_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Constraints to Selected Bones";
- ot->idname = "POSE_OT_constraints_copy";
- ot->description = "Copy constraints to other selected bones";
+ /* identifiers */
+ ot->name = "Copy Constraints to Selected Bones";
+ ot->idname = "POSE_OT_constraints_copy";
+ ot->description = "Copy constraints to other selected bones";
- /* api callbacks */
- ot->exec = pose_constraint_copy_exec;
- ot->poll = ED_operator_posemode_exclusive;
+ /* api callbacks */
+ ot->exec = pose_constraint_copy_exec;
+ ot->poll = ED_operator_posemode_exclusive;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int object_constraint_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
- Object *obact = ED_object_active_context(C);
+ Main *bmain = CTX_data_main(C);
+ Object *obact = ED_object_active_context(C);
- /* copy all constraints from active object to all selected objects */
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- /* if we're not handling the object we're copying from, copy all constraints over */
- if (obact != ob) {
- BKE_constraints_copy(&ob->constraints, &obact->constraints, true);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_TRANSFORM);
- }
- }
- CTX_DATA_END;
+ /* copy all constraints from active object to all selected objects */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ /* if we're not handling the object we're copying from, copy all constraints over */
+ if (obact != ob) {
+ BKE_constraints_copy(&ob->constraints, &obact->constraints, true);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_TRANSFORM);
+ }
+ }
+ CTX_DATA_END;
- /* force depsgraph to get recalculated since new relationships added */
- DEG_relations_tag_update(bmain);
+ /* force depsgraph to get recalculated since new relationships added */
+ DEG_relations_tag_update(bmain);
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_ADDED, NULL);
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_ADDED, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_constraints_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Constraints to Selected Objects";
- ot->idname = "OBJECT_OT_constraints_copy";
- ot->description = "Copy constraints to other selected objects";
+ /* identifiers */
+ ot->name = "Copy Constraints to Selected Objects";
+ ot->idname = "OBJECT_OT_constraints_copy";
+ ot->description = "Copy constraints to other selected objects";
- /* api callbacks */
- ot->exec = object_constraint_copy_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* api callbacks */
+ ot->exec = object_constraint_copy_exec;
+ ot->poll = ED_operator_object_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/************************ add constraint operators *********************/
/* get the Object and/or PoseChannel to use as target */
-static bool get_new_constraint_target(bContext *C, int con_type, Object **tar_ob, bPoseChannel **tar_pchan, bool add)
-{
- Object *obact = ED_object_active_context(C);
- bPoseChannel *pchanact = BKE_pose_channel_active(obact);
- bool only_curve = false, only_mesh = false, only_ob = false;
- bool found = false;
-
- /* clear tar_ob and tar_pchan fields before use
- * - assume for now that both always exist...
- */
- *tar_ob = NULL;
- *tar_pchan = NULL;
-
- /* check if constraint type doesn't requires a target
- * - if so, no need to get any targets
- */
- switch (con_type) {
- /* no-target constraints --------------------------- */
- /* null constraint - shouldn't even be added! */
- case CONSTRAINT_TYPE_NULL:
- /* limit constraints - no targets needed */
- case CONSTRAINT_TYPE_LOCLIMIT:
- case CONSTRAINT_TYPE_ROTLIMIT:
- case CONSTRAINT_TYPE_SIZELIMIT:
- case CONSTRAINT_TYPE_SAMEVOL:
- return false;
-
- /* restricted target-type constraints -------------- */
- /* NOTE: for these, we cannot try to add a target object if no valid ones are found,
- * since that doesn't work */
- /* curve-based constraints - set the only_curve and only_ob flags */
- case CONSTRAINT_TYPE_CLAMPTO:
- case CONSTRAINT_TYPE_FOLLOWPATH:
- case CONSTRAINT_TYPE_SPLINEIK:
- only_curve = true;
- only_ob = true;
- add = false;
- break;
-
- /* mesh only? */
- case CONSTRAINT_TYPE_SHRINKWRAP:
- only_mesh = true;
- only_ob = true;
- add = false;
- break;
- }
-
- /* if the active Object is Armature, and we can search for bones, do so... */
- if ((obact->type == OB_ARMATURE) && (only_ob == false)) {
- /* search in list of selected Pose-Channels for target */
- CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones_from_active_object)
- {
- /* just use the first one that we encounter, as long as it is not the active one */
- if (pchan != pchanact) {
- *tar_ob = obact;
- *tar_pchan = pchan;
- found = true;
-
- break;
- }
- }
- CTX_DATA_END;
- }
-
- /* if not yet found, try selected Objects... */
- if (found == false) {
- /* search in selected objects context */
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- /* just use the first object we encounter (that isn't the active object)
- * and which fulfills the criteria for the object-target that we've got
- */
- if (ob != obact) {
- /* for armatures in pose mode, look inside the armature for the active bone
- * so that we set up cross-armature constraints with less effort
- */
- if ((ob->type == OB_ARMATURE) && (ob->mode & OB_MODE_POSE) &&
- (!only_curve && !only_mesh))
- {
- /* just use the active bone, and assume that it is visible + usable */
- *tar_ob = ob;
- *tar_pchan = BKE_pose_channel_active(ob);
- found = true;
-
- break;
- }
- else if (((!only_curve) || (ob->type == OB_CURVE)) &&
- ((!only_mesh) || (ob->type == OB_MESH)))
- {
- /* set target */
- *tar_ob = ob;
- found = true;
-
- /* perform some special operations on the target */
- if (only_curve) {
- /* Curve-Path option must be enabled for follow-path constraints to be able to work */
- Curve *cu = (Curve *)ob->data;
- cu->flag |= CU_PATH;
- }
-
- break;
- }
- }
- }
- CTX_DATA_END;
- }
-
- /* if still not found, add a new empty to act as a target (if allowed) */
- if ((found == false) && (add)) {
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *base = BASACT(view_layer);
- Object *obt;
-
- /* add new target object */
- obt = BKE_object_add(bmain, scene, view_layer, OB_EMPTY, NULL);
-
- /* transform cent to global coords for loc */
- if (pchanact) {
- /* since by default, IK targets the tip of the last bone, use the tip of the active PoseChannel
- * if adding a target for an IK Constraint
- */
- if (con_type == CONSTRAINT_TYPE_KINEMATIC)
- mul_v3_m4v3(obt->loc, obact->obmat, pchanact->pose_tail);
- else
- mul_v3_m4v3(obt->loc, obact->obmat, pchanact->pose_head);
- }
- else {
- copy_v3_v3(obt->loc, obact->obmat[3]);
- }
-
- /* restore, BKE_object_add sets active */
- BASACT(view_layer) = base;
- base->flag |= BASE_SELECTED;
-
- /* make our new target the new object */
- *tar_ob = obt;
- found = true;
- }
-
- /* return whether there's any target */
- return found;
+static bool get_new_constraint_target(
+ bContext *C, int con_type, Object **tar_ob, bPoseChannel **tar_pchan, bool add)
+{
+ Object *obact = ED_object_active_context(C);
+ bPoseChannel *pchanact = BKE_pose_channel_active(obact);
+ bool only_curve = false, only_mesh = false, only_ob = false;
+ bool found = false;
+
+ /* clear tar_ob and tar_pchan fields before use
+ * - assume for now that both always exist...
+ */
+ *tar_ob = NULL;
+ *tar_pchan = NULL;
+
+ /* check if constraint type doesn't requires a target
+ * - if so, no need to get any targets
+ */
+ switch (con_type) {
+ /* no-target constraints --------------------------- */
+ /* null constraint - shouldn't even be added! */
+ case CONSTRAINT_TYPE_NULL:
+ /* limit constraints - no targets needed */
+ case CONSTRAINT_TYPE_LOCLIMIT:
+ case CONSTRAINT_TYPE_ROTLIMIT:
+ case CONSTRAINT_TYPE_SIZELIMIT:
+ case CONSTRAINT_TYPE_SAMEVOL:
+ return false;
+
+ /* restricted target-type constraints -------------- */
+ /* NOTE: for these, we cannot try to add a target object if no valid ones are found,
+ * since that doesn't work */
+ /* curve-based constraints - set the only_curve and only_ob flags */
+ case CONSTRAINT_TYPE_CLAMPTO:
+ case CONSTRAINT_TYPE_FOLLOWPATH:
+ case CONSTRAINT_TYPE_SPLINEIK:
+ only_curve = true;
+ only_ob = true;
+ add = false;
+ break;
+
+ /* mesh only? */
+ case CONSTRAINT_TYPE_SHRINKWRAP:
+ only_mesh = true;
+ only_ob = true;
+ add = false;
+ break;
+ }
+
+ /* if the active Object is Armature, and we can search for bones, do so... */
+ if ((obact->type == OB_ARMATURE) && (only_ob == false)) {
+ /* search in list of selected Pose-Channels for target */
+ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones_from_active_object) {
+ /* just use the first one that we encounter, as long as it is not the active one */
+ if (pchan != pchanact) {
+ *tar_ob = obact;
+ *tar_pchan = pchan;
+ found = true;
+
+ break;
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ /* if not yet found, try selected Objects... */
+ if (found == false) {
+ /* search in selected objects context */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ /* just use the first object we encounter (that isn't the active object)
+ * and which fulfills the criteria for the object-target that we've got
+ */
+ if (ob != obact) {
+ /* for armatures in pose mode, look inside the armature for the active bone
+ * so that we set up cross-armature constraints with less effort
+ */
+ if ((ob->type == OB_ARMATURE) && (ob->mode & OB_MODE_POSE) &&
+ (!only_curve && !only_mesh)) {
+ /* just use the active bone, and assume that it is visible + usable */
+ *tar_ob = ob;
+ *tar_pchan = BKE_pose_channel_active(ob);
+ found = true;
+
+ break;
+ }
+ else if (((!only_curve) || (ob->type == OB_CURVE)) &&
+ ((!only_mesh) || (ob->type == OB_MESH))) {
+ /* set target */
+ *tar_ob = ob;
+ found = true;
+
+ /* perform some special operations on the target */
+ if (only_curve) {
+ /* Curve-Path option must be enabled for follow-path constraints to be able to work */
+ Curve *cu = (Curve *)ob->data;
+ cu->flag |= CU_PATH;
+ }
+
+ break;
+ }
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ /* if still not found, add a new empty to act as a target (if allowed) */
+ if ((found == false) && (add)) {
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base = BASACT(view_layer);
+ Object *obt;
+
+ /* add new target object */
+ obt = BKE_object_add(bmain, scene, view_layer, OB_EMPTY, NULL);
+
+ /* transform cent to global coords for loc */
+ if (pchanact) {
+ /* since by default, IK targets the tip of the last bone, use the tip of the active PoseChannel
+ * if adding a target for an IK Constraint
+ */
+ if (con_type == CONSTRAINT_TYPE_KINEMATIC)
+ mul_v3_m4v3(obt->loc, obact->obmat, pchanact->pose_tail);
+ else
+ mul_v3_m4v3(obt->loc, obact->obmat, pchanact->pose_head);
+ }
+ else {
+ copy_v3_v3(obt->loc, obact->obmat[3]);
+ }
+
+ /* restore, BKE_object_add sets active */
+ BASACT(view_layer) = base;
+ base->flag |= BASE_SELECTED;
+
+ /* make our new target the new object */
+ *tar_ob = obt;
+ found = true;
+ }
+
+ /* return whether there's any target */
+ return found;
}
/* used by add constraint operators to add the constraint required */
-static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase *list, int type, const bool setTarget)
-{
- Main *bmain = CTX_data_main(C);
- bPoseChannel *pchan;
- bConstraint *con;
-
- if (list == &ob->constraints) {
- pchan = NULL;
- }
- else {
- pchan = BKE_pose_channel_active(ob);
-
- /* ensure not to confuse object/pose adding */
- if (pchan == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active pose bone to add a constraint to");
- return OPERATOR_CANCELLED;
- }
- }
- /* check if constraint to be added is valid for the given constraints stack */
- if (type == CONSTRAINT_TYPE_NULL) {
- return OPERATOR_CANCELLED;
- }
- if ((type == CONSTRAINT_TYPE_KINEMATIC) && ((!pchan) || (list != &pchan->constraints))) {
- BKE_report(op->reports, RPT_ERROR, "IK constraint can only be added to bones");
- return OPERATOR_CANCELLED;
- }
- if ((type == CONSTRAINT_TYPE_SPLINEIK) && ((!pchan) || (list != &pchan->constraints))) {
- BKE_report(op->reports, RPT_ERROR, "Spline IK constraint can only be added to bones");
- return OPERATOR_CANCELLED;
- }
-
- /* create a new constraint of the type required, and add it to the active/given constraints list */
- if (pchan)
- con = BKE_constraint_add_for_pose(ob, pchan, NULL, type);
- else
- con = BKE_constraint_add_for_object(ob, NULL, type);
-
- /* get the first selected object/bone, and make that the target
- * - apart from the buttons-window add buttons, we shouldn't add in this way
- */
- if (setTarget) {
- Object *tar_ob = NULL;
- bPoseChannel *tar_pchan = NULL;
-
- /* get the target objects, adding them as need be */
- if (get_new_constraint_target(C, type, &tar_ob, &tar_pchan, 1)) {
- /* method of setting target depends on the type of target we've got
- * - by default, just set the first target (distinction here is only for multiple-targeted constraints)
- */
- if (tar_pchan)
- set_constraint_nth_target(con, tar_ob, tar_pchan->name, 0);
- else
- set_constraint_nth_target(con, tar_ob, "", 0);
- }
- }
-
- /* do type-specific tweaking to the constraint settings */
- switch (type) {
- case CONSTRAINT_TYPE_PYTHON: /* FIXME: this code is not really valid anymore */
- {
+static int constraint_add_exec(
+ bContext *C, wmOperator *op, Object *ob, ListBase *list, int type, const bool setTarget)
+{
+ Main *bmain = CTX_data_main(C);
+ bPoseChannel *pchan;
+ bConstraint *con;
+
+ if (list == &ob->constraints) {
+ pchan = NULL;
+ }
+ else {
+ pchan = BKE_pose_channel_active(ob);
+
+ /* ensure not to confuse object/pose adding */
+ if (pchan == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active pose bone to add a constraint to");
+ return OPERATOR_CANCELLED;
+ }
+ }
+ /* check if constraint to be added is valid for the given constraints stack */
+ if (type == CONSTRAINT_TYPE_NULL) {
+ return OPERATOR_CANCELLED;
+ }
+ if ((type == CONSTRAINT_TYPE_KINEMATIC) && ((!pchan) || (list != &pchan->constraints))) {
+ BKE_report(op->reports, RPT_ERROR, "IK constraint can only be added to bones");
+ return OPERATOR_CANCELLED;
+ }
+ if ((type == CONSTRAINT_TYPE_SPLINEIK) && ((!pchan) || (list != &pchan->constraints))) {
+ BKE_report(op->reports, RPT_ERROR, "Spline IK constraint can only be added to bones");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* create a new constraint of the type required, and add it to the active/given constraints list */
+ if (pchan)
+ con = BKE_constraint_add_for_pose(ob, pchan, NULL, type);
+ else
+ con = BKE_constraint_add_for_object(ob, NULL, type);
+
+ /* get the first selected object/bone, and make that the target
+ * - apart from the buttons-window add buttons, we shouldn't add in this way
+ */
+ if (setTarget) {
+ Object *tar_ob = NULL;
+ bPoseChannel *tar_pchan = NULL;
+
+ /* get the target objects, adding them as need be */
+ if (get_new_constraint_target(C, type, &tar_ob, &tar_pchan, 1)) {
+ /* method of setting target depends on the type of target we've got
+ * - by default, just set the first target (distinction here is only for multiple-targeted constraints)
+ */
+ if (tar_pchan)
+ set_constraint_nth_target(con, tar_ob, tar_pchan->name, 0);
+ else
+ set_constraint_nth_target(con, tar_ob, "", 0);
+ }
+ }
+
+ /* do type-specific tweaking to the constraint settings */
+ switch (type) {
+ case CONSTRAINT_TYPE_PYTHON: /* FIXME: this code is not really valid anymore */
+ {
#ifdef WITH_PYTHON
- char *menustr;
- int scriptint = 0;
- /* popup a list of usable scripts */
- menustr = buildmenu_pyconstraints(bmain, NULL, &scriptint);
- /* XXX scriptint = pupmenu(menustr); */
- MEM_freeN(menustr);
-
- /* only add constraint if a script was chosen */
- if (scriptint) {
- /* add constraint */
- validate_pyconstraint_cb(bmain, con->data, &scriptint);
-
- /* make sure target allowance is set correctly */
- BPY_pyconstraint_update(ob, con);
- }
+ char *menustr;
+ int scriptint = 0;
+ /* popup a list of usable scripts */
+ menustr = buildmenu_pyconstraints(bmain, NULL, &scriptint);
+ /* XXX scriptint = pupmenu(menustr); */
+ MEM_freeN(menustr);
+
+ /* only add constraint if a script was chosen */
+ if (scriptint) {
+ /* add constraint */
+ validate_pyconstraint_cb(bmain, con->data, &scriptint);
+
+ /* make sure target allowance is set correctly */
+ BPY_pyconstraint_update(ob, con);
+ }
#endif
- break;
- }
-
- default:
- break;
- }
+ break;
+ }
- /* make sure all settings are valid - similar to above checks, but sometimes can be wrong */
- object_test_constraints(bmain, ob);
+ default:
+ break;
+ }
- if (pchan)
- BKE_pose_update_constraint_flags(ob->pose);
+ /* make sure all settings are valid - similar to above checks, but sometimes can be wrong */
+ object_test_constraints(bmain, ob);
+ if (pchan)
+ BKE_pose_update_constraint_flags(ob->pose);
- /* force depsgraph to get recalculated since new relationships added */
- DEG_relations_tag_update(bmain);
+ /* force depsgraph to get recalculated since new relationships added */
+ DEG_relations_tag_update(bmain);
- if ((ob->type == OB_ARMATURE) && (pchan)) {
- BKE_pose_tag_recalc(bmain, ob->pose); /* sort pose channels */
- if (BKE_constraints_proxylocked_owner(ob, pchan) && ob->adt) {
- /* We need to make use of ugly POSE_ANIMATION_WORKAROUND here too, else anim data are not reloaded
- * after calling `BKE_pose_rebuild()`, which causes T43872.
- * XXX Temp hack until new depsgraph hopefully solves this. */
- DEG_id_tag_update(&ob->id, ID_RECALC_ANIMATION);
- }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_TRANSFORM);
- }
- else
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ if ((ob->type == OB_ARMATURE) && (pchan)) {
+ BKE_pose_tag_recalc(bmain, ob->pose); /* sort pose channels */
+ if (BKE_constraints_proxylocked_owner(ob, pchan) && ob->adt) {
+ /* We need to make use of ugly POSE_ANIMATION_WORKAROUND here too, else anim data are not reloaded
+ * after calling `BKE_pose_rebuild()`, which causes T43872.
+ * XXX Temp hack until new depsgraph hopefully solves this. */
+ DEG_id_tag_update(&ob->id, ID_RECALC_ANIMATION);
+ }
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_TRANSFORM);
+ }
+ else
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_ADDED, ob);
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_ADDED, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/* ------------------ */
@@ -1871,121 +1904,125 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase
/* dummy operator callback */
static int object_constraint_add_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- int type = RNA_enum_get(op->ptr, "type");
- short with_targets = 0;
+ Object *ob = ED_object_active_context(C);
+ int type = RNA_enum_get(op->ptr, "type");
+ short with_targets = 0;
- if (!ob) {
- BKE_report(op->reports, RPT_ERROR, "No active object to add constraint to");
- return OPERATOR_CANCELLED;
- }
+ if (!ob) {
+ BKE_report(op->reports, RPT_ERROR, "No active object to add constraint to");
+ return OPERATOR_CANCELLED;
+ }
- /* hack: set constraint targets from selected objects in context is allowed when
- * operator name included 'with_targets', since the menu doesn't allow multiple properties
- */
- if (strstr(op->idname, "with_targets"))
- with_targets = 1;
+ /* hack: set constraint targets from selected objects in context is allowed when
+ * operator name included 'with_targets', since the menu doesn't allow multiple properties
+ */
+ if (strstr(op->idname, "with_targets"))
+ with_targets = 1;
- return constraint_add_exec(C, op, ob, &ob->constraints, type, with_targets);
+ return constraint_add_exec(C, op, ob, &ob->constraints, type, with_targets);
}
/* dummy operator callback */
static int pose_constraint_add_exec(bContext *C, wmOperator *op)
{
- Object *ob = BKE_object_pose_armature_get(ED_object_active_context(C));
- int type = RNA_enum_get(op->ptr, "type");
- short with_targets = 0;
+ Object *ob = BKE_object_pose_armature_get(ED_object_active_context(C));
+ int type = RNA_enum_get(op->ptr, "type");
+ short with_targets = 0;
- if (!ob) {
- BKE_report(op->reports, RPT_ERROR, "No active object to add constraint to");
- return OPERATOR_CANCELLED;
- }
+ if (!ob) {
+ BKE_report(op->reports, RPT_ERROR, "No active object to add constraint to");
+ return OPERATOR_CANCELLED;
+ }
- /* hack: set constraint targets from selected objects in context is allowed when
- * operator name included 'with_targets', since the menu doesn't allow multiple properties
- */
- if (strstr(op->idname, "with_targets"))
- with_targets = 1;
+ /* hack: set constraint targets from selected objects in context is allowed when
+ * operator name included 'with_targets', since the menu doesn't allow multiple properties
+ */
+ if (strstr(op->idname, "with_targets"))
+ with_targets = 1;
- return constraint_add_exec(C, op, ob, get_active_constraints(ob), type, with_targets);
+ return constraint_add_exec(C, op, ob, get_active_constraints(ob), type, with_targets);
}
/* ------------------ */
void OBJECT_OT_constraint_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Constraint";
- ot->description = "Add a constraint to the active object";
- ot->idname = "OBJECT_OT_constraint_add";
+ /* identifiers */
+ ot->name = "Add Constraint";
+ ot->description = "Add a constraint to the active object";
+ ot->idname = "OBJECT_OT_constraint_add";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_constraint_add_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_constraint_add_exec;
+ ot->poll = ED_operator_object_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
}
void OBJECT_OT_constraint_add_with_targets(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Constraint (with Targets)";
- ot->description = "Add a constraint to the active object, with target (where applicable) set to the selected Objects/Bones";
- ot->idname = "OBJECT_OT_constraint_add_with_targets";
+ /* identifiers */
+ ot->name = "Add Constraint (with Targets)";
+ ot->description =
+ "Add a constraint to the active object, with target (where applicable) set to the selected "
+ "Objects/Bones";
+ ot->idname = "OBJECT_OT_constraint_add_with_targets";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_constraint_add_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_constraint_add_exec;
+ ot->poll = ED_operator_object_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
}
void POSE_OT_constraint_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Constraint";
- ot->description = "Add a constraint to the active bone";
- ot->idname = "POSE_OT_constraint_add";
+ /* identifiers */
+ ot->name = "Add Constraint";
+ ot->description = "Add a constraint to the active bone";
+ ot->idname = "POSE_OT_constraint_add";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = pose_constraint_add_exec;
- ot->poll = ED_operator_posemode_exclusive;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = pose_constraint_add_exec;
+ ot->poll = ED_operator_posemode_exclusive;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
}
void POSE_OT_constraint_add_with_targets(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Constraint (with Targets)";
- ot->description = "Add a constraint to the active bone, with target (where applicable) set to the selected Objects/Bones";
- ot->idname = "POSE_OT_constraint_add_with_targets";
+ /* identifiers */
+ ot->name = "Add Constraint (with Targets)";
+ ot->description =
+ "Add a constraint to the active bone, with target (where applicable) set to the selected "
+ "Objects/Bones";
+ ot->idname = "POSE_OT_constraint_add_with_targets";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = pose_constraint_add_exec;
- ot->poll = ED_operator_posemode_exclusive;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = pose_constraint_add_exec;
+ ot->poll = ED_operator_posemode_exclusive;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
}
/************************ IK Constraint operators *********************/
@@ -1995,83 +2032,93 @@ void POSE_OT_constraint_add_with_targets(wmOperatorType *ot)
/* present menu with options + validation for targets to use */
static int pose_ik_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
- bPoseChannel *pchan = BKE_pose_channel_active(ob);
- bConstraint *con = NULL;
-
- uiPopupMenu *pup;
- uiLayout *layout;
- Object *tar_ob = NULL;
- bPoseChannel *tar_pchan = NULL;
-
- /* must have active bone */
- if (ELEM(NULL, ob, pchan)) {
- BKE_report(op->reports, RPT_ERROR, "Must have an active bone to add IK constraint to");
- return OPERATOR_CANCELLED;
- }
-
- /* bone must not have any constraints already */
- for (con = pchan->constraints.first; con; con = con->next) {
- if (con->type == CONSTRAINT_TYPE_KINEMATIC) break;
- }
- if (con) {
- BKE_report(op->reports, RPT_ERROR, "Bone already has an IK constraint");
- return OPERATOR_CANCELLED;
- }
-
- /* prepare popup menu to choose targeting options */
- pup = UI_popup_menu_begin(C, IFACE_("Add IK"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
-
- /* the type of targets we'll set determines the menu entries to show... */
- if (get_new_constraint_target(C, CONSTRAINT_TYPE_KINEMATIC, &tar_ob, &tar_pchan, 0)) {
- /* bone target, or object target?
- * - the only thing that matters is that we want a target...
- */
- if (tar_pchan)
- uiItemBooleanO(layout, IFACE_("To Active Bone"), ICON_NONE, "POSE_OT_ik_add", "with_targets", 1);
- else
- uiItemBooleanO(layout, IFACE_("To Active Object"), ICON_NONE, "POSE_OT_ik_add", "with_targets", 1);
- }
- else {
- /* we have a choice of adding to a new empty, or not setting any target (targetless IK) */
- uiItemBooleanO(layout, IFACE_("To New Empty Object"), ICON_NONE, "POSE_OT_ik_add", "with_targets", 1);
- uiItemBooleanO(layout, IFACE_("Without Targets"), ICON_NONE, "POSE_OT_ik_add", "with_targets", 0);
- }
-
- /* finish building the menu, and process it (should result in calling self again) */
- UI_popup_menu_end(C, pup);
-
- return OPERATOR_INTERFACE;
+ Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
+ bPoseChannel *pchan = BKE_pose_channel_active(ob);
+ bConstraint *con = NULL;
+
+ uiPopupMenu *pup;
+ uiLayout *layout;
+ Object *tar_ob = NULL;
+ bPoseChannel *tar_pchan = NULL;
+
+ /* must have active bone */
+ if (ELEM(NULL, ob, pchan)) {
+ BKE_report(op->reports, RPT_ERROR, "Must have an active bone to add IK constraint to");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* bone must not have any constraints already */
+ for (con = pchan->constraints.first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC)
+ break;
+ }
+ if (con) {
+ BKE_report(op->reports, RPT_ERROR, "Bone already has an IK constraint");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* prepare popup menu to choose targeting options */
+ pup = UI_popup_menu_begin(C, IFACE_("Add IK"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+
+ /* the type of targets we'll set determines the menu entries to show... */
+ if (get_new_constraint_target(C, CONSTRAINT_TYPE_KINEMATIC, &tar_ob, &tar_pchan, 0)) {
+ /* bone target, or object target?
+ * - the only thing that matters is that we want a target...
+ */
+ if (tar_pchan)
+ uiItemBooleanO(
+ layout, IFACE_("To Active Bone"), ICON_NONE, "POSE_OT_ik_add", "with_targets", 1);
+ else
+ uiItemBooleanO(
+ layout, IFACE_("To Active Object"), ICON_NONE, "POSE_OT_ik_add", "with_targets", 1);
+ }
+ else {
+ /* we have a choice of adding to a new empty, or not setting any target (targetless IK) */
+ uiItemBooleanO(
+ layout, IFACE_("To New Empty Object"), ICON_NONE, "POSE_OT_ik_add", "with_targets", 1);
+ uiItemBooleanO(
+ layout, IFACE_("Without Targets"), ICON_NONE, "POSE_OT_ik_add", "with_targets", 0);
+ }
+
+ /* finish building the menu, and process it (should result in calling self again) */
+ UI_popup_menu_end(C, pup);
+
+ return OPERATOR_INTERFACE;
}
/* call constraint_add_exec() to add the IK constraint */
static int pose_ik_add_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
- const bool with_targets = RNA_boolean_get(op->ptr, "with_targets");
+ Object *ob = CTX_data_active_object(C);
+ const bool with_targets = RNA_boolean_get(op->ptr, "with_targets");
- /* add the constraint - all necessary checks should have been done by the invoke() callback already... */
- return constraint_add_exec(C, op, ob, get_active_constraints(ob), CONSTRAINT_TYPE_KINEMATIC, with_targets);
+ /* add the constraint - all necessary checks should have been done by the invoke() callback already... */
+ return constraint_add_exec(
+ C, op, ob, get_active_constraints(ob), CONSTRAINT_TYPE_KINEMATIC, with_targets);
}
void POSE_OT_ik_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add IK to Bone";
- ot->description = "Add IK Constraint to the active Bone";
- ot->idname = "POSE_OT_ik_add";
+ /* identifiers */
+ ot->name = "Add IK to Bone";
+ ot->description = "Add IK Constraint to the active Bone";
+ ot->idname = "POSE_OT_ik_add";
- /* api callbacks */
- ot->invoke = pose_ik_add_invoke;
- ot->exec = pose_ik_add_exec;
- ot->poll = ED_operator_posemode_exclusive;
+ /* api callbacks */
+ ot->invoke = pose_ik_add_invoke;
+ ot->exec = pose_ik_add_exec;
+ ot->poll = ED_operator_posemode_exclusive;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "with_targets", 1, "With Targets", "Assign IK Constraint with targets derived from the select bones/objects");
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "with_targets",
+ 1,
+ "With Targets",
+ "Assign IK Constraint with targets derived from the select bones/objects");
}
/* ------------------ */
@@ -2079,48 +2126,48 @@ void POSE_OT_ik_add(wmOperatorType *ot)
/* remove IK constraints from selected bones */
static int pose_ik_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *prev_ob = NULL;
+ Object *prev_ob = NULL;
- /* only remove IK Constraints */
- CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, selected_pose_bones, Object *, ob)
- {
- bConstraint *con, *next;
+ /* only remove IK Constraints */
+ CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, pchan, selected_pose_bones, Object *, ob)
+ {
+ bConstraint *con, *next;
- /* TODO: should we be checking if these constraints were local before we try and remove them? */
- for (con = pchan->constraints.first; con; con = next) {
- next = con->next;
- if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
- BKE_constraint_remove(&pchan->constraints, con);
- }
- }
- pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_TARGET);
+ /* TODO: should we be checking if these constraints were local before we try and remove them? */
+ for (con = pchan->constraints.first; con; con = next) {
+ next = con->next;
+ if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
+ BKE_constraint_remove(&pchan->constraints, con);
+ }
+ }
+ pchan->constflag &= ~(PCHAN_HAS_IK | PCHAN_HAS_TARGET);
- if (prev_ob != ob) {
- prev_ob = ob;
+ if (prev_ob != ob) {
+ prev_ob = ob;
- /* Refresh depsgraph. */
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ /* Refresh depsgraph. */
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- /* Note, notifier might evolve. */
- WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
- }
- }
- CTX_DATA_END;
+ /* Note, notifier might evolve. */
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
+ }
+ }
+ CTX_DATA_END;
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void POSE_OT_ik_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove IK";
- ot->description = "Remove all IK Constraints from selected bones";
- ot->idname = "POSE_OT_ik_clear";
+ /* identifiers */
+ ot->name = "Remove IK";
+ ot->description = "Remove all IK Constraints from selected bones";
+ ot->idname = "POSE_OT_ik_clear";
- /* api callbacks */
- ot->exec = pose_ik_clear_exec;
- ot->poll = ED_operator_posemode_exclusive;
+ /* api callbacks */
+ ot->exec = pose_ik_clear_exec;
+ ot->poll = ED_operator_posemode_exclusive;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c
index 52b60793585..57c7ff1535d 100644
--- a/source/blender/editors/object/object_data_transfer.c
+++ b/source/blender/editors/object/object_data_transfer.c
@@ -58,402 +58,463 @@
* Note some are 'fake' ones, i.e. they are not hold by real CDLayers. */
/* Not shared with modifier, since we use a usual enum here, not a multi-choice one. */
static const EnumPropertyItem DT_layer_items[] = {
- {0, "", 0, "Vertex Data", ""},
- {DT_TYPE_MDEFORMVERT, "VGROUP_WEIGHTS", 0, "Vertex Group(s)", "Transfer active or all vertex groups"},
-#if 0 /* XXX For now, would like to finish/merge work from 2014 gsoc first. */
- {DT_TYPE_SHAPEKEY, "SHAPEKEYS", 0, "Shapekey(s)", "Transfer active or all shape keys"},
+ {0, "", 0, "Vertex Data", ""},
+ {DT_TYPE_MDEFORMVERT,
+ "VGROUP_WEIGHTS",
+ 0,
+ "Vertex Group(s)",
+ "Transfer active or all vertex groups"},
+#if 0 /* XXX For now, would like to finish/merge work from 2014 gsoc first. */
+ {DT_TYPE_SHAPEKEY, "SHAPEKEYS", 0, "Shapekey(s)", "Transfer active or all shape keys"},
#endif
-#if 0 /* XXX When SkinModifier is enabled,
+#if 0 /* XXX When SkinModifier is enabled,
* it seems to erase its own CD_MVERT_SKIN layer from final DM :( */
- {DT_TYPE_SKIN, "SKIN", 0, "Skin Weight", "Transfer skin weights"},
+ {DT_TYPE_SKIN, "SKIN", 0, "Skin Weight", "Transfer skin weights"},
#endif
- {DT_TYPE_BWEIGHT_VERT, "BEVEL_WEIGHT_VERT", 0, "Bevel Weight", "Transfer bevel weights"},
- {0, "", 0, "Edge Data", ""},
- {DT_TYPE_SHARP_EDGE, "SHARP_EDGE", 0, "Sharp", "Transfer sharp mark"},
- {DT_TYPE_SEAM, "SEAM", 0, "UV Seam", "Transfer UV seam mark"},
- {DT_TYPE_CREASE, "CREASE", 0, "Subsurf Crease", "Transfer crease values"},
- {DT_TYPE_BWEIGHT_EDGE, "BEVEL_WEIGHT_EDGE", 0, "Bevel Weight", "Transfer bevel weights"},
- {DT_TYPE_FREESTYLE_EDGE, "FREESTYLE_EDGE", 0, "Freestyle Mark", "Transfer Freestyle edge mark"},
- {0, "", 0, "Face Corner Data", ""},
- {DT_TYPE_LNOR, "CUSTOM_NORMAL", 0, "Custom Normals", "Transfer custom normals"},
- {DT_TYPE_VCOL, "VCOL", 0, "VCol", "Vertex (face corners) colors"},
- {DT_TYPE_UV, "UV", 0, "UVs", "Transfer UV layers"},
- {0, "", 0, "Face Data", ""},
- {DT_TYPE_SHARP_FACE, "SMOOTH", 0, "Smooth", "Transfer flat/smooth mark"},
- {DT_TYPE_FREESTYLE_FACE, "FREESTYLE_FACE", 0, "Freestyle Mark", "Transfer Freestyle face mark"},
- {0, NULL, 0, NULL, NULL},
+ {DT_TYPE_BWEIGHT_VERT, "BEVEL_WEIGHT_VERT", 0, "Bevel Weight", "Transfer bevel weights"},
+ {0, "", 0, "Edge Data", ""},
+ {DT_TYPE_SHARP_EDGE, "SHARP_EDGE", 0, "Sharp", "Transfer sharp mark"},
+ {DT_TYPE_SEAM, "SEAM", 0, "UV Seam", "Transfer UV seam mark"},
+ {DT_TYPE_CREASE, "CREASE", 0, "Subsurf Crease", "Transfer crease values"},
+ {DT_TYPE_BWEIGHT_EDGE, "BEVEL_WEIGHT_EDGE", 0, "Bevel Weight", "Transfer bevel weights"},
+ {DT_TYPE_FREESTYLE_EDGE,
+ "FREESTYLE_EDGE",
+ 0,
+ "Freestyle Mark",
+ "Transfer Freestyle edge mark"},
+ {0, "", 0, "Face Corner Data", ""},
+ {DT_TYPE_LNOR, "CUSTOM_NORMAL", 0, "Custom Normals", "Transfer custom normals"},
+ {DT_TYPE_VCOL, "VCOL", 0, "VCol", "Vertex (face corners) colors"},
+ {DT_TYPE_UV, "UV", 0, "UVs", "Transfer UV layers"},
+ {0, "", 0, "Face Data", ""},
+ {DT_TYPE_SHARP_FACE, "SMOOTH", 0, "Smooth", "Transfer flat/smooth mark"},
+ {DT_TYPE_FREESTYLE_FACE,
+ "FREESTYLE_FACE",
+ 0,
+ "Freestyle Mark",
+ "Transfer Freestyle face mark"},
+ {0, NULL, 0, NULL, NULL},
};
/* Note: rna_enum_dt_layers_select_src_items enum is from rna_modifier.c */
-static const EnumPropertyItem *dt_layers_select_src_itemf(
- bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *dt_layers_select_src_itemf(bContext *C,
+ PointerRNA *ptr,
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- if (!C) { /* needed for docs and i18n tools */
- return rna_enum_dt_layers_select_src_items;
- }
-
- EnumPropertyItem *item = NULL, tmp_item = {0};
- int totitem = 0;
- const int data_type = RNA_enum_get(ptr, "data_type");
-
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
-
- PropertyRNA *prop = RNA_struct_find_property(ptr, "use_reverse_transfer");
- const bool reverse_transfer = prop != NULL && RNA_property_boolean_get(ptr, prop);
- const int layers_select_dst = reverse_transfer ? RNA_enum_get(ptr, "layers_select_src") :
- RNA_enum_get(ptr, "layers_select_dst");
-
- if (!reverse_transfer || layers_select_dst == DT_LAYERS_ACTIVE_DST || layers_select_dst >= 0) {
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_ACTIVE_SRC);
- }
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_ALL_SRC);
-
-
-
- if (data_type == DT_TYPE_MDEFORMVERT) {
- Object *ob_src = CTX_data_active_object(C);
-
- if (BKE_object_pose_armature_get(ob_src)) {
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_SELECT);
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_DEFORM);
- }
-
- if (ob_src) {
- bDeformGroup *dg;
- int i;
-
- RNA_enum_item_add_separator(&item, &totitem);
-
- for (i = 0, dg = ob_src->defbase.first; dg; i++, dg = dg->next) {
- tmp_item.value = i;
- tmp_item.identifier = tmp_item.name = dg->name;
- RNA_enum_item_add(&item, &totitem, &tmp_item);
- }
- }
- }
- else if (data_type == DT_TYPE_SHAPEKEY) {
- /* TODO */
- }
- else if (data_type == DT_TYPE_UV) {
- Object *ob_src = CTX_data_active_object(C);
-
- if (ob_src) {
- Mesh *me_eval;
- int num_data, i;
-
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
-
- CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH;
- cddata_masks.lmask |= CD_MASK_MLOOPUV;
- me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_src_eval, &cddata_masks);
- num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPUV);
-
- RNA_enum_item_add_separator(&item, &totitem);
-
- for (i = 0; i < num_data; i++) {
- tmp_item.value = i;
- tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(&me_eval->ldata, CD_MLOOPUV, i);
- RNA_enum_item_add(&item, &totitem, &tmp_item);
- }
- }
- }
- else if (data_type == DT_TYPE_VCOL) {
- Object *ob_src = CTX_data_active_object(C);
-
- if (ob_src) {
- Mesh *me_eval;
- int num_data, i;
-
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
-
- CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH;
- cddata_masks.lmask |= CD_MASK_MLOOPCOL;
- me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_src_eval, &cddata_masks);
- num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPCOL);
-
- RNA_enum_item_add_separator(&item, &totitem);
-
- for (i = 0; i < num_data; i++) {
- tmp_item.value = i;
- tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(&me_eval->ldata, CD_MLOOPCOL, i);
- RNA_enum_item_add(&item, &totitem, &tmp_item);
- }
- }
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ if (!C) { /* needed for docs and i18n tools */
+ return rna_enum_dt_layers_select_src_items;
+ }
+
+ EnumPropertyItem *item = NULL, tmp_item = {0};
+ int totitem = 0;
+ const int data_type = RNA_enum_get(ptr, "data_type");
+
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+
+ PropertyRNA *prop = RNA_struct_find_property(ptr, "use_reverse_transfer");
+ const bool reverse_transfer = prop != NULL && RNA_property_boolean_get(ptr, prop);
+ const int layers_select_dst = reverse_transfer ? RNA_enum_get(ptr, "layers_select_src") :
+ RNA_enum_get(ptr, "layers_select_dst");
+
+ if (!reverse_transfer || layers_select_dst == DT_LAYERS_ACTIVE_DST || layers_select_dst >= 0) {
+ RNA_enum_items_add_value(
+ &item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_ACTIVE_SRC);
+ }
+ RNA_enum_items_add_value(
+ &item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_ALL_SRC);
+
+ if (data_type == DT_TYPE_MDEFORMVERT) {
+ Object *ob_src = CTX_data_active_object(C);
+
+ if (BKE_object_pose_armature_get(ob_src)) {
+ RNA_enum_items_add_value(
+ &item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_SELECT);
+ RNA_enum_items_add_value(
+ &item, &totitem, rna_enum_dt_layers_select_src_items, DT_LAYERS_VGROUP_SRC_BONE_DEFORM);
+ }
+
+ if (ob_src) {
+ bDeformGroup *dg;
+ int i;
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0, dg = ob_src->defbase.first; dg; i++, dg = dg->next) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = dg->name;
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+ else if (data_type == DT_TYPE_SHAPEKEY) {
+ /* TODO */
+ }
+ else if (data_type == DT_TYPE_UV) {
+ Object *ob_src = CTX_data_active_object(C);
+
+ if (ob_src) {
+ Mesh *me_eval;
+ int num_data, i;
+
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
+
+ CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH;
+ cddata_masks.lmask |= CD_MASK_MLOOPUV;
+ me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_src_eval, &cddata_masks);
+ num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPUV);
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0; i < num_data; i++) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(
+ &me_eval->ldata, CD_MLOOPUV, i);
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+ else if (data_type == DT_TYPE_VCOL) {
+ Object *ob_src = CTX_data_active_object(C);
+
+ if (ob_src) {
+ Mesh *me_eval;
+ int num_data, i;
+
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
+
+ CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH;
+ cddata_masks.lmask |= CD_MASK_MLOOPCOL;
+ me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_src_eval, &cddata_masks);
+ num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPCOL);
+
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ for (i = 0; i < num_data; i++) {
+ tmp_item.value = i;
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(
+ &me_eval->ldata, CD_MLOOPCOL, i);
+ RNA_enum_item_add(&item, &totitem, &tmp_item);
+ }
+ }
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
/* Note: rna_enum_dt_layers_select_dst_items enum is from rna_modifier.c */
-static const EnumPropertyItem *dt_layers_select_dst_itemf(
- bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *dt_layers_select_dst_itemf(bContext *C,
+ PointerRNA *ptr,
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- if (!C) { /* needed for docs and i18n tools */
- return rna_enum_dt_layers_select_dst_items;
- }
+ if (!C) { /* needed for docs and i18n tools */
+ return rna_enum_dt_layers_select_dst_items;
+ }
- EnumPropertyItem *item = NULL;
- int totitem = 0;
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
- PropertyRNA *prop = RNA_struct_find_property(ptr, "use_reverse_transfer");
- const bool reverse_transfer = prop != NULL && RNA_property_boolean_get(ptr, prop);
- const int layers_select_src = reverse_transfer ? RNA_enum_get(ptr, "layers_select_dst") :
- RNA_enum_get(ptr, "layers_select_src");
+ PropertyRNA *prop = RNA_struct_find_property(ptr, "use_reverse_transfer");
+ const bool reverse_transfer = prop != NULL && RNA_property_boolean_get(ptr, prop);
+ const int layers_select_src = reverse_transfer ? RNA_enum_get(ptr, "layers_select_dst") :
+ RNA_enum_get(ptr, "layers_select_src");
- if (reverse_transfer || layers_select_src == DT_LAYERS_ACTIVE_SRC || layers_select_src >= 0) {
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_dst_items, DT_LAYERS_ACTIVE_DST);
- }
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_dst_items, DT_LAYERS_NAME_DST);
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_layers_select_dst_items, DT_LAYERS_INDEX_DST);
+ if (reverse_transfer || layers_select_src == DT_LAYERS_ACTIVE_SRC || layers_select_src >= 0) {
+ RNA_enum_items_add_value(
+ &item, &totitem, rna_enum_dt_layers_select_dst_items, DT_LAYERS_ACTIVE_DST);
+ }
+ RNA_enum_items_add_value(
+ &item, &totitem, rna_enum_dt_layers_select_dst_items, DT_LAYERS_NAME_DST);
+ RNA_enum_items_add_value(
+ &item, &totitem, rna_enum_dt_layers_select_dst_items, DT_LAYERS_INDEX_DST);
- /* No 'specific' to-layers here, since we may transfer to several objects at once! */
+ /* No 'specific' to-layers here, since we may transfer to several objects at once! */
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
- return item;
+ return item;
}
-static const EnumPropertyItem *dt_layers_select_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool *r_free)
+static const EnumPropertyItem *dt_layers_select_itemf(bContext *C,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ bool *r_free)
{
- const bool reverse_transfer = RNA_boolean_get(ptr, "use_reverse_transfer");
-
- if (STREQ(RNA_property_identifier(prop), "layers_select_dst")) {
- if (reverse_transfer) {
- return dt_layers_select_src_itemf(C, ptr, prop, r_free);
- }
- else {
- return dt_layers_select_dst_itemf(C, ptr, prop, r_free);
- }
- }
- else if (reverse_transfer) {
- return dt_layers_select_dst_itemf(C, ptr, prop, r_free);
- }
- else {
- return dt_layers_select_src_itemf(C, ptr, prop, r_free);
- }
+ const bool reverse_transfer = RNA_boolean_get(ptr, "use_reverse_transfer");
+
+ if (STREQ(RNA_property_identifier(prop), "layers_select_dst")) {
+ if (reverse_transfer) {
+ return dt_layers_select_src_itemf(C, ptr, prop, r_free);
+ }
+ else {
+ return dt_layers_select_dst_itemf(C, ptr, prop, r_free);
+ }
+ }
+ else if (reverse_transfer) {
+ return dt_layers_select_dst_itemf(C, ptr, prop, r_free);
+ }
+ else {
+ return dt_layers_select_src_itemf(C, ptr, prop, r_free);
+ }
}
/* Note: rna_enum_dt_mix_mode_items enum is from rna_modifier.c */
-static const EnumPropertyItem *dt_mix_mode_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *dt_mix_mode_itemf(bContext *C,
+ PointerRNA *ptr,
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- EnumPropertyItem *item = NULL;
- int totitem = 0;
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
- const int dtdata_type = RNA_enum_get(ptr, "data_type");
- bool support_advanced_mixing, support_threshold;
+ const int dtdata_type = RNA_enum_get(ptr, "data_type");
+ bool support_advanced_mixing, support_threshold;
- if (!C) { /* needed for docs and i18n tools */
- return rna_enum_dt_mix_mode_items;
- }
+ if (!C) { /* needed for docs and i18n tools */
+ return rna_enum_dt_mix_mode_items;
+ }
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_TRANSFER);
+ RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_TRANSFER);
- BKE_object_data_transfer_get_dttypes_capacity(dtdata_type, &support_advanced_mixing, &support_threshold);
+ BKE_object_data_transfer_get_dttypes_capacity(
+ dtdata_type, &support_advanced_mixing, &support_threshold);
- if (support_threshold) {
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_REPLACE_ABOVE_THRESHOLD);
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_REPLACE_BELOW_THRESHOLD);
- }
+ if (support_threshold) {
+ RNA_enum_items_add_value(
+ &item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_REPLACE_ABOVE_THRESHOLD);
+ RNA_enum_items_add_value(
+ &item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_REPLACE_BELOW_THRESHOLD);
+ }
- if (support_advanced_mixing) {
- RNA_enum_item_add_separator(&item, &totitem);
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_MIX);
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_ADD);
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_SUB);
- RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_MUL);
- }
+ if (support_advanced_mixing) {
+ RNA_enum_item_add_separator(&item, &totitem);
+ RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_MIX);
+ RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_ADD);
+ RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_SUB);
+ RNA_enum_items_add_value(&item, &totitem, rna_enum_dt_mix_mode_items, CDT_MIX_MUL);
+ }
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
- return item;
+ return item;
}
static bool data_transfer_check(bContext *UNUSED(C), wmOperator *op)
{
- const int layers_select_src = RNA_enum_get(op->ptr, "layers_select_src");
- PropertyRNA *prop = RNA_struct_find_property(op->ptr, "layers_select_dst");
- const int layers_select_dst = RNA_property_enum_get(op->ptr, prop);
+ const int layers_select_src = RNA_enum_get(op->ptr, "layers_select_src");
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "layers_select_dst");
+ const int layers_select_dst = RNA_property_enum_get(op->ptr, prop);
- /* TODO: check for invalid layers_src select modes too! */
+ /* TODO: check for invalid layers_src select modes too! */
- if ((layers_select_src != DT_LAYERS_ACTIVE_SRC) && (layers_select_dst == DT_LAYERS_ACTIVE_DST)) {
- RNA_property_enum_set(op->ptr, prop, DT_LAYERS_NAME_DST);
- return true;
- }
+ if ((layers_select_src != DT_LAYERS_ACTIVE_SRC) && (layers_select_dst == DT_LAYERS_ACTIVE_DST)) {
+ RNA_property_enum_set(op->ptr, prop, DT_LAYERS_NAME_DST);
+ return true;
+ }
- return false;
+ return false;
}
/* Helper, used by both data_transfer_exec and datalayout_transfer_exec. */
-static void data_transfer_exec_preprocess_objects(
- bContext *C, wmOperator *op, Object *ob_src, ListBase *ctx_objects, const bool reverse_transfer)
+static void data_transfer_exec_preprocess_objects(bContext *C,
+ wmOperator *op,
+ Object *ob_src,
+ ListBase *ctx_objects,
+ const bool reverse_transfer)
{
- CollectionPointerLink *ctx_ob;
- CTX_data_selected_editable_objects(C, ctx_objects);
-
- if (reverse_transfer) {
- return; /* Nothing else to do in this case... */
- }
-
- for (ctx_ob = ctx_objects->first; ctx_ob; ctx_ob = ctx_ob->next) {
- Object *ob = ctx_ob->ptr.data;
- Mesh *me;
- if ((ob == ob_src) || (ob->type != OB_MESH)) {
- continue;
- }
-
- me = ob->data;
- if (ID_IS_LINKED(me)) {
- /* Do not transfer to linked data, not supported. */
- BKE_reportf(op->reports, RPT_WARNING, "Skipping object '%s', linked data '%s' cannot be modified",
- ob->id.name + 2, me->id.name + 2);
- me->id.tag &= ~LIB_TAG_DOIT;
- continue;
- }
-
- me->id.tag |= LIB_TAG_DOIT;
- }
+ CollectionPointerLink *ctx_ob;
+ CTX_data_selected_editable_objects(C, ctx_objects);
+
+ if (reverse_transfer) {
+ return; /* Nothing else to do in this case... */
+ }
+
+ for (ctx_ob = ctx_objects->first; ctx_ob; ctx_ob = ctx_ob->next) {
+ Object *ob = ctx_ob->ptr.data;
+ Mesh *me;
+ if ((ob == ob_src) || (ob->type != OB_MESH)) {
+ continue;
+ }
+
+ me = ob->data;
+ if (ID_IS_LINKED(me)) {
+ /* Do not transfer to linked data, not supported. */
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "Skipping object '%s', linked data '%s' cannot be modified",
+ ob->id.name + 2,
+ me->id.name + 2);
+ me->id.tag &= ~LIB_TAG_DOIT;
+ continue;
+ }
+
+ me->id.tag |= LIB_TAG_DOIT;
+ }
}
/* Helper, used by both data_transfer_exec and datalayout_transfer_exec. */
-static bool data_transfer_exec_is_object_valid(
- wmOperator *op, Object *ob_src, Object *ob_dst, const bool reverse_transfer)
+static bool data_transfer_exec_is_object_valid(wmOperator *op,
+ Object *ob_src,
+ Object *ob_dst,
+ const bool reverse_transfer)
{
- Mesh *me;
- if ((ob_dst == ob_src) || (ob_src->type != OB_MESH) || (ob_dst->type != OB_MESH)) {
- return false;
- }
-
- if (reverse_transfer) {
- return true;
- }
-
- me = ob_dst->data;
- if (me->id.tag & LIB_TAG_DOIT) {
- me->id.tag &= ~LIB_TAG_DOIT;
- return true;
- }
- else if (!ID_IS_LINKED(me)) {
- /* Do not apply transfer operation more than once. */
- /* XXX This is not nice regarding vgroups, which are half-Object data... :/ */
- BKE_reportf(op->reports, RPT_WARNING,
- "Skipping object '%s', data '%s' has already been processed with a previous object",
- ob_dst->id.name + 2, me->id.name + 2);
- }
- return false;
+ Mesh *me;
+ if ((ob_dst == ob_src) || (ob_src->type != OB_MESH) || (ob_dst->type != OB_MESH)) {
+ return false;
+ }
+
+ if (reverse_transfer) {
+ return true;
+ }
+
+ me = ob_dst->data;
+ if (me->id.tag & LIB_TAG_DOIT) {
+ me->id.tag &= ~LIB_TAG_DOIT;
+ return true;
+ }
+ else if (!ID_IS_LINKED(me)) {
+ /* Do not apply transfer operation more than once. */
+ /* XXX This is not nice regarding vgroups, which are half-Object data... :/ */
+ BKE_reportf(
+ op->reports,
+ RPT_WARNING,
+ "Skipping object '%s', data '%s' has already been processed with a previous object",
+ ob_dst->id.name + 2,
+ me->id.name + 2);
+ }
+ return false;
}
static int data_transfer_exec(bContext *C, wmOperator *op)
{
- Object *ob_src = ED_object_active_context(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
-
- ListBase ctx_objects;
- CollectionPointerLink *ctx_ob_dst;
-
- bool changed = false;
-
- const bool is_frozen = RNA_boolean_get(op->ptr, "use_freeze");
-
- const bool reverse_transfer = RNA_boolean_get(op->ptr, "use_reverse_transfer");
-
- const int data_type = RNA_enum_get(op->ptr, "data_type");
- const bool use_create = RNA_boolean_get(op->ptr, "use_create");
-
- const int map_vert_mode = RNA_enum_get(op->ptr, "vert_mapping");
- const int map_edge_mode = RNA_enum_get(op->ptr, "edge_mapping");
- const int map_loop_mode = RNA_enum_get(op->ptr, "loop_mapping");
- const int map_poly_mode = RNA_enum_get(op->ptr, "poly_mapping");
-
- const bool use_auto_transform = RNA_boolean_get(op->ptr, "use_auto_transform");
- const bool use_object_transform = RNA_boolean_get(op->ptr, "use_object_transform");
- const bool use_max_distance = RNA_boolean_get(op->ptr, "use_max_distance");
- const float max_distance = use_max_distance ? RNA_float_get(op->ptr, "max_distance") : FLT_MAX;
- const float ray_radius = RNA_float_get(op->ptr, "ray_radius");
- const float islands_precision = RNA_float_get(op->ptr, "islands_precision");
-
- const int layers_src = RNA_enum_get(op->ptr, "layers_select_src");
- const int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst");
- int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0};
- int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0};
- const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type);
-
- const int mix_mode = RNA_enum_get(op->ptr, "mix_mode");
- const float mix_factor = RNA_float_get(op->ptr, "mix_factor");
-
- SpaceTransform space_transform_data;
- SpaceTransform *space_transform = (use_object_transform && !use_auto_transform) ? &space_transform_data : NULL;
-
- if (is_frozen) {
- BKE_report(op->reports, RPT_INFO,
- "Operator is frozen, changes to its settings won't take effect until you unfreeze it");
- return OPERATOR_FINISHED;
- }
-
- if (reverse_transfer && ID_IS_LINKED(ob_src->data)) {
- /* Do not transfer to linked data, not supported. */
- return OPERATOR_CANCELLED;
- }
-
- if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
- layers_select_src[fromto_idx] = layers_src;
- layers_select_dst[fromto_idx] = layers_dst;
- }
-
- data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, reverse_transfer);
-
- for (ctx_ob_dst = ctx_objects.first; ctx_ob_dst; ctx_ob_dst = ctx_ob_dst->next) {
- Object *ob_dst = ctx_ob_dst->ptr.data;
-
- if (reverse_transfer) {
- SWAP(Object *, ob_src, ob_dst);
- }
-
- if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, reverse_transfer)) {
- Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
-
- if (space_transform) {
- Object *ob_dst_eval = DEG_get_evaluated_object(depsgraph, ob_dst);
- BLI_SPACE_TRANSFORM_SETUP(space_transform, ob_dst_eval, ob_src_eval);
- }
-
- if (BKE_object_data_transfer_mesh(
- depsgraph, scene_eval, ob_src_eval, ob_dst, data_type, use_create,
- map_vert_mode, map_edge_mode, map_loop_mode, map_poly_mode,
- space_transform, use_auto_transform,
- max_distance, ray_radius, islands_precision,
- layers_select_src, layers_select_dst,
- mix_mode, mix_factor, NULL, false, op->reports))
- {
- changed = true;
- }
- }
-
- DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
-
- if (reverse_transfer) {
- SWAP(Object *, ob_src, ob_dst);
- }
- }
-
- BLI_freelistN(&ctx_objects);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
-
-#if 0 /* TODO */
- /* Note: issue with that is that if canceled, operator cannot be redone... Nasty in our case. */
- return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ Object *ob_src = ED_object_active_context(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+
+ ListBase ctx_objects;
+ CollectionPointerLink *ctx_ob_dst;
+
+ bool changed = false;
+
+ const bool is_frozen = RNA_boolean_get(op->ptr, "use_freeze");
+
+ const bool reverse_transfer = RNA_boolean_get(op->ptr, "use_reverse_transfer");
+
+ const int data_type = RNA_enum_get(op->ptr, "data_type");
+ const bool use_create = RNA_boolean_get(op->ptr, "use_create");
+
+ const int map_vert_mode = RNA_enum_get(op->ptr, "vert_mapping");
+ const int map_edge_mode = RNA_enum_get(op->ptr, "edge_mapping");
+ const int map_loop_mode = RNA_enum_get(op->ptr, "loop_mapping");
+ const int map_poly_mode = RNA_enum_get(op->ptr, "poly_mapping");
+
+ const bool use_auto_transform = RNA_boolean_get(op->ptr, "use_auto_transform");
+ const bool use_object_transform = RNA_boolean_get(op->ptr, "use_object_transform");
+ const bool use_max_distance = RNA_boolean_get(op->ptr, "use_max_distance");
+ const float max_distance = use_max_distance ? RNA_float_get(op->ptr, "max_distance") : FLT_MAX;
+ const float ray_radius = RNA_float_get(op->ptr, "ray_radius");
+ const float islands_precision = RNA_float_get(op->ptr, "islands_precision");
+
+ const int layers_src = RNA_enum_get(op->ptr, "layers_select_src");
+ const int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst");
+ int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0};
+ int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0};
+ const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type);
+
+ const int mix_mode = RNA_enum_get(op->ptr, "mix_mode");
+ const float mix_factor = RNA_float_get(op->ptr, "mix_factor");
+
+ SpaceTransform space_transform_data;
+ SpaceTransform *space_transform = (use_object_transform && !use_auto_transform) ?
+ &space_transform_data :
+ NULL;
+
+ if (is_frozen) {
+ BKE_report(
+ op->reports,
+ RPT_INFO,
+ "Operator is frozen, changes to its settings won't take effect until you unfreeze it");
+ return OPERATOR_FINISHED;
+ }
+
+ if (reverse_transfer && ID_IS_LINKED(ob_src->data)) {
+ /* Do not transfer to linked data, not supported. */
+ return OPERATOR_CANCELLED;
+ }
+
+ if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
+ layers_select_src[fromto_idx] = layers_src;
+ layers_select_dst[fromto_idx] = layers_dst;
+ }
+
+ data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, reverse_transfer);
+
+ for (ctx_ob_dst = ctx_objects.first; ctx_ob_dst; ctx_ob_dst = ctx_ob_dst->next) {
+ Object *ob_dst = ctx_ob_dst->ptr.data;
+
+ if (reverse_transfer) {
+ SWAP(Object *, ob_src, ob_dst);
+ }
+
+ if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, reverse_transfer)) {
+ Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
+
+ if (space_transform) {
+ Object *ob_dst_eval = DEG_get_evaluated_object(depsgraph, ob_dst);
+ BLI_SPACE_TRANSFORM_SETUP(space_transform, ob_dst_eval, ob_src_eval);
+ }
+
+ if (BKE_object_data_transfer_mesh(depsgraph,
+ scene_eval,
+ ob_src_eval,
+ ob_dst,
+ data_type,
+ use_create,
+ map_vert_mode,
+ map_edge_mode,
+ map_loop_mode,
+ map_poly_mode,
+ space_transform,
+ use_auto_transform,
+ max_distance,
+ ray_radius,
+ islands_precision,
+ layers_select_src,
+ layers_select_dst,
+ mix_mode,
+ mix_factor,
+ NULL,
+ false,
+ op->reports)) {
+ changed = true;
+ }
+ }
+
+ DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
+
+ if (reverse_transfer) {
+ SWAP(Object *, ob_src, ob_dst);
+ }
+ }
+
+ BLI_freelistN(&ctx_objects);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
+
+#if 0 /* TODO */
+ /* Note: issue with that is that if canceled, operator cannot be redone... Nasty in our case. */
+ return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
#else
- (void)changed;
- return OPERATOR_FINISHED;
+ (void)changed;
+ return OPERATOR_FINISHED;
#endif
}
@@ -461,153 +522,233 @@ static int data_transfer_exec(bContext *C, wmOperator *op)
/* Note this context poll is only really partial, it cannot check for all possible invalid cases. */
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);
+ Object *ob = ED_object_active_context(C);
+ ID *data = (ob) ? ob->data : NULL;
+ return (ob && ob->type == OB_MESH && data);
}
/* Used by both OBJECT_OT_data_transfer and OBJECT_OT_datalayout_transfer */
-static bool data_transfer_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop)
+static bool data_transfer_poll_property(const bContext *UNUSED(C),
+ wmOperator *op,
+ const PropertyRNA *prop)
{
- PointerRNA *ptr = op->ptr;
- PropertyRNA *prop_other;
-
- const char *prop_id = RNA_property_identifier(prop);
- const int data_type = RNA_enum_get(ptr, "data_type");
- bool use_auto_transform = false;
- bool use_max_distance = false;
- bool use_modifier = false;
-
- if ((prop_other = RNA_struct_find_property(ptr, "use_auto_transform"))) {
- use_auto_transform = RNA_property_boolean_get(ptr, prop_other);
- }
- if ((prop_other = RNA_struct_find_property(ptr, "use_max_distance"))) {
- use_max_distance = RNA_property_boolean_get(ptr, prop_other);
- }
- if ((prop_other = RNA_struct_find_property(ptr, "modifier"))) {
- use_modifier = RNA_property_is_set(ptr, prop_other);
- }
-
- if (STREQ(prop_id, "modifier")) {
- return use_modifier;
- }
-
- if (use_modifier) {
- /* Hide everything but 'modifier' property, if set. */
- return false;
- }
-
- if (STREQ(prop_id, "use_object_transform") && use_auto_transform) {
- return false;
- }
- if (STREQ(prop_id, "max_distance") && !use_max_distance) {
- return false;
- }
- if (STREQ(prop_id, "islands_precision") && !DT_DATATYPE_IS_LOOP(data_type)) {
- return false;
- }
-
- if (STREQ(prop_id, "vert_mapping") && !DT_DATATYPE_IS_VERT(data_type)) {
- return false;
- }
- if (STREQ(prop_id, "edge_mapping") && !DT_DATATYPE_IS_EDGE(data_type)) {
- return false;
- }
- if (STREQ(prop_id, "loop_mapping") && !DT_DATATYPE_IS_LOOP(data_type)) {
- return false;
- }
- if (STREQ(prop_id, "poly_mapping") && !DT_DATATYPE_IS_POLY(data_type)) {
- return false;
- }
-
- if ((STREQ(prop_id, "layers_select_src") || STREQ(prop_id, "layers_select_dst")) &&
- !DT_DATATYPE_IS_MULTILAYERS(data_type))
- {
- return false;
- }
-
- /* Else, show it! */
- return true;
+ PointerRNA *ptr = op->ptr;
+ PropertyRNA *prop_other;
+
+ const char *prop_id = RNA_property_identifier(prop);
+ const int data_type = RNA_enum_get(ptr, "data_type");
+ bool use_auto_transform = false;
+ bool use_max_distance = false;
+ bool use_modifier = false;
+
+ if ((prop_other = RNA_struct_find_property(ptr, "use_auto_transform"))) {
+ use_auto_transform = RNA_property_boolean_get(ptr, prop_other);
+ }
+ if ((prop_other = RNA_struct_find_property(ptr, "use_max_distance"))) {
+ use_max_distance = RNA_property_boolean_get(ptr, prop_other);
+ }
+ if ((prop_other = RNA_struct_find_property(ptr, "modifier"))) {
+ use_modifier = RNA_property_is_set(ptr, prop_other);
+ }
+
+ if (STREQ(prop_id, "modifier")) {
+ return use_modifier;
+ }
+
+ if (use_modifier) {
+ /* Hide everything but 'modifier' property, if set. */
+ return false;
+ }
+
+ if (STREQ(prop_id, "use_object_transform") && use_auto_transform) {
+ return false;
+ }
+ if (STREQ(prop_id, "max_distance") && !use_max_distance) {
+ return false;
+ }
+ if (STREQ(prop_id, "islands_precision") && !DT_DATATYPE_IS_LOOP(data_type)) {
+ return false;
+ }
+
+ if (STREQ(prop_id, "vert_mapping") && !DT_DATATYPE_IS_VERT(data_type)) {
+ return false;
+ }
+ if (STREQ(prop_id, "edge_mapping") && !DT_DATATYPE_IS_EDGE(data_type)) {
+ return false;
+ }
+ if (STREQ(prop_id, "loop_mapping") && !DT_DATATYPE_IS_LOOP(data_type)) {
+ return false;
+ }
+ if (STREQ(prop_id, "poly_mapping") && !DT_DATATYPE_IS_POLY(data_type)) {
+ return false;
+ }
+
+ if ((STREQ(prop_id, "layers_select_src") || STREQ(prop_id, "layers_select_dst")) &&
+ !DT_DATATYPE_IS_MULTILAYERS(data_type)) {
+ return false;
+ }
+
+ /* Else, show it! */
+ return true;
}
/* Transfer mesh data from active to selected objects. */
void OBJECT_OT_data_transfer(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* Identifiers.*/
- ot->name = "Transfer Mesh Data";
- ot->idname = "OBJECT_OT_data_transfer";
- ot->description = "Transfer data layer(s) (weights, edge sharp, ...) from active to selected meshes";
-
- /* API callbacks.*/
- ot->poll = data_transfer_poll;
- ot->poll_property = data_transfer_poll_property;
- ot->invoke = WM_menu_invoke;
- ot->exec = data_transfer_exec;
- ot->check = data_transfer_check;
-
- /* Flags.*/
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
-
- /* Properties.*/
- prop = RNA_def_boolean(ot->srna, "use_reverse_transfer", false, "Reverse Transfer",
- "Transfer from selected objects to active one");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
-
- RNA_def_boolean(ot->srna, "use_freeze", false, "Freeze Operator",
- "Prevent changes to settings to re-run the operator, "
- "handy to change several things at once with heavy geometry");
-
- /* Data type to transfer. */
- ot->prop = RNA_def_enum(ot->srna, "data_type", DT_layer_items, 0, "Data Type", "Which data to transfer");
- RNA_def_boolean(ot->srna, "use_create", true, "Create Data", "Add data layers on destination meshes if needed");
-
- /* Mapping methods. */
- RNA_def_enum(ot->srna, "vert_mapping", rna_enum_dt_method_vertex_items, MREMAP_MODE_VERT_NEAREST, "Vertex Mapping",
- "Method used to map source vertices to destination ones");
- RNA_def_enum(ot->srna, "edge_mapping", rna_enum_dt_method_edge_items, MREMAP_MODE_EDGE_NEAREST, "Edge Mapping",
- "Method used to map source edges to destination ones");
- RNA_def_enum(ot->srna, "loop_mapping", rna_enum_dt_method_loop_items, MREMAP_MODE_LOOP_NEAREST_POLYNOR,
- "Face Corner Mapping", "Method used to map source faces' corners to destination ones");
- RNA_def_enum(ot->srna, "poly_mapping", rna_enum_dt_method_poly_items, MREMAP_MODE_POLY_NEAREST, "Face Mapping",
- "Method used to map source faces to destination ones");
-
- /* Mapping options and filtering. */
- RNA_def_boolean(ot->srna, "use_auto_transform", false, "Auto Transform",
- "Automatically compute transformation to get the best possible match between source and "
- "destination meshes (WARNING: results will never be as good as manual matching of objects)");
- RNA_def_boolean(ot->srna, "use_object_transform", true, "Object Transform",
- "Evaluate source and destination meshes in global space");
- RNA_def_boolean(ot->srna, "use_max_distance", false, "Only Neighbor Geometry",
- "Source elements must be closer than given distance from destination one");
- prop = RNA_def_float(ot->srna, "max_distance", 1.0f, 0.0f, FLT_MAX, "Max Distance",
- "Maximum allowed distance between source and destination element, for non-topology mappings",
- 0.0f, 100.0f);
- RNA_def_property_subtype(prop, PROP_DISTANCE);
- prop = RNA_def_float(ot->srna, "ray_radius", 0.0f, 0.0f, FLT_MAX, "Ray Radius",
- "'Width' of rays (especially useful when raycasting against vertices or edges)",
- 0.0f, 10.0f);
- RNA_def_property_subtype(prop, PROP_DISTANCE);
- prop = RNA_def_float(ot->srna, "islands_precision", 0.1f, 0.0f, 10.0f, "Islands Precision",
- "Factor controlling precision of islands handling (the higher, the better the results)",
- 0.0f, 1.0f);
- RNA_def_property_subtype(prop, PROP_FACTOR);
-
- /* How to handle multi-layers types of data. */
- prop = RNA_def_enum(ot->srna, "layers_select_src", rna_enum_dt_layers_select_src_items, DT_LAYERS_ACTIVE_SRC,
- "Source Layers Selection", "Which layers to transfer, in case of multi-layers types");
- RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_itemf);
-
- prop = RNA_def_enum(ot->srna, "layers_select_dst", rna_enum_dt_layers_select_dst_items, DT_LAYERS_ACTIVE_DST,
- "Destination Layers Matching", "How to match source and destination layers");
- RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_itemf);
-
- prop = RNA_def_enum(ot->srna, "mix_mode", rna_enum_dt_mix_mode_items, CDT_MIX_TRANSFER, "Mix Mode",
- "How to affect destination elements with source values");
- RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_mix_mode_itemf);
- RNA_def_float(ot->srna, "mix_factor", 1.0f, 0.0f, 1.0f, "Mix Factor",
- "Factor to use when applying data to destination (exact behavior depends on mix mode)", 0.0f, 1.0f);
+ PropertyRNA *prop;
+
+ /* Identifiers.*/
+ ot->name = "Transfer Mesh Data";
+ ot->idname = "OBJECT_OT_data_transfer";
+ ot->description =
+ "Transfer data layer(s) (weights, edge sharp, ...) from active to selected meshes";
+
+ /* API callbacks.*/
+ ot->poll = data_transfer_poll;
+ ot->poll_property = data_transfer_poll_property;
+ ot->invoke = WM_menu_invoke;
+ ot->exec = data_transfer_exec;
+ ot->check = data_transfer_check;
+
+ /* Flags.*/
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+
+ /* Properties.*/
+ prop = RNA_def_boolean(ot->srna,
+ "use_reverse_transfer",
+ false,
+ "Reverse Transfer",
+ "Transfer from selected objects to active one");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ RNA_def_boolean(ot->srna,
+ "use_freeze",
+ false,
+ "Freeze Operator",
+ "Prevent changes to settings to re-run the operator, "
+ "handy to change several things at once with heavy geometry");
+
+ /* Data type to transfer. */
+ ot->prop = RNA_def_enum(
+ ot->srna, "data_type", DT_layer_items, 0, "Data Type", "Which data to transfer");
+ RNA_def_boolean(ot->srna,
+ "use_create",
+ true,
+ "Create Data",
+ "Add data layers on destination meshes if needed");
+
+ /* Mapping methods. */
+ RNA_def_enum(ot->srna,
+ "vert_mapping",
+ rna_enum_dt_method_vertex_items,
+ MREMAP_MODE_VERT_NEAREST,
+ "Vertex Mapping",
+ "Method used to map source vertices to destination ones");
+ RNA_def_enum(ot->srna,
+ "edge_mapping",
+ rna_enum_dt_method_edge_items,
+ MREMAP_MODE_EDGE_NEAREST,
+ "Edge Mapping",
+ "Method used to map source edges to destination ones");
+ RNA_def_enum(ot->srna,
+ "loop_mapping",
+ rna_enum_dt_method_loop_items,
+ MREMAP_MODE_LOOP_NEAREST_POLYNOR,
+ "Face Corner Mapping",
+ "Method used to map source faces' corners to destination ones");
+ RNA_def_enum(ot->srna,
+ "poly_mapping",
+ rna_enum_dt_method_poly_items,
+ MREMAP_MODE_POLY_NEAREST,
+ "Face Mapping",
+ "Method used to map source faces to destination ones");
+
+ /* Mapping options and filtering. */
+ RNA_def_boolean(
+ ot->srna,
+ "use_auto_transform",
+ false,
+ "Auto Transform",
+ "Automatically compute transformation to get the best possible match between source and "
+ "destination meshes (WARNING: results will never be as good as manual matching of objects)");
+ RNA_def_boolean(ot->srna,
+ "use_object_transform",
+ true,
+ "Object Transform",
+ "Evaluate source and destination meshes in global space");
+ RNA_def_boolean(ot->srna,
+ "use_max_distance",
+ false,
+ "Only Neighbor Geometry",
+ "Source elements must be closer than given distance from destination one");
+ prop = RNA_def_float(
+ ot->srna,
+ "max_distance",
+ 1.0f,
+ 0.0f,
+ FLT_MAX,
+ "Max Distance",
+ "Maximum allowed distance between source and destination element, for non-topology mappings",
+ 0.0f,
+ 100.0f);
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+ prop = RNA_def_float(
+ ot->srna,
+ "ray_radius",
+ 0.0f,
+ 0.0f,
+ FLT_MAX,
+ "Ray Radius",
+ "'Width' of rays (especially useful when raycasting against vertices or edges)",
+ 0.0f,
+ 10.0f);
+ RNA_def_property_subtype(prop, PROP_DISTANCE);
+ prop = RNA_def_float(
+ ot->srna,
+ "islands_precision",
+ 0.1f,
+ 0.0f,
+ 10.0f,
+ "Islands Precision",
+ "Factor controlling precision of islands handling (the higher, the better the results)",
+ 0.0f,
+ 1.0f);
+ RNA_def_property_subtype(prop, PROP_FACTOR);
+
+ /* How to handle multi-layers types of data. */
+ prop = RNA_def_enum(ot->srna,
+ "layers_select_src",
+ rna_enum_dt_layers_select_src_items,
+ DT_LAYERS_ACTIVE_SRC,
+ "Source Layers Selection",
+ "Which layers to transfer, in case of multi-layers types");
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_itemf);
+
+ prop = RNA_def_enum(ot->srna,
+ "layers_select_dst",
+ rna_enum_dt_layers_select_dst_items,
+ DT_LAYERS_ACTIVE_DST,
+ "Destination Layers Matching",
+ "How to match source and destination layers");
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_itemf);
+
+ prop = RNA_def_enum(ot->srna,
+ "mix_mode",
+ rna_enum_dt_mix_mode_items,
+ CDT_MIX_TRANSFER,
+ "Mix Mode",
+ "How to affect destination elements with source values");
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_mix_mode_itemf);
+ RNA_def_float(
+ ot->srna,
+ "mix_factor",
+ 1.0f,
+ 0.0f,
+ 1.0f,
+ "Mix Factor",
+ "Factor to use when applying data to destination (exact behavior depends on mix mode)",
+ 0.0f,
+ 1.0f);
}
/******************************************************************************/
@@ -617,120 +758,147 @@ void OBJECT_OT_data_transfer(wmOperatorType *ot)
static bool datalayout_transfer_poll(bContext *C)
{
- return (edit_modifier_poll_generic(C, &RNA_DataTransferModifier, (1 << OB_MESH)) || data_transfer_poll(C));
+ return (edit_modifier_poll_generic(C, &RNA_DataTransferModifier, (1 << OB_MESH)) ||
+ data_transfer_poll(C));
}
static int datalayout_transfer_exec(bContext *C, wmOperator *op)
{
- Object *ob_act = ED_object_active_context(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- DataTransferModifierData *dtmd;
-
- dtmd = (DataTransferModifierData *)edit_modifier_property_get(op, ob_act, eModifierType_DataTransfer);
-
- /* If we have a modifier, we transfer data layout from this modifier's source object to active one.
- * Else, we transfer data layout from active object to all selected ones. */
- if (dtmd) {
- Object *ob_src = dtmd->ob_source;
- Object *ob_dst = ob_act;
-
- const bool use_delete = false; /* Never when used from modifier, for now. */
-
- if (!ob_src) {
- return OPERATOR_CANCELLED;
- }
-
- Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
-
- BKE_object_data_transfer_layout(depsgraph, scene_eval, ob_src_eval, ob_dst, dtmd->data_types, use_delete,
- dtmd->layers_select_src, dtmd->layers_select_dst);
-
- DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
- }
- else {
- Object *ob_src = ob_act;
-
- ListBase ctx_objects;
- CollectionPointerLink *ctx_ob_dst;
-
- const int data_type = RNA_enum_get(op->ptr, "data_type");
- const bool use_delete = RNA_boolean_get(op->ptr, "use_delete");
-
- const int layers_src = RNA_enum_get(op->ptr, "layers_select_src");
- const int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst");
- int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0};
- int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0};
- const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type);
-
- if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
- layers_select_src[fromto_idx] = layers_src;
- layers_select_dst[fromto_idx] = layers_dst;
- }
-
- Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
-
- data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, false);
-
- for (ctx_ob_dst = ctx_objects.first; ctx_ob_dst; ctx_ob_dst = ctx_ob_dst->next) {
- Object *ob_dst = ctx_ob_dst->ptr.data;
- if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, false)) {
- BKE_object_data_transfer_layout(depsgraph, scene_eval, ob_src_eval, ob_dst, data_type, use_delete,
- layers_select_src, layers_select_dst);
- }
-
- DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
- }
-
- BLI_freelistN(&ctx_objects);
- }
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
-
- return OPERATOR_FINISHED;
+ Object *ob_act = ED_object_active_context(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ DataTransferModifierData *dtmd;
+
+ dtmd = (DataTransferModifierData *)edit_modifier_property_get(
+ op, ob_act, eModifierType_DataTransfer);
+
+ /* If we have a modifier, we transfer data layout from this modifier's source object to active one.
+ * Else, we transfer data layout from active object to all selected ones. */
+ if (dtmd) {
+ Object *ob_src = dtmd->ob_source;
+ Object *ob_dst = ob_act;
+
+ const bool use_delete = false; /* Never when used from modifier, for now. */
+
+ if (!ob_src) {
+ return OPERATOR_CANCELLED;
+ }
+
+ Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
+
+ BKE_object_data_transfer_layout(depsgraph,
+ scene_eval,
+ ob_src_eval,
+ ob_dst,
+ dtmd->data_types,
+ use_delete,
+ dtmd->layers_select_src,
+ dtmd->layers_select_dst);
+
+ DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
+ }
+ else {
+ Object *ob_src = ob_act;
+
+ ListBase ctx_objects;
+ CollectionPointerLink *ctx_ob_dst;
+
+ const int data_type = RNA_enum_get(op->ptr, "data_type");
+ const bool use_delete = RNA_boolean_get(op->ptr, "use_delete");
+
+ const int layers_src = RNA_enum_get(op->ptr, "layers_select_src");
+ const int layers_dst = RNA_enum_get(op->ptr, "layers_select_dst");
+ int layers_select_src[DT_MULTILAYER_INDEX_MAX] = {0};
+ int layers_select_dst[DT_MULTILAYER_INDEX_MAX] = {0};
+ const int fromto_idx = BKE_object_data_transfer_dttype_to_srcdst_index(data_type);
+
+ if (fromto_idx != DT_MULTILAYER_INDEX_INVALID) {
+ layers_select_src[fromto_idx] = layers_src;
+ layers_select_dst[fromto_idx] = layers_dst;
+ }
+
+ Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
+
+ data_transfer_exec_preprocess_objects(C, op, ob_src, &ctx_objects, false);
+
+ for (ctx_ob_dst = ctx_objects.first; ctx_ob_dst; ctx_ob_dst = ctx_ob_dst->next) {
+ Object *ob_dst = ctx_ob_dst->ptr.data;
+ if (data_transfer_exec_is_object_valid(op, ob_src, ob_dst, false)) {
+ BKE_object_data_transfer_layout(depsgraph,
+ scene_eval,
+ ob_src_eval,
+ ob_dst,
+ data_type,
+ use_delete,
+ layers_select_src,
+ layers_select_dst);
+ }
+
+ DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
+ }
+
+ BLI_freelistN(&ctx_objects);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
+
+ return OPERATOR_FINISHED;
}
static int datalayout_transfer_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (edit_modifier_invoke_properties(C, op)) {
- return datalayout_transfer_exec(C, op);
- }
- else {
- return WM_menu_invoke(C, op, event);
- }
+ if (edit_modifier_invoke_properties(C, op)) {
+ return datalayout_transfer_exec(C, op);
+ }
+ else {
+ return WM_menu_invoke(C, op, event);
+ }
}
void OBJECT_OT_datalayout_transfer(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- ot->name = "Transfer Mesh Data Layout";
- ot->description = "Transfer layout of data layer(s) from active to selected meshes";
- ot->idname = "OBJECT_OT_datalayout_transfer";
-
- ot->poll = datalayout_transfer_poll;
- ot->poll_property = data_transfer_poll_property;
- ot->invoke = datalayout_transfer_invoke;
- ot->exec = datalayout_transfer_exec;
- ot->check = data_transfer_check;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
-
- /* Properties.*/
- edit_modifier_properties(ot);
-
- /* Data type to transfer. */
- ot->prop = RNA_def_enum(ot->srna, "data_type", DT_layer_items, 0, "Data Type", "Which data to transfer");
- RNA_def_boolean(ot->srna, "use_delete", false, "Exact Match",
- "Also delete some data layers from destination if necessary, so that it matches exactly source");
-
- /* How to handle multi-layers types of data. */
- prop = RNA_def_enum(ot->srna, "layers_select_src", rna_enum_dt_layers_select_src_items, DT_LAYERS_ACTIVE_SRC,
- "Source Layers Selection", "Which layers to transfer, in case of multi-layers types");
- RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_src_itemf);
-
- prop = RNA_def_enum(ot->srna, "layers_select_dst", rna_enum_dt_layers_select_dst_items, DT_LAYERS_ACTIVE_DST,
- "Destination Layers Matching", "How to match source and destination layers");
- RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_dst_itemf);
+ PropertyRNA *prop;
+
+ ot->name = "Transfer Mesh Data Layout";
+ ot->description = "Transfer layout of data layer(s) from active to selected meshes";
+ ot->idname = "OBJECT_OT_datalayout_transfer";
+
+ ot->poll = datalayout_transfer_poll;
+ ot->poll_property = data_transfer_poll_property;
+ ot->invoke = datalayout_transfer_invoke;
+ ot->exec = datalayout_transfer_exec;
+ ot->check = data_transfer_check;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+
+ /* Properties.*/
+ edit_modifier_properties(ot);
+
+ /* Data type to transfer. */
+ ot->prop = RNA_def_enum(
+ ot->srna, "data_type", DT_layer_items, 0, "Data Type", "Which data to transfer");
+ RNA_def_boolean(ot->srna,
+ "use_delete",
+ false,
+ "Exact Match",
+ "Also delete some data layers from destination if necessary, so that it matches "
+ "exactly source");
+
+ /* How to handle multi-layers types of data. */
+ prop = RNA_def_enum(ot->srna,
+ "layers_select_src",
+ rna_enum_dt_layers_select_src_items,
+ DT_LAYERS_ACTIVE_SRC,
+ "Source Layers Selection",
+ "Which layers to transfer, in case of multi-layers types");
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_src_itemf);
+
+ prop = RNA_def_enum(ot->srna,
+ "layers_select_dst",
+ rna_enum_dt_layers_select_dst_items,
+ DT_LAYERS_ACTIVE_DST,
+ "Destination Layers Matching",
+ "How to match source and destination layers");
+ RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, dt_layers_select_dst_itemf);
}
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index ce1a7306773..4e532b0ab41 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -27,7 +27,7 @@
#include <time.h>
#include <float.h>
#include <ctype.h>
-#include <stddef.h> //for offsetof
+#include <stddef.h> //for offsetof
#include "MEM_guardedalloc.h"
@@ -114,285 +114,298 @@
/* prototypes */
typedef struct MoveToCollectionData MoveToCollectionData;
-static void move_to_collection_menus_items(struct uiLayout *layout, struct MoveToCollectionData *menu);
+static void move_to_collection_menus_items(struct uiLayout *layout,
+ struct MoveToCollectionData *menu);
/* ************* XXX **************** */
-static void error(const char *UNUSED(arg)) {}
+static void error(const char *UNUSED(arg))
+{
+}
/* port over here */
-static void error_libdata(void) {}
+static void error_libdata(void)
+{
+}
Object *ED_object_context(bContext *C)
{
- return CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+ return CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
}
/* find the correct active object per context
* note: context can be NULL when called from a enum with PROP_ENUM_NO_CONTEXT */
Object *ED_object_active_context(bContext *C)
{
- Object *ob = NULL;
- if (C) {
- ob = ED_object_context(C);
- if (!ob) ob = CTX_data_active_object(C);
- }
- return ob;
+ Object *ob = NULL;
+ if (C) {
+ ob = ED_object_context(C);
+ if (!ob)
+ ob = CTX_data_active_object(C);
+ }
+ return ob;
}
/* ********************** object hiding *************************** */
static bool object_hide_poll(bContext *C)
{
- if (CTX_wm_space_outliner(C) != NULL) {
- return ED_outliner_collections_editor_poll(C);
- }
- else {
- return ED_operator_view3d_active(C);
- }
+ if (CTX_wm_space_outliner(C) != NULL) {
+ return ED_outliner_collections_editor_poll(C);
+ }
+ else {
+ return ED_operator_view3d_active(C);
+ }
}
static int object_hide_view_clear_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const bool select = RNA_boolean_get(op->ptr, "select");
- bool changed = false;
-
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (base->flag & BASE_HIDDEN) {
- base->flag &= ~BASE_HIDDEN;
- changed = true;
-
- if (select) {
- /* We cannot call `ED_object_base_select` because
- * base is not selectable while it is hidden. */
- base->flag |= BASE_SELECTED;
- BKE_scene_object_base_flag_sync_from_base(base);
- }
- }
- }
-
- if (!changed) {
- return OPERATOR_CANCELLED;
- }
-
- BKE_layer_collection_sync(scene, view_layer);
- DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool select = RNA_boolean_get(op->ptr, "select");
+ bool changed = false;
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->flag & BASE_HIDDEN) {
+ base->flag &= ~BASE_HIDDEN;
+ changed = true;
+
+ if (select) {
+ /* We cannot call `ED_object_base_select` because
+ * base is not selectable while it is hidden. */
+ base->flag |= BASE_SELECTED;
+ BKE_scene_object_base_flag_sync_from_base(base);
+ }
+ }
+ }
+
+ if (!changed) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_hide_view_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Show Hidden Objects";
- ot->description = "Reveal temporarily hidden objects";
- ot->idname = "OBJECT_OT_hide_view_clear";
+ /* identifiers */
+ ot->name = "Show Hidden Objects";
+ ot->description = "Reveal temporarily hidden objects";
+ ot->idname = "OBJECT_OT_hide_view_clear";
- /* api callbacks */
- ot->exec = object_hide_view_clear_exec;
- ot->poll = object_hide_poll;
+ /* api callbacks */
+ ot->exec = object_hide_view_clear_exec;
+ ot->poll = object_hide_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- PropertyRNA *prop = RNA_def_boolean(ot->srna, "select", true, "Select", "");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ PropertyRNA *prop = RNA_def_boolean(ot->srna, "select", true, "Select", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
}
static int object_hide_view_set_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const bool unselected = RNA_boolean_get(op->ptr, "unselected");
- bool changed = false;
-
- /* Hide selected or unselected objects. */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (!(base->flag & BASE_VISIBLE)) {
- continue;
- }
-
- if (!unselected) {
- if (base->flag & BASE_SELECTED) {
- ED_object_base_select(base, BA_DESELECT);
- base->flag |= BASE_HIDDEN;
- changed = true;
- }
- }
- else {
- if (!(base->flag & BASE_SELECTED)) {
- ED_object_base_select(base, BA_DESELECT);
- base->flag |= BASE_HIDDEN;
- changed = true;
- }
- }
- }
- if (!changed) {
- return OPERATOR_CANCELLED;
- }
-
- BKE_layer_collection_sync(scene, view_layer);
- DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool unselected = RNA_boolean_get(op->ptr, "unselected");
+ bool changed = false;
+
+ /* Hide selected or unselected objects. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (!(base->flag & BASE_VISIBLE)) {
+ continue;
+ }
+
+ if (!unselected) {
+ if (base->flag & BASE_SELECTED) {
+ ED_object_base_select(base, BA_DESELECT);
+ base->flag |= BASE_HIDDEN;
+ changed = true;
+ }
+ }
+ else {
+ if (!(base->flag & BASE_SELECTED)) {
+ ED_object_base_select(base, BA_DESELECT);
+ base->flag |= BASE_HIDDEN;
+ changed = true;
+ }
+ }
+ }
+ if (!changed) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_hide_view_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hide Objects";
- ot->description = "Temporarily hide objects from the viewport";
- ot->idname = "OBJECT_OT_hide_view_set";
-
- /* api callbacks */
- ot->exec = object_hide_view_set_exec;
- ot->poll = object_hide_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- PropertyRNA *prop;
- prop = RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ /* identifiers */
+ ot->name = "Hide Objects";
+ ot->description = "Temporarily hide objects from the viewport";
+ ot->idname = "OBJECT_OT_hide_view_set";
+
+ /* api callbacks */
+ ot->exec = object_hide_view_set_exec;
+ ot->poll = object_hide_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ PropertyRNA *prop;
+ prop = RNA_def_boolean(
+ ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
}
static int object_hide_collection_exec(bContext *C, wmOperator *op)
{
- wmWindow *win = CTX_wm_window(C);
+ wmWindow *win = CTX_wm_window(C);
- int index = RNA_int_get(op->ptr, "collection_index");
- const bool extend = (win->eventstate->shift != 0) ||
- RNA_boolean_get(op->ptr, "toggle");
+ int index = RNA_int_get(op->ptr, "collection_index");
+ const bool extend = (win->eventstate->shift != 0) || RNA_boolean_get(op->ptr, "toggle");
- if (win->eventstate->alt != 0) {
- index += 10;
- }
+ if (win->eventstate->alt != 0) {
+ index += 10;
+ }
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- LayerCollection *lc = BKE_layer_collection_from_index(view_layer, index);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ LayerCollection *lc = BKE_layer_collection_from_index(view_layer, index);
- if (!lc) {
- return OPERATOR_CANCELLED;
- }
+ if (!lc) {
+ return OPERATOR_CANCELLED;
+ }
- DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+ DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
- if (BKE_layer_collection_isolate(scene, view_layer, lc, extend)) {
- DEG_relations_tag_update(CTX_data_main(C));
- }
+ if (BKE_layer_collection_isolate(scene, view_layer, lc, extend)) {
+ DEG_relations_tag_update(CTX_data_main(C));
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
#define COLLECTION_INVALID_INDEX -1
void ED_collection_hide_menu_draw(const bContext *C, uiLayout *layout)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- LayerCollection *lc_scene = view_layer->layer_collections.first;
-
- uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN);
-
- for (LayerCollection *lc = lc_scene->layer_collections.first; lc; lc = lc->next) {
- int index = BKE_layer_collection_findindex(view_layer, lc);
- uiLayout *row = uiLayoutRow(layout, false);
-
- if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
- continue;
- }
-
- if (lc->collection->flag & COLLECTION_RESTRICT_VIEW) {
- continue;
- }
-
- int icon = ICON_NONE;
- if (BKE_layer_collection_has_selected_objects(view_layer, lc)) {
- icon = ICON_LAYER_ACTIVE;
- }
- else if (lc->runtime_flag & LAYER_COLLECTION_HAS_OBJECTS) {
- icon = ICON_LAYER_USED;
- }
-
- uiItemIntO(row,
- lc->collection->id.name + 2,
- icon,
- "OBJECT_OT_hide_collection",
- "collection_index",
- index);
- }
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ LayerCollection *lc_scene = view_layer->layer_collections.first;
+
+ uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN);
+
+ for (LayerCollection *lc = lc_scene->layer_collections.first; lc; lc = lc->next) {
+ int index = BKE_layer_collection_findindex(view_layer, lc);
+ uiLayout *row = uiLayoutRow(layout, false);
+
+ if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
+ continue;
+ }
+
+ if (lc->collection->flag & COLLECTION_RESTRICT_VIEW) {
+ continue;
+ }
+
+ int icon = ICON_NONE;
+ if (BKE_layer_collection_has_selected_objects(view_layer, lc)) {
+ icon = ICON_LAYER_ACTIVE;
+ }
+ else if (lc->runtime_flag & LAYER_COLLECTION_HAS_OBJECTS) {
+ icon = ICON_LAYER_USED;
+ }
+
+ uiItemIntO(row,
+ lc->collection->id.name + 2,
+ icon,
+ "OBJECT_OT_hide_collection",
+ "collection_index",
+ index);
+ }
}
static int object_hide_collection_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- /* Immediately execute if collection index was specified. */
- int index = RNA_int_get(op->ptr, "collection_index");
- if (index != COLLECTION_INVALID_INDEX) {
- return object_hide_collection_exec(C, op);
- }
+ /* Immediately execute if collection index was specified. */
+ int index = RNA_int_get(op->ptr, "collection_index");
+ if (index != COLLECTION_INVALID_INDEX) {
+ return object_hide_collection_exec(C, op);
+ }
- /* Open popup menu. */
- const char *title = CTX_IFACE_(op->type->translation_context, op->type->name);
- uiPopupMenu *pup = UI_popup_menu_begin(C, title, ICON_GROUP);
- uiLayout *layout = UI_popup_menu_layout(pup);
+ /* Open popup menu. */
+ const char *title = CTX_IFACE_(op->type->translation_context, op->type->name);
+ uiPopupMenu *pup = UI_popup_menu_begin(C, title, ICON_GROUP);
+ uiLayout *layout = UI_popup_menu_layout(pup);
- ED_collection_hide_menu_draw(C, layout);
+ ED_collection_hide_menu_draw(C, layout);
- UI_popup_menu_end(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
void OBJECT_OT_hide_collection(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hide Collection";
- ot->description = "Show only objects in collection (Shift to extend)";
- ot->idname = "OBJECT_OT_hide_collection";
-
- /* api callbacks */
- ot->exec = object_hide_collection_exec;
- ot->invoke = object_hide_collection_invoke;
- ot->poll = ED_operator_view3d_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* Properties. */
- PropertyRNA *prop;
- prop = RNA_def_int(ot->srna, "collection_index", COLLECTION_INVALID_INDEX, COLLECTION_INVALID_INDEX, INT_MAX,
- "Collection Index", "Index of the collection to change visibility", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
- prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle visibility");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ /* identifiers */
+ ot->name = "Hide Collection";
+ ot->description = "Show only objects in collection (Shift to extend)";
+ ot->idname = "OBJECT_OT_hide_collection";
+
+ /* api callbacks */
+ ot->exec = object_hide_collection_exec;
+ ot->invoke = object_hide_collection_invoke;
+ ot->poll = ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* Properties. */
+ PropertyRNA *prop;
+ prop = RNA_def_int(ot->srna,
+ "collection_index",
+ COLLECTION_INVALID_INDEX,
+ COLLECTION_INVALID_INDEX,
+ INT_MAX,
+ "Collection Index",
+ "Index of the collection to change visibility",
+ 0,
+ INT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle visibility");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
}
/* ******************* toggle editmode operator ***************** */
static bool mesh_needs_keyindex(Main *bmain, const Mesh *me)
{
- if (me->key) {
- return false; /* will be added */
- }
-
- for (const Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
- if ((ob->parent) && (ob->parent->data == me) && ELEM(ob->partype, PARVERT1, PARVERT3)) {
- return true;
- }
- if (ob->data == me) {
- for (const ModifierData *md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Hook) {
- return true;
- }
- }
- }
- }
- return false;
+ if (me->key) {
+ return false; /* will be added */
+ }
+
+ for (const Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
+ if ((ob->parent) && (ob->parent->data == me) && ELEM(ob->partype, PARVERT1, PARVERT3)) {
+ return true;
+ }
+ if (ob->data == me) {
+ for (const ModifierData *md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Hook) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
}
/**
@@ -401,96 +414,96 @@ static bool mesh_needs_keyindex(Main *bmain, const Mesh *me)
*/
static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool freedata)
{
- if (obedit == NULL) {
- return false;
- }
-
- if (obedit->type == OB_MESH) {
- Mesh *me = obedit->data;
- if (me->edit_mesh == NULL) {
- return false;
- }
-
- if (me->edit_mesh->bm->totvert > MESH_MAX_VERTS) {
- error("Too many vertices");
- return false;
- }
-
- EDBM_mesh_load(bmain, obedit);
-
- if (freedata) {
- EDBM_mesh_free(me->edit_mesh);
- MEM_freeN(me->edit_mesh);
- me->edit_mesh = NULL;
- }
- /* will be recalculated as needed. */
- {
- ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
- ED_mesh_mirror_topo_table(NULL, NULL, 'e');
- }
- }
- else if (obedit->type == OB_ARMATURE) {
- const bArmature *arm = obedit->data;
- if (arm->edbo == NULL) {
- return false;
- }
- ED_armature_from_edit(bmain, obedit->data);
- if (freedata) {
- ED_armature_edit_free(obedit->data);
- }
- /* TODO(sergey): Pose channels might have been changed, so need
- * to inform dependency graph about this. But is it really the
- * best place to do this?
- */
- DEG_relations_tag_update(bmain);
- }
- else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
- const Curve *cu = obedit->data;
- if (cu->editnurb == NULL) {
- return false;
- }
- ED_curve_editnurb_load(bmain, obedit);
- if (freedata) {
- ED_curve_editnurb_free(obedit);
- }
- }
- else if (obedit->type == OB_FONT) {
- const Curve *cu = obedit->data;
- if (cu->editfont == NULL) {
- return false;
- }
- ED_curve_editfont_load(obedit);
- if (freedata) {
- ED_curve_editfont_free(obedit);
- }
- }
- else if (obedit->type == OB_LATTICE) {
- const Lattice *lt = obedit->data;
- if (lt->editlatt == NULL) {
- return false;
- }
- BKE_editlattice_load(obedit);
- if (freedata) {
- BKE_editlattice_free(obedit);
- }
- }
- else if (obedit->type == OB_MBALL) {
- const MetaBall *mb = obedit->data;
- if (mb->editelems == NULL) {
- return false;
- }
- ED_mball_editmball_load(obedit);
- if (freedata) {
- ED_mball_editmball_free(obedit);
- }
- }
-
- return true;
+ if (obedit == NULL) {
+ return false;
+ }
+
+ if (obedit->type == OB_MESH) {
+ Mesh *me = obedit->data;
+ if (me->edit_mesh == NULL) {
+ return false;
+ }
+
+ if (me->edit_mesh->bm->totvert > MESH_MAX_VERTS) {
+ error("Too many vertices");
+ return false;
+ }
+
+ EDBM_mesh_load(bmain, obedit);
+
+ if (freedata) {
+ EDBM_mesh_free(me->edit_mesh);
+ MEM_freeN(me->edit_mesh);
+ me->edit_mesh = NULL;
+ }
+ /* will be recalculated as needed. */
+ {
+ ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
+ ED_mesh_mirror_topo_table(NULL, NULL, 'e');
+ }
+ }
+ else if (obedit->type == OB_ARMATURE) {
+ const bArmature *arm = obedit->data;
+ if (arm->edbo == NULL) {
+ return false;
+ }
+ ED_armature_from_edit(bmain, obedit->data);
+ if (freedata) {
+ ED_armature_edit_free(obedit->data);
+ }
+ /* TODO(sergey): Pose channels might have been changed, so need
+ * to inform dependency graph about this. But is it really the
+ * best place to do this?
+ */
+ DEG_relations_tag_update(bmain);
+ }
+ else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
+ const Curve *cu = obedit->data;
+ if (cu->editnurb == NULL) {
+ return false;
+ }
+ ED_curve_editnurb_load(bmain, obedit);
+ if (freedata) {
+ ED_curve_editnurb_free(obedit);
+ }
+ }
+ else if (obedit->type == OB_FONT) {
+ const Curve *cu = obedit->data;
+ if (cu->editfont == NULL) {
+ return false;
+ }
+ ED_curve_editfont_load(obedit);
+ if (freedata) {
+ ED_curve_editfont_free(obedit);
+ }
+ }
+ else if (obedit->type == OB_LATTICE) {
+ const Lattice *lt = obedit->data;
+ if (lt->editlatt == NULL) {
+ return false;
+ }
+ BKE_editlattice_load(obedit);
+ if (freedata) {
+ BKE_editlattice_free(obedit);
+ }
+ }
+ else if (obedit->type == OB_MBALL) {
+ const MetaBall *mb = obedit->data;
+ if (mb->editelems == NULL) {
+ return false;
+ }
+ ED_mball_editmball_load(obedit);
+ if (freedata) {
+ ED_mball_editmball_free(obedit);
+ }
+ }
+
+ return true;
}
bool ED_object_editmode_load(Main *bmain, Object *obedit)
{
- return ED_object_editmode_load_ex(bmain, obedit, false);
+ return ED_object_editmode_load_ex(bmain, obedit, false);
}
/**
@@ -499,387 +512,379 @@ bool ED_object_editmode_load(Main *bmain, Object *obedit)
*/
bool ED_object_editmode_exit_ex(Main *bmain, Scene *scene, Object *obedit, int flag)
{
- const bool freedata = (flag & EM_FREEDATA) != 0;
-
- if (ED_object_editmode_load_ex(bmain, obedit, freedata) == false) {
- /* in rare cases (background mode) its possible active object
- * is flagged for editmode, without 'obedit' being set [#35489] */
- if (UNLIKELY(obedit && obedit->mode & OB_MODE_EDIT)) {
- obedit->mode &= ~OB_MODE_EDIT;
- }
- return true;
- }
-
- /* freedata only 0 now on file saves and render */
- if (freedata) {
- ListBase pidlist;
- PTCacheID *pid;
-
- /* flag object caches as outdated */
- BKE_ptcache_ids_from_object(&pidlist, obedit, scene, 0);
- for (pid = pidlist.first; pid; pid = pid->next) {
- /* particles don't need reset on geometry change */
- if (pid->type != PTCACHE_TYPE_PARTICLES) {
- pid->cache->flag |= PTCACHE_OUTDATED;
- }
- }
- BLI_freelistN(&pidlist);
-
- BKE_particlesystem_reset_all(obedit);
- BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_OUTDATED);
-
- /* also flush ob recalc, doesn't take much overhead, but used for particles */
- DEG_id_tag_update(&obedit->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
-
- WM_main_add_notifier(NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
-
- obedit->mode &= ~OB_MODE_EDIT;
- }
-
- return (obedit->mode & OB_MODE_EDIT) == 0;
+ const bool freedata = (flag & EM_FREEDATA) != 0;
+
+ if (ED_object_editmode_load_ex(bmain, obedit, freedata) == false) {
+ /* in rare cases (background mode) its possible active object
+ * is flagged for editmode, without 'obedit' being set [#35489] */
+ if (UNLIKELY(obedit && obedit->mode & OB_MODE_EDIT)) {
+ obedit->mode &= ~OB_MODE_EDIT;
+ }
+ return true;
+ }
+
+ /* freedata only 0 now on file saves and render */
+ if (freedata) {
+ ListBase pidlist;
+ PTCacheID *pid;
+
+ /* flag object caches as outdated */
+ BKE_ptcache_ids_from_object(&pidlist, obedit, scene, 0);
+ for (pid = pidlist.first; pid; pid = pid->next) {
+ /* particles don't need reset on geometry change */
+ if (pid->type != PTCACHE_TYPE_PARTICLES) {
+ pid->cache->flag |= PTCACHE_OUTDATED;
+ }
+ }
+ BLI_freelistN(&pidlist);
+
+ BKE_particlesystem_reset_all(obedit);
+ BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_OUTDATED);
+
+ /* also flush ob recalc, doesn't take much overhead, but used for particles */
+ DEG_id_tag_update(&obedit->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+
+ WM_main_add_notifier(NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
+
+ obedit->mode &= ~OB_MODE_EDIT;
+ }
+
+ return (obedit->mode & OB_MODE_EDIT) == 0;
}
bool ED_object_editmode_exit(bContext *C, int flag)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *obedit = CTX_data_edit_object(C);
- return ED_object_editmode_exit_ex(bmain, scene, obedit, flag);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = CTX_data_edit_object(C);
+ return ED_object_editmode_exit_ex(bmain, scene, obedit, flag);
}
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)) {
- return false;
- }
-
- /* this checks actual object->data, for cases when other scenes have it in editmode context */
- if (BKE_object_is_in_editmode(ob)) {
- return true;
- }
-
- if (BKE_object_obdata_is_libdata(ob)) {
- error_libdata();
- return false;
- }
-
- ob->restore_mode = ob->mode;
-
- ob->mode = OB_MODE_EDIT;
-
- if (ob->type == OB_MESH) {
- BMEditMesh *em;
- ok = 1;
-
- const bool use_key_index = mesh_needs_keyindex(bmain, ob->data);
-
- EDBM_mesh_make(ob, scene->toolsettings->selectmode, use_key_index);
-
- em = BKE_editmesh_from_object(ob);
- if (LIKELY(em)) {
- /* order doesn't matter */
- EDBM_mesh_normals_update(em);
- BKE_editmesh_tessface_calc(em);
- }
-
- WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MESH, NULL);
- }
- else if (ob->type == OB_ARMATURE) {
- ok = 1;
- ED_armature_to_edit(ob->data);
- /* to ensure all goes in restposition and without striding */
-
- /* XXX: should this be ID_RECALC_GEOMETRY? */
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
-
- WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_ARMATURE, scene);
- }
- else if (ob->type == OB_FONT) {
- ok = 1;
- ED_curve_editfont_make(ob);
-
- WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_TEXT, scene);
- }
- else if (ob->type == OB_MBALL) {
- ok = 1;
- ED_mball_editmball_make(ob);
-
- WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MBALL, scene);
- }
- else if (ob->type == OB_LATTICE) {
- ok = 1;
- BKE_editlattice_make(ob);
-
- WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_LATTICE, scene);
- }
- else if (ob->type == OB_SURF || ob->type == OB_CURVE) {
- ok = 1;
- ED_curve_editnurb_make(ob);
-
- WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_CURVE, scene);
- }
-
- if (ok) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- else {
- if ((flag & EM_NO_CONTEXT) == 0) {
- ob->mode &= ~OB_MODE_EDIT;
- }
- WM_main_add_notifier(NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
- }
-
- return (ob->mode & OB_MODE_EDIT) != 0;
+ bool ok = false;
+
+ if (ELEM(NULL, ob, ob->data) || ID_IS_LINKED(ob)) {
+ return false;
+ }
+
+ /* this checks actual object->data, for cases when other scenes have it in editmode context */
+ if (BKE_object_is_in_editmode(ob)) {
+ return true;
+ }
+
+ if (BKE_object_obdata_is_libdata(ob)) {
+ error_libdata();
+ return false;
+ }
+
+ ob->restore_mode = ob->mode;
+
+ ob->mode = OB_MODE_EDIT;
+
+ if (ob->type == OB_MESH) {
+ BMEditMesh *em;
+ ok = 1;
+
+ const bool use_key_index = mesh_needs_keyindex(bmain, ob->data);
+
+ EDBM_mesh_make(ob, scene->toolsettings->selectmode, use_key_index);
+
+ em = BKE_editmesh_from_object(ob);
+ if (LIKELY(em)) {
+ /* order doesn't matter */
+ EDBM_mesh_normals_update(em);
+ BKE_editmesh_tessface_calc(em);
+ }
+
+ WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MESH, NULL);
+ }
+ else if (ob->type == OB_ARMATURE) {
+ ok = 1;
+ ED_armature_to_edit(ob->data);
+ /* to ensure all goes in restposition and without striding */
+
+ /* XXX: should this be ID_RECALC_GEOMETRY? */
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+
+ WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_ARMATURE, scene);
+ }
+ else if (ob->type == OB_FONT) {
+ ok = 1;
+ ED_curve_editfont_make(ob);
+
+ WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_TEXT, scene);
+ }
+ else if (ob->type == OB_MBALL) {
+ ok = 1;
+ ED_mball_editmball_make(ob);
+
+ WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MBALL, scene);
+ }
+ else if (ob->type == OB_LATTICE) {
+ ok = 1;
+ BKE_editlattice_make(ob);
+
+ WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_LATTICE, scene);
+ }
+ else if (ob->type == OB_SURF || ob->type == OB_CURVE) {
+ ok = 1;
+ ED_curve_editnurb_make(ob);
+
+ WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_CURVE, scene);
+ }
+
+ if (ok) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ else {
+ if ((flag & EM_NO_CONTEXT) == 0) {
+ ob->mode &= ~OB_MODE_EDIT;
+ }
+ WM_main_add_notifier(NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
+ }
+
+ return (ob->mode & OB_MODE_EDIT) != 0;
}
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;
- }
- return ED_object_editmode_enter_ex(bmain, scene, ob, 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;
+ }
+ return ED_object_editmode_enter_ex(bmain, scene, ob, flag);
}
static int editmode_toggle_exec(bContext *C, wmOperator *op)
{
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- const int mode_flag = OB_MODE_EDIT;
- const bool is_mode_set = (CTX_data_edit_object(C) != NULL);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- Object *obact = OBACT(view_layer);
-
- if (!is_mode_set) {
- if (!ED_object_mode_compat_set(C, obact, mode_flag, op->reports)) {
- return OPERATOR_CANCELLED;
- }
- }
-
- if (!is_mode_set) {
- ED_object_editmode_enter(C, 0);
- if (obact->mode & mode_flag) {
- FOREACH_SELECTED_OBJECT_BEGIN(view_layer, v3d, ob)
- {
- if ((ob != obact) && (ob->type == obact->type)) {
- ED_object_editmode_enter_ex(bmain, scene, ob, EM_NO_CONTEXT);
- }
- }
- FOREACH_SELECTED_OBJECT_END;
- }
- }
- else {
- ED_object_editmode_exit(C, EM_FREEDATA);
- if ((obact->mode & mode_flag) == 0) {
- FOREACH_OBJECT_BEGIN(view_layer, ob)
- {
- if ((ob != obact) && (ob->type == obact->type)) {
- ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
- }
- }
- FOREACH_OBJECT_END;
- }
- }
-
- ED_space_image_uv_sculpt_update(bmain, CTX_wm_manager(C), scene);
-
- WM_msg_publish_rna_prop(mbus, &obact->id, obact, Object, mode);
-
- if (G.background == false) {
- WM_toolsystem_update_from_context_view3d(C);
- }
-
- return OPERATOR_FINISHED;
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ const int mode_flag = OB_MODE_EDIT;
+ const bool is_mode_set = (CTX_data_edit_object(C) != NULL);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Object *obact = OBACT(view_layer);
+
+ if (!is_mode_set) {
+ if (!ED_object_mode_compat_set(C, obact, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ if (!is_mode_set) {
+ ED_object_editmode_enter(C, 0);
+ if (obact->mode & mode_flag) {
+ FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) {
+ if ((ob != obact) && (ob->type == obact->type)) {
+ ED_object_editmode_enter_ex(bmain, scene, ob, EM_NO_CONTEXT);
+ }
+ }
+ FOREACH_SELECTED_OBJECT_END;
+ }
+ }
+ else {
+ ED_object_editmode_exit(C, EM_FREEDATA);
+ if ((obact->mode & mode_flag) == 0) {
+ FOREACH_OBJECT_BEGIN (view_layer, ob) {
+ if ((ob != obact) && (ob->type == obact->type)) {
+ ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
+ }
+ }
+ FOREACH_OBJECT_END;
+ }
+ }
+
+ ED_space_image_uv_sculpt_update(bmain, CTX_wm_manager(C), scene);
+
+ WM_msg_publish_rna_prop(mbus, &obact->id, obact, Object, mode);
+
+ if (G.background == false) {
+ WM_toolsystem_update_from_context_view3d(C);
+ }
+
+ return OPERATOR_FINISHED;
}
static bool editmode_toggle_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- /* covers proxies too */
- if (ELEM(NULL, ob, ob->data) || ID_IS_LINKED(ob->data))
- return 0;
+ /* covers proxies too */
+ if (ELEM(NULL, ob, ob->data) || ID_IS_LINKED(ob->data))
+ return 0;
- /* if hidden but in edit mode, we still display */
- if ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT)) {
- return 0;
- }
+ /* if hidden but in edit mode, we still display */
+ if ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT)) {
+ return 0;
+ }
- return OB_TYPE_SUPPORT_EDITMODE(ob->type);
+ return OB_TYPE_SUPPORT_EDITMODE(ob->type);
}
void OBJECT_OT_editmode_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Editmode";
- ot->description = "Toggle object's editmode";
- ot->idname = "OBJECT_OT_editmode_toggle";
+ /* identifiers */
+ ot->name = "Toggle Editmode";
+ ot->description = "Toggle object's editmode";
+ ot->idname = "OBJECT_OT_editmode_toggle";
- /* api callbacks */
- ot->exec = editmode_toggle_exec;
- ot->poll = editmode_toggle_poll;
+ /* api callbacks */
+ ot->exec = editmode_toggle_exec;
+ ot->poll = editmode_toggle_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* *************************** */
static int posemode_exec(bContext *C, wmOperator *op)
{
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- Base *base = CTX_data_active_base(C);
-
- /* If the base is NULL it means we have an active object, but the object itself is hidden. */
- if (base == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- Object *obact = base->object;
- const int mode_flag = OB_MODE_POSE;
- bool is_mode_set = (obact->mode & mode_flag) != 0;
-
- if (!is_mode_set) {
- if (!ED_object_mode_compat_set(C, obact, mode_flag, op->reports)) {
- return OPERATOR_CANCELLED;
- }
- }
-
- if (obact->type != OB_ARMATURE) {
- return OPERATOR_PASS_THROUGH;
- }
-
- if (obact == CTX_data_edit_object(C)) {
- ED_object_editmode_exit(C, EM_FREEDATA);
- is_mode_set = false;
- }
-
- if (is_mode_set) {
- bool ok = ED_object_posemode_exit(C, obact);
- if (ok) {
- struct Main *bmain = CTX_data_main(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- FOREACH_OBJECT_BEGIN(view_layer, ob)
- {
- if ((ob != obact) &&
- (ob->type == OB_ARMATURE) &&
- (ob->mode & mode_flag))
- {
- ED_object_posemode_exit_ex(bmain, ob);
- }
- }
- FOREACH_OBJECT_END;
- }
- }
- else {
- bool ok = ED_object_posemode_enter(C, obact);
- if (ok) {
- struct Main *bmain = CTX_data_main(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- FOREACH_SELECTED_OBJECT_BEGIN(view_layer, v3d, ob)
- {
- if ((ob != obact) &&
- (ob->type == OB_ARMATURE) &&
- (ob->mode == OB_MODE_OBJECT) &&
- (!ID_IS_LINKED(ob)))
- {
- ED_object_posemode_enter_ex(bmain, ob);
- }
- }
- FOREACH_SELECTED_OBJECT_END;
- }
- }
-
- WM_msg_publish_rna_prop(mbus, &obact->id, obact, Object, mode);
-
- if (G.background == false) {
- WM_toolsystem_update_from_context_view3d(C);
- }
-
- return OPERATOR_FINISHED;
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ Base *base = CTX_data_active_base(C);
+
+ /* If the base is NULL it means we have an active object, but the object itself is hidden. */
+ if (base == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ Object *obact = base->object;
+ const int mode_flag = OB_MODE_POSE;
+ bool is_mode_set = (obact->mode & mode_flag) != 0;
+
+ if (!is_mode_set) {
+ if (!ED_object_mode_compat_set(C, obact, mode_flag, op->reports)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ if (obact->type != OB_ARMATURE) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
+ if (obact == CTX_data_edit_object(C)) {
+ ED_object_editmode_exit(C, EM_FREEDATA);
+ is_mode_set = false;
+ }
+
+ if (is_mode_set) {
+ bool ok = ED_object_posemode_exit(C, obact);
+ if (ok) {
+ struct Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ FOREACH_OBJECT_BEGIN (view_layer, ob) {
+ if ((ob != obact) && (ob->type == OB_ARMATURE) && (ob->mode & mode_flag)) {
+ ED_object_posemode_exit_ex(bmain, ob);
+ }
+ }
+ FOREACH_OBJECT_END;
+ }
+ }
+ else {
+ bool ok = ED_object_posemode_enter(C, obact);
+ if (ok) {
+ struct Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) {
+ if ((ob != obact) && (ob->type == OB_ARMATURE) && (ob->mode == OB_MODE_OBJECT) &&
+ (!ID_IS_LINKED(ob))) {
+ ED_object_posemode_enter_ex(bmain, ob);
+ }
+ }
+ FOREACH_SELECTED_OBJECT_END;
+ }
+ }
+
+ WM_msg_publish_rna_prop(mbus, &obact->id, obact, Object, mode);
+
+ if (G.background == false) {
+ WM_toolsystem_update_from_context_view3d(C);
+ }
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_posemode_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Pose Mode";
- ot->idname = "OBJECT_OT_posemode_toggle";
- ot->description = "Enable or disable posing/selecting bones";
+ /* identifiers */
+ ot->name = "Toggle Pose Mode";
+ ot->idname = "OBJECT_OT_posemode_toggle";
+ ot->description = "Enable or disable posing/selecting bones";
- /* api callbacks */
- ot->exec = posemode_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* api callbacks */
+ ot->exec = posemode_exec;
+ ot->poll = ED_operator_object_active_editable;
- /* flag */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flag */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************* force field toggle operator ***************** */
void ED_object_check_force_modifiers(Main *bmain, Scene *scene, Object *object)
{
- PartDeflect *pd = object->pd;
- ModifierData *md = modifiers_findByType(object, eModifierType_Surface);
-
- /* add/remove modifier as needed */
- if (!md) {
- if (pd && (pd->shape == PFIELD_SHAPE_SURFACE) && !ELEM(pd->forcefield, 0, PFIELD_GUIDE, PFIELD_TEXTURE)) {
- if (ELEM(object->type, OB_MESH, OB_SURF, OB_FONT, OB_CURVE)) {
- ED_object_modifier_add(NULL, bmain, scene, object, NULL, eModifierType_Surface);
- }
- }
- }
- else {
- if (!pd || (pd->shape != PFIELD_SHAPE_SURFACE) || ELEM(pd->forcefield, 0, PFIELD_GUIDE, PFIELD_TEXTURE)) {
- ED_object_modifier_remove(NULL, bmain, object, md);
- }
- }
+ PartDeflect *pd = object->pd;
+ ModifierData *md = modifiers_findByType(object, eModifierType_Surface);
+
+ /* add/remove modifier as needed */
+ if (!md) {
+ if (pd && (pd->shape == PFIELD_SHAPE_SURFACE) &&
+ !ELEM(pd->forcefield, 0, PFIELD_GUIDE, PFIELD_TEXTURE)) {
+ if (ELEM(object->type, OB_MESH, OB_SURF, OB_FONT, OB_CURVE)) {
+ ED_object_modifier_add(NULL, bmain, scene, object, NULL, eModifierType_Surface);
+ }
+ }
+ }
+ else {
+ if (!pd || (pd->shape != PFIELD_SHAPE_SURFACE) ||
+ ELEM(pd->forcefield, 0, PFIELD_GUIDE, PFIELD_TEXTURE)) {
+ ED_object_modifier_remove(NULL, bmain, object, md);
+ }
+ }
}
static int forcefield_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- if (ob->pd == NULL)
- ob->pd = BKE_partdeflect_new(PFIELD_FORCE);
- else if (ob->pd->forcefield == 0)
- ob->pd->forcefield = PFIELD_FORCE;
- else
- ob->pd->forcefield = 0;
+ if (ob->pd == NULL)
+ ob->pd = BKE_partdeflect_new(PFIELD_FORCE);
+ else if (ob->pd->forcefield == 0)
+ ob->pd->forcefield = PFIELD_FORCE;
+ else
+ ob->pd->forcefield = 0;
- ED_object_check_force_modifiers(CTX_data_main(C), CTX_data_scene(C), ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ ED_object_check_force_modifiers(CTX_data_main(C), CTX_data_scene(C), ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_forcefield_toggle(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Toggle Force Field";
- ot->description = "Toggle object's force field";
- ot->idname = "OBJECT_OT_forcefield_toggle";
+ /* identifiers */
+ ot->name = "Toggle Force Field";
+ ot->description = "Toggle object's force field";
+ ot->idname = "OBJECT_OT_forcefield_toggle";
- /* api callbacks */
- ot->exec = forcefield_toggle_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* api callbacks */
+ ot->exec = forcefield_toggle_exec;
+ ot->poll = ED_operator_object_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************************************** */
@@ -892,156 +897,166 @@ void OBJECT_OT_forcefield_toggle(wmOperatorType *ot)
*/
void ED_objects_recalculate_paths(bContext *C, Scene *scene, bool current_frame_only)
{
- /* Transform doesn't always have context available to do update. */
- if (C == NULL) {
- return;
- }
-
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ListBase targets = {NULL, NULL};
-
- /* loop over objects in scene */
- CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects)
- {
- /* set flag to force recalc, then grab path(s) from object */
- ob->avs.recalc |= ANIMVIZ_RECALC_PATHS;
- animviz_get_object_motionpaths(ob, &targets);
- }
- CTX_DATA_END;
-
- /* recalculate paths, then free */
- animviz_calc_motionpaths(depsgraph, bmain, scene, &targets, true, current_frame_only);
- BLI_freelistN(&targets);
-
- if (!current_frame_only) {
- /* Tag objects for copy on write - so paths will draw/redraw
- * For currently frame only we update evaluated object directly. */
- CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects)
- {
- if (ob->mpath) {
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
- }
- }
- CTX_DATA_END;
- }
+ /* Transform doesn't always have context available to do update. */
+ if (C == NULL) {
+ return;
+ }
+
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ListBase targets = {NULL, NULL};
+
+ /* loop over objects in scene */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ /* set flag to force recalc, then grab path(s) from object */
+ ob->avs.recalc |= ANIMVIZ_RECALC_PATHS;
+ animviz_get_object_motionpaths(ob, &targets);
+ }
+ CTX_DATA_END;
+
+ /* recalculate paths, then free */
+ animviz_calc_motionpaths(depsgraph, bmain, scene, &targets, true, current_frame_only);
+ BLI_freelistN(&targets);
+
+ if (!current_frame_only) {
+ /* Tag objects for copy on write - so paths will draw/redraw
+ * For currently frame only we update evaluated object directly. */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (ob->mpath) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ }
+ CTX_DATA_END;
+ }
}
-
/* show popup to determine settings */
static int object_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- if (ob == NULL)
- return OPERATOR_CANCELLED;
+ if (ob == NULL)
+ return OPERATOR_CANCELLED;
- /* set default settings from existing/stored settings */
- {
- bAnimVizSettings *avs = &ob->avs;
+ /* set default settings from existing/stored settings */
+ {
+ bAnimVizSettings *avs = &ob->avs;
- RNA_int_set(op->ptr, "start_frame", avs->path_sf);
- RNA_int_set(op->ptr, "end_frame", avs->path_ef);
- }
+ RNA_int_set(op->ptr, "start_frame", avs->path_sf);
+ RNA_int_set(op->ptr, "end_frame", avs->path_ef);
+ }
- /* show popup dialog to allow editing of range... */
- /* FIXME: hardcoded dimensions here are just arbitrary */
- return WM_operator_props_dialog_popup(C, op, 200, 200);
+ /* show popup dialog to allow editing of range... */
+ /* FIXME: hardcoded dimensions here are just arbitrary */
+ return WM_operator_props_dialog_popup(C, op, 200, 200);
}
/* Calculate/recalculate whole paths (avs.path_sf to avs.path_ef) */
static int object_calculate_paths_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- int start = RNA_int_get(op->ptr, "start_frame");
- int end = RNA_int_get(op->ptr, "end_frame");
+ Scene *scene = CTX_data_scene(C);
+ int start = RNA_int_get(op->ptr, "start_frame");
+ int end = RNA_int_get(op->ptr, "end_frame");
- /* set up path data for bones being calculated */
- CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects)
- {
- bAnimVizSettings *avs = &ob->avs;
+ /* set up path data for bones being calculated */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ bAnimVizSettings *avs = &ob->avs;
- /* grab baking settings from operator settings */
- avs->path_sf = start;
- avs->path_ef = end;
+ /* grab baking settings from operator settings */
+ avs->path_sf = start;
+ avs->path_ef = end;
- /* verify that the selected object has the appropriate settings */
- animviz_verify_motionpaths(op->reports, scene, ob, NULL);
- }
- CTX_DATA_END;
+ /* verify that the selected object has the appropriate settings */
+ animviz_verify_motionpaths(op->reports, scene, ob, NULL);
+ }
+ CTX_DATA_END;
- /* calculate the paths for objects that have them (and are tagged to get refreshed) */
- ED_objects_recalculate_paths(C, scene, false);
+ /* calculate the paths for objects that have them (and are tagged to get refreshed) */
+ ED_objects_recalculate_paths(C, scene, false);
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_paths_calculate(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Calculate Object Paths";
- ot->idname = "OBJECT_OT_paths_calculate";
- ot->description = "Calculate motion paths for the selected objects";
-
- /* api callbacks */
- ot->invoke = object_calculate_paths_invoke;
- ot->exec = object_calculate_paths_exec;
- ot->poll = ED_operator_object_active_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_int(ot->srna, "start_frame", 1, MINAFRAME, MAXFRAME, "Start",
- "First frame to calculate object paths on", MINFRAME, MAXFRAME / 2.0);
- RNA_def_int(ot->srna, "end_frame", 250, MINAFRAME, MAXFRAME, "End",
- "Last frame to calculate object paths on", MINFRAME, MAXFRAME / 2.0);
+ /* identifiers */
+ ot->name = "Calculate Object Paths";
+ ot->idname = "OBJECT_OT_paths_calculate";
+ ot->description = "Calculate motion paths for the selected objects";
+
+ /* api callbacks */
+ ot->invoke = object_calculate_paths_invoke;
+ ot->exec = object_calculate_paths_exec;
+ ot->poll = ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna,
+ "start_frame",
+ 1,
+ MINAFRAME,
+ MAXFRAME,
+ "Start",
+ "First frame to calculate object paths on",
+ MINFRAME,
+ MAXFRAME / 2.0);
+ RNA_def_int(ot->srna,
+ "end_frame",
+ 250,
+ MINAFRAME,
+ MAXFRAME,
+ "End",
+ "Last frame to calculate object paths on",
+ MINFRAME,
+ MAXFRAME / 2.0);
}
/* --------- */
static bool object_update_paths_poll(bContext *C)
{
- if (ED_operator_object_active_editable(C)) {
- Object *ob = ED_object_active_context(C);
- return (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
- }
+ if (ED_operator_object_active_editable(C)) {
+ Object *ob = ED_object_active_context(C);
+ return (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0;
+ }
- return false;
+ return false;
}
static int object_update_paths_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- if (scene == NULL)
- return OPERATOR_CANCELLED;
+ if (scene == NULL)
+ return OPERATOR_CANCELLED;
- /* calculate the paths for objects that have them (and are tagged to get refreshed) */
- ED_objects_recalculate_paths(C, scene, false);
+ /* calculate the paths for objects that have them (and are tagged to get refreshed) */
+ ED_objects_recalculate_paths(C, scene, false);
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_paths_update(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Update Object Paths";
- ot->idname = "OBJECT_OT_paths_update";
- ot->description = "Recalculate paths for selected objects";
+ /* identifiers */
+ ot->name = "Update Object Paths";
+ ot->idname = "OBJECT_OT_paths_update";
+ ot->description = "Recalculate paths for selected objects";
- /* api callbakcs */
- ot->exec = object_update_paths_exec;
- ot->poll = object_update_paths_poll;
+ /* api callbakcs */
+ ot->exec = object_update_paths_exec;
+ ot->poll = object_update_paths_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* --------- */
@@ -1049,578 +1064,568 @@ void OBJECT_OT_paths_update(wmOperatorType *ot)
/* Helper for ED_objects_clear_paths() */
static void object_clear_mpath(Object *ob)
{
- if (ob->mpath) {
- animviz_free_motionpath(ob->mpath);
- ob->mpath = NULL;
- ob->avs.path_bakeflag &= ~MOTIONPATH_BAKE_HAS_PATHS;
-
- /* tag object for copy on write - so removed paths don't still show */
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
- }
+ if (ob->mpath) {
+ animviz_free_motionpath(ob->mpath);
+ ob->mpath = NULL;
+ ob->avs.path_bakeflag &= ~MOTIONPATH_BAKE_HAS_PATHS;
+
+ /* tag object for copy on write - so removed paths don't still show */
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
/* Clear motion paths for all objects */
void ED_objects_clear_paths(bContext *C, bool only_selected)
{
- if (only_selected) {
- /* loop over all selected + sedtiable objects in scene */
- CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects)
- {
- object_clear_mpath(ob);
- }
- CTX_DATA_END;
- }
- else {
- /* loop over all edtiable objects in scene */
- CTX_DATA_BEGIN(C, Object *, ob, editable_objects)
- {
- object_clear_mpath(ob);
- }
- CTX_DATA_END;
- }
+ if (only_selected) {
+ /* loop over all selected + sedtiable objects in scene */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ object_clear_mpath(ob);
+ }
+ CTX_DATA_END;
+ }
+ else {
+ /* loop over all edtiable objects in scene */
+ CTX_DATA_BEGIN (C, Object *, ob, editable_objects) {
+ object_clear_mpath(ob);
+ }
+ CTX_DATA_END;
+ }
}
/* operator callback for this */
static int object_clear_paths_exec(bContext *C, wmOperator *op)
{
- bool only_selected = RNA_boolean_get(op->ptr, "only_selected");
+ bool only_selected = RNA_boolean_get(op->ptr, "only_selected");
- /* use the backend function for this */
- ED_objects_clear_paths(C, only_selected);
+ /* use the backend function for this */
+ ED_objects_clear_paths(C, only_selected);
- /* notifiers for updates */
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/* operator callback/wrapper */
static int object_clear_paths_invoke(bContext *C, wmOperator *op, const wmEvent *evt)
{
- if ((evt->shift) && !RNA_struct_property_is_set(op->ptr, "only_selected")) {
- RNA_boolean_set(op->ptr, "only_selected", true);
- }
- return object_clear_paths_exec(C, op);
+ if ((evt->shift) && !RNA_struct_property_is_set(op->ptr, "only_selected")) {
+ RNA_boolean_set(op->ptr, "only_selected", true);
+ }
+ return object_clear_paths_exec(C, op);
}
void OBJECT_OT_paths_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Object Paths";
- ot->idname = "OBJECT_OT_paths_clear";
- ot->description = "Clear path caches for all objects, hold Shift key for selected objects only";
-
- /* api callbacks */
- ot->invoke = object_clear_paths_invoke;
- ot->exec = object_clear_paths_exec;
- ot->poll = ED_operator_object_active_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_boolean(ot->srna, "only_selected", false, "Only Selected",
- "Only clear paths from selected objects");
- RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
+ /* identifiers */
+ ot->name = "Clear Object Paths";
+ ot->idname = "OBJECT_OT_paths_clear";
+ ot->description = "Clear path caches for all objects, hold Shift key for selected objects only";
+
+ /* api callbacks */
+ ot->invoke = object_clear_paths_invoke;
+ ot->exec = object_clear_paths_exec;
+ ot->poll = ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_boolean(
+ ot->srna, "only_selected", false, "Only Selected", "Only clear paths from selected objects");
+ RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
}
/* --------- */
static int object_update_paths_range_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
-
- /* loop over all edtiable objects in scene */
- CTX_DATA_BEGIN(C, Object *, ob, editable_objects)
- {
- /* use Preview Range or Full Frame Range - whichever is in use */
- ob->avs.path_sf = PSFRA;
- ob->avs.path_ef = PEFRA;
-
- /* tag for updates */
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- }
- CTX_DATA_END;
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+
+ /* loop over all edtiable objects in scene */
+ CTX_DATA_BEGIN (C, Object *, ob, editable_objects) {
+ /* use Preview Range or Full Frame Range - whichever is in use */
+ ob->avs.path_sf = PSFRA;
+ ob->avs.path_ef = PEFRA;
+
+ /* tag for updates */
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ }
+ CTX_DATA_END;
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_paths_range_update(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Update Range from Scene";
- ot->idname = "OBJECT_OT_paths_range_update";
- ot->description = "Update frame range for motion paths from the Scene's current frame range";
+ /* identifiers */
+ ot->name = "Update Range from Scene";
+ ot->idname = "OBJECT_OT_paths_range_update";
+ ot->description = "Update frame range for motion paths from the Scene's current frame range";
- /* callbacks */
- ot->exec = object_update_paths_range_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* callbacks */
+ ot->exec = object_update_paths_range_exec;
+ ot->poll = ED_operator_object_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
/********************** Smooth/Flat *********************/
static int shade_smooth_exec(bContext *C, wmOperator *op)
{
- ID *data;
- Curve *cu;
- Nurb *nu;
- int clear = (STREQ(op->idname, "OBJECT_OT_shade_flat"));
- bool done = false, linked_data = false;
-
- CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects)
- {
- data = ob->data;
-
- if (data && ID_IS_LINKED(data)) {
- linked_data = true;
- continue;
- }
-
- if (ob->type == OB_MESH) {
- BKE_mesh_smooth_flag_set(ob, !clear);
-
- BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- done = true;
- }
- else if (ELEM(ob->type, OB_SURF, OB_CURVE)) {
- cu = ob->data;
-
- for (nu = cu->nurb.first; nu; nu = nu->next) {
- if (!clear) nu->flag |= ME_SMOOTH;
- else nu->flag &= ~ME_SMOOTH;
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- done = true;
- }
- }
- CTX_DATA_END;
-
- if (linked_data)
- BKE_report(op->reports, RPT_WARNING, "Can't edit linked mesh or curve data");
-
- return (done) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ ID *data;
+ Curve *cu;
+ Nurb *nu;
+ int clear = (STREQ(op->idname, "OBJECT_OT_shade_flat"));
+ bool done = false, linked_data = false;
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ data = ob->data;
+
+ if (data && ID_IS_LINKED(data)) {
+ linked_data = true;
+ continue;
+ }
+
+ if (ob->type == OB_MESH) {
+ BKE_mesh_smooth_flag_set(ob, !clear);
+
+ BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ done = true;
+ }
+ else if (ELEM(ob->type, OB_SURF, OB_CURVE)) {
+ cu = ob->data;
+
+ for (nu = cu->nurb.first; nu; nu = nu->next) {
+ if (!clear)
+ nu->flag |= ME_SMOOTH;
+ else
+ nu->flag &= ~ME_SMOOTH;
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ done = true;
+ }
+ }
+ CTX_DATA_END;
+
+ if (linked_data)
+ BKE_report(op->reports, RPT_WARNING, "Can't edit linked mesh or curve data");
+
+ return (done) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
static bool shade_poll(bContext *C)
{
- return (CTX_data_edit_object(C) == NULL);
+ return (CTX_data_edit_object(C) == NULL);
}
void OBJECT_OT_shade_flat(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Shade Flat";
- ot->description = "Render and display faces uniform, using Face Normals";
- ot->idname = "OBJECT_OT_shade_flat";
+ /* identifiers */
+ ot->name = "Shade Flat";
+ ot->description = "Render and display faces uniform, using Face Normals";
+ ot->idname = "OBJECT_OT_shade_flat";
- /* api callbacks */
- ot->poll = shade_poll;
- ot->exec = shade_smooth_exec;
+ /* api callbacks */
+ ot->poll = shade_poll;
+ ot->exec = shade_smooth_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
void OBJECT_OT_shade_smooth(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Shade Smooth";
- ot->description = "Render and display faces smooth, using interpolated Vertex Normals";
- ot->idname = "OBJECT_OT_shade_smooth";
+ /* identifiers */
+ ot->name = "Shade Smooth";
+ ot->description = "Render and display faces smooth, using interpolated Vertex Normals";
+ ot->idname = "OBJECT_OT_shade_smooth";
- /* api callbacks */
- ot->poll = shade_poll;
- ot->exec = shade_smooth_exec;
+ /* api callbacks */
+ ot->poll = shade_poll;
+ ot->exec = shade_smooth_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ********************** */
-static const EnumPropertyItem *object_mode_set_itemsf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *object_mode_set_itemsf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- const EnumPropertyItem *input = rna_enum_object_mode_items;
- EnumPropertyItem *item = NULL;
- Object *ob;
- int totitem = 0;
-
- if (!C) /* needed for docs */
- return rna_enum_object_mode_items;
-
- ob = CTX_data_active_object(C);
- if (ob) {
- const bool use_mode_particle_edit = (BLI_listbase_is_empty(&ob->particlesystem) == false) ||
- (ob->soft != NULL) ||
- (modifiers_findByType(ob, eModifierType_Cloth) != NULL);
- while (input->identifier) {
- if ((input->value == OB_MODE_EDIT && OB_TYPE_SUPPORT_EDITMODE(ob->type)) ||
- (input->value == OB_MODE_POSE && (ob->type == OB_ARMATURE)) ||
- (input->value == OB_MODE_PARTICLE_EDIT && use_mode_particle_edit) ||
- (ELEM(input->value, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT,
- OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT) && (ob->type == OB_MESH)) ||
- (ELEM(input->value, OB_MODE_EDIT_GPENCIL, OB_MODE_PAINT_GPENCIL,
- OB_MODE_SCULPT_GPENCIL, OB_MODE_WEIGHT_GPENCIL) && (ob->type == OB_GPENCIL)) ||
- (input->value == OB_MODE_OBJECT))
- {
- RNA_enum_item_add(&item, &totitem, input);
- }
- input++;
- }
- }
- else {
- /* We need at least this one! */
- RNA_enum_items_add_value(&item, &totitem, input, OB_MODE_OBJECT);
- }
-
- RNA_enum_item_end(&item, &totitem);
-
- *r_free = true;
-
- return item;
+ const EnumPropertyItem *input = rna_enum_object_mode_items;
+ EnumPropertyItem *item = NULL;
+ Object *ob;
+ int totitem = 0;
+
+ if (!C) /* needed for docs */
+ return rna_enum_object_mode_items;
+
+ ob = CTX_data_active_object(C);
+ if (ob) {
+ const bool use_mode_particle_edit = (BLI_listbase_is_empty(&ob->particlesystem) == false) ||
+ (ob->soft != NULL) ||
+ (modifiers_findByType(ob, eModifierType_Cloth) != NULL);
+ while (input->identifier) {
+ if ((input->value == OB_MODE_EDIT && OB_TYPE_SUPPORT_EDITMODE(ob->type)) ||
+ (input->value == OB_MODE_POSE && (ob->type == OB_ARMATURE)) ||
+ (input->value == OB_MODE_PARTICLE_EDIT && use_mode_particle_edit) ||
+ (ELEM(input->value,
+ OB_MODE_SCULPT,
+ OB_MODE_VERTEX_PAINT,
+ OB_MODE_WEIGHT_PAINT,
+ OB_MODE_TEXTURE_PAINT) &&
+ (ob->type == OB_MESH)) ||
+ (ELEM(input->value,
+ OB_MODE_EDIT_GPENCIL,
+ OB_MODE_PAINT_GPENCIL,
+ OB_MODE_SCULPT_GPENCIL,
+ OB_MODE_WEIGHT_GPENCIL) &&
+ (ob->type == OB_GPENCIL)) ||
+ (input->value == OB_MODE_OBJECT)) {
+ RNA_enum_item_add(&item, &totitem, input);
+ }
+ input++;
+ }
+ }
+ else {
+ /* We need at least this one! */
+ RNA_enum_items_add_value(&item, &totitem, input, OB_MODE_OBJECT);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+
+ *r_free = true;
+
+ return item;
}
static bool object_mode_set_poll(bContext *C)
{
- /* Since Grease Pencil editmode is also handled here,
- * we have a special exception for allowing this operator
- * to still work in that case when there's no active object
- * so that users can exit editmode this way as per normal.
- */
- if (ED_operator_object_active_editable(C))
- return true;
- else
- return (CTX_data_gpencil_data(C) != NULL);
+ /* Since Grease Pencil editmode is also handled here,
+ * we have a special exception for allowing this operator
+ * to still work in that case when there's no active object
+ * so that users can exit editmode this way as per normal.
+ */
+ if (ED_operator_object_active_editable(C))
+ return true;
+ else
+ return (CTX_data_gpencil_data(C) != NULL);
}
static int object_mode_set_exec(bContext *C, wmOperator *op)
{
- bool use_submode = STREQ(op->idname, "OBJECT_OT_mode_set_or_submode");
- Object *ob = CTX_data_active_object(C);
- eObjectMode mode = RNA_enum_get(op->ptr, "mode");
- eObjectMode restore_mode = (ob) ? ob->mode : OB_MODE_OBJECT;
- const bool toggle = RNA_boolean_get(op->ptr, "toggle");
-
- if (use_submode) {
- /* When not changing modes use submodes, see: T55162. */
- if (toggle == false) {
- if (mode == restore_mode) {
- switch (mode) {
- case OB_MODE_EDIT:
- WM_menu_name_call(C, "VIEW3D_MT_edit_mesh_select_mode", WM_OP_INVOKE_REGION_WIN);
- return OPERATOR_INTERFACE;
- default:
- break;
- }
- }
- }
- }
-
- /* by default the operator assume is a mesh, but if gp object change mode */
- if ((ob != NULL) && (ob->type == OB_GPENCIL) && (mode == OB_MODE_EDIT)) {
- mode = OB_MODE_EDIT_GPENCIL;
- }
-
- if (!ob || !ED_object_mode_compat_test(ob, mode))
- return OPERATOR_PASS_THROUGH;
-
- if (ob->mode != mode) {
- /* we should be able to remove this call, each operator calls */
- ED_object_mode_compat_set(C, ob, mode, op->reports);
- }
-
- /* Exit current mode if it's not the mode we're setting */
- if (mode != OB_MODE_OBJECT && (ob->mode != mode || toggle)) {
- /* Enter new mode */
- ED_object_mode_toggle(C, mode);
- }
-
- if (toggle) {
- /* Special case for Object mode! */
- if (mode == OB_MODE_OBJECT && restore_mode == OB_MODE_OBJECT && ob->restore_mode != OB_MODE_OBJECT) {
- ED_object_mode_toggle(C, ob->restore_mode);
- }
- else if (ob->mode == mode) {
- /* For toggling, store old mode so we know what to go back to */
- ob->restore_mode = restore_mode;
- }
- else if (ob->restore_mode != OB_MODE_OBJECT && ob->restore_mode != mode) {
- ED_object_mode_toggle(C, ob->restore_mode);
- }
- }
-
- /* if type is OB_GPENCIL, set cursor mode */
- if ((ob) && (ob->type == OB_GPENCIL)) {
- if (ob->data) {
- bGPdata *gpd = (bGPdata *)ob->data;
- ED_gpencil_setup_modes(C, gpd, ob->mode);
- }
- }
-
- return OPERATOR_FINISHED;
+ bool use_submode = STREQ(op->idname, "OBJECT_OT_mode_set_or_submode");
+ Object *ob = CTX_data_active_object(C);
+ eObjectMode mode = RNA_enum_get(op->ptr, "mode");
+ eObjectMode restore_mode = (ob) ? ob->mode : OB_MODE_OBJECT;
+ const bool toggle = RNA_boolean_get(op->ptr, "toggle");
+
+ if (use_submode) {
+ /* When not changing modes use submodes, see: T55162. */
+ if (toggle == false) {
+ if (mode == restore_mode) {
+ switch (mode) {
+ case OB_MODE_EDIT:
+ WM_menu_name_call(C, "VIEW3D_MT_edit_mesh_select_mode", WM_OP_INVOKE_REGION_WIN);
+ return OPERATOR_INTERFACE;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ /* by default the operator assume is a mesh, but if gp object change mode */
+ if ((ob != NULL) && (ob->type == OB_GPENCIL) && (mode == OB_MODE_EDIT)) {
+ mode = OB_MODE_EDIT_GPENCIL;
+ }
+
+ if (!ob || !ED_object_mode_compat_test(ob, mode))
+ return OPERATOR_PASS_THROUGH;
+
+ if (ob->mode != mode) {
+ /* we should be able to remove this call, each operator calls */
+ ED_object_mode_compat_set(C, ob, mode, op->reports);
+ }
+
+ /* Exit current mode if it's not the mode we're setting */
+ if (mode != OB_MODE_OBJECT && (ob->mode != mode || toggle)) {
+ /* Enter new mode */
+ ED_object_mode_toggle(C, mode);
+ }
+
+ if (toggle) {
+ /* Special case for Object mode! */
+ if (mode == OB_MODE_OBJECT && restore_mode == OB_MODE_OBJECT &&
+ ob->restore_mode != OB_MODE_OBJECT) {
+ ED_object_mode_toggle(C, ob->restore_mode);
+ }
+ else if (ob->mode == mode) {
+ /* For toggling, store old mode so we know what to go back to */
+ ob->restore_mode = restore_mode;
+ }
+ else if (ob->restore_mode != OB_MODE_OBJECT && ob->restore_mode != mode) {
+ ED_object_mode_toggle(C, ob->restore_mode);
+ }
+ }
+
+ /* if type is OB_GPENCIL, set cursor mode */
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ if (ob->data) {
+ bGPdata *gpd = (bGPdata *)ob->data;
+ ED_gpencil_setup_modes(C, gpd, ob->mode);
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_mode_set(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Set Object Mode";
- ot->description = "Sets the object interaction mode";
- ot->idname = "OBJECT_OT_mode_set";
+ /* identifiers */
+ ot->name = "Set Object Mode";
+ ot->description = "Sets the object interaction mode";
+ ot->idname = "OBJECT_OT_mode_set";
- /* api callbacks */
- ot->exec = object_mode_set_exec;
+ /* api callbacks */
+ ot->exec = object_mode_set_exec;
- ot->poll = object_mode_set_poll; //ED_operator_object_active_editable;
+ ot->poll = object_mode_set_poll; //ED_operator_object_active_editable;
- /* flags */
- ot->flag = 0; /* no register/undo here, leave it to operators being called */
+ /* flags */
+ ot->flag = 0; /* no register/undo here, leave it to operators being called */
- ot->prop = RNA_def_enum(ot->srna, "mode", rna_enum_object_mode_items, OB_MODE_OBJECT, "Mode", "");
- RNA_def_enum_funcs(ot->prop, object_mode_set_itemsf);
- RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
+ ot->prop = RNA_def_enum(
+ ot->srna, "mode", rna_enum_object_mode_items, OB_MODE_OBJECT, "Mode", "");
+ RNA_def_enum_funcs(ot->prop, object_mode_set_itemsf);
+ RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
void OBJECT_OT_mode_set_or_submode(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Set Object Mode or Submode";
- ot->description = "Sets the object interaction mode";
- ot->idname = "OBJECT_OT_mode_set_or_submode";
+ /* identifiers */
+ ot->name = "Set Object Mode or Submode";
+ ot->description = "Sets the object interaction mode";
+ ot->idname = "OBJECT_OT_mode_set_or_submode";
- /* api callbacks */
- ot->exec = object_mode_set_exec;
+ /* api callbacks */
+ ot->exec = object_mode_set_exec;
- ot->poll = object_mode_set_poll; //ED_operator_object_active_editable;
+ ot->poll = object_mode_set_poll; //ED_operator_object_active_editable;
- /* flags */
- ot->flag = 0; /* no register/undo here, leave it to operators being called */
+ /* flags */
+ ot->flag = 0; /* no register/undo here, leave it to operators being called */
- ot->prop = RNA_def_enum(ot->srna, "mode", rna_enum_object_mode_items, OB_MODE_OBJECT, "Mode", "");
- RNA_def_enum_funcs(ot->prop, object_mode_set_itemsf);
- RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
+ ot->prop = RNA_def_enum(
+ ot->srna, "mode", rna_enum_object_mode_items, OB_MODE_OBJECT, "Mode", "");
+ RNA_def_enum_funcs(ot->prop, object_mode_set_itemsf);
+ RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
static bool move_to_collection_poll(bContext *C)
{
- if (CTX_wm_space_outliner(C) != NULL) {
- return ED_outliner_collections_editor_poll(C);
- }
- else {
- View3D *v3d = CTX_wm_view3d(C);
-
- if (v3d && v3d->localvd) {
- return false;
- }
-
- return ED_operator_object_active_editable(C);
- }
+ if (CTX_wm_space_outliner(C) != NULL) {
+ return ED_outliner_collections_editor_poll(C);
+ }
+ else {
+ View3D *v3d = CTX_wm_view3d(C);
+
+ if (v3d && v3d->localvd) {
+ return false;
+ }
+
+ return ED_operator_object_active_editable(C);
+ }
}
static int move_to_collection_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- PropertyRNA *prop = RNA_struct_find_property(op->ptr, "collection_index");
- const bool is_link = STREQ(op->idname, "OBJECT_OT_link_to_collection");
- const bool is_new = RNA_boolean_get(op->ptr, "is_new");
- Collection *collection;
- ListBase objects = {NULL};
-
- if (!RNA_property_is_set(op->ptr, prop)) {
- BKE_report(op->reports, RPT_ERROR, "No collection selected");
- return OPERATOR_CANCELLED;
- }
-
- int collection_index = RNA_property_int_get(op->ptr, prop);
- collection = BKE_collection_from_index(CTX_data_scene(C), collection_index);
- if (collection == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Unexpected error, collection not found");
- return OPERATOR_CANCELLED;
- }
-
- if (CTX_wm_space_outliner(C) != NULL) {
- ED_outliner_selected_objects_get(C, &objects);
- }
- else {
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- BLI_addtail(&objects, BLI_genericNodeN(ob));
- }
- CTX_DATA_END;
- }
-
- if (is_new) {
- char new_collection_name[MAX_NAME];
- RNA_string_get(op->ptr, "new_collection_name", new_collection_name);
- collection = BKE_collection_add(bmain, collection, new_collection_name);
- }
-
- Object *single_object = BLI_listbase_is_single(&objects) ?
- ((LinkData *)objects.first)->data : NULL;
-
- if ((single_object != NULL) &&
- is_link &&
- BLI_findptr(&collection->gobject, single_object, offsetof(CollectionObject, ob)))
- {
- BKE_reportf(op->reports, RPT_ERROR, "%s already in %s", single_object->id.name + 2, collection->id.name + 2);
- BLI_freelistN(&objects);
- return OPERATOR_CANCELLED;
- }
-
- for (LinkData *link = objects.first; link; link = link->next) {
- Object *ob = link->data;
-
- if (!is_link) {
- BKE_collection_object_move(bmain, scene, collection, NULL, ob);
- }
- else {
- BKE_collection_object_add(bmain, collection, ob);
- }
- }
- BLI_freelistN(&objects);
-
- BKE_reportf(op->reports,
- RPT_INFO,
- "%s %s to %s",
- (single_object != NULL) ? single_object->id.name + 2 : "Objects",
- is_link ? "linked" : "moved",
- collection->id.name + 2);
-
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
-
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "collection_index");
+ const bool is_link = STREQ(op->idname, "OBJECT_OT_link_to_collection");
+ const bool is_new = RNA_boolean_get(op->ptr, "is_new");
+ Collection *collection;
+ ListBase objects = {NULL};
+
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ BKE_report(op->reports, RPT_ERROR, "No collection selected");
+ return OPERATOR_CANCELLED;
+ }
+
+ int collection_index = RNA_property_int_get(op->ptr, prop);
+ collection = BKE_collection_from_index(CTX_data_scene(C), collection_index);
+ if (collection == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Unexpected error, collection not found");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (CTX_wm_space_outliner(C) != NULL) {
+ ED_outliner_selected_objects_get(C, &objects);
+ }
+ else {
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ BLI_addtail(&objects, BLI_genericNodeN(ob));
+ }
+ CTX_DATA_END;
+ }
+
+ if (is_new) {
+ char new_collection_name[MAX_NAME];
+ RNA_string_get(op->ptr, "new_collection_name", new_collection_name);
+ collection = BKE_collection_add(bmain, collection, new_collection_name);
+ }
+
+ Object *single_object = BLI_listbase_is_single(&objects) ? ((LinkData *)objects.first)->data :
+ NULL;
+
+ if ((single_object != NULL) && is_link &&
+ BLI_findptr(&collection->gobject, single_object, offsetof(CollectionObject, ob))) {
+ BKE_reportf(op->reports,
+ RPT_ERROR,
+ "%s already in %s",
+ single_object->id.name + 2,
+ collection->id.name + 2);
+ BLI_freelistN(&objects);
+ return OPERATOR_CANCELLED;
+ }
+
+ for (LinkData *link = objects.first; link; link = link->next) {
+ Object *ob = link->data;
+
+ if (!is_link) {
+ BKE_collection_object_move(bmain, scene, collection, NULL, ob);
+ }
+ else {
+ BKE_collection_object_add(bmain, collection, ob);
+ }
+ }
+ BLI_freelistN(&objects);
+
+ BKE_reportf(op->reports,
+ RPT_INFO,
+ "%s %s to %s",
+ (single_object != NULL) ? single_object->id.name + 2 : "Objects",
+ is_link ? "linked" : "moved",
+ collection->id.name + 2);
+
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
+
+ return OPERATOR_FINISHED;
}
struct MoveToCollectionData {
- struct MoveToCollectionData *next, *prev;
- int index;
- struct Collection *collection;
- struct ListBase submenus;
- PointerRNA ptr;
- struct wmOperatorType *ot;
+ struct MoveToCollectionData *next, *prev;
+ int index;
+ struct Collection *collection;
+ struct ListBase submenus;
+ PointerRNA ptr;
+ struct wmOperatorType *ot;
};
static int move_to_collection_menus_create(wmOperator *op, MoveToCollectionData *menu)
{
- int index = menu->index;
- for (CollectionChild *child = menu->collection->children.first;
- child != NULL;
- child = child->next)
- {
- Collection *collection = child->collection;
- MoveToCollectionData *submenu = MEM_callocN(sizeof(MoveToCollectionData),
- "MoveToCollectionData submenu - expected memleak");
- BLI_addtail(&menu->submenus, submenu);
- submenu->collection = collection;
- submenu->index = ++index;
- index = move_to_collection_menus_create(op, submenu);
- submenu->ot = op->type;
- }
- return index;
+ int index = menu->index;
+ for (CollectionChild *child = menu->collection->children.first; child != NULL;
+ child = child->next) {
+ Collection *collection = child->collection;
+ MoveToCollectionData *submenu = MEM_callocN(sizeof(MoveToCollectionData),
+ "MoveToCollectionData submenu - expected memleak");
+ BLI_addtail(&menu->submenus, submenu);
+ submenu->collection = collection;
+ submenu->index = ++index;
+ index = move_to_collection_menus_create(op, submenu);
+ submenu->ot = op->type;
+ }
+ return index;
}
static void move_to_collection_menus_free_recursive(MoveToCollectionData *menu)
{
- for (MoveToCollectionData *submenu = menu->submenus.first;
- submenu != NULL;
- submenu = submenu->next)
- {
- move_to_collection_menus_free_recursive(submenu);
- }
- BLI_freelistN(&menu->submenus);
+ for (MoveToCollectionData *submenu = menu->submenus.first; submenu != NULL;
+ submenu = submenu->next) {
+ move_to_collection_menus_free_recursive(submenu);
+ }
+ BLI_freelistN(&menu->submenus);
}
static void move_to_collection_menus_free(MoveToCollectionData **menu)
{
- if (*menu == NULL) {
- return;
- }
+ if (*menu == NULL) {
+ return;
+ }
- move_to_collection_menus_free_recursive(*menu);
- MEM_freeN(*menu);
- *menu = NULL;
+ move_to_collection_menus_free_recursive(*menu);
+ MEM_freeN(*menu);
+ *menu = NULL;
}
static void move_to_collection_menu_create(bContext *UNUSED(C), uiLayout *layout, void *menu_v)
{
- MoveToCollectionData *menu = menu_v;
- const char *name = BKE_collection_ui_name_get(menu->collection);
-
- 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);
- RNA_boolean_set(&menu->ptr, "is_new", true);
-
- uiItemFullO_ptr(layout,
- menu->ot,
- "New Collection",
- ICON_ADD,
- menu->ptr.data,
- WM_OP_INVOKE_DEFAULT,
- 0,
- NULL);
+ MoveToCollectionData *menu = menu_v;
+ const char *name = BKE_collection_ui_name_get(menu->collection);
+
+ 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);
+ RNA_boolean_set(&menu->ptr, "is_new", true);
+
+ uiItemFullO_ptr(
+ layout, menu->ot, "New Collection", ICON_ADD, menu->ptr.data, WM_OP_INVOKE_DEFAULT, 0, NULL);
}
static void move_to_collection_menus_items(uiLayout *layout, MoveToCollectionData *menu)
{
- if (BLI_listbase_is_empty(&menu->submenus)) {
- uiItemIntO(layout,
- menu->collection->id.name + 2,
- ICON_NONE,
- menu->ot->idname,
- "collection_index",
- menu->index);
- }
- else {
- uiItemMenuF(layout,
- menu->collection->id.name + 2,
- ICON_NONE,
- move_to_collection_menu_create,
- menu);
- }
+ if (BLI_listbase_is_empty(&menu->submenus)) {
+ uiItemIntO(layout,
+ menu->collection->id.name + 2,
+ ICON_NONE,
+ menu->ot->idname,
+ "collection_index",
+ menu->index);
+ }
+ else {
+ uiItemMenuF(
+ layout, menu->collection->id.name + 2, ICON_NONE, move_to_collection_menu_create, menu);
+ }
}
/* This is allocated statically because we need this available for the menus creation callback. */
@@ -1628,116 +1633,138 @@ static MoveToCollectionData *master_collection_menu = NULL;
static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Scene *scene = CTX_data_scene(C);
+ Scene *scene = CTX_data_scene(C);
- /* Reset the menus data for the current master collection, and free previously allocated data. */
- move_to_collection_menus_free(&master_collection_menu);
+ /* Reset the menus data for the current master collection, and free previously allocated data. */
+ move_to_collection_menus_free(&master_collection_menu);
- PropertyRNA *prop;
- prop = RNA_struct_find_property(op->ptr, "collection_index");
- if (RNA_property_is_set(op->ptr, prop)) {
- int collection_index = RNA_property_int_get(op->ptr, prop);
+ PropertyRNA *prop;
+ prop = RNA_struct_find_property(op->ptr, "collection_index");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ int collection_index = RNA_property_int_get(op->ptr, prop);
- if (RNA_boolean_get(op->ptr, "is_new")) {
- prop = RNA_struct_find_property(op->ptr, "new_collection_name");
- if (!RNA_property_is_set(op->ptr, prop)) {
- char name[MAX_NAME];
- Collection *collection;
+ if (RNA_boolean_get(op->ptr, "is_new")) {
+ prop = RNA_struct_find_property(op->ptr, "new_collection_name");
+ if (!RNA_property_is_set(op->ptr, prop)) {
+ char name[MAX_NAME];
+ Collection *collection;
- collection = BKE_collection_from_index(scene, collection_index);
- BKE_collection_new_name_get(collection, name);
+ collection = BKE_collection_from_index(scene, collection_index);
+ BKE_collection_new_name_get(collection, name);
- RNA_property_string_set(op->ptr, prop, name);
- return WM_operator_props_dialog_popup(C, op, 200, 100);
- }
- }
- return move_to_collection_exec(C, op);
- }
+ RNA_property_string_set(op->ptr, prop, name);
+ return WM_operator_props_dialog_popup(C, op, 200, 100);
+ }
+ }
+ return move_to_collection_exec(C, op);
+ }
- Collection *master_collection = BKE_collection_master(scene);
+ Collection *master_collection = BKE_collection_master(scene);
- /* We need the data to be allocated so it's available during menu drawing.
- * Technically we could use wmOperator->customdata. However there is no free callback
- * called to an operator that exit with OPERATOR_INTERFACE to launch a menu.
- *
- * So we are left with a memory that will necessarily leak. It's a small leak though.*/
- if (master_collection_menu == NULL) {
- master_collection_menu = MEM_callocN(sizeof(MoveToCollectionData),
- "MoveToCollectionData menu - expected eventual memleak");
- }
+ /* We need the data to be allocated so it's available during menu drawing.
+ * Technically we could use wmOperator->customdata. However there is no free callback
+ * called to an operator that exit with OPERATOR_INTERFACE to launch a menu.
+ *
+ * So we are left with a memory that will necessarily leak. It's a small leak though.*/
+ if (master_collection_menu == NULL) {
+ master_collection_menu = MEM_callocN(sizeof(MoveToCollectionData),
+ "MoveToCollectionData menu - expected eventual memleak");
+ }
- master_collection_menu->collection = master_collection;
- master_collection_menu->ot = op->type;
- move_to_collection_menus_create(op, master_collection_menu);
+ master_collection_menu->collection = master_collection;
+ master_collection_menu->ot = op->type;
+ move_to_collection_menus_create(op, master_collection_menu);
- uiPopupMenu *pup;
- uiLayout *layout;
+ uiPopupMenu *pup;
+ uiLayout *layout;
- /* Build the menus. */
- const char *title = CTX_IFACE_(op->type->translation_context, op->type->name);
- pup = UI_popup_menu_begin(C, title, ICON_NONE);
- layout = UI_popup_menu_layout(pup);
+ /* Build the menus. */
+ const char *title = CTX_IFACE_(op->type->translation_context, op->type->name);
+ pup = UI_popup_menu_begin(C, title, ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
- uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
+ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
- move_to_collection_menu_create(C, layout, master_collection_menu);
+ move_to_collection_menu_create(C, layout, master_collection_menu);
- UI_popup_menu_end(C, pup);
+ UI_popup_menu_end(C, pup);
- return OPERATOR_INTERFACE;
+ return OPERATOR_INTERFACE;
}
void OBJECT_OT_move_to_collection(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Move to Collection";
- ot->description = "Move objects to a scene collection";
- ot->idname = "OBJECT_OT_move_to_collection";
-
- /* api callbacks */
- ot->exec = move_to_collection_exec;
- ot->invoke = move_to_collection_invoke;
- ot->poll = move_to_collection_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- prop = RNA_def_int(ot->srna, "collection_index", COLLECTION_INVALID_INDEX, COLLECTION_INVALID_INDEX, INT_MAX,
- "Collection Index", "Index of the collection to move to", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
- prop = RNA_def_boolean(ot->srna, "is_new", false, "New", "Move objects to a new collection");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
- prop = RNA_def_string(ot->srna, "new_collection_name", NULL, MAX_NAME, "Name",
- "Name of the newly added collection");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Move to Collection";
+ ot->description = "Move objects to a scene collection";
+ ot->idname = "OBJECT_OT_move_to_collection";
+
+ /* api callbacks */
+ ot->exec = move_to_collection_exec;
+ ot->invoke = move_to_collection_invoke;
+ ot->poll = move_to_collection_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_int(ot->srna,
+ "collection_index",
+ COLLECTION_INVALID_INDEX,
+ COLLECTION_INVALID_INDEX,
+ INT_MAX,
+ "Collection Index",
+ "Index of the collection to move to",
+ 0,
+ INT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ prop = RNA_def_boolean(ot->srna, "is_new", false, "New", "Move objects to a new collection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ prop = RNA_def_string(ot->srna,
+ "new_collection_name",
+ NULL,
+ MAX_NAME,
+ "Name",
+ "Name of the newly added collection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ ot->prop = prop;
}
void OBJECT_OT_link_to_collection(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Link to Collection";
- ot->description = "Link objects to a collection";
- ot->idname = "OBJECT_OT_link_to_collection";
-
- /* api callbacks */
- ot->exec = move_to_collection_exec;
- ot->invoke = move_to_collection_invoke;
- ot->poll = move_to_collection_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- prop = RNA_def_int(ot->srna, "collection_index", COLLECTION_INVALID_INDEX, COLLECTION_INVALID_INDEX, INT_MAX,
- "Collection Index", "Index of the collection to move to", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
- prop = RNA_def_boolean(ot->srna, "is_new", false, "New", "Move objects to a new collection");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
- prop = RNA_def_string(ot->srna, "new_collection_name", NULL, MAX_NAME, "Name",
- "Name of the newly added collection");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Link to Collection";
+ ot->description = "Link objects to a collection";
+ ot->idname = "OBJECT_OT_link_to_collection";
+
+ /* api callbacks */
+ ot->exec = move_to_collection_exec;
+ ot->invoke = move_to_collection_invoke;
+ ot->poll = move_to_collection_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_int(ot->srna,
+ "collection_index",
+ COLLECTION_INVALID_INDEX,
+ COLLECTION_INVALID_INDEX,
+ INT_MAX,
+ "Collection Index",
+ "Index of the collection to move to",
+ 0,
+ INT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ prop = RNA_def_boolean(ot->srna, "is_new", false, "New", "Move objects to a new collection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ prop = RNA_def_string(ot->srna,
+ "new_collection_name",
+ NULL,
+ MAX_NAME,
+ "Name",
+ "Name of the newly added collection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/object/object_facemap_ops.c b/source/blender/editors/object/object_facemap_ops.c
index c46310c8c9d..a77cfab031d 100644
--- a/source/blender/editors/object/object_facemap_ops.c
+++ b/source/blender/editors/object/object_facemap_ops.c
@@ -55,438 +55,437 @@
/* called while not in editmode */
void ED_object_facemap_face_add(Object *ob, bFaceMap *fmap, int facenum)
{
- int fmap_nr;
- if (GS(((ID *)ob->data)->name) != ID_ME)
- return;
+ int fmap_nr;
+ if (GS(((ID *)ob->data)->name) != ID_ME)
+ return;
- /* get the face map number, exit if it can't be found */
- fmap_nr = BLI_findindex(&ob->fmaps, fmap);
+ /* get the face map number, exit if it can't be found */
+ fmap_nr = BLI_findindex(&ob->fmaps, fmap);
- if (fmap_nr != -1) {
- int *facemap;
- Mesh *me = ob->data;
+ if (fmap_nr != -1) {
+ int *facemap;
+ Mesh *me = ob->data;
- /* if there's is no facemap layer then create one */
- if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL)
- facemap = CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_DEFAULT, NULL, me->totpoly);
+ /* if there's is no facemap layer then create one */
+ if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL)
+ facemap = CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_DEFAULT, NULL, me->totpoly);
- facemap[facenum] = fmap_nr;
- }
+ facemap[facenum] = fmap_nr;
+ }
}
/* called while not in editmode */
void ED_object_facemap_face_remove(Object *ob, bFaceMap *fmap, int facenum)
{
- int fmap_nr;
- if (GS(((ID *)ob->data)->name) != ID_ME)
- return;
+ int fmap_nr;
+ if (GS(((ID *)ob->data)->name) != ID_ME)
+ return;
- /* get the face map number, exit if it can't be found */
- fmap_nr = BLI_findindex(&ob->fmaps, fmap);
+ /* get the face map number, exit if it can't be found */
+ fmap_nr = BLI_findindex(&ob->fmaps, fmap);
- if (fmap_nr != -1) {
- int *facemap;
- Mesh *me = ob->data;
+ if (fmap_nr != -1) {
+ int *facemap;
+ Mesh *me = ob->data;
- if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL)
- return;
+ if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL)
+ return;
- facemap[facenum] = -1;
- }
+ facemap[facenum] = -1;
+ }
}
static void object_fmap_swap_edit_mode(Object *ob, int num1, int num2)
{
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
-
- if (me->edit_mesh) {
- BMEditMesh *em = me->edit_mesh;
- const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
-
- if (cd_fmap_offset != -1) {
- BMFace *efa;
- BMIter iter;
- int *map;
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
-
- if (map) {
- if (num1 != -1) {
- if (*map == num1)
- *map = num2;
- else if (*map == num2)
- *map = num1;
- }
- }
- }
- }
- }
- }
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (me->edit_mesh) {
+ BMEditMesh *em = me->edit_mesh;
+ const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
+
+ if (cd_fmap_offset != -1) {
+ BMFace *efa;
+ BMIter iter;
+ int *map;
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
+
+ if (map) {
+ if (num1 != -1) {
+ if (*map == num1)
+ *map = num2;
+ else if (*map == num2)
+ *map = num1;
+ }
+ }
+ }
+ }
+ }
+ }
}
static void object_fmap_swap_object_mode(Object *ob, int num1, int num2)
{
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
-
- if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
- int *map = CustomData_get_layer(&me->pdata, CD_FACEMAP);
- int i;
-
- if (map) {
- for (i = 0; i < me->totpoly; i++) {
- if (num1 != -1) {
- if (map[i] == num1)
- map[i] = num2;
- else if (map[i] == num2)
- map[i] = num1;
- }
- }
- }
- }
- }
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
+ int *map = CustomData_get_layer(&me->pdata, CD_FACEMAP);
+ int i;
+
+ if (map) {
+ for (i = 0; i < me->totpoly; i++) {
+ if (num1 != -1) {
+ if (map[i] == num1)
+ map[i] = num2;
+ else if (map[i] == num2)
+ map[i] = num1;
+ }
+ }
+ }
+ }
+ }
}
static void object_facemap_swap(Object *ob, int num1, int num2)
{
- if (BKE_object_is_in_editmode(ob))
- object_fmap_swap_edit_mode(ob, num1, num2);
- else
- object_fmap_swap_object_mode(ob, num1, num2);
+ if (BKE_object_is_in_editmode(ob))
+ object_fmap_swap_edit_mode(ob, num1, num2);
+ else
+ object_fmap_swap_object_mode(ob, num1, num2);
}
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);
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
+ return (ob && !ob->id.lib && ob->type == OB_MESH && data && !data->lib);
}
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 (ob->mode == OB_MODE_EDIT) {
- return true;
- }
- }
- return false;
+ 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 (ob->mode == OB_MODE_EDIT) {
+ return true;
+ }
+ }
+ return false;
}
static int face_map_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- BKE_object_facemap_add(ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ BKE_object_facemap_add(ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_face_map_add(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Face Map";
- ot->idname = "OBJECT_OT_face_map_add";
- ot->description = "Add a new face map to the active object";
+ /* identifiers */
+ ot->name = "Add Face Map";
+ ot->idname = "OBJECT_OT_face_map_add";
+ ot->description = "Add a new face map to the active object";
- /* api callbacks */
- ot->poll = face_map_supported_poll;
- ot->exec = face_map_add_exec;
+ /* api callbacks */
+ ot->poll = face_map_supported_poll;
+ ot->exec = face_map_add_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int face_map_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
-
- if (fmap) {
- BKE_object_facemap_remove(ob, fmap);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- }
- return OPERATOR_FINISHED;
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+
+ if (fmap) {
+ BKE_object_facemap_remove(ob, fmap);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_face_map_remove(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Face Map";
- ot->idname = "OBJECT_OT_face_map_remove";
- ot->description = "Remove a face map from the active object";
+ /* identifiers */
+ ot->name = "Remove Face Map";
+ ot->idname = "OBJECT_OT_face_map_remove";
+ ot->description = "Remove a face map from the active object";
- /* api callbacks */
- ot->poll = face_map_supported_poll;
- ot->exec = face_map_remove_exec;
+ /* api callbacks */
+ ot->poll = face_map_supported_poll;
+ ot->exec = face_map_remove_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int face_map_assign_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
-
- if (fmap) {
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- BMFace *efa;
- BMIter iter;
- int *map;
- int cd_fmap_offset;
-
- if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP))
- BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP);
-
- cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
-
- if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- *map = ob->actfmap - 1;
- }
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- }
- return OPERATOR_FINISHED;
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+
+ if (fmap) {
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ BMFace *efa;
+ BMIter iter;
+ int *map;
+ int cd_fmap_offset;
+
+ if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP))
+ BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP);
+
+ cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
+
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
+ *map = ob->actfmap - 1;
+ }
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_face_map_assign(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Assign Face Map";
- ot->idname = "OBJECT_OT_face_map_assign";
- ot->description = "Assign faces to a face map";
+ /* identifiers */
+ ot->name = "Assign Face Map";
+ ot->idname = "OBJECT_OT_face_map_assign";
+ ot->description = "Assign faces to a face map";
- /* api callbacks */
- ot->poll = face_map_supported_edit_mode_poll;
- ot->exec = face_map_assign_exec;
+ /* api callbacks */
+ ot->poll = face_map_supported_edit_mode_poll;
+ ot->exec = face_map_assign_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int face_map_remove_from_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
-
- if (fmap) {
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- BMFace *efa;
- BMIter iter;
- int *map;
- int cd_fmap_offset;
- int mapindex = ob->actfmap - 1;
-
- if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP))
- return OPERATOR_CANCELLED;
-
- cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
-
- if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && *map == mapindex) {
- *map = -1;
- }
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- }
- return OPERATOR_FINISHED;
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+
+ if (fmap) {
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ BMFace *efa;
+ BMIter iter;
+ int *map;
+ int cd_fmap_offset;
+ int mapindex = ob->actfmap - 1;
+
+ if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP))
+ return OPERATOR_CANCELLED;
+
+ cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
+
+ if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && *map == mapindex) {
+ *map = -1;
+ }
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_face_map_remove_from(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove From Face Map";
- ot->idname = "OBJECT_OT_face_map_remove_from";
- ot->description = "Remove faces from a face map";
+ /* identifiers */
+ ot->name = "Remove From Face Map";
+ ot->idname = "OBJECT_OT_face_map_remove_from";
+ ot->description = "Remove faces from a face map";
- /* api callbacks */
- ot->poll = face_map_supported_edit_mode_poll;
- ot->exec = face_map_remove_from_exec;
+ /* api callbacks */
+ ot->poll = face_map_supported_edit_mode_poll;
+ ot->exec = face_map_remove_from_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static void fmap_select(Object *ob, bool select)
{
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- BMFace *efa;
- BMIter iter;
- int *map;
- int cd_fmap_offset;
- int mapindex = ob->actfmap - 1;
-
- if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP))
- BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP);
-
- cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
-
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
-
- if (*map == mapindex) {
- BM_face_select_set(em->bm, efa, select);
- }
- }
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ BMFace *efa;
+ BMIter iter;
+ int *map;
+ int cd_fmap_offset;
+ int mapindex = ob->actfmap - 1;
+
+ if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP))
+ BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP);
+
+ cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
+
+ if (*map == mapindex) {
+ BM_face_select_set(em->bm, efa, select);
+ }
+ }
}
static int face_map_select_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
- if (fmap) {
- fmap_select(ob, true);
+ if (fmap) {
+ fmap_select(ob, true);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- }
- return OPERATOR_FINISHED;
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_face_map_select(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Face Map Faces";
- ot->idname = "OBJECT_OT_face_map_select";
- ot->description = "Select faces belonging to a face map";
+ /* identifiers */
+ ot->name = "Select Face Map Faces";
+ ot->idname = "OBJECT_OT_face_map_select";
+ ot->description = "Select faces belonging to a face map";
- /* api callbacks */
- ot->poll = face_map_supported_edit_mode_poll;
- ot->exec = face_map_select_exec;
+ /* api callbacks */
+ ot->poll = face_map_supported_edit_mode_poll;
+ ot->exec = face_map_select_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int face_map_deselect_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
- if (fmap) {
- fmap_select(ob, false);
+ if (fmap) {
+ fmap_select(ob, false);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- }
- return OPERATOR_FINISHED;
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_face_map_deselect(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Deselect Face Map Faces";
- ot->idname = "OBJECT_OT_face_map_deselect";
- ot->description = "Deselect faces belonging to a face map";
+ /* identifiers */
+ ot->name = "Deselect Face Map Faces";
+ ot->idname = "OBJECT_OT_face_map_deselect";
+ ot->description = "Deselect faces belonging to a face map";
- /* api callbacks */
- ot->poll = face_map_supported_edit_mode_poll;
- ot->exec = face_map_deselect_exec;
+ /* api callbacks */
+ ot->poll = face_map_supported_edit_mode_poll;
+ ot->exec = face_map_deselect_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-
static int face_map_move_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- bFaceMap *fmap;
- int dir = RNA_enum_get(op->ptr, "direction");
- int pos1, pos2 = -1, count;
-
- fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
- if (!fmap) {
- return OPERATOR_CANCELLED;
- }
-
- count = BLI_listbase_count(&ob->fmaps);
- pos1 = BLI_findindex(&ob->fmaps, fmap);
-
- if (dir == 1) { /*up*/
- void *prev = fmap->prev;
-
- if (prev) {
- pos2 = pos1 - 1;
- }
- else {
- pos2 = count - 1;
- }
-
- BLI_remlink(&ob->fmaps, fmap);
- BLI_insertlinkbefore(&ob->fmaps, prev, fmap);
- }
- else { /*down*/
- void *next = fmap->next;
-
- if (next) {
- pos2 = pos1 + 1;
- }
- else {
- pos2 = 0;
- }
-
- BLI_remlink(&ob->fmaps, fmap);
- BLI_insertlinkafter(&ob->fmaps, next, fmap);
- }
-
- /* iterate through mesh and substitute the indices as necessary */
- object_facemap_swap(ob, pos2, pos1);
-
- ob->actfmap = pos2 + 1;
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
-
- return OPERATOR_FINISHED;
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap;
+ int dir = RNA_enum_get(op->ptr, "direction");
+ int pos1, pos2 = -1, count;
+
+ fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+ if (!fmap) {
+ return OPERATOR_CANCELLED;
+ }
+
+ count = BLI_listbase_count(&ob->fmaps);
+ pos1 = BLI_findindex(&ob->fmaps, fmap);
+
+ if (dir == 1) { /*up*/
+ void *prev = fmap->prev;
+
+ if (prev) {
+ pos2 = pos1 - 1;
+ }
+ else {
+ pos2 = count - 1;
+ }
+
+ BLI_remlink(&ob->fmaps, fmap);
+ BLI_insertlinkbefore(&ob->fmaps, prev, fmap);
+ }
+ else { /*down*/
+ void *next = fmap->next;
+
+ if (next) {
+ pos2 = pos1 + 1;
+ }
+ else {
+ pos2 = 0;
+ }
+
+ BLI_remlink(&ob->fmaps, fmap);
+ BLI_insertlinkafter(&ob->fmaps, next, fmap);
+ }
+
+ /* iterate through mesh and substitute the indices as necessary */
+ object_facemap_swap(ob, pos2, pos1);
+
+ ob->actfmap = pos2 + 1;
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
+
+ return OPERATOR_FINISHED;
}
-
void OBJECT_OT_face_map_move(wmOperatorType *ot)
{
- static EnumPropertyItem fmap_slot_move[] = {
- {1, "UP", 0, "Up", ""},
- {-1, "DOWN", 0, "Down", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Move Face Map";
- ot->idname = "OBJECT_OT_face_map_move";
- ot->description = "Move the active face map up/down in the list";
-
- /* api callbacks */
- ot->poll = face_map_supported_poll;
- ot->exec = face_map_move_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_enum(ot->srna, "direction", fmap_slot_move, 0, "Direction", "Direction to move, UP or DOWN");
+ static EnumPropertyItem fmap_slot_move[] = {
+ {1, "UP", 0, "Up", ""},
+ {-1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Move Face Map";
+ ot->idname = "OBJECT_OT_face_map_move";
+ ot->description = "Move the active face map up/down in the list";
+
+ /* api callbacks */
+ ot->poll = face_map_supported_poll;
+ ot->exec = face_map_move_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(
+ ot->srna, "direction", fmap_slot_move, 0, "Direction", "Direction to move, UP or DOWN");
}
diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c
index a1f529b3bde..a726e2c9f00 100644
--- a/source/blender/editors/object/object_gpencil_modifier.c
+++ b/source/blender/editors/object/object_gpencil_modifier.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
@@ -63,572 +62,611 @@
/******************************** API ****************************/
GpencilModifierData *ED_object_gpencil_modifier_add(
- ReportList *reports, Main *bmain, Scene *UNUSED(scene), Object *ob, const char *name, int type)
+ ReportList *reports, Main *bmain, Scene *UNUSED(scene), Object *ob, const char *name, int type)
{
- GpencilModifierData *new_md = NULL;
- const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(type);
-
- if (ob->type != OB_GPENCIL) {
- BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to object '%s'", ob->id.name + 2);
- return NULL;
- }
+ GpencilModifierData *new_md = NULL;
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(type);
- if (mti->flags & eGpencilModifierTypeFlag_Single) {
- if (BKE_gpencil_modifiers_findByType(ob, type)) {
- BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
- return NULL;
- }
- }
+ if (ob->type != OB_GPENCIL) {
+ BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to object '%s'", ob->id.name + 2);
+ return NULL;
+ }
- /* get new modifier data to add */
- new_md = BKE_gpencil_modifier_new(type);
+ if (mti->flags & eGpencilModifierTypeFlag_Single) {
+ if (BKE_gpencil_modifiers_findByType(ob, type)) {
+ BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
+ return NULL;
+ }
+ }
- BLI_addtail(&ob->greasepencil_modifiers, new_md);
+ /* get new modifier data to add */
+ new_md = BKE_gpencil_modifier_new(type);
- if (name) {
- BLI_strncpy_utf8(new_md->name, name, sizeof(new_md->name));
- }
+ BLI_addtail(&ob->greasepencil_modifiers, new_md);
- /* make sure modifier data has unique name */
- BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, new_md);
+ if (name) {
+ BLI_strncpy_utf8(new_md->name, name, sizeof(new_md->name));
+ }
+ /* make sure modifier data has unique name */
+ BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, new_md);
- bGPdata *gpd = ob->data;
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ bGPdata *gpd = ob->data;
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(bmain);
- return new_md;
+ 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)
+static bool UNUSED_FUNCTION(gpencil_object_has_modifier)(const Object *ob,
+ const GpencilModifierData *exclude,
+ GpencilModifierType type)
{
- GpencilModifierData *md;
+ GpencilModifierData *md;
- for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
- if ((md != exclude) && (md->type == type))
- return true;
- }
+ for (md = ob->greasepencil_modifiers.first; md; md = md->next) {
+ if ((md != exclude) && (md->type == type))
+ return true;
+ }
- return false;
+ return false;
}
-static bool gpencil_object_modifier_remove(
- Main *bmain, Object *ob, GpencilModifierData *md,
- bool *UNUSED(r_sort_depsgraph))
+static bool gpencil_object_modifier_remove(Main *bmain,
+ Object *ob,
+ GpencilModifierData *md,
+ bool *UNUSED(r_sort_depsgraph))
{
- /* It seems on rapid delete it is possible to
- * get called twice on same modifier, so make
- * sure it is in list. */
- if (BLI_findindex(&ob->greasepencil_modifiers, md) == -1) {
- return 0;
- }
+ /* It seems on rapid delete it is possible to
+ * get called twice on same modifier, so make
+ * sure it is in list. */
+ if (BLI_findindex(&ob->greasepencil_modifiers, md) == -1) {
+ return 0;
+ }
- DEG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
- BLI_remlink(&ob->greasepencil_modifiers, md);
- BKE_gpencil_modifier_free(md);
- BKE_object_free_derived_caches(ob);
+ BLI_remlink(&ob->greasepencil_modifiers, md);
+ BKE_gpencil_modifier_free(md);
+ BKE_object_free_derived_caches(ob);
- return 1;
+ return 1;
}
-bool ED_object_gpencil_modifier_remove(ReportList *reports, Main *bmain, Object *ob, GpencilModifierData *md)
+bool ED_object_gpencil_modifier_remove(ReportList *reports,
+ Main *bmain,
+ Object *ob,
+ GpencilModifierData *md)
{
- bool sort_depsgraph = false;
- bool ok;
+ bool sort_depsgraph = false;
+ bool ok;
- ok = gpencil_object_modifier_remove(bmain, ob, md, &sort_depsgraph);
+ ok = gpencil_object_modifier_remove(bmain, ob, md, &sort_depsgraph);
- if (!ok) {
- BKE_reportf(reports, RPT_ERROR, "Modifier '%s' not in object '%s'", md->name, ob->id.name);
- return 0;
- }
+ if (!ok) {
+ BKE_reportf(reports, RPT_ERROR, "Modifier '%s' not in object '%s'", md->name, ob->id.name);
+ return 0;
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(bmain);
- return 1;
+ return 1;
}
void ED_object_gpencil_modifier_clear(Main *bmain, Object *ob)
{
- GpencilModifierData *md = ob->greasepencil_modifiers.first;
- bool sort_depsgraph = false;
+ GpencilModifierData *md = ob->greasepencil_modifiers.first;
+ bool sort_depsgraph = false;
- if (!md)
- return;
+ if (!md)
+ return;
- while (md) {
- GpencilModifierData *next_md;
+ while (md) {
+ GpencilModifierData *next_md;
- next_md = md->next;
+ next_md = md->next;
- gpencil_object_modifier_remove(bmain, ob, md, &sort_depsgraph);
+ gpencil_object_modifier_remove(bmain, ob, md, &sort_depsgraph);
- md = next_md;
- }
+ md = next_md;
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(bmain);
}
-int ED_object_gpencil_modifier_move_up(ReportList *UNUSED(reports), Object *ob, GpencilModifierData *md)
+int ED_object_gpencil_modifier_move_up(ReportList *UNUSED(reports),
+ Object *ob,
+ GpencilModifierData *md)
{
- if (md->prev) {
- BLI_remlink(&ob->greasepencil_modifiers, md);
- BLI_insertlinkbefore(&ob->greasepencil_modifiers, md->prev, md);
- }
+ if (md->prev) {
+ BLI_remlink(&ob->greasepencil_modifiers, md);
+ BLI_insertlinkbefore(&ob->greasepencil_modifiers, md->prev, md);
+ }
- return 1;
+ return 1;
}
-int ED_object_gpencil_modifier_move_down(ReportList *UNUSED(reports), Object *ob, GpencilModifierData *md)
+int ED_object_gpencil_modifier_move_down(ReportList *UNUSED(reports),
+ Object *ob,
+ GpencilModifierData *md)
{
- if (md->next) {
- BLI_remlink(&ob->greasepencil_modifiers, md);
- BLI_insertlinkafter(&ob->greasepencil_modifiers, md->next, md);
- }
+ if (md->next) {
+ BLI_remlink(&ob->greasepencil_modifiers, md);
+ BLI_insertlinkafter(&ob->greasepencil_modifiers, md->next, md);
+ }
- return 1;
+ return 1;
}
static int gpencil_modifier_apply_obdata(
- ReportList *reports, Main *bmain, Depsgraph *depsgraph, Object *ob, GpencilModifierData *md)
-{
- const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
-
- if (mti->isDisabled && mti->isDisabled(md, 0)) {
- BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
- return 0;
- }
-
- if (ob->type == OB_GPENCIL) {
- if (ELEM(NULL, ob, ob->data)) {
- return 0;
- }
- else if (mti->bakeModifier == NULL) {
- BKE_report(reports, RPT_ERROR, "Not implemented");
- return 0;
- }
- mti->bakeModifier(bmain, depsgraph, md, ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- else {
- BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
- return 0;
- }
-
- return 1;
-}
-
-int ED_object_gpencil_modifier_apply(
- Main *bmain, ReportList *reports, Depsgraph *depsgraph,
- Object *ob, GpencilModifierData *md, int UNUSED(mode))
-{
-
- if (ob->type == OB_GPENCIL) {
- if (ob->mode != OB_MODE_OBJECT) {
- BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in paint, sculpt or edit mode");
- return 0;
- }
-
- if (((ID *)ob->data)->us > 1) {
- BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
- return 0;
- }
- }
- else if (((ID *)ob->data)->us > 1) {
- BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
- return 0;
- }
-
- if (md != ob->greasepencil_modifiers.first)
- BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected");
-
- if (!gpencil_modifier_apply_obdata(reports, bmain, depsgraph, ob, md)) {
- return 0;
- }
-
- BLI_remlink(&ob->greasepencil_modifiers, md);
- BKE_gpencil_modifier_free(md);
-
- return 1;
+ ReportList *reports, Main *bmain, Depsgraph *depsgraph, Object *ob, GpencilModifierData *md)
+{
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+
+ if (mti->isDisabled && mti->isDisabled(md, 0)) {
+ BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
+ return 0;
+ }
+
+ if (ob->type == OB_GPENCIL) {
+ if (ELEM(NULL, ob, ob->data)) {
+ return 0;
+ }
+ else if (mti->bakeModifier == NULL) {
+ BKE_report(reports, RPT_ERROR, "Not implemented");
+ return 0;
+ }
+ mti->bakeModifier(bmain, depsgraph, md, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ else {
+ BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
+ return 0;
+ }
+
+ return 1;
+}
+
+int ED_object_gpencil_modifier_apply(Main *bmain,
+ ReportList *reports,
+ Depsgraph *depsgraph,
+ Object *ob,
+ GpencilModifierData *md,
+ int UNUSED(mode))
+{
+
+ if (ob->type == OB_GPENCIL) {
+ if (ob->mode != OB_MODE_OBJECT) {
+ BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in paint, sculpt or edit mode");
+ return 0;
+ }
+
+ if (((ID *)ob->data)->us > 1) {
+ BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
+ return 0;
+ }
+ }
+ else if (((ID *)ob->data)->us > 1) {
+ BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
+ return 0;
+ }
+
+ if (md != ob->greasepencil_modifiers.first)
+ BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected");
+
+ if (!gpencil_modifier_apply_obdata(reports, bmain, depsgraph, ob, md)) {
+ return 0;
+ }
+
+ BLI_remlink(&ob->greasepencil_modifiers, md);
+ BKE_gpencil_modifier_free(md);
+
+ return 1;
}
int ED_object_gpencil_modifier_copy(ReportList *reports, Object *ob, GpencilModifierData *md)
{
- GpencilModifierData *nmd;
- const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
- GpencilModifierType type = md->type;
+ GpencilModifierData *nmd;
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
+ GpencilModifierType type = md->type;
- if (mti->flags & eGpencilModifierTypeFlag_Single) {
- if (BKE_gpencil_modifiers_findByType(ob, type)) {
- BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
- return 0;
- }
- }
+ if (mti->flags & eGpencilModifierTypeFlag_Single) {
+ if (BKE_gpencil_modifiers_findByType(ob, type)) {
+ BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
+ return 0;
+ }
+ }
- nmd = BKE_gpencil_modifier_new(md->type);
- BKE_gpencil_modifier_copyData(md, nmd);
- BLI_insertlinkafter(&ob->greasepencil_modifiers, md, nmd);
- BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, nmd);
+ nmd = BKE_gpencil_modifier_new(md->type);
+ BKE_gpencil_modifier_copyData(md, nmd);
+ BLI_insertlinkafter(&ob->greasepencil_modifiers, md, nmd);
+ BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, nmd);
- return 1;
+ return 1;
}
/************************ add modifier operator *********************/
static int gpencil_modifier_add_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- int type = RNA_enum_get(op->ptr, "type");
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ int type = RNA_enum_get(op->ptr, "type");
- if (!ED_object_gpencil_modifier_add(op->reports, bmain, scene, ob, NULL, type))
- return OPERATOR_CANCELLED;
+ if (!ED_object_gpencil_modifier_add(op->reports, bmain, scene, ob, NULL, type))
+ return OPERATOR_CANCELLED;
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static const EnumPropertyItem *gpencil_modifier_add_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *gpencil_modifier_add_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- Object *ob = ED_object_active_context(C);
- EnumPropertyItem *item = NULL;
- const EnumPropertyItem *md_item, *group_item = NULL;
- const GpencilModifierTypeInfo *mti;
- int totitem = 0, a;
+ Object *ob = ED_object_active_context(C);
+ EnumPropertyItem *item = NULL;
+ const EnumPropertyItem *md_item, *group_item = NULL;
+ const GpencilModifierTypeInfo *mti;
+ int totitem = 0, a;
- if (!ob)
- return rna_enum_object_greasepencil_modifier_type_items;
+ if (!ob)
+ return rna_enum_object_greasepencil_modifier_type_items;
- for (a = 0; rna_enum_object_greasepencil_modifier_type_items[a].identifier; a++) {
- md_item = &rna_enum_object_greasepencil_modifier_type_items[a];
- if (md_item->identifier[0]) {
- mti = BKE_gpencil_modifierType_getInfo(md_item->value);
+ for (a = 0; rna_enum_object_greasepencil_modifier_type_items[a].identifier; a++) {
+ md_item = &rna_enum_object_greasepencil_modifier_type_items[a];
+ if (md_item->identifier[0]) {
+ mti = BKE_gpencil_modifierType_getInfo(md_item->value);
- if (mti->flags & eGpencilModifierTypeFlag_NoUserAdd)
- continue;
- }
- else {
- group_item = md_item;
- md_item = NULL;
+ if (mti->flags & eGpencilModifierTypeFlag_NoUserAdd)
+ continue;
+ }
+ else {
+ group_item = md_item;
+ md_item = NULL;
- continue;
- }
+ continue;
+ }
- if (group_item) {
- RNA_enum_item_add(&item, &totitem, group_item);
- group_item = NULL;
- }
+ if (group_item) {
+ RNA_enum_item_add(&item, &totitem, group_item);
+ group_item = NULL;
+ }
- RNA_enum_item_add(&item, &totitem, md_item);
- }
+ RNA_enum_item_add(&item, &totitem, md_item);
+ }
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
- return item;
+ return item;
}
void OBJECT_OT_gpencil_modifier_add(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Add Grease Pencil Modifier";
- ot->description = "Add a procedural operation/effect to the active grease pencil object";
- ot->idname = "OBJECT_OT_gpencil_modifier_add";
+ /* identifiers */
+ ot->name = "Add Grease Pencil Modifier";
+ ot->description = "Add a procedural operation/effect to the active grease pencil object";
+ ot->idname = "OBJECT_OT_gpencil_modifier_add";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = gpencil_modifier_add_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = gpencil_modifier_add_exec;
+ ot->poll = ED_operator_object_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- prop = RNA_def_enum(ot->srna, "type", rna_enum_object_modifier_type_items, eGpencilModifierType_Thick, "Type", "");
- RNA_def_enum_funcs(prop, gpencil_modifier_add_itemf);
- ot->prop = prop;
+ /* properties */
+ prop = RNA_def_enum(ot->srna,
+ "type",
+ rna_enum_object_modifier_type_items,
+ eGpencilModifierType_Thick,
+ "Type",
+ "");
+ RNA_def_enum_funcs(prop, gpencil_modifier_add_itemf);
+ ot->prop = prop;
}
/************************ generic functions for operators using mod names and data context *********************/
static int gpencil_edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
- Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
+ Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
- if (!ob || ID_IS_LINKED(ob)) return 0;
- if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) return 0;
- if (ptr.id.data && ID_IS_LINKED(ptr.id.data)) return 0;
+ if (!ob || ID_IS_LINKED(ob))
+ return 0;
+ if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0)
+ return 0;
+ if (ptr.id.data && ID_IS_LINKED(ptr.id.data))
+ return 0;
- if (ID_IS_STATIC_OVERRIDE(ob)) {
- CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from static override");
- return (((GpencilModifierData *)ptr.data)->flag & eGpencilModifierFlag_StaticOverride_Local) != 0;
- }
+ if (ID_IS_STATIC_OVERRIDE(ob)) {
+ CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from static override");
+ return (((GpencilModifierData *)ptr.data)->flag & eGpencilModifierFlag_StaticOverride_Local) !=
+ 0;
+ }
- return 1;
+ return 1;
}
static bool gpencil_edit_modifier_poll(bContext *C)
{
- return gpencil_edit_modifier_poll_generic(C, &RNA_GpencilModifier, 0);
+ return gpencil_edit_modifier_poll_generic(C, &RNA_GpencilModifier, 0);
}
static void gpencil_edit_modifier_properties(wmOperatorType *ot)
{
- PropertyRNA *prop = RNA_def_string(ot->srna, "modifier", NULL, MAX_NAME, "Modifier", "Name of the modifier to edit");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ PropertyRNA *prop = RNA_def_string(
+ ot->srna, "modifier", NULL, MAX_NAME, "Modifier", "Name of the modifier to edit");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
static int gpencil_edit_modifier_invoke_properties(bContext *C, wmOperator *op)
{
- GpencilModifierData *md;
+ GpencilModifierData *md;
- 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;
- }
- }
+ 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;
+ }
+ }
- return false;
+ return false;
}
-static GpencilModifierData *gpencil_edit_modifier_property_get(wmOperator *op, Object *ob, int type)
+static GpencilModifierData *gpencil_edit_modifier_property_get(wmOperator *op,
+ Object *ob,
+ int type)
{
- char modifier_name[MAX_NAME];
- GpencilModifierData *md;
- RNA_string_get(op->ptr, "modifier", modifier_name);
+ char modifier_name[MAX_NAME];
+ GpencilModifierData *md;
+ RNA_string_get(op->ptr, "modifier", modifier_name);
- md = BKE_gpencil_modifiers_findByName(ob, modifier_name);
+ md = BKE_gpencil_modifiers_findByName(ob, modifier_name);
- if (md && type != 0 && md->type != type)
- md = NULL;
+ if (md && type != 0 && md->type != type)
+ md = NULL;
- return md;
+ return md;
}
/************************ remove modifier operator *********************/
static int gpencil_modifier_remove_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_active_context(C);
- GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
+ Main *bmain = CTX_data_main(C);
+ 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))
- return OPERATOR_CANCELLED;
+ if (!md || !ED_object_gpencil_modifier_remove(op->reports, bmain, ob, md))
+ return OPERATOR_CANCELLED;
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ 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 *UNUSED(event))
{
- if (gpencil_edit_modifier_invoke_properties(C, op))
- return gpencil_modifier_remove_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (gpencil_edit_modifier_invoke_properties(C, op))
+ return gpencil_modifier_remove_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_gpencil_modifier_remove(wmOperatorType *ot)
{
- ot->name = "Remove Grease Pencil Modifier";
- ot->description = "Remove a modifier from the active grease pencil object";
- ot->idname = "OBJECT_OT_gpencil_modifier_remove";
+ ot->name = "Remove Grease Pencil Modifier";
+ ot->description = "Remove a modifier from the active grease pencil object";
+ ot->idname = "OBJECT_OT_gpencil_modifier_remove";
- ot->invoke = gpencil_modifier_remove_invoke;
- ot->exec = gpencil_modifier_remove_exec;
- ot->poll = gpencil_edit_modifier_poll;
+ ot->invoke = gpencil_modifier_remove_invoke;
+ ot->exec = gpencil_modifier_remove_exec;
+ ot->poll = gpencil_edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- gpencil_edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ gpencil_edit_modifier_properties(ot);
}
/************************ move up modifier operator *********************/
static int gpencil_modifier_move_up_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
+ Object *ob = ED_object_active_context(C);
+ GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
- if (!md || !ED_object_gpencil_modifier_move_up(op->reports, ob, md))
- return OPERATOR_CANCELLED;
+ if (!md || !ED_object_gpencil_modifier_move_up(op->reports, ob, md))
+ return OPERATOR_CANCELLED;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ 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 *UNUSED(event))
{
- if (gpencil_edit_modifier_invoke_properties(C, op))
- return gpencil_modifier_move_up_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (gpencil_edit_modifier_invoke_properties(C, op))
+ return gpencil_modifier_move_up_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_gpencil_modifier_move_up(wmOperatorType *ot)
{
- ot->name = "Move Up Modifier";
- ot->description = "Move modifier up in the stack";
- ot->idname = "OBJECT_OT_gpencil_modifier_move_up";
+ ot->name = "Move Up Modifier";
+ ot->description = "Move modifier up in the stack";
+ ot->idname = "OBJECT_OT_gpencil_modifier_move_up";
- ot->invoke = gpencil_modifier_move_up_invoke;
- ot->exec = gpencil_modifier_move_up_exec;
- ot->poll = gpencil_edit_modifier_poll;
+ ot->invoke = gpencil_modifier_move_up_invoke;
+ ot->exec = gpencil_modifier_move_up_exec;
+ ot->poll = gpencil_edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- gpencil_edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ gpencil_edit_modifier_properties(ot);
}
/************************ move down modifier operator *********************/
static int gpencil_modifier_move_down_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
+ Object *ob = ED_object_active_context(C);
+ GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
- if (!md || !ED_object_gpencil_modifier_move_down(op->reports, ob, md))
- return OPERATOR_CANCELLED;
+ if (!md || !ED_object_gpencil_modifier_move_down(op->reports, ob, md))
+ return OPERATOR_CANCELLED;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ 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 *UNUSED(event))
{
- if (gpencil_edit_modifier_invoke_properties(C, op))
- return gpencil_modifier_move_down_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (gpencil_edit_modifier_invoke_properties(C, op))
+ return gpencil_modifier_move_down_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_gpencil_modifier_move_down(wmOperatorType *ot)
{
- ot->name = "Move Down Modifier";
- ot->description = "Move modifier down in the stack";
- ot->idname = "OBJECT_OT_gpencil_modifier_move_down";
+ ot->name = "Move Down Modifier";
+ ot->description = "Move modifier down in the stack";
+ ot->idname = "OBJECT_OT_gpencil_modifier_move_down";
- ot->invoke = gpencil_modifier_move_down_invoke;
- ot->exec = gpencil_modifier_move_down_exec;
- ot->poll = gpencil_edit_modifier_poll;
+ ot->invoke = gpencil_modifier_move_down_invoke;
+ ot->exec = gpencil_modifier_move_down_exec;
+ ot->poll = gpencil_edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- gpencil_edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ gpencil_edit_modifier_properties(ot);
}
/************************ apply modifier operator *********************/
static int gpencil_modifier_apply_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *ob = ED_object_active_context(C);
- GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
- int apply_as = RNA_enum_get(op->ptr, "apply_as");
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob = ED_object_active_context(C);
+ 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)) {
- return OPERATOR_CANCELLED;
- }
+ if (!md || !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);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int gpencil_modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (gpencil_edit_modifier_invoke_properties(C, op))
- return gpencil_modifier_apply_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (gpencil_edit_modifier_invoke_properties(C, op))
+ return gpencil_modifier_apply_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
static const EnumPropertyItem gpencil_modifier_apply_as_items[] = {
- {MODIFIER_APPLY_DATA, "DATA", 0, "Object Data", "Apply modifier to the object's data"},
- {MODIFIER_APPLY_SHAPE, "SHAPE", 0, "New Shape", "Apply deform-only modifier to a new shape on this object"},
- {0, NULL, 0, NULL, NULL},
+ {MODIFIER_APPLY_DATA, "DATA", 0, "Object Data", "Apply modifier to the object's data"},
+ {MODIFIER_APPLY_SHAPE,
+ "SHAPE",
+ 0,
+ "New Shape",
+ "Apply deform-only modifier to a new shape on this object"},
+ {0, NULL, 0, NULL, NULL},
};
void OBJECT_OT_gpencil_modifier_apply(wmOperatorType *ot)
{
- ot->name = "Apply Modifier";
- ot->description = "Apply modifier and remove from the stack";
- ot->idname = "OBJECT_OT_gpencil_modifier_apply";
+ ot->name = "Apply Modifier";
+ ot->description = "Apply modifier and remove from the stack";
+ ot->idname = "OBJECT_OT_gpencil_modifier_apply";
- ot->invoke = gpencil_modifier_apply_invoke;
- ot->exec = gpencil_modifier_apply_exec;
- ot->poll = gpencil_edit_modifier_poll;
+ ot->invoke = gpencil_modifier_apply_invoke;
+ ot->exec = gpencil_modifier_apply_exec;
+ ot->poll = gpencil_edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- RNA_def_enum(ot->srna, "apply_as", gpencil_modifier_apply_as_items, MODIFIER_APPLY_DATA, "Apply as", "How to apply the modifier to the geometry");
- gpencil_edit_modifier_properties(ot);
+ RNA_def_enum(ot->srna,
+ "apply_as",
+ gpencil_modifier_apply_as_items,
+ MODIFIER_APPLY_DATA,
+ "Apply as",
+ "How to apply the modifier to the geometry");
+ gpencil_edit_modifier_properties(ot);
}
/************************ copy modifier operator *********************/
static int gpencil_modifier_copy_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
+ Object *ob = ED_object_active_context(C);
+ GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
- if (!md || !ED_object_gpencil_modifier_copy(op->reports, ob, md))
- return OPERATOR_CANCELLED;
+ if (!md || !ED_object_gpencil_modifier_copy(op->reports, ob, md))
+ return OPERATOR_CANCELLED;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int gpencil_modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (gpencil_edit_modifier_invoke_properties(C, op))
- return gpencil_modifier_copy_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (gpencil_edit_modifier_invoke_properties(C, op))
+ return gpencil_modifier_copy_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_gpencil_modifier_copy(wmOperatorType *ot)
{
- ot->name = "Copy Modifier";
- ot->description = "Duplicate modifier at the same position in the stack";
- ot->idname = "OBJECT_OT_gpencil_modifier_copy";
+ ot->name = "Copy Modifier";
+ ot->description = "Duplicate modifier at the same position in the stack";
+ ot->idname = "OBJECT_OT_gpencil_modifier_copy";
- ot->invoke = gpencil_modifier_copy_invoke;
- ot->exec = gpencil_modifier_copy_exec;
- ot->poll = gpencil_edit_modifier_poll;
+ ot->invoke = gpencil_modifier_copy_invoke;
+ ot->exec = gpencil_modifier_copy_exec;
+ ot->poll = gpencil_edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- gpencil_edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ gpencil_edit_modifier_properties(ot);
}
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index 401260df406..d4e5ba42be2 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include <stdlib.h>
#include <string.h>
@@ -69,857 +68,897 @@
#include "object_intern.h"
-static int return_editmesh_indexar(
- BMEditMesh *em,
- int *r_tot, int **r_indexar, float r_cent[3])
+static int return_editmesh_indexar(BMEditMesh *em, int *r_tot, int **r_indexar, float r_cent[3])
{
- BMVert *eve;
- BMIter iter;
- int *index, nr, totvert = 0;
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) totvert++;
- }
- if (totvert == 0) return 0;
-
- *r_indexar = index = MEM_mallocN(4 * totvert, "hook indexar");
- *r_tot = totvert;
- nr = 0;
- zero_v3(r_cent);
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- *index = nr; index++;
- add_v3_v3(r_cent, eve->co);
- }
- nr++;
- }
-
- mul_v3_fl(r_cent, 1.0f / (float)totvert);
-
- return totvert;
+ BMVert *eve;
+ BMIter iter;
+ int *index, nr, totvert = 0;
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT))
+ totvert++;
+ }
+ if (totvert == 0)
+ return 0;
+
+ *r_indexar = index = MEM_mallocN(4 * totvert, "hook indexar");
+ *r_tot = totvert;
+ nr = 0;
+ zero_v3(r_cent);
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ *index = nr;
+ index++;
+ add_v3_v3(r_cent, eve->co);
+ }
+ nr++;
+ }
+
+ mul_v3_fl(r_cent, 1.0f / (float)totvert);
+
+ return totvert;
}
static bool return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *r_name, float r_cent[3])
{
- const int cd_dvert_offset = obedit->actdef ? CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT) : -1;
-
- zero_v3(r_cent);
-
- if (cd_dvert_offset != -1) {
- const int defgrp_index = obedit->actdef - 1;
- int totvert = 0;
-
- MDeformVert *dvert;
- BMVert *eve;
- BMIter iter;
-
- /* find the vertices */
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
-
- if (defvert_find_weight(dvert, defgrp_index) > 0.0f) {
- add_v3_v3(r_cent, eve->co);
- totvert++;
- }
- }
- if (totvert) {
- bDeformGroup *dg = BLI_findlink(&obedit->defbase, defgrp_index);
- BLI_strncpy(r_name, dg->name, sizeof(dg->name));
- mul_v3_fl(r_cent, 1.0f / (float)totvert);
- return true;
- }
- }
-
- return false;
+ const int cd_dvert_offset = obedit->actdef ?
+ CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT) :
+ -1;
+
+ zero_v3(r_cent);
+
+ if (cd_dvert_offset != -1) {
+ const int defgrp_index = obedit->actdef - 1;
+ int totvert = 0;
+
+ MDeformVert *dvert;
+ BMVert *eve;
+ BMIter iter;
+
+ /* find the vertices */
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+
+ if (defvert_find_weight(dvert, defgrp_index) > 0.0f) {
+ add_v3_v3(r_cent, eve->co);
+ totvert++;
+ }
+ }
+ if (totvert) {
+ bDeformGroup *dg = BLI_findlink(&obedit->defbase, defgrp_index);
+ BLI_strncpy(r_name, dg->name, sizeof(dg->name));
+ mul_v3_fl(r_cent, 1.0f / (float)totvert);
+ return true;
+ }
+ }
+
+ return false;
}
static void select_editbmesh_hook(Object *ob, HookModifierData *hmd)
{
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- BMVert *eve;
- BMIter iter;
- int index = 0, nr = 0;
-
- if (hmd->indexar == NULL)
- return;
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (nr == hmd->indexar[index]) {
- BM_vert_select_set(em->bm, eve, true);
- if (index < hmd->totindex - 1) index++;
- }
-
- nr++;
- }
-
- EDBM_select_flush(em);
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ BMVert *eve;
+ BMIter iter;
+ int index = 0, nr = 0;
+
+ if (hmd->indexar == NULL)
+ return;
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (nr == hmd->indexar[index]) {
+ BM_vert_select_set(em->bm, eve, true);
+ if (index < hmd->totindex - 1)
+ index++;
+ }
+
+ nr++;
+ }
+
+ EDBM_select_flush(em);
}
-static int return_editlattice_indexar(
- Lattice *editlatt,
- int *r_tot, int **r_indexar, float r_cent[3])
+static int return_editlattice_indexar(Lattice *editlatt,
+ int *r_tot,
+ int **r_indexar,
+ float r_cent[3])
{
- BPoint *bp;
- int *index, nr, totvert = 0, a;
-
- /* count */
- a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw;
- bp = editlatt->def;
- while (a--) {
- if (bp->f1 & SELECT) {
- if (bp->hide == 0) totvert++;
- }
- bp++;
- }
-
- if (totvert == 0) return 0;
-
- *r_indexar = index = MEM_mallocN(4 * totvert, "hook indexar");
- *r_tot = totvert;
- nr = 0;
- zero_v3(r_cent);
-
- a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw;
- bp = editlatt->def;
- while (a--) {
- if (bp->f1 & SELECT) {
- if (bp->hide == 0) {
- *index = nr; index++;
- add_v3_v3(r_cent, bp->vec);
- }
- }
- bp++;
- nr++;
- }
-
- mul_v3_fl(r_cent, 1.0f / (float)totvert);
-
- return totvert;
+ BPoint *bp;
+ int *index, nr, totvert = 0, a;
+
+ /* count */
+ a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw;
+ bp = editlatt->def;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ if (bp->hide == 0)
+ totvert++;
+ }
+ bp++;
+ }
+
+ if (totvert == 0)
+ return 0;
+
+ *r_indexar = index = MEM_mallocN(4 * totvert, "hook indexar");
+ *r_tot = totvert;
+ nr = 0;
+ zero_v3(r_cent);
+
+ a = editlatt->pntsu * editlatt->pntsv * editlatt->pntsw;
+ bp = editlatt->def;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ if (bp->hide == 0) {
+ *index = nr;
+ index++;
+ add_v3_v3(r_cent, bp->vec);
+ }
+ }
+ bp++;
+ nr++;
+ }
+
+ mul_v3_fl(r_cent, 1.0f / (float)totvert);
+
+ return totvert;
}
static void select_editlattice_hook(Object *obedit, HookModifierData *hmd)
{
- Lattice *lt = obedit->data, *editlt;
- BPoint *bp;
- int index = 0, nr = 0, a;
-
- editlt = lt->editlatt->latt;
- /* count */
- a = editlt->pntsu * editlt->pntsv * editlt->pntsw;
- bp = editlt->def;
- while (a--) {
- if (hmd->indexar[index] == nr) {
- bp->f1 |= SELECT;
- if (index < hmd->totindex - 1) index++;
- }
- nr++;
- bp++;
- }
+ Lattice *lt = obedit->data, *editlt;
+ BPoint *bp;
+ int index = 0, nr = 0, a;
+
+ editlt = lt->editlatt->latt;
+ /* count */
+ a = editlt->pntsu * editlt->pntsv * editlt->pntsw;
+ bp = editlt->def;
+ while (a--) {
+ if (hmd->indexar[index] == nr) {
+ bp->f1 |= SELECT;
+ if (index < hmd->totindex - 1)
+ index++;
+ }
+ nr++;
+ bp++;
+ }
}
-static int return_editcurve_indexar(
- Object *obedit,
- int *r_tot, int **r_indexar, float r_cent[3])
+static int return_editcurve_indexar(Object *obedit, int *r_tot, int **r_indexar, float r_cent[3])
{
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- BPoint *bp;
- BezTriple *bezt;
- int *index, a, nr, totvert = 0;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if (bezt->f1 & SELECT) totvert++;
- if (bezt->f2 & SELECT) totvert++;
- if (bezt->f3 & SELECT) totvert++;
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- if (bp->f1 & SELECT) totvert++;
- bp++;
- }
- }
- }
- if (totvert == 0) return 0;
-
- *r_indexar = index = MEM_mallocN(sizeof(*index) * totvert, "hook indexar");
- *r_tot = totvert;
- nr = 0;
- zero_v3(r_cent);
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if (bezt->f1 & SELECT) {
- *index = nr; index++;
- add_v3_v3(r_cent, bezt->vec[0]);
- }
- nr++;
- if (bezt->f2 & SELECT) {
- *index = nr; index++;
- add_v3_v3(r_cent, bezt->vec[1]);
- }
- nr++;
- if (bezt->f3 & SELECT) {
- *index = nr; index++;
- add_v3_v3(r_cent, bezt->vec[2]);
- }
- nr++;
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- if (bp->f1 & SELECT) {
- *index = nr; index++;
- add_v3_v3(r_cent, bp->vec);
- }
- nr++;
- bp++;
- }
- }
- }
-
- mul_v3_fl(r_cent, 1.0f / (float)totvert);
-
- return totvert;
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int *index, a, nr, totvert = 0;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ if (bezt->f1 & SELECT)
+ totvert++;
+ if (bezt->f2 & SELECT)
+ totvert++;
+ if (bezt->f3 & SELECT)
+ totvert++;
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ if (bp->f1 & SELECT)
+ totvert++;
+ bp++;
+ }
+ }
+ }
+ if (totvert == 0)
+ return 0;
+
+ *r_indexar = index = MEM_mallocN(sizeof(*index) * totvert, "hook indexar");
+ *r_tot = totvert;
+ nr = 0;
+ zero_v3(r_cent);
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ if (bezt->f1 & SELECT) {
+ *index = nr;
+ index++;
+ add_v3_v3(r_cent, bezt->vec[0]);
+ }
+ nr++;
+ if (bezt->f2 & SELECT) {
+ *index = nr;
+ index++;
+ add_v3_v3(r_cent, bezt->vec[1]);
+ }
+ nr++;
+ if (bezt->f3 & SELECT) {
+ *index = nr;
+ index++;
+ add_v3_v3(r_cent, bezt->vec[2]);
+ }
+ nr++;
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ *index = nr;
+ index++;
+ add_v3_v3(r_cent, bp->vec);
+ }
+ nr++;
+ bp++;
+ }
+ }
+ }
+
+ mul_v3_fl(r_cent, 1.0f / (float)totvert);
+
+ return totvert;
}
-static bool object_hook_index_array(Main *bmain, Scene *scene, Object *obedit,
- int *r_tot, int **r_indexar, char *r_name, float r_cent[3])
+static bool object_hook_index_array(Main *bmain,
+ Scene *scene,
+ Object *obedit,
+ int *r_tot,
+ int **r_indexar,
+ char *r_name,
+ float r_cent[3])
{
- *r_indexar = NULL;
- *r_tot = 0;
- r_name[0] = 0;
-
- switch (obedit->type) {
- case OB_MESH:
- {
- Mesh *me = obedit->data;
-
- BMEditMesh *em;
-
- EDBM_mesh_load(bmain, obedit);
- EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true);
-
- DEG_id_tag_update(obedit->data, 0);
-
- em = me->edit_mesh;
-
- EDBM_mesh_normals_update(em);
- BKE_editmesh_tessface_calc(em);
-
- /* check selected vertices first */
- if (return_editmesh_indexar(em, r_tot, r_indexar, r_cent) == 0) {
- return return_editmesh_vgroup(obedit, em, r_name, r_cent);
- }
- return true;
- }
- case OB_CURVE:
- case OB_SURF:
- ED_curve_editnurb_load(bmain, obedit);
- ED_curve_editnurb_make(obedit);
- return return_editcurve_indexar(obedit, r_tot, r_indexar, r_cent);
- case OB_LATTICE:
- {
- Lattice *lt = obedit->data;
- return return_editlattice_indexar(lt->editlatt->latt, r_tot, r_indexar, r_cent);
- }
- default:
- return false;
- }
+ *r_indexar = NULL;
+ *r_tot = 0;
+ r_name[0] = 0;
+
+ switch (obedit->type) {
+ case OB_MESH: {
+ Mesh *me = obedit->data;
+
+ BMEditMesh *em;
+
+ EDBM_mesh_load(bmain, obedit);
+ EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true);
+
+ DEG_id_tag_update(obedit->data, 0);
+
+ em = me->edit_mesh;
+
+ EDBM_mesh_normals_update(em);
+ BKE_editmesh_tessface_calc(em);
+
+ /* check selected vertices first */
+ if (return_editmesh_indexar(em, r_tot, r_indexar, r_cent) == 0) {
+ return return_editmesh_vgroup(obedit, em, r_name, r_cent);
+ }
+ return true;
+ }
+ case OB_CURVE:
+ case OB_SURF:
+ ED_curve_editnurb_load(bmain, obedit);
+ ED_curve_editnurb_make(obedit);
+ return return_editcurve_indexar(obedit, r_tot, r_indexar, r_cent);
+ case OB_LATTICE: {
+ Lattice *lt = obedit->data;
+ return return_editlattice_indexar(lt->editlatt->latt, r_tot, r_indexar, r_cent);
+ }
+ default:
+ return false;
+ }
}
static void select_editcurve_hook(Object *obedit, HookModifierData *hmd)
{
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- BPoint *bp;
- BezTriple *bezt;
- int index = 0, a, nr = 0;
-
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if (nr == hmd->indexar[index]) {
- bezt->f1 |= SELECT;
- if (index < hmd->totindex - 1) index++;
- }
- nr++;
- if (nr == hmd->indexar[index]) {
- bezt->f2 |= SELECT;
- if (index < hmd->totindex - 1) index++;
- }
- nr++;
- if (nr == hmd->indexar[index]) {
- bezt->f3 |= SELECT;
- if (index < hmd->totindex - 1) index++;
- }
- nr++;
-
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- if (nr == hmd->indexar[index]) {
- bp->f1 |= SELECT;
- if (index < hmd->totindex - 1) index++;
- }
- nr++;
- bp++;
- }
- }
- }
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ BPoint *bp;
+ BezTriple *bezt;
+ int index = 0, a, nr = 0;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ if (nr == hmd->indexar[index]) {
+ bezt->f1 |= SELECT;
+ if (index < hmd->totindex - 1)
+ index++;
+ }
+ nr++;
+ if (nr == hmd->indexar[index]) {
+ bezt->f2 |= SELECT;
+ if (index < hmd->totindex - 1)
+ index++;
+ }
+ nr++;
+ if (nr == hmd->indexar[index]) {
+ bezt->f3 |= SELECT;
+ if (index < hmd->totindex - 1)
+ index++;
+ }
+ nr++;
+
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ if (nr == hmd->indexar[index]) {
+ bp->f1 |= SELECT;
+ if (index < hmd->totindex - 1)
+ index++;
+ }
+ nr++;
+ bp++;
+ }
+ }
+ }
}
-static void object_hook_from_context(bContext *C, PointerRNA *ptr, const int num,
- Object **r_ob, HookModifierData **r_hmd)
+static void object_hook_from_context(
+ bContext *C, PointerRNA *ptr, const int num, Object **r_ob, HookModifierData **r_hmd)
{
- Object *ob;
- HookModifierData *hmd;
-
- if (ptr->data) { /* if modifier context is available, use that */
- ob = ptr->id.data;
- hmd = ptr->data;
- }
- else { /* use the provided property */
- ob = CTX_data_edit_object(C);
- hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
- }
-
- if (ob && hmd && (hmd->modifier.type == eModifierType_Hook)) {
- *r_ob = ob;
- *r_hmd = hmd;
- }
- else {
- *r_ob = NULL;
- *r_hmd = NULL;
- }
+ Object *ob;
+ HookModifierData *hmd;
+
+ if (ptr->data) { /* if modifier context is available, use that */
+ ob = ptr->id.data;
+ hmd = ptr->data;
+ }
+ else { /* use the provided property */
+ ob = CTX_data_edit_object(C);
+ hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
+ }
+
+ if (ob && hmd && (hmd->modifier.type == eModifierType_Hook)) {
+ *r_ob = ob;
+ *r_hmd = hmd;
+ }
+ else {
+ *r_ob = NULL;
+ *r_hmd = NULL;
+ }
}
static void object_hook_select(Object *ob, HookModifierData *hmd)
{
- if (hmd->indexar == NULL)
- return;
-
- if (ob->type == OB_MESH) select_editbmesh_hook(ob, hmd);
- else if (ob->type == OB_LATTICE) select_editlattice_hook(ob, hmd);
- else if (ob->type == OB_CURVE) select_editcurve_hook(ob, hmd);
- else if (ob->type == OB_SURF) select_editcurve_hook(ob, hmd);
+ if (hmd->indexar == NULL)
+ return;
+
+ if (ob->type == OB_MESH)
+ select_editbmesh_hook(ob, hmd);
+ else if (ob->type == OB_LATTICE)
+ select_editlattice_hook(ob, hmd);
+ else if (ob->type == OB_CURVE)
+ select_editcurve_hook(ob, hmd);
+ else if (ob->type == OB_SURF)
+ select_editcurve_hook(ob, hmd);
}
/* special poll operators for hook operators */
/* TODO: check for properties window modifier context too as alternative? */
static bool hook_op_edit_poll(bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
-
- if (obedit) {
- if (ED_operator_editmesh(C)) return 1;
- if (ED_operator_editsurfcurve(C)) return 1;
- if (ED_operator_editlattice(C)) return 1;
- //if (ED_operator_editmball(C)) return 1;
- }
-
- return 0;
+ Object *obedit = CTX_data_edit_object(C);
+
+ if (obedit) {
+ if (ED_operator_editmesh(C))
+ return 1;
+ if (ED_operator_editsurfcurve(C))
+ return 1;
+ if (ED_operator_editlattice(C))
+ return 1;
+ //if (ED_operator_editmball(C)) return 1;
+ }
+
+ return 0;
}
-static Object *add_hook_object_new(Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, Object *obedit)
+static Object *add_hook_object_new(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, Object *obedit)
{
- Base *basedit;
- Object *ob;
+ Base *basedit;
+ Object *ob;
- ob = BKE_object_add(bmain, scene, view_layer, OB_EMPTY, NULL);
+ ob = BKE_object_add(bmain, scene, view_layer, OB_EMPTY, NULL);
- basedit = BKE_view_layer_base_find(view_layer, obedit);
- BLI_assert(view_layer->basact->object == ob);
+ basedit = BKE_view_layer_base_find(view_layer, obedit);
+ BLI_assert(view_layer->basact->object == ob);
- if (v3d && v3d->localvd) {
- view_layer->basact->local_view_bits |= v3d->local_view_uuid;
- }
+ if (v3d && v3d->localvd) {
+ view_layer->basact->local_view_bits |= v3d->local_view_uuid;
+ }
- /* icky, BKE_object_add sets new base as active.
- * so set it back to the original edit object */
- view_layer->basact = basedit;
+ /* icky, BKE_object_add sets new base as active.
+ * so set it back to the original edit object */
+ view_layer->basact = basedit;
- return ob;
+ return ob;
}
-static int add_hook_object(
- const bContext *C,
- Main *bmain,
- Scene *scene,
- ViewLayer *view_layer,
- View3D *v3d,
- Object *obedit,
- Object *ob,
- int mode,
- ReportList *reports)
+static int add_hook_object(const bContext *C,
+ Main *bmain,
+ Scene *scene,
+ ViewLayer *view_layer,
+ View3D *v3d,
+ Object *obedit,
+ Object *ob,
+ int mode,
+ ReportList *reports)
{
- ModifierData *md = NULL;
- HookModifierData *hmd = NULL;
- float cent[3];
- float pose_mat[4][4];
- int tot, ok, *indexar;
- char name[MAX_NAME];
-
- ok = object_hook_index_array(bmain, scene, obedit, &tot, &indexar, name, cent);
-
- if (!ok) {
- BKE_report(reports, RPT_ERROR, "Requires selected vertices or active vertex group");
- return false;
- }
-
- if (mode == OBJECT_ADDHOOK_NEWOB && !ob) {
-
- ob = add_hook_object_new(bmain, scene, view_layer, v3d, obedit);
-
- /* transform cent to global coords for loc */
- mul_v3_m4v3(ob->loc, obedit->obmat, cent);
- }
-
- md = obedit->modifiers.first;
- while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform) {
- md = md->next;
- }
-
- hmd = (HookModifierData *) modifier_new(eModifierType_Hook);
- BLI_insertlinkbefore(&obedit->modifiers, md, hmd);
- BLI_snprintf(hmd->modifier.name, sizeof(hmd->modifier.name), "Hook-%s", ob->id.name + 2);
- modifier_unique_name(&obedit->modifiers, (ModifierData *)hmd);
-
- hmd->object = ob;
- hmd->indexar = indexar;
- copy_v3_v3(hmd->cent, cent);
- hmd->totindex = tot;
- BLI_strncpy(hmd->name, name, sizeof(hmd->name));
-
- unit_m4(pose_mat);
-
- invert_m4_m4(obedit->imat, obedit->obmat);
- if (mode == OBJECT_ADDHOOK_NEWOB) {
- /* pass */
- }
- else {
- /* may overwrite with pose-bone location, below */
- mul_v3_m4v3(cent, obedit->imat, ob->obmat[3]);
- }
-
- if (mode == OBJECT_ADDHOOK_SELOB_BONE) {
- bArmature *arm = ob->data;
- BLI_assert(ob->type == OB_ARMATURE);
- if (arm->act_bone) {
- bPoseChannel *pchan_act;
-
- BLI_strncpy(hmd->subtarget, arm->act_bone->name, sizeof(hmd->subtarget));
-
- pchan_act = BKE_pose_channel_active(ob);
- if (LIKELY(pchan_act)) {
- invert_m4_m4(pose_mat, pchan_act->pose_mat);
- mul_v3_m4v3(cent, ob->obmat, pchan_act->pose_mat[3]);
- mul_v3_m4v3(cent, obedit->imat, cent);
- }
- }
- else {
- BKE_report(reports, RPT_WARNING, "Armature has no active object bone");
- }
- }
-
- copy_v3_v3(hmd->cent, cent);
-
-
- /* matrix calculus */
- /* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
- /* (parentinv ) */
- BKE_object_where_is_calc(CTX_data_depsgraph(C), scene, ob);
-
- invert_m4_m4(ob->imat, ob->obmat);
- /* apparently this call goes from right to left... */
- mul_m4_series(hmd->parentinv, pose_mat, ob->imat, obedit->obmat);
-
- DEG_relations_tag_update(bmain);
-
- return true;
+ ModifierData *md = NULL;
+ HookModifierData *hmd = NULL;
+ float cent[3];
+ float pose_mat[4][4];
+ int tot, ok, *indexar;
+ char name[MAX_NAME];
+
+ ok = object_hook_index_array(bmain, scene, obedit, &tot, &indexar, name, cent);
+
+ if (!ok) {
+ BKE_report(reports, RPT_ERROR, "Requires selected vertices or active vertex group");
+ return false;
+ }
+
+ if (mode == OBJECT_ADDHOOK_NEWOB && !ob) {
+
+ ob = add_hook_object_new(bmain, scene, view_layer, v3d, obedit);
+
+ /* transform cent to global coords for loc */
+ mul_v3_m4v3(ob->loc, obedit->obmat, cent);
+ }
+
+ md = obedit->modifiers.first;
+ while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform) {
+ md = md->next;
+ }
+
+ hmd = (HookModifierData *)modifier_new(eModifierType_Hook);
+ BLI_insertlinkbefore(&obedit->modifiers, md, hmd);
+ BLI_snprintf(hmd->modifier.name, sizeof(hmd->modifier.name), "Hook-%s", ob->id.name + 2);
+ modifier_unique_name(&obedit->modifiers, (ModifierData *)hmd);
+
+ hmd->object = ob;
+ hmd->indexar = indexar;
+ copy_v3_v3(hmd->cent, cent);
+ hmd->totindex = tot;
+ BLI_strncpy(hmd->name, name, sizeof(hmd->name));
+
+ unit_m4(pose_mat);
+
+ invert_m4_m4(obedit->imat, obedit->obmat);
+ if (mode == OBJECT_ADDHOOK_NEWOB) {
+ /* pass */
+ }
+ else {
+ /* may overwrite with pose-bone location, below */
+ mul_v3_m4v3(cent, obedit->imat, ob->obmat[3]);
+ }
+
+ if (mode == OBJECT_ADDHOOK_SELOB_BONE) {
+ bArmature *arm = ob->data;
+ BLI_assert(ob->type == OB_ARMATURE);
+ if (arm->act_bone) {
+ bPoseChannel *pchan_act;
+
+ BLI_strncpy(hmd->subtarget, arm->act_bone->name, sizeof(hmd->subtarget));
+
+ pchan_act = BKE_pose_channel_active(ob);
+ if (LIKELY(pchan_act)) {
+ invert_m4_m4(pose_mat, pchan_act->pose_mat);
+ mul_v3_m4v3(cent, ob->obmat, pchan_act->pose_mat[3]);
+ mul_v3_m4v3(cent, obedit->imat, cent);
+ }
+ }
+ else {
+ BKE_report(reports, RPT_WARNING, "Armature has no active object bone");
+ }
+ }
+
+ copy_v3_v3(hmd->cent, cent);
+
+ /* matrix calculus */
+ /* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
+ /* (parentinv ) */
+ BKE_object_where_is_calc(CTX_data_depsgraph(C), scene, ob);
+
+ invert_m4_m4(ob->imat, ob->obmat);
+ /* apparently this call goes from right to left... */
+ mul_m4_series(hmd->parentinv, pose_mat, ob->imat, obedit->obmat);
+
+ DEG_relations_tag_update(bmain);
+
+ return true;
}
static int object_add_hook_selob_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *obedit = CTX_data_edit_object(C);
- Object *obsel = NULL;
- const bool use_bone = RNA_boolean_get(op->ptr, "use_bone");
- const int mode = use_bone ? OBJECT_ADDHOOK_SELOB_BONE : OBJECT_ADDHOOK_SELOB;
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- if (ob != obedit) {
- obsel = ob;
- break;
- }
- }
- CTX_DATA_END;
-
- if (!obsel) {
- BKE_report(op->reports, RPT_ERROR, "Cannot add hook with no other selected objects");
- return OPERATOR_CANCELLED;
- }
-
- if (use_bone && obsel->type != OB_ARMATURE) {
- BKE_report(op->reports, RPT_ERROR, "Cannot add hook bone for a non armature object");
- return OPERATOR_CANCELLED;
- }
-
- if (add_hook_object(C, bmain, scene, view_layer, NULL, obedit, obsel, mode, op->reports)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obedit = CTX_data_edit_object(C);
+ Object *obsel = NULL;
+ const bool use_bone = RNA_boolean_get(op->ptr, "use_bone");
+ const int mode = use_bone ? OBJECT_ADDHOOK_SELOB_BONE : OBJECT_ADDHOOK_SELOB;
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ if (ob != obedit) {
+ obsel = ob;
+ break;
+ }
+ }
+ CTX_DATA_END;
+
+ if (!obsel) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot add hook with no other selected objects");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (use_bone && obsel->type != OB_ARMATURE) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot add hook bone for a non armature object");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (add_hook_object(C, bmain, scene, view_layer, NULL, obedit, obsel, mode, op->reports)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void OBJECT_OT_hook_add_selob(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hook to Selected Object";
- ot->description = "Hook selected vertices to the first selected object";
- ot->idname = "OBJECT_OT_hook_add_selob";
-
- /* api callbacks */
- ot->exec = object_add_hook_selob_exec;
- ot->poll = hook_op_edit_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "use_bone", false, "Active Bone",
- "Assign the hook to the hook objects active bone");
+ /* identifiers */
+ ot->name = "Hook to Selected Object";
+ ot->description = "Hook selected vertices to the first selected object";
+ ot->idname = "OBJECT_OT_hook_add_selob";
+
+ /* api callbacks */
+ ot->exec = object_add_hook_selob_exec;
+ ot->poll = hook_op_edit_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna,
+ "use_bone",
+ false,
+ "Active Bone",
+ "Assign the hook to the hook objects active bone");
}
static int object_add_hook_newob_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- Object *obedit = CTX_data_edit_object(C);
-
- if (add_hook_object(C, bmain, scene, view_layer, v3d, obedit, NULL, OBJECT_ADDHOOK_NEWOB, op->reports)) {
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Object *obedit = CTX_data_edit_object(C);
+
+ if (add_hook_object(
+ C, bmain, scene, view_layer, v3d, obedit, NULL, OBJECT_ADDHOOK_NEWOB, op->reports)) {
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void OBJECT_OT_hook_add_newob(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Hook to New Object";
- ot->description = "Hook selected vertices to a newly created object";
- ot->idname = "OBJECT_OT_hook_add_newob";
+ /* identifiers */
+ ot->name = "Hook to New Object";
+ ot->description = "Hook selected vertices to a newly created object";
+ ot->idname = "OBJECT_OT_hook_add_newob";
- /* api callbacks */
- ot->exec = object_add_hook_newob_exec;
- ot->poll = hook_op_edit_poll;
+ /* api callbacks */
+ ot->exec = object_add_hook_newob_exec;
+ ot->poll = hook_op_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int object_hook_remove_exec(bContext *C, wmOperator *op)
{
- int num = RNA_enum_get(op->ptr, "modifier");
- Object *ob = CTX_data_edit_object(C);
- HookModifierData *hmd = NULL;
+ int num = RNA_enum_get(op->ptr, "modifier");
+ Object *ob = CTX_data_edit_object(C);
+ HookModifierData *hmd = NULL;
- hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
- if (!hmd) {
- BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
- return OPERATOR_CANCELLED;
- }
+ hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
+ if (!hmd) {
+ BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
+ return OPERATOR_CANCELLED;
+ }
- /* remove functionality */
+ /* remove functionality */
- BLI_remlink(&ob->modifiers, (ModifierData *)hmd);
- modifier_free((ModifierData *)hmd);
+ BLI_remlink(&ob->modifiers, (ModifierData *)hmd);
+ modifier_free((ModifierData *)hmd);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static const EnumPropertyItem *hook_mod_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *hook_mod_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- Object *ob = CTX_data_edit_object(C);
- EnumPropertyItem tmp = {0, "", 0, "", ""};
- EnumPropertyItem *item = NULL;
- ModifierData *md = NULL;
- int a, totitem = 0;
-
- if (!ob)
- return DummyRNA_NULL_items;
-
- for (a = 0, md = ob->modifiers.first; md; md = md->next, a++) {
- if (md->type == eModifierType_Hook) {
- tmp.value = a;
- tmp.icon = ICON_HOOK;
- tmp.identifier = md->name;
- tmp.name = md->name;
- RNA_enum_item_add(&item, &totitem, &tmp);
- }
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ Object *ob = CTX_data_edit_object(C);
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ EnumPropertyItem *item = NULL;
+ ModifierData *md = NULL;
+ int a, totitem = 0;
+
+ if (!ob)
+ return DummyRNA_NULL_items;
+
+ for (a = 0, md = ob->modifiers.first; md; md = md->next, a++) {
+ if (md->type == eModifierType_Hook) {
+ tmp.value = a;
+ tmp.icon = ICON_HOOK;
+ tmp.identifier = md->name;
+ tmp.name = md->name;
+ RNA_enum_item_add(&item, &totitem, &tmp);
+ }
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
void OBJECT_OT_hook_remove(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Remove Hook";
- ot->idname = "OBJECT_OT_hook_remove";
- ot->description = "Remove a hook from the active object";
-
- /* api callbacks */
- ot->exec = object_hook_remove_exec;
- ot->invoke = WM_menu_invoke;
- ot->poll = hook_op_edit_poll;
-
- /* flags */
- /* this operator removes modifier which isn't stored in local undo stack,
- * so redoing it from redo panel gives totally weird results */
- ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to remove");
- RNA_def_enum_funcs(prop, hook_mod_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Remove Hook";
+ ot->idname = "OBJECT_OT_hook_remove";
+ ot->description = "Remove a hook from the active object";
+
+ /* api callbacks */
+ ot->exec = object_hook_remove_exec;
+ ot->invoke = WM_menu_invoke;
+ ot->poll = hook_op_edit_poll;
+
+ /* flags */
+ /* this operator removes modifier which isn't stored in local undo stack,
+ * so redoing it from redo panel gives totally weird results */
+ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(
+ ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to remove");
+ RNA_def_enum_funcs(prop, hook_mod_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
static int object_hook_reset_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
- int num = RNA_enum_get(op->ptr, "modifier");
- Object *ob = NULL;
- HookModifierData *hmd = NULL;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
+ int num = RNA_enum_get(op->ptr, "modifier");
+ Object *ob = NULL;
+ HookModifierData *hmd = NULL;
- object_hook_from_context(C, &ptr, num, &ob, &hmd);
- if (hmd == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
- return OPERATOR_CANCELLED;
- }
+ object_hook_from_context(C, &ptr, num, &ob, &hmd);
+ if (hmd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
+ return OPERATOR_CANCELLED;
+ }
- BKE_object_modifier_hook_reset(ob, hmd);
+ BKE_object_modifier_hook_reset(ob, hmd);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_hook_reset(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Reset Hook";
- ot->description = "Recalculate and clear offset transformation";
- ot->idname = "OBJECT_OT_hook_reset";
+ /* identifiers */
+ ot->name = "Reset Hook";
+ ot->description = "Recalculate and clear offset transformation";
+ ot->idname = "OBJECT_OT_hook_reset";
- /* callbacks */
- ot->exec = object_hook_reset_exec;
- ot->poll = hook_op_edit_poll;
+ /* callbacks */
+ ot->exec = object_hook_reset_exec;
+ ot->poll = hook_op_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- prop = RNA_def_enum(ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to assign to");
- RNA_def_enum_funcs(prop, hook_mod_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ /* properties */
+ prop = RNA_def_enum(
+ ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to assign to");
+ RNA_def_enum_funcs(prop, hook_mod_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
}
static int object_hook_recenter_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
- int num = RNA_enum_get(op->ptr, "modifier");
- Object *ob = NULL;
- HookModifierData *hmd = NULL;
- Scene *scene = CTX_data_scene(C);
- float bmat[3][3], imat[3][3];
-
- object_hook_from_context(C, &ptr, num, &ob, &hmd);
- if (hmd == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
- return OPERATOR_CANCELLED;
- }
-
- /* recenter functionality */
- copy_m3_m4(bmat, ob->obmat);
- invert_m3_m3(imat, bmat);
-
- sub_v3_v3v3(hmd->cent, scene->cursor.location, ob->obmat[3]);
- mul_m3_v3(imat, hmd->cent);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
- return OPERATOR_FINISHED;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
+ int num = RNA_enum_get(op->ptr, "modifier");
+ Object *ob = NULL;
+ HookModifierData *hmd = NULL;
+ Scene *scene = CTX_data_scene(C);
+ float bmat[3][3], imat[3][3];
+
+ object_hook_from_context(C, &ptr, num, &ob, &hmd);
+ if (hmd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* recenter functionality */
+ copy_m3_m4(bmat, ob->obmat);
+ invert_m3_m3(imat, bmat);
+
+ sub_v3_v3v3(hmd->cent, scene->cursor.location, ob->obmat[3]);
+ mul_m3_v3(imat, hmd->cent);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_hook_recenter(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Recenter Hook";
- ot->description = "Set hook center to cursor position";
- ot->idname = "OBJECT_OT_hook_recenter";
+ /* identifiers */
+ ot->name = "Recenter Hook";
+ ot->description = "Set hook center to cursor position";
+ ot->idname = "OBJECT_OT_hook_recenter";
- /* callbacks */
- ot->exec = object_hook_recenter_exec;
- ot->poll = hook_op_edit_poll;
+ /* callbacks */
+ ot->exec = object_hook_recenter_exec;
+ ot->poll = hook_op_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- prop = RNA_def_enum(ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to assign to");
- RNA_def_enum_funcs(prop, hook_mod_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ /* properties */
+ prop = RNA_def_enum(
+ ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to assign to");
+ RNA_def_enum_funcs(prop, hook_mod_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
}
static int object_hook_assign_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
- int num = RNA_enum_get(op->ptr, "modifier");
- Object *ob = NULL;
- HookModifierData *hmd = NULL;
- float cent[3];
- char name[MAX_NAME];
- int *indexar, tot;
-
- object_hook_from_context(C, &ptr, num, &ob, &hmd);
- if (hmd == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
- return OPERATOR_CANCELLED;
- }
-
- /* assign functionality */
-
- if (!object_hook_index_array(bmain, scene, ob, &tot, &indexar, name, cent)) {
- BKE_report(op->reports, RPT_WARNING, "Requires selected vertices or active vertex group");
- return OPERATOR_CANCELLED;
- }
- if (hmd->indexar)
- MEM_freeN(hmd->indexar);
-
- copy_v3_v3(hmd->cent, cent);
- hmd->indexar = indexar;
- hmd->totindex = tot;
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
+ int num = RNA_enum_get(op->ptr, "modifier");
+ Object *ob = NULL;
+ HookModifierData *hmd = NULL;
+ float cent[3];
+ char name[MAX_NAME];
+ int *indexar, tot;
+
+ object_hook_from_context(C, &ptr, num, &ob, &hmd);
+ if (hmd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* assign functionality */
+
+ if (!object_hook_index_array(bmain, scene, ob, &tot, &indexar, name, cent)) {
+ BKE_report(op->reports, RPT_WARNING, "Requires selected vertices or active vertex group");
+ return OPERATOR_CANCELLED;
+ }
+ if (hmd->indexar)
+ MEM_freeN(hmd->indexar);
+
+ copy_v3_v3(hmd->cent, cent);
+ hmd->indexar = indexar;
+ hmd->totindex = tot;
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_hook_assign(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Assign to Hook";
- ot->description = "Assign the selected vertices to a hook";
- ot->idname = "OBJECT_OT_hook_assign";
-
- /* callbacks */
- ot->exec = object_hook_assign_exec;
- ot->poll = hook_op_edit_poll;
-
- /* flags */
- /* this operator changes data stored in modifier which doesn't get pushed to undo stack,
- * so redoing it from redo panel gives totally weird results */
- ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to assign to");
- RNA_def_enum_funcs(prop, hook_mod_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Assign to Hook";
+ ot->description = "Assign the selected vertices to a hook";
+ ot->idname = "OBJECT_OT_hook_assign";
+
+ /* callbacks */
+ ot->exec = object_hook_assign_exec;
+ ot->poll = hook_op_edit_poll;
+
+ /* flags */
+ /* this operator changes data stored in modifier which doesn't get pushed to undo stack,
+ * so redoing it from redo panel gives totally weird results */
+ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(
+ ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to assign to");
+ RNA_def_enum_funcs(prop, hook_mod_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
}
static int object_hook_select_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
- int num = RNA_enum_get(op->ptr, "modifier");
- Object *ob = NULL;
- HookModifierData *hmd = NULL;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
+ int num = RNA_enum_get(op->ptr, "modifier");
+ Object *ob = NULL;
+ HookModifierData *hmd = NULL;
- object_hook_from_context(C, &ptr, num, &ob, &hmd);
- if (hmd == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
- return OPERATOR_CANCELLED;
- }
+ object_hook_from_context(C, &ptr, num, &ob, &hmd);
+ if (hmd == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier");
+ return OPERATOR_CANCELLED;
+ }
- /* select functionality */
- object_hook_select(ob, hmd);
+ /* select functionality */
+ object_hook_select(ob, hmd);
- DEG_id_tag_update(ob->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
+ DEG_id_tag_update(ob->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_hook_select(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Select Hook";
- ot->description = "Select affected vertices on mesh";
- ot->idname = "OBJECT_OT_hook_select";
+ /* identifiers */
+ ot->name = "Select Hook";
+ ot->description = "Select affected vertices on mesh";
+ ot->idname = "OBJECT_OT_hook_select";
- /* callbacks */
- ot->exec = object_hook_select_exec;
- ot->poll = hook_op_edit_poll;
+ /* callbacks */
+ ot->exec = object_hook_select_exec;
+ ot->poll = hook_op_edit_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- prop = RNA_def_enum(ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to remove");
- RNA_def_enum_funcs(prop, hook_mod_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ /* properties */
+ prop = RNA_def_enum(
+ ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to remove");
+ RNA_def_enum_funcs(prop, hook_mod_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
}
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 33f821126a2..d17b6515dbb 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -34,9 +34,9 @@ struct ModifierData;
/* add hook menu */
enum eObject_Hook_Add_Mode {
- OBJECT_ADDHOOK_NEWOB = 1,
- OBJECT_ADDHOOK_SELOB,
- OBJECT_ADDHOOK_SELOB_BONE,
+ OBJECT_ADDHOOK_NEWOB = 1,
+ OBJECT_ADDHOOK_SELOB,
+ OBJECT_ADDHOOK_SELOB_BONE,
};
/* internal exports only */
@@ -141,7 +141,9 @@ bool edit_modifier_poll_generic(struct bContext *C, struct StructRNA *rna_type,
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);
-struct ModifierData *edit_modifier_property_get(struct wmOperator *op, struct Object *ob, int type);
+struct ModifierData *edit_modifier_property_get(struct wmOperator *op,
+ struct Object *ob,
+ int type);
void OBJECT_OT_modifier_add(struct wmOperatorType *ot);
void OBJECT_OT_modifier_remove(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c
index dd0a37b4498..7c881aa7cab 100644
--- a/source/blender/editors/object/object_modes.c
+++ b/source/blender/editors/object/object_modes.c
@@ -45,7 +45,7 @@
#include "ED_armature.h"
#include "ED_screen.h"
-#include "ED_object.h" /* own include */
+#include "ED_object.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name High Level Mode Operations
@@ -54,29 +54,29 @@
static const char *object_mode_op_string(eObjectMode mode)
{
- if (mode & OB_MODE_EDIT)
- return "OBJECT_OT_editmode_toggle";
- if (mode == OB_MODE_SCULPT)
- return "SCULPT_OT_sculptmode_toggle";
- if (mode == OB_MODE_VERTEX_PAINT)
- return "PAINT_OT_vertex_paint_toggle";
- if (mode == OB_MODE_WEIGHT_PAINT)
- return "PAINT_OT_weight_paint_toggle";
- if (mode == OB_MODE_TEXTURE_PAINT)
- return "PAINT_OT_texture_paint_toggle";
- if (mode == OB_MODE_PARTICLE_EDIT)
- return "PARTICLE_OT_particle_edit_toggle";
- if (mode == OB_MODE_POSE)
- return "OBJECT_OT_posemode_toggle";
- if (mode == OB_MODE_EDIT_GPENCIL)
- return "GPENCIL_OT_editmode_toggle";
- if (mode == OB_MODE_PAINT_GPENCIL)
- return "GPENCIL_OT_paintmode_toggle";
- if (mode == OB_MODE_SCULPT_GPENCIL)
- return "GPENCIL_OT_sculptmode_toggle";
- if (mode == OB_MODE_WEIGHT_GPENCIL)
- return "GPENCIL_OT_weightmode_toggle";
- return NULL;
+ if (mode & OB_MODE_EDIT)
+ return "OBJECT_OT_editmode_toggle";
+ if (mode == OB_MODE_SCULPT)
+ return "SCULPT_OT_sculptmode_toggle";
+ if (mode == OB_MODE_VERTEX_PAINT)
+ return "PAINT_OT_vertex_paint_toggle";
+ if (mode == OB_MODE_WEIGHT_PAINT)
+ return "PAINT_OT_weight_paint_toggle";
+ if (mode == OB_MODE_TEXTURE_PAINT)
+ return "PAINT_OT_texture_paint_toggle";
+ if (mode == OB_MODE_PARTICLE_EDIT)
+ return "PARTICLE_OT_particle_edit_toggle";
+ if (mode == OB_MODE_POSE)
+ return "OBJECT_OT_posemode_toggle";
+ if (mode == OB_MODE_EDIT_GPENCIL)
+ return "GPENCIL_OT_editmode_toggle";
+ if (mode == OB_MODE_PAINT_GPENCIL)
+ return "GPENCIL_OT_paintmode_toggle";
+ if (mode == OB_MODE_SCULPT_GPENCIL)
+ return "GPENCIL_OT_sculptmode_toggle";
+ if (mode == OB_MODE_WEIGHT_GPENCIL)
+ return "GPENCIL_OT_weightmode_toggle";
+ return NULL;
}
/**
@@ -85,44 +85,42 @@ static const char *object_mode_op_string(eObjectMode mode)
*/
bool ED_object_mode_compat_test(const Object *ob, eObjectMode mode)
{
- if (ob) {
- if (mode == OB_MODE_OBJECT)
- return true;
+ if (ob) {
+ if (mode == OB_MODE_OBJECT)
+ return true;
- switch (ob->type) {
- case OB_MESH:
- if (mode & (OB_MODE_EDIT | OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT |
- OB_MODE_TEXTURE_PAINT | OB_MODE_PARTICLE_EDIT))
- {
- return true;
- }
- break;
- case OB_CURVE:
- case OB_SURF:
- case OB_FONT:
- case OB_MBALL:
- if (mode & (OB_MODE_EDIT))
- return true;
- break;
- case OB_LATTICE:
- if (mode & (OB_MODE_EDIT | OB_MODE_WEIGHT_PAINT))
- return true;
- break;
- case OB_ARMATURE:
- if (mode & (OB_MODE_EDIT | OB_MODE_POSE))
- return true;
- break;
- case OB_GPENCIL:
- if (mode & (OB_MODE_EDIT | OB_MODE_EDIT_GPENCIL | OB_MODE_PAINT_GPENCIL |
- OB_MODE_SCULPT_GPENCIL | OB_MODE_WEIGHT_GPENCIL))
- {
- return true;
- }
- break;
- }
- }
+ switch (ob->type) {
+ case OB_MESH:
+ if (mode & (OB_MODE_EDIT | OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT |
+ OB_MODE_TEXTURE_PAINT | OB_MODE_PARTICLE_EDIT)) {
+ return true;
+ }
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ case OB_FONT:
+ case OB_MBALL:
+ if (mode & (OB_MODE_EDIT))
+ return true;
+ break;
+ case OB_LATTICE:
+ if (mode & (OB_MODE_EDIT | OB_MODE_WEIGHT_PAINT))
+ return true;
+ break;
+ case OB_ARMATURE:
+ if (mode & (OB_MODE_EDIT | OB_MODE_POSE))
+ return true;
+ break;
+ case OB_GPENCIL:
+ if (mode & (OB_MODE_EDIT | OB_MODE_EDIT_GPENCIL | OB_MODE_PAINT_GPENCIL |
+ OB_MODE_SCULPT_GPENCIL | OB_MODE_WEIGHT_GPENCIL)) {
+ return true;
+ }
+ break;
+ }
+ }
- return false;
+ return false;
}
/**
@@ -132,68 +130,66 @@ bool ED_object_mode_compat_test(const Object *ob, eObjectMode mode)
*/
bool ED_object_mode_compat_set(bContext *C, Object *ob, eObjectMode mode, ReportList *reports)
{
- bool ok;
- if (!ELEM(ob->mode, mode, OB_MODE_OBJECT)) {
- const char *opstring = object_mode_op_string(ob->mode);
+ bool ok;
+ if (!ELEM(ob->mode, mode, OB_MODE_OBJECT)) {
+ const char *opstring = object_mode_op_string(ob->mode);
- WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL);
- ok = ELEM(ob->mode, mode, OB_MODE_OBJECT);
- if (!ok) {
- wmOperatorType *ot = WM_operatortype_find(opstring, false);
- BKE_reportf(reports, RPT_ERROR, "Unable to execute '%s', error changing modes", ot->name);
- }
- }
- else {
- ok = true;
- }
+ WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL);
+ ok = ELEM(ob->mode, mode, OB_MODE_OBJECT);
+ if (!ok) {
+ wmOperatorType *ot = WM_operatortype_find(opstring, false);
+ BKE_reportf(reports, RPT_ERROR, "Unable to execute '%s', error changing modes", ot->name);
+ }
+ }
+ else {
+ ok = true;
+ }
- return ok;
+ return ok;
}
void ED_object_mode_toggle(bContext *C, eObjectMode mode)
{
- if (mode != OB_MODE_OBJECT) {
- const char *opstring = object_mode_op_string(mode);
+ if (mode != OB_MODE_OBJECT) {
+ const char *opstring = object_mode_op_string(mode);
- if (opstring) {
- wmOperatorType *ot = WM_operatortype_find(opstring, false);
- if (ot->flag & OPTYPE_USE_EVAL_DATA) {
- /* We need to force refresh of depsgraph after undo step,
- * redoing the operator *may* rely on some valid evaluated data. */
- struct Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- BKE_scene_view_layer_graph_evaluated_ensure(bmain, scene, view_layer);
- }
- WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_REGION_WIN, NULL);
- }
- }
+ if (opstring) {
+ wmOperatorType *ot = WM_operatortype_find(opstring, false);
+ if (ot->flag & OPTYPE_USE_EVAL_DATA) {
+ /* We need to force refresh of depsgraph after undo step,
+ * redoing the operator *may* rely on some valid evaluated data. */
+ struct Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ BKE_scene_view_layer_graph_evaluated_ensure(bmain, scene, view_layer);
+ }
+ WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_REGION_WIN, NULL);
+ }
+ }
}
-
/* Wrapper for operator */
void ED_object_mode_set(bContext *C, eObjectMode mode)
{
- wmWindowManager *wm = CTX_wm_manager(C);
- wm->op_undo_depth++;
- /* needed so we don't do undo pushes. */
- ED_object_mode_generic_enter(C, mode);
- wm->op_undo_depth--;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wm->op_undo_depth++;
+ /* needed so we don't do undo pushes. */
+ ED_object_mode_generic_enter(C, mode);
+ wm->op_undo_depth--;
}
void ED_object_mode_exit(bContext *C)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- struct Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- FOREACH_OBJECT_BEGIN(view_layer, ob)
- {
- if (ob->mode & OB_MODE_ALL_MODE_DATA) {
- ED_object_mode_generic_exit(bmain, depsgraph, scene, ob);
- }
- }
- FOREACH_OBJECT_END;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ struct Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ FOREACH_OBJECT_BEGIN (view_layer, ob) {
+ if (ob->mode & OB_MODE_ALL_MODE_DATA) {
+ ED_object_mode_generic_exit(bmain, depsgraph, scene, ob);
+ }
+ }
+ FOREACH_OBJECT_END;
}
/** \} */
@@ -206,100 +202,97 @@ void ED_object_mode_exit(bContext *C)
*
* \{ */
-bool ED_object_mode_generic_enter(
- struct bContext *C, eObjectMode object_mode)
+bool ED_object_mode_generic_enter(struct bContext *C, eObjectMode object_mode)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = OBACT(view_layer);
- if (ob == NULL) {
- return (object_mode == OB_MODE_OBJECT);
- }
- if (ob->mode == object_mode) {
- return true;
- }
- wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_mode_set", false);
- PointerRNA ptr;
- WM_operator_properties_create_ptr(&ptr, ot);
- RNA_enum_set(&ptr, "mode", object_mode);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
- WM_operator_properties_free(&ptr);
- return (ob->mode == object_mode);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ if (ob == NULL) {
+ return (object_mode == OB_MODE_OBJECT);
+ }
+ if (ob->mode == object_mode) {
+ return true;
+ }
+ wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_mode_set", false);
+ PointerRNA ptr;
+ WM_operator_properties_create_ptr(&ptr, ot);
+ RNA_enum_set(&ptr, "mode", object_mode);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
+ WM_operator_properties_free(&ptr);
+ return (ob->mode == object_mode);
}
/**
* Use for changing works-paces or changing active object.
* Caller can check #OB_MODE_ALL_MODE_DATA to test if this needs to be run.
*/
-static bool ed_object_mode_generic_exit_ex(
- struct Main *bmain,
- struct Depsgraph *depsgraph,
- struct Scene *scene, struct Object *ob,
- bool only_test)
+static bool ed_object_mode_generic_exit_ex(struct Main *bmain,
+ struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob,
+ bool only_test)
{
- BLI_assert((bmain == NULL) == only_test);
- if (ob->mode & OB_MODE_EDIT) {
- if (BKE_object_is_in_editmode(ob)) {
- if (only_test) {
- return true;
- }
- ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
- }
- }
- else if (ob->mode & OB_MODE_VERTEX_PAINT) {
- if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_VERTEX_PAINT)) {
- if (only_test) {
- return true;
- }
- ED_object_vpaintmode_exit_ex(ob);
- }
- }
- else if (ob->mode & OB_MODE_WEIGHT_PAINT) {
- if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_WEIGHT_PAINT)) {
- if (only_test) {
- return true;
- }
- ED_object_wpaintmode_exit_ex(ob);
- }
- }
- else if (ob->mode & OB_MODE_SCULPT) {
- if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_SCULPT)) {
- if (only_test) {
- return true;
- }
- ED_object_sculptmode_exit_ex(depsgraph, scene, ob);
- }
- }
- else if (ob->mode & OB_MODE_POSE) {
- if (ob->pose != NULL) {
- if (only_test) {
- return true;
- }
- ED_object_posemode_exit_ex(bmain, ob);
- }
- }
- else {
- if (only_test) {
- return false;
- }
- BLI_assert((ob->mode & OB_MODE_ALL_MODE_DATA) == 0);
- }
+ BLI_assert((bmain == NULL) == only_test);
+ if (ob->mode & OB_MODE_EDIT) {
+ if (BKE_object_is_in_editmode(ob)) {
+ if (only_test) {
+ return true;
+ }
+ ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
+ }
+ }
+ else if (ob->mode & OB_MODE_VERTEX_PAINT) {
+ if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_VERTEX_PAINT)) {
+ if (only_test) {
+ return true;
+ }
+ ED_object_vpaintmode_exit_ex(ob);
+ }
+ }
+ else if (ob->mode & OB_MODE_WEIGHT_PAINT) {
+ if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_WEIGHT_PAINT)) {
+ if (only_test) {
+ return true;
+ }
+ ED_object_wpaintmode_exit_ex(ob);
+ }
+ }
+ else if (ob->mode & OB_MODE_SCULPT) {
+ if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_SCULPT)) {
+ if (only_test) {
+ return true;
+ }
+ ED_object_sculptmode_exit_ex(depsgraph, scene, ob);
+ }
+ }
+ else if (ob->mode & OB_MODE_POSE) {
+ if (ob->pose != NULL) {
+ if (only_test) {
+ return true;
+ }
+ ED_object_posemode_exit_ex(bmain, ob);
+ }
+ }
+ else {
+ if (only_test) {
+ return false;
+ }
+ BLI_assert((ob->mode & OB_MODE_ALL_MODE_DATA) == 0);
+ }
- return false;
+ return false;
}
-void ED_object_mode_generic_exit(
- struct Main *bmain,
- struct Depsgraph *depsgraph,
- struct Scene *scene, struct Object *ob)
+void ED_object_mode_generic_exit(struct Main *bmain,
+ struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob)
{
- ed_object_mode_generic_exit_ex(bmain, depsgraph, scene, ob, false);
+ ed_object_mode_generic_exit_ex(bmain, depsgraph, scene, ob, false);
}
-bool ED_object_mode_generic_has_data(
- struct Depsgraph *depsgraph,
- struct Object *ob)
+bool ED_object_mode_generic_has_data(struct Depsgraph *depsgraph, struct Object *ob)
{
- return ed_object_mode_generic_exit_ex(NULL, depsgraph, NULL, ob, true);
+ return ed_object_mode_generic_exit_ex(NULL, depsgraph, NULL, ob, true);
}
/** \} */
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 9576cbe6fa1..7aae0a41c85 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
@@ -95,133 +94,132 @@ static void modifier_skin_customdata_delete(struct Object *ob);
static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object *ob)
{
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- BKE_object_eval_reset(ob_eval);
- if (ob->type == OB_MESH) {
- Mesh *me_eval = mesh_create_eval_final_view(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
- BKE_id_free(NULL, me_eval);
- }
- else if (ob->type == OB_LATTICE) {
- BKE_lattice_modifiers_calc(depsgraph, scene_eval, ob_eval);
- }
- else if (ob->type == OB_MBALL) {
- BKE_displist_make_mball(depsgraph, scene_eval, ob_eval);
- }
- else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
- BKE_displist_make_curveTypes(depsgraph, scene_eval, ob_eval, false, false, NULL);
- }
-}
-
-static void object_force_modifier_bind_simple_options(
- Depsgraph *depsgraph,
- Object *object,
- ModifierData *md)
-{
- ModifierData *md_eval = (ModifierData *)modifier_get_evaluated(depsgraph, object, md);
- const int mode = md_eval->mode;
- md_eval->mode |= eModifierMode_Realtime;
- object_force_modifier_update_for_bind(depsgraph, object);
- md_eval->mode = mode;
-}
-
-ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type)
-{
- ModifierData *md = NULL, *new_md = NULL;
- const ModifierTypeInfo *mti = modifierType_getInfo(type);
-
- /* Check compatibility of modifier [T25291, T50373]. */
- if (!BKE_object_support_modifier_type_check(ob, type)) {
- BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to object '%s'", ob->id.name + 2);
- return NULL;
- }
-
- if (mti->flags & eModifierTypeFlag_Single) {
- if (modifiers_findByType(ob, type)) {
- BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
- return NULL;
- }
- }
-
- if (type == eModifierType_ParticleSystem) {
- /* don't need to worry about the new modifier's name, since that is set to the number
- * of particle systems which shouldn't have too many duplicates
- */
- new_md = object_add_particle_system(bmain, scene, ob, name);
- }
- else {
- /* get new modifier data to add */
- new_md = modifier_new(type);
-
- if (mti->flags & eModifierTypeFlag_RequiresOriginalData) {
- md = ob->modifiers.first;
-
- while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform)
- md = md->next;
-
- BLI_insertlinkbefore(&ob->modifiers, md, new_md);
- }
- else
- BLI_addtail(&ob->modifiers, new_md);
-
- if (name) {
- BLI_strncpy_utf8(new_md->name, name, sizeof(new_md->name));
- }
-
- /* make sure modifier data has unique name */
-
- modifier_unique_name(&ob->modifiers, new_md);
-
- /* special cases */
- if (type == eModifierType_Softbody) {
- if (!ob->soft) {
- ob->soft = sbNew(scene);
- ob->softflag |= OB_SB_GOAL | OB_SB_EDGES;
- }
- }
- else if (type == eModifierType_Collision) {
- if (!ob->pd)
- ob->pd = BKE_partdeflect_new(0);
-
- ob->pd->deflect = 1;
- }
- else if (type == eModifierType_Surface) {
- /* pass */
- }
- else if (type == eModifierType_Multires) {
- /* set totlvl from existing MDISPS layer if object already had it */
- multiresModifier_set_levels_from_disps((MultiresModifierData *)new_md, ob);
-
- if (ob->mode & OB_MODE_SCULPT) {
- /* ensure that grid paint mask layer is created */
- BKE_sculpt_mask_layers_ensure(ob, (MultiresModifierData *)new_md);
- }
- }
- else if (type == eModifierType_Skin) {
- /* ensure skin-node customdata exists */
- BKE_mesh_ensure_skin_customdata(ob->data);
- }
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(bmain);
-
- return new_md;
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ BKE_object_eval_reset(ob_eval);
+ if (ob->type == OB_MESH) {
+ Mesh *me_eval = mesh_create_eval_final_view(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
+ BKE_id_free(NULL, me_eval);
+ }
+ else if (ob->type == OB_LATTICE) {
+ BKE_lattice_modifiers_calc(depsgraph, scene_eval, ob_eval);
+ }
+ else if (ob->type == OB_MBALL) {
+ BKE_displist_make_mball(depsgraph, scene_eval, ob_eval);
+ }
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ BKE_displist_make_curveTypes(depsgraph, scene_eval, ob_eval, false, false, NULL);
+ }
+}
+
+static void object_force_modifier_bind_simple_options(Depsgraph *depsgraph,
+ Object *object,
+ ModifierData *md)
+{
+ ModifierData *md_eval = (ModifierData *)modifier_get_evaluated(depsgraph, object, md);
+ const int mode = md_eval->mode;
+ md_eval->mode |= eModifierMode_Realtime;
+ object_force_modifier_update_for_bind(depsgraph, object);
+ md_eval->mode = mode;
+}
+
+ModifierData *ED_object_modifier_add(
+ ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type)
+{
+ ModifierData *md = NULL, *new_md = NULL;
+ const ModifierTypeInfo *mti = modifierType_getInfo(type);
+
+ /* Check compatibility of modifier [T25291, T50373]. */
+ if (!BKE_object_support_modifier_type_check(ob, type)) {
+ BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to object '%s'", ob->id.name + 2);
+ return NULL;
+ }
+
+ if (mti->flags & eModifierTypeFlag_Single) {
+ if (modifiers_findByType(ob, type)) {
+ BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
+ return NULL;
+ }
+ }
+
+ if (type == eModifierType_ParticleSystem) {
+ /* don't need to worry about the new modifier's name, since that is set to the number
+ * of particle systems which shouldn't have too many duplicates
+ */
+ new_md = object_add_particle_system(bmain, scene, ob, name);
+ }
+ else {
+ /* get new modifier data to add */
+ new_md = modifier_new(type);
+
+ if (mti->flags & eModifierTypeFlag_RequiresOriginalData) {
+ md = ob->modifiers.first;
+
+ while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform)
+ md = md->next;
+
+ BLI_insertlinkbefore(&ob->modifiers, md, new_md);
+ }
+ else
+ BLI_addtail(&ob->modifiers, new_md);
+
+ if (name) {
+ BLI_strncpy_utf8(new_md->name, name, sizeof(new_md->name));
+ }
+
+ /* make sure modifier data has unique name */
+
+ modifier_unique_name(&ob->modifiers, new_md);
+
+ /* special cases */
+ if (type == eModifierType_Softbody) {
+ if (!ob->soft) {
+ ob->soft = sbNew(scene);
+ ob->softflag |= OB_SB_GOAL | OB_SB_EDGES;
+ }
+ }
+ else if (type == eModifierType_Collision) {
+ if (!ob->pd)
+ ob->pd = BKE_partdeflect_new(0);
+
+ ob->pd->deflect = 1;
+ }
+ else if (type == eModifierType_Surface) {
+ /* pass */
+ }
+ else if (type == eModifierType_Multires) {
+ /* set totlvl from existing MDISPS layer if object already had it */
+ multiresModifier_set_levels_from_disps((MultiresModifierData *)new_md, ob);
+
+ if (ob->mode & OB_MODE_SCULPT) {
+ /* ensure that grid paint mask layer is created */
+ BKE_sculpt_mask_layers_ensure(ob, (MultiresModifierData *)new_md);
+ }
+ }
+ else if (type == eModifierType_Skin) {
+ /* ensure skin-node customdata exists */
+ BKE_mesh_ensure_skin_customdata(ob->data);
+ }
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(bmain);
+
+ 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 object_has_modifier(const Object *ob, const ModifierData *exclude,
- ModifierType type)
+static bool object_has_modifier(const Object *ob, const ModifierData *exclude, ModifierType type)
{
- ModifierData *md;
+ ModifierData *md;
- for (md = ob->modifiers.first; md; md = md->next) {
- if ((md != exclude) && (md->type == type))
- return true;
- }
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if ((md != exclude) && (md->type == type))
+ return true;
+ }
- return false;
+ return false;
}
/* If the object data of 'orig_ob' has other users, run 'callback' on
@@ -232,47 +230,44 @@ static bool object_has_modifier(const Object *ob, const ModifierData *exclude,
* If the callback ever returns true, iteration will stop and the
* function value will be true. Otherwise the function returns false.
*/
-bool ED_object_iter_other(
- Main *bmain, Object *orig_ob, const bool include_orig,
- bool (*callback)(Object *ob, void *callback_data),
- void *callback_data)
-{
- ID *ob_data_id = orig_ob->data;
- int users = ob_data_id->us;
-
- if (ob_data_id->flag & LIB_FAKEUSER)
- users--;
-
- /* First check that the object's data has multiple users */
- if (users > 1) {
- Object *ob;
- int totfound = include_orig ? 0 : 1;
-
- for (ob = bmain->objects.first; ob && totfound < users;
- ob = ob->id.next)
- {
- if (((ob != orig_ob) || include_orig) &&
- (ob->data == orig_ob->data))
- {
- if (callback(ob, callback_data))
- return true;
-
- totfound++;
- }
- }
- }
- else if (include_orig) {
- return callback(orig_ob, callback_data);
- }
-
- return false;
+bool ED_object_iter_other(Main *bmain,
+ Object *orig_ob,
+ const bool include_orig,
+ bool (*callback)(Object *ob, void *callback_data),
+ void *callback_data)
+{
+ ID *ob_data_id = orig_ob->data;
+ int users = ob_data_id->us;
+
+ if (ob_data_id->flag & LIB_FAKEUSER)
+ users--;
+
+ /* First check that the object's data has multiple users */
+ if (users > 1) {
+ Object *ob;
+ int totfound = include_orig ? 0 : 1;
+
+ for (ob = bmain->objects.first; ob && totfound < users; ob = ob->id.next) {
+ if (((ob != orig_ob) || include_orig) && (ob->data == orig_ob->data)) {
+ if (callback(ob, callback_data))
+ return true;
+
+ totfound++;
+ }
+ }
+ }
+ else if (include_orig) {
+ return callback(orig_ob, callback_data);
+ }
+
+ return false;
}
static bool object_has_modifier_cb(Object *ob, void *data)
{
- ModifierType type = *((ModifierType *)data);
+ ModifierType type = *((ModifierType *)data);
- return object_has_modifier(ob, NULL, type);
+ return object_has_modifier(ob, NULL, type);
}
/* Use with ED_object_iter_other(). Sets the total number of levels
@@ -280,2145 +275,2167 @@ static bool object_has_modifier_cb(Object *ob, void *data)
* callback_data. */
bool ED_object_multires_update_totlevels_cb(Object *ob, void *totlevel_v)
{
- ModifierData *md;
- int totlevel = *((char *)totlevel_v);
+ ModifierData *md;
+ int totlevel = *((char *)totlevel_v);
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Multires) {
- multires_set_tot_level(ob, (MultiresModifierData *)md, totlevel);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- }
- return false;
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Multires) {
+ multires_set_tot_level(ob, (MultiresModifierData *)md, totlevel);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ }
+ return false;
}
/* Return true if no modifier of type 'type' other than 'exclude' */
-static bool object_modifier_safe_to_delete(Main *bmain, Object *ob,
- ModifierData *exclude,
- ModifierType type)
-{
- return (!object_has_modifier(ob, exclude, type) &&
- !ED_object_iter_other(bmain, ob, false, object_has_modifier_cb, &type));
-}
-
-static bool object_modifier_remove(Main *bmain, Object *ob, ModifierData *md,
- bool *r_sort_depsgraph)
-{
- /* It seems on rapid delete it is possible to
- * get called twice on same modifier, so make
- * sure it is in list. */
- if (BLI_findindex(&ob->modifiers, md) == -1) {
- return 0;
- }
-
- /* special cases */
- if (md->type == eModifierType_ParticleSystem) {
- ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
-
- BLI_remlink(&ob->particlesystem, psmd->psys);
- psys_free(ob, psmd->psys);
- psmd->psys = NULL;
- }
- else if (md->type == eModifierType_Softbody) {
- if (ob->soft) {
- sbFree(ob);
- ob->softflag = 0; /* TODO(Sybren): this should probably be moved into sbFree() */
- }
- }
- else if (md->type == eModifierType_Collision) {
- if (ob->pd)
- ob->pd->deflect = 0;
-
- *r_sort_depsgraph = true;
- }
- else if (md->type == eModifierType_Surface) {
- *r_sort_depsgraph = true;
- }
- else if (md->type == eModifierType_Multires) {
- /* Delete MDisps layer if not used by another multires modifier */
- if (object_modifier_safe_to_delete(bmain, ob, md, eModifierType_Multires))
- multires_customdata_delete(ob->data);
- }
- else if (md->type == eModifierType_Skin) {
- /* Delete MVertSkin layer if not used by another skin modifier */
- if (object_modifier_safe_to_delete(bmain, ob, md, eModifierType_Skin))
- modifier_skin_customdata_delete(ob);
- }
-
- if (ELEM(md->type, eModifierType_Softbody, eModifierType_Cloth) &&
- BLI_listbase_is_empty(&ob->particlesystem))
- {
- ob->mode &= ~OB_MODE_PARTICLE_EDIT;
- }
-
- BLI_remlink(&ob->modifiers, md);
- modifier_free(md);
- BKE_object_free_derived_caches(ob);
-
- return 1;
+static bool object_modifier_safe_to_delete(Main *bmain,
+ Object *ob,
+ ModifierData *exclude,
+ ModifierType type)
+{
+ return (!object_has_modifier(ob, exclude, type) &&
+ !ED_object_iter_other(bmain, ob, false, object_has_modifier_cb, &type));
+}
+
+static bool object_modifier_remove(Main *bmain,
+ Object *ob,
+ ModifierData *md,
+ bool *r_sort_depsgraph)
+{
+ /* It seems on rapid delete it is possible to
+ * get called twice on same modifier, so make
+ * sure it is in list. */
+ if (BLI_findindex(&ob->modifiers, md) == -1) {
+ return 0;
+ }
+
+ /* special cases */
+ if (md->type == eModifierType_ParticleSystem) {
+ ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
+
+ BLI_remlink(&ob->particlesystem, psmd->psys);
+ psys_free(ob, psmd->psys);
+ psmd->psys = NULL;
+ }
+ else if (md->type == eModifierType_Softbody) {
+ if (ob->soft) {
+ sbFree(ob);
+ ob->softflag = 0; /* TODO(Sybren): this should probably be moved into sbFree() */
+ }
+ }
+ else if (md->type == eModifierType_Collision) {
+ if (ob->pd)
+ ob->pd->deflect = 0;
+
+ *r_sort_depsgraph = true;
+ }
+ else if (md->type == eModifierType_Surface) {
+ *r_sort_depsgraph = true;
+ }
+ else if (md->type == eModifierType_Multires) {
+ /* Delete MDisps layer if not used by another multires modifier */
+ if (object_modifier_safe_to_delete(bmain, ob, md, eModifierType_Multires))
+ multires_customdata_delete(ob->data);
+ }
+ else if (md->type == eModifierType_Skin) {
+ /* Delete MVertSkin layer if not used by another skin modifier */
+ if (object_modifier_safe_to_delete(bmain, ob, md, eModifierType_Skin))
+ modifier_skin_customdata_delete(ob);
+ }
+
+ if (ELEM(md->type, eModifierType_Softbody, eModifierType_Cloth) &&
+ BLI_listbase_is_empty(&ob->particlesystem)) {
+ ob->mode &= ~OB_MODE_PARTICLE_EDIT;
+ }
+
+ BLI_remlink(&ob->modifiers, md);
+ modifier_free(md);
+ BKE_object_free_derived_caches(ob);
+
+ return 1;
}
bool ED_object_modifier_remove(ReportList *reports, Main *bmain, Object *ob, ModifierData *md)
{
- bool sort_depsgraph = false;
- bool ok;
+ bool sort_depsgraph = false;
+ bool ok;
- ok = object_modifier_remove(bmain, ob, md, &sort_depsgraph);
+ ok = object_modifier_remove(bmain, ob, md, &sort_depsgraph);
- if (!ok) {
- BKE_reportf(reports, RPT_ERROR, "Modifier '%s' not in object '%s'", md->name, ob->id.name);
- return 0;
- }
+ if (!ok) {
+ BKE_reportf(reports, RPT_ERROR, "Modifier '%s' not in object '%s'", md->name, ob->id.name);
+ return 0;
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(bmain);
- return 1;
+ return 1;
}
void ED_object_modifier_clear(Main *bmain, Object *ob)
{
- ModifierData *md = ob->modifiers.first;
- bool sort_depsgraph = false;
+ ModifierData *md = ob->modifiers.first;
+ bool sort_depsgraph = false;
- if (!md)
- return;
+ if (!md)
+ return;
- while (md) {
- ModifierData *next_md;
+ while (md) {
+ ModifierData *next_md;
- next_md = md->next;
+ next_md = md->next;
- object_modifier_remove(bmain, ob, md, &sort_depsgraph);
+ object_modifier_remove(bmain, ob, md, &sort_depsgraph);
- md = next_md;
- }
+ md = next_md;
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(bmain);
}
int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md)
{
- if (md->prev) {
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ if (md->prev) {
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- if (mti->type != eModifierTypeType_OnlyDeform) {
- const ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type);
+ if (mti->type != eModifierTypeType_OnlyDeform) {
+ const ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type);
- if (nmti->flags & eModifierTypeFlag_RequiresOriginalData) {
- BKE_report(reports, RPT_WARNING, "Cannot move above a modifier requiring original data");
- return 0;
- }
- }
+ if (nmti->flags & eModifierTypeFlag_RequiresOriginalData) {
+ BKE_report(reports, RPT_WARNING, "Cannot move above a modifier requiring original data");
+ return 0;
+ }
+ }
- BLI_remlink(&ob->modifiers, md);
- BLI_insertlinkbefore(&ob->modifiers, md->prev, md);
- }
+ BLI_remlink(&ob->modifiers, md);
+ BLI_insertlinkbefore(&ob->modifiers, md->prev, md);
+ }
- return 1;
+ return 1;
}
int ED_object_modifier_move_down(ReportList *reports, Object *ob, ModifierData *md)
{
- if (md->next) {
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ if (md->next) {
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- if (mti->flags & eModifierTypeFlag_RequiresOriginalData) {
- const ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type);
+ if (mti->flags & eModifierTypeFlag_RequiresOriginalData) {
+ const ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type);
- if (nmti->type != eModifierTypeType_OnlyDeform) {
- BKE_report(reports, RPT_WARNING, "Cannot move beyond a non-deforming modifier");
- return 0;
- }
- }
+ if (nmti->type != eModifierTypeType_OnlyDeform) {
+ BKE_report(reports, RPT_WARNING, "Cannot move beyond a non-deforming modifier");
+ return 0;
+ }
+ }
- BLI_remlink(&ob->modifiers, md);
- BLI_insertlinkafter(&ob->modifiers, md->next, md);
- }
+ BLI_remlink(&ob->modifiers, md);
+ BLI_insertlinkafter(&ob->modifiers, md->next, md);
+ }
- return 1;
+ return 1;
}
int ED_object_modifier_convert(ReportList *UNUSED(reports),
- Main *bmain, Depsgraph *depsgraph, Scene *scene, ViewLayer *view_layer,
- Object *ob, ModifierData *md)
-{
- Object *obn;
- ParticleSystem *psys_orig, *psys_eval;
- ParticleCacheKey *key, **cache;
- ParticleSettings *part;
- Mesh *me;
- MVert *mvert;
- MEdge *medge;
- int a, k, kmax;
- int totvert = 0, totedge = 0, cvert = 0;
- int totpart = 0, totchild = 0;
-
- if (md->type != eModifierType_ParticleSystem) return 0;
- if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) return 0;
-
- psys_orig = ((ParticleSystemModifierData *)md)->psys;
- part = psys_orig->part;
-
- if (part->ren_as != PART_DRAW_PATH) {
- return 0;
- }
- psys_eval = psys_eval_get(depsgraph, ob, psys_orig);
- if (psys_eval->pathcache == NULL) {
- return 0;
- }
-
- totpart = psys_eval->totcached;
- totchild = psys_eval->totchildcache;
-
- if (totchild && (part->draw & PART_DRAW_PARENT) == 0)
- totpart = 0;
-
- /* count */
- cache = psys_eval->pathcache;
- for (a = 0; a < totpart; a++) {
- key = cache[a];
-
- if (key->segments > 0) {
- totvert += key->segments + 1;
- totedge += key->segments;
- }
- }
-
- cache = psys_eval->childcache;
- for (a = 0; a < totchild; a++) {
- key = cache[a];
-
- if (key->segments > 0) {
- totvert += key->segments + 1;
- totedge += key->segments;
- }
- }
-
- if (totvert == 0) return 0;
-
- /* add new mesh */
- obn = BKE_object_add(bmain, scene, view_layer, OB_MESH, NULL);
- me = obn->data;
-
- me->totvert = totvert;
- me->totedge = totedge;
-
- me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
- me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
- me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0);
-
- mvert = me->mvert;
- medge = me->medge;
-
- /* copy coordinates */
- cache = psys_eval->pathcache;
- for (a = 0; a < totpart; a++) {
- key = cache[a];
- kmax = key->segments;
- for (k = 0; k <= kmax; k++, key++, cvert++, mvert++) {
- copy_v3_v3(mvert->co, key->co);
- if (k) {
- medge->v1 = cvert - 1;
- medge->v2 = cvert;
- medge->flag = ME_EDGEDRAW | ME_EDGERENDER | ME_LOOSEEDGE;
- medge++;
- }
- else {
- /* cheap trick to select the roots */
- mvert->flag |= SELECT;
- }
- }
- }
-
- cache = psys_eval->childcache;
- for (a = 0; a < totchild; a++) {
- key = cache[a];
- kmax = key->segments;
- for (k = 0; k <= kmax; k++, key++, cvert++, mvert++) {
- copy_v3_v3(mvert->co, key->co);
- if (k) {
- medge->v1 = cvert - 1;
- medge->v2 = cvert;
- medge->flag = ME_EDGEDRAW | ME_EDGERENDER | ME_LOOSEEDGE;
- medge++;
- }
- else {
- /* cheap trick to select the roots */
- mvert->flag |= SELECT;
- }
- }
- }
-
- DEG_relations_tag_update(bmain);
-
- return 1;
+ Main *bmain,
+ Depsgraph *depsgraph,
+ Scene *scene,
+ ViewLayer *view_layer,
+ Object *ob,
+ ModifierData *md)
+{
+ Object *obn;
+ ParticleSystem *psys_orig, *psys_eval;
+ ParticleCacheKey *key, **cache;
+ ParticleSettings *part;
+ Mesh *me;
+ MVert *mvert;
+ MEdge *medge;
+ int a, k, kmax;
+ int totvert = 0, totedge = 0, cvert = 0;
+ int totpart = 0, totchild = 0;
+
+ if (md->type != eModifierType_ParticleSystem)
+ return 0;
+ if (ob && ob->mode & OB_MODE_PARTICLE_EDIT)
+ return 0;
+
+ psys_orig = ((ParticleSystemModifierData *)md)->psys;
+ part = psys_orig->part;
+
+ if (part->ren_as != PART_DRAW_PATH) {
+ return 0;
+ }
+ psys_eval = psys_eval_get(depsgraph, ob, psys_orig);
+ if (psys_eval->pathcache == NULL) {
+ return 0;
+ }
+
+ totpart = psys_eval->totcached;
+ totchild = psys_eval->totchildcache;
+
+ if (totchild && (part->draw & PART_DRAW_PARENT) == 0)
+ totpart = 0;
+
+ /* count */
+ cache = psys_eval->pathcache;
+ for (a = 0; a < totpart; a++) {
+ key = cache[a];
+
+ if (key->segments > 0) {
+ totvert += key->segments + 1;
+ totedge += key->segments;
+ }
+ }
+
+ cache = psys_eval->childcache;
+ for (a = 0; a < totchild; a++) {
+ key = cache[a];
+
+ if (key->segments > 0) {
+ totvert += key->segments + 1;
+ totedge += key->segments;
+ }
+ }
+
+ if (totvert == 0)
+ return 0;
+
+ /* add new mesh */
+ obn = BKE_object_add(bmain, scene, view_layer, OB_MESH, NULL);
+ me = obn->data;
+
+ me->totvert = totvert;
+ me->totedge = totedge;
+
+ me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
+ me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
+ me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0);
+
+ mvert = me->mvert;
+ medge = me->medge;
+
+ /* copy coordinates */
+ cache = psys_eval->pathcache;
+ for (a = 0; a < totpart; a++) {
+ key = cache[a];
+ kmax = key->segments;
+ for (k = 0; k <= kmax; k++, key++, cvert++, mvert++) {
+ copy_v3_v3(mvert->co, key->co);
+ if (k) {
+ medge->v1 = cvert - 1;
+ medge->v2 = cvert;
+ medge->flag = ME_EDGEDRAW | ME_EDGERENDER | ME_LOOSEEDGE;
+ medge++;
+ }
+ else {
+ /* cheap trick to select the roots */
+ mvert->flag |= SELECT;
+ }
+ }
+ }
+
+ cache = psys_eval->childcache;
+ for (a = 0; a < totchild; a++) {
+ key = cache[a];
+ kmax = key->segments;
+ for (k = 0; k <= kmax; k++, key++, cvert++, mvert++) {
+ copy_v3_v3(mvert->co, key->co);
+ if (k) {
+ medge->v1 = cvert - 1;
+ medge->v2 = cvert;
+ medge->flag = ME_EDGEDRAW | ME_EDGERENDER | ME_LOOSEEDGE;
+ medge++;
+ }
+ else {
+ /* cheap trick to select the roots */
+ mvert->flag |= SELECT;
+ }
+ }
+ }
+
+ DEG_relations_tag_update(bmain);
+
+ return 1;
}
/* Gets mesh for the modifier which corresponds to an evaluated state. */
-static Mesh *modifier_apply_create_mesh_for_modifier(
- Depsgraph *depsgraph,
- Scene *UNUSED(scene),
- Object *object,
- ModifierData *md,
- bool build_shapekey_layers)
-{
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
- ModifierData *md_eval = modifiers_findByName(object_eval, md->name);
- Mesh *mesh_applied = BKE_mesh_create_derived_for_modifier(
- depsgraph, scene_eval, object_eval, md_eval, build_shapekey_layers);
- return mesh_applied;
-}
-
-static int modifier_apply_shape(
- Main *bmain, ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md)
-{
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
-
- if (mti->isDisabled && mti->isDisabled(scene, md, 0)) {
- BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
- return 0;
- }
-
- /*
- * It should be ridiculously easy to extract the original verts that we want
- * and form the shape data. We can probably use the CD KEYINDEX layer (or
- * whatever I ended up calling it, too tired to check now), though this would
- * by necessity have to make some potentially ugly assumptions about the order
- * of the mesh data :-/ you can probably assume in 99% of cases that the first
- * element of a given index is the original, and any subsequent duplicates are
- * copies/interpolates, but that's an assumption that would need to be tested
- * and then predominantly stated in comments in a half dozen headers.
- */
-
- if (ob->type == OB_MESH) {
- Mesh *mesh_applied;
- Mesh *me = ob->data;
- Key *key = me->key;
- KeyBlock *kb;
-
- if (!modifier_isSameTopology(md) || mti->type == eModifierTypeType_NonGeometrical) {
- BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to shapes");
- return 0;
- }
-
- mesh_applied = modifier_apply_create_mesh_for_modifier(depsgraph, scene, ob, md, false);
- if (!mesh_applied) {
- BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply");
- return 0;
- }
-
- if (key == NULL) {
- key = me->key = BKE_key_add(bmain, (ID *)me);
- key->type = KEY_RELATIVE;
- /* if that was the first key block added, then it was the basis.
- * Initialize it with the mesh, and add another for the modifier */
- kb = BKE_keyblock_add(key, NULL);
- BKE_keyblock_convert_from_mesh(me, key, kb);
- }
-
- kb = BKE_keyblock_add(key, md->name);
- BKE_mesh_nomain_to_meshkey(mesh_applied, me, kb);
-
- BKE_id_free(NULL, mesh_applied);
- }
- else {
- BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
- return 0;
- }
- return 1;
-}
-
-static int modifier_apply_obdata(ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md)
-{
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
-
- if (mti->isDisabled && mti->isDisabled(scene, md, 0)) {
- BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
- return 0;
- }
-
- if (ob->type == OB_MESH) {
- Mesh *mesh_applied;
- Mesh *me = ob->data;
- MultiresModifierData *mmd = find_multires_modifier_before(scene, md);
-
- if (me->key && mti->type != eModifierTypeType_NonGeometrical) {
- BKE_report(reports, RPT_ERROR, "Modifier cannot be applied to a mesh with shape keys");
- return 0;
- }
-
- /* Multires: ensure that recent sculpting is applied */
- if (md->type == eModifierType_Multires)
- multires_force_update(ob);
-
- if (mmd && mmd->totlvl && mti->type == eModifierTypeType_OnlyDeform) {
- if (!multiresModifier_reshapeFromDeformModifier(depsgraph, mmd, ob, md)) {
- BKE_report(reports, RPT_ERROR, "Multires modifier returned error, skipping apply");
- return 0;
- }
- }
- else {
- mesh_applied = modifier_apply_create_mesh_for_modifier(depsgraph, scene, ob, md, true);
- if (!mesh_applied) {
- BKE_report(reports, RPT_ERROR, "Modifier returned error, skipping apply");
- return 0;
- }
-
- BKE_mesh_nomain_to_mesh(mesh_applied, me, ob, &CD_MASK_MESH, true);
-
- if (md->type == eModifierType_Multires)
- multires_customdata_delete(me);
- }
- }
- else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
- Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
- Curve *curve = ob->data;
- Curve *curve_eval = (Curve *)object_eval->data;
- int numVerts;
- float (*vertexCos)[3];
- ModifierEvalContext mectx = {depsgraph, object_eval, 0};
-
- if (ELEM(mti->type, eModifierTypeType_Constructive, eModifierTypeType_Nonconstructive)) {
- BKE_report(reports, RPT_ERROR, "Transform curve to mesh in order to apply constructive modifiers");
- return 0;
- }
-
- BKE_report(reports, RPT_INFO, "Applied modifier only changed CV points, not tessellated/bevel vertices");
-
- vertexCos = BKE_curve_nurbs_vertexCos_get(&curve_eval->nurb, &numVerts);
- mti->deformVerts(md, &mectx, NULL, vertexCos, numVerts);
- BK_curve_nurbs_vertexCos_apply(&curve->nurb, vertexCos);
-
- MEM_freeN(vertexCos);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
- else {
- BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
- return 0;
- }
-
- /* lattice modifier can be applied to particle system too */
- if (ob->particlesystem.first) {
-
- ParticleSystem *psys = ob->particlesystem.first;
-
- for (; psys; psys = psys->next) {
-
- if (psys->part->type != PART_HAIR)
- continue;
-
- psys_apply_hair_lattice(depsgraph, scene, ob, psys);
- }
- }
-
- return 1;
-}
-
-int ED_object_modifier_apply(
- Main *bmain, ReportList *reports, Depsgraph *depsgraph,
- Scene *scene, Object *ob, ModifierData *md, int mode)
-{
- int prev_mode;
-
- if (BKE_object_is_in_editmode(ob)) {
- BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in edit mode");
- return 0;
- }
- else if (((ID *) ob->data)->us > 1) {
- BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
- return 0;
- }
- else if ((ob->mode & OB_MODE_SCULPT) &&
- (find_multires_modifier_before(scene, md)) &&
- (modifier_isSameTopology(md) == false))
- {
- BKE_report(reports, RPT_ERROR, "Constructive modifier cannot be applied to multi-res data in sculpt mode");
- return 0;
- }
-
- if (md != ob->modifiers.first)
- BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected");
-
- /* Get evaluated modifier, so object links pointer to evaluated data,
- * but still use original object it is applied to the original mesh. */
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
- ModifierData *md_eval = (ob_eval) ? modifiers_findByName(ob_eval, md->name) : md;
-
- /* allow apply of a not-realtime modifier, by first re-enabling realtime. */
- prev_mode = md_eval->mode;
- md_eval->mode |= eModifierMode_Realtime;
-
- if (mode == MODIFIER_APPLY_SHAPE) {
- if (!modifier_apply_shape(bmain, reports, depsgraph, scene, ob, md_eval)) {
- md_eval->mode = prev_mode;
- return 0;
- }
- }
- else {
- if (!modifier_apply_obdata(reports, depsgraph, scene, ob, md_eval)) {
- md_eval->mode = prev_mode;
- return 0;
- }
- }
-
- md_eval->mode = prev_mode;
- BLI_remlink(&ob->modifiers, md);
- modifier_free(md);
-
- BKE_object_free_derived_caches(ob);
-
- return 1;
+static Mesh *modifier_apply_create_mesh_for_modifier(Depsgraph *depsgraph,
+ Scene *UNUSED(scene),
+ Object *object,
+ ModifierData *md,
+ bool build_shapekey_layers)
+{
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
+ ModifierData *md_eval = modifiers_findByName(object_eval, md->name);
+ Mesh *mesh_applied = BKE_mesh_create_derived_for_modifier(
+ depsgraph, scene_eval, object_eval, md_eval, build_shapekey_layers);
+ return mesh_applied;
+}
+
+static int modifier_apply_shape(Main *bmain,
+ ReportList *reports,
+ Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ ModifierData *md)
+{
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+
+ if (mti->isDisabled && mti->isDisabled(scene, md, 0)) {
+ BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
+ return 0;
+ }
+
+ /*
+ * It should be ridiculously easy to extract the original verts that we want
+ * and form the shape data. We can probably use the CD KEYINDEX layer (or
+ * whatever I ended up calling it, too tired to check now), though this would
+ * by necessity have to make some potentially ugly assumptions about the order
+ * of the mesh data :-/ you can probably assume in 99% of cases that the first
+ * element of a given index is the original, and any subsequent duplicates are
+ * copies/interpolates, but that's an assumption that would need to be tested
+ * and then predominantly stated in comments in a half dozen headers.
+ */
+
+ if (ob->type == OB_MESH) {
+ Mesh *mesh_applied;
+ Mesh *me = ob->data;
+ Key *key = me->key;
+ KeyBlock *kb;
+
+ if (!modifier_isSameTopology(md) || mti->type == eModifierTypeType_NonGeometrical) {
+ BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to shapes");
+ return 0;
+ }
+
+ mesh_applied = modifier_apply_create_mesh_for_modifier(depsgraph, scene, ob, md, false);
+ if (!mesh_applied) {
+ BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply");
+ return 0;
+ }
+
+ if (key == NULL) {
+ key = me->key = BKE_key_add(bmain, (ID *)me);
+ key->type = KEY_RELATIVE;
+ /* if that was the first key block added, then it was the basis.
+ * Initialize it with the mesh, and add another for the modifier */
+ kb = BKE_keyblock_add(key, NULL);
+ BKE_keyblock_convert_from_mesh(me, key, kb);
+ }
+
+ kb = BKE_keyblock_add(key, md->name);
+ BKE_mesh_nomain_to_meshkey(mesh_applied, me, kb);
+
+ BKE_id_free(NULL, mesh_applied);
+ }
+ else {
+ BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
+ return 0;
+ }
+ return 1;
+}
+
+static int modifier_apply_obdata(
+ ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md)
+{
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+
+ if (mti->isDisabled && mti->isDisabled(scene, md, 0)) {
+ BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
+ return 0;
+ }
+
+ if (ob->type == OB_MESH) {
+ Mesh *mesh_applied;
+ Mesh *me = ob->data;
+ MultiresModifierData *mmd = find_multires_modifier_before(scene, md);
+
+ if (me->key && mti->type != eModifierTypeType_NonGeometrical) {
+ BKE_report(reports, RPT_ERROR, "Modifier cannot be applied to a mesh with shape keys");
+ return 0;
+ }
+
+ /* Multires: ensure that recent sculpting is applied */
+ if (md->type == eModifierType_Multires)
+ multires_force_update(ob);
+
+ if (mmd && mmd->totlvl && mti->type == eModifierTypeType_OnlyDeform) {
+ if (!multiresModifier_reshapeFromDeformModifier(depsgraph, mmd, ob, md)) {
+ BKE_report(reports, RPT_ERROR, "Multires modifier returned error, skipping apply");
+ return 0;
+ }
+ }
+ else {
+ mesh_applied = modifier_apply_create_mesh_for_modifier(depsgraph, scene, ob, md, true);
+ if (!mesh_applied) {
+ BKE_report(reports, RPT_ERROR, "Modifier returned error, skipping apply");
+ return 0;
+ }
+
+ BKE_mesh_nomain_to_mesh(mesh_applied, me, ob, &CD_MASK_MESH, true);
+
+ if (md->type == eModifierType_Multires)
+ multires_customdata_delete(me);
+ }
+ }
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
+ Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
+ Curve *curve = ob->data;
+ Curve *curve_eval = (Curve *)object_eval->data;
+ int numVerts;
+ float(*vertexCos)[3];
+ ModifierEvalContext mectx = {depsgraph, object_eval, 0};
+
+ if (ELEM(mti->type, eModifierTypeType_Constructive, eModifierTypeType_Nonconstructive)) {
+ BKE_report(
+ reports, RPT_ERROR, "Transform curve to mesh in order to apply constructive modifiers");
+ return 0;
+ }
+
+ BKE_report(reports,
+ RPT_INFO,
+ "Applied modifier only changed CV points, not tessellated/bevel vertices");
+
+ vertexCos = BKE_curve_nurbs_vertexCos_get(&curve_eval->nurb, &numVerts);
+ mti->deformVerts(md, &mectx, NULL, vertexCos, numVerts);
+ BK_curve_nurbs_vertexCos_apply(&curve->nurb, vertexCos);
+
+ MEM_freeN(vertexCos);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ else {
+ BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
+ return 0;
+ }
+
+ /* lattice modifier can be applied to particle system too */
+ if (ob->particlesystem.first) {
+
+ ParticleSystem *psys = ob->particlesystem.first;
+
+ for (; psys; psys = psys->next) {
+
+ if (psys->part->type != PART_HAIR)
+ continue;
+
+ psys_apply_hair_lattice(depsgraph, scene, ob, psys);
+ }
+ }
+
+ return 1;
+}
+
+int ED_object_modifier_apply(Main *bmain,
+ ReportList *reports,
+ Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ ModifierData *md,
+ int mode)
+{
+ int prev_mode;
+
+ if (BKE_object_is_in_editmode(ob)) {
+ BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in edit mode");
+ return 0;
+ }
+ else if (((ID *)ob->data)->us > 1) {
+ BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
+ return 0;
+ }
+ else if ((ob->mode & OB_MODE_SCULPT) && (find_multires_modifier_before(scene, md)) &&
+ (modifier_isSameTopology(md) == false)) {
+ BKE_report(reports,
+ RPT_ERROR,
+ "Constructive modifier cannot be applied to multi-res data in sculpt mode");
+ return 0;
+ }
+
+ if (md != ob->modifiers.first)
+ BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected");
+
+ /* Get evaluated modifier, so object links pointer to evaluated data,
+ * but still use original object it is applied to the original mesh. */
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ ModifierData *md_eval = (ob_eval) ? modifiers_findByName(ob_eval, md->name) : md;
+
+ /* allow apply of a not-realtime modifier, by first re-enabling realtime. */
+ prev_mode = md_eval->mode;
+ md_eval->mode |= eModifierMode_Realtime;
+
+ if (mode == MODIFIER_APPLY_SHAPE) {
+ if (!modifier_apply_shape(bmain, reports, depsgraph, scene, ob, md_eval)) {
+ md_eval->mode = prev_mode;
+ return 0;
+ }
+ }
+ else {
+ if (!modifier_apply_obdata(reports, depsgraph, scene, ob, md_eval)) {
+ md_eval->mode = prev_mode;
+ return 0;
+ }
+ }
+
+ md_eval->mode = prev_mode;
+ BLI_remlink(&ob->modifiers, md);
+ modifier_free(md);
+
+ BKE_object_free_derived_caches(ob);
+
+ return 1;
}
int ED_object_modifier_copy(ReportList *UNUSED(reports), Object *ob, ModifierData *md)
{
- ModifierData *nmd;
+ ModifierData *nmd;
- nmd = modifier_new(md->type);
- modifier_copyData(md, nmd);
- BLI_insertlinkafter(&ob->modifiers, md, nmd);
- modifier_unique_name(&ob->modifiers, nmd);
+ nmd = modifier_new(md->type);
+ modifier_copyData(md, nmd);
+ BLI_insertlinkafter(&ob->modifiers, md, nmd);
+ modifier_unique_name(&ob->modifiers, nmd);
- return 1;
+ return 1;
}
/************************ add modifier operator *********************/
static int modifier_add_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- int type = RNA_enum_get(op->ptr, "type");
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ int type = RNA_enum_get(op->ptr, "type");
- if (!ED_object_modifier_add(op->reports, bmain, scene, ob, NULL, type))
- return OPERATOR_CANCELLED;
+ if (!ED_object_modifier_add(op->reports, bmain, scene, ob, NULL, type))
+ return OPERATOR_CANCELLED;
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static const EnumPropertyItem *modifier_add_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *modifier_add_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- Object *ob = ED_object_active_context(C);
- EnumPropertyItem *item = NULL;
- const EnumPropertyItem *md_item, *group_item = NULL;
- const ModifierTypeInfo *mti;
- int totitem = 0, a;
+ Object *ob = ED_object_active_context(C);
+ EnumPropertyItem *item = NULL;
+ const EnumPropertyItem *md_item, *group_item = NULL;
+ const ModifierTypeInfo *mti;
+ int totitem = 0, a;
- if (!ob)
- return rna_enum_object_modifier_type_items;
+ if (!ob)
+ return rna_enum_object_modifier_type_items;
- for (a = 0; rna_enum_object_modifier_type_items[a].identifier; a++) {
- md_item = &rna_enum_object_modifier_type_items[a];
+ for (a = 0; rna_enum_object_modifier_type_items[a].identifier; a++) {
+ md_item = &rna_enum_object_modifier_type_items[a];
- if (md_item->identifier[0]) {
- mti = modifierType_getInfo(md_item->value);
+ if (md_item->identifier[0]) {
+ mti = modifierType_getInfo(md_item->value);
- if (mti->flags & eModifierTypeFlag_NoUserAdd)
- continue;
+ if (mti->flags & eModifierTypeFlag_NoUserAdd)
+ continue;
- if (!BKE_object_support_modifier_type_check(ob, md_item->value))
- continue;
- }
- else {
- group_item = md_item;
- md_item = NULL;
+ if (!BKE_object_support_modifier_type_check(ob, md_item->value))
+ continue;
+ }
+ else {
+ group_item = md_item;
+ md_item = NULL;
- continue;
- }
+ continue;
+ }
- if (group_item) {
- RNA_enum_item_add(&item, &totitem, group_item);
- group_item = NULL;
- }
+ if (group_item) {
+ RNA_enum_item_add(&item, &totitem, group_item);
+ group_item = NULL;
+ }
- RNA_enum_item_add(&item, &totitem, md_item);
- }
+ RNA_enum_item_add(&item, &totitem, md_item);
+ }
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
- return item;
+ return item;
}
void OBJECT_OT_modifier_add(wmOperatorType *ot)
{
- PropertyRNA *prop;
+ PropertyRNA *prop;
- /* identifiers */
- ot->name = "Add Modifier";
- ot->description = "Add a procedural operation/effect to the active object";
- ot->idname = "OBJECT_OT_modifier_add";
+ /* identifiers */
+ ot->name = "Add Modifier";
+ ot->description = "Add a procedural operation/effect to the active object";
+ ot->idname = "OBJECT_OT_modifier_add";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = modifier_add_exec;
- ot->poll = ED_operator_object_active_editable;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = modifier_add_exec;
+ ot->poll = ED_operator_object_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- prop = RNA_def_enum(ot->srna, "type", rna_enum_object_modifier_type_items, eModifierType_Subsurf, "Type", "");
- RNA_def_enum_funcs(prop, modifier_add_itemf);
- ot->prop = prop;
+ /* properties */
+ prop = RNA_def_enum(
+ ot->srna, "type", rna_enum_object_modifier_type_items, eModifierType_Subsurf, "Type", "");
+ RNA_def_enum_funcs(prop, modifier_add_itemf);
+ ot->prop = prop;
}
/************************ generic functions for operators using mod names and data context *********************/
bool edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
- Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
+ Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
- if (!ob || ID_IS_LINKED(ob)) return 0;
- if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) return 0;
- if (ptr.id.data && ID_IS_LINKED(ptr.id.data)) return 0;
+ if (!ob || ID_IS_LINKED(ob))
+ return 0;
+ if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0)
+ return 0;
+ if (ptr.id.data && ID_IS_LINKED(ptr.id.data))
+ return 0;
- if (ID_IS_STATIC_OVERRIDE(ob)) {
- CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from static override");
- return (((ModifierData *)ptr.data)->flag & eModifierFlag_StaticOverride_Local) != 0;
- }
+ if (ID_IS_STATIC_OVERRIDE(ob)) {
+ CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from static override");
+ return (((ModifierData *)ptr.data)->flag & eModifierFlag_StaticOverride_Local) != 0;
+ }
- return 1;
+ return 1;
}
bool edit_modifier_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_Modifier, 0);
+ return edit_modifier_poll_generic(C, &RNA_Modifier, 0);
}
void edit_modifier_properties(wmOperatorType *ot)
{
- PropertyRNA *prop = RNA_def_string(ot->srna, "modifier", NULL, MAX_NAME, "Modifier", "Name of the modifier to edit");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ PropertyRNA *prop = RNA_def_string(
+ ot->srna, "modifier", NULL, MAX_NAME, "Modifier", "Name of the modifier to edit");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
int edit_modifier_invoke_properties(bContext *C, wmOperator *op)
{
- ModifierData *md;
+ ModifierData *md;
- 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;
- }
- }
+ 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;
+ }
+ }
- return false;
+ return false;
}
ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type)
{
- char modifier_name[MAX_NAME];
- ModifierData *md;
- RNA_string_get(op->ptr, "modifier", modifier_name);
+ char modifier_name[MAX_NAME];
+ ModifierData *md;
+ RNA_string_get(op->ptr, "modifier", modifier_name);
- md = modifiers_findByName(ob, modifier_name);
+ md = modifiers_findByName(ob, modifier_name);
- if (md && type != 0 && md->type != type)
- md = NULL;
+ if (md && type != 0 && md->type != type)
+ md = NULL;
- return md;
+ return md;
}
/************************ remove modifier operator *********************/
static int modifier_remove_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = ED_object_active_context(C);
- ModifierData *md = edit_modifier_property_get(op, ob, 0);
- int mode_orig = ob->mode;
+ Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = ED_object_active_context(C);
+ 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))
- return OPERATOR_CANCELLED;
+ if (!md || !ED_object_modifier_remove(op->reports, bmain, ob, md))
+ return OPERATOR_CANCELLED;
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- /* if cloth/softbody was removed, particle mode could be cleared */
- if (mode_orig & OB_MODE_PARTICLE_EDIT) {
- if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0) {
- if (ob == OBACT(view_layer)) {
- WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
- }
- }
- }
- return OPERATOR_FINISHED;
+ /* if cloth/softbody was removed, particle mode could be cleared */
+ if (mode_orig & OB_MODE_PARTICLE_EDIT) {
+ if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0) {
+ if (ob == OBACT(view_layer)) {
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
+ }
+ }
+ }
+ return OPERATOR_FINISHED;
}
static int modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return modifier_remove_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return modifier_remove_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_modifier_remove(wmOperatorType *ot)
{
- ot->name = "Remove Modifier";
- ot->description = "Remove a modifier from the active object";
- ot->idname = "OBJECT_OT_modifier_remove";
+ ot->name = "Remove Modifier";
+ ot->description = "Remove a modifier from the active object";
+ ot->idname = "OBJECT_OT_modifier_remove";
- ot->invoke = modifier_remove_invoke;
- ot->exec = modifier_remove_exec;
- ot->poll = edit_modifier_poll;
+ ot->invoke = modifier_remove_invoke;
+ ot->exec = modifier_remove_exec;
+ ot->poll = edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/************************ move up modifier operator *********************/
static int modifier_move_up_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- ModifierData *md = edit_modifier_property_get(op, ob, 0);
+ Object *ob = ED_object_active_context(C);
+ ModifierData *md = edit_modifier_property_get(op, ob, 0);
- if (!md || !ED_object_modifier_move_up(op->reports, ob, md))
- return OPERATOR_CANCELLED;
+ if (!md || !ED_object_modifier_move_up(op->reports, ob, md))
+ return OPERATOR_CANCELLED;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return modifier_move_up_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return modifier_move_up_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_modifier_move_up(wmOperatorType *ot)
{
- ot->name = "Move Up Modifier";
- ot->description = "Move modifier up in the stack";
- ot->idname = "OBJECT_OT_modifier_move_up";
+ ot->name = "Move Up Modifier";
+ ot->description = "Move modifier up in the stack";
+ ot->idname = "OBJECT_OT_modifier_move_up";
- ot->invoke = modifier_move_up_invoke;
- ot->exec = modifier_move_up_exec;
- ot->poll = edit_modifier_poll;
+ ot->invoke = modifier_move_up_invoke;
+ ot->exec = modifier_move_up_exec;
+ ot->poll = edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/************************ move down modifier operator *********************/
static int modifier_move_down_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- ModifierData *md = edit_modifier_property_get(op, ob, 0);
+ Object *ob = ED_object_active_context(C);
+ ModifierData *md = edit_modifier_property_get(op, ob, 0);
- if (!md || !ED_object_modifier_move_down(op->reports, ob, md))
- return OPERATOR_CANCELLED;
+ if (!md || !ED_object_modifier_move_down(op->reports, ob, md))
+ return OPERATOR_CANCELLED;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return modifier_move_down_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return modifier_move_down_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_modifier_move_down(wmOperatorType *ot)
{
- ot->name = "Move Down Modifier";
- ot->description = "Move modifier down in the stack";
- ot->idname = "OBJECT_OT_modifier_move_down";
+ ot->name = "Move Down Modifier";
+ ot->description = "Move modifier down in the stack";
+ ot->idname = "OBJECT_OT_modifier_move_down";
- ot->invoke = modifier_move_down_invoke;
- ot->exec = modifier_move_down_exec;
- ot->poll = edit_modifier_poll;
+ ot->invoke = modifier_move_down_invoke;
+ ot->exec = modifier_move_down_exec;
+ ot->poll = edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/************************ apply modifier operator *********************/
static int modifier_apply_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- ModifierData *md = edit_modifier_property_get(op, ob, 0);
- int apply_as = RNA_enum_get(op->ptr, "apply_as");
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ 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)) {
- return OPERATOR_CANCELLED;
- }
+ if (!md || !ED_object_modifier_apply(bmain, op->reports, depsgraph, scene, 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);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return modifier_apply_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return modifier_apply_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
static const EnumPropertyItem modifier_apply_as_items[] = {
- {MODIFIER_APPLY_DATA, "DATA", 0, "Object Data", "Apply modifier to the object's data"},
- {MODIFIER_APPLY_SHAPE, "SHAPE", 0, "New Shape", "Apply deform-only modifier to a new shape on this object"},
- {0, NULL, 0, NULL, NULL},
+ {MODIFIER_APPLY_DATA, "DATA", 0, "Object Data", "Apply modifier to the object's data"},
+ {MODIFIER_APPLY_SHAPE,
+ "SHAPE",
+ 0,
+ "New Shape",
+ "Apply deform-only modifier to a new shape on this object"},
+ {0, NULL, 0, NULL, NULL},
};
void OBJECT_OT_modifier_apply(wmOperatorType *ot)
{
- ot->name = "Apply Modifier";
- ot->description = "Apply modifier and remove from the stack";
- ot->idname = "OBJECT_OT_modifier_apply";
+ ot->name = "Apply Modifier";
+ ot->description = "Apply modifier and remove from the stack";
+ ot->idname = "OBJECT_OT_modifier_apply";
- ot->invoke = modifier_apply_invoke;
- ot->exec = modifier_apply_exec;
- ot->poll = edit_modifier_poll;
+ ot->invoke = modifier_apply_invoke;
+ ot->exec = modifier_apply_exec;
+ ot->poll = edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- RNA_def_enum(ot->srna, "apply_as", modifier_apply_as_items, MODIFIER_APPLY_DATA, "Apply as", "How to apply the modifier to the geometry");
- edit_modifier_properties(ot);
+ RNA_def_enum(ot->srna,
+ "apply_as",
+ modifier_apply_as_items,
+ MODIFIER_APPLY_DATA,
+ "Apply as",
+ "How to apply the modifier to the geometry");
+ edit_modifier_properties(ot);
}
/************************ convert modifier operator *********************/
static int modifier_convert_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob = ED_object_active_context(C);
- ModifierData *md = edit_modifier_property_get(op, ob, 0);
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = ED_object_active_context(C);
+ ModifierData *md = edit_modifier_property_get(op, ob, 0);
- if (!md || !ED_object_modifier_convert(op->reports, bmain, depsgraph, scene, view_layer, ob, md))
- return OPERATOR_CANCELLED;
+ if (!md || !ED_object_modifier_convert(op->reports, bmain, depsgraph, scene, view_layer, ob, md))
+ return OPERATOR_CANCELLED;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int modifier_convert_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return modifier_convert_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return modifier_convert_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_modifier_convert(wmOperatorType *ot)
{
- ot->name = "Convert Modifier";
- ot->description = "Convert particles to a mesh object";
- ot->idname = "OBJECT_OT_modifier_convert";
+ ot->name = "Convert Modifier";
+ ot->description = "Convert particles to a mesh object";
+ ot->idname = "OBJECT_OT_modifier_convert";
- ot->invoke = modifier_convert_invoke;
- ot->exec = modifier_convert_exec;
- ot->poll = edit_modifier_poll;
+ ot->invoke = modifier_convert_invoke;
+ ot->exec = modifier_convert_exec;
+ ot->poll = edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/************************ copy modifier operator *********************/
static int modifier_copy_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- ModifierData *md = edit_modifier_property_get(op, ob, 0);
+ Object *ob = ED_object_active_context(C);
+ ModifierData *md = edit_modifier_property_get(op, ob, 0);
- if (!md || !ED_object_modifier_copy(op->reports, ob, md))
- return OPERATOR_CANCELLED;
+ if (!md || !ED_object_modifier_copy(op->reports, ob, md))
+ return OPERATOR_CANCELLED;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return modifier_copy_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return modifier_copy_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_modifier_copy(wmOperatorType *ot)
{
- ot->name = "Copy Modifier";
- ot->description = "Duplicate modifier at the same position in the stack";
- ot->idname = "OBJECT_OT_modifier_copy";
+ ot->name = "Copy Modifier";
+ ot->description = "Duplicate modifier at the same position in the stack";
+ ot->idname = "OBJECT_OT_modifier_copy";
- ot->invoke = modifier_copy_invoke;
- ot->exec = modifier_copy_exec;
- ot->poll = edit_modifier_poll;
+ ot->invoke = modifier_copy_invoke;
+ ot->exec = modifier_copy_exec;
+ ot->poll = edit_modifier_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/************* multires delete higher levels operator ****************/
static bool multires_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_MultiresModifier, (1 << OB_MESH));
+ return edit_modifier_poll_generic(C, &RNA_MultiresModifier, (1 << OB_MESH));
}
static int multires_higher_levels_delete_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(
+ op, ob, eModifierType_Multires);
- if (!mmd)
- return OPERATOR_CANCELLED;
+ if (!mmd)
+ return OPERATOR_CANCELLED;
- multiresModifier_del_levels(mmd, scene, ob, 1);
+ multiresModifier_del_levels(mmd, scene, ob, 1);
- ED_object_iter_other(
- CTX_data_main(C), ob, true,
- ED_object_multires_update_totlevels_cb,
- &mmd->totlvl);
+ ED_object_iter_other(
+ CTX_data_main(C), ob, true, ED_object_multires_update_totlevels_cb, &mmd->totlvl);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static int multires_higher_levels_delete_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int multires_higher_levels_delete_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return multires_higher_levels_delete_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return multires_higher_levels_delete_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_multires_higher_levels_delete(wmOperatorType *ot)
{
- ot->name = "Delete Higher Levels";
- ot->description = "Deletes the higher resolution mesh, potential loss of detail";
- ot->idname = "OBJECT_OT_multires_higher_levels_delete";
+ ot->name = "Delete Higher Levels";
+ ot->description = "Deletes the higher resolution mesh, potential loss of detail";
+ ot->idname = "OBJECT_OT_multires_higher_levels_delete";
- ot->poll = multires_poll;
- ot->invoke = multires_higher_levels_delete_invoke;
- ot->exec = multires_higher_levels_delete_exec;
+ ot->poll = multires_poll;
+ ot->invoke = multires_higher_levels_delete_invoke;
+ ot->exec = multires_higher_levels_delete_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/****************** multires subdivide operator *********************/
static int multires_subdivide_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(
+ op, ob, eModifierType_Multires);
- if (!mmd)
- return OPERATOR_CANCELLED;
+ if (!mmd)
+ return OPERATOR_CANCELLED;
- multiresModifier_subdivide(mmd, scene, ob, 0, mmd->simple);
+ multiresModifier_subdivide(mmd, scene, ob, 0, mmd->simple);
- ED_object_iter_other(
- CTX_data_main(C), ob, true,
- ED_object_multires_update_totlevels_cb,
- &mmd->totlvl);
+ ED_object_iter_other(
+ CTX_data_main(C), ob, true, ED_object_multires_update_totlevels_cb, &mmd->totlvl);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- if (ob->mode & OB_MODE_SCULPT) {
- /* ensure that grid paint mask layer is created */
- BKE_sculpt_mask_layers_ensure(ob, mmd);
- }
+ if (ob->mode & OB_MODE_SCULPT) {
+ /* ensure that grid paint mask layer is created */
+ BKE_sculpt_mask_layers_ensure(ob, mmd);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int multires_subdivide_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return multires_subdivide_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return multires_subdivide_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_multires_subdivide(wmOperatorType *ot)
{
- ot->name = "Multires Subdivide";
- ot->description = "Add a new level of subdivision";
- ot->idname = "OBJECT_OT_multires_subdivide";
+ ot->name = "Multires Subdivide";
+ ot->description = "Add a new level of subdivision";
+ ot->idname = "OBJECT_OT_multires_subdivide";
- ot->poll = multires_poll;
- ot->invoke = multires_subdivide_invoke;
- ot->exec = multires_subdivide_exec;
+ ot->poll = multires_poll;
+ ot->invoke = multires_subdivide_invoke;
+ ot->exec = multires_subdivide_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/****************** multires reshape operator *********************/
static int multires_reshape_exec(bContext *C, wmOperator *op)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *ob = ED_object_active_context(C), *secondob = NULL;
- MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob = ED_object_active_context(C), *secondob = NULL;
+ MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(
+ op, ob, eModifierType_Multires);
- if (!mmd)
- return OPERATOR_CANCELLED;
+ if (!mmd)
+ return OPERATOR_CANCELLED;
- if (mmd->lvl == 0) {
- BKE_report(op->reports, RPT_ERROR, "Reshape can work only with higher levels of subdivisions");
- return OPERATOR_CANCELLED;
- }
+ if (mmd->lvl == 0) {
+ BKE_report(op->reports, RPT_ERROR, "Reshape can work only with higher levels of subdivisions");
+ return OPERATOR_CANCELLED;
+ }
- CTX_DATA_BEGIN(C, Object *, selob, selected_editable_objects)
- {
- if (selob->type == OB_MESH && selob != ob) {
- secondob = selob;
- break;
- }
- }
- CTX_DATA_END;
+ CTX_DATA_BEGIN (C, Object *, selob, selected_editable_objects) {
+ if (selob->type == OB_MESH && selob != ob) {
+ secondob = selob;
+ break;
+ }
+ }
+ CTX_DATA_END;
- if (!secondob) {
- BKE_report(op->reports, RPT_ERROR, "Second selected mesh object required to copy shape from");
- return OPERATOR_CANCELLED;
- }
+ if (!secondob) {
+ BKE_report(op->reports, RPT_ERROR, "Second selected mesh object required to copy shape from");
+ return OPERATOR_CANCELLED;
+ }
- if (!multiresModifier_reshapeFromObject(depsgraph, mmd, ob, secondob)) {
- BKE_report(op->reports, RPT_ERROR, "Objects do not have the same number of vertices");
- return OPERATOR_CANCELLED;
- }
+ if (!multiresModifier_reshapeFromObject(depsgraph, mmd, ob, secondob)) {
+ BKE_report(op->reports, RPT_ERROR, "Objects do not have the same number of vertices");
+ return OPERATOR_CANCELLED;
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int multires_reshape_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return multires_reshape_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return multires_reshape_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_multires_reshape(wmOperatorType *ot)
{
- ot->name = "Multires Reshape";
- ot->description = "Copy vertex coordinates from other object";
- ot->idname = "OBJECT_OT_multires_reshape";
+ ot->name = "Multires Reshape";
+ ot->description = "Copy vertex coordinates from other object";
+ ot->idname = "OBJECT_OT_multires_reshape";
- ot->poll = multires_poll;
- ot->invoke = multires_reshape_invoke;
- ot->exec = multires_reshape_exec;
+ ot->poll = multires_poll;
+ ot->invoke = multires_reshape_invoke;
+ ot->exec = multires_reshape_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
-
-
/****************** multires save external operator *********************/
static int multires_external_save_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_active_context(C);
- Mesh *me = (ob) ? ob->data : op->customdata;
- char path[FILE_MAX];
- const bool relative = RNA_boolean_get(op->ptr, "relative_path");
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_active_context(C);
+ Mesh *me = (ob) ? ob->data : op->customdata;
+ char path[FILE_MAX];
+ const bool relative = RNA_boolean_get(op->ptr, "relative_path");
- if (!me)
- return OPERATOR_CANCELLED;
+ if (!me)
+ return OPERATOR_CANCELLED;
- if (CustomData_external_test(&me->ldata, CD_MDISPS))
- return OPERATOR_CANCELLED;
+ if (CustomData_external_test(&me->ldata, CD_MDISPS))
+ return OPERATOR_CANCELLED;
- RNA_string_get(op->ptr, "filepath", path);
+ RNA_string_get(op->ptr, "filepath", path);
- if (relative)
- BLI_path_rel(path, BKE_main_blendfile_path(bmain));
+ if (relative)
+ BLI_path_rel(path, BKE_main_blendfile_path(bmain));
- CustomData_external_add(&me->ldata, &me->id, CD_MDISPS, me->totloop, path);
- CustomData_external_write(&me->ldata, &me->id, CD_MASK_MESH.lmask, me->totloop, 0);
+ CustomData_external_add(&me->ldata, &me->id, CD_MDISPS, me->totloop, path);
+ CustomData_external_write(&me->ldata, &me->id, CD_MASK_MESH.lmask, me->totloop, 0);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int multires_external_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Object *ob = ED_object_active_context(C);
- MultiresModifierData *mmd;
- Mesh *me = ob->data;
- char path[FILE_MAX];
+ Object *ob = ED_object_active_context(C);
+ MultiresModifierData *mmd;
+ Mesh *me = ob->data;
+ char path[FILE_MAX];
- if (!edit_modifier_invoke_properties(C, op))
- return OPERATOR_CANCELLED;
+ if (!edit_modifier_invoke_properties(C, op))
+ return OPERATOR_CANCELLED;
- mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
+ mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
- if (!mmd)
- return OPERATOR_CANCELLED;
+ if (!mmd)
+ return OPERATOR_CANCELLED;
- if (CustomData_external_test(&me->ldata, CD_MDISPS))
- return OPERATOR_CANCELLED;
+ if (CustomData_external_test(&me->ldata, CD_MDISPS))
+ return OPERATOR_CANCELLED;
- if (RNA_struct_property_is_set(op->ptr, "filepath"))
- return multires_external_save_exec(C, op);
+ if (RNA_struct_property_is_set(op->ptr, "filepath"))
+ return multires_external_save_exec(C, op);
- op->customdata = me;
+ op->customdata = me;
- BLI_snprintf(path, sizeof(path), "//%s.btx", me->id.name + 2);
- RNA_string_set(op->ptr, "filepath", path);
+ BLI_snprintf(path, sizeof(path), "//%s.btx", me->id.name + 2);
+ RNA_string_set(op->ptr, "filepath", path);
- WM_event_add_fileselect(C, op);
+ WM_event_add_fileselect(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
void OBJECT_OT_multires_external_save(wmOperatorType *ot)
{
- ot->name = "Multires Save External";
- ot->description = "Save displacements to an external file";
- ot->idname = "OBJECT_OT_multires_external_save";
+ ot->name = "Multires Save External";
+ ot->description = "Save displacements to an external file";
+ ot->idname = "OBJECT_OT_multires_external_save";
- /* XXX modifier no longer in context after file browser .. ot->poll = multires_poll; */
- ot->exec = multires_external_save_exec;
- ot->invoke = multires_external_save_invoke;
- ot->poll = multires_poll;
+ /* XXX modifier no longer in context after file browser .. ot->poll = multires_poll; */
+ ot->exec = multires_external_save_exec;
+ ot->invoke = multires_external_save_invoke;
+ ot->poll = multires_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- WM_operator_properties_filesel(
- ot, FILE_TYPE_FOLDER | FILE_TYPE_BTX, FILE_SPECIAL, FILE_SAVE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
- edit_modifier_properties(ot);
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_BTX,
+ FILE_SPECIAL,
+ FILE_SAVE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_ALPHA);
+ edit_modifier_properties(ot);
}
/****************** multires pack operator *********************/
static int multires_external_pack_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_active_context(C);
- Mesh *me = ob->data;
+ Object *ob = ED_object_active_context(C);
+ Mesh *me = ob->data;
- if (!CustomData_external_test(&me->ldata, CD_MDISPS))
- return OPERATOR_CANCELLED;
+ if (!CustomData_external_test(&me->ldata, CD_MDISPS))
+ return OPERATOR_CANCELLED;
- /* XXX don't remove.. */
- CustomData_external_remove(&me->ldata, &me->id, CD_MDISPS, me->totloop);
+ /* XXX don't remove.. */
+ CustomData_external_remove(&me->ldata, &me->id, CD_MDISPS, me->totloop);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_multires_external_pack(wmOperatorType *ot)
{
- ot->name = "Multires Pack External";
- ot->description = "Pack displacements from an external file";
- ot->idname = "OBJECT_OT_multires_external_pack";
+ ot->name = "Multires Pack External";
+ ot->description = "Pack displacements from an external file";
+ ot->idname = "OBJECT_OT_multires_external_pack";
- ot->poll = multires_poll;
- ot->exec = multires_external_pack_exec;
+ ot->poll = multires_poll;
+ ot->exec = multires_external_pack_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************* multires apply base ***********************/
static int multires_base_apply_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(
+ op, ob, eModifierType_Multires);
- if (!mmd)
- return OPERATOR_CANCELLED;
+ if (!mmd)
+ return OPERATOR_CANCELLED;
- multiresModifier_base_apply(mmd, scene, ob);
+ multiresModifier_base_apply(mmd, scene, ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int multires_base_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return multires_base_apply_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return multires_base_apply_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
-
void OBJECT_OT_multires_base_apply(wmOperatorType *ot)
{
- ot->name = "Multires Apply Base";
- ot->description = "Modify the base mesh to conform to the displaced mesh";
- ot->idname = "OBJECT_OT_multires_base_apply";
+ ot->name = "Multires Apply Base";
+ ot->description = "Modify the base mesh to conform to the displaced mesh";
+ ot->idname = "OBJECT_OT_multires_base_apply";
- ot->poll = multires_poll;
- ot->invoke = multires_base_apply_invoke;
- ot->exec = multires_base_apply_exec;
+ ot->poll = multires_poll;
+ ot->invoke = multires_base_apply_invoke;
+ ot->exec = multires_base_apply_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
-
/************************** skin modifier ***********************/
static void modifier_skin_customdata_delete(Object *ob)
{
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
- if (em)
- BM_data_layer_free(em->bm, &em->bm->vdata, CD_MVERT_SKIN);
- else
- CustomData_free_layer_active(&me->vdata, CD_MVERT_SKIN, me->totvert);
+ if (em)
+ BM_data_layer_free(em->bm, &em->bm->vdata, CD_MVERT_SKIN);
+ else
+ CustomData_free_layer_active(&me->vdata, CD_MVERT_SKIN, me->totvert);
}
static bool skin_poll(bContext *C)
{
- return (!CTX_data_edit_object(C) &&
- edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH)));
+ return (!CTX_data_edit_object(C) &&
+ edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH)));
}
static bool skin_edit_poll(bContext *C)
{
- return (CTX_data_edit_object(C) &&
- edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH)));
+ return (CTX_data_edit_object(C) &&
+ edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH)));
}
static void skin_root_clear(BMVert *bm_vert, GSet *visited, const int cd_vert_skin_offset)
{
- BMEdge *bm_edge;
- BMIter bm_iter;
+ BMEdge *bm_edge;
+ BMIter bm_iter;
- BM_ITER_ELEM (bm_edge, &bm_iter, bm_vert, BM_EDGES_OF_VERT) {
- BMVert *v2 = BM_edge_other_vert(bm_edge, bm_vert);
+ BM_ITER_ELEM (bm_edge, &bm_iter, bm_vert, BM_EDGES_OF_VERT) {
+ BMVert *v2 = BM_edge_other_vert(bm_edge, bm_vert);
- if (BLI_gset_add(visited, v2)) {
- MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(v2, cd_vert_skin_offset);
+ if (BLI_gset_add(visited, v2)) {
+ MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(v2, cd_vert_skin_offset);
- /* clear vertex root flag and add to visited set */
- vs->flag &= ~MVERT_SKIN_ROOT;
+ /* clear vertex root flag and add to visited set */
+ vs->flag &= ~MVERT_SKIN_ROOT;
- skin_root_clear(v2, visited, cd_vert_skin_offset);
- }
- }
+ skin_root_clear(v2, visited, cd_vert_skin_offset);
+ }
+ }
}
static int skin_root_mark_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMesh *bm = em->bm;
- BMVert *bm_vert;
- BMIter bm_iter;
- GSet *visited;
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em->bm;
+ BMVert *bm_vert;
+ BMIter bm_iter;
+ GSet *visited;
- visited = BLI_gset_ptr_new(__func__);
+ visited = BLI_gset_ptr_new(__func__);
- BKE_mesh_ensure_skin_customdata(ob->data);
+ BKE_mesh_ensure_skin_customdata(ob->data);
- const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
+ const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
- BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT) &&
- BLI_gset_add(visited, bm_vert))
- {
- MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(bm_vert, cd_vert_skin_offset);
+ BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT) && BLI_gset_add(visited, bm_vert)) {
+ MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(bm_vert, cd_vert_skin_offset);
- /* mark vertex as root and add to visited set */
- vs->flag |= MVERT_SKIN_ROOT;
+ /* mark vertex as root and add to visited set */
+ vs->flag |= MVERT_SKIN_ROOT;
- /* clear root flag from all connected vertices (recursively) */
- skin_root_clear(bm_vert, visited, cd_vert_skin_offset);
- }
- }
+ /* clear root flag from all connected vertices (recursively) */
+ skin_root_clear(bm_vert, visited, cd_vert_skin_offset);
+ }
+ }
- BLI_gset_free(visited, NULL);
+ BLI_gset_free(visited, NULL);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_skin_root_mark(wmOperatorType *ot)
{
- ot->name = "Skin Root Mark";
- ot->description = "Mark selected vertices as roots";
- ot->idname = "OBJECT_OT_skin_root_mark";
+ ot->name = "Skin Root Mark";
+ ot->description = "Mark selected vertices as roots";
+ ot->idname = "OBJECT_OT_skin_root_mark";
- ot->poll = skin_edit_poll;
- ot->exec = skin_root_mark_exec;
+ ot->poll = skin_edit_poll;
+ ot->exec = skin_root_mark_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
typedef enum {
- SKIN_LOOSE_MARK,
- SKIN_LOOSE_CLEAR,
+ SKIN_LOOSE_MARK,
+ SKIN_LOOSE_CLEAR,
} SkinLooseAction;
static int skin_loose_mark_clear_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMesh *bm = em->bm;
- BMVert *bm_vert;
- BMIter bm_iter;
- SkinLooseAction action = RNA_enum_get(op->ptr, "action");
-
- if (!CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) {
- return OPERATOR_CANCELLED;
- }
-
- BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) {
- MVertSkin *vs = CustomData_bmesh_get(
- &bm->vdata,
- bm_vert->head.data,
- CD_MVERT_SKIN);
-
- switch (action) {
- case SKIN_LOOSE_MARK:
- vs->flag |= MVERT_SKIN_LOOSE;
- break;
- case SKIN_LOOSE_CLEAR:
- vs->flag &= ~MVERT_SKIN_LOOSE;
- break;
- }
- }
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
-
- return OPERATOR_FINISHED;
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em->bm;
+ BMVert *bm_vert;
+ BMIter bm_iter;
+ SkinLooseAction action = RNA_enum_get(op->ptr, "action");
+
+ if (!CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) {
+ MVertSkin *vs = CustomData_bmesh_get(&bm->vdata, bm_vert->head.data, CD_MVERT_SKIN);
+
+ switch (action) {
+ case SKIN_LOOSE_MARK:
+ vs->flag |= MVERT_SKIN_LOOSE;
+ break;
+ case SKIN_LOOSE_CLEAR:
+ vs->flag &= ~MVERT_SKIN_LOOSE;
+ break;
+ }
+ }
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_skin_loose_mark_clear(wmOperatorType *ot)
{
- static const EnumPropertyItem action_items[] = {
- {SKIN_LOOSE_MARK, "MARK", 0, "Mark", "Mark selected vertices as loose"},
- {SKIN_LOOSE_CLEAR, "CLEAR", 0, "Clear", "Set selected vertices as not loose"},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem action_items[] = {
+ {SKIN_LOOSE_MARK, "MARK", 0, "Mark", "Mark selected vertices as loose"},
+ {SKIN_LOOSE_CLEAR, "CLEAR", 0, "Clear", "Set selected vertices as not loose"},
+ {0, NULL, 0, NULL, NULL},
+ };
- ot->name = "Skin Mark/Clear Loose";
- ot->description = "Mark/clear selected vertices as loose";
- ot->idname = "OBJECT_OT_skin_loose_mark_clear";
+ ot->name = "Skin Mark/Clear Loose";
+ ot->description = "Mark/clear selected vertices as loose";
+ ot->idname = "OBJECT_OT_skin_loose_mark_clear";
- ot->poll = skin_edit_poll;
- ot->exec = skin_loose_mark_clear_exec;
+ ot->poll = skin_edit_poll;
+ ot->exec = skin_loose_mark_clear_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_enum(ot->srna, "action", action_items, SKIN_LOOSE_MARK, "Action", NULL);
+ RNA_def_enum(ot->srna, "action", action_items, SKIN_LOOSE_MARK, "Action", NULL);
}
static int skin_radii_equalize_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMesh *bm = em->bm;
- BMVert *bm_vert;
- BMIter bm_iter;
+ Object *ob = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em->bm;
+ BMVert *bm_vert;
+ BMIter bm_iter;
- if (!CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) {
- return OPERATOR_CANCELLED;
- }
+ if (!CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) {
+ return OPERATOR_CANCELLED;
+ }
- BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) {
- MVertSkin *vs = CustomData_bmesh_get(
- &bm->vdata,
- bm_vert->head.data,
- CD_MVERT_SKIN);
- float avg = (vs->radius[0] + vs->radius[1]) * 0.5f;
+ BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) {
+ MVertSkin *vs = CustomData_bmesh_get(&bm->vdata, bm_vert->head.data, CD_MVERT_SKIN);
+ float avg = (vs->radius[0] + vs->radius[1]) * 0.5f;
- vs->radius[0] = vs->radius[1] = avg;
- }
- }
+ vs->radius[0] = vs->radius[1] = avg;
+ }
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_skin_radii_equalize(wmOperatorType *ot)
{
- ot->name = "Skin Radii Equalize";
- ot->description = "Make skin radii of selected vertices equal on each axis";
- ot->idname = "OBJECT_OT_skin_radii_equalize";
+ ot->name = "Skin Radii Equalize";
+ ot->description = "Make skin radii of selected vertices equal on each axis";
+ ot->idname = "OBJECT_OT_skin_radii_equalize";
- ot->poll = skin_edit_poll;
- ot->exec = skin_radii_equalize_exec;
+ ot->poll = skin_edit_poll;
+ ot->exec = skin_radii_equalize_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static void skin_armature_bone_create(Object *skin_ob,
- MVert *mvert, MEdge *medge,
- bArmature *arm,
- BLI_bitmap *edges_visited,
- const MeshElemMap *emap,
- EditBone *parent_bone,
- int parent_v)
-{
- int i;
-
- for (i = 0; i < emap[parent_v].count; i++) {
- int endx = emap[parent_v].indices[i];
- const MEdge *e = &medge[endx];
- EditBone *bone;
- bDeformGroup *dg;
- int v;
-
- /* ignore edge if already visited */
- if (BLI_BITMAP_TEST(edges_visited, endx))
- continue;
- BLI_BITMAP_ENABLE(edges_visited, endx);
-
- v = (e->v1 == parent_v ? e->v2 : e->v1);
-
- bone = ED_armature_ebone_add(arm, "Bone");
-
- bone->parent = parent_bone;
- bone->flag |= BONE_CONNECTED;
-
- copy_v3_v3(bone->head, mvert[parent_v].co);
- copy_v3_v3(bone->tail, mvert[v].co);
- bone->rad_head = bone->rad_tail = 0.25;
- BLI_snprintf(bone->name, sizeof(bone->name), "Bone.%.2d", endx);
-
- /* add bDeformGroup */
- if ((dg = BKE_object_defgroup_add_name(skin_ob, bone->name))) {
- ED_vgroup_vert_add(skin_ob, dg, parent_v, 1, WEIGHT_REPLACE);
- ED_vgroup_vert_add(skin_ob, dg, v, 1, WEIGHT_REPLACE);
- }
-
- skin_armature_bone_create(
- skin_ob,
- mvert, medge,
- arm,
- edges_visited,
- emap,
- bone,
- v);
- }
-}
-
-static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain, Scene *scene, Object *skin_ob)
-{
- BLI_bitmap *edges_visited;
- Mesh *me_eval_deform;
- MVert *mvert;
- Mesh *me = skin_ob->data;
- Object *arm_ob;
- bArmature *arm;
- MVertSkin *mvert_skin;
- MeshElemMap *emap;
- int *emap_mem;
- int v;
-
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, skin_ob);
-
- me_eval_deform = mesh_get_eval_deform(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
- mvert = me_eval_deform->mvert;
-
- /* add vertex weights to original mesh */
- CustomData_add_layer(
- &me->vdata,
- CD_MDEFORMVERT,
- CD_CALLOC,
- NULL,
- me->totvert);
-
- ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
- arm_ob = BKE_object_add(bmain, scene, view_layer, OB_ARMATURE, NULL);
- BKE_object_transform_copy(arm_ob, skin_ob);
- arm = arm_ob->data;
- arm->layer = 1;
- arm_ob->dtx |= OB_DRAWXRAY;
- arm->drawtype = ARM_LINE;
- arm->edbo = MEM_callocN(sizeof(ListBase), "edbo armature");
-
- mvert_skin = CustomData_get_layer(&me->vdata, CD_MVERT_SKIN);
- BKE_mesh_vert_edge_map_create(
- &emap, &emap_mem,
- me->medge, me->totvert, me->totedge);
-
- edges_visited = BLI_BITMAP_NEW(me->totedge, "edge_visited");
-
- /* note: we use EditBones here, easier to set them up and use
- * edit-armature functions to convert back to regular bones */
- for (v = 0; v < me->totvert; v++) {
- if (mvert_skin[v].flag & MVERT_SKIN_ROOT) {
- EditBone *bone = NULL;
-
- /* Unless the skin root has just one adjacent edge, create
- * a fake root bone (have it going off in the Y direction
- * (arbitrary) */
- if (emap[v].count > 1) {
- bone = ED_armature_ebone_add(arm, "Bone");
-
- copy_v3_v3(bone->head, me->mvert[v].co);
- copy_v3_v3(bone->tail, me->mvert[v].co);
-
- bone->head[1] = 1.0f;
- bone->rad_head = bone->rad_tail = 0.25;
- }
-
- if (emap[v].count >= 1) {
- skin_armature_bone_create(
- skin_ob,
- mvert, me->medge,
- arm,
- edges_visited,
- emap,
- bone,
- v);
- }
- }
- }
-
- MEM_freeN(edges_visited);
- MEM_freeN(emap);
- MEM_freeN(emap_mem);
-
- ED_armature_from_edit(bmain, arm);
- ED_armature_edit_free(arm);
-
- return arm_ob;
+ MVert *mvert,
+ MEdge *medge,
+ bArmature *arm,
+ BLI_bitmap *edges_visited,
+ const MeshElemMap *emap,
+ EditBone *parent_bone,
+ int parent_v)
+{
+ int i;
+
+ for (i = 0; i < emap[parent_v].count; i++) {
+ int endx = emap[parent_v].indices[i];
+ const MEdge *e = &medge[endx];
+ EditBone *bone;
+ bDeformGroup *dg;
+ int v;
+
+ /* ignore edge if already visited */
+ if (BLI_BITMAP_TEST(edges_visited, endx))
+ continue;
+ BLI_BITMAP_ENABLE(edges_visited, endx);
+
+ v = (e->v1 == parent_v ? e->v2 : e->v1);
+
+ bone = ED_armature_ebone_add(arm, "Bone");
+
+ bone->parent = parent_bone;
+ bone->flag |= BONE_CONNECTED;
+
+ copy_v3_v3(bone->head, mvert[parent_v].co);
+ copy_v3_v3(bone->tail, mvert[v].co);
+ bone->rad_head = bone->rad_tail = 0.25;
+ BLI_snprintf(bone->name, sizeof(bone->name), "Bone.%.2d", endx);
+
+ /* add bDeformGroup */
+ if ((dg = BKE_object_defgroup_add_name(skin_ob, bone->name))) {
+ ED_vgroup_vert_add(skin_ob, dg, parent_v, 1, WEIGHT_REPLACE);
+ ED_vgroup_vert_add(skin_ob, dg, v, 1, WEIGHT_REPLACE);
+ }
+
+ skin_armature_bone_create(skin_ob, mvert, medge, arm, edges_visited, emap, bone, v);
+ }
+}
+
+static Object *modifier_skin_armature_create(Depsgraph *depsgraph,
+ Main *bmain,
+ Scene *scene,
+ Object *skin_ob)
+{
+ BLI_bitmap *edges_visited;
+ Mesh *me_eval_deform;
+ MVert *mvert;
+ Mesh *me = skin_ob->data;
+ Object *arm_ob;
+ bArmature *arm;
+ MVertSkin *mvert_skin;
+ MeshElemMap *emap;
+ int *emap_mem;
+ int v;
+
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, skin_ob);
+
+ me_eval_deform = mesh_get_eval_deform(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
+ mvert = me_eval_deform->mvert;
+
+ /* add vertex weights to original mesh */
+ CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert);
+
+ ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
+ arm_ob = BKE_object_add(bmain, scene, view_layer, OB_ARMATURE, NULL);
+ BKE_object_transform_copy(arm_ob, skin_ob);
+ arm = arm_ob->data;
+ arm->layer = 1;
+ arm_ob->dtx |= OB_DRAWXRAY;
+ arm->drawtype = ARM_LINE;
+ arm->edbo = MEM_callocN(sizeof(ListBase), "edbo armature");
+
+ mvert_skin = CustomData_get_layer(&me->vdata, CD_MVERT_SKIN);
+ BKE_mesh_vert_edge_map_create(&emap, &emap_mem, me->medge, me->totvert, me->totedge);
+
+ edges_visited = BLI_BITMAP_NEW(me->totedge, "edge_visited");
+
+ /* note: we use EditBones here, easier to set them up and use
+ * edit-armature functions to convert back to regular bones */
+ for (v = 0; v < me->totvert; v++) {
+ if (mvert_skin[v].flag & MVERT_SKIN_ROOT) {
+ EditBone *bone = NULL;
+
+ /* Unless the skin root has just one adjacent edge, create
+ * a fake root bone (have it going off in the Y direction
+ * (arbitrary) */
+ if (emap[v].count > 1) {
+ bone = ED_armature_ebone_add(arm, "Bone");
+
+ copy_v3_v3(bone->head, me->mvert[v].co);
+ copy_v3_v3(bone->tail, me->mvert[v].co);
+
+ bone->head[1] = 1.0f;
+ bone->rad_head = bone->rad_tail = 0.25;
+ }
+
+ if (emap[v].count >= 1) {
+ skin_armature_bone_create(skin_ob, mvert, me->medge, arm, edges_visited, emap, bone, v);
+ }
+ }
+ }
+
+ MEM_freeN(edges_visited);
+ MEM_freeN(emap);
+ MEM_freeN(emap_mem);
+
+ ED_armature_from_edit(bmain, arm);
+ ED_armature_edit_free(arm);
+
+ return arm_ob;
}
static int skin_armature_create_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = CTX_data_active_object(C), *arm_ob;
- Mesh *me = ob->data;
- ModifierData *skin_md;
- ArmatureModifierData *arm_md;
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C), *arm_ob;
+ Mesh *me = ob->data;
+ ModifierData *skin_md;
+ ArmatureModifierData *arm_md;
- if (!CustomData_has_layer(&me->vdata, CD_MVERT_SKIN)) {
- BKE_reportf(op->reports, RPT_WARNING, "Mesh '%s' has no skin vertex data", me->id.name + 2);
- return OPERATOR_CANCELLED;
- }
+ if (!CustomData_has_layer(&me->vdata, CD_MVERT_SKIN)) {
+ BKE_reportf(op->reports, RPT_WARNING, "Mesh '%s' has no skin vertex data", me->id.name + 2);
+ return OPERATOR_CANCELLED;
+ }
- /* create new armature */
- arm_ob = modifier_skin_armature_create(depsgraph, bmain, scene, ob);
+ /* create new armature */
+ arm_ob = modifier_skin_armature_create(depsgraph, bmain, scene, ob);
- /* add a modifier to connect the new armature to the mesh */
- arm_md = (ArmatureModifierData *)modifier_new(eModifierType_Armature);
- if (arm_md) {
- skin_md = edit_modifier_property_get(op, ob, eModifierType_Skin);
- BLI_insertlinkafter(&ob->modifiers, skin_md, arm_md);
+ /* add a modifier to connect the new armature to the mesh */
+ arm_md = (ArmatureModifierData *)modifier_new(eModifierType_Armature);
+ if (arm_md) {
+ skin_md = edit_modifier_property_get(op, ob, eModifierType_Skin);
+ BLI_insertlinkafter(&ob->modifiers, skin_md, arm_md);
- arm_md->object = arm_ob;
- arm_md->deformflag = ARM_DEF_VGROUP | ARM_DEF_QUATERNION;
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- }
+ arm_md->object = arm_ob;
+ arm_md->deformflag = ARM_DEF_VGROUP | ARM_DEF_QUATERNION;
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int skin_armature_create_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return skin_armature_create_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return skin_armature_create_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_skin_armature_create(wmOperatorType *ot)
{
- ot->name = "Skin Armature Create";
- ot->description = "Create an armature that parallels the skin layout";
- ot->idname = "OBJECT_OT_skin_armature_create";
+ ot->name = "Skin Armature Create";
+ ot->description = "Create an armature that parallels the skin layout";
+ ot->idname = "OBJECT_OT_skin_armature_create";
- ot->poll = skin_poll;
- ot->invoke = skin_armature_create_invoke;
- ot->exec = skin_armature_create_exec;
+ ot->poll = skin_poll;
+ ot->invoke = skin_armature_create_invoke;
+ ot->exec = skin_armature_create_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/************************ delta mush bind operator *********************/
static bool correctivesmooth_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_CorrectiveSmoothModifier, 0);
+ return edit_modifier_poll_generic(C, &RNA_CorrectiveSmoothModifier, 0);
}
static int correctivesmooth_bind_exec(bContext *C, wmOperator *op)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)edit_modifier_property_get(op, ob, eModifierType_CorrectiveSmooth);
- bool is_bind;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)edit_modifier_property_get(
+ op, ob, eModifierType_CorrectiveSmooth);
+ bool is_bind;
- if (!csmd) {
- return OPERATOR_CANCELLED;
- }
+ if (!csmd) {
+ return OPERATOR_CANCELLED;
+ }
- if (!modifier_isEnabled(scene, &csmd->modifier, eModifierMode_Realtime)) {
- BKE_report(op->reports, RPT_ERROR, "Modifier is disabled");
- return OPERATOR_CANCELLED;
- }
+ if (!modifier_isEnabled(scene, &csmd->modifier, eModifierMode_Realtime)) {
+ BKE_report(op->reports, RPT_ERROR, "Modifier is disabled");
+ return OPERATOR_CANCELLED;
+ }
- is_bind = (csmd->bind_coords != NULL);
+ is_bind = (csmd->bind_coords != NULL);
- MEM_SAFE_FREE(csmd->bind_coords);
- MEM_SAFE_FREE(csmd->delta_cache);
+ MEM_SAFE_FREE(csmd->bind_coords);
+ MEM_SAFE_FREE(csmd->delta_cache);
- if (is_bind) {
- /* toggle off */
- csmd->bind_coords_num = 0;
- }
- else {
- /* Signal to modifier to recalculate. */
- CorrectiveSmoothModifierData *csmd_eval =
- (CorrectiveSmoothModifierData *)modifier_get_evaluated(depsgraph, ob, &csmd->modifier);
- csmd_eval->bind_coords_num = (unsigned int)-1;
+ if (is_bind) {
+ /* toggle off */
+ csmd->bind_coords_num = 0;
+ }
+ else {
+ /* Signal to modifier to recalculate. */
+ CorrectiveSmoothModifierData *csmd_eval = (CorrectiveSmoothModifierData *)
+ modifier_get_evaluated(depsgraph, ob, &csmd->modifier);
+ csmd_eval->bind_coords_num = (unsigned int)-1;
- /* Force modifier to run, it will call binding routine
- * (this has to happen outside of depsgraph evaluation). */
- object_force_modifier_bind_simple_options(depsgraph, ob, &csmd->modifier);
- }
+ /* Force modifier to run, it will call binding routine
+ * (this has to happen outside of depsgraph evaluation). */
+ object_force_modifier_bind_simple_options(depsgraph, ob, &csmd->modifier);
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int correctivesmooth_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return correctivesmooth_bind_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return correctivesmooth_bind_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_correctivesmooth_bind(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Corrective Smooth Bind";
- ot->description = "Bind base pose in Corrective Smooth modifier";
- ot->idname = "OBJECT_OT_correctivesmooth_bind";
+ /* identifiers */
+ ot->name = "Corrective Smooth Bind";
+ ot->description = "Bind base pose in Corrective Smooth modifier";
+ ot->idname = "OBJECT_OT_correctivesmooth_bind";
- /* api callbacks */
- ot->poll = correctivesmooth_poll;
- ot->invoke = correctivesmooth_bind_invoke;
- ot->exec = correctivesmooth_bind_exec;
+ /* api callbacks */
+ ot->poll = correctivesmooth_poll;
+ ot->invoke = correctivesmooth_bind_invoke;
+ ot->exec = correctivesmooth_bind_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/************************ mdef bind operator *********************/
static bool meshdeform_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_MeshDeformModifier, 0);
+ return edit_modifier_poll_generic(C, &RNA_MeshDeformModifier, 0);
}
static int meshdeform_bind_exec(bContext *C, wmOperator *op)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *ob = ED_object_active_context(C);
- MeshDeformModifierData *mmd = (MeshDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_MeshDeform);
-
- if (mmd == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- if (mmd->bindcagecos != NULL) {
- MEM_SAFE_FREE(mmd->bindcagecos);
- MEM_SAFE_FREE(mmd->dyngrid);
- MEM_SAFE_FREE(mmd->dyninfluences);
- MEM_SAFE_FREE(mmd->bindinfluences);
- MEM_SAFE_FREE(mmd->bindoffsets);
- MEM_SAFE_FREE(mmd->dynverts);
- MEM_SAFE_FREE(mmd->bindweights); /* Deprecated */
- MEM_SAFE_FREE(mmd->bindcos); /* Deprecated */
- mmd->totvert = 0;
- mmd->totcagevert = 0;
- mmd->totinfluence = 0;
- }
- else {
- /* Force modifier to run, it will call binding routine (this has to happen outside of depsgraph evaluation). */
- MeshDeformModifierData *mmd_eval =
- (MeshDeformModifierData *)modifier_get_evaluated(depsgraph, ob, &mmd->modifier);
- mmd_eval->bindfunc = ED_mesh_deform_bind_callback;
- object_force_modifier_bind_simple_options(depsgraph, ob, &mmd->modifier);
- mmd_eval->bindfunc = NULL;
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob = ED_object_active_context(C);
+ MeshDeformModifierData *mmd = (MeshDeformModifierData *)edit_modifier_property_get(
+ op, ob, eModifierType_MeshDeform);
+
+ if (mmd == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (mmd->bindcagecos != NULL) {
+ MEM_SAFE_FREE(mmd->bindcagecos);
+ MEM_SAFE_FREE(mmd->dyngrid);
+ MEM_SAFE_FREE(mmd->dyninfluences);
+ MEM_SAFE_FREE(mmd->bindinfluences);
+ MEM_SAFE_FREE(mmd->bindoffsets);
+ MEM_SAFE_FREE(mmd->dynverts);
+ MEM_SAFE_FREE(mmd->bindweights); /* Deprecated */
+ MEM_SAFE_FREE(mmd->bindcos); /* Deprecated */
+ mmd->totvert = 0;
+ mmd->totcagevert = 0;
+ mmd->totinfluence = 0;
+ }
+ else {
+ /* Force modifier to run, it will call binding routine (this has to happen outside of depsgraph evaluation). */
+ MeshDeformModifierData *mmd_eval = (MeshDeformModifierData *)modifier_get_evaluated(
+ depsgraph, ob, &mmd->modifier);
+ mmd_eval->bindfunc = ED_mesh_deform_bind_callback;
+ object_force_modifier_bind_simple_options(depsgraph, ob, &mmd->modifier);
+ mmd_eval->bindfunc = NULL;
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ return OPERATOR_FINISHED;
}
static int meshdeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return meshdeform_bind_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return meshdeform_bind_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_meshdeform_bind(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Mesh Deform Bind";
- ot->description = "Bind mesh to cage in mesh deform modifier";
- ot->idname = "OBJECT_OT_meshdeform_bind";
+ /* identifiers */
+ ot->name = "Mesh Deform Bind";
+ ot->description = "Bind mesh to cage in mesh deform modifier";
+ ot->idname = "OBJECT_OT_meshdeform_bind";
- /* api callbacks */
- ot->poll = meshdeform_poll;
- ot->invoke = meshdeform_bind_invoke;
- ot->exec = meshdeform_bind_exec;
+ /* api callbacks */
+ ot->poll = meshdeform_poll;
+ ot->invoke = meshdeform_bind_invoke;
+ ot->exec = meshdeform_bind_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/****************** explode refresh operator *********************/
static bool explode_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_ExplodeModifier, 0);
+ return edit_modifier_poll_generic(C, &RNA_ExplodeModifier, 0);
}
static int explode_refresh_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- ExplodeModifierData *emd = (ExplodeModifierData *)edit_modifier_property_get(op, ob, eModifierType_Explode);
+ Object *ob = ED_object_active_context(C);
+ ExplodeModifierData *emd = (ExplodeModifierData *)edit_modifier_property_get(
+ op, ob, eModifierType_Explode);
- if (!emd)
- return OPERATOR_CANCELLED;
+ if (!emd)
+ return OPERATOR_CANCELLED;
- emd->flag |= eExplodeFlag_CalcFaces;
+ emd->flag |= eExplodeFlag_CalcFaces;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int explode_refresh_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return explode_refresh_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return explode_refresh_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
-
void OBJECT_OT_explode_refresh(wmOperatorType *ot)
{
- ot->name = "Explode Refresh";
- ot->description = "Refresh data in the Explode modifier";
- ot->idname = "OBJECT_OT_explode_refresh";
+ ot->name = "Explode Refresh";
+ ot->description = "Refresh data in the Explode modifier";
+ ot->idname = "OBJECT_OT_explode_refresh";
- ot->poll = explode_poll;
- ot->invoke = explode_refresh_invoke;
- ot->exec = explode_refresh_exec;
+ ot->poll = explode_poll;
+ ot->invoke = explode_refresh_invoke;
+ ot->exec = explode_refresh_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
-
/****************** ocean bake operator *********************/
static bool ocean_bake_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_OceanModifier, 0);
+ return edit_modifier_poll_generic(C, &RNA_OceanModifier, 0);
}
typedef struct OceanBakeJob {
- /* from wmJob */
- struct Object *owner;
- short *stop, *do_update;
- float *progress;
- int current_frame;
- struct OceanCache *och;
- struct Ocean *ocean;
- struct OceanModifierData *omd;
+ /* from wmJob */
+ struct Object *owner;
+ short *stop, *do_update;
+ float *progress;
+ int current_frame;
+ struct OceanCache *och;
+ struct Ocean *ocean;
+ struct OceanModifierData *omd;
} OceanBakeJob;
static void oceanbake_free(void *customdata)
{
- OceanBakeJob *oj = customdata;
- MEM_freeN(oj);
+ OceanBakeJob *oj = customdata;
+ MEM_freeN(oj);
}
/* called by oceanbake, only to check job 'stop' value */
static int oceanbake_breakjob(void *UNUSED(customdata))
{
- //OceanBakeJob *ob = (OceanBakeJob *)customdata;
- //return *(ob->stop);
+ //OceanBakeJob *ob = (OceanBakeJob *)customdata;
+ //return *(ob->stop);
- /* this is not nice yet, need to make the jobs list template better
- * for identifying/acting upon various different jobs */
- /* but for now we'll reuse the render break... */
- return (G.is_break);
+ /* this is not nice yet, need to make the jobs list template better
+ * for identifying/acting upon various different jobs */
+ /* but for now we'll reuse the render break... */
+ return (G.is_break);
}
/* called by oceanbake, wmJob sends notifier */
static void oceanbake_update(void *customdata, float progress, int *cancel)
{
- OceanBakeJob *oj = customdata;
+ OceanBakeJob *oj = customdata;
- if (oceanbake_breakjob(oj))
- *cancel = 1;
+ if (oceanbake_breakjob(oj))
+ *cancel = 1;
- *(oj->do_update) = true;
- *(oj->progress) = progress;
+ *(oj->do_update) = true;
+ *(oj->progress) = progress;
}
static void oceanbake_startjob(void *customdata, short *stop, short *do_update, float *progress)
{
- OceanBakeJob *oj = customdata;
+ OceanBakeJob *oj = customdata;
- oj->stop = stop;
- oj->do_update = do_update;
- oj->progress = progress;
+ oj->stop = stop;
+ oj->do_update = do_update;
+ oj->progress = progress;
- G.is_break = false; /* XXX shared with render - replace with job 'stop' switch */
+ G.is_break = false; /* XXX shared with render - replace with job 'stop' switch */
- BKE_ocean_bake(oj->ocean, oj->och, oceanbake_update, (void *)oj);
+ BKE_ocean_bake(oj->ocean, oj->och, oceanbake_update, (void *)oj);
- *do_update = true;
- *stop = 0;
+ *do_update = true;
+ *stop = 0;
}
static void oceanbake_endjob(void *customdata)
{
- OceanBakeJob *oj = customdata;
+ OceanBakeJob *oj = customdata;
- if (oj->ocean) {
- BKE_ocean_free(oj->ocean);
- oj->ocean = NULL;
- }
+ if (oj->ocean) {
+ BKE_ocean_free(oj->ocean);
+ oj->ocean = NULL;
+ }
- oj->omd->oceancache = oj->och;
- oj->omd->cached = true;
+ oj->omd->oceancache = oj->och;
+ oj->omd->cached = true;
- Object *ob = oj->owner;
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+ Object *ob = oj->owner;
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
}
static int ocean_bake_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_active_context(C);
- OceanModifierData *omd = (OceanModifierData *)edit_modifier_property_get(op, ob, eModifierType_Ocean);
- Scene *scene = CTX_data_scene(C);
- OceanCache *och;
- struct Ocean *ocean;
- int f, cfra, i = 0;
- const bool free = RNA_boolean_get(op->ptr, "free");
-
- wmJob *wm_job;
- OceanBakeJob *oj;
-
- if (!omd)
- return OPERATOR_CANCELLED;
-
- if (free) {
- BKE_ocean_free_modifier_cache(omd);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
- }
-
- och = BKE_ocean_init_cache(
- omd->cachepath, modifier_path_relbase(bmain, ob),
- omd->bakestart, omd->bakeend, omd->wave_scale,
- omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution);
-
- och->time = MEM_mallocN(och->duration * sizeof(float), "foam bake time");
-
- cfra = scene->r.cfra;
-
- /* precalculate time variable before baking */
- for (f = omd->bakestart; f <= omd->bakeend; f++) {
- /* For now only simple animation of time value is supported, nothing else.
- * No drivers or other modifier parameters. */
- BKE_animsys_evaluate_animdata(CTX_data_depsgraph(C), scene, (ID *)ob, ob->adt, f, ADT_RECALC_ANIM);
-
- och->time[i] = omd->time;
- i++;
- }
-
- /* make a copy of ocean to use for baking - threadsafety */
- ocean = BKE_ocean_add();
- BKE_ocean_init_from_modifier(ocean, omd);
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_active_context(C);
+ OceanModifierData *omd = (OceanModifierData *)edit_modifier_property_get(
+ op, ob, eModifierType_Ocean);
+ Scene *scene = CTX_data_scene(C);
+ OceanCache *och;
+ struct Ocean *ocean;
+ int f, cfra, i = 0;
+ const bool free = RNA_boolean_get(op->ptr, "free");
+
+ wmJob *wm_job;
+ OceanBakeJob *oj;
+
+ if (!omd)
+ return OPERATOR_CANCELLED;
+
+ if (free) {
+ BKE_ocean_free_modifier_cache(omd);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ return OPERATOR_FINISHED;
+ }
+
+ och = BKE_ocean_init_cache(omd->cachepath,
+ modifier_path_relbase(bmain, ob),
+ omd->bakestart,
+ omd->bakeend,
+ omd->wave_scale,
+ omd->chop_amount,
+ omd->foam_coverage,
+ omd->foam_fade,
+ omd->resolution);
+
+ och->time = MEM_mallocN(och->duration * sizeof(float), "foam bake time");
+
+ cfra = scene->r.cfra;
+
+ /* precalculate time variable before baking */
+ for (f = omd->bakestart; f <= omd->bakeend; f++) {
+ /* For now only simple animation of time value is supported, nothing else.
+ * No drivers or other modifier parameters. */
+ BKE_animsys_evaluate_animdata(
+ CTX_data_depsgraph(C), scene, (ID *)ob, ob->adt, f, ADT_RECALC_ANIM);
+
+ och->time[i] = omd->time;
+ i++;
+ }
+
+ /* make a copy of ocean to use for baking - threadsafety */
+ ocean = BKE_ocean_add();
+ BKE_ocean_init_from_modifier(ocean, omd);
#if 0
- BKE_ocean_bake(ocean, och);
+ BKE_ocean_bake(ocean, och);
- omd->oceancache = och;
- omd->cached = true;
+ omd->oceancache = och;
+ omd->cached = true;
- scene->r.cfra = cfra;
+ scene->r.cfra = cfra;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
#endif
- /* job stuff */
+ /* job stuff */
- scene->r.cfra = cfra;
+ scene->r.cfra = cfra;
- /* setup job */
- wm_job = WM_jobs_get(
- CTX_wm_manager(C), CTX_wm_window(C), scene, "Ocean Simulation",
- WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_SIM_OCEAN);
- oj = MEM_callocN(sizeof(OceanBakeJob), "ocean bake job");
- oj->owner = ob;
- oj->ocean = ocean;
- oj->och = och;
- oj->omd = omd;
+ /* setup job */
+ wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ scene,
+ "Ocean Simulation",
+ WM_JOB_PROGRESS,
+ WM_JOB_TYPE_OBJECT_SIM_OCEAN);
+ oj = MEM_callocN(sizeof(OceanBakeJob), "ocean bake job");
+ oj->owner = ob;
+ oj->ocean = ocean;
+ oj->och = och;
+ oj->omd = omd;
- WM_jobs_customdata_set(wm_job, oj, oceanbake_free);
- WM_jobs_timer(wm_job, 0.1, NC_OBJECT | ND_MODIFIER, NC_OBJECT | ND_MODIFIER);
- WM_jobs_callbacks(wm_job, oceanbake_startjob, NULL, NULL, oceanbake_endjob);
+ WM_jobs_customdata_set(wm_job, oj, oceanbake_free);
+ WM_jobs_timer(wm_job, 0.1, NC_OBJECT | ND_MODIFIER, NC_OBJECT | ND_MODIFIER);
+ WM_jobs_callbacks(wm_job, oceanbake_startjob, NULL, NULL, oceanbake_endjob);
- WM_jobs_start(CTX_wm_manager(C), wm_job);
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
-
-
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int ocean_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return ocean_bake_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return ocean_bake_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
-
void OBJECT_OT_ocean_bake(wmOperatorType *ot)
{
- ot->name = "Bake Ocean";
- ot->description = "Bake an image sequence of ocean data";
- ot->idname = "OBJECT_OT_ocean_bake";
+ ot->name = "Bake Ocean";
+ ot->description = "Bake an image sequence of ocean data";
+ ot->idname = "OBJECT_OT_ocean_bake";
- ot->poll = ocean_bake_poll;
- ot->invoke = ocean_bake_invoke;
- ot->exec = ocean_bake_exec;
+ ot->poll = ocean_bake_poll;
+ ot->invoke = ocean_bake_invoke;
+ ot->exec = ocean_bake_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
- RNA_def_boolean(ot->srna, "free", false, "Free", "Free the bake, rather than generating it");
+ RNA_def_boolean(ot->srna, "free", false, "Free", "Free the bake, rather than generating it");
}
/************************ LaplacianDeform bind operator *********************/
static bool laplaciandeform_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_LaplacianDeformModifier, 0);
+ return edit_modifier_poll_generic(C, &RNA_LaplacianDeformModifier, 0);
}
static int laplaciandeform_bind_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_LaplacianDeform);
-
- if (lmd == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- if (lmd->flag & MOD_LAPLACIANDEFORM_BIND) {
- lmd->flag &= ~MOD_LAPLACIANDEFORM_BIND;
- }
- else {
- lmd->flag |= MOD_LAPLACIANDEFORM_BIND;
- }
-
- LaplacianDeformModifierData *lmd_eval =
- (LaplacianDeformModifierData *)modifier_get_evaluated(depsgraph, ob, &lmd->modifier);
- lmd_eval->flag = lmd->flag;
-
- /* Force modifier to run, it will call binding routine
- * (this has to happen outside of depsgraph evaluation). */
- object_force_modifier_bind_simple_options(depsgraph, ob, &lmd->modifier);
-
- /* This is hard to know from the modifier itself whether the evaluation is
- * happening for binding or not. So we copy all the required data here. */
- lmd->total_verts = lmd_eval->total_verts;
- if (lmd_eval->vertexco == NULL) {
- MEM_SAFE_FREE(lmd->vertexco);
- }
- else {
- lmd->vertexco = MEM_dupallocN(lmd_eval->vertexco);
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ Object *ob = ED_object_active_context(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)edit_modifier_property_get(
+ op, ob, eModifierType_LaplacianDeform);
+
+ if (lmd == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (lmd->flag & MOD_LAPLACIANDEFORM_BIND) {
+ lmd->flag &= ~MOD_LAPLACIANDEFORM_BIND;
+ }
+ else {
+ lmd->flag |= MOD_LAPLACIANDEFORM_BIND;
+ }
+
+ LaplacianDeformModifierData *lmd_eval = (LaplacianDeformModifierData *)modifier_get_evaluated(
+ depsgraph, ob, &lmd->modifier);
+ lmd_eval->flag = lmd->flag;
+
+ /* Force modifier to run, it will call binding routine
+ * (this has to happen outside of depsgraph evaluation). */
+ object_force_modifier_bind_simple_options(depsgraph, ob, &lmd->modifier);
+
+ /* This is hard to know from the modifier itself whether the evaluation is
+ * happening for binding or not. So we copy all the required data here. */
+ lmd->total_verts = lmd_eval->total_verts;
+ if (lmd_eval->vertexco == NULL) {
+ MEM_SAFE_FREE(lmd->vertexco);
+ }
+ else {
+ lmd->vertexco = MEM_dupallocN(lmd_eval->vertexco);
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ return OPERATOR_FINISHED;
}
static int laplaciandeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return laplaciandeform_bind_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return laplaciandeform_bind_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_laplaciandeform_bind(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Laplacian Deform Bind";
- ot->description = "Bind mesh to system in laplacian deform modifier";
- ot->idname = "OBJECT_OT_laplaciandeform_bind";
+ /* identifiers */
+ ot->name = "Laplacian Deform Bind";
+ ot->description = "Bind mesh to system in laplacian deform modifier";
+ ot->idname = "OBJECT_OT_laplaciandeform_bind";
- /* api callbacks */
- ot->poll = laplaciandeform_poll;
- ot->invoke = laplaciandeform_bind_invoke;
- ot->exec = laplaciandeform_bind_exec;
+ /* api callbacks */
+ ot->poll = laplaciandeform_poll;
+ ot->invoke = laplaciandeform_bind_invoke;
+ ot->exec = laplaciandeform_bind_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
/************************ sdef bind operator *********************/
static bool surfacedeform_bind_poll(bContext *C)
{
- return edit_modifier_poll_generic(C, &RNA_SurfaceDeformModifier, 0);
+ return edit_modifier_poll_generic(C, &RNA_SurfaceDeformModifier, 0);
}
static int surfacedeform_bind_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_SurfaceDeform);
+ Object *ob = ED_object_active_context(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)edit_modifier_property_get(
+ op, ob, eModifierType_SurfaceDeform);
- if (smd == NULL) {
- return OPERATOR_CANCELLED;
- }
+ if (smd == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- if (smd->flags & MOD_SDEF_BIND) {
- smd->flags &= ~MOD_SDEF_BIND;
- }
- else if (smd->target) {
- smd->flags |= MOD_SDEF_BIND;
- }
+ if (smd->flags & MOD_SDEF_BIND) {
+ smd->flags &= ~MOD_SDEF_BIND;
+ }
+ else if (smd->target) {
+ smd->flags |= MOD_SDEF_BIND;
+ }
- SurfaceDeformModifierData *smd_eval =
- (SurfaceDeformModifierData *)modifier_get_evaluated(depsgraph, ob, &smd->modifier);
- smd_eval->flags = smd->flags;
+ SurfaceDeformModifierData *smd_eval = (SurfaceDeformModifierData *)modifier_get_evaluated(
+ depsgraph, ob, &smd->modifier);
+ smd_eval->flags = smd->flags;
- /* Force modifier to run, it will call binding routine
- * (this has to happen outside of depsgraph evaluation). */
- object_force_modifier_bind_simple_options(depsgraph, ob, &smd->modifier);
+ /* Force modifier to run, it will call binding routine
+ * (this has to happen outside of depsgraph evaluation). */
+ object_force_modifier_bind_simple_options(depsgraph, ob, &smd->modifier);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ return OPERATOR_FINISHED;
}
static int surfacedeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_modifier_invoke_properties(C, op))
- return surfacedeform_bind_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_modifier_invoke_properties(C, op))
+ return surfacedeform_bind_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_surfacedeform_bind(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Surface Deform Bind";
- ot->description = "Bind mesh to target in surface deform modifier";
- ot->idname = "OBJECT_OT_surfacedeform_bind";
+ /* identifiers */
+ ot->name = "Surface Deform Bind";
+ ot->description = "Bind mesh to target in surface deform modifier";
+ ot->idname = "OBJECT_OT_surfacedeform_bind";
- /* api callbacks */
- ot->poll = surfacedeform_bind_poll;
- ot->invoke = surfacedeform_bind_invoke;
- ot->exec = surfacedeform_bind_exec;
+ /* api callbacks */
+ ot->poll = surfacedeform_bind_poll;
+ ot->invoke = surfacedeform_bind_invoke;
+ ot->exec = surfacedeform_bind_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
}
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index 024fa24480a..8e3f916b2e4 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include <stdlib.h>
#include <math.h>
@@ -46,262 +45,263 @@
#include "object_intern.h"
-
/* ************************** registration **********************************/
-
void ED_operatortypes_object(void)
{
- WM_operatortype_append(OBJECT_OT_location_clear);
- WM_operatortype_append(OBJECT_OT_rotation_clear);
- WM_operatortype_append(OBJECT_OT_scale_clear);
- WM_operatortype_append(OBJECT_OT_origin_clear);
- WM_operatortype_append(OBJECT_OT_visual_transform_apply);
- WM_operatortype_append(OBJECT_OT_transform_apply);
- WM_operatortype_append(OBJECT_OT_transform_axis_target);
- WM_operatortype_append(OBJECT_OT_origin_set);
-
- WM_operatortype_append(OBJECT_OT_mode_set);
- WM_operatortype_append(OBJECT_OT_mode_set_or_submode);
- WM_operatortype_append(OBJECT_OT_editmode_toggle);
- WM_operatortype_append(OBJECT_OT_posemode_toggle);
- WM_operatortype_append(OBJECT_OT_proxy_make);
- WM_operatortype_append(OBJECT_OT_shade_smooth);
- WM_operatortype_append(OBJECT_OT_shade_flat);
- WM_operatortype_append(OBJECT_OT_paths_calculate);
- WM_operatortype_append(OBJECT_OT_paths_update);
- WM_operatortype_append(OBJECT_OT_paths_clear);
- WM_operatortype_append(OBJECT_OT_paths_range_update);
- WM_operatortype_append(OBJECT_OT_forcefield_toggle);
-
- WM_operatortype_append(OBJECT_OT_parent_set);
- WM_operatortype_append(OBJECT_OT_parent_no_inverse_set);
- WM_operatortype_append(OBJECT_OT_parent_clear);
- WM_operatortype_append(OBJECT_OT_vertex_parent_set);
- WM_operatortype_append(OBJECT_OT_track_set);
- WM_operatortype_append(OBJECT_OT_track_clear);
- WM_operatortype_append(OBJECT_OT_make_local);
- WM_operatortype_append(OBJECT_OT_make_override_static);
- WM_operatortype_append(OBJECT_OT_make_single_user);
- WM_operatortype_append(OBJECT_OT_make_links_scene);
- WM_operatortype_append(OBJECT_OT_make_links_data);
-
- WM_operatortype_append(OBJECT_OT_select_random);
- WM_operatortype_append(OBJECT_OT_select_all);
- WM_operatortype_append(OBJECT_OT_select_same_collection);
- WM_operatortype_append(OBJECT_OT_select_by_type);
- WM_operatortype_append(OBJECT_OT_select_linked);
- WM_operatortype_append(OBJECT_OT_select_grouped);
- WM_operatortype_append(OBJECT_OT_select_mirror);
- WM_operatortype_append(OBJECT_OT_select_more);
- WM_operatortype_append(OBJECT_OT_select_less);
-
- WM_operatortype_append(COLLECTION_OT_create);
- WM_operatortype_append(COLLECTION_OT_objects_remove_all);
- WM_operatortype_append(COLLECTION_OT_objects_remove);
- WM_operatortype_append(COLLECTION_OT_objects_add_active);
- WM_operatortype_append(COLLECTION_OT_objects_remove_active);
-
- WM_operatortype_append(OBJECT_OT_delete);
- WM_operatortype_append(OBJECT_OT_text_add);
- WM_operatortype_append(OBJECT_OT_armature_add);
- WM_operatortype_append(OBJECT_OT_empty_add);
- WM_operatortype_append(OBJECT_OT_lightprobe_add);
- WM_operatortype_append(OBJECT_OT_drop_named_image);
- WM_operatortype_append(OBJECT_OT_gpencil_add);
- WM_operatortype_append(OBJECT_OT_light_add);
- WM_operatortype_append(OBJECT_OT_camera_add);
- WM_operatortype_append(OBJECT_OT_speaker_add);
- WM_operatortype_append(OBJECT_OT_add);
- WM_operatortype_append(OBJECT_OT_add_named);
- WM_operatortype_append(OBJECT_OT_effector_add);
- WM_operatortype_append(OBJECT_OT_collection_instance_add);
- WM_operatortype_append(OBJECT_OT_metaball_add);
- WM_operatortype_append(OBJECT_OT_duplicates_make_real);
- WM_operatortype_append(OBJECT_OT_duplicate);
- WM_operatortype_append(OBJECT_OT_join);
- WM_operatortype_append(OBJECT_OT_join_shapes);
- WM_operatortype_append(OBJECT_OT_convert);
-
- WM_operatortype_append(OBJECT_OT_modifier_add);
- WM_operatortype_append(OBJECT_OT_modifier_remove);
- WM_operatortype_append(OBJECT_OT_modifier_move_up);
- WM_operatortype_append(OBJECT_OT_modifier_move_down);
- WM_operatortype_append(OBJECT_OT_modifier_apply);
- WM_operatortype_append(OBJECT_OT_modifier_convert);
- WM_operatortype_append(OBJECT_OT_modifier_copy);
- WM_operatortype_append(OBJECT_OT_multires_subdivide);
- WM_operatortype_append(OBJECT_OT_multires_reshape);
- WM_operatortype_append(OBJECT_OT_multires_higher_levels_delete);
- WM_operatortype_append(OBJECT_OT_multires_base_apply);
- WM_operatortype_append(OBJECT_OT_multires_external_save);
- WM_operatortype_append(OBJECT_OT_multires_external_pack);
- WM_operatortype_append(OBJECT_OT_skin_root_mark);
- WM_operatortype_append(OBJECT_OT_skin_loose_mark_clear);
- WM_operatortype_append(OBJECT_OT_skin_radii_equalize);
- WM_operatortype_append(OBJECT_OT_skin_armature_create);
-
- /* grease pencil modifiers */
- WM_operatortype_append(OBJECT_OT_gpencil_modifier_add);
- 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_apply);
- WM_operatortype_append(OBJECT_OT_gpencil_modifier_copy);
-
- /* shader fx */
- WM_operatortype_append(OBJECT_OT_shaderfx_add);
- 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_correctivesmooth_bind);
- WM_operatortype_append(OBJECT_OT_meshdeform_bind);
- WM_operatortype_append(OBJECT_OT_explode_refresh);
- WM_operatortype_append(OBJECT_OT_ocean_bake);
-
- WM_operatortype_append(OBJECT_OT_constraint_add);
- WM_operatortype_append(OBJECT_OT_constraint_add_with_targets);
- WM_operatortype_append(POSE_OT_constraint_add);
- WM_operatortype_append(POSE_OT_constraint_add_with_targets);
- WM_operatortype_append(OBJECT_OT_constraints_copy);
- WM_operatortype_append(POSE_OT_constraints_copy);
- WM_operatortype_append(OBJECT_OT_constraints_clear);
- WM_operatortype_append(POSE_OT_constraints_clear);
- WM_operatortype_append(POSE_OT_ik_add);
- WM_operatortype_append(POSE_OT_ik_clear);
- 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_stretchto_reset);
- WM_operatortype_append(CONSTRAINT_OT_limitdistance_reset);
- WM_operatortype_append(CONSTRAINT_OT_childof_set_inverse);
- WM_operatortype_append(CONSTRAINT_OT_childof_clear_inverse);
- WM_operatortype_append(CONSTRAINT_OT_objectsolver_set_inverse);
- WM_operatortype_append(CONSTRAINT_OT_objectsolver_clear_inverse);
- WM_operatortype_append(CONSTRAINT_OT_followpath_path_animate);
-
- WM_operatortype_append(OBJECT_OT_vertex_group_add);
- WM_operatortype_append(OBJECT_OT_vertex_group_remove);
- WM_operatortype_append(OBJECT_OT_vertex_group_assign);
- WM_operatortype_append(OBJECT_OT_vertex_group_assign_new);
- WM_operatortype_append(OBJECT_OT_vertex_group_remove_from);
- WM_operatortype_append(OBJECT_OT_vertex_group_select);
- WM_operatortype_append(OBJECT_OT_vertex_group_deselect);
- WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_linked);
- WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_selected);
- WM_operatortype_append(OBJECT_OT_vertex_group_copy);
- WM_operatortype_append(OBJECT_OT_vertex_group_normalize);
- WM_operatortype_append(OBJECT_OT_vertex_group_normalize_all);
- WM_operatortype_append(OBJECT_OT_vertex_group_lock);
- WM_operatortype_append(OBJECT_OT_vertex_group_fix);
- WM_operatortype_append(OBJECT_OT_vertex_group_invert);
- WM_operatortype_append(OBJECT_OT_vertex_group_levels);
- WM_operatortype_append(OBJECT_OT_vertex_group_smooth);
- WM_operatortype_append(OBJECT_OT_vertex_group_clean);
- WM_operatortype_append(OBJECT_OT_vertex_group_quantize);
- WM_operatortype_append(OBJECT_OT_vertex_group_limit_total);
- WM_operatortype_append(OBJECT_OT_vertex_group_mirror);
- WM_operatortype_append(OBJECT_OT_vertex_group_set_active);
- WM_operatortype_append(OBJECT_OT_vertex_group_sort);
- WM_operatortype_append(OBJECT_OT_vertex_group_move);
- WM_operatortype_append(OBJECT_OT_vertex_weight_paste);
- WM_operatortype_append(OBJECT_OT_vertex_weight_delete);
- WM_operatortype_append(OBJECT_OT_vertex_weight_set_active);
- WM_operatortype_append(OBJECT_OT_vertex_weight_normalize_active_vertex);
- WM_operatortype_append(OBJECT_OT_vertex_weight_copy);
-
- WM_operatortype_append(OBJECT_OT_face_map_add);
- WM_operatortype_append(OBJECT_OT_face_map_remove);
- WM_operatortype_append(OBJECT_OT_face_map_assign);
- WM_operatortype_append(OBJECT_OT_face_map_remove_from);
- WM_operatortype_append(OBJECT_OT_face_map_select);
- WM_operatortype_append(OBJECT_OT_face_map_deselect);
- WM_operatortype_append(OBJECT_OT_face_map_move);
-
- WM_operatortype_append(TRANSFORM_OT_vertex_warp);
-
- WM_operatortype_append(OBJECT_OT_move_to_collection);
- WM_operatortype_append(OBJECT_OT_link_to_collection);
-
- WM_operatortype_append(OBJECT_OT_shape_key_add);
- WM_operatortype_append(OBJECT_OT_shape_key_remove);
- WM_operatortype_append(OBJECT_OT_shape_key_clear);
- WM_operatortype_append(OBJECT_OT_shape_key_retime);
- WM_operatortype_append(OBJECT_OT_shape_key_mirror);
- WM_operatortype_append(OBJECT_OT_shape_key_move);
-
- WM_operatortype_append(OBJECT_OT_collection_add);
- WM_operatortype_append(OBJECT_OT_collection_link);
- WM_operatortype_append(OBJECT_OT_collection_remove);
- WM_operatortype_append(OBJECT_OT_collection_unlink);
- WM_operatortype_append(OBJECT_OT_collection_objects_select);
-
- WM_operatortype_append(OBJECT_OT_hook_add_selob);
- WM_operatortype_append(OBJECT_OT_hook_add_newob);
- WM_operatortype_append(OBJECT_OT_hook_remove);
- WM_operatortype_append(OBJECT_OT_hook_select);
- WM_operatortype_append(OBJECT_OT_hook_assign);
- WM_operatortype_append(OBJECT_OT_hook_reset);
- WM_operatortype_append(OBJECT_OT_hook_recenter);
-
- WM_operatortype_append(OBJECT_OT_bake_image);
- WM_operatortype_append(OBJECT_OT_bake);
- WM_operatortype_append(OBJECT_OT_drop_named_material);
- WM_operatortype_append(OBJECT_OT_unlink_data);
- WM_operatortype_append(OBJECT_OT_laplaciandeform_bind);
-
- WM_operatortype_append(TRANSFORM_OT_vertex_random);
-
- WM_operatortype_append(OBJECT_OT_data_transfer);
- WM_operatortype_append(OBJECT_OT_datalayout_transfer);
- WM_operatortype_append(OBJECT_OT_surfacedeform_bind);
-
- WM_operatortype_append(OBJECT_OT_hide_view_clear);
- WM_operatortype_append(OBJECT_OT_hide_view_set);
- WM_operatortype_append(OBJECT_OT_hide_collection);
+ WM_operatortype_append(OBJECT_OT_location_clear);
+ WM_operatortype_append(OBJECT_OT_rotation_clear);
+ WM_operatortype_append(OBJECT_OT_scale_clear);
+ WM_operatortype_append(OBJECT_OT_origin_clear);
+ WM_operatortype_append(OBJECT_OT_visual_transform_apply);
+ WM_operatortype_append(OBJECT_OT_transform_apply);
+ WM_operatortype_append(OBJECT_OT_transform_axis_target);
+ WM_operatortype_append(OBJECT_OT_origin_set);
+
+ WM_operatortype_append(OBJECT_OT_mode_set);
+ WM_operatortype_append(OBJECT_OT_mode_set_or_submode);
+ WM_operatortype_append(OBJECT_OT_editmode_toggle);
+ WM_operatortype_append(OBJECT_OT_posemode_toggle);
+ WM_operatortype_append(OBJECT_OT_proxy_make);
+ WM_operatortype_append(OBJECT_OT_shade_smooth);
+ WM_operatortype_append(OBJECT_OT_shade_flat);
+ WM_operatortype_append(OBJECT_OT_paths_calculate);
+ WM_operatortype_append(OBJECT_OT_paths_update);
+ WM_operatortype_append(OBJECT_OT_paths_clear);
+ WM_operatortype_append(OBJECT_OT_paths_range_update);
+ WM_operatortype_append(OBJECT_OT_forcefield_toggle);
+
+ WM_operatortype_append(OBJECT_OT_parent_set);
+ WM_operatortype_append(OBJECT_OT_parent_no_inverse_set);
+ WM_operatortype_append(OBJECT_OT_parent_clear);
+ WM_operatortype_append(OBJECT_OT_vertex_parent_set);
+ WM_operatortype_append(OBJECT_OT_track_set);
+ WM_operatortype_append(OBJECT_OT_track_clear);
+ WM_operatortype_append(OBJECT_OT_make_local);
+ WM_operatortype_append(OBJECT_OT_make_override_static);
+ WM_operatortype_append(OBJECT_OT_make_single_user);
+ WM_operatortype_append(OBJECT_OT_make_links_scene);
+ WM_operatortype_append(OBJECT_OT_make_links_data);
+
+ WM_operatortype_append(OBJECT_OT_select_random);
+ WM_operatortype_append(OBJECT_OT_select_all);
+ WM_operatortype_append(OBJECT_OT_select_same_collection);
+ WM_operatortype_append(OBJECT_OT_select_by_type);
+ WM_operatortype_append(OBJECT_OT_select_linked);
+ WM_operatortype_append(OBJECT_OT_select_grouped);
+ WM_operatortype_append(OBJECT_OT_select_mirror);
+ WM_operatortype_append(OBJECT_OT_select_more);
+ WM_operatortype_append(OBJECT_OT_select_less);
+
+ WM_operatortype_append(COLLECTION_OT_create);
+ WM_operatortype_append(COLLECTION_OT_objects_remove_all);
+ WM_operatortype_append(COLLECTION_OT_objects_remove);
+ WM_operatortype_append(COLLECTION_OT_objects_add_active);
+ WM_operatortype_append(COLLECTION_OT_objects_remove_active);
+
+ WM_operatortype_append(OBJECT_OT_delete);
+ WM_operatortype_append(OBJECT_OT_text_add);
+ WM_operatortype_append(OBJECT_OT_armature_add);
+ WM_operatortype_append(OBJECT_OT_empty_add);
+ WM_operatortype_append(OBJECT_OT_lightprobe_add);
+ WM_operatortype_append(OBJECT_OT_drop_named_image);
+ WM_operatortype_append(OBJECT_OT_gpencil_add);
+ WM_operatortype_append(OBJECT_OT_light_add);
+ WM_operatortype_append(OBJECT_OT_camera_add);
+ WM_operatortype_append(OBJECT_OT_speaker_add);
+ WM_operatortype_append(OBJECT_OT_add);
+ WM_operatortype_append(OBJECT_OT_add_named);
+ WM_operatortype_append(OBJECT_OT_effector_add);
+ WM_operatortype_append(OBJECT_OT_collection_instance_add);
+ WM_operatortype_append(OBJECT_OT_metaball_add);
+ WM_operatortype_append(OBJECT_OT_duplicates_make_real);
+ WM_operatortype_append(OBJECT_OT_duplicate);
+ WM_operatortype_append(OBJECT_OT_join);
+ WM_operatortype_append(OBJECT_OT_join_shapes);
+ WM_operatortype_append(OBJECT_OT_convert);
+
+ WM_operatortype_append(OBJECT_OT_modifier_add);
+ WM_operatortype_append(OBJECT_OT_modifier_remove);
+ WM_operatortype_append(OBJECT_OT_modifier_move_up);
+ WM_operatortype_append(OBJECT_OT_modifier_move_down);
+ WM_operatortype_append(OBJECT_OT_modifier_apply);
+ WM_operatortype_append(OBJECT_OT_modifier_convert);
+ WM_operatortype_append(OBJECT_OT_modifier_copy);
+ WM_operatortype_append(OBJECT_OT_multires_subdivide);
+ WM_operatortype_append(OBJECT_OT_multires_reshape);
+ WM_operatortype_append(OBJECT_OT_multires_higher_levels_delete);
+ WM_operatortype_append(OBJECT_OT_multires_base_apply);
+ WM_operatortype_append(OBJECT_OT_multires_external_save);
+ WM_operatortype_append(OBJECT_OT_multires_external_pack);
+ WM_operatortype_append(OBJECT_OT_skin_root_mark);
+ WM_operatortype_append(OBJECT_OT_skin_loose_mark_clear);
+ WM_operatortype_append(OBJECT_OT_skin_radii_equalize);
+ WM_operatortype_append(OBJECT_OT_skin_armature_create);
+
+ /* grease pencil modifiers */
+ WM_operatortype_append(OBJECT_OT_gpencil_modifier_add);
+ 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_apply);
+ WM_operatortype_append(OBJECT_OT_gpencil_modifier_copy);
+
+ /* shader fx */
+ WM_operatortype_append(OBJECT_OT_shaderfx_add);
+ 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_correctivesmooth_bind);
+ WM_operatortype_append(OBJECT_OT_meshdeform_bind);
+ WM_operatortype_append(OBJECT_OT_explode_refresh);
+ WM_operatortype_append(OBJECT_OT_ocean_bake);
+
+ WM_operatortype_append(OBJECT_OT_constraint_add);
+ WM_operatortype_append(OBJECT_OT_constraint_add_with_targets);
+ WM_operatortype_append(POSE_OT_constraint_add);
+ WM_operatortype_append(POSE_OT_constraint_add_with_targets);
+ WM_operatortype_append(OBJECT_OT_constraints_copy);
+ WM_operatortype_append(POSE_OT_constraints_copy);
+ WM_operatortype_append(OBJECT_OT_constraints_clear);
+ WM_operatortype_append(POSE_OT_constraints_clear);
+ WM_operatortype_append(POSE_OT_ik_add);
+ WM_operatortype_append(POSE_OT_ik_clear);
+ 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_stretchto_reset);
+ WM_operatortype_append(CONSTRAINT_OT_limitdistance_reset);
+ WM_operatortype_append(CONSTRAINT_OT_childof_set_inverse);
+ WM_operatortype_append(CONSTRAINT_OT_childof_clear_inverse);
+ WM_operatortype_append(CONSTRAINT_OT_objectsolver_set_inverse);
+ WM_operatortype_append(CONSTRAINT_OT_objectsolver_clear_inverse);
+ WM_operatortype_append(CONSTRAINT_OT_followpath_path_animate);
+
+ WM_operatortype_append(OBJECT_OT_vertex_group_add);
+ WM_operatortype_append(OBJECT_OT_vertex_group_remove);
+ WM_operatortype_append(OBJECT_OT_vertex_group_assign);
+ WM_operatortype_append(OBJECT_OT_vertex_group_assign_new);
+ WM_operatortype_append(OBJECT_OT_vertex_group_remove_from);
+ WM_operatortype_append(OBJECT_OT_vertex_group_select);
+ WM_operatortype_append(OBJECT_OT_vertex_group_deselect);
+ WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_linked);
+ WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_selected);
+ WM_operatortype_append(OBJECT_OT_vertex_group_copy);
+ WM_operatortype_append(OBJECT_OT_vertex_group_normalize);
+ WM_operatortype_append(OBJECT_OT_vertex_group_normalize_all);
+ WM_operatortype_append(OBJECT_OT_vertex_group_lock);
+ WM_operatortype_append(OBJECT_OT_vertex_group_fix);
+ WM_operatortype_append(OBJECT_OT_vertex_group_invert);
+ WM_operatortype_append(OBJECT_OT_vertex_group_levels);
+ WM_operatortype_append(OBJECT_OT_vertex_group_smooth);
+ WM_operatortype_append(OBJECT_OT_vertex_group_clean);
+ WM_operatortype_append(OBJECT_OT_vertex_group_quantize);
+ WM_operatortype_append(OBJECT_OT_vertex_group_limit_total);
+ WM_operatortype_append(OBJECT_OT_vertex_group_mirror);
+ WM_operatortype_append(OBJECT_OT_vertex_group_set_active);
+ WM_operatortype_append(OBJECT_OT_vertex_group_sort);
+ WM_operatortype_append(OBJECT_OT_vertex_group_move);
+ WM_operatortype_append(OBJECT_OT_vertex_weight_paste);
+ WM_operatortype_append(OBJECT_OT_vertex_weight_delete);
+ WM_operatortype_append(OBJECT_OT_vertex_weight_set_active);
+ WM_operatortype_append(OBJECT_OT_vertex_weight_normalize_active_vertex);
+ WM_operatortype_append(OBJECT_OT_vertex_weight_copy);
+
+ WM_operatortype_append(OBJECT_OT_face_map_add);
+ WM_operatortype_append(OBJECT_OT_face_map_remove);
+ WM_operatortype_append(OBJECT_OT_face_map_assign);
+ WM_operatortype_append(OBJECT_OT_face_map_remove_from);
+ WM_operatortype_append(OBJECT_OT_face_map_select);
+ WM_operatortype_append(OBJECT_OT_face_map_deselect);
+ WM_operatortype_append(OBJECT_OT_face_map_move);
+
+ WM_operatortype_append(TRANSFORM_OT_vertex_warp);
+
+ WM_operatortype_append(OBJECT_OT_move_to_collection);
+ WM_operatortype_append(OBJECT_OT_link_to_collection);
+
+ WM_operatortype_append(OBJECT_OT_shape_key_add);
+ WM_operatortype_append(OBJECT_OT_shape_key_remove);
+ WM_operatortype_append(OBJECT_OT_shape_key_clear);
+ WM_operatortype_append(OBJECT_OT_shape_key_retime);
+ WM_operatortype_append(OBJECT_OT_shape_key_mirror);
+ WM_operatortype_append(OBJECT_OT_shape_key_move);
+
+ WM_operatortype_append(OBJECT_OT_collection_add);
+ WM_operatortype_append(OBJECT_OT_collection_link);
+ WM_operatortype_append(OBJECT_OT_collection_remove);
+ WM_operatortype_append(OBJECT_OT_collection_unlink);
+ WM_operatortype_append(OBJECT_OT_collection_objects_select);
+
+ WM_operatortype_append(OBJECT_OT_hook_add_selob);
+ WM_operatortype_append(OBJECT_OT_hook_add_newob);
+ WM_operatortype_append(OBJECT_OT_hook_remove);
+ WM_operatortype_append(OBJECT_OT_hook_select);
+ WM_operatortype_append(OBJECT_OT_hook_assign);
+ WM_operatortype_append(OBJECT_OT_hook_reset);
+ WM_operatortype_append(OBJECT_OT_hook_recenter);
+
+ WM_operatortype_append(OBJECT_OT_bake_image);
+ WM_operatortype_append(OBJECT_OT_bake);
+ WM_operatortype_append(OBJECT_OT_drop_named_material);
+ WM_operatortype_append(OBJECT_OT_unlink_data);
+ WM_operatortype_append(OBJECT_OT_laplaciandeform_bind);
+
+ WM_operatortype_append(TRANSFORM_OT_vertex_random);
+
+ WM_operatortype_append(OBJECT_OT_data_transfer);
+ WM_operatortype_append(OBJECT_OT_datalayout_transfer);
+ WM_operatortype_append(OBJECT_OT_surfacedeform_bind);
+
+ WM_operatortype_append(OBJECT_OT_hide_view_clear);
+ WM_operatortype_append(OBJECT_OT_hide_view_set);
+ WM_operatortype_append(OBJECT_OT_hide_collection);
}
void ED_operatormacros_object(void)
{
- wmOperatorType *ot;
- wmOperatorTypeMacro *otmacro;
-
- ot = WM_operatortype_append_macro("OBJECT_OT_duplicate_move", "Duplicate Objects",
- "Duplicate selected objects and move them", OPTYPE_UNDO | OPTYPE_REGISTER);
- if (ot) {
- WM_operatortype_macro_define(ot, "OBJECT_OT_duplicate");
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF);
- }
-
- /* grr, should be able to pass options on... */
- ot = WM_operatortype_append_macro("OBJECT_OT_duplicate_move_linked", "Duplicate Linked",
- "Duplicate selected objects and move them", OPTYPE_UNDO | OPTYPE_REGISTER);
- if (ot) {
- otmacro = WM_operatortype_macro_define(ot, "OBJECT_OT_duplicate");
- RNA_boolean_set(otmacro->ptr, "linked", true);
- otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
- RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF);
- }
-
+ wmOperatorType *ot;
+ wmOperatorTypeMacro *otmacro;
+
+ ot = WM_operatortype_append_macro("OBJECT_OT_duplicate_move",
+ "Duplicate Objects",
+ "Duplicate selected objects and move them",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ if (ot) {
+ WM_operatortype_macro_define(ot, "OBJECT_OT_duplicate");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF);
+ }
+
+ /* grr, should be able to pass options on... */
+ ot = WM_operatortype_append_macro("OBJECT_OT_duplicate_move_linked",
+ "Duplicate Linked",
+ "Duplicate selected objects and move them",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ if (ot) {
+ otmacro = WM_operatortype_macro_define(ot, "OBJECT_OT_duplicate");
+ RNA_boolean_set(otmacro->ptr, "linked", true);
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_enum_set(otmacro->ptr, "proportional", PROP_EDIT_OFF);
+ }
}
static bool object_mode_poll(bContext *C)
{
- Object *ob = CTX_data_active_object(C);
- return (!ob || ob->mode == OB_MODE_OBJECT);
+ Object *ob = CTX_data_active_object(C);
+ return (!ob || ob->mode == OB_MODE_OBJECT);
}
void ED_keymap_object(wmKeyConfig *keyconf)
{
- wmKeyMap *keymap;
+ wmKeyMap *keymap;
- /* Objects, Regardless of Mode -------------------------------------------------- */
- keymap = WM_keymap_ensure(keyconf, "Object Non-modal", 0, 0);
+ /* Objects, Regardless of Mode -------------------------------------------------- */
+ keymap = WM_keymap_ensure(keyconf, "Object Non-modal", 0, 0);
- /* Object Mode ---------------------------------------------------------------- */
- /* Note: this keymap gets disabled in non-objectmode, */
- keymap = WM_keymap_ensure(keyconf, "Object Mode", 0, 0);
- keymap->poll = object_mode_poll;
+ /* Object Mode ---------------------------------------------------------------- */
+ /* Note: this keymap gets disabled in non-objectmode, */
+ keymap = WM_keymap_ensure(keyconf, "Object Mode", 0, 0);
+ keymap->poll = object_mode_poll;
}
diff --git a/source/blender/editors/object/object_random.c b/source/blender/editors/object/object_random.c
index 7c176318c57..c151f565ecb 100644
--- a/source/blender/editors/object/object_random.c
+++ b/source/blender/editors/object/object_random.c
@@ -29,7 +29,6 @@
#include "BLI_math.h"
#include "BLI_rand.h"
-
#include "BKE_context.h"
#include "BKE_layer.h"
@@ -43,127 +42,142 @@
#include "object_intern.h"
-
/**
* Generic randomize vertices function
*/
-static bool object_rand_transverts(
- TransVertStore *tvs,
- const float offset, const float uniform, const float normal_factor,
- const unsigned int seed)
+static bool object_rand_transverts(TransVertStore *tvs,
+ const float offset,
+ const float uniform,
+ const float normal_factor,
+ const unsigned int seed)
{
- bool use_normal = (normal_factor != 0.0f);
- struct RNG *rng;
- TransVert *tv;
- int a;
+ bool use_normal = (normal_factor != 0.0f);
+ struct RNG *rng;
+ TransVert *tv;
+ int a;
- if (!tvs || !(tvs->transverts)) {
- return false;
- }
+ if (!tvs || !(tvs->transverts)) {
+ return false;
+ }
- rng = BLI_rng_new(seed);
+ rng = BLI_rng_new(seed);
- tv = tvs->transverts;
- for (a = 0; a < tvs->transverts_tot; a++, tv++) {
- const float t = max_ff(0.0f, uniform + ((1.0f - uniform) * BLI_rng_get_float(rng)));
- float vec[3];
- BLI_rng_get_float_unit_v3(rng, vec);
+ tv = tvs->transverts;
+ for (a = 0; a < tvs->transverts_tot; a++, tv++) {
+ const float t = max_ff(0.0f, uniform + ((1.0f - uniform) * BLI_rng_get_float(rng)));
+ float vec[3];
+ BLI_rng_get_float_unit_v3(rng, vec);
- if (use_normal && (tv->flag & TX_VERT_USE_NORMAL)) {
- float no[3];
+ if (use_normal && (tv->flag & TX_VERT_USE_NORMAL)) {
+ float no[3];
- /* avoid >90d rotation to align with normal */
- if (dot_v3v3(vec, tv->normal) < 0.0f) {
- negate_v3_v3(no, tv->normal);
- }
- else {
- copy_v3_v3(no, tv->normal);
- }
+ /* avoid >90d rotation to align with normal */
+ if (dot_v3v3(vec, tv->normal) < 0.0f) {
+ negate_v3_v3(no, tv->normal);
+ }
+ else {
+ copy_v3_v3(no, tv->normal);
+ }
- interp_v3_v3v3_slerp_safe(vec, vec, no, normal_factor);
- }
+ interp_v3_v3v3_slerp_safe(vec, vec, no, normal_factor);
+ }
- madd_v3_v3fl(tv->loc, vec, offset * t);
- }
+ madd_v3_v3fl(tv->loc, vec, offset * t);
+ }
- BLI_rng_free(rng);
+ BLI_rng_free(rng);
- return true;
+ return true;
}
static int object_rand_verts_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob_active = CTX_data_edit_object(C);
- const int ob_mode = ob_active->mode;
-
- const float offset = RNA_float_get(op->ptr, "offset");
- const float uniform = RNA_float_get(op->ptr, "uniform");
- const float normal_factor = RNA_float_get(op->ptr, "normal");
- const unsigned int seed = RNA_int_get(op->ptr, "seed");
-
- bool changed_multi = false;
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len, ob_mode);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob_iter = objects[ob_index];
-
- TransVertStore tvs = { NULL };
-
- if (ob_iter) {
- int mode = TM_ALL_JOINTS;
-
- if (normal_factor != 0.0f) {
- mode |= TX_VERT_USE_NORMAL;
- }
-
- ED_transverts_create_from_obedit(&tvs, ob_iter, mode);
- if (tvs.transverts_tot == 0) {
- continue;
- }
-
- int seed_iter = seed;
- /* This gives a consistent result regardless of object order. */
- if (ob_index) {
- seed_iter += BLI_ghashutil_strhash_p(ob_iter->id.name);
- }
-
- object_rand_transverts(&tvs, offset, uniform, normal_factor, seed_iter);
-
- ED_transverts_update_obedit(&tvs, ob_iter);
- ED_transverts_free(&tvs);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter);
- changed_multi = true;
- }
- }
- MEM_freeN(objects);
-
- return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob_active = CTX_data_edit_object(C);
+ const int ob_mode = ob_active->mode;
+
+ const float offset = RNA_float_get(op->ptr, "offset");
+ const float uniform = RNA_float_get(op->ptr, "uniform");
+ const float normal_factor = RNA_float_get(op->ptr, "normal");
+ const unsigned int seed = RNA_int_get(op->ptr, "seed");
+
+ bool changed_multi = false;
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len, ob_mode);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob_iter = objects[ob_index];
+
+ TransVertStore tvs = {NULL};
+
+ if (ob_iter) {
+ int mode = TM_ALL_JOINTS;
+
+ if (normal_factor != 0.0f) {
+ mode |= TX_VERT_USE_NORMAL;
+ }
+
+ ED_transverts_create_from_obedit(&tvs, ob_iter, mode);
+ if (tvs.transverts_tot == 0) {
+ continue;
+ }
+
+ int seed_iter = seed;
+ /* This gives a consistent result regardless of object order. */
+ if (ob_index) {
+ seed_iter += BLI_ghashutil_strhash_p(ob_iter->id.name);
+ }
+
+ object_rand_transverts(&tvs, offset, uniform, normal_factor, seed_iter);
+
+ ED_transverts_update_obedit(&tvs, ob_iter);
+ ED_transverts_free(&tvs);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter);
+ changed_multi = true;
+ }
+ }
+ MEM_freeN(objects);
+
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void TRANSFORM_OT_vertex_random(struct wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Randomize";
- ot->description = "Randomize vertices";
- ot->idname = "TRANSFORM_OT_vertex_random";
-
- /* api callbacks */
- ot->exec = object_rand_verts_exec;
- ot->poll = ED_transverts_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- ot->prop = RNA_def_float_distance(
- ot->srna, "offset", 0.1f, -FLT_MAX, FLT_MAX,
- "Amount", "Distance to offset", -10.0f, 10.0f);
- RNA_def_float_factor(ot->srna, "uniform", 0.0f, 0.0f, 1.0f, "Uniform",
- "Increase for uniform offset distance", 0.0f, 1.0f);
- RNA_def_float_factor(ot->srna, "normal", 0.0f, 0.0f, 1.0f, "Normal",
- "Align offset direction to normals", 0.0f, 1.0f);
- RNA_def_int(ot->srna, "seed", 0, 0, 10000, "Random Seed", "Seed for the random number generator", 0, 50);
+ /* identifiers */
+ ot->name = "Randomize";
+ ot->description = "Randomize vertices";
+ ot->idname = "TRANSFORM_OT_vertex_random";
+
+ /* api callbacks */
+ ot->exec = object_rand_verts_exec;
+ ot->poll = ED_transverts_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ ot->prop = RNA_def_float_distance(
+ ot->srna, "offset", 0.1f, -FLT_MAX, FLT_MAX, "Amount", "Distance to offset", -10.0f, 10.0f);
+ RNA_def_float_factor(ot->srna,
+ "uniform",
+ 0.0f,
+ 0.0f,
+ 1.0f,
+ "Uniform",
+ "Increase for uniform offset distance",
+ 0.0f,
+ 1.0f);
+ RNA_def_float_factor(ot->srna,
+ "normal",
+ 0.0f,
+ 0.0f,
+ 1.0f,
+ "Normal",
+ "Align offset direction to normals",
+ 0.0f,
+ 1.0f);
+ RNA_def_int(
+ ot->srna, "seed", 0, 0, 10000, "Random Seed", "Seed for the random number generator", 0, 50);
}
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index a9b00e7bbdd..3744632be3d 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -116,177 +115,196 @@
static bool vertex_parent_set_poll(bContext *C)
{
- return ED_operator_editmesh(C) || ED_operator_editsurfcurve(C) || ED_operator_editlattice(C);
+ return ED_operator_editmesh(C) || ED_operator_editsurfcurve(C) || ED_operator_editlattice(C);
}
static int vertex_parent_set_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *obedit = CTX_data_edit_object(C);
- BMVert *eve;
- BMIter iter;
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- Object *par;
- int a, v1 = 0, v2 = 0, v3 = 0, v4 = 0, nr = 1;
-
- /* we need 1 to 3 selected vertices */
-
- if (obedit->type == OB_MESH) {
- Mesh *me = obedit->data;
- BMEditMesh *em;
-
- EDBM_mesh_load(bmain, obedit);
- EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true);
-
- DEG_id_tag_update(obedit->data, 0);
-
- em = me->edit_mesh;
-
- EDBM_mesh_normals_update(em);
- BKE_editmesh_tessface_calc(em);
-
- /* Make sure the evaluated mesh is updated.
- *
- * Most reliable way is to update the tagged objects, which will ensure
- * proper copy-on-write update, but also will make sure all dependent
- * objects are also up to date. */
- BKE_scene_graph_update_tagged(depsgraph, bmain);
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- if (v1 == 0) v1 = nr;
- else if (v2 == 0) v2 = nr;
- else if (v3 == 0) v3 = nr;
- else if (v4 == 0) v4 = nr;
- else break;
- }
- nr++;
- }
- }
- else if (ELEM(obedit->type, OB_SURF, OB_CURVE)) {
- ListBase *editnurb = object_editcurve_get(obedit);
-
- nu = editnurb->first;
- while (nu) {
- if (nu->type == CU_BEZIER) {
- bezt = nu->bezt;
- a = nu->pntsu;
- while (a--) {
- if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
- if (v1 == 0) v1 = nr;
- else if (v2 == 0) v2 = nr;
- else if (v3 == 0) v3 = nr;
- else if (v4 == 0) v4 = nr;
- else break;
- }
- nr++;
- bezt++;
- }
- }
- else {
- bp = nu->bp;
- a = nu->pntsu * nu->pntsv;
- while (a--) {
- if (bp->f1 & SELECT) {
- if (v1 == 0) v1 = nr;
- else if (v2 == 0) v2 = nr;
- else if (v3 == 0) v3 = nr;
- else if (v4 == 0) v4 = nr;
- else break;
- }
- nr++;
- bp++;
- }
- }
- nu = nu->next;
- }
- }
- else if (obedit->type == OB_LATTICE) {
- Lattice *lt = obedit->data;
-
- a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
- bp = lt->editlatt->latt->def;
- while (a--) {
- if (bp->f1 & SELECT) {
- if (v1 == 0) v1 = nr;
- else if (v2 == 0) v2 = nr;
- else if (v3 == 0) v3 = nr;
- else if (v4 == 0) v4 = nr;
- else break;
- }
- nr++;
- bp++;
- }
- }
-
- if (v4 || !((v1 && v2 == 0 && v3 == 0) || (v1 && v2 && v3))) {
- BKE_report(op->reports, RPT_ERROR, "Select either 1 or 3 vertices to parent to");
- return OPERATOR_CANCELLED;
- }
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if (ob != obedit) {
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- par = obedit->parent;
-
- if (BKE_object_parent_loop_check(par, ob)) {
- BKE_report(op->reports, RPT_ERROR, "Loop in parents");
- }
- else {
- Object workob;
-
- ob->parent = BASACT(view_layer)->object;
- if (v3) {
- ob->partype = PARVERT3;
- ob->par1 = v1 - 1;
- ob->par2 = v2 - 1;
- ob->par3 = v3 - 1;
-
- /* inverse parent matrix */
- BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- invert_m4_m4(ob->parentinv, workob.obmat);
- }
- else {
- ob->partype = PARVERT1;
- ob->par1 = v1 - 1;
-
- /* inverse parent matrix */
- BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- invert_m4_m4(ob->parentinv, workob.obmat);
- }
- }
- }
- }
- CTX_DATA_END;
-
- DEG_relations_tag_update(bmain);
-
- WM_event_add_notifier(C, NC_OBJECT, NULL);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obedit = CTX_data_edit_object(C);
+ BMVert *eve;
+ BMIter iter;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ Object *par;
+ int a, v1 = 0, v2 = 0, v3 = 0, v4 = 0, nr = 1;
+
+ /* we need 1 to 3 selected vertices */
+
+ if (obedit->type == OB_MESH) {
+ Mesh *me = obedit->data;
+ BMEditMesh *em;
+
+ EDBM_mesh_load(bmain, obedit);
+ EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true);
+
+ DEG_id_tag_update(obedit->data, 0);
+
+ em = me->edit_mesh;
+
+ EDBM_mesh_normals_update(em);
+ BKE_editmesh_tessface_calc(em);
+
+ /* Make sure the evaluated mesh is updated.
+ *
+ * Most reliable way is to update the tagged objects, which will ensure
+ * proper copy-on-write update, but also will make sure all dependent
+ * objects are also up to date. */
+ BKE_scene_graph_update_tagged(depsgraph, bmain);
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ if (v1 == 0)
+ v1 = nr;
+ else if (v2 == 0)
+ v2 = nr;
+ else if (v3 == 0)
+ v3 = nr;
+ else if (v4 == 0)
+ v4 = nr;
+ else
+ break;
+ }
+ nr++;
+ }
+ }
+ else if (ELEM(obedit->type, OB_SURF, OB_CURVE)) {
+ ListBase *editnurb = object_editcurve_get(obedit);
+
+ nu = editnurb->first;
+ while (nu) {
+ if (nu->type == CU_BEZIER) {
+ bezt = nu->bezt;
+ a = nu->pntsu;
+ while (a--) {
+ if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) {
+ if (v1 == 0)
+ v1 = nr;
+ else if (v2 == 0)
+ v2 = nr;
+ else if (v3 == 0)
+ v3 = nr;
+ else if (v4 == 0)
+ v4 = nr;
+ else
+ break;
+ }
+ nr++;
+ bezt++;
+ }
+ }
+ else {
+ bp = nu->bp;
+ a = nu->pntsu * nu->pntsv;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ if (v1 == 0)
+ v1 = nr;
+ else if (v2 == 0)
+ v2 = nr;
+ else if (v3 == 0)
+ v3 = nr;
+ else if (v4 == 0)
+ v4 = nr;
+ else
+ break;
+ }
+ nr++;
+ bp++;
+ }
+ }
+ nu = nu->next;
+ }
+ }
+ else if (obedit->type == OB_LATTICE) {
+ Lattice *lt = obedit->data;
+
+ a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
+ bp = lt->editlatt->latt->def;
+ while (a--) {
+ if (bp->f1 & SELECT) {
+ if (v1 == 0)
+ v1 = nr;
+ else if (v2 == 0)
+ v2 = nr;
+ else if (v3 == 0)
+ v3 = nr;
+ else if (v4 == 0)
+ v4 = nr;
+ else
+ break;
+ }
+ nr++;
+ bp++;
+ }
+ }
+
+ if (v4 || !((v1 && v2 == 0 && v3 == 0) || (v1 && v2 && v3))) {
+ BKE_report(op->reports, RPT_ERROR, "Select either 1 or 3 vertices to parent to");
+ return OPERATOR_CANCELLED;
+ }
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (ob != obedit) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ par = obedit->parent;
+
+ if (BKE_object_parent_loop_check(par, ob)) {
+ BKE_report(op->reports, RPT_ERROR, "Loop in parents");
+ }
+ else {
+ Object workob;
+
+ ob->parent = BASACT(view_layer)->object;
+ if (v3) {
+ ob->partype = PARVERT3;
+ ob->par1 = v1 - 1;
+ ob->par2 = v2 - 1;
+ ob->par3 = v3 - 1;
+
+ /* inverse parent matrix */
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
+ invert_m4_m4(ob->parentinv, workob.obmat);
+ }
+ else {
+ ob->partype = PARVERT1;
+ ob->par1 = v1 - 1;
+
+ /* inverse parent matrix */
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
+ invert_m4_m4(ob->parentinv, workob.obmat);
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ DEG_relations_tag_update(bmain);
+
+ WM_event_add_notifier(C, NC_OBJECT, NULL);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_parent_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Vertex Parent";
- ot->description = "Parent selected objects to the selected vertices";
- ot->idname = "OBJECT_OT_vertex_parent_set";
-
- /* api callbacks */
- ot->invoke = WM_operator_confirm;
- ot->poll = vertex_parent_set_poll;
- ot->exec = vertex_parent_set_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Make Vertex Parent";
+ ot->description = "Parent selected objects to the selected vertices";
+ ot->idname = "OBJECT_OT_vertex_parent_set";
+
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->poll = vertex_parent_set_poll;
+ ot->exec = vertex_parent_set_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/********************** Make Proxy Operator *************************/
@@ -294,991 +312,1026 @@ void OBJECT_OT_vertex_parent_set(wmOperatorType *ot)
/* set the object to proxify */
static int make_proxy_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
-
- /* sanity checks */
- if (!scene || ID_IS_LINKED(scene) || !ob)
- return OPERATOR_CANCELLED;
-
- /* Get object to work on - use a menu if we need to... */
- if (ob->instance_collection && ID_IS_LINKED(ob->instance_collection)) {
- /* gives menu with list of objects in group */
- /* proxy_group_objects_menu(C, op, ob, ob->instance_collection); */
- WM_enum_search_invoke(C, op, event);
- return OPERATOR_CANCELLED;
- }
- else if (ID_IS_LINKED(ob)) {
- uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("OK?"), ICON_QUESTION);
- uiLayout *layout = UI_popup_menu_layout(pup);
-
- /* create operator menu item with relevant properties filled in */
- PointerRNA opptr_dummy;
- uiItemFullO_ptr(layout, op->type, op->type->name, ICON_NONE, NULL,
- WM_OP_EXEC_REGION_WIN, 0, &opptr_dummy);
-
- /* present the menu and be done... */
- UI_popup_menu_end(C, pup);
-
- /* this invoke just calls another instance of this operator... */
- return OPERATOR_INTERFACE;
- }
- else {
- /* error.. cannot continue */
- BKE_report(op->reports, RPT_ERROR, "Can only make proxy for a referenced object or collection");
- return OPERATOR_CANCELLED;
- }
-
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+
+ /* sanity checks */
+ if (!scene || ID_IS_LINKED(scene) || !ob)
+ return OPERATOR_CANCELLED;
+
+ /* Get object to work on - use a menu if we need to... */
+ if (ob->instance_collection && ID_IS_LINKED(ob->instance_collection)) {
+ /* gives menu with list of objects in group */
+ /* proxy_group_objects_menu(C, op, ob, ob->instance_collection); */
+ WM_enum_search_invoke(C, op, event);
+ return OPERATOR_CANCELLED;
+ }
+ else if (ID_IS_LINKED(ob)) {
+ uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("OK?"), ICON_QUESTION);
+ uiLayout *layout = UI_popup_menu_layout(pup);
+
+ /* create operator menu item with relevant properties filled in */
+ PointerRNA opptr_dummy;
+ uiItemFullO_ptr(
+ layout, op->type, op->type->name, ICON_NONE, NULL, WM_OP_EXEC_REGION_WIN, 0, &opptr_dummy);
+
+ /* present the menu and be done... */
+ UI_popup_menu_end(C, pup);
+
+ /* this invoke just calls another instance of this operator... */
+ return OPERATOR_INTERFACE;
+ }
+ else {
+ /* error.. cannot continue */
+ BKE_report(
+ op->reports, RPT_ERROR, "Can only make proxy for a referenced object or collection");
+ return OPERATOR_CANCELLED;
+ }
}
static int make_proxy_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *ob, *gob = ED_object_active_context(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- if (gob->instance_collection != NULL) {
- const ListBase instance_collection_objects = BKE_collection_object_cache_get(gob->instance_collection);
- Base *base = BLI_findlink(&instance_collection_objects, RNA_enum_get(op->ptr, "object"));
- ob = base->object;
- }
- else {
- ob = gob;
- }
-
- if (ob) {
- Object *newob;
- char name[MAX_ID_NAME + 4];
-
- BLI_snprintf(name, sizeof(name), "%s_proxy", ((ID *)(gob ? gob : ob))->name + 2);
-
- /* Add new object for the proxy */
- newob = BKE_object_add_from(bmain, scene, view_layer, OB_EMPTY, name, gob ? gob : ob);
-
- /* set layers OK */
- BKE_object_make_proxy(bmain, newob, ob, gob);
-
- /* Set back pointer immediately so dependency graph knows that this is
- * is a proxy and will act accordingly. Otherwise correctness of graph
- * will depend on order of bases.
- *
- * TODO(sergey): We really need to get rid of this bi-directional links
- * in proxies with something like static overrides.
- */
- newob->proxy->proxy_from = newob;
-
- /* depsgraph flushes are needed for the new data */
- DEG_relations_tag_update(bmain);
- DEG_id_tag_update(&newob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, newob);
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "No object to make proxy for");
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Object *ob, *gob = ED_object_active_context(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ if (gob->instance_collection != NULL) {
+ const ListBase instance_collection_objects = BKE_collection_object_cache_get(
+ gob->instance_collection);
+ Base *base = BLI_findlink(&instance_collection_objects, RNA_enum_get(op->ptr, "object"));
+ ob = base->object;
+ }
+ else {
+ ob = gob;
+ }
+
+ if (ob) {
+ Object *newob;
+ char name[MAX_ID_NAME + 4];
+
+ BLI_snprintf(name, sizeof(name), "%s_proxy", ((ID *)(gob ? gob : ob))->name + 2);
+
+ /* Add new object for the proxy */
+ newob = BKE_object_add_from(bmain, scene, view_layer, OB_EMPTY, name, gob ? gob : ob);
+
+ /* set layers OK */
+ BKE_object_make_proxy(bmain, newob, ob, gob);
+
+ /* Set back pointer immediately so dependency graph knows that this is
+ * is a proxy and will act accordingly. Otherwise correctness of graph
+ * will depend on order of bases.
+ *
+ * TODO(sergey): We really need to get rid of this bi-directional links
+ * in proxies with something like static overrides.
+ */
+ newob->proxy->proxy_from = newob;
+
+ /* depsgraph flushes are needed for the new data */
+ DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&newob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, newob);
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "No object to make proxy for");
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_FINISHED;
}
/* Generic itemf's for operators that take library args */
-static const EnumPropertyItem *proxy_collection_object_itemf(
- bContext *C, PointerRNA *UNUSED(ptr),
- PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *proxy_collection_object_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- EnumPropertyItem item_tmp = {0}, *item = NULL;
- int totitem = 0;
- int i = 0;
- Object *ob = ED_object_active_context(C);
-
- if (!ob || !ob->instance_collection)
- return DummyRNA_DEFAULT_items;
-
- /* find the object to affect */
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(ob->instance_collection, object)
- {
- item_tmp.identifier = item_tmp.name = object->id.name + 2;
- item_tmp.value = i++;
- RNA_enum_item_add(&item, &totitem, &item_tmp);
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ EnumPropertyItem item_tmp = {0}, *item = NULL;
+ int totitem = 0;
+ int i = 0;
+ Object *ob = ED_object_active_context(C);
+
+ if (!ob || !ob->instance_collection)
+ return DummyRNA_DEFAULT_items;
+
+ /* find the object to affect */
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (ob->instance_collection, object) {
+ item_tmp.identifier = item_tmp.name = object->id.name + 2;
+ item_tmp.value = i++;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
void OBJECT_OT_proxy_make(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Make Proxy";
- ot->idname = "OBJECT_OT_proxy_make";
- ot->description = "Add empty object to become local replacement data of a library-linked object";
-
- /* callbacks */
- ot->invoke = make_proxy_invoke;
- ot->exec = make_proxy_exec;
- ot->poll = ED_operator_object_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- /* XXX, relies on hard coded ID at the moment */
- prop = RNA_def_enum(ot->srna, "object", DummyRNA_DEFAULT_items, 0, "Proxy Object",
- "Name of lib-linked/collection object to make a proxy for");
- RNA_def_enum_funcs(prop, proxy_collection_object_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Make Proxy";
+ ot->idname = "OBJECT_OT_proxy_make";
+ ot->description = "Add empty object to become local replacement data of a library-linked object";
+
+ /* callbacks */
+ ot->invoke = make_proxy_invoke;
+ ot->exec = make_proxy_exec;
+ ot->poll = ED_operator_object_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ /* XXX, relies on hard coded ID at the moment */
+ prop = RNA_def_enum(ot->srna,
+ "object",
+ DummyRNA_DEFAULT_items,
+ 0,
+ "Proxy Object",
+ "Name of lib-linked/collection object to make a proxy for");
+ RNA_def_enum_funcs(prop, proxy_collection_object_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
/********************** Clear Parent Operator ******************* */
typedef enum eObClearParentTypes {
- CLEAR_PARENT_ALL = 0,
- CLEAR_PARENT_KEEP_TRANSFORM,
- CLEAR_PARENT_INVERSE,
+ CLEAR_PARENT_ALL = 0,
+ CLEAR_PARENT_KEEP_TRANSFORM,
+ CLEAR_PARENT_INVERSE,
} eObClearParentTypes;
EnumPropertyItem prop_clear_parent_types[] = {
- {CLEAR_PARENT_ALL, "CLEAR", 0, "Clear Parent",
- "Completely clear the parenting relationship, including involved modifiers if any"},
- {CLEAR_PARENT_KEEP_TRANSFORM, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation",
- "As 'Clear Parent', but keep the current visual transformations of the object"},
- {CLEAR_PARENT_INVERSE, "CLEAR_INVERSE", 0, "Clear Parent Inverse",
- "Reset the transform corrections applied to the parenting relationship, does not remove parenting itself"},
- {0, NULL, 0, NULL, NULL},
+ {CLEAR_PARENT_ALL,
+ "CLEAR",
+ 0,
+ "Clear Parent",
+ "Completely clear the parenting relationship, including involved modifiers if any"},
+ {CLEAR_PARENT_KEEP_TRANSFORM,
+ "CLEAR_KEEP_TRANSFORM",
+ 0,
+ "Clear and Keep Transformation",
+ "As 'Clear Parent', but keep the current visual transformations of the object"},
+ {CLEAR_PARENT_INVERSE,
+ "CLEAR_INVERSE",
+ 0,
+ "Clear Parent Inverse",
+ "Reset the transform corrections applied to the parenting relationship, does not remove "
+ "parenting itself"},
+ {0, NULL, 0, NULL, NULL},
};
/* Helper for ED_object_parent_clear() - Remove deform-modifiers associated with parent */
static void object_remove_parent_deform_modifiers(Object *ob, const Object *par)
{
- if (ELEM(par->type, OB_ARMATURE, OB_LATTICE, OB_CURVE)) {
- ModifierData *md, *mdn;
-
- /* assume that we only need to remove the first instance of matching deform modifier here */
- for (md = ob->modifiers.first; md; md = mdn) {
- bool free = false;
-
- mdn = md->next;
-
- /* need to match types (modifier + parent) and references */
- if ((md->type == eModifierType_Armature) && (par->type == OB_ARMATURE)) {
- ArmatureModifierData *amd = (ArmatureModifierData *)md;
- if (amd->object == par) {
- free = true;
- }
- }
- else if ((md->type == eModifierType_Lattice) && (par->type == OB_LATTICE)) {
- LatticeModifierData *lmd = (LatticeModifierData *)md;
- if (lmd->object == par) {
- free = true;
- }
- }
- else if ((md->type == eModifierType_Curve) && (par->type == OB_CURVE)) {
- CurveModifierData *cmd = (CurveModifierData *)md;
- if (cmd->object == par) {
- free = true;
- }
- }
-
- /* free modifier if match */
- if (free) {
- BLI_remlink(&ob->modifiers, md);
- modifier_free(md);
- }
- }
- }
+ if (ELEM(par->type, OB_ARMATURE, OB_LATTICE, OB_CURVE)) {
+ ModifierData *md, *mdn;
+
+ /* assume that we only need to remove the first instance of matching deform modifier here */
+ for (md = ob->modifiers.first; md; md = mdn) {
+ bool free = false;
+
+ mdn = md->next;
+
+ /* need to match types (modifier + parent) and references */
+ if ((md->type == eModifierType_Armature) && (par->type == OB_ARMATURE)) {
+ ArmatureModifierData *amd = (ArmatureModifierData *)md;
+ if (amd->object == par) {
+ free = true;
+ }
+ }
+ else if ((md->type == eModifierType_Lattice) && (par->type == OB_LATTICE)) {
+ LatticeModifierData *lmd = (LatticeModifierData *)md;
+ if (lmd->object == par) {
+ free = true;
+ }
+ }
+ else if ((md->type == eModifierType_Curve) && (par->type == OB_CURVE)) {
+ CurveModifierData *cmd = (CurveModifierData *)md;
+ if (cmd->object == par) {
+ free = true;
+ }
+ }
+
+ /* free modifier if match */
+ if (free) {
+ BLI_remlink(&ob->modifiers, md);
+ modifier_free(md);
+ }
+ }
+ }
}
void ED_object_parent_clear(Object *ob, const int type)
{
- if (ob->parent == NULL)
- return;
-
- switch (type) {
- case CLEAR_PARENT_ALL:
- {
- /* for deformers, remove corresponding modifiers to prevent
- * a large number of modifiers building up */
- object_remove_parent_deform_modifiers(ob, ob->parent);
-
- /* clear parenting relationship completely */
- ob->parent = NULL;
- break;
- }
- case CLEAR_PARENT_KEEP_TRANSFORM:
- {
- /* remove parent, and apply the parented transform
- * result as object's local transforms */
- ob->parent = NULL;
- BKE_object_apply_mat4(ob, ob->obmat, true, false);
- break;
- }
- case CLEAR_PARENT_INVERSE:
- {
- /* object stays parented, but the parent inverse
- * (i.e. offset from parent to retain binding state)
- * is cleared. In other words: nothing to do here! */
- break;
- }
- }
-
- /* Always clear parentinv matrix for sake of consistency, see T41950. */
- unit_m4(ob->parentinv);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ if (ob->parent == NULL)
+ return;
+
+ switch (type) {
+ case CLEAR_PARENT_ALL: {
+ /* for deformers, remove corresponding modifiers to prevent
+ * a large number of modifiers building up */
+ object_remove_parent_deform_modifiers(ob, ob->parent);
+
+ /* clear parenting relationship completely */
+ ob->parent = NULL;
+ break;
+ }
+ case CLEAR_PARENT_KEEP_TRANSFORM: {
+ /* remove parent, and apply the parented transform
+ * result as object's local transforms */
+ ob->parent = NULL;
+ BKE_object_apply_mat4(ob, ob->obmat, true, false);
+ break;
+ }
+ case CLEAR_PARENT_INVERSE: {
+ /* object stays parented, but the parent inverse
+ * (i.e. offset from parent to retain binding state)
+ * is cleared. In other words: nothing to do here! */
+ break;
+ }
+ }
+
+ /* Always clear parentinv matrix for sake of consistency, see T41950. */
+ unit_m4(ob->parentinv);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
}
/* note, poll should check for editable scene */
static int parent_clear_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- const int type = RNA_enum_get(op->ptr, "type");
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- ED_object_parent_clear(ob, type);
- }
- CTX_DATA_END;
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ const int type = RNA_enum_get(op->ptr, "type");
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ ED_object_parent_clear(ob, type);
+ }
+ CTX_DATA_END;
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_parent_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Parent";
- ot->description = "Clear the object's parenting";
- ot->idname = "OBJECT_OT_parent_clear";
+ /* identifiers */
+ ot->name = "Clear Parent";
+ ot->description = "Clear the object's parenting";
+ ot->idname = "OBJECT_OT_parent_clear";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = parent_clear_exec;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = parent_clear_exec;
- ot->poll = ED_operator_object_active_editable;
+ ot->poll = ED_operator_object_active_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_enum(ot->srna, "type", prop_clear_parent_types, CLEAR_PARENT_ALL, "Type", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_clear_parent_types, CLEAR_PARENT_ALL, "Type", "");
}
/* ******************** Make Parent Operator *********************** */
void ED_object_parent(Object *ob, Object *par, const int type, const char *substr)
{
- /* Always clear parentinv matrix for sake of consistency, see T41950. */
- unit_m4(ob->parentinv);
+ /* Always clear parentinv matrix for sake of consistency, see T41950. */
+ unit_m4(ob->parentinv);
- if (!par || BKE_object_parent_loop_check(par, ob)) {
- ob->parent = NULL;
- ob->partype = PAROBJECT;
- ob->parsubstr[0] = 0;
- return;
- }
+ if (!par || BKE_object_parent_loop_check(par, ob)) {
+ ob->parent = NULL;
+ ob->partype = PAROBJECT;
+ ob->parsubstr[0] = 0;
+ return;
+ }
- /* Other partypes are deprecated, do not use here! */
- BLI_assert(ELEM(type & PARTYPE, PAROBJECT, PARSKEL, PARVERT1, PARVERT3, PARBONE));
+ /* Other partypes are deprecated, do not use here! */
+ BLI_assert(ELEM(type & PARTYPE, PAROBJECT, PARSKEL, PARVERT1, PARVERT3, PARBONE));
- /* this could use some more checks */
+ /* this could use some more checks */
- ob->parent = par;
- ob->partype &= ~PARTYPE;
- ob->partype |= type;
- BLI_strncpy(ob->parsubstr, substr, sizeof(ob->parsubstr));
+ ob->parent = par;
+ ob->partype &= ~PARTYPE;
+ ob->partype |= type;
+ BLI_strncpy(ob->parsubstr, substr, sizeof(ob->parsubstr));
}
/* Operator Property */
EnumPropertyItem prop_make_parent_types[] = {
- {PAR_OBJECT, "OBJECT", 0, "Object", ""},
- {PAR_ARMATURE, "ARMATURE", 0, "Armature Deform", ""},
- {PAR_ARMATURE_NAME, "ARMATURE_NAME", 0, " With Empty Groups", ""},
- {PAR_ARMATURE_AUTO, "ARMATURE_AUTO", 0, " With Automatic Weights", ""},
- {PAR_ARMATURE_ENVELOPE, "ARMATURE_ENVELOPE", 0, " With Envelope Weights", ""},
- {PAR_BONE, "BONE", 0, "Bone", ""},
- {PAR_BONE_RELATIVE, "BONE_RELATIVE", 0, "Bone Relative", ""},
- {PAR_CURVE, "CURVE", 0, "Curve Deform", ""},
- {PAR_FOLLOW, "FOLLOW", 0, "Follow Path", ""},
- {PAR_PATH_CONST, "PATH_CONST", 0, "Path Constraint", ""},
- {PAR_LATTICE, "LATTICE", 0, "Lattice Deform", ""},
- {PAR_VERTEX, "VERTEX", 0, "Vertex", ""},
- {PAR_VERTEX_TRI, "VERTEX_TRI", 0, "Vertex (Triangle)", ""},
- {0, NULL, 0, NULL, NULL},
+ {PAR_OBJECT, "OBJECT", 0, "Object", ""},
+ {PAR_ARMATURE, "ARMATURE", 0, "Armature Deform", ""},
+ {PAR_ARMATURE_NAME, "ARMATURE_NAME", 0, " With Empty Groups", ""},
+ {PAR_ARMATURE_AUTO, "ARMATURE_AUTO", 0, " With Automatic Weights", ""},
+ {PAR_ARMATURE_ENVELOPE, "ARMATURE_ENVELOPE", 0, " With Envelope Weights", ""},
+ {PAR_BONE, "BONE", 0, "Bone", ""},
+ {PAR_BONE_RELATIVE, "BONE_RELATIVE", 0, "Bone Relative", ""},
+ {PAR_CURVE, "CURVE", 0, "Curve Deform", ""},
+ {PAR_FOLLOW, "FOLLOW", 0, "Follow Path", ""},
+ {PAR_PATH_CONST, "PATH_CONST", 0, "Path Constraint", ""},
+ {PAR_LATTICE, "LATTICE", 0, "Lattice Deform", ""},
+ {PAR_VERTEX, "VERTEX", 0, "Vertex", ""},
+ {PAR_VERTEX_TRI, "VERTEX_TRI", 0, "Vertex (Triangle)", ""},
+ {0, NULL, 0, NULL, NULL},
};
-bool ED_object_parent_set(ReportList *reports, const bContext *C, Scene *scene, Object *ob, Object *par,
- int partype, const bool xmirror, const bool keep_transform, const int vert_par[3])
+bool ED_object_parent_set(ReportList *reports,
+ const bContext *C,
+ Scene *scene,
+ Object *ob,
+ Object *par,
+ int partype,
+ const bool xmirror,
+ const bool keep_transform,
+ const int vert_par[3])
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- bPoseChannel *pchan = NULL;
- bPoseChannel *pchan_eval = NULL;
- const bool pararm = ELEM(partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO);
- Object *parent_eval = DEG_get_evaluated_object(depsgraph, par);
-
- DEG_id_tag_update(&par->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
-
- /* preconditions */
- if (partype == PAR_FOLLOW || partype == PAR_PATH_CONST) {
- if (par->type != OB_CURVE)
- return 0;
- else {
- Curve *cu = par->data;
- Curve *cu_eval = parent_eval->data;
- if ((cu->flag & CU_PATH) == 0) {
- cu->flag |= CU_PATH | CU_FOLLOW;
- cu_eval->flag |= CU_PATH | CU_FOLLOW;
- /* force creation of path data */
- BKE_displist_make_curveTypes(depsgraph, scene, par, false, false, NULL);
- }
- else {
- cu->flag |= CU_FOLLOW;
- cu_eval->flag |= CU_FOLLOW;
- }
-
- /* if follow, add F-Curve for ctime (i.e. "eval_time") so that path-follow works */
- if (partype == PAR_FOLLOW) {
- /* get or create F-Curve */
- bAction *act = verify_adt_action(bmain, &cu->id, 1);
- FCurve *fcu = verify_fcurve(bmain, act, NULL, NULL, "eval_time", 0, 1);
-
- /* setup dummy 'generator' modifier here to get 1-1 correspondence still working */
- if (!fcu->bezt && !fcu->fpt && !fcu->modifiers.first)
- add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR, fcu);
- }
-
- /* fall back on regular parenting now (for follow only) */
- if (partype == PAR_FOLLOW)
- partype = PAR_OBJECT;
- }
- }
- else if (ELEM(partype, PAR_BONE, PAR_BONE_RELATIVE)) {
- pchan = BKE_pose_channel_active(par);
- pchan_eval = BKE_pose_channel_active(parent_eval);
-
- if (pchan == NULL) {
- BKE_report(reports, RPT_ERROR, "No active bone");
- return false;
- }
- }
-
- if (ob != par) {
- if (BKE_object_parent_loop_check(par, ob)) {
- BKE_report(reports, RPT_ERROR, "Loop in parents");
- return false;
- }
- else {
- Object workob;
-
- /* apply transformation of previous parenting */
- if (keep_transform) {
- /* was removed because of bug [#23577],
- * but this can be handy in some cases too [#32616], so make optional */
- BKE_object_apply_mat4(ob, ob->obmat, false, false);
- }
-
- /* set the parent (except for follow-path constraint option) */
- if (partype != PAR_PATH_CONST) {
- ob->parent = par;
- /* Always clear parentinv matrix for sake of consistency, see T41950. */
- unit_m4(ob->parentinv);
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- }
-
- /* handle types */
- if (pchan)
- BLI_strncpy(ob->parsubstr, pchan->name, sizeof(ob->parsubstr));
- else
- ob->parsubstr[0] = 0;
-
- if (partype == PAR_PATH_CONST) {
- /* don't do anything here, since this is not technically "parenting" */
- }
- else if (ELEM(partype, PAR_CURVE, PAR_LATTICE) || (pararm)) {
- /* partype is now set to PAROBJECT so that invisible 'virtual' modifiers don't need to be created
- * NOTE: the old (2.4x) method was to set ob->partype = PARSKEL, creating the virtual modifiers
- */
- ob->partype = PAROBJECT; /* note, dna define, not operator property */
- /* ob->partype = PARSKEL; */ /* note, dna define, not operator property */
-
- /* BUT, to keep the deforms, we need a modifier, and then we need to set the object that it uses
- * - We need to ensure that the modifier we're adding doesn't already exist, so we check this by
- * assuming that the parent is selected too...
- */
- /* XXX currently this should only happen for meshes, curves, surfaces,
- * and lattices - this stuff isn't available for metas yet */
- if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
- ModifierData *md;
-
- switch (partype) {
- case PAR_CURVE: /* curve deform */
- if (modifiers_isDeformedByCurve(ob) != par) {
- md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Curve);
- if (md) {
- ((CurveModifierData *)md)->object = par;
- }
- if (par->runtime.curve_cache && par->runtime.curve_cache->path == NULL) {
- DEG_id_tag_update(&par->id, ID_RECALC_GEOMETRY);
- }
- }
- break;
- case PAR_LATTICE: /* lattice deform */
- if (modifiers_isDeformedByLattice(ob) != par) {
- md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Lattice);
- if (md) {
- ((LatticeModifierData *)md)->object = par;
- }
- }
- break;
- default: /* armature deform */
- if (modifiers_isDeformedByArmature(ob) != par) {
- md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Armature);
- if (md) {
- ((ArmatureModifierData *)md)->object = par;
- }
- }
- break;
- }
- }
- }
- else if (partype == PAR_BONE) {
- ob->partype = PARBONE; /* note, dna define, not operator property */
- if (pchan->bone) {
- pchan->bone->flag &= ~BONE_RELATIVE_PARENTING;
- pchan_eval->bone->flag &= ~BONE_RELATIVE_PARENTING;
- }
- }
- else if (partype == PAR_BONE_RELATIVE) {
- ob->partype = PARBONE; /* note, dna define, not operator property */
- if (pchan->bone) {
- pchan->bone->flag |= BONE_RELATIVE_PARENTING;
- pchan_eval->bone->flag |= BONE_RELATIVE_PARENTING;
- }
- }
- else if (partype == PAR_VERTEX) {
- ob->partype = PARVERT1;
- ob->par1 = vert_par[0];
- }
- else if (partype == PAR_VERTEX_TRI) {
- ob->partype = PARVERT3;
- copy_v3_v3_int(&ob->par1, vert_par);
- }
- else {
- ob->partype = PAROBJECT; /* note, dna define, not operator property */
- }
-
- /* constraint */
- if (partype == PAR_PATH_CONST) {
- bConstraint *con;
- bFollowPathConstraint *data;
- float cmat[4][4], vec[3];
-
- con = BKE_constraint_add_for_object(ob, "AutoPath", CONSTRAINT_TYPE_FOLLOWPATH);
-
- data = con->data;
- data->tar = par;
-
- BKE_constraint_target_matrix_get(depsgraph, scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra);
- sub_v3_v3v3(vec, ob->obmat[3], cmat[3]);
-
- copy_v3_v3(ob->loc, vec);
- }
- else if (pararm && (ob->type == OB_MESH) && (par->type == OB_ARMATURE)) {
- if (partype == PAR_ARMATURE_NAME) {
- ED_object_vgroup_calc_from_armature(reports, depsgraph, scene, ob, par, ARM_GROUPS_NAME, false);
- }
- else if (partype == PAR_ARMATURE_ENVELOPE) {
- ED_object_vgroup_calc_from_armature(reports, depsgraph, scene, ob, par, ARM_GROUPS_ENVELOPE, xmirror);
- }
- else if (partype == PAR_ARMATURE_AUTO) {
- WM_cursor_wait(1);
- ED_object_vgroup_calc_from_armature(reports, depsgraph, scene, ob, par, ARM_GROUPS_AUTO, xmirror);
- WM_cursor_wait(0);
- }
- /* get corrected inverse */
- ob->partype = PAROBJECT;
- BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
-
- invert_m4_m4(ob->parentinv, workob.obmat);
- }
- else if (pararm && (ob->type == OB_GPENCIL) && (par->type == OB_ARMATURE)) {
- if (partype == PAR_ARMATURE_NAME) {
- ED_gpencil_add_armature_weights(C, reports, ob, par, GP_PAR_ARMATURE_NAME);
- }
- else if ((partype == PAR_ARMATURE_AUTO) ||
- (partype == PAR_ARMATURE_ENVELOPE))
- {
- WM_cursor_wait(1);
- ED_gpencil_add_armature_weights(C, reports, ob, par, GP_PAR_ARMATURE_AUTO);
- WM_cursor_wait(0);
- }
- /* get corrected inverse */
- ob->partype = PAROBJECT;
- BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
-
- invert_m4_m4(ob->parentinv, workob.obmat);
- }
- else {
- /* calculate inverse parent matrix */
- BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- invert_m4_m4(ob->parentinv, workob.obmat);
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- }
- }
-
- return true;
+ Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ bPoseChannel *pchan = NULL;
+ bPoseChannel *pchan_eval = NULL;
+ const bool pararm = ELEM(
+ partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO);
+ Object *parent_eval = DEG_get_evaluated_object(depsgraph, par);
+
+ DEG_id_tag_update(&par->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+
+ /* preconditions */
+ if (partype == PAR_FOLLOW || partype == PAR_PATH_CONST) {
+ if (par->type != OB_CURVE)
+ return 0;
+ else {
+ Curve *cu = par->data;
+ Curve *cu_eval = parent_eval->data;
+ if ((cu->flag & CU_PATH) == 0) {
+ cu->flag |= CU_PATH | CU_FOLLOW;
+ cu_eval->flag |= CU_PATH | CU_FOLLOW;
+ /* force creation of path data */
+ BKE_displist_make_curveTypes(depsgraph, scene, par, false, false, NULL);
+ }
+ else {
+ cu->flag |= CU_FOLLOW;
+ cu_eval->flag |= CU_FOLLOW;
+ }
+
+ /* if follow, add F-Curve for ctime (i.e. "eval_time") so that path-follow works */
+ if (partype == PAR_FOLLOW) {
+ /* get or create F-Curve */
+ bAction *act = verify_adt_action(bmain, &cu->id, 1);
+ FCurve *fcu = verify_fcurve(bmain, act, NULL, NULL, "eval_time", 0, 1);
+
+ /* setup dummy 'generator' modifier here to get 1-1 correspondence still working */
+ if (!fcu->bezt && !fcu->fpt && !fcu->modifiers.first)
+ add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR, fcu);
+ }
+
+ /* fall back on regular parenting now (for follow only) */
+ if (partype == PAR_FOLLOW)
+ partype = PAR_OBJECT;
+ }
+ }
+ else if (ELEM(partype, PAR_BONE, PAR_BONE_RELATIVE)) {
+ pchan = BKE_pose_channel_active(par);
+ pchan_eval = BKE_pose_channel_active(parent_eval);
+
+ if (pchan == NULL) {
+ BKE_report(reports, RPT_ERROR, "No active bone");
+ return false;
+ }
+ }
+
+ if (ob != par) {
+ if (BKE_object_parent_loop_check(par, ob)) {
+ BKE_report(reports, RPT_ERROR, "Loop in parents");
+ return false;
+ }
+ else {
+ Object workob;
+
+ /* apply transformation of previous parenting */
+ if (keep_transform) {
+ /* was removed because of bug [#23577],
+ * but this can be handy in some cases too [#32616], so make optional */
+ BKE_object_apply_mat4(ob, ob->obmat, false, false);
+ }
+
+ /* set the parent (except for follow-path constraint option) */
+ if (partype != PAR_PATH_CONST) {
+ ob->parent = par;
+ /* Always clear parentinv matrix for sake of consistency, see T41950. */
+ unit_m4(ob->parentinv);
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ }
+
+ /* handle types */
+ if (pchan)
+ BLI_strncpy(ob->parsubstr, pchan->name, sizeof(ob->parsubstr));
+ else
+ ob->parsubstr[0] = 0;
+
+ if (partype == PAR_PATH_CONST) {
+ /* don't do anything here, since this is not technically "parenting" */
+ }
+ else if (ELEM(partype, PAR_CURVE, PAR_LATTICE) || (pararm)) {
+ /* partype is now set to PAROBJECT so that invisible 'virtual' modifiers don't need to be created
+ * NOTE: the old (2.4x) method was to set ob->partype = PARSKEL, creating the virtual modifiers
+ */
+ ob->partype = PAROBJECT; /* note, dna define, not operator property */
+ /* ob->partype = PARSKEL; */ /* note, dna define, not operator property */
+
+ /* BUT, to keep the deforms, we need a modifier, and then we need to set the object that it uses
+ * - We need to ensure that the modifier we're adding doesn't already exist, so we check this by
+ * assuming that the parent is selected too...
+ */
+ /* XXX currently this should only happen for meshes, curves, surfaces,
+ * and lattices - this stuff isn't available for metas yet */
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
+ ModifierData *md;
+
+ switch (partype) {
+ case PAR_CURVE: /* curve deform */
+ if (modifiers_isDeformedByCurve(ob) != par) {
+ md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Curve);
+ if (md) {
+ ((CurveModifierData *)md)->object = par;
+ }
+ if (par->runtime.curve_cache && par->runtime.curve_cache->path == NULL) {
+ DEG_id_tag_update(&par->id, ID_RECALC_GEOMETRY);
+ }
+ }
+ break;
+ case PAR_LATTICE: /* lattice deform */
+ if (modifiers_isDeformedByLattice(ob) != par) {
+ md = ED_object_modifier_add(
+ reports, bmain, scene, ob, NULL, eModifierType_Lattice);
+ if (md) {
+ ((LatticeModifierData *)md)->object = par;
+ }
+ }
+ break;
+ default: /* armature deform */
+ if (modifiers_isDeformedByArmature(ob) != par) {
+ md = ED_object_modifier_add(
+ reports, bmain, scene, ob, NULL, eModifierType_Armature);
+ if (md) {
+ ((ArmatureModifierData *)md)->object = par;
+ }
+ }
+ break;
+ }
+ }
+ }
+ else if (partype == PAR_BONE) {
+ ob->partype = PARBONE; /* note, dna define, not operator property */
+ if (pchan->bone) {
+ pchan->bone->flag &= ~BONE_RELATIVE_PARENTING;
+ pchan_eval->bone->flag &= ~BONE_RELATIVE_PARENTING;
+ }
+ }
+ else if (partype == PAR_BONE_RELATIVE) {
+ ob->partype = PARBONE; /* note, dna define, not operator property */
+ if (pchan->bone) {
+ pchan->bone->flag |= BONE_RELATIVE_PARENTING;
+ pchan_eval->bone->flag |= BONE_RELATIVE_PARENTING;
+ }
+ }
+ else if (partype == PAR_VERTEX) {
+ ob->partype = PARVERT1;
+ ob->par1 = vert_par[0];
+ }
+ else if (partype == PAR_VERTEX_TRI) {
+ ob->partype = PARVERT3;
+ copy_v3_v3_int(&ob->par1, vert_par);
+ }
+ else {
+ ob->partype = PAROBJECT; /* note, dna define, not operator property */
+ }
+
+ /* constraint */
+ if (partype == PAR_PATH_CONST) {
+ bConstraint *con;
+ bFollowPathConstraint *data;
+ float cmat[4][4], vec[3];
+
+ con = BKE_constraint_add_for_object(ob, "AutoPath", CONSTRAINT_TYPE_FOLLOWPATH);
+
+ data = con->data;
+ data->tar = par;
+
+ BKE_constraint_target_matrix_get(
+ depsgraph, scene, con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra);
+ sub_v3_v3v3(vec, ob->obmat[3], cmat[3]);
+
+ copy_v3_v3(ob->loc, vec);
+ }
+ else if (pararm && (ob->type == OB_MESH) && (par->type == OB_ARMATURE)) {
+ if (partype == PAR_ARMATURE_NAME) {
+ ED_object_vgroup_calc_from_armature(
+ reports, depsgraph, scene, ob, par, ARM_GROUPS_NAME, false);
+ }
+ else if (partype == PAR_ARMATURE_ENVELOPE) {
+ ED_object_vgroup_calc_from_armature(
+ reports, depsgraph, scene, ob, par, ARM_GROUPS_ENVELOPE, xmirror);
+ }
+ else if (partype == PAR_ARMATURE_AUTO) {
+ WM_cursor_wait(1);
+ ED_object_vgroup_calc_from_armature(
+ reports, depsgraph, scene, ob, par, ARM_GROUPS_AUTO, xmirror);
+ WM_cursor_wait(0);
+ }
+ /* get corrected inverse */
+ ob->partype = PAROBJECT;
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
+
+ invert_m4_m4(ob->parentinv, workob.obmat);
+ }
+ else if (pararm && (ob->type == OB_GPENCIL) && (par->type == OB_ARMATURE)) {
+ if (partype == PAR_ARMATURE_NAME) {
+ ED_gpencil_add_armature_weights(C, reports, ob, par, GP_PAR_ARMATURE_NAME);
+ }
+ else if ((partype == PAR_ARMATURE_AUTO) || (partype == PAR_ARMATURE_ENVELOPE)) {
+ WM_cursor_wait(1);
+ ED_gpencil_add_armature_weights(C, reports, ob, par, GP_PAR_ARMATURE_AUTO);
+ WM_cursor_wait(0);
+ }
+ /* get corrected inverse */
+ ob->partype = PAROBJECT;
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
+
+ invert_m4_m4(ob->parentinv, workob.obmat);
+ }
+ else {
+ /* calculate inverse parent matrix */
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
+ invert_m4_m4(ob->parentinv, workob.obmat);
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ }
+ }
+
+ return true;
}
-
-
static void parent_set_vert_find(KDTree_3d *tree, Object *child, int vert_par[3], bool is_tri)
{
- const float *co_find = child->obmat[3];
- if (is_tri) {
- KDTreeNearest_3d nearest[3];
- int tot;
-
- tot = BLI_kdtree_3d_find_nearest_n(tree, co_find, nearest, 3);
- BLI_assert(tot == 3);
- UNUSED_VARS(tot);
-
- vert_par[0] = nearest[0].index;
- vert_par[1] = nearest[1].index;
- vert_par[2] = nearest[2].index;
-
- BLI_assert(min_iii(UNPACK3(vert_par)) >= 0);
- }
- else {
- vert_par[0] = BLI_kdtree_3d_find_nearest(tree, co_find, NULL);
- BLI_assert(vert_par[0] >= 0);
- vert_par[1] = 0;
- vert_par[2] = 0;
- }
+ const float *co_find = child->obmat[3];
+ if (is_tri) {
+ KDTreeNearest_3d nearest[3];
+ int tot;
+
+ tot = BLI_kdtree_3d_find_nearest_n(tree, co_find, nearest, 3);
+ BLI_assert(tot == 3);
+ UNUSED_VARS(tot);
+
+ vert_par[0] = nearest[0].index;
+ vert_par[1] = nearest[1].index;
+ vert_par[2] = nearest[2].index;
+
+ BLI_assert(min_iii(UNPACK3(vert_par)) >= 0);
+ }
+ else {
+ vert_par[0] = BLI_kdtree_3d_find_nearest(tree, co_find, NULL);
+ BLI_assert(vert_par[0] >= 0);
+ vert_par[1] = 0;
+ vert_par[2] = 0;
+ }
}
static int parent_set_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *par = ED_object_active_context(C);
- int partype = RNA_enum_get(op->ptr, "type");
- const bool xmirror = RNA_boolean_get(op->ptr, "xmirror");
- const bool keep_transform = RNA_boolean_get(op->ptr, "keep_transform");
- bool ok = true;
-
- /* vertex parent (kdtree) */
- const bool is_vert_par = ELEM(partype, PAR_VERTEX, PAR_VERTEX_TRI);
- const bool is_tri = partype == PAR_VERTEX_TRI;
- int tree_tot;
- struct KDTree_3d *tree = NULL;
- int vert_par[3] = {0, 0, 0};
- const int *vert_par_p = is_vert_par ? vert_par : NULL;
-
-
- if (is_vert_par) {
- tree = BKE_object_as_kdtree(par, &tree_tot);
- BLI_assert(tree != NULL);
-
- if (tree_tot < (is_tri ? 3 : 1)) {
- BKE_report(op->reports, RPT_ERROR, "Not enough vertices for vertex-parent");
- ok = false;
- }
- }
-
- if (ok) {
- /* Non vertex-parent */
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if (is_vert_par) {
- parent_set_vert_find(tree, ob, vert_par, is_tri);
- }
-
- if (!ED_object_parent_set(op->reports, C, scene, ob, par, partype, xmirror, keep_transform, vert_par_p)) {
- ok = false;
- break;
- }
- }
- CTX_DATA_END;
- }
-
- if (is_vert_par) {
- BLI_kdtree_3d_free(tree);
- }
-
- if (!ok)
- return OPERATOR_CANCELLED;
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *par = ED_object_active_context(C);
+ int partype = RNA_enum_get(op->ptr, "type");
+ const bool xmirror = RNA_boolean_get(op->ptr, "xmirror");
+ const bool keep_transform = RNA_boolean_get(op->ptr, "keep_transform");
+ bool ok = true;
+
+ /* vertex parent (kdtree) */
+ const bool is_vert_par = ELEM(partype, PAR_VERTEX, PAR_VERTEX_TRI);
+ const bool is_tri = partype == PAR_VERTEX_TRI;
+ int tree_tot;
+ struct KDTree_3d *tree = NULL;
+ int vert_par[3] = {0, 0, 0};
+ const int *vert_par_p = is_vert_par ? vert_par : NULL;
+
+ if (is_vert_par) {
+ tree = BKE_object_as_kdtree(par, &tree_tot);
+ BLI_assert(tree != NULL);
+
+ if (tree_tot < (is_tri ? 3 : 1)) {
+ BKE_report(op->reports, RPT_ERROR, "Not enough vertices for vertex-parent");
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ /* Non vertex-parent */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (is_vert_par) {
+ parent_set_vert_find(tree, ob, vert_par, is_tri);
+ }
+
+ if (!ED_object_parent_set(
+ op->reports, C, scene, ob, par, partype, xmirror, keep_transform, vert_par_p)) {
+ ok = false;
+ break;
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ if (is_vert_par) {
+ BLI_kdtree_3d_free(tree);
+ }
+
+ if (!ok)
+ return OPERATOR_CANCELLED;
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
+
+ return OPERATOR_FINISHED;
}
-
static int parent_set_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
- Object *parent = ED_object_active_context(C);
- uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Set Parent To"), ICON_NONE);
- uiLayout *layout = UI_popup_menu_layout(pup);
+ Object *parent = ED_object_active_context(C);
+ uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Set Parent To"), ICON_NONE);
+ uiLayout *layout = UI_popup_menu_layout(pup);
- wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_parent_set", true);
- PointerRNA opptr;
+ wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_parent_set", true);
+ PointerRNA opptr;
#if 0
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_OBJECT);
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_OBJECT);
#else
- uiItemFullO_ptr(layout, ot, IFACE_("Object"), ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
- RNA_enum_set(&opptr, "type", PAR_OBJECT);
- RNA_boolean_set(&opptr, "keep_transform", false);
-
- uiItemFullO_ptr(
- layout, ot, IFACE_("Object (Keep Transform)"), ICON_NONE,
- NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
- RNA_enum_set(&opptr, "type", PAR_OBJECT);
- RNA_boolean_set(&opptr, "keep_transform", true);
+ uiItemFullO_ptr(layout, ot, IFACE_("Object"), ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
+ RNA_enum_set(&opptr, "type", PAR_OBJECT);
+ RNA_boolean_set(&opptr, "keep_transform", false);
+
+ uiItemFullO_ptr(layout,
+ ot,
+ IFACE_("Object (Keep Transform)"),
+ ICON_NONE,
+ NULL,
+ WM_OP_EXEC_DEFAULT,
+ 0,
+ &opptr);
+ RNA_enum_set(&opptr, "type", PAR_OBJECT);
+ RNA_boolean_set(&opptr, "keep_transform", true);
#endif
- uiItemO(layout, IFACE_("Object (Without Inverse)"), ICON_NONE, "OBJECT_OT_parent_no_inverse_set");
-
- struct {
- bool mesh, gpencil;
- } has_children_of_type = { 0 };
-
- CTX_DATA_BEGIN (C, Object *, child, selected_editable_objects)
- {
- if (child == parent) {
- continue;
- }
- if (child->type == OB_MESH) {
- has_children_of_type.mesh = true;
- }
- if (child->type == OB_GPENCIL) {
- has_children_of_type.gpencil = true;
- }
- }
- CTX_DATA_END;
-
- if (parent->type == OB_ARMATURE) {
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE);
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE_NAME);
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE_ENVELOPE);
- if (has_children_of_type.mesh || has_children_of_type.gpencil) {
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE_AUTO);
- }
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_BONE);
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_BONE_RELATIVE);
- }
- else if (parent->type == OB_CURVE) {
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_CURVE);
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_FOLLOW);
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_PATH_CONST);
- }
- else if (parent->type == OB_LATTICE) {
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_LATTICE);
- }
-
- /* vertex parenting */
- if (OB_TYPE_SUPPORT_PARVERT(parent->type)) {
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_VERTEX);
- uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_VERTEX_TRI);
- }
-
- UI_popup_menu_end(C, pup);
-
- return OPERATOR_INTERFACE;
+ uiItemO(
+ layout, IFACE_("Object (Without Inverse)"), ICON_NONE, "OBJECT_OT_parent_no_inverse_set");
+
+ struct {
+ bool mesh, gpencil;
+ } has_children_of_type = {0};
+
+ CTX_DATA_BEGIN (C, Object *, child, selected_editable_objects) {
+ if (child == parent) {
+ continue;
+ }
+ if (child->type == OB_MESH) {
+ has_children_of_type.mesh = true;
+ }
+ if (child->type == OB_GPENCIL) {
+ has_children_of_type.gpencil = true;
+ }
+ }
+ CTX_DATA_END;
+
+ if (parent->type == OB_ARMATURE) {
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE);
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE_NAME);
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE_ENVELOPE);
+ if (has_children_of_type.mesh || has_children_of_type.gpencil) {
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE_AUTO);
+ }
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_BONE);
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_BONE_RELATIVE);
+ }
+ else if (parent->type == OB_CURVE) {
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_CURVE);
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_FOLLOW);
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_PATH_CONST);
+ }
+ else if (parent->type == OB_LATTICE) {
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_LATTICE);
+ }
+
+ /* vertex parenting */
+ if (OB_TYPE_SUPPORT_PARVERT(parent->type)) {
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_VERTEX);
+ uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_VERTEX_TRI);
+ }
+
+ UI_popup_menu_end(C, pup);
+
+ return OPERATOR_INTERFACE;
}
-static bool parent_set_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop)
+static bool parent_set_poll_property(const bContext *UNUSED(C),
+ wmOperator *op,
+ const PropertyRNA *prop)
{
- const char *prop_id = RNA_property_identifier(prop);
-
- /* Only show XMirror for PAR_ARMATURE_ENVELOPE and PAR_ARMATURE_AUTO! */
- if (STREQ(prop_id, "xmirror")) {
- const int type = RNA_enum_get(op->ptr, "type");
- if (ELEM(type, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO))
- return true;
- else
- return false;
- }
-
- return true;
+ const char *prop_id = RNA_property_identifier(prop);
+
+ /* Only show XMirror for PAR_ARMATURE_ENVELOPE and PAR_ARMATURE_AUTO! */
+ if (STREQ(prop_id, "xmirror")) {
+ const int type = RNA_enum_get(op->ptr, "type");
+ if (ELEM(type, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO))
+ return true;
+ else
+ return false;
+ }
+
+ return true;
}
void OBJECT_OT_parent_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Parent";
- ot->description = "Set the object's parenting";
- ot->idname = "OBJECT_OT_parent_set";
-
- /* api callbacks */
- ot->invoke = parent_set_invoke;
- ot->exec = parent_set_exec;
- ot->poll = ED_operator_object_active;
- ot->poll_property = parent_set_poll_property;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ot->prop = RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
- RNA_def_boolean(ot->srna, "xmirror", false, "X Mirror",
- "Apply weights symmetrically along X axis, for Envelope/Automatic vertex groups creation");
- RNA_def_boolean(ot->srna, "keep_transform", false, "Keep Transform",
- "Apply transformation before parenting");
+ /* identifiers */
+ ot->name = "Make Parent";
+ ot->description = "Set the object's parenting";
+ ot->idname = "OBJECT_OT_parent_set";
+
+ /* api callbacks */
+ ot->invoke = parent_set_invoke;
+ ot->exec = parent_set_exec;
+ ot->poll = ED_operator_object_active;
+ ot->poll_property = parent_set_poll_property;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
+ RNA_def_boolean(
+ ot->srna,
+ "xmirror",
+ false,
+ "X Mirror",
+ "Apply weights symmetrically along X axis, for Envelope/Automatic vertex groups creation");
+ RNA_def_boolean(ot->srna,
+ "keep_transform",
+ false,
+ "Keep Transform",
+ "Apply transformation before parenting");
}
/* ************ Make Parent Without Inverse Operator ******************* */
static int parent_noinv_set_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *par = ED_object_active_context(C);
-
- DEG_id_tag_update(&par->id, ID_RECALC_TRANSFORM);
-
- /* context iterator */
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if (ob != par) {
- if (BKE_object_parent_loop_check(par, ob)) {
- BKE_report(op->reports, RPT_ERROR, "Loop in parents");
- }
- else {
- /* clear inverse matrix and also the object location */
- unit_m4(ob->parentinv);
- memset(ob->loc, 0, 3 * sizeof(float));
-
- /* set recalc flags */
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
-
- /* set parenting type for object - object only... */
- ob->parent = par;
- ob->partype = PAROBJECT; /* note, dna define, not operator property */
- }
- }
- }
- CTX_DATA_END;
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Object *par = ED_object_active_context(C);
+
+ DEG_id_tag_update(&par->id, ID_RECALC_TRANSFORM);
+
+ /* context iterator */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (ob != par) {
+ if (BKE_object_parent_loop_check(par, ob)) {
+ BKE_report(op->reports, RPT_ERROR, "Loop in parents");
+ }
+ else {
+ /* clear inverse matrix and also the object location */
+ unit_m4(ob->parentinv);
+ memset(ob->loc, 0, 3 * sizeof(float));
+
+ /* set recalc flags */
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+
+ /* set parenting type for object - object only... */
+ ob->parent = par;
+ ob->partype = PAROBJECT; /* note, dna define, not operator property */
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_parent_no_inverse_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Parent without Inverse";
- ot->description = "Set the object's parenting without setting the inverse parent correction";
- ot->idname = "OBJECT_OT_parent_no_inverse_set";
-
- /* api callbacks */
- ot->invoke = WM_operator_confirm;
- ot->exec = parent_noinv_set_exec;
- ot->poll = ED_operator_object_active_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Make Parent without Inverse";
+ ot->description = "Set the object's parenting without setting the inverse parent correction";
+ ot->idname = "OBJECT_OT_parent_no_inverse_set";
+
+ /* api callbacks */
+ ot->invoke = WM_operator_confirm;
+ ot->exec = parent_noinv_set_exec;
+ ot->poll = ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* ******************** Clear Track Operator ******************* */
enum {
- CLEAR_TRACK = 1,
- CLEAR_TRACK_KEEP_TRANSFORM = 2,
+ CLEAR_TRACK = 1,
+ CLEAR_TRACK_KEEP_TRANSFORM = 2,
};
static const EnumPropertyItem prop_clear_track_types[] = {
- {CLEAR_TRACK, "CLEAR", 0, "Clear Track", ""},
- {CLEAR_TRACK_KEEP_TRANSFORM, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation (Clear Track)", ""},
- {0, NULL, 0, NULL, NULL},
+ {CLEAR_TRACK, "CLEAR", 0, "Clear Track", ""},
+ {CLEAR_TRACK_KEEP_TRANSFORM,
+ "CLEAR_KEEP_TRANSFORM",
+ 0,
+ "Clear and Keep Transformation (Clear Track)",
+ ""},
+ {0, NULL, 0, NULL, NULL},
};
/* note, poll should check for editable scene */
static int object_track_clear_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- const int type = RNA_enum_get(op->ptr, "type");
-
- if (CTX_data_edit_object(C)) {
- BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in edit mode");
- return OPERATOR_CANCELLED;
- }
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- bConstraint *con, *pcon;
-
- /* remove track-object for old track */
- ob->track = NULL;
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
-
- /* also remove all tracking constraints */
- for (con = ob->constraints.last; con; con = pcon) {
- pcon = con->prev;
- if (ELEM(con->type, CONSTRAINT_TYPE_TRACKTO, CONSTRAINT_TYPE_LOCKTRACK, CONSTRAINT_TYPE_DAMPTRACK))
- BKE_constraint_remove(&ob->constraints, con);
- }
-
- if (type == CLEAR_TRACK_KEEP_TRANSFORM)
- BKE_object_apply_mat4(ob, ob->obmat, true, true);
- }
- CTX_DATA_END;
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ const int type = RNA_enum_get(op->ptr, "type");
+
+ if (CTX_data_edit_object(C)) {
+ BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in edit mode");
+ return OPERATOR_CANCELLED;
+ }
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ bConstraint *con, *pcon;
+
+ /* remove track-object for old track */
+ ob->track = NULL;
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+
+ /* also remove all tracking constraints */
+ for (con = ob->constraints.last; con; con = pcon) {
+ pcon = con->prev;
+ if (ELEM(con->type,
+ CONSTRAINT_TYPE_TRACKTO,
+ CONSTRAINT_TYPE_LOCKTRACK,
+ CONSTRAINT_TYPE_DAMPTRACK))
+ BKE_constraint_remove(&ob->constraints, con);
+ }
+
+ if (type == CLEAR_TRACK_KEEP_TRANSFORM)
+ BKE_object_apply_mat4(ob, ob->obmat, true, true);
+ }
+ CTX_DATA_END;
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_track_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Track";
- ot->description = "Clear tracking constraint or flag from object";
- ot->idname = "OBJECT_OT_track_clear";
+ /* identifiers */
+ ot->name = "Clear Track";
+ ot->description = "Clear tracking constraint or flag from object";
+ ot->idname = "OBJECT_OT_track_clear";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_track_clear_exec;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_track_clear_exec;
- ot->poll = ED_operator_objectmode;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_enum(ot->srna, "type", prop_clear_track_types, 0, "Type", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_clear_track_types, 0, "Type", "");
}
/************************** Make Track Operator *****************************/
enum {
- CREATE_TRACK_DAMPTRACK = 1,
- CREATE_TRACK_TRACKTO = 2,
- CREATE_TRACK_LOCKTRACK = 3,
+ CREATE_TRACK_DAMPTRACK = 1,
+ CREATE_TRACK_TRACKTO = 2,
+ CREATE_TRACK_LOCKTRACK = 3,
};
static const EnumPropertyItem prop_make_track_types[] = {
- {CREATE_TRACK_DAMPTRACK, "DAMPTRACK", 0, "Damped Track Constraint", ""},
- {CREATE_TRACK_TRACKTO, "TRACKTO", 0, "Track To Constraint", ""},
- {CREATE_TRACK_LOCKTRACK, "LOCKTRACK", 0, "Lock Track Constraint", ""},
- {0, NULL, 0, NULL, NULL},
+ {CREATE_TRACK_DAMPTRACK, "DAMPTRACK", 0, "Damped Track Constraint", ""},
+ {CREATE_TRACK_TRACKTO, "TRACKTO", 0, "Track To Constraint", ""},
+ {CREATE_TRACK_LOCKTRACK, "LOCKTRACK", 0, "Lock Track Constraint", ""},
+ {0, NULL, 0, NULL, NULL},
};
static int track_set_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *obact = ED_object_active_context(C);
-
- const int type = RNA_enum_get(op->ptr, "type");
-
- switch (type) {
- case CREATE_TRACK_DAMPTRACK:
- {
- bConstraint *con;
- bDampTrackConstraint *data;
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if (ob != obact) {
- con = BKE_constraint_add_for_object(ob, "AutoTrack", CONSTRAINT_TYPE_DAMPTRACK);
-
- data = con->data;
- data->tar = obact;
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
-
- /* Light, Camera and Speaker track differently by default */
- if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
- data->trackflag = TRACK_nZ;
- }
- }
- }
- CTX_DATA_END;
- break;
- }
- case CREATE_TRACK_TRACKTO:
- {
- bConstraint *con;
- bTrackToConstraint *data;
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if (ob != obact) {
- con = BKE_constraint_add_for_object(ob, "AutoTrack", CONSTRAINT_TYPE_TRACKTO);
-
- data = con->data;
- data->tar = obact;
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
-
- /* Light, Camera and Speaker track differently by default */
- if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
- data->reserved1 = TRACK_nZ;
- data->reserved2 = UP_Y;
- }
- }
- }
- CTX_DATA_END;
- break;
- }
- case CREATE_TRACK_LOCKTRACK:
- {
- bConstraint *con;
- bLockTrackConstraint *data;
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if (ob != obact) {
- con = BKE_constraint_add_for_object(ob, "AutoTrack", CONSTRAINT_TYPE_LOCKTRACK);
-
- data = con->data;
- data->tar = obact;
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
-
- /* Light, Camera and Speaker track differently by default */
- if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
- data->trackflag = TRACK_nZ;
- data->lockflag = LOCK_Y;
- }
- }
- }
- CTX_DATA_END;
- break;
- }
- }
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Object *obact = ED_object_active_context(C);
+
+ const int type = RNA_enum_get(op->ptr, "type");
+
+ switch (type) {
+ case CREATE_TRACK_DAMPTRACK: {
+ bConstraint *con;
+ bDampTrackConstraint *data;
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (ob != obact) {
+ con = BKE_constraint_add_for_object(ob, "AutoTrack", CONSTRAINT_TYPE_DAMPTRACK);
+
+ data = con->data;
+ data->tar = obact;
+ DEG_id_tag_update(&ob->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+
+ /* Light, Camera and Speaker track differently by default */
+ if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
+ data->trackflag = TRACK_nZ;
+ }
+ }
+ }
+ CTX_DATA_END;
+ break;
+ }
+ case CREATE_TRACK_TRACKTO: {
+ bConstraint *con;
+ bTrackToConstraint *data;
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (ob != obact) {
+ con = BKE_constraint_add_for_object(ob, "AutoTrack", CONSTRAINT_TYPE_TRACKTO);
+
+ data = con->data;
+ data->tar = obact;
+ DEG_id_tag_update(&ob->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+
+ /* Light, Camera and Speaker track differently by default */
+ if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
+ data->reserved1 = TRACK_nZ;
+ data->reserved2 = UP_Y;
+ }
+ }
+ }
+ CTX_DATA_END;
+ break;
+ }
+ case CREATE_TRACK_LOCKTRACK: {
+ bConstraint *con;
+ bLockTrackConstraint *data;
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (ob != obact) {
+ con = BKE_constraint_add_for_object(ob, "AutoTrack", CONSTRAINT_TYPE_LOCKTRACK);
+
+ data = con->data;
+ data->tar = obact;
+ DEG_id_tag_update(&ob->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+
+ /* Light, Camera and Speaker track differently by default */
+ if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
+ data->trackflag = TRACK_nZ;
+ data->lockflag = LOCK_Y;
+ }
+ }
+ }
+ CTX_DATA_END;
+ break;
+ }
+ }
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_track_set(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Track";
- ot->description = "Make the object track another object, using various methods/constraints";
- ot->idname = "OBJECT_OT_track_set";
+ /* identifiers */
+ ot->name = "Make Track";
+ ot->description = "Make the object track another object, using various methods/constraints";
+ ot->idname = "OBJECT_OT_track_set";
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = track_set_exec;
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = track_set_exec;
- ot->poll = ED_operator_objectmode;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", prop_make_track_types, 0, "Type", "");
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_make_track_types, 0, "Type", "");
}
/************************** Link to Scene Operator *****************************/
@@ -1286,1296 +1339,1315 @@ void OBJECT_OT_track_set(wmOperatorType *ot)
#if 0
static void link_to_scene(Main *UNUSED(bmain), unsigned short UNUSED(nr))
{
- Scene *sce = (Scene *) BLI_findlink(&bmain->scene, G.curscreen->scenenr - 1);
- Base *base, *nbase;
-
- if (sce == NULL) return;
- if (sce->id.lib) return;
-
- for (base = FIRSTBASE; base; base = base->next) {
- if (BASE_SELECTED(v3d, base)) {
- nbase = MEM_mallocN(sizeof(Base), "newbase");
- *nbase = *base;
- BLI_addhead(&(sce->base), nbase);
- id_us_plus((ID *)base->object);
- }
- }
+ Scene *sce = (Scene *) BLI_findlink(&bmain->scene, G.curscreen->scenenr - 1);
+ Base *base, *nbase;
+
+ if (sce == NULL) return;
+ if (sce->id.lib) return;
+
+ for (base = FIRSTBASE; base; base = base->next) {
+ if (BASE_SELECTED(v3d, base)) {
+ nbase = MEM_mallocN(sizeof(Base), "newbase");
+ *nbase = *base;
+ BLI_addhead(&(sce->base), nbase);
+ id_us_plus((ID *)base->object);
+ }
+ }
}
#endif
static int make_links_scene_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene_to = BLI_findlink(&bmain->scenes, RNA_enum_get(op->ptr, "scene"));
-
- if (scene_to == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Could not find scene");
- return OPERATOR_CANCELLED;
- }
-
- if (scene_to == CTX_data_scene(C)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot link objects into the same scene");
- return OPERATOR_CANCELLED;
- }
-
- if (ID_IS_LINKED(scene_to)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot link objects into a linked scene");
- return OPERATOR_CANCELLED;
- }
-
- Collection *collection_to = BKE_collection_master(scene_to);
- CTX_DATA_BEGIN (C, Base *, base, selected_bases)
- {
- BKE_collection_object_add(bmain, collection_to, base->object);
- }
- CTX_DATA_END;
-
- DEG_relations_tag_update(bmain);
-
- /* redraw the 3D view because the object center points are colored differently */
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
-
- /* one day multiple scenes will be visible, then we should have some update function for them */
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene_to = BLI_findlink(&bmain->scenes, RNA_enum_get(op->ptr, "scene"));
+
+ if (scene_to == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Could not find scene");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (scene_to == CTX_data_scene(C)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot link objects into the same scene");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (ID_IS_LINKED(scene_to)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot link objects into a linked scene");
+ return OPERATOR_CANCELLED;
+ }
+
+ Collection *collection_to = BKE_collection_master(scene_to);
+ CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
+ BKE_collection_object_add(bmain, collection_to, base->object);
+ }
+ CTX_DATA_END;
+
+ DEG_relations_tag_update(bmain);
+
+ /* redraw the 3D view because the object center points are colored differently */
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
+
+ /* one day multiple scenes will be visible, then we should have some update function for them */
+ return OPERATOR_FINISHED;
}
enum {
- MAKE_LINKS_OBDATA = 1,
- MAKE_LINKS_MATERIALS = 2,
- MAKE_LINKS_ANIMDATA = 3,
- MAKE_LINKS_GROUP = 4,
- MAKE_LINKS_DUPLICOLLECTION = 5,
- MAKE_LINKS_MODIFIERS = 6,
- MAKE_LINKS_FONTS = 7,
+ MAKE_LINKS_OBDATA = 1,
+ MAKE_LINKS_MATERIALS = 2,
+ MAKE_LINKS_ANIMDATA = 3,
+ MAKE_LINKS_GROUP = 4,
+ MAKE_LINKS_DUPLICOLLECTION = 5,
+ MAKE_LINKS_MODIFIERS = 6,
+ MAKE_LINKS_FONTS = 7,
};
/* Return true if make link data is allowed, false otherwise */
static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst)
{
- switch (type) {
- case MAKE_LINKS_OBDATA:
- if (ob_src->type == ob_dst->type && ob_src->type != OB_EMPTY) {
- return true;
- }
- break;
- case MAKE_LINKS_MATERIALS:
- if (OB_TYPE_SUPPORT_MATERIAL(ob_src->type) && OB_TYPE_SUPPORT_MATERIAL(ob_dst->type)) {
- return true;
- }
- break;
- case MAKE_LINKS_DUPLICOLLECTION:
- if (ob_dst->type == OB_EMPTY) {
- return true;
- }
- break;
- case MAKE_LINKS_ANIMDATA:
- case MAKE_LINKS_GROUP:
- return true;
- case MAKE_LINKS_MODIFIERS:
- if (!ELEM(OB_EMPTY, ob_src->type, ob_dst->type)) {
- return true;
- }
- break;
- case MAKE_LINKS_FONTS:
- if ((ob_src->data != ob_dst->data) && (ob_src->type == OB_FONT) && (ob_dst->type == OB_FONT)) {
- return true;
- }
- break;
- }
- return false;
+ switch (type) {
+ case MAKE_LINKS_OBDATA:
+ if (ob_src->type == ob_dst->type && ob_src->type != OB_EMPTY) {
+ return true;
+ }
+ break;
+ case MAKE_LINKS_MATERIALS:
+ if (OB_TYPE_SUPPORT_MATERIAL(ob_src->type) && OB_TYPE_SUPPORT_MATERIAL(ob_dst->type)) {
+ return true;
+ }
+ break;
+ case MAKE_LINKS_DUPLICOLLECTION:
+ if (ob_dst->type == OB_EMPTY) {
+ return true;
+ }
+ break;
+ case MAKE_LINKS_ANIMDATA:
+ case MAKE_LINKS_GROUP:
+ return true;
+ case MAKE_LINKS_MODIFIERS:
+ if (!ELEM(OB_EMPTY, ob_src->type, ob_dst->type)) {
+ return true;
+ }
+ break;
+ case MAKE_LINKS_FONTS:
+ if ((ob_src->data != ob_dst->data) && (ob_src->type == OB_FONT) &&
+ (ob_dst->type == OB_FONT)) {
+ return true;
+ }
+ break;
+ }
+ return false;
}
static int make_links_data_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- Main *bmain = CTX_data_main(C);
- const int type = RNA_enum_get(op->ptr, "type");
- Object *ob_src;
- ID *obdata_id;
- int a;
-
- /* collection */
- LinkNode *ob_collections = NULL;
- bool is_cycle = false;
- bool is_lib = false;
-
- ob_src = ED_object_active_context(C);
-
- /* avoid searching all collections in source object each time */
- if (type == MAKE_LINKS_GROUP) {
- ob_collections = BKE_object_groups(bmain, scene, ob_src);
- }
-
- CTX_DATA_BEGIN (C, Base *, base_dst, selected_editable_bases)
- {
- Object *ob_dst = base_dst->object;
-
- if (ob_src != ob_dst) {
- if (allow_make_links_data(type, ob_src, ob_dst)) {
- obdata_id = ob_dst->data;
-
- switch (type) {
- case MAKE_LINKS_OBDATA: /* obdata */
- id_us_min(obdata_id);
-
- obdata_id = ob_src->data;
- id_us_plus(obdata_id);
- ob_dst->data = obdata_id;
-
- /* if amount of material indices changed: */
- test_object_materials(bmain, ob_dst, ob_dst->data);
-
- DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
- break;
- case MAKE_LINKS_MATERIALS:
- /* new approach, using functions from kernel */
- for (a = 0; a < ob_src->totcol; a++) {
- Material *ma = give_current_material(ob_src, a + 1);
- /* also works with `ma == NULL` */
- assign_material(bmain, ob_dst, ma, a + 1, BKE_MAT_ASSIGN_USERPREF);
- }
- DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
- break;
- case MAKE_LINKS_ANIMDATA:
- BKE_animdata_copy_id(bmain, (ID *)ob_dst, (ID *)ob_src, 0);
- if (ob_dst->data && ob_src->data) {
- if (ID_IS_LINKED(obdata_id)) {
- is_lib = true;
- break;
- }
- BKE_animdata_copy_id(bmain, (ID *)ob_dst->data, (ID *)ob_src->data, 0);
- }
- DEG_id_tag_update(&ob_dst->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- break;
- case MAKE_LINKS_GROUP:
- {
- LinkNode *collection_node;
-
- /* first clear collections */
- BKE_object_groups_clear(bmain, scene, ob_dst);
-
- /* now add in the collections from the link nodes */
- for (collection_node = ob_collections; collection_node; collection_node = collection_node->next) {
- if (ob_dst->instance_collection != collection_node->link) {
- BKE_collection_object_add(bmain, collection_node->link, ob_dst);
- }
- else {
- is_cycle = true;
- }
- }
- break;
- }
- case MAKE_LINKS_DUPLICOLLECTION:
- ob_dst->instance_collection = ob_src->instance_collection;
- if (ob_dst->instance_collection) {
- id_us_plus(&ob_dst->instance_collection->id);
- ob_dst->transflag |= OB_DUPLICOLLECTION;
- }
- break;
- case MAKE_LINKS_MODIFIERS:
- BKE_object_link_modifiers(scene, ob_dst, ob_src);
- DEG_id_tag_update(&ob_dst->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- break;
- case MAKE_LINKS_FONTS:
- {
- Curve *cu_src = ob_src->data;
- Curve *cu_dst = ob_dst->data;
-
- if (ID_IS_LINKED(obdata_id)) {
- is_lib = true;
- break;
- }
-
- if (cu_dst->vfont)
- id_us_min(&cu_dst->vfont->id);
- cu_dst->vfont = cu_src->vfont;
- id_us_plus((ID *)cu_dst->vfont);
- if (cu_dst->vfontb)
- id_us_min(&cu_dst->vfontb->id);
- cu_dst->vfontb = cu_src->vfontb;
- id_us_plus((ID *)cu_dst->vfontb);
- if (cu_dst->vfonti)
- id_us_min(&cu_dst->vfonti->id);
- cu_dst->vfonti = cu_src->vfonti;
- id_us_plus((ID *)cu_dst->vfonti);
- if (cu_dst->vfontbi)
- id_us_min(&cu_dst->vfontbi->id);
- cu_dst->vfontbi = cu_src->vfontbi;
- id_us_plus((ID *)cu_dst->vfontbi);
-
- DEG_id_tag_update(&ob_dst->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- break;
- }
- }
- }
- }
- }
- CTX_DATA_END;
-
- if (type == MAKE_LINKS_GROUP) {
- if (ob_collections) {
- BLI_linklist_free(ob_collections, NULL);
- }
-
- if (is_cycle) {
- BKE_report(op->reports, RPT_WARNING, "Skipped some collections because of cycle detected");
- }
- }
-
- if (is_lib) {
- BKE_report(op->reports, RPT_WARNING, "Skipped editing library object data");
- }
-
- DEG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C));
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, CTX_wm_view3d(C));
- WM_event_add_notifier(C, NC_OBJECT, NULL);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ Main *bmain = CTX_data_main(C);
+ const int type = RNA_enum_get(op->ptr, "type");
+ Object *ob_src;
+ ID *obdata_id;
+ int a;
+
+ /* collection */
+ LinkNode *ob_collections = NULL;
+ bool is_cycle = false;
+ bool is_lib = false;
+
+ ob_src = ED_object_active_context(C);
+
+ /* avoid searching all collections in source object each time */
+ if (type == MAKE_LINKS_GROUP) {
+ ob_collections = BKE_object_groups(bmain, scene, ob_src);
+ }
+
+ CTX_DATA_BEGIN (C, Base *, base_dst, selected_editable_bases) {
+ Object *ob_dst = base_dst->object;
+
+ if (ob_src != ob_dst) {
+ if (allow_make_links_data(type, ob_src, ob_dst)) {
+ obdata_id = ob_dst->data;
+
+ switch (type) {
+ case MAKE_LINKS_OBDATA: /* obdata */
+ id_us_min(obdata_id);
+
+ obdata_id = ob_src->data;
+ id_us_plus(obdata_id);
+ ob_dst->data = obdata_id;
+
+ /* if amount of material indices changed: */
+ test_object_materials(bmain, ob_dst, ob_dst->data);
+
+ DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
+ break;
+ case MAKE_LINKS_MATERIALS:
+ /* new approach, using functions from kernel */
+ for (a = 0; a < ob_src->totcol; a++) {
+ Material *ma = give_current_material(ob_src, a + 1);
+ /* also works with `ma == NULL` */
+ assign_material(bmain, ob_dst, ma, a + 1, BKE_MAT_ASSIGN_USERPREF);
+ }
+ DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
+ break;
+ case MAKE_LINKS_ANIMDATA:
+ BKE_animdata_copy_id(bmain, (ID *)ob_dst, (ID *)ob_src, 0);
+ if (ob_dst->data && ob_src->data) {
+ if (ID_IS_LINKED(obdata_id)) {
+ is_lib = true;
+ break;
+ }
+ BKE_animdata_copy_id(bmain, (ID *)ob_dst->data, (ID *)ob_src->data, 0);
+ }
+ DEG_id_tag_update(&ob_dst->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ break;
+ case MAKE_LINKS_GROUP: {
+ LinkNode *collection_node;
+
+ /* first clear collections */
+ BKE_object_groups_clear(bmain, scene, ob_dst);
+
+ /* now add in the collections from the link nodes */
+ for (collection_node = ob_collections; collection_node;
+ collection_node = collection_node->next) {
+ if (ob_dst->instance_collection != collection_node->link) {
+ BKE_collection_object_add(bmain, collection_node->link, ob_dst);
+ }
+ else {
+ is_cycle = true;
+ }
+ }
+ break;
+ }
+ case MAKE_LINKS_DUPLICOLLECTION:
+ ob_dst->instance_collection = ob_src->instance_collection;
+ if (ob_dst->instance_collection) {
+ id_us_plus(&ob_dst->instance_collection->id);
+ ob_dst->transflag |= OB_DUPLICOLLECTION;
+ }
+ break;
+ case MAKE_LINKS_MODIFIERS:
+ BKE_object_link_modifiers(scene, ob_dst, ob_src);
+ DEG_id_tag_update(&ob_dst->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ break;
+ case MAKE_LINKS_FONTS: {
+ Curve *cu_src = ob_src->data;
+ Curve *cu_dst = ob_dst->data;
+
+ if (ID_IS_LINKED(obdata_id)) {
+ is_lib = true;
+ break;
+ }
+
+ if (cu_dst->vfont)
+ id_us_min(&cu_dst->vfont->id);
+ cu_dst->vfont = cu_src->vfont;
+ id_us_plus((ID *)cu_dst->vfont);
+ if (cu_dst->vfontb)
+ id_us_min(&cu_dst->vfontb->id);
+ cu_dst->vfontb = cu_src->vfontb;
+ id_us_plus((ID *)cu_dst->vfontb);
+ if (cu_dst->vfonti)
+ id_us_min(&cu_dst->vfonti->id);
+ cu_dst->vfonti = cu_src->vfonti;
+ id_us_plus((ID *)cu_dst->vfonti);
+ if (cu_dst->vfontbi)
+ id_us_min(&cu_dst->vfontbi->id);
+ cu_dst->vfontbi = cu_src->vfontbi;
+ id_us_plus((ID *)cu_dst->vfontbi);
+
+ DEG_id_tag_update(&ob_dst->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ break;
+ }
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ if (type == MAKE_LINKS_GROUP) {
+ if (ob_collections) {
+ BLI_linklist_free(ob_collections, NULL);
+ }
+
+ if (is_cycle) {
+ BKE_report(op->reports, RPT_WARNING, "Skipped some collections because of cycle detected");
+ }
+ }
+
+ if (is_lib) {
+ BKE_report(op->reports, RPT_WARNING, "Skipped editing library object data");
+ }
+
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C));
+ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, CTX_wm_view3d(C));
+ WM_event_add_notifier(C, NC_OBJECT, NULL);
+
+ return OPERATOR_FINISHED;
}
-
void OBJECT_OT_make_links_scene(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Link Objects to Scene";
- ot->description = "Link selection to another scene";
- ot->idname = "OBJECT_OT_make_links_scene";
-
- /* api callbacks */
- ot->invoke = WM_enum_search_invoke;
- ot->exec = make_links_scene_exec;
- /* better not run the poll check */
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "scene", DummyRNA_NULL_items, 0, "Scene", "");
- RNA_def_enum_funcs(prop, RNA_scene_local_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Link Objects to Scene";
+ ot->description = "Link selection to another scene";
+ ot->idname = "OBJECT_OT_make_links_scene";
+
+ /* api callbacks */
+ ot->invoke = WM_enum_search_invoke;
+ ot->exec = make_links_scene_exec;
+ /* better not run the poll check */
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna, "scene", DummyRNA_NULL_items, 0, "Scene", "");
+ RNA_def_enum_funcs(prop, RNA_scene_local_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
void OBJECT_OT_make_links_data(wmOperatorType *ot)
{
- static const EnumPropertyItem make_links_items[] = {
- {MAKE_LINKS_OBDATA, "OBDATA", 0, "Object Data", ""},
- {MAKE_LINKS_MATERIALS, "MATERIAL", 0, "Materials", ""},
- {MAKE_LINKS_ANIMDATA, "ANIMATION", 0, "Animation Data", ""},
- {MAKE_LINKS_GROUP, "GROUPS", 0, "Collection", ""},
- {MAKE_LINKS_DUPLICOLLECTION, "DUPLICOLLECTION", 0, "Instance Collection", ""},
- {MAKE_LINKS_MODIFIERS, "MODIFIERS", 0, "Modifiers", ""},
- {MAKE_LINKS_FONTS, "FONTS", 0, "Fonts", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Link Data";
- ot->description = "Apply active object links to other selected objects";
- ot->idname = "OBJECT_OT_make_links_data";
-
- /* api callbacks */
- ot->exec = make_links_data_exec;
- ot->poll = ED_operator_object_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", make_links_items, 0, "Type", "");
+ static const EnumPropertyItem make_links_items[] = {
+ {MAKE_LINKS_OBDATA, "OBDATA", 0, "Object Data", ""},
+ {MAKE_LINKS_MATERIALS, "MATERIAL", 0, "Materials", ""},
+ {MAKE_LINKS_ANIMDATA, "ANIMATION", 0, "Animation Data", ""},
+ {MAKE_LINKS_GROUP, "GROUPS", 0, "Collection", ""},
+ {MAKE_LINKS_DUPLICOLLECTION, "DUPLICOLLECTION", 0, "Instance Collection", ""},
+ {MAKE_LINKS_MODIFIERS, "MODIFIERS", 0, "Modifiers", ""},
+ {MAKE_LINKS_FONTS, "FONTS", 0, "Fonts", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Link Data";
+ ot->description = "Apply active object links to other selected objects";
+ ot->idname = "OBJECT_OT_make_links_data";
+
+ /* api callbacks */
+ ot->exec = make_links_data_exec;
+ ot->poll = ED_operator_object_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", make_links_items, 0, "Type", "");
}
-
/**************************** Make Single User ********************************/
static void libblock_relink_collection(Collection *collection)
{
- BKE_libblock_relink_to_newid(&collection->id);
+ BKE_libblock_relink_to_newid(&collection->id);
- for (CollectionObject *cob = collection->gobject.first; cob != NULL; cob = cob->next) {
- BKE_libblock_relink_to_newid(&cob->ob->id);
- }
+ for (CollectionObject *cob = collection->gobject.first; cob != NULL; cob = cob->next) {
+ BKE_libblock_relink_to_newid(&cob->ob->id);
+ }
- for (CollectionChild *child = collection->children.first; child; child = child->next) {
- libblock_relink_collection(child->collection);
- }
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ libblock_relink_collection(child->collection);
+ }
}
-static Collection *single_object_users_collection(
- Main *bmain, Scene *scene, Collection *collection,
- const int flag, const bool copy_collections, const bool is_master_collection)
+static Collection *single_object_users_collection(Main *bmain,
+ Scene *scene,
+ Collection *collection,
+ const int flag,
+ const bool copy_collections,
+ const bool is_master_collection)
{
- /* Generate new copies for objects in given collection and all its children,
- * and optionnaly also copy collections themselves. */
- if (copy_collections && !is_master_collection) {
- collection = ID_NEW_SET(collection, BKE_collection_copy(bmain, NULL, collection));
- }
-
- /* We do not remap to new objects here, this is done in separate step. */
- for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
- Object *ob = cob->ob;
- /* an object may be in more than one collection */
- if ((ob->id.newid == NULL) && ((ob->flag & flag) == flag)) {
- if (!ID_IS_LINKED(ob) && BKE_object_scenes_users_get(bmain, ob) > 1) {
- ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
- }
- }
- }
-
- /* Since master collection has already be duplicated as part of scene copy, we do not duplictae it here.
- * However, this means its children need to be re-added manually here, otherwise their parent lists are empty
- * (which will lead to crashes, see T63101). */
- CollectionChild *child_next, *child = collection->children.first;
- CollectionChild *orig_child_last = collection->children.last;
- for (; child != NULL; child = child_next) {
- child_next = child->next;
- Collection *collection_child_new = single_object_users_collection(
- bmain, scene, child->collection, flag, copy_collections, false);
- if (is_master_collection && copy_collections && child->collection != collection_child_new) {
- BKE_collection_child_add(bmain, collection, collection_child_new);
- BLI_remlink(&collection->children, child);
- MEM_freeN(child);
- if (child == orig_child_last) {
- break;
- }
- }
- }
-
- return collection;
+ /* Generate new copies for objects in given collection and all its children,
+ * and optionnaly also copy collections themselves. */
+ if (copy_collections && !is_master_collection) {
+ collection = ID_NEW_SET(collection, BKE_collection_copy(bmain, NULL, collection));
+ }
+
+ /* We do not remap to new objects here, this is done in separate step. */
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ Object *ob = cob->ob;
+ /* an object may be in more than one collection */
+ if ((ob->id.newid == NULL) && ((ob->flag & flag) == flag)) {
+ if (!ID_IS_LINKED(ob) && BKE_object_scenes_users_get(bmain, ob) > 1) {
+ ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
+ }
+ }
+ }
+
+ /* Since master collection has already be duplicated as part of scene copy, we do not duplictae it here.
+ * However, this means its children need to be re-added manually here, otherwise their parent lists are empty
+ * (which will lead to crashes, see T63101). */
+ CollectionChild *child_next, *child = collection->children.first;
+ CollectionChild *orig_child_last = collection->children.last;
+ for (; child != NULL; child = child_next) {
+ child_next = child->next;
+ Collection *collection_child_new = single_object_users_collection(
+ bmain, scene, child->collection, flag, copy_collections, false);
+ if (is_master_collection && copy_collections && child->collection != collection_child_new) {
+ BKE_collection_child_add(bmain, collection, collection_child_new);
+ BLI_remlink(&collection->children, child);
+ MEM_freeN(child);
+ if (child == orig_child_last) {
+ break;
+ }
+ }
+ }
+
+ return collection;
}
/* Warning, sets ID->newid pointers of objects and collections, but does not clear them. */
-static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_collections)
+static void single_object_users(
+ Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_collections)
{
- /* duplicate all the objects of the scene (and matching collections, if required). */
- Collection *master_collection = BKE_collection_master(scene);
- single_object_users_collection(bmain, scene, master_collection, flag, copy_collections, true);
-
- /* duplicate collections that consist entirely of duplicated objects */
- /* XXX I guess that was designed for calls from 'make single user' operator... But since copy_collection is
- * always false then, was not doing anything. And that kind of behavior should be added at operator level,
- * not in a utility function also used by rather different code... */
+ /* duplicate all the objects of the scene (and matching collections, if required). */
+ Collection *master_collection = BKE_collection_master(scene);
+ single_object_users_collection(bmain, scene, master_collection, flag, copy_collections, true);
+
+ /* duplicate collections that consist entirely of duplicated objects */
+ /* XXX I guess that was designed for calls from 'make single user' operator... But since copy_collection is
+ * always false then, was not doing anything. And that kind of behavior should be added at operator level,
+ * not in a utility function also used by rather different code... */
#if 0
- if (copy_collections) {
- Collection *collection, *collectionn;
- for (collection = bmain->collections.first; collection; collection = collection->id.next) {
- bool all_duplicated = true;
- bool any_duplicated = false;
-
- for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
- any_duplicated = true;
- if (cob->ob->id.newid == NULL) {
- all_duplicated = false;
- break;
- }
- }
-
- if (any_duplicated && all_duplicated) {
- // TODO: test if this works, with child collections ..
- collectionn = ID_NEW_SET(collection, BKE_collection_copy(bmain, NULL, collection));
-
- for (CollectionObject *cob = collectionn->gobject.first; cob; cob = cob->next) {
- cob->ob = (Object *)cob->ob->id.newid;
- }
- }
- }
- }
+ if (copy_collections) {
+ Collection *collection, *collectionn;
+ for (collection = bmain->collections.first; collection; collection = collection->id.next) {
+ bool all_duplicated = true;
+ bool any_duplicated = false;
+
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ any_duplicated = true;
+ if (cob->ob->id.newid == NULL) {
+ all_duplicated = false;
+ break;
+ }
+ }
+
+ if (any_duplicated && all_duplicated) {
+ // TODO: test if this works, with child collections ..
+ collectionn = ID_NEW_SET(collection, BKE_collection_copy(bmain, NULL, collection));
+
+ for (CollectionObject *cob = collectionn->gobject.first; cob; cob = cob->next) {
+ cob->ob = (Object *)cob->ob->id.newid;
+ }
+ }
+ }
+ }
#endif
- /* Collection and object pointers in collections */
- libblock_relink_collection(master_collection);
+ /* Collection and object pointers in collections */
+ libblock_relink_collection(master_collection);
- /* collection pointers in scene */
- BKE_scene_groups_relink(scene);
+ /* collection pointers in scene */
+ BKE_scene_groups_relink(scene);
- /* active camera */
- ID_NEW_REMAP(scene->camera);
- if (v3d) {
- ID_NEW_REMAP(v3d->camera);
- }
+ /* active camera */
+ ID_NEW_REMAP(scene->camera);
+ if (v3d) {
+ ID_NEW_REMAP(v3d->camera);
+ }
- /* Making single user may affect other scenes if they share with current one some collections in their ViewLayer. */
- BKE_main_collection_sync(bmain);
+ /* Making single user may affect other scenes if they share with current one some collections in their ViewLayer. */
+ BKE_main_collection_sync(bmain);
}
/* not an especially efficient function, only added so the single user
* button can be functional.*/
void ED_object_single_user(Main *bmain, Scene *scene, Object *ob)
{
- FOREACH_SCENE_OBJECT_BEGIN(scene, ob_iter)
- {
- ob_iter->flag &= ~OB_DONE;
- }
- FOREACH_SCENE_OBJECT_END;
+ FOREACH_SCENE_OBJECT_BEGIN (scene, ob_iter) {
+ ob_iter->flag &= ~OB_DONE;
+ }
+ FOREACH_SCENE_OBJECT_END;
- /* tag only the one object */
- ob->flag |= OB_DONE;
+ /* tag only the one object */
+ ob->flag |= OB_DONE;
- single_object_users(bmain, scene, NULL, OB_DONE, false);
- BKE_main_id_clear_newpoins(bmain);
+ single_object_users(bmain, scene, NULL, OB_DONE, false);
+ BKE_main_id_clear_newpoins(bmain);
}
static void new_id_matar(Main *bmain, Material **matar, const int totcol)
{
- ID *id;
- int a;
-
- for (a = 0; a < totcol; a++) {
- id = (ID *)matar[a];
- if (id && !ID_IS_LINKED(id)) {
- if (id->newid) {
- matar[a] = (Material *)id->newid;
- id_us_plus(id->newid);
- id_us_min(id);
- }
- else if (id->us > 1) {
- matar[a] = ID_NEW_SET(id, BKE_material_copy(bmain, matar[a]));
- id_us_min(id);
- }
- }
- }
+ ID *id;
+ int a;
+
+ for (a = 0; a < totcol; a++) {
+ id = (ID *)matar[a];
+ if (id && !ID_IS_LINKED(id)) {
+ if (id->newid) {
+ matar[a] = (Material *)id->newid;
+ id_us_plus(id->newid);
+ id_us_min(id);
+ }
+ else if (id->us > 1) {
+ matar[a] = ID_NEW_SET(id, BKE_material_copy(bmain, matar[a]));
+ id_us_min(id);
+ }
+ }
+ }
}
-static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
+static void single_obdata_users(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
{
- Light *la;
- Curve *cu;
- /* Camera *cam; */
- Mesh *me;
- Lattice *lat;
- ID *id;
-
- FOREACH_OBJECT_FLAG_BEGIN(scene, view_layer, v3d, flag, ob)
- {
- if (!ID_IS_LINKED(ob)) {
- id = ob->data;
-
- if (id && id->us > 1 && !ID_IS_LINKED(id)) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
-
- switch (ob->type) {
- case OB_LAMP:
- ob->data = la = ID_NEW_SET(ob->data, BKE_light_copy(bmain, ob->data));
- break;
- case OB_CAMERA:
- ob->data = ID_NEW_SET(ob->data, BKE_camera_copy(bmain, ob->data));
- break;
- case OB_MESH:
- /* Needed to remap texcomesh below. */
- me = ob->data = ID_NEW_SET(ob->data, BKE_mesh_copy(bmain, ob->data));
- if (me->key) /* We do not need to set me->key->id.newid here... */
- BKE_animdata_copy_id_action(bmain, (ID *)me->key, false);
- break;
- case OB_MBALL:
- ob->data = ID_NEW_SET(ob->data, BKE_mball_copy(bmain, ob->data));
- break;
- case OB_CURVE:
- case OB_SURF:
- case OB_FONT:
- ob->data = cu = ID_NEW_SET(ob->data, BKE_curve_copy(bmain, ob->data));
- ID_NEW_REMAP(cu->bevobj);
- ID_NEW_REMAP(cu->taperobj);
- if (cu->key) /* We do not need to set cu->key->id.newid here... */
- BKE_animdata_copy_id_action(bmain, (ID *)cu->key, false);
- break;
- case OB_LATTICE:
- ob->data = lat = ID_NEW_SET(ob->data, BKE_lattice_copy(bmain, ob->data));
- if (lat->key) /* We do not need to set lat->key->id.newid here... */
- BKE_animdata_copy_id_action(bmain, (ID *)lat->key, false);
- break;
- case OB_ARMATURE:
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- ob->data = ID_NEW_SET(ob->data, BKE_armature_copy(bmain, ob->data));
- BKE_pose_rebuild(bmain, ob, ob->data, true);
- break;
- case OB_SPEAKER:
- ob->data = ID_NEW_SET(ob->data, BKE_speaker_copy(bmain, ob->data));
- break;
- case OB_LIGHTPROBE:
- ob->data = ID_NEW_SET(ob->data, BKE_lightprobe_copy(bmain, ob->data));
- break;
- case OB_GPENCIL:
- ob->data = ID_NEW_SET(ob->data, BKE_gpencil_copy(bmain, ob->data));
- break;
- default:
- printf("ERROR %s: can't copy %s\n", __func__, id->name);
- BLI_assert(!"This should never happen.");
-
- /* We need to end the FOREACH_OBJECT_FLAG_BEGIN iterator to prevent memory leak. */
- BKE_scene_objects_iterator_end(&iter_macro);
- return;
- }
-
- /* Copy animation data after object data became local,
- * otherwise old and new object data will share the same
- * AnimData structure, which is not what we want.
- * (sergey)
- */
- BKE_animdata_copy_id_action(bmain, (ID *)ob->data, false);
-
- id_us_min(id);
- }
- }
- }
- FOREACH_OBJECT_FLAG_END;
-
- me = bmain->meshes.first;
- while (me) {
- ID_NEW_REMAP(me->texcomesh);
- me = me->id.next;
- }
+ Light *la;
+ Curve *cu;
+ /* Camera *cam; */
+ Mesh *me;
+ Lattice *lat;
+ ID *id;
+
+ FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
+ if (!ID_IS_LINKED(ob)) {
+ id = ob->data;
+
+ if (id && id->us > 1 && !ID_IS_LINKED(id)) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+
+ switch (ob->type) {
+ case OB_LAMP:
+ ob->data = la = ID_NEW_SET(ob->data, BKE_light_copy(bmain, ob->data));
+ break;
+ case OB_CAMERA:
+ ob->data = ID_NEW_SET(ob->data, BKE_camera_copy(bmain, ob->data));
+ break;
+ case OB_MESH:
+ /* Needed to remap texcomesh below. */
+ me = ob->data = ID_NEW_SET(ob->data, BKE_mesh_copy(bmain, ob->data));
+ if (me->key) /* We do not need to set me->key->id.newid here... */
+ BKE_animdata_copy_id_action(bmain, (ID *)me->key, false);
+ break;
+ case OB_MBALL:
+ ob->data = ID_NEW_SET(ob->data, BKE_mball_copy(bmain, ob->data));
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ case OB_FONT:
+ ob->data = cu = ID_NEW_SET(ob->data, BKE_curve_copy(bmain, ob->data));
+ ID_NEW_REMAP(cu->bevobj);
+ ID_NEW_REMAP(cu->taperobj);
+ if (cu->key) /* We do not need to set cu->key->id.newid here... */
+ BKE_animdata_copy_id_action(bmain, (ID *)cu->key, false);
+ break;
+ case OB_LATTICE:
+ ob->data = lat = ID_NEW_SET(ob->data, BKE_lattice_copy(bmain, ob->data));
+ if (lat->key) /* We do not need to set lat->key->id.newid here... */
+ BKE_animdata_copy_id_action(bmain, (ID *)lat->key, false);
+ break;
+ case OB_ARMATURE:
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ ob->data = ID_NEW_SET(ob->data, BKE_armature_copy(bmain, ob->data));
+ BKE_pose_rebuild(bmain, ob, ob->data, true);
+ break;
+ case OB_SPEAKER:
+ ob->data = ID_NEW_SET(ob->data, BKE_speaker_copy(bmain, ob->data));
+ break;
+ case OB_LIGHTPROBE:
+ ob->data = ID_NEW_SET(ob->data, BKE_lightprobe_copy(bmain, ob->data));
+ break;
+ case OB_GPENCIL:
+ ob->data = ID_NEW_SET(ob->data, BKE_gpencil_copy(bmain, ob->data));
+ break;
+ default:
+ printf("ERROR %s: can't copy %s\n", __func__, id->name);
+ BLI_assert(!"This should never happen.");
+
+ /* We need to end the FOREACH_OBJECT_FLAG_BEGIN iterator to prevent memory leak. */
+ BKE_scene_objects_iterator_end(&iter_macro);
+ return;
+ }
+
+ /* Copy animation data after object data became local,
+ * otherwise old and new object data will share the same
+ * AnimData structure, which is not what we want.
+ * (sergey)
+ */
+ BKE_animdata_copy_id_action(bmain, (ID *)ob->data, false);
+
+ id_us_min(id);
+ }
+ }
+ }
+ FOREACH_OBJECT_FLAG_END;
+
+ me = bmain->meshes.first;
+ while (me) {
+ ID_NEW_REMAP(me->texcomesh);
+ me = me->id.next;
+ }
}
-static void single_object_action_users(Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
+static void single_object_action_users(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
{
- FOREACH_OBJECT_FLAG_BEGIN(scene, view_layer, v3d, flag, ob)
- {
- if (!ID_IS_LINKED(ob)) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- BKE_animdata_copy_id_action(bmain, &ob->id, false);
- }
- }
- FOREACH_OBJECT_FLAG_END;
+ FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
+ if (!ID_IS_LINKED(ob)) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ BKE_animdata_copy_id_action(bmain, &ob->id, false);
+ }
+ }
+ FOREACH_OBJECT_FLAG_END;
}
-static void single_mat_users(Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
+static void single_mat_users(
+ Main *bmain, Scene *scene, ViewLayer *view_layer, View3D *v3d, const int flag)
{
- Material *ma, *man;
- int a;
-
- FOREACH_OBJECT_FLAG_BEGIN(scene, view_layer, v3d, flag, ob)
- {
- if (!ID_IS_LINKED(ob)) {
- for (a = 1; a <= ob->totcol; a++) {
- ma = give_current_material(ob, a);
- if (ma) {
- /* do not test for LIB_TAG_NEW or use newid:
- * this functions guaranteed delivers single_users! */
-
- if (ma->id.us > 1) {
- man = BKE_material_copy(bmain, ma);
- BKE_animdata_copy_id_action(bmain, &man->id, false);
- if (man->nodetree != NULL) {
- BKE_animdata_copy_id_action(bmain, &man->nodetree->id, false);
- }
-
- man->id.us = 0;
- assign_material(bmain, ob, man, a, BKE_MAT_ASSIGN_USERPREF);
- }
- }
- }
- }
- }
- FOREACH_OBJECT_FLAG_END;
+ Material *ma, *man;
+ int a;
+
+ FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
+ if (!ID_IS_LINKED(ob)) {
+ for (a = 1; a <= ob->totcol; a++) {
+ ma = give_current_material(ob, a);
+ if (ma) {
+ /* do not test for LIB_TAG_NEW or use newid:
+ * this functions guaranteed delivers single_users! */
+
+ if (ma->id.us > 1) {
+ man = BKE_material_copy(bmain, ma);
+ BKE_animdata_copy_id_action(bmain, &man->id, false);
+ if (man->nodetree != NULL) {
+ BKE_animdata_copy_id_action(bmain, &man->nodetree->id, false);
+ }
+
+ man->id.us = 0;
+ assign_material(bmain, ob, man, a, BKE_MAT_ASSIGN_USERPREF);
+ }
+ }
+ }
+ }
+ }
+ FOREACH_OBJECT_FLAG_END;
}
static void single_mat_users_expand(Main *bmain)
{
- /* only when 'parent' blocks are LIB_TAG_NEW */
- Object *ob;
- Mesh *me;
- Curve *cu;
- MetaBall *mb;
- bGPdata *gpd;
-
- for (ob = bmain->objects.first; ob; ob = ob->id.next)
- if (ob->id.tag & LIB_TAG_NEW)
- new_id_matar(bmain, ob->mat, ob->totcol);
-
- for (me = bmain->meshes.first; me; me = me->id.next)
- if (me->id.tag & LIB_TAG_NEW)
- new_id_matar(bmain, me->mat, me->totcol);
-
- for (cu = bmain->curves.first; cu; cu = cu->id.next)
- if (cu->id.tag & LIB_TAG_NEW)
- new_id_matar(bmain, cu->mat, cu->totcol);
-
- for (mb = bmain->metaballs.first; mb; mb = mb->id.next)
- if (mb->id.tag & LIB_TAG_NEW)
- new_id_matar(bmain, mb->mat, mb->totcol);
-
- for (gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next)
- if (gpd->id.tag & LIB_TAG_NEW)
- new_id_matar(bmain, gpd->mat, gpd->totcol);
+ /* only when 'parent' blocks are LIB_TAG_NEW */
+ Object *ob;
+ Mesh *me;
+ Curve *cu;
+ MetaBall *mb;
+ bGPdata *gpd;
+
+ for (ob = bmain->objects.first; ob; ob = ob->id.next)
+ if (ob->id.tag & LIB_TAG_NEW)
+ new_id_matar(bmain, ob->mat, ob->totcol);
+
+ for (me = bmain->meshes.first; me; me = me->id.next)
+ if (me->id.tag & LIB_TAG_NEW)
+ new_id_matar(bmain, me->mat, me->totcol);
+
+ for (cu = bmain->curves.first; cu; cu = cu->id.next)
+ if (cu->id.tag & LIB_TAG_NEW)
+ new_id_matar(bmain, cu->mat, cu->totcol);
+
+ for (mb = bmain->metaballs.first; mb; mb = mb->id.next)
+ if (mb->id.tag & LIB_TAG_NEW)
+ new_id_matar(bmain, mb->mat, mb->totcol);
+
+ for (gpd = bmain->gpencils.first; gpd; gpd = gpd->id.next)
+ if (gpd->id.tag & LIB_TAG_NEW)
+ new_id_matar(bmain, gpd->mat, gpd->totcol);
}
/* used for copying scenes */
-void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bool copy_collections)
+void ED_object_single_users(Main *bmain,
+ Scene *scene,
+ const bool full,
+ const bool copy_collections)
{
- single_object_users(bmain, scene, NULL, 0, copy_collections);
-
- if (full) {
- single_obdata_users(bmain, scene, NULL, NULL, 0);
- single_object_action_users(bmain, scene, NULL, NULL, 0);
- single_mat_users_expand(bmain);
- }
-
- /* Relink nodetrees' pointers that have been duplicated. */
- FOREACH_NODETREE_BEGIN(bmain, ntree, id)
- {
- /* This is a bit convoluted, we want to root ntree of copied IDs and only those,
- * so we first check that old ID has been copied and that ntree is root tree of old ID,
- * then get root tree of new ID and remap its pointers to new ID... */
- if (id->newid && (&ntree->id != id)) {
- ntree = ntreeFromID(id->newid);
- BKE_libblock_relink_to_newid(&ntree->id);
- }
- } FOREACH_NODETREE_END;
-
- /* Relink datablock pointer properties */
- {
- IDP_RelinkProperty(scene->id.properties);
-
- FOREACH_SCENE_OBJECT_BEGIN(scene, ob)
- {
- if (!ID_IS_LINKED(ob)) {
- IDP_RelinkProperty(ob->id.properties);
- }
- }
- FOREACH_SCENE_OBJECT_END;
-
- if (scene->nodetree) {
- IDP_RelinkProperty(scene->nodetree->id.properties);
- for (bNode *node = scene->nodetree->nodes.first; node; node = node->next) {
- IDP_RelinkProperty(node->prop);
- }
- }
-
- if (scene->world) {
- IDP_RelinkProperty(scene->world->id.properties);
- }
-
- if (scene->clip) {
- IDP_RelinkProperty(scene->clip->id.properties);
- }
- }
- BKE_main_id_clear_newpoins(bmain);
- DEG_relations_tag_update(bmain);
+ single_object_users(bmain, scene, NULL, 0, copy_collections);
+
+ if (full) {
+ single_obdata_users(bmain, scene, NULL, NULL, 0);
+ single_object_action_users(bmain, scene, NULL, NULL, 0);
+ single_mat_users_expand(bmain);
+ }
+
+ /* Relink nodetrees' pointers that have been duplicated. */
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ /* This is a bit convoluted, we want to root ntree of copied IDs and only those,
+ * so we first check that old ID has been copied and that ntree is root tree of old ID,
+ * then get root tree of new ID and remap its pointers to new ID... */
+ if (id->newid && (&ntree->id != id)) {
+ ntree = ntreeFromID(id->newid);
+ BKE_libblock_relink_to_newid(&ntree->id);
+ }
+ }
+ FOREACH_NODETREE_END;
+
+ /* Relink datablock pointer properties */
+ {
+ IDP_RelinkProperty(scene->id.properties);
+
+ FOREACH_SCENE_OBJECT_BEGIN (scene, ob) {
+ if (!ID_IS_LINKED(ob)) {
+ IDP_RelinkProperty(ob->id.properties);
+ }
+ }
+ FOREACH_SCENE_OBJECT_END;
+
+ if (scene->nodetree) {
+ IDP_RelinkProperty(scene->nodetree->id.properties);
+ for (bNode *node = scene->nodetree->nodes.first; node; node = node->next) {
+ IDP_RelinkProperty(node->prop);
+ }
+ }
+
+ if (scene->world) {
+ IDP_RelinkProperty(scene->world->id.properties);
+ }
+
+ if (scene->clip) {
+ IDP_RelinkProperty(scene->clip->id.properties);
+ }
+ }
+ BKE_main_id_clear_newpoins(bmain);
+ DEG_relations_tag_update(bmain);
}
/******************************* Make Local ***********************************/
enum {
- MAKE_LOCAL_SELECT_OB = 1,
- MAKE_LOCAL_SELECT_OBDATA = 2,
- MAKE_LOCAL_SELECT_OBDATA_MATERIAL = 3,
- MAKE_LOCAL_ALL = 4,
+ MAKE_LOCAL_SELECT_OB = 1,
+ MAKE_LOCAL_SELECT_OBDATA = 2,
+ MAKE_LOCAL_SELECT_OBDATA_MATERIAL = 3,
+ MAKE_LOCAL_ALL = 4,
};
-static int tag_localizable_looper(
- void *UNUSED(user_data), ID *UNUSED(self_id), ID **id_pointer, const int UNUSED(cb_flag))
+static int tag_localizable_looper(void *UNUSED(user_data),
+ ID *UNUSED(self_id),
+ ID **id_pointer,
+ const int UNUSED(cb_flag))
{
- if (*id_pointer) {
- (*id_pointer)->tag &= ~LIB_TAG_DOIT;
- }
+ if (*id_pointer) {
+ (*id_pointer)->tag &= ~LIB_TAG_DOIT;
+ }
- return IDWALK_RET_NOP;
+ return IDWALK_RET_NOP;
}
static void tag_localizable_objects(bContext *C, const int mode)
{
- Main *bmain = CTX_data_main(C);
-
- BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
-
- /* Set LIB_TAG_DOIT flag for all selected objects, so next we can check whether
- * object is gonna to become local or not.
- */
- CTX_DATA_BEGIN (C, Object *, object, selected_objects)
- {
- object->id.tag |= LIB_TAG_DOIT;
-
- /* If data is also gonna to become local, mark data we're interested in
- * as gonna-to-be-local.
- */
- if (mode == MAKE_LOCAL_SELECT_OBDATA && object->data) {
- ID *data_id = (ID *) object->data;
- data_id->tag |= LIB_TAG_DOIT;
- }
- }
- CTX_DATA_END;
-
- /* Also forbid making objects local if other library objects are using
- * them for modifiers or constraints.
- */
- for (Object *object = bmain->objects.first; object; object = object->id.next) {
- if ((object->id.tag & LIB_TAG_DOIT) == 0) {
- BKE_library_foreach_ID_link(NULL, &object->id, tag_localizable_looper, NULL, IDWALK_READONLY);
- }
- if (object->data) {
- ID *data_id = (ID *) object->data;
- if ((data_id->tag & LIB_TAG_DOIT) == 0) {
- BKE_library_foreach_ID_link(NULL, data_id, tag_localizable_looper, NULL, IDWALK_READONLY);
- }
- }
- }
-
- /* TODO(sergey): Drivers targets? */
+ Main *bmain = CTX_data_main(C);
+
+ BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
+
+ /* Set LIB_TAG_DOIT flag for all selected objects, so next we can check whether
+ * object is gonna to become local or not.
+ */
+ CTX_DATA_BEGIN (C, Object *, object, selected_objects) {
+ object->id.tag |= LIB_TAG_DOIT;
+
+ /* If data is also gonna to become local, mark data we're interested in
+ * as gonna-to-be-local.
+ */
+ if (mode == MAKE_LOCAL_SELECT_OBDATA && object->data) {
+ ID *data_id = (ID *)object->data;
+ data_id->tag |= LIB_TAG_DOIT;
+ }
+ }
+ CTX_DATA_END;
+
+ /* Also forbid making objects local if other library objects are using
+ * them for modifiers or constraints.
+ */
+ for (Object *object = bmain->objects.first; object; object = object->id.next) {
+ if ((object->id.tag & LIB_TAG_DOIT) == 0) {
+ BKE_library_foreach_ID_link(
+ NULL, &object->id, tag_localizable_looper, NULL, IDWALK_READONLY);
+ }
+ if (object->data) {
+ ID *data_id = (ID *)object->data;
+ if ((data_id->tag & LIB_TAG_DOIT) == 0) {
+ BKE_library_foreach_ID_link(NULL, data_id, tag_localizable_looper, NULL, IDWALK_READONLY);
+ }
+ }
+ }
+
+ /* TODO(sergey): Drivers targets? */
}
/**
* Instance indirectly referenced zero user objects,
* otherwise they're lost on reload, see T40595.
*/
-static bool make_local_all__instance_indirect_unused(Main *bmain, ViewLayer *view_layer, Collection *collection)
+static bool make_local_all__instance_indirect_unused(Main *bmain,
+ ViewLayer *view_layer,
+ Collection *collection)
{
- Object *ob;
- bool changed = false;
+ Object *ob;
+ bool changed = false;
- for (ob = bmain->objects.first; ob; ob = ob->id.next) {
- if (ID_IS_LINKED(ob) && (ob->id.us == 0)) {
- Base *base;
+ for (ob = bmain->objects.first; ob; ob = ob->id.next) {
+ if (ID_IS_LINKED(ob) && (ob->id.us == 0)) {
+ Base *base;
- id_us_plus(&ob->id);
+ id_us_plus(&ob->id);
- BKE_collection_object_add(bmain, collection, ob);
- base = BKE_view_layer_base_find(view_layer, ob);
- base->flag |= BASE_SELECTED;
- BKE_scene_object_base_flag_sync_from_base(base);
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+ BKE_collection_object_add(bmain, collection, ob);
+ base = BKE_view_layer_base_find(view_layer, ob);
+ base->flag |= BASE_SELECTED;
+ BKE_scene_object_base_flag_sync_from_base(base);
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- changed = true;
- }
- }
+ changed = true;
+ }
+ }
- return changed;
+ return changed;
}
static void make_local_animdata_tag_strips(ListBase *strips)
{
- NlaStrip *strip;
+ NlaStrip *strip;
- for (strip = strips->first; strip; strip = strip->next) {
- if (strip->act) {
- strip->act->id.tag &= ~LIB_TAG_PRE_EXISTING;
- }
+ for (strip = strips->first; strip; strip = strip->next) {
+ if (strip->act) {
+ strip->act->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ }
- make_local_animdata_tag_strips(&strip->strips);
- }
+ make_local_animdata_tag_strips(&strip->strips);
+ }
}
/* Tag all actions used by given animdata to be made local. */
static void make_local_animdata_tag(AnimData *adt)
{
- if (adt) {
- /* Actions - Active and Temp */
- if (adt->action) {
- adt->action->id.tag &= ~LIB_TAG_PRE_EXISTING;
- }
- if (adt->tmpact) {
- adt->tmpact->id.tag &= ~LIB_TAG_PRE_EXISTING;
- }
-
- /* Drivers */
- /* TODO: need to handle the ID-targets too? */
-
- /* NLA Data */
- for (NlaTrack *nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
- make_local_animdata_tag_strips(&nlt->strips);
- }
- }
+ if (adt) {
+ /* Actions - Active and Temp */
+ if (adt->action) {
+ adt->action->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ }
+ if (adt->tmpact) {
+ adt->tmpact->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ }
+
+ /* Drivers */
+ /* TODO: need to handle the ID-targets too? */
+
+ /* NLA Data */
+ for (NlaTrack *nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
+ make_local_animdata_tag_strips(&nlt->strips);
+ }
+ }
}
static void make_local_material_tag(Material *ma)
{
- if (ma) {
- ma->id.tag &= ~LIB_TAG_PRE_EXISTING;
- make_local_animdata_tag(BKE_animdata_from_id(&ma->id));
+ if (ma) {
+ ma->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ make_local_animdata_tag(BKE_animdata_from_id(&ma->id));
- /* About nodetrees: root one is made local together with material, others we keep linked for now... */
- }
+ /* About nodetrees: root one is made local together with material, others we keep linked for now... */
+ }
}
static int make_local_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- ParticleSystem *psys;
- Material *ma, ***matarar;
- const int mode = RNA_enum_get(op->ptr, "type");
- int a;
-
- /* Note: we (ab)use LIB_TAG_PRE_EXISTING to cherry pick which ID to make local... */
- if (mode == MAKE_LOCAL_ALL) {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Collection *collection = CTX_data_collection(C);
-
- BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
-
- /* De-select so the user can differentiate newly instanced from existing objects. */
- BKE_view_layer_base_deselect_all(view_layer);
-
- if (make_local_all__instance_indirect_unused(bmain, view_layer, collection)) {
- BKE_report(op->reports, RPT_INFO, "Orphan library objects added to the current scene to avoid loss");
- }
- }
- else {
- BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
- tag_localizable_objects(C, mode);
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- if ((ob->id.tag & LIB_TAG_DOIT) == 0) {
- continue;
- }
-
- ob->id.tag &= ~LIB_TAG_PRE_EXISTING;
- make_local_animdata_tag(BKE_animdata_from_id(&ob->id));
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- psys->part->id.tag &= ~LIB_TAG_PRE_EXISTING;
- }
-
- if (mode == MAKE_LOCAL_SELECT_OBDATA_MATERIAL) {
- for (a = 0; a < ob->totcol; a++) {
- ma = ob->mat[a];
- if (ma) {
- make_local_material_tag(ma);
- }
- }
-
- matarar = (Material ***)give_matarar(ob);
- if (matarar) {
- for (a = 0; a < ob->totcol; a++) {
- ma = (*matarar)[a];
- if (ma) {
- make_local_material_tag(ma);
- }
- }
- }
- }
-
- if (ELEM(mode, MAKE_LOCAL_SELECT_OBDATA, MAKE_LOCAL_SELECT_OBDATA_MATERIAL) && ob->data != NULL) {
- ID *ob_data = ob->data;
- ob_data->tag &= ~LIB_TAG_PRE_EXISTING;
- make_local_animdata_tag(BKE_animdata_from_id(ob_data));
- }
- }
- CTX_DATA_END;
- }
-
- BKE_library_make_local(bmain, NULL, NULL, true, false); /* NULL is all libs */
-
- WM_event_add_notifier(C, NC_WINDOW, NULL);
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ ParticleSystem *psys;
+ Material *ma, ***matarar;
+ const int mode = RNA_enum_get(op->ptr, "type");
+ int a;
+
+ /* Note: we (ab)use LIB_TAG_PRE_EXISTING to cherry pick which ID to make local... */
+ if (mode == MAKE_LOCAL_ALL) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Collection *collection = CTX_data_collection(C);
+
+ BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
+
+ /* De-select so the user can differentiate newly instanced from existing objects. */
+ BKE_view_layer_base_deselect_all(view_layer);
+
+ if (make_local_all__instance_indirect_unused(bmain, view_layer, collection)) {
+ BKE_report(op->reports,
+ RPT_INFO,
+ "Orphan library objects added to the current scene to avoid loss");
+ }
+ }
+ else {
+ BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
+ tag_localizable_objects(C, mode);
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ if ((ob->id.tag & LIB_TAG_DOIT) == 0) {
+ continue;
+ }
+
+ ob->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ make_local_animdata_tag(BKE_animdata_from_id(&ob->id));
+ for (psys = ob->particlesystem.first; psys; psys = psys->next) {
+ psys->part->id.tag &= ~LIB_TAG_PRE_EXISTING;
+ }
+
+ if (mode == MAKE_LOCAL_SELECT_OBDATA_MATERIAL) {
+ for (a = 0; a < ob->totcol; a++) {
+ ma = ob->mat[a];
+ if (ma) {
+ make_local_material_tag(ma);
+ }
+ }
+
+ matarar = (Material ***)give_matarar(ob);
+ if (matarar) {
+ for (a = 0; a < ob->totcol; a++) {
+ ma = (*matarar)[a];
+ if (ma) {
+ make_local_material_tag(ma);
+ }
+ }
+ }
+ }
+
+ if (ELEM(mode, MAKE_LOCAL_SELECT_OBDATA, MAKE_LOCAL_SELECT_OBDATA_MATERIAL) &&
+ ob->data != NULL) {
+ ID *ob_data = ob->data;
+ ob_data->tag &= ~LIB_TAG_PRE_EXISTING;
+ make_local_animdata_tag(BKE_animdata_from_id(ob_data));
+ }
+ }
+ CTX_DATA_END;
+ }
+
+ BKE_library_make_local(bmain, NULL, NULL, true, false); /* NULL is all libs */
+
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_make_local(wmOperatorType *ot)
{
- static const EnumPropertyItem type_items[] = {
- {MAKE_LOCAL_SELECT_OB, "SELECT_OBJECT", 0, "Selected Objects", ""},
- {MAKE_LOCAL_SELECT_OBDATA, "SELECT_OBDATA", 0, "Selected Objects and Data", ""},
- {MAKE_LOCAL_SELECT_OBDATA_MATERIAL, "SELECT_OBDATA_MATERIAL", 0, "Selected Objects, Data and Materials", ""},
- {MAKE_LOCAL_ALL, "ALL", 0, "All", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Make Local";
- ot->description = "Make library linked data-blocks local to this file";
- ot->idname = "OBJECT_OT_make_local";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = make_local_exec;
- ot->poll = ED_operator_objectmode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
+ static const EnumPropertyItem type_items[] = {
+ {MAKE_LOCAL_SELECT_OB, "SELECT_OBJECT", 0, "Selected Objects", ""},
+ {MAKE_LOCAL_SELECT_OBDATA, "SELECT_OBDATA", 0, "Selected Objects and Data", ""},
+ {MAKE_LOCAL_SELECT_OBDATA_MATERIAL,
+ "SELECT_OBDATA_MATERIAL",
+ 0,
+ "Selected Objects, Data and Materials",
+ ""},
+ {MAKE_LOCAL_ALL, "ALL", 0, "All", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Make Local";
+ ot->description = "Make library linked data-blocks local to this file";
+ ot->idname = "OBJECT_OT_make_local";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = make_local_exec;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
}
-
static void make_override_static_tag_object(Object *obact, Object *ob)
{
- if (ob == obact) {
- return;
- }
-
- if (!ID_IS_LINKED(ob)) {
- return;
- }
-
- /* Note: all this is very case-by-case bad handling, ultimately we'll want a real full
- * 'automatic', generic handling of all this,
- * will probably require adding some override-aware stuff to library_query code... */
-
- if (obact->type == OB_ARMATURE && ob->modifiers.first != NULL) {
- for (ModifierData *md = ob->modifiers.first; md != NULL; md = md->next) {
- if (md->type == eModifierType_Armature) {
- ArmatureModifierData *amd = (ArmatureModifierData *)md;
- if (amd->object == obact) {
- ob->id.tag |= LIB_TAG_DOIT;
- break;
- }
- }
- }
- }
- else if (ob->parent == obact) {
- ob->id.tag |= LIB_TAG_DOIT;
- }
-
- if (ob->id.tag & LIB_TAG_DOIT) {
- printf("Indirectly overriding %s for %s\n", ob->id.name, obact->id.name);
- }
+ if (ob == obact) {
+ return;
+ }
+
+ if (!ID_IS_LINKED(ob)) {
+ return;
+ }
+
+ /* Note: all this is very case-by-case bad handling, ultimately we'll want a real full
+ * 'automatic', generic handling of all this,
+ * will probably require adding some override-aware stuff to library_query code... */
+
+ if (obact->type == OB_ARMATURE && ob->modifiers.first != NULL) {
+ for (ModifierData *md = ob->modifiers.first; md != NULL; md = md->next) {
+ if (md->type == eModifierType_Armature) {
+ ArmatureModifierData *amd = (ArmatureModifierData *)md;
+ if (amd->object == obact) {
+ ob->id.tag |= LIB_TAG_DOIT;
+ break;
+ }
+ }
+ }
+ }
+ else if (ob->parent == obact) {
+ ob->id.tag |= LIB_TAG_DOIT;
+ }
+
+ if (ob->id.tag & LIB_TAG_DOIT) {
+ printf("Indirectly overriding %s for %s\n", ob->id.name, obact->id.name);
+ }
}
static void make_override_static_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_static_tag_collections(coll_child->collection);
- }
+ collection->id.tag |= LIB_TAG_DOIT;
+ for (CollectionChild *coll_child = collection->children.first; coll_child != NULL;
+ coll_child = coll_child->next) {
+ make_override_static_tag_collections(coll_child->collection);
+ }
}
/* Set the object to override. */
static int make_override_static_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Scene *scene = CTX_data_scene(C);
- Object *obact = ED_object_active_context(C);
-
- /* Sanity checks. */
- if (!scene || ID_IS_LINKED(scene) || !obact) {
- return OPERATOR_CANCELLED;
- }
-
- /* Get object to work on - use a menu if we need to... */
- if (!ID_IS_LINKED(obact) && obact->instance_collection != NULL && ID_IS_LINKED(obact->instance_collection)) {
- /* Gives menu with list of objects in group. */
- WM_enum_search_invoke(C, op, event);
- return OPERATOR_CANCELLED;
- }
- else if (ID_IS_LINKED(obact)) {
- uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("OK?"), ICON_QUESTION);
- uiLayout *layout = UI_popup_menu_layout(pup);
-
- /* Create operator menu item with relevant properties filled in. */
- PointerRNA opptr_dummy;
- uiItemFullO_ptr(layout, op->type, op->type->name, ICON_NONE, NULL,
- WM_OP_EXEC_REGION_WIN, 0, &opptr_dummy);
-
- /* Present the menu and be done... */
- UI_popup_menu_end(C, pup);
-
- /* This invoke just calls another instance of this operator... */
- return OPERATOR_INTERFACE;
- }
- else {
- /* Error.. cannot continue. */
- BKE_report(op->reports, RPT_ERROR, "Can only make static override for a referenced object or collection");
- return OPERATOR_CANCELLED;
- }
-
+ Scene *scene = CTX_data_scene(C);
+ Object *obact = ED_object_active_context(C);
+
+ /* Sanity checks. */
+ if (!scene || ID_IS_LINKED(scene) || !obact) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Get object to work on - use a menu if we need to... */
+ if (!ID_IS_LINKED(obact) && obact->instance_collection != NULL &&
+ ID_IS_LINKED(obact->instance_collection)) {
+ /* Gives menu with list of objects in group. */
+ WM_enum_search_invoke(C, op, event);
+ return OPERATOR_CANCELLED;
+ }
+ else if (ID_IS_LINKED(obact)) {
+ uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("OK?"), ICON_QUESTION);
+ uiLayout *layout = UI_popup_menu_layout(pup);
+
+ /* Create operator menu item with relevant properties filled in. */
+ PointerRNA opptr_dummy;
+ uiItemFullO_ptr(
+ layout, op->type, op->type->name, ICON_NONE, NULL, WM_OP_EXEC_REGION_WIN, 0, &opptr_dummy);
+
+ /* Present the menu and be done... */
+ UI_popup_menu_end(C, pup);
+
+ /* This invoke just calls another instance of this operator... */
+ return OPERATOR_INTERFACE;
+ }
+ else {
+ /* Error.. cannot continue. */
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Can only make static override for a referenced object or collection");
+ return OPERATOR_CANCELLED;
+ }
}
static int make_override_static_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *obact = CTX_data_active_object(C);
-
- bool success = false;
-
- if (!ID_IS_LINKED(obact) && obact->instance_collection != NULL && ID_IS_LINKED(obact->instance_collection)) {
- Object *obcollection = obact;
- Collection *collection = obcollection->instance_collection;
-
- const ListBase dup_collection_objects = BKE_collection_object_cache_get(collection);
- Base *base = BLI_findlink(&dup_collection_objects, RNA_enum_get(op->ptr, "object"));
- obact = base->object;
-
- /* First, we make a static override of the linked collection itself, and all its children. */
- make_override_static_tag_collections(collection);
-
- /* Then, we make static 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;
- }
- }
- }
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
-
- success = BKE_override_static_create_from_tag(bmain);
-
- /* Instantiate our newly overridden objects in scene, if not yet done. */
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Collection *new_collection = (Collection *)collection->id.newid;
-
- BKE_collection_child_add(bmain, scene->master_collection, new_collection);
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(new_collection, new_ob)
- {
- if (new_ob != NULL && new_ob->id.override_static != 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);
- }
- /* parent to 'collection' empty */
- if (new_ob->parent == NULL) {
- new_ob->parent = obcollection;
- }
- if (new_ob == (Object *)obact->id.newid) {
- /* TODO: is setting active needed? */
- BKE_view_layer_base_select_and_set_active(view_layer, base);
- }
- else {
- /* Disable auto-override tags for non-active objects, will help with performaces... */
- new_ob->id.override_static->flag &= ~STATICOVERRIDE_AUTO;
- }
- /* We still want to store all objects' current override status (i.e. change of parent). */
- BKE_override_static_operations_create(bmain, &new_ob->id, true);
- }
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
-
- /* obcollection is no more duplicollection-ing,
- * it merely parents whole collection of overriding instantiated objects. */
- obcollection->instance_collection = NULL;
-
- /* 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_listbase(&bmain->objects, LIB_TAG_DOIT, false);
- }
- /* 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_static_tag_object(obact, ob);
- }
-
- success = BKE_override_static_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_listbase(&bmain->objects, LIB_TAG_DOIT, false);
- }
- /* TODO: probably more cases where we want to do automated smart things in the future! */
- else {
- success = (BKE_override_static_create_from_id(bmain, &obact->id) != NULL);
- }
-
- WM_event_add_notifier(C, NC_WINDOW, NULL);
-
- return success ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ Main *bmain = CTX_data_main(C);
+ Object *obact = CTX_data_active_object(C);
+
+ bool success = false;
+
+ if (!ID_IS_LINKED(obact) && obact->instance_collection != NULL &&
+ ID_IS_LINKED(obact->instance_collection)) {
+ Object *obcollection = obact;
+ Collection *collection = obcollection->instance_collection;
+
+ const ListBase dup_collection_objects = BKE_collection_object_cache_get(collection);
+ Base *base = BLI_findlink(&dup_collection_objects, RNA_enum_get(op->ptr, "object"));
+ obact = base->object;
+
+ /* First, we make a static override of the linked collection itself, and all its children. */
+ make_override_static_tag_collections(collection);
+
+ /* Then, we make static 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;
+ }
+ }
+ }
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+
+ success = BKE_override_static_create_from_tag(bmain);
+
+ /* Instantiate our newly overridden objects in scene, if not yet done. */
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Collection *new_collection = (Collection *)collection->id.newid;
+
+ BKE_collection_child_add(bmain, scene->master_collection, new_collection);
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (new_collection, new_ob) {
+ if (new_ob != NULL && new_ob->id.override_static != 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);
+ }
+ /* parent to 'collection' empty */
+ if (new_ob->parent == NULL) {
+ new_ob->parent = obcollection;
+ }
+ if (new_ob == (Object *)obact->id.newid) {
+ /* TODO: is setting active needed? */
+ BKE_view_layer_base_select_and_set_active(view_layer, base);
+ }
+ else {
+ /* Disable auto-override tags for non-active objects, will help with performaces... */
+ new_ob->id.override_static->flag &= ~STATICOVERRIDE_AUTO;
+ }
+ /* We still want to store all objects' current override status (i.e. change of parent). */
+ BKE_override_static_operations_create(bmain, &new_ob->id, true);
+ }
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+
+ /* obcollection is no more duplicollection-ing,
+ * it merely parents whole collection of overriding instantiated objects. */
+ obcollection->instance_collection = NULL;
+
+ /* 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_listbase(&bmain->objects, LIB_TAG_DOIT, false);
+ }
+ /* 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_static_tag_object(obact, ob);
+ }
+
+ success = BKE_override_static_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_listbase(&bmain->objects, LIB_TAG_DOIT, false);
+ }
+ /* TODO: probably more cases where we want to do automated smart things in the future! */
+ else {
+ success = (BKE_override_static_create_from_id(bmain, &obact->id) != NULL);
+ }
+
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+
+ return success ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
static bool make_override_static_poll(bContext *C)
{
- Object *obact = CTX_data_active_object(C);
+ Object *obact = CTX_data_active_object(C);
- /* Object must be directly linked to be overridable. */
- return (BKE_override_static_is_enabled() &&
- ED_operator_objectmode(C) && obact != NULL &&
- ((ID_IS_LINKED(obact) && obact->id.tag & LIB_TAG_EXTERN) ||
- (!ID_IS_LINKED(obact) && obact->instance_collection != NULL && ID_IS_LINKED(obact->instance_collection))));
+ /* Object must be directly linked to be overridable. */
+ return (BKE_override_static_is_enabled() && ED_operator_objectmode(C) && obact != NULL &&
+ ((ID_IS_LINKED(obact) && obact->id.tag & LIB_TAG_EXTERN) ||
+ (!ID_IS_LINKED(obact) && obact->instance_collection != NULL &&
+ ID_IS_LINKED(obact->instance_collection))));
}
void OBJECT_OT_make_override_static(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Make Static Override";
- ot->description = "Make local override of this library linked data-block";
- ot->idname = "OBJECT_OT_make_override_static";
-
- /* api callbacks */
- ot->invoke = make_override_static_invoke;
- ot->exec = make_override_static_exec;
- ot->poll = make_override_static_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- PropertyRNA *prop;
- prop = RNA_def_enum(ot->srna, "object", DummyRNA_DEFAULT_items, 0, "Override Object",
- "Name of lib-linked/collection object to make an override from");
- RNA_def_enum_funcs(prop, proxy_collection_object_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ /* identifiers */
+ ot->name = "Make Static Override";
+ ot->description = "Make local override of this library linked data-block";
+ ot->idname = "OBJECT_OT_make_override_static";
+
+ /* api callbacks */
+ ot->invoke = make_override_static_invoke;
+ ot->exec = make_override_static_exec;
+ ot->poll = make_override_static_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ PropertyRNA *prop;
+ prop = RNA_def_enum(ot->srna,
+ "object",
+ DummyRNA_DEFAULT_items,
+ 0,
+ "Override Object",
+ "Name of lib-linked/collection object to make an override from");
+ RNA_def_enum_funcs(prop, proxy_collection_object_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
enum {
- MAKE_SINGLE_USER_ALL = 1,
- MAKE_SINGLE_USER_SELECTED = 2,
+ MAKE_SINGLE_USER_ALL = 1,
+ MAKE_SINGLE_USER_SELECTED = 2,
};
static int make_single_user_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C); /* ok if this is NULL */
- const int flag = (RNA_enum_get(op->ptr, "type") == MAKE_SINGLE_USER_SELECTED) ? SELECT : 0;
- const bool copy_collections = false;
- bool update_deps = false;
-
- if (RNA_boolean_get(op->ptr, "object")) {
- if (flag == SELECT) {
- BKE_view_layer_selected_objects_tag(view_layer, OB_DONE);
- single_object_users(bmain, scene, v3d, OB_DONE, copy_collections);
- }
- else {
- single_object_users(bmain, scene, v3d, 0, copy_collections);
- }
-
- /* needed since object relationships may have changed */
- update_deps = true;
- }
-
- if (RNA_boolean_get(op->ptr, "obdata")) {
- single_obdata_users(bmain, scene, view_layer, v3d, flag);
- }
-
- if (RNA_boolean_get(op->ptr, "material")) {
- single_mat_users(bmain, scene, view_layer, v3d, flag);
- }
-
- if (RNA_boolean_get(op->ptr, "animation")) {
- single_object_action_users(bmain, scene, view_layer, v3d, flag);
- }
-
- BKE_main_id_clear_newpoins(bmain);
-
- WM_event_add_notifier(C, NC_WINDOW, NULL);
-
- if (update_deps) {
- DEG_relations_tag_update(bmain);
- }
-
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C); /* ok if this is NULL */
+ const int flag = (RNA_enum_get(op->ptr, "type") == MAKE_SINGLE_USER_SELECTED) ? SELECT : 0;
+ const bool copy_collections = false;
+ bool update_deps = false;
+
+ if (RNA_boolean_get(op->ptr, "object")) {
+ if (flag == SELECT) {
+ BKE_view_layer_selected_objects_tag(view_layer, OB_DONE);
+ single_object_users(bmain, scene, v3d, OB_DONE, copy_collections);
+ }
+ else {
+ single_object_users(bmain, scene, v3d, 0, copy_collections);
+ }
+
+ /* needed since object relationships may have changed */
+ update_deps = true;
+ }
+
+ if (RNA_boolean_get(op->ptr, "obdata")) {
+ single_obdata_users(bmain, scene, view_layer, v3d, flag);
+ }
+
+ if (RNA_boolean_get(op->ptr, "material")) {
+ single_mat_users(bmain, scene, view_layer, v3d, flag);
+ }
+
+ if (RNA_boolean_get(op->ptr, "animation")) {
+ single_object_action_users(bmain, scene, view_layer, v3d, flag);
+ }
+
+ BKE_main_id_clear_newpoins(bmain);
+
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+
+ if (update_deps) {
+ DEG_relations_tag_update(bmain);
+ }
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_make_single_user(wmOperatorType *ot)
{
- static const EnumPropertyItem type_items[] = {
- {MAKE_SINGLE_USER_SELECTED, "SELECTED_OBJECTS", 0, "Selected Objects", ""},
- {MAKE_SINGLE_USER_ALL, "ALL", 0, "All", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Make Single User";
- ot->description = "Make linked data local to each object";
- ot->idname = "OBJECT_OT_make_single_user";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = make_single_user_exec;
- ot->poll = ED_operator_objectmode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", type_items, MAKE_SINGLE_USER_SELECTED, "Type", "");
-
- RNA_def_boolean(ot->srna, "object", 0, "Object", "Make single user objects");
- RNA_def_boolean(ot->srna, "obdata", 0, "Object Data", "Make single user object data");
- RNA_def_boolean(ot->srna, "material", 0, "Materials", "Make materials local to each data-block");
- RNA_def_boolean(ot->srna, "animation", 0, "Object Animation", "Make animation data local to each object");
+ static const EnumPropertyItem type_items[] = {
+ {MAKE_SINGLE_USER_SELECTED, "SELECTED_OBJECTS", 0, "Selected Objects", ""},
+ {MAKE_SINGLE_USER_ALL, "ALL", 0, "All", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Make Single User";
+ ot->description = "Make linked data local to each object";
+ ot->idname = "OBJECT_OT_make_single_user";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = make_single_user_exec;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", type_items, MAKE_SINGLE_USER_SELECTED, "Type", "");
+
+ RNA_def_boolean(ot->srna, "object", 0, "Object", "Make single user objects");
+ RNA_def_boolean(ot->srna, "obdata", 0, "Object Data", "Make single user object data");
+ RNA_def_boolean(ot->srna, "material", 0, "Materials", "Make materials local to each data-block");
+ RNA_def_boolean(
+ ot->srna, "animation", 0, "Object Animation", "Make animation data local to each object");
}
static int drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Main *bmain = CTX_data_main(C);
- Base *base = ED_view3d_give_base_under_cursor(C, event->mval);
- Material *ma;
- char name[MAX_ID_NAME - 2];
+ Main *bmain = CTX_data_main(C);
+ Base *base = ED_view3d_give_base_under_cursor(C, event->mval);
+ Material *ma;
+ char name[MAX_ID_NAME - 2];
- RNA_string_get(op->ptr, "name", name);
- ma = (Material *)BKE_libblock_find_name(bmain, ID_MA, name);
- if (base == NULL || ma == NULL)
- return OPERATOR_CANCELLED;
+ RNA_string_get(op->ptr, "name", name);
+ ma = (Material *)BKE_libblock_find_name(bmain, ID_MA, name);
+ if (base == NULL || ma == NULL)
+ return OPERATOR_CANCELLED;
- assign_material(CTX_data_main(C), base->object, ma, 1, BKE_MAT_ASSIGN_USERPREF);
+ assign_material(CTX_data_main(C), base->object, ma, 1, BKE_MAT_ASSIGN_USERPREF);
- DEG_id_tag_update(&base->object->id, ID_RECALC_TRANSFORM);
+ DEG_id_tag_update(&base->object->id, ID_RECALC_TRANSFORM);
- WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, base->object);
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C));
- WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma);
+ WM_event_add_notifier(C, NC_OBJECT | ND_OB_SHADING, base->object);
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C));
+ WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/* used for dropbox */
/* assigns to object under cursor, only first material slot */
void OBJECT_OT_drop_named_material(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Drop Named Material on Object";
- ot->idname = "OBJECT_OT_drop_named_material";
+ /* identifiers */
+ ot->name = "Drop Named Material on Object";
+ ot->idname = "OBJECT_OT_drop_named_material";
- /* api callbacks */
- ot->invoke = drop_named_material_invoke;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->invoke = drop_named_material_invoke;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL;
- /* properties */
- RNA_def_string(ot->srna, "name", "Material", MAX_ID_NAME - 2, "Name", "Material name to assign");
+ /* properties */
+ RNA_def_string(ot->srna, "name", "Material", MAX_ID_NAME - 2, "Name", "Material name to assign");
}
static int object_unlink_data_exec(bContext *C, wmOperator *op)
{
- ID *id;
- PropertyPointerRNA pprop;
+ ID *id;
+ PropertyPointerRNA pprop;
- UI_context_active_but_prop_get_templateID(C, &pprop.ptr, &pprop.prop);
+ UI_context_active_but_prop_get_templateID(C, &pprop.ptr, &pprop.prop);
- if (pprop.prop == NULL) {
- BKE_report(op->reports, RPT_ERROR, "Incorrect context for running object data unlink");
- return OPERATOR_CANCELLED;
- }
+ if (pprop.prop == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Incorrect context for running object data unlink");
+ return OPERATOR_CANCELLED;
+ }
- id = pprop.ptr.id.data;
+ id = pprop.ptr.id.data;
- if (GS(id->name) == ID_OB) {
- Object *ob = (Object *)id;
- if (ob->data) {
- ID *id_data = ob->data;
+ if (GS(id->name) == ID_OB) {
+ Object *ob = (Object *)id;
+ if (ob->data) {
+ ID *id_data = ob->data;
- if (GS(id_data->name) == ID_IM) {
- id_us_min(id_data);
- ob->data = NULL;
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Can't unlink this object data");
- return OPERATOR_CANCELLED;
- }
- }
- }
+ if (GS(id_data->name) == ID_IM) {
+ id_us_min(id_data);
+ ob->data = NULL;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Can't unlink this object data");
+ return OPERATOR_CANCELLED;
+ }
+ }
+ }
- RNA_property_update(C, &pprop.ptr, pprop.prop);
+ RNA_property_update(C, &pprop.ptr, pprop.prop);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
/**
@@ -2583,13 +2655,13 @@ static int object_unlink_data_exec(bContext *C, wmOperator *op)
*/
void OBJECT_OT_unlink_data(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Unlink";
- ot->idname = "OBJECT_OT_unlink_data";
+ /* identifiers */
+ ot->name = "Unlink";
+ ot->idname = "OBJECT_OT_unlink_data";
- /* api callbacks */
- ot->exec = object_unlink_data_exec;
+ /* api callbacks */
+ ot->exec = object_unlink_data_exec;
- /* flags */
- ot->flag = OPTYPE_INTERNAL;
+ /* flags */
+ ot->flag = OPTYPE_INTERNAL;
}
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index 919055aa668..06bd4d76973 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -96,26 +96,26 @@
*/
void ED_object_base_select(Base *base, eObjectSelect_Mode mode)
{
- if (mode == BA_INVERT) {
- mode = (base->flag & BASE_SELECTED) != 0 ? BA_DESELECT : BA_SELECT;
- }
-
- if (base) {
- switch (mode) {
- case BA_SELECT:
- if ((base->flag & BASE_SELECTABLE) != 0) {
- base->flag |= BASE_SELECTED;
- }
- break;
- case BA_DESELECT:
- base->flag &= ~BASE_SELECTED;
- break;
- case BA_INVERT:
- /* Never happens. */
- break;
- }
- BKE_scene_object_base_flag_sync_from_base(base);
- }
+ if (mode == BA_INVERT) {
+ mode = (base->flag & BASE_SELECTED) != 0 ? BA_DESELECT : BA_SELECT;
+ }
+
+ if (base) {
+ switch (mode) {
+ case BA_SELECT:
+ if ((base->flag & BASE_SELECTABLE) != 0) {
+ base->flag |= BASE_SELECTED;
+ }
+ break;
+ case BA_DESELECT:
+ base->flag &= ~BASE_SELECTED;
+ break;
+ case BA_INVERT:
+ /* Never happens. */
+ break;
+ }
+ BKE_scene_object_base_flag_sync_from_base(base);
+ }
}
/**
@@ -123,75 +123,77 @@ void ED_object_base_select(Base *base, eObjectSelect_Mode mode)
*/
void ED_object_base_activate(bContext *C, Base *base)
{
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- view_layer->basact = base;
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
- WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active);
- DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_SELECT);
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ view_layer->basact = base;
+
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+ WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active);
+ DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_SELECT);
}
-bool ED_object_base_deselect_all_ex(ViewLayer *view_layer, View3D *v3d, int action, bool *r_any_visible)
+bool ED_object_base_deselect_all_ex(ViewLayer *view_layer,
+ View3D *v3d,
+ int action,
+ bool *r_any_visible)
{
- if (action == SEL_TOGGLE) {
- action = SEL_SELECT;
- FOREACH_VISIBLE_BASE_BEGIN(view_layer, v3d, base) {
- if (v3d && ((v3d->object_type_exclude_select & (1 << base->object->type)) != 0)) {
- continue;
- }
- if ((base->flag & BASE_SELECTED) != 0) {
- action = SEL_DESELECT;
- break;
- }
- }
- FOREACH_VISIBLE_BASE_END;
- }
-
- bool any_visible = false;
- bool changed = false;
- FOREACH_VISIBLE_BASE_BEGIN(view_layer, v3d, base) {
- if (v3d && ((v3d->object_type_exclude_select & (1 << base->object->type)) != 0)) {
- continue;
- }
- switch (action) {
- case SEL_SELECT:
- if ((base->flag & BASE_SELECTED) == 0) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- break;
- case SEL_DESELECT:
- if ((base->flag & BASE_SELECTED) != 0) {
- ED_object_base_select(base, BA_DESELECT);
- changed = true;
- }
- break;
- case SEL_INVERT:
- if ((base->flag & BASE_SELECTED) != 0) {
- ED_object_base_select(base, BA_DESELECT);
- changed = true;
- }
- else {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- break;
- }
- any_visible = true;
- }
- FOREACH_VISIBLE_BASE_END;
- if (r_any_visible) {
- *r_any_visible = any_visible;
- }
- return changed;
+ if (action == SEL_TOGGLE) {
+ action = SEL_SELECT;
+ FOREACH_VISIBLE_BASE_BEGIN (view_layer, v3d, base) {
+ if (v3d && ((v3d->object_type_exclude_select & (1 << base->object->type)) != 0)) {
+ continue;
+ }
+ if ((base->flag & BASE_SELECTED) != 0) {
+ action = SEL_DESELECT;
+ break;
+ }
+ }
+ FOREACH_VISIBLE_BASE_END;
+ }
+
+ bool any_visible = false;
+ bool changed = false;
+ FOREACH_VISIBLE_BASE_BEGIN (view_layer, v3d, base) {
+ if (v3d && ((v3d->object_type_exclude_select & (1 << base->object->type)) != 0)) {
+ continue;
+ }
+ switch (action) {
+ case SEL_SELECT:
+ if ((base->flag & BASE_SELECTED) == 0) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ break;
+ case SEL_DESELECT:
+ if ((base->flag & BASE_SELECTED) != 0) {
+ ED_object_base_select(base, BA_DESELECT);
+ changed = true;
+ }
+ break;
+ case SEL_INVERT:
+ if ((base->flag & BASE_SELECTED) != 0) {
+ ED_object_base_select(base, BA_DESELECT);
+ changed = true;
+ }
+ else {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ break;
+ }
+ any_visible = true;
+ }
+ FOREACH_VISIBLE_BASE_END;
+ if (r_any_visible) {
+ *r_any_visible = any_visible;
+ }
+ return changed;
}
-
bool ED_object_base_deselect_all(ViewLayer *view_layer, View3D *v3d, int action)
{
- return ED_object_base_deselect_all_ex(view_layer, v3d, action, NULL);
+ return ED_object_base_deselect_all_ex(view_layer, v3d, action, NULL);
}
/** \} */
@@ -202,17 +204,17 @@ bool ED_object_base_deselect_all(ViewLayer *view_layer, View3D *v3d, int action)
static int get_base_select_priority(Base *base)
{
- if (base->flag & BASE_VISIBLE) {
- if (base->flag & BASE_SELECTABLE) {
- return 3;
- }
- else {
- return 2;
- }
- }
- else {
- return 1;
- }
+ if (base->flag & BASE_VISIBLE) {
+ if (base->flag & BASE_SELECTABLE) {
+ return 3;
+ }
+ else {
+ return 2;
+ }
+ }
+ else {
+ return 1;
+ }
}
/**
@@ -221,36 +223,36 @@ static int get_base_select_priority(Base *base)
*/
Base *ED_object_find_first_by_data_id(ViewLayer *view_layer, ID *id)
{
- BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name)));
-
- /* Try active object. */
- Base *basact = view_layer->basact;
-
- if (basact && basact->object && basact->object->data == id) {
- return basact;
- }
-
- /* Try all objects. */
- Base *base_best = NULL;
- int priority_best = 0;
-
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (base->object && base->object->data == id) {
- if (base->flag & BASE_SELECTED) {
- return base;
- }
- else {
- int priority_test = get_base_select_priority(base);
-
- if (priority_test > priority_best) {
- priority_best = priority_test;
- base_best = base;
- }
- }
- }
- }
-
- return base_best;
+ BLI_assert(OB_DATA_SUPPORT_ID(GS(id->name)));
+
+ /* Try active object. */
+ Base *basact = view_layer->basact;
+
+ if (basact && basact->object && basact->object->data == id) {
+ return basact;
+ }
+
+ /* Try all objects. */
+ Base *base_best = NULL;
+ int priority_best = 0;
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->object && base->object->data == id) {
+ if (base->flag & BASE_SELECTED) {
+ return base;
+ }
+ else {
+ int priority_test = get_base_select_priority(base);
+
+ if (priority_test > priority_best) {
+ priority_best = priority_test;
+ base_best = base;
+ }
+ }
+ }
+ }
+
+ return base_best;
}
/**
@@ -259,36 +261,35 @@ Base *ED_object_find_first_by_data_id(ViewLayer *view_layer, ID *id)
*
* \returns false if not found in current view layer
*/
-bool ED_object_jump_to_object(
- bContext *C, Object *ob, const bool UNUSED(reveal_hidden))
+bool ED_object_jump_to_object(bContext *C, Object *ob, const bool UNUSED(reveal_hidden))
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- Base *base = BKE_view_layer_base_find(view_layer, ob);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
- if (base == NULL) {
- return false;
- }
+ if (base == NULL) {
+ return false;
+ }
- /* TODO, use 'reveal_hidden', as is done with bones. */
+ /* TODO, use 'reveal_hidden', as is done with bones. */
- if (view_layer->basact != base || !(base->flag & BASE_SELECTED)) {
- /* Select if not selected. */
- if (!(base->flag & BASE_SELECTED)) {
- ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT);
+ if (view_layer->basact != base || !(base->flag & BASE_SELECTED)) {
+ /* Select if not selected. */
+ if (!(base->flag & BASE_SELECTED)) {
+ ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT);
- if (base->flag & BASE_VISIBLE) {
- ED_object_base_select(base, BA_SELECT);
- }
+ if (base->flag & BASE_VISIBLE) {
+ ED_object_base_select(base, BA_SELECT);
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
- }
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+ }
- /* Make active if not active. */
- ED_object_base_activate(C, base);
- }
+ /* Make active if not active. */
+ ED_object_base_activate(C, base);
+ }
- return true;
+ return true;
}
/**
@@ -298,79 +299,80 @@ bool ED_object_jump_to_object(
*
* \returns false if object not in layer, bone not found, or other error
*/
-bool ED_object_jump_to_bone(
- bContext *C, Object *ob, const char *bone_name,
- const bool reveal_hidden)
+bool ED_object_jump_to_bone(bContext *C,
+ Object *ob,
+ const char *bone_name,
+ const bool reveal_hidden)
{
- /* Verify it's a valid armature object. */
- if (ob == NULL || ob->type != OB_ARMATURE) {
- return false;
- }
-
- bArmature *arm = ob->data;
-
- /* Activate the armature object. */
- if (!ED_object_jump_to_object(C, ob, reveal_hidden)) {
- return false;
- }
-
- /* Switch to pose mode from object mode. */
- if (!ELEM(ob->mode, OB_MODE_EDIT, OB_MODE_POSE)) {
- ED_object_mode_set(C, OB_MODE_POSE);
- }
-
- if (ob->mode == OB_MODE_EDIT && arm->edbo != NULL) {
- /* In Edit mode select and activate the target Edit-Bone. */
- EditBone *ebone = ED_armature_ebone_find_name(arm->edbo, bone_name);
- if (ebone != NULL) {
- if (reveal_hidden) {
- /* Unhide the bone. */
- ebone->flag &= ~BONE_HIDDEN_A;
-
- if ((arm->layer & ebone->layer) == 0) {
- arm->layer |= 1U << bitscan_forward_uint(ebone->layer);
- }
- }
-
- /* Select it. */
- ED_armature_edit_deselect_all(ob);
-
- if (EBONE_SELECTABLE(arm, ebone)) {
- ED_armature_ebone_select_set(ebone, true);
- ED_armature_edit_sync_selection(arm->edbo);
- }
-
- arm->act_edbone = ebone;
-
- ED_pose_bone_select_tag_update(ob);
- return true;
- }
- }
- else if (ob->mode == OB_MODE_POSE && ob->pose != NULL) {
- /* In Pose mode select and activate the target Bone/Pose-Channel. */
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
- if (pchan != NULL) {
- if (reveal_hidden) {
- /* Unhide the bone. */
- pchan->bone->flag &= ~BONE_HIDDEN_P;
-
- if ((arm->layer & pchan->bone->layer) == 0) {
- arm->layer |= 1U << bitscan_forward_uint(pchan->bone->layer);
- }
- }
-
- /* Select it. */
- ED_pose_deselect_all(ob, SEL_DESELECT, true);
- ED_pose_bone_select(ob, pchan, true);
-
- arm->act_bone = pchan->bone;
-
- ED_pose_bone_select_tag_update(ob);
- return true;
- }
- }
-
- return false;
+ /* Verify it's a valid armature object. */
+ if (ob == NULL || ob->type != OB_ARMATURE) {
+ return false;
+ }
+
+ bArmature *arm = ob->data;
+
+ /* Activate the armature object. */
+ if (!ED_object_jump_to_object(C, ob, reveal_hidden)) {
+ return false;
+ }
+
+ /* Switch to pose mode from object mode. */
+ if (!ELEM(ob->mode, OB_MODE_EDIT, OB_MODE_POSE)) {
+ ED_object_mode_set(C, OB_MODE_POSE);
+ }
+
+ if (ob->mode == OB_MODE_EDIT && arm->edbo != NULL) {
+ /* In Edit mode select and activate the target Edit-Bone. */
+ EditBone *ebone = ED_armature_ebone_find_name(arm->edbo, bone_name);
+ if (ebone != NULL) {
+ if (reveal_hidden) {
+ /* Unhide the bone. */
+ ebone->flag &= ~BONE_HIDDEN_A;
+
+ if ((arm->layer & ebone->layer) == 0) {
+ arm->layer |= 1U << bitscan_forward_uint(ebone->layer);
+ }
+ }
+
+ /* Select it. */
+ ED_armature_edit_deselect_all(ob);
+
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ ED_armature_ebone_select_set(ebone, true);
+ ED_armature_edit_sync_selection(arm->edbo);
+ }
+
+ arm->act_edbone = ebone;
+
+ ED_pose_bone_select_tag_update(ob);
+ return true;
+ }
+ }
+ else if (ob->mode == OB_MODE_POSE && ob->pose != NULL) {
+ /* In Pose mode select and activate the target Bone/Pose-Channel. */
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
+ if (pchan != NULL) {
+ if (reveal_hidden) {
+ /* Unhide the bone. */
+ pchan->bone->flag &= ~BONE_HIDDEN_P;
+
+ if ((arm->layer & pchan->bone->layer) == 0) {
+ arm->layer |= 1U << bitscan_forward_uint(pchan->bone->layer);
+ }
+ }
+
+ /* Select it. */
+ ED_pose_deselect_all(ob, SEL_DESELECT, true);
+ ED_pose_bone_select(ob, pchan, true);
+
+ arm->act_bone = pchan->bone;
+
+ ED_pose_bone_select_tag_update(ob);
+ return true;
+ }
+ }
+
+ return false;
}
/** \} */
@@ -381,16 +383,16 @@ bool ED_object_jump_to_bone(
static bool objects_selectable_poll(bContext *C)
{
- /* we don't check for linked scenes here, selection is
- * still allowed then for inspection of scene */
- Object *obact = CTX_data_active_object(C);
+ /* we don't check for linked scenes here, selection is
+ * still allowed then for inspection of scene */
+ Object *obact = CTX_data_active_object(C);
- if (CTX_data_edit_object(C))
- return 0;
- if (obact && obact->mode)
- return 0;
+ if (CTX_data_edit_object(C))
+ return 0;
+ if (obact && obact->mode)
+ return 0;
- return 1;
+ return 1;
}
/** \} */
@@ -401,51 +403,54 @@ static bool objects_selectable_poll(bContext *C)
static int object_select_by_type_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- short obtype, extend;
-
- obtype = RNA_enum_get(op->ptr, "type");
- extend = RNA_boolean_get(op->ptr, "extend");
-
- if (extend == 0) {
- ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT);
- }
-
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (base->object->type == obtype) {
- ED_object_base_select(base, BA_SELECT);
- }
- }
- CTX_DATA_END;
-
- Scene *scene = CTX_data_scene(C);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
-
- return OPERATOR_FINISHED;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ short obtype, extend;
+
+ obtype = RNA_enum_get(op->ptr, "type");
+ extend = RNA_boolean_get(op->ptr, "extend");
+
+ if (extend == 0) {
+ ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT);
+ }
+
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
+ if (base->object->type == obtype) {
+ ED_object_base_select(base, BA_SELECT);
+ }
+ }
+ CTX_DATA_END;
+
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_select_by_type(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select By Type";
- ot->description = "Select all visible objects that are of a type";
- ot->idname = "OBJECT_OT_select_by_type";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_select_by_type_exec;
- ot->poll = objects_selectable_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_type_items, 1, "Type", "");
- RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_ID);
+ /* identifiers */
+ ot->name = "Select By Type";
+ ot->description = "Select all visible objects that are of a type";
+ ot->idname = "OBJECT_OT_select_by_type";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_select_by_type_exec;
+ ot->poll = objects_selectable_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "extend",
+ false,
+ "Extend",
+ "Extend selection instead of deselecting everything first");
+ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_type_items, 1, "Type", "");
+ RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_ID);
}
/** \} */
@@ -455,270 +460,273 @@ void OBJECT_OT_select_by_type(wmOperatorType *ot)
* \{ */
enum {
- OBJECT_SELECT_LINKED_IPO = 1,
- OBJECT_SELECT_LINKED_OBDATA,
- OBJECT_SELECT_LINKED_MATERIAL,
- OBJECT_SELECT_LINKED_DUPGROUP,
- OBJECT_SELECT_LINKED_PARTICLE,
- OBJECT_SELECT_LINKED_LIBRARY,
- OBJECT_SELECT_LINKED_LIBRARY_OBDATA,
+ OBJECT_SELECT_LINKED_IPO = 1,
+ OBJECT_SELECT_LINKED_OBDATA,
+ OBJECT_SELECT_LINKED_MATERIAL,
+ OBJECT_SELECT_LINKED_DUPGROUP,
+ OBJECT_SELECT_LINKED_PARTICLE,
+ OBJECT_SELECT_LINKED_LIBRARY,
+ OBJECT_SELECT_LINKED_LIBRARY_OBDATA,
};
static const EnumPropertyItem prop_select_linked_types[] = {
- //{OBJECT_SELECT_LINKED_IPO, "IPO", 0, "Object IPO", ""}, // XXX deprecated animation system stuff...
- {OBJECT_SELECT_LINKED_OBDATA, "OBDATA", 0, "Object Data", ""},
- {OBJECT_SELECT_LINKED_MATERIAL, "MATERIAL", 0, "Material", ""},
- {OBJECT_SELECT_LINKED_DUPGROUP, "DUPGROUP", 0, "Instanced Collection", ""},
- {OBJECT_SELECT_LINKED_PARTICLE, "PARTICLE", 0, "Particle System", ""},
- {OBJECT_SELECT_LINKED_LIBRARY, "LIBRARY", 0, "Library", ""},
- {OBJECT_SELECT_LINKED_LIBRARY_OBDATA, "LIBRARY_OBDATA", 0, "Library (Object Data)", ""},
- {0, NULL, 0, NULL, NULL},
+ //{OBJECT_SELECT_LINKED_IPO, "IPO", 0, "Object IPO", ""}, // XXX deprecated animation system stuff...
+ {OBJECT_SELECT_LINKED_OBDATA, "OBDATA", 0, "Object Data", ""},
+ {OBJECT_SELECT_LINKED_MATERIAL, "MATERIAL", 0, "Material", ""},
+ {OBJECT_SELECT_LINKED_DUPGROUP, "DUPGROUP", 0, "Instanced Collection", ""},
+ {OBJECT_SELECT_LINKED_PARTICLE, "PARTICLE", 0, "Particle System", ""},
+ {OBJECT_SELECT_LINKED_LIBRARY, "LIBRARY", 0, "Library", ""},
+ {OBJECT_SELECT_LINKED_LIBRARY_OBDATA, "LIBRARY_OBDATA", 0, "Library (Object Data)", ""},
+ {0, NULL, 0, NULL, NULL},
};
static bool object_select_all_by_obdata(bContext *C, void *obdata)
{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
- if (base->object->data == obdata) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- }
- CTX_DATA_END;
-
- return changed;
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
+ if (base->object->data == obdata) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ return changed;
}
static bool object_select_all_by_material(bContext *C, Material *mat)
{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
- Object *ob = base->object;
- Material *mat1;
- int a;
-
- for (a = 1; a <= ob->totcol; a++) {
- mat1 = give_current_material(ob, a);
-
- if (mat1 == mat) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- }
- }
- CTX_DATA_END;
-
- return changed;
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
+ Object *ob = base->object;
+ Material *mat1;
+ int a;
+
+ for (a = 1; a <= ob->totcol; a++) {
+ mat1 = give_current_material(ob, a);
+
+ if (mat1 == mat) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ return changed;
}
static bool object_select_all_by_instance_collection(bContext *C, Object *ob)
{
- bool changed = false;
- Collection *instance_collection = (ob->transflag & OB_DUPLICOLLECTION) ? ob->instance_collection : NULL;
-
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
- Collection *instance_collection_other = (base->object->transflag & OB_DUPLICOLLECTION) ? base->object->instance_collection : NULL;
- if (instance_collection == instance_collection_other) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- }
- CTX_DATA_END;
-
- return changed;
+ bool changed = false;
+ Collection *instance_collection = (ob->transflag & OB_DUPLICOLLECTION) ?
+ ob->instance_collection :
+ NULL;
+
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
+ Collection *instance_collection_other = (base->object->transflag & OB_DUPLICOLLECTION) ?
+ base->object->instance_collection :
+ NULL;
+ if (instance_collection == instance_collection_other) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ return changed;
}
static bool object_select_all_by_particle(bContext *C, Object *ob)
{
- ParticleSystem *psys_act = psys_get_current(ob);
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
- /* loop through other particles*/
- ParticleSystem *psys;
-
- for (psys = base->object->particlesystem.first; psys; psys = psys->next) {
- if (psys->part == psys_act->part) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- break;
- }
-
- if (base->flag & BASE_SELECTED) {
- break;
- }
- }
- }
- }
- CTX_DATA_END;
-
- return changed;
+ ParticleSystem *psys_act = psys_get_current(ob);
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
+ /* loop through other particles*/
+ ParticleSystem *psys;
+
+ for (psys = base->object->particlesystem.first; psys; psys = psys->next) {
+ if (psys->part == psys_act->part) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ break;
+ }
+
+ if (base->flag & BASE_SELECTED) {
+ break;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ return changed;
}
static bool object_select_all_by_library(bContext *C, Library *lib)
{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
- if (lib == base->object->id.lib) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- }
- CTX_DATA_END;
-
- return changed;
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
+ if (lib == base->object->id.lib) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ return changed;
}
static bool object_select_all_by_library_obdata(bContext *C, Library *lib)
{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
- if (base->object->data && lib == ((ID *)base->object->data)->lib) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- }
- CTX_DATA_END;
-
- return changed;
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
+ if (base->object->data && lib == ((ID *)base->object->data)->lib) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ return changed;
}
void ED_object_select_linked_by_id(bContext *C, ID *id)
{
- int idtype = GS(id->name);
- bool changed = false;
-
- if (OB_DATA_SUPPORT_ID(idtype)) {
- changed = object_select_all_by_obdata(C, id);
- }
- else if (idtype == ID_MA) {
- changed = object_select_all_by_material(C, (Material *)id);
- }
- else if (idtype == ID_LI) {
- changed = object_select_all_by_library(C, (Library *) id);
- }
-
- if (changed) {
- Scene *scene = CTX_data_scene(C);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
+ int idtype = GS(id->name);
+ bool changed = false;
+
+ if (OB_DATA_SUPPORT_ID(idtype)) {
+ changed = object_select_all_by_obdata(C, id);
+ }
+ else if (idtype == ID_MA) {
+ changed = object_select_all_by_material(C, (Material *)id);
+ }
+ else if (idtype == ID_LI) {
+ changed = object_select_all_by_library(C, (Library *)id);
+ }
+
+ if (changed) {
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ }
}
static int object_select_linked_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- Object *ob;
- int nr = RNA_enum_get(op->ptr, "type");
- bool changed = false, extend;
-
- extend = RNA_boolean_get(op->ptr, "extend");
-
- if (extend == 0) {
- ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT);
- }
-
- ob = OBACT(view_layer);
- if (ob == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active object");
- return OPERATOR_CANCELLED;
- }
-
- if (nr == OBJECT_SELECT_LINKED_IPO) {
- // XXX old animation system
- //if (ob->ipo == 0) return OPERATOR_CANCELLED;
- //object_select_all_by_ipo(C, ob->ipo)
- return OPERATOR_CANCELLED;
- }
- else if (nr == OBJECT_SELECT_LINKED_OBDATA) {
- if (ob->data == NULL)
- return OPERATOR_CANCELLED;
-
- changed = object_select_all_by_obdata(C, ob->data);
- }
- else if (nr == OBJECT_SELECT_LINKED_MATERIAL) {
- Material *mat = NULL;
-
- mat = give_current_material(ob, ob->actcol);
- if (mat == NULL) return OPERATOR_CANCELLED;
-
- changed = object_select_all_by_material(C, mat);
- }
- else if (nr == OBJECT_SELECT_LINKED_DUPGROUP) {
- if (ob->instance_collection == NULL)
- return OPERATOR_CANCELLED;
-
- changed = object_select_all_by_instance_collection(C, ob);
- }
- else if (nr == OBJECT_SELECT_LINKED_PARTICLE) {
- if (BLI_listbase_is_empty(&ob->particlesystem))
- return OPERATOR_CANCELLED;
-
- changed = object_select_all_by_particle(C, ob);
- }
- else if (nr == OBJECT_SELECT_LINKED_LIBRARY) {
- /* do nothing */
- changed = object_select_all_by_library(C, ob->id.lib);
- }
- else if (nr == OBJECT_SELECT_LINKED_LIBRARY_OBDATA) {
- if (ob->data == NULL)
- return OPERATOR_CANCELLED;
-
- changed = object_select_all_by_library_obdata(C, ((ID *) ob->data)->lib);
- }
- else
- return OPERATOR_CANCELLED;
-
- if (changed) {
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_CANCELLED;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Object *ob;
+ int nr = RNA_enum_get(op->ptr, "type");
+ bool changed = false, extend;
+
+ extend = RNA_boolean_get(op->ptr, "extend");
+
+ if (extend == 0) {
+ ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT);
+ }
+
+ ob = OBACT(view_layer);
+ if (ob == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active object");
+ return OPERATOR_CANCELLED;
+ }
+
+ if (nr == OBJECT_SELECT_LINKED_IPO) {
+ // XXX old animation system
+ //if (ob->ipo == 0) return OPERATOR_CANCELLED;
+ //object_select_all_by_ipo(C, ob->ipo)
+ return OPERATOR_CANCELLED;
+ }
+ else if (nr == OBJECT_SELECT_LINKED_OBDATA) {
+ if (ob->data == NULL)
+ return OPERATOR_CANCELLED;
+
+ changed = object_select_all_by_obdata(C, ob->data);
+ }
+ else if (nr == OBJECT_SELECT_LINKED_MATERIAL) {
+ Material *mat = NULL;
+
+ mat = give_current_material(ob, ob->actcol);
+ if (mat == NULL)
+ return OPERATOR_CANCELLED;
+
+ changed = object_select_all_by_material(C, mat);
+ }
+ else if (nr == OBJECT_SELECT_LINKED_DUPGROUP) {
+ if (ob->instance_collection == NULL)
+ return OPERATOR_CANCELLED;
+
+ changed = object_select_all_by_instance_collection(C, ob);
+ }
+ else if (nr == OBJECT_SELECT_LINKED_PARTICLE) {
+ if (BLI_listbase_is_empty(&ob->particlesystem))
+ return OPERATOR_CANCELLED;
+
+ changed = object_select_all_by_particle(C, ob);
+ }
+ else if (nr == OBJECT_SELECT_LINKED_LIBRARY) {
+ /* do nothing */
+ changed = object_select_all_by_library(C, ob->id.lib);
+ }
+ else if (nr == OBJECT_SELECT_LINKED_LIBRARY_OBDATA) {
+ if (ob->data == NULL)
+ return OPERATOR_CANCELLED;
+
+ changed = object_select_all_by_library_obdata(C, ((ID *)ob->data)->lib);
+ }
+ else
+ return OPERATOR_CANCELLED;
+
+ if (changed) {
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_select_linked(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Linked";
- ot->description = "Select all visible objects that are linked";
- ot->idname = "OBJECT_OT_select_linked";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_select_linked_exec;
- ot->poll = objects_selectable_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
- ot->prop = RNA_def_enum(ot->srna, "type", prop_select_linked_types, 0, "Type", "");
+ /* identifiers */
+ ot->name = "Select Linked";
+ ot->description = "Select all visible objects that are linked";
+ ot->idname = "OBJECT_OT_select_linked";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_select_linked_exec;
+ ot->poll = objects_selectable_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "extend",
+ false,
+ "Extend",
+ "Extend selection instead of deselecting everything first");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_select_linked_types, 0, "Type", "");
}
/** \} */
@@ -728,371 +736,379 @@ void OBJECT_OT_select_linked(wmOperatorType *ot)
* \{ */
enum {
- OBJECT_GRPSEL_CHILDREN_RECURSIVE = 0,
- OBJECT_GRPSEL_CHILDREN = 1,
- OBJECT_GRPSEL_PARENT = 2,
- OBJECT_GRPSEL_SIBLINGS = 3,
- OBJECT_GRPSEL_TYPE = 4,
- OBJECT_GRPSEL_COLLECTION = 5,
- OBJECT_GRPSEL_HOOK = 7,
- OBJECT_GRPSEL_PASS = 8,
- OBJECT_GRPSEL_COLOR = 9,
- OBJECT_GRPSEL_KEYINGSET = 10,
- OBJECT_GRPSEL_LIGHT_TYPE = 11,
+ OBJECT_GRPSEL_CHILDREN_RECURSIVE = 0,
+ OBJECT_GRPSEL_CHILDREN = 1,
+ OBJECT_GRPSEL_PARENT = 2,
+ OBJECT_GRPSEL_SIBLINGS = 3,
+ OBJECT_GRPSEL_TYPE = 4,
+ OBJECT_GRPSEL_COLLECTION = 5,
+ OBJECT_GRPSEL_HOOK = 7,
+ OBJECT_GRPSEL_PASS = 8,
+ OBJECT_GRPSEL_COLOR = 9,
+ OBJECT_GRPSEL_KEYINGSET = 10,
+ OBJECT_GRPSEL_LIGHT_TYPE = 11,
};
static const EnumPropertyItem prop_select_grouped_types[] = {
- {OBJECT_GRPSEL_CHILDREN_RECURSIVE, "CHILDREN_RECURSIVE", 0, "Children", ""},
- {OBJECT_GRPSEL_CHILDREN, "CHILDREN", 0, "Immediate Children", ""},
- {OBJECT_GRPSEL_PARENT, "PARENT", 0, "Parent", ""},
- {OBJECT_GRPSEL_SIBLINGS, "SIBLINGS", 0, "Siblings", "Shared Parent"},
- {OBJECT_GRPSEL_TYPE, "TYPE", 0, "Type", "Shared object type"},
- {OBJECT_GRPSEL_COLLECTION, "COLLECTION", 0, "Collection", "Shared collection"},
- {OBJECT_GRPSEL_HOOK, "HOOK", 0, "Hook", ""},
- {OBJECT_GRPSEL_PASS, "PASS", 0, "Pass", "Render pass Index"},
- {OBJECT_GRPSEL_COLOR, "COLOR", 0, "Color", "Object Color"},
- {OBJECT_GRPSEL_KEYINGSET, "KEYINGSET", 0, "Keying Set", "Objects included in active Keying Set"},
- {OBJECT_GRPSEL_LIGHT_TYPE, "LIGHT_TYPE", 0, "Light Type", "Matching light types"},
- {0, NULL, 0, NULL, NULL},
+ {OBJECT_GRPSEL_CHILDREN_RECURSIVE, "CHILDREN_RECURSIVE", 0, "Children", ""},
+ {OBJECT_GRPSEL_CHILDREN, "CHILDREN", 0, "Immediate Children", ""},
+ {OBJECT_GRPSEL_PARENT, "PARENT", 0, "Parent", ""},
+ {OBJECT_GRPSEL_SIBLINGS, "SIBLINGS", 0, "Siblings", "Shared Parent"},
+ {OBJECT_GRPSEL_TYPE, "TYPE", 0, "Type", "Shared object type"},
+ {OBJECT_GRPSEL_COLLECTION, "COLLECTION", 0, "Collection", "Shared collection"},
+ {OBJECT_GRPSEL_HOOK, "HOOK", 0, "Hook", ""},
+ {OBJECT_GRPSEL_PASS, "PASS", 0, "Pass", "Render pass Index"},
+ {OBJECT_GRPSEL_COLOR, "COLOR", 0, "Color", "Object Color"},
+ {OBJECT_GRPSEL_KEYINGSET,
+ "KEYINGSET",
+ 0,
+ "Keying Set",
+ "Objects included in active Keying Set"},
+ {OBJECT_GRPSEL_LIGHT_TYPE, "LIGHT_TYPE", 0, "Light Type", "Matching light types"},
+ {0, NULL, 0, NULL, NULL},
};
static bool select_grouped_children(bContext *C, Object *ob, const bool recursive)
{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
- {
- if (ob == base->object->parent) {
- if ((base->flag & BASE_SELECTED) == 0) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
-
- if (recursive) {
- changed |= select_grouped_children(C, base->object, 1);
- }
- }
- }
- CTX_DATA_END;
- return changed;
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ if (ob == base->object->parent) {
+ if ((base->flag & BASE_SELECTED) == 0) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+
+ if (recursive) {
+ changed |= select_grouped_children(C, base->object, 1);
+ }
+ }
+ }
+ CTX_DATA_END;
+ return changed;
}
static bool select_grouped_parent(bContext *C) /* Makes parent active and de-selected OBACT */
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- Base *baspar, *basact = CTX_data_active_base(C);
- bool changed = false;
-
- if (!basact || !(basact->object->parent)) {
- return 0; /* we know OBACT is valid */
- }
-
- baspar = BKE_view_layer_base_find(view_layer, basact->object->parent);
-
- /* can be NULL if parent in other scene */
- if (baspar && BASE_SELECTABLE(v3d, baspar)) {
- ED_object_base_select(baspar, BA_SELECT);
- ED_object_base_activate(C, baspar);
- changed = true;
- }
- return changed;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Base *baspar, *basact = CTX_data_active_base(C);
+ bool changed = false;
+
+ if (!basact || !(basact->object->parent)) {
+ return 0; /* we know OBACT is valid */
+ }
+
+ baspar = BKE_view_layer_base_find(view_layer, basact->object->parent);
+
+ /* can be NULL if parent in other scene */
+ if (baspar && BASE_SELECTABLE(v3d, baspar)) {
+ ED_object_base_select(baspar, BA_SELECT);
+ ED_object_base_activate(C, baspar);
+ changed = true;
+ }
+ return changed;
}
-
-#define COLLECTION_MENU_MAX 24
+#define COLLECTION_MENU_MAX 24
/* Select objects in the same group as the active */
static bool select_grouped_collection(bContext *C, Object *ob)
{
- bool changed = false;
- Collection *collection, *ob_collections[COLLECTION_MENU_MAX];
- int collection_count = 0, i;
- uiPopupMenu *pup;
- uiLayout *layout;
-
- for (collection = CTX_data_main(C)->collections.first; collection && collection_count < COLLECTION_MENU_MAX; collection = collection->id.next) {
- if (BKE_collection_has_object(collection, ob)) {
- ob_collections[collection_count] = collection;
- collection_count++;
- }
- }
-
- if (!collection_count)
- return 0;
- else if (collection_count == 1) {
- collection = ob_collections[0];
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
- if (BKE_collection_has_object(collection, base->object)) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- }
- CTX_DATA_END;
- return changed;
- }
-
- /* build the menu. */
- pup = UI_popup_menu_begin(C, IFACE_("Select Collection"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
-
- for (i = 0; i < collection_count; i++) {
- collection = ob_collections[i];
- uiItemStringO(layout, collection->id.name + 2, 0, "OBJECT_OT_select_same_collection", "collection", collection->id.name + 2);
- }
-
- UI_popup_menu_end(C, pup);
- return changed; /* The operator already handle this! */
+ bool changed = false;
+ Collection *collection, *ob_collections[COLLECTION_MENU_MAX];
+ int collection_count = 0, i;
+ uiPopupMenu *pup;
+ uiLayout *layout;
+
+ for (collection = CTX_data_main(C)->collections.first;
+ collection && collection_count < COLLECTION_MENU_MAX;
+ collection = collection->id.next) {
+ if (BKE_collection_has_object(collection, ob)) {
+ ob_collections[collection_count] = collection;
+ collection_count++;
+ }
+ }
+
+ if (!collection_count)
+ return 0;
+ else if (collection_count == 1) {
+ collection = ob_collections[0];
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
+ if (BKE_collection_has_object(collection, base->object)) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ }
+ CTX_DATA_END;
+ return changed;
+ }
+
+ /* build the menu. */
+ pup = UI_popup_menu_begin(C, IFACE_("Select Collection"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+
+ for (i = 0; i < collection_count; i++) {
+ collection = ob_collections[i];
+ uiItemStringO(layout,
+ collection->id.name + 2,
+ 0,
+ "OBJECT_OT_select_same_collection",
+ "collection",
+ collection->id.name + 2);
+ }
+
+ UI_popup_menu_end(C, pup);
+ return changed; /* The operator already handle this! */
}
static bool select_grouped_object_hooks(bContext *C, Object *ob)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
-
- bool changed = false;
- Base *base;
- ModifierData *md;
- HookModifierData *hmd;
-
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Hook) {
- hmd = (HookModifierData *) md;
- if (hmd->object) {
- base = BKE_view_layer_base_find(view_layer, hmd->object);
- if (base && ((base->flag & BASE_SELECTED) == 0) && (BASE_SELECTABLE(v3d, base))) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- }
- }
- return changed;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+
+ bool changed = false;
+ Base *base;
+ ModifierData *md;
+ HookModifierData *hmd;
+
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Hook) {
+ hmd = (HookModifierData *)md;
+ if (hmd->object) {
+ base = BKE_view_layer_base_find(view_layer, hmd->object);
+ if (base && ((base->flag & BASE_SELECTED) == 0) && (BASE_SELECTABLE(v3d, base))) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ }
+ }
+ return changed;
}
/* Select objects with the same parent as the active (siblings),
* parent can be NULL also */
static bool select_grouped_siblings(bContext *C, Object *ob)
{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
- {
- if ((base->object->parent == ob->parent) && ((base->flag & BASE_SELECTED) == 0)) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- CTX_DATA_END;
- return changed;
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ if ((base->object->parent == ob->parent) && ((base->flag & BASE_SELECTED) == 0)) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ CTX_DATA_END;
+ return changed;
}
static bool select_grouped_lighttype(bContext *C, Object *ob)
{
- Light *la = ob->data;
-
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
- {
- if (base->object->type == OB_LAMP) {
- Light *la_test = base->object->data;
- if ((la->type == la_test->type) && ((base->flag & BASE_SELECTED) == 0)) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- }
- CTX_DATA_END;
- return changed;
+ Light *la = ob->data;
+
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ if (base->object->type == OB_LAMP) {
+ Light *la_test = base->object->data;
+ if ((la->type == la_test->type) && ((base->flag & BASE_SELECTED) == 0)) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ }
+ CTX_DATA_END;
+ return changed;
}
static bool select_grouped_type(bContext *C, Object *ob)
{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
- {
- if ((base->object->type == ob->type) && ((base->flag & BASE_SELECTED) == 0)) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- CTX_DATA_END;
- return changed;
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ if ((base->object->type == ob->type) && ((base->flag & BASE_SELECTED) == 0)) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ CTX_DATA_END;
+ return changed;
}
static bool select_grouped_index_object(bContext *C, Object *ob)
{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
- {
- if ((base->object->index == ob->index) && ((base->flag & BASE_SELECTED) == 0)) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- CTX_DATA_END;
- return changed;
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ if ((base->object->index == ob->index) && ((base->flag & BASE_SELECTED) == 0)) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ CTX_DATA_END;
+ return changed;
}
static bool select_grouped_color(bContext *C, Object *ob)
{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
- {
- if (((base->flag & BASE_SELECTED) == 0) && (compare_v3v3(base->object->color, ob->color, 0.005f))) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- }
- }
- CTX_DATA_END;
- return changed;
+ bool changed = false;
+
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ if (((base->flag & BASE_SELECTED) == 0) &&
+ (compare_v3v3(base->object->color, ob->color, 0.005f))) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
+ }
+ CTX_DATA_END;
+ return changed;
}
static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList *reports)
{
- KeyingSet *ks = ANIM_scene_get_active_keyingset(CTX_data_scene(C));
- bool changed = false;
-
- /* firstly, validate KeyingSet */
- if (ks == NULL) {
- BKE_report(reports, RPT_ERROR, "No active Keying Set to use");
- return false;
- }
- else if (ANIM_validate_keyingset(C, NULL, ks) != 0) {
- if (ks->paths.first == NULL) {
- if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) {
- BKE_report(reports, RPT_ERROR,
- "Use another Keying Set, as the active one depends on the currently "
- "selected objects or cannot find any targets due to unsuitable context");
- }
- else {
- BKE_report(reports, RPT_ERROR, "Keying Set does not contain any paths");
- }
- }
- return false;
- }
-
- /* select each object that Keying Set refers to */
- /* TODO: perhaps to be more in line with the rest of these, we should only take objects
- * if the passed in object is included in this too */
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
- {
- /* only check for this object if it isn't selected already, to limit time wasted */
- if ((base->flag & BASE_SELECTED) == 0) {
- KS_Path *ksp;
-
- /* this is the slow way... we could end up with > 500 items here,
- * with none matching, but end up doing this on 1000 objects...
- */
- for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
- /* if id matches, select then stop looping (match found) */
- if (ksp->id == (ID *)base->object) {
- ED_object_base_select(base, BA_SELECT);
- changed = true;
- break;
- }
- }
- }
- }
- CTX_DATA_END;
-
- return changed;
+ KeyingSet *ks = ANIM_scene_get_active_keyingset(CTX_data_scene(C));
+ bool changed = false;
+
+ /* firstly, validate KeyingSet */
+ if (ks == NULL) {
+ BKE_report(reports, RPT_ERROR, "No active Keying Set to use");
+ return false;
+ }
+ else if (ANIM_validate_keyingset(C, NULL, ks) != 0) {
+ if (ks->paths.first == NULL) {
+ if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) {
+ BKE_report(reports,
+ RPT_ERROR,
+ "Use another Keying Set, as the active one depends on the currently "
+ "selected objects or cannot find any targets due to unsuitable context");
+ }
+ else {
+ BKE_report(reports, RPT_ERROR, "Keying Set does not contain any paths");
+ }
+ }
+ return false;
+ }
+
+ /* select each object that Keying Set refers to */
+ /* TODO: perhaps to be more in line with the rest of these, we should only take objects
+ * if the passed in object is included in this too */
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ /* only check for this object if it isn't selected already, to limit time wasted */
+ if ((base->flag & BASE_SELECTED) == 0) {
+ KS_Path *ksp;
+
+ /* this is the slow way... we could end up with > 500 items here,
+ * with none matching, but end up doing this on 1000 objects...
+ */
+ for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
+ /* if id matches, select then stop looping (match found) */
+ if (ksp->id == (ID *)base->object) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ break;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ return changed;
}
static int object_select_grouped_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- Object *ob;
- const int type = RNA_enum_get(op->ptr, "type");
- bool changed = false, extend;
-
- extend = RNA_boolean_get(op->ptr, "extend");
-
- if (extend == 0) {
- changed = ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT);
- }
-
- ob = OBACT(view_layer);
- if (ob == NULL) {
- BKE_report(op->reports, RPT_ERROR, "No active object");
- return OPERATOR_CANCELLED;
- }
-
- switch (type) {
- case OBJECT_GRPSEL_CHILDREN_RECURSIVE:
- changed |= select_grouped_children(C, ob, true);
- break;
- case OBJECT_GRPSEL_CHILDREN:
- changed |= select_grouped_children(C, ob, false);
- break;
- case OBJECT_GRPSEL_PARENT:
- changed |= select_grouped_parent(C);
- break;
- case OBJECT_GRPSEL_SIBLINGS:
- changed |= select_grouped_siblings(C, ob);
- break;
- case OBJECT_GRPSEL_TYPE:
- changed |= select_grouped_type(C, ob);
- break;
- case OBJECT_GRPSEL_COLLECTION:
- changed |= select_grouped_collection(C, ob);
- break;
- case OBJECT_GRPSEL_HOOK:
- changed |= select_grouped_object_hooks(C, ob);
- break;
- case OBJECT_GRPSEL_PASS:
- changed |= select_grouped_index_object(C, ob);
- break;
- case OBJECT_GRPSEL_COLOR:
- changed |= select_grouped_color(C, ob);
- break;
- case OBJECT_GRPSEL_KEYINGSET:
- changed |= select_grouped_keyingset(C, ob, op->reports);
- break;
- case OBJECT_GRPSEL_LIGHT_TYPE:
- if (ob->type != OB_LAMP) {
- BKE_report(op->reports, RPT_ERROR, "Active object must be a light");
- break;
- }
- changed |= select_grouped_lighttype(C, ob);
- break;
- default:
- break;
- }
-
- if (changed) {
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_CANCELLED;
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ Object *ob;
+ const int type = RNA_enum_get(op->ptr, "type");
+ bool changed = false, extend;
+
+ extend = RNA_boolean_get(op->ptr, "extend");
+
+ if (extend == 0) {
+ changed = ED_object_base_deselect_all(view_layer, v3d, SEL_DESELECT);
+ }
+
+ ob = OBACT(view_layer);
+ if (ob == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "No active object");
+ return OPERATOR_CANCELLED;
+ }
+
+ switch (type) {
+ case OBJECT_GRPSEL_CHILDREN_RECURSIVE:
+ changed |= select_grouped_children(C, ob, true);
+ break;
+ case OBJECT_GRPSEL_CHILDREN:
+ changed |= select_grouped_children(C, ob, false);
+ break;
+ case OBJECT_GRPSEL_PARENT:
+ changed |= select_grouped_parent(C);
+ break;
+ case OBJECT_GRPSEL_SIBLINGS:
+ changed |= select_grouped_siblings(C, ob);
+ break;
+ case OBJECT_GRPSEL_TYPE:
+ changed |= select_grouped_type(C, ob);
+ break;
+ case OBJECT_GRPSEL_COLLECTION:
+ changed |= select_grouped_collection(C, ob);
+ break;
+ case OBJECT_GRPSEL_HOOK:
+ changed |= select_grouped_object_hooks(C, ob);
+ break;
+ case OBJECT_GRPSEL_PASS:
+ changed |= select_grouped_index_object(C, ob);
+ break;
+ case OBJECT_GRPSEL_COLOR:
+ changed |= select_grouped_color(C, ob);
+ break;
+ case OBJECT_GRPSEL_KEYINGSET:
+ changed |= select_grouped_keyingset(C, ob, op->reports);
+ break;
+ case OBJECT_GRPSEL_LIGHT_TYPE:
+ if (ob->type != OB_LAMP) {
+ BKE_report(op->reports, RPT_ERROR, "Active object must be a light");
+ break;
+ }
+ changed |= select_grouped_lighttype(C, ob);
+ break;
+ default:
+ break;
+ }
+
+ if (changed) {
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ return OPERATOR_FINISHED;
+ }
+
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_select_grouped(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Grouped";
- ot->description = "Select all visible objects grouped by various properties";
- ot->idname = "OBJECT_OT_select_grouped";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_select_grouped_exec;
- ot->poll = objects_selectable_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
- ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
+ /* identifiers */
+ ot->name = "Select Grouped";
+ ot->description = "Select all visible objects grouped by various properties";
+ ot->idname = "OBJECT_OT_select_grouped";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_select_grouped_exec;
+ ot->poll = objects_selectable_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "extend",
+ false,
+ "Extend",
+ "Extend selection instead of deselecting everything first");
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
}
/** \} */
@@ -1103,46 +1119,46 @@ void OBJECT_OT_select_grouped(wmOperatorType *ot)
static int object_select_all_exec(bContext *C, wmOperator *op)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
- int action = RNA_enum_get(op->ptr, "action");
- bool any_visible = false;
-
- bool changed = ED_object_base_deselect_all_ex(view_layer, v3d, action, &any_visible);
-
- if (changed) {
- Scene *scene = CTX_data_scene(C);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
-
- return OPERATOR_FINISHED;
- }
- else if (any_visible == false) {
- /* TODO(campbell): Looks like we could remove this,
- * if not comment should say why its needed. */
- return OPERATOR_PASS_THROUGH;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ int action = RNA_enum_get(op->ptr, "action");
+ bool any_visible = false;
+
+ bool changed = ED_object_base_deselect_all_ex(view_layer, v3d, action, &any_visible);
+
+ if (changed) {
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
+ return OPERATOR_FINISHED;
+ }
+ else if (any_visible == false) {
+ /* TODO(campbell): Looks like we could remove this,
+ * if not comment should say why its needed. */
+ return OPERATOR_PASS_THROUGH;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void OBJECT_OT_select_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "(De)select All";
- ot->description = "Change selection of all visible objects in scene";
- ot->idname = "OBJECT_OT_select_all";
+ /* identifiers */
+ ot->name = "(De)select All";
+ ot->description = "Change selection of all visible objects in scene";
+ ot->idname = "OBJECT_OT_select_all";
- /* api callbacks */
- ot->exec = object_select_all_exec;
- ot->poll = objects_selectable_poll;
+ /* api callbacks */
+ ot->exec = object_select_all_exec;
+ ot->poll = objects_selectable_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_select_all(ot);
+ WM_operator_properties_select_all(ot);
}
/** \} */
@@ -1153,54 +1169,55 @@ void OBJECT_OT_select_all(wmOperatorType *ot)
static int object_select_same_collection_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Collection *collection;
- char collection_name[MAX_ID_NAME];
+ Main *bmain = CTX_data_main(C);
+ Collection *collection;
+ char collection_name[MAX_ID_NAME];
- /* passthrough if no objects are visible */
- if (CTX_DATA_COUNT(C, visible_bases) == 0) return OPERATOR_PASS_THROUGH;
+ /* passthrough if no objects are visible */
+ if (CTX_DATA_COUNT(C, visible_bases) == 0)
+ return OPERATOR_PASS_THROUGH;
- RNA_string_get(op->ptr, "collection", collection_name);
+ RNA_string_get(op->ptr, "collection", collection_name);
- collection = (Collection *)BKE_libblock_find_name(bmain, ID_GR, collection_name);
+ collection = (Collection *)BKE_libblock_find_name(bmain, ID_GR, collection_name);
- if (!collection) {
- return OPERATOR_PASS_THROUGH;
- }
+ if (!collection) {
+ return OPERATOR_PASS_THROUGH;
+ }
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
- if (BKE_collection_has_object(collection, base->object)) {
- ED_object_base_select(base, BA_SELECT);
- }
- }
- }
- CTX_DATA_END;
+ CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
+ if (BKE_collection_has_object(collection, base->object)) {
+ ED_object_base_select(base, BA_SELECT);
+ }
+ }
+ }
+ CTX_DATA_END;
- Scene *scene = CTX_data_scene(C);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_select_same_collection(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Same Collection";
- ot->description = "Select object in the same collection";
- ot->idname = "OBJECT_OT_select_same_collection";
+ /* identifiers */
+ ot->name = "Select Same Collection";
+ ot->description = "Select object in the same collection";
+ ot->idname = "OBJECT_OT_select_same_collection";
- /* api callbacks */
- ot->exec = object_select_same_collection_exec;
- ot->poll = objects_selectable_poll;
+ /* api callbacks */
+ ot->exec = object_select_same_collection_exec;
+ ot->poll = objects_selectable_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_string(ot->srna, "collection", NULL, MAX_ID_NAME, "Collection", "Name of the collection to select");
+ RNA_def_string(
+ ot->srna, "collection", NULL, MAX_ID_NAME, "Collection", "Name of the collection to select");
}
/** \} */
@@ -1211,58 +1228,58 @@ void OBJECT_OT_select_same_collection(wmOperatorType *ot)
static int object_select_mirror_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- bool extend;
-
- extend = RNA_boolean_get(op->ptr, "extend");
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ bool extend;
- CTX_DATA_BEGIN (C, Base *, primbase, selected_bases)
- {
- char name_flip[MAXBONENAME];
+ extend = RNA_boolean_get(op->ptr, "extend");
- BLI_string_flip_side_name(name_flip, primbase->object->id.name + 2, true, sizeof(name_flip));
+ CTX_DATA_BEGIN (C, Base *, primbase, selected_bases) {
+ char name_flip[MAXBONENAME];
- if (!STREQ(name_flip, primbase->object->id.name + 2)) {
- Object *ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, name_flip);
- if (ob) {
- Base *secbase = BKE_view_layer_base_find(view_layer, ob);
+ BLI_string_flip_side_name(name_flip, primbase->object->id.name + 2, true, sizeof(name_flip));
- if (secbase) {
- ED_object_base_select(secbase, BA_SELECT);
- }
- }
- }
+ if (!STREQ(name_flip, primbase->object->id.name + 2)) {
+ Object *ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, name_flip);
+ if (ob) {
+ Base *secbase = BKE_view_layer_base_find(view_layer, ob);
- if (extend == false) ED_object_base_select(primbase, BA_DESELECT);
+ if (secbase) {
+ ED_object_base_select(secbase, BA_SELECT);
+ }
+ }
+ }
- }
- CTX_DATA_END;
+ if (extend == false)
+ ED_object_base_select(primbase, BA_DESELECT);
+ }
+ CTX_DATA_END;
- /* undo? */
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ /* undo? */
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_select_mirror(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Mirror";
- ot->description = "Select the Mirror objects of the selected object eg. L.sword -> R.sword";
- ot->idname = "OBJECT_OT_select_mirror";
+ /* identifiers */
+ ot->name = "Select Mirror";
+ ot->description = "Select the Mirror objects of the selected object eg. L.sword -> R.sword";
+ ot->idname = "OBJECT_OT_select_mirror";
- /* api callbacks */
- ot->exec = object_select_mirror_exec;
- ot->poll = objects_selectable_poll;
+ /* api callbacks */
+ ot->exec = object_select_mirror_exec;
+ ot->poll = objects_selectable_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first");
+ RNA_def_boolean(
+ ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first");
}
/** \} */
@@ -1273,116 +1290,114 @@ void OBJECT_OT_select_mirror(wmOperatorType *ot)
static bool object_select_more_less(bContext *C, const bool select)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- Object *ob = base->object;
- ob->flag &= ~OB_DONE;
- ob->id.tag &= ~LIB_TAG_DOIT;
- /* parent may be in another scene */
- if (ob->parent) {
- ob->parent->flag &= ~OB_DONE;
- ob->parent->id.tag &= ~LIB_TAG_DOIT;
- }
- }
-
- ListBase ctx_base_list;
- CollectionPointerLink *ctx_base;
- CTX_data_selectable_bases(C, &ctx_base_list);
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
- {
- ob->flag |= OB_DONE;
- }
- CTX_DATA_END;
-
-
- for (ctx_base = ctx_base_list.first; ctx_base; ctx_base = ctx_base->next) {
- Object *ob = ((Base *)ctx_base->ptr.data)->object;
- if (ob->parent) {
- if ((ob->flag & OB_DONE) != (ob->parent->flag & OB_DONE)) {
- ob->id.tag |= LIB_TAG_DOIT;
- ob->parent->id.tag |= LIB_TAG_DOIT;
- }
- }
- }
-
- bool changed = false;
- const short select_mode = select ? BA_SELECT : BA_DESELECT;
- const short select_flag = select ? BASE_SELECTED : 0;
-
- for (ctx_base = ctx_base_list.first; ctx_base; ctx_base = ctx_base->next) {
- Base *base = ctx_base->ptr.data;
- Object *ob = base->object;
- if ((ob->id.tag & LIB_TAG_DOIT) && ((base->flag & BASE_SELECTED) != select_flag)) {
- ED_object_base_select(base, select_mode);
- changed = true;
- }
- }
-
- BLI_freelistN(&ctx_base_list);
-
- return changed;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ Object *ob = base->object;
+ ob->flag &= ~OB_DONE;
+ ob->id.tag &= ~LIB_TAG_DOIT;
+ /* parent may be in another scene */
+ if (ob->parent) {
+ ob->parent->flag &= ~OB_DONE;
+ ob->parent->id.tag &= ~LIB_TAG_DOIT;
+ }
+ }
+
+ ListBase ctx_base_list;
+ CollectionPointerLink *ctx_base;
+ CTX_data_selectable_bases(C, &ctx_base_list);
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ ob->flag |= OB_DONE;
+ }
+ CTX_DATA_END;
+
+ for (ctx_base = ctx_base_list.first; ctx_base; ctx_base = ctx_base->next) {
+ Object *ob = ((Base *)ctx_base->ptr.data)->object;
+ if (ob->parent) {
+ if ((ob->flag & OB_DONE) != (ob->parent->flag & OB_DONE)) {
+ ob->id.tag |= LIB_TAG_DOIT;
+ ob->parent->id.tag |= LIB_TAG_DOIT;
+ }
+ }
+ }
+
+ bool changed = false;
+ const short select_mode = select ? BA_SELECT : BA_DESELECT;
+ const short select_flag = select ? BASE_SELECTED : 0;
+
+ for (ctx_base = ctx_base_list.first; ctx_base; ctx_base = ctx_base->next) {
+ Base *base = ctx_base->ptr.data;
+ Object *ob = base->object;
+ if ((ob->id.tag & LIB_TAG_DOIT) && ((base->flag & BASE_SELECTED) != select_flag)) {
+ ED_object_base_select(base, select_mode);
+ changed = true;
+ }
+ }
+
+ BLI_freelistN(&ctx_base_list);
+
+ return changed;
}
static int object_select_more_exec(bContext *C, wmOperator *UNUSED(op))
{
- bool changed = object_select_more_less(C, true);
-
- if (changed) {
- Scene *scene = CTX_data_scene(C);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ bool changed = object_select_more_less(C, true);
+
+ if (changed) {
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void OBJECT_OT_select_more(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select More";
- ot->idname = "OBJECT_OT_select_more";
- ot->description = "Select connected parent/child objects";
+ /* identifiers */
+ ot->name = "Select More";
+ ot->idname = "OBJECT_OT_select_more";
+ ot->description = "Select connected parent/child objects";
- /* api callbacks */
- ot->exec = object_select_more_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = object_select_more_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int object_select_less_exec(bContext *C, wmOperator *UNUSED(op))
{
- bool changed = object_select_more_less(C, false);
-
- if (changed) {
- Scene *scene = CTX_data_scene(C);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ bool changed = object_select_more_less(C, false);
+
+ if (changed) {
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void OBJECT_OT_select_less(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Less";
- ot->idname = "OBJECT_OT_select_less";
- ot->description = "Deselect objects at the boundaries of parent/child relationships";
+ /* identifiers */
+ ot->name = "Select Less";
+ ot->idname = "OBJECT_OT_select_less";
+ ot->description = "Deselect objects at the boundaries of parent/child relationships";
- /* api callbacks */
- ot->exec = object_select_less_exec;
- ot->poll = ED_operator_objectmode;
+ /* api callbacks */
+ ot->exec = object_select_less_exec;
+ ot->poll = ED_operator_objectmode;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
@@ -1393,46 +1408,45 @@ void OBJECT_OT_select_less(wmOperatorType *ot)
static int object_select_random_exec(bContext *C, wmOperator *op)
{
- const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
- const int seed = WM_operator_properties_select_random_seed_increment_get(op);
- const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
+ const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
+ const int seed = WM_operator_properties_select_random_seed_increment_get(op);
+ const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
- RNG *rng = BLI_rng_new_srandom(seed);
+ RNG *rng = BLI_rng_new_srandom(seed);
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
- {
- if (BLI_rng_get_float(rng) < randfac) {
- ED_object_base_select(base, select);
- }
- }
- CTX_DATA_END;
+ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
+ if (BLI_rng_get_float(rng) < randfac) {
+ ED_object_base_select(base, select);
+ }
+ }
+ CTX_DATA_END;
- BLI_rng_free(rng);
+ BLI_rng_free(rng);
- Scene *scene = CTX_data_scene(C);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_select_random(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Random";
- ot->description = "Set select on random visible objects";
- ot->idname = "OBJECT_OT_select_random";
+ /* identifiers */
+ ot->name = "Select Random";
+ ot->description = "Set select on random visible objects";
+ ot->idname = "OBJECT_OT_select_random";
- /* api callbacks */
- /*ot->invoke = object_select_random_invoke XXX - need a number popup ;*/
- ot->exec = object_select_random_exec;
- ot->poll = objects_selectable_poll;
+ /* api callbacks */
+ /*ot->invoke = object_select_random_invoke XXX - need a number popup ;*/
+ ot->exec = object_select_random_exec;
+ ot->poll = objects_selectable_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- WM_operator_properties_select_random(ot);
+ /* properties */
+ WM_operator_properties_select_random(ot);
}
/** \} */
diff --git a/source/blender/editors/object/object_shader_fx.c b/source/blender/editors/object/object_shader_fx.c
index 8580ea10d35..64535d8f281 100644
--- a/source/blender/editors/object/object_shader_fx.c
+++ b/source/blender/editors/object/object_shader_fx.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
@@ -63,400 +62,410 @@
/******************************** API ****************************/
-ShaderFxData *ED_object_shaderfx_add(ReportList *reports, Main *bmain, Scene *UNUSED(scene), Object *ob, const char *name, int type)
+ShaderFxData *ED_object_shaderfx_add(
+ ReportList *reports, Main *bmain, Scene *UNUSED(scene), Object *ob, const char *name, int type)
{
- ShaderFxData *new_fx = NULL;
- const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(type);
+ ShaderFxData *new_fx = NULL;
+ const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(type);
- if (ob->type != OB_GPENCIL) {
- BKE_reportf(reports, RPT_WARNING, "Effect cannot be added to object '%s'", ob->id.name + 2);
- return NULL;
- }
+ if (ob->type != OB_GPENCIL) {
+ BKE_reportf(reports, RPT_WARNING, "Effect cannot be added to object '%s'", ob->id.name + 2);
+ return NULL;
+ }
- if (fxi->flags & eShaderFxTypeFlag_Single) {
- if (BKE_shaderfx_findByType(ob, type)) {
- BKE_report(reports, RPT_WARNING, "Only one Effect of this type is allowed");
- return NULL;
- }
- }
+ if (fxi->flags & eShaderFxTypeFlag_Single) {
+ if (BKE_shaderfx_findByType(ob, type)) {
+ BKE_report(reports, RPT_WARNING, "Only one Effect of this type is allowed");
+ return NULL;
+ }
+ }
- /* get new effect data to add */
- new_fx = BKE_shaderfx_new(type);
+ /* get new effect data to add */
+ new_fx = BKE_shaderfx_new(type);
- BLI_addtail(&ob->shader_fx, new_fx);
+ BLI_addtail(&ob->shader_fx, new_fx);
- if (name) {
- BLI_strncpy_utf8(new_fx->name, name, sizeof(new_fx->name));
- }
+ if (name) {
+ BLI_strncpy_utf8(new_fx->name, name, sizeof(new_fx->name));
+ }
- /* make sure effect data has unique name */
- BKE_shaderfx_unique_name(&ob->shader_fx, new_fx);
+ /* make sure effect data has unique name */
+ BKE_shaderfx_unique_name(&ob->shader_fx, new_fx);
- bGPdata *gpd = ob->data;
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ bGPdata *gpd = ob->data;
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(bmain);
- return new_fx;
+ return new_fx;
}
/* Return true if the object has a effect of type 'type' other than
* the shaderfx pointed to be 'exclude', otherwise returns false. */
-static bool UNUSED_FUNCTION(object_has_shaderfx)(
- const Object *ob, const ShaderFxData *exclude,
- ShaderFxType type)
+static bool UNUSED_FUNCTION(object_has_shaderfx)(const Object *ob,
+ const ShaderFxData *exclude,
+ ShaderFxType type)
{
- ShaderFxData *fx;
+ ShaderFxData *fx;
- for (fx = ob->shader_fx.first; fx; fx = fx->next) {
- if ((fx != exclude) && (fx->type == type))
- return true;
- }
+ for (fx = ob->shader_fx.first; fx; fx = fx->next) {
+ if ((fx != exclude) && (fx->type == type))
+ return true;
+ }
- return false;
+ return false;
}
-static bool object_shaderfx_remove(
- Main *bmain, Object *ob, ShaderFxData *fx,
- bool *UNUSED(r_sort_depsgraph))
+static bool object_shaderfx_remove(Main *bmain,
+ Object *ob,
+ ShaderFxData *fx,
+ bool *UNUSED(r_sort_depsgraph))
{
- /* It seems on rapid delete it is possible to
- * get called twice on same effect, so make
- * sure it is in list. */
- if (BLI_findindex(&ob->shader_fx, fx) == -1) {
- return 0;
- }
+ /* It seems on rapid delete it is possible to
+ * get called twice on same effect, so make
+ * sure it is in list. */
+ if (BLI_findindex(&ob->shader_fx, fx) == -1) {
+ return 0;
+ }
- DEG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
- BLI_remlink(&ob->shader_fx, fx);
- BKE_shaderfx_free(fx);
- BKE_object_free_derived_caches(ob);
+ BLI_remlink(&ob->shader_fx, fx);
+ BKE_shaderfx_free(fx);
+ BKE_object_free_derived_caches(ob);
- return 1;
+ return 1;
}
bool ED_object_shaderfx_remove(ReportList *reports, Main *bmain, Object *ob, ShaderFxData *fx)
{
- bool sort_depsgraph = false;
- bool ok;
+ bool sort_depsgraph = false;
+ bool ok;
- ok = object_shaderfx_remove(bmain, ob, fx, &sort_depsgraph);
+ ok = object_shaderfx_remove(bmain, ob, fx, &sort_depsgraph);
- if (!ok) {
- BKE_reportf(reports, RPT_ERROR, "Effect '%s' not in object '%s'", fx->name, ob->id.name);
- return 0;
- }
+ if (!ok) {
+ BKE_reportf(reports, RPT_ERROR, "Effect '%s' not in object '%s'", fx->name, ob->id.name);
+ return 0;
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(bmain);
- return 1;
+ return 1;
}
void ED_object_shaderfx_clear(Main *bmain, Object *ob)
{
- ShaderFxData *fx = ob->shader_fx.first;
- bool sort_depsgraph = false;
+ ShaderFxData *fx = ob->shader_fx.first;
+ bool sort_depsgraph = false;
- if (!fx)
- return;
+ if (!fx)
+ return;
- while (fx) {
- ShaderFxData *next_fx;
+ while (fx) {
+ ShaderFxData *next_fx;
- next_fx = fx->next;
+ next_fx = fx->next;
- object_shaderfx_remove(bmain, ob, fx, &sort_depsgraph);
+ object_shaderfx_remove(bmain, ob, fx, &sort_depsgraph);
- fx = next_fx;
- }
+ fx = next_fx;
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(bmain);
}
int ED_object_shaderfx_move_up(ReportList *UNUSED(reports), Object *ob, ShaderFxData *fx)
{
- if (fx->prev) {
- BLI_remlink(&ob->shader_fx, fx);
- BLI_insertlinkbefore(&ob->shader_fx, fx->prev, fx);
- }
+ if (fx->prev) {
+ BLI_remlink(&ob->shader_fx, fx);
+ BLI_insertlinkbefore(&ob->shader_fx, fx->prev, fx);
+ }
- return 1;
+ return 1;
}
int ED_object_shaderfx_move_down(ReportList *UNUSED(reports), Object *ob, ShaderFxData *fx)
{
- if (fx->next) {
- BLI_remlink(&ob->shader_fx, fx);
- BLI_insertlinkafter(&ob->shader_fx, fx->next, fx);
- }
+ if (fx->next) {
+ BLI_remlink(&ob->shader_fx, fx);
+ BLI_insertlinkafter(&ob->shader_fx, fx->next, fx);
+ }
- return 1;
+ return 1;
}
/************************ add effect operator *********************/
static int shaderfx_add_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_active_context(C);
- int type = RNA_enum_get(op->ptr, "type");
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *ob = ED_object_active_context(C);
+ int type = RNA_enum_get(op->ptr, "type");
- if (!ED_object_shaderfx_add(op->reports, bmain, scene, ob, NULL, type))
- return OPERATOR_CANCELLED;
+ if (!ED_object_shaderfx_add(op->reports, bmain, scene, ob, NULL, type))
+ return OPERATOR_CANCELLED;
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static const EnumPropertyItem *shaderfx_add_itemf(
- bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *shaderfx_add_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- Object *ob = ED_object_active_context(C);
- EnumPropertyItem *item = NULL;
- const EnumPropertyItem *fx_item, *group_item = NULL;
- const ShaderFxTypeInfo *mti;
- int totitem = 0, a;
-
- if (!ob)
- return rna_enum_object_shaderfx_type_items;
-
- for (a = 0; rna_enum_object_shaderfx_type_items[a].identifier; a++) {
- fx_item = &rna_enum_object_shaderfx_type_items[a];
- if (fx_item->identifier[0]) {
- mti = BKE_shaderfxType_getInfo(fx_item->value);
-
- if (mti->flags & eShaderFxTypeFlag_NoUserAdd)
- continue;
- }
- else {
- group_item = fx_item;
- fx_item = NULL;
-
- continue;
- }
-
- if (group_item) {
- RNA_enum_item_add(&item, &totitem, group_item);
- group_item = NULL;
- }
-
- RNA_enum_item_add(&item, &totitem, fx_item);
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ Object *ob = ED_object_active_context(C);
+ EnumPropertyItem *item = NULL;
+ const EnumPropertyItem *fx_item, *group_item = NULL;
+ const ShaderFxTypeInfo *mti;
+ int totitem = 0, a;
+
+ if (!ob)
+ return rna_enum_object_shaderfx_type_items;
+
+ for (a = 0; rna_enum_object_shaderfx_type_items[a].identifier; a++) {
+ fx_item = &rna_enum_object_shaderfx_type_items[a];
+ if (fx_item->identifier[0]) {
+ mti = BKE_shaderfxType_getInfo(fx_item->value);
+
+ if (mti->flags & eShaderFxTypeFlag_NoUserAdd)
+ continue;
+ }
+ else {
+ group_item = fx_item;
+ fx_item = NULL;
+
+ continue;
+ }
+
+ if (group_item) {
+ RNA_enum_item_add(&item, &totitem, group_item);
+ group_item = NULL;
+ }
+
+ RNA_enum_item_add(&item, &totitem, fx_item);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
void OBJECT_OT_shaderfx_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Effect";
- ot->description = "Add a visual effect to the active object";
- ot->idname = "OBJECT_OT_shaderfx_add";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = shaderfx_add_exec;
- ot->poll = ED_operator_object_active_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_shaderfx_type_items, eShaderFxType_Blur, "Type", "");
- RNA_def_enum_funcs(ot->prop, shaderfx_add_itemf);
- RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_ID); /* Abused, for "Light"... */
+ /* identifiers */
+ ot->name = "Add Effect";
+ ot->description = "Add a visual effect to the active object";
+ ot->idname = "OBJECT_OT_shaderfx_add";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = shaderfx_add_exec;
+ ot->poll = ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(
+ ot->srna, "type", rna_enum_object_shaderfx_type_items, eShaderFxType_Blur, "Type", "");
+ RNA_def_enum_funcs(ot->prop, shaderfx_add_itemf);
+ RNA_def_property_translation_context(ot->prop,
+ BLT_I18NCONTEXT_ID_ID); /* Abused, for "Light"... */
}
/************************ generic functions for operators using names and data context *********************/
static bool edit_shaderfx_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "shaderfx", rna_type);
- Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
-
- if (!ptr.data) {
- CTX_wm_operator_poll_msg_set(C, "Context missing 'shaderfx'");
- return 0;
- }
-
- if (!ob || ID_IS_LINKED(ob)) return 0;
- if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) return 0;
- if (ptr.id.data && ID_IS_LINKED(ptr.id.data)) return 0;
-
- if (ID_IS_STATIC_OVERRIDE(ob)) {
- CTX_wm_operator_poll_msg_set(C, "Cannot edit shaderfxs coming from static override");
- return (((ShaderFxData *)ptr.data)->flag & eShaderFxFlag_StaticOverride_Local) != 0;
- }
-
- return 1;
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "shaderfx", rna_type);
+ Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
+
+ if (!ptr.data) {
+ CTX_wm_operator_poll_msg_set(C, "Context missing 'shaderfx'");
+ return 0;
+ }
+
+ if (!ob || ID_IS_LINKED(ob))
+ return 0;
+ if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0)
+ return 0;
+ if (ptr.id.data && ID_IS_LINKED(ptr.id.data))
+ return 0;
+
+ if (ID_IS_STATIC_OVERRIDE(ob)) {
+ CTX_wm_operator_poll_msg_set(C, "Cannot edit shaderfxs coming from static override");
+ return (((ShaderFxData *)ptr.data)->flag & eShaderFxFlag_StaticOverride_Local) != 0;
+ }
+
+ return 1;
}
static bool edit_shaderfx_poll(bContext *C)
{
- return edit_shaderfx_poll_generic(C, &RNA_ShaderFx, 0);
+ return edit_shaderfx_poll_generic(C, &RNA_ShaderFx, 0);
}
static void edit_shaderfx_properties(wmOperatorType *ot)
{
- PropertyRNA *prop = RNA_def_string(ot->srna, "shaderfx", NULL, MAX_NAME, "Shader", "Name of the shaderfx to edit");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ PropertyRNA *prop = RNA_def_string(
+ ot->srna, "shaderfx", NULL, MAX_NAME, "Shader", "Name of the shaderfx to edit");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
static int edit_shaderfx_invoke_properties(bContext *C, wmOperator *op)
{
- ShaderFxData *fx;
-
- if (RNA_struct_property_is_set(op->ptr, "shaderfx")) {
- return true;
- }
- else {
- PointerRNA ptr = CTX_data_pointer_get_type(C, "shaderfx", &RNA_ShaderFx);
- if (ptr.data) {
- fx = ptr.data;
- RNA_string_set(op->ptr, "shaderfx", fx->name);
- return true;
- }
- }
-
- return false;
+ ShaderFxData *fx;
+
+ if (RNA_struct_property_is_set(op->ptr, "shaderfx")) {
+ return true;
+ }
+ else {
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "shaderfx", &RNA_ShaderFx);
+ if (ptr.data) {
+ fx = ptr.data;
+ RNA_string_set(op->ptr, "shaderfx", fx->name);
+ return true;
+ }
+ }
+
+ return false;
}
static ShaderFxData *edit_shaderfx_property_get(wmOperator *op, Object *ob, int type)
{
- char shaderfx_name[MAX_NAME];
- ShaderFxData *fx;
- RNA_string_get(op->ptr, "shaderfx", shaderfx_name);
+ char shaderfx_name[MAX_NAME];
+ ShaderFxData *fx;
+ RNA_string_get(op->ptr, "shaderfx", shaderfx_name);
- fx = BKE_shaderfx_findByName(ob, shaderfx_name);
+ fx = BKE_shaderfx_findByName(ob, shaderfx_name);
- if (fx && type != 0 && fx->type != type)
- fx = NULL;
+ if (fx && type != 0 && fx->type != type)
+ fx = NULL;
- return fx;
+ return fx;
}
/************************ remove shaderfx operator *********************/
static int shaderfx_remove_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_active_context(C);
- ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0);
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_active_context(C);
+ ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0);
- if (!fx || !ED_object_shaderfx_remove(op->reports, bmain, ob, fx))
- return OPERATOR_CANCELLED;
+ if (!fx || !ED_object_shaderfx_remove(op->reports, bmain, ob, fx))
+ return OPERATOR_CANCELLED;
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int shaderfx_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_shaderfx_invoke_properties(C, op))
- return shaderfx_remove_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_shaderfx_invoke_properties(C, op))
+ return shaderfx_remove_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
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->idname = "OBJECT_OT_shaderfx_remove";
+ ot->name = "Remove Grease Pencil Modifier";
+ ot->description = "Remove a shaderfx from the active grease pencil object";
+ ot->idname = "OBJECT_OT_shaderfx_remove";
- ot->invoke = shaderfx_remove_invoke;
- ot->exec = shaderfx_remove_exec;
- ot->poll = edit_shaderfx_poll;
+ ot->invoke = shaderfx_remove_invoke;
+ ot->exec = shaderfx_remove_exec;
+ ot->poll = edit_shaderfx_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_shaderfx_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_shaderfx_properties(ot);
}
/************************ move up shaderfx operator *********************/
static int shaderfx_move_up_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0);
+ Object *ob = ED_object_active_context(C);
+ ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0);
- if (!fx || !ED_object_shaderfx_move_up(op->reports, ob, fx))
- return OPERATOR_CANCELLED;
+ if (!fx || !ED_object_shaderfx_move_up(op->reports, ob, fx))
+ return OPERATOR_CANCELLED;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int shaderfx_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_shaderfx_invoke_properties(C, op))
- return shaderfx_move_up_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_shaderfx_invoke_properties(C, op))
+ return shaderfx_move_up_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_shaderfx_move_up(wmOperatorType *ot)
{
- ot->name = "Move Up Modifier";
- ot->description = "Move shaderfx up in the stack";
- ot->idname = "OBJECT_OT_shaderfx_move_up";
+ ot->name = "Move Up Modifier";
+ ot->description = "Move shaderfx up in the stack";
+ ot->idname = "OBJECT_OT_shaderfx_move_up";
- ot->invoke = shaderfx_move_up_invoke;
- ot->exec = shaderfx_move_up_exec;
- ot->poll = edit_shaderfx_poll;
+ ot->invoke = shaderfx_move_up_invoke;
+ ot->exec = shaderfx_move_up_exec;
+ ot->poll = edit_shaderfx_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_shaderfx_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_shaderfx_properties(ot);
}
/************************ move down shaderfx operator *********************/
static int shaderfx_move_down_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_active_context(C);
- ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0);
+ Object *ob = ED_object_active_context(C);
+ ShaderFxData *fx = edit_shaderfx_property_get(op, ob, 0);
- if (!fx || !ED_object_shaderfx_move_down(op->reports, ob, fx))
- return OPERATOR_CANCELLED;
+ if (!fx || !ED_object_shaderfx_move_down(op->reports, ob, fx))
+ return OPERATOR_CANCELLED;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
static int shaderfx_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_shaderfx_invoke_properties(C, op))
- return shaderfx_move_down_exec(C, op);
- else
- return OPERATOR_CANCELLED;
+ if (edit_shaderfx_invoke_properties(C, op))
+ return shaderfx_move_down_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
}
void OBJECT_OT_shaderfx_move_down(wmOperatorType *ot)
{
- ot->name = "Move Down Modifier";
- ot->description = "Move shaderfx down in the stack";
- ot->idname = "OBJECT_OT_shaderfx_move_down";
+ ot->name = "Move Down Modifier";
+ ot->description = "Move shaderfx down in the stack";
+ ot->idname = "OBJECT_OT_shaderfx_move_down";
- ot->invoke = shaderfx_move_down_invoke;
- ot->exec = shaderfx_move_down_exec;
- ot->poll = edit_shaderfx_poll;
+ ot->invoke = shaderfx_move_down_invoke;
+ ot->exec = shaderfx_move_down_exec;
+ ot->poll = edit_shaderfx_poll;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_shaderfx_properties(ot);
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_shaderfx_properties(ot);
}
diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c
index d445177f236..aa0c6cbeef4 100644
--- a/source/blender/editors/object/object_shapekey.c
+++ b/source/blender/editors/object/object_shapekey.c
@@ -21,14 +21,13 @@
* \ingroup edobj
*/
-
#include <math.h>
#include <string.h>
#ifndef WIN32
-#include <unistd.h>
+# include <unistd.h>
#else
-#include <io.h>
+# include <io.h>
#endif
#include "MEM_guardedalloc.h"
@@ -54,7 +53,7 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
-#include "BLI_sys_types.h" // for intptr_t support
+#include "BLI_sys_types.h" // for intptr_t support
#include "ED_object.h"
#include "ED_mesh.h"
@@ -71,429 +70,434 @@
static void ED_object_shape_key_add(bContext *C, Object *ob, const bool from_mix)
{
- Main *bmain = CTX_data_main(C);
- KeyBlock *kb;
- if ((kb = BKE_object_shapekey_insert(bmain, ob, NULL, from_mix))) {
- Key *key = BKE_key_from_object(ob);
- /* for absolute shape keys, new keys may not be added last */
- ob->shapenr = BLI_findindex(&key->block, kb) + 1;
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- }
+ Main *bmain = CTX_data_main(C);
+ KeyBlock *kb;
+ if ((kb = BKE_object_shapekey_insert(bmain, ob, NULL, from_mix))) {
+ Key *key = BKE_key_from_object(ob);
+ /* for absolute shape keys, new keys may not be added last */
+ ob->shapenr = BLI_findindex(&key->block, kb) + 1;
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
}
/*********************** remove shape key ***********************/
static bool object_shapekey_remove(Main *bmain, Object *ob)
{
- KeyBlock *kb;
- Key *key = BKE_key_from_object(ob);
+ KeyBlock *kb;
+ Key *key = BKE_key_from_object(ob);
- if (key == NULL) {
- return false;
- }
+ if (key == NULL) {
+ return false;
+ }
- kb = BLI_findlink(&key->block, ob->shapenr - 1);
- if (kb) {
- return BKE_object_shapekey_remove(bmain, ob, kb);
- }
+ kb = BLI_findlink(&key->block, ob->shapenr - 1);
+ if (kb) {
+ return BKE_object_shapekey_remove(bmain, ob, kb);
+ }
- return false;
+ return false;
}
-static bool object_shape_key_mirror(bContext *C, Object *ob,
- int *r_totmirr, int *r_totfail, bool use_topology)
+static bool object_shape_key_mirror(
+ bContext *C, Object *ob, int *r_totmirr, int *r_totfail, bool use_topology)
{
- KeyBlock *kb;
- Key *key;
- int totmirr = 0, totfail = 0;
-
- *r_totmirr = *r_totfail = 0;
-
- key = BKE_key_from_object(ob);
- if (key == NULL)
- return 0;
-
- kb = BLI_findlink(&key->block, ob->shapenr - 1);
-
- if (kb) {
- char *tag_elem = MEM_callocN(sizeof(char) * kb->totelem, "shape_key_mirror");
-
-
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
- MVert *mv;
- int i1, i2;
- float *fp1, *fp2;
- float tvec[3];
-
- ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 's');
-
- for (i1 = 0, mv = me->mvert; i1 < me->totvert; i1++, mv++) {
- i2 = mesh_get_x_mirror_vert(ob, NULL, i1, use_topology);
- if (i2 == i1) {
- fp1 = ((float *)kb->data) + i1 * 3;
- fp1[0] = -fp1[0];
- tag_elem[i1] = 1;
- totmirr++;
- }
- else if (i2 != -1) {
- if (tag_elem[i1] == 0 && tag_elem[i2] == 0) {
- fp1 = ((float *)kb->data) + i1 * 3;
- fp2 = ((float *)kb->data) + i2 * 3;
-
- copy_v3_v3(tvec, fp1);
- copy_v3_v3(fp1, fp2);
- copy_v3_v3(fp2, tvec);
-
- /* flip x axis */
- fp1[0] = -fp1[0];
- fp2[0] = -fp2[0];
- totmirr++;
- }
- tag_elem[i1] = tag_elem[i2] = 1;
- }
- else {
- totfail++;
- }
- }
-
- ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 'e');
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = ob->data;
- int i1, i2;
- float *fp1, *fp2;
- int u, v, w;
- /* half but found up odd value */
- const int pntsu_half = (lt->pntsu / 2) + (lt->pntsu % 2);
-
- /* currently editmode isn't supported by mesh so
- * ignore here for now too */
-
- /* if (lt->editlatt) lt = lt->editlatt->latt; */
-
- for (w = 0; w < lt->pntsw; w++) {
- for (v = 0; v < lt->pntsv; v++) {
- for (u = 0; u < pntsu_half; u++) {
- int u_inv = (lt->pntsu - 1) - u;
- float tvec[3];
- if (u == u_inv) {
- i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
- fp1 = ((float *)kb->data) + i1 * 3;
- fp1[0] = -fp1[0];
- totmirr++;
- }
- else {
- i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
- i2 = BKE_lattice_index_from_uvw(lt, u_inv, v, w);
-
- fp1 = ((float *)kb->data) + i1 * 3;
- fp2 = ((float *)kb->data) + i2 * 3;
-
- copy_v3_v3(tvec, fp1);
- copy_v3_v3(fp1, fp2);
- copy_v3_v3(fp2, tvec);
- fp1[0] = -fp1[0];
- fp2[0] = -fp2[0];
- totmirr++;
- }
- }
- }
- }
- }
-
- MEM_freeN(tag_elem);
- }
-
- *r_totmirr = totmirr;
- *r_totfail = totfail;
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- return 1;
+ KeyBlock *kb;
+ Key *key;
+ int totmirr = 0, totfail = 0;
+
+ *r_totmirr = *r_totfail = 0;
+
+ key = BKE_key_from_object(ob);
+ if (key == NULL)
+ return 0;
+
+ kb = BLI_findlink(&key->block, ob->shapenr - 1);
+
+ if (kb) {
+ char *tag_elem = MEM_callocN(sizeof(char) * kb->totelem, "shape_key_mirror");
+
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ MVert *mv;
+ int i1, i2;
+ float *fp1, *fp2;
+ float tvec[3];
+
+ ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 's');
+
+ for (i1 = 0, mv = me->mvert; i1 < me->totvert; i1++, mv++) {
+ i2 = mesh_get_x_mirror_vert(ob, NULL, i1, use_topology);
+ if (i2 == i1) {
+ fp1 = ((float *)kb->data) + i1 * 3;
+ fp1[0] = -fp1[0];
+ tag_elem[i1] = 1;
+ totmirr++;
+ }
+ else if (i2 != -1) {
+ if (tag_elem[i1] == 0 && tag_elem[i2] == 0) {
+ fp1 = ((float *)kb->data) + i1 * 3;
+ fp2 = ((float *)kb->data) + i2 * 3;
+
+ copy_v3_v3(tvec, fp1);
+ copy_v3_v3(fp1, fp2);
+ copy_v3_v3(fp2, tvec);
+
+ /* flip x axis */
+ fp1[0] = -fp1[0];
+ fp2[0] = -fp2[0];
+ totmirr++;
+ }
+ tag_elem[i1] = tag_elem[i2] = 1;
+ }
+ else {
+ totfail++;
+ }
+ }
+
+ ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 'e');
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = ob->data;
+ int i1, i2;
+ float *fp1, *fp2;
+ int u, v, w;
+ /* half but found up odd value */
+ const int pntsu_half = (lt->pntsu / 2) + (lt->pntsu % 2);
+
+ /* currently editmode isn't supported by mesh so
+ * ignore here for now too */
+
+ /* if (lt->editlatt) lt = lt->editlatt->latt; */
+
+ for (w = 0; w < lt->pntsw; w++) {
+ for (v = 0; v < lt->pntsv; v++) {
+ for (u = 0; u < pntsu_half; u++) {
+ int u_inv = (lt->pntsu - 1) - u;
+ float tvec[3];
+ if (u == u_inv) {
+ i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
+ fp1 = ((float *)kb->data) + i1 * 3;
+ fp1[0] = -fp1[0];
+ totmirr++;
+ }
+ else {
+ i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
+ i2 = BKE_lattice_index_from_uvw(lt, u_inv, v, w);
+
+ fp1 = ((float *)kb->data) + i1 * 3;
+ fp2 = ((float *)kb->data) + i2 * 3;
+
+ copy_v3_v3(tvec, fp1);
+ copy_v3_v3(fp1, fp2);
+ copy_v3_v3(fp2, tvec);
+ fp1[0] = -fp1[0];
+ fp2[0] = -fp2[0];
+ totmirr++;
+ }
+ }
+ }
+ }
+ }
+
+ MEM_freeN(tag_elem);
+ }
+
+ *r_totmirr = totmirr;
+ *r_totfail = totfail;
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return 1;
}
/********************** shape key operators *********************/
static bool shape_key_mode_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);
+ 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);
}
static bool shape_key_mode_exists_poll(bContext *C)
{
- Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
+ 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);
+ /* 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);
}
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;
- Key *key = BKE_key_from_object(ob);
+ /* 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 (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data) && ob->mode != OB_MODE_EDIT &&
+ key && key->totkey > 1);
}
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));
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
+ return (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data));
}
static int shape_key_add_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- const bool from_mix = RNA_boolean_get(op->ptr, "from_mix");
+ Object *ob = ED_object_context(C);
+ const bool from_mix = RNA_boolean_get(op->ptr, "from_mix");
- ED_object_shape_key_add(C, ob, from_mix);
+ ED_object_shape_key_add(C, ob, from_mix);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(CTX_data_main(C));
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(CTX_data_main(C));
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_shape_key_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Shape Key";
- ot->idname = "OBJECT_OT_shape_key_add";
- ot->description = "Add shape key to the object";
-
- /* api callbacks */
- ot->poll = shape_key_mode_poll;
- ot->exec = shape_key_add_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "from_mix", true, "From Mix", "Create the new shape key from the existing mix of keys");
+ /* identifiers */
+ ot->name = "Add Shape Key";
+ ot->idname = "OBJECT_OT_shape_key_add";
+ ot->description = "Add shape key to the object";
+
+ /* api callbacks */
+ ot->poll = shape_key_mode_poll;
+ ot->exec = shape_key_add_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna,
+ "from_mix",
+ true,
+ "From Mix",
+ "Create the new shape key from the existing mix of keys");
}
static int shape_key_remove_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *ob = ED_object_context(C);
- bool changed = false;
-
- if (RNA_boolean_get(op->ptr, "all")) {
- changed = BKE_object_shapekey_free(bmain, ob);
- }
- else {
- changed = object_shapekey_remove(bmain, ob);
- }
-
- if (changed) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- DEG_relations_tag_update(CTX_data_main(C));
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Main *bmain = CTX_data_main(C);
+ Object *ob = ED_object_context(C);
+ bool changed = false;
+
+ if (RNA_boolean_get(op->ptr, "all")) {
+ changed = BKE_object_shapekey_free(bmain, ob);
+ }
+ else {
+ changed = object_shapekey_remove(bmain, ob);
+ }
+
+ if (changed) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ DEG_relations_tag_update(CTX_data_main(C));
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void OBJECT_OT_shape_key_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Shape Key";
- ot->idname = "OBJECT_OT_shape_key_remove";
- ot->description = "Remove shape key from the object";
+ /* identifiers */
+ ot->name = "Remove Shape Key";
+ ot->idname = "OBJECT_OT_shape_key_remove";
+ ot->description = "Remove shape key from the object";
- /* api callbacks */
- ot->poll = shape_key_mode_exists_poll;
- ot->exec = shape_key_remove_exec;
+ /* api callbacks */
+ ot->poll = shape_key_mode_exists_poll;
+ ot->exec = shape_key_remove_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* properties */
- RNA_def_boolean(ot->srna, "all", 0, "All", "Remove all shape keys");
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", 0, "All", "Remove all shape keys");
}
static int shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- Key *key = BKE_key_from_object(ob);
- KeyBlock *kb = BKE_keyblock_from_object(ob);
+ Object *ob = ED_object_context(C);
+ Key *key = BKE_key_from_object(ob);
+ KeyBlock *kb = BKE_keyblock_from_object(ob);
- if (!key || !kb)
- return OPERATOR_CANCELLED;
+ if (!key || !kb)
+ return OPERATOR_CANCELLED;
- for (kb = key->block.first; kb; kb = kb->next)
- kb->curval = 0.0f;
+ for (kb = key->block.first; kb; kb = kb->next)
+ kb->curval = 0.0f;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_shape_key_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Shape Keys";
- ot->description = "Clear weights for all shape keys";
- ot->idname = "OBJECT_OT_shape_key_clear";
+ /* identifiers */
+ ot->name = "Clear Shape Keys";
+ ot->description = "Clear weights for all shape keys";
+ ot->idname = "OBJECT_OT_shape_key_clear";
- /* api callbacks */
- ot->poll = shape_key_poll;
- ot->exec = shape_key_clear_exec;
+ /* api callbacks */
+ ot->poll = shape_key_poll;
+ ot->exec = shape_key_clear_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/* starting point and step size could be optional */
static int shape_key_retime_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- Key *key = BKE_key_from_object(ob);
- KeyBlock *kb = BKE_keyblock_from_object(ob);
- float cfra = 0.0f;
+ Object *ob = ED_object_context(C);
+ Key *key = BKE_key_from_object(ob);
+ KeyBlock *kb = BKE_keyblock_from_object(ob);
+ float cfra = 0.0f;
- if (!key || !kb)
- return OPERATOR_CANCELLED;
+ if (!key || !kb)
+ return OPERATOR_CANCELLED;
- for (kb = key->block.first; kb; kb = kb->next) {
- kb->pos = cfra;
- cfra += 0.1f;
- }
+ for (kb = key->block.first; kb; kb = kb->next) {
+ kb->pos = cfra;
+ cfra += 0.1f;
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_shape_key_retime(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Re-Time Shape Keys";
- ot->description = "Resets the timing for absolute shape keys";
- ot->idname = "OBJECT_OT_shape_key_retime";
+ /* identifiers */
+ ot->name = "Re-Time Shape Keys";
+ ot->description = "Resets the timing for absolute shape keys";
+ ot->idname = "OBJECT_OT_shape_key_retime";
- /* api callbacks */
- ot->poll = shape_key_poll;
- ot->exec = shape_key_retime_exec;
+ /* api callbacks */
+ ot->poll = shape_key_poll;
+ ot->exec = shape_key_retime_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int shape_key_mirror_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- int totmirr = 0, totfail = 0;
- bool use_topology = RNA_boolean_get(op->ptr, "use_topology");
+ Object *ob = ED_object_context(C);
+ int totmirr = 0, totfail = 0;
+ bool use_topology = RNA_boolean_get(op->ptr, "use_topology");
- if (!object_shape_key_mirror(C, ob, &totmirr, &totfail, use_topology))
- return OPERATOR_CANCELLED;
+ if (!object_shape_key_mirror(C, ob, &totmirr, &totfail, use_topology))
+ return OPERATOR_CANCELLED;
- ED_mesh_report_mirror(op, totmirr, totfail);
+ ED_mesh_report_mirror(op, totmirr, totfail);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_shape_key_mirror(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Mirror Shape Key";
- ot->idname = "OBJECT_OT_shape_key_mirror";
- ot->description = "Mirror the current shape key along the local X axis";
-
- /* api callbacks */
- ot->poll = shape_key_mode_poll;
- ot->exec = shape_key_mirror_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "use_topology", 0, "Topology Mirror",
- "Use topology based mirroring (for when both sides of mesh have matching, unique topology)");
+ /* identifiers */
+ ot->name = "Mirror Shape Key";
+ ot->idname = "OBJECT_OT_shape_key_mirror";
+ ot->description = "Mirror the current shape key along the local X axis";
+
+ /* api callbacks */
+ ot->poll = shape_key_mode_poll;
+ ot->exec = shape_key_mirror_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(
+ ot->srna,
+ "use_topology",
+ 0,
+ "Topology Mirror",
+ "Use topology based mirroring (for when both sides of mesh have matching, unique topology)");
}
-
enum {
- KB_MOVE_TOP = -2,
- KB_MOVE_UP = -1,
- KB_MOVE_DOWN = 1,
- KB_MOVE_BOTTOM = 2,
+ KB_MOVE_TOP = -2,
+ KB_MOVE_UP = -1,
+ KB_MOVE_DOWN = 1,
+ KB_MOVE_BOTTOM = 2,
};
static int shape_key_move_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
-
- Key *key = BKE_key_from_object(ob);
- const int type = RNA_enum_get(op->ptr, "type");
- const int totkey = key->totkey;
- const int act_index = ob->shapenr - 1;
- int new_index;
-
- switch (type) {
- case KB_MOVE_TOP:
- /* Replace the ref key only if we're at the top already (only for relative keys) */
- new_index = (ELEM(act_index, 0, 1) || key->type == KEY_NORMAL) ? 0 : 1;
- break;
- case KB_MOVE_BOTTOM:
- new_index = totkey - 1;
- break;
- case KB_MOVE_UP:
- case KB_MOVE_DOWN:
- default:
- new_index = (totkey + act_index + type) % totkey;
- break;
- }
-
- if (!BKE_keyblock_move(ob, act_index, new_index)) {
- return OPERATOR_CANCELLED;
- }
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- return OPERATOR_FINISHED;
+ Object *ob = ED_object_context(C);
+
+ Key *key = BKE_key_from_object(ob);
+ const int type = RNA_enum_get(op->ptr, "type");
+ const int totkey = key->totkey;
+ const int act_index = ob->shapenr - 1;
+ int new_index;
+
+ switch (type) {
+ case KB_MOVE_TOP:
+ /* Replace the ref key only if we're at the top already (only for relative keys) */
+ new_index = (ELEM(act_index, 0, 1) || key->type == KEY_NORMAL) ? 0 : 1;
+ break;
+ case KB_MOVE_BOTTOM:
+ new_index = totkey - 1;
+ break;
+ case KB_MOVE_UP:
+ case KB_MOVE_DOWN:
+ default:
+ new_index = (totkey + act_index + type) % totkey;
+ break;
+ }
+
+ if (!BKE_keyblock_move(ob, act_index, new_index)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_shape_key_move(wmOperatorType *ot)
{
- static const EnumPropertyItem slot_move[] = {
- {KB_MOVE_TOP, "TOP", 0, "Top", "Top of the list"},
- {KB_MOVE_UP, "UP", 0, "Up", ""},
- {KB_MOVE_DOWN, "DOWN", 0, "Down", ""},
- {KB_MOVE_BOTTOM, "BOTTOM", 0, "Bottom", "Bottom of the list"},
- { 0, NULL, 0, NULL, NULL }
- };
-
- /* identifiers */
- ot->name = "Move Shape Key";
- ot->idname = "OBJECT_OT_shape_key_move";
- ot->description = "Move the active shape key up/down in the list";
-
- /* api callbacks */
- ot->poll = shape_key_move_poll;
- ot->exec = shape_key_move_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
+ static const EnumPropertyItem slot_move[] = {
+ {KB_MOVE_TOP, "TOP", 0, "Top", "Top of the list"},
+ {KB_MOVE_UP, "UP", 0, "Up", ""},
+ {KB_MOVE_DOWN, "DOWN", 0, "Down", ""},
+ {KB_MOVE_BOTTOM, "BOTTOM", 0, "Bottom", "Bottom of the list"},
+ {0, NULL, 0, NULL, NULL}};
+
+ /* identifiers */
+ ot->name = "Move Shape Key";
+ ot->idname = "OBJECT_OT_shape_key_move";
+ ot->description = "Move the active shape key up/down in the list";
+
+ /* api callbacks */
+ ot->poll = shape_key_move_poll;
+ ot->exec = shape_key_move_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
}
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index f7a49f3fcb7..f2f6afcac81 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -21,7 +21,6 @@
* \ingroup edobj
*/
-
#include <stdlib.h>
#include <string.h>
@@ -80,321 +79,353 @@
/* clear location of object */
static void object_clear_loc(Object *ob, const bool clear_delta)
{
- /* clear location if not locked */
- if ((ob->protectflag & OB_LOCK_LOCX) == 0) {
- ob->loc[0] = 0.0f;
- if (clear_delta) ob->dloc[0] = 0.0f;
- }
- if ((ob->protectflag & OB_LOCK_LOCY) == 0) {
- ob->loc[1] = 0.0f;
- if (clear_delta) ob->dloc[1] = 0.0f;
- }
- if ((ob->protectflag & OB_LOCK_LOCZ) == 0) {
- ob->loc[2] = 0.0f;
- if (clear_delta) ob->dloc[2] = 0.0f;
- }
+ /* clear location if not locked */
+ if ((ob->protectflag & OB_LOCK_LOCX) == 0) {
+ ob->loc[0] = 0.0f;
+ if (clear_delta)
+ ob->dloc[0] = 0.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_LOCY) == 0) {
+ ob->loc[1] = 0.0f;
+ if (clear_delta)
+ ob->dloc[1] = 0.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_LOCZ) == 0) {
+ ob->loc[2] = 0.0f;
+ if (clear_delta)
+ ob->dloc[2] = 0.0f;
+ }
}
/* clear rotation of object */
static void object_clear_rot(Object *ob, const bool clear_delta)
{
- /* clear rotations that aren't locked */
- if (ob->protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) {
- if (ob->protectflag & OB_LOCK_ROT4D) {
- /* perform clamping on a component by component basis */
- if (ob->rotmode == ROT_MODE_AXISANGLE) {
- if ((ob->protectflag & OB_LOCK_ROTW) == 0) {
- ob->rotAngle = 0.0f;
- if (clear_delta) ob->drotAngle = 0.0f;
- }
- if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
- ob->rotAxis[0] = 0.0f;
- if (clear_delta) ob->drotAxis[0] = 0.0f;
- }
- if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
- ob->rotAxis[1] = 0.0f;
- if (clear_delta) ob->drotAxis[1] = 0.0f;
- }
- if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
- ob->rotAxis[2] = 0.0f;
- if (clear_delta) ob->drotAxis[2] = 0.0f;
- }
-
- /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */
- if (IS_EQF(ob->rotAxis[0], ob->rotAxis[1]) && IS_EQF(ob->rotAxis[1], ob->rotAxis[2]))
- ob->rotAxis[1] = 1.0f;
- if (IS_EQF(ob->drotAxis[0], ob->drotAxis[1]) && IS_EQF(ob->drotAxis[1], ob->drotAxis[2]) && clear_delta)
- ob->drotAxis[1] = 1.0f;
- }
- else if (ob->rotmode == ROT_MODE_QUAT) {
- if ((ob->protectflag & OB_LOCK_ROTW) == 0) {
- ob->quat[0] = 1.0f;
- if (clear_delta) ob->dquat[0] = 1.0f;
- }
- if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
- ob->quat[1] = 0.0f;
- if (clear_delta) ob->dquat[1] = 0.0f;
- }
- if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
- ob->quat[2] = 0.0f;
- if (clear_delta) ob->dquat[2] = 0.0f;
- }
- if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
- ob->quat[3] = 0.0f;
- if (clear_delta) ob->dquat[3] = 0.0f;
- }
- /* TODO: does this quat need normalizing now? */
- }
- else {
- /* the flag may have been set for the other modes, so just ignore the extra flag... */
- if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
- ob->rot[0] = 0.0f;
- if (clear_delta) ob->drot[0] = 0.0f;
- }
- if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
- ob->rot[1] = 0.0f;
- if (clear_delta) ob->drot[1] = 0.0f;
- }
- if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
- ob->rot[2] = 0.0f;
- if (clear_delta) ob->drot[2] = 0.0f;
- }
- }
- }
- else {
- /* perform clamping using euler form (3-components) */
- /* FIXME: deltas are not handled for these cases yet... */
- float eul[3], oldeul[3], quat1[4] = {0};
-
- if (ob->rotmode == ROT_MODE_QUAT) {
- copy_qt_qt(quat1, ob->quat);
- quat_to_eul(oldeul, ob->quat);
- }
- else if (ob->rotmode == ROT_MODE_AXISANGLE) {
- axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, ob->rotAxis, ob->rotAngle);
- }
- else {
- copy_v3_v3(oldeul, ob->rot);
- }
-
- eul[0] = eul[1] = eul[2] = 0.0f;
-
- if (ob->protectflag & OB_LOCK_ROTX)
- eul[0] = oldeul[0];
- if (ob->protectflag & OB_LOCK_ROTY)
- eul[1] = oldeul[1];
- if (ob->protectflag & OB_LOCK_ROTZ)
- eul[2] = oldeul[2];
-
- if (ob->rotmode == ROT_MODE_QUAT) {
- eul_to_quat(ob->quat, eul);
- /* quaternions flip w sign to accumulate rotations correctly */
- if ((quat1[0] < 0.0f && ob->quat[0] > 0.0f) || (quat1[0] > 0.0f && ob->quat[0] < 0.0f)) {
- mul_qt_fl(ob->quat, -1.0f);
- }
- }
- else if (ob->rotmode == ROT_MODE_AXISANGLE) {
- eulO_to_axis_angle(ob->rotAxis, &ob->rotAngle, eul, EULER_ORDER_DEFAULT);
- }
- else {
- copy_v3_v3(ob->rot, eul);
- }
- }
- } // Duplicated in source/blender/editors/armature/editarmature.c
- else {
- if (ob->rotmode == ROT_MODE_QUAT) {
- unit_qt(ob->quat);
- if (clear_delta) unit_qt(ob->dquat);
- }
- else if (ob->rotmode == ROT_MODE_AXISANGLE) {
- unit_axis_angle(ob->rotAxis, &ob->rotAngle);
- if (clear_delta) unit_axis_angle(ob->drotAxis, &ob->drotAngle);
- }
- else {
- zero_v3(ob->rot);
- if (clear_delta) zero_v3(ob->drot);
- }
- }
+ /* clear rotations that aren't locked */
+ if (ob->protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) {
+ if (ob->protectflag & OB_LOCK_ROT4D) {
+ /* perform clamping on a component by component basis */
+ if (ob->rotmode == ROT_MODE_AXISANGLE) {
+ if ((ob->protectflag & OB_LOCK_ROTW) == 0) {
+ ob->rotAngle = 0.0f;
+ if (clear_delta)
+ ob->drotAngle = 0.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
+ ob->rotAxis[0] = 0.0f;
+ if (clear_delta)
+ ob->drotAxis[0] = 0.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
+ ob->rotAxis[1] = 0.0f;
+ if (clear_delta)
+ ob->drotAxis[1] = 0.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
+ ob->rotAxis[2] = 0.0f;
+ if (clear_delta)
+ ob->drotAxis[2] = 0.0f;
+ }
+
+ /* check validity of axis - axis should never be 0,0,0 (if so, then we make it rotate about y) */
+ if (IS_EQF(ob->rotAxis[0], ob->rotAxis[1]) && IS_EQF(ob->rotAxis[1], ob->rotAxis[2]))
+ ob->rotAxis[1] = 1.0f;
+ if (IS_EQF(ob->drotAxis[0], ob->drotAxis[1]) && IS_EQF(ob->drotAxis[1], ob->drotAxis[2]) &&
+ clear_delta)
+ ob->drotAxis[1] = 1.0f;
+ }
+ else if (ob->rotmode == ROT_MODE_QUAT) {
+ if ((ob->protectflag & OB_LOCK_ROTW) == 0) {
+ ob->quat[0] = 1.0f;
+ if (clear_delta)
+ ob->dquat[0] = 1.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
+ ob->quat[1] = 0.0f;
+ if (clear_delta)
+ ob->dquat[1] = 0.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
+ ob->quat[2] = 0.0f;
+ if (clear_delta)
+ ob->dquat[2] = 0.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
+ ob->quat[3] = 0.0f;
+ if (clear_delta)
+ ob->dquat[3] = 0.0f;
+ }
+ /* TODO: does this quat need normalizing now? */
+ }
+ else {
+ /* the flag may have been set for the other modes, so just ignore the extra flag... */
+ if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
+ ob->rot[0] = 0.0f;
+ if (clear_delta)
+ ob->drot[0] = 0.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
+ ob->rot[1] = 0.0f;
+ if (clear_delta)
+ ob->drot[1] = 0.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
+ ob->rot[2] = 0.0f;
+ if (clear_delta)
+ ob->drot[2] = 0.0f;
+ }
+ }
+ }
+ else {
+ /* perform clamping using euler form (3-components) */
+ /* FIXME: deltas are not handled for these cases yet... */
+ float eul[3], oldeul[3], quat1[4] = {0};
+
+ if (ob->rotmode == ROT_MODE_QUAT) {
+ copy_qt_qt(quat1, ob->quat);
+ quat_to_eul(oldeul, ob->quat);
+ }
+ else if (ob->rotmode == ROT_MODE_AXISANGLE) {
+ axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, ob->rotAxis, ob->rotAngle);
+ }
+ else {
+ copy_v3_v3(oldeul, ob->rot);
+ }
+
+ eul[0] = eul[1] = eul[2] = 0.0f;
+
+ if (ob->protectflag & OB_LOCK_ROTX)
+ eul[0] = oldeul[0];
+ if (ob->protectflag & OB_LOCK_ROTY)
+ eul[1] = oldeul[1];
+ if (ob->protectflag & OB_LOCK_ROTZ)
+ eul[2] = oldeul[2];
+
+ if (ob->rotmode == ROT_MODE_QUAT) {
+ eul_to_quat(ob->quat, eul);
+ /* quaternions flip w sign to accumulate rotations correctly */
+ if ((quat1[0] < 0.0f && ob->quat[0] > 0.0f) || (quat1[0] > 0.0f && ob->quat[0] < 0.0f)) {
+ mul_qt_fl(ob->quat, -1.0f);
+ }
+ }
+ else if (ob->rotmode == ROT_MODE_AXISANGLE) {
+ eulO_to_axis_angle(ob->rotAxis, &ob->rotAngle, eul, EULER_ORDER_DEFAULT);
+ }
+ else {
+ copy_v3_v3(ob->rot, eul);
+ }
+ }
+ } // Duplicated in source/blender/editors/armature/editarmature.c
+ else {
+ if (ob->rotmode == ROT_MODE_QUAT) {
+ unit_qt(ob->quat);
+ if (clear_delta)
+ unit_qt(ob->dquat);
+ }
+ else if (ob->rotmode == ROT_MODE_AXISANGLE) {
+ unit_axis_angle(ob->rotAxis, &ob->rotAngle);
+ if (clear_delta)
+ unit_axis_angle(ob->drotAxis, &ob->drotAngle);
+ }
+ else {
+ zero_v3(ob->rot);
+ if (clear_delta)
+ zero_v3(ob->drot);
+ }
+ }
}
/* clear scale of object */
static void object_clear_scale(Object *ob, const bool clear_delta)
{
- /* clear scale factors which are not locked */
- if ((ob->protectflag & OB_LOCK_SCALEX) == 0) {
- ob->scale[0] = 1.0f;
- if (clear_delta) ob->dscale[0] = 1.0f;
- }
- if ((ob->protectflag & OB_LOCK_SCALEY) == 0) {
- ob->scale[1] = 1.0f;
- if (clear_delta) ob->dscale[1] = 1.0f;
- }
- if ((ob->protectflag & OB_LOCK_SCALEZ) == 0) {
- ob->scale[2] = 1.0f;
- if (clear_delta) ob->dscale[2] = 1.0f;
- }
+ /* clear scale factors which are not locked */
+ if ((ob->protectflag & OB_LOCK_SCALEX) == 0) {
+ ob->scale[0] = 1.0f;
+ if (clear_delta)
+ ob->dscale[0] = 1.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_SCALEY) == 0) {
+ ob->scale[1] = 1.0f;
+ if (clear_delta)
+ ob->dscale[1] = 1.0f;
+ }
+ if ((ob->protectflag & OB_LOCK_SCALEZ) == 0) {
+ ob->scale[2] = 1.0f;
+ if (clear_delta)
+ ob->dscale[2] = 1.0f;
+ }
}
/* --------------- */
/* generic exec for clear-transform operators */
-static int object_clear_transform_generic_exec(bContext *C, wmOperator *op,
+static int object_clear_transform_generic_exec(bContext *C,
+ wmOperator *op,
void (*clear_func)(Object *, const bool),
const char default_ksName[])
{
- Scene *scene = CTX_data_scene(C);
- KeyingSet *ks;
- const bool clear_delta = RNA_boolean_get(op->ptr, "clear_delta");
-
- /* sanity checks */
- if (ELEM(NULL, clear_func, default_ksName)) {
- BKE_report(op->reports, RPT_ERROR, "Programming error: missing clear transform function or keying set name");
- return OPERATOR_CANCELLED;
- }
-
- /* get KeyingSet to use */
- ks = ANIM_get_keyingset_for_autokeying(scene, default_ksName);
-
- /* operate on selected objects only if they aren't in weight-paint mode
- * (so that object-transform clearing won't be applied at same time as bone-clearing)
- */
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if (!(ob->mode & OB_MODE_WEIGHT_PAINT)) {
- /* run provided clearing function */
- clear_func(ob, clear_delta);
-
- ED_autokeyframe_object(C, scene, ob, ks);
-
- /* tag for updates */
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- }
- }
- CTX_DATA_END;
-
- /* this is needed so children are also updated */
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-
- return OPERATOR_FINISHED;
+ Scene *scene = CTX_data_scene(C);
+ KeyingSet *ks;
+ const bool clear_delta = RNA_boolean_get(op->ptr, "clear_delta");
+
+ /* sanity checks */
+ if (ELEM(NULL, clear_func, default_ksName)) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Programming error: missing clear transform function or keying set name");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get KeyingSet to use */
+ ks = ANIM_get_keyingset_for_autokeying(scene, default_ksName);
+
+ /* operate on selected objects only if they aren't in weight-paint mode
+ * (so that object-transform clearing won't be applied at same time as bone-clearing)
+ */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (!(ob->mode & OB_MODE_WEIGHT_PAINT)) {
+ /* run provided clearing function */
+ clear_func(ob, clear_delta);
+
+ ED_autokeyframe_object(C, scene, ob, ks);
+
+ /* tag for updates */
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ }
+ }
+ CTX_DATA_END;
+
+ /* this is needed so children are also updated */
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
}
/* --------------- */
-
static int object_location_clear_exec(bContext *C, wmOperator *op)
{
- return object_clear_transform_generic_exec(C, op, object_clear_loc, ANIM_KS_LOCATION_ID);
+ return object_clear_transform_generic_exec(C, op, object_clear_loc, ANIM_KS_LOCATION_ID);
}
void OBJECT_OT_location_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Location";
- ot->description = "Clear the object's location";
- ot->idname = "OBJECT_OT_location_clear";
-
- /* api callbacks */
- ot->exec = object_location_clear_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
-
- /* properties */
- ot->prop = RNA_def_boolean(ot->srna, "clear_delta", false, "Clear Delta",
- "Clear delta location in addition to clearing the normal location transform");
+ /* identifiers */
+ ot->name = "Clear Location";
+ ot->description = "Clear the object's location";
+ ot->idname = "OBJECT_OT_location_clear";
+
+ /* api callbacks */
+ ot->exec = object_location_clear_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_boolean(
+ ot->srna,
+ "clear_delta",
+ false,
+ "Clear Delta",
+ "Clear delta location in addition to clearing the normal location transform");
}
static int object_rotation_clear_exec(bContext *C, wmOperator *op)
{
- return object_clear_transform_generic_exec(C, op, object_clear_rot, ANIM_KS_ROTATION_ID);
+ return object_clear_transform_generic_exec(C, op, object_clear_rot, ANIM_KS_ROTATION_ID);
}
void OBJECT_OT_rotation_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Rotation";
- ot->description = "Clear the object's rotation";
- ot->idname = "OBJECT_OT_rotation_clear";
-
- /* api callbacks */
- ot->exec = object_rotation_clear_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_boolean(ot->srna, "clear_delta", false, "Clear Delta",
- "Clear delta rotation in addition to clearing the normal rotation transform");
+ /* identifiers */
+ ot->name = "Clear Rotation";
+ ot->description = "Clear the object's rotation";
+ ot->idname = "OBJECT_OT_rotation_clear";
+
+ /* api callbacks */
+ ot->exec = object_rotation_clear_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_boolean(
+ ot->srna,
+ "clear_delta",
+ false,
+ "Clear Delta",
+ "Clear delta rotation in addition to clearing the normal rotation transform");
}
static int object_scale_clear_exec(bContext *C, wmOperator *op)
{
- return object_clear_transform_generic_exec(C, op, object_clear_scale, ANIM_KS_SCALING_ID);
+ return object_clear_transform_generic_exec(C, op, object_clear_scale, ANIM_KS_SCALING_ID);
}
void OBJECT_OT_scale_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Scale";
- ot->description = "Clear the object's scale";
- ot->idname = "OBJECT_OT_scale_clear";
-
- /* api callbacks */
- ot->exec = object_scale_clear_exec;
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- ot->prop = RNA_def_boolean(ot->srna, "clear_delta", false, "Clear Delta",
- "Clear delta scale in addition to clearing the normal scale transform");
+ /* identifiers */
+ ot->name = "Clear Scale";
+ ot->description = "Clear the object's scale";
+ ot->idname = "OBJECT_OT_scale_clear";
+
+ /* api callbacks */
+ ot->exec = object_scale_clear_exec;
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_boolean(
+ ot->srna,
+ "clear_delta",
+ false,
+ "Clear Delta",
+ "Clear delta scale in addition to clearing the normal scale transform");
}
/* --------------- */
static int object_origin_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- float *v1, *v3;
- float mat[3][3];
+ float *v1, *v3;
+ float mat[3][3];
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if (ob->parent) {
- /* vectors pointed to by v1 and v3 will get modified */
- v1 = ob->loc;
- v3 = ob->parentinv[3];
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (ob->parent) {
+ /* vectors pointed to by v1 and v3 will get modified */
+ v1 = ob->loc;
+ v3 = ob->parentinv[3];
- copy_m3_m4(mat, ob->parentinv);
- negate_v3_v3(v3, v1);
- mul_m3_v3(mat, v3);
- }
+ copy_m3_m4(mat, ob->parentinv);
+ negate_v3_v3(v3, v1);
+ mul_m3_v3(mat, v3);
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- }
- CTX_DATA_END;
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ }
+ CTX_DATA_END;
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_origin_clear(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clear Origin";
- ot->description = "Clear the object's origin";
- ot->idname = "OBJECT_OT_origin_clear";
+ /* identifiers */
+ ot->name = "Clear Origin";
+ ot->description = "Clear the object's origin";
+ ot->idname = "OBJECT_OT_origin_clear";
- /* api callbacks */
- ot->exec = object_origin_clear_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = object_origin_clear_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/*************************** Apply Transformation ****************************/
@@ -403,885 +434,947 @@ void OBJECT_OT_origin_clear(wmOperatorType *ot)
* should stay in the same place, e.g. for apply-size-rot or object center */
static void ignore_parent_tx(const bContext *C, Main *bmain, Scene *scene, Object *ob)
{
- Object workob;
- Object *ob_child;
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
-
- /* a change was made, adjust the children to compensate */
- for (ob_child = bmain->objects.first; ob_child; ob_child = ob_child->id.next) {
- if (ob_child->parent == ob) {
- BKE_object_apply_mat4(ob_child, ob_child->obmat, true, false);
- BKE_object_workob_calc_parent(depsgraph, scene, ob_child, &workob);
- invert_m4_m4(ob_child->parentinv, workob.obmat);
- }
- }
+ Object workob;
+ Object *ob_child;
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+
+ /* a change was made, adjust the children to compensate */
+ for (ob_child = bmain->objects.first; ob_child; ob_child = ob_child->id.next) {
+ if (ob_child->parent == ob) {
+ BKE_object_apply_mat4(ob_child, ob_child->obmat, true, false);
+ BKE_object_workob_calc_parent(depsgraph, scene, ob_child, &workob);
+ invert_m4_m4(ob_child->parentinv, workob.obmat);
+ }
+ }
}
-static int apply_objects_internal(
- bContext *C, ReportList *reports,
- bool apply_loc, bool apply_rot, bool apply_scale,
- bool do_props)
+static int apply_objects_internal(bContext *C,
+ ReportList *reports,
+ bool apply_loc,
+ bool apply_rot,
+ bool apply_scale,
+ bool do_props)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- float rsmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale;
- bool changed = true;
-
- /* first check if we can execute */
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if (ELEM(ob->type, OB_MESH, OB_ARMATURE, OB_LATTICE, OB_MBALL, OB_CURVE, OB_SURF, OB_FONT, OB_GPENCIL)) {
- ID *obdata = ob->data;
- if (ID_REAL_USERS(obdata) > 1) {
- BKE_reportf(reports, RPT_ERROR,
- "Cannot apply to a multi user: Object \"%s\", %s \"%s\", aborting",
- ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
- changed = false;
- }
-
- if (ID_IS_LINKED(obdata)) {
- BKE_reportf(reports, RPT_ERROR,
- "Cannot apply to library data: Object \"%s\", %s \"%s\", aborting",
- ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
- changed = false;
- }
- }
-
- if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
- ID *obdata = ob->data;
- Curve *cu;
-
- cu = ob->data;
-
- if (((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) && (apply_rot || apply_loc)) {
- BKE_reportf(reports, RPT_ERROR,
- "Rotation/Location can't apply to a 2D curve: Object \"%s\", %s \"%s\", aborting",
- ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
- changed = false;
- }
- if (cu->key) {
- BKE_reportf(reports, RPT_ERROR,
- "Can't apply to a curve with shape-keys: Object \"%s\", %s \"%s\", aborting",
- ob->id.name + 2, BKE_idcode_to_name(GS(obdata->name)), obdata->name + 2);
- changed = false;
- }
- }
-
- if (ob->type == OB_FONT) {
- if (apply_rot || apply_loc) {
- BKE_reportf(reports, RPT_ERROR,
- "Font's can only have scale applied: \"%s\"",
- ob->id.name + 2);
- changed = false;
- }
- }
-
- if (ob->type == OB_GPENCIL) {
- bGPdata *gpd = ob->data;
- if (gpd) {
- if (gpd->layers.first) {
- /* Unsupported configuration */
- bool has_unparented_layers = false;
-
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* Parented layers aren't supported as we can't easily re-evaluate
- * the scene to sample parent movement */
- if (gpl->parent == NULL) {
- has_unparented_layers = true;
- break;
- }
- }
-
- if (has_unparented_layers == false) {
- BKE_reportf(reports, RPT_ERROR,
- "Can't apply to a GP datablock where all layers are parented: Object \"%s\", %s \"%s\", aborting",
- ob->id.name + 2, BKE_idcode_to_name(ID_GD), gpd->id.name + 2);
- changed = false;
- }
- }
- else {
- /* No layers/data */
- BKE_reportf(reports, RPT_ERROR,
- "Can't apply to GP datablock with no layers: Object \"%s\", %s \"%s\", aborting",
- ob->id.name + 2, BKE_idcode_to_name(ID_GD), gpd->id.name + 2);
- }
- }
- }
-
- if (ob->type == OB_LAMP) {
- Light *la = ob->data;
- if (la->type == LA_AREA) {
- if (apply_rot || apply_loc) {
- BKE_reportf(reports, RPT_ERROR,
- "Area Lights can only have scale applied: \"%s\"",
- ob->id.name + 2);
- changed = false;
- }
- }
- }
- }
- CTX_DATA_END;
-
- if (!changed)
- return OPERATOR_CANCELLED;
-
- changed = false;
-
- /* now execute */
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
-
- /* calculate rotation/scale matrix */
- if (apply_scale && apply_rot)
- BKE_object_to_mat3(ob, rsmat);
- else if (apply_scale)
- BKE_object_scale_to_mat3(ob, rsmat);
- else if (apply_rot) {
- float tmat[3][3], timat[3][3];
-
- /* simple rotation matrix */
- BKE_object_rot_to_mat3(ob, rsmat, true);
-
- /* correct for scale, note mul_m3_m3m3 has swapped args! */
- BKE_object_scale_to_mat3(ob, tmat);
- invert_m3_m3(timat, tmat);
- mul_m3_m3m3(rsmat, timat, rsmat);
- mul_m3_m3m3(rsmat, rsmat, tmat);
- }
- else
- unit_m3(rsmat);
-
- copy_m4_m3(mat, rsmat);
-
- /* calculate translation */
- if (apply_loc) {
- copy_v3_v3(mat[3], ob->loc);
-
- if (!(apply_scale && apply_rot)) {
- float tmat[3][3];
- /* correct for scale and rotation that is still applied */
- BKE_object_to_mat3(ob, obmat);
- invert_m3_m3(iobmat, obmat);
- mul_m3_m3m3(tmat, rsmat, iobmat);
- mul_m3_v3(tmat, mat[3]);
- }
- }
-
- /* apply to object data */
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
-
- if (apply_scale)
- multiresModifier_scale_disp(depsgraph, scene, ob);
-
- /* adjust data */
- BKE_mesh_transform(me, mat, true);
-
- /* update normals */
- BKE_mesh_calc_normals(me);
- }
- else if (ob->type == OB_ARMATURE) {
- ED_armature_transform_apply(bmain, ob, mat, do_props);
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = ob->data;
-
- BKE_lattice_transform(lt, mat, true);
- }
- else if (ob->type == OB_MBALL) {
- MetaBall *mb = ob->data;
- BKE_mball_transform(mb, mat, do_props);
- }
- else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
- Curve *cu = ob->data;
- scale = mat3_to_scale(rsmat);
- BKE_curve_transform_ex(cu, mat, true, do_props, scale);
- }
- else if (ob->type == OB_FONT) {
- Curve *cu = ob->data;
- int i;
-
- scale = mat3_to_scale(rsmat);
-
- for (i = 0; i < cu->totbox; i++) {
- TextBox *tb = &cu->tb[i];
- tb->x *= scale;
- tb->y *= scale;
- tb->w *= scale;
- tb->h *= scale;
- }
-
- if (do_props) {
- cu->fsize *= scale;
- }
- }
- else if (ob->type == OB_GPENCIL) {
- bGPdata *gpd = ob->data;
- BKE_gpencil_transform(gpd, mat);
- }
- else if (ob->type == OB_CAMERA) {
- MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
-
- /* applying scale on camera actually scales clip's reconstruction.
- * of there's clip assigned to camera nothing to do actually.
- */
- if (!clip)
- continue;
-
- if (apply_scale)
- BKE_tracking_reconstruction_scale(&clip->tracking, ob->scale);
- }
- else if (ob->type == OB_EMPTY) {
- /* It's possible for empties too, even though they don't
- * really have obdata, since we can simply apply the maximum
- * scaling to the empty's drawsize.
- *
- * Core Assumptions:
- * 1) Most scaled empties have uniform scaling
- * (i.e. for visibility reasons), AND/OR
- * 2) Preserving non-uniform scaling is not that important,
- * and is something that many users would be willing to
- * sacrifice for having an easy way to do this.
- */
-
- if ((apply_loc == false) &&
- (apply_rot == false) &&
- (apply_scale == true))
- {
- float max_scale = max_fff(fabsf(ob->scale[0]), fabsf(ob->scale[1]), fabsf(ob->scale[2]));
- ob->empty_drawsize *= max_scale;
- }
- }
- else if (ob->type == OB_LAMP) {
- Light *la = ob->data;
- if (la->type != LA_AREA) {
- continue;
- }
-
- bool keeps_aspect_ratio = compare_ff_relative(rsmat[0][0], rsmat[1][1], FLT_EPSILON, 64);
- if ((la->area_shape == LA_AREA_SQUARE) && !keeps_aspect_ratio) {
- la->area_shape = LA_AREA_RECT;
- la->area_sizey = la->area_size;
- }
- else if ((la->area_shape == LA_AREA_DISK) && !keeps_aspect_ratio) {
- la->area_shape = LA_AREA_ELLIPSE;
- la->area_sizey = la->area_size;
- }
-
- la->area_size *= rsmat[0][0];
- la->area_sizey *= rsmat[1][1];
- la->area_sizez *= rsmat[2][2];
- }
- else {
- continue;
- }
-
- if (apply_loc)
- zero_v3(ob->loc);
- if (apply_scale)
- ob->scale[0] = ob->scale[1] = ob->scale[2] = 1.0f;
- if (apply_rot) {
- zero_v3(ob->rot);
- unit_qt(ob->quat);
- unit_axis_angle(ob->rotAxis, &ob->rotAngle);
- }
-
- BKE_object_where_is_calc(depsgraph, scene, ob);
- if (ob->type == OB_ARMATURE) {
- BKE_pose_where_is(depsgraph, scene, ob); /* needed for bone parents */
- }
-
- ignore_parent_tx(C, bmain, scene, ob);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
-
- changed = true;
- }
- CTX_DATA_END;
-
- if (!changed) {
- BKE_report(reports, RPT_WARNING, "Objects have no data to transform");
- return OPERATOR_CANCELLED;
- }
-
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- return OPERATOR_FINISHED;
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ float rsmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale;
+ bool changed = true;
+
+ /* first check if we can execute */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (ELEM(ob->type,
+ OB_MESH,
+ OB_ARMATURE,
+ OB_LATTICE,
+ OB_MBALL,
+ OB_CURVE,
+ OB_SURF,
+ OB_FONT,
+ OB_GPENCIL)) {
+ ID *obdata = ob->data;
+ if (ID_REAL_USERS(obdata) > 1) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Cannot apply to a multi user: Object \"%s\", %s \"%s\", aborting",
+ ob->id.name + 2,
+ BKE_idcode_to_name(GS(obdata->name)),
+ obdata->name + 2);
+ changed = false;
+ }
+
+ if (ID_IS_LINKED(obdata)) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Cannot apply to library data: Object \"%s\", %s \"%s\", aborting",
+ ob->id.name + 2,
+ BKE_idcode_to_name(GS(obdata->name)),
+ obdata->name + 2);
+ changed = false;
+ }
+ }
+
+ if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
+ ID *obdata = ob->data;
+ Curve *cu;
+
+ cu = ob->data;
+
+ if (((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) && (apply_rot || apply_loc)) {
+ BKE_reportf(
+ reports,
+ RPT_ERROR,
+ "Rotation/Location can't apply to a 2D curve: Object \"%s\", %s \"%s\", aborting",
+ ob->id.name + 2,
+ BKE_idcode_to_name(GS(obdata->name)),
+ obdata->name + 2);
+ changed = false;
+ }
+ if (cu->key) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Can't apply to a curve with shape-keys: Object \"%s\", %s \"%s\", aborting",
+ ob->id.name + 2,
+ BKE_idcode_to_name(GS(obdata->name)),
+ obdata->name + 2);
+ changed = false;
+ }
+ }
+
+ if (ob->type == OB_FONT) {
+ if (apply_rot || apply_loc) {
+ BKE_reportf(
+ reports, RPT_ERROR, "Font's can only have scale applied: \"%s\"", ob->id.name + 2);
+ changed = false;
+ }
+ }
+
+ if (ob->type == OB_GPENCIL) {
+ bGPdata *gpd = ob->data;
+ if (gpd) {
+ if (gpd->layers.first) {
+ /* Unsupported configuration */
+ bool has_unparented_layers = false;
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* Parented layers aren't supported as we can't easily re-evaluate
+ * the scene to sample parent movement */
+ if (gpl->parent == NULL) {
+ has_unparented_layers = true;
+ break;
+ }
+ }
+
+ if (has_unparented_layers == false) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Can't apply to a GP datablock where all layers are parented: Object "
+ "\"%s\", %s \"%s\", aborting",
+ ob->id.name + 2,
+ BKE_idcode_to_name(ID_GD),
+ gpd->id.name + 2);
+ changed = false;
+ }
+ }
+ else {
+ /* No layers/data */
+ BKE_reportf(
+ reports,
+ RPT_ERROR,
+ "Can't apply to GP datablock with no layers: Object \"%s\", %s \"%s\", aborting",
+ ob->id.name + 2,
+ BKE_idcode_to_name(ID_GD),
+ gpd->id.name + 2);
+ }
+ }
+ }
+
+ if (ob->type == OB_LAMP) {
+ Light *la = ob->data;
+ if (la->type == LA_AREA) {
+ if (apply_rot || apply_loc) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Area Lights can only have scale applied: \"%s\"",
+ ob->id.name + 2);
+ changed = false;
+ }
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ if (!changed)
+ return OPERATOR_CANCELLED;
+
+ changed = false;
+
+ /* now execute */
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+
+ /* calculate rotation/scale matrix */
+ if (apply_scale && apply_rot)
+ BKE_object_to_mat3(ob, rsmat);
+ else if (apply_scale)
+ BKE_object_scale_to_mat3(ob, rsmat);
+ else if (apply_rot) {
+ float tmat[3][3], timat[3][3];
+
+ /* simple rotation matrix */
+ BKE_object_rot_to_mat3(ob, rsmat, true);
+
+ /* correct for scale, note mul_m3_m3m3 has swapped args! */
+ BKE_object_scale_to_mat3(ob, tmat);
+ invert_m3_m3(timat, tmat);
+ mul_m3_m3m3(rsmat, timat, rsmat);
+ mul_m3_m3m3(rsmat, rsmat, tmat);
+ }
+ else
+ unit_m3(rsmat);
+
+ copy_m4_m3(mat, rsmat);
+
+ /* calculate translation */
+ if (apply_loc) {
+ copy_v3_v3(mat[3], ob->loc);
+
+ if (!(apply_scale && apply_rot)) {
+ float tmat[3][3];
+ /* correct for scale and rotation that is still applied */
+ BKE_object_to_mat3(ob, obmat);
+ invert_m3_m3(iobmat, obmat);
+ mul_m3_m3m3(tmat, rsmat, iobmat);
+ mul_m3_v3(tmat, mat[3]);
+ }
+ }
+
+ /* apply to object data */
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (apply_scale)
+ multiresModifier_scale_disp(depsgraph, scene, ob);
+
+ /* adjust data */
+ BKE_mesh_transform(me, mat, true);
+
+ /* update normals */
+ BKE_mesh_calc_normals(me);
+ }
+ else if (ob->type == OB_ARMATURE) {
+ ED_armature_transform_apply(bmain, ob, mat, do_props);
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = ob->data;
+
+ BKE_lattice_transform(lt, mat, true);
+ }
+ else if (ob->type == OB_MBALL) {
+ MetaBall *mb = ob->data;
+ BKE_mball_transform(mb, mat, do_props);
+ }
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
+ Curve *cu = ob->data;
+ scale = mat3_to_scale(rsmat);
+ BKE_curve_transform_ex(cu, mat, true, do_props, scale);
+ }
+ else if (ob->type == OB_FONT) {
+ Curve *cu = ob->data;
+ int i;
+
+ scale = mat3_to_scale(rsmat);
+
+ for (i = 0; i < cu->totbox; i++) {
+ TextBox *tb = &cu->tb[i];
+ tb->x *= scale;
+ tb->y *= scale;
+ tb->w *= scale;
+ tb->h *= scale;
+ }
+
+ if (do_props) {
+ cu->fsize *= scale;
+ }
+ }
+ else if (ob->type == OB_GPENCIL) {
+ bGPdata *gpd = ob->data;
+ BKE_gpencil_transform(gpd, mat);
+ }
+ else if (ob->type == OB_CAMERA) {
+ MovieClip *clip = BKE_object_movieclip_get(scene, ob, false);
+
+ /* applying scale on camera actually scales clip's reconstruction.
+ * of there's clip assigned to camera nothing to do actually.
+ */
+ if (!clip)
+ continue;
+
+ if (apply_scale)
+ BKE_tracking_reconstruction_scale(&clip->tracking, ob->scale);
+ }
+ else if (ob->type == OB_EMPTY) {
+ /* It's possible for empties too, even though they don't
+ * really have obdata, since we can simply apply the maximum
+ * scaling to the empty's drawsize.
+ *
+ * Core Assumptions:
+ * 1) Most scaled empties have uniform scaling
+ * (i.e. for visibility reasons), AND/OR
+ * 2) Preserving non-uniform scaling is not that important,
+ * and is something that many users would be willing to
+ * sacrifice for having an easy way to do this.
+ */
+
+ if ((apply_loc == false) && (apply_rot == false) && (apply_scale == true)) {
+ float max_scale = max_fff(fabsf(ob->scale[0]), fabsf(ob->scale[1]), fabsf(ob->scale[2]));
+ ob->empty_drawsize *= max_scale;
+ }
+ }
+ else if (ob->type == OB_LAMP) {
+ Light *la = ob->data;
+ if (la->type != LA_AREA) {
+ continue;
+ }
+
+ bool keeps_aspect_ratio = compare_ff_relative(rsmat[0][0], rsmat[1][1], FLT_EPSILON, 64);
+ if ((la->area_shape == LA_AREA_SQUARE) && !keeps_aspect_ratio) {
+ la->area_shape = LA_AREA_RECT;
+ la->area_sizey = la->area_size;
+ }
+ else if ((la->area_shape == LA_AREA_DISK) && !keeps_aspect_ratio) {
+ la->area_shape = LA_AREA_ELLIPSE;
+ la->area_sizey = la->area_size;
+ }
+
+ la->area_size *= rsmat[0][0];
+ la->area_sizey *= rsmat[1][1];
+ la->area_sizez *= rsmat[2][2];
+ }
+ else {
+ continue;
+ }
+
+ if (apply_loc)
+ zero_v3(ob->loc);
+ if (apply_scale)
+ ob->scale[0] = ob->scale[1] = ob->scale[2] = 1.0f;
+ if (apply_rot) {
+ zero_v3(ob->rot);
+ unit_qt(ob->quat);
+ unit_axis_angle(ob->rotAxis, &ob->rotAngle);
+ }
+
+ BKE_object_where_is_calc(depsgraph, scene, ob);
+ if (ob->type == OB_ARMATURE) {
+ BKE_pose_where_is(depsgraph, scene, ob); /* needed for bone parents */
+ }
+
+ ignore_parent_tx(C, bmain, scene, ob);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+
+ changed = true;
+ }
+ CTX_DATA_END;
+
+ if (!changed) {
+ BKE_report(reports, RPT_WARNING, "Objects have no data to transform");
+ return OPERATOR_CANCELLED;
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ return OPERATOR_FINISHED;
}
static int visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- bool changed = false;
+ Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ bool changed = false;
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- BKE_object_where_is_calc(depsgraph, scene, ob);
- BKE_object_apply_mat4(ob, ob->obmat, true, true);
- BKE_object_where_is_calc(depsgraph, scene, ob);
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ BKE_object_where_is_calc(depsgraph, scene, ob);
+ BKE_object_apply_mat4(ob, ob->obmat, true, true);
+ BKE_object_where_is_calc(depsgraph, scene, ob);
- /* update for any children that may get moved */
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ /* update for any children that may get moved */
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- changed = true;
- }
- CTX_DATA_END;
+ changed = true;
+ }
+ CTX_DATA_END;
- if (!changed)
- return OPERATOR_CANCELLED;
+ if (!changed)
+ return OPERATOR_CANCELLED;
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- return OPERATOR_FINISHED;
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_visual_transform_apply(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Apply Visual Transform";
- ot->description = "Apply the object's visual transformation to its data";
- ot->idname = "OBJECT_OT_visual_transform_apply";
+ /* identifiers */
+ ot->name = "Apply Visual Transform";
+ ot->description = "Apply the object's visual transformation to its data";
+ ot->idname = "OBJECT_OT_visual_transform_apply";
- /* api callbacks */
- ot->exec = visual_transform_apply_exec;
- ot->poll = ED_operator_scene_editable;
+ /* api callbacks */
+ ot->exec = visual_transform_apply_exec;
+ ot->poll = ED_operator_scene_editable;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int object_transform_apply_exec(bContext *C, wmOperator *op)
{
- const bool loc = RNA_boolean_get(op->ptr, "location");
- const bool rot = RNA_boolean_get(op->ptr, "rotation");
- const bool sca = RNA_boolean_get(op->ptr, "scale");
- const bool do_props = RNA_boolean_get(op->ptr, "properties");
-
- if (loc || rot || sca) {
- return apply_objects_internal(C, op->reports, loc, rot, sca, do_props);
- }
- else {
- /* allow for redo */
- return OPERATOR_FINISHED;
- }
+ const bool loc = RNA_boolean_get(op->ptr, "location");
+ const bool rot = RNA_boolean_get(op->ptr, "rotation");
+ const bool sca = RNA_boolean_get(op->ptr, "scale");
+ const bool do_props = RNA_boolean_get(op->ptr, "properties");
+
+ if (loc || rot || sca) {
+ return apply_objects_internal(C, op->reports, loc, rot, sca, do_props);
+ }
+ else {
+ /* allow for redo */
+ return OPERATOR_FINISHED;
+ }
}
void OBJECT_OT_transform_apply(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Apply Object Transform";
- ot->description = "Apply the object's transformation to its data";
- ot->idname = "OBJECT_OT_transform_apply";
-
- /* api callbacks */
- ot->exec = object_transform_apply_exec;
- ot->poll = ED_operator_objectmode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "location", true, "Location", "");
- RNA_def_boolean(ot->srna, "rotation", true, "Rotation", "");
- RNA_def_boolean(ot->srna, "scale", true, "Scale", "");
- RNA_def_boolean(ot->srna, "properties", true, "Apply Properties",
- "Modify properties such as curve vertex radius, font size and bone envelope");
+ /* identifiers */
+ ot->name = "Apply Object Transform";
+ ot->description = "Apply the object's transformation to its data";
+ ot->idname = "OBJECT_OT_transform_apply";
+
+ /* api callbacks */
+ ot->exec = object_transform_apply_exec;
+ ot->poll = ED_operator_objectmode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_boolean(ot->srna, "location", true, "Location", "");
+ RNA_def_boolean(ot->srna, "rotation", true, "Rotation", "");
+ RNA_def_boolean(ot->srna, "scale", true, "Scale", "");
+ RNA_def_boolean(ot->srna,
+ "properties",
+ true,
+ "Apply Properties",
+ "Modify properties such as curve vertex radius, font size and bone envelope");
}
/********************* Set Object Center ************************/
enum {
- GEOMETRY_TO_ORIGIN = 0,
- ORIGIN_TO_GEOMETRY,
- ORIGIN_TO_CURSOR,
- ORIGIN_TO_CENTER_OF_MASS_SURFACE,
- ORIGIN_TO_CENTER_OF_MASS_VOLUME,
+ GEOMETRY_TO_ORIGIN = 0,
+ ORIGIN_TO_GEOMETRY,
+ ORIGIN_TO_CURSOR,
+ ORIGIN_TO_CENTER_OF_MASS_SURFACE,
+ ORIGIN_TO_CENTER_OF_MASS_VOLUME,
};
static int object_origin_set_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *obact = CTX_data_active_object(C);
- Object *obedit = CTX_data_edit_object(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Object *tob;
- float cent[3], cent_neg[3], centn[3];
- const float *cursor = scene->cursor.location;
- int centermode = RNA_enum_get(op->ptr, "type");
-
- ListBase ctx_data_list;
- CollectionPointerLink *ctx_ob;
- CollectionPointerLink *ctx_ob_act = NULL;
-
- /* keep track of what is changed */
- int tot_change = 0, tot_lib_error = 0, tot_multiuser_arm_error = 0;
-
- if (obedit && centermode != GEOMETRY_TO_ORIGIN) {
- BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in edit mode");
- return OPERATOR_CANCELLED;
- }
-
- int around;
- {
- PropertyRNA *prop_center = RNA_struct_find_property(op->ptr, "center");
- if (RNA_property_is_set(op->ptr, prop_center)) {
- around = RNA_property_enum_get(op->ptr, prop_center);
- }
- else {
- if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_BOUNDS) {
- around = V3D_AROUND_CENTER_BOUNDS;
- }
- else {
- around = V3D_AROUND_CENTER_MEDIAN;
- }
- RNA_property_enum_set(op->ptr, prop_center, around);
- }
- }
-
- zero_v3(cent);
-
- if (obedit) {
- if (obedit->type == OB_MESH) {
- Mesh *me = obedit->data;
- BMEditMesh *em = me->edit_mesh;
- BMVert *eve;
- BMIter iter;
-
- if (centermode == ORIGIN_TO_CURSOR) {
- copy_v3_v3(cent, cursor);
- invert_m4_m4(obedit->imat, obedit->obmat);
- 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 {
- float min[3], max[3];
- INIT_MINMAX(min, max);
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- minmax_v3v3_v3(min, max, eve->co);
- }
- mid_v3_v3v3(cent, min, max);
- }
- }
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- sub_v3_v3(eve->co, cent);
- }
-
- EDBM_mesh_normals_update(em);
- tot_change++;
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
- }
- }
-
- CTX_data_selected_editable_objects(C, &ctx_data_list);
-
- /* reset flags */
- for (ctx_ob = ctx_data_list.first;
- ctx_ob;
- ctx_ob = ctx_ob->next)
- {
- Object *ob = ctx_ob->ptr.data;
- ob->flag &= ~OB_DONE;
-
- /* move active first */
- if (ob == obact) {
- ctx_ob_act = ctx_ob;
- }
- }
-
- if (ctx_ob_act) {
- BLI_listbase_rotate_first(&ctx_data_list, (LinkData *)ctx_ob_act);
- }
-
- for (tob = bmain->objects.first; tob; tob = tob->id.next) {
- if (tob->data)
- ((ID *)tob->data)->tag &= ~LIB_TAG_DOIT;
- if (tob->instance_collection)
- ((ID *)tob->instance_collection)->tag &= ~LIB_TAG_DOIT;
- }
-
- for (ctx_ob = ctx_data_list.first;
- ctx_ob;
- ctx_ob = ctx_ob->next)
- {
- Object *ob = ctx_ob->ptr.data;
-
- if ((ob->flag & OB_DONE) == 0) {
- bool do_inverse_offset = false;
- ob->flag |= OB_DONE;
-
- if (centermode == ORIGIN_TO_CURSOR) {
- copy_v3_v3(cent, cursor);
- invert_m4_m4(ob->imat, ob->obmat);
- mul_m4_v3(ob->imat, cent);
- }
-
- if (ob->data == NULL) {
- /* special support for dupligroups */
- if ((ob->transflag & OB_DUPLICOLLECTION) && ob->instance_collection && (ob->instance_collection->id.tag & LIB_TAG_DOIT) == 0) {
- if (ID_IS_LINKED(ob->instance_collection)) {
- tot_lib_error++;
- }
- else {
- if (centermode == ORIGIN_TO_CURSOR) {
- /* done */
- }
- else {
- float min[3], max[3];
- /* only bounds support */
- INIT_MINMAX(min, max);
- BKE_object_minmax_dupli(depsgraph, scene, ob, min, max, true);
- mid_v3_v3v3(cent, min, max);
- invert_m4_m4(ob->imat, ob->obmat);
- mul_m4_v3(ob->imat, cent);
- }
-
- add_v3_v3(ob->instance_collection->instance_offset, cent);
-
- tot_change++;
- ob->instance_collection->id.tag |= LIB_TAG_DOIT;
- do_inverse_offset = true;
- }
- }
- }
- else if (ID_IS_LINKED(ob->data)) {
- tot_lib_error++;
- }
-
- if (obedit == NULL && ob->type == OB_MESH) {
- Mesh *me = ob->data;
-
- if (centermode == ORIGIN_TO_CURSOR) {
- /* done */
- }
- else if (centermode == ORIGIN_TO_CENTER_OF_MASS_SURFACE) {
- BKE_mesh_center_of_surface(me, cent);
- }
- 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 {
- BKE_mesh_center_bounds(me, cent);
- }
-
- negate_v3_v3(cent_neg, cent);
- BKE_mesh_translate(me, cent_neg, 1);
-
- tot_change++;
- me->id.tag |= LIB_TAG_DOIT;
- do_inverse_offset = true;
- }
- else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
- Curve *cu = ob->data;
-
- if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
- else if (around == V3D_AROUND_CENTER_MEDIAN) { BKE_curve_center_median(cu, cent); }
- else { BKE_curve_center_bounds(cu, cent); }
-
- /* don't allow Z change if curve is 2D */
- if ((ob->type == OB_CURVE) && !(cu->flag & CU_3D))
- cent[2] = 0.0;
-
- negate_v3_v3(cent_neg, cent);
- BKE_curve_translate(cu, cent_neg, 1);
-
- tot_change++;
- cu->id.tag |= LIB_TAG_DOIT;
- do_inverse_offset = true;
-
- if (obedit) {
- if (centermode == GEOMETRY_TO_ORIGIN) {
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
- }
- break;
- }
- }
- else if (ob->type == OB_FONT) {
- /* get from bb */
-
- Curve *cu = ob->data;
-
- if (ob->runtime.bb == NULL && (centermode != ORIGIN_TO_CURSOR)) {
- /* do nothing*/
- }
- else {
- if (centermode == ORIGIN_TO_CURSOR) {
- /* done */
- }
- else {
- /* extra 0.5 is the height o above line */
- cent[0] = 0.5f * (ob->runtime.bb->vec[4][0] + ob->runtime.bb->vec[0][0]);
- cent[1] = 0.5f * (ob->runtime.bb->vec[0][1] + ob->runtime.bb->vec[2][1]);
- }
-
- cent[2] = 0.0f;
-
- cu->xof = cu->xof - cent[0];
- cu->yof = cu->yof - cent[1];
-
- tot_change++;
- cu->id.tag |= LIB_TAG_DOIT;
- do_inverse_offset = true;
- }
- }
- else if (ob->type == OB_ARMATURE) {
- bArmature *arm = ob->data;
-
- if (ID_REAL_USERS(arm) > 1) {
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *obact = CTX_data_active_object(C);
+ Object *obedit = CTX_data_edit_object(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *tob;
+ float cent[3], cent_neg[3], centn[3];
+ const float *cursor = scene->cursor.location;
+ int centermode = RNA_enum_get(op->ptr, "type");
+
+ ListBase ctx_data_list;
+ CollectionPointerLink *ctx_ob;
+ CollectionPointerLink *ctx_ob_act = NULL;
+
+ /* keep track of what is changed */
+ int tot_change = 0, tot_lib_error = 0, tot_multiuser_arm_error = 0;
+
+ if (obedit && centermode != GEOMETRY_TO_ORIGIN) {
+ BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in edit mode");
+ return OPERATOR_CANCELLED;
+ }
+
+ int around;
+ {
+ PropertyRNA *prop_center = RNA_struct_find_property(op->ptr, "center");
+ if (RNA_property_is_set(op->ptr, prop_center)) {
+ around = RNA_property_enum_get(op->ptr, prop_center);
+ }
+ else {
+ if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_BOUNDS) {
+ around = V3D_AROUND_CENTER_BOUNDS;
+ }
+ else {
+ around = V3D_AROUND_CENTER_MEDIAN;
+ }
+ RNA_property_enum_set(op->ptr, prop_center, around);
+ }
+ }
+
+ zero_v3(cent);
+
+ if (obedit) {
+ if (obedit->type == OB_MESH) {
+ Mesh *me = obedit->data;
+ BMEditMesh *em = me->edit_mesh;
+ BMVert *eve;
+ BMIter iter;
+
+ if (centermode == ORIGIN_TO_CURSOR) {
+ copy_v3_v3(cent, cursor);
+ invert_m4_m4(obedit->imat, obedit->obmat);
+ 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 {
+ float min[3], max[3];
+ INIT_MINMAX(min, max);
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ minmax_v3v3_v3(min, max, eve->co);
+ }
+ mid_v3_v3v3(cent, min, max);
+ }
+ }
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ sub_v3_v3(eve->co, cent);
+ }
+
+ EDBM_mesh_normals_update(em);
+ tot_change++;
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ }
+ }
+
+ CTX_data_selected_editable_objects(C, &ctx_data_list);
+
+ /* reset flags */
+ for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
+ Object *ob = ctx_ob->ptr.data;
+ ob->flag &= ~OB_DONE;
+
+ /* move active first */
+ if (ob == obact) {
+ ctx_ob_act = ctx_ob;
+ }
+ }
+
+ if (ctx_ob_act) {
+ BLI_listbase_rotate_first(&ctx_data_list, (LinkData *)ctx_ob_act);
+ }
+
+ for (tob = bmain->objects.first; tob; tob = tob->id.next) {
+ if (tob->data)
+ ((ID *)tob->data)->tag &= ~LIB_TAG_DOIT;
+ if (tob->instance_collection)
+ ((ID *)tob->instance_collection)->tag &= ~LIB_TAG_DOIT;
+ }
+
+ for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
+ Object *ob = ctx_ob->ptr.data;
+
+ if ((ob->flag & OB_DONE) == 0) {
+ bool do_inverse_offset = false;
+ ob->flag |= OB_DONE;
+
+ if (centermode == ORIGIN_TO_CURSOR) {
+ copy_v3_v3(cent, cursor);
+ invert_m4_m4(ob->imat, ob->obmat);
+ mul_m4_v3(ob->imat, cent);
+ }
+
+ if (ob->data == NULL) {
+ /* special support for dupligroups */
+ if ((ob->transflag & OB_DUPLICOLLECTION) && ob->instance_collection &&
+ (ob->instance_collection->id.tag & LIB_TAG_DOIT) == 0) {
+ if (ID_IS_LINKED(ob->instance_collection)) {
+ tot_lib_error++;
+ }
+ else {
+ if (centermode == ORIGIN_TO_CURSOR) {
+ /* done */
+ }
+ else {
+ float min[3], max[3];
+ /* only bounds support */
+ INIT_MINMAX(min, max);
+ BKE_object_minmax_dupli(depsgraph, scene, ob, min, max, true);
+ mid_v3_v3v3(cent, min, max);
+ invert_m4_m4(ob->imat, ob->obmat);
+ mul_m4_v3(ob->imat, cent);
+ }
+
+ add_v3_v3(ob->instance_collection->instance_offset, cent);
+
+ tot_change++;
+ ob->instance_collection->id.tag |= LIB_TAG_DOIT;
+ do_inverse_offset = true;
+ }
+ }
+ }
+ else if (ID_IS_LINKED(ob->data)) {
+ tot_lib_error++;
+ }
+
+ if (obedit == NULL && ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (centermode == ORIGIN_TO_CURSOR) {
+ /* done */
+ }
+ else if (centermode == ORIGIN_TO_CENTER_OF_MASS_SURFACE) {
+ BKE_mesh_center_of_surface(me, cent);
+ }
+ 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 {
+ BKE_mesh_center_bounds(me, cent);
+ }
+
+ negate_v3_v3(cent_neg, cent);
+ BKE_mesh_translate(me, cent_neg, 1);
+
+ tot_change++;
+ me->id.tag |= LIB_TAG_DOIT;
+ do_inverse_offset = true;
+ }
+ else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
+ Curve *cu = ob->data;
+
+ if (centermode == ORIGIN_TO_CURSOR) { /* done */
+ }
+ else if (around == V3D_AROUND_CENTER_MEDIAN) {
+ BKE_curve_center_median(cu, cent);
+ }
+ else {
+ BKE_curve_center_bounds(cu, cent);
+ }
+
+ /* don't allow Z change if curve is 2D */
+ if ((ob->type == OB_CURVE) && !(cu->flag & CU_3D))
+ cent[2] = 0.0;
+
+ negate_v3_v3(cent_neg, cent);
+ BKE_curve_translate(cu, cent_neg, 1);
+
+ tot_change++;
+ cu->id.tag |= LIB_TAG_DOIT;
+ do_inverse_offset = true;
+
+ if (obedit) {
+ if (centermode == GEOMETRY_TO_ORIGIN) {
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ }
+ break;
+ }
+ }
+ else if (ob->type == OB_FONT) {
+ /* get from bb */
+
+ Curve *cu = ob->data;
+
+ if (ob->runtime.bb == NULL && (centermode != ORIGIN_TO_CURSOR)) {
+ /* do nothing*/
+ }
+ else {
+ if (centermode == ORIGIN_TO_CURSOR) {
+ /* done */
+ }
+ else {
+ /* extra 0.5 is the height o above line */
+ cent[0] = 0.5f * (ob->runtime.bb->vec[4][0] + ob->runtime.bb->vec[0][0]);
+ cent[1] = 0.5f * (ob->runtime.bb->vec[0][1] + ob->runtime.bb->vec[2][1]);
+ }
+
+ cent[2] = 0.0f;
+
+ cu->xof = cu->xof - cent[0];
+ cu->yof = cu->yof - cent[1];
+
+ tot_change++;
+ cu->id.tag |= LIB_TAG_DOIT;
+ do_inverse_offset = true;
+ }
+ }
+ else if (ob->type == OB_ARMATURE) {
+ bArmature *arm = ob->data;
+
+ if (ID_REAL_USERS(arm) > 1) {
#if 0
- BKE_report(op->reports, RPT_ERROR, "Cannot apply to a multi user armature");
- return;
+ BKE_report(op->reports, RPT_ERROR, "Cannot apply to a multi user armature");
+ return;
#endif
- tot_multiuser_arm_error++;
- }
- else {
- /* Function to recenter armatures in editarmature.c
- * Bone + object locations are handled there.
- */
- ED_armature_origin_set(bmain, ob, cursor, centermode, around);
-
- tot_change++;
- arm->id.tag |= LIB_TAG_DOIT;
- /* do_inverse_offset = true; */ /* docenter_armature() handles this */
-
- BKE_object_where_is_calc(depsgraph, scene, ob);
- BKE_pose_where_is(depsgraph, scene, ob); /* needed for bone parents */
-
- ignore_parent_tx(C, bmain, scene, ob);
-
- if (obedit)
- break;
- }
- }
- else if (ob->type == OB_MBALL) {
- MetaBall *mb = ob->data;
-
- if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
- else if (around == V3D_AROUND_CENTER_MEDIAN) { BKE_mball_center_median(mb, cent); }
- else { BKE_mball_center_bounds(mb, cent); }
-
- negate_v3_v3(cent_neg, cent);
- BKE_mball_translate(mb, cent_neg);
-
- tot_change++;
- mb->id.tag |= LIB_TAG_DOIT;
- do_inverse_offset = true;
-
- if (obedit) {
- if (centermode == GEOMETRY_TO_ORIGIN) {
- DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
- }
- break;
- }
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = ob->data;
-
- if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
- else if (around == V3D_AROUND_CENTER_MEDIAN) { BKE_lattice_center_median(lt, cent); }
- else { BKE_lattice_center_bounds(lt, cent); }
-
- negate_v3_v3(cent_neg, cent);
- BKE_lattice_translate(lt, cent_neg, 1);
-
- tot_change++;
- lt->id.tag |= LIB_TAG_DOIT;
- do_inverse_offset = true;
- }
- else if (ob->type == OB_GPENCIL) {
- bGPdata *gpd = ob->data;
- float gpcenter[3];
- if (gpd) {
- if (centermode == ORIGIN_TO_GEOMETRY) {
- zero_v3(gpcenter);
- BKE_gpencil_centroid_3d(gpd, gpcenter);
- add_v3_v3(gpcenter, ob->obmat[3]);
- }
- if (centermode == ORIGIN_TO_CURSOR) {
- copy_v3_v3(gpcenter, cursor);
- }
- if ((centermode == ORIGIN_TO_GEOMETRY) || (centermode == ORIGIN_TO_CURSOR)) {
- bGPDspoint *pt;
- float imat[3][3], bmat[3][3];
- float offset_global[3];
- float offset_local[3];
- int i;
-
- sub_v3_v3v3(offset_global, gpcenter, ob->obmat[3]);
- copy_m3_m4(bmat, obact->obmat);
- invert_m3_m3(imat, bmat);
- mul_m3_v3(imat, offset_global);
- mul_v3_m3v3(offset_local, imat, offset_global);
-
- float diff_mat[4][4];
- float inverse_diff_mat[4][4];
-
- /* recalculate all strokes
- * (all layers are considered without evaluating lock attributes) */
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* calculate difference matrix */
- ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
- /* undo matrix */
- invert_m4_m4(inverse_diff_mat, diff_mat);
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, gps) == false)
- continue;
-
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- float mpt[3];
- mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x);
- sub_v3_v3(mpt, offset_local);
- mul_v3_m4v3(&pt->x, diff_mat, mpt);
- }
- }
- }
- }
- DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
-
- tot_change++;
- if (centermode == ORIGIN_TO_GEOMETRY) {
- copy_v3_v3(ob->loc, gpcenter);
- }
- ob->id.tag |= LIB_TAG_DOIT;
- do_inverse_offset = true;
- }
- else {
- BKE_report(op->reports, RPT_WARNING, "Grease Pencil Object does not support this set origin option");
- }
- }
- }
-
- /* offset other selected objects */
- if (do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) {
- CollectionPointerLink *ctx_link_other;
- float obmat[4][4];
-
- /* was the object data modified
- * note: the functions above must set 'cent' */
-
- /* convert the offset to parent space */
- BKE_object_to_mat4(ob, obmat);
- mul_v3_mat3_m4v3(centn, obmat, cent); /* omit translation part */
-
- add_v3_v3(ob->loc, centn);
-
- BKE_object_where_is_calc(depsgraph, scene, ob);
- if (ob->type == OB_ARMATURE) {
- BKE_pose_where_is(depsgraph, scene, ob); /* needed for bone parents */
- }
-
- ignore_parent_tx(C, bmain, scene, ob);
-
- /* other users? */
- //CTX_DATA_BEGIN (C, Object *, ob_other, selected_editable_objects)
- //{
-
- /* use existing context looper */
- for (ctx_link_other = ctx_data_list.first;
- ctx_link_other;
- ctx_link_other = ctx_link_other->next)
- {
- Object *ob_other = ctx_link_other->ptr.data;
-
- if ((ob_other->flag & OB_DONE) == 0 &&
- ((ob->data && (ob->data == ob_other->data)) ||
- (ob->instance_collection == ob_other->instance_collection &&
- (ob->transflag | ob_other->transflag) & OB_DUPLICOLLECTION)))
- {
- ob_other->flag |= OB_DONE;
- DEG_id_tag_update(&ob_other->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
-
- mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */
- add_v3_v3(ob_other->loc, centn);
-
- BKE_object_where_is_calc(depsgraph, scene, ob_other);
- if (ob_other->type == OB_ARMATURE) {
- /* needed for bone parents */
- BKE_pose_where_is(depsgraph, scene, ob_other);
- }
- ignore_parent_tx(C, bmain, scene, ob_other);
- }
- }
- //CTX_DATA_END;
- }
- }
- }
- BLI_freelistN(&ctx_data_list);
-
- for (tob = bmain->objects.first; tob; tob = tob->id.next) {
- if (tob->data && (((ID *)tob->data)->tag & LIB_TAG_DOIT)) {
- BKE_object_batch_cache_dirty_tag(tob);
- DEG_id_tag_update(&tob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- }
- }
-
- if (tot_change) {
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
- }
-
- /* Warn if any errors occurred */
- if (tot_lib_error + tot_multiuser_arm_error) {
- BKE_reportf(op->reports, RPT_WARNING, "%i object(s) not centered, %i changed:", tot_lib_error + tot_multiuser_arm_error, tot_change);
- if (tot_lib_error)
- BKE_reportf(op->reports, RPT_WARNING, "|%i linked library object(s)", tot_lib_error);
- if (tot_multiuser_arm_error)
- BKE_reportf(op->reports, RPT_WARNING, "|%i multiuser armature object(s)", tot_multiuser_arm_error);
- }
-
- return OPERATOR_FINISHED;
+ tot_multiuser_arm_error++;
+ }
+ else {
+ /* Function to recenter armatures in editarmature.c
+ * Bone + object locations are handled there.
+ */
+ ED_armature_origin_set(bmain, ob, cursor, centermode, around);
+
+ tot_change++;
+ arm->id.tag |= LIB_TAG_DOIT;
+ /* do_inverse_offset = true; */ /* docenter_armature() handles this */
+
+ BKE_object_where_is_calc(depsgraph, scene, ob);
+ BKE_pose_where_is(depsgraph, scene, ob); /* needed for bone parents */
+
+ ignore_parent_tx(C, bmain, scene, ob);
+
+ if (obedit)
+ break;
+ }
+ }
+ else if (ob->type == OB_MBALL) {
+ MetaBall *mb = ob->data;
+
+ if (centermode == ORIGIN_TO_CURSOR) { /* done */
+ }
+ else if (around == V3D_AROUND_CENTER_MEDIAN) {
+ BKE_mball_center_median(mb, cent);
+ }
+ else {
+ BKE_mball_center_bounds(mb, cent);
+ }
+
+ negate_v3_v3(cent_neg, cent);
+ BKE_mball_translate(mb, cent_neg);
+
+ tot_change++;
+ mb->id.tag |= LIB_TAG_DOIT;
+ do_inverse_offset = true;
+
+ if (obedit) {
+ if (centermode == GEOMETRY_TO_ORIGIN) {
+ DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
+ }
+ break;
+ }
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = ob->data;
+
+ if (centermode == ORIGIN_TO_CURSOR) { /* done */
+ }
+ else if (around == V3D_AROUND_CENTER_MEDIAN) {
+ BKE_lattice_center_median(lt, cent);
+ }
+ else {
+ BKE_lattice_center_bounds(lt, cent);
+ }
+
+ negate_v3_v3(cent_neg, cent);
+ BKE_lattice_translate(lt, cent_neg, 1);
+
+ tot_change++;
+ lt->id.tag |= LIB_TAG_DOIT;
+ do_inverse_offset = true;
+ }
+ else if (ob->type == OB_GPENCIL) {
+ bGPdata *gpd = ob->data;
+ float gpcenter[3];
+ if (gpd) {
+ if (centermode == ORIGIN_TO_GEOMETRY) {
+ zero_v3(gpcenter);
+ BKE_gpencil_centroid_3d(gpd, gpcenter);
+ add_v3_v3(gpcenter, ob->obmat[3]);
+ }
+ if (centermode == ORIGIN_TO_CURSOR) {
+ copy_v3_v3(gpcenter, cursor);
+ }
+ if ((centermode == ORIGIN_TO_GEOMETRY) || (centermode == ORIGIN_TO_CURSOR)) {
+ bGPDspoint *pt;
+ float imat[3][3], bmat[3][3];
+ float offset_global[3];
+ float offset_local[3];
+ int i;
+
+ sub_v3_v3v3(offset_global, gpcenter, ob->obmat[3]);
+ copy_m3_m4(bmat, obact->obmat);
+ invert_m3_m3(imat, bmat);
+ mul_m3_v3(imat, offset_global);
+ mul_v3_m3v3(offset_local, imat, offset_global);
+
+ float diff_mat[4][4];
+ float inverse_diff_mat[4][4];
+
+ /* recalculate all strokes
+ * (all layers are considered without evaluating lock attributes) */
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* calculate difference matrix */
+ ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
+ /* undo matrix */
+ invert_m4_m4(inverse_diff_mat, diff_mat);
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps) == false)
+ continue;
+
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ float mpt[3];
+ mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x);
+ sub_v3_v3(mpt, offset_local);
+ mul_v3_m4v3(&pt->x, diff_mat, mpt);
+ }
+ }
+ }
+ }
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+
+ tot_change++;
+ if (centermode == ORIGIN_TO_GEOMETRY) {
+ copy_v3_v3(ob->loc, gpcenter);
+ }
+ ob->id.tag |= LIB_TAG_DOIT;
+ do_inverse_offset = true;
+ }
+ else {
+ BKE_report(op->reports,
+ RPT_WARNING,
+ "Grease Pencil Object does not support this set origin option");
+ }
+ }
+ }
+
+ /* offset other selected objects */
+ if (do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) {
+ CollectionPointerLink *ctx_link_other;
+ float obmat[4][4];
+
+ /* was the object data modified
+ * note: the functions above must set 'cent' */
+
+ /* convert the offset to parent space */
+ BKE_object_to_mat4(ob, obmat);
+ mul_v3_mat3_m4v3(centn, obmat, cent); /* omit translation part */
+
+ add_v3_v3(ob->loc, centn);
+
+ BKE_object_where_is_calc(depsgraph, scene, ob);
+ if (ob->type == OB_ARMATURE) {
+ BKE_pose_where_is(depsgraph, scene, ob); /* needed for bone parents */
+ }
+
+ ignore_parent_tx(C, bmain, scene, ob);
+
+ /* other users? */
+ //CTX_DATA_BEGIN (C, Object *, ob_other, selected_editable_objects)
+ //{
+
+ /* use existing context looper */
+ for (ctx_link_other = ctx_data_list.first; ctx_link_other;
+ ctx_link_other = ctx_link_other->next) {
+ Object *ob_other = ctx_link_other->ptr.data;
+
+ if ((ob_other->flag & OB_DONE) == 0 &&
+ ((ob->data && (ob->data == ob_other->data)) ||
+ (ob->instance_collection == ob_other->instance_collection &&
+ (ob->transflag | ob_other->transflag) & OB_DUPLICOLLECTION))) {
+ ob_other->flag |= OB_DONE;
+ DEG_id_tag_update(&ob_other->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+
+ mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */
+ add_v3_v3(ob_other->loc, centn);
+
+ BKE_object_where_is_calc(depsgraph, scene, ob_other);
+ if (ob_other->type == OB_ARMATURE) {
+ /* needed for bone parents */
+ BKE_pose_where_is(depsgraph, scene, ob_other);
+ }
+ ignore_parent_tx(C, bmain, scene, ob_other);
+ }
+ }
+ //CTX_DATA_END;
+ }
+ }
+ }
+ BLI_freelistN(&ctx_data_list);
+
+ for (tob = bmain->objects.first; tob; tob = tob->id.next) {
+ if (tob->data && (((ID *)tob->data)->tag & LIB_TAG_DOIT)) {
+ BKE_object_batch_cache_dirty_tag(tob);
+ DEG_id_tag_update(&tob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ }
+ }
+
+ if (tot_change) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ }
+
+ /* Warn if any errors occurred */
+ if (tot_lib_error + tot_multiuser_arm_error) {
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "%i object(s) not centered, %i changed:",
+ tot_lib_error + tot_multiuser_arm_error,
+ tot_change);
+ if (tot_lib_error)
+ BKE_reportf(op->reports, RPT_WARNING, "|%i linked library object(s)", tot_lib_error);
+ if (tot_multiuser_arm_error)
+ BKE_reportf(
+ op->reports, RPT_WARNING, "|%i multiuser armature object(s)", tot_multiuser_arm_error);
+ }
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_origin_set(wmOperatorType *ot)
{
- static const EnumPropertyItem prop_set_center_types[] = {
- {GEOMETRY_TO_ORIGIN, "GEOMETRY_ORIGIN", 0, "Geometry to Origin", "Move object geometry to object origin"},
- {ORIGIN_TO_GEOMETRY, "ORIGIN_GEOMETRY", 0, "Origin to Geometry",
- "Calculate the center of geometry based on the current pivot point (median, otherwise bounding-box)"},
- {ORIGIN_TO_CURSOR, "ORIGIN_CURSOR", 0, "Origin to 3D Cursor",
- "Move object origin to position of the 3D cursor"},
- /* Intentional naming mismatch since some scripts refer to this. */
- {ORIGIN_TO_CENTER_OF_MASS_SURFACE, "ORIGIN_CENTER_OF_MASS", 0, "Origin to Center of Mass (Surface)",
- "Calculate the center of mass from the surface area"},
- {ORIGIN_TO_CENTER_OF_MASS_VOLUME, "ORIGIN_CENTER_OF_VOLUME", 0, "Origin to Center of Mass (Volume)",
- "Calculate the center of mass from the volume (must be manifold geometry with consistent normals)"},
- {0, NULL, 0, NULL, NULL},
- };
-
- static const EnumPropertyItem prop_set_bounds_types[] = {
- {V3D_AROUND_CENTER_MEDIAN, "MEDIAN", 0, "Median Center", ""},
- {V3D_AROUND_CENTER_BOUNDS, "BOUNDS", 0, "Bounds Center", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Set Origin";
- ot->description = "Set the object's origin, by either moving the data, or set to center of data, or use 3D cursor";
- ot->idname = "OBJECT_OT_origin_set";
-
- /* api callbacks */
- ot->invoke = WM_menu_invoke;
- ot->exec = object_origin_set_exec;
-
- ot->poll = ED_operator_scene_editable;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- ot->prop = RNA_def_enum(ot->srna, "type", prop_set_center_types, 0, "Type", "");
- RNA_def_enum(ot->srna, "center", prop_set_bounds_types, V3D_AROUND_CENTER_MEDIAN, "Center", "");
+ static const EnumPropertyItem prop_set_center_types[] = {
+ {GEOMETRY_TO_ORIGIN,
+ "GEOMETRY_ORIGIN",
+ 0,
+ "Geometry to Origin",
+ "Move object geometry to object origin"},
+ {ORIGIN_TO_GEOMETRY,
+ "ORIGIN_GEOMETRY",
+ 0,
+ "Origin to Geometry",
+ "Calculate the center of geometry based on the current pivot point (median, otherwise "
+ "bounding-box)"},
+ {ORIGIN_TO_CURSOR,
+ "ORIGIN_CURSOR",
+ 0,
+ "Origin to 3D Cursor",
+ "Move object origin to position of the 3D cursor"},
+ /* Intentional naming mismatch since some scripts refer to this. */
+ {ORIGIN_TO_CENTER_OF_MASS_SURFACE,
+ "ORIGIN_CENTER_OF_MASS",
+ 0,
+ "Origin to Center of Mass (Surface)",
+ "Calculate the center of mass from the surface area"},
+ {ORIGIN_TO_CENTER_OF_MASS_VOLUME,
+ "ORIGIN_CENTER_OF_VOLUME",
+ 0,
+ "Origin to Center of Mass (Volume)",
+ "Calculate the center of mass from the volume (must be manifold geometry with consistent "
+ "normals)"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem prop_set_bounds_types[] = {
+ {V3D_AROUND_CENTER_MEDIAN, "MEDIAN", 0, "Median Center", ""},
+ {V3D_AROUND_CENTER_BOUNDS, "BOUNDS", 0, "Bounds Center", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Set Origin";
+ ot->description =
+ "Set the object's origin, by either moving the data, or set to center of data, or use 3D "
+ "cursor";
+ ot->idname = "OBJECT_OT_origin_set";
+
+ /* api callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = object_origin_set_exec;
+
+ ot->poll = ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_set_center_types, 0, "Type", "");
+ RNA_def_enum(ot->srna, "center", prop_set_bounds_types, V3D_AROUND_CENTER_MEDIAN, "Center", "");
}
/* -------------------------------------------------------------------- */
@@ -1300,431 +1393,429 @@ void OBJECT_OT_origin_set(wmOperatorType *ot)
#define USE_FAKE_DEPTH_INIT
struct XFormAxisItem {
- Object *ob;
- float rot_mat[3][3];
- void *obtfm;
- float xform_dist;
+ Object *ob;
+ float rot_mat[3][3];
+ void *obtfm;
+ float xform_dist;
#ifdef USE_RELATIVE_ROTATION
- /* use when translating multiple */
- float xform_rot_offset[3][3];
+ /* use when translating multiple */
+ float xform_rot_offset[3][3];
#endif
};
struct XFormAxisData {
- ViewContext vc;
- struct {
- float depth;
- float normal[3];
- bool is_depth_valid;
- bool is_normal_valid;
- } prev;
-
- struct XFormAxisItem *object_data;
- uint object_data_len;
- bool is_translate;
-
- int init_event;
+ ViewContext vc;
+ struct {
+ float depth;
+ float normal[3];
+ bool is_depth_valid;
+ bool is_normal_valid;
+ } prev;
+
+ struct XFormAxisItem *object_data;
+ uint object_data_len;
+ bool is_translate;
+
+ int init_event;
};
#ifdef USE_FAKE_DEPTH_INIT
-static void object_transform_axis_target_calc_depth_init(struct XFormAxisData *xfd, const int mval[2])
+static void object_transform_axis_target_calc_depth_init(struct XFormAxisData *xfd,
+ const int mval[2])
{
- struct XFormAxisItem *item = xfd->object_data;
- float view_co_a[3], view_co_b[3];
- const float mval_fl[2] = {UNPACK2(mval)};
- ED_view3d_win_to_ray(xfd->vc.ar, mval_fl, view_co_a, view_co_b);
- add_v3_v3(view_co_b, view_co_a);
- float center[3] = {0.0f};
- int center_tot = 0;
- for (int i = 0; i < xfd->object_data_len; i++, item++) {
- const Object *ob = item->ob;
- const float *ob_co_a = ob->obmat[3];
- float ob_co_b[3];
- add_v3_v3v3(ob_co_b, ob->obmat[3], ob->obmat[2]);
- float view_isect[3], ob_isect[3];
- if (isect_line_line_v3(view_co_a, view_co_b, ob_co_a, ob_co_b, view_isect, ob_isect)) {
- add_v3_v3(center, view_isect);
- center_tot += 1;
- }
- }
- if (center_tot) {
- mul_v3_fl(center, 1.0f / center_tot);
- float center_proj[3];
- ED_view3d_project(xfd->vc.ar, center, center_proj);
- xfd->prev.depth = center_proj[2];
- xfd->prev.is_depth_valid = true;
- }
+ struct XFormAxisItem *item = xfd->object_data;
+ float view_co_a[3], view_co_b[3];
+ const float mval_fl[2] = {UNPACK2(mval)};
+ ED_view3d_win_to_ray(xfd->vc.ar, mval_fl, view_co_a, view_co_b);
+ add_v3_v3(view_co_b, view_co_a);
+ float center[3] = {0.0f};
+ int center_tot = 0;
+ for (int i = 0; i < xfd->object_data_len; i++, item++) {
+ const Object *ob = item->ob;
+ const float *ob_co_a = ob->obmat[3];
+ float ob_co_b[3];
+ add_v3_v3v3(ob_co_b, ob->obmat[3], ob->obmat[2]);
+ float view_isect[3], ob_isect[3];
+ if (isect_line_line_v3(view_co_a, view_co_b, ob_co_a, ob_co_b, view_isect, ob_isect)) {
+ add_v3_v3(center, view_isect);
+ center_tot += 1;
+ }
+ }
+ if (center_tot) {
+ mul_v3_fl(center, 1.0f / center_tot);
+ float center_proj[3];
+ ED_view3d_project(xfd->vc.ar, center, center_proj);
+ xfd->prev.depth = center_proj[2];
+ xfd->prev.is_depth_valid = true;
+ }
}
-#endif /* USE_FAKE_DEPTH_INIT */
+#endif /* USE_FAKE_DEPTH_INIT */
static bool object_is_target_compat(const Object *ob)
{
- if (ob->type == OB_LAMP) {
- const Light *la = ob->data;
- if (ELEM(la->type, LA_SUN, LA_SPOT, LA_AREA)) {
- return true;
- }
- }
- /* We might want to enable this later, for now just lights. */
+ if (ob->type == OB_LAMP) {
+ const Light *la = ob->data;
+ if (ELEM(la->type, LA_SUN, LA_SPOT, LA_AREA)) {
+ return true;
+ }
+ }
+ /* We might want to enable this later, for now just lights. */
#if 0
- else if (ob->type == OB_CAMERA) {
- return true;
- }
+ else if (ob->type == OB_CAMERA) {
+ return true;
+ }
#endif
- return false;
+ return false;
}
static void object_transform_axis_target_free_data(wmOperator *op)
{
- struct XFormAxisData *xfd = op->customdata;
- struct XFormAxisItem *item = xfd->object_data;
+ struct XFormAxisData *xfd = op->customdata;
+ struct XFormAxisItem *item = xfd->object_data;
#ifdef USE_RENDER_OVERRIDE
- if (xfd->vc.rv3d->depths) {
- xfd->vc.rv3d->depths->damaged = true;
- }
+ if (xfd->vc.rv3d->depths) {
+ xfd->vc.rv3d->depths->damaged = true;
+ }
#endif
- for (int i = 0; i < xfd->object_data_len; i++, item++) {
- MEM_freeN(item->obtfm);
- }
- MEM_freeN(xfd->object_data);
- MEM_freeN(xfd);
- op->customdata = NULL;
+ for (int i = 0; i < xfd->object_data_len; i++, item++) {
+ MEM_freeN(item->obtfm);
+ }
+ MEM_freeN(xfd->object_data);
+ MEM_freeN(xfd);
+ op->customdata = NULL;
}
/* We may want to expose as alternative to: BKE_object_apply_rotation */
static void object_apply_rotation(Object *ob, const float rmat[3][3])
{
- float size[3];
- float loc[3];
- float rmat4[4][4];
- copy_m4_m3(rmat4, rmat);
-
- copy_v3_v3(size, ob->scale);
- copy_v3_v3(loc, ob->loc);
- BKE_object_apply_mat4(ob, rmat4, true, true);
- copy_v3_v3(ob->scale, size);
- copy_v3_v3(ob->loc, loc);
+ float size[3];
+ float loc[3];
+ float rmat4[4][4];
+ copy_m4_m3(rmat4, rmat);
+
+ copy_v3_v3(size, ob->scale);
+ copy_v3_v3(loc, ob->loc);
+ BKE_object_apply_mat4(ob, rmat4, true, true);
+ copy_v3_v3(ob->scale, size);
+ copy_v3_v3(ob->loc, loc);
}
/* We may want to extract this to: BKE_object_apply_location */
static void object_apply_location(Object *ob, const float loc[3])
{
- /* quick but weak */
- Object ob_prev = *ob;
- float mat[4][4];
- copy_m4_m4(mat, ob->obmat);
- copy_v3_v3(mat[3], loc);
- BKE_object_apply_mat4(ob, mat, true, true);
- copy_v3_v3(mat[3], ob->loc);
- *ob = ob_prev;
- copy_v3_v3(ob->loc, mat[3]);
+ /* quick but weak */
+ Object ob_prev = *ob;
+ float mat[4][4];
+ copy_m4_m4(mat, ob->obmat);
+ copy_v3_v3(mat[3], loc);
+ BKE_object_apply_mat4(ob, mat, true, true);
+ copy_v3_v3(mat[3], ob->loc);
+ *ob = ob_prev;
+ copy_v3_v3(ob->loc, mat[3]);
}
-static void object_orient_to_location(
- Object *ob, float rot_orig[3][3], const float axis[3], const float location[3])
+static void object_orient_to_location(Object *ob,
+ float rot_orig[3][3],
+ const float axis[3],
+ const float location[3])
{
- float delta[3];
- sub_v3_v3v3(delta, ob->obmat[3], location);
- if (normalize_v3(delta) != 0.0f) {
- if (len_squared_v3v3(delta, axis) > FLT_EPSILON) {
- float delta_rot[3][3];
- float final_rot[3][3];
- rotation_between_vecs_to_mat3(delta_rot, axis, delta);
+ float delta[3];
+ sub_v3_v3v3(delta, ob->obmat[3], location);
+ if (normalize_v3(delta) != 0.0f) {
+ if (len_squared_v3v3(delta, axis) > FLT_EPSILON) {
+ float delta_rot[3][3];
+ float final_rot[3][3];
+ rotation_between_vecs_to_mat3(delta_rot, axis, delta);
- mul_m3_m3m3(final_rot, delta_rot, rot_orig);
+ mul_m3_m3m3(final_rot, delta_rot, rot_orig);
- object_apply_rotation(ob, final_rot);
+ object_apply_rotation(ob, final_rot);
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
- }
- }
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ }
+ }
}
static void object_transform_axis_target_cancel(bContext *C, wmOperator *op)
{
- struct XFormAxisData *xfd = op->customdata;
- struct XFormAxisItem *item = xfd->object_data;
- for (int i = 0; i < xfd->object_data_len; i++, item++) {
- BKE_object_tfm_restore(item->ob, item->obtfm);
- DEG_id_tag_update(&item->ob->id, ID_RECALC_TRANSFORM);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob);
- }
-
- object_transform_axis_target_free_data(op);
+ struct XFormAxisData *xfd = op->customdata;
+ struct XFormAxisItem *item = xfd->object_data;
+ for (int i = 0; i < xfd->object_data_len; i++, item++) {
+ BKE_object_tfm_restore(item->ob, item->obtfm);
+ DEG_id_tag_update(&item->ob->id, ID_RECALC_TRANSFORM);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob);
+ }
+
+ object_transform_axis_target_free_data(op);
}
static int object_transform_axis_target_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ViewContext vc;
- ED_view3d_viewcontext_init(C, &vc);
-
- if (vc.obact == NULL || !object_is_target_compat(vc.obact)) {
- /* Falls back to texture space transform. */
- return OPERATOR_PASS_THROUGH;
- }
+ ViewContext vc;
+ ED_view3d_viewcontext_init(C, &vc);
+ if (vc.obact == NULL || !object_is_target_compat(vc.obact)) {
+ /* Falls back to texture space transform. */
+ return OPERATOR_PASS_THROUGH;
+ }
#ifdef USE_RENDER_OVERRIDE
- int flag2_prev = vc.v3d->flag2;
- vc.v3d->flag2 |= V3D_HIDE_OVERLAYS;
+ int flag2_prev = vc.v3d->flag2;
+ vc.v3d->flag2 |= V3D_HIDE_OVERLAYS;
#endif
- ED_view3d_autodist_init(vc.depsgraph, vc.ar, vc.v3d, 0);
+ ED_view3d_autodist_init(vc.depsgraph, vc.ar, vc.v3d, 0);
- if (vc.rv3d->depths != NULL) {
- vc.rv3d->depths->damaged = true;
- }
- ED_view3d_depth_update(vc.ar);
+ if (vc.rv3d->depths != NULL) {
+ vc.rv3d->depths->damaged = true;
+ }
+ ED_view3d_depth_update(vc.ar);
#ifdef USE_RENDER_OVERRIDE
- vc.v3d->flag2 = flag2_prev;
+ vc.v3d->flag2 = flag2_prev;
#endif
- if (vc.rv3d->depths == NULL) {
- BKE_report(op->reports, RPT_WARNING, "Unable to access depth buffer, using view plane");
- return OPERATOR_CANCELLED;
- }
+ if (vc.rv3d->depths == NULL) {
+ BKE_report(op->reports, RPT_WARNING, "Unable to access depth buffer, using view plane");
+ return OPERATOR_CANCELLED;
+ }
- ED_region_tag_redraw(vc.ar);
+ ED_region_tag_redraw(vc.ar);
- struct XFormAxisData *xfd;
- xfd = op->customdata = MEM_callocN(sizeof(struct XFormAxisData), __func__);
+ struct XFormAxisData *xfd;
+ xfd = op->customdata = MEM_callocN(sizeof(struct XFormAxisData), __func__);
- /* Don't change this at runtime. */
- xfd->vc = vc;
- xfd->vc.mval[0] = event->mval[0];
- xfd->vc.mval[1] = event->mval[1];
+ /* Don't change this at runtime. */
+ xfd->vc = vc;
+ xfd->vc.mval[0] = event->mval[0];
+ xfd->vc.mval[1] = event->mval[1];
- xfd->prev.depth = 1.0f;
- xfd->prev.is_depth_valid = false;
- xfd->prev.is_normal_valid = false;
- xfd->is_translate = false;
+ xfd->prev.depth = 1.0f;
+ xfd->prev.is_depth_valid = false;
+ xfd->prev.is_normal_valid = false;
+ xfd->is_translate = false;
- xfd->init_event = WM_userdef_event_type_from_keymap_type(event->type);
+ xfd->init_event = WM_userdef_event_type_from_keymap_type(event->type);
- {
- struct XFormAxisItem *object_data = NULL;
- BLI_array_declare(object_data);
+ {
+ struct XFormAxisItem *object_data = NULL;
+ BLI_array_declare(object_data);
- struct XFormAxisItem *item = BLI_array_append_ret(object_data);
- item->ob = xfd->vc.obact;
+ struct XFormAxisItem *item = BLI_array_append_ret(object_data);
+ item->ob = xfd->vc.obact;
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if ((ob != xfd->vc.obact) && object_is_target_compat(ob)) {
- item = BLI_array_append_ret(object_data);
- item->ob = ob;
- }
- }
- CTX_DATA_END;
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if ((ob != xfd->vc.obact) && object_is_target_compat(ob)) {
+ item = BLI_array_append_ret(object_data);
+ item->ob = ob;
+ }
+ }
+ CTX_DATA_END;
- xfd->object_data = object_data;
- xfd->object_data_len = BLI_array_len(object_data);
+ xfd->object_data = object_data;
+ xfd->object_data_len = BLI_array_len(object_data);
- if (xfd->object_data_len != BLI_array_len(object_data)) {
- xfd->object_data = MEM_reallocN(xfd->object_data, xfd->object_data_len * sizeof(*xfd->object_data));
- }
- }
+ if (xfd->object_data_len != BLI_array_len(object_data)) {
+ xfd->object_data = MEM_reallocN(xfd->object_data,
+ xfd->object_data_len * sizeof(*xfd->object_data));
+ }
+ }
- {
- struct XFormAxisItem *item = xfd->object_data;
- for (int i = 0; i < xfd->object_data_len; i++, item++) {
- item->obtfm = BKE_object_tfm_backup(item->ob);
- BKE_object_rot_to_mat3(item->ob, item->rot_mat, true);
- }
- }
+ {
+ struct XFormAxisItem *item = xfd->object_data;
+ for (int i = 0; i < xfd->object_data_len; i++, item++) {
+ item->obtfm = BKE_object_tfm_backup(item->ob);
+ BKE_object_rot_to_mat3(item->ob, item->rot_mat, true);
+ }
+ }
- WM_event_add_modal_handler(C, op);
+ WM_event_add_modal_handler(C, op);
- return OPERATOR_RUNNING_MODAL;
+ return OPERATOR_RUNNING_MODAL;
}
static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- struct XFormAxisData *xfd = op->customdata;
- ARegion *ar = xfd->vc.ar;
-
- view3d_operator_needs_opengl(C);
-
- const bool is_translate = (event->ctrl != 0);
- const bool is_translate_init = is_translate && (xfd->is_translate != is_translate);
-
- if (event->type == MOUSEMOVE || is_translate_init) {
- const ViewDepths *depths = xfd->vc.rv3d->depths;
- if (depths &&
- ((unsigned int)event->mval[0] < depths->w) &&
- ((unsigned int)event->mval[1] < depths->h))
- {
- double depth = (double)ED_view3d_depth_read_cached(&xfd->vc, event->mval);
- float location_world[3];
- if (depth == 1.0f) {
- if (xfd->prev.is_depth_valid) {
- depth = (double)xfd->prev.depth;
- }
- }
+ struct XFormAxisData *xfd = op->customdata;
+ ARegion *ar = xfd->vc.ar;
+
+ view3d_operator_needs_opengl(C);
+
+ const bool is_translate = (event->ctrl != 0);
+ const bool is_translate_init = is_translate && (xfd->is_translate != is_translate);
+
+ if (event->type == MOUSEMOVE || is_translate_init) {
+ const ViewDepths *depths = xfd->vc.rv3d->depths;
+ if (depths && ((unsigned int)event->mval[0] < depths->w) &&
+ ((unsigned int)event->mval[1] < depths->h)) {
+ double depth = (double)ED_view3d_depth_read_cached(&xfd->vc, event->mval);
+ float location_world[3];
+ if (depth == 1.0f) {
+ if (xfd->prev.is_depth_valid) {
+ depth = (double)xfd->prev.depth;
+ }
+ }
#ifdef USE_FAKE_DEPTH_INIT
- /* First time only. */
- if (depth == 1.0f) {
- if (xfd->prev.is_depth_valid == false) {
- object_transform_axis_target_calc_depth_init(xfd, event->mval);
- if (xfd->prev.is_depth_valid) {
- depth = (double)xfd->prev.depth;
- }
- }
- }
+ /* First time only. */
+ if (depth == 1.0f) {
+ if (xfd->prev.is_depth_valid == false) {
+ object_transform_axis_target_calc_depth_init(xfd, event->mval);
+ if (xfd->prev.is_depth_valid) {
+ depth = (double)xfd->prev.depth;
+ }
+ }
+ }
#endif
- if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
- xfd->prev.depth = depth;
- xfd->prev.is_depth_valid = true;
- if (ED_view3d_depth_unproject(ar, event->mval, depth, location_world)) {
- if (is_translate) {
-
- float normal[3];
- bool normal_found = false;
- if (ED_view3d_depth_read_cached_normal(&xfd->vc, event->mval, normal)) {
- normal_found = true;
-
- /* cheap attempt to smooth normals out a bit! */
- const uint ofs = 2;
- for (uint x = -ofs; x <= ofs; x += ofs / 2) {
- for (uint y = -ofs; y <= ofs; y += ofs / 2) {
- if (x != 0 && y != 0) {
- int mval_ofs[2] = {event->mval[0] + x, event->mval[1] + y};
- float n[3];
- if (ED_view3d_depth_read_cached_normal(
- &xfd->vc, mval_ofs, n))
- {
- add_v3_v3(normal, n);
- }
- }
- }
- }
- normalize_v3(normal);
- }
- else if (xfd->prev.is_normal_valid) {
- copy_v3_v3(normal, xfd->prev.normal);
- normal_found = true;
- }
-
- if (normal_found) {
+ if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
+ xfd->prev.depth = depth;
+ xfd->prev.is_depth_valid = true;
+ if (ED_view3d_depth_unproject(ar, event->mval, depth, location_world)) {
+ if (is_translate) {
+
+ float normal[3];
+ bool normal_found = false;
+ if (ED_view3d_depth_read_cached_normal(&xfd->vc, event->mval, normal)) {
+ normal_found = true;
+
+ /* cheap attempt to smooth normals out a bit! */
+ const uint ofs = 2;
+ for (uint x = -ofs; x <= ofs; x += ofs / 2) {
+ for (uint y = -ofs; y <= ofs; y += ofs / 2) {
+ if (x != 0 && y != 0) {
+ int mval_ofs[2] = {event->mval[0] + x, event->mval[1] + y};
+ float n[3];
+ if (ED_view3d_depth_read_cached_normal(&xfd->vc, mval_ofs, n)) {
+ add_v3_v3(normal, n);
+ }
+ }
+ }
+ }
+ normalize_v3(normal);
+ }
+ else if (xfd->prev.is_normal_valid) {
+ copy_v3_v3(normal, xfd->prev.normal);
+ normal_found = true;
+ }
+
+ if (normal_found) {
#ifdef USE_RELATIVE_ROTATION
- if (is_translate_init && xfd->object_data_len > 1) {
- float xform_rot_offset_inv_first[3][3];
- struct XFormAxisItem *item = xfd->object_data;
- for (int i = 0; i < xfd->object_data_len; i++, item++) {
- copy_m3_m4(item->xform_rot_offset, item->ob->obmat);
- normalize_m3(item->xform_rot_offset);
-
- if (i == 0) {
- invert_m3_m3(xform_rot_offset_inv_first, xfd->object_data[0].xform_rot_offset);
- }
- else {
- mul_m3_m3m3(item->xform_rot_offset,
- item->xform_rot_offset,
- xform_rot_offset_inv_first);
- }
- }
- }
+ if (is_translate_init && xfd->object_data_len > 1) {
+ float xform_rot_offset_inv_first[3][3];
+ struct XFormAxisItem *item = xfd->object_data;
+ for (int i = 0; i < xfd->object_data_len; i++, item++) {
+ copy_m3_m4(item->xform_rot_offset, item->ob->obmat);
+ normalize_m3(item->xform_rot_offset);
+
+ if (i == 0) {
+ invert_m3_m3(xform_rot_offset_inv_first, xfd->object_data[0].xform_rot_offset);
+ }
+ else {
+ mul_m3_m3m3(item->xform_rot_offset,
+ item->xform_rot_offset,
+ xform_rot_offset_inv_first);
+ }
+ }
+ }
#endif
- struct XFormAxisItem *item = xfd->object_data;
- for (int i = 0; i < xfd->object_data_len; i++, item++) {
- if (is_translate_init) {
- float ob_axis[3];
- item->xform_dist = len_v3v3(item->ob->obmat[3], location_world);
- normalize_v3_v3(ob_axis, item->ob->obmat[2]);
- /* Scale to avoid adding distance when moving between surfaces. */
- float scale = fabsf(dot_v3v3(ob_axis, normal));
- item->xform_dist *= scale;
- }
+ struct XFormAxisItem *item = xfd->object_data;
+ for (int i = 0; i < xfd->object_data_len; i++, item++) {
+ if (is_translate_init) {
+ float ob_axis[3];
+ item->xform_dist = len_v3v3(item->ob->obmat[3], location_world);
+ normalize_v3_v3(ob_axis, item->ob->obmat[2]);
+ /* Scale to avoid adding distance when moving between surfaces. */
+ float scale = fabsf(dot_v3v3(ob_axis, normal));
+ item->xform_dist *= scale;
+ }
- float target_normal[3];
- copy_v3_v3(target_normal, normal);
+ float target_normal[3];
+ copy_v3_v3(target_normal, normal);
#ifdef USE_RELATIVE_ROTATION
- if (i != 0) {
- mul_m3_v3(item->xform_rot_offset, target_normal);
- }
+ if (i != 0) {
+ mul_m3_v3(item->xform_rot_offset, target_normal);
+ }
#endif
- {
- float loc[3];
-
- copy_v3_v3(loc, location_world);
- madd_v3_v3fl(loc, target_normal, item->xform_dist);
- object_apply_location(item->ob, loc);
- /* so orient behaves as expected */
- copy_v3_v3(item->ob->obmat[3], loc);
- }
-
- object_orient_to_location(item->ob, item->rot_mat, item->rot_mat[2], location_world);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob);
- }
- copy_v3_v3(xfd->prev.normal, normal);
- xfd->prev.is_normal_valid = true;
- }
- }
- else {
- struct XFormAxisItem *item = xfd->object_data;
- for (int i = 0; i < xfd->object_data_len; i++, item++) {
- object_orient_to_location(item->ob, item->rot_mat, item->rot_mat[2], location_world);
- WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob);
- }
- xfd->prev.is_normal_valid = false;
- }
- }
- }
- }
- xfd->is_translate = is_translate;
-
- ED_region_tag_redraw(xfd->vc.ar);
- }
-
- bool is_finished = false;
-
- if (ISMOUSE(xfd->init_event)) {
- if ((event->type == xfd->init_event) && (event->val == KM_RELEASE)) {
- is_finished = true;
- }
- }
- else {
- if (ELEM(event->type, LEFTMOUSE, RETKEY, PADENTER)) {
- is_finished = true;
- }
- }
-
- if (is_finished) {
- object_transform_axis_target_free_data(op);
- return OPERATOR_FINISHED;
- }
- else if (ELEM(event->type, ESCKEY, RIGHTMOUSE)) {
- object_transform_axis_target_cancel(C, op);
- return OPERATOR_CANCELLED;
- }
-
-
- return OPERATOR_RUNNING_MODAL;
+ {
+ float loc[3];
+
+ copy_v3_v3(loc, location_world);
+ madd_v3_v3fl(loc, target_normal, item->xform_dist);
+ object_apply_location(item->ob, loc);
+ /* so orient behaves as expected */
+ copy_v3_v3(item->ob->obmat[3], loc);
+ }
+
+ object_orient_to_location(
+ item->ob, item->rot_mat, item->rot_mat[2], location_world);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob);
+ }
+ copy_v3_v3(xfd->prev.normal, normal);
+ xfd->prev.is_normal_valid = true;
+ }
+ }
+ else {
+ struct XFormAxisItem *item = xfd->object_data;
+ for (int i = 0; i < xfd->object_data_len; i++, item++) {
+ object_orient_to_location(item->ob, item->rot_mat, item->rot_mat[2], location_world);
+ WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob);
+ }
+ xfd->prev.is_normal_valid = false;
+ }
+ }
+ }
+ }
+ xfd->is_translate = is_translate;
+
+ ED_region_tag_redraw(xfd->vc.ar);
+ }
+
+ bool is_finished = false;
+
+ if (ISMOUSE(xfd->init_event)) {
+ if ((event->type == xfd->init_event) && (event->val == KM_RELEASE)) {
+ is_finished = true;
+ }
+ }
+ else {
+ if (ELEM(event->type, LEFTMOUSE, RETKEY, PADENTER)) {
+ is_finished = true;
+ }
+ }
+
+ if (is_finished) {
+ object_transform_axis_target_free_data(op);
+ return OPERATOR_FINISHED;
+ }
+ else if (ELEM(event->type, ESCKEY, RIGHTMOUSE)) {
+ object_transform_axis_target_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
}
void OBJECT_OT_transform_axis_target(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Interactive Light Track to Cursor";
- ot->description = "Interactively point cameras and lights to a location (Ctrl translates)";
- ot->idname = "OBJECT_OT_transform_axis_target";
-
- /* api callbacks */
- ot->invoke = object_transform_axis_target_invoke;
- ot->cancel = object_transform_axis_target_cancel;
- ot->modal = object_transform_axis_target_modal;
- ot->poll = ED_operator_region_view3d_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+ /* identifiers */
+ ot->name = "Interactive Light Track to Cursor";
+ ot->description = "Interactively point cameras and lights to a location (Ctrl translates)";
+ ot->idname = "OBJECT_OT_transform_axis_target";
+
+ /* api callbacks */
+ ot->invoke = object_transform_axis_target_invoke;
+ ot->cancel = object_transform_axis_target_cancel;
+ ot->modal = object_transform_axis_target_modal;
+ ot->poll = ED_operator_region_view3d_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
}
#undef USE_RELATIVE_ROTATION
diff --git a/source/blender/editors/object/object_utils.c b/source/blender/editors/object/object_utils.c
index 39f5dad7698..06a755c30bd 100644
--- a/source/blender/editors/object/object_utils.c
+++ b/source/blender/editors/object/object_utils.c
@@ -39,111 +39,106 @@
#include "ED_armature.h"
#include "ED_curve.h"
-#include "ED_object.h" /* own include */
-
+#include "ED_object.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Active Element Center
* \{ */
-bool ED_object_calc_active_center_for_editmode(
- Object *obedit, const bool select_only, float r_center[3])
+bool ED_object_calc_active_center_for_editmode(Object *obedit,
+ const bool select_only,
+ float r_center[3])
{
- switch (obedit->type) {
- case OB_MESH:
- {
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMEditSelection ese;
-
- if (BM_select_history_active_get(em->bm, &ese)) {
- BM_editselection_center(&ese, r_center);
- return true;
- }
- break;
- }
- case OB_ARMATURE:
- {
- bArmature *arm = obedit->data;
- EditBone *ebo = arm->act_edbone;
-
- if (ebo && (!select_only || (ebo->flag & (BONE_SELECTED | BONE_ROOTSEL)))) {
- copy_v3_v3(r_center, ebo->head);
- return true;
- }
-
- break;
- }
- case OB_CURVE:
- case OB_SURF:
- {
- Curve *cu = obedit->data;
-
- if (ED_curve_active_center(cu, r_center)) {
- return true;
- }
- break;
- }
- case OB_MBALL:
- {
- MetaBall *mb = obedit->data;
- MetaElem *ml_act = mb->lastelem;
-
- if (ml_act && (!select_only || (ml_act->flag & SELECT))) {
- copy_v3_v3(r_center, &ml_act->x);
- return true;
- }
- break;
- }
- case OB_LATTICE:
- {
- BPoint *actbp = BKE_lattice_active_point_get(obedit->data);
-
- if (actbp) {
- copy_v3_v3(r_center, actbp->vec);
- return true;
- }
- break;
- }
- }
-
- return false;
+ switch (obedit->type) {
+ case OB_MESH: {
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMEditSelection ese;
+
+ if (BM_select_history_active_get(em->bm, &ese)) {
+ BM_editselection_center(&ese, r_center);
+ return true;
+ }
+ break;
+ }
+ case OB_ARMATURE: {
+ bArmature *arm = obedit->data;
+ EditBone *ebo = arm->act_edbone;
+
+ if (ebo && (!select_only || (ebo->flag & (BONE_SELECTED | BONE_ROOTSEL)))) {
+ copy_v3_v3(r_center, ebo->head);
+ return true;
+ }
+
+ break;
+ }
+ case OB_CURVE:
+ case OB_SURF: {
+ Curve *cu = obedit->data;
+
+ if (ED_curve_active_center(cu, r_center)) {
+ return true;
+ }
+ break;
+ }
+ case OB_MBALL: {
+ MetaBall *mb = obedit->data;
+ MetaElem *ml_act = mb->lastelem;
+
+ if (ml_act && (!select_only || (ml_act->flag & SELECT))) {
+ copy_v3_v3(r_center, &ml_act->x);
+ return true;
+ }
+ break;
+ }
+ case OB_LATTICE: {
+ BPoint *actbp = BKE_lattice_active_point_get(obedit->data);
+
+ if (actbp) {
+ copy_v3_v3(r_center, actbp->vec);
+ return true;
+ }
+ break;
+ }
+ }
+
+ return false;
}
-bool ED_object_calc_active_center_for_posemode(
- Object *ob, const bool select_only, float r_center[3])
+bool ED_object_calc_active_center_for_posemode(Object *ob,
+ const bool select_only,
+ float r_center[3])
{
- bPoseChannel *pchan = BKE_pose_channel_active(ob);
- if (pchan && (!select_only || (pchan->bone->flag & BONE_SELECTED))) {
- copy_v3_v3(r_center, pchan->pose_head);
- return true;
- }
- return false;
+ bPoseChannel *pchan = BKE_pose_channel_active(ob);
+ if (pchan && (!select_only || (pchan->bone->flag & BONE_SELECTED))) {
+ copy_v3_v3(r_center, pchan->pose_head);
+ return true;
+ }
+ return false;
}
-bool ED_object_calc_active_center(
- Object *ob, const bool select_only, float r_center[3])
+bool ED_object_calc_active_center(Object *ob, const bool select_only, float r_center[3])
{
- if (ob->mode & OB_MODE_EDIT) {
- if (ED_object_calc_active_center_for_editmode(ob, select_only, r_center)) {
- mul_m4_v3(ob->obmat, r_center);
- return true;
- }
- return false;
- }
- else if (ob->mode & OB_MODE_POSE) {
- if (ED_object_calc_active_center_for_posemode(ob, select_only, r_center)) {
- mul_m4_v3(ob->obmat, r_center);
- return true;
- }
- return false;
- }
- else {
- if (!select_only || (ob->flag & SELECT)) {
- copy_v3_v3(r_center, ob->obmat[3]);
- return true;
- }
- return false;
- }
+ if (ob->mode & OB_MODE_EDIT) {
+ if (ED_object_calc_active_center_for_editmode(ob, select_only, r_center)) {
+ mul_m4_v3(ob->obmat, r_center);
+ return true;
+ }
+ return false;
+ }
+ else if (ob->mode & OB_MODE_POSE) {
+ if (ED_object_calc_active_center_for_posemode(ob, select_only, r_center)) {
+ mul_m4_v3(ob->obmat, r_center);
+ return true;
+ }
+ return false;
+ }
+ else {
+ if (!select_only || (ob->flag & SELECT)) {
+ copy_v3_v3(r_center, ob->obmat[3]);
+ return true;
+ }
+ return false;
+ }
}
/** \} */
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index cd8b7d082ef..9af0b64bde2 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -44,7 +44,6 @@
#include "BLI_utildefines.h"
#include "BLI_utildefines_stack.h"
-
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_deform.h"
@@ -78,40 +77,39 @@
/************************ Exported Functions **********************/
static bool vertex_group_use_vert_sel(Object *ob)
{
- if (ob->mode == OB_MODE_EDIT) {
- return true;
- }
- else if ((ob->type == OB_MESH) &&
- ((Mesh *)ob->data)->editflag & (ME_EDIT_PAINT_VERT_SEL | ME_EDIT_PAINT_FACE_SEL))
- {
- return true;
- }
- else {
- return false;
- }
+ if (ob->mode == OB_MODE_EDIT) {
+ return true;
+ }
+ else if ((ob->type == OB_MESH) &&
+ ((Mesh *)ob->data)->editflag & (ME_EDIT_PAINT_VERT_SEL | ME_EDIT_PAINT_FACE_SEL)) {
+ return true;
+ }
+ else {
+ return false;
+ }
}
static Lattice *vgroup_edit_lattice(Object *ob)
{
- Lattice *lt = ob->data;
- BLI_assert(ob->type == OB_LATTICE);
- return (lt->editlatt) ? lt->editlatt->latt : lt;
+ Lattice *lt = ob->data;
+ BLI_assert(ob->type == OB_LATTICE);
+ return (lt->editlatt) ? lt->editlatt->latt : lt;
}
bool ED_vgroup_sync_from_pose(Object *ob)
{
- Object *armobj = BKE_object_pose_armature_get(ob);
- if (armobj && (armobj->mode & OB_MODE_POSE)) {
- struct bArmature *arm = armobj->data;
- if (arm->act_bone) {
- int def_num = defgroup_name_index(ob, arm->act_bone->name);
- if (def_num != -1) {
- ob->actdef = def_num + 1;
- return true;
- }
- }
- }
- return false;
+ Object *armobj = BKE_object_pose_armature_get(ob);
+ if (armobj && (armobj->mode & OB_MODE_POSE)) {
+ struct bArmature *arm = armobj->data;
+ if (arm->act_bone) {
+ int def_num = defgroup_name_index(ob, arm->act_bone->name);
+ if (def_num != -1) {
+ ob->actdef = def_num + 1;
+ return true;
+ }
+ }
+ }
+ return false;
}
/**
@@ -119,128 +117,128 @@ bool ED_vgroup_sync_from_pose(Object *ob)
*/
void ED_vgroup_data_clamp_range(ID *id, const int total)
{
- MDeformVert **dvert_arr;
- int dvert_tot;
-
- if (ED_vgroup_parray_alloc(id, &dvert_arr, &dvert_tot, false)) {
- int i;
- for (i = 0; i < dvert_tot; i++) {
- MDeformVert *dv = dvert_arr[i];
- int j;
- for (j = 0; j < dv->totweight; j++) {
- if (dv->dw[j].def_nr >= total) {
- defvert_remove_group(dv, &dv->dw[j]);
- j--;
- }
- }
- }
- }
-}
-
-bool ED_vgroup_parray_alloc(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, const bool use_vert_sel)
-{
- *dvert_tot = 0;
- *dvert_arr = NULL;
-
- if (id) {
- switch (GS(id->name)) {
- case ID_ME:
- {
- Mesh *me = (Mesh *)id;
-
- if (me->edit_mesh) {
- BMEditMesh *em = me->edit_mesh;
- BMesh *bm = em->bm;
- const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
- BMIter iter;
- BMVert *eve;
- int i;
-
- if (cd_dvert_offset == -1) {
- return false;
- }
-
- i = em->bm->totvert;
-
- *dvert_arr = MEM_mallocN(sizeof(void *) * i, "vgroup parray from me");
- *dvert_tot = i;
-
- i = 0;
- if (use_vert_sel) {
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- (*dvert_arr)[i] = BM_elem_flag_test(eve, BM_ELEM_SELECT) ?
- BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset) : NULL;
- i++;
- }
- }
- else {
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- (*dvert_arr)[i] = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
- i++;
- }
- }
-
- return true;
- }
- else if (me->dvert) {
- MVert *mvert = me->mvert;
- MDeformVert *dvert = me->dvert;
- int i;
-
- *dvert_tot = me->totvert;
- *dvert_arr = MEM_mallocN(sizeof(void *) * me->totvert, "vgroup parray from me");
-
- if (use_vert_sel) {
- for (i = 0; i < me->totvert; i++) {
- (*dvert_arr)[i] = (mvert[i].flag & SELECT) ?
- &dvert[i] : NULL;
- }
- }
- else {
- for (i = 0; i < me->totvert; i++) {
- (*dvert_arr)[i] = me->dvert + i;
- }
- }
-
- return true;
- }
- return false;
- }
- case ID_LT:
- {
- int i = 0;
-
- Lattice *lt = (Lattice *)id;
- lt = (lt->editlatt) ? lt->editlatt->latt : lt;
-
- if (lt->dvert) {
- BPoint *def = lt->def;
- *dvert_tot = lt->pntsu * lt->pntsv * lt->pntsw;
- *dvert_arr = MEM_mallocN(sizeof(void *) * (*dvert_tot), "vgroup parray from me");
-
- if (use_vert_sel) {
- for (i = 0; i < *dvert_tot; i++) {
- (*dvert_arr)[i] = (def->f1 & SELECT) ?
- &lt->dvert[i] : NULL;
- }
- }
- else {
- for (i = 0; i < *dvert_tot; i++) {
- (*dvert_arr)[i] = lt->dvert + i;
- }
- }
-
- return true;
- }
- return false;
- }
-
- default:
- break;
- }
- }
-
- return false;
+ MDeformVert **dvert_arr;
+ int dvert_tot;
+
+ if (ED_vgroup_parray_alloc(id, &dvert_arr, &dvert_tot, false)) {
+ int i;
+ for (i = 0; i < dvert_tot; i++) {
+ MDeformVert *dv = dvert_arr[i];
+ int j;
+ for (j = 0; j < dv->totweight; j++) {
+ if (dv->dw[j].def_nr >= total) {
+ defvert_remove_group(dv, &dv->dw[j]);
+ j--;
+ }
+ }
+ }
+ }
+}
+
+bool ED_vgroup_parray_alloc(ID *id,
+ MDeformVert ***dvert_arr,
+ int *dvert_tot,
+ const bool use_vert_sel)
+{
+ *dvert_tot = 0;
+ *dvert_arr = NULL;
+
+ if (id) {
+ switch (GS(id->name)) {
+ case ID_ME: {
+ Mesh *me = (Mesh *)id;
+
+ if (me->edit_mesh) {
+ BMEditMesh *em = me->edit_mesh;
+ BMesh *bm = em->bm;
+ const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
+ BMIter iter;
+ BMVert *eve;
+ int i;
+
+ if (cd_dvert_offset == -1) {
+ return false;
+ }
+
+ i = em->bm->totvert;
+
+ *dvert_arr = MEM_mallocN(sizeof(void *) * i, "vgroup parray from me");
+ *dvert_tot = i;
+
+ i = 0;
+ if (use_vert_sel) {
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ (*dvert_arr)[i] = BM_elem_flag_test(eve, BM_ELEM_SELECT) ?
+ BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset) :
+ NULL;
+ i++;
+ }
+ }
+ else {
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ (*dvert_arr)[i] = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+ i++;
+ }
+ }
+
+ return true;
+ }
+ else if (me->dvert) {
+ MVert *mvert = me->mvert;
+ MDeformVert *dvert = me->dvert;
+ int i;
+
+ *dvert_tot = me->totvert;
+ *dvert_arr = MEM_mallocN(sizeof(void *) * me->totvert, "vgroup parray from me");
+
+ if (use_vert_sel) {
+ for (i = 0; i < me->totvert; i++) {
+ (*dvert_arr)[i] = (mvert[i].flag & SELECT) ? &dvert[i] : NULL;
+ }
+ }
+ else {
+ for (i = 0; i < me->totvert; i++) {
+ (*dvert_arr)[i] = me->dvert + i;
+ }
+ }
+
+ return true;
+ }
+ return false;
+ }
+ case ID_LT: {
+ int i = 0;
+
+ Lattice *lt = (Lattice *)id;
+ lt = (lt->editlatt) ? lt->editlatt->latt : lt;
+
+ if (lt->dvert) {
+ BPoint *def = lt->def;
+ *dvert_tot = lt->pntsu * lt->pntsv * lt->pntsw;
+ *dvert_arr = MEM_mallocN(sizeof(void *) * (*dvert_tot), "vgroup parray from me");
+
+ if (use_vert_sel) {
+ for (i = 0; i < *dvert_tot; i++) {
+ (*dvert_arr)[i] = (def->f1 & SELECT) ? &lt->dvert[i] : NULL;
+ }
+ }
+ else {
+ for (i = 0; i < *dvert_tot; i++) {
+ (*dvert_arr)[i] = lt->dvert + i;
+ }
+ }
+
+ return true;
+ }
+ return false;
+ }
+
+ default:
+ break;
+ }
+ }
+
+ return false;
}
/**
@@ -249,45 +247,46 @@ bool ED_vgroup_parray_alloc(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, co
*
* \note \a dvert_array has mirrored weights filled in, in case cleanup operations are needed on both.
*/
-void ED_vgroup_parray_mirror_sync(
- Object *ob,
- MDeformVert **dvert_array, const int dvert_tot,
- const bool *vgroup_validmap, const int vgroup_tot)
-{
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- MDeformVert **dvert_array_all = NULL;
- int dvert_tot_all;
-
- /* get an array of all verts, not only selected */
- if (ED_vgroup_parray_alloc(ob->data, &dvert_array_all, &dvert_tot_all, false) == false) {
- BLI_assert(0);
- return;
- }
- if (em) {
- BM_mesh_elem_table_ensure(em->bm, BM_VERT);
- }
-
- int flip_map_len;
- const int *flip_map = defgroup_flip_map(ob, &flip_map_len, true);
-
- for (int i_src = 0; i_src < dvert_tot; i_src++) {
- if (dvert_array[i_src] != NULL) {
- /* its selected, check if its mirror exists */
- int i_dst = ED_mesh_mirror_get_vert(ob, i_src);
- if (i_dst != -1 && dvert_array_all[i_dst] != NULL) {
- /* we found a match! */
- const MDeformVert *dv_src = dvert_array[i_src];
- MDeformVert *dv_dst = dvert_array_all[i_dst];
-
- defvert_mirror_subset(dv_dst, dv_src, vgroup_validmap, vgroup_tot, flip_map, flip_map_len);
-
- dvert_array[i_dst] = dvert_array_all[i_dst];
- }
- }
- }
-
- MEM_freeN((void *)flip_map);
- MEM_freeN(dvert_array_all);
+void ED_vgroup_parray_mirror_sync(Object *ob,
+ MDeformVert **dvert_array,
+ const int dvert_tot,
+ const bool *vgroup_validmap,
+ const int vgroup_tot)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ MDeformVert **dvert_array_all = NULL;
+ int dvert_tot_all;
+
+ /* get an array of all verts, not only selected */
+ if (ED_vgroup_parray_alloc(ob->data, &dvert_array_all, &dvert_tot_all, false) == false) {
+ BLI_assert(0);
+ return;
+ }
+ if (em) {
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ }
+
+ int flip_map_len;
+ const int *flip_map = defgroup_flip_map(ob, &flip_map_len, true);
+
+ for (int i_src = 0; i_src < dvert_tot; i_src++) {
+ if (dvert_array[i_src] != NULL) {
+ /* its selected, check if its mirror exists */
+ int i_dst = ED_mesh_mirror_get_vert(ob, i_src);
+ if (i_dst != -1 && dvert_array_all[i_dst] != NULL) {
+ /* we found a match! */
+ const MDeformVert *dv_src = dvert_array[i_src];
+ MDeformVert *dv_dst = dvert_array_all[i_dst];
+
+ defvert_mirror_subset(dv_dst, dv_src, vgroup_validmap, vgroup_tot, flip_map, flip_map_len);
+
+ dvert_array[i_dst] = dvert_array_all[i_dst];
+ }
+ }
+ }
+
+ MEM_freeN((void *)flip_map);
+ MEM_freeN(dvert_array_all);
}
/**
@@ -295,247 +294,252 @@ void ED_vgroup_parray_mirror_sync(
*
* similar to #ED_vgroup_parray_mirror_sync but only fill in mirror points.
*/
-void ED_vgroup_parray_mirror_assign(
- Object *ob,
- MDeformVert **dvert_array, const int dvert_tot)
-{
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- MDeformVert **dvert_array_all = NULL;
- int dvert_tot_all;
- int i;
-
- /* get an array of all verts, not only selected */
- if (ED_vgroup_parray_alloc(ob->data, &dvert_array_all, &dvert_tot_all, false) == false) {
- BLI_assert(0);
- return;
- }
- BLI_assert(dvert_tot == dvert_tot_all);
- if (em) {
- BM_mesh_elem_table_ensure(em->bm, BM_VERT);
- }
-
- for (i = 0; i < dvert_tot; i++) {
- if (dvert_array[i] == NULL) {
- /* its unselected, check if its mirror is */
- int i_sel = ED_mesh_mirror_get_vert(ob, i);
- if ((i_sel != -1) && (i_sel != i) && (dvert_array[i_sel])) {
- /* we found a match! */
- dvert_array[i] = dvert_array_all[i];
- }
- }
- }
-
- MEM_freeN(dvert_array_all);
-}
-
-void ED_vgroup_parray_remove_zero(
- MDeformVert **dvert_array, const int dvert_tot,
- const bool *vgroup_validmap, const int vgroup_tot,
- const float epsilon, const bool keep_single)
-{
- MDeformVert *dv;
- int i;
-
- for (i = 0; i < dvert_tot; i++) {
- int j;
-
- /* in case its not selected */
- if (!(dv = dvert_array[i])) {
- continue;
- }
-
- j = dv->totweight;
-
- while (j--) {
- MDeformWeight *dw;
-
- if (keep_single && dv->totweight == 1)
- break;
-
- dw = dv->dw + j;
- if ((dw->def_nr < vgroup_tot) && vgroup_validmap[dw->def_nr]) {
- if (dw->weight <= epsilon) {
- defvert_remove_group(dv, dw);
- }
- }
- }
- }
+void ED_vgroup_parray_mirror_assign(Object *ob, MDeformVert **dvert_array, const int dvert_tot)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ MDeformVert **dvert_array_all = NULL;
+ int dvert_tot_all;
+ int i;
+
+ /* get an array of all verts, not only selected */
+ if (ED_vgroup_parray_alloc(ob->data, &dvert_array_all, &dvert_tot_all, false) == false) {
+ BLI_assert(0);
+ return;
+ }
+ BLI_assert(dvert_tot == dvert_tot_all);
+ if (em) {
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ }
+
+ for (i = 0; i < dvert_tot; i++) {
+ if (dvert_array[i] == NULL) {
+ /* its unselected, check if its mirror is */
+ int i_sel = ED_mesh_mirror_get_vert(ob, i);
+ if ((i_sel != -1) && (i_sel != i) && (dvert_array[i_sel])) {
+ /* we found a match! */
+ dvert_array[i] = dvert_array_all[i];
+ }
+ }
+ }
+
+ MEM_freeN(dvert_array_all);
+}
+
+void ED_vgroup_parray_remove_zero(MDeformVert **dvert_array,
+ const int dvert_tot,
+ const bool *vgroup_validmap,
+ const int vgroup_tot,
+ const float epsilon,
+ const bool keep_single)
+{
+ MDeformVert *dv;
+ int i;
+
+ for (i = 0; i < dvert_tot; i++) {
+ int j;
+
+ /* in case its not selected */
+ if (!(dv = dvert_array[i])) {
+ continue;
+ }
+
+ j = dv->totweight;
+
+ while (j--) {
+ MDeformWeight *dw;
+
+ if (keep_single && dv->totweight == 1)
+ break;
+
+ dw = dv->dw + j;
+ if ((dw->def_nr < vgroup_tot) && vgroup_validmap[dw->def_nr]) {
+ if (dw->weight <= epsilon) {
+ defvert_remove_group(dv, dw);
+ }
+ }
+ }
+ }
}
/* matching index only */
bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
{
- MDeformVert **dvert_array_from = NULL, **dvf;
- MDeformVert **dvert_array = NULL, **dv;
- int dvert_tot_from;
- int dvert_tot;
- int i;
- int defbase_tot_from = BLI_listbase_count(&ob_from->defbase);
- int defbase_tot = BLI_listbase_count(&ob->defbase);
- bool new_vgroup = false;
-
- if (ob == ob_from)
- return true;
-
- /* in case we copy vgroup between two objects using same data, we only have to care about object side of things. */
- if (ob->data != ob_from->data) {
- ED_vgroup_parray_alloc(ob_from->data, &dvert_array_from, &dvert_tot_from, false);
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
-
- if ((dvert_array == NULL) && (dvert_array_from != NULL) && BKE_object_defgroup_data_create(ob->data)) {
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
- new_vgroup = true;
- }
-
- if (dvert_tot == 0 || (dvert_tot != dvert_tot_from) || dvert_array_from == NULL || dvert_array == NULL) {
- if (dvert_array)
- MEM_freeN(dvert_array);
- if (dvert_array_from)
- MEM_freeN(dvert_array_from);
-
- if (new_vgroup == true) {
- /* free the newly added vgroup since it wasn't compatible */
- BKE_object_defgroup_remove_all(ob);
- }
-
- /* if true: both are 0 and nothing needs changing, consider this a success */
- return (dvert_tot == dvert_tot_from);
- }
- }
-
- /* do the copy */
- BLI_freelistN(&ob->defbase);
- BLI_duplicatelist(&ob->defbase, &ob_from->defbase);
- ob->actdef = ob_from->actdef;
-
- if (defbase_tot_from < defbase_tot) {
- /* correct vgroup indices because the number of vgroups is being reduced. */
- int *remap = MEM_mallocN(sizeof(int) * (defbase_tot + 1), __func__);
- for (i = 0; i <= defbase_tot_from; i++) remap[i] = i;
- for (; i <= defbase_tot; i++) remap[i] = 0; /* can't use these, so disable */
-
- BKE_object_defgroup_remap_update_users(ob, remap);
- MEM_freeN(remap);
- }
-
- if (dvert_array_from != NULL && dvert_array != NULL) {
- dvf = dvert_array_from;
- dv = dvert_array;
-
- for (i = 0; i < dvert_tot; i++, dvf++, dv++) {
- MEM_SAFE_FREE((*dv)->dw);
- *(*dv) = *(*dvf);
-
- if ((*dv)->dw) {
- (*dv)->dw = MEM_dupallocN((*dv)->dw);
- }
- }
-
- MEM_freeN(dvert_array);
- MEM_freeN(dvert_array_from);
- }
-
- return true;
-}
-
-void ED_vgroup_parray_to_weight_array(
- const MDeformVert **dvert_array, const int dvert_tot,
- float *dvert_weights, const int def_nr)
-{
- int i;
-
- for (i = 0; i < dvert_tot; i++) {
- const MDeformVert *dv = dvert_array[i];
- dvert_weights[i] = dv ? defvert_find_weight(dv, def_nr) : 0.0f;
- }
-}
-
-void ED_vgroup_parray_from_weight_array(
- MDeformVert **dvert_array, const int dvert_tot,
- const float *dvert_weights, const int def_nr, const bool remove_zero)
-{
- int i;
-
- for (i = 0; i < dvert_tot; i++) {
- MDeformVert *dv = dvert_array[i];
- if (dv) {
- if (dvert_weights[i] > 0.0f) {
- MDeformWeight *dw = defvert_verify_index(dv, def_nr);
- BLI_assert(IN_RANGE_INCL(dvert_weights[i], 0.0f, 1.0f));
- dw->weight = dvert_weights[i];
- }
- else {
- MDeformWeight *dw = defvert_find_index(dv, def_nr);
- if (dw) {
- if (remove_zero) {
- defvert_remove_group(dv, dw);
- }
- else {
- dw->weight = 0.0f;
- }
- }
- }
- }
- }
+ MDeformVert **dvert_array_from = NULL, **dvf;
+ MDeformVert **dvert_array = NULL, **dv;
+ int dvert_tot_from;
+ int dvert_tot;
+ int i;
+ int defbase_tot_from = BLI_listbase_count(&ob_from->defbase);
+ int defbase_tot = BLI_listbase_count(&ob->defbase);
+ bool new_vgroup = false;
+
+ if (ob == ob_from)
+ return true;
+
+ /* in case we copy vgroup between two objects using same data, we only have to care about object side of things. */
+ if (ob->data != ob_from->data) {
+ ED_vgroup_parray_alloc(ob_from->data, &dvert_array_from, &dvert_tot_from, false);
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
+
+ if ((dvert_array == NULL) && (dvert_array_from != NULL) &&
+ BKE_object_defgroup_data_create(ob->data)) {
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
+ new_vgroup = true;
+ }
+
+ if (dvert_tot == 0 || (dvert_tot != dvert_tot_from) || dvert_array_from == NULL ||
+ dvert_array == NULL) {
+ if (dvert_array)
+ MEM_freeN(dvert_array);
+ if (dvert_array_from)
+ MEM_freeN(dvert_array_from);
+
+ if (new_vgroup == true) {
+ /* free the newly added vgroup since it wasn't compatible */
+ BKE_object_defgroup_remove_all(ob);
+ }
+
+ /* if true: both are 0 and nothing needs changing, consider this a success */
+ return (dvert_tot == dvert_tot_from);
+ }
+ }
+
+ /* do the copy */
+ BLI_freelistN(&ob->defbase);
+ BLI_duplicatelist(&ob->defbase, &ob_from->defbase);
+ ob->actdef = ob_from->actdef;
+
+ if (defbase_tot_from < defbase_tot) {
+ /* correct vgroup indices because the number of vgroups is being reduced. */
+ int *remap = MEM_mallocN(sizeof(int) * (defbase_tot + 1), __func__);
+ for (i = 0; i <= defbase_tot_from; i++)
+ remap[i] = i;
+ for (; i <= defbase_tot; i++)
+ remap[i] = 0; /* can't use these, so disable */
+
+ BKE_object_defgroup_remap_update_users(ob, remap);
+ MEM_freeN(remap);
+ }
+
+ if (dvert_array_from != NULL && dvert_array != NULL) {
+ dvf = dvert_array_from;
+ dv = dvert_array;
+
+ for (i = 0; i < dvert_tot; i++, dvf++, dv++) {
+ MEM_SAFE_FREE((*dv)->dw);
+ *(*dv) = *(*dvf);
+
+ if ((*dv)->dw) {
+ (*dv)->dw = MEM_dupallocN((*dv)->dw);
+ }
+ }
+
+ MEM_freeN(dvert_array);
+ MEM_freeN(dvert_array_from);
+ }
+
+ return true;
}
+void ED_vgroup_parray_to_weight_array(const MDeformVert **dvert_array,
+ const int dvert_tot,
+ float *dvert_weights,
+ const int def_nr)
+{
+ int i;
-/* TODO, cache flip data to speedup calls within a loop. */
-static void mesh_defvert_mirror_update_internal(
- Object *ob,
- MDeformVert *dvert_dst, MDeformVert *dvert_src,
- const int def_nr)
-{
- if (def_nr == -1) {
- /* all vgroups, add groups where needed */
- int flip_map_len;
- int *flip_map = defgroup_flip_map(ob, &flip_map_len, true);
- defvert_sync_mapped(dvert_dst, dvert_src, flip_map, flip_map_len, true);
- MEM_freeN(flip_map);
- }
- else {
- /* single vgroup */
- MDeformWeight *dw = defvert_verify_index(dvert_dst, defgroup_flip_index(ob, def_nr, 1));
- if (dw) {
- dw->weight = defvert_find_weight(dvert_src, def_nr);
- }
- }
+ for (i = 0; i < dvert_tot; i++) {
+ const MDeformVert *dv = dvert_array[i];
+ dvert_weights[i] = dv ? defvert_find_weight(dv, def_nr) : 0.0f;
+ }
}
-static void ED_mesh_defvert_mirror_update_em(
- Object *ob, BMVert *eve, int def_nr, int vidx,
- const int cd_dvert_offset)
+void ED_vgroup_parray_from_weight_array(MDeformVert **dvert_array,
+ const int dvert_tot,
+ const float *dvert_weights,
+ const int def_nr,
+ const bool remove_zero)
{
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- BMVert *eve_mirr;
- bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+ int i;
+
+ for (i = 0; i < dvert_tot; i++) {
+ MDeformVert *dv = dvert_array[i];
+ if (dv) {
+ if (dvert_weights[i] > 0.0f) {
+ MDeformWeight *dw = defvert_verify_index(dv, def_nr);
+ BLI_assert(IN_RANGE_INCL(dvert_weights[i], 0.0f, 1.0f));
+ dw->weight = dvert_weights[i];
+ }
+ else {
+ MDeformWeight *dw = defvert_find_index(dv, def_nr);
+ if (dw) {
+ if (remove_zero) {
+ defvert_remove_group(dv, dw);
+ }
+ else {
+ dw->weight = 0.0f;
+ }
+ }
+ }
+ }
+ }
+}
- eve_mirr = editbmesh_get_x_mirror_vert(ob, em, eve, eve->co, vidx, use_topology);
+/* TODO, cache flip data to speedup calls within a loop. */
+static void mesh_defvert_mirror_update_internal(Object *ob,
+ MDeformVert *dvert_dst,
+ MDeformVert *dvert_src,
+ const int def_nr)
+{
+ if (def_nr == -1) {
+ /* all vgroups, add groups where needed */
+ int flip_map_len;
+ int *flip_map = defgroup_flip_map(ob, &flip_map_len, true);
+ defvert_sync_mapped(dvert_dst, dvert_src, flip_map, flip_map_len, true);
+ MEM_freeN(flip_map);
+ }
+ else {
+ /* single vgroup */
+ MDeformWeight *dw = defvert_verify_index(dvert_dst, defgroup_flip_index(ob, def_nr, 1));
+ if (dw) {
+ dw->weight = defvert_find_weight(dvert_src, def_nr);
+ }
+ }
+}
- if (eve_mirr && eve_mirr != eve) {
- MDeformVert *dvert_src = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
- MDeformVert *dvert_dst = BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset);
- mesh_defvert_mirror_update_internal(ob, dvert_dst, dvert_src, def_nr);
- }
+static void ED_mesh_defvert_mirror_update_em(
+ Object *ob, BMVert *eve, int def_nr, int vidx, const int cd_dvert_offset)
+{
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ BMVert *eve_mirr;
+ bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+
+ eve_mirr = editbmesh_get_x_mirror_vert(ob, em, eve, eve->co, vidx, use_topology);
+
+ if (eve_mirr && eve_mirr != eve) {
+ MDeformVert *dvert_src = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+ MDeformVert *dvert_dst = BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset);
+ mesh_defvert_mirror_update_internal(ob, dvert_dst, dvert_src, def_nr);
+ }
}
static void ED_mesh_defvert_mirror_update_ob(Object *ob, int def_nr, int vidx)
{
- int vidx_mirr;
- Mesh *me = ob->data;
- bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+ int vidx_mirr;
+ Mesh *me = ob->data;
+ bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
- if (vidx == -1)
- return;
+ if (vidx == -1)
+ return;
- vidx_mirr = mesh_get_x_mirror_vert(ob, NULL, vidx, use_topology);
+ vidx_mirr = mesh_get_x_mirror_vert(ob, NULL, vidx, use_topology);
- if ((vidx_mirr) >= 0 && (vidx_mirr != vidx)) {
- MDeformVert *dvert_src = &me->dvert[vidx];
- MDeformVert *dvert_dst = &me->dvert[vidx_mirr];
- mesh_defvert_mirror_update_internal(ob, dvert_dst, dvert_src, def_nr);
- }
+ if ((vidx_mirr) >= 0 && (vidx_mirr != vidx)) {
+ MDeformVert *dvert_src = &me->dvert[vidx];
+ MDeformVert *dvert_dst = &me->dvert[vidx_mirr];
+ mesh_defvert_mirror_update_internal(ob, dvert_dst, dvert_src, def_nr);
+ }
}
/**
@@ -543,420 +547,426 @@ static void ED_mesh_defvert_mirror_update_ob(Object *ob, int def_nr, int vidx)
*/
void ED_vgroup_vert_active_mirror(Object *ob, int def_nr)
{
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- MDeformVert *dvert_act;
-
- if (me->editflag & ME_EDIT_MIRROR_X) {
- if (em) {
- BMVert *eve_act;
- dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
- if (dvert_act) {
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
- ED_mesh_defvert_mirror_update_em(ob, eve_act, def_nr, -1, cd_dvert_offset);
- }
- }
- else {
- int v_act;
- dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
- if (dvert_act) {
- ED_mesh_defvert_mirror_update_ob(ob, def_nr, v_act);
- }
- }
- }
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ MDeformVert *dvert_act;
+
+ if (me->editflag & ME_EDIT_MIRROR_X) {
+ if (em) {
+ BMVert *eve_act;
+ dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
+ if (dvert_act) {
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+ ED_mesh_defvert_mirror_update_em(ob, eve_act, def_nr, -1, cd_dvert_offset);
+ }
+ }
+ else {
+ int v_act;
+ dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
+ if (dvert_act) {
+ ED_mesh_defvert_mirror_update_ob(ob, def_nr, v_act);
+ }
+ }
+ }
}
static void vgroup_remove_weight(Object *ob, const int def_nr)
{
- MDeformVert *dvert_act;
- MDeformWeight *dw;
-
- dvert_act = ED_mesh_active_dvert_get_only(ob);
+ MDeformVert *dvert_act;
+ MDeformWeight *dw;
- dw = defvert_find_index(dvert_act, def_nr);
- defvert_remove_group(dvert_act, dw);
+ dvert_act = ED_mesh_active_dvert_get_only(ob);
+ dw = defvert_find_index(dvert_act, def_nr);
+ defvert_remove_group(dvert_act, dw);
}
static bool vgroup_normalize_active_vertex(Object *ob, eVGroupSelect subset_type)
{
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- BMVert *eve_act;
- int v_act;
- MDeformVert *dvert_act;
- int subset_count, vgroup_tot;
- const bool *vgroup_validmap;
-
-
- if (em) {
- dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
- }
- else {
- dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
- }
-
- if (dvert_act == NULL) {
- return false;
- }
-
- vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
- defvert_normalize_subset(dvert_act, vgroup_validmap, vgroup_tot);
- MEM_freeN((void *)vgroup_validmap);
-
- if (me->editflag & ME_EDIT_MIRROR_X) {
- if (em) {
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
- ED_mesh_defvert_mirror_update_em(ob, eve_act, -1, -1, cd_dvert_offset);
- }
- else {
- ED_mesh_defvert_mirror_update_ob(ob, -1, v_act);
- }
- }
-
- return true;
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ BMVert *eve_act;
+ int v_act;
+ MDeformVert *dvert_act;
+ int subset_count, vgroup_tot;
+ const bool *vgroup_validmap;
+
+ if (em) {
+ dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
+ }
+ else {
+ dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
+ }
+
+ if (dvert_act == NULL) {
+ return false;
+ }
+
+ vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
+ ob, subset_type, &vgroup_tot, &subset_count);
+ defvert_normalize_subset(dvert_act, vgroup_validmap, vgroup_tot);
+ MEM_freeN((void *)vgroup_validmap);
+
+ if (me->editflag & ME_EDIT_MIRROR_X) {
+ if (em) {
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+ ED_mesh_defvert_mirror_update_em(ob, eve_act, -1, -1, cd_dvert_offset);
+ }
+ else {
+ ED_mesh_defvert_mirror_update_ob(ob, -1, v_act);
+ }
+ }
+
+ return true;
}
static void vgroup_copy_active_to_sel(Object *ob, eVGroupSelect subset_type)
{
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- MDeformVert *dvert_act;
- int i, vgroup_tot, subset_count;
- const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
-
-
- if (em) {
- BMIter iter;
- BMVert *eve, *eve_act;
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
-
- dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
- if (dvert_act) {
- BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && eve != eve_act) {
- MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
- defvert_copy_subset(dv, dvert_act, vgroup_validmap, vgroup_tot);
- if (me->editflag & ME_EDIT_MIRROR_X) {
- ED_mesh_defvert_mirror_update_em(ob, eve, -1, i, cd_dvert_offset);
- }
- }
- }
- }
- }
- else {
- MDeformVert *dv;
- int v_act;
-
- dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
- if (dvert_act) {
- dv = me->dvert;
- for (i = 0; i < me->totvert; i++, dv++) {
- if ((me->mvert[i].flag & SELECT) && dv != dvert_act) {
- defvert_copy_subset(dv, dvert_act, vgroup_validmap, vgroup_tot);
- if (me->editflag & ME_EDIT_MIRROR_X) {
- ED_mesh_defvert_mirror_update_ob(ob, -1, i);
- }
- }
- }
- }
- }
-
- MEM_freeN((void *)vgroup_validmap);
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ MDeformVert *dvert_act;
+ int i, vgroup_tot, subset_count;
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
+ ob, subset_type, &vgroup_tot, &subset_count);
+
+ if (em) {
+ BMIter iter;
+ BMVert *eve, *eve_act;
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+
+ dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
+ if (dvert_act) {
+ BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && eve != eve_act) {
+ MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+ defvert_copy_subset(dv, dvert_act, vgroup_validmap, vgroup_tot);
+ if (me->editflag & ME_EDIT_MIRROR_X) {
+ ED_mesh_defvert_mirror_update_em(ob, eve, -1, i, cd_dvert_offset);
+ }
+ }
+ }
+ }
+ }
+ else {
+ MDeformVert *dv;
+ int v_act;
+
+ dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
+ if (dvert_act) {
+ dv = me->dvert;
+ for (i = 0; i < me->totvert; i++, dv++) {
+ if ((me->mvert[i].flag & SELECT) && dv != dvert_act) {
+ defvert_copy_subset(dv, dvert_act, vgroup_validmap, vgroup_tot);
+ if (me->editflag & ME_EDIT_MIRROR_X) {
+ ED_mesh_defvert_mirror_update_ob(ob, -1, i);
+ }
+ }
+ }
+ }
+ }
+
+ MEM_freeN((void *)vgroup_validmap);
}
/***********************Start weight transfer (WT)*********************************/
static const EnumPropertyItem WT_vertex_group_select_item[] = {
- {WT_VGROUP_ACTIVE,
- "ACTIVE", 0, "Active Group", "The active Vertex Group"},
- {WT_VGROUP_BONE_SELECT,
- "BONE_SELECT", 0, "Selected Pose Bones", "All Vertex Groups assigned to Selection"},
- {WT_VGROUP_BONE_DEFORM,
- "BONE_DEFORM", 0, "Deform Pose Bones", "All Vertex Groups assigned to Deform Bones"},
- {WT_VGROUP_ALL,
- "ALL", 0, "All Groups", "All Vertex Groups"},
- {0, NULL, 0, NULL, NULL},
+ {WT_VGROUP_ACTIVE, "ACTIVE", 0, "Active Group", "The active Vertex Group"},
+ {WT_VGROUP_BONE_SELECT,
+ "BONE_SELECT",
+ 0,
+ "Selected Pose Bones",
+ "All Vertex Groups assigned to Selection"},
+ {WT_VGROUP_BONE_DEFORM,
+ "BONE_DEFORM",
+ 0,
+ "Deform Pose Bones",
+ "All Vertex Groups assigned to Deform Bones"},
+ {WT_VGROUP_ALL, "ALL", 0, "All Groups", "All Vertex Groups"},
+ {0, NULL, 0, NULL, NULL},
};
-const EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(
- const bContext *C, PointerRNA *UNUSED(ptr),
- PropertyRNA *UNUSED(prop), bool *r_free, const unsigned int selection_mask)
+const EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(const bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free,
+ const unsigned int selection_mask)
{
- Object *ob;
- EnumPropertyItem *item = NULL;
- int totitem = 0;
-
- if (C == NULL) {
- /* needed for docs and i18n tools */
- return WT_vertex_group_select_item;
- }
-
- ob = CTX_data_active_object(C);
- if (selection_mask & (1 << WT_VGROUP_ACTIVE))
- RNA_enum_items_add_value(&item, &totitem, WT_vertex_group_select_item, WT_VGROUP_ACTIVE);
-
- if (BKE_object_pose_armature_get(ob)) {
- if (selection_mask & (1 << WT_VGROUP_BONE_SELECT))
- RNA_enum_items_add_value(&item, &totitem, WT_vertex_group_select_item, WT_VGROUP_BONE_SELECT);
- if (selection_mask & (1 << WT_VGROUP_BONE_DEFORM))
- RNA_enum_items_add_value(&item, &totitem, WT_vertex_group_select_item, WT_VGROUP_BONE_DEFORM);
- }
-
- if (selection_mask & (1 << WT_VGROUP_ALL))
- RNA_enum_items_add_value(&item, &totitem, WT_vertex_group_select_item, WT_VGROUP_ALL);
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ Object *ob;
+ EnumPropertyItem *item = NULL;
+ int totitem = 0;
+
+ if (C == NULL) {
+ /* needed for docs and i18n tools */
+ return WT_vertex_group_select_item;
+ }
+
+ ob = CTX_data_active_object(C);
+ if (selection_mask & (1 << WT_VGROUP_ACTIVE))
+ RNA_enum_items_add_value(&item, &totitem, WT_vertex_group_select_item, WT_VGROUP_ACTIVE);
+
+ if (BKE_object_pose_armature_get(ob)) {
+ if (selection_mask & (1 << WT_VGROUP_BONE_SELECT))
+ RNA_enum_items_add_value(
+ &item, &totitem, WT_vertex_group_select_item, WT_VGROUP_BONE_SELECT);
+ if (selection_mask & (1 << WT_VGROUP_BONE_DEFORM))
+ RNA_enum_items_add_value(
+ &item, &totitem, WT_vertex_group_select_item, WT_VGROUP_BONE_DEFORM);
+ }
+
+ if (selection_mask & (1 << WT_VGROUP_ALL))
+ RNA_enum_items_add_value(&item, &totitem, WT_vertex_group_select_item, WT_VGROUP_ALL);
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
-static const EnumPropertyItem *rna_vertex_group_with_single_itemf(
- bContext *C, PointerRNA *ptr,
- PropertyRNA *prop, bool *r_free)
+static const EnumPropertyItem *rna_vertex_group_with_single_itemf(bContext *C,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ bool *r_free)
{
- return ED_object_vgroup_selection_itemf_helper(C, ptr, prop, r_free, WT_VGROUP_MASK_ALL);
+ return ED_object_vgroup_selection_itemf_helper(C, ptr, prop, r_free, WT_VGROUP_MASK_ALL);
}
-static const EnumPropertyItem *rna_vertex_group_select_itemf(
- bContext *C, PointerRNA *ptr,
- PropertyRNA *prop, bool *r_free)
+static const EnumPropertyItem *rna_vertex_group_select_itemf(bContext *C,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ bool *r_free)
{
- return ED_object_vgroup_selection_itemf_helper(
- C, ptr, prop, r_free, WT_VGROUP_MASK_ALL & ~(1 << WT_VGROUP_ACTIVE));
+ return ED_object_vgroup_selection_itemf_helper(
+ C, ptr, prop, r_free, WT_VGROUP_MASK_ALL & ~(1 << WT_VGROUP_ACTIVE));
}
static void vgroup_operator_subset_select_props(wmOperatorType *ot, bool use_active)
{
- PropertyRNA *prop;
-
- prop = RNA_def_enum(
- ot->srna,
- "group_select_mode", DummyRNA_NULL_items,
- use_active ? WT_VGROUP_ACTIVE : WT_VGROUP_ALL, "Subset",
- "Define which subset of Groups shall be used");
-
- if (use_active) {
- RNA_def_enum_funcs(prop, rna_vertex_group_with_single_itemf);
- }
- else {
- RNA_def_enum_funcs(prop, rna_vertex_group_select_itemf);
- }
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ prop = RNA_def_enum(ot->srna,
+ "group_select_mode",
+ DummyRNA_NULL_items,
+ use_active ? WT_VGROUP_ACTIVE : WT_VGROUP_ALL,
+ "Subset",
+ "Define which subset of Groups shall be used");
+
+ if (use_active) {
+ RNA_def_enum_funcs(prop, rna_vertex_group_with_single_itemf);
+ }
+ else {
+ RNA_def_enum_funcs(prop, rna_vertex_group_select_itemf);
+ }
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
-
/***********************End weight transfer (WT)***********************************/
/* for Mesh in Object mode */
/* allows editmode for Lattice */
static void ED_vgroup_nr_vert_add(
- Object *ob,
- const int def_nr, const int vertnum,
- const float weight, const int assignmode)
-{
- /* add the vert to the deform group with the
- * specified number
- */
- MDeformVert *dvert = NULL;
- int tot;
-
- /* get the vert */
- BKE_object_defgroup_array_get(ob->data, &dvert, &tot);
-
- if (dvert == NULL)
- return;
-
- /* check that vertnum is valid before trying to get the relevant dvert */
- if ((vertnum < 0) || (vertnum >= tot))
- return;
-
-
- if (dvert) {
- MDeformVert *dv = &dvert[vertnum];
- MDeformWeight *dw;
-
- /* Lets first check to see if this vert is
- * already in the weight group -- if so
- * lets update it
- */
-
- dw = defvert_find_index(dv, def_nr);
-
- if (dw) {
- switch (assignmode) {
- case WEIGHT_REPLACE:
- dw->weight = weight;
- break;
- case WEIGHT_ADD:
- dw->weight += weight;
- if (dw->weight >= 1.0f)
- dw->weight = 1.0f;
- break;
- case WEIGHT_SUBTRACT:
- dw->weight -= weight;
- /* if the weight is zero or less than
- * remove the vert from the deform group
- */
- if (dw->weight <= 0.0f) {
- defvert_remove_group(dv, dw);
- }
- break;
- }
- }
- else {
- /* if the vert wasn't in the deform group then
- * we must take a different form of action ...
- */
-
- switch (assignmode) {
- case WEIGHT_SUBTRACT:
- /* if we are subtracting then we don't
- * need to do anything
- */
- return;
-
- case WEIGHT_REPLACE:
- case WEIGHT_ADD:
- /* if we are doing an additive assignment, then
- * we need to create the deform weight
- */
-
- /* we checked if the vertex was added before so no need to test again, simply add */
- defvert_add_index_notest(dv, def_nr, weight);
- break;
- }
- }
- }
+ Object *ob, const int def_nr, const int vertnum, const float weight, const int assignmode)
+{
+ /* add the vert to the deform group with the
+ * specified number
+ */
+ MDeformVert *dvert = NULL;
+ int tot;
+
+ /* get the vert */
+ BKE_object_defgroup_array_get(ob->data, &dvert, &tot);
+
+ if (dvert == NULL)
+ return;
+
+ /* check that vertnum is valid before trying to get the relevant dvert */
+ if ((vertnum < 0) || (vertnum >= tot))
+ return;
+
+ if (dvert) {
+ MDeformVert *dv = &dvert[vertnum];
+ MDeformWeight *dw;
+
+ /* Lets first check to see if this vert is
+ * already in the weight group -- if so
+ * lets update it
+ */
+
+ dw = defvert_find_index(dv, def_nr);
+
+ if (dw) {
+ switch (assignmode) {
+ case WEIGHT_REPLACE:
+ dw->weight = weight;
+ break;
+ case WEIGHT_ADD:
+ dw->weight += weight;
+ if (dw->weight >= 1.0f)
+ dw->weight = 1.0f;
+ break;
+ case WEIGHT_SUBTRACT:
+ dw->weight -= weight;
+ /* if the weight is zero or less than
+ * remove the vert from the deform group
+ */
+ if (dw->weight <= 0.0f) {
+ defvert_remove_group(dv, dw);
+ }
+ break;
+ }
+ }
+ else {
+ /* if the vert wasn't in the deform group then
+ * we must take a different form of action ...
+ */
+
+ switch (assignmode) {
+ case WEIGHT_SUBTRACT:
+ /* if we are subtracting then we don't
+ * need to do anything
+ */
+ return;
+
+ case WEIGHT_REPLACE:
+ case WEIGHT_ADD:
+ /* if we are doing an additive assignment, then
+ * we need to create the deform weight
+ */
+
+ /* we checked if the vertex was added before so no need to test again, simply add */
+ defvert_add_index_notest(dv, def_nr, weight);
+ break;
+ }
+ }
+ }
}
/* called while not in editmode */
void ED_vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight, int assignmode)
{
- /* add the vert to the deform group with the
- * specified assign mode
- */
- const int def_nr = BLI_findindex(&ob->defbase, dg);
-
- MDeformVert *dv = NULL;
- int tot;
-
- /* get the deform group number, exit if
- * it can't be found
- */
- if (def_nr != -1) {
-
- /* if there's no deform verts then create some,
- */
- if (BKE_object_defgroup_array_get(ob->data, &dv, &tot) && dv == NULL)
- BKE_object_defgroup_data_create(ob->data);
-
- /* call another function to do the work
- */
- ED_vgroup_nr_vert_add(ob, def_nr, vertnum, weight, assignmode);
- }
+ /* add the vert to the deform group with the
+ * specified assign mode
+ */
+ const int def_nr = BLI_findindex(&ob->defbase, dg);
+
+ MDeformVert *dv = NULL;
+ int tot;
+
+ /* get the deform group number, exit if
+ * it can't be found
+ */
+ if (def_nr != -1) {
+
+ /* if there's no deform verts then create some,
+ */
+ if (BKE_object_defgroup_array_get(ob->data, &dv, &tot) && dv == NULL)
+ BKE_object_defgroup_data_create(ob->data);
+
+ /* call another function to do the work
+ */
+ ED_vgroup_nr_vert_add(ob, def_nr, vertnum, weight, assignmode);
+ }
}
/* mesh object mode, lattice can be in editmode */
void ED_vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum)
{
- /* This routine removes the vertex from the specified
- * deform group.
- */
-
- /* TODO, this is slow in a loop, better pass def_nr directly, but leave for later... - campbell */
- const int def_nr = BLI_findindex(&ob->defbase, dg);
-
- if (def_nr != -1) {
- MDeformVert *dvert = NULL;
- int tot;
-
- /* get the deform vertices corresponding to the
- * vertnum
- */
- BKE_object_defgroup_array_get(ob->data, &dvert, &tot);
-
- if (dvert) {
- MDeformVert *dv = &dvert[vertnum];
- MDeformWeight *dw;
-
- dw = defvert_find_index(dv, def_nr);
- defvert_remove_group(dv, dw); /* dw can be NULL */
- }
- }
+ /* This routine removes the vertex from the specified
+ * deform group.
+ */
+
+ /* TODO, this is slow in a loop, better pass def_nr directly, but leave for later... - campbell */
+ const int def_nr = BLI_findindex(&ob->defbase, dg);
+
+ if (def_nr != -1) {
+ MDeformVert *dvert = NULL;
+ int tot;
+
+ /* get the deform vertices corresponding to the
+ * vertnum
+ */
+ BKE_object_defgroup_array_get(ob->data, &dvert, &tot);
+
+ if (dvert) {
+ MDeformVert *dv = &dvert[vertnum];
+ MDeformWeight *dw;
+
+ dw = defvert_find_index(dv, def_nr);
+ defvert_remove_group(dv, dw); /* dw can be NULL */
+ }
+ }
}
static float get_vert_def_nr(Object *ob, const int def_nr, const int vertnum)
{
- MDeformVert *dv = NULL;
-
- /* get the deform vertices corresponding to the vertnum */
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
-
- if (me->edit_mesh) {
- BMEditMesh *em = me->edit_mesh;
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
- /* warning, this lookup is _not_ fast */
-
- if (cd_dvert_offset != -1 && vertnum < em->bm->totvert) {
- BMVert *eve;
- BM_mesh_elem_table_ensure(em->bm, BM_VERT);
- eve = BM_vert_at_index(em->bm, vertnum);
- dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
- }
- else {
- return 0.0f;
- }
- }
- else {
- if (me->dvert) {
- if (vertnum >= me->totvert) {
- return 0.0f;
- }
- dv = &me->dvert[vertnum];
- }
- }
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = vgroup_edit_lattice(ob);
-
- if (lt->dvert) {
- if (vertnum >= lt->pntsu * lt->pntsv * lt->pntsw) {
- return 0.0f;
- }
- dv = &lt->dvert[vertnum];
- }
- }
-
- if (dv) {
- MDeformWeight *dw = defvert_find_index(dv, def_nr);
- if (dw) {
- return dw->weight;
- }
- }
-
- return -1;
+ MDeformVert *dv = NULL;
+
+ /* get the deform vertices corresponding to the vertnum */
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (me->edit_mesh) {
+ BMEditMesh *em = me->edit_mesh;
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+ /* warning, this lookup is _not_ fast */
+
+ if (cd_dvert_offset != -1 && vertnum < em->bm->totvert) {
+ BMVert *eve;
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ eve = BM_vert_at_index(em->bm, vertnum);
+ dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+ }
+ else {
+ return 0.0f;
+ }
+ }
+ else {
+ if (me->dvert) {
+ if (vertnum >= me->totvert) {
+ return 0.0f;
+ }
+ dv = &me->dvert[vertnum];
+ }
+ }
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = vgroup_edit_lattice(ob);
+
+ if (lt->dvert) {
+ if (vertnum >= lt->pntsu * lt->pntsv * lt->pntsw) {
+ return 0.0f;
+ }
+ dv = &lt->dvert[vertnum];
+ }
+ }
+
+ if (dv) {
+ MDeformWeight *dw = defvert_find_index(dv, def_nr);
+ if (dw) {
+ return dw->weight;
+ }
+ }
+
+ return -1;
}
float ED_vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum)
{
- const int def_nr = BLI_findindex(&ob->defbase, dg);
+ const int def_nr = BLI_findindex(&ob->defbase, dg);
- if (def_nr == -1) {
- return -1;
- }
+ if (def_nr == -1) {
+ return -1;
+ }
- return get_vert_def_nr(ob, def_nr, vertnum);
+ return get_vert_def_nr(ob, def_nr, vertnum);
}
void ED_vgroup_select_by_name(Object *ob, const char *name)
{
- /* note: ob->actdef==0 signals on painting to create a new one,
+ /* note: ob->actdef==0 signals on painting to create a new one,
* if a bone in posemode is selected */
- ob->actdef = defgroup_name_index(ob, name) + 1;
+ ob->actdef = defgroup_name_index(ob, name) + 1;
}
/********************** Operator Implementations *********************/
@@ -964,186 +974,192 @@ void ED_vgroup_select_by_name(Object *ob, const char *name)
/* only in editmode */
static void vgroup_select_verts(Object *ob, int select)
{
- const int def_nr = ob->actdef - 1;
-
- if (!BLI_findlink(&ob->defbase, def_nr)) {
- return;
- }
-
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
-
- if (me->edit_mesh) {
- BMEditMesh *em = me->edit_mesh;
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
-
- if (cd_dvert_offset != -1) {
- BMIter iter;
- BMVert *eve;
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
- if (defvert_find_index(dv, def_nr)) {
- BM_vert_select_set(em->bm, eve, select);
- }
- }
- }
-
- /* this has to be called, because this function operates on vertices only */
- if (select) EDBM_select_flush(em); /* vertices to edges/faces */
- else EDBM_deselect_flush(em);
- }
- }
- else {
- if (me->dvert) {
- MVert *mv;
- MDeformVert *dv;
- int i;
-
- mv = me->mvert;
- dv = me->dvert;
-
- for (i = 0; i < me->totvert; i++, mv++, dv++) {
- if (!(mv->flag & ME_HIDE)) {
- if (defvert_find_index(dv, def_nr)) {
- if (select) mv->flag |= SELECT;
- else mv->flag &= ~SELECT;
- }
- }
- }
-
- paintvert_flush_flags(ob);
- }
- }
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = vgroup_edit_lattice(ob);
-
- if (lt->dvert) {
- MDeformVert *dv;
- BPoint *bp, *actbp = BKE_lattice_active_point_get(lt);
- int a, tot;
-
- dv = lt->dvert;
-
- tot = lt->pntsu * lt->pntsv * lt->pntsw;
- for (a = 0, bp = lt->def; a < tot; a++, bp++, dv++) {
- if (defvert_find_index(dv, def_nr)) {
- if (select) bp->f1 |= SELECT;
- else {
- bp->f1 &= ~SELECT;
- if (actbp && bp == actbp) lt->actbp = LT_ACTBP_NONE;
- }
- }
- }
- }
- }
+ const int def_nr = ob->actdef - 1;
+
+ if (!BLI_findlink(&ob->defbase, def_nr)) {
+ return;
+ }
+
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (me->edit_mesh) {
+ BMEditMesh *em = me->edit_mesh;
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+
+ if (cd_dvert_offset != -1) {
+ BMIter iter;
+ BMVert *eve;
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
+ MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+ if (defvert_find_index(dv, def_nr)) {
+ BM_vert_select_set(em->bm, eve, select);
+ }
+ }
+ }
+
+ /* this has to be called, because this function operates on vertices only */
+ if (select)
+ EDBM_select_flush(em); /* vertices to edges/faces */
+ else
+ EDBM_deselect_flush(em);
+ }
+ }
+ else {
+ if (me->dvert) {
+ MVert *mv;
+ MDeformVert *dv;
+ int i;
+
+ mv = me->mvert;
+ dv = me->dvert;
+
+ for (i = 0; i < me->totvert; i++, mv++, dv++) {
+ if (!(mv->flag & ME_HIDE)) {
+ if (defvert_find_index(dv, def_nr)) {
+ if (select)
+ mv->flag |= SELECT;
+ else
+ mv->flag &= ~SELECT;
+ }
+ }
+ }
+
+ paintvert_flush_flags(ob);
+ }
+ }
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = vgroup_edit_lattice(ob);
+
+ if (lt->dvert) {
+ MDeformVert *dv;
+ BPoint *bp, *actbp = BKE_lattice_active_point_get(lt);
+ int a, tot;
+
+ dv = lt->dvert;
+
+ tot = lt->pntsu * lt->pntsv * lt->pntsw;
+ for (a = 0, bp = lt->def; a < tot; a++, bp++, dv++) {
+ if (defvert_find_index(dv, def_nr)) {
+ if (select)
+ bp->f1 |= SELECT;
+ else {
+ bp->f1 &= ~SELECT;
+ if (actbp && bp == actbp)
+ lt->actbp = LT_ACTBP_NONE;
+ }
+ }
+ }
+ }
+ }
}
static void vgroup_duplicate(Object *ob)
{
- bDeformGroup *dg, *cdg;
- char name[sizeof(dg->name)];
- MDeformWeight *dw_org, *dw_cpy;
- MDeformVert **dvert_array = NULL;
- int i, idg, icdg, dvert_tot = 0;
-
- dg = BLI_findlink(&ob->defbase, (ob->actdef - 1));
- if (!dg)
- return;
-
- if (!strstr(dg->name, "_copy")) {
- BLI_snprintf(name, sizeof(name), "%s_copy", dg->name);
- }
- else {
- BLI_strncpy(name, dg->name, sizeof(name));
- }
-
- cdg = defgroup_duplicate(dg);
- BLI_strncpy(cdg->name, name, sizeof(cdg->name));
- defgroup_unique_name(cdg, ob);
-
- BLI_addtail(&ob->defbase, cdg);
-
- idg = (ob->actdef - 1);
- ob->actdef = BLI_listbase_count(&ob->defbase);
- icdg = (ob->actdef - 1);
-
- /* TODO, we might want to allow only copy selected verts here? - campbell */
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
-
- if (dvert_array) {
- for (i = 0; i < dvert_tot; i++) {
- MDeformVert *dv = dvert_array[i];
- dw_org = defvert_find_index(dv, idg);
- if (dw_org) {
- /* defvert_verify_index re-allocs org so need to store the weight first */
- const float weight = dw_org->weight;
- dw_cpy = defvert_verify_index(dv, icdg);
- dw_cpy->weight = weight;
- }
- }
-
- MEM_freeN(dvert_array);
- }
+ bDeformGroup *dg, *cdg;
+ char name[sizeof(dg->name)];
+ MDeformWeight *dw_org, *dw_cpy;
+ MDeformVert **dvert_array = NULL;
+ int i, idg, icdg, dvert_tot = 0;
+
+ dg = BLI_findlink(&ob->defbase, (ob->actdef - 1));
+ if (!dg)
+ return;
+
+ if (!strstr(dg->name, "_copy")) {
+ BLI_snprintf(name, sizeof(name), "%s_copy", dg->name);
+ }
+ else {
+ BLI_strncpy(name, dg->name, sizeof(name));
+ }
+
+ cdg = defgroup_duplicate(dg);
+ BLI_strncpy(cdg->name, name, sizeof(cdg->name));
+ defgroup_unique_name(cdg, ob);
+
+ BLI_addtail(&ob->defbase, cdg);
+
+ idg = (ob->actdef - 1);
+ ob->actdef = BLI_listbase_count(&ob->defbase);
+ icdg = (ob->actdef - 1);
+
+ /* TODO, we might want to allow only copy selected verts here? - campbell */
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
+
+ if (dvert_array) {
+ for (i = 0; i < dvert_tot; i++) {
+ MDeformVert *dv = dvert_array[i];
+ dw_org = defvert_find_index(dv, idg);
+ if (dw_org) {
+ /* defvert_verify_index re-allocs org so need to store the weight first */
+ const float weight = dw_org->weight;
+ dw_cpy = defvert_verify_index(dv, icdg);
+ dw_cpy->weight = weight;
+ }
+ }
+
+ MEM_freeN(dvert_array);
+ }
}
static bool vgroup_normalize(Object *ob)
{
- MDeformWeight *dw;
- MDeformVert *dv, **dvert_array = NULL;
- int i, dvert_tot = 0;
- const int def_nr = ob->actdef - 1;
+ MDeformWeight *dw;
+ MDeformVert *dv, **dvert_array = NULL;
+ int i, dvert_tot = 0;
+ const int def_nr = ob->actdef - 1;
- const int use_vert_sel = vertex_group_use_vert_sel(ob);
+ const int use_vert_sel = vertex_group_use_vert_sel(ob);
- if (!BLI_findlink(&ob->defbase, def_nr)) {
- return false;
- }
+ if (!BLI_findlink(&ob->defbase, def_nr)) {
+ return false;
+ }
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
- if (dvert_array) {
- float weight_max = 0.0f;
+ if (dvert_array) {
+ float weight_max = 0.0f;
- for (i = 0; i < dvert_tot; i++) {
+ for (i = 0; i < dvert_tot; i++) {
- /* in case its not selected */
- if (!(dv = dvert_array[i])) {
- continue;
- }
+ /* in case its not selected */
+ if (!(dv = dvert_array[i])) {
+ continue;
+ }
- dw = defvert_find_index(dv, def_nr);
- if (dw) {
- weight_max = max_ff(dw->weight, weight_max);
- }
- }
+ dw = defvert_find_index(dv, def_nr);
+ if (dw) {
+ weight_max = max_ff(dw->weight, weight_max);
+ }
+ }
- if (weight_max > 0.0f) {
- for (i = 0; i < dvert_tot; i++) {
+ if (weight_max > 0.0f) {
+ for (i = 0; i < dvert_tot; i++) {
- /* in case its not selected */
- if (!(dv = dvert_array[i])) {
- continue;
- }
+ /* in case its not selected */
+ if (!(dv = dvert_array[i])) {
+ continue;
+ }
- dw = defvert_find_index(dv, def_nr);
- if (dw) {
- dw->weight /= weight_max;
+ dw = defvert_find_index(dv, def_nr);
+ if (dw) {
+ dw->weight /= weight_max;
- /* in case of division errors with very low weights */
- CLAMP(dw->weight, 0.0f, 1.0f);
- }
- }
- }
+ /* in case of division errors with very low weights */
+ CLAMP(dw->weight, 0.0f, 1.0f);
+ }
+ }
+ }
- MEM_freeN(dvert_array);
+ MEM_freeN(dvert_array);
- return true;
- }
+ return true;
+ }
- return false;
+ return false;
}
/* This finds all of the vertices face-connected to vert by an edge and returns a
@@ -1151,64 +1167,64 @@ static bool vgroup_normalize(Object *ob)
* count is an int passed by reference so it can be assigned the value of the length here. */
static int *getSurroundingVerts(Mesh *me, int vert, int *count)
{
- MPoly *mp = me->mpoly;
- int i = me->totpoly;
- /* Instead of looping twice on all polys and loops, and use a temp array, let's rather
- * use a BLI_array, with a reasonable starting/reserved size (typically, there are not
- * many vertices face-linked to another one, even 8 might be too high...). */
- int *verts = NULL;
- BLI_array_declare(verts);
-
- BLI_array_reserve(verts, 8);
- while (i--) {
- int j = mp->totloop;
- int first_l = mp->totloop - 1;
- MLoop *ml = &me->mloop[mp->loopstart];
- while (j--) {
- /* XXX This assume a vert can only be once in a poly, even though
- * it seems logical to me, not totally sure of that. */
- if (ml->v == vert) {
- int a, b, k;
- if (j == first_l) {
- /* We are on the first corner. */
- a = ml[1].v;
- b = ml[j].v;
- }
- else if (!j) {
- /* We are on the last corner. */
- a = (ml - 1)->v;
- b = me->mloop[mp->loopstart].v;
- }
- else {
- a = (ml - 1)->v;
- b = (ml + 1)->v;
- }
-
- /* Append a and b verts to array, if not yet present. */
- k = BLI_array_len(verts);
- /* XXX Maybe a == b is enough? */
- while (k-- && !(a == b && a == -1)) {
- if (verts[k] == a)
- a = -1;
- else if (verts[k] == b)
- b = -1;
- }
- if (a != -1)
- BLI_array_append(verts, a);
- if (b != -1)
- BLI_array_append(verts, b);
-
- /* Vert found in this poly, we can go to next one! */
- break;
- }
- ml++;
- }
- mp++;
- }
-
- /* Do not free the array! */
- *count = BLI_array_len(verts);
- return verts;
+ MPoly *mp = me->mpoly;
+ int i = me->totpoly;
+ /* Instead of looping twice on all polys and loops, and use a temp array, let's rather
+ * use a BLI_array, with a reasonable starting/reserved size (typically, there are not
+ * many vertices face-linked to another one, even 8 might be too high...). */
+ int *verts = NULL;
+ BLI_array_declare(verts);
+
+ BLI_array_reserve(verts, 8);
+ while (i--) {
+ int j = mp->totloop;
+ int first_l = mp->totloop - 1;
+ MLoop *ml = &me->mloop[mp->loopstart];
+ while (j--) {
+ /* XXX This assume a vert can only be once in a poly, even though
+ * it seems logical to me, not totally sure of that. */
+ if (ml->v == vert) {
+ int a, b, k;
+ if (j == first_l) {
+ /* We are on the first corner. */
+ a = ml[1].v;
+ b = ml[j].v;
+ }
+ else if (!j) {
+ /* We are on the last corner. */
+ a = (ml - 1)->v;
+ b = me->mloop[mp->loopstart].v;
+ }
+ else {
+ a = (ml - 1)->v;
+ b = (ml + 1)->v;
+ }
+
+ /* Append a and b verts to array, if not yet present. */
+ k = BLI_array_len(verts);
+ /* XXX Maybe a == b is enough? */
+ while (k-- && !(a == b && a == -1)) {
+ if (verts[k] == a)
+ a = -1;
+ else if (verts[k] == b)
+ b = -1;
+ }
+ if (a != -1)
+ BLI_array_append(verts, a);
+ if (b != -1)
+ BLI_array_append(verts, b);
+
+ /* Vert found in this poly, we can go to next one! */
+ break;
+ }
+ ml++;
+ }
+ mp++;
+ }
+
+ /* Do not free the array! */
+ *count = BLI_array_len(verts);
+ return verts;
}
/* get a single point in space by averaging a point cloud (vectors of size 3)
@@ -1216,40 +1232,45 @@ static int *getSurroundingVerts(Mesh *me, int vert, int *count)
*/
static void getSingleCoordinate(MVert *points, int count, float coord[3])
{
- int i;
- zero_v3(coord);
- for (i = 0; i < count; i++) {
- add_v3_v3(coord, points[i].co);
- }
- mul_v3_fl(coord, 1.0f / count);
+ int i;
+ zero_v3(coord);
+ for (i = 0; i < count; i++) {
+ add_v3_v3(coord, points[i].co);
+ }
+ mul_v3_fl(coord, 1.0f / count);
}
/* given a plane and a start and end position,
* compute the amount of vertical distance relative to the plane and store it in dists,
* then get the horizontal and vertical change and store them in changes
*/
-static void getVerticalAndHorizontalChange(
- const float norm[3], float d, const float coord[3],
- const float start[3], float distToStart,
- float *end, float (*changes)[2], float *dists, int index)
-{
- /* A = Q - ((Q - P).N)N
- * D = (a * x0 + b * y0 +c * z0 + d) */
- float projA[3], projB[3];
- float plane[4];
-
- plane_from_point_normal_v3(plane, coord, norm);
-
- closest_to_plane_normalized_v3(projA, plane, start);
- closest_to_plane_normalized_v3(projB, plane, end);
- /* (vertical and horizontal refer to the plane's y and xz respectively)
- * vertical distance */
- dists[index] = dot_v3v3(norm, end) + d;
- /* vertical change */
- changes[index][0] = dists[index] - distToStart;
- //printf("vc %f %f\n", distance(end, projB, 3) - distance(start, projA, 3), changes[index][0]);
- /* horizontal change */
- changes[index][1] = len_v3v3(projA, projB);
+static void getVerticalAndHorizontalChange(const float norm[3],
+ float d,
+ const float coord[3],
+ const float start[3],
+ float distToStart,
+ float *end,
+ float (*changes)[2],
+ float *dists,
+ int index)
+{
+ /* A = Q - ((Q - P).N)N
+ * D = (a * x0 + b * y0 +c * z0 + d) */
+ float projA[3], projB[3];
+ float plane[4];
+
+ plane_from_point_normal_v3(plane, coord, norm);
+
+ closest_to_plane_normalized_v3(projA, plane, start);
+ closest_to_plane_normalized_v3(projB, plane, end);
+ /* (vertical and horizontal refer to the plane's y and xz respectively)
+ * vertical distance */
+ dists[index] = dot_v3v3(norm, end) + d;
+ /* vertical change */
+ changes[index][0] = dists[index] - distToStart;
+ //printf("vc %f %f\n", distance(end, projB, 3) - distance(start, projA, 3), changes[index][0]);
+ /* horizontal change */
+ changes[index][1] = len_v3v3(projA, projB);
}
/* by changing nonzero weights, try to move a vertex in me->mverts with index 'index' to
@@ -1261,2336 +1282,2435 @@ static void getVerticalAndHorizontalChange(
* norm and d are the plane's properties for the equation: ax + by + cz + d = 0
* coord is a point on the plane
*/
-static void moveCloserToDistanceFromPlane(
- Depsgraph *depsgraph, Scene *scene, Object *ob, Mesh *me, int index, float norm[3],
- float coord[3], float d, float distToBe, float strength, float cp)
-{
- Mesh *me_deform;
- MDeformWeight *dw;
- MVert m;
- MDeformVert *dvert = me->dvert + index;
- int totweight = dvert->totweight;
- float oldw = 0;
- float oldPos[3] = {0};
- float vc, hc, dist = 0.0f;
- int i, k;
- float (*changes)[2] = MEM_mallocN(sizeof(float *) * totweight * 2, "vertHorzChange");
- float *dists = MEM_mallocN(sizeof(float) * totweight, "distance");
-
- /* track if up or down moved it closer for each bone */
- int *upDown = MEM_callocN(sizeof(int) * totweight, "upDownTracker");
-
- int *dwIndices = MEM_callocN(sizeof(int) * totweight, "dwIndexTracker");
- float distToStart;
- int bestIndex = 0;
- bool wasChange;
- char wasUp;
- int lastIndex = -1;
- float originalDistToBe = distToBe;
- do {
- wasChange = false;
- me_deform = mesh_get_eval_deform(depsgraph, scene, ob, &CD_MASK_BAREMESH);
- m = me_deform->mvert[index];
- copy_v3_v3(oldPos, m.co);
- distToStart = dot_v3v3(norm, oldPos) + d;
-
- if (distToBe == originalDistToBe) {
- distToBe += distToStart - distToStart * strength;
- }
- for (i = 0; i < totweight; i++) {
- dwIndices[i] = i;
- dw = (dvert->dw + i);
- vc = hc = 0;
- if (!dw->weight) {
- changes[i][0] = 0;
- changes[i][1] = 0;
- dists[i] = distToStart;
- continue;
- }
- for (k = 0; k < 2; k++) {
- if (me_deform) {
- /* DO NOT try to do own cleanup here, this is call for dramatic failures and bugs!
- * Better to over-free and recompute a bit. */
- BKE_object_free_derived_caches(ob);
- }
- oldw = dw->weight;
- if (k) {
- dw->weight *= 1 + cp;
- }
- else {
- dw->weight /= 1 + cp;
- }
- if (dw->weight == oldw) {
- changes[i][0] = 0;
- changes[i][1] = 0;
- dists[i] = distToStart;
- break;
- }
- if (dw->weight > 1) {
- dw->weight = 1;
- }
- me_deform = mesh_get_eval_deform(depsgraph, scene, ob, &CD_MASK_BAREMESH);
- m = me_deform->mvert[index];
- getVerticalAndHorizontalChange(norm, d, coord, oldPos, distToStart, m.co, changes, dists, i);
- dw->weight = oldw;
- if (!k) {
- vc = changes[i][0];
- hc = changes[i][1];
- dist = dists[i];
- }
- else {
- if (fabsf(dist - distToBe) < fabsf(dists[i] - distToBe)) {
- upDown[i] = 0;
- changes[i][0] = vc;
- changes[i][1] = hc;
- dists[i] = dist;
- }
- else {
- upDown[i] = 1;
- }
- if (fabsf(dists[i] - distToBe) > fabsf(distToStart - distToBe)) {
- changes[i][0] = 0;
- changes[i][1] = 0;
- dists[i] = distToStart;
- }
- }
- }
- }
- /* sort the changes by the vertical change */
- for (k = 0; k < totweight; k++) {
- float tf;
- int ti;
- bestIndex = k;
- for (i = k + 1; i < totweight; i++) {
- dist = dists[i];
-
- if (fabsf(dist) > fabsf(dists[i])) {
- bestIndex = i;
- }
- }
- /* switch with k */
- if (bestIndex != k) {
- ti = upDown[k];
- upDown[k] = upDown[bestIndex];
- upDown[bestIndex] = ti;
-
- ti = dwIndices[k];
- dwIndices[k] = dwIndices[bestIndex];
- dwIndices[bestIndex] = ti;
-
- tf = changes[k][0];
- changes[k][0] = changes[bestIndex][0];
- changes[bestIndex][0] = tf;
-
- tf = changes[k][1];
- changes[k][1] = changes[bestIndex][1];
- changes[bestIndex][1] = tf;
-
- tf = dists[k];
- dists[k] = dists[bestIndex];
- dists[bestIndex] = tf;
- }
- }
- bestIndex = -1;
- /* find the best change with an acceptable horizontal change */
- for (i = 0; i < totweight; i++) {
- if (fabsf(changes[i][0]) > fabsf(changes[i][1] * 2.0f)) {
- bestIndex = i;
- break;
- }
- }
- if (bestIndex != -1) {
- wasChange = true;
- /* it is a good place to stop if it tries to move the opposite direction
- * (relative to the plane) of last time */
- if (lastIndex != -1) {
- if (wasUp != upDown[bestIndex]) {
- wasChange = false;
- }
- }
- lastIndex = bestIndex;
- wasUp = upDown[bestIndex];
- dw = (dvert->dw + dwIndices[bestIndex]);
- oldw = dw->weight;
- if (upDown[bestIndex]) {
- dw->weight *= 1 + cp;
- }
- else {
- dw->weight /= 1 + cp;
- }
- if (dw->weight > 1) {
- dw->weight = 1;
- }
- if (oldw == dw->weight) {
- wasChange = false;
- }
- if (me_deform) {
- /* DO NOT try to do own cleanup here, this is call for dramatic failures and bugs!
- * Better to over-free and recompute a bit. */
- BKE_object_free_derived_caches(ob);
- }
- }
- } while (wasChange && ((distToStart - distToBe) / fabsf(distToStart - distToBe) ==
- (dists[bestIndex] - distToBe) / fabsf(dists[bestIndex] - distToBe)));
-
- MEM_freeN(upDown);
- MEM_freeN(changes);
- MEM_freeN(dists);
- MEM_freeN(dwIndices);
+static void moveCloserToDistanceFromPlane(Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ Mesh *me,
+ int index,
+ float norm[3],
+ float coord[3],
+ float d,
+ float distToBe,
+ float strength,
+ float cp)
+{
+ Mesh *me_deform;
+ MDeformWeight *dw;
+ MVert m;
+ MDeformVert *dvert = me->dvert + index;
+ int totweight = dvert->totweight;
+ float oldw = 0;
+ float oldPos[3] = {0};
+ float vc, hc, dist = 0.0f;
+ int i, k;
+ float(*changes)[2] = MEM_mallocN(sizeof(float *) * totweight * 2, "vertHorzChange");
+ float *dists = MEM_mallocN(sizeof(float) * totweight, "distance");
+
+ /* track if up or down moved it closer for each bone */
+ int *upDown = MEM_callocN(sizeof(int) * totweight, "upDownTracker");
+
+ int *dwIndices = MEM_callocN(sizeof(int) * totweight, "dwIndexTracker");
+ float distToStart;
+ int bestIndex = 0;
+ bool wasChange;
+ char wasUp;
+ int lastIndex = -1;
+ float originalDistToBe = distToBe;
+ do {
+ wasChange = false;
+ me_deform = mesh_get_eval_deform(depsgraph, scene, ob, &CD_MASK_BAREMESH);
+ m = me_deform->mvert[index];
+ copy_v3_v3(oldPos, m.co);
+ distToStart = dot_v3v3(norm, oldPos) + d;
+
+ if (distToBe == originalDistToBe) {
+ distToBe += distToStart - distToStart * strength;
+ }
+ for (i = 0; i < totweight; i++) {
+ dwIndices[i] = i;
+ dw = (dvert->dw + i);
+ vc = hc = 0;
+ if (!dw->weight) {
+ changes[i][0] = 0;
+ changes[i][1] = 0;
+ dists[i] = distToStart;
+ continue;
+ }
+ for (k = 0; k < 2; k++) {
+ if (me_deform) {
+ /* DO NOT try to do own cleanup here, this is call for dramatic failures and bugs!
+ * Better to over-free and recompute a bit. */
+ BKE_object_free_derived_caches(ob);
+ }
+ oldw = dw->weight;
+ if (k) {
+ dw->weight *= 1 + cp;
+ }
+ else {
+ dw->weight /= 1 + cp;
+ }
+ if (dw->weight == oldw) {
+ changes[i][0] = 0;
+ changes[i][1] = 0;
+ dists[i] = distToStart;
+ break;
+ }
+ if (dw->weight > 1) {
+ dw->weight = 1;
+ }
+ me_deform = mesh_get_eval_deform(depsgraph, scene, ob, &CD_MASK_BAREMESH);
+ m = me_deform->mvert[index];
+ getVerticalAndHorizontalChange(
+ norm, d, coord, oldPos, distToStart, m.co, changes, dists, i);
+ dw->weight = oldw;
+ if (!k) {
+ vc = changes[i][0];
+ hc = changes[i][1];
+ dist = dists[i];
+ }
+ else {
+ if (fabsf(dist - distToBe) < fabsf(dists[i] - distToBe)) {
+ upDown[i] = 0;
+ changes[i][0] = vc;
+ changes[i][1] = hc;
+ dists[i] = dist;
+ }
+ else {
+ upDown[i] = 1;
+ }
+ if (fabsf(dists[i] - distToBe) > fabsf(distToStart - distToBe)) {
+ changes[i][0] = 0;
+ changes[i][1] = 0;
+ dists[i] = distToStart;
+ }
+ }
+ }
+ }
+ /* sort the changes by the vertical change */
+ for (k = 0; k < totweight; k++) {
+ float tf;
+ int ti;
+ bestIndex = k;
+ for (i = k + 1; i < totweight; i++) {
+ dist = dists[i];
+
+ if (fabsf(dist) > fabsf(dists[i])) {
+ bestIndex = i;
+ }
+ }
+ /* switch with k */
+ if (bestIndex != k) {
+ ti = upDown[k];
+ upDown[k] = upDown[bestIndex];
+ upDown[bestIndex] = ti;
+
+ ti = dwIndices[k];
+ dwIndices[k] = dwIndices[bestIndex];
+ dwIndices[bestIndex] = ti;
+
+ tf = changes[k][0];
+ changes[k][0] = changes[bestIndex][0];
+ changes[bestIndex][0] = tf;
+
+ tf = changes[k][1];
+ changes[k][1] = changes[bestIndex][1];
+ changes[bestIndex][1] = tf;
+
+ tf = dists[k];
+ dists[k] = dists[bestIndex];
+ dists[bestIndex] = tf;
+ }
+ }
+ bestIndex = -1;
+ /* find the best change with an acceptable horizontal change */
+ for (i = 0; i < totweight; i++) {
+ if (fabsf(changes[i][0]) > fabsf(changes[i][1] * 2.0f)) {
+ bestIndex = i;
+ break;
+ }
+ }
+ if (bestIndex != -1) {
+ wasChange = true;
+ /* it is a good place to stop if it tries to move the opposite direction
+ * (relative to the plane) of last time */
+ if (lastIndex != -1) {
+ if (wasUp != upDown[bestIndex]) {
+ wasChange = false;
+ }
+ }
+ lastIndex = bestIndex;
+ wasUp = upDown[bestIndex];
+ dw = (dvert->dw + dwIndices[bestIndex]);
+ oldw = dw->weight;
+ if (upDown[bestIndex]) {
+ dw->weight *= 1 + cp;
+ }
+ else {
+ dw->weight /= 1 + cp;
+ }
+ if (dw->weight > 1) {
+ dw->weight = 1;
+ }
+ if (oldw == dw->weight) {
+ wasChange = false;
+ }
+ if (me_deform) {
+ /* DO NOT try to do own cleanup here, this is call for dramatic failures and bugs!
+ * Better to over-free and recompute a bit. */
+ BKE_object_free_derived_caches(ob);
+ }
+ }
+ } while (wasChange && ((distToStart - distToBe) / fabsf(distToStart - distToBe) ==
+ (dists[bestIndex] - distToBe) / fabsf(dists[bestIndex] - distToBe)));
+
+ MEM_freeN(upDown);
+ MEM_freeN(changes);
+ MEM_freeN(dists);
+ MEM_freeN(dwIndices);
}
/* this is used to try to smooth a surface by only adjusting the nonzero weights of a vertex
* but it could be used to raise or lower an existing 'bump.' */
-static void vgroup_fix(const bContext *C, Scene *scene, Object *ob, float distToBe, float strength, float cp)
-{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- int i;
-
- Mesh *me = ob->data;
- MVert *mvert = me->mvert;
- int *verts = NULL;
- if (!(me->editflag & ME_EDIT_PAINT_VERT_SEL))
- return;
- for (i = 0; i < me->totvert && mvert; i++, mvert++) {
- if (mvert->flag & SELECT) {
- int count = 0;
- if ((verts = getSurroundingVerts(me, i, &count))) {
- MVert m;
- MVert *p = MEM_callocN(sizeof(MVert) * (count), "deformedPoints");
- int k;
-
- Mesh *me_deform = mesh_get_eval_deform(depsgraph, scene, ob, &CD_MASK_BAREMESH);
- k = count;
- while (k--) {
- p[k] = me_deform->mvert[verts[k]];
- }
-
- if (count >= 3) {
- float d /*, dist */ /* UNUSED */, mag;
- float coord[3];
- float norm[3];
- getSingleCoordinate(p, count, coord);
- m = me_deform->mvert[i];
- sub_v3_v3v3(norm, m.co, coord);
- mag = normalize_v3(norm);
- if (mag) { /* zeros fix */
- d = -dot_v3v3(norm, coord);
- /* dist = (dot_v3v3(norm, m.co) + d); */ /* UNUSED */
- moveCloserToDistanceFromPlane(depsgraph, scene, ob, me, i, norm, coord, d, distToBe, strength, cp);
- }
- }
-
- MEM_freeN(verts);
- MEM_freeN(p);
- }
- }
- }
-}
-
-static void vgroup_levels_subset(
- Object *ob, const bool *vgroup_validmap, const int vgroup_tot,
- const int UNUSED(subset_count),
- const float offset, const float gain)
-{
- MDeformWeight *dw;
- MDeformVert *dv, **dvert_array = NULL;
- int i, dvert_tot = 0;
-
- const bool use_vert_sel = vertex_group_use_vert_sel(ob);
- const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
-
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
-
- if (dvert_array) {
-
- for (i = 0; i < dvert_tot; i++) {
- int j;
-
- /* in case its not selected */
- if (!(dv = dvert_array[i])) {
- continue;
- }
-
- j = vgroup_tot;
- while (j--) {
- if (vgroup_validmap[j]) {
- dw = defvert_find_index(dv, j);
- if (dw) {
- dw->weight = gain * (dw->weight + offset);
-
- CLAMP(dw->weight, 0.0f, 1.0f);
- }
- }
- }
- }
-
- if (use_mirror && use_vert_sel) {
- ED_vgroup_parray_mirror_sync(
- ob, dvert_array, dvert_tot,
- vgroup_validmap, vgroup_tot);
- }
-
- MEM_freeN(dvert_array);
- }
-}
-
-static bool vgroup_normalize_all(
- Object *ob,
- const bool *vgroup_validmap,
- const int vgroup_tot,
- const int subset_count,
- const bool lock_active,
- ReportList *reports)
-{
- MDeformVert *dv, **dvert_array = NULL;
- int i, dvert_tot = 0;
- const int def_nr = ob->actdef - 1;
-
- const int use_vert_sel = vertex_group_use_vert_sel(ob);
-
- if (subset_count == 0) {
- BKE_report(reports, RPT_ERROR, "No vertex groups to operate on");
- return false;
- }
-
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
-
- if (dvert_array) {
- const int defbase_tot = BLI_listbase_count(&ob->defbase);
- bool *lock_flags = BKE_object_defgroup_lock_flags_get(ob, defbase_tot);
- bool changed = false;
-
- if ((lock_active == true) &&
- (lock_flags != NULL) &&
- (def_nr < defbase_tot))
- {
- lock_flags[def_nr] = true;
- }
-
- if (lock_flags) {
- for (i = 0; i < defbase_tot; i++) {
- if (lock_flags[i] == false) {
- break;
- }
- }
-
- if (i == defbase_tot) {
- BKE_report(reports, RPT_ERROR, "All groups are locked");
- goto finally;
- }
- }
-
- for (i = 0; i < dvert_tot; i++) {
- /* in case its not selected */
- if ((dv = dvert_array[i])) {
- if (lock_flags) {
- defvert_normalize_lock_map(
- dv, vgroup_validmap, vgroup_tot,
- lock_flags, defbase_tot);
- }
- else if (lock_active) {
- defvert_normalize_lock_single(
- dv, vgroup_validmap, vgroup_tot,
- def_nr);
- }
- else {
- defvert_normalize_subset(dv, vgroup_validmap, vgroup_tot);
- }
- }
- }
-
- changed = true;
-
-finally:
- if (lock_flags) {
- MEM_freeN(lock_flags);
- }
-
- MEM_freeN(dvert_array);
-
- return changed;
- }
-
- return false;
+static void vgroup_fix(
+ const bContext *C, Scene *scene, Object *ob, float distToBe, float strength, float cp)
+{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ int i;
+
+ Mesh *me = ob->data;
+ MVert *mvert = me->mvert;
+ int *verts = NULL;
+ if (!(me->editflag & ME_EDIT_PAINT_VERT_SEL))
+ return;
+ for (i = 0; i < me->totvert && mvert; i++, mvert++) {
+ if (mvert->flag & SELECT) {
+ int count = 0;
+ if ((verts = getSurroundingVerts(me, i, &count))) {
+ MVert m;
+ MVert *p = MEM_callocN(sizeof(MVert) * (count), "deformedPoints");
+ int k;
+
+ Mesh *me_deform = mesh_get_eval_deform(depsgraph, scene, ob, &CD_MASK_BAREMESH);
+ k = count;
+ while (k--) {
+ p[k] = me_deform->mvert[verts[k]];
+ }
+
+ if (count >= 3) {
+ float d /*, dist */ /* UNUSED */, mag;
+ float coord[3];
+ float norm[3];
+ getSingleCoordinate(p, count, coord);
+ m = me_deform->mvert[i];
+ sub_v3_v3v3(norm, m.co, coord);
+ mag = normalize_v3(norm);
+ if (mag) { /* zeros fix */
+ d = -dot_v3v3(norm, coord);
+ /* dist = (dot_v3v3(norm, m.co) + d); */ /* UNUSED */
+ moveCloserToDistanceFromPlane(
+ depsgraph, scene, ob, me, i, norm, coord, d, distToBe, strength, cp);
+ }
+ }
+
+ MEM_freeN(verts);
+ MEM_freeN(p);
+ }
+ }
+ }
+}
+
+static void vgroup_levels_subset(Object *ob,
+ const bool *vgroup_validmap,
+ const int vgroup_tot,
+ const int UNUSED(subset_count),
+ const float offset,
+ const float gain)
+{
+ MDeformWeight *dw;
+ MDeformVert *dv, **dvert_array = NULL;
+ int i, dvert_tot = 0;
+
+ const bool use_vert_sel = vertex_group_use_vert_sel(ob);
+ const bool use_mirror = (ob->type == OB_MESH) ?
+ (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 :
+ false;
+
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
+
+ if (dvert_array) {
+
+ for (i = 0; i < dvert_tot; i++) {
+ int j;
+
+ /* in case its not selected */
+ if (!(dv = dvert_array[i])) {
+ continue;
+ }
+
+ j = vgroup_tot;
+ while (j--) {
+ if (vgroup_validmap[j]) {
+ dw = defvert_find_index(dv, j);
+ if (dw) {
+ dw->weight = gain * (dw->weight + offset);
+
+ CLAMP(dw->weight, 0.0f, 1.0f);
+ }
+ }
+ }
+ }
+
+ if (use_mirror && use_vert_sel) {
+ ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot, vgroup_validmap, vgroup_tot);
+ }
+
+ MEM_freeN(dvert_array);
+ }
+}
+
+static bool vgroup_normalize_all(Object *ob,
+ const bool *vgroup_validmap,
+ const int vgroup_tot,
+ const int subset_count,
+ const bool lock_active,
+ ReportList *reports)
+{
+ MDeformVert *dv, **dvert_array = NULL;
+ int i, dvert_tot = 0;
+ const int def_nr = ob->actdef - 1;
+
+ const int use_vert_sel = vertex_group_use_vert_sel(ob);
+
+ if (subset_count == 0) {
+ BKE_report(reports, RPT_ERROR, "No vertex groups to operate on");
+ return false;
+ }
+
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
+
+ if (dvert_array) {
+ const int defbase_tot = BLI_listbase_count(&ob->defbase);
+ bool *lock_flags = BKE_object_defgroup_lock_flags_get(ob, defbase_tot);
+ bool changed = false;
+
+ if ((lock_active == true) && (lock_flags != NULL) && (def_nr < defbase_tot)) {
+ lock_flags[def_nr] = true;
+ }
+
+ if (lock_flags) {
+ for (i = 0; i < defbase_tot; i++) {
+ if (lock_flags[i] == false) {
+ break;
+ }
+ }
+
+ if (i == defbase_tot) {
+ BKE_report(reports, RPT_ERROR, "All groups are locked");
+ goto finally;
+ }
+ }
+
+ for (i = 0; i < dvert_tot; i++) {
+ /* in case its not selected */
+ if ((dv = dvert_array[i])) {
+ if (lock_flags) {
+ defvert_normalize_lock_map(dv, vgroup_validmap, vgroup_tot, lock_flags, defbase_tot);
+ }
+ else if (lock_active) {
+ defvert_normalize_lock_single(dv, vgroup_validmap, vgroup_tot, def_nr);
+ }
+ else {
+ defvert_normalize_subset(dv, vgroup_validmap, vgroup_tot);
+ }
+ }
+ }
+
+ changed = true;
+
+ finally:
+ if (lock_flags) {
+ MEM_freeN(lock_flags);
+ }
+
+ MEM_freeN(dvert_array);
+
+ return changed;
+ }
+
+ return false;
}
enum {
- VGROUP_TOGGLE,
- VGROUP_LOCK,
- VGROUP_UNLOCK,
- VGROUP_INVERT,
+ VGROUP_TOGGLE,
+ VGROUP_LOCK,
+ VGROUP_UNLOCK,
+ VGROUP_INVERT,
};
static const EnumPropertyItem vgroup_lock_actions[] = {
- {VGROUP_TOGGLE, "TOGGLE", 0, "Toggle", "Unlock all vertex groups if there is at least one locked group, lock all in other case"},
- {VGROUP_LOCK, "LOCK", 0, "Lock", "Lock all vertex groups"},
- {VGROUP_UNLOCK, "UNLOCK", 0, "Unlock", "Unlock all vertex groups"},
- {VGROUP_INVERT, "INVERT", 0, "Invert", "Invert the lock state of all vertex groups"},
- {0, NULL, 0, NULL, NULL},
+ {VGROUP_TOGGLE,
+ "TOGGLE",
+ 0,
+ "Toggle",
+ "Unlock all vertex groups if there is at least one locked group, lock all in other case"},
+ {VGROUP_LOCK, "LOCK", 0, "Lock", "Lock all vertex groups"},
+ {VGROUP_UNLOCK, "UNLOCK", 0, "Unlock", "Unlock all vertex groups"},
+ {VGROUP_INVERT, "INVERT", 0, "Invert", "Invert the lock state of all vertex groups"},
+ {0, NULL, 0, NULL, NULL},
};
static void vgroup_lock_all(Object *ob, int action)
{
- bDeformGroup *dg;
-
- if (action == VGROUP_TOGGLE) {
- action = VGROUP_LOCK;
- for (dg = ob->defbase.first; dg; dg = dg->next) {
- if (dg->flag & DG_LOCK_WEIGHT) {
- action = VGROUP_UNLOCK;
- break;
- }
- }
- }
-
- for (dg = ob->defbase.first; dg; dg = dg->next) {
- switch (action) {
- case VGROUP_LOCK:
- dg->flag |= DG_LOCK_WEIGHT;
- break;
- case VGROUP_UNLOCK:
- dg->flag &= ~DG_LOCK_WEIGHT;
- break;
- case VGROUP_INVERT:
- dg->flag ^= DG_LOCK_WEIGHT;
- break;
- }
- }
-}
-
-static void vgroup_invert_subset(
- Object *ob,
- const bool *vgroup_validmap, const int vgroup_tot,
- const int UNUSED(subset_count), const bool auto_assign, const bool auto_remove)
-{
- MDeformWeight *dw;
- MDeformVert *dv, **dvert_array = NULL;
- int i, dvert_tot = 0;
- const bool use_vert_sel = vertex_group_use_vert_sel(ob);
- const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
-
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
-
- if (dvert_array) {
- for (i = 0; i < dvert_tot; i++) {
- int j;
-
- /* in case its not selected */
- if (!(dv = dvert_array[i])) {
- continue;
- }
-
- j = vgroup_tot;
- while (j--) {
-
- if (vgroup_validmap[j]) {
- if (auto_assign) {
- dw = defvert_verify_index(dv, j);
- }
- else {
- dw = defvert_find_index(dv, j);
- }
-
- if (dw) {
- dw->weight = 1.0f - dw->weight;
- CLAMP(dw->weight, 0.0f, 1.0f);
- }
- }
- }
- }
-
- if (use_mirror && use_vert_sel) {
- ED_vgroup_parray_mirror_sync(
- ob, dvert_array, dvert_tot,
- vgroup_validmap, vgroup_tot);
- }
-
- if (auto_remove) {
- ED_vgroup_parray_remove_zero(
- dvert_array, dvert_tot,
- vgroup_validmap, vgroup_tot,
- 0.0f, false);
- }
-
- MEM_freeN(dvert_array);
- }
-}
-
-static void vgroup_smooth_subset(
- Object *ob, const bool *vgroup_validmap, const int vgroup_tot,
- const int subset_count,
- const float fac, const int repeat,
- const float fac_expand)
-{
- const float ifac = 1.0f - fac;
- MDeformVert **dvert_array = NULL;
- int dvert_tot = 0;
- int *vgroup_subset_map = BLI_array_alloca(vgroup_subset_map, subset_count);
- float *vgroup_subset_weights = BLI_array_alloca(vgroup_subset_weights, subset_count);
- const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
- const bool use_select = vertex_group_use_vert_sel(ob);
- const bool use_hide = use_select;
-
- const int expand_sign = signum_i(fac_expand);
- const float expand = fabsf(fac_expand);
- const float iexpand = 1.0f - expand;
-
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- BMesh *bm = em ? em->bm : NULL;
- Mesh *me = em ? NULL : ob->data;
-
- MeshElemMap *emap;
- int *emap_mem;
-
- float *weight_accum_prev;
- float *weight_accum_curr;
-
- unsigned int subset_index;
-
- /* vertex indices that will be smoothed, (only to avoid iterating over verts that do nothing) */
- unsigned int *verts_used;
- STACK_DECLARE(verts_used);
-
-
- BKE_object_defgroup_subset_to_index_array(vgroup_validmap, vgroup_tot, vgroup_subset_map);
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
- memset(vgroup_subset_weights, 0, sizeof(*vgroup_subset_weights) * subset_count);
-
- if (bm) {
- BM_mesh_elem_table_ensure(bm, BM_VERT);
- BM_mesh_elem_index_ensure(bm, BM_VERT);
-
- emap = NULL;
- emap_mem = NULL;
- }
- else {
- BKE_mesh_vert_edge_map_create(&emap, &emap_mem, me->medge, me->totvert, me->totedge);
- }
-
- weight_accum_prev = MEM_mallocN(sizeof(*weight_accum_prev) * dvert_tot, __func__);
- weight_accum_curr = MEM_mallocN(sizeof(*weight_accum_curr) * dvert_tot, __func__);
-
- verts_used = MEM_mallocN(sizeof(*verts_used) * dvert_tot, __func__);
- STACK_INIT(verts_used, dvert_tot);
-
-#define IS_BM_VERT_READ(v) \
- (use_hide ? (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == 0) : true)
-#define IS_BM_VERT_WRITE(v) \
- (use_select ? (BM_elem_flag_test(v, BM_ELEM_SELECT) != 0) : true)
-
-#define IS_ME_VERT_READ(v) \
- (use_hide ? (((v)->flag & ME_HIDE) == 0) : true)
-#define IS_ME_VERT_WRITE(v) \
- (use_select ? (((v)->flag & SELECT) != 0) : true)
-
- /* initialize used verts */
- if (bm) {
- for (int i = 0; i < dvert_tot; i++) {
- BMVert *v = BM_vert_at_index(bm, i);
- if (IS_BM_VERT_WRITE(v)) {
- BMIter eiter;
- BMEdge *e;
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- BMVert *v_other = BM_edge_other_vert(e, v);
- if (IS_BM_VERT_READ(v_other)) {
- STACK_PUSH(verts_used, i);
- break;
- }
- }
- }
- }
- }
- else {
- for (int i = 0; i < dvert_tot; i++) {
- const MVert *v = &me->mvert[i];
- if (IS_ME_VERT_WRITE(v)) {
- for (int j = 0; j < emap[i].count; j++) {
- const MEdge *e = &me->medge[emap[i].indices[j]];
- const MVert *v_other = &me->mvert[(e->v1 == i) ? e->v2 : e->v1];
- if (IS_ME_VERT_READ(v_other)) {
- STACK_PUSH(verts_used, i);
- break;
- }
- }
- }
- }
- }
-
- for (subset_index = 0; subset_index < subset_count; subset_index++) {
- const int def_nr = vgroup_subset_map[subset_index];
- int iter;
-
- ED_vgroup_parray_to_weight_array((const MDeformVert **)dvert_array, dvert_tot, weight_accum_prev, def_nr);
- memcpy(weight_accum_curr, weight_accum_prev, sizeof(*weight_accum_curr) * dvert_tot);
-
- for (iter = 0; iter < repeat; iter++) {
- unsigned *vi_step, *vi_end = verts_used + STACK_SIZE(verts_used);
-
- /* avoid looping over all verts */
- // for (i = 0; i < dvert_tot; i++)
- for (vi_step = verts_used; vi_step != vi_end; vi_step++) {
- const unsigned int i = *vi_step;
- float weight_tot = 0.0f;
- float weight = 0.0f;
+ bDeformGroup *dg;
+
+ if (action == VGROUP_TOGGLE) {
+ action = VGROUP_LOCK;
+ for (dg = ob->defbase.first; dg; dg = dg->next) {
+ if (dg->flag & DG_LOCK_WEIGHT) {
+ action = VGROUP_UNLOCK;
+ break;
+ }
+ }
+ }
+
+ for (dg = ob->defbase.first; dg; dg = dg->next) {
+ switch (action) {
+ case VGROUP_LOCK:
+ dg->flag |= DG_LOCK_WEIGHT;
+ break;
+ case VGROUP_UNLOCK:
+ dg->flag &= ~DG_LOCK_WEIGHT;
+ break;
+ case VGROUP_INVERT:
+ dg->flag ^= DG_LOCK_WEIGHT;
+ break;
+ }
+ }
+}
+
+static void vgroup_invert_subset(Object *ob,
+ const bool *vgroup_validmap,
+ const int vgroup_tot,
+ const int UNUSED(subset_count),
+ const bool auto_assign,
+ const bool auto_remove)
+{
+ MDeformWeight *dw;
+ MDeformVert *dv, **dvert_array = NULL;
+ int i, dvert_tot = 0;
+ const bool use_vert_sel = vertex_group_use_vert_sel(ob);
+ const bool use_mirror = (ob->type == OB_MESH) ?
+ (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 :
+ false;
+
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
+
+ if (dvert_array) {
+ for (i = 0; i < dvert_tot; i++) {
+ int j;
+
+ /* in case its not selected */
+ if (!(dv = dvert_array[i])) {
+ continue;
+ }
+
+ j = vgroup_tot;
+ while (j--) {
+
+ if (vgroup_validmap[j]) {
+ if (auto_assign) {
+ dw = defvert_verify_index(dv, j);
+ }
+ else {
+ dw = defvert_find_index(dv, j);
+ }
+
+ if (dw) {
+ dw->weight = 1.0f - dw->weight;
+ CLAMP(dw->weight, 0.0f, 1.0f);
+ }
+ }
+ }
+ }
+
+ if (use_mirror && use_vert_sel) {
+ ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot, vgroup_validmap, vgroup_tot);
+ }
+
+ if (auto_remove) {
+ ED_vgroup_parray_remove_zero(
+ dvert_array, dvert_tot, vgroup_validmap, vgroup_tot, 0.0f, false);
+ }
+
+ MEM_freeN(dvert_array);
+ }
+}
+
+static void vgroup_smooth_subset(Object *ob,
+ const bool *vgroup_validmap,
+ const int vgroup_tot,
+ const int subset_count,
+ const float fac,
+ const int repeat,
+ const float fac_expand)
+{
+ const float ifac = 1.0f - fac;
+ MDeformVert **dvert_array = NULL;
+ int dvert_tot = 0;
+ int *vgroup_subset_map = BLI_array_alloca(vgroup_subset_map, subset_count);
+ float *vgroup_subset_weights = BLI_array_alloca(vgroup_subset_weights, subset_count);
+ const bool use_mirror = (ob->type == OB_MESH) ?
+ (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 :
+ false;
+ const bool use_select = vertex_group_use_vert_sel(ob);
+ const bool use_hide = use_select;
+
+ const int expand_sign = signum_i(fac_expand);
+ const float expand = fabsf(fac_expand);
+ const float iexpand = 1.0f - expand;
+
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BMesh *bm = em ? em->bm : NULL;
+ Mesh *me = em ? NULL : ob->data;
+
+ MeshElemMap *emap;
+ int *emap_mem;
+
+ float *weight_accum_prev;
+ float *weight_accum_curr;
+
+ unsigned int subset_index;
+
+ /* vertex indices that will be smoothed, (only to avoid iterating over verts that do nothing) */
+ unsigned int *verts_used;
+ STACK_DECLARE(verts_used);
+
+ BKE_object_defgroup_subset_to_index_array(vgroup_validmap, vgroup_tot, vgroup_subset_map);
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
+ memset(vgroup_subset_weights, 0, sizeof(*vgroup_subset_weights) * subset_count);
+
+ if (bm) {
+ BM_mesh_elem_table_ensure(bm, BM_VERT);
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+
+ emap = NULL;
+ emap_mem = NULL;
+ }
+ else {
+ BKE_mesh_vert_edge_map_create(&emap, &emap_mem, me->medge, me->totvert, me->totedge);
+ }
+
+ weight_accum_prev = MEM_mallocN(sizeof(*weight_accum_prev) * dvert_tot, __func__);
+ weight_accum_curr = MEM_mallocN(sizeof(*weight_accum_curr) * dvert_tot, __func__);
+
+ verts_used = MEM_mallocN(sizeof(*verts_used) * dvert_tot, __func__);
+ STACK_INIT(verts_used, dvert_tot);
+
+#define IS_BM_VERT_READ(v) (use_hide ? (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == 0) : true)
+#define IS_BM_VERT_WRITE(v) (use_select ? (BM_elem_flag_test(v, BM_ELEM_SELECT) != 0) : true)
+
+#define IS_ME_VERT_READ(v) (use_hide ? (((v)->flag & ME_HIDE) == 0) : true)
+#define IS_ME_VERT_WRITE(v) (use_select ? (((v)->flag & SELECT) != 0) : true)
+
+ /* initialize used verts */
+ if (bm) {
+ for (int i = 0; i < dvert_tot; i++) {
+ BMVert *v = BM_vert_at_index(bm, i);
+ if (IS_BM_VERT_WRITE(v)) {
+ BMIter eiter;
+ BMEdge *e;
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ if (IS_BM_VERT_READ(v_other)) {
+ STACK_PUSH(verts_used, i);
+ break;
+ }
+ }
+ }
+ }
+ }
+ else {
+ for (int i = 0; i < dvert_tot; i++) {
+ const MVert *v = &me->mvert[i];
+ if (IS_ME_VERT_WRITE(v)) {
+ for (int j = 0; j < emap[i].count; j++) {
+ const MEdge *e = &me->medge[emap[i].indices[j]];
+ const MVert *v_other = &me->mvert[(e->v1 == i) ? e->v2 : e->v1];
+ if (IS_ME_VERT_READ(v_other)) {
+ STACK_PUSH(verts_used, i);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ for (subset_index = 0; subset_index < subset_count; subset_index++) {
+ const int def_nr = vgroup_subset_map[subset_index];
+ int iter;
+
+ ED_vgroup_parray_to_weight_array(
+ (const MDeformVert **)dvert_array, dvert_tot, weight_accum_prev, def_nr);
+ memcpy(weight_accum_curr, weight_accum_prev, sizeof(*weight_accum_curr) * dvert_tot);
+
+ for (iter = 0; iter < repeat; iter++) {
+ unsigned *vi_step, *vi_end = verts_used + STACK_SIZE(verts_used);
+
+ /* avoid looping over all verts */
+ // for (i = 0; i < dvert_tot; i++)
+ for (vi_step = verts_used; vi_step != vi_end; vi_step++) {
+ const unsigned int i = *vi_step;
+ float weight_tot = 0.0f;
+ float weight = 0.0f;
#define WEIGHT_ACCUMULATE \
- { \
- float weight_other = weight_accum_prev[i_other]; \
- float tot_factor = 1.0f; \
- if (expand_sign == 1) { /* expand */ \
- if (weight_other < weight_accum_prev[i]) { \
- weight_other = (weight_accum_prev[i] * expand) + (weight_other * iexpand); \
- tot_factor = iexpand; \
- } \
- } \
- else if (expand_sign == -1) { /* contract */ \
- if (weight_other > weight_accum_prev[i]) { \
- weight_other = (weight_accum_prev[i] * expand) + (weight_other * iexpand); \
- tot_factor = iexpand; \
- } \
- } \
- weight += tot_factor * weight_other; \
- weight_tot += tot_factor; \
- } ((void)0)
-
-
- if (bm) {
- BMVert *v = BM_vert_at_index(bm, i);
- BMIter eiter;
- BMEdge *e;
-
- /* checked already */
- BLI_assert(IS_BM_VERT_WRITE(v));
-
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- BMVert *v_other = BM_edge_other_vert(e, v);
- if (IS_BM_VERT_READ(v_other)) {
- const int i_other = BM_elem_index_get(v_other);
-
- WEIGHT_ACCUMULATE;
- }
- }
- }
- else {
- int j;
-
- /* checked already */
- BLI_assert(IS_ME_VERT_WRITE(&me->mvert[i]));
-
- for (j = 0; j < emap[i].count; j++) {
- MEdge *e = &me->medge[emap[i].indices[j]];
- const int i_other = (e->v1 == i ? e->v2 : e->v1);
- MVert *v_other = &me->mvert[i_other];
-
- if (IS_ME_VERT_READ(v_other)) {
- WEIGHT_ACCUMULATE;
- }
- }
- }
+ { \
+ float weight_other = weight_accum_prev[i_other]; \
+ float tot_factor = 1.0f; \
+ if (expand_sign == 1) { /* expand */ \
+ if (weight_other < weight_accum_prev[i]) { \
+ weight_other = (weight_accum_prev[i] * expand) + (weight_other * iexpand); \
+ tot_factor = iexpand; \
+ } \
+ } \
+ else if (expand_sign == -1) { /* contract */ \
+ if (weight_other > weight_accum_prev[i]) { \
+ weight_other = (weight_accum_prev[i] * expand) + (weight_other * iexpand); \
+ tot_factor = iexpand; \
+ } \
+ } \
+ weight += tot_factor * weight_other; \
+ weight_tot += tot_factor; \
+ } \
+ ((void)0)
+
+ if (bm) {
+ BMVert *v = BM_vert_at_index(bm, i);
+ BMIter eiter;
+ BMEdge *e;
+
+ /* checked already */
+ BLI_assert(IS_BM_VERT_WRITE(v));
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ if (IS_BM_VERT_READ(v_other)) {
+ const int i_other = BM_elem_index_get(v_other);
+
+ WEIGHT_ACCUMULATE;
+ }
+ }
+ }
+ else {
+ int j;
+
+ /* checked already */
+ BLI_assert(IS_ME_VERT_WRITE(&me->mvert[i]));
+
+ for (j = 0; j < emap[i].count; j++) {
+ MEdge *e = &me->medge[emap[i].indices[j]];
+ const int i_other = (e->v1 == i ? e->v2 : e->v1);
+ MVert *v_other = &me->mvert[i_other];
+
+ if (IS_ME_VERT_READ(v_other)) {
+ WEIGHT_ACCUMULATE;
+ }
+ }
+ }
#undef WEIGHT_ACCUMULATE
- if (weight_tot != 0.0f) {
- weight /= weight_tot;
- weight = (weight_accum_prev[i] * ifac) + (weight * fac);
+ if (weight_tot != 0.0f) {
+ weight /= weight_tot;
+ weight = (weight_accum_prev[i] * ifac) + (weight * fac);
- /* should be within range, just clamp because of float precision */
- CLAMP(weight, 0.0f, 1.0f);
- weight_accum_curr[i] = weight;
- }
- }
+ /* should be within range, just clamp because of float precision */
+ CLAMP(weight, 0.0f, 1.0f);
+ weight_accum_curr[i] = weight;
+ }
+ }
- SWAP(float *, weight_accum_curr, weight_accum_prev);
- }
+ SWAP(float *, weight_accum_curr, weight_accum_prev);
+ }
- ED_vgroup_parray_from_weight_array(dvert_array, dvert_tot, weight_accum_prev, def_nr, true);
- }
+ ED_vgroup_parray_from_weight_array(dvert_array, dvert_tot, weight_accum_prev, def_nr, true);
+ }
#undef IS_BM_VERT_READ
#undef IS_BM_VERT_WRITE
#undef IS_ME_VERT_READ
#undef IS_ME_VERT_WRITE
- MEM_freeN(weight_accum_curr);
- MEM_freeN(weight_accum_prev);
- MEM_freeN(verts_used);
-
- if (bm) {
- /* pass */
- }
- else {
- MEM_freeN(emap);
- MEM_freeN(emap_mem);
- }
-
- if (dvert_array)
- MEM_freeN(dvert_array);
-
- /* not so efficient to get 'dvert_array' again just so unselected verts are NULL'd */
- if (use_mirror) {
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, true);
- ED_vgroup_parray_mirror_sync(
- ob, dvert_array, dvert_tot,
- vgroup_validmap, vgroup_tot);
- if (dvert_array)
- MEM_freeN(dvert_array);
- }
+ MEM_freeN(weight_accum_curr);
+ MEM_freeN(weight_accum_prev);
+ MEM_freeN(verts_used);
+
+ if (bm) {
+ /* pass */
+ }
+ else {
+ MEM_freeN(emap);
+ MEM_freeN(emap_mem);
+ }
+
+ if (dvert_array)
+ MEM_freeN(dvert_array);
+
+ /* not so efficient to get 'dvert_array' again just so unselected verts are NULL'd */
+ if (use_mirror) {
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, true);
+ ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot, vgroup_validmap, vgroup_tot);
+ if (dvert_array)
+ MEM_freeN(dvert_array);
+ }
}
static int inv_cmp_mdef_vert_weights(const void *a1, const void *a2)
{
- /* qsort sorts in ascending order. We want descending order to save a memcopy
- * so this compare function is inverted from the standard greater than comparison qsort needs.
- * A normal compare function is called with two pointer arguments and should return an integer
- * less than, equal to, or greater than zero corresponding to whether its first argument is
- * considered less than, equal to, or greater than its second argument.
- * This does the opposite. */
- const struct MDeformWeight *dw1 = a1, *dw2 = a2;
-
- if (dw1->weight < dw2->weight) return 1;
- else if (dw1->weight > dw2->weight) return -1;
- else if (&dw1 < &dw2) return 1; /* compare address for stable sort algorithm */
- else return -1;
+ /* qsort sorts in ascending order. We want descending order to save a memcopy
+ * so this compare function is inverted from the standard greater than comparison qsort needs.
+ * A normal compare function is called with two pointer arguments and should return an integer
+ * less than, equal to, or greater than zero corresponding to whether its first argument is
+ * considered less than, equal to, or greater than its second argument.
+ * This does the opposite. */
+ const struct MDeformWeight *dw1 = a1, *dw2 = a2;
+
+ if (dw1->weight < dw2->weight)
+ return 1;
+ else if (dw1->weight > dw2->weight)
+ return -1;
+ else if (&dw1 < &dw2)
+ return 1; /* compare address for stable sort algorithm */
+ else
+ return -1;
}
/* Used for limiting the number of influencing bones per vertex when exporting
* skinned meshes. if all_deform_weights is True, limit all deform modifiers
* to max_weights regardless of type, otherwise,
* only limit the number of influencing bones per vertex. */
-static int vgroup_limit_total_subset(
- Object *ob,
- const bool *vgroup_validmap,
- const int vgroup_tot,
- const int subset_count,
- const int max_weights)
-{
- MDeformVert *dv, **dvert_array = NULL;
- int i, dvert_tot = 0;
- const int use_vert_sel = vertex_group_use_vert_sel(ob);
- int remove_tot = 0;
-
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
-
- if (dvert_array) {
- int num_to_drop = 0;
-
- for (i = 0; i < dvert_tot; i++) {
-
- MDeformWeight *dw_temp;
- int bone_count = 0, non_bone_count = 0;
- int j;
-
- /* in case its not selected */
- if (!(dv = dvert_array[i])) {
- continue;
- }
-
- num_to_drop = subset_count - max_weights;
-
- /* first check if we even need to test further */
- if (num_to_drop > 0) {
- /* re-pack dw array so that non-bone weights are first, bone-weighted verts at end
- * sort the tail, then copy only the truncated array back to dv->dw */
- dw_temp = MEM_mallocN(sizeof(MDeformWeight) * dv->totweight, __func__);
- bone_count = 0; non_bone_count = 0;
- for (j = 0; j < dv->totweight; j++) {
- if (LIKELY(dv->dw[j].def_nr < vgroup_tot) &&
- vgroup_validmap[dv->dw[j].def_nr])
- {
- dw_temp[dv->totweight - 1 - bone_count] = dv->dw[j];
- bone_count += 1;
- }
- else {
- dw_temp[non_bone_count] = dv->dw[j];
- non_bone_count += 1;
- }
- }
- BLI_assert(bone_count + non_bone_count == dv->totweight);
- num_to_drop = bone_count - max_weights;
- if (num_to_drop > 0) {
- qsort(&dw_temp[non_bone_count], bone_count, sizeof(MDeformWeight), inv_cmp_mdef_vert_weights);
- dv->totweight -= num_to_drop;
- /* Do we want to clean/normalize here? */
- MEM_freeN(dv->dw);
- dv->dw = MEM_reallocN(dw_temp, sizeof(MDeformWeight) * dv->totweight);
- remove_tot += num_to_drop;
- }
- else {
- MEM_freeN(dw_temp);
- }
- }
-
- }
- MEM_freeN(dvert_array);
-
- }
-
- return remove_tot;
-}
-
-
-static void vgroup_clean_subset(
- Object *ob, const bool *vgroup_validmap, const int vgroup_tot, const int UNUSED(subset_count),
- const float epsilon, const bool keep_single)
-{
- MDeformVert **dvert_array = NULL;
- int dvert_tot = 0;
- const bool use_vert_sel = vertex_group_use_vert_sel(ob);
- const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
-
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
-
- if (dvert_array) {
- if (use_mirror && use_vert_sel) {
- /* correct behavior in this case isn't well defined
- * for now assume both sides are mirrored correctly,
- * so cleaning one side also cleans the other */
- ED_vgroup_parray_mirror_assign(ob, dvert_array, dvert_tot);
- }
-
- ED_vgroup_parray_remove_zero(
- dvert_array, dvert_tot,
- vgroup_validmap, vgroup_tot,
- epsilon, keep_single);
-
- MEM_freeN(dvert_array);
- }
-}
-
-static void vgroup_quantize_subset(
- Object *ob, const bool *vgroup_validmap, const int vgroup_tot, const int UNUSED(subset_count),
- const int steps)
-{
- MDeformVert **dvert_array = NULL;
- int dvert_tot = 0;
- const bool use_vert_sel = vertex_group_use_vert_sel(ob);
- const bool use_mirror = (ob->type == OB_MESH) ? (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 : false;
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
-
- if (dvert_array) {
- const float steps_fl = steps;
- MDeformVert *dv;
- int i;
-
- if (use_mirror && use_vert_sel) {
- ED_vgroup_parray_mirror_assign(ob, dvert_array, dvert_tot);
- }
-
- for (i = 0; i < dvert_tot; i++) {
- MDeformWeight *dw;
- int j;
-
- /* in case its not selected */
- if (!(dv = dvert_array[i])) {
- continue;
- }
-
- for (j = 0, dw = dv->dw; j < dv->totweight; j++, dw++) {
- if ((dw->def_nr < vgroup_tot) && vgroup_validmap[dw->def_nr]) {
- dw->weight = floorf((dw->weight * steps_fl) + 0.5f) / steps_fl;
- CLAMP(dw->weight, 0.0f, 1.0f);
- }
- }
- }
-
- MEM_freeN(dvert_array);
- }
-}
-
-static void dvert_mirror_op(
- MDeformVert *dvert, MDeformVert *dvert_mirr,
- const char sel, const char sel_mirr,
- const int *flip_map, const int flip_map_len,
- const bool mirror_weights, const bool flip_vgroups, const bool all_vgroups,
- const int act_vgroup)
-{
- BLI_assert(sel || sel_mirr);
-
- if (sel_mirr && sel) {
- /* swap */
- if (mirror_weights) {
- if (all_vgroups) {
- SWAP(MDeformVert, *dvert, *dvert_mirr);
- }
- else {
- MDeformWeight *dw = defvert_find_index(dvert, act_vgroup);
- MDeformWeight *dw_mirr = defvert_find_index(dvert_mirr, act_vgroup);
-
- if (dw && dw_mirr) {
- SWAP(float, dw->weight, dw_mirr->weight);
- }
- else if (dw) {
- dw_mirr = defvert_verify_index(dvert_mirr, act_vgroup);
- dw_mirr->weight = dw->weight;
- defvert_remove_group(dvert, dw);
- }
- else if (dw_mirr) {
- dw = defvert_verify_index(dvert, act_vgroup);
- dw->weight = dw_mirr->weight;
- defvert_remove_group(dvert_mirr, dw_mirr);
- }
- }
- }
-
- if (flip_vgroups) {
- defvert_flip(dvert, flip_map, flip_map_len);
- defvert_flip(dvert_mirr, flip_map, flip_map_len);
- }
- }
- else {
- /* dvert should always be the target, only swaps pointer */
- if (sel_mirr) {
- SWAP(MDeformVert *, dvert, dvert_mirr);
- }
-
- if (mirror_weights) {
- if (all_vgroups) {
- defvert_copy(dvert, dvert_mirr);
- }
- else {
- defvert_copy_index(dvert, act_vgroup, dvert_mirr, act_vgroup);
- }
- }
-
- /* flip map already modified for 'all_vgroups' */
- if (flip_vgroups) {
- defvert_flip(dvert, flip_map, flip_map_len);
- }
- }
+static int vgroup_limit_total_subset(Object *ob,
+ const bool *vgroup_validmap,
+ const int vgroup_tot,
+ const int subset_count,
+ const int max_weights)
+{
+ MDeformVert *dv, **dvert_array = NULL;
+ int i, dvert_tot = 0;
+ const int use_vert_sel = vertex_group_use_vert_sel(ob);
+ int remove_tot = 0;
+
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
+
+ if (dvert_array) {
+ int num_to_drop = 0;
+
+ for (i = 0; i < dvert_tot; i++) {
+
+ MDeformWeight *dw_temp;
+ int bone_count = 0, non_bone_count = 0;
+ int j;
+
+ /* in case its not selected */
+ if (!(dv = dvert_array[i])) {
+ continue;
+ }
+
+ num_to_drop = subset_count - max_weights;
+
+ /* first check if we even need to test further */
+ if (num_to_drop > 0) {
+ /* re-pack dw array so that non-bone weights are first, bone-weighted verts at end
+ * sort the tail, then copy only the truncated array back to dv->dw */
+ dw_temp = MEM_mallocN(sizeof(MDeformWeight) * dv->totweight, __func__);
+ bone_count = 0;
+ non_bone_count = 0;
+ for (j = 0; j < dv->totweight; j++) {
+ if (LIKELY(dv->dw[j].def_nr < vgroup_tot) && vgroup_validmap[dv->dw[j].def_nr]) {
+ dw_temp[dv->totweight - 1 - bone_count] = dv->dw[j];
+ bone_count += 1;
+ }
+ else {
+ dw_temp[non_bone_count] = dv->dw[j];
+ non_bone_count += 1;
+ }
+ }
+ BLI_assert(bone_count + non_bone_count == dv->totweight);
+ num_to_drop = bone_count - max_weights;
+ if (num_to_drop > 0) {
+ qsort(&dw_temp[non_bone_count],
+ bone_count,
+ sizeof(MDeformWeight),
+ inv_cmp_mdef_vert_weights);
+ dv->totweight -= num_to_drop;
+ /* Do we want to clean/normalize here? */
+ MEM_freeN(dv->dw);
+ dv->dw = MEM_reallocN(dw_temp, sizeof(MDeformWeight) * dv->totweight);
+ remove_tot += num_to_drop;
+ }
+ else {
+ MEM_freeN(dw_temp);
+ }
+ }
+ }
+ MEM_freeN(dvert_array);
+ }
+
+ return remove_tot;
+}
+
+static void vgroup_clean_subset(Object *ob,
+ const bool *vgroup_validmap,
+ const int vgroup_tot,
+ const int UNUSED(subset_count),
+ const float epsilon,
+ const bool keep_single)
+{
+ MDeformVert **dvert_array = NULL;
+ int dvert_tot = 0;
+ const bool use_vert_sel = vertex_group_use_vert_sel(ob);
+ const bool use_mirror = (ob->type == OB_MESH) ?
+ (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 :
+ false;
+
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
+
+ if (dvert_array) {
+ if (use_mirror && use_vert_sel) {
+ /* correct behavior in this case isn't well defined
+ * for now assume both sides are mirrored correctly,
+ * so cleaning one side also cleans the other */
+ ED_vgroup_parray_mirror_assign(ob, dvert_array, dvert_tot);
+ }
+
+ ED_vgroup_parray_remove_zero(
+ dvert_array, dvert_tot, vgroup_validmap, vgroup_tot, epsilon, keep_single);
+
+ MEM_freeN(dvert_array);
+ }
+}
+
+static void vgroup_quantize_subset(Object *ob,
+ const bool *vgroup_validmap,
+ const int vgroup_tot,
+ const int UNUSED(subset_count),
+ const int steps)
+{
+ MDeformVert **dvert_array = NULL;
+ int dvert_tot = 0;
+ const bool use_vert_sel = vertex_group_use_vert_sel(ob);
+ const bool use_mirror = (ob->type == OB_MESH) ?
+ (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X) != 0 :
+ false;
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, use_vert_sel);
+
+ if (dvert_array) {
+ const float steps_fl = steps;
+ MDeformVert *dv;
+ int i;
+
+ if (use_mirror && use_vert_sel) {
+ ED_vgroup_parray_mirror_assign(ob, dvert_array, dvert_tot);
+ }
+
+ for (i = 0; i < dvert_tot; i++) {
+ MDeformWeight *dw;
+ int j;
+
+ /* in case its not selected */
+ if (!(dv = dvert_array[i])) {
+ continue;
+ }
+
+ for (j = 0, dw = dv->dw; j < dv->totweight; j++, dw++) {
+ if ((dw->def_nr < vgroup_tot) && vgroup_validmap[dw->def_nr]) {
+ dw->weight = floorf((dw->weight * steps_fl) + 0.5f) / steps_fl;
+ CLAMP(dw->weight, 0.0f, 1.0f);
+ }
+ }
+ }
+
+ MEM_freeN(dvert_array);
+ }
+}
+
+static void dvert_mirror_op(MDeformVert *dvert,
+ MDeformVert *dvert_mirr,
+ const char sel,
+ const char sel_mirr,
+ const int *flip_map,
+ const int flip_map_len,
+ const bool mirror_weights,
+ const bool flip_vgroups,
+ const bool all_vgroups,
+ const int act_vgroup)
+{
+ BLI_assert(sel || sel_mirr);
+
+ if (sel_mirr && sel) {
+ /* swap */
+ if (mirror_weights) {
+ if (all_vgroups) {
+ SWAP(MDeformVert, *dvert, *dvert_mirr);
+ }
+ else {
+ MDeformWeight *dw = defvert_find_index(dvert, act_vgroup);
+ MDeformWeight *dw_mirr = defvert_find_index(dvert_mirr, act_vgroup);
+
+ if (dw && dw_mirr) {
+ SWAP(float, dw->weight, dw_mirr->weight);
+ }
+ else if (dw) {
+ dw_mirr = defvert_verify_index(dvert_mirr, act_vgroup);
+ dw_mirr->weight = dw->weight;
+ defvert_remove_group(dvert, dw);
+ }
+ else if (dw_mirr) {
+ dw = defvert_verify_index(dvert, act_vgroup);
+ dw->weight = dw_mirr->weight;
+ defvert_remove_group(dvert_mirr, dw_mirr);
+ }
+ }
+ }
+
+ if (flip_vgroups) {
+ defvert_flip(dvert, flip_map, flip_map_len);
+ defvert_flip(dvert_mirr, flip_map, flip_map_len);
+ }
+ }
+ else {
+ /* dvert should always be the target, only swaps pointer */
+ if (sel_mirr) {
+ SWAP(MDeformVert *, dvert, dvert_mirr);
+ }
+
+ if (mirror_weights) {
+ if (all_vgroups) {
+ defvert_copy(dvert, dvert_mirr);
+ }
+ else {
+ defvert_copy_index(dvert, act_vgroup, dvert_mirr, act_vgroup);
+ }
+ }
+
+ /* flip map already modified for 'all_vgroups' */
+ if (flip_vgroups) {
+ defvert_flip(dvert, flip_map, flip_map_len);
+ }
+ }
}
/* TODO, vgroup locking */
/* TODO, face masking */
-void ED_vgroup_mirror(
- Object *ob,
- const bool mirror_weights, const bool flip_vgroups,
- const bool all_vgroups, const bool use_topology,
- int *r_totmirr, int *r_totfail)
-{
-
-#define VGROUP_MIRR_OP \
- dvert_mirror_op(dvert, dvert_mirr, \
- sel, sel_mirr, \
- flip_map, flip_map_len, \
- mirror_weights, flip_vgroups, \
- all_vgroups, def_nr \
- )
-
- BMVert *eve, *eve_mirr;
- MDeformVert *dvert, *dvert_mirr;
- char sel, sel_mirr;
- int *flip_map = NULL, flip_map_len;
- const int def_nr = ob->actdef - 1;
- int totmirr = 0, totfail = 0;
-
- *r_totmirr = *r_totfail = 0;
-
- if ((mirror_weights == false && flip_vgroups == false) ||
- (BLI_findlink(&ob->defbase, def_nr) == NULL))
- {
- return;
- }
-
- if (flip_vgroups) {
- flip_map = all_vgroups ?
- defgroup_flip_map(ob, &flip_map_len, false) :
- defgroup_flip_map_single(ob, &flip_map_len, false, def_nr);
-
- BLI_assert(flip_map != NULL);
-
- if (flip_map == NULL) {
- /* something went wrong!, possibly no groups */
- return;
- }
- }
- else {
- flip_map = NULL;
- flip_map_len = 0;
- }
-
- /* only the active group */
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
-
- if (em) {
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
- BMIter iter;
-
- if (cd_dvert_offset == -1) {
- goto cleanup;
- }
-
- EDBM_verts_mirror_cache_begin(em, 0, true, false, use_topology);
-
- BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
-
- /* Go through the list of editverts and assign them */
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(eve, BM_ELEM_TAG)) {
- if ((eve_mirr = EDBM_verts_mirror_get(em, eve))) {
- if (eve_mirr != eve) {
- if (!BM_elem_flag_test(eve_mirr, BM_ELEM_TAG)) {
- sel = BM_elem_flag_test(eve, BM_ELEM_SELECT);
- sel_mirr = BM_elem_flag_test(eve_mirr, BM_ELEM_SELECT);
-
- if ((sel || sel_mirr) && (eve != eve_mirr)) {
- dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
- dvert_mirr = BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset);
-
- VGROUP_MIRR_OP;
- totmirr++;
- }
-
- /* don't use these again */
- BM_elem_flag_enable(eve, BM_ELEM_TAG);
- BM_elem_flag_enable(eve_mirr, BM_ELEM_TAG);
- }
- }
- }
- else {
- totfail++;
- }
- }
- }
- EDBM_verts_mirror_cache_end(em);
- }
- else {
- /* object mode / weight paint */
- MVert *mv, *mv_mirr;
- int vidx, vidx_mirr;
- const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
-
- if (me->dvert == NULL) {
- goto cleanup;
- }
-
- if (!use_vert_sel) {
- sel = sel_mirr = true;
- }
-
- /* tag verts we have used */
- for (vidx = 0, mv = me->mvert; vidx < me->totvert; vidx++, mv++) {
- mv->flag &= ~ME_VERT_TMP_TAG;
- }
-
- for (vidx = 0, mv = me->mvert; vidx < me->totvert; vidx++, mv++) {
- if ((mv->flag & ME_VERT_TMP_TAG) == 0) {
- if ((vidx_mirr = mesh_get_x_mirror_vert(ob, NULL, vidx, use_topology)) != -1) {
- if (vidx != vidx_mirr) {
- mv_mirr = &me->mvert[vidx_mirr];
- if ((mv_mirr->flag & ME_VERT_TMP_TAG) == 0) {
-
- if (use_vert_sel) {
- sel = mv->flag & SELECT;
- sel_mirr = mv_mirr->flag & SELECT;
- }
-
- if (sel || sel_mirr) {
- dvert = &me->dvert[vidx];
- dvert_mirr = &me->dvert[vidx_mirr];
-
- VGROUP_MIRR_OP;
- totmirr++;
- }
-
- mv->flag |= ME_VERT_TMP_TAG;
- mv_mirr->flag |= ME_VERT_TMP_TAG;
- }
- }
- }
- else {
- totfail++;
- }
- }
- }
- }
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = vgroup_edit_lattice(ob);
- int i1, i2;
- int u, v, w;
- int pntsu_half;
- /* half but found up odd value */
-
- if (lt->pntsu == 1 || lt->dvert == NULL) {
- goto cleanup;
- }
-
- /* unlike editmesh we know that by only looping over the first half of
- * the 'u' indices it will cover all points except the middle which is
- * ok in this case */
- pntsu_half = lt->pntsu / 2;
-
- for (w = 0; w < lt->pntsw; w++) {
- for (v = 0; v < lt->pntsv; v++) {
- for (u = 0; u < pntsu_half; u++) {
- int u_inv = (lt->pntsu - 1) - u;
- if (u != u_inv) {
- BPoint *bp, *bp_mirr;
-
- i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
- i2 = BKE_lattice_index_from_uvw(lt, u_inv, v, w);
-
- bp = &lt->def[i1];
- bp_mirr = &lt->def[i2];
-
- sel = bp->f1 & SELECT;
- sel_mirr = bp_mirr->f1 & SELECT;
-
- if (sel || sel_mirr) {
- dvert = &lt->dvert[i1];
- dvert_mirr = &lt->dvert[i2];
-
- VGROUP_MIRR_OP;
- totmirr++;
- }
- }
- }
- }
- }
- }
-
- /* disabled, confusing when you have an active pose bone */
+void ED_vgroup_mirror(Object *ob,
+ const bool mirror_weights,
+ const bool flip_vgroups,
+ const bool all_vgroups,
+ const bool use_topology,
+ int *r_totmirr,
+ int *r_totfail)
+{
+
+#define VGROUP_MIRR_OP \
+ dvert_mirror_op(dvert, \
+ dvert_mirr, \
+ sel, \
+ sel_mirr, \
+ flip_map, \
+ flip_map_len, \
+ mirror_weights, \
+ flip_vgroups, \
+ all_vgroups, \
+ def_nr)
+
+ BMVert *eve, *eve_mirr;
+ MDeformVert *dvert, *dvert_mirr;
+ char sel, sel_mirr;
+ int *flip_map = NULL, flip_map_len;
+ const int def_nr = ob->actdef - 1;
+ int totmirr = 0, totfail = 0;
+
+ *r_totmirr = *r_totfail = 0;
+
+ if ((mirror_weights == false && flip_vgroups == false) ||
+ (BLI_findlink(&ob->defbase, def_nr) == NULL)) {
+ return;
+ }
+
+ if (flip_vgroups) {
+ flip_map = all_vgroups ? defgroup_flip_map(ob, &flip_map_len, false) :
+ defgroup_flip_map_single(ob, &flip_map_len, false, def_nr);
+
+ BLI_assert(flip_map != NULL);
+
+ if (flip_map == NULL) {
+ /* something went wrong!, possibly no groups */
+ return;
+ }
+ }
+ else {
+ flip_map = NULL;
+ flip_map_len = 0;
+ }
+
+ /* only the active group */
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+
+ if (em) {
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+ BMIter iter;
+
+ if (cd_dvert_offset == -1) {
+ goto cleanup;
+ }
+
+ EDBM_verts_mirror_cache_begin(em, 0, true, false, use_topology);
+
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
+
+ /* Go through the list of editverts and assign them */
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(eve, BM_ELEM_TAG)) {
+ if ((eve_mirr = EDBM_verts_mirror_get(em, eve))) {
+ if (eve_mirr != eve) {
+ if (!BM_elem_flag_test(eve_mirr, BM_ELEM_TAG)) {
+ sel = BM_elem_flag_test(eve, BM_ELEM_SELECT);
+ sel_mirr = BM_elem_flag_test(eve_mirr, BM_ELEM_SELECT);
+
+ if ((sel || sel_mirr) && (eve != eve_mirr)) {
+ dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+ dvert_mirr = BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset);
+
+ VGROUP_MIRR_OP;
+ totmirr++;
+ }
+
+ /* don't use these again */
+ BM_elem_flag_enable(eve, BM_ELEM_TAG);
+ BM_elem_flag_enable(eve_mirr, BM_ELEM_TAG);
+ }
+ }
+ }
+ else {
+ totfail++;
+ }
+ }
+ }
+ EDBM_verts_mirror_cache_end(em);
+ }
+ else {
+ /* object mode / weight paint */
+ MVert *mv, *mv_mirr;
+ int vidx, vidx_mirr;
+ const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
+
+ if (me->dvert == NULL) {
+ goto cleanup;
+ }
+
+ if (!use_vert_sel) {
+ sel = sel_mirr = true;
+ }
+
+ /* tag verts we have used */
+ for (vidx = 0, mv = me->mvert; vidx < me->totvert; vidx++, mv++) {
+ mv->flag &= ~ME_VERT_TMP_TAG;
+ }
+
+ for (vidx = 0, mv = me->mvert; vidx < me->totvert; vidx++, mv++) {
+ if ((mv->flag & ME_VERT_TMP_TAG) == 0) {
+ if ((vidx_mirr = mesh_get_x_mirror_vert(ob, NULL, vidx, use_topology)) != -1) {
+ if (vidx != vidx_mirr) {
+ mv_mirr = &me->mvert[vidx_mirr];
+ if ((mv_mirr->flag & ME_VERT_TMP_TAG) == 0) {
+
+ if (use_vert_sel) {
+ sel = mv->flag & SELECT;
+ sel_mirr = mv_mirr->flag & SELECT;
+ }
+
+ if (sel || sel_mirr) {
+ dvert = &me->dvert[vidx];
+ dvert_mirr = &me->dvert[vidx_mirr];
+
+ VGROUP_MIRR_OP;
+ totmirr++;
+ }
+
+ mv->flag |= ME_VERT_TMP_TAG;
+ mv_mirr->flag |= ME_VERT_TMP_TAG;
+ }
+ }
+ }
+ else {
+ totfail++;
+ }
+ }
+ }
+ }
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = vgroup_edit_lattice(ob);
+ int i1, i2;
+ int u, v, w;
+ int pntsu_half;
+ /* half but found up odd value */
+
+ if (lt->pntsu == 1 || lt->dvert == NULL) {
+ goto cleanup;
+ }
+
+ /* unlike editmesh we know that by only looping over the first half of
+ * the 'u' indices it will cover all points except the middle which is
+ * ok in this case */
+ pntsu_half = lt->pntsu / 2;
+
+ for (w = 0; w < lt->pntsw; w++) {
+ for (v = 0; v < lt->pntsv; v++) {
+ for (u = 0; u < pntsu_half; u++) {
+ int u_inv = (lt->pntsu - 1) - u;
+ if (u != u_inv) {
+ BPoint *bp, *bp_mirr;
+
+ i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
+ i2 = BKE_lattice_index_from_uvw(lt, u_inv, v, w);
+
+ bp = &lt->def[i1];
+ bp_mirr = &lt->def[i2];
+
+ sel = bp->f1 & SELECT;
+ sel_mirr = bp_mirr->f1 & SELECT;
+
+ if (sel || sel_mirr) {
+ dvert = &lt->dvert[i1];
+ dvert_mirr = &lt->dvert[i2];
+
+ VGROUP_MIRR_OP;
+ totmirr++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* disabled, confusing when you have an active pose bone */
#if 0
- /* flip active group index */
- if (flip_vgroups && flip_map[def_nr] >= 0)
- ob->actdef = flip_map[def_nr] + 1;
+ /* flip active group index */
+ if (flip_vgroups && flip_map[def_nr] >= 0)
+ ob->actdef = flip_map[def_nr] + 1;
#endif
cleanup:
- *r_totmirr = totmirr;
- *r_totfail = totfail;
+ *r_totmirr = totmirr;
+ *r_totfail = totfail;
- if (flip_map) MEM_freeN(flip_map);
+ if (flip_map)
+ MEM_freeN(flip_map);
#undef VGROUP_MIRR_OP
-
}
static void vgroup_delete_active(Object *ob)
{
- bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
- if (!dg)
- return;
+ bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
+ if (!dg)
+ return;
- BKE_object_defgroup_remove(ob, dg);
+ BKE_object_defgroup_remove(ob, dg);
}
/* only in editmode */
static void vgroup_assign_verts(Object *ob, const float weight)
{
- const int def_nr = ob->actdef - 1;
-
- if (!BLI_findlink(&ob->defbase, def_nr))
- return;
-
- if (ob->type == OB_MESH) {
- Mesh *me = ob->data;
-
- if (me->edit_mesh) {
- BMEditMesh *em = me->edit_mesh;
- int cd_dvert_offset;
-
- BMIter iter;
- BMVert *eve;
-
- if (!CustomData_has_layer(&em->bm->vdata, CD_MDEFORMVERT))
- BM_data_layer_add(em->bm, &em->bm->vdata, CD_MDEFORMVERT);
-
- cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
-
- /* Go through the list of editverts and assign them */
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- MDeformVert *dv;
- MDeformWeight *dw;
- dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); /* can be NULL */
- dw = defvert_verify_index(dv, def_nr);
- if (dw) {
- dw->weight = weight;
- }
- }
- }
- }
- else {
- MVert *mv;
- MDeformVert *dv;
- int i;
-
- if (!me->dvert) {
- BKE_object_defgroup_data_create(&me->id);
- }
-
- mv = me->mvert;
- dv = me->dvert;
-
- for (i = 0; i < me->totvert; i++, mv++, dv++) {
- if (mv->flag & SELECT) {
- MDeformWeight *dw;
- dw = defvert_verify_index(dv, def_nr);
- if (dw) {
- dw->weight = weight;
- }
- }
- }
- }
- }
- else if (ob->type == OB_LATTICE) {
- Lattice *lt = vgroup_edit_lattice(ob);
- MDeformVert *dv;
- BPoint *bp;
- int a, tot;
-
- if (lt->dvert == NULL)
- BKE_object_defgroup_data_create(&lt->id);
-
- dv = lt->dvert;
-
- tot = lt->pntsu * lt->pntsv * lt->pntsw;
- for (a = 0, bp = lt->def; a < tot; a++, bp++, dv++) {
- if (bp->f1 & SELECT) {
- MDeformWeight *dw;
-
- dw = defvert_verify_index(dv, def_nr);
- if (dw) {
- dw->weight = weight;
- }
- }
- }
- }
+ const int def_nr = ob->actdef - 1;
+
+ if (!BLI_findlink(&ob->defbase, def_nr))
+ return;
+
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (me->edit_mesh) {
+ BMEditMesh *em = me->edit_mesh;
+ int cd_dvert_offset;
+
+ BMIter iter;
+ BMVert *eve;
+
+ if (!CustomData_has_layer(&em->bm->vdata, CD_MDEFORMVERT))
+ BM_data_layer_add(em->bm, &em->bm->vdata, CD_MDEFORMVERT);
+
+ cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+
+ /* Go through the list of editverts and assign them */
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+ MDeformVert *dv;
+ MDeformWeight *dw;
+ dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); /* can be NULL */
+ dw = defvert_verify_index(dv, def_nr);
+ if (dw) {
+ dw->weight = weight;
+ }
+ }
+ }
+ }
+ else {
+ MVert *mv;
+ MDeformVert *dv;
+ int i;
+
+ if (!me->dvert) {
+ BKE_object_defgroup_data_create(&me->id);
+ }
+
+ mv = me->mvert;
+ dv = me->dvert;
+
+ for (i = 0; i < me->totvert; i++, mv++, dv++) {
+ if (mv->flag & SELECT) {
+ MDeformWeight *dw;
+ dw = defvert_verify_index(dv, def_nr);
+ if (dw) {
+ dw->weight = weight;
+ }
+ }
+ }
+ }
+ }
+ else if (ob->type == OB_LATTICE) {
+ Lattice *lt = vgroup_edit_lattice(ob);
+ MDeformVert *dv;
+ BPoint *bp;
+ int a, tot;
+
+ if (lt->dvert == NULL)
+ BKE_object_defgroup_data_create(&lt->id);
+
+ dv = lt->dvert;
+
+ tot = lt->pntsu * lt->pntsv * lt->pntsw;
+ for (a = 0, bp = lt->def; a < tot; a++, bp++, dv++) {
+ if (bp->f1 & SELECT) {
+ MDeformWeight *dw;
+
+ dw = defvert_verify_index(dv, def_nr);
+ if (dw) {
+ dw->weight = weight;
+ }
+ }
+ }
+ }
}
/********************** vertex group operators *********************/
static bool vertex_group_poll(bContext *C)
{
- Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
+ 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) && data && !ID_IS_LINKED(data) &&
+ OB_TYPE_SUPPORT_VGROUP(ob->type) && ob->defbase.first);
}
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) && OB_TYPE_SUPPORT_VGROUP(ob->type) &&
- data && !ID_IS_LINKED(data));
+ 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));
}
static bool vertex_group_mesh_poll(bContext *C)
{
- Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
+ 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 (ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data) && ob->type == OB_MESH &&
+ ob->defbase.first);
}
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));
+ 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));
}
-
-static bool UNUSED_FUNCTION(vertex_group_poll_edit) (bContext *C)
+static bool UNUSED_FUNCTION(vertex_group_poll_edit)(bContext *C)
{
- Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
+ 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 (!(ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data)))
+ return 0;
- return BKE_object_is_in_editmode_vgroup(ob);
+ return BKE_object_is_in_editmode_vgroup(ob);
}
/* editmode _or_ weight paint vertex sel */
-static bool vertex_group_vert_poll_ex(bContext *C, const bool needs_select, 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)))
- return false;
-
- if (ob_type_flag && (((1 << ob->type) & ob_type_flag)) == 0) {
- return false;
- }
-
- if (BKE_object_is_in_editmode_vgroup(ob)) {
- return true;
- }
- else if (ob->mode & OB_MODE_WEIGHT_PAINT) {
- if (needs_select) {
- if (BKE_object_is_in_wpaint_select_vert(ob)) {
- return true;
- }
- else {
- CTX_wm_operator_poll_msg_set(C, "Vertex select needs to be enabled in weight paint mode");
- return false;
- }
- }
- else {
- return true;
- }
- }
- else {
- return false;
- }
+static bool vertex_group_vert_poll_ex(bContext *C,
+ const bool needs_select,
+ 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)))
+ return false;
+
+ if (ob_type_flag && (((1 << ob->type) & ob_type_flag)) == 0) {
+ return false;
+ }
+
+ if (BKE_object_is_in_editmode_vgroup(ob)) {
+ return true;
+ }
+ else if (ob->mode & OB_MODE_WEIGHT_PAINT) {
+ if (needs_select) {
+ if (BKE_object_is_in_wpaint_select_vert(ob)) {
+ return true;
+ }
+ else {
+ CTX_wm_operator_poll_msg_set(C, "Vertex select needs to be enabled in weight paint mode");
+ return false;
+ }
+ }
+ else {
+ return true;
+ }
+ }
+ else {
+ return false;
+ }
}
#if 0
static bool vertex_group_vert_poll(bContext *C)
{
- return vertex_group_vert_poll_ex(C, false, 0);
+ return vertex_group_vert_poll_ex(C, false, 0);
}
#endif
-
static bool vertex_group_mesh_vert_poll(bContext *C)
{
- return vertex_group_vert_poll_ex(C, false, (1 << OB_MESH));
+ return vertex_group_vert_poll_ex(C, false, (1 << OB_MESH));
}
static bool vertex_group_vert_select_poll(bContext *C)
{
- return vertex_group_vert_poll_ex(C, true, 0);
+ return vertex_group_vert_poll_ex(C, true, 0);
}
#if 0
static bool vertex_group_mesh_vert_select_poll(bContext *C)
{
- return vertex_group_vert_poll_ex(C, true, (1 << OB_MESH));
+ return vertex_group_vert_poll_ex(C, true, (1 << OB_MESH));
}
#endif
-
/* editmode _or_ weight paint vertex sel and active group unlocked */
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 (!(BKE_object_is_in_editmode_vgroup(ob) ||
- BKE_object_is_in_wpaint_select_vert(ob)))
- {
- return 0;
- }
-
- if (ob->actdef != 0) {
- bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
- if (dg) {
- return !(dg->flag & DG_LOCK_WEIGHT);
- }
- }
- return 1;
+ 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 (!(BKE_object_is_in_editmode_vgroup(ob) || BKE_object_is_in_wpaint_select_vert(ob))) {
+ return 0;
+ }
+
+ if (ob->actdef != 0) {
+ bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
+ if (dg) {
+ return !(dg->flag & DG_LOCK_WEIGHT);
+ }
+ }
+ return 1;
}
static bool vertex_group_vert_select_mesh_poll(bContext *C)
{
- Object *ob = ED_object_context(C);
- ID *data = (ob) ? ob->data : NULL;
+ 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 (!(ob && !ID_IS_LINKED(ob) && data && !ID_IS_LINKED(data)))
+ return 0;
- /* only difference to #vertex_group_vert_select_poll */
- if (ob->type != OB_MESH)
- return 0;
+ /* only difference to #vertex_group_vert_select_poll */
+ if (ob->type != OB_MESH)
+ return 0;
- return (BKE_object_is_in_editmode_vgroup(ob) ||
- BKE_object_is_in_wpaint_select_vert(ob));
+ return (BKE_object_is_in_editmode_vgroup(ob) || BKE_object_is_in_wpaint_select_vert(ob));
}
static int vertex_group_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- BKE_object_defgroup_add(ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ BKE_object_defgroup_add(ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_add(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Add Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_add";
- ot->description = "Add a new vertex group to the active object";
+ /* identifiers */
+ ot->name = "Add Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_add";
+ ot->description = "Add a new vertex group to the active object";
- /* api callbacks */
- ot->poll = vertex_group_supported_poll;
- ot->exec = vertex_group_add_exec;
+ /* api callbacks */
+ ot->poll = vertex_group_supported_poll;
+ ot->exec = vertex_group_add_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int vertex_group_remove_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- if (RNA_boolean_get(op->ptr, "all"))
- BKE_object_defgroup_remove_all(ob);
- else if (RNA_boolean_get(op->ptr, "all_unlocked"))
- BKE_object_defgroup_remove_all_ex(ob, true);
- else
- vgroup_delete_active(ob);
+ if (RNA_boolean_get(op->ptr, "all"))
+ BKE_object_defgroup_remove_all(ob);
+ else if (RNA_boolean_get(op->ptr, "all_unlocked"))
+ BKE_object_defgroup_remove_all_ex(ob, true);
+ else
+ vgroup_delete_active(ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_remove(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Remove Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_remove";
- ot->description = "Delete the active or all vertex groups from the active object";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_remove_exec;
-
- /* flags */
- /* redo operator will fail in this case because vertex groups aren't stored
- * in local edit mode stack and toggling "all" property will lead to
- * all groups deleted without way to restore them (see [#29527], sergey) */
- ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
-
- /* properties */
- PropertyRNA *prop = RNA_def_boolean(ot->srna, "all", 0, "All", "Remove all vertex groups");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "all_unlocked", 0, "All Unlocked", "Remove all unlocked vertex groups");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* identifiers */
+ ot->name = "Remove Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_remove";
+ ot->description = "Delete the active or all vertex groups from the active object";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_remove_exec;
+
+ /* flags */
+ /* redo operator will fail in this case because vertex groups aren't stored
+ * in local edit mode stack and toggling "all" property will lead to
+ * all groups deleted without way to restore them (see [#29527], sergey) */
+ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
+
+ /* properties */
+ PropertyRNA *prop = RNA_def_boolean(ot->srna, "all", 0, "All", "Remove all vertex groups");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(
+ ot->srna, "all_unlocked", 0, "All Unlocked", "Remove all unlocked vertex groups");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
static int vertex_group_assign_exec(bContext *C, wmOperator *UNUSED(op))
{
- ToolSettings *ts = CTX_data_tool_settings(C);
- Object *ob = ED_object_context(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Object *ob = ED_object_context(C);
- vgroup_assign_verts(ob, ts->vgroup_weight);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ vgroup_assign_verts(ob, ts->vgroup_weight);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_assign(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Assign to Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_assign";
- ot->description = "Assign the selected vertices to the active vertex group";
-
- /* api callbacks */
- ot->poll = vertex_group_vert_select_unlocked_poll;
- ot->exec = vertex_group_assign_exec;
-
- /* flags */
- /* redo operator will fail in this case because vertex group assignment
- * isn't stored in local edit mode stack and toggling "new" property will
- * lead to creating plenty of new vertex groups (see [#29527], sergey) */
- ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Assign to Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_assign";
+ ot->description = "Assign the selected vertices to the active vertex group";
+
+ /* api callbacks */
+ ot->poll = vertex_group_vert_select_unlocked_poll;
+ ot->exec = vertex_group_assign_exec;
+
+ /* flags */
+ /* redo operator will fail in this case because vertex group assignment
+ * isn't stored in local edit mode stack and toggling "new" property will
+ * lead to creating plenty of new vertex groups (see [#29527], sergey) */
+ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
}
/* 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)
{
- /* create new group... */
- Object *ob = ED_object_context(C);
- BKE_object_defgroup_add(ob);
+ /* create new group... */
+ Object *ob = ED_object_context(C);
+ BKE_object_defgroup_add(ob);
- /* assign selection to new group */
- return vertex_group_assign_exec(C, op);
+ /* assign selection to new group */
+ return vertex_group_assign_exec(C, op);
}
void OBJECT_OT_vertex_group_assign_new(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Assign to New Group";
- ot->idname = "OBJECT_OT_vertex_group_assign_new";
- ot->description = "Assign the selected vertices to a new vertex group";
-
- /* api callbacks */
- ot->poll = vertex_group_vert_select_poll;
- ot->exec = vertex_group_assign_new_exec;
-
- /* flags */
- /* redo operator will fail in this case because vertex group assignment
- * isn't stored in local edit mode stack and toggling "new" property will
- * lead to creating plenty of new vertex groups (see [#29527], sergey) */
- ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Assign to New Group";
+ ot->idname = "OBJECT_OT_vertex_group_assign_new";
+ ot->description = "Assign the selected vertices to a new vertex group";
+
+ /* api callbacks */
+ ot->poll = vertex_group_vert_select_poll;
+ ot->exec = vertex_group_assign_new_exec;
+
+ /* flags */
+ /* redo operator will fail in this case because vertex group assignment
+ * isn't stored in local edit mode stack and toggling "new" property will
+ * lead to creating plenty of new vertex groups (see [#29527], sergey) */
+ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
}
static int vertex_group_remove_from_exec(bContext *C, wmOperator *op)
{
- const bool use_all_groups = RNA_boolean_get(op->ptr, "use_all_groups");
- const bool use_all_verts = RNA_boolean_get(op->ptr, "use_all_verts");
+ const bool use_all_groups = RNA_boolean_get(op->ptr, "use_all_groups");
+ const bool use_all_verts = RNA_boolean_get(op->ptr, "use_all_verts");
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- if (use_all_groups) {
- if (BKE_object_defgroup_clear_all(ob, true) == false) {
- return OPERATOR_CANCELLED;
- }
- }
- else {
- bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
+ if (use_all_groups) {
+ if (BKE_object_defgroup_clear_all(ob, true) == false) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ bDeformGroup *dg = BLI_findlink(&ob->defbase, ob->actdef - 1);
- if ((dg == NULL) || (BKE_object_defgroup_clear(ob, dg, !use_all_verts) == false)) {
- return OPERATOR_CANCELLED;
- }
- }
+ if ((dg == NULL) || (BKE_object_defgroup_clear(ob, dg, !use_all_verts) == false)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot)
{
- PropertyRNA *prop;
- /* identifiers */
- ot->name = "Remove from Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_remove_from";
- ot->description = "Remove the selected vertices from active or all vertex group(s)";
-
- /* api callbacks */
- ot->poll = vertex_group_vert_select_unlocked_poll;
- ot->exec = vertex_group_remove_from_exec;
-
- /* flags */
- /* redo operator will fail in this case because vertex groups assignment
- * isn't stored in local edit mode stack and toggling "all" property will lead to
- * removing vertices from all groups (see [#29527], sergey) */
- ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_boolean(ot->srna, "use_all_groups", 0, "All Groups", "Remove from all groups");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "use_all_verts", 0, "All Verts", "Clear the active group");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+ /* identifiers */
+ ot->name = "Remove from Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_remove_from";
+ ot->description = "Remove the selected vertices from active or all vertex group(s)";
+
+ /* api callbacks */
+ ot->poll = vertex_group_vert_select_unlocked_poll;
+ ot->exec = vertex_group_remove_from_exec;
+
+ /* flags */
+ /* redo operator will fail in this case because vertex groups assignment
+ * isn't stored in local edit mode stack and toggling "all" property will lead to
+ * removing vertices from all groups (see [#29527], sergey) */
+ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_boolean(ot->srna, "use_all_groups", 0, "All Groups", "Remove from all groups");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "use_all_verts", 0, "All Verts", "Clear the active group");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- if (!ob || ID_IS_LINKED(ob))
- return OPERATOR_CANCELLED;
+ if (!ob || ID_IS_LINKED(ob))
+ return OPERATOR_CANCELLED;
- vgroup_select_verts(ob, 1);
- DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
+ vgroup_select_verts(ob, 1);
+ DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_select(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Select Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_select";
- ot->description = "Select all the vertices assigned to the active vertex group";
+ /* identifiers */
+ ot->name = "Select Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_select";
+ ot->description = "Select all the vertices assigned to the active vertex group";
- /* api callbacks */
- ot->poll = vertex_group_vert_select_poll;
- ot->exec = vertex_group_select_exec;
+ /* api callbacks */
+ ot->poll = vertex_group_vert_select_poll;
+ ot->exec = vertex_group_select_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- vgroup_select_verts(ob, 0);
- DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
+ vgroup_select_verts(ob, 0);
+ DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_deselect(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Deselect Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_deselect";
- ot->description = "Deselect all selected vertices assigned to the active vertex group";
+ /* identifiers */
+ ot->name = "Deselect Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_deselect";
+ ot->description = "Deselect all selected vertices assigned to the active vertex group";
- /* api callbacks */
- ot->poll = vertex_group_vert_select_poll;
- ot->exec = vertex_group_deselect_exec;
+ /* api callbacks */
+ ot->poll = vertex_group_vert_select_poll;
+ ot->exec = vertex_group_deselect_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int vertex_group_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- vgroup_duplicate(ob);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
+ vgroup_duplicate(ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_copy(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_copy";
- ot->description = "Make a copy of the active vertex group";
+ /* identifiers */
+ ot->name = "Copy Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_copy";
+ ot->description = "Make a copy of the active vertex group";
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_copy_exec;
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_copy_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int vertex_group_levels_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- float offset = RNA_float_get(op->ptr, "offset");
- float gain = RNA_float_get(op->ptr, "gain");
- eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
+ float offset = RNA_float_get(op->ptr, "offset");
+ float gain = RNA_float_get(op->ptr, "gain");
+ eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
- int subset_count, vgroup_tot;
+ int subset_count, vgroup_tot;
- const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
- vgroup_levels_subset(ob, vgroup_validmap, vgroup_tot, subset_count, offset, gain);
- MEM_freeN((void *)vgroup_validmap);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
+ ob, subset_type, &vgroup_tot, &subset_count);
+ vgroup_levels_subset(ob, vgroup_validmap, vgroup_tot, subset_count, offset, gain);
+ MEM_freeN((void *)vgroup_validmap);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_levels(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Vertex Group Levels";
- ot->idname = "OBJECT_OT_vertex_group_levels";
- ot->description = "Add some offset and multiply with some gain the weights of the active vertex group";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_levels_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- vgroup_operator_subset_select_props(ot, true);
- RNA_def_float(ot->srna, "offset", 0.f, -1.0, 1.0, "Offset", "Value to add to weights", -1.0f, 1.f);
- RNA_def_float(ot->srna, "gain", 1.f, 0.f, FLT_MAX, "Gain", "Value to multiply weights by", 0.0f, 10.f);
+ /* identifiers */
+ ot->name = "Vertex Group Levels";
+ ot->idname = "OBJECT_OT_vertex_group_levels";
+ ot->description =
+ "Add some offset and multiply with some gain the weights of the active vertex group";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_levels_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ vgroup_operator_subset_select_props(ot, true);
+ RNA_def_float(
+ ot->srna, "offset", 0.f, -1.0, 1.0, "Offset", "Value to add to weights", -1.0f, 1.f);
+ RNA_def_float(
+ ot->srna, "gain", 1.f, 0.f, FLT_MAX, "Gain", "Value to multiply weights by", 0.0f, 10.f);
}
static int vertex_group_normalize_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- bool changed;
+ Object *ob = ED_object_context(C);
+ bool changed;
- changed = vgroup_normalize(ob);
+ changed = vgroup_normalize(ob);
- if (changed) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ if (changed) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void OBJECT_OT_vertex_group_normalize(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Normalize Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_normalize";
- ot->description = "Normalize weights of the active vertex group, so that the highest ones are now 1.0";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_normalize_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Normalize Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_normalize";
+ ot->description =
+ "Normalize weights of the active vertex group, so that the highest ones are now 1.0";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_normalize_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- bool lock_active = RNA_boolean_get(op->ptr, "lock_active");
- eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
- bool changed;
- int subset_count, vgroup_tot;
- const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
-
- changed = vgroup_normalize_all(ob, vgroup_validmap, vgroup_tot, subset_count, lock_active, op->reports);
- MEM_freeN((void *)vgroup_validmap);
-
- if (changed) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
-
- return OPERATOR_FINISHED;
- }
- else {
- /* allow to adjust settings */
- return OPERATOR_FINISHED;
- }
+ Object *ob = ED_object_context(C);
+ bool lock_active = RNA_boolean_get(op->ptr, "lock_active");
+ eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
+ bool changed;
+ int subset_count, vgroup_tot;
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
+ ob, subset_type, &vgroup_tot, &subset_count);
+
+ changed = vgroup_normalize_all(
+ ob, vgroup_validmap, vgroup_tot, subset_count, lock_active, op->reports);
+ MEM_freeN((void *)vgroup_validmap);
+
+ if (changed) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ /* allow to adjust settings */
+ return OPERATOR_FINISHED;
+ }
}
void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Normalize All Vertex Groups";
- ot->idname = "OBJECT_OT_vertex_group_normalize_all";
- ot->description = "Normalize all weights of all vertex groups, "
- "so that for each vertex, the sum of all weights is 1.0";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_normalize_all_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- vgroup_operator_subset_select_props(ot, false);
- RNA_def_boolean(ot->srna, "lock_active", true, "Lock Active",
- "Keep the values of the active group while normalizing others");
+ /* identifiers */
+ ot->name = "Normalize All Vertex Groups";
+ ot->idname = "OBJECT_OT_vertex_group_normalize_all";
+ ot->description =
+ "Normalize all weights of all vertex groups, "
+ "so that for each vertex, the sum of all weights is 1.0";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_normalize_all_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ vgroup_operator_subset_select_props(ot, false);
+ RNA_def_boolean(ot->srna,
+ "lock_active",
+ true,
+ "Lock Active",
+ "Keep the values of the active group while normalizing others");
}
static int vertex_group_fix_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
- Scene *scene = CTX_data_scene(C);
-
- float distToBe = RNA_float_get(op->ptr, "dist");
- float strength = RNA_float_get(op->ptr, "strength");
- float cp = RNA_float_get(op->ptr, "accuracy");
- ModifierData *md = ob->modifiers.first;
-
- while (md) {
- if (md->type == eModifierType_Mirror && (md->mode & eModifierMode_Realtime)) {
- break;
- }
- md = md->next;
- }
-
- if (md && md->type == eModifierType_Mirror) {
- BKE_report(op->reports, RPT_ERROR_INVALID_CONTEXT, "This operator does not support an active mirror modifier");
- return OPERATOR_CANCELLED;
- }
- vgroup_fix(C, scene, ob, distToBe, strength, cp);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
-
- return OPERATOR_FINISHED;
+ Object *ob = CTX_data_active_object(C);
+ Scene *scene = CTX_data_scene(C);
+
+ float distToBe = RNA_float_get(op->ptr, "dist");
+ float strength = RNA_float_get(op->ptr, "strength");
+ float cp = RNA_float_get(op->ptr, "accuracy");
+ ModifierData *md = ob->modifiers.first;
+
+ while (md) {
+ if (md->type == eModifierType_Mirror && (md->mode & eModifierMode_Realtime)) {
+ break;
+ }
+ md = md->next;
+ }
+
+ if (md && md->type == eModifierType_Mirror) {
+ BKE_report(op->reports,
+ RPT_ERROR_INVALID_CONTEXT,
+ "This operator does not support an active mirror modifier");
+ return OPERATOR_CANCELLED;
+ }
+ vgroup_fix(C, scene, ob, distToBe, strength, cp);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_fix(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Fix Vertex Group Deform";
- ot->idname = "OBJECT_OT_vertex_group_fix";
- ot->description = "Modify the position of selected vertices by changing only their respective "
- "groups' weights (this tool may be slow for many vertices)";
-
- /* api callbacks */
- ot->poll = vertex_group_mesh_poll;
- ot->exec = vertex_group_fix_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_float(ot->srna, "dist", 0.0f, -FLT_MAX, FLT_MAX, "Distance", "The distance to move to", -10.0f, 10.0f);
- RNA_def_float(ot->srna, "strength", 1.f, -2.0f, FLT_MAX, "Strength",
- "The distance moved can be changed by this multiplier", -2.0f, 2.0f);
- RNA_def_float(ot->srna, "accuracy", 1.0f, 0.05f, FLT_MAX, "Change Sensitivity",
- "Change the amount weights are altered with each iteration: lower values are slower", 0.05f, 1.f);
+ /* identifiers */
+ ot->name = "Fix Vertex Group Deform";
+ ot->idname = "OBJECT_OT_vertex_group_fix";
+ ot->description =
+ "Modify the position of selected vertices by changing only their respective "
+ "groups' weights (this tool may be slow for many vertices)";
+
+ /* api callbacks */
+ ot->poll = vertex_group_mesh_poll;
+ ot->exec = vertex_group_fix_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ RNA_def_float(ot->srna,
+ "dist",
+ 0.0f,
+ -FLT_MAX,
+ FLT_MAX,
+ "Distance",
+ "The distance to move to",
+ -10.0f,
+ 10.0f);
+ RNA_def_float(ot->srna,
+ "strength",
+ 1.f,
+ -2.0f,
+ FLT_MAX,
+ "Strength",
+ "The distance moved can be changed by this multiplier",
+ -2.0f,
+ 2.0f);
+ RNA_def_float(
+ ot->srna,
+ "accuracy",
+ 1.0f,
+ 0.05f,
+ FLT_MAX,
+ "Change Sensitivity",
+ "Change the amount weights are altered with each iteration: lower values are slower",
+ 0.05f,
+ 1.f);
}
-
static int vertex_group_lock_exec(bContext *C, wmOperator *op)
{
- Object *ob = CTX_data_active_object(C);
+ Object *ob = CTX_data_active_object(C);
- int action = RNA_enum_get(op->ptr, "action");
+ int action = RNA_enum_get(op->ptr, "action");
- vgroup_lock_all(ob, action);
+ vgroup_lock_all(ob, action);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_lock(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Change the Lock On Vertex Groups";
- ot->idname = "OBJECT_OT_vertex_group_lock";
- ot->description = "Change the lock state of all vertex groups of active object";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_lock_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_enum(ot->srna, "action", vgroup_lock_actions, VGROUP_TOGGLE, "Action",
- "Lock action to execute on vertex groups");
+ /* identifiers */
+ ot->name = "Change the Lock On Vertex Groups";
+ ot->idname = "OBJECT_OT_vertex_group_lock";
+ ot->description = "Change the lock state of all vertex groups of active object";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_lock_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna,
+ "action",
+ vgroup_lock_actions,
+ VGROUP_TOGGLE,
+ "Action",
+ "Lock action to execute on vertex groups");
}
static int vertex_group_invert_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- bool auto_assign = RNA_boolean_get(op->ptr, "auto_assign");
- bool auto_remove = RNA_boolean_get(op->ptr, "auto_remove");
+ Object *ob = ED_object_context(C);
+ bool auto_assign = RNA_boolean_get(op->ptr, "auto_assign");
+ bool auto_remove = RNA_boolean_get(op->ptr, "auto_remove");
- eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
+ eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
- int subset_count, vgroup_tot;
+ int subset_count, vgroup_tot;
- const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
- vgroup_invert_subset(ob, vgroup_validmap, vgroup_tot, subset_count, auto_assign, auto_remove);
- MEM_freeN((void *)vgroup_validmap);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
+ ob, subset_type, &vgroup_tot, &subset_count);
+ vgroup_invert_subset(ob, vgroup_validmap, vgroup_tot, subset_count, auto_assign, auto_remove);
+ MEM_freeN((void *)vgroup_validmap);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_invert(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Invert Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_invert";
- ot->description = "Invert active vertex group's weights";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_invert_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- vgroup_operator_subset_select_props(ot, true);
- RNA_def_boolean(ot->srna, "auto_assign", true, "Add Weights",
- "Add verts from groups that have zero weight before inverting");
- RNA_def_boolean(ot->srna, "auto_remove", true, "Remove Weights",
- "Remove verts from groups that have zero weight after inverting");
+ /* identifiers */
+ ot->name = "Invert Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_invert";
+ ot->description = "Invert active vertex group's weights";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_invert_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ vgroup_operator_subset_select_props(ot, true);
+ RNA_def_boolean(ot->srna,
+ "auto_assign",
+ true,
+ "Add Weights",
+ "Add verts from groups that have zero weight before inverting");
+ RNA_def_boolean(ot->srna,
+ "auto_remove",
+ true,
+ "Remove Weights",
+ "Remove verts from groups that have zero weight after inverting");
}
static int vertex_group_smooth_exec(bContext *C, wmOperator *op)
{
- const float fac = RNA_float_get(op->ptr, "factor");
- const int repeat = RNA_int_get(op->ptr, "repeat");
- eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
- const float fac_expand = RNA_float_get(op->ptr, "expand");
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *ob_ctx = ED_object_context(C);
-
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len,
- ob_ctx->mode);
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob = objects[ob_index];
-
- int subset_count, vgroup_tot;
-
- const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob,
- subset_type,
- &vgroup_tot,
- &subset_count);
-
- vgroup_smooth_subset(ob, vgroup_validmap, vgroup_tot, subset_count, fac, repeat, fac_expand);
- MEM_freeN((void *)vgroup_validmap);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- }
- MEM_freeN(objects);
-
- return OPERATOR_FINISHED;
+ const float fac = RNA_float_get(op->ptr, "factor");
+ const int repeat = RNA_int_get(op->ptr, "repeat");
+ eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
+ const float fac_expand = RNA_float_get(op->ptr, "expand");
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob_ctx = ED_object_context(C);
+
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len, ob_ctx->mode);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *ob = objects[ob_index];
+
+ int subset_count, vgroup_tot;
+
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
+ ob, subset_type, &vgroup_tot, &subset_count);
+
+ vgroup_smooth_subset(ob, vgroup_validmap, vgroup_tot, subset_count, fac, repeat, fac_expand);
+ MEM_freeN((void *)vgroup_validmap);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ }
+ MEM_freeN(objects);
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_smooth(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Smooth Vertex Weights";
- ot->idname = "OBJECT_OT_vertex_group_smooth";
- ot->description = "Smooth weights for selected vertices";
-
- /* api callbacks */
- ot->poll = vertex_group_mesh_vert_poll;
- ot->exec = vertex_group_smooth_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- vgroup_operator_subset_select_props(ot, true);
- RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0, "Factor", "", 0.0f, 1.0f);
- RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200);
-
- RNA_def_float(ot->srna, "expand", 0.0f, -1.0f, 1.0, "Expand/Contract", "Expand/contract weights", -1.0f, 1.0f);
+ /* identifiers */
+ ot->name = "Smooth Vertex Weights";
+ ot->idname = "OBJECT_OT_vertex_group_smooth";
+ ot->description = "Smooth weights for selected vertices";
+
+ /* api callbacks */
+ ot->poll = vertex_group_mesh_vert_poll;
+ ot->exec = vertex_group_smooth_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ vgroup_operator_subset_select_props(ot, true);
+ RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0, "Factor", "", 0.0f, 1.0f);
+ RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200);
+
+ RNA_def_float(ot->srna,
+ "expand",
+ 0.0f,
+ -1.0f,
+ 1.0,
+ "Expand/Contract",
+ "Expand/contract weights",
+ -1.0f,
+ 1.0f);
}
static int vertex_group_clean_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- float limit = RNA_float_get(op->ptr, "limit");
- bool keep_single = RNA_boolean_get(op->ptr, "keep_single");
- eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
+ float limit = RNA_float_get(op->ptr, "limit");
+ bool keep_single = RNA_boolean_get(op->ptr, "keep_single");
+ eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
- int subset_count, vgroup_tot;
+ int subset_count, vgroup_tot;
- const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
- vgroup_clean_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit, keep_single);
- MEM_freeN((void *)vgroup_validmap);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
+ ob, subset_type, &vgroup_tot, &subset_count);
+ vgroup_clean_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit, keep_single);
+ MEM_freeN((void *)vgroup_validmap);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_clean(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Clean Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_clean";
- ot->description = "Remove vertex group assignments which are not required";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_clean_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- vgroup_operator_subset_select_props(ot, true);
- RNA_def_float(ot->srna, "limit", 0.0f, 0.0f, 1.0, "Limit",
- "Remove vertices which weight is below or equal to this limit", 0.0f, 0.99f);
- RNA_def_boolean(ot->srna, "keep_single", false, "Keep Single",
- "Keep verts assigned to at least one group when cleaning");
+ /* identifiers */
+ ot->name = "Clean Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_clean";
+ ot->description = "Remove vertex group assignments which are not required";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_clean_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ vgroup_operator_subset_select_props(ot, true);
+ RNA_def_float(ot->srna,
+ "limit",
+ 0.0f,
+ 0.0f,
+ 1.0,
+ "Limit",
+ "Remove vertices which weight is below or equal to this limit",
+ 0.0f,
+ 0.99f);
+ RNA_def_boolean(ot->srna,
+ "keep_single",
+ false,
+ "Keep Single",
+ "Keep verts assigned to at least one group when cleaning");
}
static int vertex_group_quantize_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- const int steps = RNA_int_get(op->ptr, "steps");
- eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
+ const int steps = RNA_int_get(op->ptr, "steps");
+ eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
- int subset_count, vgroup_tot;
+ int subset_count, vgroup_tot;
- const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
- vgroup_quantize_subset(ob, vgroup_validmap, vgroup_tot, subset_count, steps);
- MEM_freeN((void *)vgroup_validmap);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
+ ob, subset_type, &vgroup_tot, &subset_count);
+ vgroup_quantize_subset(ob, vgroup_validmap, vgroup_tot, subset_count, steps);
+ MEM_freeN((void *)vgroup_validmap);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_quantize(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Quantize Vertex Weights";
- ot->idname = "OBJECT_OT_vertex_group_quantize";
- ot->description = "Set weights to a fixed number of steps";
+ /* identifiers */
+ ot->name = "Quantize Vertex Weights";
+ ot->idname = "OBJECT_OT_vertex_group_quantize";
+ ot->description = "Set weights to a fixed number of steps";
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_quantize_exec;
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_quantize_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- vgroup_operator_subset_select_props(ot, true);
- RNA_def_int(ot->srna, "steps", 4, 1, 1000, "Steps", "Number of steps between 0 and 1", 1, 100);
+ vgroup_operator_subset_select_props(ot, true);
+ RNA_def_int(ot->srna, "steps", 4, 1, 1000, "Steps", "Number of steps between 0 and 1", 1, 100);
}
static int vertex_group_limit_total_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
+ Object *ob = ED_object_context(C);
- const int limit = RNA_int_get(op->ptr, "limit");
- eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
+ const int limit = RNA_int_get(op->ptr, "limit");
+ eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode");
- int subset_count, vgroup_tot;
+ int subset_count, vgroup_tot;
- const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count);
- int remove_tot = vgroup_limit_total_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit);
- MEM_freeN((void *)vgroup_validmap);
+ const bool *vgroup_validmap = BKE_object_defgroup_subset_from_select_type(
+ ob, subset_type, &vgroup_tot, &subset_count);
+ int remove_tot = vgroup_limit_total_subset(ob, vgroup_validmap, vgroup_tot, subset_count, limit);
+ MEM_freeN((void *)vgroup_validmap);
- BKE_reportf(op->reports, remove_tot ? RPT_INFO : RPT_WARNING, "%d vertex weights limited", remove_tot);
+ BKE_reportf(
+ op->reports, remove_tot ? RPT_INFO : RPT_WARNING, "%d vertex weights limited", remove_tot);
- if (remove_tot) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ if (remove_tot) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- return OPERATOR_FINISHED;
- }
- else {
- /* note, would normally return canceled, except we want the redo
- * UI to show up for users to change */
- return OPERATOR_FINISHED;
- }
+ return OPERATOR_FINISHED;
+ }
+ else {
+ /* note, would normally return canceled, except we want the redo
+ * UI to show up for users to change */
+ return OPERATOR_FINISHED;
+ }
}
void OBJECT_OT_vertex_group_limit_total(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Limit Number of Weights per Vertex";
- ot->idname = "OBJECT_OT_vertex_group_limit_total";
- ot->description = "Limit deform weights associated with a vertex to a specified number by removing lowest weights";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_limit_total_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- vgroup_operator_subset_select_props(ot, false);
- RNA_def_int(ot->srna, "limit", 4, 1, 32, "Limit", "Maximum number of deform weights", 1, 32);
+ /* identifiers */
+ ot->name = "Limit Number of Weights per Vertex";
+ ot->idname = "OBJECT_OT_vertex_group_limit_total";
+ ot->description =
+ "Limit deform weights associated with a vertex to a specified number by removing lowest "
+ "weights";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_limit_total_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ vgroup_operator_subset_select_props(ot, false);
+ RNA_def_int(ot->srna, "limit", 4, 1, 32, "Limit", "Maximum number of deform weights", 1, 32);
}
static int vertex_group_mirror_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- int totmirr = 0, totfail = 0;
+ Object *ob = ED_object_context(C);
+ int totmirr = 0, totfail = 0;
- ED_vgroup_mirror(
- ob,
- RNA_boolean_get(op->ptr, "mirror_weights"),
- RNA_boolean_get(op->ptr, "flip_group_names"),
- RNA_boolean_get(op->ptr, "all_groups"),
- RNA_boolean_get(op->ptr, "use_topology"),
- &totmirr, &totfail);
+ ED_vgroup_mirror(ob,
+ RNA_boolean_get(op->ptr, "mirror_weights"),
+ RNA_boolean_get(op->ptr, "flip_group_names"),
+ RNA_boolean_get(op->ptr, "all_groups"),
+ RNA_boolean_get(op->ptr, "use_topology"),
+ &totmirr,
+ &totfail);
- ED_mesh_report_mirror(op, totmirr, totfail);
+ ED_mesh_report_mirror(op, totmirr, totfail);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Mirror Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_mirror";
- ot->description = "Mirror vertex group, flip weights and/or names, editing only selected vertices, "
- "flipping when both sides are selected otherwise copy from unselected";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_mirror_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean(ot->srna, "mirror_weights", true, "Mirror Weights", "Mirror weights");
- RNA_def_boolean(ot->srna, "flip_group_names", true, "Flip Group Names", "Flip vertex group names");
- RNA_def_boolean(ot->srna, "all_groups", false, "All Groups", "Mirror all vertex groups weights");
- RNA_def_boolean(ot->srna, "use_topology", 0, "Topology Mirror",
- "Use topology based mirroring (for when both sides of mesh have matching, unique topology)");
+ /* identifiers */
+ ot->name = "Mirror Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_mirror";
+ ot->description =
+ "Mirror vertex group, flip weights and/or names, editing only selected vertices, "
+ "flipping when both sides are selected otherwise copy from unselected";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_mirror_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "mirror_weights", true, "Mirror Weights", "Mirror weights");
+ RNA_def_boolean(
+ ot->srna, "flip_group_names", true, "Flip Group Names", "Flip vertex group names");
+ RNA_def_boolean(ot->srna, "all_groups", false, "All Groups", "Mirror all vertex groups weights");
+ RNA_def_boolean(
+ ot->srna,
+ "use_topology",
+ 0,
+ "Topology Mirror",
+ "Use topology based mirroring (for when both sides of mesh have matching, unique topology)");
}
static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
- Object *ob_active = ED_object_context(C);
- int retval = OPERATOR_CANCELLED;
-
- FOREACH_SCENE_OBJECT_BEGIN(scene, ob_iter)
- {
- if (ob_iter->type == ob_active->type) {
- if (ob_iter != ob_active && ob_iter->data == ob_active->data) {
- BLI_freelistN(&ob_iter->defbase);
- BLI_duplicatelist(&ob_iter->defbase, &ob_active->defbase);
- ob_iter->actdef = ob_active->actdef;
-
- DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter);
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob_iter->data);
-
- retval = OPERATOR_FINISHED;
- }
- }
- }
- FOREACH_SCENE_OBJECT_END;
-
- return retval;
+ Scene *scene = CTX_data_scene(C);
+ Object *ob_active = ED_object_context(C);
+ int retval = OPERATOR_CANCELLED;
+
+ FOREACH_SCENE_OBJECT_BEGIN (scene, ob_iter) {
+ if (ob_iter->type == ob_active->type) {
+ if (ob_iter != ob_active && ob_iter->data == ob_active->data) {
+ BLI_freelistN(&ob_iter->defbase);
+ BLI_duplicatelist(&ob_iter->defbase, &ob_active->defbase);
+ ob_iter->actdef = ob_active->actdef;
+
+ DEG_id_tag_update(&ob_iter->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob_iter->data);
+
+ retval = OPERATOR_FINISHED;
+ }
+ }
+ }
+ FOREACH_SCENE_OBJECT_END;
+
+ return retval;
}
void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Vertex Groups to Linked";
- ot->idname = "OBJECT_OT_vertex_group_copy_to_linked";
- ot->description = "Replace vertex groups of all users of the same geometry data by vertex groups of active object";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_copy_to_linked_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* identifiers */
+ ot->name = "Copy Vertex Groups to Linked";
+ ot->idname = "OBJECT_OT_vertex_group_copy_to_linked";
+ ot->description =
+ "Replace vertex groups of all users of the same geometry data by vertex groups of active "
+ "object";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_copy_to_linked_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op)
{
- Object *obact = ED_object_context(C);
- int changed_tot = 0;
- int fail = 0;
-
- CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
- {
- if (obact != ob) {
- if (ED_vgroup_array_copy(ob, obact)) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
- changed_tot++;
- }
- else {
- fail++;
- }
- }
- }
- CTX_DATA_END;
-
- if ((changed_tot == 0 && fail == 0) || fail) {
- BKE_reportf(op->reports, RPT_ERROR,
- "Copy vertex groups to selected: %d done, %d failed (object data must have matching indices)",
- changed_tot, fail);
- }
-
- return OPERATOR_FINISHED;
+ Object *obact = ED_object_context(C);
+ int changed_tot = 0;
+ int fail = 0;
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) {
+ if (obact != ob) {
+ if (ED_vgroup_array_copy(ob, obact)) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
+ changed_tot++;
+ }
+ else {
+ fail++;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ if ((changed_tot == 0 && fail == 0) || fail) {
+ BKE_reportf(op->reports,
+ RPT_ERROR,
+ "Copy vertex groups to selected: %d done, %d failed (object data must have "
+ "matching indices)",
+ changed_tot,
+ fail);
+ }
+
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_copy_to_selected(wmOperatorType *ot)
{
- /* identifiers */
- ot->name = "Copy Vertex Group to Selected";
- ot->idname = "OBJECT_OT_vertex_group_copy_to_selected";
- ot->description = "Replace vertex groups of selected objects by vertex groups of active object";
+ /* identifiers */
+ ot->name = "Copy Vertex Group to Selected";
+ ot->idname = "OBJECT_OT_vertex_group_copy_to_selected";
+ ot->description = "Replace vertex groups of selected objects by vertex groups of active object";
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_copy_to_selected_exec;
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_copy_to_selected_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int set_active_group_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- int nr = RNA_enum_get(op->ptr, "group");
+ Object *ob = ED_object_context(C);
+ int nr = RNA_enum_get(op->ptr, "group");
- BLI_assert(nr + 1 >= 0);
- ob->actdef = nr + 1;
+ BLI_assert(nr + 1 >= 0);
+ ob->actdef = nr + 1;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
-static const EnumPropertyItem *vgroup_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+static const EnumPropertyItem *vgroup_itemf(bContext *C,
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
{
- Object *ob = ED_object_context(C);
- EnumPropertyItem tmp = {0, "", 0, "", ""};
- EnumPropertyItem *item = NULL;
- bDeformGroup *def;
- int a, totitem = 0;
-
- if (!ob)
- return DummyRNA_NULL_items;
-
- for (a = 0, def = ob->defbase.first; def; def = def->next, a++) {
- tmp.value = a;
- tmp.icon = ICON_GROUP_VERTEX;
- tmp.identifier = def->name;
- tmp.name = def->name;
- RNA_enum_item_add(&item, &totitem, &tmp);
- }
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
-
- return item;
+ Object *ob = ED_object_context(C);
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ EnumPropertyItem *item = NULL;
+ bDeformGroup *def;
+ int a, totitem = 0;
+
+ if (!ob)
+ return DummyRNA_NULL_items;
+
+ for (a = 0, def = ob->defbase.first; def; def = def->next, a++) {
+ tmp.value = a;
+ tmp.icon = ICON_GROUP_VERTEX;
+ tmp.identifier = def->name;
+ tmp.name = def->name;
+ RNA_enum_item_add(&item, &totitem, &tmp);
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
}
void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Set Active Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_set_active";
- ot->description = "Set the active vertex group";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = set_active_group_exec;
- ot->invoke = WM_menu_invoke;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "Vertex group to set as active");
- RNA_def_enum_funcs(prop, vgroup_itemf);
- RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
- ot->prop = prop;
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Set Active Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_set_active";
+ ot->description = "Set the active vertex group";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = set_active_group_exec;
+ ot->invoke = WM_menu_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(
+ ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "Vertex group to set as active");
+ RNA_def_enum_funcs(prop, vgroup_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
/* 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)
{
- bDeformGroup *def;
- int defbase_tot = BLI_listbase_count(&ob->defbase);
- char *name_array = MEM_mallocN(MAX_VGROUP_NAME * sizeof(char) * defbase_tot, "sort vgroups");
- char *name;
-
- name = name_array;
- for (def = ob->defbase.first; def; def = def->next) {
- BLI_strncpy(name, def->name, MAX_VGROUP_NAME);
- name += MAX_VGROUP_NAME;
- }
-
- return name_array;
+ bDeformGroup *def;
+ int defbase_tot = BLI_listbase_count(&ob->defbase);
+ char *name_array = MEM_mallocN(MAX_VGROUP_NAME * sizeof(char) * defbase_tot, "sort vgroups");
+ char *name;
+
+ name = name_array;
+ for (def = ob->defbase.first; def; def = def->next) {
+ BLI_strncpy(name, def->name, MAX_VGROUP_NAME);
+ name += MAX_VGROUP_NAME;
+ }
+
+ return name_array;
}
static int vgroup_do_remap(Object *ob, const char *name_array, wmOperator *op)
{
- MDeformVert *dvert = NULL;
- bDeformGroup *def;
- int defbase_tot = BLI_listbase_count(&ob->defbase);
-
- /* needs a dummy index at the start*/
- int *sort_map_update = MEM_mallocN(sizeof(int) * (defbase_tot + 1), "sort vgroups");
- int *sort_map = sort_map_update + 1;
-
- const char *name;
- int i;
-
- name = name_array;
- for (def = ob->defbase.first, i = 0; def; def = def->next, i++) {
- sort_map[i] = BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name));
- name += MAX_VGROUP_NAME;
-
- BLI_assert(sort_map[i] != -1);
- }
-
- if (ob->mode == OB_MODE_EDIT) {
- if (ob->type == OB_MESH) {
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
-
- if (cd_dvert_offset != -1) {
- BMIter iter;
- BMVert *eve;
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
- if (dvert->totweight) {
- defvert_remap(dvert, sort_map, defbase_tot);
- }
- }
- }
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Editmode lattice is not supported yet");
- MEM_freeN(sort_map_update);
- return OPERATOR_CANCELLED;
- }
- }
- else {
- int dvert_tot = 0;
-
- BKE_object_defgroup_array_get(ob->data, &dvert, &dvert_tot);
-
- /*create as necessary*/
- if (dvert) {
- while (dvert_tot--) {
- if (dvert->totweight)
- defvert_remap(dvert, sort_map, defbase_tot);
- dvert++;
- }
- }
- }
-
- /* update users */
- for (i = 0; i < defbase_tot; i++)
- sort_map[i]++;
-
- sort_map_update[0] = 0;
- BKE_object_defgroup_remap_update_users(ob, sort_map_update);
-
- BLI_assert(sort_map_update[ob->actdef] >= 0);
- ob->actdef = sort_map_update[ob->actdef];
-
- MEM_freeN(sort_map_update);
-
- return OPERATOR_FINISHED;
+ MDeformVert *dvert = NULL;
+ bDeformGroup *def;
+ int defbase_tot = BLI_listbase_count(&ob->defbase);
+
+ /* needs a dummy index at the start*/
+ int *sort_map_update = MEM_mallocN(sizeof(int) * (defbase_tot + 1), "sort vgroups");
+ int *sort_map = sort_map_update + 1;
+
+ const char *name;
+ int i;
+
+ name = name_array;
+ for (def = ob->defbase.first, i = 0; def; def = def->next, i++) {
+ sort_map[i] = BLI_findstringindex(&ob->defbase, name, offsetof(bDeformGroup, name));
+ name += MAX_VGROUP_NAME;
+
+ BLI_assert(sort_map[i] != -1);
+ }
+
+ if (ob->mode == OB_MODE_EDIT) {
+ if (ob->type == OB_MESH) {
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+
+ if (cd_dvert_offset != -1) {
+ BMIter iter;
+ BMVert *eve;
+
+ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
+ dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+ if (dvert->totweight) {
+ defvert_remap(dvert, sort_map, defbase_tot);
+ }
+ }
+ }
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Editmode lattice is not supported yet");
+ MEM_freeN(sort_map_update);
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ int dvert_tot = 0;
+
+ BKE_object_defgroup_array_get(ob->data, &dvert, &dvert_tot);
+
+ /*create as necessary*/
+ if (dvert) {
+ while (dvert_tot--) {
+ if (dvert->totweight)
+ defvert_remap(dvert, sort_map, defbase_tot);
+ dvert++;
+ }
+ }
+ }
+
+ /* update users */
+ for (i = 0; i < defbase_tot; i++)
+ sort_map[i]++;
+
+ sort_map_update[0] = 0;
+ BKE_object_defgroup_remap_update_users(ob, sort_map_update);
+
+ BLI_assert(sort_map_update[ob->actdef] >= 0);
+ ob->actdef = sort_map_update[ob->actdef];
+
+ MEM_freeN(sort_map_update);
+
+ return OPERATOR_FINISHED;
}
static int vgroup_sort_name(const void *def_a_ptr, const void *def_b_ptr)
{
- const bDeformGroup *def_a = def_a_ptr;
- const bDeformGroup *def_b = def_b_ptr;
+ const bDeformGroup *def_a = def_a_ptr;
+ const bDeformGroup *def_b = def_b_ptr;
- return BLI_natstrcmp(def_a->name, def_b->name);
+ return BLI_natstrcmp(def_a->name, def_b->name);
}
/**
@@ -3599,395 +3719,423 @@ static int vgroup_sort_name(const void *def_a_ptr, const void *def_b_ptr)
*/
static void vgroup_sort_bone_hierarchy(Object *ob, ListBase *bonebase)
{
- if (bonebase == NULL) {
- Object *armobj = modifiers_isDeformedByArmature(ob);
- if (armobj != NULL) {
- bArmature *armature = armobj->data;
- bonebase = &armature->bonebase;
- }
- }
-
- if (bonebase != NULL) {
- Bone *bone;
- for (bone = bonebase->last; bone; bone = bone->prev) {
- bDeformGroup *dg = defgroup_find_name(ob, bone->name);
- vgroup_sort_bone_hierarchy(ob, &bone->childbase);
-
- if (dg != NULL) {
- BLI_remlink(&ob->defbase, dg);
- BLI_addhead(&ob->defbase, dg);
- }
- }
- }
-
- return;
+ if (bonebase == NULL) {
+ Object *armobj = modifiers_isDeformedByArmature(ob);
+ if (armobj != NULL) {
+ bArmature *armature = armobj->data;
+ bonebase = &armature->bonebase;
+ }
+ }
+
+ if (bonebase != NULL) {
+ Bone *bone;
+ for (bone = bonebase->last; bone; bone = bone->prev) {
+ bDeformGroup *dg = defgroup_find_name(ob, bone->name);
+ vgroup_sort_bone_hierarchy(ob, &bone->childbase);
+
+ if (dg != NULL) {
+ BLI_remlink(&ob->defbase, dg);
+ BLI_addhead(&ob->defbase, dg);
+ }
+ }
+ }
+
+ return;
}
enum {
- SORT_TYPE_NAME = 0,
- SORT_TYPE_BONEHIERARCHY = 1,
+ SORT_TYPE_NAME = 0,
+ SORT_TYPE_BONEHIERARCHY = 1,
};
static int vertex_group_sort_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- char *name_array;
- int ret;
- int sort_type = RNA_enum_get(op->ptr, "sort_type");
-
- /*init remapping*/
- name_array = vgroup_init_remap(ob);
-
- /*sort vgroup names*/
- switch (sort_type) {
- case SORT_TYPE_NAME:
- BLI_listbase_sort(&ob->defbase, vgroup_sort_name);
- break;
- case SORT_TYPE_BONEHIERARCHY:
- vgroup_sort_bone_hierarchy(ob, NULL);
- break;
- }
-
- /*remap vgroup data to map to correct names*/
- ret = vgroup_do_remap(ob, name_array, op);
-
- if (ret != OPERATOR_CANCELLED) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
- }
-
- if (name_array) MEM_freeN(name_array);
-
- return ret;
+ Object *ob = ED_object_context(C);
+ char *name_array;
+ int ret;
+ int sort_type = RNA_enum_get(op->ptr, "sort_type");
+
+ /*init remapping*/
+ name_array = vgroup_init_remap(ob);
+
+ /*sort vgroup names*/
+ switch (sort_type) {
+ case SORT_TYPE_NAME:
+ BLI_listbase_sort(&ob->defbase, vgroup_sort_name);
+ break;
+ case SORT_TYPE_BONEHIERARCHY:
+ vgroup_sort_bone_hierarchy(ob, NULL);
+ break;
+ }
+
+ /*remap vgroup data to map to correct names*/
+ ret = vgroup_do_remap(ob, name_array, op);
+
+ if (ret != OPERATOR_CANCELLED) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
+ }
+
+ if (name_array)
+ MEM_freeN(name_array);
+
+ return ret;
}
void OBJECT_OT_vertex_group_sort(wmOperatorType *ot)
{
- static const EnumPropertyItem vgroup_sort_type[] = {
- {SORT_TYPE_NAME, "NAME", 0, "Name", ""},
- {SORT_TYPE_BONEHIERARCHY, "BONE_HIERARCHY", 0, "Bone Hierarchy", ""},
- {0, NULL, 0, NULL, NULL},
- };
+ static const EnumPropertyItem vgroup_sort_type[] = {
+ {SORT_TYPE_NAME, "NAME", 0, "Name", ""},
+ {SORT_TYPE_BONEHIERARCHY, "BONE_HIERARCHY", 0, "Bone Hierarchy", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
- ot->name = "Sort Vertex Groups";
- ot->idname = "OBJECT_OT_vertex_group_sort";
- ot->description = "Sort vertex groups";
+ ot->name = "Sort Vertex Groups";
+ ot->idname = "OBJECT_OT_vertex_group_sort";
+ ot->description = "Sort vertex groups";
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vertex_group_sort_exec;
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vertex_group_sort_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_enum(ot->srna, "sort_type", vgroup_sort_type, SORT_TYPE_NAME, "Sort type", "Sort type");
+ RNA_def_enum(ot->srna, "sort_type", vgroup_sort_type, SORT_TYPE_NAME, "Sort type", "Sort type");
}
static int vgroup_move_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- bDeformGroup *def;
- char *name_array;
- int dir = RNA_enum_get(op->ptr, "direction");
- int ret = OPERATOR_FINISHED;
+ Object *ob = ED_object_context(C);
+ bDeformGroup *def;
+ char *name_array;
+ int dir = RNA_enum_get(op->ptr, "direction");
+ int ret = OPERATOR_FINISHED;
- def = BLI_findlink(&ob->defbase, ob->actdef - 1);
- if (!def) {
- return OPERATOR_CANCELLED;
- }
+ def = BLI_findlink(&ob->defbase, ob->actdef - 1);
+ if (!def) {
+ return OPERATOR_CANCELLED;
+ }
- name_array = vgroup_init_remap(ob);
+ name_array = vgroup_init_remap(ob);
- if (BLI_listbase_link_move(&ob->defbase, def, dir)) {
- ret = vgroup_do_remap(ob, name_array, op);
+ if (BLI_listbase_link_move(&ob->defbase, def, dir)) {
+ ret = vgroup_do_remap(ob, name_array, op);
- if (ret != OPERATOR_CANCELLED) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
- }
- }
+ if (ret != OPERATOR_CANCELLED) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
+ }
+ }
- if (name_array) MEM_freeN(name_array);
+ if (name_array)
+ MEM_freeN(name_array);
- return ret;
+ return ret;
}
void OBJECT_OT_vertex_group_move(wmOperatorType *ot)
{
- static const EnumPropertyItem vgroup_slot_move[] = {
- {-1, "UP", 0, "Up", ""},
- {1, "DOWN", 0, "Down", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- /* identifiers */
- ot->name = "Move Vertex Group";
- ot->idname = "OBJECT_OT_vertex_group_move";
- ot->description = "Move the active vertex group up/down in the list";
-
- /* api callbacks */
- ot->poll = vertex_group_poll;
- ot->exec = vgroup_move_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_enum(ot->srna, "direction", vgroup_slot_move, 0, "Direction",
- "Direction to move the active vertex group towards");
+ static const EnumPropertyItem vgroup_slot_move[] = {
+ {-1, "UP", 0, "Up", ""},
+ {1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Move Vertex Group";
+ ot->idname = "OBJECT_OT_vertex_group_move";
+ ot->description = "Move the active vertex group up/down in the list";
+
+ /* api callbacks */
+ ot->poll = vertex_group_poll;
+ ot->exec = vgroup_move_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna,
+ "direction",
+ vgroup_slot_move,
+ 0,
+ "Direction",
+ "Direction to move the active vertex group towards");
}
static void vgroup_copy_active_to_sel_single(Object *ob, const int def_nr)
{
- MDeformVert *dvert_act;
-
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- float weight_act;
- int i;
-
- if (em) {
- const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
- BMIter iter;
- BMVert *eve, *eve_act;
-
- dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
- if (dvert_act == NULL) {
- return;
- }
- weight_act = defvert_find_weight(dvert_act, def_nr);
-
- BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
- if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && (eve != eve_act)) {
- MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
- MDeformWeight *dw = defvert_find_index(dv, def_nr);
- if (dw) {
- dw->weight = weight_act;
-
- if (me->editflag & ME_EDIT_MIRROR_X) {
- ED_mesh_defvert_mirror_update_em(ob, eve, -1, i, cd_dvert_offset);
- }
- }
- }
- }
-
- if (me->editflag & ME_EDIT_MIRROR_X) {
- ED_mesh_defvert_mirror_update_em(ob, eve_act, -1, -1, cd_dvert_offset);
- }
- }
- else {
- MDeformVert *dv;
- int v_act;
-
- dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
- if (dvert_act == NULL) {
- return;
- }
- weight_act = defvert_find_weight(dvert_act, def_nr);
-
- dv = me->dvert;
- for (i = 0; i < me->totvert; i++, dv++) {
- if ((me->mvert[i].flag & SELECT) && (dv != dvert_act)) {
- MDeformWeight *dw = defvert_find_index(dv, def_nr);
- if (dw) {
- dw->weight = weight_act;
- if (me->editflag & ME_EDIT_MIRROR_X) {
- ED_mesh_defvert_mirror_update_ob(ob, -1, i);
- }
- }
- }
- }
-
- if (me->editflag & ME_EDIT_MIRROR_X) {
- ED_mesh_defvert_mirror_update_ob(ob, -1, v_act);
- }
- }
+ MDeformVert *dvert_act;
+
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ float weight_act;
+ int i;
+
+ if (em) {
+ const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
+ BMIter iter;
+ BMVert *eve, *eve_act;
+
+ dvert_act = ED_mesh_active_dvert_get_em(ob, &eve_act);
+ if (dvert_act == NULL) {
+ return;
+ }
+ weight_act = defvert_find_weight(dvert_act, def_nr);
+
+ BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
+ if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && (eve != eve_act)) {
+ MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+ MDeformWeight *dw = defvert_find_index(dv, def_nr);
+ if (dw) {
+ dw->weight = weight_act;
+
+ if (me->editflag & ME_EDIT_MIRROR_X) {
+ ED_mesh_defvert_mirror_update_em(ob, eve, -1, i, cd_dvert_offset);
+ }
+ }
+ }
+ }
+
+ if (me->editflag & ME_EDIT_MIRROR_X) {
+ ED_mesh_defvert_mirror_update_em(ob, eve_act, -1, -1, cd_dvert_offset);
+ }
+ }
+ else {
+ MDeformVert *dv;
+ int v_act;
+
+ dvert_act = ED_mesh_active_dvert_get_ob(ob, &v_act);
+ if (dvert_act == NULL) {
+ return;
+ }
+ weight_act = defvert_find_weight(dvert_act, def_nr);
+
+ dv = me->dvert;
+ for (i = 0; i < me->totvert; i++, dv++) {
+ if ((me->mvert[i].flag & SELECT) && (dv != dvert_act)) {
+ MDeformWeight *dw = defvert_find_index(dv, def_nr);
+ if (dw) {
+ dw->weight = weight_act;
+ if (me->editflag & ME_EDIT_MIRROR_X) {
+ ED_mesh_defvert_mirror_update_ob(ob, -1, i);
+ }
+ }
+ }
+ }
+
+ if (me->editflag & ME_EDIT_MIRROR_X) {
+ ED_mesh_defvert_mirror_update_ob(ob, -1, v_act);
+ }
+ }
}
static bool check_vertex_group_accessible(wmOperator *op, Object *ob, int def_nr)
{
- bDeformGroup *dg = BLI_findlink(&ob->defbase, def_nr);
+ bDeformGroup *dg = BLI_findlink(&ob->defbase, def_nr);
- if (!dg) {
- BKE_report(op->reports, RPT_ERROR, "Invalid vertex group index");
- return false;
- }
+ if (!dg) {
+ BKE_report(op->reports, RPT_ERROR, "Invalid vertex group index");
+ return false;
+ }
- if (dg->flag & DG_LOCK_WEIGHT) {
- BKE_report(op->reports, RPT_ERROR, "Vertex group is locked");
- return false;
- }
+ if (dg->flag & DG_LOCK_WEIGHT) {
+ BKE_report(op->reports, RPT_ERROR, "Vertex group is locked");
+ return false;
+ }
- return true;
+ return true;
}
static int vertex_weight_paste_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- const int def_nr = RNA_int_get(op->ptr, "weight_group");
+ Object *ob = ED_object_context(C);
+ const int def_nr = RNA_int_get(op->ptr, "weight_group");
- if (!check_vertex_group_accessible(op, ob, def_nr)) {
- return OPERATOR_CANCELLED;
- }
+ if (!check_vertex_group_accessible(op, ob, def_nr)) {
+ return OPERATOR_CANCELLED;
+ }
- vgroup_copy_active_to_sel_single(ob, def_nr);
+ vgroup_copy_active_to_sel_single(ob, def_nr);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_weight_paste(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- ot->name = "Paste Weight to Selected";
- ot->idname = "OBJECT_OT_vertex_weight_paste";
- ot->description = "Copy this group's weight to other selected verts (disabled if vertex group is locked)";
-
- /* api callbacks */
- ot->poll = vertex_group_vert_select_mesh_poll;
- ot->exec = vertex_weight_paste_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- prop = RNA_def_int(ot->srna, "weight_group", -1, -1, INT_MAX, "Weight Index",
- "Index of source weight in active vertex group", -1, INT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ PropertyRNA *prop;
+
+ ot->name = "Paste Weight to Selected";
+ ot->idname = "OBJECT_OT_vertex_weight_paste";
+ ot->description =
+ "Copy this group's weight to other selected verts (disabled if vertex group is locked)";
+
+ /* api callbacks */
+ ot->poll = vertex_group_vert_select_mesh_poll;
+ ot->exec = vertex_weight_paste_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_int(ot->srna,
+ "weight_group",
+ -1,
+ -1,
+ INT_MAX,
+ "Weight Index",
+ "Index of source weight in active vertex group",
+ -1,
+ INT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
}
static int vertex_weight_delete_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- const int def_nr = RNA_int_get(op->ptr, "weight_group");
+ Object *ob = ED_object_context(C);
+ const int def_nr = RNA_int_get(op->ptr, "weight_group");
- if (!check_vertex_group_accessible(op, ob, def_nr)) {
- return OPERATOR_CANCELLED;
- }
+ if (!check_vertex_group_accessible(op, ob, def_nr)) {
+ return OPERATOR_CANCELLED;
+ }
- vgroup_remove_weight(ob, def_nr);
+ vgroup_remove_weight(ob, def_nr);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_weight_delete(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- ot->name = "Delete Weight";
- ot->idname = "OBJECT_OT_vertex_weight_delete";
- ot->description = "Delete this weight from the vertex (disabled if vertex group is locked)";
-
- /* api callbacks */
- ot->poll = vertex_group_vert_select_mesh_poll;
- ot->exec = vertex_weight_delete_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- prop = RNA_def_int(ot->srna, "weight_group", -1, -1, INT_MAX, "Weight Index",
- "Index of source weight in active vertex group", -1, INT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ PropertyRNA *prop;
+
+ ot->name = "Delete Weight";
+ ot->idname = "OBJECT_OT_vertex_weight_delete";
+ ot->description = "Delete this weight from the vertex (disabled if vertex group is locked)";
+
+ /* api callbacks */
+ ot->poll = vertex_group_vert_select_mesh_poll;
+ ot->exec = vertex_weight_delete_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_int(ot->srna,
+ "weight_group",
+ -1,
+ -1,
+ INT_MAX,
+ "Weight Index",
+ "Index of source weight in active vertex group",
+ -1,
+ INT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
}
static int vertex_weight_set_active_exec(bContext *C, wmOperator *op)
{
- Object *ob = ED_object_context(C);
- const int wg_index = RNA_int_get(op->ptr, "weight_group");
+ Object *ob = ED_object_context(C);
+ const int wg_index = RNA_int_get(op->ptr, "weight_group");
- if (wg_index != -1) {
- ob->actdef = wg_index + 1;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- }
+ if (wg_index != -1) {
+ ob->actdef = wg_index + 1;
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_weight_set_active(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- ot->name = "Set Active Group";
- ot->idname = "OBJECT_OT_vertex_weight_set_active";
- ot->description = "Set as active vertex group";
-
- /* api callbacks */
- ot->poll = vertex_group_vert_select_mesh_poll;
- ot->exec = vertex_weight_set_active_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- prop = RNA_def_int(ot->srna, "weight_group", -1, -1, INT_MAX, "Weight Index",
- "Index of source weight in active vertex group", -1, INT_MAX);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ PropertyRNA *prop;
+
+ ot->name = "Set Active Group";
+ ot->idname = "OBJECT_OT_vertex_weight_set_active";
+ ot->description = "Set as active vertex group";
+
+ /* api callbacks */
+ ot->poll = vertex_group_vert_select_mesh_poll;
+ ot->exec = vertex_weight_set_active_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_int(ot->srna,
+ "weight_group",
+ -1,
+ -1,
+ INT_MAX,
+ "Weight Index",
+ "Index of source weight in active vertex group",
+ -1,
+ INT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
}
static int vertex_weight_normalize_active_vertex_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
- eVGroupSelect subset_type = ts->vgroupsubset;
- bool changed;
-
- changed = vgroup_normalize_active_vertex(ob, subset_type);
-
- if (changed) {
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
+ Object *ob = ED_object_context(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ eVGroupSelect subset_type = ts->vgroupsubset;
+ bool changed;
+
+ changed = vgroup_normalize_active_vertex(ob, subset_type);
+
+ if (changed) {
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void OBJECT_OT_vertex_weight_normalize_active_vertex(wmOperatorType *ot)
{
- ot->name = "Normalize Active";
- ot->idname = "OBJECT_OT_vertex_weight_normalize_active_vertex";
- ot->description = "Normalize active vertex's weights";
+ ot->name = "Normalize Active";
+ ot->idname = "OBJECT_OT_vertex_weight_normalize_active_vertex";
+ ot->description = "Normalize active vertex's weights";
- /* api callbacks */
- ot->poll = vertex_group_vert_select_mesh_poll;
- ot->exec = vertex_weight_normalize_active_vertex_exec;
+ /* api callbacks */
+ ot->poll = vertex_group_vert_select_mesh_poll;
+ ot->exec = vertex_weight_normalize_active_vertex_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int vertex_weight_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
- eVGroupSelect subset_type = ts->vgroupsubset;
+ Object *ob = ED_object_context(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ eVGroupSelect subset_type = ts->vgroupsubset;
- vgroup_copy_active_to_sel(ob, subset_type);
+ vgroup_copy_active_to_sel(ob, subset_type);
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_weight_copy(wmOperatorType *ot)
{
- ot->name = "Copy Active";
- ot->idname = "OBJECT_OT_vertex_weight_copy";
- ot->description = "Copy weights from active to selected";
+ ot->name = "Copy Active";
+ ot->idname = "OBJECT_OT_vertex_weight_copy";
+ ot->description = "Copy weights from active to selected";
- /* api callbacks */
- ot->poll = vertex_group_vert_select_mesh_poll;
- ot->exec = vertex_weight_copy_exec;
+ /* api callbacks */
+ ot->poll = vertex_group_vert_select_mesh_poll;
+ ot->exec = vertex_weight_copy_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
diff --git a/source/blender/editors/object/object_warp.c b/source/blender/editors/object/object_warp.c
index 753e29ca9a7..3a089acb330 100644
--- a/source/blender/editors/object/object_warp.c
+++ b/source/blender/editors/object/object_warp.c
@@ -40,264 +40,275 @@
#include "object_intern.h"
-
-static void object_warp_calc_view_matrix(float r_mat_view[4][4], float r_center_view[3],
- Object *obedit, float viewmat[4][4], const float center[3],
+static void object_warp_calc_view_matrix(float r_mat_view[4][4],
+ float r_center_view[3],
+ Object *obedit,
+ float viewmat[4][4],
+ const float center[3],
const float offset_angle)
{
- float mat_offset[4][4];
- float viewmat_roll[4][4];
+ float mat_offset[4][4];
+ float viewmat_roll[4][4];
- /* apply the rotation offset by rolling the view */
- axis_angle_to_mat4_single(mat_offset, 'Z', offset_angle);
- mul_m4_m4m4(viewmat_roll, mat_offset, viewmat);
+ /* apply the rotation offset by rolling the view */
+ axis_angle_to_mat4_single(mat_offset, 'Z', offset_angle);
+ mul_m4_m4m4(viewmat_roll, mat_offset, viewmat);
- /* apply the view and the object matrix */
- mul_m4_m4m4(r_mat_view, viewmat_roll, obedit->obmat);
+ /* apply the view and the object matrix */
+ mul_m4_m4m4(r_mat_view, viewmat_roll, obedit->obmat);
- /* get the view-space cursor */
- mul_v3_m4v3(r_center_view, viewmat_roll, center);
+ /* get the view-space cursor */
+ mul_v3_m4v3(r_center_view, viewmat_roll, center);
}
-
static void object_warp_transverts_minmax_x(TransVertStore *tvs,
- float mat_view[4][4], const float center_view[3],
- float *r_min, float *r_max)
+ float mat_view[4][4],
+ const float center_view[3],
+ float *r_min,
+ float *r_max)
{
- /* no need to apply translation and cursor offset for every vertex, delay this */
- const float x_ofs = (mat_view[3][0] - center_view[0]);
- float min = FLT_MAX, max = -FLT_MAX;
-
- TransVert *tv;
- int i;
+ /* no need to apply translation and cursor offset for every vertex, delay this */
+ const float x_ofs = (mat_view[3][0] - center_view[0]);
+ float min = FLT_MAX, max = -FLT_MAX;
+ TransVert *tv;
+ int i;
- tv = tvs->transverts;
- for (i = 0; i < tvs->transverts_tot; i++, tv++) {
- float val;
+ tv = tvs->transverts;
+ for (i = 0; i < tvs->transverts_tot; i++, tv++) {
+ float val;
- /* convert objectspace->viewspace */
- val = dot_m4_v3_row_x(mat_view, tv->loc);
+ /* convert objectspace->viewspace */
+ val = dot_m4_v3_row_x(mat_view, tv->loc);
- min = min_ff(min, val);
- max = max_ff(max, val);
- }
+ min = min_ff(min, val);
+ max = max_ff(max, val);
+ }
- *r_min = min + x_ofs;
- *r_max = max + x_ofs;
+ *r_min = min + x_ofs;
+ *r_max = max + x_ofs;
}
-
static void object_warp_transverts(TransVertStore *tvs,
- float mat_view[4][4], const float center_view[3],
- const float angle_, const float min, const float max)
+ float mat_view[4][4],
+ const float center_view[3],
+ const float angle_,
+ const float min,
+ const float max)
{
- TransVert *tv;
- int i;
- const float angle = -angle_;
- /* cache vars for tiny speedup */
+ TransVert *tv;
+ int i;
+ const float angle = -angle_;
+ /* cache vars for tiny speedup */
#if 1
- const float range = max - min;
- const float range_inv = 1.0f / range;
- const float min_ofs = min + (0.5f * range);
+ const float range = max - min;
+ const float range_inv = 1.0f / range;
+ const float min_ofs = min + (0.5f * range);
#endif
- float dir_min[2], dir_max[2];
- float imat_view[4][4];
-
+ float dir_min[2], dir_max[2];
+ float imat_view[4][4];
- invert_m4_m4(imat_view, mat_view);
+ invert_m4_m4(imat_view, mat_view);
- /* calculate the direction vectors outside min/max range */
- {
- const float phi = angle * 0.5f;
+ /* calculate the direction vectors outside min/max range */
+ {
+ const float phi = angle * 0.5f;
- dir_max[0] = cosf(phi);
- dir_max[1] = sinf(phi);
+ dir_max[0] = cosf(phi);
+ dir_max[1] = sinf(phi);
- dir_min[0] = -dir_max[0];
- dir_min[1] = dir_max[1];
- }
+ dir_min[0] = -dir_max[0];
+ dir_min[1] = dir_max[1];
+ }
+ tv = tvs->transverts;
+ for (i = 0; i < tvs->transverts_tot; i++, tv++) {
+ float co[3], co_add[2];
+ float val, phi;
- tv = tvs->transverts;
- for (i = 0; i < tvs->transverts_tot; i++, tv++) {
- float co[3], co_add[2];
- float val, phi;
+ /* convert objectspace->viewspace */
+ mul_v3_m4v3(co, mat_view, tv->loc);
+ sub_v2_v2(co, center_view);
- /* convert objectspace->viewspace */
- mul_v3_m4v3(co, mat_view, tv->loc);
- sub_v2_v2(co, center_view);
+ val = co[0];
+ /* is overwritten later anyway */
+ // co[0] = 0.0f;
- val = co[0];
- /* is overwritten later anyway */
- // co[0] = 0.0f;
+ if (val < min) {
+ mul_v2_v2fl(co_add, dir_min, min - val);
+ val = min;
+ }
+ else if (val > max) {
+ mul_v2_v2fl(co_add, dir_max, val - max);
+ val = max;
+ }
+ else {
+ zero_v2(co_add);
+ }
- if (val < min) {
- mul_v2_v2fl(co_add, dir_min, min - val);
- val = min;
- }
- else if (val > max) {
- mul_v2_v2fl(co_add, dir_max, val - max);
- val = max;
- }
- else {
- zero_v2(co_add);
- }
-
- /* map from x axis to (-0.5 - 0.5) */
+ /* map from x axis to (-0.5 - 0.5) */
#if 0
- val = ((val - min) / (max - min)) - 0.5f;
+ val = ((val - min) / (max - min)) - 0.5f;
#else
- val = (val - min_ofs) * range_inv;
+ val = (val - min_ofs) * range_inv;
#endif
- /* convert the x axis into a rotation */
- phi = val * angle;
+ /* convert the x axis into a rotation */
+ phi = val * angle;
- co[0] = -sinf(phi) * co[1];
- co[1] = cosf(phi) * co[1];
+ co[0] = -sinf(phi) * co[1];
+ co[1] = cosf(phi) * co[1];
- add_v2_v2(co, co_add);
+ add_v2_v2(co, co_add);
- /* convert viewspace->objectspace */
- add_v2_v2(co, center_view);
- mul_v3_m4v3(tv->loc, imat_view, co);
- }
+ /* convert viewspace->objectspace */
+ add_v2_v2(co, center_view);
+ mul_v3_m4v3(tv->loc, imat_view, co);
+ }
}
static int object_warp_verts_exec(bContext *C, wmOperator *op)
{
- const float warp_angle = RNA_float_get(op->ptr, "warp_angle");
- const float offset_angle = RNA_float_get(op->ptr, "offset_angle");
-
- TransVertStore tvs = {NULL};
- Object *obedit = CTX_data_edit_object(C);
-
- /* typically from 'rv3d' and 3d cursor */
- float viewmat[4][4];
- float center[3];
-
- /* 'viewmat' relative vars */
- float mat_view[4][4];
- float center_view[3];
-
- float min, max;
-
-
- ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS | TM_SKIP_HANDLES);
- if (tvs.transverts == NULL) {
- return OPERATOR_CANCELLED;
- }
-
-
- /* get viewmatrix */
- {
- PropertyRNA *prop_viewmat = RNA_struct_find_property(op->ptr, "viewmat");
- if (RNA_property_is_set(op->ptr, prop_viewmat)) {
- RNA_property_float_get_array(op->ptr, prop_viewmat, (float *)viewmat);
- }
- else {
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
-
- if (rv3d) {
- copy_m4_m4(viewmat, rv3d->viewmat);
- }
- else {
- unit_m4(viewmat);
- }
-
- RNA_property_float_set_array(op->ptr, prop_viewmat, (float *)viewmat);
- }
- }
-
-
- /* get center */
- {
- PropertyRNA *prop_center = RNA_struct_find_property(op->ptr, "center");
- if (RNA_property_is_set(op->ptr, prop_center)) {
- RNA_property_float_get_array(op->ptr, prop_center, center);
- }
- else {
- const Scene *scene = CTX_data_scene(C);
- copy_v3_v3(center, scene->cursor.location);
-
- RNA_property_float_set_array(op->ptr, prop_center, center);
- }
- }
-
-
- object_warp_calc_view_matrix(mat_view, center_view, obedit, viewmat, center, offset_angle);
-
-
- /* get minmax */
- {
- PropertyRNA *prop_min = RNA_struct_find_property(op->ptr, "min");
- PropertyRNA *prop_max = RNA_struct_find_property(op->ptr, "max");
-
- if (RNA_property_is_set(op->ptr, prop_min) ||
- RNA_property_is_set(op->ptr, prop_max))
- {
- min = RNA_property_float_get(op->ptr, prop_min);
- max = RNA_property_float_get(op->ptr, prop_max);
- }
- else {
- /* handy to set the bounds of the mesh */
- object_warp_transverts_minmax_x(&tvs, mat_view, center_view, &min, &max);
-
- RNA_property_float_set(op->ptr, prop_min, min);
- RNA_property_float_set(op->ptr, prop_max, max);
- }
-
- if (min > max) {
- SWAP(float, min, max);
- }
- }
-
- if (min != max) {
- object_warp_transverts(&tvs, mat_view, center_view, warp_angle, min, max);
- }
-
- ED_transverts_update_obedit(&tvs, obedit);
- ED_transverts_free(&tvs);
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
-
- return OPERATOR_FINISHED;
+ const float warp_angle = RNA_float_get(op->ptr, "warp_angle");
+ const float offset_angle = RNA_float_get(op->ptr, "offset_angle");
+
+ TransVertStore tvs = {NULL};
+ Object *obedit = CTX_data_edit_object(C);
+
+ /* typically from 'rv3d' and 3d cursor */
+ float viewmat[4][4];
+ float center[3];
+
+ /* 'viewmat' relative vars */
+ float mat_view[4][4];
+ float center_view[3];
+
+ float min, max;
+
+ ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS | TM_SKIP_HANDLES);
+ if (tvs.transverts == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* get viewmatrix */
+ {
+ PropertyRNA *prop_viewmat = RNA_struct_find_property(op->ptr, "viewmat");
+ if (RNA_property_is_set(op->ptr, prop_viewmat)) {
+ RNA_property_float_get_array(op->ptr, prop_viewmat, (float *)viewmat);
+ }
+ else {
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+
+ if (rv3d) {
+ copy_m4_m4(viewmat, rv3d->viewmat);
+ }
+ else {
+ unit_m4(viewmat);
+ }
+
+ RNA_property_float_set_array(op->ptr, prop_viewmat, (float *)viewmat);
+ }
+ }
+
+ /* get center */
+ {
+ PropertyRNA *prop_center = RNA_struct_find_property(op->ptr, "center");
+ if (RNA_property_is_set(op->ptr, prop_center)) {
+ RNA_property_float_get_array(op->ptr, prop_center, center);
+ }
+ else {
+ const Scene *scene = CTX_data_scene(C);
+ copy_v3_v3(center, scene->cursor.location);
+
+ RNA_property_float_set_array(op->ptr, prop_center, center);
+ }
+ }
+
+ object_warp_calc_view_matrix(mat_view, center_view, obedit, viewmat, center, offset_angle);
+
+ /* get minmax */
+ {
+ PropertyRNA *prop_min = RNA_struct_find_property(op->ptr, "min");
+ PropertyRNA *prop_max = RNA_struct_find_property(op->ptr, "max");
+
+ if (RNA_property_is_set(op->ptr, prop_min) || RNA_property_is_set(op->ptr, prop_max)) {
+ min = RNA_property_float_get(op->ptr, prop_min);
+ max = RNA_property_float_get(op->ptr, prop_max);
+ }
+ else {
+ /* handy to set the bounds of the mesh */
+ object_warp_transverts_minmax_x(&tvs, mat_view, center_view, &min, &max);
+
+ RNA_property_float_set(op->ptr, prop_min, min);
+ RNA_property_float_set(op->ptr, prop_max, max);
+ }
+
+ if (min > max) {
+ SWAP(float, min, max);
+ }
+ }
+
+ if (min != max) {
+ object_warp_transverts(&tvs, mat_view, center_view, warp_angle, min, max);
+ }
+
+ ED_transverts_update_obedit(&tvs, obedit);
+ ED_transverts_free(&tvs);
+
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
+
+ return OPERATOR_FINISHED;
}
void TRANSFORM_OT_vertex_warp(struct wmOperatorType *ot)
{
- PropertyRNA *prop;
-
- /* identifiers */
- ot->name = "Warp";
- ot->description = "Warp vertices around the cursor";
- ot->idname = "TRANSFORM_OT_vertex_warp";
-
- /* api callbacks */
- ot->exec = object_warp_verts_exec;
- ot->poll = ED_transverts_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* props */
- prop = RNA_def_float(ot->srna, "warp_angle", DEG2RADF(360.0f), -FLT_MAX, FLT_MAX, "Warp Angle",
- "Amount to warp about the cursor", DEG2RADF(-360.0f), DEG2RADF(360.0f));
- RNA_def_property_subtype(prop, PROP_ANGLE);
-
- prop = RNA_def_float(ot->srna, "offset_angle", DEG2RADF(0.0f), -FLT_MAX, FLT_MAX, "Offset Angle",
- "Angle to use as the basis for warping", DEG2RADF(-360.0f), DEG2RADF(360.0f));
- RNA_def_property_subtype(prop, PROP_ANGLE);
-
- prop = RNA_def_float(ot->srna, "min", -1.0f, -FLT_MAX, FLT_MAX, "Min", "", -100.0, 100.0);
- prop = RNA_def_float(ot->srna, "max", 1.0f, -FLT_MAX, FLT_MAX, "Max", "", -100.0, 100.0);
-
- /* hidden props */
- prop = RNA_def_float_matrix(ot->srna, "viewmat", 4, 4, NULL, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f);
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
-
- prop = RNA_def_float_vector_xyz(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "", -FLT_MAX, FLT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Warp";
+ ot->description = "Warp vertices around the cursor";
+ ot->idname = "TRANSFORM_OT_vertex_warp";
+
+ /* api callbacks */
+ ot->exec = object_warp_verts_exec;
+ ot->poll = ED_transverts_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ prop = RNA_def_float(ot->srna,
+ "warp_angle",
+ DEG2RADF(360.0f),
+ -FLT_MAX,
+ FLT_MAX,
+ "Warp Angle",
+ "Amount to warp about the cursor",
+ DEG2RADF(-360.0f),
+ DEG2RADF(360.0f));
+ RNA_def_property_subtype(prop, PROP_ANGLE);
+
+ prop = RNA_def_float(ot->srna,
+ "offset_angle",
+ DEG2RADF(0.0f),
+ -FLT_MAX,
+ FLT_MAX,
+ "Offset Angle",
+ "Angle to use as the basis for warping",
+ DEG2RADF(-360.0f),
+ DEG2RADF(360.0f));
+ RNA_def_property_subtype(prop, PROP_ANGLE);
+
+ prop = RNA_def_float(ot->srna, "min", -1.0f, -FLT_MAX, FLT_MAX, "Min", "", -100.0, 100.0);
+ prop = RNA_def_float(ot->srna, "max", 1.0f, -FLT_MAX, FLT_MAX, "Max", "", -100.0, 100.0);
+
+ /* hidden props */
+ prop = RNA_def_float_matrix(
+ ot->srna, "viewmat", 4, 4, NULL, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ prop = RNA_def_float_vector_xyz(
+ ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}