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