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