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