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