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