svn merge -r 12856:12937 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / source / blender / src / buttons_editing.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <time.h>
34 #include <math.h>
35 #include <stdlib.h>
36 #include <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 |= SELECT;
543                                                                         else bp->f1 &= ~SELECT;
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(ELEM(i, eModifierType_Cloth, eModifierType_Collision)) continue;
984
985                 if((mti->flags&eModifierTypeFlag_AcceptsCVs) ||
986                    (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
987                         entries[numEntries].name = mti->name;
988                         entries[numEntries].ID = i;
989
990                         ++numEntries;
991                 }
992         }
993
994         qsort(entries, numEntries, sizeof(*entries), menuEntry_compare_names);
995
996
997         for(i = 0; i < numEntries; ++i)
998                 uiDefBut(block, BUTM, B_MODIFIER_RECALC, entries[i].name,
999                          0, yco -= 20, 160, 19, NULL, 0, 0, 1, entries[i].ID, "");
1000
1001         uiTextBoundsBlock(block, 50);
1002         uiBlockSetDirection(block, UI_DOWN);
1003
1004         return block;
1005 }
1006
1007 static void modifiers_del(void *ob_v, void *md_v)
1008 {
1009         Object *ob = ob_v;
1010         ModifierData *md;
1011
1012                 /* It seems on rapid delete it is possible to
1013                  * get called twice on same modifier, so make
1014                  * sure it is in list.
1015                  */
1016         for (md=ob->modifiers.first; md; md=md->next)
1017                 if (md==md_v)
1018                         break;
1019         
1020         if (!md)
1021                 return;
1022
1023         if(md->type==eModifierType_ParticleSystem){
1024                 ParticleSystemModifierData *psmd=(ParticleSystemModifierData*)md;
1025                 BLI_remlink(&ob->particlesystem, psmd->psys);
1026                 psys_free(ob,psmd->psys);
1027         }
1028
1029         BLI_remlink(&ob->modifiers, md_v);
1030
1031         modifier_free(md_v);
1032
1033         BIF_undo_push("Del modifier");
1034 }
1035
1036 int mod_moveUp(void *ob_v, void *md_v)
1037 {
1038         Object *ob = ob_v;
1039         ModifierData *md = md_v;
1040
1041         if (md->prev) {
1042                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1043
1044                 if (mti->type!=eModifierTypeType_OnlyDeform) {
1045                         ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type);
1046
1047                         if (nmti->flags&eModifierTypeFlag_RequiresOriginalData)
1048                                 return -1;
1049                 }
1050
1051                 BLI_remlink(&ob->modifiers, md);
1052                 BLI_insertlink(&ob->modifiers, md->prev->prev, md);
1053         }
1054
1055         return 0;
1056 }
1057
1058 static void modifiers_moveUp(void *ob_v, void *md_v)
1059 {
1060         if( mod_moveUp( ob_v, md_v ) )
1061                 error("Cannot move above a modifier requiring original data.");
1062         else
1063                 BIF_undo_push("Move modifier");
1064 }
1065
1066 int mod_moveDown(void *ob_v, void *md_v)
1067 {
1068         Object *ob = ob_v;
1069         ModifierData *md = md_v;
1070
1071         if (md->next) {
1072                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1073
1074                 if (mti->flags&eModifierTypeFlag_RequiresOriginalData) {
1075                         ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type);
1076
1077                         if (nmti->type!=eModifierTypeType_OnlyDeform)
1078                                 return -1;
1079                 }
1080
1081                 BLI_remlink(&ob->modifiers, md);
1082                 BLI_insertlink(&ob->modifiers, md->next, md);
1083         }
1084
1085         return 0;
1086 }
1087
1088 static void modifiers_moveDown(void *ob_v, void *md_v)
1089 {
1090         if( mod_moveDown( ob_v, md_v ) )
1091                 error("Cannot move beyond a non-deforming modifier.");
1092         else
1093                 BIF_undo_push("Move modifier");
1094 }
1095
1096 static void modifier_testLatticeObj(char *name, ID **idpp)
1097 {
1098         ID *id;
1099
1100         for (id= G.main->object.first; id; id= id->next) {
1101                 if( strcmp(name, id->name+2)==0 ) {
1102                         if (((Object *)id)->type != OB_LATTICE) {
1103                                 error ("Lattice deform object must be a lattice");
1104                                 break;
1105                         } 
1106                         *idpp= id;
1107                         return;
1108                 }
1109         }
1110         *idpp= 0;
1111 }
1112
1113 static void modifier_testCurveObj(char *name, ID **idpp)
1114 {
1115         ID *id;
1116
1117         for (id= G.main->object.first; id; id= id->next) {
1118                 if( strcmp(name, id->name+2)==0 ) {
1119                         if (((Object *)id)->type != OB_CURVE) {
1120                                 error ("Curve deform object must be a curve");
1121                                 break;
1122                         } 
1123                         *idpp= id;
1124                         return;
1125                 }
1126         }
1127         *idpp= 0;
1128 }
1129
1130 static void modifier_testMeshObj(char *name, ID **idpp)
1131 {
1132         ID *id;
1133
1134         for (id= G.main->object.first; id; id= id->next) {
1135                 /* no boolean on its own object */
1136                 if(id != (ID *)OBACT) {
1137                         if( strcmp(name, id->name+2)==0 ) {
1138                                 if (((Object *)id)->type != OB_MESH) {
1139                                         error ("Boolean modifier object must be a mesh");
1140                                         break;
1141                                 } 
1142                                 *idpp= id;
1143                                 return;
1144                         }
1145                 }
1146         }
1147         *idpp= NULL;
1148 }
1149
1150 static void modifier_testArmatureObj(char *name, ID **idpp)
1151 {
1152         ID *id;
1153
1154         for (id= G.main->object.first; id; id= id->next) {
1155                 if( strcmp(name, id->name+2)==0 ) {
1156                         if (((Object *)id)->type != OB_ARMATURE) {
1157                                 error ("Armature deform object must be an armature");
1158                                 break;
1159                         } 
1160                         *idpp= id;
1161                         return;
1162                 }
1163         }
1164         *idpp= 0;
1165 }
1166
1167 static void modifier_testTexture(char *name, ID **idpp)
1168 {
1169         ID *id;
1170
1171         for(id = G.main->tex.first; id; id = id->next) {
1172                 if(strcmp(name, id->name + 2) == 0) {
1173                         *idpp = id;
1174                         /* texture gets user, objects not: delete object = clear modifier */
1175                         id_us_plus(id);
1176                         return;
1177                 }
1178         }
1179         *idpp = 0;
1180 }
1181
1182 #if 0 /* this is currently unused, but could be useful in the future */
1183 static void modifier_testMaterial(char *name, ID **idpp)
1184 {
1185         ID *id;
1186
1187         for(id = G.main->mat.first; id; id = id->next) {
1188                 if(strcmp(name, id->name + 2) == 0) {
1189                         *idpp = id;
1190                         return;
1191                 }
1192         }
1193         *idpp = 0;
1194 }
1195 #endif
1196
1197 static void modifier_testImage(char *name, ID **idpp)
1198 {
1199         ID *id;
1200
1201         for(id = G.main->image.first; id; id = id->next) {
1202                 if(strcmp(name, id->name + 2) == 0) {
1203                         *idpp = id;
1204                         return;
1205                 }
1206         }
1207         *idpp = 0;
1208 }
1209
1210 /* autocomplete callback for ID buttons */
1211 void autocomplete_image(char *str, void *arg_v)
1212 {
1213         /* search if str matches the beginning of an ID struct */
1214         if(str[0]) {
1215                 AutoComplete *autocpl = autocomplete_begin(str, 22);
1216                 ID *id;
1217
1218                 for(id = G.main->image.first; id; id = id->next)
1219                         autocomplete_do_name(autocpl, id->name+2);
1220
1221                 autocomplete_end(autocpl, str);
1222         }
1223 }
1224
1225 /* autocomplete callback for ID buttons */
1226 void autocomplete_meshob(char *str, void *arg_v)
1227 {
1228         /* search if str matches the beginning of an ID struct */
1229         if(str[0]) {
1230                 AutoComplete *autocpl = autocomplete_begin(str, 22);
1231                 ID *id;
1232
1233                 for(id = G.main->object.first; id; id = id->next)
1234                         if(((Object *)id)->type == OB_MESH)
1235                                 autocomplete_do_name(autocpl, id->name+2);
1236
1237                 autocomplete_end(autocpl, str);
1238         }
1239 }
1240 static void modifiers_convertParticles(void *obv, void *mdv)
1241 {
1242         Object *obn;
1243         ModifierData *md = mdv;
1244         ParticleSystem *psys;
1245         ParticleCacheKey *key, **cache;
1246         Mesh *me;
1247         MVert *mvert;
1248         MFace *mface;
1249         int a, k, kmax;
1250         int totvert=0, totface=0, cvert=0;
1251         int totpart=0, totchild=0;
1252
1253         if(md->type != eModifierType_ParticleSystem) return;
1254
1255         if(G.f & G_PARTICLEEDIT) return;
1256
1257         psys=((ParticleSystemModifierData *)md)->psys;
1258
1259         if(psys->part->draw_as != PART_DRAW_PATH || psys->pathcache == 0) return;
1260
1261         totpart= psys->totcached;
1262         totchild= psys->totchildcache;
1263
1264         if(totchild && (psys->part->draw&PART_DRAW_PARENT)==0)
1265                 totpart= 0;
1266
1267         /* count */
1268         cache= psys->pathcache;
1269         for(a=0; a<totpart; a++) {
1270                 key= cache[a];
1271                 totvert+= (int)(key->col[3])+1;
1272                 totface+= (int)(key->col[3]);
1273         }
1274
1275         cache= psys->childcache;
1276         for(a=0; a<totchild; a++) {
1277                 key= cache[a];
1278                 totvert+= (int)(key->col[3])+1;
1279                 totface+= (int)(key->col[3]);
1280         }
1281
1282         if(totvert==0) return;
1283
1284         /* add new mesh */
1285         obn= add_object(OB_MESH);
1286         me= obn->data;
1287         
1288         me->totvert= totvert;
1289         me->totface= totface;
1290         
1291         me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
1292         me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, totface);
1293         
1294         mvert= me->mvert;
1295         mface= me->mface;
1296
1297         /* copy coordinates */
1298         cache= psys->pathcache;
1299         for(a=0; a<totpart; a++){
1300                 key= cache[a];
1301                 kmax= (int)(key->col[3]);
1302                 for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
1303                         VECCOPY(mvert->co,key->co);
1304                         if(k){
1305                                 mface->v1= cvert-1;
1306                                 mface->v2= cvert;
1307                                 mface++;
1308                         }
1309                 }
1310         }
1311
1312         cache=psys->childcache;
1313         for(a=0; a<totchild; a++) {
1314                 key=cache[a];
1315                 kmax=(int)(key->col[3]);
1316                 for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
1317                         VECCOPY(mvert->co,key->co);
1318                         if(k){
1319                                 mface->v1=cvert-1;
1320                                 mface->v2=cvert;
1321                                 mface++;
1322                         }
1323                 }
1324         }
1325         make_edges(me, 0);
1326 }
1327 static void modifiers_applyModifier(void *obv, void *mdv)
1328 {
1329         Object *ob = obv;
1330         ModifierData *md = mdv;
1331         DerivedMesh *dm;
1332         Mesh *me = ob->data;
1333         int converted = 0;
1334
1335         if (G.obedit) {
1336                 error("Modifiers cannot be applied in editmode");
1337                 return;
1338         } else if (((ID*) ob->data)->us>1) {
1339                 error("Modifiers cannot be applied to multi-user data");
1340                 return;
1341         }
1342
1343         if (md!=ob->modifiers.first) {
1344                 if (!okee("Modifier is not first"))
1345                         return;
1346         }
1347
1348         if (ob->type==OB_MESH) {
1349                 if(me->mr && multires_modifier_warning()) {
1350                         error("Modifier changes topology; cannot apply with multires active");
1351                         return;
1352                 }
1353                 if(me->key) {
1354                         error("Modifier cannot be applied to Mesh with Shape Keys");
1355                         return;
1356                 }
1357         
1358                 sculptmode_pmv_off(me);
1359         
1360                 dm = mesh_create_derived_for_modifier(ob, md);
1361                 if (!dm) {
1362                         error("Modifier is disabled or returned error, skipping apply");
1363                         return;
1364                 }
1365
1366                 DM_to_mesh(dm, me);
1367                 converted = 1;
1368
1369                 dm->release(dm);
1370         } 
1371         else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
1372                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1373                 Curve *cu = ob->data;
1374                 int numVerts;
1375                 float (*vertexCos)[3];
1376
1377                 if (!okee("Apply will only change CV points, not tesselated/bevel vertices"))
1378                         return;
1379
1380                 if (!(md->mode&eModifierMode_Realtime) || (mti->isDisabled && mti->isDisabled(md))) {
1381                         error("Modifier is disabled, skipping apply");
1382                         return;
1383                 }
1384
1385                 vertexCos = curve_getVertexCos(cu, &cu->nurb, &numVerts);
1386                 mti->deformVerts(md, ob, NULL, vertexCos, numVerts);
1387                 curve_applyVertexCos(cu, &cu->nurb, vertexCos);
1388
1389                 converted = 1;
1390
1391                 MEM_freeN(vertexCos);
1392
1393                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1394         }
1395         else {
1396                 error("Cannot apply modifier for this object type");
1397                 return;
1398         }
1399
1400         if (converted) {
1401                 BLI_remlink(&ob->modifiers, md);
1402                 modifier_free(md);
1403
1404                 BIF_undo_push("Apply modifier");
1405         }
1406 }
1407
1408 static void modifiers_copyModifier(void *ob_v, void *md_v)
1409 {
1410         Object *ob = ob_v;
1411         ModifierData *md = md_v;
1412         ModifierData *nmd = modifier_new(md->type);
1413
1414         modifier_copyData(md, nmd);
1415
1416         BLI_insertlink(&ob->modifiers, md, nmd);
1417
1418         BIF_undo_push("Copy modifier");
1419 }
1420
1421 static void modifiers_setOnCage(void *ob_v, void *md_v)
1422 {
1423         Object *ob = ob_v;
1424         ModifierData *md;
1425         
1426         int i, cageIndex = modifiers_getCageIndex(ob, NULL );
1427
1428         for( i = 0, md=ob->modifiers.first; md; ++i, md=md->next )
1429                 if( md == md_v ) {
1430                         if( i >= cageIndex )
1431                                 md->mode ^= eModifierMode_OnCage;
1432                         break;
1433                 }
1434 }
1435
1436 static void modifiers_clearHookOffset(void *ob_v, void *md_v)
1437 {
1438         Object *ob = ob_v;
1439         ModifierData *md = md_v;
1440         HookModifierData *hmd = (HookModifierData*) md;
1441         
1442         if (hmd->object) {
1443                 Mat4Invert(hmd->object->imat, hmd->object->obmat);
1444                 Mat4MulSerie(hmd->parentinv, hmd->object->imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL);
1445                 BIF_undo_push("Clear hook offset");
1446         }
1447 }
1448
1449 static void modifiers_cursorHookCenter(void *ob_v, void *md_v)
1450 {
1451         Object *ob = ob_v;
1452         ModifierData *md = md_v;
1453         HookModifierData *hmd = (HookModifierData*) md;
1454
1455         if (G.vd) {
1456                 float *curs = give_cursor();
1457                 float bmat[3][3], imat[3][3];
1458
1459                 where_is_object(ob);
1460         
1461                 Mat3CpyMat4(bmat, ob->obmat);
1462                 Mat3Inv(imat, bmat);
1463
1464                 curs= give_cursor();
1465                 hmd->cent[0]= curs[0]-ob->obmat[3][0];
1466                 hmd->cent[1]= curs[1]-ob->obmat[3][1];
1467                 hmd->cent[2]= curs[2]-ob->obmat[3][2];
1468                 Mat3MulVecfl(imat, hmd->cent);
1469
1470                 BIF_undo_push("Hook cursor center");
1471         }
1472 }
1473
1474 static void modifiers_selectHook(void *ob_v, void *md_v)
1475 {
1476         ModifierData *md = md_v;
1477         HookModifierData *hmd = (HookModifierData*) md;
1478
1479         hook_select(hmd);
1480 }
1481
1482 static void modifiers_reassignHook(void *ob_v, void *md_v)
1483 {
1484         ModifierData *md = md_v;
1485         HookModifierData *hmd = (HookModifierData*) md;
1486         float cent[3];
1487         int *indexar, tot, ok;
1488         char name[32];
1489                 
1490         ok= hook_getIndexArray(&tot, &indexar, name, cent);
1491
1492         if (!ok) {
1493                 error("Requires selected vertices or active Vertex Group");
1494         } else {
1495                 if (hmd->indexar) {
1496                         MEM_freeN(hmd->indexar);
1497                 }
1498
1499                 VECCOPY(hmd->cent, cent);
1500                 hmd->indexar = indexar;
1501                 hmd->totindex = tot;
1502         }
1503 }
1504
1505 static void modifiers_convertToReal(void *ob_v, void *md_v)
1506 {
1507         Object *ob = ob_v;
1508         ModifierData *md = md_v;
1509         ModifierData *nmd = modifier_new(md->type);
1510
1511         modifier_copyData(md, nmd);
1512         nmd->mode &= ~eModifierMode_Virtual;
1513
1514         BLI_addhead(&ob->modifiers, nmd);
1515
1516         ob->partype = PAROBJECT;
1517
1518         BIF_undo_push("Modifier convert to real");
1519 }
1520
1521 static void build_uvlayer_menu_vars(CustomData *data, char **menu_string,
1522                                     int *uvlayer_tmp, char *uvlayer_name)
1523 {
1524         char strtmp[38];
1525         int totuv, i;
1526         CustomDataLayer *layer
1527                     = &data->layers[CustomData_get_layer_index(data, CD_MTFACE)];
1528
1529         *uvlayer_tmp = -1;
1530
1531         totuv = CustomData_number_of_layers(data, CD_MTFACE);
1532
1533         *menu_string = MEM_callocN(sizeof(**menu_string) * (totuv * 38 + 10),
1534                                    "menu_string");
1535         sprintf(*menu_string, "UV Layer%%t");
1536         for(i = 0; i < totuv; i++) {
1537                 /* assign first layer as uvlayer_name if uvlayer_name is null. */
1538                 if(strcmp(layer->name, uvlayer_name) == 0) *uvlayer_tmp = i + 1;
1539                 sprintf(strtmp, "|%s%%x%d", layer->name, i + 1);
1540                 strcat(*menu_string, strtmp);
1541                 layer++;
1542         }
1543
1544         /* there is no uvlayer defined, or else it was deleted. Assign active
1545          * layer, then recalc modifiers.
1546          */
1547         if(*uvlayer_tmp == -1) {
1548                 if(CustomData_get_active_layer_index(data, CD_MTFACE) != -1) {
1549                         *uvlayer_tmp = 1;
1550                         layer = data->layers;
1551                         for(i = 0; i < CustomData_get_active_layer_index(data, CD_MTFACE);
1552                             i++, layer++) {
1553                                 if(layer->type == CD_MTFACE) (*uvlayer_tmp)++;
1554                         }
1555                         strcpy(uvlayer_name, layer->name);
1556
1557                         /* update the modifiers */
1558                         do_modifier_panels(B_MODIFIER_RECALC);
1559                 } else {
1560                         /* ok we have no uv layers, so make sure menu button knows that.*/
1561                         *uvlayer_tmp = 0;
1562                 }
1563         }
1564 }
1565
1566 void set_displace_uvlayer(void *arg1, void *arg2)
1567 {
1568         DisplaceModifierData *dmd=arg1;
1569         CustomDataLayer *layer = arg2;
1570
1571         /*check we have UV layers*/
1572         if (dmd->uvlayer_tmp < 1) return;
1573         layer = layer + (dmd->uvlayer_tmp-1);
1574         
1575         strcpy(dmd->uvlayer_name, layer->name);
1576 }
1577
1578 void set_uvproject_uvlayer(void *arg1, void *arg2)
1579 {
1580         UVProjectModifierData *umd=arg1;
1581         CustomDataLayer *layer = arg2;
1582
1583         /*check we have UV layers*/
1584         if (umd->uvlayer_tmp < 1) return;
1585         layer = layer + (umd->uvlayer_tmp-1);
1586         
1587         strcpy(umd->uvlayer_name, layer->name);
1588 }
1589
1590 static void modifiers_bindMeshDeform(void *ob_v, void *md_v)
1591 {
1592         MeshDeformModifierData *mmd = (MeshDeformModifierData*) md_v;
1593         Object *ob = (Object*)ob_v;
1594
1595         if(mmd->bindcos) {
1596                 if(mmd->bindweights) MEM_freeN(mmd->bindweights);
1597                 if(mmd->bindcos) MEM_freeN(mmd->bindcos);
1598                 if(mmd->dyngrid) MEM_freeN(mmd->dyngrid);
1599                 if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences);
1600                 if(mmd->dynverts) MEM_freeN(mmd->dynverts);
1601                 mmd->bindweights= NULL;
1602                 mmd->bindcos= NULL;
1603                 mmd->dyngrid= NULL;
1604                 mmd->dyninfluences= NULL;
1605                 mmd->dynverts= NULL;
1606                 mmd->totvert= 0;
1607                 mmd->totcagevert= 0;
1608                 mmd->totinfluence= 0;
1609         }
1610         else {
1611                 DerivedMesh *dm;
1612                 int mode= mmd->modifier.mode;
1613
1614                 /* force modifier to run, it will call binding routine */
1615                 mmd->needbind= 1;
1616                 mmd->modifier.mode |= eModifierMode_Realtime;
1617
1618                 if(ob->type == OB_MESH) {
1619                         dm= mesh_create_derived_view(ob, 0);
1620                         dm->release(dm);
1621                 }
1622                 else if(ob->type == OB_LATTICE) {
1623                         lattice_calc_modifiers(ob);
1624                 }
1625                 else if(ob->type==OB_MBALL) {
1626                         makeDispListMBall(ob);
1627                 }
1628                 else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
1629                         makeDispListCurveTypes(ob, 0);
1630                 }
1631
1632                 mmd->needbind= 0;
1633                 mmd->modifier.mode= mode;
1634         }
1635 }
1636
1637 void modifiers_explodeFacepa(void *arg1, void *arg2)
1638 {
1639         ExplodeModifierData *emd=arg1;
1640
1641         emd->flag |= eExplodeFlag_CalcFaces;
1642 }
1643
1644 static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco, int *yco, int index, int cageIndex, int lastCageIndex)
1645 {
1646         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1647         uiBut *but;
1648         int isVirtual = md->mode&eModifierMode_Virtual;
1649         int x = *xco, y = *yco, color = md->error?TH_REDALERT:TH_BUT_NEUTRAL;
1650         int editing = (G.obedit==ob);
1651         short height=26, width = 295, buttonWidth = width-120-10;
1652         char str[128];
1653
1654         /* rounded header */
1655         uiBlockSetCol(block, color);
1656                 /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1657         uiDefBut(block, ROUNDBOX, 0, "", x-10, y-4, width, 25, NULL, 7.0, 0.0, 
1658                          (!isVirtual && (md->mode&eModifierMode_Expanded))?3:15, 20, ""); 
1659         uiBlockSetCol(block, TH_AUTO);
1660         
1661         /* open/close icon */
1662         if (!isVirtual && md->type!=eModifierType_Collision) {
1663                 uiBlockSetEmboss(block, UI_EMBOSSN);
1664                 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");
1665         }
1666
1667         uiBlockSetEmboss(block, UI_EMBOSS);
1668         
1669         if (isVirtual) {
1670                 sprintf(str, "%s parent deform", md->name);
1671                 uiDefBut(block, LABEL, 0, str, x+10, y-1, width-110, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name"); 
1672
1673                 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");
1674                 uiButSetFunc(but, modifiers_convertToReal, ob, md);
1675         } else {
1676                 uiBlockBeginAlign(block);
1677                 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"); 
1678
1679                 /* Softbody not allowed in this situation, enforce! */
1680                 if ((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) {
1681                         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");
1682                         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");
1683                         if (mti->flags&eModifierTypeFlag_SupportsEditmode) {
1684                                 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)");
1685                         }
1686                 }
1687                 uiBlockEndAlign(block);
1688
1689                 uiBlockSetEmboss(block, UI_EMBOSSR);
1690
1691                 if (ob->type==OB_MESH && modifier_couldBeCage(md) && index<=lastCageIndex) {
1692                         int icon, color;
1693
1694                         if (index==cageIndex) {
1695                                 color = TH_BUT_SETTING;
1696                                 icon = VICON_EDITMODE_HLT;
1697                         } else if (index<cageIndex) {
1698                                 color = TH_BUT_NEUTRAL;
1699                                 icon = VICON_EDITMODE_DEHLT;
1700                         } else {
1701                                 color = TH_BUT_NEUTRAL;
1702                                 icon = ICON_BLANK1;
1703                         }
1704                         uiBlockSetCol(block, color);
1705                         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");
1706                         uiButSetFunc(but, modifiers_setOnCage, ob, md);
1707                         uiBlockSetCol(block, TH_AUTO);
1708                 }
1709
1710                 uiBlockSetCol(block, TH_BUT_ACTION);
1711
1712                 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");
1713                 uiButSetFunc(but, modifiers_moveUp, ob, md);
1714
1715                 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");
1716                 uiButSetFunc(but, modifiers_moveDown, ob, md);
1717                 
1718                 uiBlockSetEmboss(block, UI_EMBOSSN);
1719                 
1720                 // deletion over the deflection panel
1721                 if(md->type!=eModifierType_Collision)
1722                 {
1723                         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");
1724                         uiButSetFunc(but, modifiers_del, ob, md);
1725                 }
1726                 uiBlockSetCol(block, TH_AUTO);
1727         }
1728
1729         uiBlockSetEmboss(block, UI_EMBOSS);
1730
1731         if (isVirtual || !(md->mode&eModifierMode_Expanded)) {
1732                 y -= 18;
1733         } else {
1734                 int cy = y - 8;
1735                 int lx = x + width - 60 - 15;
1736
1737                 if (md->type==eModifierType_Subsurf) {
1738                         height = 105;
1739                 } else if (md->type==eModifierType_Lattice) {
1740                         height = 48;
1741                 } else if (md->type==eModifierType_Curve) {
1742                         height = 72;
1743                 } else if (md->type==eModifierType_Build) {
1744                         height = 86;
1745                 } else if (md->type==eModifierType_Mirror) {
1746                         height = 86;
1747                 } else if (md->type==eModifierType_EdgeSplit) {
1748                         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1749                         height = 48;
1750                         if(emd->flags & MOD_EDGESPLIT_FROMANGLE) height += 19;
1751                 } else if (md->type==eModifierType_Displace) {
1752                         DisplaceModifierData *dmd = (DisplaceModifierData *)md;
1753                         height = 124;
1754                         if(dmd->texmapping == MOD_DISP_MAP_OBJECT ||
1755                            dmd->texmapping == MOD_DISP_MAP_UV)
1756                                 height += 19;
1757                 } else if (md->type==eModifierType_UVProject) {
1758                         height = 114 + ((UVProjectModifierData *)md)->num_projectors * 19;
1759                 } else if (md->type==eModifierType_Decimate) {
1760                         height = 48;
1761                 } else if (md->type==eModifierType_Smooth) {
1762                         height = 86;
1763                 } else if (md->type==eModifierType_Cast) {
1764                         height = 143;
1765                 } else if (md->type==eModifierType_Wave) {
1766                         WaveModifierData *wmd = (WaveModifierData *)md;
1767                         height = 294;
1768                         if(wmd->texmapping == MOD_WAV_MAP_OBJECT ||
1769                            wmd->texmapping == MOD_WAV_MAP_UV)
1770                                 height += 19;
1771                         if(wmd->flag & MOD_WAVE_NORM)
1772                                 height += 19;
1773                 } else if (md->type==eModifierType_Armature) {
1774                         height = 105;
1775                 } else if (md->type==eModifierType_Hook) {
1776                         HookModifierData *hmd = (HookModifierData*) md;
1777                         height = 86;
1778                         if (editing)
1779                                 height += 20;
1780                         if(hmd->indexar==NULL)
1781                                 height += 20;
1782                 } else if (md->type==eModifierType_Softbody) {
1783                         height = 31;
1784                 } else if (md->type==eModifierType_Cloth) {
1785                         height = 26;
1786                 } else if (md->type==eModifierType_Collision) {
1787                         height = 19;
1788                 } else if (md->type==eModifierType_Boolean) {
1789                         height = 48;
1790                 } else if (md->type==eModifierType_Array) {
1791                         height = 211;
1792                 } else if (md->type==eModifierType_MeshDeform) {
1793                         MeshDeformModifierData *mmd= (MeshDeformModifierData*)md;
1794                         height = (mmd->bindcos)? 73: 93;
1795                 } else if (md->type==eModifierType_ParticleSystem) {
1796                         height = 31;
1797                 } else if (md->type==eModifierType_ParticleInstance) {
1798                         height = 94;
1799                 } else if (md->type==eModifierType_Explode) {
1800                         height = 94;
1801                 }
1802                                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1803                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y-height-2, width, height-2, NULL, 5.0, 0.0, 12, 40, ""); 
1804
1805                 y -= 18;
1806
1807                 if (!isVirtual && (md->type!=eModifierType_Collision)) {
1808                         uiBlockBeginAlign(block);
1809                         if (md->type==eModifierType_ParticleSystem) {
1810                                 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");
1811                                 uiButSetFunc(but, modifiers_convertParticles, ob, md);
1812                         }
1813                         else{
1814                                 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");
1815                                 uiButSetFunc(but, modifiers_applyModifier, ob, md);
1816                         }
1817                         
1818                         if (md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (md->type!=eModifierType_Cloth)) {
1819                                 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");
1820                                 uiButSetFunc(but, modifiers_copyModifier, ob, md);
1821                         }
1822                         uiBlockEndAlign(block);
1823                 }
1824
1825                 lx = x + 10;
1826                 cy = y + 10 - 1;
1827                 uiBlockBeginAlign(block);
1828                 if (md->type==eModifierType_Subsurf) {
1829                         SubsurfModifierData *smd = (SubsurfModifierData*) md;
1830                         char subsurfmenu[]="Subsurf Type%t|Catmull-Clark%x0|Simple Subdiv.%x1";
1831                         uiDefButS(block, MENU, B_MODIFIER_RECALC, subsurfmenu,          lx,(cy-=19),buttonWidth,19, &smd->subdivType, 0, 0, 0, 0, "Selects type of subdivision algorithm.");
1832                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Levels:",             lx, (cy-=19), buttonWidth,19, &smd->levels, 1, 6, 0, 0, "Number subdivisions to perform");
1833                         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");
1834
1835                         /* Disabled until non-EM DerivedMesh implementation is complete */
1836
1837                         /*
1838                         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");
1839                         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");
1840                         */
1841
1842                         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");
1843                         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");
1844                 } else if (md->type==eModifierType_Lattice) {
1845                         LatticeModifierData *lmd = (LatticeModifierData*) md;
1846                         uiDefIDPoinBut(block, modifier_testLatticeObj, ID_OB, B_CHANGEDEP, "Ob: ",      lx, (cy-=19), buttonWidth,19, &lmd->object, "Lattice object to deform with");
1847                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &lmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1848                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1849                 } else if (md->type==eModifierType_Curve) {
1850                         CurveModifierData *cmd = (CurveModifierData*) md;
1851                         uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &cmd->object, "Curve object to deform with");
1852                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &cmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1853                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1854                         
1855                         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");
1856                         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");
1857                         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");
1858                         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");
1859                         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");
1860                         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");
1861                 } else if (md->type==eModifierType_Build) {
1862                         BuildModifierData *bmd = (BuildModifierData*) md;
1863                         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");
1864                         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");
1865                         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.");
1866                         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.");
1867                 } else if (md->type==eModifierType_Mirror) {
1868                         MirrorModifierData *mmd = (MirrorModifierData*) md;
1869                         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");
1870                         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");
1871                         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");
1872                         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");
1873                         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");
1874                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_U, B_MODIFIER_RECALC,
1875                                      "Mirror U",
1876                                      lx, (cy-=19), buttonWidth/2, 19,
1877                                      &mmd->flag, 0, 0, 0, 0,
1878                                      "Mirror the U texture coordinate around "
1879                                      "the 0.5 point");
1880                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_V, B_MODIFIER_RECALC,
1881                                      "Mirror V",
1882                                      lx + buttonWidth/2 + 1, cy, buttonWidth/2, 19,
1883                                      &mmd->flag, 0, 0, 0, 0,
1884                                      "Mirror the V texture coordinate around "
1885                                      "the 0.5 point");
1886                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1887                                        "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1888                                        &mmd->mirror_ob,
1889                                        "Object to use as mirror");
1890
1891                 } else if (md->type==eModifierType_EdgeSplit) {
1892                         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1893                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMANGLE,
1894                                      B_MODIFIER_RECALC, "From Edge Angle",
1895                                      lx, (cy -= 19), buttonWidth, 19,
1896                                      &emd->flags, 0, 0, 0, 0,
1897                                      "Split edges with high angle between faces");
1898                         if(emd->flags & MOD_EDGESPLIT_FROMANGLE) {
1899                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Split Angle:",
1900                                           lx, (cy -= 19), buttonWidth, 19, &emd->split_angle,
1901                                           0.0, 180.0, 100, 2,
1902                                           "Angle above which to split edges");
1903                         }
1904                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMFLAG,
1905                                      B_MODIFIER_RECALC, "From Marked As Sharp",
1906                                      lx, (cy -= 19), buttonWidth, 19,
1907                                      &emd->flags, 0, 0, 0, 0,
1908                                      "Split edges that are marked as sharp");
1909                 } else if (md->type==eModifierType_Displace) {
1910                         DisplaceModifierData *dmd = (DisplaceModifierData*) md;
1911                         but = uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",
1912                                        lx, (cy -= 19), buttonWidth, 19,
1913                                        &dmd->defgrp_name, 0.0, 31.0, 0, 0,
1914                                        "Name of vertex group to displace"
1915                                        " (displace whole mesh if blank)");
1916                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1917                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,
1918                                        "Texture: ", lx, (cy -= 19), buttonWidth, 19,
1919                                        &dmd->texture,
1920                                        "Texture to use as displacement input");
1921                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Midlevel:",
1922                                   lx, (cy -= 19), buttonWidth, 19, &dmd->midlevel,
1923                                   0, 1, 10, 3,
1924                                   "Material value that gives no displacement");
1925                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Strength:",
1926                                   lx, (cy -= 19), buttonWidth, 19, &dmd->strength,
1927                                   -1000, 1000, 10, 0.1,
1928                                   "Strength of displacement");
1929                         sprintf(str, "Direction%%t|Normal%%x%d|RGB -> XYZ%%x%d|"
1930                                 "Z%%x%d|Y%%x%d|X%%x%d",
1931                                 MOD_DISP_DIR_NOR, MOD_DISP_DIR_RGB_XYZ,
1932                                 MOD_DISP_DIR_Z, MOD_DISP_DIR_Y, MOD_DISP_DIR_X);
1933                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1934                                   lx, (cy -= 19), buttonWidth, 19, &dmd->direction,
1935                                   0.0, 1.0, 0, 0, "Displace direction");
1936                         sprintf(str, "Texture Coordinates%%t"
1937                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
1938                                 MOD_DISP_MAP_LOCAL, MOD_DISP_MAP_GLOBAL,
1939                                 MOD_DISP_MAP_OBJECT, MOD_DISP_MAP_UV);
1940                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1941                                   lx, (cy -= 19), buttonWidth, 19, &dmd->texmapping,
1942                                   0.0, 1.0, 0, 0,
1943                                   "Texture coordinates used for displacement input");
1944                         if (dmd->texmapping == MOD_DISP_MAP_UV) {
1945                                 char *strtmp;
1946                                 int i;
1947                                 CustomData *fdata = G.obedit ? &G.editMesh->fdata
1948                                                              : &((Mesh*)ob->data)->fdata;
1949                                 build_uvlayer_menu_vars(fdata, &strtmp, &dmd->uvlayer_tmp,
1950                                                         dmd->uvlayer_name);
1951                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
1952                                       lx, (cy -= 19), buttonWidth, 19, &dmd->uvlayer_tmp,
1953                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
1954                                 MEM_freeN(strtmp);
1955                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
1956                                 uiButSetFunc(but, set_displace_uvlayer, dmd,
1957                                              &fdata->layers[i]);
1958                         }
1959                         if(dmd->texmapping == MOD_DISP_MAP_OBJECT) {
1960                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1961                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1962                                                &dmd->map_object,
1963                                                "Object to get texture coordinates from");
1964                         }
1965                 } else if (md->type==eModifierType_UVProject) {
1966                         UVProjectModifierData *umd = (UVProjectModifierData *) md;
1967                         int i;
1968                         char *strtmp;
1969                         CustomData *fdata = G.obedit ? &G.editMesh->fdata
1970                                                      : &((Mesh*)ob->data)->fdata;
1971                         build_uvlayer_menu_vars(fdata, &strtmp, &umd->uvlayer_tmp,
1972                                                 umd->uvlayer_name);
1973                         but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
1974                               lx, (cy -= 19), buttonWidth, 19, &umd->uvlayer_tmp,
1975                               0.0, 1.0, 0, 0, "Set the UV layer to use");
1976                         i = CustomData_get_layer_index(fdata, CD_MTFACE);
1977                         uiButSetFunc(but, set_uvproject_uvlayer, umd, &fdata->layers[i]);
1978                         MEM_freeN(strtmp);
1979                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspX:",
1980                                   lx, (cy -= 19), buttonWidth / 2, 19, &umd->aspectx,
1981                                   1, 1000, 100, 2,
1982                                   "Horizontal Aspect Ratio");
1983                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspY:",
1984                                   lx + (buttonWidth / 2) + 1, cy, buttonWidth / 2, 19,
1985                                   &umd->aspecty,
1986                                   1, 1000, 100, 2,
1987                                   "Vertical Aspect Ratio");
1988                         uiDefButI(block, NUM, B_MODIFIER_RECALC, "Projectors:",
1989                                   lx, (cy -= 19), buttonWidth, 19, &umd->num_projectors,
1990                                   1, MOD_UVPROJECT_MAXPROJECTORS, 0, 0,
1991                                   "Number of objects to use as projectors");
1992                         for(i = 0; i < umd->num_projectors; ++i) {
1993                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1994                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1995                                                &umd->projectors[i],
1996                                                "Object to use as projector");
1997                         }
1998                         uiDefIDPoinBut(block, modifier_testImage, ID_IM, B_CHANGEDEP,
1999                                        "Image: ", lx, (cy -= 19), buttonWidth, 19,
2000                                        &umd->image,
2001                                        "Image to project (only faces with this image "
2002                                        "will be altered");
2003                         uiButSetCompleteFunc(but, autocomplete_image, (void *)ob);
2004                         uiDefButBitI(block, TOG, MOD_UVPROJECT_OVERRIDEIMAGE,
2005                                      B_MODIFIER_RECALC, "Override Image",
2006                                      lx, (cy -= 19), buttonWidth, 19,
2007                                      &umd->flags, 0, 0, 0, 0,
2008                                      "Override faces' current images with the "
2009                                      "given image");
2010                 } else if (md->type==eModifierType_Decimate) {
2011                         DecimateModifierData *dmd = (DecimateModifierData*) md;
2012                         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");
2013                         sprintf(str, "Face Count: %d", dmd->faceCount);
2014                         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");
2015                 } else if (md->type==eModifierType_Smooth) {
2016                         SmoothModifierData *smd = (SmoothModifierData*) md;
2017
2018                         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");
2019                         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");
2020                         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");
2021
2022                         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)");
2023                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Repeat:",     lx,(cy-=19),buttonWidth, 19, &smd->repeat, 0.0, 30.0, 1, 0, "Number of smoothing iterations");
2024                         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");
2025                 } else if (md->type==eModifierType_Cast) {
2026                         CastModifierData *cmd = (CastModifierData*) md;
2027
2028                         char casttypemenu[]="Projection Type%t|Sphere%x0|Cylinder%x1|Cuboid%x2";
2029                         uiDefButS(block, MENU, B_MODIFIER_RECALC, casttypemenu,         lx,(cy-=19),buttonWidth - 30,19, &cmd->type, 0, 0, 0, 0, "Projection type to apply");
2030                         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");
2031                         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");
2032                         if (cmd->type != MOD_CAST_TYPE_CYLINDER) {
2033                                 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");
2034                         }
2035                         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");
2036                         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)");
2037                         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)");
2038                         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)");
2039                         if (ob->type == OB_MESH) {
2040                                 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");
2041                         }
2042                         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");
2043                         if(cmd->object) {
2044                                 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");
2045                         }
2046                 } else if (md->type==eModifierType_Wave) {
2047                         WaveModifierData *wmd = (WaveModifierData*) md;
2048                         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");
2049                         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");
2050                         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");
2051                         uiDefButBitS(block, TOG, MOD_WAVE_NORM, B_MODIFIER_RECALC, "Normals",   lx,(cy-=19),buttonWidth,19, &wmd->flag, 0, 0, 0, 0, "Displace along normals");
2052                         if (wmd->flag & MOD_WAVE_NORM){
2053                                 if (ob->type==OB_MESH) {
2054                                         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");
2055                                         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");
2056                                         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");
2057                                 }
2058                                 else
2059                                         uiDefBut(block, LABEL, 1, "Meshes Only",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");                                
2060                         }
2061
2062                         uiBlockBeginAlign(block);
2063                         if(wmd->speed >= 0)
2064                                 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");
2065                         else
2066                                 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");
2067                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Lifetime:",   lx,(cy-=19),buttonWidth,19, &wmd->lifetime,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the lifespan of the wave");
2068                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Damptime:",   lx,(cy-=19),buttonWidth,19, &wmd->damp,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the dampingtime of the wave");
2069                         cy -= 9;
2070                         uiBlockBeginAlign(block);
2071                         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");
2072                         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");
2073                         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)");
2074                         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");
2075                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,"Texture: ", lx, (cy -= 19), 220, 19, &wmd->texture,"Texture with which to modulate wave");
2076                         sprintf(str, "Texture Coordinates%%t"
2077                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
2078                                 MOD_WAV_MAP_LOCAL, MOD_WAV_MAP_GLOBAL,
2079                                 MOD_WAV_MAP_OBJECT, MOD_WAV_MAP_UV);
2080                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2081                                   lx, (cy -= 19), 220, 19, &wmd->texmapping,
2082                                   0.0, 1.0, 0, 0,
2083                                   "Texture coordinates used for modulation input");
2084                         if (wmd->texmapping == MOD_WAV_MAP_UV) {
2085                                 char *strtmp;
2086                                 int i;
2087                                 CustomData *fdata = G.obedit ? &G.editMesh->fdata
2088                                                              : &((Mesh*)ob->data)->fdata;
2089                                 build_uvlayer_menu_vars(fdata, &strtmp, &wmd->uvlayer_tmp,
2090                                                         wmd->uvlayer_name);
2091                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
2092                                       lx, (cy -= 19), 220, 19, &wmd->uvlayer_tmp,
2093                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
2094                                 MEM_freeN(strtmp);
2095                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
2096                                 uiButSetFunc(but, set_displace_uvlayer, wmd,
2097                                              &fdata->layers[i]);
2098                         }
2099                         if(wmd->texmapping == MOD_DISP_MAP_OBJECT) {
2100                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2101                                                "Ob: ", lx, (cy -= 19), 220, 19,
2102                                                &wmd->map_object,
2103                                                "Object to get texture coordinates from");
2104                         }
2105             cy -= 9;
2106                         uiBlockBeginAlign(block);
2107                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Speed:",   lx,(cy-=19),220,19, &wmd->speed, -2.0, 2.0, 0, 0, "Specify the wave speed");
2108                         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");
2109                         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");
2110                         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");
2111                 } else if (md->type==eModifierType_Armature) {
2112                         ArmatureModifierData *amd = (ArmatureModifierData*) md;
2113                         uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &amd->object, "Armature object to deform with");
2114                         
2115                         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");
2116                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2117                         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");
2118                         
2119                         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");
2120                         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");
2121                         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");
2122                         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");
2123                         
2124                         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");
2125
2126                 } else if (md->type==eModifierType_Hook) {
2127                         HookModifierData *hmd = (HookModifierData*) md;
2128                         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");
2129                         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");
2130                         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"); 
2131                         if(hmd->indexar==NULL) {
2132                                 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &hmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
2133                                 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2134                         }
2135                         uiBlockBeginAlign(block);
2136                         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");
2137                         uiButSetFunc(but, modifiers_clearHookOffset, ob, md);
2138                         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");
2139                         uiButSetFunc(but, modifiers_cursorHookCenter, ob, md);
2140
2141                         if (editing) {
2142                                 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");
2143                                 uiButSetFunc(but, modifiers_selectHook, ob, md);
2144                                 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");
2145                                 uiButSetFunc(but, modifiers_reassignHook, ob, md);
2146                         }
2147                 } else if (md->type==eModifierType_Softbody) {
2148                         uiDefBut(block, LABEL, 1, "See Softbody panel.",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2149                 } else if (md->type==eModifierType_Boolean) {
2150                         BooleanModifierData *bmd = (BooleanModifierData*) md;
2151                         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");
2152                         uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &bmd->object, "Mesh object to use for boolean operation");
2153                 } else if (md->type==eModifierType_Array) {
2154                         ArrayModifierData *amd = (ArrayModifierData*) md;
2155                         float range = 10000;
2156                         int cytop, halfwidth = (width - 5)/2 - 15;
2157                         int halflx = lx + halfwidth + 10;
2158
2159                         uiBlockSetEmboss(block, UI_EMBOSSX);
2160                         uiBlockEndAlign(block);
2161
2162                         /* length parameters */
2163                         uiBlockBeginAlign(block);
2164                         sprintf(str, "Length Fit%%t|Fixed Count%%x%d|Fixed Length%%x%d"
2165                                 "|Fit To Curve Length%%x%d",
2166                                 MOD_ARR_FIXEDCOUNT, MOD_ARR_FITLENGTH, MOD_ARR_FITCURVE);
2167                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2168                                   lx, (cy-=19), buttonWidth, 19, &amd->fit_type,
2169                                   0.0, 1.0, 0, 0, "Array length calculation method");
2170                         switch(amd->fit_type)
2171                         {
2172                         case MOD_ARR_FIXEDCOUNT:
2173                                 uiDefButI(block, NUM, B_MODIFIER_RECALC, "Count:",
2174                                           lx, (cy -= 19), buttonWidth, 19, &amd->count,
2175                                           1, 1000, 0, 0, "Number of duplicates to make");
2176                                 break;
2177                         case MOD_ARR_FITLENGTH:
2178                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Length:",
2179                                           lx, (cy -= 19), buttonWidth, 19, &amd->length,
2180                                           0, range, 10, 2,
2181                                           "Length to fit array within");
2182                                 break;
2183                         case MOD_ARR_FITCURVE:
2184                                 uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB,
2185                                                B_CHANGEDEP, "Ob: ",
2186                                                lx, (cy -= 19), buttonWidth, 19, &amd->curve_ob,
2187                                                "Curve object to fit array length to");
2188                                 break;
2189                         }
2190                         uiBlockEndAlign(block);
2191
2192                         /* offset parameters */
2193                         cy -= 10;
2194                         cytop= cy;
2195                         uiBlockBeginAlign(block);
2196                         uiDefButBitI(block, TOG, MOD_ARR_OFF_CONST, B_MODIFIER_RECALC,
2197                                      "Constant Offset", lx, (cy-=19), halfwidth, 19,
2198                                      &amd->offset_type, 0, 0, 0, 0,
2199                                      "Constant offset between duplicates "
2200                                      "(local coordinates)");
2201                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2202                                   lx, (cy-=19), halfwidth, 19,
2203                                   &amd->offset[0],
2204                                   -range, range, 10, 3,
2205                                   "Constant component for duplicate offsets "
2206                                   "(local coordinates)");
2207                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2208                                   lx, (cy-=19), halfwidth, 19,
2209                                   &amd->offset[1],
2210                                   -range, range, 10, 3,
2211                                   "Constant component for duplicate offsets "
2212                                   "(local coordinates)");
2213                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2214                                   lx, (cy-=19), halfwidth, 19,
2215                                   &amd->offset[2],
2216                                   -range, range, 10, 3,
2217                                   "Constant component for duplicate offsets "
2218                                   "(local coordinates)");
2219                         uiBlockEndAlign(block);
2220
2221                         cy= cytop;
2222                         uiBlockBeginAlign(block);
2223                         uiDefButBitI(block, TOG, MOD_ARR_OFF_RELATIVE, B_MODIFIER_RECALC,
2224                                      "Relative Offset", halflx, (cy-=19), halfwidth, 19,
2225                                      &amd->offset_type, 0, 0, 0, 0,
2226                                      "Offset between duplicates relative to object width "
2227                                      "(local coordinates)");
2228                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2229                                   halflx, (cy-=19), halfwidth, 19,
2230                                   &amd->scale[0],
2231                                   -range, range, 10, 3,
2232                                   "Component for duplicate offsets relative to object "
2233                                   "width (local coordinates)");
2234                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2235                                   halflx, (cy-=19), halfwidth, 19,
2236                                   &amd->scale[1],
2237                                   -range, range, 10, 3,
2238                                   "Component for duplicate offsets relative to object "
2239                                   "width (local coordinates)");
2240                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2241                                   halflx, (cy-=19), halfwidth, 19,
2242                                   &amd->scale[2],
2243                                   -range, range, 10, 3,
2244                                   "Component for duplicate offsets relative to object "
2245                                   "width (local coordinates)");
2246                         uiBlockEndAlign(block);
2247
2248                         /* vertex merging parameters */
2249                         cy -= 10;
2250                         cytop= cy;
2251
2252                         uiBlockBeginAlign(block);
2253                         uiDefButBitI(block, TOG, MOD_ARR_MERGE, B_MODIFIER_RECALC,
2254                                      "Merge",
2255                                      lx, (cy-=19), halfwidth/2, 19, &amd->flags,
2256                                      0, 0, 0, 0,
2257                                      "Merge vertices in adjacent duplicates");
2258                         uiDefButBitI(block, TOG, MOD_ARR_MERGEFINAL, B_MODIFIER_RECALC,
2259                                      "First Last",
2260                                      lx + halfwidth/2, cy, (halfwidth+1)/2, 19,
2261                                      &amd->flags,
2262                                      0, 0, 0, 0,
2263                                      "Merge vertices in first duplicate with vertices"
2264                                      " in last duplicate");
2265                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Limit:",
2266                                           lx, (cy-=19), halfwidth, 19, &amd->merge_dist,
2267                                           0, 1.0f, 1, 4,
2268                                           "Limit below which to merge vertices");
2269
2270                         /* offset ob */
2271                         cy = cytop;
2272                         uiBlockBeginAlign(block);
2273                         uiDefButBitI(block, TOG, MOD_ARR_OFF_OBJ, B_MODIFIER_RECALC,
2274                                      "Object Offset", halflx, (cy -= 19), halfwidth, 19,
2275                                      &amd->offset_type, 0, 0, 0, 0,
2276                                      "Add an object transformation to the total offset");
2277                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2278                                        "Ob: ", halflx, (cy -= 19), halfwidth, 19,
2279                                        &amd->offset_ob,
2280                                        "Object from which to take offset transformation");
2281                         uiBlockEndAlign(block);
2282
2283                         cy -= 10;
2284                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2285                                              B_CHANGEDEP, "Start cap: ",
2286                                              lx, (cy -= 19), halfwidth, 19,
2287                                              &amd->start_cap,
2288                                              "Mesh object to use as start cap");
2289                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2290                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2291                                              B_CHANGEDEP, "End cap: ",
2292                                              halflx, cy, halfwidth, 19,
2293                                              &amd->end_cap,
2294                                              "Mesh object to use as end cap");
2295                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2296                 } else if (md->type==eModifierType_MeshDeform) {
2297                         MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
2298
2299                         uiBlockBeginAlign(block);
2300                         uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &mmd->object, "Mesh object to be use as cage"); 
2301                         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");
2302                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2303                         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");
2304
2305                         uiBlockBeginAlign(block);
2306                         if(mmd->bindcos) {
2307                                 but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Unbind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Unbind mesh from cage");
2308                                 uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
2309                         }
2310                         else {
2311                                 but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Bind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Bind mesh to cage");
2312                                 uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
2313                                 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");
2314                                 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");
2315                         }
2316                         uiBlockEndAlign(block);
2317                 } else if (md->type==eModifierType_ParticleSystem) {
2318                         uiDefBut(block, LABEL, 1, "See Particle buttons.",      lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2319                 } else if (md->type==eModifierType_ParticleInstance) {
2320                         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
2321                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy -= 19), buttonWidth, 19, &pimd->ob, "Object that has the particlesystem");
2322                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "PSYS:", lx, (cy -= 19), buttonWidth, 19, &pimd->psys, 1, 10, 10, 3, "Particlesystem number in the object");
2323                         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");
2324                         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");
2325                         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");
2326                         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");
2327                         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");
2328                         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");
2329                 } else if (md->type==eModifierType_Explode) {
2330                         ExplodeModifierData *emd = (ExplodeModifierData*) md;
2331                         uiBut *but;
2332                         char *menustr= get_vertexgroup_menustr(ob);
2333                         int defCount=BLI_countlist(&ob->defbase);
2334                         if(defCount==0) emd->vgroup=0;
2335
2336                         but=uiDefButS(block, MENU, B_MODIFIER_RECALC, menustr,  lx, (cy-=19), buttonWidth/2,19, &emd->vgroup, 0, defCount, 0, 0, "Protect this vertex group");
2337                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2338                         MEM_freeN(menustr);
2339
2340                         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");
2341                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2342
2343                         but=uiDefBut(block, BUT, B_MODIFIER_RECALC, "Refresh",  lx, (cy-=19), buttonWidth/2,19, 0, 0, 0, 0, 0, "Recalculate faces assigned to particles");
2344                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2345
2346                         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");
2347                         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");
2348                         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");
2349                         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");
2350                 }
2351
2352                 uiBlockEndAlign(block);
2353
2354                 y-=height;
2355         }
2356
2357         if (md->error) {
2358                 char str[512];
2359
2360                 y -= 20;
2361
2362                 uiBlockSetCol(block, color);
2363                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
2364                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y, width, 20, NULL, 5.0, 0.0, 15, 40, ""); 
2365                 uiBlockSetCol(block, TH_AUTO);
2366
2367                 sprintf(str, "Modifier Error: %s", md->error);
2368                 uiDefBut(block, LABEL, B_NOP, str, x+15, y+15, width-35, 19, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
2369         }
2370
2371         uiClearButLock();
2372
2373         y -= 3+6;
2374
2375         *xco = x;
2376         *yco = y;
2377 }
2378
2379 static void editing_panel_modifiers(Object *ob)
2380 {
2381         ModifierData *md;
2382         uiBlock *block;
2383         char str[64];
2384         int xco, yco, i, lastCageIndex, cageIndex = modifiers_getCageIndex(ob, &lastCageIndex);
2385
2386         block= uiNewBlock(&curarea->uiblocks, "editing_panel_modifiers", UI_EMBOSS, UI_HELV, curarea->win);
2387         if( uiNewPanel(curarea, block, "Modifiers", "Editing", 640, 0, 318, 204)==0) return;
2388         
2389         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2390         uiNewPanelHeight(block, 204);
2391
2392         uiDefBlockBut(block, modifiers_add_menu, ob, "Add Modifier", 0, 190, 130, 20, "Add a new modifier");
2393
2394         sprintf(str, "To: %s", ob->id.name+2);
2395         uiDefBut(block, LABEL, 1, str,  140, 190, 150, 20, NULL, 0.0, 0.0, 0, 0, "Object whose modifier stack is being edited");
2396
2397         xco = 0;
2398         yco = 160;
2399
2400         md = modifiers_getVirtualModifierList(ob);
2401
2402         for (i=0; md; i++, md=md->next) {
2403                 draw_modifier(block, ob, md, &xco, &yco, i, cageIndex, lastCageIndex);
2404                 if (md->mode&eModifierMode_Virtual) i--;
2405         }
2406         
2407         if(yco < 0) uiNewPanelHeight(block, 204-yco);
2408 }
2409
2410 static char *make_key_menu(Key *key, int startindex)
2411 {
2412         KeyBlock *kb;
2413         int index= 1;
2414         char *str, item[64];
2415
2416         for (kb = key->block.first; kb; kb=kb->next, index++);
2417         str= MEM_mallocN(index*40, "key string");
2418         str[0]= 0;
2419         
2420         index= startindex;
2421         for (kb = key->block.first; kb; kb=kb->next, index++) {
2422                 sprintf (item,  "|%s%%x%d", kb->name, index);
2423                 strcat(str, item);
2424         }
2425         
2426         return str;
2427 }
2428
2429 static void editing_panel_shapes(Object *ob)
2430 {
2431         uiBlock *block;
2432         Key *key= NULL;
2433         KeyBlock *kb;
2434         int icon;
2435         char *strp;
2436         
2437         block= uiNewBlock(&curarea->uiblocks, "editing_panel_shapes", UI_EMBOSS, UI_HELV, curarea->win);
2438         uiNewPanelTabbed("Modifiers", "Editing");
2439         if( uiNewPanel(curarea, block, "Shapes", "Editing", 640, 0, 318, 204)==0) return;
2440         
2441         /* Todo check data is library here */
2442         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2443         
2444         uiDefBut(block, BUT, B_ADDKEY, "Add Shape Key" ,        10, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "Add new Shape Key");
2445         
2446         key= ob_get_key(ob);
2447         if(key==NULL) {
2448                 /* label aligns add button */
2449                 uiDefBut(block, LABEL, 0, "",           170, 180,140,20, NULL, 0, 0, 0, 0, "");
2450                 return;
2451         }
2452         
2453         uiDefButS(block, TOG, B_RELKEY, "Relative",             170, 180,140,20, &key->type, 0, 0, 0, 0, "Makes Shape Keys relative");
2454
2455         kb= BLI_findlink(&key->block, ob->shapenr-1);
2456         if(kb==NULL) {
2457                 ob->shapenr= 1;
2458                 kb= key->block.first;
2459         }
2460
2461         uiBlockBeginAlign(block);
2462         if(ob->shapeflag & OB_SHAPE_LOCK) icon= ICON_PIN_HLT; else icon= ICON_PIN_DEHLT;
2463         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");
2464         if(kb->flag & KEYBLOCK_MUTE) icon= ICON_MUTE_IPO_ON; else icon = ICON_MUTE_IPO_OFF;
2465         uiDefIconButBitS(block, TOG, KEYBLOCK_MUTE, B_MODIFIER_RECALC, icon, 35,150,20,20, &kb->flag, 0, 0, 0, 0, "Mute the current Shape");
2466         uiSetButLock(G.obedit==ob, "Unable to perform in EditMode");
2467         uiDefIconBut(block, BUT, B_PREVKEY, ICON_TRIA_LEFT,             55,150,20,20, NULL, 0, 0, 0, 0, "Previous Shape Key");
2468         strp= make_key_menu(key, 1);
2469         uiDefButS(block, MENU, B_SETKEY, strp,                                  75,150,20,20, &ob->shapenr, 0, 0, 0, 0, "Browse existing choices");
2470         MEM_freeN(strp);
2471         
2472         uiDefIconBut(block, BUT, B_NEXTKEY, ICON_TRIA_RIGHT,    95,150,20,20, NULL, 0, 0, 0, 0, "Next Shape Key");
2473         uiClearButLock();
2474         uiDefBut(block, TEX, B_NAMEKEY, "",                                             115, 150, 170, 20, kb->name, 0.0, 31.0, 0, 0, "Current Shape Key name");
2475         uiDefIconBut(block, BUT, B_DELKEY, ICON_X,                              285,150,25,20, 0, 0, 0, 0, 0, "Deletes current Shape Key");
2476         uiBlockEndAlign(block);
2477
2478         if(key->type && (ob->shapeflag & OB_SHAPE_LOCK)==0 && ob->shapenr!=1) {
2479                 uiBlockBeginAlign(block);
2480                 make_rvk_slider(block, ob, ob->shapenr-1,                       10, 120, 150, 20, "Key value, when used it inserts an animation curve point");
2481                 uiDefButF(block, NUM, B_REDR, "Min ",                           160,120, 75, 20, &kb->slidermin, -10.0, 10.0, 100, 1, "Minumum for slider");
2482                 uiDefButF(block, NUM, B_REDR, "Max ",                           235,120, 75, 20, &kb->slidermax, -10.0, 10.0, 100, 1, "Maximum for slider");
2483                 uiBlockEndAlign(block);
2484         }
2485         if(key->type && ob->shapenr!=1) {
2486                 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");
2487
2488                 strp= make_key_menu(key, 0);
2489                 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");
2490                 MEM_freeN(strp);
2491         }
2492         
2493         if(key->type==0)
2494                 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");
2495         
2496 }
2497
2498 /* *************************** FONT ******************************** */
2499
2500 static short give_vfontnr(VFont *vfont)
2501 {
2502         VFont *vf;
2503         short nr= 1;
2504
2505         vf= G.main->vfont.first;
2506         while(vf) {
2507                 if(vf==vfont) return nr;
2508                 nr++;
2509                 vf= vf->id.next;
2510         }
2511         return -1;
2512 }
2513
2514 static VFont *give_vfontpointer(int nr) /* nr= button */
2515 {
2516         VFont *vf;
2517         short tel= 1;
2518
2519         vf= G.main->vfont.first;
2520         while(vf) {
2521                 if(tel==nr) return vf;
2522                 tel++;
2523                 vf= vf->id.next;
2524         }
2525         return G.main->vfont.first;
2526 }
2527
2528 VFont *exist_vfont(char *str)
2529 {
2530         VFont *vf;
2531
2532         vf= G.main->vfont.first;
2533         while(vf) {
2534                 if(strcmp(vf->name, str)==0) return vf;
2535                 vf= vf->id.next;
2536         }
2537         return 0;
2538 }
2539
2540 static char *give_vfontbutstr(void)
2541 {
2542         VFont *vf;
2543         int len= 0;
2544         char *str, di[FILE_MAXDIR], fi[FILE_MAXFILE];
2545
2546         vf= G.main->vfont.first;
2547         while(vf) {
2548                 strcpy(di, vf->name);
2549                 BLI_splitdirstring(di, fi);
2550                 len+= strlen(fi)+4;
2551                 vf= vf->id.next;
2552         }
2553
2554         str= MEM_callocN(len+21, "vfontbutstr");
2555         strcpy(str, "FONTS %t");
2556         vf= G.main->vfont.first;
2557         while(vf) {
2558
2559                 if(vf->id.us==0) strcat(str, "|0 ");
2560                 else strcat(str, "|   ");
2561
2562                 strcpy(di, vf->name);
2563                 BLI_splitdirstring(di, fi);
2564
2565                 strcat(str, fi);
2566                 vf= vf->id.next;
2567         }
2568         return str;
2569 }
2570
2571 static void load_buts_vfont(char *name)
2572 {
2573         VFont *vf;
2574         Curve *cu;
2575
2576         if(OBACT && OBACT->type==OB_FONT) cu= OBACT->data;
2577         else return;
2578
2579         vf= exist_vfont(name);
2580         if(vf==0) {
2581                 vf= load_vfont(name);
2582                 if(vf==0) return;
2583         }
2584         else id_us_plus((ID *)vf);
2585         
2586         switch(cu->curinfo.flag & CU_STYLE) {
2587                 case CU_BOLD:
2588                         if(cu->vfontb) cu->vfontb->id.us--;
2589                         cu->vfontb= vf;
2590                         break;
2591                 case CU_ITALIC:
2592                         if(cu->vfonti) cu->vfonti->id.us--;             
2593                         cu->vfonti= vf;
2594                         break;                                          
2595                 case (CU_BOLD|CU_ITALIC):
2596                         if(cu->vfontbi) cu->vfontbi->id.us--;
2597                         cu->vfontbi= vf;
2598                         break;
2599                 default:
2600                         if(cu->vfont) cu->vfont->id.us--;
2601                         cu->vfont= vf;
2602                         break;                                          
2603         }       
2604
2605         DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
2606         BIF_undo_push("Load vector font");
2607         allqueue(REDRAWVIEW3D, 0);
2608         allqueue(REDRAWBUTSEDIT, 0);
2609 }
2610
2611 static void set_unicode_text_fs(char *file)
2612 {
2613         if (file > 0) paste_unicodeText(file); 
2614 }
2615
2616 void do_fontbuts(unsigned short event)
2617 {
2618         Curve *cu;
2619         VFont *vf;
2620         Object *ob;
2621         ScrArea *sa;
2622         char str[80];
2623         int ctevt;
2624         char *ctmenu;
2625         DynStr *ds;
2626         int i, style=0;
2627
2628         ob= OBACT;
2629
2630         switch(event) {
2631         case B_MAKEFONT:
2632                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2633                 allqueue(REDRAWVIEW3D, 0);
2634                 break;
2635
2636         case B_STYLETOSELU:     
2637         case B_STYLETOSELB:
2638         case B_STYLETOSELI:
2639                 switch (event) {
2640                         case B_STYLETOSELU: style = CU_UNDERLINE; break;
2641                         case B_STYLETOSELB: style = CU_BOLD; break;                     
2642                         case B_STYLETOSELI: style = CU_ITALIC; break;
2643                 }
2644                 if (style_to_sel(style, ((Curve*)ob->data)->curinfo.flag & style)) {
2645                         text_to_curve(ob, 0);
2646                         makeDispListCurveTypes(ob, 0);
2647                         allqueue(REDRAWVIEW3D, 0);
2648                 }
2649                 allqueue(REDRAWBUTSEDIT, 0);
2650                 break;          
2651                 
2652         case B_FASTFONT:
2653                 if (G.obedit) {
2654                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2655                         allqueue(REDRAWVIEW3D, 0);
2656                 }
2657                 break;
2658         case B_INSTB:
2659                 cu= ob->data;
2660                 if (cu->totbox < 256) {
2661                         for (i = cu->totbox; i>cu->actbox; i--) cu->tb[i]= cu->tb[i-1];
2662                         cu->tb[cu->actbox]= cu->tb[cu->actbox-1];
2663                         cu->actbox++;
2664                         cu->totbox++;
2665                         allqueue(REDRAWBUTSEDIT, 0);
2666                         allqueue(REDRAWVIEW3D, 0);
2667                         text_to_curve(ob, 0);
2668                         makeDispListCurveTypes(ob, 0);
2669                 }
2670                 else {
2671                         error("Do you really need that many text frames?");
2672                 }
2673                 break;
2674         case B_DELTB:
2675                 cu= ob->data;
2676                 if (cu->totbox > 1) {
2677                         for (i = cu->actbox-1; i < cu->totbox; i++) cu->tb[i]= cu->tb[i+1];
2678                         cu->totbox--;
2679                         cu->actbox--;
2680                         allqueue(REDRAWBUTSEDIT, 0);
2681                         allqueue(REDRAWVIEW3D, 0);
2682                         text_to_curve(ob, 0);
2683                         makeDispListCurveTypes(ob, 0);
2684                 }
2685                 break;
2686         case B_TOUPPER:
2687                 to_upper();
2688                 break;
2689         case B_LOADFONT:
2690                 vf= give_vfontpointer(G.buts->texnr);
2691                 if(vf && vf->id.prev!=vf->id.next) strcpy(str, vf->name);
2692                 else strcpy(str, U.fontdir);
2693
2694                 sa= closest_bigger_area();
2695                 areawinset(sa->win);
2696
2697                 activate_fileselect(FILE_LOADFONT, "SELECT FONT", str, load_buts_vfont);
2698
2699                 break;
2700         case B_PACKFONT:
2701                 if (ob) {
2702                         cu= ob->data;
2703                         if(cu && cu->vfont) {
2704                                 if (cu->vfont->packedfile) {
2705                                         if (G.fileflags & G_AUTOPACK) {
2706                                                 if (okee("Disable AutoPack ?")) {
2707                                                         G.fileflags &= ~G_AUTOPACK;
2708                                                 }
2709                                         }
2710
2711                                         if ((G.fileflags & G_AUTOPACK) == 0) {
2712                                                 if (unpackVFont(cu->vfont, PF_ASK) == RET_OK) {
2713                                                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2714                                                         allqueue(REDRAWVIEW3D, 0);
2715                                                 }
2716                                         }
2717                                 } else {
2718                                         cu->vfont->packedfile = newPackedFile(cu->vfont->name);
2719                                 }
2720                         }
2721                 }
2722                 allqueue(REDRAWHEADERS, 0);
2723                 allqueue(REDRAWBUTSEDIT, 0);
2724                 break;
2725
2726         case B_LOAD3DTEXT:
2727                 if (!G.obedit) { error("Only in editmode!"); return; }
2728                 if (G.obedit->type != OB_FONT) return;  
2729                 activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, load_3dtext_fs);
2730                 break;
2731                 
2732         case B_LOREM:
2733                 if (!G.obedit) { error("Only in editmode!"); return; }
2734                 if (G.obedit->type != OB_FONT) return;  
2735                 add_lorem();
2736                 
2737                 break;          
2738
2739         case B_SETFONT:
2740                 if(ob) {
2741                         cu= ob->data;
2742
2743                         vf= give_vfontpointer(G.buts->texnr);
2744                         if(vf) {
2745                                 id_us_plus((ID *)vf);
2746
2747                                 switch(cu->curinfo.flag & CU_STYLE) {
2748                                         case CU_BOLD:
2749                                                 cu->vfontb->id.us--;
2750                                                 cu->vfontb= vf;
2751                                                 break;
2752                                         case CU_ITALIC:
2753                                                 cu->vfonti->id.us--;
2754                                                 cu->vfonti= vf;
2755                                                 break;                                          
2756                                         case (CU_BOLD|CU_ITALIC):
2757                                                 cu->vfontbi->id.us--;
2758                                                 cu->vfontbi= vf;
2759                                                 break;
2760                                         default:
2761                                                 cu->vfont->id.us--;
2762                                                 cu->vfont= vf;
2763                                                 break;                                          
2764                                 }
2765                                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2766
2767                                 BIF_undo_push("Set vector font");
2768                                 allqueue(REDRAWVIEW3D, 0);
2769                                 allqueue(REDRAWBUTSEDIT, 0);
2770                         }
2771                 }
2772                 break;
2773                 
2774         case B_SETCHAR:
2775                 G.charmin = 0x0000;
2776                 G.charmax = 0xffff;
2777                 if(G.charstart < 0)
2778                         G.charstart = 0;        
2779                 if(G.charstart > (0xffff - 12*6))
2780                         G.charstart = 0xffff - (12*6);
2781                 allqueue(REDRAWBUTSEDIT, 0);
2782                 break;
2783                 
2784         case B_SETUPCHAR:
2785                 G.charstart = G.charstart - (12*6);
2786                 if(G.charstart < 0)
2787                         G.charstart = 0;        
2788                 if(G.charstart < G.charmin)
2789                         G.charstart = G.charmin;
2790                 allqueue(REDRAWBUTSEDIT, 0);
2791                 break;
2792                 
2793         case B_SETCAT:
2794                 // Create new dynamic string
2795                 ds = BLI_dynstr_new();
2796                 
2797                 // Fill the dynamic string with entries
2798                 for(i=0;i<104;i++)
2799                 {
2800                         BLI_dynstr_append(ds, "|");
2801                         BLI_dynstr_append(ds, uctabname[i].name);
2802                 }
2803                 
2804                 // Create the menu string from dyn string
2805                 ctmenu = BLI_dynstr_get_cstring(ds);
2806                 
2807                 // Call the popup menu
2808                 ctevt = pupmenu_col(ctmenu, 40);
2809                 G.charstart = uctabname[ctevt-1].start;
2810                 G.charmin = uctabname[ctevt-1].start;
2811                 G.charmax = uctabname[ctevt-1].end;
2812
2813                 // Free all data
2814                 BLI_dynstr_free(ds);
2815                 MEM_freeN(ctmenu);
2816
2817                 // And refresh
2818                 allqueue(REDRAWVIEW3D, 0);
2819                 allqueue(REDRAWBUTSEDIT, 0);
2820                 
2821                 break;  
2822                 
2823         case B_SETDOWNCHAR:
2824                 G.charstart = G.charstart + (12*6);
2825                 if(G.charstart > (0xffff - 12*6))
2826                         G.charstart = 0xffff - (12*6);
2827                 if(G.charstart > G.charmax - 12*6)
2828                         G.charstart = G.charmax - 12*6;
2829                 allqueue(REDRAWBUTSEDIT, 0);
2830                 break;
2831                 
2832         case B_SETUNITEXT:
2833                 sa= closest_bigger_area();
2834                 areawinset(sa->win);
2835
2836                 if(ob==G.obedit) {
2837                         activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, set_unicode_text_fs);
2838                 }
2839                 break;          
2840                 
2841         case B_TEXTONCURVE:
2842                 if(ob) {
2843                         cu= ob->data;
2844                         if(cu->textoncurve && cu->textoncurve->type!=OB_CURVE) {
2845                                 error("Only Curve Objects");
2846                                 cu->textoncurve= 0;
2847                                 allqueue(REDRAWBUTSEDIT, 0);
2848                         }
2849                         DAG_scene_sort(G.scene); // makes new dag
2850                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2851                         allqueue(REDRAWVIEW3D, 0);
2852                 }
2853         }
2854 }
2855
2856 #ifdef INTERNATIONAL
2857 static void editing_panel_char_type(Object *ob, Curve *cu)
2858 {
2859         uiBlock *block;
2860
2861         block= uiNewBlock(&curarea->uiblocks, "editing_panel_char_type", UI_EMBOSS, UI_HELV, curarea->win);
2862         uiNewPanelTabbed("Font", "Editing");
2863         if(uiNewPanel(curarea, block, "Char", "Editing", 640, 0, 318, 204)==0) 
2864                 return;
2865
2866         // Set the selected font
2867         G.selfont = cu->vfont;
2868         
2869         uiDefIconBut(block, BUT, B_SETUNITEXT, ICON_TEXT,       0,210,20,20, 0, 0, 0, 0, 0, "Load Unicode Text file");
2870
2871         // Unicode categorization selection button
2872         uiDefBut(block, BUT, B_SETCAT, "Unicode Table", 22,210,226,20, 0, 0, 0, 0, 0, "Select Unicode Table");
2873         uiDefButI(block, NUM, /*B_SETUPCHAR*/ 0, "", 250,210,50,20, &G.charstart, 0, 0xffff, 0, 0, "UT");
2874
2875         // Character selection button
2876         uiDefBut(block, CHARTAB, B_SETCHAR, "", 0, 0, 264, 200, 0, 0, 0, 0, 0, "Select character");
2877
2878         // Buttons to change the max, min
2879         uiDefButI(block, BUT, B_SETUPCHAR, "U", 280, 185, 15, 15, &G.charstart, 0, 0xffff, 0, 0, "Scroll character table up");
2880         uiDefButI(block, BUT, B_SETDOWNCHAR, "D", 280, 0, 15, 15, &G.charstart, 0, 0xffff, 0, 0, "Scroll character table down");
2881 }
2882 #endif
2883
2884 static void editing_panel_font_type(Object *ob, Curve *cu)
2885 {
2886         uiBlock *block;
2887         char *strp;
2888         static int packdummy = 0;
2889         char str[32];
2890
2891         block= uiNewBlock(&curarea->uiblocks, "editing_panel_font_type", UI_EMBOSS, UI_HELV, curarea->win);
2892         if(uiNewPanel(curarea, block, "Font", "Editing", 640, 0, 470, 204)==0) return;
2893
2894         switch(cu->curinfo.flag & CU_STYLE) {
2895                 case CU_BOLD:
2896                         G.buts->texnr= give_vfontnr(cu->vfontb);
2897                         break;
2898                 case CU_ITALIC:
2899                         G.buts->texnr= give_vfontnr(cu->vfonti);
2900                         break;                                          
2901                 case (CU_BOLD|CU_ITALIC):
2902                         G.buts->texnr= give_vfontnr(cu->vfontbi);
2903                         break;
2904                 default:
2905                         G.buts->texnr= give_vfontnr(cu->vfont);
2906                         break;                                          
2907         }       
2908
2909         strp= give_vfontbutstr();
2910 //      vfd= cu->vfont->data;
2911
2912         uiDefBut(block, BUT,B_LOADFONT, "Load", 480,188,68,20, 0, 0, 0, 0, 0, "Load a new font");
2913         uiDefButS(block, MENU, B_SETFONT, strp, 550,188,220,20, &G.buts->texnr, 0, 0, 0, 0, "Change font for object");
2914
2915         if (cu->vfont->packedfile) {
2916                 packdummy = 1;
2917         } else {
2918                 packdummy = 0;
2919         }
2920         uiDefIconButI(block, TOG|BIT|0, B_PACKFONT, ICON_PACKAGE,       772,188,20,20, &packdummy, 0, 0, 0, 0, "Pack/Unpack this font");
2921
2922         /* This doesn't work anyway */
2923 //      uiDefBut(block, LABEL, 0, vfd->name,  480, 165,314,20, 0, 0, 0, 0, 0, "Postscript name of the font");
2924
2925         uiDefBut(block, BUT, B_LOAD3DTEXT, "Insert Text", 480, 165, 90, 20, 0, 0, 0, 0, 0, "Insert text file at cursor");
2926         uiDefBut(block, BUT, B_LOREM, "Lorem", 575, 165, 70, 20, 0, 0, 0, 0, 0, "Insert a paragraph of Lorem Ipsum at cursor"); 
2927         uiDefButC(block, TOG|BIT|2,B_STYLETOSELU, "U",          727,165,20,20, &(cu->curinfo.flag), 0,0, 0, 0, "");     
2928         uiBlockBeginAlign(block);
2929         uiDefButBitC(block, TOG, CU_BOLD, B_STYLETOSELB, "B",           752,165,20,20, &(cu->curinfo.flag), 0,0, 0, 0, "");
2930         uiDefButBitC(block, TOG, CU_ITALIC, B_STYLETOSELI, "i",         772,165,20,20, &(cu->curinfo.flag), 0, 0, 0, 0, "");    
2931         uiBlockEndAlign(block);
2932
2933         MEM_freeN(strp);
2934
2935         uiBlockBeginAlign(block);
2936         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");
2937         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");
2938         uiDefButS(block, ROW,B_MAKEFONT, "Right",               574,135,47,20, &cu->spacemode, 0.0,2.0, 0, 0,&nbs