2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
21 * Contributor(s): Blender Foundation, 2009
23 * ***** END GPL LICENSE BLOCK *****
26 /** \file blender/editors/object/object_modifier.c
35 #include "MEM_guardedalloc.h"
37 #include "DNA_anim_types.h"
38 #include "DNA_armature_types.h"
39 #include "DNA_curve_types.h"
40 #include "DNA_key_types.h"
41 #include "DNA_mesh_types.h"
42 #include "DNA_meshdata_types.h"
43 #include "DNA_object_force.h"
44 #include "DNA_scene_types.h"
46 #include "BLI_bitmap.h"
48 #include "BLI_listbase.h"
49 #include "BLI_string.h"
50 #include "BLI_string_utf8.h"
51 #include "BLI_path_util.h"
52 #include "BLI_utildefines.h"
54 #include "BKE_animsys.h"
55 #include "BKE_curve.h"
56 #include "BKE_context.h"
57 #include "BKE_depsgraph.h"
58 #include "BKE_displist.h"
59 #include "BKE_DerivedMesh.h"
60 #include "BKE_effect.h"
61 #include "BKE_global.h"
63 #include "BKE_lattice.h"
66 #include "BKE_mesh_mapping.h"
67 #include "BKE_modifier.h"
68 #include "BKE_multires.h"
69 #include "BKE_report.h"
70 #include "BKE_object.h"
71 #include "BKE_object_deform.h"
72 #include "BKE_ocean.h"
73 #include "BKE_paint.h"
74 #include "BKE_particle.h"
75 #include "BKE_softbody.h"
76 #include "BKE_editmesh.h"
78 #include "RNA_access.h"
79 #include "RNA_define.h"
80 #include "RNA_enum_types.h"
82 #include "ED_armature.h"
83 #include "ED_object.h"
84 #include "ED_screen.h"
90 #include "object_intern.h"
92 static void modifier_skin_customdata_delete(struct Object *ob);
94 /******************************** API ****************************/
96 ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type)
98 ModifierData *md = NULL, *new_md = NULL;
99 const ModifierTypeInfo *mti = modifierType_getInfo(type);
101 /* Check compatibility of modifier [T25291, T50373]. */
102 if (!BKE_object_support_modifier_type_check(ob, type)) {
103 BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to object '%s'", ob->id.name + 2);
107 if (mti->flags & eModifierTypeFlag_Single) {
108 if (modifiers_findByType(ob, type)) {
109 BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
114 if (type == eModifierType_ParticleSystem) {
115 /* don't need to worry about the new modifier's name, since that is set to the number
116 * of particle systems which shouldn't have too many duplicates
118 new_md = object_add_particle_system(scene, ob, name);
121 /* get new modifier data to add */
122 new_md = modifier_new(type);
124 if (mti->flags & eModifierTypeFlag_RequiresOriginalData) {
125 md = ob->modifiers.first;
127 while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform)
130 BLI_insertlinkbefore(&ob->modifiers, md, new_md);
133 BLI_addtail(&ob->modifiers, new_md);
136 BLI_strncpy_utf8(new_md->name, name, sizeof(new_md->name));
139 /* make sure modifier data has unique name */
141 modifier_unique_name(&ob->modifiers, new_md);
144 if (type == eModifierType_Softbody) {
146 ob->soft = sbNew(scene);
147 ob->softflag |= OB_SB_GOAL | OB_SB_EDGES;
150 else if (type == eModifierType_Collision) {
152 ob->pd = object_add_collision_fields(0);
156 else if (type == eModifierType_Surface) {
159 else if (type == eModifierType_Multires) {
160 /* set totlvl from existing MDISPS layer if object already had it */
161 multiresModifier_set_levels_from_disps((MultiresModifierData *)new_md, ob);
163 if (ob->mode & OB_MODE_SCULPT) {
164 /* ensure that grid paint mask layer is created */
165 BKE_sculpt_mask_layers_ensure(ob, (MultiresModifierData *)new_md);
168 else if (type == eModifierType_Skin) {
169 /* ensure skin-node customdata exists */
170 BKE_mesh_ensure_skin_customdata(ob->data);
174 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
175 DAG_relations_tag_update(bmain);
180 /* Return true if the object has a modifier of type 'type' other than
181 * the modifier pointed to be 'exclude', otherwise returns false. */
182 static bool object_has_modifier(const Object *ob, const ModifierData *exclude,
187 for (md = ob->modifiers.first; md; md = md->next) {
188 if ((md != exclude) && (md->type == type))
195 /* If the object data of 'orig_ob' has other users, run 'callback' on
198 * If include_orig is true, the callback will run on 'orig_ob' too.
200 * If the callback ever returns true, iteration will stop and the
201 * function value will be true. Otherwise the function returns false.
203 bool ED_object_iter_other(Main *bmain, Object *orig_ob, const bool include_orig,
204 bool (*callback)(Object *ob, void *callback_data),
207 ID *ob_data_id = orig_ob->data;
208 int users = ob_data_id->us;
210 if (ob_data_id->flag & LIB_FAKEUSER)
213 /* First check that the object's data has multiple users */
216 int totfound = include_orig ? 0 : 1;
218 for (ob = bmain->object.first; ob && totfound < users;
221 if (((ob != orig_ob) || include_orig) &&
222 (ob->data == orig_ob->data))
224 if (callback(ob, callback_data))
231 else if (include_orig) {
232 return callback(orig_ob, callback_data);
238 static bool object_has_modifier_cb(Object *ob, void *data)
240 ModifierType type = *((ModifierType *)data);
242 return object_has_modifier(ob, NULL, type);
245 /* Use with ED_object_iter_other(). Sets the total number of levels
246 * for any multires modifiers on the object to the int pointed to by
248 bool ED_object_multires_update_totlevels_cb(Object *ob, void *totlevel_v)
251 int totlevel = *((char *)totlevel_v);
253 for (md = ob->modifiers.first; md; md = md->next) {
254 if (md->type == eModifierType_Multires) {
255 multires_set_tot_level(ob, (MultiresModifierData *)md, totlevel);
256 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
262 /* Return true if no modifier of type 'type' other than 'exclude' */
263 static bool object_modifier_safe_to_delete(Main *bmain, Object *ob,
264 ModifierData *exclude,
267 return (!object_has_modifier(ob, exclude, type) &&
268 !ED_object_iter_other(bmain, ob, false,
269 object_has_modifier_cb, &type));
272 static bool object_modifier_remove(Main *bmain, Object *ob, ModifierData *md,
273 bool *r_sort_depsgraph)
275 /* It seems on rapid delete it is possible to
276 * get called twice on same modifier, so make
277 * sure it is in list. */
278 if (BLI_findindex(&ob->modifiers, md) == -1) {
283 if (md->type == eModifierType_ParticleSystem) {
284 ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
286 BLI_remlink(&ob->particlesystem, psmd->psys);
287 psys_free(ob, psmd->psys);
290 else if (md->type == eModifierType_Softbody) {
297 else if (md->type == eModifierType_Collision) {
301 *r_sort_depsgraph = true;
303 else if (md->type == eModifierType_Surface) {
304 *r_sort_depsgraph = true;
306 else if (md->type == eModifierType_Multires) {
307 /* Delete MDisps layer if not used by another multires modifier */
308 if (object_modifier_safe_to_delete(bmain, ob, md, eModifierType_Multires))
309 multires_customdata_delete(ob->data);
311 else if (md->type == eModifierType_Skin) {
312 /* Delete MVertSkin layer if not used by another skin modifier */
313 if (object_modifier_safe_to_delete(bmain, ob, md, eModifierType_Skin))
314 modifier_skin_customdata_delete(ob);
317 if (ELEM(md->type, eModifierType_Softbody, eModifierType_Cloth) &&
318 BLI_listbase_is_empty(&ob->particlesystem))
320 ob->mode &= ~OB_MODE_PARTICLE_EDIT;
323 DAG_relations_tag_update(bmain);
325 BLI_remlink(&ob->modifiers, md);
327 BKE_object_free_derived_caches(ob);
332 bool ED_object_modifier_remove(ReportList *reports, Main *bmain, Object *ob, ModifierData *md)
334 bool sort_depsgraph = false;
337 ok = object_modifier_remove(bmain, ob, md, &sort_depsgraph);
340 BKE_reportf(reports, RPT_ERROR, "Modifier '%s' not in object '%s'", md->name, ob->id.name);
344 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
345 DAG_relations_tag_update(bmain);
350 void ED_object_modifier_clear(Main *bmain, Object *ob)
352 ModifierData *md = ob->modifiers.first;
353 bool sort_depsgraph = false;
359 ModifierData *next_md;
363 object_modifier_remove(bmain, ob, md, &sort_depsgraph);
368 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
369 DAG_relations_tag_update(bmain);
372 int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md)
375 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
377 if (mti->type != eModifierTypeType_OnlyDeform) {
378 const ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type);
380 if (nmti->flags & eModifierTypeFlag_RequiresOriginalData) {
381 BKE_report(reports, RPT_WARNING, "Cannot move above a modifier requiring original data");
386 BLI_remlink(&ob->modifiers, md);
387 BLI_insertlinkbefore(&ob->modifiers, md->prev, md);
393 int ED_object_modifier_move_down(ReportList *reports, Object *ob, ModifierData *md)
396 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
398 if (mti->flags & eModifierTypeFlag_RequiresOriginalData) {
399 const ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type);
401 if (nmti->type != eModifierTypeType_OnlyDeform) {
402 BKE_report(reports, RPT_WARNING, "Cannot move beyond a non-deforming modifier");
407 BLI_remlink(&ob->modifiers, md);
408 BLI_insertlinkafter(&ob->modifiers, md->next, md);
414 int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *scene, SceneLayer *sl, Object *ob, ModifierData *md)
417 ParticleSystem *psys;
418 ParticleCacheKey *key, **cache;
419 ParticleSettings *part;
424 int totvert = 0, totedge = 0, cvert = 0;
425 int totpart = 0, totchild = 0;
427 if (md->type != eModifierType_ParticleSystem) return 0;
428 if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) return 0;
430 psys = ((ParticleSystemModifierData *)md)->psys;
433 if (part->ren_as != PART_DRAW_PATH || psys->pathcache == NULL)
436 totpart = psys->totcached;
437 totchild = psys->totchildcache;
439 if (totchild && (part->draw & PART_DRAW_PARENT) == 0)
443 cache = psys->pathcache;
444 for (a = 0; a < totpart; a++) {
447 if (key->segments > 0) {
448 totvert += key->segments + 1;
449 totedge += key->segments;
453 cache = psys->childcache;
454 for (a = 0; a < totchild; a++) {
457 if (key->segments > 0) {
458 totvert += key->segments + 1;
459 totedge += key->segments;
463 if (totvert == 0) return 0;
466 obn = BKE_object_add(bmain, scene, sl, OB_MESH, NULL);
469 me->totvert = totvert;
470 me->totedge = totedge;
472 me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
473 me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
474 me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0);
479 /* copy coordinates */
480 cache = psys->pathcache;
481 for (a = 0; a < totpart; a++) {
483 kmax = key->segments;
484 for (k = 0; k <= kmax; k++, key++, cvert++, mvert++) {
485 copy_v3_v3(mvert->co, key->co);
487 medge->v1 = cvert - 1;
489 medge->flag = ME_EDGEDRAW | ME_EDGERENDER | ME_LOOSEEDGE;
493 /* cheap trick to select the roots */
494 mvert->flag |= SELECT;
499 cache = psys->childcache;
500 for (a = 0; a < totchild; a++) {
502 kmax = key->segments;
503 for (k = 0; k <= kmax; k++, key++, cvert++, mvert++) {
504 copy_v3_v3(mvert->co, key->co);
506 medge->v1 = cvert - 1;
508 medge->flag = ME_EDGEDRAW | ME_EDGERENDER | ME_LOOSEEDGE;
512 /* cheap trick to select the roots */
513 mvert->flag |= SELECT;
518 DAG_relations_tag_update(bmain);
523 static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, ModifierData *md)
525 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
529 if (mti->isDisabled && mti->isDisabled(md, 0)) {
530 BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
535 * It should be ridiculously easy to extract the original verts that we want
536 * and form the shape data. We can probably use the CD KEYINDEX layer (or
537 * whatever I ended up calling it, too tired to check now), though this would
538 * by necessity have to make some potentially ugly assumptions about the order
539 * of the mesh data :-/ you can probably assume in 99% of cases that the first
540 * element of a given index is the original, and any subsequent duplicates are
541 * copies/interpolates, but that's an assumption that would need to be tested
542 * and then predominantly stated in comments in a half dozen headers.
545 if (ob->type == OB_MESH) {
551 if (!modifier_isSameTopology(md) || mti->type == eModifierTypeType_NonGeometrical) {
552 BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to shapes");
556 dm = mesh_create_derived_for_modifier(scene, ob, md, 0);
558 BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply");
563 key = me->key = BKE_key_add((ID *)me);
564 key->type = KEY_RELATIVE;
565 /* if that was the first key block added, then it was the basis.
566 * Initialize it with the mesh, and add another for the modifier */
567 kb = BKE_keyblock_add(key, NULL);
568 BKE_keyblock_convert_from_mesh(me, kb);
571 kb = BKE_keyblock_add(key, md->name);
572 DM_to_meshkey(dm, me, kb);
577 BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
583 static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob, ModifierData *md)
585 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
589 if (mti->isDisabled && mti->isDisabled(md, 0)) {
590 BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
594 if (ob->type == OB_MESH) {
597 MultiresModifierData *mmd = find_multires_modifier_before(scene, md);
599 if (me->key && mti->type != eModifierTypeType_NonGeometrical) {
600 BKE_report(reports, RPT_ERROR, "Modifier cannot be applied to a mesh with shape keys");
604 /* Multires: ensure that recent sculpting is applied */
605 if (md->type == eModifierType_Multires)
606 multires_force_update(ob);
608 if (mmd && mmd->totlvl && mti->type == eModifierTypeType_OnlyDeform) {
609 if (!multiresModifier_reshapeFromDeformMod(scene, mmd, ob, md)) {
610 BKE_report(reports, RPT_ERROR, "Multires modifier returned error, skipping apply");
615 dm = mesh_create_derived_for_modifier(scene, ob, md, 1);
617 BKE_report(reports, RPT_ERROR, "Modifier returned error, skipping apply");
621 DM_to_mesh(dm, me, ob, CD_MASK_MESH, true);
623 if (md->type == eModifierType_Multires)
624 multires_customdata_delete(me);
627 else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
630 float (*vertexCos)[3];
632 if (ELEM(mti->type, eModifierTypeType_Constructive, eModifierTypeType_Nonconstructive)) {
633 BKE_report(reports, RPT_ERROR, "Cannot apply constructive modifiers on curve");
638 BKE_report(reports, RPT_INFO, "Applied modifier only changed CV points, not tessellated/bevel vertices");
640 vertexCos = BKE_curve_nurbs_vertexCos_get(&cu->nurb, &numVerts);
641 mti->deformVerts(md, ob, NULL, vertexCos, numVerts, 0);
642 BK_curve_nurbs_vertexCos_apply(&cu->nurb, vertexCos);
644 MEM_freeN(vertexCos);
646 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
649 BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
653 /* lattice modifier can be applied to particle system too */
654 if (ob->particlesystem.first) {
656 ParticleSystem *psys = ob->particlesystem.first;
658 for (; psys; psys = psys->next) {
660 if (psys->part->type != PART_HAIR)
663 psys_apply_hair_lattice(scene, ob, psys);
670 int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, ModifierData *md, int mode)
675 BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in edit mode");
678 else if (((ID *) ob->data)->us > 1) {
679 BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
682 else if ((ob->mode & OB_MODE_SCULPT) &&
683 (find_multires_modifier_before(scene, md)) &&
684 (modifier_isSameTopology(md) == false))
686 BKE_report(reports, RPT_ERROR, "Constructive modifier cannot be applied to multi-res data in sculpt mode");
690 if (md != ob->modifiers.first)
691 BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected");
693 /* allow apply of a not-realtime modifier, by first re-enabling realtime. */
694 prev_mode = md->mode;
695 md->mode |= eModifierMode_Realtime;
697 if (mode == MODIFIER_APPLY_SHAPE) {
698 if (!modifier_apply_shape(reports, scene, ob, md)) {
699 md->mode = prev_mode;
704 if (!modifier_apply_obdata(reports, scene, ob, md)) {
705 md->mode = prev_mode;
710 BLI_remlink(&ob->modifiers, md);
713 BKE_object_free_derived_caches(ob);
718 int ED_object_modifier_copy(ReportList *UNUSED(reports), Object *ob, ModifierData *md)
722 nmd = modifier_new(md->type);
723 modifier_copyData(md, nmd);
724 BLI_insertlinkafter(&ob->modifiers, md, nmd);
725 modifier_unique_name(&ob->modifiers, nmd);
730 /************************ add modifier operator *********************/
732 static int modifier_add_exec(bContext *C, wmOperator *op)
734 Main *bmain = CTX_data_main(C);
735 Scene *scene = CTX_data_scene(C);
736 Object *ob = ED_object_active_context(C);
737 int type = RNA_enum_get(op->ptr, "type");
739 if (!ED_object_modifier_add(op->reports, bmain, scene, ob, NULL, type))
740 return OPERATOR_CANCELLED;
742 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
744 return OPERATOR_FINISHED;
747 static EnumPropertyItem *modifier_add_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
749 Object *ob = ED_object_active_context(C);
750 EnumPropertyItem *item = NULL, *md_item, *group_item = NULL;
751 const ModifierTypeInfo *mti;
755 return rna_enum_object_modifier_type_items;
757 for (a = 0; rna_enum_object_modifier_type_items[a].identifier; a++) {
758 md_item = &rna_enum_object_modifier_type_items[a];
760 if (md_item->identifier[0]) {
761 mti = modifierType_getInfo(md_item->value);
763 if (mti->flags & eModifierTypeFlag_NoUserAdd)
766 if (!BKE_object_support_modifier_type_check(ob, md_item->value))
770 group_item = md_item;
777 RNA_enum_item_add(&item, &totitem, group_item);
781 RNA_enum_item_add(&item, &totitem, md_item);
784 RNA_enum_item_end(&item, &totitem);
790 void OBJECT_OT_modifier_add(wmOperatorType *ot)
795 ot->name = "Add Modifier";
796 ot->description = "Add a procedural operation/effect to the active object";
797 ot->idname = "OBJECT_OT_modifier_add";
800 ot->invoke = WM_menu_invoke;
801 ot->exec = modifier_add_exec;
802 ot->poll = ED_operator_object_active_editable;
805 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
808 prop = RNA_def_enum(ot->srna, "type", rna_enum_object_modifier_type_items, eModifierType_Subsurf, "Type", "");
809 RNA_def_enum_funcs(prop, modifier_add_itemf);
813 /************************ generic functions for operators using mod names and data context *********************/
815 int edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
817 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
818 Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
820 if (!ob || ID_IS_LINKED_DATABLOCK(ob)) return 0;
821 if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) return 0;
822 if (ptr.id.data && ID_IS_LINKED_DATABLOCK(ptr.id.data)) return 0;
827 int edit_modifier_poll(bContext *C)
829 return edit_modifier_poll_generic(C, &RNA_Modifier, 0);
832 void edit_modifier_properties(wmOperatorType *ot)
834 RNA_def_string(ot->srna, "modifier", NULL, MAX_NAME, "Modifier", "Name of the modifier to edit");
837 int edit_modifier_invoke_properties(bContext *C, wmOperator *op)
841 if (RNA_struct_property_is_set(op->ptr, "modifier")) {
845 PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
848 RNA_string_set(op->ptr, "modifier", md->name);
856 ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type)
858 char modifier_name[MAX_NAME];
860 RNA_string_get(op->ptr, "modifier", modifier_name);
862 md = modifiers_findByName(ob, modifier_name);
864 if (md && type != 0 && md->type != type)
870 /************************ remove modifier operator *********************/
872 static int modifier_remove_exec(bContext *C, wmOperator *op)
874 Main *bmain = CTX_data_main(C);
875 SceneLayer *sl = CTX_data_scene_layer(C);
876 Object *ob = ED_object_active_context(C);
877 ModifierData *md = edit_modifier_property_get(op, ob, 0);
878 int mode_orig = ob->mode;
880 if (!md || !ED_object_modifier_remove(op->reports, bmain, ob, md))
881 return OPERATOR_CANCELLED;
883 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
885 /* if cloth/softbody was removed, particle mode could be cleared */
886 if (mode_orig & OB_MODE_PARTICLE_EDIT)
887 if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0)
888 if (sl->basact && sl->basact->object == ob)
889 WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
891 return OPERATOR_FINISHED;
894 static int modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
896 if (edit_modifier_invoke_properties(C, op))
897 return modifier_remove_exec(C, op);
899 return OPERATOR_CANCELLED;
902 void OBJECT_OT_modifier_remove(wmOperatorType *ot)
904 ot->name = "Remove Modifier";
905 ot->description = "Remove a modifier from the active object";
906 ot->idname = "OBJECT_OT_modifier_remove";
908 ot->invoke = modifier_remove_invoke;
909 ot->exec = modifier_remove_exec;
910 ot->poll = edit_modifier_poll;
913 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
914 edit_modifier_properties(ot);
917 /************************ move up modifier operator *********************/
919 static int modifier_move_up_exec(bContext *C, wmOperator *op)
921 Object *ob = ED_object_active_context(C);
922 ModifierData *md = edit_modifier_property_get(op, ob, 0);
924 if (!md || !ED_object_modifier_move_up(op->reports, ob, md))
925 return OPERATOR_CANCELLED;
927 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
928 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
930 return OPERATOR_FINISHED;
933 static int modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
935 if (edit_modifier_invoke_properties(C, op))
936 return modifier_move_up_exec(C, op);
938 return OPERATOR_CANCELLED;
941 void OBJECT_OT_modifier_move_up(wmOperatorType *ot)
943 ot->name = "Move Up Modifier";
944 ot->description = "Move modifier up in the stack";
945 ot->idname = "OBJECT_OT_modifier_move_up";
947 ot->invoke = modifier_move_up_invoke;
948 ot->exec = modifier_move_up_exec;
949 ot->poll = edit_modifier_poll;
952 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
953 edit_modifier_properties(ot);
956 /************************ move down modifier operator *********************/
958 static int modifier_move_down_exec(bContext *C, wmOperator *op)
960 Object *ob = ED_object_active_context(C);
961 ModifierData *md = edit_modifier_property_get(op, ob, 0);
963 if (!md || !ED_object_modifier_move_down(op->reports, ob, md))
964 return OPERATOR_CANCELLED;
966 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
967 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
969 return OPERATOR_FINISHED;
972 static int modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
974 if (edit_modifier_invoke_properties(C, op))
975 return modifier_move_down_exec(C, op);
977 return OPERATOR_CANCELLED;
980 void OBJECT_OT_modifier_move_down(wmOperatorType *ot)
982 ot->name = "Move Down Modifier";
983 ot->description = "Move modifier down in the stack";
984 ot->idname = "OBJECT_OT_modifier_move_down";
986 ot->invoke = modifier_move_down_invoke;
987 ot->exec = modifier_move_down_exec;
988 ot->poll = edit_modifier_poll;
991 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
992 edit_modifier_properties(ot);
995 /************************ apply modifier operator *********************/
997 static int modifier_apply_exec(bContext *C, wmOperator *op)
999 Scene *scene = CTX_data_scene(C);
1000 Object *ob = ED_object_active_context(C);
1001 ModifierData *md = edit_modifier_property_get(op, ob, 0);
1002 int apply_as = RNA_enum_get(op->ptr, "apply_as");
1004 if (!md || !ED_object_modifier_apply(op->reports, scene, ob, md, apply_as)) {
1005 return OPERATOR_CANCELLED;
1008 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1009 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1011 return OPERATOR_FINISHED;
1014 static int modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1016 if (edit_modifier_invoke_properties(C, op))
1017 return modifier_apply_exec(C, op);
1019 return OPERATOR_CANCELLED;
1022 static EnumPropertyItem modifier_apply_as_items[] = {
1023 {MODIFIER_APPLY_DATA, "DATA", 0, "Object Data", "Apply modifier to the object's data"},
1024 {MODIFIER_APPLY_SHAPE, "SHAPE", 0, "New Shape", "Apply deform-only modifier to a new shape on this object"},
1025 {0, NULL, 0, NULL, NULL}
1028 void OBJECT_OT_modifier_apply(wmOperatorType *ot)
1030 ot->name = "Apply Modifier";
1031 ot->description = "Apply modifier and remove from the stack";
1032 ot->idname = "OBJECT_OT_modifier_apply";
1034 ot->invoke = modifier_apply_invoke;
1035 ot->exec = modifier_apply_exec;
1036 ot->poll = edit_modifier_poll;
1039 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1041 RNA_def_enum(ot->srna, "apply_as", modifier_apply_as_items, MODIFIER_APPLY_DATA, "Apply as", "How to apply the modifier to the geometry");
1042 edit_modifier_properties(ot);
1045 /************************ convert modifier operator *********************/
1047 static int modifier_convert_exec(bContext *C, wmOperator *op)
1049 Main *bmain = CTX_data_main(C);
1050 Scene *scene = CTX_data_scene(C);
1051 SceneLayer *sl = CTX_data_scene_layer(C);
1052 Object *ob = ED_object_active_context(C);
1053 ModifierData *md = edit_modifier_property_get(op, ob, 0);
1055 if (!md || !ED_object_modifier_convert(op->reports, bmain, scene, sl, ob, md))
1056 return OPERATOR_CANCELLED;
1058 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1059 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1061 return OPERATOR_FINISHED;
1064 static int modifier_convert_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1066 if (edit_modifier_invoke_properties(C, op))
1067 return modifier_convert_exec(C, op);
1069 return OPERATOR_CANCELLED;
1072 void OBJECT_OT_modifier_convert(wmOperatorType *ot)
1074 ot->name = "Convert Modifier";
1075 ot->description = "Convert particles to a mesh object";
1076 ot->idname = "OBJECT_OT_modifier_convert";
1078 ot->invoke = modifier_convert_invoke;
1079 ot->exec = modifier_convert_exec;
1080 ot->poll = edit_modifier_poll;
1083 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1084 edit_modifier_properties(ot);
1087 /************************ copy modifier operator *********************/
1089 static int modifier_copy_exec(bContext *C, wmOperator *op)
1091 Object *ob = ED_object_active_context(C);
1092 ModifierData *md = edit_modifier_property_get(op, ob, 0);
1094 if (!md || !ED_object_modifier_copy(op->reports, ob, md))
1095 return OPERATOR_CANCELLED;
1097 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1098 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1100 return OPERATOR_FINISHED;
1103 static int modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1105 if (edit_modifier_invoke_properties(C, op))
1106 return modifier_copy_exec(C, op);
1108 return OPERATOR_CANCELLED;
1111 void OBJECT_OT_modifier_copy(wmOperatorType *ot)
1113 ot->name = "Copy Modifier";
1114 ot->description = "Duplicate modifier at the same position in the stack";
1115 ot->idname = "OBJECT_OT_modifier_copy";
1117 ot->invoke = modifier_copy_invoke;
1118 ot->exec = modifier_copy_exec;
1119 ot->poll = edit_modifier_poll;
1122 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1123 edit_modifier_properties(ot);
1126 /************* multires delete higher levels operator ****************/
1128 static int multires_poll(bContext *C)
1130 return edit_modifier_poll_generic(C, &RNA_MultiresModifier, (1 << OB_MESH));
1133 static int multires_higher_levels_delete_exec(bContext *C, wmOperator *op)
1135 Object *ob = ED_object_active_context(C);
1136 MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
1139 return OPERATOR_CANCELLED;
1141 multiresModifier_del_levels(mmd, ob, 1);
1143 ED_object_iter_other(CTX_data_main(C), ob, true,
1144 ED_object_multires_update_totlevels_cb,
1147 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1149 return OPERATOR_FINISHED;
1152 static int multires_higher_levels_delete_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1154 if (edit_modifier_invoke_properties(C, op))
1155 return multires_higher_levels_delete_exec(C, op);
1157 return OPERATOR_CANCELLED;
1160 void OBJECT_OT_multires_higher_levels_delete(wmOperatorType *ot)
1162 ot->name = "Delete Higher Levels";
1163 ot->description = "Deletes the higher resolution mesh, potential loss of detail";
1164 ot->idname = "OBJECT_OT_multires_higher_levels_delete";
1166 ot->poll = multires_poll;
1167 ot->invoke = multires_higher_levels_delete_invoke;
1168 ot->exec = multires_higher_levels_delete_exec;
1171 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1172 edit_modifier_properties(ot);
1175 /****************** multires subdivide operator *********************/
1177 static int multires_subdivide_exec(bContext *C, wmOperator *op)
1179 Object *ob = ED_object_active_context(C);
1180 MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
1183 return OPERATOR_CANCELLED;
1185 multiresModifier_subdivide(mmd, ob, 0, mmd->simple);
1187 ED_object_iter_other(CTX_data_main(C), ob, true,
1188 ED_object_multires_update_totlevels_cb,
1191 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1192 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1194 if (ob->mode & OB_MODE_SCULPT) {
1195 /* ensure that grid paint mask layer is created */
1196 BKE_sculpt_mask_layers_ensure(ob, mmd);
1199 return OPERATOR_FINISHED;
1202 static int multires_subdivide_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1204 if (edit_modifier_invoke_properties(C, op))
1205 return multires_subdivide_exec(C, op);
1207 return OPERATOR_CANCELLED;
1210 void OBJECT_OT_multires_subdivide(wmOperatorType *ot)
1212 ot->name = "Multires Subdivide";
1213 ot->description = "Add a new level of subdivision";
1214 ot->idname = "OBJECT_OT_multires_subdivide";
1216 ot->poll = multires_poll;
1217 ot->invoke = multires_subdivide_invoke;
1218 ot->exec = multires_subdivide_exec;
1221 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1222 edit_modifier_properties(ot);
1225 /****************** multires reshape operator *********************/
1227 static int multires_reshape_exec(bContext *C, wmOperator *op)
1229 Object *ob = ED_object_active_context(C), *secondob = NULL;
1230 Scene *scene = CTX_data_scene(C);
1231 MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
1234 return OPERATOR_CANCELLED;
1236 if (mmd->lvl == 0) {
1237 BKE_report(op->reports, RPT_ERROR, "Reshape can work only with higher levels of subdivisions");
1238 return OPERATOR_CANCELLED;
1241 CTX_DATA_BEGIN(C, Object *, selob, selected_editable_objects)
1243 if (selob->type == OB_MESH && selob != ob) {
1251 BKE_report(op->reports, RPT_ERROR, "Second selected mesh object required to copy shape from");
1252 return OPERATOR_CANCELLED;
1255 if (!multiresModifier_reshape(scene, mmd, ob, secondob)) {
1256 BKE_report(op->reports, RPT_ERROR, "Objects do not have the same number of vertices");
1257 return OPERATOR_CANCELLED;
1260 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1261 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1263 return OPERATOR_FINISHED;
1266 static int multires_reshape_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1268 if (edit_modifier_invoke_properties(C, op))
1269 return multires_reshape_exec(C, op);
1271 return OPERATOR_CANCELLED;
1274 void OBJECT_OT_multires_reshape(wmOperatorType *ot)
1276 ot->name = "Multires Reshape";
1277 ot->description = "Copy vertex coordinates from other object";
1278 ot->idname = "OBJECT_OT_multires_reshape";
1280 ot->poll = multires_poll;
1281 ot->invoke = multires_reshape_invoke;
1282 ot->exec = multires_reshape_exec;
1285 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1286 edit_modifier_properties(ot);
1291 /****************** multires save external operator *********************/
1293 static int multires_external_save_exec(bContext *C, wmOperator *op)
1295 Object *ob = ED_object_active_context(C);
1296 Mesh *me = (ob) ? ob->data : op->customdata;
1297 char path[FILE_MAX];
1298 const bool relative = RNA_boolean_get(op->ptr, "relative_path");
1301 return OPERATOR_CANCELLED;
1303 if (CustomData_external_test(&me->ldata, CD_MDISPS))
1304 return OPERATOR_CANCELLED;
1306 RNA_string_get(op->ptr, "filepath", path);
1309 BLI_path_rel(path, G.main->name);
1311 CustomData_external_add(&me->ldata, &me->id, CD_MDISPS, me->totloop, path);
1312 CustomData_external_write(&me->ldata, &me->id, CD_MASK_MESH, me->totloop, 0);
1314 return OPERATOR_FINISHED;
1317 static int multires_external_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1319 Object *ob = ED_object_active_context(C);
1320 MultiresModifierData *mmd;
1321 Mesh *me = ob->data;
1322 char path[FILE_MAX];
1324 if (!edit_modifier_invoke_properties(C, op))
1325 return OPERATOR_CANCELLED;
1327 mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
1330 return OPERATOR_CANCELLED;
1332 if (CustomData_external_test(&me->ldata, CD_MDISPS))
1333 return OPERATOR_CANCELLED;
1335 if (RNA_struct_property_is_set(op->ptr, "filepath"))
1336 return multires_external_save_exec(C, op);
1338 op->customdata = me;
1340 BLI_snprintf(path, sizeof(path), "//%s.btx", me->id.name + 2);
1341 RNA_string_set(op->ptr, "filepath", path);
1343 WM_event_add_fileselect(C, op);
1345 return OPERATOR_RUNNING_MODAL;
1348 void OBJECT_OT_multires_external_save(wmOperatorType *ot)
1350 ot->name = "Multires Save External";
1351 ot->description = "Save displacements to an external file";
1352 ot->idname = "OBJECT_OT_multires_external_save";
1354 /* XXX modifier no longer in context after file browser .. ot->poll = multires_poll; */
1355 ot->exec = multires_external_save_exec;
1356 ot->invoke = multires_external_save_invoke;
1357 ot->poll = multires_poll;
1360 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1362 WM_operator_properties_filesel(
1363 ot, FILE_TYPE_FOLDER | FILE_TYPE_BTX, FILE_SPECIAL, FILE_SAVE,
1364 WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
1365 edit_modifier_properties(ot);
1368 /****************** multires pack operator *********************/
1370 static int multires_external_pack_exec(bContext *C, wmOperator *UNUSED(op))
1372 Object *ob = ED_object_active_context(C);
1373 Mesh *me = ob->data;
1375 if (!CustomData_external_test(&me->ldata, CD_MDISPS))
1376 return OPERATOR_CANCELLED;
1378 /* XXX don't remove.. */
1379 CustomData_external_remove(&me->ldata, &me->id, CD_MDISPS, me->totloop);
1381 return OPERATOR_FINISHED;
1384 void OBJECT_OT_multires_external_pack(wmOperatorType *ot)
1386 ot->name = "Multires Pack External";
1387 ot->description = "Pack displacements from an external file";
1388 ot->idname = "OBJECT_OT_multires_external_pack";
1390 ot->poll = multires_poll;
1391 ot->exec = multires_external_pack_exec;
1394 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1397 /********************* multires apply base ***********************/
1398 static int multires_base_apply_exec(bContext *C, wmOperator *op)
1400 Object *ob = ED_object_active_context(C);
1401 MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
1404 return OPERATOR_CANCELLED;
1406 multiresModifier_base_apply(mmd, ob);
1408 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1409 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1411 return OPERATOR_FINISHED;
1414 static int multires_base_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1416 if (edit_modifier_invoke_properties(C, op))
1417 return multires_base_apply_exec(C, op);
1419 return OPERATOR_CANCELLED;
1423 void OBJECT_OT_multires_base_apply(wmOperatorType *ot)
1425 ot->name = "Multires Apply Base";
1426 ot->description = "Modify the base mesh to conform to the displaced mesh";
1427 ot->idname = "OBJECT_OT_multires_base_apply";
1429 ot->poll = multires_poll;
1430 ot->invoke = multires_base_apply_invoke;
1431 ot->exec = multires_base_apply_exec;
1434 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1435 edit_modifier_properties(ot);
1439 /************************** skin modifier ***********************/
1441 static void modifier_skin_customdata_delete(Object *ob)
1443 Mesh *me = ob->data;
1444 BMEditMesh *em = me->edit_btmesh;
1447 BM_data_layer_free(em->bm, &em->bm->vdata, CD_MVERT_SKIN);
1449 CustomData_free_layer_active(&me->vdata, CD_MVERT_SKIN, me->totvert);
1452 static int skin_poll(bContext *C)
1454 return (!CTX_data_edit_object(C) &&
1455 edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH)));
1458 static int skin_edit_poll(bContext *C)
1460 return (CTX_data_edit_object(C) &&
1461 edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH)));
1464 static void skin_root_clear(BMVert *bm_vert, GSet *visited, const int cd_vert_skin_offset)
1469 BM_ITER_ELEM (bm_edge, &bm_iter, bm_vert, BM_EDGES_OF_VERT) {
1470 BMVert *v2 = BM_edge_other_vert(bm_edge, bm_vert);
1472 if (BLI_gset_add(visited, v2)) {
1473 MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(v2, cd_vert_skin_offset);
1475 /* clear vertex root flag and add to visited set */
1476 vs->flag &= ~MVERT_SKIN_ROOT;
1478 skin_root_clear(v2, visited, cd_vert_skin_offset);
1483 static int skin_root_mark_exec(bContext *C, wmOperator *UNUSED(op))
1485 Object *ob = CTX_data_edit_object(C);
1486 BMEditMesh *em = BKE_editmesh_from_object(ob);
1492 visited = BLI_gset_ptr_new(__func__);
1494 BKE_mesh_ensure_skin_customdata(ob->data);
1496 const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
1498 BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
1499 if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT) &&
1500 BLI_gset_add(visited, bm_vert))
1502 MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(bm_vert, cd_vert_skin_offset);
1504 /* mark vertex as root and add to visited set */
1505 vs->flag |= MVERT_SKIN_ROOT;
1507 /* clear root flag from all connected vertices (recursively) */
1508 skin_root_clear(bm_vert, visited, cd_vert_skin_offset);
1512 BLI_gset_free(visited, NULL);
1514 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1515 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1517 return OPERATOR_FINISHED;
1520 void OBJECT_OT_skin_root_mark(wmOperatorType *ot)
1522 ot->name = "Skin Root Mark";
1523 ot->description = "Mark selected vertices as roots";
1524 ot->idname = "OBJECT_OT_skin_root_mark";
1526 ot->poll = skin_edit_poll;
1527 ot->exec = skin_root_mark_exec;
1530 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1538 static int skin_loose_mark_clear_exec(bContext *C, wmOperator *op)
1540 Object *ob = CTX_data_edit_object(C);
1541 BMEditMesh *em = BKE_editmesh_from_object(ob);
1545 SkinLooseAction action = RNA_enum_get(op->ptr, "action");
1547 if (!CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) {
1548 return OPERATOR_CANCELLED;
1551 BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
1552 if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) {
1553 MVertSkin *vs = CustomData_bmesh_get(&bm->vdata,
1559 case SKIN_LOOSE_MARK:
1560 vs->flag |= MVERT_SKIN_LOOSE;
1562 case SKIN_LOOSE_CLEAR:
1563 vs->flag &= ~MVERT_SKIN_LOOSE;
1569 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1570 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1572 return OPERATOR_FINISHED;
1575 void OBJECT_OT_skin_loose_mark_clear(wmOperatorType *ot)
1577 static EnumPropertyItem action_items[] = {
1578 {SKIN_LOOSE_MARK, "MARK", 0, "Mark", "Mark selected vertices as loose"},
1579 {SKIN_LOOSE_CLEAR, "CLEAR", 0, "Clear", "Set selected vertices as not loose"},
1580 {0, NULL, 0, NULL, NULL}
1583 ot->name = "Skin Mark/Clear Loose";
1584 ot->description = "Mark/clear selected vertices as loose";
1585 ot->idname = "OBJECT_OT_skin_loose_mark_clear";
1587 ot->poll = skin_edit_poll;
1588 ot->exec = skin_loose_mark_clear_exec;
1591 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1593 RNA_def_enum(ot->srna, "action", action_items, SKIN_LOOSE_MARK, "Action", NULL);
1596 static int skin_radii_equalize_exec(bContext *C, wmOperator *UNUSED(op))
1598 Object *ob = CTX_data_edit_object(C);
1599 BMEditMesh *em = BKE_editmesh_from_object(ob);
1604 if (!CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) {
1605 return OPERATOR_CANCELLED;
1608 BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
1609 if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT)) {
1610 MVertSkin *vs = CustomData_bmesh_get(&bm->vdata,
1613 float avg = (vs->radius[0] + vs->radius[1]) * 0.5f;
1615 vs->radius[0] = vs->radius[1] = avg;
1619 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1620 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1622 return OPERATOR_FINISHED;
1625 void OBJECT_OT_skin_radii_equalize(wmOperatorType *ot)
1627 ot->name = "Skin Radii Equalize";
1628 ot->description = "Make skin radii of selected vertices equal on each axis";
1629 ot->idname = "OBJECT_OT_skin_radii_equalize";
1631 ot->poll = skin_edit_poll;
1632 ot->exec = skin_radii_equalize_exec;
1635 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1638 static void skin_armature_bone_create(Object *skin_ob,
1639 MVert *mvert, MEdge *medge,
1641 BLI_bitmap *edges_visited,
1642 const MeshElemMap *emap,
1643 EditBone *parent_bone,
1648 for (i = 0; i < emap[parent_v].count; i++) {
1649 int endx = emap[parent_v].indices[i];
1650 const MEdge *e = &medge[endx];
1655 /* ignore edge if already visited */
1656 if (BLI_BITMAP_TEST(edges_visited, endx))
1658 BLI_BITMAP_ENABLE(edges_visited, endx);
1660 v = (e->v1 == parent_v ? e->v2 : e->v1);
1662 bone = ED_armature_edit_bone_add(arm, "Bone");
1664 bone->parent = parent_bone;
1665 bone->flag |= BONE_CONNECTED;
1667 copy_v3_v3(bone->head, mvert[parent_v].co);
1668 copy_v3_v3(bone->tail, mvert[v].co);
1669 bone->rad_head = bone->rad_tail = 0.25;
1670 BLI_snprintf(bone->name, sizeof(bone->name), "Bone.%.2d", endx);
1672 /* add bDeformGroup */
1673 if ((dg = BKE_object_defgroup_add_name(skin_ob, bone->name))) {
1674 ED_vgroup_vert_add(skin_ob, dg, parent_v, 1, WEIGHT_REPLACE);
1675 ED_vgroup_vert_add(skin_ob, dg, v, 1, WEIGHT_REPLACE);
1678 skin_armature_bone_create(skin_ob,
1688 static Object *modifier_skin_armature_create(Main *bmain, Scene *scene, SceneLayer *sl, Object *skin_ob)
1690 BLI_bitmap *edges_visited;
1691 DerivedMesh *deform_dm;
1693 Mesh *me = skin_ob->data;
1696 MVertSkin *mvert_skin;
1701 deform_dm = mesh_get_derived_deform(scene, skin_ob, CD_MASK_BAREMESH);
1702 mvert = deform_dm->getVertArray(deform_dm);
1704 /* add vertex weights to original mesh */
1705 CustomData_add_layer(&me->vdata,
1711 arm_ob = BKE_object_add(bmain, scene, sl, OB_ARMATURE, NULL);
1712 BKE_object_transform_copy(arm_ob, skin_ob);
1715 arm_ob->dtx |= OB_DRAWXRAY;
1716 arm->drawtype = ARM_LINE;
1717 arm->edbo = MEM_callocN(sizeof(ListBase), "edbo armature");
1719 mvert_skin = CustomData_get_layer(&me->vdata, CD_MVERT_SKIN);
1720 BKE_mesh_vert_edge_map_create(&emap, &emap_mem,
1721 me->medge, me->totvert, me->totedge);
1723 edges_visited = BLI_BITMAP_NEW(me->totedge, "edge_visited");
1725 /* note: we use EditBones here, easier to set them up and use
1726 * edit-armature functions to convert back to regular bones */
1727 for (v = 0; v < me->totvert; v++) {
1728 if (mvert_skin[v].flag & MVERT_SKIN_ROOT) {
1729 EditBone *bone = NULL;
1731 /* Unless the skin root has just one adjacent edge, create
1732 * a fake root bone (have it going off in the Y direction
1734 if (emap[v].count > 1) {
1735 bone = ED_armature_edit_bone_add(arm, "Bone");
1737 copy_v3_v3(bone->head, me->mvert[v].co);
1738 copy_v3_v3(bone->tail, me->mvert[v].co);
1740 bone->head[1] = 1.0f;
1741 bone->rad_head = bone->rad_tail = 0.25;
1744 if (emap[v].count >= 1) {
1745 skin_armature_bone_create(skin_ob,
1756 MEM_freeN(edges_visited);
1758 MEM_freeN(emap_mem);
1760 ED_armature_from_edit(arm);
1761 ED_armature_edit_free(arm);
1766 static int skin_armature_create_exec(bContext *C, wmOperator *op)
1768 Main *bmain = CTX_data_main(C);
1769 Scene *scene = CTX_data_scene(C);
1770 SceneLayer *sl = CTX_data_scene_layer(C);
1771 Object *ob = CTX_data_active_object(C), *arm_ob;
1772 Mesh *me = ob->data;
1773 ModifierData *skin_md;
1774 ArmatureModifierData *arm_md;
1776 if (!CustomData_has_layer(&me->vdata, CD_MVERT_SKIN)) {
1777 BKE_reportf(op->reports, RPT_WARNING, "Mesh '%s' has no skin vertex data", me->id.name + 2);
1778 return OPERATOR_CANCELLED;
1781 /* create new armature */
1782 arm_ob = modifier_skin_armature_create(bmain, scene, sl, ob);
1784 /* add a modifier to connect the new armature to the mesh */
1785 arm_md = (ArmatureModifierData *)modifier_new(eModifierType_Armature);
1787 skin_md = edit_modifier_property_get(op, ob, eModifierType_Skin);
1788 BLI_insertlinkafter(&ob->modifiers, skin_md, arm_md);
1790 arm_md->object = arm_ob;
1791 arm_md->deformflag = ARM_DEF_VGROUP | ARM_DEF_QUATERNION;
1792 DAG_relations_tag_update(bmain);
1793 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1796 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1798 return OPERATOR_FINISHED;
1801 static int skin_armature_create_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1803 if (edit_modifier_invoke_properties(C, op))
1804 return skin_armature_create_exec(C, op);
1806 return OPERATOR_CANCELLED;
1809 void OBJECT_OT_skin_armature_create(wmOperatorType *ot)
1811 ot->name = "Skin Armature Create";
1812 ot->description = "Create an armature that parallels the skin layout";
1813 ot->idname = "OBJECT_OT_skin_armature_create";
1815 ot->poll = skin_poll;
1816 ot->invoke = skin_armature_create_invoke;
1817 ot->exec = skin_armature_create_exec;
1820 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1821 edit_modifier_properties(ot);
1823 /************************ delta mush bind operator *********************/
1825 static int correctivesmooth_poll(bContext *C)
1827 return edit_modifier_poll_generic(C, &RNA_CorrectiveSmoothModifier, 0);
1830 static int correctivesmooth_bind_exec(bContext *C, wmOperator *op)
1832 Scene *scene = CTX_data_scene(C);
1833 Object *ob = ED_object_active_context(C);
1834 CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)edit_modifier_property_get(op, ob, eModifierType_CorrectiveSmooth);
1838 return OPERATOR_CANCELLED;
1841 if (!modifier_isEnabled(scene, &csmd->modifier, eModifierMode_Realtime)) {
1842 BKE_report(op->reports, RPT_ERROR, "Modifier is disabled");
1843 return OPERATOR_CANCELLED;
1846 is_bind = (csmd->bind_coords != NULL);
1848 MEM_SAFE_FREE(csmd->bind_coords);
1849 MEM_SAFE_FREE(csmd->delta_cache);
1853 csmd->bind_coords_num = 0;
1856 /* signal to modifier to recalculate */
1857 csmd->bind_coords_num = (unsigned int)-1;
1860 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1861 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1863 return OPERATOR_FINISHED;
1866 static int correctivesmooth_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1868 if (edit_modifier_invoke_properties(C, op))
1869 return correctivesmooth_bind_exec(C, op);
1871 return OPERATOR_CANCELLED;
1874 void OBJECT_OT_correctivesmooth_bind(wmOperatorType *ot)
1877 ot->name = "Corrective Smooth Bind";
1878 ot->description = "Bind base pose in Corrective Smooth modifier";
1879 ot->idname = "OBJECT_OT_correctivesmooth_bind";
1882 ot->poll = correctivesmooth_poll;
1883 ot->invoke = correctivesmooth_bind_invoke;
1884 ot->exec = correctivesmooth_bind_exec;
1887 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1888 edit_modifier_properties(ot);
1891 /************************ mdef bind operator *********************/
1893 static int meshdeform_poll(bContext *C)
1895 return edit_modifier_poll_generic(C, &RNA_MeshDeformModifier, 0);
1898 static int meshdeform_bind_exec(bContext *C, wmOperator *op)
1900 Scene *scene = CTX_data_scene(C);
1901 Object *ob = ED_object_active_context(C);
1902 MeshDeformModifierData *mmd = (MeshDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_MeshDeform);
1905 return OPERATOR_CANCELLED;
1907 if (mmd->bindcagecos) {
1908 MEM_freeN(mmd->bindcagecos);
1909 if (mmd->dyngrid) MEM_freeN(mmd->dyngrid);
1910 if (mmd->dyninfluences) MEM_freeN(mmd->dyninfluences);
1911 if (mmd->bindinfluences) MEM_freeN(mmd->bindinfluences);
1912 if (mmd->bindoffsets) MEM_freeN(mmd->bindoffsets);
1913 if (mmd->dynverts) MEM_freeN(mmd->dynverts);
1914 if (mmd->bindweights) MEM_freeN(mmd->bindweights); /* deprecated */
1915 if (mmd->bindcos) MEM_freeN(mmd->bindcos); /* deprecated */
1917 mmd->bindcagecos = NULL;
1918 mmd->dyngrid = NULL;
1919 mmd->dyninfluences = NULL;
1920 mmd->bindinfluences = NULL;
1921 mmd->bindoffsets = NULL;
1922 mmd->dynverts = NULL;
1923 mmd->bindweights = NULL; /* deprecated */
1924 mmd->bindcos = NULL; /* deprecated */
1926 mmd->totcagevert = 0;
1927 mmd->totinfluence = 0;
1929 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1930 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
1934 int mode = mmd->modifier.mode;
1936 /* force modifier to run, it will call binding routine */
1937 mmd->bindfunc = mesh_deform_bind;
1938 mmd->modifier.mode |= eModifierMode_Realtime;
1940 if (ob->type == OB_MESH) {
1941 dm = mesh_create_derived_view(scene, ob, 0);
1944 else if (ob->type == OB_LATTICE) {
1945 BKE_lattice_modifiers_calc(scene, ob);
1947 else if (ob->type == OB_MBALL) {
1948 BKE_displist_make_mball(CTX_data_main(C)->eval_ctx, scene, ob);
1950 else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
1951 BKE_displist_make_curveTypes(scene, ob, 0);
1954 mmd->bindfunc = NULL;
1955 mmd->modifier.mode = mode;
1958 return OPERATOR_FINISHED;
1961 static int meshdeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1963 if (edit_modifier_invoke_properties(C, op))
1964 return meshdeform_bind_exec(C, op);
1966 return OPERATOR_CANCELLED;
1969 void OBJECT_OT_meshdeform_bind(wmOperatorType *ot)
1972 ot->name = "Mesh Deform Bind";
1973 ot->description = "Bind mesh to cage in mesh deform modifier";
1974 ot->idname = "OBJECT_OT_meshdeform_bind";
1977 ot->poll = meshdeform_poll;
1978 ot->invoke = meshdeform_bind_invoke;
1979 ot->exec = meshdeform_bind_exec;
1982 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
1983 edit_modifier_properties(ot);
1986 /****************** explode refresh operator *********************/
1988 static int explode_poll(bContext *C)
1990 return edit_modifier_poll_generic(C, &RNA_ExplodeModifier, 0);
1993 static int explode_refresh_exec(bContext *C, wmOperator *op)
1995 Object *ob = ED_object_active_context(C);
1996 ExplodeModifierData *emd = (ExplodeModifierData *)edit_modifier_property_get(op, ob, eModifierType_Explode);
1999 return OPERATOR_CANCELLED;
2001 emd->flag |= eExplodeFlag_CalcFaces;
2003 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2004 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
2006 return OPERATOR_FINISHED;
2009 static int explode_refresh_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
2011 if (edit_modifier_invoke_properties(C, op))
2012 return explode_refresh_exec(C, op);
2014 return OPERATOR_CANCELLED;
2018 void OBJECT_OT_explode_refresh(wmOperatorType *ot)
2020 ot->name = "Explode Refresh";
2021 ot->description = "Refresh data in the Explode modifier";
2022 ot->idname = "OBJECT_OT_explode_refresh";
2024 ot->poll = explode_poll;
2025 ot->invoke = explode_refresh_invoke;
2026 ot->exec = explode_refresh_exec;
2029 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
2030 edit_modifier_properties(ot);
2034 /****************** ocean bake operator *********************/
2036 static int ocean_bake_poll(bContext *C)
2038 return edit_modifier_poll_generic(C, &RNA_OceanModifier, 0);
2041 /* copied from init_ocean_modifier, MOD_ocean.c */
2042 static void init_ocean_modifier_bake(struct Ocean *oc, struct OceanModifierData *omd)
2044 int do_heightfield, do_chop, do_normals, do_jacobian;
2046 if (!omd || !oc) return;
2048 do_heightfield = true;
2049 do_chop = (omd->chop_amount > 0);
2050 do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS);
2051 do_jacobian = (omd->flag & MOD_OCEAN_GENERATE_FOAM);
2053 BKE_ocean_init(oc, omd->resolution * omd->resolution, omd->resolution * omd->resolution, omd->spatial_size, omd->spatial_size,
2054 omd->wind_velocity, omd->smallest_wave, 1.0, omd->wave_direction, omd->damp, omd->wave_alignment,
2055 omd->depth, omd->time,
2056 do_heightfield, do_chop, do_normals, do_jacobian,
2060 typedef struct OceanBakeJob {
2063 short *stop, *do_update;
2066 struct OceanCache *och;
2067 struct Ocean *ocean;
2068 struct OceanModifierData *omd;
2071 static void oceanbake_free(void *customdata)
2073 OceanBakeJob *oj = customdata;
2077 /* called by oceanbake, only to check job 'stop' value */
2078 static int oceanbake_breakjob(void *UNUSED(customdata))
2080 //OceanBakeJob *ob = (OceanBakeJob *)customdata;
2081 //return *(ob->stop);
2083 /* this is not nice yet, need to make the jobs list template better
2084 * for identifying/acting upon various different jobs */
2085 /* but for now we'll reuse the render break... */
2086 return (G.is_break);
2089 /* called by oceanbake, wmJob sends notifier */
2090 static void oceanbake_update(void *customdata, float progress, int *cancel)
2092 OceanBakeJob *oj = customdata;
2094 if (oceanbake_breakjob(oj))
2097 *(oj->do_update) = true;
2098 *(oj->progress) = progress;
2101 static void oceanbake_startjob(void *customdata, short *stop, short *do_update, float *progress)
2103 OceanBakeJob *oj = customdata;
2106 oj->do_update = do_update;
2107 oj->progress = progress;
2109 G.is_break = false; /* XXX shared with render - replace with job 'stop' switch */
2111 BKE_ocean_bake(oj->ocean, oj->och, oceanbake_update, (void *)oj);
2117 static void oceanbake_endjob(void *customdata)
2119 OceanBakeJob *oj = customdata;
2122 BKE_ocean_free(oj->ocean);
2126 oj->omd->oceancache = oj->och;
2127 oj->omd->cached = true;
2130 static int ocean_bake_exec(bContext *C, wmOperator *op)
2132 Object *ob = ED_object_active_context(C);
2133 OceanModifierData *omd = (OceanModifierData *)edit_modifier_property_get(op, ob, eModifierType_Ocean);
2134 Scene *scene = CTX_data_scene(C);
2136 struct Ocean *ocean;
2138 const bool free = RNA_boolean_get(op->ptr, "free");
2144 return OPERATOR_CANCELLED;
2147 omd->refresh |= MOD_OCEAN_REFRESH_CLEAR_CACHE;
2148 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2149 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
2150 return OPERATOR_FINISHED;
2153 och = BKE_ocean_init_cache(omd->cachepath, modifier_path_relbase(ob),
2154 omd->bakestart, omd->bakeend, omd->wave_scale,
2155 omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution);
2157 och->time = MEM_mallocN(och->duration * sizeof(float), "foam bake time");
2159 cfra = scene->r.cfra;
2161 /* precalculate time variable before baking */
2162 for (f = omd->bakestart; f <= omd->bakeend; f++) {
2163 /* from physics_fluid.c:
2165 * XXX: This can't be used due to an anim sys optimization that ignores recalc object animation,
2166 * leaving it for the depgraph (this ignores object animation such as modifier properties though... :/ )
2167 * --> BKE_animsys_evaluate_all_animation(G.main, eval_time);
2168 * This doesn't work with drivers:
2169 * --> BKE_animsys_evaluate_animdata(&fsDomain->id, fsDomain->adt, eval_time, ADT_RECALC_ALL);
2172 /* Modifying the global scene isn't nice, but we can do it in
2173 * this part of the process before a threaded job is created */
2175 //scene->r.cfra = f;
2176 //ED_update_for_newframe(CTX_data_main(C), scene, 1);
2178 /* ok, this doesn't work with drivers, but is way faster.
2179 * let's use this for now and hope nobody wants to drive the time value... */
2180 BKE_animsys_evaluate_animdata(scene, (ID *)ob, ob->adt, f, ADT_RECALC_ANIM);
2182 och->time[i] = omd->time;
2186 /* make a copy of ocean to use for baking - threadsafety */
2187 ocean = BKE_ocean_add();
2188 init_ocean_modifier_bake(ocean, omd);
2191 BKE_ocean_bake(ocean, och);
2193 omd->oceancache = och;
2196 scene->r.cfra = cfra;
2198 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2199 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
2204 scene->r.cfra = cfra;
2207 wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Ocean Simulation",
2208 WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_SIM_OCEAN);
2209 oj = MEM_callocN(sizeof(OceanBakeJob), "ocean bake job");
2214 WM_jobs_customdata_set(wm_job, oj, oceanbake_free);
2215 WM_jobs_timer(wm_job, 0.1, NC_OBJECT | ND_MODIFIER, NC_OBJECT | ND_MODIFIER);
2216 WM_jobs_callbacks(wm_job, oceanbake_startjob, NULL, NULL, oceanbake_endjob);
2218 WM_jobs_start(CTX_wm_manager(C), wm_job);
2222 return OPERATOR_FINISHED;
2225 static int ocean_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
2227 if (edit_modifier_invoke_properties(C, op))
2228 return ocean_bake_exec(C, op);
2230 return OPERATOR_CANCELLED;
2234 void OBJECT_OT_ocean_bake(wmOperatorType *ot)
2236 ot->name = "Bake Ocean";
2237 ot->description = "Bake an image sequence of ocean data";
2238 ot->idname = "OBJECT_OT_ocean_bake";
2240 ot->poll = ocean_bake_poll;
2241 ot->invoke = ocean_bake_invoke;
2242 ot->exec = ocean_bake_exec;
2245 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
2246 edit_modifier_properties(ot);
2248 RNA_def_boolean(ot->srna, "free", false, "Free", "Free the bake, rather than generating it");
2251 /************************ LaplacianDeform bind operator *********************/
2253 static int laplaciandeform_poll(bContext *C)
2255 return edit_modifier_poll_generic(C, &RNA_LaplacianDeformModifier, 0);
2258 static int laplaciandeform_bind_exec(bContext *C, wmOperator *op)
2260 Object *ob = ED_object_active_context(C);
2261 LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_LaplacianDeform);
2264 return OPERATOR_CANCELLED;
2265 if (lmd->flag & MOD_LAPLACIANDEFORM_BIND) {
2266 lmd->flag &= ~MOD_LAPLACIANDEFORM_BIND;
2269 lmd->flag |= MOD_LAPLACIANDEFORM_BIND;
2271 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2272 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
2273 return OPERATOR_FINISHED;
2276 static int laplaciandeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
2278 if (edit_modifier_invoke_properties(C, op))
2279 return laplaciandeform_bind_exec(C, op);
2281 return OPERATOR_CANCELLED;
2284 void OBJECT_OT_laplaciandeform_bind(wmOperatorType *ot)
2287 ot->name = "Laplacian Deform Bind";
2288 ot->description = "Bind mesh to system in laplacian deform modifier";
2289 ot->idname = "OBJECT_OT_laplaciandeform_bind";
2292 ot->poll = laplaciandeform_poll;
2293 ot->invoke = laplaciandeform_bind_invoke;
2294 ot->exec = laplaciandeform_bind_exec;
2297 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
2298 edit_modifier_properties(ot);
2301 /************************ sdef bind operator *********************/
2303 static int surfacedeform_bind_poll(bContext *C)
2305 return edit_modifier_poll_generic(C, &RNA_SurfaceDeformModifier, 0);
2308 static int surfacedeform_bind_exec(bContext *C, wmOperator *op)
2310 Object *ob = ED_object_active_context(C);
2311 SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_SurfaceDeform);
2314 return OPERATOR_CANCELLED;
2316 if (smd->flags & MOD_SDEF_BIND) {
2317 smd->flags &= ~MOD_SDEF_BIND;
2319 else if (smd->target) {
2320 smd->flags |= MOD_SDEF_BIND;
2323 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2324 WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
2326 return OPERATOR_FINISHED;
2329 static int surfacedeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
2331 if (edit_modifier_invoke_properties(C, op))
2332 return surfacedeform_bind_exec(C, op);
2334 return OPERATOR_CANCELLED;
2337 void OBJECT_OT_surfacedeform_bind(wmOperatorType *ot)
2340 ot->name = "Surface Deform Bind";
2341 ot->description = "Bind mesh to target in surface deform modifier";
2342 ot->idname = "OBJECT_OT_surfacedeform_bind";
2345 ot->poll = surfacedeform_bind_poll;
2346 ot->invoke = surfacedeform_bind_invoke;
2347 ot->exec = surfacedeform_bind_exec;
2350 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
2351 edit_modifier_properties(ot);