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