merge 16951:17122
[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, 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, *layerdata=layer->data;
726         int type= layer->type;
727         int index= CustomData_get_layer_index(data, type);
728         int i, actindex, rndindex;
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         CustomData_set_layer_active(data, type, layer - &data->layers[index]);
740
741         /* Multires is handled seperately because the display data is separate
742            from the data stored in multires */
743         if(me && me->mr) {
744                 multires_delete_layer(me, &me->mr->fdata, type, layer - &data->layers[index]);
745                 multires_level_to_editmesh(OBACT, me, 0);
746                 multires_finish_mesh_update(OBACT);
747         }
748         else if(G.obedit) {
749                 EM_free_data_layer(data, type);
750         }
751         else if(me) {
752                 CustomData_free_layer_active(data, type, me->totface);
753                 mesh_update_customdata_pointers(me);
754         }
755
756         if(!CustomData_has_layer(data, type)) {
757                 if(type == CD_MCOL && (G.f & G_VERTEXPAINT))
758                         G.f &= ~G_VERTEXPAINT; /* get out of vertexpaint mode */
759         }
760
761         /*reconstruct active layer*/
762         if (actlayerdata != layerdata) {
763                 /*find index. . .*/
764                 actindex = CustomData_get_layer_index(data, type);
765                 for (i=actindex; i<data->totlayer; i++) {
766                         if (data->layers[i].data == actlayerdata) {
767                                 actindex = i - actindex;
768                                 break;
769                         }
770                 }
771                 
772                 /*set index. . .*/
773                 CustomData_set_layer_active(data, type, actindex);
774         }
775         
776         if (rndlayerdata != layerdata) {
777                 /*find index. . .*/
778                 rndindex = CustomData_get_layer_index(data, type);
779                 for (i=rndindex; i<data->totlayer; i++) {
780                         if (data->layers[i].data == rndlayerdata) {
781                                 rndindex = i - rndindex;
782                                 break;
783                         }
784                 }
785                 
786                 /*set index. . .*/
787                 CustomData_set_layer_render(data, type, rndindex);
788         }
789         
790         
791         DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
792         
793         if(type == CD_MTFACE)
794                 BIF_undo_push("Delete UV Texture");
795         else if(type == CD_MCOL)
796                 BIF_undo_push("Delete Vertex Color");
797
798         allqueue(REDRAWVIEW3D, 0);
799         allqueue(REDRAWIMAGE, 0);
800         allqueue(REDRAWBUTSEDIT, 0);
801 }
802
803 static int customdata_buttons(
804         uiBlock *block, Mesh *me, CustomData *data,
805         int type, int *activep, int *renderp,
806         int setevt, int setevt_rnd, int newevt,
807         char *label, char *shortlabel, char *browsetip, char *browsetip_rnd,
808         char *newtip, char *deltip, int x, int y)
809 {
810         CustomDataLayer *layer;
811         uiBut *but;
812         int i, count= CustomData_number_of_layers(data, type);
813
814         if(count >= MAX_MTFACE) {
815                 uiDefBut(block, LABEL, 0, label, x,y,220,19, 0, 0.0, 0, 0, 0, "");
816         }
817         else {
818                 uiDefBut(block, LABEL, 0, label, x,y,140,19, 0, 0.0, 0, 0, 0, "");
819                 uiBlockBeginAlign(block);
820                 uiDefBut(block, BUT, newevt, "New", x+140,y,80,19, 0,0,0,0,0, newtip);
821                 uiBlockEndAlign(block);
822         }
823
824         y -= (count)? 24: 19;
825
826         uiBlockBeginAlign(block);
827         for (count=1, i=0; i<data->totlayer; i++) {
828                 layer= &data->layers[i];
829
830                 if(layer->type == type) {
831                         *activep= layer->active + 1;
832                         *renderp= layer->active_rnd + 1;
833                         
834                         uiDefIconButI(block, ROW, setevt, ICON_VIEW3D, x,y,25,19, activep, 1.0, count, 0, 0, browsetip);
835                         uiDefIconButI(block, ROW, setevt_rnd, ICON_SCENE, x+25,y,25,19, renderp, 1.0, count, 0, 0, browsetip_rnd);
836                         but=uiDefBut(block, TEX, setevt, "", x+50,y,145,19, layer->name, 0.0, 31.0, 0, 0, label);
837                         uiButSetFunc(but, verify_customdata_name_func, data, layer);
838                         but= uiDefIconBut(block, BUT, B_NOP, VICON_X, x+195,y,25,19, NULL, 0.0, 0.0, 0.0, 0.0, deltip);
839                         uiButSetFunc(but, delete_customdata_layer, me, layer);
840
841
842                         count++;
843                         y -= 19;
844                 }
845         }
846         uiBlockEndAlign(block);
847
848         return y;
849 }
850
851 static void editing_panel_mesh_type(Object *ob, Mesh *me)
852 {
853         uiBlock *block;
854         uiBut *but;
855         float val;
856         CustomData *fdata;
857         int yco;
858
859         block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_type", UI_EMBOSS, UI_HELV, curarea->win);
860         if( uiNewPanel(curarea, block, "Mesh", "Editing", 320, 0, 318, 204)==0) return;
861         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
862
863         uiBlockBeginAlign(block);
864         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");
865         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");
866         uiBlockEndAlign(block);
867
868         /* Retopo */
869         if(G.obedit) {
870                 uiBlockBeginAlign(block);
871                 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");
872                 uiButSetFunc(but,retopo_toggle,ob,me);
873                 if(G.scene->toolsettings->retopo_mode) {
874                         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.");
875                         uiButSetFunc(but,retopo_paint_toggle,ob,me);
876                         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");
877                         uiButSetFunc(but,retopo_do_all_cb,ob,me);
878                 }
879                 uiBlockEndAlign(block);
880         }
881
882         uiBlockBeginAlign(block);
883         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");
884         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");
885         uiDefBut(block, BUT,B_DOCENTERCURSOR, "Center Cursor",          10, 60, 170, 19, 0, 0, 0, 0, 0, "Shifts object's origin to cursor location");
886         uiBlockEndAlign(block);
887
888         uiBlockBeginAlign(block);
889         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");
890         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");
891         uiBlockEndAlign(block);
892
893         uiDefIDPoinBut(block, test_meshpoin_but, ID_ME, B_REDR, "TexMesh: ",    190,180,220,19, &me->texcomesh, "Derive texture coordinates from another mesh.");
894
895         if(me->msticky) val= 1.0; else val= 0.0;
896         uiDefBut(block, LABEL, 0, "Sticky",                             190,155,140,19, 0, val, 0, 0, 0, "");
897         uiBlockBeginAlign(block);
898         if(me->msticky==NULL) {
899                 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");
900         }
901         else uiDefBut(block, BUT, B_DELSTICKY, "Delete",        330,155, 80,19, 0, 0, 0, 0, 0, "Deletes Sticky texture coordinates");
902         uiBlockEndAlign(block);
903
904         fdata= (G.obedit)? &G.editMesh->fdata: &me->fdata;
905         yco= customdata_buttons(block, me, fdata, CD_MTFACE, &acttface, &acttface_rnd,
906                 B_SETTFACE, B_SETTFACE_RND, B_NEWTFACE, "UV Texture", "UV Texture:",
907                 "Set active UV texture", "Set rendering UV texture", "Creates a new UV texture layer",
908                 "Removes the current UV texture layer", 190, 130);
909
910         yco= customdata_buttons(block, me, fdata, CD_MCOL, &actmcol, &actmcol_rnd,
911                 B_SETMCOL, B_SETMCOL_RND, B_NEWMCOL, "Vertex Color", "Vertex Color:",
912                 "Sets active vertex color layer", "Sets rendering vertex color layer", "Creates a new vertex color layer",
913                 "Removes the current vertex color layer", 190, yco-5);
914
915         if(yco < 0)
916                 uiNewPanelHeight(block, 204 - yco);
917 }
918
919 /* *************************** MODIFIERS ******************************** */
920
921 void do_modifier_panels(unsigned short event)
922 {
923         Object *ob = OBACT;
924
925         switch(event) {
926         case B_MODIFIER_REDRAW:
927                 allqueue(REDRAWBUTSEDIT, 0);
928                 allqueue(REDRAWOOPS, 0);
929                 break;
930
931         case B_MODIFIER_RECALC:
932                 allqueue(REDRAWBUTSEDIT, 0);
933                 allqueue(REDRAWVIEW3D, 0);
934                 allqueue(REDRAWIMAGE, 0);
935                 allqueue(REDRAWOOPS, 0);
936                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
937                 object_handle_update(ob);
938                 countall();
939                 break;
940         }
941 }
942
943 static void modifiers_add(void *ob_v, int type)
944 {
945         Object *ob = ob_v;
946         ModifierTypeInfo *mti = modifierType_getInfo(type);
947         
948         if (mti->flags&eModifierTypeFlag_RequiresOriginalData) {
949                 ModifierData *md = ob->modifiers.first;
950
951                 while (md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform) {
952                         md = md->next;
953                 }
954
955                 BLI_insertlinkbefore(&ob->modifiers, md, modifier_new(type));
956         } else {
957                 BLI_addtail(&ob->modifiers, modifier_new(type));
958         }
959         BIF_undo_push("Add modifier");
960 }
961
962 typedef struct MenuEntry {
963         char *name;
964         int ID;
965 } MenuEntry;
966
967 static int menuEntry_compare_names(const void *entry1, const void *entry2)
968 {
969         return strcmp(((MenuEntry *)entry1)->name, ((MenuEntry *)entry2)->name);
970 }
971
972 static uiBlock *modifiers_add_menu(void *ob_v)
973 {
974         Object *ob = ob_v;
975         uiBlock *block;
976         int i, yco=0;
977         int numEntries = 0;
978         MenuEntry entries[NUM_MODIFIER_TYPES];
979         
980         block= uiNewBlock(&curarea->uiblocks, "modifier_add_menu",
981                           UI_EMBOSSP, UI_HELV, curarea->win);
982         uiBlockSetButmFunc(block, modifiers_add, ob);
983
984         for (i=eModifierType_None+1; i<NUM_MODIFIER_TYPES; i++) {
985                 ModifierTypeInfo *mti = modifierType_getInfo(i);
986
987                 /* Only allow adding through appropriate other interfaces */
988                 if(ELEM3(i, eModifierType_Softbody, eModifierType_Hook, eModifierType_ParticleSystem)) continue;
989                 
990                 if(ELEM3(i, eModifierType_Cloth, eModifierType_Collision, eModifierType_Fluidsim)) continue;
991
992                 if((mti->flags&eModifierTypeFlag_AcceptsCVs) ||
993                    (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
994                         entries[numEntries].name = mti->name;
995                         entries[numEntries].ID = i;
996
997                         ++numEntries;
998                 }
999         }
1000
1001         qsort(entries, numEntries, sizeof(*entries), menuEntry_compare_names);
1002
1003
1004         for(i = 0; i < numEntries; ++i)
1005                 uiDefBut(block, BUTM, B_MODIFIER_RECALC, entries[i].name,
1006                          0, yco -= 20, 160, 19, NULL, 0, 0, 1, entries[i].ID, "");
1007
1008         uiTextBoundsBlock(block, 50);
1009         uiBlockSetDirection(block, UI_DOWN);
1010
1011         return block;
1012 }
1013
1014 static void modifiers_del(void *ob_v, void *md_v)
1015 {
1016         Object *ob = ob_v;
1017         ModifierData *md;
1018
1019                 /* It seems on rapid delete it is possible to
1020                  * get called twice on same modifier, so make
1021                  * sure it is in list.
1022                  */
1023         for (md=ob->modifiers.first; md; md=md->next)
1024                 if (md==md_v)
1025                         break;
1026         
1027         if (!md)
1028                 return;
1029
1030         if(md->type==eModifierType_ParticleSystem){
1031                 ParticleSystemModifierData *psmd=(ParticleSystemModifierData*)md;
1032                 BLI_remlink(&ob->particlesystem, psmd->psys);
1033                 psys_free(ob,psmd->psys);
1034         }
1035
1036         BLI_remlink(&ob->modifiers, md_v);
1037
1038         modifier_free(md_v);
1039
1040         BIF_undo_push("Del modifier");
1041 }
1042
1043 int mod_moveUp(void *ob_v, void *md_v)
1044 {
1045         Object *ob = ob_v;
1046         ModifierData *md = md_v;
1047
1048         if (md->prev) {
1049                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1050
1051                 if (mti->type!=eModifierTypeType_OnlyDeform) {
1052                         ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type);
1053
1054                         if (nmti->flags&eModifierTypeFlag_RequiresOriginalData)
1055                                 return -1;
1056                 }
1057
1058                 BLI_remlink(&ob->modifiers, md);
1059                 BLI_insertlink(&ob->modifiers, md->prev->prev, md);
1060         }
1061
1062         return 0;
1063 }
1064
1065 static void modifiers_moveUp(void *ob_v, void *md_v)
1066 {
1067         if( mod_moveUp( ob_v, md_v ) )
1068                 error("Cannot move above a modifier requiring original data.");
1069         else
1070                 BIF_undo_push("Move modifier");
1071 }
1072
1073 int mod_moveDown(void *ob_v, void *md_v)
1074 {
1075         Object *ob = ob_v;
1076         ModifierData *md = md_v;
1077
1078         if (md->next) {
1079                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1080
1081                 if (mti->flags&eModifierTypeFlag_RequiresOriginalData) {
1082                         ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type);
1083
1084                         if (nmti->type!=eModifierTypeType_OnlyDeform)
1085                                 return -1;
1086                 }
1087
1088                 BLI_remlink(&ob->modifiers, md);
1089                 BLI_insertlink(&ob->modifiers, md->next, md);
1090         }
1091
1092         return 0;
1093 }
1094
1095 static void modifiers_moveDown(void *ob_v, void *md_v)
1096 {
1097         if( mod_moveDown( ob_v, md_v ) )
1098                 error("Cannot move beyond a non-deforming modifier.");
1099         else
1100                 BIF_undo_push("Move modifier");
1101 }
1102
1103 static void modifier_testLatticeObj(char *name, ID **idpp)
1104 {
1105         ID *id;
1106
1107         for (id= G.main->object.first; id; id= id->next) {
1108                 if( strcmp(name, id->name+2)==0 ) {
1109                         if (((Object *)id)->type != OB_LATTICE) {
1110                                 error ("Lattice deform object must be a lattice");
1111                                 break;
1112                         } 
1113                         *idpp= id;
1114                         return;
1115                 }
1116         }
1117         *idpp= 0;
1118 }
1119
1120 static void modifier_testCurveObj(char *name, ID **idpp)
1121 {
1122         ID *id;
1123
1124         for (id= G.main->object.first; id; id= id->next) {
1125                 if( strcmp(name, id->name+2)==0 ) {
1126                         if (((Object *)id)->type != OB_CURVE) {
1127                                 error ("Curve deform object must be a curve");
1128                                 break;
1129                         } 
1130                         *idpp= id;
1131                         return;
1132                 }
1133         }
1134         *idpp= 0;
1135 }
1136
1137 static void modifier_testMeshObj(char *name, ID **idpp)
1138 {
1139         ID *id;
1140
1141         for (id= G.main->object.first; id; id= id->next) {
1142                 /* no boolean on its own object */
1143                 if(id != (ID *)OBACT) {
1144                         if( strcmp(name, id->name+2)==0 ) {
1145                                 if (((Object *)id)->type != OB_MESH) {
1146                                         error ("Boolean modifier object must be a mesh");
1147                                         break;
1148                                 } 
1149                                 *idpp= id;
1150                                 return;
1151                         }
1152                 }
1153         }
1154         *idpp= NULL;
1155 }
1156
1157 static void modifier_testArmatureObj(char *name, ID **idpp)
1158 {
1159         ID *id;
1160
1161         for (id= G.main->object.first; id; id= id->next) {
1162                 if( strcmp(name, id->name+2)==0 ) {
1163                         if (((Object *)id)->type != OB_ARMATURE) {
1164                                 error ("Armature deform object must be an armature");
1165                                 break;
1166                         } 
1167                         *idpp= id;
1168                         return;
1169                 }
1170         }
1171         *idpp= 0;
1172 }
1173
1174 static void modifier_testTexture(char *name, ID **idpp)
1175 {
1176         ID *id;
1177
1178         for(id = G.main->tex.first; id; id = id->next) {
1179                 if(strcmp(name, id->name + 2) == 0) {
1180                         *idpp = id;
1181                         /* texture gets user, objects not: delete object = clear modifier */
1182                         id_us_plus(id);
1183                         return;
1184                 }
1185         }
1186         *idpp = 0;
1187 }
1188
1189 #if 0 /* this is currently unused, but could be useful in the future */
1190 static void modifier_testMaterial(char *name, ID **idpp)
1191 {
1192         ID *id;
1193
1194         for(id = G.main->mat.first; id; id = id->next) {
1195                 if(strcmp(name, id->name + 2) == 0) {
1196                         *idpp = id;
1197                         return;
1198                 }
1199         }
1200         *idpp = 0;
1201 }
1202 #endif
1203
1204 static void modifier_testImage(char *name, ID **idpp)
1205 {
1206         ID *id;
1207
1208         for(id = G.main->image.first; id; id = id->next) {
1209                 if(strcmp(name, id->name + 2) == 0) {
1210                         *idpp = id;
1211                         return;
1212                 }
1213         }
1214         *idpp = 0;
1215 }
1216
1217 /* autocomplete callback for ID buttons */
1218 void autocomplete_image(char *str, void *arg_v)
1219 {
1220         /* search if str matches the beginning of an ID struct */
1221         if(str[0]) {
1222                 AutoComplete *autocpl = autocomplete_begin(str, 22);
1223                 ID *id;
1224
1225                 for(id = G.main->image.first; id; id = id->next)
1226                         autocomplete_do_name(autocpl, id->name+2);
1227
1228                 autocomplete_end(autocpl, str);
1229         }
1230 }
1231
1232 /* autocomplete callback for ID buttons */
1233 void autocomplete_meshob(char *str, void *arg_v)
1234 {
1235         /* search if str matches the beginning of an ID struct */
1236         if(str[0]) {
1237                 AutoComplete *autocpl = autocomplete_begin(str, 22);
1238                 ID *id;
1239
1240                 for(id = G.main->object.first; id; id = id->next)
1241                         if(((Object *)id)->type == OB_MESH)
1242                                 autocomplete_do_name(autocpl, id->name+2);
1243
1244                 autocomplete_end(autocpl, str);
1245         }
1246 }
1247 static void modifiers_convertParticles(void *obv, void *mdv)
1248 {
1249         Object *obn;
1250         ModifierData *md = mdv;
1251         ParticleSystem *psys;
1252         ParticleCacheKey *key, **cache;
1253         ParticleSettings *part;
1254         Mesh *me;
1255         MVert *mvert;
1256         MEdge *medge;
1257         int a, k, kmax;
1258         int totvert=0, totedge=0, cvert=0;
1259         int totpart=0, totchild=0;
1260
1261         if(md->type != eModifierType_ParticleSystem) return;
1262
1263         if(G.f & G_PARTICLEEDIT) return;
1264
1265         psys=((ParticleSystemModifierData *)md)->psys;
1266         part= psys->part;
1267
1268         if(part->draw_as == PART_DRAW_GR || part->draw_as == PART_DRAW_OB) {
1269                 make_object_duplilist_real(NULL);
1270         }
1271         else {
1272                 if(part->draw_as != PART_DRAW_PATH || psys->pathcache == 0)
1273                         return;
1274
1275                 totpart= psys->totcached;
1276                 totchild= psys->totchildcache;
1277
1278                 if(totchild && (part->draw&PART_DRAW_PARENT)==0)
1279                         totpart= 0;
1280
1281                 /* count */
1282                 cache= psys->pathcache;
1283                 for(a=0; a<totpart; a++) {
1284                         key= cache[a];
1285                         totvert+= key->steps+1;
1286                         totedge+= key->steps;
1287                 }
1288
1289                 cache= psys->childcache;
1290                 for(a=0; a<totchild; a++) {
1291                         key= cache[a];
1292                         totvert+= key->steps+1;
1293                         totedge+= key->steps;
1294                 }
1295
1296                 if(totvert==0) return;
1297
1298                 /* add new mesh */
1299                 obn= add_object(OB_MESH);
1300                 me= obn->data;
1301                 
1302                 me->totvert= totvert;
1303                 me->totedge= totedge;
1304                 
1305                 me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
1306                 me->medge= CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
1307                 me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0);
1308                 
1309                 mvert= me->mvert;
1310                 medge= me->medge;
1311
1312                 /* copy coordinates */
1313                 cache= psys->pathcache;
1314                 for(a=0; a<totpart; a++) {
1315                         key= cache[a];
1316                         kmax= key->steps;
1317                         for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
1318                                 VECCOPY(mvert->co,key->co);
1319                                 if(k) {
1320                                         medge->v1= cvert-1;
1321                                         medge->v2= cvert;
1322                                         medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE;
1323                                         medge++;
1324                                 }
1325                         }
1326                 }
1327
1328                 cache=psys->childcache;
1329                 for(a=0; a<totchild; a++) {
1330                         key=cache[a];
1331                         kmax=key->steps;
1332                         for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
1333                                 VECCOPY(mvert->co,key->co);
1334                                 if(k) {
1335                                         medge->v1=cvert-1;
1336                                         medge->v2=cvert;
1337                                         medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE;
1338                                         medge++;
1339                                 }
1340                         }
1341                 }
1342         }
1343
1344         DAG_scene_sort(G.scene);
1345
1346         allqueue(REDRAWVIEW3D, 0);
1347         allqueue(REDRAWOOPS, 0);
1348         
1349         BIF_undo_push("Convert particles to mesh object(s).");
1350 }
1351
1352 static void modifiers_applyModifier(void *obv, void *mdv)
1353 {
1354         Object *ob = obv;
1355         ModifierData *md = mdv;
1356         DerivedMesh *dm;
1357         Mesh *me = ob->data;
1358         int converted = 0;
1359
1360         if (G.obedit) {
1361                 error("Modifiers cannot be applied in editmode");
1362                 return;
1363         } else if (((ID*) ob->data)->us>1) {
1364                 error("Modifiers cannot be applied to multi-user data");
1365                 return;
1366         }
1367
1368         if (md!=ob->modifiers.first) {
1369                 if (!okee("Modifier is not first"))
1370                         return;
1371         }
1372
1373         if (ob->type==OB_MESH) {
1374                 if(me->mr && multires_modifier_warning()) {
1375                         error("Modifier changes topology; cannot apply with multires active");
1376                         return;
1377                 }
1378                 if(me->key) {
1379                         error("Modifier cannot be applied to Mesh with Shape Keys");
1380                         return;
1381                 }
1382         
1383                 mesh_pmv_off(ob, me);
1384         
1385                 dm = mesh_create_derived_for_modifier(ob, md);
1386                 if (!dm) {
1387                         error("Modifier is disabled or returned error, skipping apply");
1388                         return;
1389                 }
1390
1391                 DM_to_mesh(dm, me);
1392                 converted = 1;
1393
1394                 dm->release(dm);
1395         } 
1396         else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
1397                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1398                 Curve *cu = ob->data;
1399                 int numVerts;
1400                 float (*vertexCos)[3];
1401
1402                 if (!okee("Apply will only change CV points, not tesselated/bevel vertices"))
1403                         return;
1404
1405                 if (!(md->mode&eModifierMode_Realtime) || (mti->isDisabled && mti->isDisabled(md))) {
1406                         error("Modifier is disabled, skipping apply");
1407                         return;
1408                 }
1409
1410                 vertexCos = curve_getVertexCos(cu, &cu->nurb, &numVerts);
1411                 mti->deformVerts(md, ob, NULL, vertexCos, numVerts);
1412                 curve_applyVertexCos(cu, &cu->nurb, vertexCos);
1413
1414                 converted = 1;
1415
1416                 MEM_freeN(vertexCos);
1417
1418                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1419         }
1420         else {
1421                 error("Cannot apply modifier for this object type");
1422                 return;
1423         }
1424
1425         if (converted) {
1426                 BLI_remlink(&ob->modifiers, md);
1427                 modifier_free(md);
1428
1429                 BIF_undo_push("Apply modifier");
1430         }
1431 }
1432
1433 static void modifiers_copyModifier(void *ob_v, void *md_v)
1434 {
1435         Object *ob = ob_v;
1436         ModifierData *md = md_v;
1437         ModifierData *nmd = modifier_new(md->type);
1438
1439         modifier_copyData(md, nmd);
1440
1441         BLI_insertlink(&ob->modifiers, md, nmd);
1442
1443         BIF_undo_push("Copy modifier");
1444 }
1445
1446 static void modifiers_setOnCage(void *ob_v, void *md_v)
1447 {
1448         Object *ob = ob_v;
1449         ModifierData *md;
1450         
1451         int i, cageIndex = modifiers_getCageIndex(ob, NULL );
1452
1453         for( i = 0, md=ob->modifiers.first; md; ++i, md=md->next )
1454                 if( md == md_v ) {
1455                         if( i >= cageIndex )
1456                                 md->mode ^= eModifierMode_OnCage;
1457                         break;
1458                 }
1459 }
1460
1461 static void modifiers_clearHookOffset(void *ob_v, void *md_v)
1462 {
1463         Object *ob = ob_v;
1464         ModifierData *md = md_v;
1465         HookModifierData *hmd = (HookModifierData*) md;
1466         
1467         if (hmd->object) {
1468                 Mat4Invert(hmd->object->imat, hmd->object->obmat);
1469                 Mat4MulSerie(hmd->parentinv, hmd->object->imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL);
1470                 BIF_undo_push("Clear hook offset");
1471         }
1472 }
1473
1474 static void modifiers_cursorHookCenter(void *ob_v, void *md_v)
1475 {
1476         Object *ob = ob_v;
1477         ModifierData *md = md_v;
1478         HookModifierData *hmd = (HookModifierData*) md;
1479
1480         if (G.vd) {
1481                 float *curs = give_cursor();
1482                 float bmat[3][3], imat[3][3];
1483
1484                 where_is_object(ob);
1485         
1486                 Mat3CpyMat4(bmat, ob->obmat);
1487                 Mat3Inv(imat, bmat);
1488
1489                 curs= give_cursor();
1490                 hmd->cent[0]= curs[0]-ob->obmat[3][0];
1491                 hmd->cent[1]= curs[1]-ob->obmat[3][1];
1492                 hmd->cent[2]= curs[2]-ob->obmat[3][2];
1493                 Mat3MulVecfl(imat, hmd->cent);
1494
1495                 BIF_undo_push("Hook cursor center");
1496         }
1497 }
1498
1499 static void modifiers_selectHook(void *ob_v, void *md_v)
1500 {
1501         ModifierData *md = md_v;
1502         HookModifierData *hmd = (HookModifierData*) md;
1503
1504         hook_select(hmd);
1505 }
1506
1507 static void modifiers_reassignHook(void *ob_v, void *md_v)
1508 {
1509         ModifierData *md = md_v;
1510         HookModifierData *hmd = (HookModifierData*) md;
1511         float cent[3];
1512         int *indexar, tot, ok;
1513         char name[32];
1514                 
1515         ok= hook_getIndexArray(&tot, &indexar, name, cent);
1516
1517         if (!ok) {
1518                 error("Requires selected vertices or active Vertex Group");
1519         } else {
1520                 if (hmd->indexar) {
1521                         MEM_freeN(hmd->indexar);
1522                 }
1523
1524                 VECCOPY(hmd->cent, cent);
1525                 hmd->indexar = indexar;
1526                 hmd->totindex = tot;
1527         }
1528 }
1529
1530 static void modifiers_convertToReal(void *ob_v, void *md_v)
1531 {
1532         Object *ob = ob_v;
1533         ModifierData *md = md_v;
1534         ModifierData *nmd = modifier_new(md->type);
1535
1536         modifier_copyData(md, nmd);
1537         nmd->mode &= ~eModifierMode_Virtual;
1538
1539         BLI_addhead(&ob->modifiers, nmd);
1540
1541         ob->partype = PAROBJECT;
1542
1543         BIF_undo_push("Modifier convert to real");
1544 }
1545
1546 static void build_uvlayer_menu_vars(CustomData *data, char **menu_string,
1547                                     int *uvlayer_tmp, char *uvlayer_name)
1548 {
1549         char strtmp[38];
1550         int totuv, i;
1551         CustomDataLayer *layer
1552                     = &data->layers[CustomData_get_layer_index(data, CD_MTFACE)];
1553
1554         *uvlayer_tmp = -1;
1555
1556         totuv = CustomData_number_of_layers(data, CD_MTFACE);
1557
1558         *menu_string = MEM_callocN(sizeof(**menu_string) * (totuv * 38 + 10),
1559                                    "menu_string");
1560         sprintf(*menu_string, "UV Layer%%t");
1561         for(i = 0; i < totuv; i++) {
1562                 /* assign first layer as uvlayer_name if uvlayer_name is null. */
1563                 if(strcmp(layer->name, uvlayer_name) == 0) *uvlayer_tmp = i + 1;
1564                 sprintf(strtmp, "|%s%%x%d", layer->name, i + 1);
1565                 strcat(*menu_string, strtmp);
1566                 layer++;
1567         }
1568
1569         /* there is no uvlayer defined, or else it was deleted. Assign active
1570          * layer, then recalc modifiers.
1571          */
1572         if(*uvlayer_tmp == -1) {
1573                 if(CustomData_get_active_layer_index(data, CD_MTFACE) != -1) {
1574                         *uvlayer_tmp = 1;
1575                         layer = data->layers;
1576                         for(i = 0; i < CustomData_get_active_layer_index(data, CD_MTFACE);
1577                             i++, layer++) {
1578                                 if(layer->type == CD_MTFACE) (*uvlayer_tmp)++;
1579                         }
1580                         strcpy(uvlayer_name, layer->name);
1581
1582                         /* update the modifiers */
1583                         do_modifier_panels(B_MODIFIER_RECALC);
1584                 } else {
1585                         /* ok we have no uv layers, so make sure menu button knows that.*/
1586                         *uvlayer_tmp = 0;
1587                 }
1588         }
1589 }
1590
1591 void set_wave_uvlayer(void *arg1, void *arg2)
1592 {
1593         WaveModifierData *wmd=arg1;
1594         CustomDataLayer *layer = arg2;
1595
1596         /*check we have UV layers*/
1597         if (wmd->uvlayer_tmp < 1) return;
1598         layer = layer + (wmd->uvlayer_tmp-1);
1599         
1600         strcpy(wmd->uvlayer_name, layer->name);
1601 }
1602
1603 void set_displace_uvlayer(void *arg1, void *arg2)
1604 {
1605         DisplaceModifierData *dmd=arg1;
1606         CustomDataLayer *layer = arg2;
1607
1608         /*check we have UV layers*/
1609         if (dmd->uvlayer_tmp < 1) return;
1610         layer = layer + (dmd->uvlayer_tmp-1);
1611         
1612         strcpy(dmd->uvlayer_name, layer->name);
1613 }
1614
1615 void set_uvproject_uvlayer(void *arg1, void *arg2)
1616 {
1617         UVProjectModifierData *umd=arg1;
1618         CustomDataLayer *layer = arg2;
1619
1620         /*check we have UV layers*/
1621         if (umd->uvlayer_tmp < 1) return;
1622         layer = layer + (umd->uvlayer_tmp-1);
1623         
1624         strcpy(umd->uvlayer_name, layer->name);
1625 }
1626
1627 static void modifiers_bindMeshDeform(void *ob_v, void *md_v)
1628 {
1629         MeshDeformModifierData *mmd = (MeshDeformModifierData*) md_v;
1630         Object *ob = (Object*)ob_v;
1631
1632         if(mmd->bindcos) {
1633                 if(mmd->bindweights) MEM_freeN(mmd->bindweights);
1634                 if(mmd->bindcos) MEM_freeN(mmd->bindcos);
1635                 if(mmd->dyngrid) MEM_freeN(mmd->dyngrid);
1636                 if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences);
1637                 if(mmd->dynverts) MEM_freeN(mmd->dynverts);
1638                 mmd->bindweights= NULL;
1639                 mmd->bindcos= NULL;
1640                 mmd->dyngrid= NULL;
1641                 mmd->dyninfluences= NULL;
1642                 mmd->dynverts= NULL;
1643                 mmd->totvert= 0;
1644                 mmd->totcagevert= 0;
1645                 mmd->totinfluence= 0;
1646         }
1647         else {
1648                 DerivedMesh *dm;
1649                 int mode= mmd->modifier.mode;
1650
1651                 /* force modifier to run, it will call binding routine */
1652                 mmd->needbind= 1;
1653                 mmd->modifier.mode |= eModifierMode_Realtime;
1654
1655                 if(ob->type == OB_MESH) {
1656                         dm= mesh_create_derived_view(ob, 0);
1657                         dm->release(dm);
1658                 }
1659                 else if(ob->type == OB_LATTICE) {
1660                         lattice_calc_modifiers(ob);
1661                 }
1662                 else if(ob->type==OB_MBALL) {
1663                         makeDispListMBall(ob);
1664                 }
1665                 else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
1666                         makeDispListCurveTypes(ob, 0);
1667                 }
1668
1669                 mmd->needbind= 0;
1670                 mmd->modifier.mode= mode;
1671         }
1672 }
1673
1674 void modifiers_explodeFacepa(void *arg1, void *arg2)
1675 {
1676         ExplodeModifierData *emd=arg1;
1677
1678         emd->flag |= eExplodeFlag_CalcFaces;
1679 }
1680
1681 void modifiers_explodeDelVg(void *arg1, void *arg2)
1682 {
1683         ExplodeModifierData *emd=arg1;
1684         emd->vgroup = 0;
1685 }
1686
1687 static int modifier_is_fluid_particles(ModifierData *md) {
1688         if(md->type == eModifierType_ParticleSystem) {
1689                 if(((ParticleSystemModifierData *)md)->psys->part->type == PART_FLUID)
1690                         return 1;
1691         }
1692         return 0;
1693 }
1694 static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco, int *yco, int index, int cageIndex, int lastCageIndex)
1695 {
1696         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1697         uiBut *but;
1698         int isVirtual = md->mode&eModifierMode_Virtual;
1699         int x = *xco, y = *yco, color = md->error?TH_REDALERT:TH_BUT_NEUTRAL;
1700         int editing = (G.obedit==ob);
1701         short height=26, width = 295, buttonWidth = width-120-10;
1702         char str[128];
1703
1704         /* rounded header */
1705         uiBlockSetCol(block, color);
1706                 /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1707         uiDefBut(block, ROUNDBOX, 0, "", x-10, y-4, width, 25, NULL, 7.0, 0.0, 
1708                          (!isVirtual && (md->mode&eModifierMode_Expanded))?3:15, 20, ""); 
1709         uiBlockSetCol(block, TH_AUTO);
1710         
1711         /* open/close icon */
1712         if (!isVirtual) {
1713                 uiBlockSetEmboss(block, UI_EMBOSSN);
1714                 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");
1715         }
1716
1717         uiBlockSetEmboss(block, UI_EMBOSS);
1718         
1719         if (isVirtual) {
1720                 sprintf(str, "%s parent deform", md->name);
1721                 uiDefBut(block, LABEL, 0, str, x+10, y-1, width-110, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name"); 
1722
1723                 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");
1724                 uiButSetFunc(but, modifiers_convertToReal, ob, md);
1725         } else {
1726                 uiBlockBeginAlign(block);
1727                 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"); 
1728
1729                 /* Softbody not allowed in this situation, enforce! */
1730                 if ((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) {
1731                         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");
1732                         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");
1733                         if (mti->flags&eModifierTypeFlag_SupportsEditmode) {
1734                                 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)");
1735                         }
1736                 }
1737                 uiBlockEndAlign(block);
1738
1739                 uiBlockSetEmboss(block, UI_EMBOSSR);
1740
1741                 if (ob->type==OB_MESH && modifier_couldBeCage(md) && index<=lastCageIndex) {
1742                         int icon, color;
1743
1744                         if (index==cageIndex) {
1745                                 color = TH_BUT_SETTING;
1746                                 icon = VICON_EDITMODE_HLT;
1747                         } else if (index<cageIndex) {
1748                                 color = TH_BUT_NEUTRAL;
1749                                 icon = VICON_EDITMODE_DEHLT;
1750                         } else {
1751                                 color = TH_BUT_NEUTRAL;
1752                                 icon = ICON_BLANK1;
1753                         }
1754                         uiBlockSetCol(block, color);
1755                         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");
1756                         uiButSetFunc(but, modifiers_setOnCage, ob, md);
1757                         uiBlockSetCol(block, TH_AUTO);
1758                 }
1759
1760                 uiBlockSetCol(block, TH_BUT_ACTION);
1761
1762                 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");
1763                 uiButSetFunc(but, modifiers_moveUp, ob, md);
1764
1765                 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");
1766                 uiButSetFunc(but, modifiers_moveDown, ob, md);
1767                 
1768                 uiBlockSetEmboss(block, UI_EMBOSSN);
1769                 
1770                 // deletion over the deflection panel
1771                 // fluid particle modifier can't be deleted here
1772                 if(md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Collision && !modifier_is_fluid_particles(md))
1773                 {
1774                         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");
1775                         uiButSetFunc(but, modifiers_del, ob, md);
1776                 }
1777                 uiBlockSetCol(block, TH_AUTO);
1778         }
1779
1780         uiBlockSetEmboss(block, UI_EMBOSS);
1781
1782         if (isVirtual || !(md->mode&eModifierMode_Expanded)) {
1783                 y -= 18;
1784         } else {
1785                 int cy = y - 8;
1786                 int lx = x + width - 60 - 15;
1787
1788                 if (md->type==eModifierType_Subsurf) {
1789                         height = 105;
1790                 } else if (md->type==eModifierType_Lattice) {
1791                         height = 48;
1792                 } else if (md->type==eModifierType_Curve) {
1793                         height = 72;
1794                 } else if (md->type==eModifierType_Build) {
1795                         height = 86;
1796                 } else if (md->type==eModifierType_Mirror) {
1797                         height = 105;
1798                 } else if (md->type==eModifierType_Bevel) {
1799                         BevelModifierData *bmd = (BevelModifierData*) md;
1800                         height = 105; /* height = 124; */
1801                         if ((bmd->lim_flags & BME_BEVEL_ANGLE) || ((bmd->lim_flags & BME_BEVEL_WEIGHT) && !(bmd->flags & BME_BEVEL_VERT))) height += 19;
1802                 } else if (md->type==eModifierType_EdgeSplit) {
1803                         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1804                         height = 48;
1805                         if(emd->flags & MOD_EDGESPLIT_FROMANGLE) height += 19;
1806                 } else if (md->type==eModifierType_Displace) {
1807                         DisplaceModifierData *dmd = (DisplaceModifierData *)md;
1808                         height = 124;
1809                         if(dmd->texmapping == MOD_DISP_MAP_OBJECT ||
1810                            dmd->texmapping == MOD_DISP_MAP_UV)
1811                                 height += 19;
1812                 } else if (md->type==eModifierType_UVProject) {
1813                         height = 114 + ((UVProjectModifierData *)md)->num_projectors * 19;
1814                 } else if (md->type==eModifierType_Decimate) {
1815                         height = 48;
1816                 } else if (md->type==eModifierType_Smooth) {
1817                         height = 86;
1818                 } else if (md->type==eModifierType_Cast) {
1819                         height = 143;
1820                 } else if (md->type==eModifierType_Wave) {
1821                         WaveModifierData *wmd = (WaveModifierData *)md;
1822                         height = 315;
1823                         if(wmd->texmapping == MOD_WAV_MAP_OBJECT ||
1824                            wmd->texmapping == MOD_WAV_MAP_UV)
1825                                 height += 19;
1826                         if(wmd->flag & MOD_WAVE_NORM)
1827                                 height += 19;
1828                 } else if (md->type==eModifierType_Armature) {
1829                         height = 105;
1830                 } else if (md->type==eModifierType_Hook) {
1831                         HookModifierData *hmd = (HookModifierData*) md;
1832                         height = 86;
1833                         if (editing)
1834                                 height += 20;
1835                         if(hmd->indexar==NULL)
1836                                 height += 20;
1837                 } else if (md->type==eModifierType_Softbody) {
1838                         height = 31;
1839                 } else if (md->type==eModifierType_Cloth) {
1840                         height = 31;
1841                 } else if (md->type==eModifierType_Collision) {
1842                         height = 31;
1843                 } else if (md->type==eModifierType_Fluidsim) {
1844                         height = 31;
1845                 } else if (md->type==eModifierType_Boolean) {
1846                         height = 48;
1847                 } else if (md->type==eModifierType_Array) {
1848                         height = 211;
1849                 } else if (md->type==eModifierType_MeshDeform) {
1850                         MeshDeformModifierData *mmd= (MeshDeformModifierData*)md;
1851                         height = (mmd->bindcos)? 73: 93;
1852                 } else if (md->type==eModifierType_ParticleSystem) {
1853                         height = 31;
1854                 } else if (md->type==eModifierType_ParticleInstance) {
1855                         height = 94;
1856                 } else if (md->type==eModifierType_Explode) {
1857                         height = 94;
1858                 } else if (md->type==eModifierType_Shrinkwrap) {
1859                         ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
1860                         height = 86 + 3;
1861                         if (smd->shrinkType == MOD_SHRINKWRAP_PROJECT)
1862                         {
1863                                 height += 19*5;
1864                                 if(smd->projAxis == 0) height += 19;
1865                         }
1866                         else if (smd->shrinkType == MOD_SHRINKWRAP_NEAREST_SURFACE)
1867                                 height += 19;
1868                 } else if (md->type == eModifierType_Mask) {
1869                         height = 66;
1870                 } else if (md->type==eModifierType_SimpleDeform) {
1871                         SimpleDeformModifierData *smd = (SimpleDeformModifierData*) md;
1872                         height += 19*5;
1873                         if(smd->origin != NULL) height += 19;
1874                         if(smd->mode == MOD_SIMPLEDEFORM_MODE_STRETCH
1875                         || smd->mode == MOD_SIMPLEDEFORM_MODE_TAPER  )
1876                                 height += 19;
1877                 }
1878                                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1879                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y-height-2, width, height-2, NULL, 5.0, 0.0, 12, 40, ""); 
1880
1881                 y -= 18;
1882
1883                 if (!isVirtual && (md->type!=eModifierType_Collision)) {
1884                         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); /* only here obdata, the rest of modifiers is ob level */
1885
1886                         uiBlockBeginAlign(block);
1887                         if (md->type==eModifierType_ParticleSystem) {
1888                                 ParticleSystem *psys;
1889                         psys= ((ParticleSystemModifierData *)md)->psys;
1890
1891                         if(!(G.f & G_PARTICLEEDIT)) {
1892                                         if(ELEM3(psys->part->draw_as, PART_DRAW_PATH, PART_DRAW_GR, PART_DRAW_OB) && psys->pathcache) {
1893                                                 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");
1894                                                 uiButSetFunc(but, modifiers_convertParticles, ob, md);
1895                                         }
1896                                 }
1897                         }
1898                         else{
1899                                 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");
1900                                 uiButSetFunc(but, modifiers_applyModifier, ob, md);
1901                         }
1902                         
1903                         if (md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (md->type!=eModifierType_Cloth)) {
1904                                 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");
1905                                 uiButSetFunc(but, modifiers_copyModifier, ob, md);
1906                         }
1907                         uiBlockEndAlign(block);
1908                         
1909                         uiSetButLock(ob && ob->id.lib, ERROR_LIBDATA_MESSAGE);
1910                 }
1911
1912                 lx = x + 10;
1913                 cy = y + 10 - 1;
1914                 uiBlockBeginAlign(block);
1915                 if (md->type==eModifierType_Subsurf) {
1916                         SubsurfModifierData *smd = (SubsurfModifierData*) md;
1917                         char subsurfmenu[]="Subsurf Type%t|Catmull-Clark%x0|Simple Subdiv.%x1";
1918                         uiDefButS(block, MENU, B_MODIFIER_RECALC, subsurfmenu,          lx,(cy-=19),buttonWidth,19, &smd->subdivType, 0, 0, 0, 0, "Selects type of subdivision algorithm.");
1919                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Levels:",             lx, (cy-=19), buttonWidth,19, &smd->levels, 1, 6, 0, 0, "Number subdivisions to perform");
1920                         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");
1921
1922                         /* Disabled until non-EM DerivedMesh implementation is complete */
1923
1924                         /*
1925                         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");
1926                         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");
1927                         */
1928
1929                         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");
1930                         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");
1931                 } else if (md->type==eModifierType_Lattice) {
1932                         LatticeModifierData *lmd = (LatticeModifierData*) md;
1933                         uiDefIDPoinBut(block, modifier_testLatticeObj, ID_OB, B_CHANGEDEP, "Ob: ",      lx, (cy-=19), buttonWidth,19, &lmd->object, "Lattice object to deform with");
1934                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &lmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1935                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1936                 } else if (md->type==eModifierType_Curve) {
1937                         CurveModifierData *cmd = (CurveModifierData*) md;
1938                         uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &cmd->object, "Curve object to deform with");
1939                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &cmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1940                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1941                         
1942                         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");
1943                         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");
1944                         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");
1945                         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");
1946                         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");
1947                         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");
1948                 } else if (md->type==eModifierType_Build) {
1949                         BuildModifierData *bmd = (BuildModifierData*) md;
1950                         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");
1951                         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");
1952                         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.");
1953                         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.");
1954                 } else if (md->type==eModifierType_Mirror) {
1955                         MirrorModifierData *mmd = (MirrorModifierData*) md;
1956                         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");
1957                         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");
1958                         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");
1959                         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");
1960                         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");
1961                         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)");
1962                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_U, B_MODIFIER_RECALC,
1963                                      "Mirror U",
1964                                      lx, (cy-=19), buttonWidth/2, 19,
1965                                      &mmd->flag, 0, 0, 0, 0,
1966                                      "Mirror the U texture coordinate around "
1967                                      "the 0.5 point");
1968                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_V, B_MODIFIER_RECALC,
1969                                      "Mirror V",
1970                                      lx + buttonWidth/2 + 1, cy, buttonWidth/2, 19,
1971                                      &mmd->flag, 0, 0, 0, 0,
1972                                      "Mirror the V texture coordinate around "
1973                                      "the 0.5 point");
1974                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1975                                        "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1976                                        &mmd->mirror_ob,
1977                                        "Object to use as mirror");
1978                 } else if (md->type==eModifierType_Bevel) {
1979                         BevelModifierData *bmd = (BevelModifierData*) md;
1980                         /*uiDefButS(block, ROW, B_MODIFIER_RECALC, "Distance",
1981                                           lx, (cy -= 19), (buttonWidth/2), 19, &bmd->val_flags,
1982                                           11.0, 0, 0, 0,
1983                                           "Interpret bevel value as a constant distance from each edge");
1984                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "Radius",
1985                                           (lx+buttonWidth/2), cy, (buttonWidth - buttonWidth/2), 19, &bmd->val_flags,
1986                                           11.0, BME_BEVEL_RADIUS, 0, 0,
1987                                           "Interpret bevel value as a radius - smaller angles will be beveled more");*/
1988                         uiBlockBeginAlign(block);
1989                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Width: ",
1990                                           lx, (cy -= 19), buttonWidth, 19, &bmd->value,
1991                                           0.0, 0.5, 5, 4,
1992                                           "Bevel value/amount");
1993                         /*uiDefButI(block, NUM, B_MODIFIER_RECALC, "Recurs",
1994                                           lx, (cy -= 19), buttonWidth, 19, &bmd->res,
1995                                           1, 4, 5, 2,
1996                                           "Number of times to bevel");*/
1997                         uiDefButBitS(block, TOG, BME_BEVEL_VERT,
1998                                           B_MODIFIER_RECALC, "Only Vertices",
1999                                           lx, (cy -= 19), buttonWidth, 19,
2000                                           &bmd->flags, 0, 0, 0, 0,
2001                                           "Bevel only verts/corners; not edges");
2002                         uiBlockEndAlign(block);
2003                                           
2004                         uiDefBut(block, LABEL, 1, "Limit using:",       lx, (cy-=25), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2005                         uiBlockBeginAlign(block);
2006                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "None",
2007                                           lx, (cy -= 19), (buttonWidth/3), 19, &bmd->lim_flags,
2008                                           12.0, 0, 0, 0,
2009                                           "Bevel the entire mesh by a constant amount");
2010                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "Angle",
2011                                           (lx+buttonWidth/3), cy, (buttonWidth/3), 19, &bmd->lim_flags,
2012                                           12.0, BME_BEVEL_ANGLE, 0, 0,
2013                                           "Only bevel edges with sharp enough angles between faces");
2014                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "BevWeight",
2015                                           lx+(2*buttonWidth/3), cy, buttonWidth-2*(buttonWidth/3), 19, &bmd->lim_flags,
2016                                           12.0, BME_BEVEL_WEIGHT, 0, 0,
2017                                           "Use bevel weights to determine how much bevel is applied; apply them separately in vert/edge select mode");
2018                         if ((bmd->lim_flags & BME_BEVEL_WEIGHT) && !(bmd->flags & BME_BEVEL_VERT)) {
2019                                 uiDefButS(block, ROW, B_MODIFIER_RECALC, "Min",
2020                                           lx, (cy -= 19), (buttonWidth/3), 19, &bmd->e_flags,
2021                                           13.0, BME_BEVEL_EMIN, 0, 0,
2022                                           "The sharpest edge's weight is used when weighting a vert");
2023                                 uiDefButS(block, ROW, B_MODIFIER_RECALC, "Average",
2024                                           (lx+buttonWidth/3), cy, (buttonWidth/3), 19, &bmd->e_flags,
2025                                           13.0, 0, 0, 0,
2026                                           "The edge weights are averaged when weighting a vert");
2027                                 uiDefButS(block, ROW, B_MODIFIER_RECALC, "Max",
2028                                           (lx+2*(buttonWidth/3)), cy, buttonWidth-2*(buttonWidth/3), 19, &bmd->e_flags,
2029                                           13.0, BME_BEVEL_EMAX, 0, 0,
2030                                           "The largest edge's wieght is used when weighting a vert");
2031                         }
2032                         else if (bmd->lim_flags & BME_BEVEL_ANGLE) {
2033                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Angle:",
2034                                           lx, (cy -= 19), buttonWidth, 19, &bmd->bevel_angle,
2035                                           0.0, 180.0, 100, 2,
2036                                           "Angle above which to bevel edges");
2037                         }
2038                 } else if (md->type==eModifierType_EdgeSplit) {
2039                         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
2040                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMANGLE,
2041                                      B_MODIFIER_RECALC, "From Edge Angle",
2042                                      lx, (cy -= 19), buttonWidth, 19,
2043                                      &emd->flags, 0, 0, 0, 0,
2044                                      "Split edges with high angle between faces");
2045                         if(emd->flags & MOD_EDGESPLIT_FROMANGLE) {
2046                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Split Angle:",
2047                                           lx, (cy -= 19), buttonWidth, 19, &emd->split_angle,
2048                                           0.0, 180.0, 100, 2,
2049                                           "Angle above which to split edges");
2050                         }
2051                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMFLAG,
2052                                      B_MODIFIER_RECALC, "From Marked As Sharp",
2053                                      lx, (cy -= 19), buttonWidth, 19,
2054                                      &emd->flags, 0, 0, 0, 0,
2055                                      "Split edges that are marked as sharp");
2056                 } else if (md->type==eModifierType_Displace) {
2057                         DisplaceModifierData *dmd = (DisplaceModifierData*) md;
2058                         but = uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",
2059                                        lx, (cy -= 19), buttonWidth, 19,
2060                                        &dmd->defgrp_name, 0.0, 31.0, 0, 0,
2061                                        "Name of vertex group to displace"
2062                                        " (displace whole mesh if blank)");
2063                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2064                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,
2065                                        "Texture: ", lx, (cy -= 19), buttonWidth, 19,
2066                                        &dmd->texture,
2067                                        "Texture to use as displacement input");
2068                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Midlevel:",
2069                                   lx, (cy -= 19), buttonWidth, 19, &dmd->midlevel,
2070                                   0, 1, 10, 3,
2071                                   "Material value that gives no displacement");
2072                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Strength:",
2073                                   lx, (cy -= 19), buttonWidth, 19, &dmd->strength,
2074                                   -1000, 1000, 10, 0.1,
2075                                   "Strength of displacement");
2076                         sprintf(str, "Direction%%t|Normal%%x%d|RGB -> XYZ%%x%d|"
2077                                 "Z%%x%d|Y%%x%d|X%%x%d",
2078                                 MOD_DISP_DIR_NOR, MOD_DISP_DIR_RGB_XYZ,
2079                                 MOD_DISP_DIR_Z, MOD_DISP_DIR_Y, MOD_DISP_DIR_X);
2080                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2081                                   lx, (cy -= 19), buttonWidth, 19, &dmd->direction,
2082                                   0.0, 1.0, 0, 0, "Displace direction");
2083                         sprintf(str, "Texture Coordinates%%t"
2084                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
2085                                 MOD_DISP_MAP_LOCAL, MOD_DISP_MAP_GLOBAL,
2086                                 MOD_DISP_MAP_OBJECT, MOD_DISP_MAP_UV);
2087                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2088                                   lx, (cy -= 19), buttonWidth, 19, &dmd->texmapping,
2089                                   0.0, 1.0, 0, 0,
2090                                   "Texture coordinates used for displacement input");
2091                         if (dmd->texmapping == MOD_DISP_MAP_UV) {
2092                                 char *strtmp;
2093                                 int i;
2094                                 CustomData *fdata = G.obedit ? &G.editMesh->fdata
2095                                                              : &((Mesh*)ob->data)->fdata;
2096                                 build_uvlayer_menu_vars(fdata, &strtmp, &dmd->uvlayer_tmp,
2097                                                         dmd->uvlayer_name);
2098                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
2099                                       lx, (cy -= 19), buttonWidth, 19, &dmd->uvlayer_tmp,
2100                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
2101                                 MEM_freeN(strtmp);
2102                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
2103                                 uiButSetFunc(but, set_displace_uvlayer, dmd,
2104                                              &fdata->layers[i]);
2105                         }
2106                         if(dmd->texmapping == MOD_DISP_MAP_OBJECT) {
2107                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2108                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
2109                                                &dmd->map_object,
2110                                                "Object to get texture coordinates from");
2111                         }
2112                 } else if (md->type==eModifierType_UVProject) {
2113                         UVProjectModifierData *umd = (UVProjectModifierData *) md;
2114                         int i;
2115                         char *strtmp;
2116                         CustomData *fdata = G.obedit ? &G.editMesh->fdata
2117                                                      : &((Mesh*)ob->data)->fdata;
2118                         build_uvlayer_menu_vars(fdata, &strtmp, &umd->uvlayer_tmp,
2119                                                 umd->uvlayer_name);
2120                         but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
2121                               lx, (cy -= 19), buttonWidth, 19, &umd->uvlayer_tmp,
2122                               0.0, 1.0, 0, 0, "Set the UV layer to use");
2123                         i = CustomData_get_layer_index(fdata, CD_MTFACE);
2124                         uiButSetFunc(but, set_uvproject_uvlayer, umd, &fdata->layers[i]);
2125                         MEM_freeN(strtmp);
2126                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspX:",
2127                                   lx, (cy -= 19), buttonWidth / 2, 19, &umd->aspectx,
2128                                   1, 1000, 100, 2,
2129                                   "Horizontal Aspect Ratio");
2130                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspY:",
2131                                   lx + (buttonWidth / 2) + 1, cy, buttonWidth / 2, 19,
2132                                   &umd->aspecty,
2133                                   1, 1000, 100, 2,
2134                                   "Vertical Aspect Ratio");
2135                         uiDefButI(block, NUM, B_MODIFIER_RECALC, "Projectors:",
2136                                   lx, (cy -= 19), buttonWidth, 19, &umd->num_projectors,
2137                                   1, MOD_UVPROJECT_MAXPROJECTORS, 0, 0,
2138                                   "Number of objects to use as projectors");
2139                         for(i = 0; i < umd->num_projectors; ++i) {
2140                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2141                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
2142                                                &umd->projectors[i],
2143                                                "Object to use as projector");
2144                         }
2145                         uiDefIDPoinBut(block, modifier_testImage, ID_IM, B_CHANGEDEP,
2146                                        "Image: ", lx, (cy -= 19), buttonWidth, 19,
2147                                        &umd->image,
2148                                        "Image to project (only faces with this image "
2149                                        "will be altered");
2150                         uiButSetCompleteFunc(but, autocomplete_image, (void *)ob);
2151                         uiDefButBitI(block, TOG, MOD_UVPROJECT_OVERRIDEIMAGE,
2152                                      B_MODIFIER_RECALC, "Override Image",
2153                                      lx, (cy -= 19), buttonWidth, 19,
2154                                      &umd->flags, 0, 0, 0, 0,
2155                                      "Override faces' current images with the "
2156                                      "given image");
2157                 } else if (md->type==eModifierType_Decimate) {
2158                         DecimateModifierData *dmd = (DecimateModifierData*) md;
2159                         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");
2160                         sprintf(str, "Face Count: %d", dmd->faceCount);
2161                         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");
2162                 } else if (md->type==eModifierType_Mask) {
2163                         MaskModifierData *mmd = (MaskModifierData *)md;
2164                         
2165                         sprintf(str, "Mask Mode%%t|Vertex Group%%x%d|Selected Bones%%x%d|",
2166                                 MOD_MASK_MODE_VGROUP,MOD_MASK_MODE_ARM);
2167                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2168                                 lx, (cy -= 19), buttonWidth, 19, &mmd->mode,
2169                                 0.0, 1.0, 0, 0, "How masking region is defined");
2170                                           
2171                         if (mmd->mode == MOD_MASK_MODE_ARM) {
2172                                 uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP,
2173                                     "Ob: ", lx, (cy -= 19), buttonWidth, 19, &mmd->ob_arm,
2174                                     "Armature to use as source of bones to mask");
2175                         }
2176                         else {
2177                                 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", 
2178                                         lx, (cy-=19), buttonWidth, 19, &mmd->vgroup, 
2179                                         0.0, 31.0, 0, 0, "Vertex Group name");
2180                                 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2181                         }
2182                         
2183                         uiDefButBitI(block, TOG, MOD_MASK_INV, B_MODIFIER_RECALC, "Inverse",            
2184                                 lx, (cy-=19), buttonWidth, 19, &mmd->flag, 
2185                                 0, 0, 0, 0, "Use vertices that are not part of region defined");
2186                 } else if (md->type==eModifierType_Smooth) {
2187                         SmoothModifierData *smd = (SmoothModifierData*) md;
2188
2189                         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");
2190                         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");
2191                         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");
2192
2193                         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)");
2194                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Repeat:",     lx,(cy-=19),buttonWidth, 19, &smd->repeat, 0.0, 30.0, 1, 0, "Number of smoothing iterations");
2195                         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");
2196                 } else if (md->type==eModifierType_Cast) {
2197                         CastModifierData *cmd = (CastModifierData*) md;
2198
2199                         char casttypemenu[]="Projection Type%t|Sphere%x0|Cylinder%x1|Cuboid%x2";
2200                         uiDefButS(block, MENU, B_MODIFIER_RECALC, casttypemenu,         lx,(cy-=19),buttonWidth - 30,19, &cmd->type, 0, 0, 0, 0, "Projection type to apply");
2201                         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");
2202                         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");
2203                         if (cmd->type != MOD_CAST_TYPE_CYLINDER) {
2204                                 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");
2205                         }
2206                         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");
2207                         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)");
2208                         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)");
2209                         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)");
2210                         if (ob->type == OB_MESH) {
2211                                 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");
2212                         }
2213                         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");
2214                         if(cmd->object) {
2215                                 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");
2216                         }
2217                 } else if (md->type==eModifierType_Wave) {
2218                         WaveModifierData *wmd = (WaveModifierData*) md;
2219                         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");
2220                         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");
2221                         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");
2222                         uiDefButBitS(block, TOG, MOD_WAVE_NORM, B_MODIFIER_RECALC, "Normals",   lx,(cy-=19),buttonWidth,19, &wmd->flag, 0, 0, 0, 0, "Displace along normals");
2223                         if (wmd->flag & MOD_WAVE_NORM){
2224                                 if (ob->type==OB_MESH) {
2225                                         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");
2226                                         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");
2227                                         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");
2228                                 }
2229                                 else
2230                                         uiDefBut(block, LABEL, 1, "Meshes Only",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");                                
2231                         }
2232
2233                         uiBlockBeginAlign(block);
2234                         if(wmd->speed >= 0)
2235                                 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");
2236                         else
2237                                 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");
2238                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Lifetime:",   lx,(cy-=19),buttonWidth,19, &wmd->lifetime,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the lifespan of the wave");
2239                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Damptime:",   lx,(cy-=19),buttonWidth,19, &wmd->damp,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the dampingtime of the wave");
2240                         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");
2241
2242                         cy -= 9;
2243                         uiBlockBeginAlign(block);
2244                         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");
2245                         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");
2246                         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)");
2247                         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");
2248                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,"Texture: ", lx, (cy -= 19), 220, 19, &wmd->texture,"Texture with which to modulate wave");
2249                         sprintf(str, "Texture Coordinates%%t"
2250                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
2251                                 MOD_WAV_MAP_LOCAL, MOD_WAV_MAP_GLOBAL,
2252                                 MOD_WAV_MAP_OBJECT, MOD_WAV_MAP_UV);
2253                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2254                                   lx, (cy -= 19), 220, 19, &wmd->texmapping,
2255                                   0.0, 1.0, 0, 0,
2256                                   "Texture coordinates used for modulation input");
2257                         if (wmd->texmapping == MOD_WAV_MAP_UV) {
2258                                 char *strtmp;
2259                                 int i;
2260                                 CustomData *fdata = G.obedit ? &G.editMesh->fdata
2261                                                              : &((Mesh*)ob->data)->fdata;
2262                                 build_uvlayer_menu_vars(fdata, &strtmp, &wmd->uvlayer_tmp,
2263                                                         wmd->uvlayer_name);
2264                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
2265                                       lx, (cy -= 19), 220, 19, &wmd->uvlayer_tmp,
2266                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
2267                                 MEM_freeN(strtmp);
2268                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
2269                                 uiButSetFunc(but, set_wave_uvlayer, wmd,
2270                                              &fdata->layers[i]);
2271                         }
2272                         if(wmd->texmapping == MOD_DISP_MAP_OBJECT) {
2273                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2274                                                "Ob: ", lx, (cy -= 19), 220, 19,
2275                                                &wmd->map_object,
2276                                                "Object to get texture coordinates from");
2277                         }
2278                         cy -= 9;
2279                         uiBlockBeginAlign(block);
2280                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Speed:",   lx,(cy-=19),220,19, &wmd->speed, -2.0, 2.0, 0, 0, "Specify the wave speed");
2281                         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");
2282                         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");
2283                         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");
2284                 } else if (md->type==eModifierType_Armature) {
2285                         ArmatureModifierData *amd = (ArmatureModifierData*) md;
2286                         uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &amd->object, "Armature object to deform with");
2287                         
2288                         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");
2289                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2290                         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");
2291                         
2292                         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");
2293                         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");
2294                         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");
2295                         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");
2296                         
2297                         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");
2298
2299                 } else if (md->type==eModifierType_Hook) {
2300                         HookModifierData *hmd = (HookModifierData*) md;
2301                         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");
2302                         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");
2303                         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"); 
2304                         if(hmd->indexar==NULL) {
2305                                 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &hmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
2306                                 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2307                         }
2308                         uiBlockBeginAlign(block);
2309                         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");
2310                         uiButSetFunc(but, modifiers_clearHookOffset, ob, md);
2311                         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");
2312                         uiButSetFunc(but, modifiers_cursorHookCenter, ob, md);
2313
2314                         if (editing) {
2315                                 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");
2316                                 uiButSetFunc(but, modifiers_selectHook, ob, md);
2317                                 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");
2318                                 uiButSetFunc(but, modifiers_reassignHook, ob, md);
2319                         }
2320                 } else if (md->type==eModifierType_Softbody) {
2321                         uiDefBut(block, LABEL, 1, "See Soft Body panel.",       lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2322                 } else if (md->type==eModifierType_Cloth) {
2323                         uiDefBut(block, LABEL, 1, "See Cloth panel.",   lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2324
2325                 } else if (md->type==eModifierType_Collision) {
2326                         uiDefBut(block, LABEL, 1, "See Collision panel.",       lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2327                 } else if (md->type==eModifierType_Fluidsim) {
2328                         uiDefBut(block, LABEL, 1, "See Fluidsim panel.",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2329                 } else if (md->type==eModifierType_Boolean) {
2330                         BooleanModifierData *bmd = (BooleanModifierData*) md;
2331                         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");
2332                         uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &bmd->object, "Mesh object to use for boolean operation");
2333                 } else if (md->type==eModifierType_Array) {
2334                         ArrayModifierData *amd = (ArrayModifierData*) md;
2335                         float range = 10000;
2336                         int cytop, halfwidth = (width - 5)/2 - 15;
2337                         int halflx = lx + halfwidth + 10;
2338
2339                         uiBlockSetEmboss(block, UI_EMBOSSX);
2340                         uiBlockEndAlign(block);
2341
2342                         /* length parameters */
2343                         uiBlockBeginAlign(block);
2344                         sprintf(str, "Length Fit%%t|Fixed Count%%x%d|Fixed Length%%x%d"
2345                                 "|Fit To Curve Length%%x%d",
2346                                 MOD_ARR_FIXEDCOUNT, MOD_ARR_FITLENGTH, MOD_ARR_FITCURVE);
2347                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2348                                   lx, (cy-=19), buttonWidth, 19, &amd->fit_type,
2349                                   0.0, 1.0, 0, 0, "Array length calculation method");
2350                         switch(amd->fit_type)
2351                         {
2352                         case MOD_ARR_FIXEDCOUNT:
2353                                 uiDefButI(block, NUM, B_MODIFIER_RECALC, "Count:",
2354                                           lx, (cy -= 19), buttonWidth, 19, &amd->count,
2355                                           1, 1000, 0, 0, "Number of duplicates to make");
2356                                 break;
2357                         case MOD_ARR_FITLENGTH:
2358                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Length:",
2359                                           lx, (cy -= 19), buttonWidth, 19, &amd->length,
2360                                           0, range, 10, 2,
2361                                           "Length to fit array within");
2362                                 break;
2363                         case MOD_ARR_FITCURVE:
2364                                 uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB,
2365                                                B_CHANGEDEP, "Ob: ",
2366                                                lx, (cy -= 19), buttonWidth, 19, &amd->curve_ob,
2367                                                "Curve object to fit array length to");
2368                                 break;
2369                         }
2370                         uiBlockEndAlign(block);
2371
2372                         /* offset parameters */
2373                         cy -= 10;
2374                         cytop= cy;
2375                         uiBlockBeginAlign(block);
2376                         uiDefButBitI(block, TOG, MOD_ARR_OFF_CONST, B_MODIFIER_RECALC,
2377                                      "Constant Offset", lx, (cy-=19), halfwidth, 19,
2378                                      &amd->offset_type, 0, 0, 0, 0,
2379                                      "Constant offset between duplicates "
2380                                      "(local coordinates)");
2381                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2382                                   lx, (cy-=19), halfwidth, 19,
2383                                   &amd->offset[0],
2384                                   -range, range, 10, 3,
2385                                   "Constant component for duplicate offsets "
2386                                   "(local coordinates)");
2387                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2388                                   lx, (cy-=19), halfwidth, 19,
2389                                   &amd->offset[1],
2390                                   -range, range, 10, 3,
2391                                   "Constant component for duplicate offsets "
2392                                   "(local coordinates)");
2393                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2394                                   lx, (cy-=19), halfwidth, 19,
2395                                   &amd->offset[2],
2396                                   -range, range, 10, 3,
2397                                   "Constant component for duplicate offsets "
2398                                   "(local coordinates)");
2399                         uiBlockEndAlign(block);
2400
2401                         cy= cytop;
2402                         uiBlockBeginAlign(block);
2403                         uiDefButBitI(block, TOG, MOD_ARR_OFF_RELATIVE, B_MODIFIER_RECALC,
2404                                      "Relative Offset", halflx, (cy-=19), halfwidth, 19,
2405                                      &amd->offset_type, 0, 0, 0, 0,
2406                                      "Offset between duplicates relative to object width "
2407                                      "(local coordinates)");
2408                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2409                                   halflx, (cy-=19), halfwidth, 19,
2410                                   &amd->scale[0],
2411                                   -range, range, 10, 3,
2412                                   "Component for duplicate offsets relative to object "
2413                                   "width (local coordinates)");
2414                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2415                                   halflx, (cy-=19), halfwidth, 19,
2416                                   &amd->scale[1],
2417                                   -range, range, 10, 3,
2418                                   "Component for duplicate offsets relative to object "
2419                                   "width (local coordinates)");
2420                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2421                                   halflx, (cy-=19), halfwidth, 19,
2422                                   &amd->scale[2],
2423                                   -range, range, 10, 3,
2424                                   "Component for duplicate offsets relative to object "
2425                                   "width (local coordinates)");
2426                         uiBlockEndAlign(block);
2427
2428                         /* vertex merging parameters */
2429                         cy -= 10;
2430                         cytop= cy;
2431
2432                         uiBlockBeginAlign(block);
2433                         uiDefButBitI(block, TOG, MOD_ARR_MERGE, B_MODIFIER_RECALC,
2434                                      "Merge",
2435                                      lx, (cy-=19), halfwidth/2, 19, &amd->flags,
2436                                      0, 0, 0, 0,
2437                                      "Merge vertices in adjacent duplicates");
2438                         uiDefButBitI(block, TOG, MOD_ARR_MERGEFINAL, B_MODIFIER_RECALC,
2439                                      "First Last",
2440                                      lx + halfwidth/2, cy, (halfwidth+1)/2, 19,
2441                                      &amd->flags,
2442                                      0, 0, 0, 0,
2443                                      "Merge vertices in first duplicate with vertices"
2444                                      " in last duplicate");
2445                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Limit:",
2446                                           lx, (cy-=19), halfwidth, 19, &amd->merge_dist,
2447                                           0, 1.0f, 1, 4,
2448                                           "Limit below which to merge vertices");
2449
2450                         /* offset ob */
2451                         cy = cytop;
2452                         uiBlockBeginAlign(block);
2453                         uiDefButBitI(block, TOG, MOD_ARR_OFF_OBJ, B_MODIFIER_RECALC,
2454                                      "Object Offset", halflx, (cy -= 19), halfwidth, 19,
2455                                      &amd->offset_type, 0, 0, 0, 0,
2456                                      "Add an object transformation to the total offset");
2457                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2458                                        "Ob: ", halflx, (cy -= 19), halfwidth, 19,
2459                                        &amd->offset_ob,
2460                                        "Object from which to take offset transformation");
2461                         uiBlockEndAlign(block);
2462
2463                         cy -= 10;
2464                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2465                                              B_CHANGEDEP, "Start cap: ",
2466                                              lx, (cy -= 19), halfwidth, 19,
2467                                              &amd->start_cap,
2468                                              "Mesh object to use as start cap");
2469                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2470                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2471                                              B_CHANGEDEP, "End cap: ",
2472                                              halflx, cy, halfwidth, 19,
2473                                              &amd->end_cap,
2474                                              "Mesh object to use as end cap");
2475                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2476                 } else if (md->type==eModifierType_MeshDeform) {
2477                         MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
2478
2479                         uiBlockBeginAlign(block);
2480                         uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &mmd->object, "Mesh object to be use as cage"); 
2481                         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");
2482                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2483                         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");
2484
2485                         uiBlockBeginAlign(block);
2486                         if(mmd->bindcos) {
2487                                 but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Unbind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Unbind mesh from cage");
2488                                 uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
2489                         }
2490                         else {
2491                                 but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Bind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Bind mesh to cage");
2492                                 uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
2493                                 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");
2494                                 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!)");
2495                         }
2496                         uiBlockEndAlign(block);
2497                 } else if (md->type==eModifierType_ParticleSystem) {
2498                         uiDefBut(block, LABEL, 1, "See Particle buttons.",      lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2499                 } else if (md->type==eModifierType_ParticleInstance) {
2500                         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
2501                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy -= 19), buttonWidth, 19, &pimd->ob, "Object that has the particlesystem");
2502                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "PSYS:", lx, (cy -= 19), buttonWidth, 19, &pimd->psys, 1, 10, 10, 3, "Particlesystem number in the object");
2503                         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");
2504                         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");
2505                         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");
2506                         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");
2507                         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");
2508                         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");
2509                 } else if (md->type==eModifierType_Explode) {
2510                         ExplodeModifierData *emd = (ExplodeModifierData*) md;
2511                         uiBut *but;
2512                         char *menustr= get_vertexgroup_menustr(ob);
2513                         int defCount=BLI_countlist(&ob->defbase);
2514                         if(defCount==0) emd->vgroup=0;
2515                         uiBlockBeginAlign(block);
2516                         but=uiDefButS(block, MENU, B_MODIFIER_RECALC, menustr,  lx, (cy-=19), buttonWidth-20,19, &emd->vgroup, 0, defCount, 0, 0, "Protect this vertex group");
2517                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2518                         MEM_freeN(menustr);
2519                         
2520                         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");
2521                         uiButSetFunc(but, modifiers_explodeDelVg, (void *)emd, (void *)NULL);
2522                         
2523
2524                         but=uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "",     lx, (cy-=19), buttonWidth,19, &emd->protect, 0.0f, 1.0f, 0, 0, "Clean vertex group edges");
2525                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2526
2527                         but=uiDefBut(block, BUT, B_MODIFIER_RECALC, "Refresh",  lx, (cy-=19), buttonWidth/2,19, 0, 0, 0, 0, 0, "Recalculate faces assigned to particles");
2528                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2529
2530                         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");
2531                         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");
2532                         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");
2533                         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");
2534                         uiBlockEndAlign(block);
2535                 } else if (md->type==eModifierType_Shrinkwrap) {
2536                         ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
2537
2538                         char shrinktypemenu[]="Shrinkwrap type%t|nearest surface point %x0|projection %x1|nearest vertex %x2";
2539
2540                         uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &smd->target, "Target to shrink to");
2541
2542                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &smd->vgroup_name, 0, 31, 0, 0, "Vertex Group name");
2543                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2544
2545                         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");
2546
2547                         cy -= 3;
2548                         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.");
2549
2550                         if (smd->shrinkType == MOD_SHRINKWRAP_PROJECT){
2551
2552
2553                                 /* UI for projection axis */
2554                                 uiBlockBeginAlign(block);
2555                                 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");
2556                                 if(smd->projAxis == 0)
2557                                 {
2558                                         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");
2559                                 }
2560
2561                                 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");
2562                                 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");
2563                                 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");
2564
2565
2566                                 /* allowed directions of projection axis */
2567                                 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");
2568                                 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");
2569
2570                                 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");
2571                                 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");
2572                                 uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob2: ",        lx, (cy-=19), buttonWidth,19, &smd->auxTarget, "Aditional mesh to project over");
2573                         }
2574                         else if (smd->shrinkType == MOD_SHRINKWRAP_NEAREST_SURFACE){
2575                                 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");
2576                         }
2577
2578                         uiBlockEndAlign(block);
2579
2580                 } else if (md->type==eModifierType_SimpleDeform) {
2581                         SimpleDeformModifierData *smd = (SimpleDeformModifierData*) md;
2582                         char simpledeform_modemenu[] = "Deform type%t|Twist %x1|Bend %x2|Taper %x3|Strech %x4";
2583
2584                         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.");
2585                         
2586                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &smd->vgroup_name, 0, 31, 0, 0, "Vertex Group name");
2587                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2588
2589                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ",      lx, (cy-=19), buttonWidth,19, &smd->origin, "Origin of modifier space coordinates");
2590                         if(smd->origin != NULL)
2591                                 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");
2592
2593                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Factor:",     lx,(cy-=19),buttonWidth,19, &smd->factor, -10.0f, 10.0f, 0.5f, 0, "Deform Factor");
2594
2595                         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");
2596                         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");
2597
2598                         if(smd->mode == MOD_SIMPLEDEFORM_MODE_STRETCH
2599                         || smd->mode == MOD_SIMPLEDEFORM_MODE_TAPER  )
2600                         {
2601                                 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");
2602                                 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");
2603                         }
2604                 }
2605
2606                 uiBlockEndAlign(block);
2607
2608                 y-=height;
2609         }
2610
2611         if (md->error) {
2612                 y -= 6;
2613
2614                 uiBlockSetCol(block, color);
2615                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
2616                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y, width, 20, NULL, 5.0, 0.0, 15, 40, ""); 
2617                 uiBlockSetCol(block, TH_AUTO);
2618
2619                 uiDefIconBut(block,LABEL,B_NOP,ICON_ERROR, x-9, y,19,19, 0,0,0,0,0, "");
2620                 uiDefBut(block, LABEL, B_NOP, md->error, x+5, y, width-15, 19, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
2621
2622                 y -= 18;
2623         }
2624
2625         uiClearButLock();
2626
2627         y -= 3+6;
2628
2629         *xco = x;
2630         *yco = y;
2631 }
2632
2633 static void editing_panel_modifiers(Object *ob)
2634 {
2635         ModifierData *md;
2636         uiBlock *block;
2637         char str[64];
2638         int xco, yco, i, lastCageIndex, cageIndex = modifiers_getCageIndex(ob, &lastCageIndex);
2639
2640         block= uiNewBlock(&curarea->uiblocks, "editing_panel_modifiers", UI_EMBOSS, UI_HELV, curarea->win);
2641         if( uiNewPanel(curarea, block, "Modifiers", "Editing", 640, 0, 318, 204)==0) return;
2642         
2643         uiSetButLock((ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
2644         uiNewPanelHeight(block, 204);
2645
2646         uiDefBlockBut(block, modifiers_add_menu, ob, "Add Modifier", 0, 190, 130, 20, "Add a new modifier");
2647
2648         sprintf(str, "To: %s", ob->id.name+2);
2649         uiDefBut(block, LABEL, 1, str,  140, 190, 160, 20, NULL, 0.0, 0.0, 0, 0, "Object whose modifier stack is being edited");
2650
2651         xco = 0;
2652         yco = 160;
2653
2654         md = modifiers_getVirtualModifierList(ob);
2655
2656         for (i=0; md; i++, md=md->next) {
2657                 draw_modifier(block, ob, md, &xco, &yco, i, cageIndex, lastCageIndex);
2658                 if (md->mode&eModifierMode_Virtual) i--;
2659         }
2660         
2661         if(yco < 0) uiNewPanelHeight(block, 204-yco);
2662 }
2663
2664 static char *make_key_menu(Key *key, int startindex)
2665 {
2666         KeyBlock *kb;
2667         int index= 1;
2668         char *str, item[64];
2669
2670         for (kb = key->block.first; kb; kb=kb->next, index++);
2671         str= MEM_mallocN(index*40, "key string");
2672         str[0]= 0;
2673         
2674         index= startindex;
2675         for (kb = key->block.first; kb; kb=kb->next, index++) {
2676                 sprintf (item,  "|%s%%x%d", kb->name, index);
2677                 strcat(str, item);
2678         }
2679         
2680         return str;
2681 }
2682
2683 static void editing_panel_shapes(Object *ob)
2684 {
2685         uiBlock *block;
2686         Key *key= NULL;
2687         KeyBlock *kb;
2688         int icon;
2689         char *strp;
2690         
2691         block= uiNewBlock(&curarea->uiblocks, "editing_panel_shapes", UI_EMBOSS, UI_HELV, curarea->win);
2692         uiNewPanelTabbed("Modifiers", "Editing");
2693         if( uiNewPanel(curarea, block, "Shapes", "Editing", 640, 0, 318, 204)==0) return;
2694         
2695         /* Todo check data is library here */
2696         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2697         
2698         uiDefBut(block, BUT, B_ADDKEY, "Add Shape Key" ,        10, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "Add new Shape Key");
2699         
2700         key= ob_get_key(ob);
2701         if(key==NULL) {
2702                 /* label aligns add button */
2703                 uiDefBut(block, LABEL, 0, "",           170, 180,140,20, NULL, 0, 0, 0, 0, "");
2704                 return;
2705         }
2706         
2707         uiDefButS(block, TOG, B_RELKEY, "Relative",             170, 180,140,20, &key->type, 0, 0, 0, 0, "Makes Shape Keys relative");
2708
2709         kb= BLI_findlink(&key->block, ob->shapenr-1);
2710         if(kb==NULL) {
2711                 ob->shapenr= 1;
2712                 kb= key->block.first;
2713         }
2714
2715         uiBlockBeginAlign(block);
2716         if(ob->shapeflag & OB_SHAPE_LOCK) icon= ICON_PIN_HLT; else icon= ICON_PIN_DEHLT;
2717         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");
2718         if(kb->flag & KEYBLOCK_MUTE) icon= ICON_MUTE_IPO_ON; else icon = ICON_MUTE_IPO_OFF;
2719         uiDefIconButBitS(block, TOG, KEYBLOCK_MUTE, B_MODIFIER_RECALC, icon, 35,150,20,20, &kb->flag, 0, 0, 0, 0, "Mute the current Shape");
2720         uiSetButLock(G.obedit==ob, "Unable to perform in EditMode");
2721         uiDefIconBut(block, BUT, B_PREVKEY, ICON_TRIA_LEFT,             55,150,20,20, NULL, 0, 0, 0, 0, "Previous Shape Key");
2722         strp= make_key_menu(key, 1);
2723         uiDefButS(block, MENU, B_SETKEY, strp,                                  75,150,20,20, &ob->shapenr, 0, 0, 0, 0, "Browse existing choices");
2724         MEM_freeN(strp);
2725         
2726         uiDefIconBut(block, BUT, B_NEXTKEY, ICON_TRIA_RIGHT,    95,150,20,20, NULL, 0, 0, 0, 0, "Next Shape Key");
2727         uiClearButLock();
2728         uiDefBut(block, TEX, B_NAMEKEY, "",                                             115, 150, 170, 20, kb->name, 0.0, 31.0, 0, 0, "Current Shape Key name");
2729         uiDefIconBut(block, BUT, B_DELKEY, ICON_X,                              285,150,25,20, 0, 0, 0, 0, 0, "Deletes current Shape Key");
2730         uiBlockEndAlign(block);
2731
2732         if(key->type && (ob->shapeflag & OB_SHAPE_LOCK)==0 && ob->shapenr!=1) {
2733                 uiBlockBeginAlign(block);
2734                 make_rvk_slider(block, ob, ob->shapenr-1,                       10, 120, 150, 20, "Key value, when used it inserts an animation curve point");
2735                 uiDefButF(block, NUM, B_REDR, "Min ",                           160,120, 75, 20, &kb->slidermin, -10.0, 10.0, 100, 1, "Minumum for slider");
2736                 uiDefButF(block, NUM, B_REDR, "Max ",                           235,120, 75, 20, &kb->slidermax, -10.0, 10.0, 100, 1, "Maximum for slider");
2737                 uiBlockEndAlign(block);
2738         }
2739         if(key->type && ob->shapenr!=1) {
2740                 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");
2741
2742                 strp= make_key_menu(key, 0);
2743                 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");
2744                 MEM_freeN(strp);
2745         }
2746         
2747         if(key->type==0)
2748                 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");
2749         
2750 }
2751
2752 /* *************************** FONT ******************************** */
2753
2754 static short give_vfontnr(VFont *vfont)
2755 {
2756         VFont *vf;
2757         short nr= 1;
2758
2759         vf= G.main->vfont.first;
2760         while(vf) {
2761                 if(vf==vfont) return nr;
2762                 nr++;
2763                 vf= vf->id.next;
2764         }
2765         return -1;
2766 }
2767
2768 static VFont *give_vfontpointer(int nr) /* nr= button */
2769 {
2770         VFont *vf;
2771         short tel= 1;
2772
2773         vf= G.main->vfont.first;
2774         while(vf) {
2775                 if(tel==nr) return vf;
2776                 tel++;
2777                 vf= vf->id.next;
2778         }
2779         return G.main->vfont.first;
2780 }
2781
2782 VFont *exist_vfont(char *str)
2783 {
2784         VFont *vf;
2785
2786         vf= G.main->vfont.first;
2787         while(vf) {
2788                 if(strcmp(vf->name, str)==0) return vf;
2789                 vf= vf->id.next;
2790         }
2791         return 0;
2792 }
2793
2794 static char *give_vfontbutstr(void)
2795 {
2796         VFont *vf;
2797         int len= 0;
2798         char *str, di[FILE_MAXDIR], fi[FILE_MAXFILE];
2799
2800         vf= G.main->vfont.first;
2801         while(vf) {
2802                 strcpy(di, vf->name);
2803                 BLI_splitdirstring(di, fi);
2804                 len+= strlen(fi)+4;
2805                 vf= vf->id.next;
2806         }
2807
2808         str= MEM_callocN(len+21, "vfontbutstr");
2809         strcpy(str, "FONTS %t");
2810         vf= G.main->vfont.first;
2811         while(vf) {
2812
2813                 if(vf->id.us==0) strcat(str, "|0 ");
2814                 else strcat(str, "|   ");
2815
2816                 strcpy(di, vf->name);
2817                 BLI_splitdirstring(di, fi);
2818
2819                 strcat(str, fi);
2820                 vf= vf->id.next;
2821         }
2822         return str;
2823 }
2824
2825 static void load_buts_vfont(char *name)
2826 {
2827         VFont *vf;
2828         Curve *cu;
2829
2830         if(OBACT && OBACT->type==OB_FONT) cu= OBACT->data;
2831         else return;
2832
2833         vf= exist_vfont(name);
2834         if(vf==0) {
2835                 vf= load_vfont(name);
2836                 if(vf==0) return;
2837         }
2838         else id_us_plus((ID *)vf);
2839         
2840         switch(cu->curinfo.flag & CU_STYLE) {
2841                 case CU_BOLD:
2842                         if(cu->vfontb) cu->vfontb->id.us--;
2843                         cu->vfontb= vf;
2844                         break;
2845                 case CU_ITALIC:
2846                         if(cu->vfonti) cu->vfonti->id.us--;             
2847                         cu->vfonti= vf;
2848                         break;                                          
2849                 case (CU_BOLD|CU_ITALIC):
2850                         if(cu->vfontbi) cu->vfontbi->id.us--;
2851                         cu->vfontbi= vf;
2852                         break;
2853                 default:
2854                         if(cu->vfont) cu->vfont->id.us--;
2855                         cu->vfont= vf;
2856                         break;                                          
2857         }       
2858
2859         DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
2860         BIF_undo_push("Load vector font");
2861         allqueue(REDRAWVIEW3D, 0);
2862         allqueue(REDRAWBUTSEDIT, 0);
2863 }
2864
2865 static void set_unicode_text_fs(char *file)
2866 {
2867         if (file) paste_unicodeText(file); 
2868 }
2869
2870 void do_fontbuts(unsigned short event)
2871 {
2872         Curve *cu;
2873         VFont *vf;
2874         Object *ob;
2875         ScrArea *sa;
2876         char str[80];
2877         int ctevt;
2878         char *ctmenu;
2879         DynStr *ds;
2880         int i, style=0;
2881