d90869a1059e0d437a8f278dec2b9eefe43e38c7
[blender-staging.git] / source / blender / editors / interface / interface_templates.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * Contributor(s): Blender Foundation 2009.
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 #include <stdlib.h>
26
27 #include "MEM_guardedalloc.h"
28
29 #include "BLI_string.h"
30
31 #include "BKE_context.h"
32 #include "BKE_library.h"
33 #include "BKE_utildefines.h"
34
35 #include "ED_screen.h"
36
37 #include "RNA_access.h"
38
39 #include "WM_api.h"
40 #include "WM_types.h"
41
42 #include "UI_interface.h"
43 #include "UI_resources.h"
44
45 void ui_template_fix_linking()
46 {
47 }
48
49 /********************** Header Template *************************/
50
51 void uiTemplateHeader(uiLayout *layout, bContext *C)
52 {
53         uiBlock *block;
54         
55         block= uiLayoutFreeBlock(layout);
56         ED_area_header_standardbuttons(C, block, 0);
57 }
58
59 /******************* Header ID Template ************************/
60
61 typedef struct TemplateHeaderID {
62         PointerRNA ptr;
63         PropertyRNA *prop;
64
65         int flag;
66         short browse;
67
68         char newop[256];
69         char openop[256];
70         char unlinkop[256];
71 } TemplateHeaderID;
72
73 static void template_header_id_cb(bContext *C, void *arg_litem, void *arg_event)
74 {
75         TemplateHeaderID *template= (TemplateHeaderID*)arg_litem;
76         PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop);
77         ID *idtest, *id= idptr.data;
78         ListBase *lb= wich_libbase(CTX_data_main(C), ID_TXT);
79         int nr, event= GET_INT_FROM_POINTER(arg_event);
80         
81         if(event == UI_ID_BROWSE && template->browse == 32767)
82                 event= UI_ID_ADD_NEW;
83         else if(event == UI_ID_BROWSE && template->browse == 32766)
84                 event= UI_ID_OPEN;
85
86         switch(event) {
87                 case UI_ID_BROWSE: {
88                         if(template->browse== -2) {
89                                 /* XXX implement or find a replacement
90                                  * activate_databrowse((ID *)G.buts->lockpoin, GS(id->name), 0, B_MESHBROWSE, &template->browse, do_global_buttons); */
91                                 return;
92                         }
93                         if(template->browse < 0)
94                                 return;
95
96                         for(idtest=lb->first, nr=1; idtest; idtest=idtest->next, nr++) {
97                                 if(nr==template->browse) {
98                                         if(id == idtest)
99                                                 return;
100
101                                         id= idtest;
102                                         RNA_id_pointer_create(id, &idptr);
103                                         RNA_property_pointer_set(&template->ptr, template->prop, idptr);
104                                         RNA_property_update(C, &template->ptr, template->prop);
105                                         /* XXX */
106
107                                         break;
108                                 }
109                         }
110                         break;
111                 }
112 #if 0
113                 case UI_ID_DELETE:
114                         id= NULL;
115                         break;
116                 case UI_ID_FAKE_USER:
117                         if(id) {
118                                 if(id->flag & LIB_FAKEUSER) id->us++;
119                                 else id->us--;
120                         }
121                         else return;
122                         break;
123 #endif
124                 case UI_ID_PIN:
125                         break;
126                 case UI_ID_ADD_NEW:
127                         WM_operator_name_call(C, template->newop, WM_OP_INVOKE_REGION_WIN, NULL);
128                         break;
129                 case UI_ID_OPEN:
130                         WM_operator_name_call(C, template->openop, WM_OP_INVOKE_REGION_WIN, NULL);
131                         break;
132 #if 0
133                 case UI_ID_ALONE:
134                         if(!id || id->us < 1)
135                                 return;
136                         break;
137                 case UI_ID_LOCAL:
138                         if(!id || id->us < 1)
139                                 return;
140                         break;
141                 case UI_ID_AUTO_NAME:
142                         break;
143 #endif
144         }
145 }
146
147 static void template_header_ID(bContext *C, uiBlock *block, TemplateHeaderID *template)
148 {
149         uiBut *but;
150         TemplateHeaderID *duptemplate;
151         PointerRNA idptr;
152         ListBase *lb;
153         int x= 0, y= 0;
154
155         idptr= RNA_property_pointer_get(&template->ptr, template->prop);
156         lb= wich_libbase(CTX_data_main(C), ID_TXT);
157
158         uiBlockBeginAlign(block);
159         if(template->flag & UI_ID_BROWSE) {
160                 char *extrastr, *str;
161                 
162                 if((template->flag & UI_ID_ADD_NEW) && (template->flag && UI_ID_OPEN))
163                         extrastr= "OPEN NEW %x 32766 |ADD NEW %x 32767";
164                 else if(template->flag & UI_ID_ADD_NEW)
165                         extrastr= "ADD NEW %x 32767";
166                 else if(template->flag & UI_ID_OPEN)
167                         extrastr= "OPEN NEW %x 32766";
168                 else
169                         extrastr= NULL;
170
171                 duptemplate= MEM_dupallocN(template);
172                 IDnames_to_pupstring(&str, NULL, extrastr, lb, idptr.data, &duptemplate->browse);
173
174                 but= uiDefButS(block, MENU, 0, str, x, y, UI_UNIT_X, UI_UNIT_Y, &duptemplate->browse, 0, 0, 0, 0, "Browse existing choices, or add new");
175                 uiButSetNFunc(but, template_header_id_cb, duptemplate, SET_INT_IN_POINTER(UI_ID_BROWSE));
176                 x+= UI_UNIT_X;
177         
178                 MEM_freeN(str);
179         }
180
181         /* text button with name */
182         if(idptr.data) {
183                 char name[64];
184
185                 text_idbutton(idptr.data, name);
186                 but= uiDefButR(block, TEX, 0, name, x, y, UI_UNIT_X*6, UI_UNIT_Y, &idptr, "name", -1, 0, 0, -1, -1, NULL);
187                 uiButSetNFunc(but, template_header_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME));
188                 x += UI_UNIT_X*6;
189
190                 /* delete button */
191                 if(template->flag & UI_ID_DELETE) {
192                         but= uiDefIconButO(block, BUT, template->unlinkop, WM_OP_EXEC_REGION_WIN, ICON_X, x, y, UI_UNIT_X, UI_UNIT_Y, NULL);
193                         x += UI_UNIT_X;
194                 }
195         }
196         uiBlockEndAlign(block);
197 }
198
199 void uiTemplateHeaderID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop)
200 {
201         TemplateHeaderID *template;
202         uiBlock *block;
203         PropertyRNA *prop;
204
205         if(!ptr->data)
206                 return;
207
208         prop= RNA_struct_find_property(ptr, propname);
209
210         if(!prop) {
211                 printf("uiTemplateHeaderID: property not found: %s\n", propname);
212                 return;
213         }
214
215         template= MEM_callocN(sizeof(TemplateHeaderID), "TemplateHeaderID");
216         template->ptr= *ptr;
217         template->prop= prop;
218         template->flag= UI_ID_BROWSE|UI_ID_RENAME;
219
220         if(newop) {
221                 template->flag |= UI_ID_ADD_NEW;
222                 BLI_strncpy(template->newop, newop, sizeof(template->newop));
223         }
224         if(openop) {
225                 template->flag |= UI_ID_OPEN;
226                 BLI_strncpy(template->openop, openop, sizeof(template->openop));
227         }
228         if(unlinkop) {
229                 template->flag |= UI_ID_DELETE;
230                 BLI_strncpy(template->unlinkop, unlinkop, sizeof(template->unlinkop));
231         }
232
233         block= uiLayoutFreeBlock(layout);
234         template_header_ID(C, block, template);
235
236         MEM_freeN(template);
237 }
238
239 /************************ Modifier Template *************************/
240
241 #define ERROR_LIBDATA_MESSAGE "Can't edit external libdata"
242
243 #define B_NOP                           0
244 #define B_MODIFIER_RECALC       1
245 #define B_MODIFIER_REDRAW       2
246 #define B_CHANGEDEP                     3
247 #define B_ARM_RECALCDATA        4
248
249 #include <string.h>
250
251 #include "DNA_armature_types.h"
252 #include "DNA_curve_types.h"
253 #include "DNA_object_force.h"
254 #include "DNA_object_types.h"
255 #include "DNA_mesh_types.h"
256 #include "DNA_meshdata_types.h"
257 #include "DNA_modifier_types.h"
258 #include "DNA_particle_types.h"
259 #include "DNA_scene_types.h"
260
261 #include "BKE_bmesh.h"
262 #include "BKE_curve.h"
263 #include "BKE_depsgraph.h"
264 #include "BKE_DerivedMesh.h"
265 #include "BKE_displist.h"
266 #include "BKE_global.h"
267 #include "BKE_lattice.h"
268 #include "BKE_main.h"
269 #include "BKE_mesh.h"
270 #include "BKE_modifier.h"
271 #include "BKE_object.h"
272 #include "BKE_particle.h"
273 #include "BKE_report.h"
274
275 #include "UI_resources.h"
276 #include "ED_util.h"
277
278 #include "BLI_arithb.h"
279 #include "BLI_listbase.h"
280
281 #include "ED_object.h"
282
283 void do_modifier_panels(bContext *C, void *arg, int event)
284 {
285         Scene *scene= CTX_data_scene(C);
286         Object *ob = CTX_data_active_object(C);
287
288         switch(event) {
289         case B_MODIFIER_REDRAW:
290                 WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
291                 break;
292
293         case B_MODIFIER_RECALC:
294                 WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
295                 DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
296                 object_handle_update(scene, ob);
297                 // XXX countall();
298                 break;
299         }
300 }
301
302 static void modifiers_del(bContext *C, void *ob_v, void *md_v)
303 {
304         ReportList reports;
305
306         BKE_reports_init(&reports, RPT_STORE);
307
308         if(ED_object_modifier_delete(&reports, ob_v, md_v))
309                 ED_undo_push(C, "Delete modifier");
310         else
311                 uiPupMenuReports(C, &reports);
312
313         BKE_reports_clear(&reports);
314 }
315
316 static void modifiers_moveUp(bContext *C, void *ob_v, void *md_v)
317 {
318         ReportList reports;
319
320         BKE_reports_init(&reports, RPT_STORE);
321
322         if(ED_object_modifier_move_up(&reports, ob_v, md_v))
323                 ED_undo_push(C, "Move modifier");
324         else
325                 uiPupMenuReports(C, &reports);
326
327         BKE_reports_clear(&reports);
328 }
329
330 static void modifiers_moveDown(bContext *C, void *ob_v, void *md_v)
331 {
332         ReportList reports;
333
334         BKE_reports_init(&reports, RPT_STORE);
335
336         if(ED_object_modifier_move_down(&reports, ob_v, md_v))
337                 ED_undo_push(C, "Move modifier");
338         else
339                 uiPupMenuReports(C, &reports);
340
341         BKE_reports_clear(&reports);
342 }
343
344 static void modifier_testLatticeObj(bContext *C, char *name, ID **idpp)
345 {
346         Main *bmain= CTX_data_main(C);
347         ID *id;
348
349         for (id= bmain->object.first; id; id= id->next) {
350                 if( strcmp(name, id->name+2)==0 ) {
351                         if (((Object *)id)->type != OB_LATTICE) {
352                                 uiPupMenuError(C, "Lattice deform object must be a lattice");
353                                 break;
354                         } 
355                         *idpp= id;
356                         return;
357                 }
358         }
359         *idpp= 0;
360 }
361
362 static void modifier_testCurveObj(bContext *C, char *name, ID **idpp)
363 {
364         Main *bmain= CTX_data_main(C);
365         ID *id;
366
367         for (id= bmain->object.first; id; id= id->next) {
368                 if( strcmp(name, id->name+2)==0 ) {
369                         if (((Object *)id)->type != OB_CURVE) {
370                                 uiPupMenuError(C, "Curve deform object must be a curve");
371                                 break;
372                         } 
373                         *idpp= id;
374                         return;
375                 }
376         }
377         *idpp= 0;
378 }
379
380 static void modifier_testMeshObj(bContext *C, char *name, ID **idpp)
381 {
382         Main *bmain= CTX_data_main(C);
383         Object *obact= CTX_data_active_object(C);
384         ID *id;
385
386         for (id= bmain->object.first; id; id= id->next) {
387                 /* no boolean on its own object */
388                 if(id != (ID *)obact) {
389                         if( strcmp(name, id->name+2)==0 ) {
390                                 if (((Object *)id)->type != OB_MESH) {
391                                         uiPupMenuError(C, "Boolean modifier object must be a mesh");
392                                         break;
393                                 } 
394                                 *idpp= id;
395                                 return;
396                         }
397                 }
398         }
399         *idpp= NULL;
400 }
401
402 static void modifier_testArmatureObj(bContext *C, char *name, ID **idpp)
403 {
404         Main *bmain= CTX_data_main(C);
405         ID *id;
406
407         for (id= bmain->object.first; id; id= id->next) {
408                 if( strcmp(name, id->name+2)==0 ) {
409                         if (((Object *)id)->type != OB_ARMATURE) {
410                                 uiPupMenuError(C, "Armature deform object must be an armature");
411                                 break;
412                         } 
413                         *idpp= id;
414                         return;
415                 }
416         }
417         *idpp= 0;
418 }
419
420 static void modifier_testTexture(bContext *C, char *name, ID **idpp)
421 {
422         Main *bmain= CTX_data_main(C);
423         ID *id;
424
425         for(id = bmain->tex.first; id; id = id->next) {
426                 if(strcmp(name, id->name + 2) == 0) {
427                         *idpp = id;
428                         /* texture gets user, objects not: delete object = clear modifier */
429                         id_us_plus(id);
430                         return;
431                 }
432         }
433         *idpp = 0;
434 }
435
436 #if 0 /* this is currently unused, but could be useful in the future */
437 static void modifier_testMaterial(bContext *C, char *name, ID **idpp)
438 {
439         Main *bmain= CTX_data_main(C);
440         ID *id;
441
442         for(id = bmain->mat.first; id; id = id->next) {
443                 if(strcmp(name, id->name + 2) == 0) {
444                         *idpp = id;
445                         return;
446                 }
447         }
448         *idpp = 0;
449 }
450 #endif
451
452 static void modifier_testImage(bContext *C, char *name, ID **idpp)
453 {
454         Main *bmain= CTX_data_main(C);
455         ID *id;
456
457         for(id = bmain->image.first; id; id = id->next) {
458                 if(strcmp(name, id->name + 2) == 0) {
459                         *idpp = id;
460                         return;
461                 }
462         }
463         *idpp = 0;
464 }
465
466 /* autocomplete callback for ID buttons */
467 void autocomplete_image(bContext *C, char *str, void *arg_v)
468 {
469         Main *bmain= CTX_data_main(C);
470
471         /* search if str matches the beginning of an ID struct */
472         if(str[0]) {
473                 AutoComplete *autocpl = autocomplete_begin(str, 22);
474                 ID *id;
475
476                 for(id = bmain->image.first; id; id = id->next)
477                         autocomplete_do_name(autocpl, id->name+2);
478
479                 autocomplete_end(autocpl, str);
480         }
481 }
482
483 /* autocomplete callback for ID buttons */
484 void autocomplete_meshob(bContext *C, char *str, void *arg_v)
485 {
486         Main *bmain= CTX_data_main(C);
487
488         /* search if str matches the beginning of an ID struct */
489         if(str[0]) {
490                 AutoComplete *autocpl = autocomplete_begin(str, 22);
491                 ID *id;
492
493                 for(id = bmain->object.first; id; id = id->next)
494                         if(((Object *)id)->type == OB_MESH)
495                                 autocomplete_do_name(autocpl, id->name+2);
496
497                 autocomplete_end(autocpl, str);
498         }
499 }
500
501 static void modifiers_convertParticles(bContext *C, void *obv, void *mdv)
502 {
503         Scene *scene= CTX_data_scene(C);
504         ReportList reports;
505
506         BKE_reports_init(&reports, RPT_STORE);
507
508         if(ED_object_modifier_convert(&reports, scene, obv, mdv))
509                 ED_undo_push(C, "Convert particles to mesh object(s).");
510         else
511                 uiPupMenuReports(C, &reports);
512
513         BKE_reports_clear(&reports);
514 }
515
516 static void modifiers_applyModifier(bContext *C, void *obv, void *mdv)
517 {
518         Scene *scene= CTX_data_scene(C);
519         ReportList reports;
520
521         BKE_reports_init(&reports, RPT_STORE);
522
523         if(ED_object_modifier_apply(&reports, scene, obv, mdv))
524                 ED_undo_push(C, "Apply modifier");
525         else
526                 uiPupMenuReports(C, &reports);
527
528         BKE_reports_clear(&reports);
529 }
530
531 static void modifiers_copyModifier(bContext *C, void *ob_v, void *md_v)
532 {
533         ReportList reports;
534
535         BKE_reports_init(&reports, RPT_STORE);
536
537         if(ED_object_modifier_copy(&reports, ob_v, md_v))
538                 ED_undo_push(C, "Copy modifier");
539         else
540                 uiPupMenuReports(C, &reports);
541
542         BKE_reports_clear(&reports);
543 }
544
545 static void modifiers_setOnCage(bContext *C, void *ob_v, void *md_v)
546 {
547         Object *ob = ob_v;
548         ModifierData *md;
549         
550         int i, cageIndex = modifiers_getCageIndex(ob, NULL );
551
552         for( i = 0, md=ob->modifiers.first; md; ++i, md=md->next )
553                 if( md == md_v ) {
554                         if( i >= cageIndex )
555                                 md->mode ^= eModifierMode_OnCage;
556                         break;
557                 }
558 }
559
560 static void modifiers_clearHookOffset(bContext *C, void *ob_v, void *md_v)
561 {
562         Object *ob = ob_v;
563         ModifierData *md = md_v;
564         HookModifierData *hmd = (HookModifierData*) md;
565         
566         if (hmd->object) {
567                 Mat4Invert(hmd->object->imat, hmd->object->obmat);
568                 Mat4MulSerie(hmd->parentinv, hmd->object->imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL);
569                 ED_undo_push(C, "Clear hook offset");
570         }
571 }
572
573 static void modifiers_cursorHookCenter(bContext *C, void *ob_v, void *md_v)
574 {
575         /* XXX 
576         Object *ob = ob_v;
577         ModifierData *md = md_v;
578         HookModifierData *hmd = (HookModifierData*) md;
579
580         if(G.vd) {
581                 float *curs = give_cursor();
582                 float bmat[3][3], imat[3][3];
583
584                 where_is_object(ob);
585         
586                 Mat3CpyMat4(bmat, ob->obmat);
587                 Mat3Inv(imat, bmat);
588
589                 curs= give_cursor();
590                 hmd->cent[0]= curs[0]-ob->obmat[3][0];
591                 hmd->cent[1]= curs[1]-ob->obmat[3][1];
592                 hmd->cent[2]= curs[2]-ob->obmat[3][2];
593                 Mat3MulVecfl(imat, hmd->cent);
594
595                 ED_undo_push(C, "Hook cursor center");
596         }*/
597 }
598
599 static void modifiers_selectHook(bContext *C, void *ob_v, void *md_v)
600 {
601         /* XXX ModifierData *md = md_v;
602         HookModifierData *hmd = (HookModifierData*) md;
603
604         hook_select(hmd);*/
605 }
606
607 static void modifiers_reassignHook(bContext *C, void *ob_v, void *md_v)
608 {
609         /* XXX ModifierData *md = md_v;
610         HookModifierData *hmd = (HookModifierData*) md;
611         float cent[3];
612         int *indexar, tot, ok;
613         char name[32];
614                 
615         ok= hook_getIndexArray(&tot, &indexar, name, cent);
616
617         if (!ok) {
618                 uiPupMenuError(C, "Requires selected vertices or active Vertex Group");
619         } else {
620                 if (hmd->indexar) {
621                         MEM_freeN(hmd->indexar);
622                 }
623
624                 VECCOPY(hmd->cent, cent);
625                 hmd->indexar = indexar;
626                 hmd->totindex = tot;
627         }*/
628 }
629
630 static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v)
631 {
632         Object *ob = ob_v;
633         ModifierData *md = md_v;
634         ModifierData *nmd = modifier_new(md->type);
635
636         modifier_copyData(md, nmd);
637         nmd->mode &= ~eModifierMode_Virtual;
638
639         BLI_addhead(&ob->modifiers, nmd);
640
641         ob->partype = PAROBJECT;
642
643         ED_undo_push(C, "Modifier convert to real");
644 }
645
646 static void build_uvlayer_menu_vars(CustomData *data, char **menu_string,
647                                     int *uvlayer_tmp, char *uvlayer_name)
648 {
649         char strtmp[38];
650         int totuv, i;
651         CustomDataLayer *layer
652                     = &data->layers[CustomData_get_layer_index(data, CD_MTFACE)];
653
654         *uvlayer_tmp = -1;
655
656         totuv = CustomData_number_of_layers(data, CD_MTFACE);
657
658         *menu_string = MEM_callocN(sizeof(**menu_string) * (totuv * 38 + 10),
659                                    "menu_string");
660         sprintf(*menu_string, "UV Layer%%t");
661         for(i = 0; i < totuv; i++) {
662                 /* assign first layer as uvlayer_name if uvlayer_name is null. */
663                 if(strcmp(layer->name, uvlayer_name) == 0) *uvlayer_tmp = i + 1;
664                 sprintf(strtmp, "|%s%%x%d", layer->name, i + 1);
665                 strcat(*menu_string, strtmp);
666                 layer++;
667         }
668
669         /* there is no uvlayer defined, or else it was deleted. Assign active
670          * layer, then recalc modifiers.
671          */
672         if(*uvlayer_tmp == -1) {
673                 if(CustomData_get_active_layer_index(data, CD_MTFACE) != -1) {
674                         *uvlayer_tmp = 1;
675                         layer = data->layers;
676                         for(i = 0; i < CustomData_get_active_layer_index(data, CD_MTFACE);
677                             i++, layer++) {
678                                 if(layer->type == CD_MTFACE) (*uvlayer_tmp)++;
679                         }
680                         strcpy(uvlayer_name, layer->name);
681
682                         /* update the modifiers */
683                         /* XXX do_modifier_panels(B_MODIFIER_RECALC);*/
684                 } else {
685                         /* ok we have no uv layers, so make sure menu button knows that.*/
686                         *uvlayer_tmp = 0;
687                 }
688         }
689 }
690
691 void set_wave_uvlayer(bContext *C, void *arg1, void *arg2)
692 {
693         WaveModifierData *wmd=arg1;
694         CustomDataLayer *layer = arg2;
695
696         /*check we have UV layers*/
697         if (wmd->uvlayer_tmp < 1) return;
698         layer = layer + (wmd->uvlayer_tmp-1);
699         
700         strcpy(wmd->uvlayer_name, layer->name);
701 }
702
703 void set_displace_uvlayer(bContext *C, void *arg1, void *arg2)
704 {
705         DisplaceModifierData *dmd=arg1;
706         CustomDataLayer *layer = arg2;
707
708         /*check we have UV layers*/
709         if (dmd->uvlayer_tmp < 1) return;
710         layer = layer + (dmd->uvlayer_tmp-1);
711         
712         strcpy(dmd->uvlayer_name, layer->name);
713 }
714
715 void set_uvproject_uvlayer(bContext *C, void *arg1, void *arg2)
716 {
717         UVProjectModifierData *umd=arg1;
718         CustomDataLayer *layer = arg2;
719
720         /*check we have UV layers*/
721         if (umd->uvlayer_tmp < 1) return;
722         layer = layer + (umd->uvlayer_tmp-1);
723         
724         strcpy(umd->uvlayer_name, layer->name);
725 }
726
727 static void modifiers_bindMeshDeform(bContext *C, void *ob_v, void *md_v)
728 {
729         Scene *scene= CTX_data_scene(C);
730         MeshDeformModifierData *mmd = (MeshDeformModifierData*) md_v;
731         Object *ob = (Object*)ob_v;
732
733         if(mmd->bindcos) {
734                 if(mmd->bindweights) MEM_freeN(mmd->bindweights);
735                 if(mmd->bindcos) MEM_freeN(mmd->bindcos);
736                 if(mmd->dyngrid) MEM_freeN(mmd->dyngrid);
737                 if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences);
738                 if(mmd->dynverts) MEM_freeN(mmd->dynverts);
739                 mmd->bindweights= NULL;
740                 mmd->bindcos= NULL;
741                 mmd->dyngrid= NULL;
742                 mmd->dyninfluences= NULL;
743                 mmd->dynverts= NULL;
744                 mmd->totvert= 0;
745                 mmd->totcagevert= 0;
746                 mmd->totinfluence= 0;
747         }
748         else {
749                 DerivedMesh *dm;
750                 int mode= mmd->modifier.mode;
751
752                 /* force modifier to run, it will call binding routine */
753                 mmd->needbind= 1;
754                 mmd->modifier.mode |= eModifierMode_Realtime;
755
756                 if(ob->type == OB_MESH) {
757                         dm= mesh_create_derived_view(scene, ob, 0);
758                         dm->release(dm);
759                 }
760                 else if(ob->type == OB_LATTICE) {
761                         lattice_calc_modifiers(scene, ob);
762                 }
763                 else if(ob->type==OB_MBALL) {
764                         makeDispListMBall(scene, ob);
765                 }
766                 else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
767                         makeDispListCurveTypes(scene, ob, 0);
768                 }
769
770                 mmd->needbind= 0;
771                 mmd->modifier.mode= mode;
772         }
773 }
774
775 void modifiers_explodeFacepa(bContext *C, void *arg1, void *arg2)
776 {
777         ExplodeModifierData *emd=arg1;
778
779         emd->flag |= eExplodeFlag_CalcFaces;
780 }
781
782 void modifiers_explodeDelVg(bContext *C, void *arg1, void *arg2)
783 {
784         ExplodeModifierData *emd=arg1;
785         emd->vgroup = 0;
786 }
787
788 static int modifier_is_fluid_particles(ModifierData *md)
789 {
790         if(md->type == eModifierType_ParticleSystem) {
791                 if(((ParticleSystemModifierData *)md)->psys->part->type == PART_FLUID)
792                         return 1;
793         }
794         return 0;
795 }
796
797 static uiLayout *draw_modifier(bContext *C, uiLayout *layout, Object *ob, ModifierData *md, int index, int cageIndex, int lastCageIndex)
798 {
799         Object *obedit= CTX_data_edit_object(C);
800         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
801         uiBut *but;
802         uiBlock *block;
803         uiLayout *column, *row, *result= NULL;
804         int isVirtual = md->mode&eModifierMode_Virtual;
805         int x = 0, y = 0; // XXX , color = md->error?TH_REDALERT:TH_BUT_NEUTRAL;
806         int editing = (obedit==ob);
807         short width = 295, buttonWidth = width-120-10;
808         char str[128];
809
810         column= uiLayoutColumn(layout, 1);
811
812         /* rounded header */
813         /* XXX uiBlockSetCol(block, color); */
814                 /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
815         block= uiLayoutFreeBlock(uiLayoutBox(column));
816         uiBlockSetHandleFunc(block, do_modifier_panels, NULL);
817
818         //uiDefBut(block, ROUNDBOX, 0, "", x-10, y-4, width, 25, NULL, 7.0, 0.0, 
819         //               (!isVirtual && (md->mode&eModifierMode_Expanded))?3:15, 20, ""); 
820         /* XXX uiBlockSetCol(block, TH_AUTO); */
821         
822         /* open/close icon */
823         if (!isVirtual) {
824                 uiBlockSetEmboss(block, UI_EMBOSSN);
825                 uiDefIconButBitI(block, ICONTOG, eModifierMode_Expanded, B_MODIFIER_REDRAW, VICON_DISCLOSURE_TRI_RIGHT, x-10, y-2, 20, 20, &md->mode, 0.0, 0.0, 0.0, 0.0, "Collapse/Expand Modifier");
826         }
827
828         uiBlockSetEmboss(block, UI_EMBOSS);
829         
830         if (isVirtual) {
831                 sprintf(str, "%s parent deform", md->name);
832                 uiDefBut(block, LABEL, 0, str, x+10, y-1, width-110, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name"); 
833
834                 but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Make Real", x+width-100, y, 80, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Convert virtual modifier to a real modifier");
835                 uiButSetFunc(but, modifiers_convertToReal, ob, md);
836         } else {
837                 uiBlockBeginAlign(block);
838                 uiDefBut(block, TEX, B_MODIFIER_REDRAW, "", x+10, y-1, buttonWidth-60, 19, md->name, 0.0, sizeof(md->name)-1, 0.0, 0.0, "Modifier name"); 
839
840                 /* Softbody not allowed in this situation, enforce! */
841                 if (((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) && (md->type!=eModifierType_Surface)) {
842                         uiDefIconButBitI(block, TOG, eModifierMode_Render, B_MODIFIER_RECALC, ICON_SCENE, x+10+buttonWidth-60, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during rendering");
843                         but= uiDefIconButBitI(block, TOG, eModifierMode_Realtime, B_MODIFIER_RECALC, VICON_VIEW3D, x+10+buttonWidth-40, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during interactive display");
844                         if (mti->flags&eModifierTypeFlag_SupportsEditmode) {
845                                 uiDefIconButBitI(block, TOG, eModifierMode_Editmode, B_MODIFIER_RECALC, VICON_EDIT, x+10+buttonWidth-20, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during Editmode (only if enabled for display)");
846                         }
847                 }
848                 uiBlockEndAlign(block);
849
850                 /* XXX uiBlockSetEmboss(block, UI_EMBOSSR); */
851
852                 if (ob->type==OB_MESH && modifier_couldBeCage(md) && index<=lastCageIndex) {
853                         int icon; //, color;
854
855                         if (index==cageIndex) {
856                                 // XXX color = TH_BUT_SETTING;
857                                 icon = VICON_EDITMODE_HLT;
858                         } else if (index<cageIndex) {
859                                 // XXX color = TH_BUT_NEUTRAL;
860                                 icon = VICON_EDITMODE_DEHLT;
861                         } else {
862                                 // XXX color = TH_BUT_NEUTRAL;
863                                 icon = ICON_BLANK1;
864                         }
865                         /* XXX uiBlockSetCol(block, color); */
866                         but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, icon, x+width-105, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Apply modifier to editing cage during Editmode");
867                         uiButSetFunc(but, modifiers_setOnCage, ob, md);
868                         /* XXX uiBlockSetCol(block, TH_AUTO); */
869                 }
870
871                 /* XXX uiBlockSetCol(block, TH_BUT_ACTION); */
872
873                 but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_MOVE_UP, x+width-75, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Move modifier up in stack");
874                 uiButSetFunc(but, modifiers_moveUp, ob, md);
875
876                 but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_MOVE_DOWN, x+width-75+20, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Move modifier down in stack");
877                 uiButSetFunc(but, modifiers_moveDown, ob, md);
878                 
879                 uiBlockSetEmboss(block, UI_EMBOSSN);
880                 
881                 // deletion over the deflection panel
882                 // fluid particle modifier can't be deleted here
883                 if(md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Collision && md->type!=eModifierType_Surface && !modifier_is_fluid_particles(md))
884                 {
885                         but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_X, x+width-70+40, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Delete modifier");
886                         uiButSetFunc(but, modifiers_del, ob, md);
887                 }
888                 /* XXX uiBlockSetCol(block, TH_AUTO); */
889         }
890
891         uiBlockSetEmboss(block, UI_EMBOSS);
892
893         if(!isVirtual && (md->mode&eModifierMode_Expanded)) {
894                 int cy = y - 8;
895                 int lx = x + width - 60 - 15;
896                 uiLayout *box;
897
898                 box= uiLayoutBox(column);
899                 row= uiLayoutRow(box, 1);
900
901                 y -= 18;
902
903                 if (!isVirtual && (md->type!=eModifierType_Collision) && (md->type!=eModifierType_Surface)) {
904                         uiBlockSetButLock(block, object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); /* only here obdata, the rest of modifiers is ob level */
905
906                         uiBlockBeginAlign(block);
907                         if (md->type==eModifierType_ParticleSystem) {
908                         ParticleSystem *psys= ((ParticleSystemModifierData *)md)->psys;
909
910                         if(!(G.f & G_PARTICLEEDIT)) {
911                                         if(ELEM3(psys->part->draw_as, PART_DRAW_PATH, PART_DRAW_GR, PART_DRAW_OB) && psys->pathcache) {
912                                                 but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Convert",        lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Convert the current particles to a mesh object");
913                                                 uiButSetFunc(but, modifiers_convertParticles, ob, md);
914                                         }
915                                 }
916                         }
917                         else{
918                                 but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Apply",  lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Apply the current modifier and remove from the stack");
919                                 uiButSetFunc(but, modifiers_applyModifier, ob, md);
920                         }
921                         
922                         uiBlockClearButLock(block);
923                         uiBlockSetButLock(block, ob && ob->id.lib, ERROR_LIBDATA_MESSAGE);
924
925                         if (md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (md->type!=eModifierType_Cloth)) {
926                                 but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Copy",   lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Duplicate the current modifier at the same position in the stack");
927                                 uiButSetFunc(but, modifiers_copyModifier, ob, md);
928                         }
929                         uiBlockEndAlign(block);
930                 }
931
932                 result= uiLayoutColumn(box, 0);
933                 block= uiLayoutFreeBlock(box);
934
935                 lx = x + 10;
936                 cy = y + 10 - 1;
937                 uiBlockBeginAlign(block);
938                 if (md->type==eModifierType_Subsurf) {
939                         SubsurfModifierData *smd = (SubsurfModifierData*) md;
940                         char subsurfmenu[]="Subsurf Type%t|Catmull-Clark%x0|Simple Subdiv.%x1";
941                         uiDefButS(block, MENU, B_MODIFIER_RECALC, subsurfmenu,          lx,(cy-=19),buttonWidth,19, &smd->subdivType, 0, 0, 0, 0, "Selects type of subdivision algorithm.");
942                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Levels:",             lx, (cy-=19), buttonWidth,19, &smd->levels, 1, 6, 0, 0, "Number subdivisions to perform");
943                         uiDefButS(block, NUM, B_MODIFIER_REDRAW, "Render Levels:",              lx, (cy-=19), buttonWidth,19, &smd->renderLevels, 1, 6, 0, 0, "Number subdivisions to perform when rendering");
944
945                         /* Disabled until non-EM DerivedMesh implementation is complete */
946
947                         /*
948                         uiDefButBitS(block, TOG, eSubsurfModifierFlag_Incremental, B_MODIFIER_RECALC, "Incremental", lx, (cy-=19),90,19,&smd->flags, 0, 0, 0, 0, "Use incremental calculation, even outside of mesh mode");
949                         uiDefButBitS(block, TOG, eSubsurfModifierFlag_DebugIncr, B_MODIFIER_RECALC, "Debug", lx+90, cy,buttonWidth-90,19,&smd->flags, 0, 0, 0, 0, "Visualize the subsurf incremental calculation, for debugging effect of other modifiers");
950                         */
951
952                         uiDefButBitS(block, TOG, eSubsurfModifierFlag_ControlEdges, B_MODIFIER_RECALC, "Optimal Draw", lx, (cy-=19), buttonWidth,19,&smd->flags, 0, 0, 0, 0, "Skip drawing/rendering of interior subdivided edges");
953                         uiDefButBitS(block, TOG, eSubsurfModifierFlag_SubsurfUv, B_MODIFIER_RECALC, "Subsurf UV", lx, (cy-=19),buttonWidth,19,&smd->flags, 0, 0, 0, 0, "Use subsurf to subdivide UVs");
954                 } else if (md->type==eModifierType_Lattice) {
955                         LatticeModifierData *lmd = (LatticeModifierData*) md;
956                         uiDefIDPoinBut(block, modifier_testLatticeObj, ID_OB, B_CHANGEDEP, "Ob: ",      lx, (cy-=19), buttonWidth,19, &lmd->object, "Lattice object to deform with");
957                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &lmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
958                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
959                 } else if (md->type==eModifierType_Curve) {
960                         CurveModifierData *cmd = (CurveModifierData*) md;
961                         uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &cmd->object, "Curve object to deform with");
962                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &cmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
963                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
964                         
965                         uiDefButS(block, ROW,B_MODIFIER_RECALC,"X",             lx, (cy-=19), 19,19, &cmd->defaxis, 12.0, MOD_CURVE_POSX, 0, 0, "The axis that the curve deforms along");
966                         uiDefButS(block, ROW,B_MODIFIER_RECALC,"Y",             (lx+buttonWidth/6), cy, 19,19, &cmd->defaxis, 12.0, MOD_CURVE_POSY, 0, 0, "The axis that the curve deforms along");
967                         uiDefButS(block, ROW,B_MODIFIER_RECALC,"Z",             (lx+2*buttonWidth/6), cy, 19,19, &cmd->defaxis, 12.0, MOD_CURVE_POSZ, 0, 0, "The axis that the curve deforms along");
968                         uiDefButS(block, ROW,B_MODIFIER_RECALC,"-X",            (lx+3*buttonWidth/6), cy, 24,19, &cmd->defaxis, 12.0, MOD_CURVE_NEGX, 0, 0, "The axis that the curve deforms along");
969                         uiDefButS(block, ROW,B_MODIFIER_RECALC,"-Y",            (lx+4*buttonWidth/6), cy, 24,19, &cmd->defaxis, 12.0, MOD_CURVE_NEGY, 0, 0, "The axis that the curve deforms along");
970                         uiDefButS(block, ROW,B_MODIFIER_RECALC,"-Z",            (lx+buttonWidth-buttonWidth/6), cy, 24,19, &cmd->defaxis, 12.0, MOD_CURVE_NEGZ, 0, 0, "The axis that the curve deforms along");
971                 } else if (md->type==eModifierType_Build) {
972                         BuildModifierData *bmd = (BuildModifierData*) md;
973                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Start:", lx, (cy-=19), buttonWidth,19, &bmd->start, 1.0, MAXFRAMEF, 100, 0, "Specify the start frame of the effect");
974                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Length:", lx, (cy-=19), buttonWidth,19, &bmd->length, 1.0, MAXFRAMEF, 100, 0, "Specify the total time the build effect requires");
975                         uiDefButI(block, TOG, B_MODIFIER_RECALC, "Randomize", lx, (cy-=19), buttonWidth,19, &bmd->randomize, 0, 0, 1, 0, "Randomize the faces or edges during build.");
976                         uiDefButI(block, NUM, B_MODIFIER_RECALC, "Seed:", lx, (cy-=19), buttonWidth,19, &bmd->seed, 1.0, MAXFRAMEF, 100, 0, "Specify the seed for random if used.");
977                 } else if (md->type==eModifierType_Mirror) {
978                         MirrorModifierData *mmd = (MirrorModifierData*) md;
979                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Merge Limit:", lx, (cy-=19), buttonWidth,19, &mmd->tolerance, 0.0, 1.0, 10, 10, "Distance from axis within which mirrored vertices are merged");
980                         uiDefButBitS(block, TOG, MOD_MIR_AXIS_X, B_MODIFIER_RECALC, "X",        lx,(cy-=19),20,19, &mmd->flag, 0, 0, 0, 0, "Enable X axis mirror");
981                         uiDefButBitS(block, TOG, MOD_MIR_AXIS_Y, B_MODIFIER_RECALC, "Y",        lx+20,cy,20,19,    &mmd->flag, 0, 0, 0, 0, "Enable Y axis mirror");
982                         uiDefButBitS(block, TOG, MOD_MIR_AXIS_Z, B_MODIFIER_RECALC, "Z",        lx+40,cy,20,19,    &mmd->flag, 0, 0, 0, 0, "Enable Z axis mirror");
983                         uiDefButBitS(block, TOG, MOD_MIR_CLIPPING, B_MODIFIER_RECALC, "Do Clipping",    lx+60, cy, buttonWidth-60,19, &mmd->flag, 1, 2, 0, 0, "Prevents during Transform vertices to go through Mirror");
984                         uiDefButBitS(block, TOG, MOD_MIR_VGROUP, B_MODIFIER_RECALC, "Mirror Vgroups",   lx, (cy-=19), buttonWidth,19, &mmd->flag, 1, 2, 0, 0, "Mirror vertex groups (e.g. .R->.L)");
985                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_U, B_MODIFIER_RECALC,
986                                      "Mirror U",
987                                      lx, (cy-=19), buttonWidth/2, 19,
988                                      &mmd->flag, 0, 0, 0, 0,
989                                      "Mirror the U texture coordinate around "
990                                      "the 0.5 point");
991                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_V, B_MODIFIER_RECALC,
992                                      "Mirror V",
993                                      lx + buttonWidth/2 + 1, cy, buttonWidth/2, 19,
994                                      &mmd->flag, 0, 0, 0, 0,
995                                      "Mirror the V texture coordinate around "
996                                      "the 0.5 point");
997                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
998                                        "Ob: ", lx, (cy -= 19), buttonWidth, 19,
999                                        &mmd->mirror_ob,
1000                                        "Object to use as mirror");
1001                 } else if (md->type==eModifierType_Bevel) {
1002                         BevelModifierData *bmd = (BevelModifierData*) md;
1003                         /*uiDefButS(block, ROW, B_MODIFIER_RECALC, "Distance",
1004                                           lx, (cy -= 19), (buttonWidth/2), 19, &bmd->val_flags,
1005                                           11.0, 0, 0, 0,
1006                                           "Interpret bevel value as a constant distance from each edge");
1007                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "Radius",
1008                                           (lx+buttonWidth/2), cy, (buttonWidth - buttonWidth/2), 19, &bmd->val_flags,
1009                                           11.0, BME_BEVEL_RADIUS, 0, 0,
1010                                           "Interpret bevel value as a radius - smaller angles will be beveled more");*/
1011                         uiBlockBeginAlign(block);
1012                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Width: ",
1013                                           lx, (cy -= 19), buttonWidth, 19, &bmd->value,
1014                                           0.0, 0.5, 5, 4,
1015                                           "Bevel value/amount");
1016                         /*uiDefButI(block, NUM, B_MODIFIER_RECALC, "Recurs",
1017                                           lx, (cy -= 19), buttonWidth, 19, &bmd->res,
1018                                           1, 4, 5, 2,
1019                                           "Number of times to bevel");*/
1020                         uiDefButBitS(block, TOG, BME_BEVEL_VERT,
1021                                           B_MODIFIER_RECALC, "Only Vertices",
1022                                           lx, (cy -= 19), buttonWidth, 19,
1023                                           &bmd->flags, 0, 0, 0, 0,
1024                                           "Bevel only verts/corners; not edges");
1025                         uiBlockEndAlign(block);
1026                                           
1027                         uiDefBut(block, LABEL, 1, "Limit using:",       lx, (cy-=25), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
1028                         uiBlockBeginAlign(block);
1029                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "None",
1030                                           lx, (cy -= 19), (buttonWidth/3), 19, &bmd->lim_flags,
1031                                           12.0, 0, 0, 0,
1032                                           "Bevel the entire mesh by a constant amount");
1033                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "Angle",
1034                                           (lx+buttonWidth/3), cy, (buttonWidth/3), 19, &bmd->lim_flags,
1035                                           12.0, BME_BEVEL_ANGLE, 0, 0,
1036                                           "Only bevel edges with sharp enough angles between faces");
1037                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "BevWeight",
1038                                           lx+(2*buttonWidth/3), cy, buttonWidth-2*(buttonWidth/3), 19, &bmd->lim_flags,
1039                                           12.0, BME_BEVEL_WEIGHT, 0, 0,
1040                                           "Use bevel weights to determine how much bevel is applied; apply them separately in vert/edge select mode");
1041                         if ((bmd->lim_flags & BME_BEVEL_WEIGHT) && !(bmd->flags & BME_BEVEL_VERT)) {
1042                                 uiDefButS(block, ROW, B_MODIFIER_RECALC, "Min",
1043                                           lx, (cy -= 19), (buttonWidth/3), 19, &bmd->e_flags,
1044                                           13.0, BME_BEVEL_EMIN, 0, 0,
1045                                           "The sharpest edge's weight is used when weighting a vert");
1046                                 uiDefButS(block, ROW, B_MODIFIER_RECALC, "Average",
1047                                           (lx+buttonWidth/3), cy, (buttonWidth/3), 19, &bmd->e_flags,
1048                                           13.0, 0, 0, 0,
1049                                           "The edge weights are averaged when weighting a vert");
1050                                 uiDefButS(block, ROW, B_MODIFIER_RECALC, "Max",
1051                                           (lx+2*(buttonWidth/3)), cy, buttonWidth-2*(buttonWidth/3), 19, &bmd->e_flags,
1052                                           13.0, BME_BEVEL_EMAX, 0, 0,
1053                                           "The largest edge's wieght is used when weighting a vert");
1054                         }
1055                         else if (bmd->lim_flags & BME_BEVEL_ANGLE) {
1056                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Angle:",
1057                                           lx, (cy -= 19), buttonWidth, 19, &bmd->bevel_angle,
1058                                           0.0, 180.0, 100, 2,
1059                                           "Angle above which to bevel edges");
1060                         }
1061                 } else if (md->type==eModifierType_EdgeSplit) {
1062                         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1063                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMANGLE,
1064                                      B_MODIFIER_RECALC, "From Edge Angle",
1065                                      lx, (cy -= 19), buttonWidth, 19,
1066                                      &emd->flags, 0, 0, 0, 0,
1067                                      "Split edges with high angle between faces");
1068                         if(emd->flags & MOD_EDGESPLIT_FROMANGLE) {
1069                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Split Angle:",
1070                                           lx, (cy -= 19), buttonWidth, 19, &emd->split_angle,
1071                                           0.0, 180.0, 100, 2,
1072                                           "Angle above which to split edges");
1073                         }
1074                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMFLAG,
1075                                      B_MODIFIER_RECALC, "From Marked As Sharp",
1076                                      lx, (cy -= 19), buttonWidth, 19,
1077                                      &emd->flags, 0, 0, 0, 0,
1078                                      "Split edges that are marked as sharp");
1079                 } else if (md->type==eModifierType_Displace) {
1080                         DisplaceModifierData *dmd = (DisplaceModifierData*) md;
1081                         but = uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",
1082                                        lx, (cy -= 19), buttonWidth, 19,
1083                                        &dmd->defgrp_name, 0.0, 31.0, 0, 0,
1084                                        "Name of vertex group to displace"
1085                                        " (displace whole mesh if blank)");
1086                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1087                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,
1088                                        "Texture: ", lx, (cy -= 19), buttonWidth, 19,
1089                                        &dmd->texture,
1090                                        "Texture to use as displacement input");
1091                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Midlevel:",
1092                                   lx, (cy -= 19), buttonWidth, 19, &dmd->midlevel,
1093                                   0, 1, 10, 3,
1094                                   "Material value that gives no displacement");
1095                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Strength:",
1096                                   lx, (cy -= 19), buttonWidth, 19, &dmd->strength,
1097                                   -1000, 1000, 10, 0.1,
1098                                   "Strength of displacement");
1099                         sprintf(str, "Direction%%t|Normal%%x%d|RGB -> XYZ%%x%d|"
1100                                 "Z%%x%d|Y%%x%d|X%%x%d",
1101                                 MOD_DISP_DIR_NOR, MOD_DISP_DIR_RGB_XYZ,
1102                                 MOD_DISP_DIR_Z, MOD_DISP_DIR_Y, MOD_DISP_DIR_X);
1103                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1104                                   lx, (cy -= 19), buttonWidth, 19, &dmd->direction,
1105                                   0.0, 1.0, 0, 0, "Displace direction");
1106                         sprintf(str, "Texture Coordinates%%t"
1107                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
1108                                 MOD_DISP_MAP_LOCAL, MOD_DISP_MAP_GLOBAL,
1109                                 MOD_DISP_MAP_OBJECT, MOD_DISP_MAP_UV);
1110                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1111                                   lx, (cy -= 19), buttonWidth, 19, &dmd->texmapping,
1112                                   0.0, 1.0, 0, 0,
1113                                   "Texture coordinates used for displacement input");
1114                         if (dmd->texmapping == MOD_DISP_MAP_UV) {
1115                                 char *strtmp;
1116                                 int i;
1117                                 Mesh *me= (Mesh*)ob->data;
1118                                 CustomData *fdata = obedit? &me->edit_mesh->fdata: &me->fdata;
1119                                 build_uvlayer_menu_vars(fdata, &strtmp, &dmd->uvlayer_tmp,
1120                                                         dmd->uvlayer_name);
1121                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
1122                                       lx, (cy -= 19), buttonWidth, 19, &dmd->uvlayer_tmp,
1123                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
1124                                 MEM_freeN(strtmp);
1125                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
1126                                 uiButSetFunc(but, set_displace_uvlayer, dmd,
1127                                              &fdata->layers[i]);
1128                         }
1129                         if(dmd->texmapping == MOD_DISP_MAP_OBJECT) {
1130                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1131                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1132                                                &dmd->map_object,
1133                                                "Object to get texture coordinates from");
1134                         }
1135                 } else if (md->type==eModifierType_UVProject) {
1136                         UVProjectModifierData *umd = (UVProjectModifierData *) md;
1137                         int i;
1138                         char *strtmp;
1139                         Mesh *me= (Mesh*)ob->data;
1140                         CustomData *fdata = obedit? &me->edit_mesh->fdata: &me->fdata;
1141                         build_uvlayer_menu_vars(fdata, &strtmp, &umd->uvlayer_tmp,
1142                                                 umd->uvlayer_name);
1143                         but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
1144                               lx, (cy -= 19), buttonWidth, 19, &umd->uvlayer_tmp,
1145                               0.0, 1.0, 0, 0, "Set the UV layer to use");
1146                         i = CustomData_get_layer_index(fdata, CD_MTFACE);
1147                         uiButSetFunc(but, set_uvproject_uvlayer, umd, &fdata->layers[i]);
1148                         MEM_freeN(strtmp);
1149                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspX:",
1150                                   lx, (cy -= 19), buttonWidth / 2, 19, &umd->aspectx,
1151                                   1, 1000, 100, 2,
1152                                   "Horizontal Aspect Ratio");
1153                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspY:",
1154                                   lx + (buttonWidth / 2) + 1, cy, buttonWidth / 2, 19,
1155                                   &umd->aspecty,
1156                                   1, 1000, 100, 2,
1157                                   "Vertical Aspect Ratio");
1158                         uiDefButI(block, NUM, B_MODIFIER_RECALC, "Projectors:",
1159                                   lx, (cy -= 19), buttonWidth, 19, &umd->num_projectors,
1160                                   1, MOD_UVPROJECT_MAXPROJECTORS, 0, 0,
1161                                   "Number of objects to use as projectors");
1162                         for(i = 0; i < umd->num_projectors; ++i) {
1163                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1164                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1165                                                &umd->projectors[i],
1166                                                "Object to use as projector");
1167                         }
1168                         uiDefIDPoinBut(block, modifier_testImage, ID_IM, B_CHANGEDEP,
1169                                        "Image: ", lx, (cy -= 19), buttonWidth, 19,
1170                                        &umd->image,
1171                                        "Image to project (only faces with this image "
1172                                        "will be altered");
1173                         uiButSetCompleteFunc(but, autocomplete_image, (void *)ob);
1174                         uiDefButBitI(block, TOG, MOD_UVPROJECT_OVERRIDEIMAGE,
1175                                      B_MODIFIER_RECALC, "Override Image",
1176                                      lx, (cy -= 19), buttonWidth, 19,
1177                                      &umd->flags, 0, 0, 0, 0,
1178                                      "Override faces' current images with the "
1179                                      "given image");
1180                 } else if (md->type==eModifierType_Decimate) {
1181                         DecimateModifierData *dmd = (DecimateModifierData*) md;
1182                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Ratio:",      lx,(cy-=19),buttonWidth,19, &dmd->percent, 0.0, 1.0, 10, 0, "Defines the percentage of triangles to reduce to");
1183                         sprintf(str, "Face Count: %d", dmd->faceCount);
1184                         uiDefBut(block, LABEL, 1, str,  lx, (cy-=19), 160,19, NULL, 0.0, 0.0, 0, 0, "Displays the current number of faces in the decimated mesh");
1185                 } else if (md->type==eModifierType_Mask) {
1186                         MaskModifierData *mmd = (MaskModifierData *)md;
1187                         
1188                         sprintf(str, "Mask Mode%%t|Vertex Group%%x%d|Selected Bones%%x%d|",
1189                                 MOD_MASK_MODE_VGROUP,MOD_MASK_MODE_ARM);
1190                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1191                                 lx, (cy -= 19), buttonWidth, 19, &mmd->mode,
1192                                 0.0, 1.0, 0, 0, "How masking region is defined");
1193                                           
1194                         if (mmd->mode == MOD_MASK_MODE_ARM) {
1195                                 uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP,
1196                                     "Ob: ", lx, (cy -= 19), buttonWidth, 19, &mmd->ob_arm,
1197                                     "Armature to use as source of bones to mask");
1198                         }
1199                         else {
1200                                 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", 
1201                                         lx, (cy-=19), buttonWidth, 19, &mmd->vgroup, 
1202                                         0.0, 31.0, 0, 0, "Vertex Group name");
1203                                 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1204                         }
1205                         
1206                         uiDefButBitI(block, TOG, MOD_MASK_INV, B_MODIFIER_RECALC, "Inverse",            
1207                                 lx, (cy-=19), buttonWidth, 19, &mmd->flag, 
1208                                 0, 0, 0, 0, "Use vertices that are not part of region defined");
1209                 } else if (md->type==eModifierType_Smooth) {
1210                         SmoothModifierData *smd = (SmoothModifierData*) md;
1211
1212                         uiDefButBitS(block, TOG, MOD_SMOOTH_X, B_MODIFIER_RECALC, "X",          lx,(cy-=19),45,19, &smd->flag, 0, 0, 0, 0, "Enable X axis smoothing");
1213                         uiDefButBitS(block, TOG, MOD_SMOOTH_Y, B_MODIFIER_RECALC, "Y",          lx+45,cy,45,19, &smd->flag, 0, 0, 0, 0, "Enable Y axis smoothing");
1214                         uiDefButBitS(block, TOG, MOD_SMOOTH_Z, B_MODIFIER_RECALC, "Z",          lx+90,cy,45,19, &smd->flag, 0, 0, 0, 0, "Enable Z axis smoothing");
1215
1216                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Factor:",     lx,(cy-=19),buttonWidth, 19, &smd->fac, -10.0, 10.0, 0.5, 0, "Define the amount of smoothing, from 0.0 to 1.0 (lower / higher values can deform the mesh)");
1217                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Repeat:",     lx,(cy-=19),buttonWidth, 19, &smd->repeat, 0.0, 30.0, 1, 0, "Number of smoothing iterations");
1218                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &smd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to define which vertices are affected");
1219                 } else if (md->type==eModifierType_Cast) {
1220                         CastModifierData *cmd = (CastModifierData*) md;
1221
1222                         char casttypemenu[]="Projection Type%t|Sphere%x0|Cylinder%x1|Cuboid%x2";
1223                         uiDefButS(block, MENU, B_MODIFIER_RECALC, casttypemenu,         lx,(cy-=19),buttonWidth - 30,19, &cmd->type, 0, 0, 0, 0, "Projection type to apply");
1224                         uiDefButBitS(block, TOG, MOD_CAST_X, B_MODIFIER_RECALC, "X",            lx,(cy-=19),45,19, &cmd->flag, 0, 0, 0, 0, "Enable (local) X axis deformation");
1225                         uiDefButBitS(block, TOG, MOD_CAST_Y, B_MODIFIER_RECALC, "Y",            lx+45,cy,45,19, &cmd->flag, 0, 0, 0, 0, "Enable (local) Y axis deformation");
1226                         if (cmd->type != MOD_CAST_TYPE_CYLINDER) {
1227                                 uiDefButBitS(block, TOG, MOD_CAST_Z, B_MODIFIER_RECALC, "Z",            lx+90,cy,45,19, &cmd->flag, 0, 0, 0, 0, "Enable (local) Z axis deformation");
1228                         }
1229                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Factor:",     lx,(cy-=19),buttonWidth, 19, &cmd->fac, -10.0, 10.0, 5, 0, "Define the amount of deformation");
1230                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Radius:",     lx,(cy-=19),buttonWidth, 19, &cmd->radius, 0.0, 100.0, 10.0, 0, "Only deform vertices within this distance from the center of the effect (leave as 0 for infinite)");
1231                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Size:",       lx,(cy-=19),buttonWidth, 19, &cmd->size, 0.0, 100.0, 10.0, 0, "Size of projection shape (leave as 0 for auto)");
1232                         uiDefButBitS(block, TOG, MOD_CAST_SIZE_FROM_RADIUS, B_MODIFIER_RECALC, "From radius",           lx+buttonWidth,cy,80,19, &cmd->flag, 0, 0, 0, 0, "Use radius as size of projection shape (0 = auto)");
1233                         if (ob->type == OB_MESH) {
1234                                 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &cmd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to define which vertices are affected");
1235                         }
1236                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx,(cy-=19), buttonWidth,19, &cmd->object, "Control object: if available, its location determines the center of the effect");
1237                         if(cmd->object) {
1238                                 uiDefButBitS(block, TOG, MOD_CAST_USE_OB_TRANSFORM, B_MODIFIER_RECALC, "Use transform",         lx+buttonWidth,cy,80,19, &cmd->flag, 0, 0, 0, 0, "Use object transform to control projection shape");
1239                         }
1240                 } else if (md->type==eModifierType_Wave) {
1241                         WaveModifierData *wmd = (WaveModifierData*) md;
1242                         uiDefButBitS(block, TOG, MOD_WAVE_X, B_MODIFIER_RECALC, "X",            lx,(cy-=19),45,19, &wmd->flag, 0, 0, 0, 0, "Enable X axis motion");
1243                         uiDefButBitS(block, TOG, MOD_WAVE_Y, B_MODIFIER_RECALC, "Y",            lx+45,cy,45,19, &wmd->flag, 0, 0, 0, 0, "Enable Y axis motion");
1244                         uiDefButBitS(block, TOG, MOD_WAVE_CYCL, B_MODIFIER_RECALC, "Cycl",      lx+90,cy,buttonWidth-90,19, &wmd->flag, 0, 0, 0, 0, "Enable cyclic wave effect");
1245                         uiDefButBitS(block, TOG, MOD_WAVE_NORM, B_MODIFIER_RECALC, "Normals",   lx,(cy-=19),buttonWidth,19, &wmd->flag, 0, 0, 0, 0, "Displace along normals");
1246                         if (wmd->flag & MOD_WAVE_NORM){
1247                                 if (ob->type==OB_MESH) {
1248                                         uiDefButBitS(block, TOG, MOD_WAVE_NORM_X, B_MODIFIER_RECALC, "X",       lx,(cy-=19),buttonWidth/3,19, &wmd->flag, 0, 0, 0, 0, "Enable displacement along the X normal");
1249                                         uiDefButBitS(block, TOG, MOD_WAVE_NORM_Y, B_MODIFIER_RECALC, "Y",       lx+(buttonWidth/3),cy,buttonWidth/3,19, &wmd->flag, 0, 0, 0, 0, "Enable displacement along the Y normal");
1250                                         uiDefButBitS(block, TOG, MOD_WAVE_NORM_Z, B_MODIFIER_RECALC, "Z",       lx+(buttonWidth/3)*2,cy,buttonWidth/3,19, &wmd->flag, 0, 0, 0, 0, "Enable displacement along the Z normal");
1251                                 }
1252                                 else
1253                                         uiDefBut(block, LABEL, 1, "Meshes Only",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");                                
1254                         }
1255
1256                         uiBlockBeginAlign(block);
1257                         if(wmd->speed >= 0)
1258                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Time sta:",   lx,(cy-=19),buttonWidth,19, &wmd->timeoffs, -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify starting frame of the wave");
1259                         else
1260                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Time end:",   lx,(cy-=19),buttonWidth,19, &wmd->timeoffs, -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify ending frame of the wave");
1261                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Lifetime:",   lx,(cy-=19),buttonWidth,19, &wmd->lifetime,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the lifespan of the wave");
1262                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Damptime:",   lx,(cy-=19),buttonWidth,19, &wmd->damp,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the dampingtime of the wave");
1263                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Falloff:",    lx,(cy-=19),buttonWidth,19, &wmd->falloff,  0, 100, 100, 0, "Specify the falloff radius of the waves");
1264
1265                         cy -= 9;
1266                         uiBlockBeginAlign(block);
1267                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Sta x:",              lx,(cy-=19),113,19, &wmd->startx, -100.0, 100.0, 100, 0, "Starting position for the X axis");
1268                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Sta y:",              lx+115,cy,105,19, &wmd->starty, -100.0, 100.0, 100, 0, "Starting position for the Y axis");
1269                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_MODIFIER_RECALC, "Ob: ", lx, (cy-=19), 220,19, &wmd->objectcenter, "Object to use as Starting Position (leave blank to disable)");
1270                         uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",lx, (cy -= 19), 220, 19,&wmd->defgrp_name, 0.0, 31.0, 0, 0, "Name of vertex group with which to modulate displacement");
1271                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,"Texture: ", lx, (cy -= 19), 220, 19, &wmd->texture,"Texture with which to modulate wave");
1272                         sprintf(str, "Texture Coordinates%%t"
1273                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
1274                                 MOD_WAV_MAP_LOCAL, MOD_WAV_MAP_GLOBAL,
1275                                 MOD_WAV_MAP_OBJECT, MOD_WAV_MAP_UV);
1276                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1277                                   lx, (cy -= 19), 220, 19, &wmd->texmapping,
1278                                   0.0, 1.0, 0, 0,
1279                                   "Texture coordinates used for modulation input");
1280                         if (wmd->texmapping == MOD_WAV_MAP_UV) {
1281                                 char *strtmp;
1282                                 int i;
1283                                 Mesh *me = (Mesh*)ob->data;
1284                                 CustomData *fdata = obedit? &me->edit_mesh->fdata: &me->fdata;
1285                                 build_uvlayer_menu_vars(fdata, &strtmp, &wmd->uvlayer_tmp,
1286                                                         wmd->uvlayer_name);
1287                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
1288                                       lx, (cy -= 19), 220, 19, &wmd->uvlayer_tmp,
1289                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
1290                                 MEM_freeN(strtmp);
1291                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
1292                                 uiButSetFunc(but, set_wave_uvlayer, wmd,
1293                                              &fdata->layers[i]);
1294                         }
1295                         if(wmd->texmapping == MOD_DISP_MAP_OBJECT) {
1296                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1297                                                "Ob: ", lx, (cy -= 19), 220, 19,
1298                                                &wmd->map_object,
1299                                                "Object to get texture coordinates from");
1300                         }
1301                         cy -= 9;
1302                         uiBlockBeginAlign(block);
1303                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Speed:",   lx,(cy-=19),220,19, &wmd->speed, -2.0, 2.0, 0, 0, "Specify the wave speed");
1304                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Height:",  lx,(cy-=19),220,19, &wmd->height, -2.0, 2.0, 0, 0, "Specify the amplitude of the wave");
1305                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Width:",   lx,(cy-=19),220,19, &wmd->width, 0.0, 5.0, 0, 0, "Specify the width of the wave");
1306                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Narrow:",  lx,(cy-=19),220,19, &wmd->narrow, 0.0, 10.0, 0, 0, "Specify how narrow the wave follows");
1307                 } else if (md->type==eModifierType_Hook) {
1308                         HookModifierData *hmd = (HookModifierData*) md;
1309                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Falloff: ",           lx, (cy-=19), buttonWidth,19, &hmd->falloff, 0.0, 100.0, 100, 0, "If not zero, the distance from hook where influence ends");
1310                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Force: ",          lx, (cy-=19), buttonWidth,19, &hmd->force, 0.0, 1.0, 100, 0, "Set relative force of hook");
1311                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &hmd->object, "Parent Object for hook, also recalculates and clears offset"); 
1312                         if(hmd->indexar==NULL) {
1313                                 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &hmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1314                                 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1315                         }
1316                         uiBlockBeginAlign(block);
1317                         but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Reset",          lx, (cy-=19), 80,19,                    NULL, 0.0, 0.0, 0, 0, "Recalculate and clear offset (transform) of hook");
1318                         uiButSetFunc(but, modifiers_clearHookOffset, ob, md);
1319                         but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Recenter",       lx+80, cy, buttonWidth-80,19,   NULL, 0.0, 0.0, 0, 0, "Sets hook center to cursor position");
1320                         uiButSetFunc(but, modifiers_cursorHookCenter, ob, md);
1321
1322                         if (editing) {
1323                                 but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Select",                 lx, (cy-=19), 80,19, NULL, 0.0, 0.0, 0, 0, "Selects effected vertices on mesh");
1324                                 uiButSetFunc(but, modifiers_selectHook, ob, md);
1325                                 but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Reassign",               lx+80, cy, buttonWidth-80,19, NULL, 0.0, 0.0, 0, 0, "Reassigns selected vertices to hook");
1326                                 uiButSetFunc(but, modifiers_reassignHook, ob, md);
1327                         }
1328                 } else if (md->type==eModifierType_Softbody) {
1329                         uiDefBut(block, LABEL, 1, "See Soft Body panel.",       lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
1330                 } else if (md->type==eModifierType_Cloth) {
1331                         uiDefBut(block, LABEL, 1, "See Cloth panel.",   lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
1332
1333                 } else if (md->type==eModifierType_Collision) {
1334                         uiDefBut(block, LABEL, 1, "See Collision panel.",       lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
1335                 } else if (md->type==eModifierType_Surface) {
1336                         uiDefBut(block, LABEL, 1, "See Fields panel.",  lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
1337                 } else if (md->type==eModifierType_Fluidsim) {
1338                         uiDefBut(block, LABEL, 1, "See Fluidsim panel.",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
1339                 } else if (md->type==eModifierType_Boolean) {
1340                         BooleanModifierData *bmd = (BooleanModifierData*) md;
1341                         uiDefButI(block, MENU, B_MODIFIER_RECALC, "Operation%t|Intersect%x0|Union%x1|Difference%x2",    lx,(cy-=19),buttonWidth,19, &bmd->operation, 0.0, 1.0, 0, 0, "Boolean operation to perform");
1342                         uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &bmd->object, "Mesh object to use for boolean operation");
1343                 } else if (md->type==eModifierType_Array) {
1344                         ArrayModifierData *amd = (ArrayModifierData*) md;
1345                         float range = 10000;
1346                         int cytop, halfwidth = (width - 5)/2 - 15;
1347                         int halflx = lx + halfwidth + 10;
1348
1349                         // XXX uiBlockSetEmboss(block, UI_EMBOSSX);
1350                         uiBlockEndAlign(block);
1351
1352                         /* length parameters */
1353                         uiBlockBeginAlign(block);
1354                         sprintf(str, "Length Fit%%t|Fixed Count%%x%d|Fixed Length%%x%d"
1355                                 "|Fit To Curve Length%%x%d",
1356                                 MOD_ARR_FIXEDCOUNT, MOD_ARR_FITLENGTH, MOD_ARR_FITCURVE);
1357                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1358                                   lx, (cy-=19), buttonWidth, 19, &amd->fit_type,
1359                                   0.0, 1.0, 0, 0, "Array length calculation method");
1360                         switch(amd->fit_type)
1361                         {
1362                         case MOD_ARR_FIXEDCOUNT:
1363                                 uiDefButI(block, NUM, B_MODIFIER_RECALC, "Count:",
1364                                           lx, (cy -= 19), buttonWidth, 19, &amd->count,
1365                                           1, 1000, 0, 0, "Number of duplicates to make");
1366                                 break;
1367                         case MOD_ARR_FITLENGTH:
1368                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Length:",
1369                                           lx, (cy -= 19), buttonWidth, 19, &amd->length,
1370                                           0, range, 10, 2,
1371                                           "Length to fit array within");
1372                                 break;
1373                         case MOD_ARR_FITCURVE:
1374                                 uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB,
1375                                                B_CHANGEDEP, "Ob: ",
1376                                                lx, (cy -= 19), buttonWidth, 19, &amd->curve_ob,
1377                                                "Curve object to fit array length to");
1378                                 break;
1379                         }
1380                         uiBlockEndAlign(block);
1381
1382                         /* offset parameters */
1383                         cy -= 10;
1384                         cytop= cy;
1385                         uiBlockBeginAlign(block);
1386                         uiDefButBitI(block, TOG, MOD_ARR_OFF_CONST, B_MODIFIER_RECALC,
1387                                      "Constant Offset", lx, (cy-=19), halfwidth, 19,
1388                                      &amd->offset_type, 0, 0, 0, 0,
1389                                      "Constant offset between duplicates "
1390                                      "(local coordinates)");
1391                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
1392                                   lx, (cy-=19), halfwidth, 19,
1393                                   &amd->offset[0],
1394                                   -range, range, 10, 3,
1395                                   "Constant component for duplicate offsets "
1396                                   "(local coordinates)");
1397                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
1398                                   lx, (cy-=19), halfwidth, 19,
1399                                   &amd->offset[1],
1400                                   -range, range, 10, 3,
1401                                   "Constant component for duplicate offsets "
1402                                   "(local coordinates)");
1403                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
1404                                   lx, (cy-=19), halfwidth, 19,
1405                                   &amd->offset[2],
1406                                   -range, range, 10, 3,
1407                                   "Constant component for duplicate offsets "
1408                                   "(local coordinates)");
1409                         uiBlockEndAlign(block);
1410
1411                         cy= cytop;
1412                         uiBlockBeginAlign(block);
1413                         uiDefButBitI(block, TOG, MOD_ARR_OFF_RELATIVE, B_MODIFIER_RECALC,
1414                                      "Relative Offset", halflx, (cy-=19), halfwidth, 19,
1415                                      &amd->offset_type, 0, 0, 0, 0,
1416                                      "Offset between duplicates relative to object width "
1417                                      "(local coordinates)");
1418                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
1419                                   halflx, (cy-=19), halfwidth, 19,
1420                                   &amd->scale[0],
1421                                   -range, range, 10, 3,
1422                                   "Component for duplicate offsets relative to object "
1423                                   "width (local coordinates)");
1424                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
1425                                   halflx, (cy-=19), halfwidth, 19,
1426                                   &amd->scale[1],
1427                                   -range, range, 10, 3,
1428                                   "Component for duplicate offsets relative to object "
1429                                   "width (local coordinates)");
1430                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
1431                                   halflx, (cy-=19), halfwidth, 19,
1432                                   &amd->scale[2],
1433                                   -range, range, 10, 3,
1434                                   "Component for duplicate offsets relative to object "
1435                                   "width (local coordinates)");
1436                         uiBlockEndAlign(block);
1437
1438                         /* vertex merging parameters */
1439                         cy -= 10;
1440                         cytop= cy;
1441
1442                         uiBlockBeginAlign(block);
1443                         uiDefButBitI(block, TOG, MOD_ARR_MERGE, B_MODIFIER_RECALC,
1444                                      "Merge",
1445                                      lx, (cy-=19), halfwidth/2, 19, &amd->flags,
1446                                      0, 0, 0, 0,
1447                                      "Merge vertices in adjacent duplicates");
1448                         uiDefButBitI(block, TOG, MOD_ARR_MERGEFINAL, B_MODIFIER_RECALC,
1449                                      "First Last",
1450                                      lx + halfwidth/2, cy, (halfwidth+1)/2, 19,
1451                                      &amd->flags,
1452                                      0, 0, 0, 0,
1453                                      "Merge vertices in first duplicate with vertices"
1454                                      " in last duplicate");
1455                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Limit:",
1456                                           lx, (cy-=19), halfwidth, 19, &amd->merge_dist,
1457                                           0, 1.0f, 1, 4,
1458                                           "Limit below which to merge vertices");
1459
1460                         /* offset ob */
1461                         cy = cytop;
1462                         uiBlockBeginAlign(block);
1463                         uiDefButBitI(block, TOG, MOD_ARR_OFF_OBJ, B_MODIFIER_RECALC,
1464                                      "Object Offset", halflx, (cy -= 19), halfwidth, 19,
1465                                      &amd->offset_type, 0, 0, 0, 0,
1466                                      "Add an object transformation to the total offset");
1467                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1468                                        "Ob: ", halflx, (cy -= 19), halfwidth, 19,
1469                                        &amd->offset_ob,
1470                                        "Object from which to take offset transformation");
1471                         uiBlockEndAlign(block);
1472
1473                         cy -= 10;
1474                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
1475                                              B_CHANGEDEP, "Start cap: ",
1476                                              lx, (cy -= 19), halfwidth, 19,
1477                                              &amd->start_cap,
1478                                              "Mesh object to use as start cap");
1479                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
1480                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
1481                                              B_CHANGEDEP, "End cap: ",
1482                                              halflx, cy, halfwidth, 19,
1483                                              &amd->end_cap,
1484                                              "Mesh object to use as end cap");
1485                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
1486                 } else if (md->type==eModifierType_MeshDeform) {
1487                         MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
1488
1489                         uiBlockBeginAlign(block);
1490                         uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &mmd->object, "Mesh object to be use as cage"); 
1491                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-19), buttonWidth-40,19, &mmd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to control overall meshdeform influence");
1492                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1493                         uiDefButBitS(block, TOG, MOD_MDEF_INVERT_VGROUP, B_MODIFIER_RECALC, "Inv", lx+buttonWidth-40, (cy-=19), 40,19, &mmd->flag, 0.0, 31.0, 0, 0, "Invert vertex group influence");
1494
1495                         uiBlockBeginAlign(block);
1496                         if(mmd->bindcos) {
1497                                 but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Unbind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Unbind mesh from cage");
1498                                 uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
1499                         }
1500                         else {
1501                                 but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Bind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Bind mesh to cage");
1502                                 uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
1503                                 uiDefButS(block, NUM, B_NOP, "Precision:", lx,(cy-19), buttonWidth/2 + 20,19, &mmd->gridsize, 2, 10, 0.5, 0, "The grid size for binding");
1504                                 uiDefButBitS(block, TOG, MOD_MDEF_DYNAMIC_BIND, B_MODIFIER_RECALC, "Dynamic", lx+(buttonWidth+1)/2 + 20, (cy-=19), buttonWidth/2 - 20,19, &mmd->flag, 0.0, 31.0, 0, 0, "Recompute binding dynamically on top of other deformers like Shape Keys (slower and more memory consuming!)");
1505                         }
1506                         uiBlockEndAlign(block);
1507                 } else if (md->type==eModifierType_ParticleSystem) {
1508                         uiDefBut(block, LABEL, 1, "See Particle buttons.",      lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
1509                 } else if (md->type==eModifierType_ParticleInstance) {
1510                         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
1511                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy -= 19), buttonWidth, 19, &pimd->ob, "Object that has the particlesystem");
1512                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "PSYS:", lx, (cy -= 19), buttonWidth, 19, &pimd->psys, 1, 10, 10, 3, "Particlesystem number in the object");
1513                         uiDefButBitS(block, TOG, eParticleInstanceFlag_Parents, B_MODIFIER_RECALC, "Normal",    lx, (cy -= 19), buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Create instances from normal particles");
1514                         uiDefButBitS(block, TOG, eParticleInstanceFlag_Children, B_MODIFIER_RECALC, "Children", lx+buttonWidth/3, cy, buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Create instances from child particles");
1515                         uiDefButBitS(block, TOG, eParticleInstanceFlag_Path, B_MODIFIER_RECALC, "Path", lx+buttonWidth*2/3, cy, buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Create instances along particle paths");
1516                         uiDefButBitS(block, TOG, eParticleInstanceFlag_Unborn, B_MODIFIER_RECALC, "Unborn",     lx, (cy -= 19), buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Show instances when particles are unborn");
1517                         uiDefButBitS(block, TOG, eParticleInstanceFlag_Alive, B_MODIFIER_RECALC, "Alive",       lx+buttonWidth/3, cy, buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Show instances when particles are alive");
1518                         uiDefButBitS(block, TOG, eParticleInstanceFlag_Dead, B_MODIFIER_RECALC, "Dead", lx+buttonWidth*2/3, cy, buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Show instances when particles are dead");
1519                 } else if (md->type==eModifierType_Explode) {
1520                         ExplodeModifierData *emd = (ExplodeModifierData*) md;
1521                         uiBut *but;
1522                         char *menustr= NULL; /* XXX get_vertexgroup_menustr(ob); */
1523                         int defCount=BLI_countlist(&ob->defbase);
1524                         if(defCount==0) emd->vgroup=0;
1525                         uiBlockBeginAlign(block);
1526                         but=uiDefButS(block, MENU, B_MODIFIER_RECALC, menustr,  lx, (cy-=19), buttonWidth-20,19, &emd->vgroup, 0, defCount, 0, 0, "Protect this vertex group");
1527                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
1528                         MEM_freeN(menustr);
1529                         
1530                         but=uiDefIconBut(block, BUT, B_MODIFIER_RECALC, ICON_X, (lx+buttonWidth)-20, cy, 20,19, 0, 0, 0, 0, 0, "Disable use of vertex group");
1531                         uiButSetFunc(but, modifiers_explodeDelVg, (void *)emd, (void *)NULL);
1532                         
1533
1534                         but=uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "",     lx, (cy-=19), buttonWidth,19, &emd->protect, 0.0f, 1.0f, 0, 0, "Clean vertex group edges");
1535                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
1536
1537                         but=uiDefBut(block, BUT, B_MODIFIER_RECALC, "Refresh",  lx, (cy-=19), buttonWidth/2,19, 0, 0, 0, 0, 0, "Recalculate faces assigned to particles");
1538                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
1539
1540                         uiDefButBitS(block, TOG, eExplodeFlag_EdgeSplit, B_MODIFIER_RECALC, "Split Edges",      lx+buttonWidth/2, cy, buttonWidth/2,19, &emd->flag, 0, 0, 0, 0, "Split face edges for nicer shrapnel");
1541                         uiDefButBitS(block, TOG, eExplodeFlag_Unborn, B_MODIFIER_RECALC, "Unborn",      lx, (cy-=19), buttonWidth/3,19, &emd->flag, 0, 0, 0, 0, "Show mesh when particles are unborn");
1542                         uiDefButBitS(block, TOG, eExplodeFlag_Alive, B_MODIFIER_RECALC, "Alive",        lx+buttonWidth/3, cy, buttonWidth/3,19, &emd->flag, 0, 0, 0, 0, "Show mesh when particles are alive");
1543                         uiDefButBitS(block, TOG, eExplodeFlag_Dead, B_MODIFIER_RECALC, "Dead",  lx+buttonWidth*2/3, cy, buttonWidth/3,19, &emd->flag, 0, 0, 0, 0, "Show mesh when particles are dead");
1544                         uiBlockEndAlign(block);
1545                 } else if (md->type==eModifierType_Shrinkwrap) {
1546                         ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
1547
1548                         char shrinktypemenu[]="Shrinkwrap type%t|nearest surface point %x0|projection %x1|nearest vertex %x2";
1549
1550                         uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &smd->target, "Target to shrink to");
1551
1552                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &smd->vgroup_name, 0, 31, 0, 0, "Vertex Group name");
1553                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1554
1555                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Offset:",     lx,(cy-=19),buttonWidth,19, &smd->keepDist, 0.0f, 100.0f, 1.0f, 0, "Specify distance to keep from the target");
1556
1557                         cy -= 3;
1558                         uiDefButS(block, MENU, B_MODIFIER_RECALC, shrinktypemenu, lx,(cy-=19),buttonWidth,19, &smd->shrinkType, 0, 0, 0, 0, "Selects type of shrinkwrap algorithm for target position.");
1559
1560                         uiDefButC(block, NUM, B_MODIFIER_RECALC, "SS Levels:",          lx, (cy-=19), buttonWidth,19, &smd->subsurfLevels, 0, 6, 0, 0, "This indicates the number of CCSubdivisions that must be performed before extracting vertexs positions and normals");
1561
1562                         if (smd->shrinkType == MOD_SHRINKWRAP_PROJECT){
1563
1564
1565                                 /* UI for projection axis */
1566                                 uiBlockBeginAlign(block);
1567                                 uiDefButC(block, ROW, B_MODIFIER_RECALC, "Normal"    , lx,(cy-=19),buttonWidth,19, &smd->projAxis, 18.0, MOD_SHRINKWRAP_PROJECT_OVER_NORMAL, 0, 0, "Projection over X axis");
1568
1569                                 uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS, B_MODIFIER_RECALC, "X",    lx+buttonWidth/3*0,(cy-=19),buttonWidth/3,19, &smd->projAxis, 0, 0, 0, 0, "Projection over X axis");
1570                                 uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS, B_MODIFIER_RECALC, "Y",    lx+buttonWidth/3*1,cy,buttonWidth/3,19, &smd->projAxis, 0, 0, 0, 0, "Projection over Y axis");
1571                                 uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS, B_MODIFIER_RECALC, "Z",    lx+buttonWidth/3*2,cy,buttonWidth/3,19, &smd->projAxis, 0, 0, 0, 0, "Projection over Z axis");
1572
1573
1574                                 /* allowed directions of projection axis */
1575                                 uiDefButBitS(block, TOG, MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR, B_MODIFIER_RECALC, "Negative",   lx,(cy-=19),buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Allows to move the vertex in the negative direction of axis");
1576                                 uiDefButBitS(block, TOG, MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR, B_MODIFIER_RECALC, "Positive",   lx + buttonWidth/2,cy,buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Allows to move the vertex in the positive direction of axis");
1577
1578                                 uiDefButBitS(block, TOG, MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE, B_MODIFIER_RECALC, "Cull frontfaces",lx,(cy-=19),buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Controls whether a vertex can be projected to a front face on target");
1579                                 uiDefButBitS(block, TOG, MOD_SHRINKWRAP_CULL_TARGET_BACKFACE,  B_MODIFIER_RECALC, "Cull backfaces",     lx+buttonWidth/2,cy,buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Controls whether a vertex can be projected to a back face on target");
1580                                 uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob2: ",        lx, (cy-=19), buttonWidth,19, &smd->auxTarget, "Aditional mesh to project over");
1581                         }
1582                         else if (smd->shrinkType == MOD_SHRINKWRAP_NEAREST_SURFACE){
1583                                 uiDefButBitS(block, TOG, MOD_SHRINKWRAP_KEEP_ABOVE_SURFACE, B_MODIFIER_RECALC, "Above surface", lx,(cy-=19),buttonWidth,19, &smd->shrinkOpts, 0, 0, 0, 0, "Vertices are kept on the front side of faces");
1584                         }
1585
1586                         uiBlockEndAlign(block);
1587
1588                 } else if (md->type==eModifierType_SimpleDeform) {
1589                         SimpleDeformModifierData *smd = (SimpleDeformModifierData*) md;
1590                         char simpledeform_modemenu[] = "Deform type%t|Twist %x1|Bend %x2|Taper %x3|Strech %x4";
1591
1592                         uiDefButC(block, MENU, B_MODIFIER_RECALC, simpledeform_modemenu, lx,(cy-=19),buttonWidth,19, &smd->mode, 0, 0, 0, 0, "Selects type of deform to apply to object.");
1593                         
1594                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &smd->vgroup_name, 0, 31, 0, 0, "Vertex Group name");
1595                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1596
1597                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ",      lx, (cy-=19), buttonWidth,19, &smd->origin, "Origin of modifier space coordinates");
1598                         if(smd->origin != NULL)
1599                                 uiDefButBitC(block, TOG, MOD_SIMPLEDEFORM_ORIGIN_LOCAL, B_MODIFIER_RECALC, "Relative",lx,(cy-=19),buttonWidth,19, &smd->originOpts, 0, 0, 0, 0, "Sets the origin of deform space to be relative to the object");
1600
1601                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Factor:",     lx,(cy-=19),buttonWidth,19, &smd->factor, -10.0f, 10.0f, 0.5f, 0, "Deform Factor");
1602
1603                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Upper Limit:",        lx,(cy-=19),buttonWidth,19, &smd->limit[1], 0.0f, 1.0f, 5.0f, 0, "Upper Limit for deform");
1604                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Lower Limit:",        lx,(cy-=19),buttonWidth,19, &smd->limit[0], 0.0f, 1.0f, 5.0f, 0, "Lower Limit for deform");
1605
1606                         if(smd->mode == MOD_SIMPLEDEFORM_MODE_STRETCH
1607                         || smd->mode == MOD_SIMPLEDEFORM_MODE_TAPER  )
1608                         {
1609                                 uiDefButBitC(block, TOG, MOD_SIMPLEDEFORM_LOCK_AXIS_X, B_MODIFIER_RECALC, "Loc X", lx,             (cy-=19),buttonWidth/2,19, &smd->axis, 0, 0, 0, 0, "Disallow changes on the X coordinate");
1610                                 uiDefButBitC(block, TOG, MOD_SIMPLEDEFORM_LOCK_AXIS_Y, B_MODIFIER_RECALC, "Loc Y", lx+(buttonWidth/2), (cy),buttonWidth/2,19, &smd->axis, 0, 0, 0, 0, "Disallow changes on the Y coordinate");
1611                         }
1612                 }
1613
1614                 uiBlockEndAlign(block);
1615         }
1616
1617         if (md->error) {
1618
1619                 row = uiLayoutRow(uiLayoutBox(column), 0);
1620
1621                 /* XXX uiBlockSetCol(block, color); */
1622                 uiItemL(row, md->error, ICON_ERROR);
1623                 /* XXX uiBlockSetCol(block, TH_AUTO); */
1624         }
1625
1626         return result;
1627 }
1628
1629 uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
1630 {
1631         Object *ob;
1632         ModifierData *md, *vmd;
1633         int i, lastCageIndex, cageIndex;
1634
1635         /* verify we have valid data */
1636         if(!RNA_struct_is_a(ptr->type, &RNA_Modifier)) {
1637                 printf("uiTemplateModifier: expected modifier on object.\n");
1638                 return NULL;
1639         }
1640
1641         ob= ptr->id.data;
1642         md= ptr->data;
1643
1644         if(!ob || !(GS(ob->id.name) == ID_OB)) {
1645                 printf("uiTemplateModifier: expected modifier on object.\n");
1646                 return NULL;
1647         }
1648         
1649         uiBlockSetButLock(uiLayoutBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
1650         
1651         /* find modifier and draw it */
1652         cageIndex = modifiers_getCageIndex(ob, &lastCageIndex);
1653
1654         // XXX virtual modifiers are not accesible for python
1655         vmd = modifiers_getVirtualModifierList(ob);
1656
1657         for(i=0; vmd; i++, vmd=vmd->next) {
1658                 if(md == vmd)
1659                         return draw_modifier(C, layout, ob, md, i, cageIndex, lastCageIndex);
1660                 else if(vmd->mode&eModifierMode_Virtual)
1661                         i--;
1662         }
1663
1664         return NULL;
1665 }
1666