2ec30bfa864e93418bba85d358916ff694747765
[blender-staging.git] / source / blender / src / buttons_editing.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  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <time.h>
31 #include <math.h>
32 #include <stdlib.h>
33 #include <stddef.h>
34 #include <string.h>
35
36 #ifdef WIN32
37 #ifndef snprintf
38 #define snprintf _snprintf
39 #endif
40 #endif
41
42 #include "MEM_guardedalloc.h"
43 #include "DNA_screen_types.h"
44 #include "DNA_space_types.h"
45 #include "DNA_scene_types.h"
46
47 #include "DNA_action_types.h"
48 #include "DNA_armature_types.h"
49 #include "DNA_brush_types.h"
50 #include "DNA_camera_types.h"
51 #include "DNA_cloth_types.h"
52 #include "DNA_color_types.h"
53 #include "DNA_constraint_types.h"
54 #include "DNA_curve_types.h"
55 #include "DNA_effect_types.h"
56 #include "DNA_group_types.h"
57 #include "DNA_key_types.h"
58 #include "DNA_lamp_types.h"
59 #include "DNA_lattice_types.h"
60 #include "DNA_material_types.h"
61 #include "DNA_meta_types.h"
62 #include "DNA_mesh_types.h"
63 #include "DNA_meshdata_types.h"
64 #include "DNA_modifier_types.h"
65 #include "DNA_nla_types.h"
66 #include "DNA_object_types.h"
67 #include "DNA_object_force.h"
68 #include "DNA_particle_types.h"
69 #include "DNA_radio_types.h"
70 #include "DNA_screen_types.h"
71 #include "DNA_texture_types.h"
72 #include "DNA_userdef_types.h"
73 #include "DNA_vfont_types.h"
74 #include "DNA_view3d_types.h"
75 #include "DNA_world_types.h"
76 #include "DNA_packedFile_types.h"
77
78 #include "BKE_blender.h"
79 #include "BKE_brush.h"
80 #include "BKE_cloth.h"
81 #include "BKE_curve.h"
82 #include "BKE_customdata.h"
83 #include "BKE_colortools.h"
84 #include "BKE_deform.h"
85 #include "BKE_depsgraph.h"
86 #include "BKE_global.h"
87 #include "BKE_key.h"
88 #include "BKE_library.h"
89 #include "BKE_main.h"
90 #include "BKE_mesh.h"
91 #include "BKE_modifier.h"
92 #include "BKE_multires.h"
93 #include "BKE_packedFile.h"
94 #include "BKE_particle.h"
95 #include "BKE_scene.h"
96 #include "BKE_bmesh.h"
97
98 #include "BLI_blenlib.h"
99 #include "BLI_arithb.h"
100 #include "BLI_vfontdata.h"
101 #include "BLI_editVert.h"
102 #include "BLI_dynstr.h"
103
104 #include "BSE_filesel.h"
105
106 #include "BIF_gl.h"
107 #include "BIF_editaction.h"
108 #include "BIF_editarmature.h"
109 #include "BIF_editconstraint.h"
110 #include "BIF_editdeform.h"
111 #include "BIF_editfont.h"
112 #include "BIF_editkey.h"
113 #include "BIF_editmesh.h"
114 #include "BIF_editparticle.h"
115 #include "BIF_imasel.h"
116 #include "BIF_interface.h"
117 #include "BIF_meshtools.h"
118 #include "BIF_mywindow.h"
119 #include "BIF_poselib.h"
120 #include "BIF_poseobject.h"
121 #include "BIF_renderwin.h"
122 #include "BIF_resources.h"
123 #include "BIF_retopo.h"
124 #include "BIF_screen.h"
125 #include "BIF_scrarea.h"
126 #include "BIF_space.h"
127 #include "BIF_toets.h"
128 #include "BIF_toolbox.h"
129 #include "BIF_previewrender.h"
130 #include "BIF_butspace.h"
131
132 #ifdef WITH_VERSE
133 #include "BIF_verse.h"
134 #endif
135
136 #include "mydevice.h"
137 #include "blendef.h"
138
139 #include "BKE_action.h"
140 #include "BKE_anim.h"
141 #include "BKE_armature.h"
142 #include "BKE_constraint.h"
143 #include "BKE_curve.h"
144 #include "BKE_displist.h"
145 #include "BKE_DerivedMesh.h"
146 #include "BKE_effect.h"
147 #include "BKE_font.h"
148 #include "BKE_icons.h"
149 #include "BKE_image.h"
150 #include "BKE_ipo.h"
151 #include "BKE_lattice.h"
152 #include "BKE_material.h"
153 #include "BKE_mball.h"
154 #include "BKE_mesh.h"
155 #include "BKE_object.h"
156 #include "BKE_texture.h"
157 #include "BKE_utildefines.h"
158
159 #include "BIF_poseobject.h"
160
161 #include "BDR_drawobject.h"
162 #include "BDR_editcurve.h"
163 #include "BDR_editface.h"
164 #include "BDR_editobject.h"
165 #include "BDR_sculptmode.h"
166 #include "BDR_vpaint.h"
167 #include "BDR_unwrapper.h"
168
169 #include "BSE_drawview.h"
170 #include "BSE_editipo.h"
171 #include "BSE_edit.h"
172 #include "BSE_filesel.h"
173 #include "BSE_headerbuttons.h"
174 #include "BSE_trans_types.h"
175 #include "BSE_view.h"
176 #include "BSE_seqaudio.h"
177
178 #include "RE_render_ext.h"              // make_sticky
179
180 #include "butspace.h" // own module
181 #include "multires.h"
182
183 #include "reeb.h"
184
185 static float editbutweight= 1.0;
186 float editbutvweight= 1;
187 static int actmcol= 0, acttface= 0, acttface_rnd = 0, acttface_clone = 0, acttface_mask = 0, actmcol_rnd = 0;
188
189 extern ListBase editNurb;
190
191 /* *************************** Unicode Character Groups ****************** */
192 unicodect uctabname[125] = {
193         {"All", "All", 0x0000, 0xffff},
194         {"Basic Latin", "Basic Latin", 0x0000, 0x007f},
195         {"Latin 1 Supp", "Latin-1 Supplement", 0x0080, 0x00ff}, 
196
197         {"Latin Ext. A.", "Latin Extended-A", 0x0100, 0x017F},
198         {"Latin Ext. B.", "Latin Extended-B", 0x0180,0x024F}, 
199         {"Latin Ext. Add.", "Latin Extended Additional", 0x1e00, 0x1eff},
200
201         {"IPA Ext", "IPA Extensions", 0x0250, 0x02AF},
202         {"Spacing Mod.", "Spacing Modifier Letters", 0x02b0, 0x02ff},
203
204         {"Comb. Dia.", "Combining Diacritical Marks", 0x0300, 0x036F},
205         {"Greek, Coptic", "Greek and Coptic", 0x0370, 0x03ff},
206         {"Greek Ext.", "Greek Extended", 0x1f00, 0x1fff},
207
208         {"Cyrillic", "Cyrillic", 0x0400, 0x04ff},
209         {"Cyrillic Supp.", "Cyrillic Supplementary", 0x0500, 0x052f},
210
211         {"Armenian", "Armenian", 0x0530, 0x058f},
212         {"Hebrew", "Hebrew", 0x0590, 0x05ff},
213
214         
215         {"Arabic", "Arabic", 0x0600, 0x06ff},
216         {"Syriac", "Syriac", 0x0700, 0x074f},
217
218         {"Thaana", "Thaana", 0x0780, 0x07bf},
219         {"Devanagari", "Devanagari", 0x0900, 0x097f},
220
221         {"Bengali", "Bengali", 0x0980, 0x09ff},
222         {"Gurmukhi", "Gurmukhi", 0x0a00, 0x0a7f},
223
224         {"Gujarati", "Gujarati", 0x0a80, 0x0aff},
225         {"Oriya", "Oriya", 0x0b00, 0x0b7f},
226
227         {"Tamil", "Tamil", 0x0b80, 0x0bff},
228         {"Tegulu", "Tegulu", 0x0c00, 0x0c7f},
229
230         {"Kannada", "Kannada", 0x0c80, 0x0cff},
231         {"Malayalam", "Malayalam", 0x0d00, 0x0d7f},
232
233         {"Sinhala", "Sinhala", 0x0d80, 0x0dff},
234         {"Thai", "Thai", 0x0e00, 0x0e7f},
235
236         {"Lao", "Lao", 0x0e80, 0x0eff},
237         {"Tibetan", "Tibetan", 0x0f00, 0x0fff},
238
239         {"Myanmar", "Myanmar", 0x1000, 0x109f},
240         {"Georgian", "Georgian", 0x10a0, 0x10ff},
241
242         {"Ethiopic", "Ethiopic", 0x1200, 0x137f},
243
244         {"Cherokee", "Cherokee", 0x13a0, 0x13ff},
245         {"Unif. Canadian", "Unified Canadian Aboriginal Syllabics", 0x1400, 0x167f},
246
247         {"Ogham", "Ogham", 0x1680, 0x169f},
248         {"Runic", "Runic", 0x16a0, 0x16ff},
249
250         {"Tagalog", "Tagalog", 0x1700, 0x171f},
251         {"Hanunoo", "Hanunoo", 0x1720, 0x173f},
252
253         {"Buhid", "Buhid", 0x1740, 0x175f},
254         {"Tagbanwa", "Tagbanwa", 0x1760, 0x177f},
255
256         {"Khmer", "Khmer", 0x1780, 0x17ff},
257         {"Khmer Symb", "Khmer Symbols", 0x19e0, 0x19ff},
258
259         {"Mongolian", "Mongolian", 0x1800, 0x18af},
260
261         {"Limbu", "Limbu", 0x1900, 0x194f},
262         {"Tai Le", "Tai Le", 0x1950, 0x197f},
263
264         {"Phon. Ext.", "Phonetic Extensions", 0x1d00, 0x1d7f},
265
266
267         {"Gen. Punct.", "General Punctutation", 0x2000, 0x206f},
268         {"Super, Sub", "Superscripts and Subscripts", 0x2070, 0x209f},
269
270         {"Curr. Symb.", "Currency Symbols", 0x20a0, 0x20cf},
271         {"Comb. Diacrit.", "Combining Diacritical Marks for Symbols", 0x20d0, 0x20ff},
272
273         {"Letter Symb", "Letterlike Symbols", 0x2100, 0x214f},
274         {"Numb. Forms", "Number Forms", 0x2150, 0x218f},
275
276         {"Arrows", "Arrows", 0x2190, 0x21ff},
277         {"Math Oper.", "Mathematical Operators", 0x2200, 0x22ff},
278
279         {"Misc. Tech.", "Miscellaneous Technical", 0x2300, 0x23ff},
280         {"Ctrl. Pict.", "Control Pictures", 0x2400, 0x243f},
281
282         {"OCR", "Optical Character Recognition", 0x2440, 0x245f},
283         {"Enc. Alpha", "Enclosed Alphanumerics", 0x2460, 0x24ff},
284
285         {"Bow Drawing", "Box Drawing", 0x2500, 0x257f},
286         {"BLock Elem.", "Block Elements", 0x2580, 0x259f},
287
288         {"Geom. Shapes", "Geometric Shapes", 0x25a0, 0x25ff},
289         {"Misc. Symb.", "Miscellaneous Symbols", 0x2600, 0x26ff},
290
291         {"Dingbats", "Dingbats", 0x2700, 0x27bf},
292         {"Misc. Math A", "Miscellaneous Mathematical Symbols-A", 0x27c0, 0x27ef},
293
294         {"Supp. Arrows-A", "Supplemental Arrows-A", 0x27f0, 0x27ff},
295         {"Braille Pat.", "Braille Patterns", 0x2800, 0x28ff},
296
297         {"Supp. Arrows-B", "Supplemental Arrows-B", 0x2900, 0x297f},
298         {"Misc. Math B", "Miscellaneous Mathematical Symbols-B", 0x2980, 0x29ff},
299
300         {"Supp. Math Op.", "Supplemental Mathematical Operators", 0x2a00, 0x2aff},
301         {"Misc. Symb.", "Miscellaneous Symbols and Arrows", 0x2b00, 0x2bff},
302
303         {"Kangxi Rad.", "Kangxi Radicals", 0x2f00, 0x2fdf},
304
305         {"Ideographic", "Ideographic Description Characters", 0x2ff0, 0x2fff},
306
307         {"Hiragana", "Hiragana", 0x3040, 0x309f},
308         {"Katakana", "Katakana", 0x30a0, 0x30ff},
309         {"Katakana Ext.", "Katakana Phonetic Extensions", 0x31f0, 0x31ff},
310
311         {"Bopomofo", "Bopomofo", 0x3100, 0x312f},
312         {"Bopomofo Ext.", "Bopomofo Extended", 0x31a0, 0x31bf},
313
314         {"Hangul", "Hangul Jamo", 0x1100, 0x11ff},
315         {"Hangul Comp.", "Hangul Compatibility Jamo", 0x3130, 0x318f},
316         {"Hangul Syll.", "Hangul Syllables", 0xac00, 0xd7af},
317
318         {"Kanbun", "Kanbun", 0x3190, 0x319f},
319
320
321
322         {"Yijing Hex.", "Yijing Hexagram Symbols", 0x4dc0, 0x4dff},
323
324         {"Yi Syllables", "Yi Syllables", 0xa000, 0xa48f},
325         {"Yi Radicals", "Yi Radicals", 0xa490, 0xa4cf},
326
327         {"High Surr.", "High Surrogate Area", 0xd800, 0xdbff},
328
329         {"Low Surr.", "Low Surrogates", 0xdc00, 0xdfff},
330         {"Priv. Use Area", "Private Use Area", 0xe000, 0xf8ff},
331
332         {"CJK Rad. Supp.", "CJK Radicals Supplement", 0x2e80, 0x2eff},
333         {"CJK Ideographs", "CJK Unified Ideographs", 0x4e00, 0x9faf},
334         {"CJK Ideog. Ext. A", "CJK Unified Ideographs Extension A", 0x3400, 0x4dbf},
335         {"CJK Ideog. Ext. B", "CJK Unified Ideographs Extension B", 0x20000, 0x2a6df},
336         {"CJK Symbols.", "CJK Symbols and Punctuation", 0x3000, 0x303f},
337         {"Enclosed CJK", "Enclosed CJK Letters and Months", 0x3200, 0x32ff},
338         {"CJK Comp.", "CJK Compatibility", 0x3300, 0x33ff},
339         {"CJK Comp. Ideog.", "CJK Compatibility Ideographs", 0xf900, 0xfaff},
340         {"CJK Comp. Forms", "CJK Compatibility Forms", 0xfe30, 0xfe4f},
341         {"CJK Comp. Supp.", "CJK Compatibility Ideographs Supplement", 0x2f800, 0x2fa1f},
342
343         {"Alpha. Pres. Forms", "Alphabetic Presentation Forms", 0xfb00, 0xfb4f},
344
345         {"Arabic Pres. A", "Arabic Presentation Forms-A", 0xfb50, 0xfdff},
346         {"Arabic Pres. B", "Arabic Presentation Forms-B", 0xfe70, 0xfeff},
347
348         {"Var. Sel.", "Variation Selectors", 0xfe00, 0xfe0f},
349
350         {"Comb. Half", "Combining Half Marks", 0xfe20, 0xfe2f},
351
352         {"Sml. From Var.", "Small Form Variants", 0xfe50, 0xfe6f},
353
354         {"Half, Full Forms", "Halfwidth and Fullwidth Forms", 0xff00, 0xffef},
355         {"Specials", "Specials", 0xfff0, 0xffff},
356
357         {"Lin. B Syllab.", "Linear B Syllabary", 0x10000, 0x1007f},
358         {"Lin. B Idog.", "Linear B Ideograms", 0x10080, 0x100ff},
359
360         {"Aegean Num.", "Aegean Numbers", 0x10100, 0x1013f},
361         {"Old Italic", "Old Italic", 0x10300, 0x1032f},
362
363         {"Gothic", "Gothic", 0x10330, 0x1034f},
364         {"Ugaritic", "Ugaritic", 0x10380, 0x1039f},
365
366         {"Deseret", "Deseret", 0x10400, 0x1044f},
367         {"Shavian", "Shavian", 0x10450, 0x1047f},
368
369         {"Osmanya", "Osmanya", 0x10480, 0x104af},
370         {"Cypriot Syll", "Cypriot Syllabary", 0x10800, 0x1083f},
371
372         {"Bysantine Mus.", "Bysantine Musical Symbols", 0x1d000, 0x1d0ff},
373         {"Music Symb.", "Musical Symbols", 0x1d100, 0x1d1ff},
374
375         {"Tai Xuan Symb", "Tai Xuan Jing Symbols", 0x1d300, 0x1d35f},
376         {"Math. Alpha Symb.", "Mathematical Alpanumeric Symbols", 0x1d400, 0x1d7ff},
377
378
379         {"Tags", "Tags", 0xe0000, 0xe007f},
380         {"Var. Supp", "Variation Selectors Supplement", 0xe0100, 0xe01ef},
381
382         {"Supp. Priv. A", "Supplementary Private Use Area-A", 0xf0000, 0xffffd},
383         {"Supp. Priv. B", "Supplementary Private Use Area-B", 0x100000, 0x10fffd}
384 };
385
386
387 /* *************************** static functions prototypes ****************** */
388 VFont *exist_vfont(char *str);
389
390 /* *************** */
391
392 void do_common_editbuts(unsigned short event) // old name, is a mix of object and editing events.... 
393 {
394         EditMesh *em = G.editMesh;
395         EditFace *efa;
396         Base *base;
397         Object *ob= OBACT;
398         Material *ma;
399         Nurb *nu;
400         Curve *cu;
401         BezTriple *bezt;
402         BPoint *bp;
403         unsigned int local;
404         int a, bit, index= -1;
405
406         switch(event) {
407                 
408         case B_MATWICH:
409                 if(G.obedit && G.obedit->actcol>0) {
410                         if(G.obedit->type == OB_MESH) {
411                                 for(efa= em->faces.first; efa; efa= efa->next) {
412                                         if(efa->f & SELECT) {
413                                                 if(index== -1) index= efa->mat_nr;
414                                                 else if(index!=efa->mat_nr) {
415                                                         error("Mixed colors");
416                                                         return;
417                                                 }
418                                         }
419                                 }
420                         }
421                         else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
422                                 nu= editNurb.first;
423                                 while(nu) {
424                                         if( isNurbsel(nu) ) {
425                                                 if(index== -1) index= nu->mat_nr;
426                                                 else if(index!=nu->mat_nr) {
427                                                         error("Mixed colors");
428                                                         return;
429                                                 }
430                                         }
431                                         nu= nu->next;
432                                 }                               
433                         }
434                         if(index>=0) {
435                                 G.obedit->actcol= index+1;
436                                 scrarea_queue_winredraw(curarea);
437                         }
438                 }
439                 break;
440         case B_MATNEW:
441                 new_material_to_objectdata(ob);
442                 scrarea_queue_winredraw(curarea);
443                 BIF_undo_push("New material");
444                 allqueue(REDRAWBUTSSHADING, 0);
445                 allqueue(REDRAWVIEW3D_Z, 0);
446                 allqueue(REDRAWOOPS, 0);
447                 break;
448         case B_MATDEL:
449                 delete_material_index();
450                 scrarea_queue_winredraw(curarea);
451                 BIF_undo_push("Delete material index");
452                 allqueue(REDRAWBUTSSHADING, 0);
453                 allqueue(REDRAWVIEW3D_Z, 0);
454                 allqueue(REDRAWOOPS, 0);
455                 break;
456         case B_MATASS:
457                 if(G.obedit && G.obedit->actcol>0) {
458                         if(G.obedit->type == OB_MESH) {
459                                 efa= em->faces.first;
460                                 while(efa) {
461                                         if(efa->f & SELECT)
462                                                 efa->mat_nr= G.obedit->actcol-1;
463                                         efa= efa->next;
464                                 }
465                         }
466                         else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
467                                 nu= editNurb.first;
468                                 while(nu) {
469                                         if( isNurbsel(nu) )
470                                                 nu->mat_nr= nu->charidx= G.obedit->actcol-1;
471                                         nu= nu->next;
472                                 }
473                         }
474                         else if (G.obedit->type == OB_FONT) {
475                         if (mat_to_sel()) {
476                                 allqueue(REDRAWVIEW3D, 0);
477                         }
478                         }
479                         allqueue(REDRAWVIEW3D_Z, 0);
480                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
481                         shade_buttons_change_3d();
482                         BIF_undo_push("Assign material index");
483                 }
484                 break;
485         case B_MATASS_BROWSE:
486                 /* if slot available, make that index active, and assign */
487                 /* else, make new slot, and assign */
488                 ma= BLI_findlink(&G.main->mat, G.buts->menunr-1);
489                 if(ma) {
490                         ob->actcol= find_material_index(ob, ma);
491                         if(ob->actcol==0) {
492                                 assign_material(ob, ma, ob->totcol+1);
493                                 ob->actcol= ob->totcol;
494                         }
495                 }
496                 else {
497                         do_common_editbuts(B_MATNEW);
498                 }
499                 do_common_editbuts(B_MATASS);
500                 break;
501                 
502         case B_MATCOL2:
503                 ma= give_current_material(ob, ob->actcol);
504                 BKE_icon_changed(BKE_icon_getid((ID *)ma));
505                 allqueue(REDRAWVIEW3D, 0);
506                 allqueue(REDRAWBUTSEDIT, 0);
507                 break;
508                 
509         case B_MATSEL:
510         case B_MATDESEL:
511                 if(G.obedit) {
512                         if(G.obedit->type == OB_MESH) {
513                                 if (event==B_MATSEL) {
514                                         editmesh_select_by_material(G.obedit->actcol-1);
515                                 } else {
516                                         editmesh_deselect_by_material(G.obedit->actcol-1);
517                                 }
518                         }
519                         else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
520                                 nu= editNurb.first;
521                                 while(nu) {
522                                         if(nu->mat_nr==G.obedit->actcol-1) {
523                                                 if(nu->bezt) {
524                                                         a= nu->pntsu;
525                                                         bezt= nu->bezt;
526                                                         while(a--) {
527                                                                 if(bezt->hide==0) {
528                                                                         if(event==B_MATSEL) {
529                                                                                 bezt->f1 |= SELECT;
530                                                                                 bezt->f2 |= SELECT;
531                                                                                 bezt->f3 |= SELECT;
532                                                                         }
533                                                                         else {
534                                                                                 bezt->f1 &= ~SELECT;
535                                                                                 bezt->f2 &= ~SELECT;
536                                                                                 bezt->f3 &= ~SELECT;
537                                                                         }
538                                                                 }
539                                                                 bezt++;
540                                                         }
541                                                 }
542                                                 else if(nu->bp) {
543                                                         a= nu->pntsu*nu->pntsv;
544                                                         bp= nu->bp;
545                                                         while(a--) {
546                                                                 if(bp->hide==0) {
547                                                                         if(event==B_MATSEL) bp->f1 |= SELECT;
548                                                                         else bp->f1 &= ~SELECT;
549                                                                 }
550                                                                 bp++;
551                                                         }
552                                                 }
553                                         }
554                                         nu= nu->next;
555                                 }
556                                 BIF_undo_push("Select material index");
557                         }
558                         allqueue(REDRAWIMAGE, 0);
559                         allqueue(REDRAWVIEW3D, 0);
560                 }
561                 countall();
562                 break;
563         case B_HIDE:
564                 if(G.obedit) {
565                         if(G.obedit->type == OB_MESH) hide_mesh(0);
566                         else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) hideNurb(0);
567                 }
568                 break;
569         case B_REVEAL:
570                 if(G.obedit) {
571                         if(G.obedit->type == OB_MESH) reveal_mesh();
572                         else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) revealNurb();
573                 }
574                 else if(FACESEL_PAINT_TEST) reveal_tface();
575                 
576                 break;
577         case B_SELSWAP:
578                 if(G.obedit) {
579                         if(G.obedit->type == OB_MESH) selectswap_mesh();
580                         else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) selectswapNurb();
581                 }
582                 break;
583         case B_AUTOTEX:
584                 if(ob && G.obedit==0) {
585                         if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) tex_space_curve(ob->data);
586                 }
587                 break;
588         case B_DOCENTER:
589                 docenter(0);
590                 break;
591         case B_DOCENTERNEW:
592                 docenter_new();
593                 break;
594         case B_DOCENTERCURSOR:
595                 docenter_cursor();
596                 break;
597         case B_SETSMOOTH:
598         case B_SETSOLID:
599                 if(G.obedit) {
600                         if(G.obedit->type == OB_MESH) {
601                                 mesh_set_smooth_faces((event==B_SETSMOOTH));
602                         }
603                         else {
604                                 nurb_set_smooth((event==B_SETSMOOTH));
605                         }
606                 }
607                 else if(G.vd) {
608                         base= FIRSTBASE;
609                         while(base) {
610                                 if(TESTBASELIB(base)) {
611                                         if(base->object->type==OB_MESH) {
612                                                 mesh_set_smooth_flag(base->object, (event==B_SETSMOOTH));
613                                         }
614                                         else if ELEM(base->object->type, OB_SURF, OB_CURVE) {
615                                                 cu= base->object->data;
616                                                 nu= cu->nurb.first;
617                                                 while(nu) {
618                                                         if(event==B_SETSMOOTH) nu->flag |= ME_SMOOTH;
619                                                         else nu->flag &= ~ME_SMOOTH;
620                                                         nu= nu->next;
621                                                 }
622                                                 makeDispListCurveTypes(base->object, 0);
623                                         }
624                                 }
625                                 base= base->next;
626                         }
627                         allqueue(REDRAWVIEW3D, 0);
628                         
629                         if(event == B_SETSMOOTH) BIF_undo_push("Set Smooth");
630                         else BIF_undo_push("Set Solid");
631                 }
632                 break;
633         case B_CHANGEDEP:
634                 DAG_scene_sort(G.scene); // makes new dag
635                 if(ob) ob->recalc |= OB_RECALC;
636                 allqueue(REDRAWVIEW3D, 0);
637                 break;
638         
639         case B_ADDKEY:
640                 insert_shapekey(ob);
641                 break;
642         case B_SETKEY:
643                 ob->shapeflag |= OB_SHAPE_TEMPLOCK;
644                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
645                 allqueue(REDRAWVIEW3D, 0);
646                 allqueue(REDRAWIPO, 0);
647                 allqueue(REDRAWBUTSEDIT, 0);
648                 break;
649         case B_LOCKKEY:
650                 ob->shapeflag &= ~OB_SHAPE_TEMPLOCK;
651                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
652                 allqueue(REDRAWVIEW3D, 0);
653                 allqueue(REDRAWIPO, 0);
654                 allqueue(REDRAWBUTSEDIT, 0);
655                 break;
656         case B_NEXTKEY:
657         {
658                 Key *key= ob_get_key(ob);
659                 if(ob->shapenr == BLI_countlist(&key->block))
660                    ob->shapenr= 1;
661                 else ob->shapenr++;
662                 do_common_editbuts(B_SETKEY);
663                 break;
664         }
665         case B_PREVKEY:
666         {
667                 Key *key= ob_get_key(ob);
668                 if(ob->shapenr <= 1)
669                         ob->shapenr= BLI_countlist(&key->block);
670                 else ob->shapenr--;
671                 do_common_editbuts(B_SETKEY);
672                 break;
673         }
674         case B_NAMEKEY:
675                 allspace(REMAKEIPO, 0);
676         allqueue (REDRAWIPO, 0);
677                 break;
678         case B_DELKEY:
679                 delete_key(OBACT);
680                 allqueue(REDRAWACTION, 0);
681                 break;
682                 
683                 
684         default:
685                 if (G.vd==NULL)
686                         break;
687                 
688                 if(event>=B_OBLAY && event<=B_OBLAY+31) {
689                         local= BASACT->lay & 0xFF000000;
690                         BASACT->lay -= local;
691                         if(BASACT->lay==0 || (G.qual & LR_SHIFTKEY)==0) {
692                                 bit= event-B_OBLAY;
693                                 BASACT->lay= 1<<bit;
694                                 scrarea_queue_winredraw(curarea);
695                         }
696                         BASACT->lay += local;
697                         /* optimal redraw */
698                         if( (ob->lay & G.vd->lay) && (BASACT->lay & G.vd->lay) );
699                         else if( (ob->lay & G.vd->lay)==0 && (BASACT->lay & G.vd->lay)==0 );
700                         else {
701                                 allqueue(REDRAWVIEW3D, 0);
702                                 DAG_scene_sort(G.scene);
703                         }
704                         ob->lay= BASACT->lay;
705                 }
706         }
707
708 }
709
710 /* *************************** MESH  ******************************** */
711
712 static void verify_customdata_name_func(void *data1, void *data2)
713 {
714         CustomData *data= (CustomData*)data1;
715         CustomDataLayer *layer= (CustomDataLayer*)data2;
716
717         CustomData_set_layer_unique_name(data, layer - data->layers);
718 }
719
720 static void delete_customdata_layer(void *data1, void *data2)
721 {
722         Mesh *me= (Mesh*)data1;
723         CustomData *data= (G.obedit)? &G.editMesh->fdata: &me->fdata;
724         CustomDataLayer *layer= (CustomDataLayer*)data2;
725         void *actlayerdata, *rndlayerdata, *clonelayerdata, *masklayerdata, *layerdata=layer->data;
726         int type= layer->type;
727         int index= CustomData_get_layer_index(data, type);
728         int i, actindex, rndindex, cloneindex, maskindex;
729         
730         /*ok, deleting a non-active layer needs to preserve the active layer indices.
731           to do this, we store a pointer to the .data member of both layer and the active layer,
732           (to detect if we're deleting the active layer or not), then use the active
733           layer data pointer to find where the active layer has ended up.
734           
735           this is necassary because the deletion functions only support deleting the active
736           layer. */
737         actlayerdata = data->layers[CustomData_get_active_layer_index(data, type)].data;
738         rndlayerdata = data->layers[CustomData_get_render_layer_index(data, type)].data;
739         clonelayerdata = data->layers[CustomData_get_clone_layer_index(data, type)].data;
740         masklayerdata = data->layers[CustomData_get_mask_layer_index(data, type)].data;
741         CustomData_set_layer_active(data, type, layer - &data->layers[index]);
742
743         /* Multires is handled seperately because the display data is separate
744            from the data stored in multires */
745         if(me && me->mr) {
746                 multires_delete_layer(me, &me->mr->fdata, type, layer - &data->layers[index]);
747                 multires_level_to_editmesh(OBACT, me, 0);
748                 multires_finish_mesh_update(OBACT);
749         }
750         else if(G.obedit) {
751                 EM_free_data_layer(data, type);
752         }
753         else if(me) {
754                 CustomData_free_layer_active(data, type, me->totface);
755                 mesh_update_customdata_pointers(me);
756         }
757
758         if(!CustomData_has_layer(data, type)) {
759                 if(type == CD_MCOL && (G.f & G_VERTEXPAINT))
760                         G.f &= ~G_VERTEXPAINT; /* get out of vertexpaint mode */
761         }
762
763         /*reconstruct active layer*/
764         if (actlayerdata != layerdata) {
765                 /*find index. . .*/
766                 actindex = CustomData_get_layer_index(data, type);
767                 for (i=actindex; i<data->totlayer; i++) {
768                         if (data->layers[i].data == actlayerdata) {
769                                 actindex = i - actindex;
770                                 break;
771                         }
772                 }
773                 
774                 /*set index. . .*/
775                 CustomData_set_layer_active(data, type, actindex);
776         }
777         
778         if (rndlayerdata != layerdata) {
779                 /*find index. . .*/
780                 rndindex = CustomData_get_layer_index(data, type);
781                 for (i=rndindex; i<data->totlayer; i++) {
782                         if (data->layers[i].data == rndlayerdata) {
783                                 rndindex = i - rndindex;
784                                 break;
785                         }
786                 }
787                 
788                 /*set index. . .*/
789                 CustomData_set_layer_render(data, type, rndindex);
790         }
791         
792         if (clonelayerdata != layerdata) {
793                 /*find index. . .*/
794                 cloneindex = CustomData_get_layer_index(data, type);
795                 for (i=cloneindex; i<data->totlayer; i++) {
796                         if (data->layers[i].data == clonelayerdata) {
797                                 cloneindex = i - cloneindex;
798                                 break;
799                         }
800                 }
801                 
802                 /*set index. . .*/
803                 CustomData_set_layer_clone(data, type, cloneindex);
804         }
805         
806         if (masklayerdata != layerdata) {
807                 /*find index. . .*/
808                 maskindex = CustomData_get_layer_index(data, type);
809                 for (i=maskindex; i<data->totlayer; i++) {
810                         if (data->layers[i].data == masklayerdata) {
811                                 maskindex = i - maskindex;
812                                 break;
813                         }
814                 }
815                 
816                 /*set index. . .*/
817                 CustomData_set_layer_mask(data, type, maskindex);
818         }
819         
820         DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
821         
822         if(type == CD_MTFACE)
823                 BIF_undo_push("Delete UV Texture");
824         else if(type == CD_MCOL)
825                 BIF_undo_push("Delete Vertex Color");
826
827         allqueue(REDRAWVIEW3D, 0);
828         allqueue(REDRAWIMAGE, 0);
829         allqueue(REDRAWBUTSEDIT, 0);
830 }
831
832 static int customdata_buttons(
833         uiBlock *block, Mesh *me, CustomData *data,
834         int type, int *activep, int *renderp, int *clonep, int *maskp,
835         int setevt, int setevt_rnd, int setevt_clone, int setevt_mask, int newevt,
836         char *label, char *shortlabel, char *browsetip, char *browsetip_rnd, char *browsetip_clone, char *browsetip_mask,
837         char *newtip, char *deltip, int x, int y)
838 {
839         CustomDataLayer *layer;
840         uiBut *but;
841         int i, count= CustomData_number_of_layers(data, type);
842
843         if(count >= MAX_MTFACE) {
844                 uiDefBut(block, LABEL, 0, label, x,y,220,19, 0, 0.0, 0, 0, 0, "");
845         }
846         else {
847                 uiDefBut(block, LABEL, 0, label, x,y,140,19, 0, 0.0, 0, 0, 0, "");
848                 uiBlockBeginAlign(block);
849                 uiDefBut(block, BUT, newevt, "New", x+140,y,80,19, 0,0,0,0,0, newtip);
850                 uiBlockEndAlign(block);
851         }
852
853         y -= (count)? 24: 19;
854
855         uiBlockBeginAlign(block);
856         for (count=1, i=0; i<data->totlayer; i++) {
857                 layer= &data->layers[i];
858
859                 if(layer->type == type) {
860                         int xi = 0;
861                         *activep= layer->active + 1;
862                         *renderp= layer->active_rnd + 1;
863                         if (clonep) *clonep= layer->active_clone + 1;
864                         if (maskp) *maskp= layer->active_mask + 1;
865                         
866                         
867                         uiDefIconButI(block, ROW, setevt, ICON_VIEW3D, x,y,25,19, activep, 1.0, count, 0, 0, browsetip);
868                         uiDefIconButI(block, ROW, setevt_rnd, ICON_SCENE, x+25,y,25,19, renderp, 1.0, count, 0, 0, browsetip_rnd);
869                         
870                         if (clonep) {
871                                 uiDefIconButI(block, ROW, setevt_clone, ICON_TEXTURE, x+50,y,25,19, clonep, 1.0, count, 0, 0, browsetip_clone);
872                                 xi += 25;
873                         }
874                         
875                         if (maskp) {
876                                 uiDefIconButI(block, ROW, setevt_mask, ICON_PAINT, x+50+xi,y,25,19, maskp, 1.0, count, 0, 0, browsetip_mask);
877                                 xi += 25;
878                         }
879                         
880                         but=uiDefBut(block, TEX, setevt, "", x+50+xi,y,145-xi,19, layer->name, 0.0, 31.0, 0, 0, label);
881                         uiButSetFunc(but, verify_customdata_name_func, data, layer);
882                         but= uiDefIconBut(block, BUT, B_NOP, VICON_X, x+195,y,25,19, NULL, 0.0, 0.0, 0.0, 0.0, deltip);
883                         uiButSetFunc(but, delete_customdata_layer, me, layer);
884
885
886                         count++;
887                         y -= 19;
888                 }
889         }
890         uiBlockEndAlign(block);
891
892         return y;
893 }
894
895 static void editing_panel_mesh_type(Object *ob, Mesh *me)
896 {
897         uiBlock *block;
898         uiBut *but;
899         float val;
900         CustomData *fdata;
901         int yco;
902
903         block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_type", UI_EMBOSS, UI_HELV, curarea->win);
904         if( uiNewPanel(curarea, block, "Mesh", "Editing", 320, 0, 318, 204)==0) return;
905         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
906
907         uiBlockBeginAlign(block);
908         uiDefButBitS(block, TOG, ME_AUTOSMOOTH, REDRAWVIEW3D, "Auto Smooth",10,180,170,19, &me->flag, 0, 0, 0, 0, "Treats all set-smoothed faces with angles less than Degr: as 'smooth' during render");
909         uiDefButS(block, NUM, B_DIFF, "Degr:",                          10,160,170,19, &me->smoothresh, 1, 80, 0, 0, "Defines maximum angle between face normals that 'Auto Smooth' will operate on");
910         uiBlockEndAlign(block);
911
912         /* Retopo */
913         if(G.obedit) {
914                 uiBlockBeginAlign(block);
915                 but= uiDefButBitC(block,TOG,RETOPO,B_NOP, "Retopo", 10,130,170,19, &G.scene->toolsettings->retopo_mode, 0,0,0,0, "Turn on the re-topology tool");
916                 uiButSetFunc(but,retopo_toggle,ob,me);
917                 if(G.scene->toolsettings->retopo_mode) {
918                         but= uiDefButBitC(block,TOG,RETOPO_PAINT,B_NOP,"Paint", 10,110,55,19, &G.scene->toolsettings->retopo_mode,0,0,0,0, "Draw intersecting lines in the 3d view, ENTER creates quad or tri faces, wrapped onto other objects in the 3d view.");
919                         uiButSetFunc(but,retopo_paint_toggle,ob,me);
920                         but= uiDefBut(block,BUT,B_NOP,"Retopo All", 65,110,115,19, 0,0,0,0,0, "Apply the re-topology tool to all selected vertices");
921                         uiButSetFunc(but,retopo_do_all_cb,ob,me);
922                 }
923                 uiBlockEndAlign(block);
924         }
925
926         uiBlockBeginAlign(block);
927         uiDefBut(block, BUT,B_DOCENTER, "Center",                                       10, 80, 65, 19, 0, 0, 0, 0, 0, "Shifts object data to be centered about object's origin");
928         uiDefBut(block, BUT,B_DOCENTERNEW, "Center New",                        75, 80, 105, 19, 0, 0, 0, 0, 0, "Shifts object's origin to center of object data");
929         uiDefBut(block, BUT,B_DOCENTERCURSOR, "Center Cursor",          10, 60, 170, 19, 0, 0, 0, 0, 0, "Shifts object's origin to cursor location");
930         uiBlockEndAlign(block);
931
932         uiBlockBeginAlign(block);
933         uiDefButBitS(block, TOG, ME_TWOSIDED, REDRAWVIEW3D, "Double Sided",     10,30,170,19, &me->flag, 0, 0, 0, 0, "Render/display the mesh with double or single sided lighting");
934         uiDefButBitS(block, TOG, ME_NOPUNOFLIP, REDRAWVIEW3D, "No V.Normal Flip", 10,10,170,19, &me->flag, 0, 0, 0, 0, "Disables flipping of vertexnormals during render");
935         uiBlockEndAlign(block);
936
937         uiDefIDPoinBut(block, test_meshpoin_but, ID_ME, B_REDR, "TexMesh: ",    190,180,220,19, &me->texcomesh, "Derive texture coordinates from another mesh.");
938
939         if(me->msticky) val= 1.0; else val= 0.0;
940         uiDefBut(block, LABEL, 0, "Sticky",                             190,155,140,19, 0, val, 0, 0, 0, "");
941         uiBlockBeginAlign(block);
942         if(me->msticky==NULL) {
943                 uiDefBut(block, BUT, B_MAKESTICKY, "Make",              330,155, 80,19, 0, 0, 0, 0, 0, "Creates Sticky coordinates from the current camera view background picture");
944         }
945         else uiDefBut(block, BUT, B_DELSTICKY, "Delete",        330,155, 80,19, 0, 0, 0, 0, 0, "Deletes Sticky texture coordinates");
946         uiBlockEndAlign(block);
947
948         fdata= (G.obedit)? &G.editMesh->fdata: &me->fdata;
949         yco= customdata_buttons(block, me, fdata, CD_MTFACE, &acttface, &acttface_rnd, (G.f & G_TEXTUREPAINT ? &acttface_clone : NULL), (G.f & G_TEXTUREPAINT ? &acttface_mask : NULL),
950                 B_SETTFACE, B_SETTFACE_RND, B_SETTFACE_CLONE, B_SETTFACE_MASK, B_NEWTFACE, "UV Texture", "UV Texture:",
951                 "Set active UV texture", "Set rendering UV texture", "Set the layer used for texturepaint cloning", "Set the texture paint stencil layer", "Creates a new UV texture layer",
952                 "Removes the current UV texture layer", 190, 130);
953
954         yco= customdata_buttons(block, me, fdata, CD_MCOL, &actmcol, &actmcol_rnd, NULL, NULL,
955                 B_SETMCOL, B_SETMCOL_RND, B_NOP, B_NOP, B_NEWMCOL, "Vertex Color", "Vertex Color:",
956                 "Sets active vertex color layer", "Sets rendering vertex color layer", "", "", "Creates a new vertex color layer",
957                 "Removes the current vertex color layer", 190, yco-5);
958
959         if(yco < 0)
960                 uiNewPanelHeight(block, 204 - yco);
961 }
962
963 /* *************************** MODIFIERS ******************************** */
964
965 void do_modifier_panels(unsigned short event)
966 {
967         Object *ob = OBACT;
968
969         switch(event) {
970         case B_MODIFIER_REDRAW:
971                 allqueue(REDRAWBUTSEDIT, 0);
972                 allqueue(REDRAWOOPS, 0);
973                 break;
974
975         case B_MODIFIER_RECALC:
976                 allqueue(REDRAWBUTSEDIT, 0);
977                 allqueue(REDRAWVIEW3D, 0);
978                 allqueue(REDRAWIMAGE, 0);
979                 allqueue(REDRAWOOPS, 0);
980                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
981                 object_handle_update(ob);
982                 countall();
983                 break;
984         }
985 }
986
987 static void modifiers_add(void *ob_v, int type)
988 {
989         Object *ob = ob_v;
990         ModifierTypeInfo *mti = modifierType_getInfo(type);
991         
992         if (mti->flags&eModifierTypeFlag_RequiresOriginalData) {
993                 ModifierData *md = ob->modifiers.first;
994
995                 while (md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform) {
996                         md = md->next;
997                 }
998
999                 BLI_insertlinkbefore(&ob->modifiers, md, modifier_new(type));
1000         } else {
1001                 BLI_addtail(&ob->modifiers, modifier_new(type));
1002         }
1003         BIF_undo_push("Add modifier");
1004 }
1005
1006 typedef struct MenuEntry {
1007         char *name;
1008         int ID;
1009 } MenuEntry;
1010
1011 static int menuEntry_compare_names(const void *entry1, const void *entry2)
1012 {
1013         return strcmp(((MenuEntry *)entry1)->name, ((MenuEntry *)entry2)->name);
1014 }
1015
1016 static uiBlock *modifiers_add_menu(void *ob_v)
1017 {
1018         Object *ob = ob_v;
1019         uiBlock *block;
1020         int i, yco=0;
1021         int numEntries = 0;
1022         MenuEntry entries[NUM_MODIFIER_TYPES];
1023         
1024         block= uiNewBlock(&curarea->uiblocks, "modifier_add_menu",
1025                           UI_EMBOSSP, UI_HELV, curarea->win);
1026         uiBlockSetButmFunc(block, modifiers_add, ob);
1027
1028         for (i=eModifierType_None+1; i<NUM_MODIFIER_TYPES; i++) {
1029                 ModifierTypeInfo *mti = modifierType_getInfo(i);
1030
1031                 /* Only allow adding through appropriate other interfaces */
1032                 if(ELEM3(i, eModifierType_Softbody, eModifierType_Hook, eModifierType_ParticleSystem)) continue;
1033                 
1034                 if(ELEM4(i, eModifierType_Cloth, eModifierType_Collision, eModifierType_Surface, eModifierType_Fluidsim)) continue;
1035
1036                 if((mti->flags&eModifierTypeFlag_AcceptsCVs) ||
1037                    (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
1038                         entries[numEntries].name = mti->name;
1039                         entries[numEntries].ID = i;
1040
1041                         ++numEntries;
1042                 }
1043         }
1044
1045         qsort(entries, numEntries, sizeof(*entries), menuEntry_compare_names);
1046
1047
1048         for(i = 0; i < numEntries; ++i)
1049                 uiDefBut(block, BUTM, B_MODIFIER_RECALC, entries[i].name,
1050                          0, yco -= 20, 160, 19, NULL, 0, 0, 1, entries[i].ID, "");
1051
1052         uiTextBoundsBlock(block, 50);
1053         uiBlockSetDirection(block, UI_DOWN);
1054
1055         return block;
1056 }
1057
1058 static void modifiers_del(void *ob_v, void *md_v)
1059 {
1060         Object *ob = ob_v;
1061         ModifierData *md;
1062
1063                 /* It seems on rapid delete it is possible to
1064                  * get called twice on same modifier, so make
1065                  * sure it is in list.
1066                  */
1067         for (md=ob->modifiers.first; md; md=md->next)
1068                 if (md==md_v)
1069                         break;
1070         
1071         if (!md)
1072                 return;
1073
1074         if(md->type==eModifierType_ParticleSystem){
1075                 ParticleSystemModifierData *psmd=(ParticleSystemModifierData*)md;
1076                 BLI_remlink(&ob->particlesystem, psmd->psys);
1077                 psys_free(ob,psmd->psys);
1078         }
1079
1080         BLI_remlink(&ob->modifiers, md_v);
1081
1082         modifier_free(md_v);
1083
1084         BIF_undo_push("Del modifier");
1085 }
1086
1087 int mod_moveUp(void *ob_v, void *md_v)
1088 {
1089         Object *ob = ob_v;
1090         ModifierData *md = md_v;
1091
1092         if (md->prev) {
1093                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1094
1095                 if (mti->type!=eModifierTypeType_OnlyDeform) {
1096                         ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type);
1097
1098                         if (nmti->flags&eModifierTypeFlag_RequiresOriginalData)
1099                                 return -1;
1100                 }
1101
1102                 BLI_remlink(&ob->modifiers, md);
1103                 BLI_insertlink(&ob->modifiers, md->prev->prev, md);
1104         }
1105
1106         return 0;
1107 }
1108
1109 static void modifiers_moveUp(void *ob_v, void *md_v)
1110 {
1111         if( mod_moveUp( ob_v, md_v ) )
1112                 error("Cannot move above a modifier requiring original data.");
1113         else
1114                 BIF_undo_push("Move modifier");
1115 }
1116
1117 int mod_moveDown(void *ob_v, void *md_v)
1118 {
1119         Object *ob = ob_v;
1120         ModifierData *md = md_v;
1121
1122         if (md->next) {
1123                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1124
1125                 if (mti->flags&eModifierTypeFlag_RequiresOriginalData) {
1126                         ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type);
1127
1128                         if (nmti->type!=eModifierTypeType_OnlyDeform)
1129                                 return -1;
1130                 }
1131
1132                 BLI_remlink(&ob->modifiers, md);
1133                 BLI_insertlink(&ob->modifiers, md->next, md);
1134         }
1135
1136         return 0;
1137 }
1138
1139 static void modifiers_moveDown(void *ob_v, void *md_v)
1140 {
1141         if( mod_moveDown( ob_v, md_v ) )
1142                 error("Cannot move beyond a non-deforming modifier.");
1143         else
1144                 BIF_undo_push("Move modifier");
1145 }
1146
1147 static void modifier_testLatticeObj(char *name, ID **idpp)
1148 {
1149         ID *id;
1150
1151         for (id= G.main->object.first; id; id= id->next) {
1152                 if( strcmp(name, id->name+2)==0 ) {
1153                         if (((Object *)id)->type != OB_LATTICE) {
1154                                 error ("Lattice deform object must be a lattice");
1155                                 break;
1156                         } 
1157                         *idpp= id;
1158                         return;
1159                 }
1160         }
1161         *idpp= 0;
1162 }
1163
1164 static void modifier_testCurveObj(char *name, ID **idpp)
1165 {
1166         ID *id;
1167
1168         for (id= G.main->object.first; id; id= id->next) {
1169                 if( strcmp(name, id->name+2)==0 ) {
1170                         if (((Object *)id)->type != OB_CURVE) {
1171                                 error ("Curve deform object must be a curve");
1172                                 break;
1173                         } 
1174                         *idpp= id;
1175                         return;
1176                 }
1177         }
1178         *idpp= 0;
1179 }
1180
1181 static void modifier_testMeshObj(char *name, ID **idpp)
1182 {
1183         ID *id;
1184
1185         for (id= G.main->object.first; id; id= id->next) {
1186                 /* no boolean on its own object */
1187                 if(id != (ID *)OBACT) {
1188                         if( strcmp(name, id->name+2)==0 ) {
1189                                 if (((Object *)id)->type != OB_MESH) {
1190                                         error ("Boolean modifier object must be a mesh");
1191                                         break;
1192                                 } 
1193                                 *idpp= id;
1194                                 return;
1195                         }
1196                 }
1197         }
1198         *idpp= NULL;
1199 }
1200
1201 static void modifier_testArmatureObj(char *name, ID **idpp)
1202 {
1203         ID *id;
1204
1205         for (id= G.main->object.first; id; id= id->next) {
1206                 if( strcmp(name, id->name+2)==0 ) {
1207                         if (((Object *)id)->type != OB_ARMATURE) {
1208                                 error ("Armature deform object must be an armature");
1209                                 break;
1210                         } 
1211                         *idpp= id;
1212                         return;
1213                 }
1214         }
1215         *idpp= 0;
1216 }
1217
1218 static void modifier_testTexture(char *name, ID **idpp)
1219 {
1220         ID *id;
1221
1222         for(id = G.main->tex.first; id; id = id->next) {
1223                 if(strcmp(name, id->name + 2) == 0) {
1224                         *idpp = id;
1225                         /* texture gets user, objects not: delete object = clear modifier */
1226                         id_us_plus(id);
1227                         return;
1228                 }
1229         }
1230         *idpp = 0;
1231 }
1232
1233 #if 0 /* this is currently unused, but could be useful in the future */
1234 static void modifier_testMaterial(char *name, ID **idpp)
1235 {
1236         ID *id;
1237
1238         for(id = G.main->mat.first; id; id = id->next) {
1239                 if(strcmp(name, id->name + 2) == 0) {
1240                         *idpp = id;
1241                         return;
1242                 }
1243         }
1244         *idpp = 0;
1245 }
1246 #endif
1247
1248 static void modifier_testImage(char *name, ID **idpp)
1249 {
1250         ID *id;
1251
1252         for(id = G.main->image.first; id; id = id->next) {
1253                 if(strcmp(name, id->name + 2) == 0) {
1254                         *idpp = id;
1255                         return;
1256                 }
1257         }
1258         *idpp = 0;
1259 }
1260
1261 /* autocomplete callback for ID buttons */
1262 void autocomplete_image(char *str, void *arg_v)
1263 {
1264         /* search if str matches the beginning of an ID struct */
1265         if(str[0]) {
1266                 AutoComplete *autocpl = autocomplete_begin(str, 22);
1267                 ID *id;
1268
1269                 for(id = G.main->image.first; id; id = id->next)
1270                         autocomplete_do_name(autocpl, id->name+2);
1271
1272                 autocomplete_end(autocpl, str);
1273         }
1274 }
1275
1276 /* autocomplete callback for ID buttons */
1277 void autocomplete_meshob(char *str, void *arg_v)
1278 {
1279         /* search if str matches the beginning of an ID struct */
1280         if(str[0]) {
1281                 AutoComplete *autocpl = autocomplete_begin(str, 22);
1282                 ID *id;
1283
1284                 for(id = G.main->object.first; id; id = id->next)
1285                         if(((Object *)id)->type == OB_MESH)
1286                                 autocomplete_do_name(autocpl, id->name+2);
1287
1288                 autocomplete_end(autocpl, str);
1289         }
1290 }
1291 static void modifiers_convertParticles(void *obv, void *mdv)
1292 {
1293         Object *obn;
1294         ModifierData *md = mdv;
1295         ParticleSystem *psys;
1296         ParticleCacheKey *key, **cache;
1297         ParticleSettings *part;
1298         Mesh *me;
1299         MVert *mvert;
1300         MEdge *medge;
1301         int a, k, kmax;
1302         int totvert=0, totedge=0, cvert=0;
1303         int totpart=0, totchild=0;
1304
1305         if(md->type != eModifierType_ParticleSystem) return;
1306
1307         if(G.f & G_PARTICLEEDIT) return;
1308
1309         psys=((ParticleSystemModifierData *)md)->psys;
1310         part= psys->part;
1311
1312         if(part->draw_as == PART_DRAW_GR || part->draw_as == PART_DRAW_OB) {
1313                 make_object_duplilist_real(NULL);
1314         }
1315         else {
1316                 if(part->draw_as != PART_DRAW_PATH || psys->pathcache == 0)
1317                         return;
1318
1319                 totpart= psys->totcached;
1320                 totchild= psys->totchildcache;
1321
1322                 if(totchild && (part->draw&PART_DRAW_PARENT)==0)
1323                         totpart= 0;
1324
1325                 /* count */
1326                 cache= psys->pathcache;
1327                 for(a=0; a<totpart; a++) {
1328                         key= cache[a];
1329                         totvert+= key->steps+1;
1330                         totedge+= key->steps;
1331                 }
1332
1333                 cache= psys->childcache;
1334                 for(a=0; a<totchild; a++) {
1335                         key= cache[a];
1336                         totvert+= key->steps+1;
1337                         totedge+= key->steps;
1338                 }
1339
1340                 if(totvert==0) return;
1341
1342                 /* add new mesh */
1343                 obn= add_object(OB_MESH);
1344                 me= obn->data;
1345                 
1346                 me->totvert= totvert;
1347                 me->totedge= totedge;
1348                 
1349                 me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
1350                 me->medge= CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
1351                 me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0);
1352                 
1353                 mvert= me->mvert;
1354                 medge= me->medge;
1355
1356                 /* copy coordinates */
1357                 cache= psys->pathcache;
1358                 for(a=0; a<totpart; a++) {
1359                         key= cache[a];
1360                         kmax= key->steps;
1361                         for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
1362                                 VECCOPY(mvert->co,key->co);
1363                                 if(k) {
1364                                         medge->v1= cvert-1;
1365                                         medge->v2= cvert;
1366                                         medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE;
1367                                         medge++;
1368                                 }
1369                         }
1370                 }
1371
1372                 cache=psys->childcache;
1373                 for(a=0; a<totchild; a++) {
1374                         key=cache[a];
1375                         kmax=key->steps;
1376                         for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
1377                                 VECCOPY(mvert->co,key->co);
1378                                 if(k) {
1379                                         medge->v1=cvert-1;
1380                                         medge->v2=cvert;
1381                                         medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE;
1382                                         medge++;
1383                                 }
1384                         }
1385                 }
1386         }
1387
1388         DAG_scene_sort(G.scene);
1389
1390         allqueue(REDRAWVIEW3D, 0);
1391         allqueue(REDRAWOOPS, 0);
1392         
1393         BIF_undo_push("Convert particles to mesh object(s).");
1394 }
1395
1396 static void modifiers_applyModifier(void *obv, void *mdv)
1397 {
1398         Object *ob = obv;
1399         ModifierData *md = mdv;
1400         DerivedMesh *dm;
1401         Mesh *me = ob->data;
1402         int converted = 0;
1403
1404         if (G.obedit) {
1405                 error("Modifiers cannot be applied in editmode");
1406                 return;
1407         } else if (((ID*) ob->data)->us>1) {
1408                 error("Modifiers cannot be applied to multi-user data");
1409                 return;
1410         }
1411
1412         if (md!=ob->modifiers.first) {
1413                 if (!okee("Modifier is not first"))
1414                         return;
1415         }
1416
1417         if (ob->type==OB_MESH) {
1418                 if(me->mr && multires_modifier_warning()) {
1419                         error("Modifier changes topology; cannot apply with multires active");
1420                         return;
1421                 }
1422                 if(me->key) {
1423                         error("Modifier cannot be applied to Mesh with Shape Keys");
1424                         return;
1425                 }
1426         
1427                 mesh_pmv_off(ob, me);
1428         
1429                 dm = mesh_create_derived_for_modifier(ob, md);
1430                 if (!dm) {
1431                         error("Modifier is disabled or returned error, skipping apply");
1432                         return;
1433                 }
1434
1435                 DM_to_mesh(dm, me);
1436                 converted = 1;
1437
1438                 dm->release(dm);
1439         } 
1440         else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
1441                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1442                 Curve *cu = ob->data;
1443                 int numVerts;
1444                 float (*vertexCos)[3];
1445
1446                 if (!okee("Apply will only change CV points, not tesselated/bevel vertices"))
1447                         return;
1448
1449                 if (!(md->mode&eModifierMode_Realtime) || (mti->isDisabled && mti->isDisabled(md))) {
1450                         error("Modifier is disabled, skipping apply");
1451                         return;
1452                 }
1453
1454                 vertexCos = curve_getVertexCos(cu, &cu->nurb, &numVerts);
1455                 mti->deformVerts(md, ob, NULL, vertexCos, numVerts);
1456                 curve_applyVertexCos(cu, &cu->nurb, vertexCos);
1457
1458                 converted = 1;
1459
1460                 MEM_freeN(vertexCos);
1461
1462                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1463         }
1464         else {
1465                 error("Cannot apply modifier for this object type");
1466                 return;
1467         }
1468
1469         if (converted) {
1470                 BLI_remlink(&ob->modifiers, md);
1471                 modifier_free(md);
1472
1473                 BIF_undo_push("Apply modifier");
1474         }
1475 }
1476
1477 static void modifiers_copyModifier(void *ob_v, void *md_v)
1478 {
1479         Object *ob = ob_v;
1480         ModifierData *md = md_v;
1481         ModifierData *nmd = modifier_new(md->type);
1482
1483         modifier_copyData(md, nmd);
1484
1485         BLI_insertlink(&ob->modifiers, md, nmd);
1486
1487         BIF_undo_push("Copy modifier");
1488 }
1489
1490 static void modifiers_setOnCage(void *ob_v, void *md_v)
1491 {
1492         Object *ob = ob_v;
1493         ModifierData *md;
1494         
1495         int i, cageIndex = modifiers_getCageIndex(ob, NULL );
1496
1497         for( i = 0, md=ob->modifiers.first; md; ++i, md=md->next )
1498                 if( md == md_v ) {
1499                         if( i >= cageIndex )
1500                                 md->mode ^= eModifierMode_OnCage;
1501                         break;
1502                 }
1503 }
1504
1505 static void modifiers_clearHookOffset(void *ob_v, void *md_v)
1506 {
1507         Object *ob = ob_v;
1508         ModifierData *md = md_v;
1509         HookModifierData *hmd = (HookModifierData*) md;
1510         
1511         if (hmd->object) {
1512                 Mat4Invert(hmd->object->imat, hmd->object->obmat);
1513                 Mat4MulSerie(hmd->parentinv, hmd->object->imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL);
1514                 BIF_undo_push("Clear hook offset");
1515         }
1516 }
1517
1518 static void modifiers_cursorHookCenter(void *ob_v, void *md_v)
1519 {
1520         Object *ob = ob_v;
1521         ModifierData *md = md_v;
1522         HookModifierData *hmd = (HookModifierData*) md;
1523
1524         if (G.vd) {
1525                 float *curs = give_cursor();
1526                 float bmat[3][3], imat[3][3];
1527
1528                 where_is_object(ob);
1529         
1530                 Mat3CpyMat4(bmat, ob->obmat);
1531                 Mat3Inv(imat, bmat);
1532
1533                 curs= give_cursor();
1534                 hmd->cent[0]= curs[0]-ob->obmat[3][0];
1535                 hmd->cent[1]= curs[1]-ob->obmat[3][1];
1536                 hmd->cent[2]= curs[2]-ob->obmat[3][2];
1537                 Mat3MulVecfl(imat, hmd->cent);
1538
1539                 BIF_undo_push("Hook cursor center");
1540         }
1541 }
1542
1543 static void modifiers_selectHook(void *ob_v, void *md_v)
1544 {
1545         ModifierData *md = md_v;
1546         HookModifierData *hmd = (HookModifierData*) md;
1547
1548         hook_select(hmd);
1549 }
1550
1551 static void modifiers_reassignHook(void *ob_v, void *md_v)
1552 {
1553         ModifierData *md = md_v;
1554         HookModifierData *hmd = (HookModifierData*) md;
1555         float cent[3];
1556         int *indexar, tot, ok;
1557         char name[32];
1558                 
1559         ok= hook_getIndexArray(&tot, &indexar, name, cent);
1560
1561         if (!ok) {
1562                 error("Requires selected vertices or active Vertex Group");
1563         } else {
1564                 if (hmd->indexar) {
1565                         MEM_freeN(hmd->indexar);
1566                 }
1567
1568                 VECCOPY(hmd->cent, cent);
1569                 hmd->indexar = indexar;
1570                 hmd->totindex = tot;
1571         }
1572 }
1573
1574 static void modifiers_convertToReal(void *ob_v, void *md_v)
1575 {
1576         Object *ob = ob_v;
1577         ModifierData *md = md_v;
1578         ModifierData *nmd = modifier_new(md->type);
1579
1580         modifier_copyData(md, nmd);
1581         nmd->mode &= ~eModifierMode_Virtual;
1582
1583         BLI_addhead(&ob->modifiers, nmd);
1584
1585         ob->partype = PAROBJECT;
1586
1587         BIF_undo_push("Modifier convert to real");
1588 }
1589
1590 static void build_uvlayer_menu_vars(CustomData *data, char **menu_string,
1591                                     int *uvlayer_tmp, char *uvlayer_name)
1592 {
1593         char strtmp[38];
1594         int totuv, i;
1595         CustomDataLayer *layer
1596                     = &data->layers[CustomData_get_layer_index(data, CD_MTFACE)];
1597
1598         *uvlayer_tmp = -1;
1599
1600         totuv = CustomData_number_of_layers(data, CD_MTFACE);
1601
1602         *menu_string = MEM_callocN(sizeof(**menu_string) * (totuv * 38 + 10),
1603                                    "menu_string");
1604         sprintf(*menu_string, "UV Layer%%t");
1605         for(i = 0; i < totuv; i++) {
1606                 /* assign first layer as uvlayer_name if uvlayer_name is null. */
1607                 if(strcmp(layer->name, uvlayer_name) == 0) *uvlayer_tmp = i + 1;
1608                 sprintf(strtmp, "|%s%%x%d", layer->name, i + 1);
1609                 strcat(*menu_string, strtmp);
1610                 layer++;
1611         }
1612
1613         /* there is no uvlayer defined, or else it was deleted. Assign active
1614          * layer, then recalc modifiers.
1615          */
1616         if(*uvlayer_tmp == -1) {
1617                 if(CustomData_get_active_layer_index(data, CD_MTFACE) != -1) {
1618                         *uvlayer_tmp = 1;
1619                         layer = data->layers;
1620                         for(i = 0; i < CustomData_get_active_layer_index(data, CD_MTFACE);
1621                             i++, layer++) {
1622                                 if(layer->type == CD_MTFACE) (*uvlayer_tmp)++;
1623                         }
1624                         strcpy(uvlayer_name, layer->name);
1625
1626                         /* update the modifiers */
1627                         do_modifier_panels(B_MODIFIER_RECALC);
1628                 } else {
1629                         /* ok we have no uv layers, so make sure menu button knows that.*/
1630                         *uvlayer_tmp = 0;
1631                 }
1632         }
1633 }
1634
1635 void set_wave_uvlayer(void *arg1, void *arg2)
1636 {
1637         WaveModifierData *wmd=arg1;
1638         CustomDataLayer *layer = arg2;
1639
1640         /*check we have UV layers*/
1641         if (wmd->uvlayer_tmp < 1) return;
1642         layer = layer + (wmd->uvlayer_tmp-1);
1643         
1644         strcpy(wmd->uvlayer_name, layer->name);
1645 }
1646
1647 void set_displace_uvlayer(void *arg1, void *arg2)
1648 {
1649         DisplaceModifierData *dmd=arg1;
1650         CustomDataLayer *layer = arg2;
1651
1652         /*check we have UV layers*/
1653         if (dmd->uvlayer_tmp < 1) return;
1654         layer = layer + (dmd->uvlayer_tmp-1);
1655         
1656         strcpy(dmd->uvlayer_name, layer->name);
1657 }
1658
1659 void set_uvproject_uvlayer(void *arg1, void *arg2)
1660 {
1661         UVProjectModifierData *umd=arg1;
1662         CustomDataLayer *layer = arg2;
1663
1664         /*check we have UV layers*/
1665         if (umd->uvlayer_tmp < 1) return;
1666         layer = layer + (umd->uvlayer_tmp-1);
1667         
1668         strcpy(umd->uvlayer_name, layer->name);
1669 }
1670
1671 static void modifiers_bindMeshDeform(void *ob_v, void *md_v)
1672 {
1673         MeshDeformModifierData *mmd = (MeshDeformModifierData*) md_v;
1674         Object *ob = (Object*)ob_v;
1675
1676         if(mmd->bindcos) {
1677                 if(mmd->bindweights) MEM_freeN(mmd->bindweights);
1678                 if(mmd->bindcos) MEM_freeN(mmd->bindcos);
1679                 if(mmd->dyngrid) MEM_freeN(mmd->dyngrid);
1680                 if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences);
1681                 if(mmd->dynverts) MEM_freeN(mmd->dynverts);
1682                 mmd->bindweights= NULL;
1683                 mmd->bindcos= NULL;
1684                 mmd->dyngrid= NULL;
1685                 mmd->dyninfluences= NULL;
1686                 mmd->dynverts= NULL;
1687                 mmd->totvert= 0;
1688                 mmd->totcagevert= 0;
1689                 mmd->totinfluence= 0;
1690         }
1691         else {
1692                 DerivedMesh *dm;
1693                 int mode= mmd->modifier.mode;
1694
1695                 /* force modifier to run, it will call binding routine */
1696                 mmd->needbind= 1;
1697                 mmd->modifier.mode |= eModifierMode_Realtime;
1698
1699                 if(ob->type == OB_MESH) {
1700                         dm= mesh_create_derived_view(ob, 0);
1701                         dm->release(dm);
1702                 }
1703                 else if(ob->type == OB_LATTICE) {
1704                         lattice_calc_modifiers(ob);
1705                 }
1706                 else if(ob->type==OB_MBALL) {
1707                         makeDispListMBall(ob);
1708                 }
1709                 else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
1710                         makeDispListCurveTypes(ob, 0);
1711                 }
1712
1713                 mmd->needbind= 0;
1714                 mmd->modifier.mode= mode;
1715         }
1716 }
1717
1718 void modifiers_explodeFacepa(void *arg1, void *arg2)
1719 {
1720         ExplodeModifierData *emd=arg1;
1721
1722         emd->flag |= eExplodeFlag_CalcFaces;
1723 }
1724
1725 void modifiers_explodeDelVg(void *arg1, void *arg2)
1726 {
1727         ExplodeModifierData *emd=arg1;
1728         emd->vgroup = 0;
1729 }
1730
1731 static int modifier_is_fluid_particles(ModifierData *md) {
1732         if(md->type == eModifierType_ParticleSystem) {
1733                 if(((ParticleSystemModifierData *)md)->psys->part->type == PART_FLUID)
1734                         return 1;
1735         }
1736         return 0;
1737 }
1738 static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco, int *yco, int index, int cageIndex, int lastCageIndex)
1739 {
1740         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1741         uiBut *but;
1742         int isVirtual = md->mode&eModifierMode_Virtual;
1743         int x = *xco, y = *yco, color = md->error?TH_REDALERT:TH_BUT_NEUTRAL;
1744         int editing = (G.obedit==ob);
1745         short height=26, width = 295, buttonWidth = width-120-10;
1746         char str[128];
1747
1748         /* rounded header */
1749         uiBlockSetCol(block, color);
1750                 /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1751         uiDefBut(block, ROUNDBOX, 0, "", x-10, y-4, width, 25, NULL, 7.0, 0.0, 
1752                          (!isVirtual && (md->mode&eModifierMode_Expanded))?3:15, 20, ""); 
1753         uiBlockSetCol(block, TH_AUTO);
1754         
1755         /* open/close icon */
1756         if (!isVirtual) {
1757                 uiBlockSetEmboss(block, UI_EMBOSSN);
1758                 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");
1759         }
1760
1761         uiBlockSetEmboss(block, UI_EMBOSS);
1762         
1763         if (isVirtual) {
1764                 sprintf(str, "%s parent deform", md->name);
1765                 uiDefBut(block, LABEL, 0, str, x+10, y-1, width-110, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name"); 
1766
1767                 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");
1768                 uiButSetFunc(but, modifiers_convertToReal, ob, md);
1769         } else {
1770                 uiBlockBeginAlign(block);
1771                 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"); 
1772
1773                 /* Softbody not allowed in this situation, enforce! */
1774                 if (((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) && (md->type!=eModifierType_Surface)) {
1775                         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");
1776                         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");
1777                         if (mti->flags&eModifierTypeFlag_SupportsEditmode) {
1778                                 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)");
1779                         }
1780                 }
1781                 uiBlockEndAlign(block);
1782
1783                 uiBlockSetEmboss(block, UI_EMBOSSR);
1784
1785                 if (ob->type==OB_MESH && modifier_couldBeCage(md) && index<=lastCageIndex) {
1786                         int icon, color;
1787
1788                         if (index==cageIndex) {
1789                                 color = TH_BUT_SETTING;
1790                                 icon = VICON_EDITMODE_HLT;
1791                         } else if (index<cageIndex) {
1792                                 color = TH_BUT_NEUTRAL;
1793                                 icon = VICON_EDITMODE_DEHLT;
1794                         } else {
1795                                 color = TH_BUT_NEUTRAL;
1796                                 icon = ICON_BLANK1;
1797                         }
1798                         uiBlockSetCol(block, color);
1799                         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");
1800                         uiButSetFunc(but, modifiers_setOnCage, ob, md);
1801                         uiBlockSetCol(block, TH_AUTO);
1802                 }
1803
1804                 uiBlockSetCol(block, TH_BUT_ACTION);
1805
1806                 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");
1807                 uiButSetFunc(but, modifiers_moveUp, ob, md);
1808
1809                 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");
1810                 uiButSetFunc(but, modifiers_moveDown, ob, md);
1811                 
1812                 uiBlockSetEmboss(block, UI_EMBOSSN);
1813                 
1814                 // deletion over the deflection panel
1815                 // fluid particle modifier can't be deleted here
1816                 if(md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Collision && md->type!=eModifierType_Surface && !modifier_is_fluid_particles(md))
1817                 {
1818                         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");
1819                         uiButSetFunc(but, modifiers_del, ob, md);
1820                 }
1821                 uiBlockSetCol(block, TH_AUTO);
1822         }
1823
1824         uiBlockSetEmboss(block, UI_EMBOSS);
1825
1826         if (isVirtual || !(md->mode&eModifierMode_Expanded)) {
1827                 y -= 18;
1828         } else {
1829                 int cy = y - 8;
1830                 int lx = x + width - 60 - 15;
1831
1832                 if (md->type==eModifierType_Subsurf) {
1833                         height = 105;
1834                 } else if (md->type==eModifierType_Lattice) {
1835                         height = 48;
1836                 } else if (md->type==eModifierType_Curve) {
1837                         height = 72;
1838                 } else if (md->type==eModifierType_Build) {
1839                         height = 86;
1840                 } else if (md->type==eModifierType_Mirror) {
1841                         height = 105;
1842                 } else if (md->type==eModifierType_Bevel) {
1843                         BevelModifierData *bmd = (BevelModifierData*) md;
1844                         height = 105; /* height = 124; */
1845                         if ((bmd->lim_flags & BME_BEVEL_ANGLE) || ((bmd->lim_flags & BME_BEVEL_WEIGHT) && !(bmd->flags & BME_BEVEL_VERT))) height += 19;
1846                 } else if (md->type==eModifierType_EdgeSplit) {
1847                         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1848                         height = 48;
1849                         if(emd->flags & MOD_EDGESPLIT_FROMANGLE) height += 19;
1850                 } else if (md->type==eModifierType_Displace) {
1851                         DisplaceModifierData *dmd = (DisplaceModifierData *)md;
1852                         height = 124;
1853                         if(dmd->texmapping == MOD_DISP_MAP_OBJECT ||
1854                            dmd->texmapping == MOD_DISP_MAP_UV)
1855                                 height += 19;
1856                 } else if (md->type==eModifierType_UVProject) {
1857                         height = 114 + ((UVProjectModifierData *)md)->num_projectors * 19;
1858                 } else if (md->type==eModifierType_Decimate) {
1859                         height = 48;
1860                 } else if (md->type==eModifierType_Smooth) {
1861                         height = 86;
1862                 } else if (md->type==eModifierType_Cast) {
1863                         height = 143;
1864                 } else if (md->type==eModifierType_Wave) {
1865                         WaveModifierData *wmd = (WaveModifierData *)md;
1866                         height = 315;
1867                         if(wmd->texmapping == MOD_WAV_MAP_OBJECT ||
1868                            wmd->texmapping == MOD_WAV_MAP_UV)
1869                                 height += 19;
1870                         if(wmd->flag & MOD_WAVE_NORM)
1871                                 height += 19;
1872                 } else if (md->type==eModifierType_Armature) {
1873                         height = 105;
1874                 } else if (md->type==eModifierType_Hook) {
1875                         HookModifierData *hmd = (HookModifierData*) md;
1876                         height = 86;
1877                         if (editing)
1878                                 height += 20;
1879                         if(hmd->indexar==NULL)
1880                                 height += 20;
1881                 } else if (md->type==eModifierType_Softbody) {
1882                         height = 31;
1883                 } else if (md->type==eModifierType_Cloth) {
1884                         height = 31;
1885                 } else if (md->type==eModifierType_Collision) {
1886                         height = 31;
1887                 } else if (md->type==eModifierType_Surface) {
1888                         height = 31;
1889                 } else if (md->type==eModifierType_Fluidsim) {
1890                         height = 31;
1891                 } else if (md->type==eModifierType_Boolean) {
1892                         height = 48;
1893                 } else if (md->type==eModifierType_Array) {
1894                         height = 211;
1895                 } else if (md->type==eModifierType_MeshDeform) {
1896                         MeshDeformModifierData *mmd= (MeshDeformModifierData*)md;
1897                         height = (mmd->bindcos)? 73: 93;
1898                 } else if (md->type==eModifierType_ParticleSystem) {
1899                         height = 31;
1900                 } else if (md->type==eModifierType_ParticleInstance) {
1901                         height = 94;
1902                 } else if (md->type==eModifierType_Explode) {
1903                         height = 94;
1904                 } else if (md->type==eModifierType_Shrinkwrap) {
1905                         ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
1906                         height = 86 + 3;
1907                         if (smd->shrinkType == MOD_SHRINKWRAP_PROJECT)
1908                         {
1909                                 height += 19*5;
1910                                 if(smd->projAxis == 0) height += 19;
1911                         }
1912                         else if (smd->shrinkType == MOD_SHRINKWRAP_NEAREST_SURFACE)
1913                                 height += 19;
1914                 } else if (md->type == eModifierType_Mask) {
1915                         height = 66;
1916                 } else if (md->type==eModifierType_SimpleDeform) {
1917                         SimpleDeformModifierData *smd = (SimpleDeformModifierData*) md;
1918                         height += 19*5;
1919                         if(smd->origin != NULL) height += 19;
1920                         if(smd->mode == MOD_SIMPLEDEFORM_MODE_STRETCH
1921                         || smd->mode == MOD_SIMPLEDEFORM_MODE_TAPER  )
1922                                 height += 19;
1923                 }
1924                                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1925                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y-height-2, width, height-2, NULL, 5.0, 0.0, 12, 40, ""); 
1926
1927                 y -= 18;
1928
1929                 if (!isVirtual && (md->type!=eModifierType_Collision) && (md->type!=eModifierType_Surface)) {
1930                         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); /* only here obdata, the rest of modifiers is ob level */
1931
1932                         uiBlockBeginAlign(block);
1933                         if (md->type==eModifierType_ParticleSystem) {
1934                                 ParticleSystem *psys;
1935                         psys= ((ParticleSystemModifierData *)md)->psys;
1936
1937                         if(!(G.f & G_PARTICLEEDIT)) {
1938                                         if(ELEM3(psys->part->draw_as, PART_DRAW_PATH, PART_DRAW_GR, PART_DRAW_OB) && psys->pathcache) {
1939                                                 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");
1940                                                 uiButSetFunc(but, modifiers_convertParticles, ob, md);
1941                                         }
1942                                 }
1943                         }
1944                         else{
1945                                 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");
1946                                 uiButSetFunc(but, modifiers_applyModifier, ob, md);
1947                         }
1948                         
1949                         uiClearButLock();
1950                         uiSetButLock(ob && ob->id.lib, ERROR_LIBDATA_MESSAGE);
1951
1952                         if (md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (md->type!=eModifierType_Cloth)) {
1953                                 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");
1954                                 uiButSetFunc(but, modifiers_copyModifier, ob, md);
1955                         }
1956                         uiBlockEndAlign(block);
1957                 }
1958
1959                 lx = x + 10;
1960                 cy = y + 10 - 1;
1961                 uiBlockBeginAlign(block);
1962                 if (md->type==eModifierType_Subsurf) {
1963                         SubsurfModifierData *smd = (SubsurfModifierData*) md;
1964                         char subsurfmenu[]="Subsurf Type%t|Catmull-Clark%x0|Simple Subdiv.%x1";
1965                         uiDefButS(block, MENU, B_MODIFIER_RECALC, subsurfmenu,          lx,(cy-=19),buttonWidth,19, &smd->subdivType, 0, 0, 0, 0, "Selects type of subdivision algorithm.");
1966                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Levels:",             lx, (cy-=19), buttonWidth,19, &smd->levels, 1, 6, 0, 0, "Number subdivisions to perform");
1967                         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");
1968
1969                         /* Disabled until non-EM DerivedMesh implementation is complete */
1970
1971                         /*
1972                         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");
1973                         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");
1974                         */
1975
1976                         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");
1977                         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");
1978                 } else if (md->type==eModifierType_Lattice) {
1979                         LatticeModifierData *lmd = (LatticeModifierData*) md;
1980                         uiDefIDPoinBut(block, modifier_testLatticeObj, ID_OB, B_CHANGEDEP, "Ob: ",      lx, (cy-=19), buttonWidth,19, &lmd->object, "Lattice object to deform with");
1981                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &lmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1982                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1983                 } else if (md->type==eModifierType_Curve) {
1984                         CurveModifierData *cmd = (CurveModifierData*) md;
1985                         uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &cmd->object, "Curve object to deform with");
1986                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &cmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1987                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1988                         
1989                         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");
1990                         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");
1991                         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");
1992                         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");
1993                         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");
1994                         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");
1995                 } else if (md->type==eModifierType_Build) {
1996                         BuildModifierData *bmd = (BuildModifierData*) md;
1997                         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");
1998                         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");
1999                         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.");
2000                         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.");
2001                 } else if (md->type==eModifierType_Mirror) {
2002                         MirrorModifierData *mmd = (MirrorModifierData*) md;
2003                         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");
2004                         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");
2005                         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");
2006                         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");
2007                         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");
2008                         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)");
2009                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_U, B_MODIFIER_RECALC,
2010                                      "Mirror U",
2011                                      lx, (cy-=19), buttonWidth/2, 19,
2012                                      &mmd->flag, 0, 0, 0, 0,
2013                                      "Mirror the U texture coordinate around "
2014                                      "the 0.5 point");
2015                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_V, B_MODIFIER_RECALC,
2016                                      "Mirror V",
2017                                      lx + buttonWidth/2 + 1, cy, buttonWidth/2, 19,
2018                                      &mmd->flag, 0, 0, 0, 0,
2019                                      "Mirror the V texture coordinate around "
2020                                      "the 0.5 point");
2021                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2022                                        "Ob: ", lx, (cy -= 19), buttonWidth, 19,
2023                                        &mmd->mirror_ob,
2024                                        "Object to use as mirror");
2025                 } else if (md->type==eModifierType_Bevel) {
2026                         BevelModifierData *bmd = (BevelModifierData*) md;
2027                         /*uiDefButS(block, ROW, B_MODIFIER_RECALC, "Distance",
2028                                           lx, (cy -= 19), (buttonWidth/2), 19, &bmd->val_flags,
2029                                           11.0, 0, 0, 0,
2030                                           "Interpret bevel value as a constant distance from each edge");
2031                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "Radius",
2032                                           (lx+buttonWidth/2), cy, (buttonWidth - buttonWidth/2), 19, &bmd->val_flags,
2033                                           11.0, BME_BEVEL_RADIUS, 0, 0,
2034                                           "Interpret bevel value as a radius - smaller angles will be beveled more");*/
2035                         uiBlockBeginAlign(block);
2036                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Width: ",
2037                                           lx, (cy -= 19), buttonWidth, 19, &bmd->value,
2038                                           0.0, 0.5, 5, 4,
2039                                           "Bevel value/amount");
2040                         /*uiDefButI(block, NUM, B_MODIFIER_RECALC, "Recurs",
2041                                           lx, (cy -= 19), buttonWidth, 19, &bmd->res,
2042                                           1, 4, 5, 2,
2043                                           "Number of times to bevel");*/
2044                         uiDefButBitS(block, TOG, BME_BEVEL_VERT,
2045                                           B_MODIFIER_RECALC, "Only Vertices",
2046                                           lx, (cy -= 19), buttonWidth, 19,
2047                                           &bmd->flags, 0, 0, 0, 0,
2048                                           "Bevel only verts/corners; not edges");
2049                         uiBlockEndAlign(block);
2050                                           
2051                         uiDefBut(block, LABEL, 1, "Limit using:",       lx, (cy-=25), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2052                         uiBlockBeginAlign(block);
2053                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "None",
2054                                           lx, (cy -= 19), (buttonWidth/3), 19, &bmd->lim_flags,
2055                                           12.0, 0, 0, 0,
2056                                           "Bevel the entire mesh by a constant amount");
2057                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "Angle",
2058                                           (lx+buttonWidth/3), cy, (buttonWidth/3), 19, &bmd->lim_flags,
2059                                           12.0, BME_BEVEL_ANGLE, 0, 0,
2060                                           "Only bevel edges with sharp enough angles between faces");
2061                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "BevWeight",
2062                                           lx+(2*buttonWidth/3), cy, buttonWidth-2*(buttonWidth/3), 19, &bmd->lim_flags,
2063                                           12.0, BME_BEVEL_WEIGHT, 0, 0,
2064                                           "Use bevel weights to determine how much bevel is applied; apply them separately in vert/edge select mode");
2065                         if ((bmd->lim_flags & BME_BEVEL_WEIGHT) && !(bmd->flags & BME_BEVEL_VERT)) {
2066                                 uiDefButS(block, ROW, B_MODIFIER_RECALC, "Min",
2067                                           lx, (cy -= 19), (buttonWidth/3), 19, &bmd->e_flags,
2068                                           13.0, BME_BEVEL_EMIN, 0, 0,
2069                                           "The sharpest edge's weight is used when weighting a vert");
2070                                 uiDefButS(block, ROW, B_MODIFIER_RECALC, "Average",
2071                                           (lx+buttonWidth/3), cy, (buttonWidth/3), 19, &bmd->e_flags,
2072                                           13.0, 0, 0, 0,
2073                                           "The edge weights are averaged when weighting a vert");
2074                                 uiDefButS(block, ROW, B_MODIFIER_RECALC, "Max",
2075                                           (lx+2*(buttonWidth/3)), cy, buttonWidth-2*(buttonWidth/3), 19, &bmd->e_flags,
2076                                           13.0, BME_BEVEL_EMAX, 0, 0,
2077                                           "The largest edge's wieght is used when weighting a vert");
2078                         }
2079                         else if (bmd->lim_flags & BME_BEVEL_ANGLE) {
2080                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Angle:",
2081                                           lx, (cy -= 19), buttonWidth, 19, &bmd->bevel_angle,
2082                                           0.0, 180.0, 100, 2,
2083                                           "Angle above which to bevel edges");
2084                         }
2085                 } else if (md->type==eModifierType_EdgeSplit) {
2086                         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
2087                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMANGLE,
2088                                      B_MODIFIER_RECALC, "From Edge Angle",
2089                                      lx, (cy -= 19), buttonWidth, 19,
2090                                      &emd->flags, 0, 0, 0, 0,
2091                                      "Split edges with high angle between faces");
2092                         if(emd->flags & MOD_EDGESPLIT_FROMANGLE) {
2093                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Split Angle:",
2094                                           lx, (cy -= 19), buttonWidth, 19, &emd->split_angle,
2095                                           0.0, 180.0, 100, 2,
2096                                           "Angle above which to split edges");
2097                         }
2098                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMFLAG,
2099                                      B_MODIFIER_RECALC, "From Marked As Sharp",
2100                                      lx, (cy -= 19), buttonWidth, 19,
2101                                      &emd->flags, 0, 0, 0, 0,
2102                                      "Split edges that are marked as sharp");
2103                 } else if (md->type==eModifierType_Displace) {
2104                         DisplaceModifierData *dmd = (DisplaceModifierData*) md;
2105                         but = uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",
2106                                        lx, (cy -= 19), buttonWidth, 19,
2107                                        &dmd->defgrp_name, 0.0, 31.0, 0, 0,
2108                                        "Name of vertex group to displace"
2109                                        " (displace whole mesh if blank)");
2110                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2111                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,
2112                                        "Texture: ", lx, (cy -= 19), buttonWidth, 19,
2113                                        &dmd->texture,
2114                                        "Texture to use as displacement input");
2115                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Midlevel:",
2116                                   lx, (cy -= 19), buttonWidth, 19, &dmd->midlevel,
2117                                   0, 1, 10, 3,
2118                                   "Material value that gives no displacement");
2119                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Strength:",
2120                                   lx, (cy -= 19), buttonWidth, 19, &dmd->strength,
2121                                   -1000, 1000, 10, 0.1,
2122                                   "Strength of displacement");
2123                         sprintf(str, "Direction%%t|Normal%%x%d|RGB -> XYZ%%x%d|"
2124                                 "Z%%x%d|Y%%x%d|X%%x%d",
2125                                 MOD_DISP_DIR_NOR, MOD_DISP_DIR_RGB_XYZ,
2126                                 MOD_DISP_DIR_Z, MOD_DISP_DIR_Y, MOD_DISP_DIR_X);
2127                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2128                                   lx, (cy -= 19), buttonWidth, 19, &dmd->direction,
2129                                   0.0, 1.0, 0, 0, "Displace direction");
2130                         sprintf(str, "Texture Coordinates%%t"
2131                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
2132                                 MOD_DISP_MAP_LOCAL, MOD_DISP_MAP_GLOBAL,
2133                                 MOD_DISP_MAP_OBJECT, MOD_DISP_MAP_UV);
2134                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2135                                   lx, (cy -= 19), buttonWidth, 19, &dmd->texmapping,
2136                                   0.0, 1.0, 0, 0,
2137                                   "Texture coordinates used for displacement input");
2138                         if (dmd->texmapping == MOD_DISP_MAP_UV) {
2139                                 char *strtmp;
2140                                 int i;
2141                                 CustomData *fdata = G.obedit ? &G.editMesh->fdata
2142                                                              : &((Mesh*)ob->data)->fdata;
2143                                 build_uvlayer_menu_vars(fdata, &strtmp, &dmd->uvlayer_tmp,
2144                                                         dmd->uvlayer_name);
2145                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
2146                                       lx, (cy -= 19), buttonWidth, 19, &dmd->uvlayer_tmp,
2147                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
2148                                 MEM_freeN(strtmp);
2149                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
2150                                 uiButSetFunc(but, set_displace_uvlayer, dmd,
2151                                              &fdata->layers[i]);
2152                         }
2153                         if(dmd->texmapping == MOD_DISP_MAP_OBJECT) {
2154                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2155                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
2156                                                &dmd->map_object,
2157                                                "Object to get texture coordinates from");
2158                         }
2159                 } else if (md->type==eModifierType_UVProject) {
2160                         UVProjectModifierData *umd = (UVProjectModifierData *) md;
2161                         int i;
2162                         char *strtmp;
2163                         CustomData *fdata = G.obedit ? &G.editMesh->fdata
2164                                                      : &((Mesh*)ob->data)->fdata;
2165                         build_uvlayer_menu_vars(fdata, &strtmp, &umd->uvlayer_tmp,
2166                                                 umd->uvlayer_name);
2167                         but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
2168                               lx, (cy -= 19), buttonWidth, 19, &umd->uvlayer_tmp,
2169                               0.0, 1.0, 0, 0, "Set the UV layer to use");
2170                         i = CustomData_get_layer_index(fdata, CD_MTFACE);
2171                         uiButSetFunc(but, set_uvproject_uvlayer, umd, &fdata->layers[i]);
2172                         MEM_freeN(strtmp);
2173                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspX:",
2174                                   lx, (cy -= 19), buttonWidth / 2, 19, &umd->aspectx,
2175                                   1, 1000, 100, 2,
2176                                   "Horizontal Aspect Ratio");
2177                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspY:",
2178                                   lx + (buttonWidth / 2) + 1, cy, buttonWidth / 2, 19,
2179                                   &umd->aspecty,
2180                                   1, 1000, 100, 2,
2181                                   "Vertical Aspect Ratio");
2182                         uiDefButI(block, NUM, B_MODIFIER_RECALC, "Projectors:",
2183                                   lx, (cy -= 19), buttonWidth, 19, &umd->num_projectors,
2184                                   1, MOD_UVPROJECT_MAXPROJECTORS, 0, 0,
2185                                   "Number of objects to use as projectors");
2186                         for(i = 0; i < umd->num_projectors; ++i) {
2187                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2188                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
2189                                                &umd->projectors[i],
2190                                                "Object to use as projector");
2191                         }
2192                         uiDefIDPoinBut(block, modifier_testImage, ID_IM, B_CHANGEDEP,
2193                                        "Image: ", lx, (cy -= 19), buttonWidth, 19,
2194                                        &umd->image,
2195                                        "Image to project (only faces with this image "
2196                                        "will be altered");
2197                         uiButSetCompleteFunc(but, autocomplete_image, (void *)ob);
2198                         uiDefButBitI(block, TOG, MOD_UVPROJECT_OVERRIDEIMAGE,
2199                                      B_MODIFIER_RECALC, "Override Image",
2200                                      lx, (cy -= 19), buttonWidth, 19,
2201                                      &umd->flags, 0, 0, 0, 0,
2202                                      "Override faces' current images with the "
2203                                      "given image");
2204                 } else if (md->type==eModifierType_Decimate) {
2205                         DecimateModifierData *dmd = (DecimateModifierData*) md;
2206                         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");
2207                         sprintf(str, "Face Count: %d", dmd->faceCount);
2208                         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");
2209                 } else if (md->type==eModifierType_Mask) {
2210                         MaskModifierData *mmd = (MaskModifierData *)md;
2211                         
2212                         sprintf(str, "Mask Mode%%t|Vertex Group%%x%d|Selected Bones%%x%d|",
2213                                 MOD_MASK_MODE_VGROUP,MOD_MASK_MODE_ARM);
2214                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2215                                 lx, (cy -= 19), buttonWidth, 19, &mmd->mode,
2216                                 0.0, 1.0, 0, 0, "How masking region is defined");
2217                                           
2218                         if (mmd->mode == MOD_MASK_MODE_ARM) {
2219                                 uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP,
2220                                     "Ob: ", lx, (cy -= 19), buttonWidth, 19, &mmd->ob_arm,
2221                                     "Armature to use as source of bones to mask");
2222                         }
2223                         else {
2224                                 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", 
2225                                         lx, (cy-=19), buttonWidth, 19, &mmd->vgroup, 
2226                                         0.0, 31.0, 0, 0, "Vertex Group name");
2227                                 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2228                         }
2229                         
2230                         uiDefButBitI(block, TOG, MOD_MASK_INV, B_MODIFIER_RECALC, "Inverse",            
2231                                 lx, (cy-=19), buttonWidth, 19, &mmd->flag, 
2232                                 0, 0, 0, 0, "Use vertices that are not part of region defined");
2233                 } else if (md->type==eModifierType_Smooth) {
2234                         SmoothModifierData *smd = (SmoothModifierData*) md;
2235
2236                         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");
2237                         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");
2238                         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");
2239
2240                         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)");
2241                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Repeat:",     lx,(cy-=19),buttonWidth, 19, &smd->repeat, 0.0, 30.0, 1, 0, "Number of smoothing iterations");
2242                         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");
2243                 } else if (md->type==eModifierType_Cast) {
2244                         CastModifierData *cmd = (CastModifierData*) md;
2245
2246                         char casttypemenu[]="Projection Type%t|Sphere%x0|Cylinder%x1|Cuboid%x2";
2247                         uiDefButS(block, MENU, B_MODIFIER_RECALC, casttypemenu,         lx,(cy-=19),buttonWidth - 30,19, &cmd->type, 0, 0, 0, 0, "Projection type to apply");
2248                         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");
2249                         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");
2250                         if (cmd->type != MOD_CAST_TYPE_CYLINDER) {
2251                                 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");
2252                         }
2253                         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");
2254                         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)");
2255                         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)");
2256                         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)");
2257                         if (ob->type == OB_MESH) {
2258                                 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");
2259                         }
2260                         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");
2261                         if(cmd->object) {
2262                                 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");
2263                         }
2264                 } else if (md->type==eModifierType_Wave) {
2265                         WaveModifierData *wmd = (WaveModifierData*) md;
2266                         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");
2267                         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");
2268                         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");
2269                         uiDefButBitS(block, TOG, MOD_WAVE_NORM, B_MODIFIER_RECALC, "Normals",   lx,(cy-=19),buttonWidth,19, &wmd->flag, 0, 0, 0, 0, "Displace along normals");
2270                         if (wmd->flag & MOD_WAVE_NORM){
2271                                 if (ob->type==OB_MESH) {
2272                                         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");
2273                                         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");
2274                                         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");
2275                                 }
2276                                 else
2277                                         uiDefBut(block, LABEL, 1, "Meshes Only",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");                                
2278                         }
2279
2280                         uiBlockBeginAlign(block);
2281                         if(wmd->speed >= 0)
2282                                 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");
2283                         else
2284                                 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");
2285                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Lifetime:",   lx,(cy-=19),buttonWidth,19, &wmd->lifetime,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the lifespan of the wave");
2286                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Damptime:",   lx,(cy-=19),buttonWidth,19, &wmd->damp,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the dampingtime of the wave");
2287                         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");
2288
2289                         cy -= 9;
2290                         uiBlockBeginAlign(block);
2291                         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");
2292                         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");
2293                         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)");
2294                         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");
2295                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,"Texture: ", lx, (cy -= 19), 220, 19, &wmd->texture,"Texture with which to modulate wave");
2296                         sprintf(str, "Texture Coordinates%%t"
2297                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
2298                                 MOD_WAV_MAP_LOCAL, MOD_WAV_MAP_GLOBAL,
2299                                 MOD_WAV_MAP_OBJECT, MOD_WAV_MAP_UV);
2300                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2301                                   lx, (cy -= 19), 220, 19, &wmd->texmapping,
2302                                   0.0, 1.0, 0, 0,
2303                                   "Texture coordinates used for modulation input");
2304                         if (wmd->texmapping == MOD_WAV_MAP_UV) {
2305                                 char *strtmp;
2306                                 int i;
2307                                 CustomData *fdata = G.obedit ? &G.editMesh->fdata
2308                                                              : &((Mesh*)ob->data)->fdata;
2309                                 build_uvlayer_menu_vars(fdata, &strtmp, &wmd->uvlayer_tmp,
2310                                                         wmd->uvlayer_name);
2311                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
2312                                       lx, (cy -= 19), 220, 19, &wmd->uvlayer_tmp,
2313                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
2314                                 MEM_freeN(strtmp);
2315                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
2316                                 uiButSetFunc(but, set_wave_uvlayer, wmd,
2317                                              &fdata->layers[i]);
2318                         }
2319                         if(wmd->texmapping == MOD_DISP_MAP_OBJECT) {
2320                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2321                                                "Ob: ", lx, (cy -= 19), 220, 19,
2322                                                &wmd->map_object,
2323                                                "Object to get texture coordinates from");
2324                         }
2325                         cy -= 9;
2326                         uiBlockBeginAlign(block);
2327                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Speed:",   lx,(cy-=19),220,19, &wmd->speed, -2.0, 2.0, 0, 0, "Specify the wave speed");
2328                         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");
2329                         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");
2330                         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");
2331                 } else if (md->type==eModifierType_Armature) {
2332                         ArmatureModifierData *amd = (ArmatureModifierData*) md;
2333                         uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &amd->object, "Armature object to deform with");
2334                         
2335                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth-40,19, &amd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to control overall armature influence");
2336                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2337                         uiDefButBitS(block, TOG, ARM_DEF_INVERT_VGROUP, B_ARM_RECALCDATA, "Inv",        lx+buttonWidth-40,cy, 40, 20, &amd->deformflag, 0, 0, 0, 0, "Invert vertex group influence");
2338                         
2339                         uiDefButBitS(block, TOG, ARM_DEF_VGROUP, B_ARM_RECALCDATA, "Vert.Groups",       lx,cy-=19,buttonWidth/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable VertexGroups defining deform");
2340                         uiDefButBitS(block, TOG, ARM_DEF_ENVELOPE, B_ARM_RECALCDATA, "Envelopes",       lx+buttonWidth/2,cy,(buttonWidth + 1)/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable Bone Envelopes defining deform");
2341                         uiDefButBitS(block, TOG, ARM_DEF_QUATERNION, B_ARM_RECALCDATA, "Quaternion",    lx,(cy-=19),buttonWidth/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable deform rotation interpolation with Quaternions");
2342                         uiDefButBitS(block, TOG, ARM_DEF_B_BONE_REST, B_ARM_RECALCDATA, "B-Bone Rest", lx+buttonWidth/2,cy,(buttonWidth + 1)/2,20, &amd->deformflag, 0, 0, 0, 0, "Make B-Bones deform already in rest position");
2343                         
2344                         uiDefButS(block, TOG, B_ARM_RECALCDATA, "MultiModifier",        lx,cy-=19, buttonWidth, 20, &amd->multi, 0, 0, 0, 0, "Use same input as previous modifier, and mix results using overall vgroup");
2345
2346                 } else if (md->type==eModifierType_Hook) {
2347                         HookModifierData *hmd = (HookModifierData*) md;
2348                         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");
2349                         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");
2350                         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"); 
2351                         if(hmd->indexar==NULL) {
2352                                 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &hmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
2353                                 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2354                         }
2355                         uiBlockBeginAlign(block);
2356                         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");
2357                         uiButSetFunc(but, modifiers_clearHookOffset, ob, md);
2358                         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");
2359                         uiButSetFunc(but, modifiers_cursorHookCenter, ob, md);
2360
2361                         if (editing) {
2362                                 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");
2363                                 uiButSetFunc(but, modifiers_selectHook, ob, md);
2364                                 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");
2365                                 uiButSetFunc(but, modifiers_reassignHook, ob, md);
2366                         }
2367                 } else if (md->type==eModifierType_Softbody) {
2368                         uiDefBut(block, LABEL, 1, "See Soft Body panel.",       lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2369                 } else if (md->type==eModifierType_Cloth) {
2370                         uiDefBut(block, LABEL, 1, "See Cloth panel.",   lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2371
2372                 } else if (md->type==eModifierType_Collision) {
2373                         uiDefBut(block, LABEL, 1, "See Collision panel.",       lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2374                 } else if (md->type==eModifierType_Surface) {
2375                         uiDefBut(block, LABEL, 1, "See Fields panel.",  lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2376                 } else if (md->type==eModifierType_Fluidsim) {
2377                         uiDefBut(block, LABEL, 1, "See Fluidsim panel.",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2378                 } else if (md->type==eModifierType_Boolean) {
2379                         BooleanModifierData *bmd = (BooleanModifierData*) md;
2380                         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");
2381                         uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &bmd->object, "Mesh object to use for boolean operation");
2382                 } else if (md->type==eModifierType_Array) {
2383                         ArrayModifierData *amd = (ArrayModifierData*) md;
2384                         float range = 10000;
2385                         int cytop, halfwidth = (width - 5)/2 - 15;
2386                         int halflx = lx + halfwidth + 10;
2387
2388                         uiBlockSetEmboss(block, UI_EMBOSSX);
2389                         uiBlockEndAlign(block);
2390
2391                         /* length parameters */
2392                         uiBlockBeginAlign(block);
2393                         sprintf(str, "Length Fit%%t|Fixed Count%%x%d|Fixed Length%%x%d"
2394                                 "|Fit To Curve Length%%x%d",
2395                                 MOD_ARR_FIXEDCOUNT, MOD_ARR_FITLENGTH, MOD_ARR_FITCURVE);
2396                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2397                                   lx, (cy-=19), buttonWidth, 19, &amd->fit_type,
2398                                   0.0, 1.0, 0, 0, "Array length calculation method");
2399                         switch(amd->fit_type)
2400                         {
2401                         case MOD_ARR_FIXEDCOUNT:
2402                                 uiDefButI(block, NUM, B_MODIFIER_RECALC, "Count:",
2403                                           lx, (cy -= 19), buttonWidth, 19, &amd->count,
2404                                           1, 1000, 0, 0, "Number of duplicates to make");
2405                                 break;
2406                         case MOD_ARR_FITLENGTH:
2407                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Length:",
2408                                           lx, (cy -= 19), buttonWidth, 19, &amd->length,
2409                                           0, range, 10, 2,
2410                                           "Length to fit array within");
2411                                 break;
2412                         case MOD_ARR_FITCURVE:
2413                                 uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB,
2414                                                B_CHANGEDEP, "Ob: ",
2415                                                lx, (cy -= 19), buttonWidth, 19, &amd->curve_ob,
2416                                                "Curve object to fit array length to");
2417                                 break;
2418                         }
2419                         uiBlockEndAlign(block);
2420
2421                         /* offset parameters */
2422                         cy -= 10;
2423                         cytop= cy;
2424                         uiBlockBeginAlign(block);
2425                         uiDefButBitI(block, TOG, MOD_ARR_OFF_CONST, B_MODIFIER_RECALC,
2426                                      "Constant Offset", lx, (cy-=19), halfwidth, 19,
2427                                      &amd->offset_type, 0, 0, 0, 0,
2428                                      "Constant offset between duplicates "
2429                                      "(local coordinates)");
2430                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2431                                   lx, (cy-=19), halfwidth, 19,
2432                                   &amd->offset[0],
2433                                   -range, range, 10, 3,
2434                                   "Constant component for duplicate offsets "
2435                                   "(local coordinates)");
2436                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2437                                   lx, (cy-=19), halfwidth, 19,
2438                                   &amd->offset[1],
2439                                   -range, range, 10, 3,
2440                                   "Constant component for duplicate offsets "
2441                                   "(local coordinates)");
2442                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2443                                   lx, (cy-=19), halfwidth, 19,
2444                                   &amd->offset[2],
2445                                   -range, range, 10, 3,
2446                                   "Constant component for duplicate offsets "
2447                                   "(local coordinates)");
2448                         uiBlockEndAlign(block);
2449
2450                         cy= cytop;
2451                         uiBlockBeginAlign(block);
2452                         uiDefButBitI(block, TOG, MOD_ARR_OFF_RELATIVE, B_MODIFIER_RECALC,
2453                                      "Relative Offset", halflx, (cy-=19), halfwidth, 19,
2454                                      &amd->offset_type, 0, 0, 0, 0,
2455                                      "Offset between duplicates relative to object width "
2456                                      "(local coordinates)");
2457                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2458                                   halflx, (cy-=19), halfwidth, 19,
2459                                   &amd->scale[0],
2460                                   -range, range, 10, 3,
2461                                   "Component for duplicate offsets relative to object "
2462                                   "width (local coordinates)");
2463                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2464                                   halflx, (cy-=19), halfwidth, 19,
2465                                   &amd->scale[1],
2466                                   -range, range, 10, 3,
2467                                   "Component for duplicate offsets relative to object "
2468                                   "width (local coordinates)");
2469                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2470                                   halflx, (cy-=19), halfwidth, 19,
2471                                   &amd->scale[2],
2472                                   -range, range, 10, 3,
2473                                   "Component for duplicate offsets relative to object "
2474                                   "width (local coordinates)");
2475                         uiBlockEndAlign(block);
2476
2477                         /* vertex merging parameters */
2478                         cy -= 10;
2479                         cytop= cy;
2480
2481                         uiBlockBeginAlign(block);
2482                         uiDefButBitI(block, TOG, MOD_ARR_MERGE, B_MODIFIER_RECALC,
2483                                      "Merge",
2484                                      lx, (cy-=19), halfwidth/2, 19, &amd->flags,
2485                                      0, 0, 0, 0,
2486                                      "Merge vertices in adjacent duplicates");
2487                         uiDefButBitI(block, TOG, MOD_ARR_MERGEFINAL, B_MODIFIER_RECALC,
2488                                      "First Last",
2489                                      lx + halfwidth/2, cy, (halfwidth+1)/2, 19,
2490                                      &amd->flags,
2491                                      0, 0, 0, 0,
2492                                      "Merge vertices in first duplicate with vertices"
2493                                      " in last duplicate");
2494                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Limit:",
2495                                           lx, (cy-=19), halfwidth, 19, &amd->merge_dist,
2496                                           0, 1.0f, 1, 4,
2497                                           "Limit below which to merge vertices");
2498
2499                         /* offset ob */
2500                         cy = cytop;
2501                         uiBlockBeginAlign(block);
2502                         uiDefButBitI(block, TOG, MOD_ARR_OFF_OBJ, B_MODIFIER_RECALC,
2503                                      "Object Offset", halflx, (cy -= 19), halfwidth, 19,
2504                                      &amd->offset_type, 0, 0, 0, 0,
2505                                      "Add an object transformation to the total offset");
2506                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2507                                        "Ob: ", halflx, (cy -= 19), halfwidth, 19,
2508                                        &amd->offset_ob,
2509                                        "Object from which to take offset transformation");
2510                         uiBlockEndAlign(block);
2511
2512                         cy -= 10;
2513                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2514                                              B_CHANGEDEP, "Start cap: ",
2515                                              lx, (cy -= 19), halfwidth, 19,
2516                                              &amd->start_cap,
2517                                              "Mesh object to use as start cap");
2518                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2519                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2520                                              B_CHANGEDEP, "End cap: ",
2521                                              halflx, cy, halfwidth, 19,
2522                                              &amd->end_cap,
2523                                              "Mesh object to use as end cap");
2524                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2525                 } else if (md->type==eModifierType_MeshDeform) {
2526                         MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
2527
2528                         uiBlockBeginAlign(block);
2529                         uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &mmd->object, "Mesh object to be use as cage"); 
2530                         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");
2531                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2532                         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");
2533
2534                         uiBlockBeginAlign(block);
2535                         if(mmd->bindcos) {
2536                                 but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Unbind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Unbind mesh from cage");
2537                                 uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
2538                         }
2539                         else {
2540                                 but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Bind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Bind mesh to cage");
2541                                 uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
2542                                 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");
2543                                 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!)");
2544                         }
2545                         uiBlockEndAlign(block);
2546                 } else if (md->type==eModifierType_ParticleSystem) {
2547                         uiDefBut(block, LABEL, 1, "See Particle buttons.",      lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2548                 } else if (md->type==eModifierType_ParticleInstance) {
2549                         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
2550                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy -= 19), buttonWidth, 19, &pimd->ob, "Object that has the particlesystem");
2551                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "PSYS:", lx, (cy -= 19), buttonWidth, 19, &pimd->psys, 1, 10, 10, 3, "Particlesystem number in the object");
2552                         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");
2553                         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");
2554                         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");
2555                         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");
2556                         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");
2557                         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");
2558                 } else if (md->type==eModifierType_Explode) {
2559                         ExplodeModifierData *emd = (ExplodeModifierData*) md;
2560                         uiBut *but;
2561                         char *menustr= get_vertexgroup_menustr(ob);
2562                         int defCount=BLI_countlist(&ob->defbase);
2563                         if(defCount==0) emd->vgroup=0;
2564                         uiBlockBeginAlign(block);
2565                         but=uiDefButS(block, MENU, B_MODIFIER_RECALC, menustr,  lx, (cy-=19), buttonWidth-20,19, &emd->vgroup, 0, defCount, 0, 0, "Protect this vertex group");
2566                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2567                         MEM_freeN(menustr);
2568                         
2569                         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");
2570                         uiButSetFunc(but, modifiers_explodeDelVg, (void *)emd, (void *)NULL);
2571                         
2572
2573                         but=uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "",     lx, (cy-=19), buttonWidth,19, &emd->protect, 0.0f, 1.0f, 0, 0, "Clean vertex group edges");
2574                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2575
2576                         but=uiDefBut(block, BUT, B_MODIFIER_RECALC, "Refresh",  lx, (cy-=19), buttonWidth/2,19, 0, 0, 0, 0, 0, "Recalculate faces assigned to particles");
2577                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2578
2579                         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");
2580                         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");
2581                         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");
2582                         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");
2583                         uiBlockEndAlign(block);
2584                 } else if (md->type==eModifierType_Shrinkwrap) {
2585                         ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
2586
2587                         char shrinktypemenu[]="Shrinkwrap type%t|nearest surface point %x0|projection %x1|nearest vertex %x2";
2588
2589                         uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &smd->target, "Target to shrink to");
2590
2591                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &smd->vgroup_name, 0, 31, 0, 0, "Vertex Group name");
2592                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2593
2594                         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");
2595
2596                         cy -= 3;
2597                         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.");
2598
2599                         if (smd->shrinkType == MOD_SHRINKWRAP_PROJECT){
2600
2601
2602                                 /* UI for projection axis */
2603                                 uiBlockBeginAlign(block);
2604                                 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");
2605                                 if(smd->projAxis == 0)
2606                                 {
2607                                         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");
2608                                 }
2609
2610                                 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");
2611                                 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");
2612                                 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");
2613
2614
2615                                 /* allowed directions of projection axis */
2616                                 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");
2617                                 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");
2618
2619                                 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");
2620                                 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");
2621                                 uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob2: ",        lx, (cy-=19), buttonWidth,19, &smd->auxTarget, "Aditional mesh to project over");
2622                         }
2623                         else if (smd->shrinkType == MOD_SHRINKWRAP_NEAREST_SURFACE){
2624                                 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");
2625                         }
2626
2627                         uiBlockEndAlign(block);
2628
2629                 } else if (md->type==eModifierType_SimpleDeform) {
2630                         SimpleDeformModifierData *smd = (SimpleDeformModifierData*) md;
2631                         char simpledeform_modemenu[] = "Deform type%t|Twist %x1|Bend %x2|Taper %x3|Strech %x4";
2632
2633                         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.");
2634                         
2635                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &smd->vgroup_name, 0, 31, 0, 0, "Vertex Group name");
2636                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2637
2638                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ",      lx, (cy-=19), buttonWidth,19, &smd->origin, "Origin of modifier space coordinates");
2639                         if(smd->origin != NULL)
2640                                 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");
2641
2642                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Factor:",     lx,(cy-=19),buttonWidth,19, &smd->factor, -10.0f, 10.0f, 0.5f, 0, "Deform Factor");
2643
2644                         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");
2645                         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");
2646
2647                         if(smd->mode == MOD_SIMPLEDEFORM_MODE_STRETCH
2648                         || smd->mode == MOD_SIMPLEDEFORM_MODE_TAPER  )
2649                         {
2650                                 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");
2651                                 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");
2652                         }
2653                 }
2654
2655                 uiBlockEndAlign(block);
2656
2657                 y-=height;
2658         }
2659
2660         if (md->error) {
2661                 y -= 6;
2662
2663                 uiBlockSetCol(block, color);
2664                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
2665                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y, width, 20, NULL, 5.0, 0.0, 15, 40, ""); 
2666                 uiBlockSetCol(block, TH_AUTO);
2667
2668                 uiDefIconBut(block,LABEL,B_NOP,ICON_ERROR, x-9, y,19,19, 0,0,0,0,0, "");
2669                 uiDefBut(block, LABEL, B_NOP, md->error, x+5, y, width-15, 19, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
2670
2671                 y -= 18;
2672         }
2673
2674         uiClearButLock();
2675
2676         y -= 3+6;
2677
2678         *xco = x;
2679         *yco = y;
2680 }
2681
2682 static void editing_panel_modifiers(Object *ob)
2683 {
2684         ModifierData *md;
2685         uiBlock *block;
2686         char str[64];
2687         int xco, yco, i, lastCageIndex, cageIndex = modifiers_getCageIndex(ob, &lastCageIndex);
2688
2689         block= uiNewBlock(&curarea->uiblocks, "editing_panel_modifiers", UI_EMBOSS, UI_HELV, curarea->win);
2690         if( uiNewPanel(curarea, block, "Modifiers", "Editing", 640, 0, 318, 204)==0) return;
2691         
2692         uiSetButLock((ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
2693         uiNewPanelHeight(block, 204);
2694
2695         uiDefBlockBut(block, modifiers_add_menu, ob, "Add Modifier", 0, 190, 130, 20, "Add a new modifier");
2696
2697         sprintf(str, "To: %s", ob->id.name+2);
2698         uiDefBut(block, LABEL, 1, str,  140, 190, 160, 20, NULL, 0.0, 0.0, 0, 0, "Object whose modifier stack is being edited");
2699
2700         xco = 0;
2701         yco = 160;
2702
2703         md = modifiers_getVirtualModifierList(ob);
2704
2705         for (i=0; md; i++, md=md->next) {
2706                 draw_modifier(block, ob, md, &xco, &yco, i, cageIndex, lastCageIndex);
2707                 if (md->mode&eModifierMode_Virtual) i--;
2708         }
2709         
2710         if(yco < 0) uiNewPanelHeight(block, 204-yco);
2711 }
2712
2713 static char *make_key_menu(Key *key, int startindex)
2714 {
2715         KeyBlock *kb;
2716         int index= 1;
2717         char *str, item[64];
2718
2719         for (kb = key->block.first; kb; kb=kb->next, index++);
2720         str= MEM_mallocN(index*40, "key string");
2721         str[0]= 0;
2722         
2723         index= startindex;
2724         for (kb = key->block.first; kb; kb=kb->next, index++) {
2725                 sprintf (item,  "|%s%%x%d", kb->name, index);
2726                 strcat(str, item);
2727         }
2728         
2729         return str;
2730 }
2731
2732 static void editing_panel_shapes(Object *ob)
2733 {
2734         uiBlock *block;
2735         Key *key= NULL;
2736         KeyBlock *kb;
2737         int icon;
2738         char *strp;
2739         
2740         block= uiNewBlock(&curarea->uiblocks, "editing_panel_shapes", UI_EMBOSS, UI_HELV, curarea->win);
2741         uiNewPanelTabbed("Modifiers", "Editing");
2742         if( uiNewPanel(curarea, block, "Shapes", "Editing", 640, 0, 318, 204)==0) return;
2743         
2744         /* Todo check data is library here */
2745         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2746         
2747         uiDefBut(block, BUT, B_ADDKEY, "Add Shape Key" ,        10, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "Add new Shape Key");
2748         
2749         key= ob_get_key(ob);
2750         if(key==NULL) {
2751                 /* label aligns add button */
2752                 uiDefBut(block, LABEL, 0, "",           170, 180,140,20, NULL, 0, 0, 0, 0, "");
2753                 return;
2754         }
2755         
2756         uiDefButS(block, TOG, B_RELKEY, "Relative",             170, 180,140,20, &key->type, 0, 0, 0, 0, "Makes Shape Keys relative");
2757
2758         kb= BLI_findlink(&key->block, ob->shapenr-1);
2759         if(kb==NULL) {
2760                 ob->shapenr= 1;
2761                 kb= key->block.first;
2762         }
2763
2764         uiBlockBeginAlign(block);
2765         if(ob->shapeflag & OB_SHAPE_LOCK) icon= ICON_PIN_HLT; else icon= ICON_PIN_DEHLT;
2766         uiDefIconButBitS(block, TOG, OB_SHAPE_LOCK, B_LOCKKEY, icon, 10,150,25,20, &ob->shapeflag, 0, 0, 0, 0, "Always show the current Shape for this Object");
2767         if(kb->flag & KEYBLOCK_MUTE) icon= ICON_MUTE_IPO_ON; else icon = ICON_MUTE_IPO_OFF;
2768         uiDefIconButBitS(block, TOG, KEYBLOCK_MUTE, B_MODIFIER_RECALC, icon, 35,150,20,20, &kb->flag, 0, 0, 0, 0, "Mute the current Shape");
2769         uiSetButLock(G.obedit==ob, "Unable to perform in EditMode");
2770         uiDefIconBut(block, BUT, B_PREVKEY, ICON_TRIA_LEFT,             55,150,20,20, NULL, 0, 0, 0, 0, "Previous Shape Key");
2771         strp= make_key_menu(key, 1);
2772         uiDefButS(block, MENU, B_SETKEY, strp,                                  75,150,20,20, &ob->shapenr, 0, 0, 0, 0, "Browse existing choices");
2773         MEM_freeN(strp);
2774         
2775         uiDefIconBut(block, BUT, B_NEXTKEY, ICON_TRIA_RIGHT,    95,150,20,20, NULL, 0, 0, 0, 0, "Next Shape Key");
2776         uiClearButLock();
2777         uiDefBut(block, TEX, B_NAMEKEY, "",                                             115, 150, 170, 20, kb->name, 0.0, 31.0, 0, 0, "Current Shape Key name");
2778         uiDefIconBut(block, BUT, B_DELKEY, ICON_X,                              285,150,25,20, 0, 0, 0, 0, 0, "Deletes current Shape Key");
2779         uiBlockEndAlign(block);
2780
2781         if(key->type && (ob->shapeflag & OB_SHAPE_LOCK)==0 && ob->shapenr!=1) {
2782                 uiBlockBeginAlign(block);
2783                 make_rvk_slider(block, ob, ob->shapenr-1,                       10, 120, 150, 20, "Key value, when used it inserts an animation curve point");
2784                 uiDefButF(block, NUM, B_REDR, "Min ",                           160,120, 75, 20, &kb->slidermin, -10.0, 10.0, 100, 1, "Minumum for slider");
2785                 uiDefButF(block, NUM, B_REDR, "Max ",                           235,120, 75, 20, &kb->slidermax, -10.0, 10.0,