144b266759ddeb364821b893a784a7b776eb3464
[blender-staging.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         MEdge *medge;
1258         int a, k, kmax;
1259         int totvert=0, totedge=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+= key->steps+1;
1281                 totedge+= key->steps;
1282         }
1283
1284         cache= psys->childcache;
1285         for(a=0; a<totchild; a++) {
1286                 key= cache[a];
1287                 totvert+= key->steps+1;
1288                 totedge+= key->steps;
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->totedge= totedge;
1299         
1300         me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
1301         me->medge= CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
1302         me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0);
1303         
1304         mvert= me->mvert;
1305         medge= me->medge;
1306
1307         /* copy coordinates */
1308         cache= psys->pathcache;
1309         for(a=0; a<totpart; a++) {
1310                 key= cache[a];
1311                 kmax= key->steps;
1312                 for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
1313                         VECCOPY(mvert->co,key->co);
1314                         if(k) {
1315                                 medge->v1= cvert-1;
1316                                 medge->v2= cvert;
1317                                 medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE;
1318                                 medge++;
1319                         }
1320                 }
1321         }
1322
1323         cache=psys->childcache;
1324         for(a=0; a<totchild; a++) {
1325                 key=cache[a];
1326                 kmax=key->steps;
1327                 for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
1328                         VECCOPY(mvert->co,key->co);
1329                         if(k) {
1330                                 medge->v1=cvert-1;
1331                                 medge->v2=cvert;
1332                                 medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE;
1333                                 medge++;
1334                         }
1335                 }
1336         }
1337
1338         DAG_scene_sort(G.scene);
1339 }
1340
1341 static void modifiers_applyModifier(void *obv, void *mdv)
1342 {
1343         Object *ob = obv;
1344         ModifierData *md = mdv;
1345         DerivedMesh *dm;
1346         Mesh *me = ob->data;
1347         int converted = 0;
1348
1349         if (G.obedit) {
1350                 error("Modifiers cannot be applied in editmode");
1351                 return;
1352         } else if (((ID*) ob->data)->us>1) {
1353                 error("Modifiers cannot be applied to multi-user data");
1354                 return;
1355         }
1356
1357         if (md!=ob->modifiers.first) {
1358                 if (!okee("Modifier is not first"))
1359                         return;
1360         }
1361
1362         if (ob->type==OB_MESH) {
1363                 if(me->mr && multires_modifier_warning()) {
1364                         error("Modifier changes topology; cannot apply with multires active");
1365                         return;
1366                 }
1367                 if(me->key) {
1368                         error("Modifier cannot be applied to Mesh with Shape Keys");
1369                         return;
1370                 }
1371         
1372                 mesh_pmv_off(ob, me);
1373         
1374                 dm = mesh_create_derived_for_modifier(ob, md);
1375                 if (!dm) {
1376                         error("Modifier is disabled or returned error, skipping apply");
1377                         return;
1378                 }
1379
1380                 DM_to_mesh(dm, me);
1381                 converted = 1;
1382
1383                 dm->release(dm);
1384         } 
1385         else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
1386                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1387                 Curve *cu = ob->data;
1388                 int numVerts;
1389                 float (*vertexCos)[3];
1390
1391                 if (!okee("Apply will only change CV points, not tesselated/bevel vertices"))
1392                         return;
1393
1394                 if (!(md->mode&eModifierMode_Realtime) || (mti->isDisabled && mti->isDisabled(md))) {
1395                         error("Modifier is disabled, skipping apply");
1396                         return;
1397                 }
1398
1399                 vertexCos = curve_getVertexCos(cu, &cu->nurb, &numVerts);
1400                 mti->deformVerts(md, ob, NULL, vertexCos, numVerts);
1401                 curve_applyVertexCos(cu, &cu->nurb, vertexCos);
1402
1403                 converted = 1;
1404
1405                 MEM_freeN(vertexCos);
1406
1407                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1408         }
1409         else {
1410                 error("Cannot apply modifier for this object type");
1411                 return;
1412         }
1413
1414         if (converted) {
1415                 BLI_remlink(&ob->modifiers, md);
1416                 modifier_free(md);
1417
1418                 BIF_undo_push("Apply modifier");
1419         }
1420 }
1421
1422 static void modifiers_copyModifier(void *ob_v, void *md_v)
1423 {
1424         Object *ob = ob_v;
1425         ModifierData *md = md_v;
1426         ModifierData *nmd = modifier_new(md->type);
1427
1428         modifier_copyData(md, nmd);
1429
1430         BLI_insertlink(&ob->modifiers, md, nmd);
1431
1432         BIF_undo_push("Copy modifier");
1433 }
1434
1435 static void modifiers_setOnCage(void *ob_v, void *md_v)
1436 {
1437         Object *ob = ob_v;
1438         ModifierData *md;
1439         
1440         int i, cageIndex = modifiers_getCageIndex(ob, NULL );
1441
1442         for( i = 0, md=ob->modifiers.first; md; ++i, md=md->next )
1443                 if( md == md_v ) {
1444                         if( i >= cageIndex )
1445                                 md->mode ^= eModifierMode_OnCage;
1446                         break;
1447                 }
1448 }
1449
1450 static void modifiers_clearHookOffset(void *ob_v, void *md_v)
1451 {
1452         Object *ob = ob_v;
1453         ModifierData *md = md_v;
1454         HookModifierData *hmd = (HookModifierData*) md;
1455         
1456         if (hmd->object) {
1457                 Mat4Invert(hmd->object->imat, hmd->object->obmat);
1458                 Mat4MulSerie(hmd->parentinv, hmd->object->imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL);
1459                 BIF_undo_push("Clear hook offset");
1460         }
1461 }
1462
1463 static void modifiers_cursorHookCenter(void *ob_v, void *md_v)
1464 {
1465         Object *ob = ob_v;
1466         ModifierData *md = md_v;
1467         HookModifierData *hmd = (HookModifierData*) md;
1468
1469         if (G.vd) {
1470                 float *curs = give_cursor();
1471                 float bmat[3][3], imat[3][3];
1472
1473                 where_is_object(ob);
1474         
1475                 Mat3CpyMat4(bmat, ob->obmat);
1476                 Mat3Inv(imat, bmat);
1477
1478                 curs= give_cursor();
1479                 hmd->cent[0]= curs[0]-ob->obmat[3][0];
1480                 hmd->cent[1]= curs[1]-ob->obmat[3][1];
1481                 hmd->cent[2]= curs[2]-ob->obmat[3][2];
1482                 Mat3MulVecfl(imat, hmd->cent);
1483
1484                 BIF_undo_push("Hook cursor center");
1485         }
1486 }
1487
1488 static void modifiers_selectHook(void *ob_v, void *md_v)
1489 {
1490         ModifierData *md = md_v;
1491         HookModifierData *hmd = (HookModifierData*) md;
1492
1493         hook_select(hmd);
1494 }
1495
1496 static void modifiers_reassignHook(void *ob_v, void *md_v)
1497 {
1498         ModifierData *md = md_v;
1499         HookModifierData *hmd = (HookModifierData*) md;
1500         float cent[3];
1501         int *indexar, tot, ok;
1502         char name[32];
1503                 
1504         ok= hook_getIndexArray(&tot, &indexar, name, cent);
1505
1506         if (!ok) {
1507                 error("Requires selected vertices or active Vertex Group");
1508         } else {
1509                 if (hmd->indexar) {
1510                         MEM_freeN(hmd->indexar);
1511                 }
1512
1513                 VECCOPY(hmd->cent, cent);
1514                 hmd->indexar = indexar;
1515                 hmd->totindex = tot;
1516         }
1517 }
1518
1519 static void modifiers_convertToReal(void *ob_v, void *md_v)
1520 {
1521         Object *ob = ob_v;
1522         ModifierData *md = md_v;
1523         ModifierData *nmd = modifier_new(md->type);
1524
1525         modifier_copyData(md, nmd);
1526         nmd->mode &= ~eModifierMode_Virtual;
1527
1528         BLI_addhead(&ob->modifiers, nmd);
1529
1530         ob->partype = PAROBJECT;
1531
1532         BIF_undo_push("Modifier convert to real");
1533 }
1534
1535 static void build_uvlayer_menu_vars(CustomData *data, char **menu_string,
1536                                     int *uvlayer_tmp, char *uvlayer_name)
1537 {
1538         char strtmp[38];
1539         int totuv, i;
1540         CustomDataLayer *layer
1541                     = &data->layers[CustomData_get_layer_index(data, CD_MTFACE)];
1542
1543         *uvlayer_tmp = -1;
1544
1545         totuv = CustomData_number_of_layers(data, CD_MTFACE);
1546
1547         *menu_string = MEM_callocN(sizeof(**menu_string) * (totuv * 38 + 10),
1548                                    "menu_string");
1549         sprintf(*menu_string, "UV Layer%%t");
1550         for(i = 0; i < totuv; i++) {
1551                 /* assign first layer as uvlayer_name if uvlayer_name is null. */
1552                 if(strcmp(layer->name, uvlayer_name) == 0) *uvlayer_tmp = i + 1;
1553                 sprintf(strtmp, "|%s%%x%d", layer->name, i + 1);
1554                 strcat(*menu_string, strtmp);
1555                 layer++;
1556         }
1557
1558         /* there is no uvlayer defined, or else it was deleted. Assign active
1559          * layer, then recalc modifiers.
1560          */
1561         if(*uvlayer_tmp == -1) {
1562                 if(CustomData_get_active_layer_index(data, CD_MTFACE) != -1) {
1563                         *uvlayer_tmp = 1;
1564                         layer = data->layers;
1565                         for(i = 0; i < CustomData_get_active_layer_index(data, CD_MTFACE);
1566                             i++, layer++) {
1567                                 if(layer->type == CD_MTFACE) (*uvlayer_tmp)++;
1568                         }
1569                         strcpy(uvlayer_name, layer->name);
1570
1571                         /* update the modifiers */
1572                         do_modifier_panels(B_MODIFIER_RECALC);
1573                 } else {
1574                         /* ok we have no uv layers, so make sure menu button knows that.*/
1575                         *uvlayer_tmp = 0;
1576                 }
1577         }
1578 }
1579
1580 void set_displace_uvlayer(void *arg1, void *arg2)
1581 {
1582         DisplaceModifierData *dmd=arg1;
1583         CustomDataLayer *layer = arg2;
1584
1585         /*check we have UV layers*/
1586         if (dmd->uvlayer_tmp < 1) return;
1587         layer = layer + (dmd->uvlayer_tmp-1);
1588         
1589         strcpy(dmd->uvlayer_name, layer->name);
1590 }
1591
1592 void set_uvproject_uvlayer(void *arg1, void *arg2)
1593 {
1594         UVProjectModifierData *umd=arg1;
1595         CustomDataLayer *layer = arg2;
1596
1597         /*check we have UV layers*/
1598         if (umd->uvlayer_tmp < 1) return;
1599         layer = layer + (umd->uvlayer_tmp-1);
1600         
1601         strcpy(umd->uvlayer_name, layer->name);
1602 }
1603
1604 static void modifiers_bindMeshDeform(void *ob_v, void *md_v)
1605 {
1606         MeshDeformModifierData *mmd = (MeshDeformModifierData*) md_v;
1607         Object *ob = (Object*)ob_v;
1608
1609         if(mmd->bindcos) {
1610                 if(mmd->bindweights) MEM_freeN(mmd->bindweights);
1611                 if(mmd->bindcos) MEM_freeN(mmd->bindcos);
1612                 if(mmd->dyngrid) MEM_freeN(mmd->dyngrid);
1613                 if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences);
1614                 if(mmd->dynverts) MEM_freeN(mmd->dynverts);
1615                 mmd->bindweights= NULL;
1616                 mmd->bindcos= NULL;
1617                 mmd->dyngrid= NULL;
1618                 mmd->dyninfluences= NULL;
1619                 mmd->dynverts= NULL;
1620                 mmd->totvert= 0;
1621                 mmd->totcagevert= 0;
1622                 mmd->totinfluence= 0;
1623         }
1624         else {
1625                 DerivedMesh *dm;
1626                 int mode= mmd->modifier.mode;
1627
1628                 /* force modifier to run, it will call binding routine */
1629                 mmd->needbind= 1;
1630                 mmd->modifier.mode |= eModifierMode_Realtime;
1631
1632                 if(ob->type == OB_MESH) {
1633                         dm= mesh_create_derived_view(ob, 0);
1634                         dm->release(dm);
1635                 }
1636                 else if(ob->type == OB_LATTICE) {
1637                         lattice_calc_modifiers(ob);
1638                 }
1639                 else if(ob->type==OB_MBALL) {
1640                         makeDispListMBall(ob);
1641                 }
1642                 else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
1643                         makeDispListCurveTypes(ob, 0);
1644                 }
1645
1646                 mmd->needbind= 0;
1647                 mmd->modifier.mode= mode;
1648         }
1649 }
1650
1651 void modifiers_explodeFacepa(void *arg1, void *arg2)
1652 {
1653         ExplodeModifierData *emd=arg1;
1654
1655         emd->flag |= eExplodeFlag_CalcFaces;
1656 }
1657
1658 static int modifier_is_fluid_particles(ModifierData *md) {
1659         if(md->type == eModifierType_ParticleSystem) {
1660                 if(((ParticleSystemModifierData *)md)->psys->part->type == PART_FLUID)
1661                         return 1;
1662         }
1663         return 0;
1664 }
1665 static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco, int *yco, int index, int cageIndex, int lastCageIndex)
1666 {
1667         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1668         uiBut *but;
1669         int isVirtual = md->mode&eModifierMode_Virtual;
1670         int x = *xco, y = *yco, color = md->error?TH_REDALERT:TH_BUT_NEUTRAL;
1671         int editing = (G.obedit==ob);
1672         short height=26, width = 295, buttonWidth = width-120-10;
1673         char str[128];
1674
1675         /* rounded header */
1676         uiBlockSetCol(block, color);
1677                 /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1678         uiDefBut(block, ROUNDBOX, 0, "", x-10, y-4, width, 25, NULL, 7.0, 0.0, 
1679                          (!isVirtual && (md->mode&eModifierMode_Expanded))?3:15, 20, ""); 
1680         uiBlockSetCol(block, TH_AUTO);
1681         
1682         /* open/close icon */
1683         if (!isVirtual) {
1684                 uiBlockSetEmboss(block, UI_EMBOSSN);
1685                 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");
1686         }
1687
1688         uiBlockSetEmboss(block, UI_EMBOSS);
1689         
1690         if (isVirtual) {
1691                 sprintf(str, "%s parent deform", md->name);
1692                 uiDefBut(block, LABEL, 0, str, x+10, y-1, width-110, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name"); 
1693
1694                 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");
1695                 uiButSetFunc(but, modifiers_convertToReal, ob, md);
1696         } else {
1697                 uiBlockBeginAlign(block);
1698                 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"); 
1699
1700                 /* Softbody not allowed in this situation, enforce! */
1701                 if ((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) {
1702                         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");
1703                         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");
1704                         if (mti->flags&eModifierTypeFlag_SupportsEditmode) {
1705                                 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)");
1706                         }
1707                 }
1708                 uiBlockEndAlign(block);
1709
1710                 uiBlockSetEmboss(block, UI_EMBOSSR);
1711
1712                 if (ob->type==OB_MESH && modifier_couldBeCage(md) && index<=lastCageIndex) {
1713                         int icon, color;
1714
1715                         if (index==cageIndex) {
1716                                 color = TH_BUT_SETTING;
1717                                 icon = VICON_EDITMODE_HLT;
1718                         } else if (index<cageIndex) {
1719                                 color = TH_BUT_NEUTRAL;
1720                                 icon = VICON_EDITMODE_DEHLT;
1721                         } else {
1722                                 color = TH_BUT_NEUTRAL;
1723                                 icon = ICON_BLANK1;
1724                         }
1725                         uiBlockSetCol(block, color);
1726                         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");
1727                         uiButSetFunc(but, modifiers_setOnCage, ob, md);
1728                         uiBlockSetCol(block, TH_AUTO);
1729                 }
1730
1731                 uiBlockSetCol(block, TH_BUT_ACTION);
1732
1733                 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");
1734                 uiButSetFunc(but, modifiers_moveUp, ob, md);
1735
1736                 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");
1737                 uiButSetFunc(but, modifiers_moveDown, ob, md);
1738                 
1739                 uiBlockSetEmboss(block, UI_EMBOSSN);
1740                 
1741                 // deletion over the deflection panel
1742                 // fluid particle modifier can't be deleted here
1743                 if(md->type!=eModifierType_Collision && !modifier_is_fluid_particles(md))
1744                 {
1745                         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");
1746                         uiButSetFunc(but, modifiers_del, ob, md);
1747                 }
1748                 uiBlockSetCol(block, TH_AUTO);
1749         }
1750
1751         uiBlockSetEmboss(block, UI_EMBOSS);
1752
1753         if (isVirtual || !(md->mode&eModifierMode_Expanded)) {
1754                 y -= 18;
1755         } else {
1756                 int cy = y - 8;
1757                 int lx = x + width - 60 - 15;
1758
1759                 if (md->type==eModifierType_Subsurf) {
1760                         height = 105;
1761                 } else if (md->type==eModifierType_Lattice) {
1762                         height = 48;
1763                 } else if (md->type==eModifierType_Curve) {
1764                         height = 72;
1765                 } else if (md->type==eModifierType_Build) {
1766                         height = 86;
1767                 } else if (md->type==eModifierType_Mirror) {
1768                         height = 86;
1769                 } else if (md->type==eModifierType_Bevel) {
1770                         BevelModifierData *bmd = (BevelModifierData*) md;
1771                         height = 105; /* height = 124; */
1772                         if ((bmd->lim_flags & BME_BEVEL_ANGLE) || ((bmd->lim_flags & BME_BEVEL_WEIGHT) && !(bmd->flags & BME_BEVEL_VERT))) height += 19;
1773                 } else if (md->type==eModifierType_EdgeSplit) {
1774                         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1775                         height = 48;
1776                         if(emd->flags & MOD_EDGESPLIT_FROMANGLE) height += 19;
1777                 } else if (md->type==eModifierType_Displace) {
1778                         DisplaceModifierData *dmd = (DisplaceModifierData *)md;
1779                         height = 124;
1780                         if(dmd->texmapping == MOD_DISP_MAP_OBJECT ||
1781                            dmd->texmapping == MOD_DISP_MAP_UV)
1782                                 height += 19;
1783                 } else if (md->type==eModifierType_UVProject) {
1784                         height = 114 + ((UVProjectModifierData *)md)->num_projectors * 19;
1785                 } else if (md->type==eModifierType_Decimate) {
1786                         height = 48;
1787                 } else if (md->type==eModifierType_Smooth) {
1788                         height = 86;
1789                 } else if (md->type==eModifierType_Cast) {
1790                         height = 143;
1791                 } else if (md->type==eModifierType_Wave) {
1792                         WaveModifierData *wmd = (WaveModifierData *)md;
1793                         height = 294;
1794                         if(wmd->texmapping == MOD_WAV_MAP_OBJECT ||
1795                            wmd->texmapping == MOD_WAV_MAP_UV)
1796                                 height += 19;
1797                         if(wmd->flag & MOD_WAVE_NORM)
1798                                 height += 19;
1799                 } else if (md->type==eModifierType_Armature) {
1800                         height = 105;
1801                 } else if (md->type==eModifierType_Hook) {
1802                         HookModifierData *hmd = (HookModifierData*) md;
1803                         height = 86;
1804                         if (editing)
1805                                 height += 20;
1806                         if(hmd->indexar==NULL)
1807                                 height += 20;
1808                 } else if (md->type==eModifierType_Softbody) {
1809                         height = 31;
1810                 } else if (md->type==eModifierType_Cloth) {
1811                         height = 31;
1812                 } else if (md->type==eModifierType_Collision) {
1813                         height = 31;
1814                 } else if (md->type==eModifierType_Boolean) {
1815                         height = 48;
1816                 } else if (md->type==eModifierType_Array) {
1817                         height = 211;
1818                 } else if (md->type==eModifierType_MeshDeform) {
1819                         MeshDeformModifierData *mmd= (MeshDeformModifierData*)md;
1820                         height = (mmd->bindcos)? 73: 93;
1821                 } else if (md->type==eModifierType_ParticleSystem) {
1822                         height = 31;
1823                 } else if (md->type==eModifierType_ParticleInstance) {
1824                         height = 94;
1825                 } else if (md->type==eModifierType_Explode) {
1826                         height = 94;
1827                 }
1828                                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1829                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y-height-2, width, height-2, NULL, 5.0, 0.0, 12, 40, ""); 
1830
1831                 y -= 18;
1832
1833                 if (!isVirtual && (md->type!=eModifierType_Collision)) {
1834                         uiBlockBeginAlign(block);
1835                         if (md->type==eModifierType_ParticleSystem) {
1836                                 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");
1837                                 uiButSetFunc(but, modifiers_convertParticles, ob, md);
1838                         }
1839                         else{
1840                                 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");
1841                                 uiButSetFunc(but, modifiers_applyModifier, ob, md);
1842                         }
1843                         
1844                         if (md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (md->type!=eModifierType_Cloth)) {
1845                                 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");
1846                                 uiButSetFunc(but, modifiers_copyModifier, ob, md);
1847                         }
1848                         uiBlockEndAlign(block);
1849                 }
1850
1851                 lx = x + 10;
1852                 cy = y + 10 - 1;
1853                 uiBlockBeginAlign(block);
1854                 if (md->type==eModifierType_Subsurf) {
1855                         SubsurfModifierData *smd = (SubsurfModifierData*) md;
1856                         char subsurfmenu[]="Subsurf Type%t|Catmull-Clark%x0|Simple Subdiv.%x1";
1857                         uiDefButS(block, MENU, B_MODIFIER_RECALC, subsurfmenu,          lx,(cy-=19),buttonWidth,19, &smd->subdivType, 0, 0, 0, 0, "Selects type of subdivision algorithm.");
1858                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Levels:",             lx, (cy-=19), buttonWidth,19, &smd->levels, 1, 6, 0, 0, "Number subdivisions to perform");
1859                         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");
1860
1861                         /* Disabled until non-EM DerivedMesh implementation is complete */
1862
1863                         /*
1864                         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");
1865                         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");
1866                         */
1867
1868                         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");
1869                         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");
1870                 } else if (md->type==eModifierType_Lattice) {
1871                         LatticeModifierData *lmd = (LatticeModifierData*) md;
1872                         uiDefIDPoinBut(block, modifier_testLatticeObj, ID_OB, B_CHANGEDEP, "Ob: ",      lx, (cy-=19), buttonWidth,19, &lmd->object, "Lattice object to deform with");
1873                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &lmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1874                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1875                 } else if (md->type==eModifierType_Curve) {
1876                         CurveModifierData *cmd = (CurveModifierData*) md;
1877                         uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &cmd->object, "Curve object to deform with");
1878                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &cmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1879                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1880                         
1881                         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");
1882                         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");
1883                         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");
1884                         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");
1885                         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");
1886                         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");
1887                 } else if (md->type==eModifierType_Build) {
1888                         BuildModifierData *bmd = (BuildModifierData*) md;
1889                         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");
1890                         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");
1891                         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.");
1892                         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.");
1893                 } else if (md->type==eModifierType_Mirror) {
1894                         MirrorModifierData *mmd = (MirrorModifierData*) md;
1895                         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");
1896                         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");
1897                         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");
1898                         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");
1899                         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");
1900                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_U, B_MODIFIER_RECALC,
1901                                      "Mirror U",
1902                                      lx, (cy-=19), buttonWidth/2, 19,
1903                                      &mmd->flag, 0, 0, 0, 0,
1904                                      "Mirror the U texture coordinate around "
1905                                      "the 0.5 point");
1906                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_V, B_MODIFIER_RECALC,
1907                                      "Mirror V",
1908                                      lx + buttonWidth/2 + 1, cy, buttonWidth/2, 19,
1909                                      &mmd->flag, 0, 0, 0, 0,
1910                                      "Mirror the V texture coordinate around "
1911                                      "the 0.5 point");
1912                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1913                                        "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1914                                        &mmd->mirror_ob,
1915                                        "Object to use as mirror");
1916                 } else if (md->type==eModifierType_Bevel) {
1917                         BevelModifierData *bmd = (BevelModifierData*) md;
1918                         /*uiDefButS(block, ROW, B_MODIFIER_RECALC, "Distance",
1919                                           lx, (cy -= 19), (buttonWidth/2), 19, &bmd->val_flags,
1920                                           11.0, 0, 0, 0,
1921                                           "Interpret bevel value as a constant distance from each edge");
1922                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "Radius",
1923                                           (lx+buttonWidth/2), cy, (buttonWidth - buttonWidth/2), 19, &bmd->val_flags,
1924                                           11.0, BME_BEVEL_RADIUS, 0, 0,
1925                                           "Interpret bevel value as a radius - smaller angles will be beveled more");*/
1926                         uiBlockBeginAlign(block);
1927                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Width: ",
1928                                           lx, (cy -= 19), buttonWidth, 19, &bmd->value,
1929                                           0.0, 0.5, 5, 2,
1930                                           "Bevel value/amount");
1931                         /*uiDefButI(block, NUM, B_MODIFIER_RECALC, "Recurs",
1932                                           lx, (cy -= 19), buttonWidth, 19, &bmd->res,
1933                                           1, 4, 5, 2,
1934                                           "Number of times to bevel");*/
1935                         uiDefButBitS(block, TOG, BME_BEVEL_VERT,
1936                                           B_MODIFIER_RECALC, "Only Vertices",
1937                                           lx, (cy -= 19), buttonWidth, 19,
1938                                           &bmd->flags, 0, 0, 0, 0,
1939                                           "Bevel only verts/corners; not edges");
1940                         uiBlockEndAlign(block);
1941                                           
1942                         uiDefBut(block, LABEL, 1, "Limit using:",       lx, (cy-=25), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
1943                         uiBlockBeginAlign(block);
1944                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "None",
1945                                           lx, (cy -= 19), (buttonWidth/3), 19, &bmd->lim_flags,
1946                                           12.0, 0, 0, 0,
1947                                           "Bevel the entire mesh by a constant amount");
1948                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "Angle",
1949                                           (lx+buttonWidth/3), cy, (buttonWidth/3), 19, &bmd->lim_flags,
1950                                           12.0, BME_BEVEL_ANGLE, 0, 0,
1951                                           "Only bevel edges with sharp enough angles between faces");
1952                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "BevWeight",
1953                                           lx+(2*buttonWidth/3), cy, buttonWidth-2*(buttonWidth/3), 19, &bmd->lim_flags,
1954                                           12.0, BME_BEVEL_WEIGHT, 0, 0,
1955                                           "Use bevel weights to determine how much bevel is applied; apply them separately in vert/edge select mode");
1956                         if ((bmd->lim_flags & BME_BEVEL_WEIGHT) && !(bmd->flags & BME_BEVEL_VERT)) {
1957                                 uiDefButS(block, ROW, B_MODIFIER_RECALC, "Min",
1958                                           lx, (cy -= 19), (buttonWidth/3), 19, &bmd->e_flags,
1959                                           13.0, BME_BEVEL_EMIN, 0, 0,
1960                                           "The sharpest edge's weight is used when weighting a vert");
1961                                 uiDefButS(block, ROW, B_MODIFIER_RECALC, "Average",
1962                                           (lx+buttonWidth/3), cy, (buttonWidth/3), 19, &bmd->e_flags,
1963                                           13.0, 0, 0, 0,
1964                                           "The edge weights are averaged when weighting a vert");
1965                                 uiDefButS(block, ROW, B_MODIFIER_RECALC, "Max",
1966                                           (lx+2*(buttonWidth/3)), cy, buttonWidth-2*(buttonWidth/3), 19, &bmd->e_flags,
1967                                           13.0, BME_BEVEL_EMAX, 0, 0,
1968                                           "The largest edge's wieght is used when weighting a vert");
1969                         }
1970                         else if (bmd->lim_flags & BME_BEVEL_ANGLE) {
1971                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Angle:",
1972                                           lx, (cy -= 19), buttonWidth, 19, &bmd->bevel_angle,
1973                                           0.0, 180.0, 100, 2,
1974                                           "Angle above which to bevel edges");
1975                         }
1976                 } else if (md->type==eModifierType_EdgeSplit) {
1977                         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1978                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMANGLE,
1979                                      B_MODIFIER_RECALC, "From Edge Angle",
1980                                      lx, (cy -= 19), buttonWidth, 19,
1981                                      &emd->flags, 0, 0, 0, 0,
1982                                      "Split edges with high angle between faces");
1983                         if(emd->flags & MOD_EDGESPLIT_FROMANGLE) {
1984                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Split Angle:",
1985                                           lx, (cy -= 19), buttonWidth, 19, &emd->split_angle,
1986                                           0.0, 180.0, 100, 2,
1987                                           "Angle above which to split edges");
1988                         }
1989                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMFLAG,
1990                                      B_MODIFIER_RECALC, "From Marked As Sharp",
1991                                      lx, (cy -= 19), buttonWidth, 19,
1992                                      &emd->flags, 0, 0, 0, 0,
1993                                      "Split edges that are marked as sharp");
1994                 } else if (md->type==eModifierType_Displace) {
1995                         DisplaceModifierData *dmd = (DisplaceModifierData*) md;
1996                         but = uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",
1997                                        lx, (cy -= 19), buttonWidth, 19,
1998                                        &dmd->defgrp_name, 0.0, 31.0, 0, 0,
1999                                        "Name of vertex group to displace"
2000                                        " (displace whole mesh if blank)");
2001                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2002                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,
2003                                        "Texture: ", lx, (cy -= 19), buttonWidth, 19,
2004                                        &dmd->texture,
2005                                        "Texture to use as displacement input");
2006                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Midlevel:",
2007                                   lx, (cy -= 19), buttonWidth, 19, &dmd->midlevel,
2008                                   0, 1, 10, 3,
2009                                   "Material value that gives no displacement");
2010                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Strength:",
2011                                   lx, (cy -= 19), buttonWidth, 19, &dmd->strength,
2012                                   -1000, 1000, 10, 0.1,
2013                                   "Strength of displacement");
2014                         sprintf(str, "Direction%%t|Normal%%x%d|RGB -> XYZ%%x%d|"
2015                                 "Z%%x%d|Y%%x%d|X%%x%d",
2016                                 MOD_DISP_DIR_NOR, MOD_DISP_DIR_RGB_XYZ,
2017                                 MOD_DISP_DIR_Z, MOD_DISP_DIR_Y, MOD_DISP_DIR_X);
2018                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2019                                   lx, (cy -= 19), buttonWidth, 19, &dmd->direction,
2020                                   0.0, 1.0, 0, 0, "Displace direction");
2021                         sprintf(str, "Texture Coordinates%%t"
2022                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
2023                                 MOD_DISP_MAP_LOCAL, MOD_DISP_MAP_GLOBAL,
2024                                 MOD_DISP_MAP_OBJECT, MOD_DISP_MAP_UV);
2025                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2026                                   lx, (cy -= 19), buttonWidth, 19, &dmd->texmapping,
2027                                   0.0, 1.0, 0, 0,
2028                                   "Texture coordinates used for displacement input");
2029                         if (dmd->texmapping == MOD_DISP_MAP_UV) {
2030                                 char *strtmp;
2031                                 int i;
2032                                 CustomData *fdata = G.obedit ? &G.editMesh->fdata
2033                                                              : &((Mesh*)ob->data)->fdata;
2034                                 build_uvlayer_menu_vars(fdata, &strtmp, &dmd->uvlayer_tmp,
2035                                                         dmd->uvlayer_name);
2036                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
2037                                       lx, (cy -= 19), buttonWidth, 19, &dmd->uvlayer_tmp,
2038                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
2039                                 MEM_freeN(strtmp);
2040                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
2041                                 uiButSetFunc(but, set_displace_uvlayer, dmd,
2042                                              &fdata->layers[i]);
2043                         }
2044                         if(dmd->texmapping == MOD_DISP_MAP_OBJECT) {
2045                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2046                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
2047                                                &dmd->map_object,
2048                                                "Object to get texture coordinates from");
2049                         }
2050                 } else if (md->type==eModifierType_UVProject) {
2051                         UVProjectModifierData *umd = (UVProjectModifierData *) md;
2052                         int i;
2053                         char *strtmp;
2054                         CustomData *fdata = G.obedit ? &G.editMesh->fdata
2055                                                      : &((Mesh*)ob->data)->fdata;
2056                         build_uvlayer_menu_vars(fdata, &strtmp, &umd->uvlayer_tmp,
2057                                                 umd->uvlayer_name);
2058                         but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
2059                               lx, (cy -= 19), buttonWidth, 19, &umd->uvlayer_tmp,
2060                               0.0, 1.0, 0, 0, "Set the UV layer to use");
2061                         i = CustomData_get_layer_index(fdata, CD_MTFACE);
2062                         uiButSetFunc(but, set_uvproject_uvlayer, umd, &fdata->layers[i]);
2063                         MEM_freeN(strtmp);
2064                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspX:",
2065                                   lx, (cy -= 19), buttonWidth / 2, 19, &umd->aspectx,
2066                                   1, 1000, 100, 2,
2067                                   "Horizontal Aspect Ratio");
2068                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspY:",
2069                                   lx + (buttonWidth / 2) + 1, cy, buttonWidth / 2, 19,
2070                                   &umd->aspecty,
2071                                   1, 1000, 100, 2,
2072                                   "Vertical Aspect Ratio");
2073                         uiDefButI(block, NUM, B_MODIFIER_RECALC, "Projectors:",
2074                                   lx, (cy -= 19), buttonWidth, 19, &umd->num_projectors,
2075                                   1, MOD_UVPROJECT_MAXPROJECTORS, 0, 0,
2076                                   "Number of objects to use as projectors");
2077                         for(i = 0; i < umd->num_projectors; ++i) {
2078                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2079                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
2080                                                &umd->projectors[i],
2081                                                "Object to use as projector");
2082                         }
2083                         uiDefIDPoinBut(block, modifier_testImage, ID_IM, B_CHANGEDEP,
2084                                        "Image: ", lx, (cy -= 19), buttonWidth, 19,
2085                                        &umd->image,
2086                                        "Image to project (only faces with this image "
2087                                        "will be altered");
2088                         uiButSetCompleteFunc(but, autocomplete_image, (void *)ob);
2089                         uiDefButBitI(block, TOG, MOD_UVPROJECT_OVERRIDEIMAGE,
2090                                      B_MODIFIER_RECALC, "Override Image",
2091                                      lx, (cy -= 19), buttonWidth, 19,
2092                                      &umd->flags, 0, 0, 0, 0,
2093                                      "Override faces' current images with the "
2094                                      "given image");
2095                 } else if (md->type==eModifierType_Decimate) {
2096                         DecimateModifierData *dmd = (DecimateModifierData*) md;
2097                         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");
2098                         sprintf(str, "Face Count: %d", dmd->faceCount);
2099                         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");
2100                 } else if (md->type==eModifierType_Smooth) {
2101                         SmoothModifierData *smd = (SmoothModifierData*) md;
2102
2103                         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");
2104                         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");
2105                         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");
2106
2107                         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)");
2108                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Repeat:",     lx,(cy-=19),buttonWidth, 19, &smd->repeat, 0.0, 30.0, 1, 0, "Number of smoothing iterations");
2109                         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");
2110                 } else if (md->type==eModifierType_Cast) {
2111                         CastModifierData *cmd = (CastModifierData*) md;
2112
2113                         char casttypemenu[]="Projection Type%t|Sphere%x0|Cylinder%x1|Cuboid%x2";
2114                         uiDefButS(block, MENU, B_MODIFIER_RECALC, casttypemenu,         lx,(cy-=19),buttonWidth - 30,19, &cmd->type, 0, 0, 0, 0, "Projection type to apply");
2115                         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");
2116                         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");
2117                         if (cmd->type != MOD_CAST_TYPE_CYLINDER) {
2118                                 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");
2119                         }
2120                         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");
2121                         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)");
2122                         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)");
2123                         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)");
2124                         if (ob->type == OB_MESH) {
2125                                 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");
2126                         }
2127                         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");
2128                         if(cmd->object) {
2129                                 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");
2130                         }
2131                 } else if (md->type==eModifierType_Wave) {
2132                         WaveModifierData *wmd = (WaveModifierData*) md;
2133                         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");
2134                         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");
2135                         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");
2136                         uiDefButBitS(block, TOG, MOD_WAVE_NORM, B_MODIFIER_RECALC, "Normals",   lx,(cy-=19),buttonWidth,19, &wmd->flag, 0, 0, 0, 0, "Displace along normals");
2137                         if (wmd->flag & MOD_WAVE_NORM){
2138                                 if (ob->type==OB_MESH) {
2139                                         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");
2140                                         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");
2141                                         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");
2142                                 }
2143                                 else
2144                                         uiDefBut(block, LABEL, 1, "Meshes Only",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");                                
2145                         }
2146
2147                         uiBlockBeginAlign(block);
2148                         if(wmd->speed >= 0)
2149                                 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");
2150                         else
2151                                 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");
2152                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Lifetime:",   lx,(cy-=19),buttonWidth,19, &wmd->lifetime,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the lifespan of the wave");
2153                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Damptime:",   lx,(cy-=19),buttonWidth,19, &wmd->damp,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the dampingtime of the wave");
2154                         cy -= 9;
2155                         uiBlockBeginAlign(block);
2156                         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");
2157                         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");
2158                         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)");
2159                         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");
2160                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,"Texture: ", lx, (cy -= 19), 220, 19, &wmd->texture,"Texture with which to modulate wave");
2161                         sprintf(str, "Texture Coordinates%%t"
2162                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
2163                                 MOD_WAV_MAP_LOCAL, MOD_WAV_MAP_GLOBAL,
2164                                 MOD_WAV_MAP_OBJECT, MOD_WAV_MAP_UV);
2165                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2166                                   lx, (cy -= 19), 220, 19, &wmd->texmapping,
2167                                   0.0, 1.0, 0, 0,
2168                                   "Texture coordinates used for modulation input");
2169                         if (wmd->texmapping == MOD_WAV_MAP_UV) {
2170                                 char *strtmp;
2171                                 int i;
2172                                 CustomData *fdata = G.obedit ? &G.editMesh->fdata
2173                                                              : &((Mesh*)ob->data)->fdata;
2174                                 build_uvlayer_menu_vars(fdata, &strtmp, &wmd->uvlayer_tmp,
2175                                                         wmd->uvlayer_name);
2176                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
2177                                       lx, (cy -= 19), 220, 19, &wmd->uvlayer_tmp,
2178                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
2179                                 MEM_freeN(strtmp);
2180                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
2181                                 uiButSetFunc(but, set_displace_uvlayer, wmd,
2182                                              &fdata->layers[i]);
2183                         }
2184                         if(wmd->texmapping == MOD_DISP_MAP_OBJECT) {
2185                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2186                                                "Ob: ", lx, (cy -= 19), 220, 19,
2187                                                &wmd->map_object,
2188                                                "Object to get texture coordinates from");
2189                         }
2190             cy -= 9;
2191                         uiBlockBeginAlign(block);
2192                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Speed:",   lx,(cy-=19),220,19, &wmd->speed, -2.0, 2.0, 0, 0, "Specify the wave speed");
2193                         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");
2194                         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");
2195                         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");
2196                 } else if (md->type==eModifierType_Armature) {
2197                         ArmatureModifierData *amd = (ArmatureModifierData*) md;
2198                         uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &amd->object, "Armature object to deform with");
2199                         
2200                         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");
2201                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2202                         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");
2203                         
2204                         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");
2205                         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");
2206                         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");
2207                         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");
2208                         
2209                         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");
2210
2211                 } else if (md->type==eModifierType_Hook) {
2212                         HookModifierData *hmd = (HookModifierData*) md;
2213                         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");
2214                         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");
2215                         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"); 
2216                         if(hmd->indexar==NULL) {
2217                                 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &hmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
2218                                 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2219                         }
2220                         uiBlockBeginAlign(block);
2221                         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");
2222                         uiButSetFunc(but, modifiers_clearHookOffset, ob, md);
2223                         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");
2224                         uiButSetFunc(but, modifiers_cursorHookCenter, ob, md);
2225
2226                         if (editing) {
2227                                 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");
2228                                 uiButSetFunc(but, modifiers_selectHook, ob, md);
2229                                 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");
2230                                 uiButSetFunc(but, modifiers_reassignHook, ob, md);
2231                         }
2232                 } else if (md->type==eModifierType_Softbody) {
2233                         uiDefBut(block, LABEL, 1, "See Softbody panel.",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2234                 } else if (md->type==eModifierType_Cloth) {
2235                         uiDefBut(block, LABEL, 1, "See Cloth panel.",   lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2236                 } else if (md->type==eModifierType_Collision) {
2237                         uiDefBut(block, LABEL, 1, "See Deflection panel.",      lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2238                 } else if (md->type==eModifierType_Boolean) {
2239                         BooleanModifierData *bmd = (BooleanModifierData*) md;
2240                         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");
2241                         uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &bmd->object, "Mesh object to use for boolean operation");
2242                 } else if (md->type==eModifierType_Array) {
2243                         ArrayModifierData *amd = (ArrayModifierData*) md;
2244                         float range = 10000;
2245                         int cytop, halfwidth = (width - 5)/2 - 15;
2246                         int halflx = lx + halfwidth + 10;
2247
2248                         uiBlockSetEmboss(block, UI_EMBOSSX);
2249                         uiBlockEndAlign(block);
2250
2251                         /* length parameters */
2252                         uiBlockBeginAlign(block);
2253                         sprintf(str, "Length Fit%%t|Fixed Count%%x%d|Fixed Length%%x%d"
2254                                 "|Fit To Curve Length%%x%d",
2255                                 MOD_ARR_FIXEDCOUNT, MOD_ARR_FITLENGTH, MOD_ARR_FITCURVE);
2256                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2257                                   lx, (cy-=19), buttonWidth, 19, &amd->fit_type,
2258                                   0.0, 1.0, 0, 0, "Array length calculation method");
2259                         switch(amd->fit_type)
2260                         {
2261                         case MOD_ARR_FIXEDCOUNT:
2262                                 uiDefButI(block, NUM, B_MODIFIER_RECALC, "Count:",
2263                                           lx, (cy -= 19), buttonWidth, 19, &amd->count,
2264                                           1, 1000, 0, 0, "Number of duplicates to make");
2265                                 break;
2266                         case MOD_ARR_FITLENGTH:
2267                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Length:",
2268                                           lx, (cy -= 19), buttonWidth, 19, &amd->length,
2269                                           0, range, 10, 2,
2270                                           "Length to fit array within");
2271                                 break;
2272                         case MOD_ARR_FITCURVE:
2273                                 uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB,
2274                                                B_CHANGEDEP, "Ob: ",
2275                                                lx, (cy -= 19), buttonWidth, 19, &amd->curve_ob,
2276                                                "Curve object to fit array length to");
2277                                 break;
2278                         }
2279                         uiBlockEndAlign(block);
2280
2281                         /* offset parameters */
2282                         cy -= 10;
2283                         cytop= cy;
2284                         uiBlockBeginAlign(block);
2285                         uiDefButBitI(block, TOG, MOD_ARR_OFF_CONST, B_MODIFIER_RECALC,
2286                                      "Constant Offset", lx, (cy-=19), halfwidth, 19,
2287                                      &amd->offset_type, 0, 0, 0, 0,
2288                                      "Constant offset between duplicates "
2289                                      "(local coordinates)");
2290                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2291                                   lx, (cy-=19), halfwidth, 19,
2292                                   &amd->offset[0],
2293                                   -range, range, 10, 3,
2294                                   "Constant component for duplicate offsets "
2295                                   "(local coordinates)");
2296                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2297                                   lx, (cy-=19), halfwidth, 19,
2298                                   &amd->offset[1],
2299                                   -range, range, 10, 3,
2300                                   "Constant component for duplicate offsets "
2301                                   "(local coordinates)");
2302                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2303                                   lx, (cy-=19), halfwidth, 19,
2304                                   &amd->offset[2],
2305                                   -range, range, 10, 3,
2306                                   "Constant component for duplicate offsets "
2307                                   "(local coordinates)");
2308                         uiBlockEndAlign(block);
2309
2310                         cy= cytop;
2311                         uiBlockBeginAlign(block);
2312                         uiDefButBitI(block, TOG, MOD_ARR_OFF_RELATIVE, B_MODIFIER_RECALC,
2313                                      "Relative Offset", halflx, (cy-=19), halfwidth, 19,
2314                                      &amd->offset_type, 0, 0, 0, 0,
2315                                      "Offset between duplicates relative to object width "
2316                                      "(local coordinates)");
2317                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2318                                   halflx, (cy-=19), halfwidth, 19,
2319                                   &amd->scale[0],
2320                                   -range, range, 10, 3,
2321                                   "Component for duplicate offsets relative to object "
2322                                   "width (local coordinates)");
2323                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2324                                   halflx, (cy-=19), halfwidth, 19,
2325                                   &amd->scale[1],
2326                                   -range, range, 10, 3,
2327                                   "Component for duplicate offsets relative to object "
2328                                   "width (local coordinates)");
2329                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2330                                   halflx, (cy-=19), halfwidth, 19,
2331                                   &amd->scale[2],
2332                                   -range, range, 10, 3,
2333                                   "Component for duplicate offsets relative to object "
2334                                   "width (local coordinates)");
2335                         uiBlockEndAlign(block);
2336
2337                         /* vertex merging parameters */
2338                         cy -= 10;
2339                         cytop= cy;
2340
2341                         uiBlockBeginAlign(block);
2342                         uiDefButBitI(block, TOG, MOD_ARR_MERGE, B_MODIFIER_RECALC,
2343                                      "Merge",
2344                                      lx, (cy-=19), halfwidth/2, 19, &amd->flags,
2345                                      0, 0, 0, 0,
2346                                      "Merge vertices in adjacent duplicates");
2347                         uiDefButBitI(block, TOG, MOD_ARR_MERGEFINAL, B_MODIFIER_RECALC,
2348                                      "First Last",
2349                                      lx + halfwidth/2, cy, (halfwidth+1)/2, 19,
2350                                      &amd->flags,
2351                                      0, 0, 0, 0,
2352                                      "Merge vertices in first duplicate with vertices"
2353                                      " in last duplicate");
2354                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Limit:",
2355                                           lx, (cy-=19), halfwidth, 19, &amd->merge_dist,
2356                                           0, 1.0f, 1, 4,
2357                                           "Limit below which to merge vertices");
2358
2359                         /* offset ob */
2360                         cy = cytop;
2361                         uiBlockBeginAlign(block);
2362                         uiDefButBitI(block, TOG, MOD_ARR_OFF_OBJ, B_MODIFIER_RECALC,
2363                                      "Object Offset", halflx, (cy -= 19), halfwidth, 19,
2364                                      &amd->offset_type, 0, 0, 0, 0,
2365                                      "Add an object transformation to the total offset");
2366                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2367                                        "Ob: ", halflx, (cy -= 19), halfwidth, 19,
2368                                        &amd->offset_ob,
2369                                        "Object from which to take offset transformation");
2370                         uiBlockEndAlign(block);
2371
2372                         cy -= 10;
2373                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2374                                              B_CHANGEDEP, "Start cap: ",
2375                                              lx, (cy -= 19), halfwidth, 19,
2376                                              &amd->start_cap,
2377                                              "Mesh object to use as start cap");
2378                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2379                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2380                                              B_CHANGEDEP, "End cap: ",
2381                                              halflx, cy, halfwidth, 19,
2382                                              &amd->end_cap,
2383                                              "Mesh object to use as end cap");
2384                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2385                 } else if (md->type==eModifierType_MeshDeform) {
2386                         MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
2387
2388                         uiBlockBeginAlign(block);
2389                         uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &mmd->object, "Mesh object to be use as cage"); 
2390                         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");
2391                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2392                         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");
2393
2394                         uiBlockBeginAlign(block);
2395                         if(mmd->bindcos) {
2396                                 but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Unbind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Unbind mesh from cage");
2397                                 uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
2398                         }
2399                         else {
2400                                 but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Bind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Bind mesh to cage");
2401                                 uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
2402                                 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");
2403                                 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");
2404                         }
2405                         uiBlockEndAlign(block);
2406                 } else if (md->type==eModifierType_ParticleSystem) {
2407                         uiDefBut(block, LABEL, 1, "See Particle buttons.",      lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2408                 } else if (md->type==eModifierType_ParticleInstance) {
2409                         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
2410                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy -= 19), buttonWidth, 19, &pimd->ob, "Object that has the particlesystem");
2411                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "PSYS:", lx, (cy -= 19), buttonWidth, 19, &pimd->psys, 1, 10, 10, 3, "Particlesystem number in the object");
2412                         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");
2413                         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");
2414                         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");
2415                         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");
2416                         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");
2417                         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");
2418                 } else if (md->type==eModifierType_Explode) {
2419                         ExplodeModifierData *emd = (ExplodeModifierData*) md;
2420                         uiBut *but;
2421                         char *menustr= get_vertexgroup_menustr(ob);
2422                         int defCount=BLI_countlist(&ob->defbase);
2423                         if(defCount==0) emd->vgroup=0;
2424
2425                         but=uiDefButS(block, MENU, B_MODIFIER_RECALC, menustr,  lx, (cy-=19), buttonWidth/2,19, &emd->vgroup, 0, defCount, 0, 0, "Protect this vertex group");
2426                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2427                         MEM_freeN(menustr);
2428
2429                         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");
2430                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2431
2432                         but=uiDefBut(block, BUT, B_MODIFIER_RECALC, "Refresh",  lx, (cy-=19), buttonWidth/2,19, 0, 0, 0, 0, 0, "Recalculate faces assigned to particles");
2433                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2434
2435                         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");
2436                         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");
2437                         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");
2438                         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");
2439                 }
2440
2441                 uiBlockEndAlign(block);
2442
2443                 y-=height;
2444         }
2445
2446         if (md->error) {
2447                 char str[512];
2448
2449                 y -= 20;
2450
2451                 uiBlockSetCol(block, color);
2452                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
2453                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y, width, 20, NULL, 5.0, 0.0, 15, 40, ""); 
2454                 uiBlockSetCol(block, TH_AUTO);
2455
2456                 sprintf(str, "Modifier Error: %s", md->error);
2457                 uiDefBut(block, LABEL, B_NOP, str, x+15, y+15, width-35, 19, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
2458         }
2459
2460         uiClearButLock();
2461
2462         y -= 3+6;
2463
2464         *xco = x;
2465         *yco = y;
2466 }
2467
2468 static void editing_panel_modifiers(Object *ob)
2469 {
2470         ModifierData *md;
2471         uiBlock *block;
2472         char str[64];
2473         int xco, yco, i, lastCageIndex, cageIndex = modifiers_getCageIndex(ob, &lastCageIndex);
2474
2475         block= uiNewBlock(&curarea->uiblocks, "editing_panel_modifiers", UI_EMBOSS, UI_HELV, curarea->win);
2476         if( uiNewPanel(curarea, block, "Modifiers", "Editing", 640, 0, 318, 204)==0) return;
2477         
2478         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2479         uiNewPanelHeight(block, 204);
2480
2481         uiDefBlockBut(block, modifiers_add_menu, ob, "Add Modifier", 0, 190, 130, 20, "Add a new modifier");
2482
2483         sprintf(str, "To: %s", ob->id.name+2);
2484         uiDefBut(block, LABEL, 1, str,  140, 190, 150, 20, NULL, 0.0, 0.0, 0, 0, "Object whose modifier stack is being edited");
2485
2486         xco = 0;
2487         yco = 160;
2488
2489         md = modifiers_getVirtualModifierList(ob);
2490
2491         for (i=0; md; i++, md=md->next) {
2492                 draw_modifier(block, ob, md, &xco, &yco, i, cageIndex, lastCageIndex);
2493                 if (md->mode&eModifierMode_Virtual) i--;
2494         }
2495         
2496         if(yco < 0) uiNewPanelHeight(block, 204-yco);
2497 }
2498
2499 static char *make_key_menu(Key *key, int startindex)
2500 {
2501         KeyBlock *kb;
2502         int index= 1;
2503         char *str, item[64];
2504
2505         for (kb = key->block.first; kb; kb=kb->next, index++);
2506         str= MEM_mallocN(index*40, "key string");
2507         str[0]= 0;
2508         
2509         index= startindex;
2510         for (kb = key->block.first; kb; kb=kb->next, index++) {
2511                 sprintf (item,  "|%s%%x%d", kb->name, index);
2512                 strcat(str, item);
2513         }
2514         
2515         return str;
2516 }
2517
2518 static void editing_panel_shapes(Object *ob)
2519 {
2520         uiBlock *block;
2521         Key *key= NULL;
2522         KeyBlock *kb;
2523         int icon;
2524         char *strp;
2525         
2526         block= uiNewBlock(&curarea->uiblocks, "editing_panel_shapes", UI_EMBOSS, UI_HELV, curarea->win);
2527         uiNewPanelTabbed("Modifiers", "Editing");
2528         if( uiNewPanel(curarea, block, "Shapes", "Editing", 640, 0, 318, 204)==0) return;
2529         
2530         /* Todo check data is library here */
2531         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2532         
2533         uiDefBut(block, BUT, B_ADDKEY, "Add Shape Key" ,        10, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "Add new Shape Key");
2534         
2535         key= ob_get_key(ob);
2536         if(key==NULL) {
2537                 /* label aligns add button */
2538                 uiDefBut(block, LABEL, 0, "",           170, 180,140,20, NULL, 0, 0, 0, 0, "");
2539                 return;
2540         }
2541         
2542         uiDefButS(block, TOG, B_RELKEY, "Relative",             170, 180,140,20, &key->type, 0, 0, 0, 0, "Makes Shape Keys relative");
2543
2544         kb= BLI_findlink(&key->block, ob->shapenr-1);
2545         if(kb==NULL) {
2546                 ob->shapenr= 1;
2547                 kb= key->block.first;
2548         }
2549
2550         uiBlockBeginAlign(block);
2551         if(ob->shapeflag & OB_SHAPE_LOCK) icon= ICON_PIN_HLT; else icon= ICON_PIN_DEHLT;
2552         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");
2553         if(kb->flag & KEYBLOCK_MUTE) icon= ICON_MUTE_IPO_ON; else icon = ICON_MUTE_IPO_OFF;
2554         uiDefIconButBitS(block, TOG, KEYBLOCK_MUTE, B_MODIFIER_RECALC, icon, 35,150,20,20, &kb->flag, 0, 0, 0, 0, "Mute the current Shape");
2555         uiSetButLock(G.obedit==ob, "Unable to perform in EditMode");
2556         uiDefIconBut(block, BUT, B_PREVKEY, ICON_TRIA_LEFT,             55,150,20,20, NULL, 0, 0, 0, 0, "Previous Shape Key");
2557         strp= make_key_menu(key, 1);
2558         uiDefButS(block, MENU, B_SETKEY, strp,                                  75,150,20,20, &ob->shapenr, 0, 0, 0, 0, "Browse existing choices");
2559         MEM_freeN(strp);
2560         
2561         uiDefIconBut(block, BUT, B_NEXTKEY, ICON_TRIA_RIGHT,    95,150,20,20, NULL, 0, 0, 0, 0, "Next Shape Key");
2562         uiClearButLock();
2563         uiDefBut(block, TEX, B_NAMEKEY, "",                                             115, 150, 170, 20, kb->name, 0.0, 31.0, 0, 0, "Current Shape Key name");
2564         uiDefIconBut(block, BUT, B_DELKEY, ICON_X,                              285,150,25,20, 0, 0, 0, 0, 0, "Deletes current Shape Key");
2565         uiBlockEndAlign(block);
2566
2567         if(key->type && (ob->shapeflag & OB_SHAPE_LOCK)==0 && ob->shapenr!=1) {
2568                 uiBlockBeginAlign(block);
2569                 make_rvk_slider(block, ob, ob->shapenr-1,                       10, 120, 150, 20, "Key value, when used it inserts an animation curve point");
2570                 uiDefButF(block, NUM, B_REDR, "Min ",                           160,120, 75, 20, &kb->slidermin, -10.0, 10.0, 100, 1, "Minumum for slider");
2571                 uiDefButF(block, NUM, B_REDR, "Max ",                           235,120, 75, 20, &kb->slidermax, -10.0, 10.0, 100, 1, "Maximum for slider");
2572                 uiBlockEndAlign(block);
2573         }
2574         if(key->type && ob->shapenr!=1) {
2575                 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");
2576
2577                 strp= make_key_menu(key, 0);
2578                 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");
2579                 MEM_freeN(strp);
2580         }
2581         
2582         if(key->type==0)
2583                 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");
2584         
2585 }
2586
2587 /* *************************** FONT ******************************** */
2588
2589 static short give_vfontnr(VFont *vfont)
2590 {
2591         VFont *vf;
2592         short nr= 1;
2593
2594         vf= G.main->vfont.first;
2595         while(vf) {
2596                 if(vf==vfont) return nr;
2597                 nr++;
2598                 vf= vf->id.next;
2599         }
2600         return -1;
2601 }
2602
2603 static VFont *give_vfontpointer(int nr) /* nr= button */
2604 {
2605         VFont *vf;
2606         short tel= 1;
2607
2608         vf= G.main->vfont.first;
2609         while(vf) {
2610                 if(tel==nr) return vf;
2611                 tel++;
2612                 vf= vf->id.next;
2613         }
2614         return G.main->vfont.first;
2615 }
2616
2617 VFont *exist_vfont(char *str)
2618 {
2619         VFont *vf;
2620
2621         vf= G.main->vfont.first;
2622         while(vf) {
2623                 if(strcmp(vf->name, str)==0) return vf;
2624                 vf= vf->id.next;
2625         }
2626         return 0;
2627 }
2628
2629 static char *give_vfontbutstr(void)
2630 {
2631         VFont *vf;
2632         int len= 0;
2633         char *str, di[FILE_MAXDIR], fi[FILE_MAXFILE];
2634
2635         vf= G.main->vfont.first;
2636         while(vf) {
2637                 strcpy(di, vf->name);
2638                 BLI_splitdirstring(di, fi);
2639                 len+= strlen(fi)+4;
2640                 vf= vf->id.next;
2641         }
2642
2643         str= MEM_callocN(len+21, "vfontbutstr");
2644         strcpy(str, "FONTS %t");
2645         vf= G.main->vfont.first;
2646         while(vf) {
2647
2648                 if(vf->id.us==0) strcat(str, "|0 ");
2649                 else strcat(str, "|   ");
2650
2651                 strcpy(di, vf->name);
2652                 BLI_splitdirstring(di, fi);
2653
2654                 strcat(str, fi);
2655                 vf= vf->id.next;
2656         }
2657         return str;
2658 }
2659
2660 static void load_buts_vfont(char *name)
2661 {
2662         VFont *vf;
2663         Curve *cu;
2664
2665         if(OBACT && OBACT->type==OB_FONT) cu= OBACT->data;
2666         else return;
2667
2668         vf= exist_vfont(name);
2669         if(vf==0) {
2670                 vf= load_vfont(name);
2671                 if(vf==0) return;
2672         }
2673         else id_us_plus((ID *)vf);
2674         
2675         switch(cu->curinfo.flag & CU_STYLE) {
2676                 case CU_BOLD:
2677                         if(cu->vfontb) cu->vfontb->id.us--;
2678                         cu->vfontb= vf;
2679                         break;
2680                 case CU_ITALIC:
2681                         if(cu->vfonti) cu->vfonti->id.us--;             
2682                         cu->vfonti= vf;
2683                         break;                                          
2684                 case (CU_BOLD|CU_ITALIC):
2685                         if(cu->vfontbi) cu->vfontbi->id.us--;
2686                         cu->vfontbi= vf;
2687                         break;
2688                 default:
2689                         if(cu->vfont) cu->vfont->id.us--;
2690                         cu->vfont= vf;
2691                         break;                                          
2692         }       
2693
2694         DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
2695         BIF_undo_push("Load vector font");
2696         allqueue(REDRAWVIEW3D, 0);
2697         allqueue(REDRAWBUTSEDIT, 0);
2698 }
2699
2700 static void set_unicode_text_fs(char *file)
2701 {
2702         if (file) paste_unicodeText(file); 
2703 }
2704
2705 void do_fontbuts(unsigned short event)
2706 {
2707         Curve *cu;
2708         VFont *vf;
2709         Object *ob;
2710         ScrArea *sa;
2711         char str[80];
2712         int ctevt;
2713         char *ctmenu;
2714         DynStr *ds;
2715         int i, style=0;
2716
2717         ob= OBACT;
2718
2719         switch(event) {
2720         case B_MAKEFONT:
2721                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2722                 allqueue(REDRAWVIEW3D, 0);
2723                 break;
2724
2725         case B_STYLETOSELU:     
2726         case B_STYLETOSELB:
2727         case B_STYLETOSELI:
2728                 switch (event) {
2729                         case B_STYLETOSELU: style = CU_UNDERLINE; break;
2730                         case B_STYLETOSELB: style = CU_BOLD; break;                     
2731                         case B_STYLETOSELI: style = CU_ITALIC; break;
2732                 }
2733                 if (style_to_sel(style, ((Curve*)ob->data)->curinfo.flag & style)) {
2734                         text_to_curve(ob, 0);
2735                         makeDispListCurveTypes(ob, 0);
2736                         allqueue(REDRAWVIEW3D, 0);
2737                 }
2738                 allqueue(REDRAWBUTSEDIT, 0);
2739                 break;          
2740                 
2741         case B_FASTFONT:
2742                 if (G.obedit) {
2743                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2744                         allqueue(REDRAWVIEW3D, 0);
2745                 }
2746                 break;
2747         case B_INSTB:
2748                 cu= ob->data;
2749                 if (cu->totbox < 256) {
2750                         for (i = cu->totbox; i>cu->actbox; i--) cu->tb[i]= cu->tb[i-1];
2751                         cu->tb[cu->actbox]= cu->tb[cu->actbox-1];
2752                         cu->actbox++;
2753                         cu->totbox++;
2754                         allqueue(REDRAWBUTSEDIT, 0);
2755                         allqueue(REDRAWVIEW3D, 0);
2756                         text_to_curve(ob, 0);
2757                         makeDispListCurveTypes(ob, 0);
2758                 }
2759                 else {
2760                         error("Do you really need that many text frames?");
2761                 }
2762                 break;
2763         case B_DELTB:
2764                 cu= ob->data;
2765                 if (cu->totbox > 1) {
2766                         for (i = cu->actbox-1; i < cu->totbox; i++) cu->tb[i]= cu->tb[i+1];
2767                         cu->totbox--;
2768                         cu->actbox--;
2769                         allqueue(REDRAWBUTSEDIT, 0);
2770                         allqueue(REDRAWVIEW3D, 0);
2771                         text_to_curve(ob, 0);
2772                         makeDispListCurveTypes(ob, 0);
2773                 }
2774                 break;
2775         case B_TOUPPER:
2776                 to_upper();
2777                 break;
2778         case B_LOADFONT:
2779                 vf= give_vfontpointer(G.buts->texnr);
2780                 if(vf && vf->id.prev!=vf->id.next) strcpy(str, vf->name);
2781                 else strcpy(str, U.fontdir);
2782
2783                 sa= closest_bigger_area();
2784                 areawinset(sa->win);
2785
2786                 activate_fileselect(FILE_LOADFONT, "SELECT FONT", str, load_buts_vfont);
2787
2788                 break;
2789         case B_PACKFONT:
2790                 if (ob) {
2791                         cu= ob->data;
2792                         if(cu && cu->vfont) {
2793                                 if (cu->vfont->packedfile) {
2794                                         if (G.fileflags & G_AUTOPACK) {
2795                                                 if (okee("Disable AutoPack ?")) {
2796                                                         G.fileflags &= ~G_AUTOPACK;
2797                                                 }
2798                                         }
2799
2800                                         if ((G.fileflags & G_AUTOPACK) == 0) {
2801                                                 if (unpackVFont(cu->vfont, PF_ASK) == RET_OK) {
2802                                                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2803                                                         allqueue(REDRAWVIEW3D, 0);
2804                                                 }
2805                                         }
2806                                 } else {
2807                                         cu->vfont->packedfile = newPackedFile(cu->vfont->name);
2808                                 }
2809                         }
2810                 }
2811                 allqueue(REDRAWHEADERS, 0);
2812                 allqueue(REDRAWBUTSEDIT, 0);
2813                 break;
2814
2815         case B_LOAD3DTEXT:
2816                 if (!G.obedit) { error("Only in editmode!"); return; }
2817                 if (G.obedit->type != OB_FONT) return;  
2818                 activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, load_3dtext_fs);
2819                 break;
2820                 
2821         case B_LOREM:
2822                 if (!G.obedit) { error("Only in editmode!"); return; }
2823                 if (G.obedit->type != OB_FONT) return;  
2824                 add_lorem();
2825                 
2826                 break;          
2827
2828         case B_SETFONT:
2829                 if(ob) {
2830                         cu= ob->data;
2831
2832                         vf= give_vfontpointer(G.buts->texnr);
2833                         if(vf) {
2834                                 id_us_plus((ID *)vf);
2835
2836                                 switch(cu->curinfo.flag & CU_STYLE) {
2837                                         case CU_BOLD:
2838                                                 cu->vfontb->id.us--;
2839                                                 cu->vfontb= vf;
2840                                                 break;
2841                                         case CU_ITALIC:
2842                                                 cu->vfonti->id.us--;
2843                                                 cu->vfonti= vf;
2844                                                 br