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