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