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