merge from trunk - r17500 to HEAD
[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(ELEM3(i, eModifierType_Cloth, eModifierType_Collision, 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)) {
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 && !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_Fluidsim) {
1888                         height = 31;
1889                 } else if (md->type==eModifierType_Boolean) {
1890                         height = 48;
1891                 } else if (md->type==eModifierType_Array) {
1892                         height = 211;
1893                 } else if (md->type==eModifierType_MeshDeform) {
1894                         MeshDeformModifierData *mmd= (MeshDeformModifierData*)md;
1895                         height = (mmd->bindcos)? 73: 93;
1896                 } else if (md->type==eModifierType_ParticleSystem) {
1897                         height = 31;
1898                 } else if (md->type==eModifierType_ParticleInstance) {
1899                         height = 94;
1900                 } else if (md->type==eModifierType_Explode) {
1901                         height = 94;
1902                 } else if (md->type==eModifierType_Shrinkwrap) {
1903                         ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
1904                         height = 86 + 3;
1905                         if (smd->shrinkType == MOD_SHRINKWRAP_PROJECT)
1906                         {
1907                                 height += 19*5;
1908                                 if(smd->projAxis == 0) height += 19;
1909                         }
1910                         else if (smd->shrinkType == MOD_SHRINKWRAP_NEAREST_SURFACE)
1911                                 height += 19;
1912                 } else if (md->type == eModifierType_Mask) {
1913                         height = 66;
1914                 } else if (md->type==eModifierType_SimpleDeform) {
1915                         SimpleDeformModifierData *smd = (SimpleDeformModifierData*) md;
1916                         height += 19*5;
1917                         if(smd->origin != NULL) height += 19;
1918                         if(smd->mode == MOD_SIMPLEDEFORM_MODE_STRETCH
1919                         || smd->mode == MOD_SIMPLEDEFORM_MODE_TAPER  )
1920                                 height += 19;
1921                 }
1922                                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1923                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y-height-2, width, height-2, NULL, 5.0, 0.0, 12, 40, ""); 
1924
1925                 y -= 18;
1926
1927                 if (!isVirtual && (md->type!=eModifierType_Collision)) {
1928                         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); /* only here obdata, the rest of modifiers is ob level */
1929
1930                         uiBlockBeginAlign(block);
1931                         if (md->type==eModifierType_ParticleSystem) {
1932                                 ParticleSystem *psys;
1933                         psys= ((ParticleSystemModifierData *)md)->psys;
1934
1935                         if(!(G.f & G_PARTICLEEDIT)) {
1936                                         if(ELEM3(psys->part->draw_as, PART_DRAW_PATH, PART_DRAW_GR, PART_DRAW_OB) && psys->pathcache) {
1937                                                 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");
1938                                                 uiButSetFunc(but, modifiers_convertParticles, ob, md);
1939                                         }
1940                                 }
1941                         }
1942                         else{
1943                                 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");
1944                                 uiButSetFunc(but, modifiers_applyModifier, ob, md);
1945                         }
1946                         
1947                         if (md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (md->type!=eModifierType_Cloth)) {
1948                                 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");
1949                                 uiButSetFunc(but, modifiers_copyModifier, ob, md);
1950                         }
1951                         uiBlockEndAlign(block);
1952                         
1953                         uiSetButLock(ob && ob->id.lib, ERROR_LIBDATA_MESSAGE);
1954                 }
1955
1956                 lx = x + 10;
1957                 cy = y + 10 - 1;
1958                 uiBlockBeginAlign(block);
1959                 if (md->type==eModifierType_Subsurf) {
1960                         SubsurfModifierData *smd = (SubsurfModifierData*) md;
1961                         char subsurfmenu[]="Subsurf Type%t|Catmull-Clark%x0|Simple Subdiv.%x1";
1962                         uiDefButS(block, MENU, B_MODIFIER_RECALC, subsurfmenu,          lx,(cy-=19),buttonWidth,19, &smd->subdivType, 0, 0, 0, 0, "Selects type of subdivision algorithm.");
1963                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Levels:",             lx, (cy-=19), buttonWidth,19, &smd->levels, 1, 6, 0, 0, "Number subdivisions to perform");
1964                         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");
1965
1966                         /* Disabled until non-EM DerivedMesh implementation is complete */
1967
1968                         /*
1969                         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");
1970                         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");
1971                         */
1972
1973                         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");
1974                         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");
1975                 } else if (md->type==eModifierType_Lattice) {
1976                         LatticeModifierData *lmd = (LatticeModifierData*) md;
1977                         uiDefIDPoinBut(block, modifier_testLatticeObj, ID_OB, B_CHANGEDEP, "Ob: ",      lx, (cy-=19), buttonWidth,19, &lmd->object, "Lattice object to deform with");
1978                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &lmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1979                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1980                 } else if (md->type==eModifierType_Curve) {
1981                         CurveModifierData *cmd = (CurveModifierData*) md;
1982                         uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &cmd->object, "Curve object to deform with");
1983                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &cmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1984                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1985                         
1986                         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");
1987                         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");
1988                         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");
1989                         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");
1990                         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");
1991                         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");
1992                 } else if (md->type==eModifierType_Build) {
1993                         BuildModifierData *bmd = (BuildModifierData*) md;
1994                         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");
1995                         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");
1996                         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.");
1997                         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.");
1998                 } else if (md->type==eModifierType_Mirror) {
1999                         MirrorModifierData *mmd = (MirrorModifierData*) md;
2000                         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");
2001                         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");
2002                         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");
2003                         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");
2004                         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");
2005                         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)");
2006                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_U, B_MODIFIER_RECALC,
2007                                      "Mirror U",
2008                                      lx, (cy-=19), buttonWidth/2, 19,
2009                                      &mmd->flag, 0, 0, 0, 0,
2010                                      "Mirror the U texture coordinate around "
2011                                      "the 0.5 point");
2012                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_V, B_MODIFIER_RECALC,
2013                                      "Mirror V",
2014                                      lx + buttonWidth/2 + 1, cy, buttonWidth/2, 19,
2015                                      &mmd->flag, 0, 0, 0, 0,
2016                                      "Mirror the V texture coordinate around "
2017                                      "the 0.5 point");
2018                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2019                                        "Ob: ", lx, (cy -= 19), buttonWidth, 19,
2020                                        &mmd->mirror_ob,
2021                                        "Object to use as mirror");
2022                 } else if (md->type==eModifierType_Bevel) {
2023                         BevelModifierData *bmd = (BevelModifierData*) md;
2024                         /*uiDefButS(block, ROW, B_MODIFIER_RECALC, "Distance",
2025                                           lx, (cy -= 19), (buttonWidth/2), 19, &bmd->val_flags,
2026                                           11.0, 0, 0, 0,
2027                                           "Interpret bevel value as a constant distance from each edge");
2028                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "Radius",
2029                                           (lx+buttonWidth/2), cy, (buttonWidth - buttonWidth/2), 19, &bmd->val_flags,
2030                                           11.0, BME_BEVEL_RADIUS, 0, 0,
2031                                           "Interpret bevel value as a radius - smaller angles will be beveled more");*/
2032                         uiBlockBeginAlign(block);
2033                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Width: ",
2034                                           lx, (cy -= 19), buttonWidth, 19, &bmd->value,
2035                                           0.0, 0.5, 5, 4,
2036                                           "Bevel value/amount");
2037                         /*uiDefButI(block, NUM, B_MODIFIER_RECALC, "Recurs",
2038                                           lx, (cy -= 19), buttonWidth, 19, &bmd->res,
2039                                           1, 4, 5, 2,
2040                                           "Number of times to bevel");*/
2041                         uiDefButBitS(block, TOG, BME_BEVEL_VERT,
2042                                           B_MODIFIER_RECALC, "Only Vertices",
2043                                           lx, (cy -= 19), buttonWidth, 19,
2044                                           &bmd->flags, 0, 0, 0, 0,
2045                                           "Bevel only verts/corners; not edges");
2046                         uiBlockEndAlign(block);
2047                                           
2048                         uiDefBut(block, LABEL, 1, "Limit using:",       lx, (cy-=25), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2049                         uiBlockBeginAlign(block);
2050                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "None",
2051                                           lx, (cy -= 19), (buttonWidth/3), 19, &bmd->lim_flags,
2052                                           12.0, 0, 0, 0,
2053                                           "Bevel the entire mesh by a constant amount");
2054                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "Angle",
2055                                           (lx+buttonWidth/3), cy, (buttonWidth/3), 19, &bmd->lim_flags,
2056                                           12.0, BME_BEVEL_ANGLE, 0, 0,
2057                                           "Only bevel edges with sharp enough angles between faces");
2058                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "BevWeight",
2059                                           lx+(2*buttonWidth/3), cy, buttonWidth-2*(buttonWidth/3), 19, &bmd->lim_flags,
2060                                           12.0, BME_BEVEL_WEIGHT, 0, 0,
2061                                           "Use bevel weights to determine how much bevel is applied; apply them separately in vert/edge select mode");
2062                         if ((bmd->lim_flags & BME_BEVEL_WEIGHT) && !(bmd->flags & BME_BEVEL_VERT)) {
2063                                 uiDefButS(block, ROW, B_MODIFIER_RECALC, "Min",
2064                                           lx, (cy -= 19), (buttonWidth/3), 19, &bmd->e_flags,
2065                                           13.0, BME_BEVEL_EMIN, 0, 0,
2066                                           "The sharpest edge's weight is used when weighting a vert");
2067                                 uiDefButS(block, ROW, B_MODIFIER_RECALC, "Average",
2068                                           (lx+buttonWidth/3), cy, (buttonWidth/3), 19, &bmd->e_flags,
2069                                           13.0, 0, 0, 0,
2070                                           "The edge weights are averaged when weighting a vert");
2071                                 uiDefButS(block, ROW, B_MODIFIER_RECALC, "Max",
2072                                           (lx+2*(buttonWidth/3)), cy, buttonWidth-2*(buttonWidth/3), 19, &bmd->e_flags,
2073                                           13.0, BME_BEVEL_EMAX, 0, 0,
2074                                           "The largest edge's wieght is used when weighting a vert");
2075                         }
2076                         else if (bmd->lim_flags & BME_BEVEL_ANGLE) {
2077                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Angle:",
2078                                           lx, (cy -= 19), buttonWidth, 19, &bmd->bevel_angle,
2079                                           0.0, 180.0, 100, 2,
2080                                           "Angle above which to bevel edges");
2081                         }
2082                 } else if (md->type==eModifierType_EdgeSplit) {
2083                         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
2084                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMANGLE,
2085                                      B_MODIFIER_RECALC, "From Edge Angle",
2086                                      lx, (cy -= 19), buttonWidth, 19,
2087                                      &emd->flags, 0, 0, 0, 0,
2088                                      "Split edges with high angle between faces");
2089                         if(emd->flags & MOD_EDGESPLIT_FROMANGLE) {
2090                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Split Angle:",
2091                                           lx, (cy -= 19), buttonWidth, 19, &emd->split_angle,
2092                                           0.0, 180.0, 100, 2,
2093                                           "Angle above which to split edges");
2094                         }
2095                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMFLAG,
2096                                      B_MODIFIER_RECALC, "From Marked As Sharp",
2097                                      lx, (cy -= 19), buttonWidth, 19,
2098                                      &emd->flags, 0, 0, 0, 0,
2099                                      "Split edges that are marked as sharp");
2100                 } else if (md->type==eModifierType_Displace) {
2101                         DisplaceModifierData *dmd = (DisplaceModifierData*) md;
2102                         but = uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",
2103                                        lx, (cy -= 19), buttonWidth, 19,
2104                                        &dmd->defgrp_name, 0.0, 31.0, 0, 0,
2105                                        "Name of vertex group to displace"
2106                                        " (displace whole mesh if blank)");
2107                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2108                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,
2109                                        "Texture: ", lx, (cy -= 19), buttonWidth, 19,
2110                                        &dmd->texture,
2111                                        "Texture to use as displacement input");
2112                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Midlevel:",
2113                                   lx, (cy -= 19), buttonWidth, 19, &dmd->midlevel,
2114                                   0, 1, 10, 3,
2115                                   "Material value that gives no displacement");
2116                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Strength:",
2117                                   lx, (cy -= 19), buttonWidth, 19, &dmd->strength,
2118                                   -1000, 1000, 10, 0.1,
2119                                   "Strength of displacement");
2120                         sprintf(str, "Direction%%t|Normal%%x%d|RGB -> XYZ%%x%d|"
2121                                 "Z%%x%d|Y%%x%d|X%%x%d",
2122                                 MOD_DISP_DIR_NOR, MOD_DISP_DIR_RGB_XYZ,
2123                                 MOD_DISP_DIR_Z, MOD_DISP_DIR_Y, MOD_DISP_DIR_X);
2124                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2125                                   lx, (cy -= 19), buttonWidth, 19, &dmd->direction,
2126                                   0.0, 1.0, 0, 0, "Displace direction");
2127                         sprintf(str, "Texture Coordinates%%t"
2128                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
2129                                 MOD_DISP_MAP_LOCAL, MOD_DISP_MAP_GLOBAL,
2130                                 MOD_DISP_MAP_OBJECT, MOD_DISP_MAP_UV);
2131                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2132                                   lx, (cy -= 19), buttonWidth, 19, &dmd->texmapping,
2133                                   0.0, 1.0, 0, 0,
2134                                   "Texture coordinates used for displacement input");
2135                         if (dmd->texmapping == MOD_DISP_MAP_UV) {
2136                                 char *strtmp;
2137                                 int i;
2138                                 CustomData *fdata = G.obedit ? &G.editMesh->fdata
2139                                                              : &((Mesh*)ob->data)->fdata;
2140                                 build_uvlayer_menu_vars(fdata, &strtmp, &dmd->uvlayer_tmp,
2141                                                         dmd->uvlayer_name);
2142                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
2143                                       lx, (cy -= 19), buttonWidth, 19, &dmd->uvlayer_tmp,
2144                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
2145                                 MEM_freeN(strtmp);
2146                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
2147                                 uiButSetFunc(but, set_displace_uvlayer, dmd,
2148                                              &fdata->layers[i]);
2149                         }
2150                         if(dmd->texmapping == MOD_DISP_MAP_OBJECT) {
2151                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2152                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
2153                                                &dmd->map_object,
2154                                                "Object to get texture coordinates from");
2155                         }
2156                 } else if (md->type==eModifierType_UVProject) {
2157                         UVProjectModifierData *umd = (UVProjectModifierData *) md;
2158                         int i;
2159                         char *strtmp;
2160                         CustomData *fdata = G.obedit ? &G.editMesh->fdata
2161                                                      : &((Mesh*)ob->data)->fdata;
2162                         build_uvlayer_menu_vars(fdata, &strtmp, &umd->uvlayer_tmp,
2163                                                 umd->uvlayer_name);
2164                         but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
2165                               lx, (cy -= 19), buttonWidth, 19, &umd->uvlayer_tmp,
2166                               0.0, 1.0, 0, 0, "Set the UV layer to use");
2167                         i = CustomData_get_layer_index(fdata, CD_MTFACE);
2168                         uiButSetFunc(but, set_uvproject_uvlayer, umd, &fdata->layers[i]);
2169                         MEM_freeN(strtmp);
2170                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspX:",
2171                                   lx, (cy -= 19), buttonWidth / 2, 19, &umd->aspectx,
2172                                   1, 1000, 100, 2,
2173                                   "Horizontal Aspect Ratio");
2174                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspY:",
2175                                   lx + (buttonWidth / 2) + 1, cy, buttonWidth / 2, 19,
2176                                   &umd->aspecty,
2177                                   1, 1000, 100, 2,
2178                                   "Vertical Aspect Ratio");
2179                         uiDefButI(block, NUM, B_MODIFIER_RECALC, "Projectors:",
2180                                   lx, (cy -= 19), buttonWidth, 19, &umd->num_projectors,
2181                                   1, MOD_UVPROJECT_MAXPROJECTORS, 0, 0,
2182                                   "Number of objects to use as projectors");
2183                         for(i = 0; i < umd->num_projectors; ++i) {
2184                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2185                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
2186                                                &umd->projectors[i],
2187                                                "Object to use as projector");
2188                         }
2189                         uiDefIDPoinBut(block, modifier_testImage, ID_IM, B_CHANGEDEP,
2190                                        "Image: ", lx, (cy -= 19), buttonWidth, 19,
2191                                        &umd->image,
2192                                        "Image to project (only faces with this image "
2193                                        "will be altered");
2194                         uiButSetCompleteFunc(but, autocomplete_image, (void *)ob);
2195                         uiDefButBitI(block, TOG, MOD_UVPROJECT_OVERRIDEIMAGE,
2196                                      B_MODIFIER_RECALC, "Override Image",
2197                                      lx, (cy -= 19), buttonWidth, 19,
2198                                      &umd->flags, 0, 0, 0, 0,
2199                                      "Override faces' current images with the "
2200                                      "given image");
2201                 } else if (md->type==eModifierType_Decimate) {
2202                         DecimateModifierData *dmd = (DecimateModifierData*) md;
2203                         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");
2204                         sprintf(str, "Face Count: %d", dmd->faceCount);
2205                         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");
2206                 } else if (md->type==eModifierType_Mask) {
2207                         MaskModifierData *mmd = (MaskModifierData *)md;
2208                         
2209                         sprintf(str, "Mask Mode%%t|Vertex Group%%x%d|Selected Bones%%x%d|",
2210                                 MOD_MASK_MODE_VGROUP,MOD_MASK_MODE_ARM);
2211                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2212                                 lx, (cy -= 19), buttonWidth, 19, &mmd->mode,
2213                                 0.0, 1.0, 0, 0, "How masking region is defined");
2214                                           
2215                         if (mmd->mode == MOD_MASK_MODE_ARM) {
2216                                 uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP,
2217                                     "Ob: ", lx, (cy -= 19), buttonWidth, 19, &mmd->ob_arm,
2218                                     "Armature to use as source of bones to mask");
2219                         }
2220                         else {
2221                                 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", 
2222                                         lx, (cy-=19), buttonWidth, 19, &mmd->vgroup, 
2223                                         0.0, 31.0, 0, 0, "Vertex Group name");
2224                                 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2225                         }
2226                         
2227                         uiDefButBitI(block, TOG, MOD_MASK_INV, B_MODIFIER_RECALC, "Inverse",            
2228                                 lx, (cy-=19), buttonWidth, 19, &mmd->flag, 
2229                                 0, 0, 0, 0, "Use vertices that are not part of region defined");
2230                 } else if (md->type==eModifierType_Smooth) {
2231                         SmoothModifierData *smd = (SmoothModifierData*) md;
2232
2233                         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");
2234                         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");
2235                         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");
2236
2237                         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)");
2238                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Repeat:",     lx,(cy-=19),buttonWidth, 19, &smd->repeat, 0.0, 30.0, 1, 0, "Number of smoothing iterations");
2239                         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");
2240                 } else if (md->type==eModifierType_Cast) {
2241                         CastModifierData *cmd = (CastModifierData*) md;
2242
2243                         char casttypemenu[]="Projection Type%t|Sphere%x0|Cylinder%x1|Cuboid%x2";
2244                         uiDefButS(block, MENU, B_MODIFIER_RECALC, casttypemenu,         lx,(cy-=19),buttonWidth - 30,19, &cmd->type, 0, 0, 0, 0, "Projection type to apply");
2245                         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");
2246                         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");
2247                         if (cmd->type != MOD_CAST_TYPE_CYLINDER) {
2248                                 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");
2249                         }
2250                         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");
2251                         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)");
2252                         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)");
2253                         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)");
2254                         if (ob->type == OB_MESH) {
2255                                 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");
2256                         }
2257                         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");
2258                         if(cmd->object) {
2259                                 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");
2260                         }
2261                 } else if (md->type==eModifierType_Wave) {
2262                         WaveModifierData *wmd = (WaveModifierData*) md;
2263                         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");
2264                         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");
2265                         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");
2266                         uiDefButBitS(block, TOG, MOD_WAVE_NORM, B_MODIFIER_RECALC, "Normals",   lx,(cy-=19),buttonWidth,19, &wmd->flag, 0, 0, 0, 0, "Displace along normals");
2267                         if (wmd->flag & MOD_WAVE_NORM){
2268                                 if (ob->type==OB_MESH) {
2269                                         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");
2270                                         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");
2271                                         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");
2272                                 }
2273                                 else
2274                                         uiDefBut(block, LABEL, 1, "Meshes Only",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");                                
2275                         }
2276
2277                         uiBlockBeginAlign(block);
2278                         if(wmd->speed >= 0)
2279                                 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");
2280                         else
2281                                 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");
2282                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Lifetime:",   lx,(cy-=19),buttonWidth,19, &wmd->lifetime,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the lifespan of the wave");
2283                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Damptime:",   lx,(cy-=19),buttonWidth,19, &wmd->damp,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the dampingtime of the wave");
2284                         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");
2285
2286                         cy -= 9;
2287                         uiBlockBeginAlign(block);
2288                         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");
2289                         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");
2290                         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)");
2291                         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");
2292                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,"Texture: ", lx, (cy -= 19), 220, 19, &wmd->texture,"Texture with which to modulate wave");
2293                         sprintf(str, "Texture Coordinates%%t"
2294                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
2295                                 MOD_WAV_MAP_LOCAL, MOD_WAV_MAP_GLOBAL,
2296                                 MOD_WAV_MAP_OBJECT, MOD_WAV_MAP_UV);
2297                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2298                                   lx, (cy -= 19), 220, 19, &wmd->texmapping,
2299                                   0.0, 1.0, 0, 0,
2300                                   "Texture coordinates used for modulation input");
2301                         if (wmd->texmapping == MOD_WAV_MAP_UV) {
2302                                 char *strtmp;
2303                                 int i;
2304                                 CustomData *fdata = G.obedit ? &G.editMesh->fdata
2305                                                              : &((Mesh*)ob->data)->fdata;
2306                                 build_uvlayer_menu_vars(fdata, &strtmp, &wmd->uvlayer_tmp,
2307                                                         wmd->uvlayer_name);
2308                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
2309                                       lx, (cy -= 19), 220, 19, &wmd->uvlayer_tmp,
2310                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
2311                                 MEM_freeN(strtmp);
2312                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
2313                                 uiButSetFunc(but, set_wave_uvlayer, wmd,
2314                                              &fdata->layers[i]);
2315                         }
2316                         if(wmd->texmapping == MOD_DISP_MAP_OBJECT) {
2317                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2318                                                "Ob: ", lx, (cy -= 19), 220, 19,
2319                                                &wmd->map_object,
2320                                                "Object to get texture coordinates from");
2321                         }
2322                         cy -= 9;
2323                         uiBlockBeginAlign(block);
2324                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Speed:",   lx,(cy-=19),220,19, &wmd->speed, -2.0, 2.0, 0, 0, "Specify the wave speed");
2325                         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");
2326                         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");
2327                         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");
2328                 } else if (md->type==eModifierType_Armature) {
2329                         ArmatureModifierData *amd = (ArmatureModifierData*) md;
2330                         uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &amd->object, "Armature object to deform with");
2331                         
2332                         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");
2333                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2334                         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");
2335                         
2336                         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");
2337                         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");
2338                         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");
2339                         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");
2340                         
2341                         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");
2342
2343                 } else if (md->type==eModifierType_Hook) {
2344                         HookModifierData *hmd = (HookModifierData*) md;
2345                         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");
2346                         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");
2347                         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"); 
2348                         if(hmd->indexar==NULL) {
2349                                 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &hmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
2350                                 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2351                         }
2352                         uiBlockBeginAlign(block);
2353                         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");
2354                         uiButSetFunc(but, modifiers_clearHookOffset, ob, md);
2355                         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");
2356                         uiButSetFunc(but, modifiers_cursorHookCenter, ob, md);
2357
2358                         if (editing) {
2359                                 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");
2360                                 uiButSetFunc(but, modifiers_selectHook, ob, md);
2361                                 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");
2362                                 uiButSetFunc(but, modifiers_reassignHook, ob, md);
2363                         }
2364                 } else if (md->type==eModifierType_Softbody) {
2365                         uiDefBut(block, LABEL, 1, "See Soft Body panel.",       lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2366                 } else if (md->type==eModifierType_Cloth) {
2367                         uiDefBut(block, LABEL, 1, "See Cloth panel.",   lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2368
2369                 } else if (md->type==eModifierType_Collision) {
2370                         uiDefBut(block, LABEL, 1, "See Collision panel.",       lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2371                 } else if (md->type==eModifierType_Fluidsim) {
2372                         uiDefBut(block, LABEL, 1, "See Fluidsim panel.",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2373                 } else if (md->type==eModifierType_Boolean) {
2374                         BooleanModifierData *bmd = (BooleanModifierData*) md;
2375                         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");
2376                         uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &bmd->object, "Mesh object to use for boolean operation");
2377                 } else if (md->type==eModifierType_Array) {
2378                         ArrayModifierData *amd = (ArrayModifierData*) md;
2379                         float range = 10000;
2380                         int cytop, halfwidth = (width - 5)/2 - 15;
2381                         int halflx = lx + halfwidth + 10;
2382
2383                         uiBlockSetEmboss(block, UI_EMBOSSX);
2384                         uiBlockEndAlign(block);
2385
2386                         /* length parameters */
2387                         uiBlockBeginAlign(block);
2388                         sprintf(str, "Length Fit%%t|Fixed Count%%x%d|Fixed Length%%x%d"
2389                                 "|Fit To Curve Length%%x%d",
2390                                 MOD_ARR_FIXEDCOUNT, MOD_ARR_FITLENGTH, MOD_ARR_FITCURVE);
2391                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2392                                   lx, (cy-=19), buttonWidth, 19, &amd->fit_type,
2393                                   0.0, 1.0, 0, 0, "Array length calculation method");
2394                         switch(amd->fit_type)
2395                         {
2396                         case MOD_ARR_FIXEDCOUNT:
2397                                 uiDefButI(block, NUM, B_MODIFIER_RECALC, "Count:",
2398                                           lx, (cy -= 19), buttonWidth, 19, &amd->count,
2399                                           1, 1000, 0, 0, "Number of duplicates to make");
2400                                 break;
2401                         case MOD_ARR_FITLENGTH:
2402                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Length:",
2403                                           lx, (cy -= 19), buttonWidth, 19, &amd->length,
2404                                           0, range, 10, 2,
2405                                           "Length to fit array within");
2406                                 break;
2407                         case MOD_ARR_FITCURVE:
2408                                 uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB,
2409                                                B_CHANGEDEP, "Ob: ",
2410                                                lx, (cy -= 19), buttonWidth, 19, &amd->curve_ob,
2411                                                "Curve object to fit array length to");
2412                                 break;
2413                         }
2414                         uiBlockEndAlign(block);
2415
2416                         /* offset parameters */
2417                         cy -= 10;
2418                         cytop= cy;
2419                         uiBlockBeginAlign(block);
2420                         uiDefButBitI(block, TOG, MOD_ARR_OFF_CONST, B_MODIFIER_RECALC,
2421                                      "Constant Offset", lx, (cy-=19), halfwidth, 19,
2422                                      &amd->offset_type, 0, 0, 0, 0,
2423                                      "Constant offset between duplicates "
2424                                      "(local coordinates)");
2425                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2426                                   lx, (cy-=19), halfwidth, 19,
2427                                   &amd->offset[0],
2428                                   -range, range, 10, 3,
2429                                   "Constant component for duplicate offsets "
2430                                   "(local coordinates)");
2431                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2432                                   lx, (cy-=19), halfwidth, 19,
2433                                   &amd->offset[1],
2434                                   -range, range, 10, 3,
2435                                   "Constant component for duplicate offsets "
2436                                   "(local coordinates)");
2437                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2438                                   lx, (cy-=19), halfwidth, 19,
2439                                   &amd->offset[2],
2440                                   -range, range, 10, 3,
2441                                   "Constant component for duplicate offsets "
2442                                   "(local coordinates)");
2443                         uiBlockEndAlign(block);
2444
2445                         cy= cytop;
2446                         uiBlockBeginAlign(block);
2447                         uiDefButBitI(block, TOG, MOD_ARR_OFF_RELATIVE, B_MODIFIER_RECALC,
2448                                      "Relative Offset", halflx, (cy-=19), halfwidth, 19,
2449                                      &amd->offset_type, 0, 0, 0, 0,
2450                                      "Offset between duplicates relative to object width "
2451                                      "(local coordinates)");
2452                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2453                                   halflx, (cy-=19), halfwidth, 19,
2454                                   &amd->scale[0],
2455                                   -range, range, 10, 3,
2456                                   "Component for duplicate offsets relative to object "
2457                                   "width (local coordinates)");
2458                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2459                                   halflx, (cy-=19), halfwidth, 19,
2460                                   &amd->scale[1],
2461                                   -range, range, 10, 3,
2462                                   "Component for duplicate offsets relative to object "
2463                                   "width (local coordinates)");
2464                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2465                                   halflx, (cy-=19), halfwidth, 19,
2466                                   &amd->scale[2],
2467                                   -range, range, 10, 3,
2468                                   "Component for duplicate offsets relative to object "
2469                                   "width (local coordinates)");
2470                         uiBlockEndAlign(block);
2471
2472                         /* vertex merging parameters */
2473                         cy -= 10;
2474                         cytop= cy;
2475
2476                         uiBlockBeginAlign(block);
2477                         uiDefButBitI(block, TOG, MOD_ARR_MERGE, B_MODIFIER_RECALC,
2478                                      "Merge",
2479                                      lx, (cy-=19), halfwidth/2, 19, &amd->flags,
2480                                      0, 0, 0, 0,
2481                                      "Merge vertices in adjacent duplicates");
2482                         uiDefButBitI(block, TOG, MOD_ARR_MERGEFINAL, B_MODIFIER_RECALC,
2483                                      "First Last",
2484                                      lx + halfwidth/2, cy, (halfwidth+1)/2, 19,
2485                                      &amd->flags,
2486                                      0, 0, 0, 0,
2487                                      "Merge vertices in first duplicate with vertices"
2488                                      " in last duplicate");
2489                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Limit:",
2490                                           lx, (cy-=19), halfwidth, 19, &amd->merge_dist,
2491                                           0, 1.0f, 1, 4,
2492                                           "Limit below which to merge vertices");
2493
2494                         /* offset ob */
2495                         cy = cytop;
2496                         uiBlockBeginAlign(block);
2497                         uiDefButBitI(block, TOG, MOD_ARR_OFF_OBJ, B_MODIFIER_RECALC,
2498                                      "Object Offset", halflx, (cy -= 19), halfwidth, 19,
2499                                      &amd->offset_type, 0, 0, 0, 0,
2500                                      "Add an object transformation to the total offset");
2501                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2502                                        "Ob: ", halflx, (cy -= 19), halfwidth, 19,
2503                                        &amd->offset_ob,
2504                                        "Object from which to take offset transformation");
2505                         uiBlockEndAlign(block);
2506
2507                         cy -= 10;
2508                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2509                                              B_CHANGEDEP, "Start cap: ",
2510                                              lx, (cy -= 19), halfwidth, 19,
2511                                              &amd->start_cap,
2512                                              "Mesh object to use as start cap");
2513                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2514                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2515                                              B_CHANGEDEP, "End cap: ",
2516                                              halflx, cy, halfwidth, 19,
2517                                              &amd->end_cap,
2518                                              "Mesh object to use as end cap");
2519                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2520                 } else if (md->type==eModifierType_MeshDeform) {
2521                         MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
2522
2523                         uiBlockBeginAlign(block);
2524                         uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &mmd->object, "Mesh object to be use as cage"); 
2525                         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");
2526                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2527                         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");
2528
2529                         uiBlockBeginAlign(block);
2530                         if(mmd->bindcos) {
2531                                 but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Unbind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Unbind mesh from cage");
2532                                 uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
2533                         }
2534                         else {
2535                                 but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Bind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Bind mesh to cage");
2536                                 uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
2537                                 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");
2538                                 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!)");
2539                         }
2540                         uiBlockEndAlign(block);
2541                 } else if (md->type==eModifierType_ParticleSystem) {
2542                         uiDefBut(block, LABEL, 1, "See Particle buttons.",      lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2543                 } else if (md->type==eModifierType_ParticleInstance) {
2544                         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
2545                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy -= 19), buttonWidth, 19, &pimd->ob, "Object that has the particlesystem");
2546                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "PSYS:", lx, (cy -= 19), buttonWidth, 19, &pimd->psys, 1, 10, 10, 3, "Particlesystem number in the object");
2547                         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");
2548                         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");
2549                         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");
2550                         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");
2551                         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");
2552                         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");
2553                 } else if (md->type==eModifierType_Explode) {
2554                         ExplodeModifierData *emd = (ExplodeModifierData*) md;
2555                         uiBut *but;
2556                         char *menustr= get_vertexgroup_menustr(ob);
2557                         int defCount=BLI_countlist(&ob->defbase);
2558                         if(defCount==0) emd->vgroup=0;
2559                         uiBlockBeginAlign(block);
2560                         but=uiDefButS(block, MENU, B_MODIFIER_RECALC, menustr,  lx, (cy-=19), buttonWidth-20,19, &emd->vgroup, 0, defCount, 0, 0, "Protect this vertex group");
2561                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2562                         MEM_freeN(menustr);
2563                         
2564                         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");
2565                         uiButSetFunc(but, modifiers_explodeDelVg, (void *)emd, (void *)NULL);
2566                         
2567
2568                         but=uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "",     lx, (cy-=19), buttonWidth,19, &emd->protect, 0.0f, 1.0f, 0, 0, "Clean vertex group edges");
2569                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2570
2571                         but=uiDefBut(block, BUT, B_MODIFIER_RECALC, "Refresh",  lx, (cy-=19), buttonWidth/2,19, 0, 0, 0, 0, 0, "Recalculate faces assigned to particles");
2572                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2573
2574                         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");
2575                         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");
2576                         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");
2577                         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");
2578                         uiBlockEndAlign(block);
2579                 } else if (md->type==eModifierType_Shrinkwrap) {
2580                         ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
2581
2582                         char shrinktypemenu[]="Shrinkwrap type%t|nearest surface point %x0|projection %x1|nearest vertex %x2";
2583
2584                         uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &smd->target, "Target to shrink to");
2585
2586                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &smd->vgroup_name, 0, 31, 0, 0, "Vertex Group name");
2587                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2588
2589                         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");
2590
2591                         cy -= 3;
2592                         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.");
2593
2594                         if (smd->shrinkType == MOD_SHRINKWRAP_PROJECT){
2595
2596
2597                                 /* UI for projection axis */
2598                                 uiBlockBeginAlign(block);
2599                                 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");
2600                                 if(smd->projAxis == 0)
2601                                 {
2602                                         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");
2603                                 }
2604
2605                                 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");
2606                                 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");
2607                                 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");
2608
2609
2610                                 /* allowed directions of projection axis */
2611                                 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");
2612                                 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");
2613
2614                                 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");
2615                                 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");
2616                                 uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob2: ",        lx, (cy-=19), buttonWidth,19, &smd->auxTarget, "Aditional mesh to project over");
2617                         }
2618                         else if (smd->shrinkType == MOD_SHRINKWRAP_NEAREST_SURFACE){
2619                                 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");
2620                         }
2621
2622                         uiBlockEndAlign(block);
2623
2624                 } else if (md->type==eModifierType_SimpleDeform) {
2625                         SimpleDeformModifierData *smd = (SimpleDeformModifierData*) md;
2626                         char simpledeform_modemenu[] = "Deform type%t|Twist %x1|Bend %x2|Taper %x3|Strech %x4";
2627
2628                         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.");
2629                         
2630                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &smd->vgroup_name, 0, 31, 0, 0, "Vertex Group name");
2631                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2632
2633                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ",      lx, (cy-=19), buttonWidth,19, &smd->origin, "Origin of modifier space coordinates");
2634                         if(smd->origin != NULL)
2635                                 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");
2636
2637                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Factor:",     lx,(cy-=19),buttonWidth,19, &smd->factor, -10.0f, 10.0f, 0.5f, 0, "Deform Factor");
2638
2639                         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");
2640                         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");
2641
2642                         if(smd->mode == MOD_SIMPLEDEFORM_MODE_STRETCH
2643                         || smd->mode == MOD_SIMPLEDEFORM_MODE_TAPER  )
2644                         {
2645                                 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");
2646                                 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");
2647                         }
2648                 }
2649
2650                 uiBlockEndAlign(block);
2651
2652                 y-=height;
2653         }
2654
2655         if (md->error) {
2656                 y -= 6;
2657
2658                 uiBlockSetCol(block, color);
2659                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
2660                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y, width, 20, NULL, 5.0, 0.0, 15, 40, ""); 
2661                 uiBlockSetCol(block, TH_AUTO);
2662
2663                 uiDefIconBut(block,LABEL,B_NOP,ICON_ERROR, x-9, y,19,19, 0,0,0,0,0, "");
2664                 uiDefBut(block, LABEL, B_NOP, md->error, x+5, y, width-15, 19, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
2665
2666                 y -= 18;
2667         }
2668
2669         uiClearButLock();
2670
2671         y -= 3+6;
2672
2673         *xco = x;
2674         *yco = y;
2675 }
2676
2677 static void editing_panel_modifiers(Object *ob)
2678 {
2679         ModifierData *md;
2680         uiBlock *block;
2681         char str[64];
2682         int xco, yco, i, lastCageIndex, cageIndex = modifiers_getCageIndex(ob, &lastCageIndex);
2683
2684         block= uiNewBlock(&curarea->uiblocks, "editing_panel_modifiers", UI_EMBOSS, UI_HELV, curarea->win);
2685         if( uiNewPanel(curarea, block, "Modifiers", "Editing", 640, 0, 318, 204)==0) return;
2686         
2687         uiSetButLock((ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
2688         uiNewPanelHeight(block, 204);
2689
2690         uiDefBlockBut(block, modifiers_add_menu, ob, "Add Modifier", 0, 190, 130, 20, "Add a new modifier");
2691
2692         sprintf(str, "To: %s", ob->id.name+2);
2693         uiDefBut(block, LABEL, 1, str,  140, 190, 160, 20, NULL, 0.0, 0.0, 0, 0, "Object whose modifier stack is being edited");
2694
2695         xco = 0;
2696         yco = 160;
2697
2698         md = modifiers_getVirtualModifierList(ob);
2699
2700         for (i=0; md; i++, md=md->next) {
2701                 draw_modifier(block, ob, md, &xco, &yco, i, cageIndex, lastCageIndex);
2702                 if (md->mode&eModifierMode_Virtual) i--;
2703         }
2704         
2705         if(yco < 0) uiNewPanelHeight(block, 204-yco);
2706 }
2707
2708 static char *make_key_menu(Key *key, int startindex)
2709 {
2710         KeyBlock *kb;
2711         int index= 1;
2712         char *str, item[64];
2713
2714         for (kb = key->block.first; kb; kb=kb->next, index++);
2715         str= MEM_mallocN(index*40, "key string");
2716         str[0]= 0;
2717         
2718         index= startindex;
2719         for (kb = key->block.first; kb; kb=kb->next, index++) {
2720                 sprintf (item,  "|%s%%x%d", kb->name, index);
2721                 strcat(str, item);
2722         }
2723         
2724         return str;
2725 }
2726
2727 static void editing_panel_shapes(Object *ob)
2728 {
2729         uiBlock *block;
2730         Key *key= NULL;
2731         KeyBlock *kb;
2732         int icon;
2733         char *strp;
2734         
2735         block= uiNewBlock(&curarea->uiblocks, "editing_panel_shapes", UI_EMBOSS, UI_HELV, curarea->win);
2736         uiNewPanelTabbed("Modifiers", "Editing");
2737         if( uiNewPanel(curarea, block, "Shapes", "Editing", 640, 0, 318, 204)==0) return;
2738         
2739         /* Todo check data is library here */
2740         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2741         
2742         uiDefBut(block, BUT, B_ADDKEY, "Add Shape Key" ,        10, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "Add new Shape Key");
2743         
2744         key= ob_get_key(ob);
2745         if(key==NULL) {
2746                 /* label aligns add button */
2747                 uiDefBut(block, LABEL, 0, "",           170, 180,140,20, NULL, 0, 0, 0, 0, "");
2748                 return;
2749         }
2750         
2751         uiDefButS(block, TOG, B_RELKEY, "Relative",             170, 180,140,20, &key->type, 0, 0, 0, 0, "Makes Shape Keys relative");
2752
2753         kb= BLI_findlink(&key->block, ob->shapenr-1);
2754         if(kb==NULL) {
2755                 ob->shapenr= 1;
2756                 kb= key->block.first;
2757         }
2758
2759         uiBlockBeginAlign(block);
2760         if(ob->shapeflag & OB_SHAPE_LOCK) icon= ICON_PIN_HLT; else icon= ICON_PIN_DEHLT;
2761         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");
2762         if(kb->flag & KEYBLOCK_MUTE) icon= ICON_MUTE_IPO_ON; else icon = ICON_MUTE_IPO_OFF;
2763         uiDefIconButBitS(block, TOG, KEYBLOCK_MUTE, B_MODIFIER_RECALC, icon, 35,150,20,20, &kb->flag, 0, 0, 0, 0, "Mute the current Shape");
2764         uiSetButLock(G.obedit==ob, "Unable to perform in EditMode");
2765         uiDefIconBut(block, BUT, B_PREVKEY, ICON_TRIA_LEFT,             55,150,20,20, NULL, 0, 0, 0, 0, "Previous Shape Key");
2766         strp= make_key_menu(key, 1);
2767         uiDefButS(block, MENU, B_SETKEY, strp,                                  75,150,20,20, &ob->shapenr, 0, 0, 0, 0, "Browse existing choices");
2768         MEM_freeN(strp);
2769         
2770         uiDefIconBut(block, BUT, B_NEXTKEY, ICON_TRIA_RIGHT,    95,150,20,20, NULL, 0, 0, 0, 0, "Next Shape Key");
2771         uiClearButLock();
2772         uiDefBut(block, TEX, B_NAMEKEY, "",                                             115, 150, 170, 20, kb->name, 0.0, 31.0, 0, 0, "Current Shape Key name");
2773         uiDefIconBut(block, BUT, B_DELKEY, ICON_X,                              285,150,25,20, 0, 0, 0, 0, 0, "Deletes current Shape Key");
2774         uiBlockEndAlign(block);
2775
2776         if(key->type && (ob->shapeflag & OB_SHAPE_LOCK)==0 && ob->shapenr!=1) {
2777                 uiBlockBeginAlign(block);
2778                 make_rvk_slider(block, ob, ob->shapenr-1,                       10, 120, 150, 20, "Key value, when used it inserts an animation curve point");
2779                 uiDefButF(block, NUM, B_REDR, "Min ",                           160,120, 75, 20, &kb->slidermin, -10.0, 10.0, 100, 1, "Minumum for slider");
2780                 uiDefButF(block, NUM, B_REDR, "Max ",                           235,120, 75, 20, &kb->slidermax, -10.0, 10.0, 100, 1, "Maximum for slider");
2781                 uiBlockEndAlign(block);
2782         }
2783         if(key->type && ob->shapenr!=1) {
2784                 uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",     10, 90, 150,19, &kb->vgroup, 0.0, 31.0, 0, 0, "Vertex Weight Group name, to blend with Basis Shape");
2785
2786                 strp= make_key_menu(key, 0);
2787                 uiDefButS(block, MENU, B_MODIFIER_RECALC, strp,         160, 90, 150,19, &kb->relative, 0.0, 0.0, 0, 0, "Shape used as a relative key");
2788                 MEM_freeN(strp);
2789         }