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